Index: head/lib/libdisk/create_chunk.c =================================================================== --- head/lib/libdisk/create_chunk.c (revision 48584) +++ head/lib/libdisk/create_chunk.c (revision 48585) @@ -1,373 +1,375 @@ /* * ---------------------------------------------------------------------------- * "THE BEER-WARE LICENSE" (Revision 42): * wrote this file. As long as you retain this notice you * can do whatever you want with this stuff. If we meet some day, and you think * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp * ---------------------------------------------------------------------------- * - * $Id: create_chunk.c,v 1.35 1999/05/04 22:44:47 msmith Exp $ + * $Id: create_chunk.c,v 1.36 1999/05/12 23:50:50 msmith Exp $ * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "libdisk.h" /* Clone these two from sysinstall because we need our own copies * due to link order problems with `crunch'. Feh! */ static int isDebug() { static int debug = 0; /* Allow debugger to tweak it */ return debug; } /* Write something to the debugging port */ static void msgDebug(char *fmt, ...) { va_list args; char *dbg; static int DebugFD = -1; if (DebugFD == -1) DebugFD = open("/dev/ttyv1", O_RDWR); dbg = (char *)alloca(FILENAME_MAX); strcpy(dbg, "DEBUG: "); va_start(args, fmt); vsnprintf((char *)(dbg + strlen(dbg)), FILENAME_MAX, fmt, args); va_end(args); write(DebugFD, dbg, strlen(dbg)); } void Fixup_FreeBSD_Names(struct disk *d, struct chunk *c) { struct chunk *c1, *c3; int j; if (!strcmp(c->name, "X")) return; /* reset all names to "X" */ for (c1 = c->part; c1 ; c1 = c1->next) { c1->oname = c1->name; c1->name = malloc(12); if(!c1->name) err(1,"Malloc failed"); strcpy(c1->name,"X"); } /* Allocate the first swap-partition we find */ for (c1 = c->part; c1 ; c1 = c1->next) { if (c1->type == unused) continue; if (c1->subtype != FS_SWAP) continue; sprintf(c1->name,"%s%c",c->name,SWAP_PART+'a'); break; } /* Allocate the first root-partition we find */ for (c1 = c->part; c1 ; c1 = c1->next) { if (c1->type == unused) continue; if (!(c1->flags & CHUNK_IS_ROOT)) continue; sprintf(c1->name,"%s%c",c->name,0+'a'); break; } /* Try to give them the same as they had before */ for (c1 = c->part; c1 ; c1 = c1->next) { if (strcmp(c1->name,"X")) continue; for(c3 = c->part; c3 ; c3 = c3->next) if (c1 != c3 && !strcmp(c3->name, c1->oname)) { goto newname; } strcpy(c1->name,c1->oname); newname: } /* Allocate the rest sequentially */ for (c1 = c->part; c1 ; c1 = c1->next) { const char order[] = "efghabd"; if (c1->type == unused) continue; if (strcmp("X",c1->name)) continue; for(j=0;jname,"%s%c",c->name,order[j]); for(c3 = c->part; c3 ; c3 = c3->next) if (c1 != c3 && !strcmp(c3->name, c1->name)) goto match; break; match: strcpy(c1->name,"X"); continue; } } for (c1 = c->part; c1 ; c1 = c1->next) { free(c1->oname); c1->oname = 0; } } void Fixup_Extended_Names(struct disk *d, struct chunk *c) { struct chunk *c1; int j=5; for (c1 = c->part; c1 ; c1 = c1->next) { if (c1->type == unused) continue; free(c1->name); c1->name = malloc(12); if(!c1->name) err(1,"malloc failed"); sprintf(c1->name,"%ss%d",d->chunks->name,j++); if (c1->type == freebsd) Fixup_FreeBSD_Names(d,c1); } } void Fixup_Names(struct disk *d) { struct chunk *c1, *c2, *c3; int i,j; c1 = d->chunks; for(i=1,c2 = c1->part; c2 ; c2 = c2->next) { c2->flags &= ~CHUNK_BSD_COMPAT; if (c2->type == unused) continue; if (strcmp(c2->name,"X")) continue; #ifndef __alpha__ c2->oname = malloc(12); if(!c2->oname) err(1,"malloc failed"); for(j=1;j<=NDOSPART;j++) { sprintf(c2->oname,"%ss%d",c1->name,j); for(c3 = c1->part; c3 ; c3 = c3->next) if (c3 != c2 && !strcmp(c3->name, c2->oname)) goto match; free(c2->name); c2->name = c2->oname; c2->oname = 0; break; match: continue; } if (c2->oname) free(c2->oname); #else free(c2->name); c2->name = strdup(c1->name); #endif } for(c2 = c1->part; c2 ; c2 = c2->next) { if (c2->type == freebsd) { c2->flags |= CHUNK_BSD_COMPAT; break; } } for(c2 = c1->part; c2 ; c2 = c2->next) { if (c2->type == freebsd) Fixup_FreeBSD_Names(d,c2); if (c2->type == extended) Fixup_Extended_Names(d,c2); } } int Create_Chunk(struct disk *d, u_long offset, u_long size, chunk_e type, int subtype, u_long flags) { int i; u_long l; if(!(flags & CHUNK_FORCE_ALL)) { /* Never use the first track */ if (!offset) { offset += d->bios_sect; size -= d->bios_sect; } /* Always end on cylinder boundary */ l = (offset+size) % (d->bios_sect * d->bios_hd); size -= l; } i = Add_Chunk(d,offset,size,"X",type,subtype,flags); Fixup_Names(d); return i; } struct chunk * Create_Chunk_DWIM(struct disk *d, struct chunk *parent , u_long size, chunk_e type, int subtype, u_long flags) { int i; struct chunk *c1; u_long offset,edge; if (!parent) parent = d->chunks; for (c1=parent->part; c1 ; c1 = c1->next) { if (c1->type != unused) continue; if (c1->size < size) continue; offset = c1->offset; goto found; } return 0; found: if (parent->flags & CHUNK_BAD144) { edge = c1->end - d->bios_sect - 127; if (offset > edge) return 0; if (offset + size > edge) size = edge - offset + 1; } i = Add_Chunk(d,offset,size,"X",type,subtype,flags); if (i) return 0; Fixup_Names(d); for (c1=parent->part; c1 ; c1 = c1->next) if (c1->offset == offset) return c1; err(1,"Serious internal trouble"); } int MakeDev(struct chunk *c1, const char *path) { char *p = c1->name; u_long cmaj, bmaj, min, unit, part, slice; char buf[BUFSIZ], buf2[BUFSIZ]; *buf2 = '\0'; if (isDebug()) msgDebug("MakeDev: Called with %s on path %s\n", p, path); if (!strcmp(p, "X")) return 0; if (!strncmp(p, "wd", 2)) bmaj = 0, cmaj = 3, p += 2; else if (!strncmp(p, "ad", 2)) /* XXX change if "ad' moves */ bmaj = 0, cmaj = 3, p += 2; else if (!strncmp(p, "sd", 2)) bmaj = 4, cmaj = 13, p += 2; else if (!strncmp(p, "wfd", 3)) bmaj = 1, cmaj = 87, p += 3; else if (!strncmp(p, "fla", 3)) - bmaj = 28, cmaj = 101, p += 3; + bmaj = 28, cmaj = 102, p += 3; + else if (!strncmp(p, "ida", 3)) + bmaj = 29, cmaj = 109, p += 3; else if (!strncmp(p, "da", 2)) /* CAM support */ bmaj = 4, cmaj = 13, p += 2; else { msgDebug("MakeDev: Unknown major/minor for devtype %s\n", p); return 0; } if (!isdigit(*p)) { msgDebug("MakeDev: Invalid disk unit passed: %s\n", p); return 0; } unit = *p - '0'; p++; if (!*p) { slice = 1; part = 2; goto done; } else if (isdigit(*p)) { unit *= 10; unit += (*p - '0'); p++; } #ifndef __alpha__ if (*p != 's') { msgDebug("MakeDev: `%s' is not a valid slice delimiter\n", p); return 0; } p++; if (!isdigit(*p)) { msgDebug("MakeDev: `%s' is an invalid slice number\n", p); return 0; } slice = *p - '0'; p++; if (isdigit(*p)) { slice *= 10; slice += (*p - '0'); p++; } slice = slice + 1; #else slice = 0; #endif if (!*p) { part = 2; if(c1->type == freebsd) sprintf(buf2, "%sc", c1->name); goto done; } if (*p < 'a' || *p > 'h') { msgDebug("MakeDev: `%s' is not a valid partition name.\n", p); return 0; } part = *p - 'a'; done: if (isDebug()) msgDebug("MakeDev: Unit %d, Slice %d, Part %d\n", unit, slice, part); if (unit > 32) return 0; if (slice > 32) return 0; min = unit * 8 + 65536 * slice + part; sprintf(buf, "%s/r%s", path, c1->name); unlink(buf); if (mknod(buf, S_IFCHR|0640, makedev(cmaj,min)) == -1) { msgDebug("mknod of %s returned failure status!\n", buf); return 0; } if (*buf2) { sprintf(buf, "%s/r%s", path, buf2); unlink(buf); if (mknod(buf, S_IFCHR|0640, makedev(cmaj,min)) == -1) { msgDebug("mknod of %s returned failure status!\n", buf); return 0; } } sprintf(buf, "%s/%s", path, c1->name); unlink(buf); if (mknod(buf, S_IFBLK|0640, makedev(bmaj,min)) == -1) { msgDebug("mknod of %s returned failure status!\n", buf); return 0; } return 1; } int MakeDevChunk(struct chunk *c1, const char *path) { int i; i = MakeDev(c1, path); if (c1->next) MakeDevChunk(c1->next, path); if (c1->part) MakeDevChunk(c1->part, path); return i; } int MakeDevDisk(struct disk *d, const char *path) { return MakeDevChunk(d->chunks, path); } Index: head/lib/libdisk/disk.c =================================================================== --- head/lib/libdisk/disk.c (revision 48584) +++ head/lib/libdisk/disk.c (revision 48585) @@ -1,494 +1,494 @@ /* * ---------------------------------------------------------------------------- * "THE BEER-WARE LICENSE" (Revision 42): * wrote this file. As long as you retain this notice you * can do whatever you want with this stuff. If we meet some day, and you think * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp * ---------------------------------------------------------------------------- * - * $Id: disk.c,v 1.43 1999/05/08 21:21:50 dfr Exp $ + * $Id: disk.c,v 1.44 1999/05/09 11:34:56 dfr Exp $ * */ #include #include #include #include #include #include #include #include #include #include #include #include "libdisk.h" #define DOSPTYP_EXTENDED 5 #define DOSPTYP_ONTRACK 84 const char *chunk_n[] = { "whole", "unknown", "fat", "freebsd", "extended", "part", "unused", NULL }; struct disk * Open_Disk(const char *name) { return Int_Open_Disk(name,0); } static u_int32_t Read_Int32(u_int32_t *p) { u_int8_t *bp = (u_int8_t *)p; return bp[0] | (bp[1] << 8) | (bp[2] << 16) | (bp[3] << 24); } struct disk * Int_Open_Disk(const char *name, u_long size) { int i,fd; struct diskslices ds; struct disklabel dl; char device[64]; struct disk *d; struct dos_partition *dp; void *p; u_long offset = 0; strcpy(device,"/dev/r"); strcat(device,name); d = (struct disk *)malloc(sizeof *d); if(!d) err(1,"malloc failed"); memset(d,0,sizeof *d); fd = open(device,O_RDONLY); if (fd < 0) { #ifdef DEBUG warn("open(%s) failed",device); #endif return 0; } memset(&dl,0,sizeof dl); ioctl(fd,DIOCGDINFO,&dl); i = ioctl(fd,DIOCGSLICEINFO,&ds); if (i < 0) { #ifdef DEBUG warn("DIOCGSLICEINFO(%s) failed",device); #endif close(fd); return 0; } #ifdef DEBUG for(i=0;idp_start) >= size) continue; if (Read_Int32(&dp->dp_start) + Read_Int32(&dp->dp_size) >= size) continue; if (!Read_Int32(&dp->dp_size)) continue; if (dp->dp_typ == DOSPTYP_ONTRACK) { d->flags |= DISK_ON_TRACK; offset = 63; } } free(p); d->bios_sect = dl.d_nsectors; d->bios_hd = dl.d_ntracks; d->name = strdup(name); if (dl.d_ntracks && dl.d_nsectors) d->bios_cyl = size/(dl.d_ntracks*dl.d_nsectors); if (Add_Chunk(d, -offset, size, name, whole, 0, 0)) #ifdef DEBUG warn("Failed to add 'whole' chunk"); #else {} #endif #ifdef __i386__ for(i=BASE_SLICE;i ds.dss_slices[i].ds_size) continue; sprintf(pname,"%s%c",sname,j+'a'); if (Add_Chunk(d, dl.d_partitions[j].p_offset + ds.dss_slices[i].ds_offset, dl.d_partitions[j].p_size, pname,part, dl.d_partitions[j].p_fstype, 0) && j != 3) #ifdef DEBUG warn( "Failed to add chunk for partition %c [%lu,%lu]", j + 'a',dl.d_partitions[j].p_offset, dl.d_partitions[j].p_size); #else {} #endif } } } #endif /* __i386__ */ #ifdef __alpha__ { struct disklabel dl; char pname[20]; int j,k; strcpy(pname,"/dev/r"); strcat(pname,name); j = open(pname,O_RDONLY); if (j < 0) { #ifdef DEBUG warn("open(%s)",pname); #endif goto nolabel; } k = ioctl(j,DIOCGDINFO,&dl); if (k < 0) { #ifdef DEBUG warn("ioctl(%s,DIOCGDINFO)",pname); #endif close(j); goto nolabel; } close(j); All_FreeBSD(d, 1); for(j=0; j <= dl.d_npartitions; j++) { if (j == RAW_PART) continue; if (j == 3) continue; if (j == dl.d_npartitions) { j = 3; dl.d_npartitions=0; } if (!dl.d_partitions[j].p_size) continue; if (dl.d_partitions[j].p_size + dl.d_partitions[j].p_offset > ds.dss_slices[WHOLE_DISK_SLICE].ds_size) continue; sprintf(pname,"%s%c",name,j+'a'); if (Add_Chunk(d, dl.d_partitions[j].p_offset, dl.d_partitions[j].p_size, pname,part, dl.d_partitions[j].p_fstype, 0) && j != 3) #ifdef DEBUG warn( "Failed to add chunk for partition %c [%lu,%lu]", j + 'a',dl.d_partitions[j].p_offset, dl.d_partitions[j].p_size); #else {} #endif } nolabel:; } #endif /* __alpha__ */ close(fd); Fixup_Names(d); Bios_Limit_Chunk(d->chunks,1024*d->bios_hd*d->bios_sect); return d; } void Debug_Disk(struct disk *d) { printf("Debug_Disk(%s)",d->name); printf(" flags=%lx",d->flags); #if 0 printf(" real_geom=%lu/%lu/%lu",d->real_cyl,d->real_hd,d->real_sect); #endif printf(" bios_geom=%lu/%lu/%lu = %lu\n", d->bios_cyl,d->bios_hd,d->bios_sect, d->bios_cyl*d->bios_hd*d->bios_sect); #if defined(__i386__) printf(" boot1=%p, boot2=%p, bootmgr=%p\n", d->boot1,d->boot2,d->bootmgr); #elif defined(__alpha__) printf(" boot1=%p, bootmgr=%p\n", d->boot1,d->bootmgr); #endif Debug_Chunk(d->chunks); } void Free_Disk(struct disk *d) { if(d->chunks) Free_Chunk(d->chunks); if(d->name) free(d->name); if(d->bootmgr) free(d->bootmgr); if(d->boot1) free(d->boot1); #if defined(__i386__) if(d->boot2) free(d->boot2); #endif free(d); } struct disk * Clone_Disk(struct disk *d) { struct disk *d2; d2 = (struct disk*) malloc(sizeof *d2); if(!d2) err(1,"malloc failed"); *d2 = *d; d2->name = strdup(d2->name); d2->chunks = Clone_Chunk(d2->chunks); if(d2->bootmgr) { d2->bootmgr = malloc(DOSPARTOFF); memcpy(d2->bootmgr,d->bootmgr,DOSPARTOFF); } #if defined(__i386__) if(d2->boot1) { d2->boot1 = malloc(512); memcpy(d2->boot1,d->boot1,512); } if(d2->boot2) { d2->boot2 = malloc(512*15); memcpy(d2->boot2,d->boot2,512*15); } #elif defined(__alpha__) if(d2->boot1) { d2->boot1 = malloc(512*15); memcpy(d2->boot1,d->boot1,512*15); } #endif return d2; } #if 0 void Collapse_Disk(struct disk *d) { while(Collapse_Chunk(d,d->chunks)) ; } #endif -static char * device_list[] = {"wd", "ad", "sd", "da", "wfd", "fla", 0}; +static char * device_list[] = {"wd", "ad", "sd", "da", "wfd", "fla", "ida", 0}; char ** Disk_Names() { int i,j,k; char disk[25]; char diskname[25]; struct stat st; struct diskslices ds; int fd; static char **disks; disks = malloc(sizeof *disks * (1 + MAX_NO_DISKS)); memset(disks,0,sizeof *disks * (1 + MAX_NO_DISKS)); k = 0; for (j = 0; device_list[j]; j++) { for (i = 0; i < MAX_NO_DISKS; i++) { sprintf(diskname, "%s%d", device_list[j], i); sprintf(disk, "/dev/r%s", diskname); if (stat(disk, &st) || !(st.st_mode & S_IFCHR)) continue; if ((fd = open(disk, O_RDWR)) == -1) continue; if (ioctl(fd, DIOCGSLICEINFO, &ds) == -1) { close(fd); continue; } disks[k++] = strdup(diskname); if(k == MAX_NO_DISKS) return disks; } } return disks; } void Set_Boot_Mgr(struct disk *d, const u_char *b) { if (d->bootmgr) free(d->bootmgr); if (!b) { d->bootmgr = 0; } else { d->bootmgr = malloc(DOSPARTOFF); if(!d->bootmgr) err(1,"malloc failed"); memcpy(d->bootmgr,b,DOSPARTOFF); } } void Set_Boot_Blocks(struct disk *d, const u_char *b1, const u_char *b2) { #if defined(__i386__) if (d->boot1) free(d->boot1); d->boot1 = malloc(512); if(!d->boot1) err(1,"malloc failed"); memcpy(d->boot1,b1,512); if (d->boot2) free(d->boot2); d->boot2 = malloc(15*512); if(!d->boot2) err(1,"malloc failed"); memcpy(d->boot2,b2,15*512); #elif defined(__alpha__) if (d->boot1) free(d->boot1); d->boot1 = malloc(15*512); if(!d->boot1) err(1,"malloc failed"); memcpy(d->boot1,b1,15*512); #endif } const char * slice_type_name( int type, int subtype ) { switch (type) { case 0: return "whole"; case 1: switch (subtype) { case 1: return "fat (12-bit)"; case 2: return "XENIX /"; case 3: return "XENIX /usr"; case 4: return "fat (16-bit,<=32Mb)"; case 5: return "extended DOS"; case 6: return "fat (16-bit,>32Mb)"; case 7: return "NTFS/HPFS/QNX"; case 8: return "AIX bootable"; case 9: return "AIX data"; case 10: return "OS/2 bootmgr"; case 11: return "fat (32-bit)"; case 12: return "fat (32-bit,LBA)"; case 14: return "fat (16-bit,>32Mb,LBA)"; case 15: return "extended DOS, LBA"; case 18: return "Compaq Diagnostic"; case 84: return "OnTrack diskmgr"; case 100: return "Netware 2.x"; case 101: return "Netware 3.x"; case 115: return "SCO UnixWare"; case 128: return "Minix 1.1"; case 129: return "Minix 1.5"; case 130: return "linux_swap"; case 131: return "ext2fs"; case 166: return "OpenBSD FFS"; /* 0xA6 */ case 169: return "NetBSD FFS"; /* 0xA9 */ case 182: return "OpenBSD"; /* dedicated */ case 183: return "bsd/os"; case 184: return "bsd/os swap"; default: return "unknown"; } case 2: return "fat"; case 3: switch (subtype) { case 165: return "freebsd"; default: return "unknown"; } case 4: return "extended"; case 5: return "part"; case 6: return "unused"; default: return "unknown"; } }