disk.c revision 8180
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.6 1995/04/30 06:09:26 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 struct dos_partition *dp; 44 void *p; 45 46 strcpy(device,"/dev/r"); 47 strcat(device,name); 48 49 d = (struct disk *)malloc(sizeof *d); 50 if(!d) err(1,"malloc failed"); 51 memset(d,0,sizeof *d); 52 53 fd = open(device,O_RDONLY); 54 if (fd < 0) { 55 warn("open(%s) failed",device); 56 return 0; 57 } 58 59 memset(&dl,0,sizeof dl); 60 ioctl(fd,DIOCGDINFO,&dl); 61 i = ioctl(fd,DIOCGSLICEINFO,&ds); 62 if (i < 0) { 63 warn("DIOCGSLICEINFO(%s) failed",device); 64 close(fd); 65 return 0; 66 } 67 68 if (!size) 69 size = ds.dss_slices[WHOLE_DISK_SLICE].ds_size; 70 71 p = read_block(fd,0); 72 dp = (struct dos_partition*)(p+DOSPARTOFF); 73 for(i=0;i<NDOSPART;i++) { 74 if (dp->dp_start >= size) continue; 75 if (dp->dp_start+dp->dp_size >= size) continue; 76 if (!dp->dp_size) continue; 77 78 if (dp->dp_typ == DOSPTYP_ONTRACK) 79 d->flags |= DISK_ON_TRACK; 80 81 } 82 free(p); 83 84 d->bios_sect = dl.d_nsectors; 85 d->bios_hd = dl.d_ntracks; 86 87 d->name = strdup(name); 88 89 90 if (dl.d_ntracks && dl.d_nsectors) 91 d->bios_cyl = size/(dl.d_ntracks*dl.d_nsectors); 92 93 if (Add_Chunk(d, 0, size, name,whole,0,0)) 94 warn("Failed to add 'whole' chunk"); 95 96 if (ds.dss_slices[COMPATIBILITY_SLICE].ds_offset) 97 if (Add_Chunk(d, 0, 1, "-",reserved,0,0)) 98 warn("Failed to add MBR chunk"); 99 100 for(i=BASE_SLICE;i < 12 && i<ds.dss_nslices;i++) { 101 char sname[20]; 102 chunk_e ce; 103 u_long flags=0; 104 int subtype=0; 105 if (! ds.dss_slices[i].ds_size) 106 continue; 107 sprintf(sname,"%ss%d",name,i-1); 108 switch (ds.dss_slices[i].ds_type) { 109 case 0xa5: 110 ce = freebsd; 111 break; 112 case 0x1: 113 case 0x6: 114 ce = fat; 115 break; 116 case DOSPTYP_EXTENDED: 117 ce = extended; 118 break; 119 default: 120 ce = foo; 121 subtype = -ds.dss_slices[i].ds_type; 122 break; 123 } 124 flags |= CHUNK_ALIGN; 125 if (Add_Chunk(d,ds.dss_slices[i].ds_offset, 126 ds.dss_slices[i].ds_size, sname,ce,subtype,flags)) 127 warn("failed to add chunk for slice %d",i - 1); 128 if (ce == extended) 129 if (Add_Chunk(d,ds.dss_slices[i].ds_offset, 130 1, "-",reserved, subtype, flags)) 131 warn("failed to add MBR chunk for slice %d",i - 1); 132 if (ds.dss_slices[i].ds_type == 0xa5) { 133 struct disklabel *dl; 134 135 dl = read_disklabel(fd, 136 ds.dss_slices[i].ds_offset + LABELSECTOR); 137 if(dl) { 138 char pname[20]; 139 int j; 140 u_long l; 141 if (dl->d_partitions[RAW_PART].p_offset == 0 && 142 dl->d_partitions[RAW_PART].p_size == 143 ds.dss_slices[i].ds_size) 144 l = ds.dss_slices[i].ds_offset; 145 else 146 l = 0; 147 for(j=0; j < dl->d_npartitions; j++) { 148 sprintf(pname,"%s%c",sname,j+'a'); 149 if (j == RAW_PART || j == 3) 150 continue; 151 if (!dl->d_partitions[j].p_size) 152 continue; 153 if (Add_Chunk(d, 154 dl->d_partitions[j].p_offset + 155 l, 156 dl->d_partitions[j].p_size, 157 pname,part,0,0)) 158 warn( 159 "Failed to add chunk for partition %c [%lu,%lu]", 160 j + 'a',dl->d_partitions[j].p_offset,dl->d_partitions[j].p_size); 161 } 162 sprintf(pname,"%sd",sname); 163 if (dl->d_partitions[3].p_size) 164 Add_Chunk(d, 165 dl->d_partitions[3].p_offset + 166 l, 167 dl->d_partitions[3].p_size, 168 pname,part,0,0); 169 free(dl); 170 } 171 } 172 } 173 close(fd); 174 return d; 175} 176 177void 178Debug_Disk(struct disk *d) 179{ 180 printf("Debug_Disk(%s)",d->name); 181 printf(" flags=%lx",d->flags); 182 printf(" real_geom=%lu/%lu/%lu",d->real_cyl,d->real_hd,d->real_sect); 183 printf(" bios_geom=%lu/%lu/%lu\n",d->bios_cyl,d->bios_hd,d->bios_sect); 184 printf(" boot1=%p, boot2=%p, bootmgr=%p\n", 185 d->boot1,d->boot2,d->bootmgr); 186 Debug_Chunk(d->chunks); 187} 188 189void 190Free_Disk(struct disk *d) 191{ 192 if(d->chunks) Free_Chunk(d->chunks); 193 if(d->name) free(d->name); 194 if(d->bootmgr) free(d->bootmgr); 195 if(d->boot1) free(d->boot1); 196 if(d->boot2) free(d->boot2); 197 free(d); 198} 199 200struct disk * 201Clone_Disk(struct disk *d) 202{ 203 struct disk *d2; 204 205 d2 = (struct disk*) malloc(sizeof *d2); 206 if(!d2) err(1,"malloc failed"); 207 *d2 = *d; 208 d2->name = strdup(d2->name); 209 d2->chunks = Clone_Chunk(d2->chunks); 210 if(d2->bootmgr) { 211 d2->bootmgr = malloc(DOSPARTOFF); 212 memcpy(d2->bootmgr,d->bootmgr,DOSPARTOFF); 213 } 214 if(d2->boot1) { 215 d2->boot1 = malloc(512); 216 memcpy(d2->boot1,d->boot1,512); 217 } 218 if(d2->boot2) { 219 d2->boot2 = malloc(512*7); 220 memcpy(d2->boot2,d->boot2,512*7); 221 } 222 return d2; 223} 224 225void 226Collapse_Disk(struct disk *d) 227{ 228 229 while(Collapse_Chunk(d,d->chunks)) 230 ; 231} 232 233static char * device_list[] = {"wd","sd",0}; 234 235char ** 236Disk_Names() 237{ 238 int i,j,k; 239 char disk[25]; 240 char diskname[25]; 241 struct stat st; 242 struct diskslices ds; 243 int fd; 244 static char **disks; 245 246 disks = malloc(sizeof *disks * (1 + MAX_NO_DISKS)); 247 memset(disks,0,sizeof *disks * (1 + MAX_NO_DISKS)); 248 k = 0; 249 for (j = 0; device_list[j]; j++) { 250 for (i = 0; i < 10; i++) { 251 sprintf(diskname, "%s%d", device_list[j], i); 252 sprintf(disk, "/dev/r%s", diskname); 253 if (stat(disk, &st) || !(st.st_mode & S_IFCHR)) 254 continue; 255 if ((fd = open(disk, O_RDWR)) == -1) 256 continue; 257 if (ioctl(fd, DIOCGSLICEINFO, &ds) == -1) { 258 close(fd); 259 continue; 260 } 261 disks[k++] = strdup(diskname); 262 if(k == MAX_NO_DISKS) 263 return disks; 264 } 265 } 266 return disks; 267} 268 269void 270Set_Boot_Mgr(struct disk *d, u_char *b) 271{ 272 if (d->bootmgr) 273 free(d->bootmgr); 274 d->bootmgr = malloc(DOSPARTOFF); 275 if(!d->bootmgr) err(1,"malloc failed"); 276 memcpy(d->bootmgr,b,DOSPARTOFF); 277} 278 279void 280Set_Boot_Blocks(struct disk *d, u_char *b1, u_char *b2) 281{ 282 if (d->boot1) free(d->boot1); 283 d->boot1 = malloc(512); 284 if(!d->boot1) err(1,"malloc failed"); 285 memcpy(d->boot1,b1,512); 286 if (d->boot2) free(d->boot2); 287 d->boot2 = malloc(7*512); 288 if(!d->boot2) err(1,"malloc failed"); 289 memcpy(d->boot2,b2,7*512); 290} 291