disk.c revision 8160
1/* 2 * ---------------------------------------------------------------------------- 3 * "THE BEER-WARE LICENSE" (Revision 42): 4 * <phk@login.dknet.dk> wrote this file. As long as you retain this notice you 5 * can do whatever you want with this stuff. If we meet some day, and you think 6 * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp 7 * ---------------------------------------------------------------------------- 8 * 9 * $Id: disk.c,v 1.4 1995/04/29 04:50:37 phk Exp $ 10 * 11 */ 12 13#include <stdio.h> 14#include <stdlib.h> 15#include <unistd.h> 16#include <fcntl.h> 17#include <string.h> 18#include <err.h> 19#include <sys/types.h> 20#include <sys/stat.h> 21#include <sys/ioctl.h> 22#include <sys/disklabel.h> 23#include <sys/diskslice.h> 24#include "libdisk.h" 25 26#define DOSPTYP_EXTENDED 5 27#define DOSPTYP_ONTRACK 84 28 29struct disk * 30Open_Disk(char *name) 31{ 32 return Int_Open_Disk(name,0); 33} 34 35struct disk * 36Int_Open_Disk(char *name, u_long size) 37{ 38 int i,fd; 39 struct diskslices ds; 40 struct disklabel dl; 41 char device[64]; 42 struct disk *d; 43 44 strcpy(device,"/dev/r"); 45 strcat(device,name); 46 47 fd = open(device,O_RDONLY); 48 if (fd < 0) { 49 warn("open(%s) failed",device); 50 return 0; 51 } 52 i = ioctl(fd,DIOCGDINFO,&dl); 53 if (i < 0) { 54 warn("DIOCGDINFO(%s) failed",device); 55 close(fd); 56 return 0; 57 } 58 i = ioctl(fd,DIOCGSLICEINFO,&ds); 59 if (i < 0) { 60 warn("DIOCGSLICEINFO(%s) failed",device); 61 close(fd); 62 return 0; 63 } 64 65 d = (struct disk *)malloc(sizeof *d); 66 if(!d) err(1,"malloc failed"); 67 68 memset(d,0,sizeof *d); 69 70 d->bios_sect = dl.d_nsectors; 71 d->bios_hd = dl.d_ntracks; 72 73 d->name = strdup(name); 74 75 if (!size) 76 size = ds.dss_slices[WHOLE_DISK_SLICE].ds_size; 77 78 if (dl.d_ntracks && dl.d_nsectors) 79 d->bios_cyl = size/(dl.d_ntracks*dl.d_nsectors); 80 81 if (Add_Chunk(d, 0, size, name,whole,0,0)) 82 warn("Failed to add 'whole' chunk"); 83 84 if (ds.dss_slices[COMPATIBILITY_SLICE].ds_offset) 85 if (Add_Chunk(d, 0, 1, "-",reserved,0,0)) 86 warn("Failed to add MBR chunk"); 87 88 for(i=BASE_SLICE;i<ds.dss_nslices;i++) { 89 char sname[20]; 90 chunk_e ce; 91 u_long flags=0; 92 int subtype=0; 93 if (! ds.dss_slices[i].ds_size) 94 continue; 95 sprintf(sname,"%ss%d",name,i-1); 96 switch (ds.dss_slices[i].ds_type) { 97 case 0xa5: 98 ce = freebsd; 99 break; 100 case 0x1: 101 case 0x6: 102 ce = fat; 103 break; 104 case DOSPTYP_EXTENDED: 105 ce = extended; 106 break; 107 default: 108 ce = foo; 109 subtype = -ds.dss_slices[i].ds_type; 110 break; 111 } 112 flags |= CHUNK_ALIGN; 113 if (Add_Chunk(d,ds.dss_slices[i].ds_offset, 114 ds.dss_slices[i].ds_size, sname,ce,subtype,flags)) 115 warn("failed to add chunk for slice %d",i - 1); 116 if (ce == extended) 117 if (Add_Chunk(d,ds.dss_slices[i].ds_offset, 118 1, "-",reserved, subtype, flags)) 119 warn("failed to add MBR chunk for slice %d",i - 1); 120 if (ds.dss_slices[i].ds_type == 0xa5) { 121 struct disklabel *dl; 122 int j; 123 124 dl = read_disklabel(fd, 125 ds.dss_slices[i].ds_offset + LABELSECTOR); 126 if(dl) { 127 char pname[20]; 128 for(j=0; j < dl->d_npartitions; j++) { 129 sprintf(pname,"%s%c",sname,j+'a'); 130 if (j == 2 || j == 3) 131 continue; 132 if (!dl->d_partitions[j].p_size) 133 continue; 134 if (Add_Chunk(d, 135 dl->d_partitions[j].p_offset, 136 dl->d_partitions[j].p_size, 137 pname,part,0,0)) 138 warn("Failed to add chunk for partition %c",j + 'a'); 139 } 140 sprintf(pname,"%sd",sname); 141 if (!dl->d_partitions[3].p_size) 142 continue; 143 Add_Chunk(d, 144 dl->d_partitions[3].p_offset, 145 dl->d_partitions[3].p_size, 146 pname,part,0,0); 147 } 148 free(dl); 149 } 150 } 151 close(fd); 152 return d; 153} 154 155void 156Debug_Disk(struct disk *d) 157{ 158 printf("Debug_Disk(%s)",d->name); 159 printf(" flags=%lx",d->flags); 160 printf(" real_geom=%lu/%lu/%lu",d->real_cyl,d->real_hd,d->real_sect); 161 printf(" bios_geom=%lu/%lu/%lu\n",d->bios_cyl,d->bios_hd,d->bios_sect); 162 Debug_Chunk(d->chunks); 163} 164 165void 166Free_Disk(struct disk *d) 167{ 168 if(d->chunks) Free_Chunk(d->chunks); 169 if(d->name) free(d->name); 170 if(d->bootmgr) free(d->bootmgr); 171 if(d->boot1) free(d->boot1); 172 if(d->boot2) free(d->boot2); 173 free(d); 174} 175 176struct disk * 177Clone_Disk(struct disk *d) 178{ 179 struct disk *d2; 180 181 d2 = (struct disk*) malloc(sizeof *d2); 182 if(!d2) err(1,"malloc failed"); 183 *d2 = *d; 184 d2->name = strdup(d2->name); 185 d2->chunks = Clone_Chunk(d2->chunks); 186 if(d2->bootmgr) { 187 d2->bootmgr = malloc(DOSPARTOFF); 188 memcpy(d2->bootmgr,d->bootmgr,DOSPARTOFF); 189 } 190 if(d2->boot1) { 191 d2->boot1 = malloc(512); 192 memcpy(d2->boot1,d->boot1,512); 193 } 194 if(d2->boot2) { 195 d2->boot2 = malloc(512*7); 196 memcpy(d2->boot2,d->boot2,512*7); 197 } 198 return d2; 199} 200 201void 202Collapse_Disk(struct disk *d) 203{ 204 205 while(Collapse_Chunk(d,d->chunks)) 206 ; 207} 208 209static char * device_list[] = {"wd","sd",0}; 210 211char ** 212Disk_Names() 213{ 214 int i,j,k; 215 char disk[25]; 216 char diskname[25]; 217 struct stat st; 218 struct diskslices ds; 219 int fd; 220 static char **disks; 221 222 disks = malloc(sizeof *disks * (1 + MAX_NO_DISKS)); 223 memset(disks,0,sizeof *disks * (1 + MAX_NO_DISKS)); 224 k = 0; 225 for (j = 0; device_list[j]; j++) { 226 for (i = 0; i < 10; i++) { 227 sprintf(diskname, "%s%d", device_list[j], i); 228 sprintf(disk, "/dev/r%s", diskname); 229 if (stat(disk, &st) || !(st.st_mode & S_IFCHR)) 230 continue; 231 if ((fd = open(disk, O_RDWR)) == -1) 232 continue; 233 if (ioctl(fd, DIOCGSLICEINFO, &ds) == -1) { 234 close(fd); 235 continue; 236 } 237 disks[k++] = strdup(diskname); 238 if(k == MAX_NO_DISKS) 239 return disks; 240 } 241 } 242 return disks; 243} 244 245void 246Set_Boot_Mgr(struct disk *d, u_char *b) 247{ 248 if (d->bootmgr) 249 free(d->bootmgr); 250 d->bootmgr = malloc(DOSPARTOFF); 251 if(!d->bootmgr) err(1,"malloc failed"); 252 memcpy(d->bootmgr,b,DOSPARTOFF); 253} 254 255void 256Set_Boot_Blocks(struct disk *d, u_char *b1, u_char *b2) 257{ 258 if (d->boot1) free(d->boot1); 259 d->boot1 = malloc(512); 260 if(!d->boot1) err(1,"malloc failed"); 261 memcpy(d->boot1,b1,512); 262 if (d->boot2) free(d->boot2); 263 d->boot2 = malloc(7*512); 264 if(!d->boot2) err(1,"malloc failed"); 265 memcpy(d->boot2,b2,7*512); 266} 267