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