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