disk.c revision 8156
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 "libdisk.h" 24 25#define DOSPTYP_EXTENDED 5 26#define DOSPTYP_ONTRACK 84 27 28struct disk * 29Open_Disk(char *name) 30{ 31 return Int_Open_Disk(name,0); 32} 33 34struct disk * 35Int_Open_Disk(char *name, u_long size) 36{ 37 int i,fd; 38 struct diskslices ds; 39 char device[64]; 40 struct disk *d; 41 42 strcpy(device,"/dev/r"); 43 strcat(device,name); 44 45 fd = open(device,O_RDONLY); 46 if (fd < 0) { 47 warn("open(%s) failed",device); 48 return 0; 49 } 50 i = ioctl(fd,DIOCGSLICEINFO,&ds); 51 if (i < 0) { 52 warn("DIOCSLICEINFO(%s) failed",device); 53 close(fd); 54 return 0; 55 } 56 57 d = (struct disk *)malloc(sizeof *d); 58 if(!d) err(1,"malloc failed"); 59 60 memset(d,0,sizeof *d); 61 62 d->name = strdup(name); 63 64 if (!size) 65 size = ds.dss_slices[WHOLE_DISK_SLICE].ds_size; 66 67 Add_Chunk(d, 0, size, name,whole,0,0); 68 Add_Chunk(d, 0, 1, "-",reserved,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 (ce == extended) 98 Add_Chunk(d,ds.dss_slices[i].ds_offset, 99 1, "-",reserved, subtype, flags); 100 if (ds.dss_slices[i].ds_type == 0xa5) { 101 struct disklabel *dl; 102 int j; 103 104 dl = read_disklabel(fd, 105 ds.dss_slices[i].ds_offset + LABELSECTOR); 106 if(dl) { 107 for(j=0; j < dl->d_npartitions; j++) { 108 char pname[20]; 109 sprintf(pname,"%s%c",sname,j+'a'); 110 if (j == 2) 111 continue; 112 if (!dl->d_partitions[j].p_size) 113 continue; 114 Add_Chunk(d, 115 dl->d_partitions[j].p_offset, 116 dl->d_partitions[j].p_size, 117 pname,part,0,0); 118 } 119 } 120 free(dl); 121 } 122 } 123 close(fd); 124 return d; 125} 126 127void 128Debug_Disk(struct disk *d) 129{ 130 printf("Debug_Disk(%s)",d->name); 131 printf(" flags=%lx",d->flags); 132 printf(" real_geom=%lu/%lu/%lu",d->real_cyl,d->real_hd,d->real_sect); 133 printf(" bios_geom=%lu/%lu/%lu\n",d->bios_cyl,d->bios_hd,d->bios_sect); 134 Debug_Chunk(d->chunks); 135} 136 137void 138Free_Disk(struct disk *d) 139{ 140 if(d->chunks) 141 Free_Chunk(d->chunks); 142 if(d->name) 143 free(d->name); 144 free(d); 145} 146 147struct disk * 148Clone_Disk(struct disk *d) 149{ 150 struct disk *d2; 151 152 d2 = (struct disk*) malloc(sizeof *d2); 153 if(!d2) err(1,"malloc failed"); 154 *d2 = *d; 155 d2->name = strdup(d2->name); 156 d2->chunks = Clone_Chunk(d2->chunks); 157 return d2; 158} 159 160void 161Collapse_Disk(struct disk *d) 162{ 163 164 while(Collapse_Chunk(d,d->chunks)) 165 ; 166} 167 168int 169Aligned(struct disk *d, u_long offset) 170{ 171 if (offset % d->bios_sect) 172 return 0; 173 return 1; 174} 175 176u_long 177Prev_Aligned(struct disk *d, u_long offset) 178{ 179 return (offset / d->bios_sect) * d->bios_sect; 180} 181 182u_long 183Next_Aligned(struct disk *d, u_long offset) 184{ 185 return Prev_Aligned(d,offset + d->bios_sect); 186} 187