disk.c revision 8153
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$ 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/ioctl.h> 21#include <sys/disklabel.h> 22#include <sys/diskslice.h> 23#include <sys/queue.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 char device[64]; 41 struct disk *d; 42 43 strcpy(device,"/dev/r"); 44 strcat(device,name); 45 46 fd = open(device,O_RDONLY); 47 if (fd < 0) { 48 warn("open(%s) failed",device); 49 return 0; 50 } 51 i = ioctl(fd,DIOCGSLICEINFO,&ds); 52 if (i < 0) { 53 warn("DIOCSLICEINFO(%s) failed",device); 54 close(fd); 55 return 0; 56 } 57 58 d = (struct disk *)malloc(sizeof *d); 59 if(!d) err(1,"malloc failed"); 60 61 memset(d,0,sizeof *d); 62 63 d->name = strdup(name); 64 65 if (!size) 66 size = ds.dss_slices[WHOLE_DISK_SLICE].ds_size; 67 68 Add_Chunk(d, 0, size, name,whole,0,0); 69 70 for(i=2;i<ds.dss_nslices;i++) { 71 char sname[20]; 72 chunk_e ce; 73 u_long flags=0; 74 int subtype=0; 75 if (! ds.dss_slices[i].ds_size) 76 continue; 77 sprintf(sname,"%ss%d",name,i-1); 78 switch (ds.dss_slices[i].ds_type) { 79 case 0xa5: 80 ce = freebsd; 81 break; 82 case 0x1: 83 case 0x6: 84 ce = fat; 85 break; 86 case DOSPTYP_EXTENDED: 87 ce = extended; 88 break; 89 default: 90 ce = foo; 91 subtype = -ds.dss_slices[i].ds_type; 92 break; 93 } 94 flags |= CHUNK_ALIGN; 95 Add_Chunk(d,ds.dss_slices[i].ds_offset, 96 ds.dss_slices[i].ds_size, sname,ce,subtype,flags); 97 if (ds.dss_slices[i].ds_type == 0xa5) { 98 struct disklabel *dl; 99 int j; 100 101 dl = read_disklabel(fd, 102 ds.dss_slices[i].ds_offset + LABELSECTOR); 103 if(dl) { 104 for(j=0; j < dl->d_npartitions; j++) { 105 char pname[20]; 106 sprintf(pname,"%s%c",sname,j+'a'); 107 if (j == 2) 108 continue; 109 if (!dl->d_partitions[j].p_size) 110 continue; 111 Add_Chunk(d, 112 dl->d_partitions[j].p_offset, 113 dl->d_partitions[j].p_size, 114 pname,part,0,0); 115 } 116 } 117 free(dl); 118 } 119 } 120 close(fd); 121 return d; 122} 123 124void 125Debug_Disk(struct disk *d) 126{ 127 printf("Debug_Disk(%s)",d->name); 128 printf(" flags=%lx",d->flags); 129 printf(" real_geom=%lu/%lu/%lu",d->real_cyl,d->real_hd,d->real_sect); 130 printf(" bios_geom=%lu/%lu/%lu\n",d->bios_cyl,d->bios_hd,d->bios_sect); 131 Debug_Chunk(d->chunks); 132} 133 134void 135Free_Disk(struct disk *d) 136{ 137 if(d->chunks) 138 Free_Chunk(d->chunks); 139 if(d->name) 140 free(d->name); 141 free(d); 142} 143 144struct disk * 145Clone_Disk(struct disk *d) 146{ 147 struct disk *d2; 148 149 d2 = (struct disk*) malloc(sizeof *d2); 150 if(!d2) err(1,"malloc failed"); 151 *d2 = *d; 152 d2->name = strdup(d2->name); 153 d2->chunks = Clone_Chunk(d2->chunks); 154 return d2; 155} 156 157void 158Collapse_Disk(struct disk *d) 159{ 160 161 while(Collapse_Chunk(d,d->chunks)) 162 ; 163} 164 165int 166Aligned(struct disk *d, u_long offset) 167{ 168 if (offset % d->bios_sect) 169 return 0; 170 return 1; 171} 172 173u_long 174Prev_Aligned(struct disk *d, u_long offset) 175{ 176 return (offset / d->bios_sect) * d->bios_sect; 177} 178 179u_long 180Next_Aligned(struct disk *d, u_long offset) 181{ 182 return Prev_Aligned(d,offset + d->bios_sect); 183} 184