diff options
Diffstat (limited to 'release/libdisk')
-rw-r--r-- | release/libdisk/Makefile | 23 | ||||
-rw-r--r-- | release/libdisk/blocks.c | 41 | ||||
-rw-r--r-- | release/libdisk/change.c | 61 | ||||
-rw-r--r-- | release/libdisk/chunk.c | 433 | ||||
-rw-r--r-- | release/libdisk/create_chunk.c | 297 | ||||
-rw-r--r-- | release/libdisk/disk.c | 327 | ||||
-rw-r--r-- | release/libdisk/disklabel.c | 33 | ||||
-rw-r--r-- | release/libdisk/libdisk.h | 315 | ||||
-rw-r--r-- | release/libdisk/rules.c | 316 | ||||
-rw-r--r-- | release/libdisk/tst01.c | 308 | ||||
-rw-r--r-- | release/libdisk/write_disk.c | 233 |
11 files changed, 2387 insertions, 0 deletions
diff --git a/release/libdisk/Makefile b/release/libdisk/Makefile new file mode 100644 index 0000000..3d58dfa --- /dev/null +++ b/release/libdisk/Makefile @@ -0,0 +1,23 @@ +LIB= disk +SRCS= blocks.c disklabel.c dkcksum.c chunk.c disk.c change.c \ + create_chunk.c rules.c write_disk.c data.c + +CFLAGS+= -Wall -g +CLEANFILES+= tmp.c tst01 tst01.o data.c +VPATH= ${.CURDIR}/../../sbin/disklabel +NOPROFILE= yes +NOSHARED= yes + +.include <bsd.lib.mk> + +BOOTS=/usr/mdec + +data.c: libdisk.h ${BOOTS}/boot1 ${BOOTS}/boot2 + file2c 'const unsigned char boot1[] = {' '};' \ + < ${BOOTS}/boot1 > tmp.c + file2c 'const unsigned char boot2[] = {' '};' \ + < ${BOOTS}/boot2 >> tmp.c + mv tmp.c data.c + +tst01: tst01.o libdisk.a + cc ${CFLAGS} -static tst01.o -o tst01 libdisk.a diff --git a/release/libdisk/blocks.c b/release/libdisk/blocks.c new file mode 100644 index 0000000..85a9c44 --- /dev/null +++ b/release/libdisk/blocks.c @@ -0,0 +1,41 @@ +/* + * ---------------------------------------------------------------------------- + * "THE BEER-WARE LICENSE" (Revision 42): + * <phk@login.dknet.dk> 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: blocks.c,v 1.2 1995/04/29 01:55:17 phk Exp $ + * + */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <err.h> +#include "libdisk.h" + +void * +read_block(int fd, daddr_t block) +{ + void *foo; + + foo = malloc(512); + if (!foo) + err(1,"malloc"); + if (-1 == lseek(fd,block * 512,SEEK_SET)) + err(1,"lseek"); + if (512 != read(fd,foo, 512)) + err(1,"read"); + return foo; +} + +void +write_block(int fd, daddr_t block, void *foo) +{ + if (-1 == lseek(fd,block * 512,SEEK_SET)) + err(1,"lseek"); + if (512 != write(fd,foo, 512)) + err(1,"write"); +} diff --git a/release/libdisk/change.c b/release/libdisk/change.c new file mode 100644 index 0000000..57ccbfa --- /dev/null +++ b/release/libdisk/change.c @@ -0,0 +1,61 @@ +/* + * ---------------------------------------------------------------------------- + * "THE BEER-WARE LICENSE" (Revision 42): + * <phk@login.dknet.dk> 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: change.c,v 1.8.2.1 1995/06/05 02:24:20 jkh Exp $ + * + */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <fcntl.h> +#include <string.h> +#include <err.h> +#include <sys/types.h> +#include "libdisk.h" + +#if 0 +struct disk * +Set_Phys_Geom(struct disk *disk, u_long cyl, u_long hd, u_long sect) +{ + struct disk *d = Int_Open_Disk(disk->name,cyl*hd*sect); + d->real_cyl = cyl; + d->real_hd = hd; + d->real_sect = sect; + d->bios_cyl = disk->bios_cyl; + d->bios_hd = disk->bios_hd; + d->bios_sect = disk->bios_sect; + d->flags = disk->flags; + Free_Disk(disk); + return d; +} +#endif + +void +Set_Bios_Geom(struct disk *disk, u_long cyl, u_long hd, u_long sect) +{ + disk->bios_cyl = cyl; + disk->bios_hd = hd; + disk->bios_sect = sect; + Bios_Limit_Chunk(disk->chunks,1024*hd*sect); +} + +void +All_FreeBSD(struct disk *d) +{ + struct chunk *c; + + again: + for (c=d->chunks->part;c;c=c->next) + if (c->type != unused) { + Delete_Chunk(d,c); + goto again; + } + c=d->chunks; + Create_Chunk(d,c->offset,c->size,freebsd,0xa5,0); +} diff --git a/release/libdisk/chunk.c b/release/libdisk/chunk.c new file mode 100644 index 0000000..906911a --- /dev/null +++ b/release/libdisk/chunk.c @@ -0,0 +1,433 @@ +/* + * ---------------------------------------------------------------------------- + * "THE BEER-WARE LICENSE" (Revision 42): + * <phk@login.dknet.dk> 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: chunk.c,v 1.14.2.2 1995/06/05 02:24:25 jkh Exp $ + * + */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <sys/types.h> +#include <err.h> +#include "libdisk.h" + +#define new_chunk() memset(malloc(sizeof(struct chunk)), 0, sizeof(struct chunk)) + +/* Is c2 completely inside c1 ? */ + +static int +Chunk_Inside(struct chunk *c1, struct chunk *c2) +{ + /* if c1 ends before c2 do */ + if (c1->end < c2->end) + return 0; + /* if c1 starts after c2 do */ + if (c1->offset > c2->offset) + return 0; + return 1; +} + +struct chunk * +Find_Mother_Chunk(struct chunk *chunks, u_long offset, u_long end, chunk_e type) +{ + struct chunk *c1,*c2,ct; + ct.offset = offset; + ct.end = end; + switch (type) { + case whole: + if (Chunk_Inside(chunks,&ct)) + return chunks; + case extended: + for(c1=chunks->part;c1;c1=c1->next) { + if (c1->type != type) + continue; + if (Chunk_Inside(c1,&ct)) + return c1; + } + return 0; + case freebsd: + for(c1=chunks->part;c1;c1=c1->next) { + if (c1->type == type) + if (Chunk_Inside(c1,&ct)) + return c1; + if (c1->type != extended) + continue; + for(c2=c1->part;c2;c2=c2->next) + if (c2->type == type + && Chunk_Inside(c2,&ct)) + return c2; + } + return 0; + default: + warn("Unsupported mother (0x%x) in Find_Mother_Chunk"); + return 0; + } +} + +void +Free_Chunk(struct chunk *c1) +{ + if(!c1) return; + if(c1->private && c1->private_free) + (*c1->private_free)(c1->private); + if(c1->part) + Free_Chunk(c1->part); + if(c1->next) + Free_Chunk(c1->next); + free(c1->name); + free(c1); +} + +struct chunk * +Clone_Chunk(struct chunk *c1) +{ + struct chunk *c2; + if(!c1) + return 0; + c2 = new_chunk(); + if (!c2) err(1,"malloc failed"); + *c2 = *c1; + if (c1->private && c1->private_clone) + c2->private = c2->private_clone(c2->private); + c2->name = strdup(c2->name); + c2->next = Clone_Chunk(c2->next); + c2->part = Clone_Chunk(c2->part); + return c2; +} + +int +Insert_Chunk(struct chunk *c2, u_long offset, u_long size, char *name, chunk_e type, int subtype, u_long flags) +{ + struct chunk *ct,*cs; + + /* We will only insert into empty spaces */ + if (c2->type != unused) + return __LINE__; + + ct = new_chunk(); + if (!ct) err(1,"malloc failed"); + memset(ct,0,sizeof *ct); + ct->disk = c2->disk; + ct->offset = offset; + ct->size = size; + ct->end = offset + size - 1; + ct->type = type; + ct->name = strdup(name); + ct->subtype = subtype; + ct->flags = flags; + + if (!Chunk_Inside(c2,ct)) { + Free_Chunk(ct); + return __LINE__; + } + + if(type==freebsd || type==extended) { + cs = new_chunk(); + if (!cs) err(1,"malloc failed"); + memset(cs,0,sizeof *cs); + cs->disk = c2->disk; + cs->offset = offset; + cs->size = size; + cs->end = offset + size - 1; + cs->type = unused; + cs->name = strdup("-"); + ct->part = cs; + } + + /* Make a new chunk for any trailing unused space */ + if (c2->end > ct->end) { + cs = new_chunk(); + if (!cs) err(1,"malloc failed"); + *cs = *c2; + cs->disk = c2->disk; + cs->offset = ct->end + 1; + cs->size = c2->end - ct->end; + if(c2->name) + cs->name = strdup(c2->name); + c2->next = cs; + c2->size -= c2->end - ct->end; + c2->end = ct->end; + } + /* If no leading unused space just occupy the old chunk */ + if (c2->offset == ct->offset) { + c2->name = ct->name; + c2->type = ct->type; + c2->part = ct->part; + c2->subtype = ct->subtype; + c2->flags = ct->flags; + ct->name = 0; + ct->part = 0; + Free_Chunk(ct); + return 0; + } + /* else insert new chunk and adjust old one */ + c2->end = ct->offset - 1; + c2->size -= ct->size; + ct->next = c2->next; + c2->next = ct; + return 0; +} + +int +Add_Chunk(struct disk *d, long offset, u_long size, char *name, chunk_e type, + int subtype, u_long flags) +{ + struct chunk *c1,*c2,ct; + u_long end = offset + size - 1; + ct.offset = offset; + ct.end = end; + ct.size = size; + + if (type == whole) { + d->chunks = c1 = new_chunk(); + if (!c1) err(1,"malloc failed"); + memset(c1,0,sizeof *c1); + c2 = c1->part = new_chunk(); + if (!c2) err(1,"malloc failed"); + memset(c2,0,sizeof *c2); + c2->disk = c1->disk = d; + c2->offset = c1->offset = offset; + c2->size = c1->size = size; + c2->end = c1->end = end; + c1->name = strdup(name); + c2->name = strdup("-"); + c1->type = type; + c2->type = unused; + c1->flags = flags; + c1->subtype = subtype; + return 0; + } + if (type == freebsd) + subtype = 0xa5; + c1 = 0; + if(!c1 && (type == freebsd || type == fat || type == unknown)) + c1 = Find_Mother_Chunk(d->chunks,offset,end,extended); + if(!c1 && (type == freebsd || type == fat || type == unknown)) + c1 = Find_Mother_Chunk(d->chunks,offset,end,whole); + if(!c1 && type == extended) + c1 = Find_Mother_Chunk(d->chunks,offset,end,whole); + if(!c1 && type == part) + c1 = Find_Mother_Chunk(d->chunks,offset,end,freebsd); + if(!c1) + return __LINE__; + for(c2=c1->part;c2;c2=c2->next) { + if (c2->type != unused) + continue; + if(Chunk_Inside(c2,&ct)) { + if (type != freebsd) + goto doit; + if (!(flags & CHUNK_ALIGN)) + goto doit; + if (offset == d->chunks->offset + && end == d->chunks->end) + goto doit; + + /* Round down to prev cylinder */ + offset = Prev_Cyl_Aligned(d,offset); + /* Stay inside the parent */ + if (offset < c2->offset) + offset = c2->offset; + /* Round up to next cylinder */ + offset = Next_Cyl_Aligned(d,offset); + /* Keep one track clear in front of parent */ + if (offset == c1->offset) + offset = Next_Track_Aligned(d,offset+1); + + /* Work on the (end+1) */ + size += offset; + /* Round up to cylinder */ + size = Next_Cyl_Aligned(d,size); + /* Stay inside parent */ + if ((size-1) > c2->end) + size = c2->end+1; + /* Round down to cylinder */ + size = Prev_Cyl_Aligned(d,size); + + /* Convert back to size */ + size -= offset; + + doit: + return Insert_Chunk(c2,offset,size,name, + type,subtype,flags); + } + } + return __LINE__; +} + +char * +ShowChunkFlags(struct chunk *c) +{ + static char ret[10]; + + int i=0; + if (c->flags & CHUNK_BSD_COMPAT) ret[i++] = 'C'; + if (c->flags & CHUNK_ACTIVE) ret[i++] = 'A'; + if (c->flags & CHUNK_ALIGN) ret[i++] = '='; + if (c->flags & CHUNK_PAST_1024) ret[i++] = '>'; + if (c->flags & CHUNK_IS_ROOT) ret[i++] = 'R'; + if (c->flags & CHUNK_BAD144) ret[i++] = 'B'; + ret[i++] = '\0'; + return ret; +} + +void +Print_Chunk(struct chunk *c1,int offset) +{ + int i; + if(!c1) return; + for(i=0;i<offset-2;i++) putchar(' '); + for(;i<offset;i++) putchar('-'); + putchar('>'); + for(;i<10;i++) putchar(' '); + printf("%p %8ld %8lu %8lu %-8s %-8s 0x%02x %s", + c1, c1->offset, c1->size, c1->end, c1->name, + chunk_n[c1->type],c1->subtype, + ShowChunkFlags(c1)); + putchar('\n'); + Print_Chunk(c1->part,offset + 2); + Print_Chunk(c1->next,offset); +} + +void +Debug_Chunk(struct chunk *c1) +{ + Print_Chunk(c1,2); +} + +void +Bios_Limit_Chunk(struct chunk *c1, u_long limit) +{ + if (c1->part) + Bios_Limit_Chunk(c1->part,limit); + if (c1->next) + Bios_Limit_Chunk(c1->next,limit); + if (c1->end >= limit) { + c1->flags |= CHUNK_PAST_1024; + } else { + c1->flags &= ~CHUNK_PAST_1024; + } +} + +int +Delete_Chunk(struct disk *d, struct chunk *c) +{ + struct chunk *c1=0,*c2,*c3; + chunk_e type = c->type; + + if(type == whole) + return 1; + if(!c1 && (type == freebsd || type == fat || type == unknown)) + c1 = Find_Mother_Chunk(d->chunks,c->offset,c->end,extended); + if(!c1 && (type == freebsd || type == fat || type == unknown)) + c1 = Find_Mother_Chunk(d->chunks,c->offset,c->end,whole); + if(!c1 && type == extended) + c1 = Find_Mother_Chunk(d->chunks,c->offset,c->end,whole); + if(!c1 && type == part) + c1 = Find_Mother_Chunk(d->chunks,c->offset,c->end,freebsd); + if(!c1) + return 1; + for(c2=c1->part;c2;c2=c2->next) { + if (c2 == c) { + c2->type = unused; + c2->subtype = 0; + c2->flags = 0; + free(c2->name); + c2->name = strdup("-"); + Free_Chunk(c2->part); + c2->part =0; + goto scan; + } + } + return 1; + scan: + for(c2=c1->part;c2;c2=c2->next) { + if (c2->type != unused) + continue; + if (!c2->next) + continue; + if (c2->next->type != unused) + continue; + c3 = c2->next; + c2->size += c3->size; + c2->end = c3->end; + c2->next = c3->next; + c3->next = 0; + Free_Chunk(c3); + goto scan; + } + Fixup_Names(d); + return 0; +} + +#if 0 +int +Collapse_Chunk(struct disk *d, struct chunk *c1) +{ + struct chunk *c2, *c3; + + if(c1->next && Collapse_Chunk(d,c1->next)) + return 1; + + if(c1->type == unused && c1->next && c1->next->type == unused) { + c3 = c1->next; + c1->size += c3->size; + c1->end = c3->end; + c1->next = c3->next; + c3->next = 0; + Free_Chunk(c3); + return 1; + } + c3 = c1->part; + if(!c3) + return 0; + if (Collapse_Chunk(d,c1->part)) + return 1; + + if (c1->type == whole) + return 0; + + if(c3->type == unused && c3->size == c1->size) { + Delete_Chunk(d,c1); + return 1; + } + if(c3->type == unused) { + c2 = new_chunk(); + if (!c2) err(1,"malloc failed"); + *c2 = *c1; + c1->next = c2; + c1->disk = d; + c1->name = strdup("-"); + c1->part = 0; + c1->type = unused; + c1->flags = 0; + c1->subtype = 0; + c1->size = c3->size; + c1->end = c3->end; + c2->offset += c1->size; + c2->size -= c1->size; + c2->part = c3->next; + c3->next = 0; + Free_Chunk(c3); + return 1; + } + for(c2=c3;c2->next;c2 = c2->next) + c3 = c2; + if (c2 && c2->type == unused) { + c3->next = 0; + c2->next = c1->next; + c1->next = c2; + c1->size -= c2->size; + c1->end -= c2->size; + return 1; + } + + return 0; +} +#endif diff --git a/release/libdisk/create_chunk.c b/release/libdisk/create_chunk.c new file mode 100644 index 0000000..ad0c802 --- /dev/null +++ b/release/libdisk/create_chunk.c @@ -0,0 +1,297 @@ +/* + * ---------------------------------------------------------------------------- + * "THE BEER-WARE LICENSE" (Revision 42): + * <phk@login.dknet.dk> 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.20.2.1 1995/05/31 23:53:45 jkh Exp $ + * + */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <ctype.h> +#include <sys/types.h> +#include <sys/disklabel.h> +#include <sys/diskslice.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <err.h> +#include "libdisk.h" + +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;j<strlen(order);j++) { + sprintf(c1->name,"%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; + 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); + } + 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; + + /* 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; + } + warn("Not enough unused space"); + 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) { + warn("Didn't cut it"); + 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, char *path) +{ + char *p = c1->name; + u_long cmaj,bmaj,min,unit,part,slice; + char buf[BUFSIZ],buf2[BUFSIZ]; + + *buf2 = '\0'; + + if(!strcmp(p,"X")) + return 0; + + if (p[0] == 'w' && p[1] == 'd') { + bmaj = 0; cmaj = 3; + } else if (p[0] == 's' && p[1] == 'd') { + bmaj = 4; cmaj = 13; + } else { + return 0; + } + p += 2; + if (!isdigit(*p)) + return 0; + unit = *p - '0'; + p++; + if (isdigit(*p)) { + unit *= 10; + unit = *p - '0'; + p++; + } + if (!*p) { + slice = 1; + part = 2; + goto done; + } + if (*p != 's') + return 0; + p++; + if (!isdigit(*p)) + return 0; + slice = *p - '0'; + p++; + if (isdigit(*p)) { + slice *= 10; + slice = *p - '0'; + p++; + } + slice = slice+1; + if (!*p) { + part = 2; + if(c1->type == freebsd) + sprintf(buf2,"%sc",c1->name); + goto done; + } + if (*p < 'a' || *p > 'h') + return 0; + part = *p - 'a'; + done: + 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); mknod(buf,S_IFCHR|0640,makedev(cmaj,min)); + if(*buf2) { + sprintf(buf,"%s/r%s",path,buf2); + unlink(buf); mknod(buf,S_IFCHR|0640,makedev(cmaj,min)); + } + sprintf(buf,"%s/%s",path,c1->name); + unlink(buf); mknod(buf,S_IFBLK|0640,makedev(bmaj,min)); + return 1; +} + +void +MakeDevChunk(struct chunk *c1,char *path) +{ + MakeDev(c1,path); + if (c1->next) MakeDevChunk(c1->next,path); + if (c1->part) MakeDevChunk(c1->part,path); +} + +void +MakeDevDisk(struct disk *d,char *path) +{ + MakeDevChunk(d->chunks,path); +} diff --git a/release/libdisk/disk.c b/release/libdisk/disk.c new file mode 100644 index 0000000..cfac7b5 --- /dev/null +++ b/release/libdisk/disk.c @@ -0,0 +1,327 @@ +/* + * ---------------------------------------------------------------------------- + * "THE BEER-WARE LICENSE" (Revision 42): + * <phk@login.dknet.dk> 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.19.2.2 1995/06/05 02:24:27 jkh Exp $ + * + */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <fcntl.h> +#include <string.h> +#include <err.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/ioctl.h> +#include <sys/disklabel.h> +#include <sys/diskslice.h> +#include "libdisk.h" + +#define DOSPTYP_EXTENDED 5 +#define DOSPTYP_ONTRACK 84 + +char *chunk_n[] = { + "whole", + "unknown", + "fat", + "freebsd", + "extended", + "part", + "unused", + NULL +}; + +struct disk * +Open_Disk(char *name) +{ + return Int_Open_Disk(name,0); +} + +struct disk * +Int_Open_Disk(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) { + warn("open(%s) failed",device); + return 0; + } + + memset(&dl,0,sizeof dl); + ioctl(fd,DIOCGDINFO,&dl); + i = ioctl(fd,DIOCGSLICEINFO,&ds); + if (i < 0) { + warn("DIOCGSLICEINFO(%s) failed",device); + close(fd); + return 0; + } + +#ifdef DEBUG + for(i=0;i<ds.dss_nslices;i++) + if(ds.dss_slices[i].ds_openmask) + printf(" open(%d)=0x%2x", + i,ds.dss_slices[i].ds_openmask); + printf("\n"); +#endif + + if (!size) + size = ds.dss_slices[WHOLE_DISK_SLICE].ds_size; + + p = read_block(fd,0); + dp = (struct dos_partition*)(p+DOSPARTOFF); + for(i=0;i<NDOSPART;i++) { + if (dp->dp_start >= size) continue; + if (dp->dp_start+dp->dp_size >= size) continue; + if (!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)) + warn("Failed to add 'whole' chunk"); + + for(i=BASE_SLICE;i<ds.dss_nslices;i++) { + char sname[20]; + chunk_e ce; + u_long flags=0; + int subtype=0; + if (! ds.dss_slices[i].ds_size) + continue; + ds.dss_slices[i].ds_offset -= offset; + sprintf(sname,"%ss%d",name,i-1); + subtype = ds.dss_slices[i].ds_type; + switch (ds.dss_slices[i].ds_type) { + case 0xa5: + ce = freebsd; + break; + case 0x1: + case 0x6: + case 0x4: + ce = fat; + break; + case DOSPTYP_EXTENDED: + ce = extended; + break; + default: + ce = unknown; + break; + } + if (Add_Chunk(d,ds.dss_slices[i].ds_offset, + ds.dss_slices[i].ds_size, sname,ce,subtype,flags)) + warn("failed to add chunk for slice %d",i - 1); + + if (ds.dss_slices[i].ds_type != 0xa5) + continue; + { + struct disklabel dl; + char pname[20]; + int j,k; + + strcpy(pname,"/dev/r"); + strcat(pname,sname); + j = open(pname,O_RDONLY); + if (j < 0) { + warn("open(%s)",pname); + continue; + } + k = ioctl(j,DIOCGDINFO,&dl); + if (k < 0) { + warn("ioctl(%s,DIOCGDINFO)",pname); + close(j); + continue; + } + close(j); + + 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[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) + warn( + "Failed to add chunk for partition %c [%lu,%lu]", + j + 'a',dl.d_partitions[j].p_offset, + dl.d_partitions[j].p_size); + } + } + } + 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\n",d->bios_cyl,d->bios_hd,d->bios_sect); + printf(" boot1=%p, boot2=%p, bootmgr=%p\n", + d->boot1,d->boot2,d->bootmgr); + 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(d->boot2) free(d->boot2); + 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(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); + } + return d2; +} + +#if 0 +void +Collapse_Disk(struct disk *d) +{ + + while(Collapse_Chunk(d,d->chunks)) + ; +} +#endif + +static char * device_list[] = {"wd","sd",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 < 10; 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, 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, u_char *b1, u_char *b2) +{ + 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); +} diff --git a/release/libdisk/disklabel.c b/release/libdisk/disklabel.c new file mode 100644 index 0000000..9714e6c --- /dev/null +++ b/release/libdisk/disklabel.c @@ -0,0 +1,33 @@ +/* + * ---------------------------------------------------------------------------- + * "THE BEER-WARE LICENSE" (Revision 42): + * <phk@login.dknet.dk> 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$ + * + */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <err.h> +#include <sys/disklabel.h> +#include "libdisk.h" + +struct disklabel * +read_disklabel(int fd, daddr_t block) +{ + struct disklabel *dp; + + dp = (struct disklabel *) read_block(fd,block); + if (dp->d_magic != DISKMAGIC) + return 0; + if (dp->d_magic2 != DISKMAGIC) + return 0; + if (dkcksum(dp) != 0) + return 0; + return dp; +} diff --git a/release/libdisk/libdisk.h b/release/libdisk/libdisk.h new file mode 100644 index 0000000..e7d6bd3 --- /dev/null +++ b/release/libdisk/libdisk.h @@ -0,0 +1,315 @@ +/* + * ---------------------------------------------------------------------------- + * "THE BEER-WARE LICENSE" (Revision 42): + * <phk@login.dknet.dk> 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: libdisk.h,v 1.18.2.2 1995/06/05 02:24:32 jkh Exp $ + * + */ + +#define MAX_NO_DISKS 20 + /* Max # of disks Disk_Names() will return */ + +typedef enum { + whole, + unknown, + fat, + freebsd, + extended, + part, + unused, + } chunk_e; + +extern char *chunk_n[]; + +struct disk { + char *name; + u_long flags; +# define DISK_ON_TRACK 1 +#if 0 + u_long real_cyl; + u_long real_hd; + u_long real_sect; +#endif + u_long bios_cyl; + u_long bios_hd; + u_long bios_sect; + u_char *bootmgr; + u_char *boot1; + u_char *boot2; + struct chunk *chunks; +}; + +struct chunk { + struct chunk *next; + struct chunk *part; + struct disk *disk; + long offset; + u_long size; + u_long end; + char *name; + char *oname; + /* Used during Fixup_Names() to avoid renaming more than + * absolutely needed. + */ + chunk_e type; + int subtype; + u_long flags; +# define CHUNK_PAST_1024 1 + /* this chunk cannot be booted from because it + * extends past cylinder 1024 + */ +# define CHUNK_BSD_COMPAT 2 + /* this chunk is in the BSD-compatibility, and has a + * short name too, ie wd0s4f -> wd0f + */ +# define CHUNK_BAD144 4 + /* this chunk has bad144 mapping */ +# define CHUNK_ALIGN 8 + /* This chunk should be aligned */ +# define CHUNK_IS_ROOT 16 + /* This 'part' is a rootfs, allocate 'a' */ +# define CHUNK_ACTIVE 32 + /* This is the active slice in the MBR */ + + void (*private_free)(void*); + void *(*private_clone)(void*); + void *private; + /* For data private to the application, and the management + * thereof. If the functions are not provided, no storage + * management is done, Cloning will just copy the pointer + * and freeing will just forget it. + */ +}; + +struct disk * +Open_Disk(char *devname); + /* Will open the named disk, and return populated tree. + */ + +struct disk * +Clone_Disk(struct disk *disk); + /* Clone a copy of a tree. Useful for "Undo" functionality + */ + +void +Free_Disk(struct disk *disk); + /* Free a tree made with Open_Disk() or Clone_Disk() + */ + +void +Debug_Disk(struct disk *disk); + /* Print the content of the tree to stdout + */ + +#if 0 +struct disk * +Set_Phys_Geom(struct disk *disk, u_long cyl, u_long heads, u_long sects); + /* Use a different physical geometry. Makes sense for ST506 disks only. + * The tree returned is read from the disk, using this geometry. + */ +#endif + +void +Set_Bios_Geom(struct disk *disk, u_long cyl, u_long heads, u_long sects); + /* Set the geometry the bios uses. + */ + +int +Delete_Chunk(struct disk *disk, struct chunk *); + /* Free a chunk of disk_space + */ + +void +Collapse_Disk(struct disk *disk); + /* Experimental, do not use. + */ +int +Collapse_Chunk(struct disk *disk, struct chunk *chunk); + /* Experimental, do not use. + */ + +int +Create_Chunk(struct disk *disk, u_long offset, u_long size, chunk_e type, int subtype, u_long flags); + /* Create a chunk with the specified paramters + */ + +void +All_FreeBSD(struct disk *d); + /* Make one FreeBSD chunk covering the entire disk + */ + +char * +CheckRules(struct disk *); + /* Return char* to warnings about broken design rules in this disklayout + */ + +char ** +Disk_Names(); + /* Return char** with all disk's names (wd0, wd1 ...). You must free + * each pointer, as well as the array by hand + */ + +void +Set_Boot_Mgr(struct disk *d, u_char *bootmgr); + /* Use this boot-manager on this disk. Gets written when Write_Disk() + * is called + */ + +void +Set_Boot_Blocks(struct disk *d, u_char *boot1, u_char *boot2); + /* Use these boot-blocks on this disk. Gets written when Write_Disk() + * is called + */ + +int +Write_Disk(struct disk *d); + /* Write all the MBRs, disklabels, bootblocks and boot managers + */ + +int +Cyl_Aligned(struct disk *d, u_long offset); + /* Check if offset is aligned on a cylinder according to the + * bios geometry + */ + +u_long +Next_Cyl_Aligned(struct disk *d, u_long offset); + /* Round offset up to next cylinder according to the bios-geometry + */ + +u_long +Prev_Cyl_Aligned(struct disk *d, u_long offset); + /* Round offset down to previous cylinder according to the bios- + * geometry + */ + +int +Track_Aligned(struct disk *d, u_long offset); + /* Check if offset is aligned on a track according to the + * bios geometry + */ + +u_long +Next_Track_Aligned(struct disk *d, u_long offset); + /* Round offset up to next track according to the bios-geometry + */ + +u_long +Prev_Track_Aligned(struct disk *d, u_long offset); + /* Check if offset is aligned on a track according to the + * bios geometry + */ + +struct chunk * +Create_Chunk_DWIM(struct disk *d, struct chunk *parent , u_long size, chunk_e type, int subtype, u_long flags); + /* This one creates a partition inside the given parent of the given + * size, and returns a pointer to it. The first unused chunk big + * enough is used. + */ + +void +MakeDevDisk(struct disk *d,char *path); + /* Make device nodes for all chunks on this disk */ + +char * +ShowChunkFlags(struct chunk *c); + /* Return string to show flags. */ + +char * +ChunkCanBeRoot(struct chunk *c); + /* Return NULL if chunk can be /, explanation otherwise */ + +/* + * Implementation details >>> DO NOT USE <<< + */ + +void Debug_Chunk(struct chunk *); +void Free_Chunk(struct chunk *); +struct chunk * Clone_Chunk(struct chunk *); +int Add_Chunk(struct disk *, long , u_long , char *, chunk_e, int , u_long); +void Bios_Limit_Chunk(struct chunk *, u_long); +void * read_block(int, daddr_t ); +void write_block(int fd, daddr_t block, void *foo); +struct disklabel * read_disklabel(int, daddr_t); +u_short dkcksum(struct disklabel *); +struct chunk * Find_Mother_Chunk(struct chunk *, u_long , u_long , chunk_e); +struct disk * Int_Open_Disk(char *name, u_long size); +void Fixup_Names(struct disk *); + +#define dprintf printf + +/* TODO + * + * Need a error string mechanism from the functions instead of warn() + * + * Make sure only FreeBSD start at offset==0 + * + * Collapse must align. + * + * Make Write_Disk(struct disk*) + * + * Consider booting from OnTrack'ed disks. + * + * Get Bios-geom, ST506 & OnTrack from driver (or otherwise) + * + * Make Create_DWIM(). + * + * Make Is_Unchanged(struct disk *d1, struct chunk *c1) + * + * don't rename slices unless we have to + * + *Sample output from tst01: + * + * Debug_Disk(wd0) flags=0 real_geom=0/0/0 bios_geom=0/0/0 + * >> 0x3d040 0 1411200 1411199 wd0 0 whole 0 0 + * >>>> 0x3d080 0 960120 960119 wd0s1 3 freebsd 0 8 + * >>>>>> 0x3d100 0 40960 40959 wd0s1a 5 part 0 0 + * >>>>>> 0x3d180 40960 131072 172031 wd0s1b 5 part 0 0 + * >>>>>> 0x3d1c0 172032 409600 581631 wd0s1e 5 part 0 0 + * >>>>>> 0x3d200 581632 378488 960119 wd0s1f 5 part 0 0 + * >>>> 0x3d140 960120 5670 965789 wd0s2 4 extended 0 8 + * >>>>>> 0x3d2c0 960120 63 960182 - 6 unused 0 0 + * >>>>>> 0x3d0c0 960183 5607 965789 wd0s5 2 fat 0 8 + * >>>> 0x3d280 965790 1890 967679 wd0s3 1 foo -2 8 + * >>>> 0x3d300 967680 443520 1411199 wd0s4 3 freebsd 0 8 + * >>>>>> 0x3d340 967680 443520 1411199 wd0s4a 5 part 0 0 + * + * ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ + * level chunkptr start size end name type subtype flags + * + * Underlying data structure: + * + * Legend: + * <struct chunk> --> part + * | + * v next + * + * <wd0> --> <wd0s1> --> <wd0s1a> + * | | + * | v + * | <wd0s1b> + * | | + * | v + * | <wd0s1e> + * | | + * | v + * | <wd0s1f> + * | + * v + * <wd0s2> --> <unused> + * | | + * | v + * | <wd0s5> + * | + * v + * <wd0s3> + * | + * v + * <wd0s4> --> <wd0s4a> + * + * + */ diff --git a/release/libdisk/rules.c b/release/libdisk/rules.c new file mode 100644 index 0000000..1ea9ca8 --- /dev/null +++ b/release/libdisk/rules.c @@ -0,0 +1,316 @@ +/* + * ---------------------------------------------------------------------------- + * "THE BEER-WARE LICENSE" (Revision 42): + * <phk@login.dknet.dk> 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: rules.c,v 1.10.2.1 1995/06/03 08:40:33 jkh Exp $ + * + */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <sys/types.h> +#include <sys/diskslice.h> +#include <sys/disklabel.h> +#include <err.h> +#include "libdisk.h" + +int +Track_Aligned(struct disk *d, u_long offset) +{ + if (!d->bios_sect) + return 1; + if (offset % d->bios_sect) + return 0; + return 1; +} + +u_long +Prev_Track_Aligned(struct disk *d, u_long offset) +{ + if (!d->bios_sect) + return offset; + return (offset / d->bios_sect) * d->bios_sect; +} + +u_long +Next_Track_Aligned(struct disk *d, u_long offset) +{ + if (!d->bios_sect) + return offset; + return Prev_Track_Aligned(d,offset + d->bios_sect-1); +} + +int +Cyl_Aligned(struct disk *d, u_long offset) +{ + if (!d->bios_sect || !d->bios_hd) + return 1; + if (offset % (d->bios_sect * d->bios_hd)) + return 0; + return 1; +} + +u_long +Prev_Cyl_Aligned(struct disk *d, u_long offset) +{ + if (!d->bios_sect || !d->bios_hd) + return offset; + return (offset / (d->bios_sect*d->bios_hd)) * d->bios_sect * d->bios_hd; +} + +u_long +Next_Cyl_Aligned(struct disk *d, u_long offset) +{ + if (!d->bios_sect || !d->bios_hd) + return offset; + return Prev_Cyl_Aligned(d,offset + (d->bios_sect * d->bios_hd)-1); +} + +/* + * Rule#0: + * Chunks of type 'whole' can have max NDOSPART children. + * Only one of them can have the "active" flag + */ +void +Rule_000(struct disk *d, struct chunk *c, char *msg) +{ + int i=0,j=0; + struct chunk *c1; + + if (c->type != whole) + return; + for (c1=c->part; c1; c1=c1->next) { + if (c1->type != unused) continue; + if (c1->flags & CHUNK_ACTIVE) + j++; + i++; + } + if (i > NDOSPART) + sprintf(msg+strlen(msg), + "%d is too many children of the 'whole' chunk. Max is %d\n", + i, NDOSPART); + if (j > 1) + sprintf(msg+strlen(msg), + "Too many active children of 'whole'"); +} + +/* + * Rule#1: + * All children of 'whole' and 'extended' must be track-aligned. + * Exception: the end can be unaligned if it matches the end of 'whole' + */ +void +Rule_001(struct disk *d, struct chunk *c, char *msg) +{ + int i; + struct chunk *c1; + + if (c->type != whole && c->type != extended) + return; + for (i=0, c1=c->part; c1; c1=c1->next) { + if (c1->type == unused) continue; + c1->flags |= CHUNK_ALIGN; + if (!Track_Aligned(d,c1->offset)) + sprintf(msg+strlen(msg), + "chunk '%s' [%ld..%ld] does not start on a track boundary\n", + c1->name,c1->offset,c1->end); + if ((c->type == whole || c->end == c1->end) + || Cyl_Aligned(d,c1->end+1)) + ; + else + sprintf(msg+strlen(msg), + "chunk '%s' [%ld..%ld] does not end on a cylinder boundary\n", + c1->name,c1->offset,c1->end); + } +} + +/* + * Rule#2: + * Max one 'fat' as child of 'whole' + */ +void +Rule_002(struct disk *d, struct chunk *c, char *msg) +{ + int i; + struct chunk *c1; + + if (c->type != whole) + return; + for (i=0, c1=c->part; c1; c1=c1->next) { + if (c1->type != fat) + continue; + i++; + } + if (i > 1) { + sprintf(msg+strlen(msg), + "Max one 'fat' allowed as child of 'whole'\n"); + } +} + +/* + * Rule#3: + * Max one extended as child of 'whole' + */ +void +Rule_003(struct disk *d, struct chunk *c, char *msg) +{ + int i; + struct chunk *c1; + + if (c->type != whole) + return; + for (i=0, c1=c->part; c1; c1=c1->next) { + if (c1->type != extended) + continue; + i++; + } + if (i > 1) { + sprintf(msg+strlen(msg), + "Max one 'extended' allowed as child of 'whole'\n"); + } +} + +/* + * Rule#4: + * Max seven 'part' as children of 'freebsd' + * Max one CHUNK_IS_ROOT child per 'freebsd' + * If Bad144, space for table must exist. + * If Bad144 & root, bad144 table must be inside 1024 + */ +void +Rule_004(struct disk *d, struct chunk *c, char *msg) +{ + int i=0,k=0; + struct chunk *c1; + u_long l; + + if (c->type != freebsd) + return; + + if (c->flags & CHUNK_BAD144) { + l = c->end - 127 - d->bios_sect + 1; + for (c1=c->part; c1; c1=c1->next) { + if (c1->end < l || c1->type == unused) + continue; + sprintf(msg+strlen(msg), + "Blocks %lu to %lu are needed for bad144 information, but isn't unused.\n", + l, c->end); + break; + } + if (c->flags & CHUNK_PAST_1024) { + for (c1=c->part; c1; c1=c1->next) { + if (c1->flags & CHUNK_IS_ROOT) { + sprintf(msg+strlen(msg), + "You have assigned root to a slice which uses bad144, and\n extends past the first 1023 cylinders, and thus cannot be booted from.\n"); + break; + } + } + } + } + + for (c1=c->part; c1; c1=c1->next) { + if (c1->type != part) + continue; + if (c1->flags & CHUNK_IS_ROOT) { + k++; + if (c1->flags & CHUNK_PAST_1024) + sprintf(msg+strlen(msg), + "Root filesystem extends past cylinder 1024, and cannot be booted from\n"); + } + i++; + } + if (i > 7) { + sprintf(msg+strlen(msg), + "Max seven partitions per freebsd slice\n"); + } + if (k > 1) { + sprintf(msg+strlen(msg), + "Max one root partition child per freebsd slice\n"); + } +} + +void +Check_Chunk(struct disk *d, struct chunk *c, char *msg) +{ + Rule_000(d,c,msg); + Rule_001(d,c,msg); + Rule_002(d,c,msg); + Rule_003(d,c,msg); + Rule_004(d,c,msg); + if (c->part) + Check_Chunk(d,c->part,msg); + if (c->next) + Check_Chunk(d,c->next,msg); + + if (c->end >= 1024*d->bios_hd*d->bios_sect) + c->flags |= CHUNK_PAST_1024; + else + c->flags &= ~CHUNK_PAST_1024; +} + +char * +CheckRules(struct disk *d) +{ + char msg[BUFSIZ]; + + *msg = '\0'; + Check_Chunk(d,d->chunks,msg); + if (*msg) + return strdup(msg); + return 0; +} + +char * +ChunkCanBeRoot(struct chunk *c) +{ + struct chunk *c1; + struct disk *d = c->disk; + char msg[BUFSIZ]; + + *msg = '\0'; + if (c->flags & CHUNK_PAST_1024) { + strcat(msg, +"The root partition must end before cylinder 1024 seen from\n"); + strcat(msg, +"the BIOS' point of view, or it cannot be booted from.\n"); + return strdup(msg); + } + for (c1=d->chunks->part;;) { + for (; c1; c1=c1->next) + if (c1->offset <= c->offset && c1->end >= c->end) + break; + if (!c1) { + strcat(msg, +"Internal trouble, cannot find this chunk in the chunk-tree\n"); + return strdup(msg); + } + if (c1->type == freebsd) + break; + c1 = c1->part; + } + + if (c1->type != freebsd) { + strcat(msg, +"The root partition must be in a FreeBSD slice, otherwise\n"); + strcat(msg, +"the kernel cannot be booted from it\n"); + return strdup(msg); + } + + if ((c1->flags & CHUNK_BAD144) && (c1->flags & CHUNK_PAST_1024)) { + strcat(msg, +"This partition is unsuitable for root, because the FreeBSD slice\n"); + strcat(msg, +"it is inside has bad144 enabled, but the badblock data lives past\n"); + strcat(msg, +"the 1024th cylinder, and the bootblocks cannot get to it there.\n"); + return strdup(msg); + } + return NULL; +} diff --git a/release/libdisk/tst01.c b/release/libdisk/tst01.c new file mode 100644 index 0000000..2793778 --- /dev/null +++ b/release/libdisk/tst01.c @@ -0,0 +1,308 @@ +/* + * ---------------------------------------------------------------------------- + * "THE BEER-WARE LICENSE" (Revision 42): + * <phk@login.dknet.dk> 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: tst01.c,v 1.14.2.1 1995/06/05 02:24:35 jkh Exp $ + * + */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <fcntl.h> +#include <string.h> +#include <err.h> +#ifdef READLINE +#include <readline/readline.h> +#include <readline/history.h> +#endif +#include <sys/types.h> +#include "libdisk.h" + +u_char mbr[] = { +250,51,192,142,208,188,0,124,139,244,80,7,80,31,251,252,191,0,6,185,0,1, +242,165,234,29,6,0,0,190,190,7,179,4,128,60,128,116,14,128,60,0,117,28, +131,198,16,254,203,117,239,205,24,139,20,139,76,2,139,238,131,198,16,254, +203,116,26,128,60,0,116,244,190,139,6,172,60,0,116,11,86,187,7,0,180,14, +205,16,94,235,240,235,254,191,5,0,187,0,124,184,1,2,87,205,19,95,115,12, +51,192,205,19,79,117,237,190,163,6,235,211,190,194,6,191,254,125,129,61, +85,170,117,199,139,245,234,0,124,0,0,73,110,118,97,108,105,100,32,112,97, +114,116,105,116,105,111,110,32,116,97,98,108,101,0,69,114,114,111,114,32, +108,111,97,100,105,110,103,32,111,112,101,114,97,116,105,110,103,32,115, +121,115,116,101,109,0,77,105,115,115,105,110,103,32,111,112,101,114,97, +116,105,110,103,32,115,121,115,116,101,109,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,128, +1,1,0,4,15,63,60,63,0,0,0,241,239,0,0,0,0,1,61,5,15,63,243,48,240,0,0,144, +208,2,0,0,0,1,244,165,15,63,170,192,192,3,0,144,208,2,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,85,170 +}; + +u_char bteasy17[] = { +51,192,142,192,142,216,142,208,188,0,124,252,139,244,191,0,6,185,0,1,242, +165,234,96,6,0,0,139,213,88,162,72,7,60,53,116,28,180,16,246,228,5,174, +4,150,246,68,4,255,116,62,198,4,128,232,218,0,138,116,1,139,76,2,235,8, +232,207,0,185,1,0,50,209,187,0,124,184,1,2,205,19,114,30,129,191,254,1, +85,170,117,22,234,0,124,0,0,128,250,129,116,2,178,128,139,234,66,128,242, +179,136,22,58,7,191,190,7,185,4,0,198,6,45,7,49,50,246,136,45,138,69,4, +60,0,116,35,60,5,116,31,254,198,190,42,7,232,113,0,190,72,7,70,70,139,28, +10,255,116,5,50,125,4,117,243,141,183,114,7,232,90,0,131,199,16,254,6,45, +7,226,203,128,62,117,4,2,116,11,190,59,7,10,246,117,10,205,24,235,172,190, +42,7,232,57,0,232,54,0,50,228,205,26,139,218,131,195,96,180,1,205,22,180, +0,117,11,205,26,59,211,114,242,160,72,7,235,10,205,22,138,196,60,28,116, +243,4,246,60,49,114,214,60,53,119,210,80,190,40,7,187,27,6,83,252,172,80, +36,127,180,14,205,16,88,168,128,116,242,195,86,184,1,3,187,0,6,185,1,0, +50,246,205,19,94,198,6,72,7,63,195,13,138,13,10,70,48,32,46,32,46,32,46, +160,100,105,115,107,32,49,13,10,10,68,101,102,97,117,108,116,58,32,70,63, +160,0,1,0,4,0,6,3,7,7,10,10,99,14,100,14,101,20,128,20,129,25,130,30,147, +36,165,39,159,43,117,47,82,47,219,50,64,55,242,61,0,100,111,243,72,80,70, +211,79,115,178,85,110,105,248,78,111,118,101,108,236,77,105,110,105,248, +76,105,110,117,248,65,109,111,101,98,225,66,83,196,66,83,68,233,80,67,73, +216,67,80,205,86,101,110,105,248,68,111,115,115,101,227,63,191,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,85,170 +}; + +int +scan_block(int fd, daddr_t block) +{ + u_char foo[512]; + + if (-1 == lseek(fd,block * 512,SEEK_SET)) + err(1,"lseek"); + if (512 != read(fd,foo, 512)) + return 1; + return 0; +} + +void +Scan_Disk(struct disk *d) +{ + char device[64]; + u_long l; + int i,j,fd; + + strcpy(device,"/dev/r"); + strcat(device,d->name); + + fd = open(device,O_RDWR); + if (fd < 0) { + warn("open(%s) failed",device); + return; + } + for(i=-1,l=0;;l++) { + j = scan_block(fd,l); + if (j != i) { + if (i == -1) { + printf("%c: %lu.",j ? 'B' : 'G', l); + fflush(stdout); + } else if (i == 0) { + printf(".%lu\nB: %lu.",l-1,l); + fflush(stdout); + } else { + printf(".%lu\nG: %lu.",l-1,l); + fflush(stdout); + } + i = j; + } + } + close(fd); +} + +int +main(int argc, char **argv) +{ + struct disk *d,*db; + char myprompt[BUFSIZ]; +#ifndef READLINE + char input[BUFSIZ]; +#endif + char *p,*q=0; + char **cp,*cmds[200]; + int ncmd,i; + + if (argc < 2) { + fprintf(stderr,"Usage:\n\t%s diskname\n",argv[0]); + exit(1); + } + d = Open_Disk(argv[1]); + if (!d) + err(1,"Couldn't open disk %s",argv[1]); + + sprintf(myprompt,"%s %s> ",argv[0],argv[1]); + while(1) { + printf("--==##==--\n"); + p = CheckRules(d); + Debug_Disk(d); + if (p) { + printf("%s",p); + free(p); + } +#ifdef READLINE + if (q) + free(q); + q = p = readline(myprompt); +#else + printf(myprompt); + fflush(stdout); + q = p = fgets(input,sizeof(input),stdin); +#endif + if(!p) + break; + for(cp = cmds; (*cp = strsep(&p, " \t\n")) != NULL;) + if (**cp != '\0') + cp++; + ncmd = cp - cmds; + if(!ncmd) + continue; + if (!strcasecmp(*cmds,"quit")) { break; } + if (!strcasecmp(*cmds,"exit")) { break; } + if (!strcasecmp(*cmds,"q")) { break; } + if (!strcasecmp(*cmds,"x")) { break; } + if (!strcasecmp(*cmds,"dwim") && ncmd == 6) { + printf("dwim = %p\n", + Create_Chunk_DWIM(d, + (struct chunk *)strtol(cmds[1],0,0), + strtol(cmds[2],0,0), + strtol(cmds[3],0,0), + strtol(cmds[4],0,0), + strtol(cmds[5],0,0))); + continue; + } + if (!strcasecmp(*cmds,"mknod")) { + MakeDevDisk(d,"/tmp"); + continue; + } + if (!strcasecmp(*cmds,"delete") && ncmd == 2) { + printf("delete = %d\n", + Delete_Chunk(d, + (struct chunk *)strtol(cmds[1],0,0))); + continue; + } + if (!strcasecmp(*cmds,"allfreebsd")) { + All_FreeBSD(d); + continue; + } + if (!strcasecmp(*cmds,"bios") && ncmd == 4) { + Set_Bios_Geom(d, + strtol(cmds[1],0,0), + strtol(cmds[2],0,0), + strtol(cmds[3],0,0)); + continue; + } +#if 0 + if (!strcasecmp(*cmds,"phys") && ncmd == 4) { + d = Set_Phys_Geom(d, + strtol(cmds[1],0,0), + strtol(cmds[2],0,0), + strtol(cmds[3],0,0)); + continue; + } +#endif +#if 0 + if (!strcasecmp(*cmds,"collapse")) { + if (cmds[1]) + while (Collapse_Chunk(d, + (struct chunk *)strtol(cmds[1],0,0))) + ; + else + Collapse_Disk(d); + continue; + } +#endif + if (!strcasecmp(*cmds,"list")) { + cp = Disk_Names(); + printf("Disks:"); + for(i=0;cp[i];i++) { + printf(" %s",cp[i]); + free(cp[i]); + } + free(cp); + continue; + } + if (!strcasecmp(*cmds,"create") && ncmd == 6) { + + printf("Create=%d\n", + Create_Chunk(d, + strtol(cmds[1],0,0), + strtol(cmds[2],0,0), + strtol(cmds[3],0,0), + strtol(cmds[4],0,0), + strtol(cmds[5],0,0))); + continue; + } + if (!strcasecmp(*cmds,"read")) { + db = d; + if (ncmd > 1) + d = Open_Disk(cmds[1]); + else + d = Open_Disk(argv[1]); + if (d) + Free_Disk(db); + else + d = db; + continue; + } + if (!strcasecmp(*cmds,"scan")) { + Scan_Disk(d); + continue; + } + if (!strcasecmp(*cmds,"bteasy")) { + Set_Boot_Mgr(d,bteasy17); + continue; + } + if (!strcasecmp(*cmds,"mbr")) { + Set_Boot_Mgr(d,mbr); + continue; + } + if (!strcasecmp(*cmds,"boot")) { + extern u_char boot1[],boot2[]; + Set_Boot_Blocks(d,boot1,boot2); + continue; + } + if (!strcasecmp(*cmds,"write")) { + printf("Write=%d\n", + Write_Disk(d)); + Free_Disk(d); + d = Open_Disk(d->name); + continue; + } + if (strcasecmp(*cmds,"help")) + printf("\007ERROR\n"); + printf("CMDS:\n"); + printf("\tallfreebsd\n"); + printf("\tbios cyl hd sect\n"); + printf("\tboot\n"); + printf("\tbteasy17\n"); +#if 0 + printf("\tcollapse [pointer]\n"); +#endif + printf("\tcreate offset size enum subtype flags\n"); + printf("\t\tsubtype(part): swap=1, ffs=7\n"); + printf("\tdelete pointer\n"); + printf("\tlist\n"); + printf("\tmbr\n"); +#if 0 + printf("\tphys cyl hd sect\n"); +#endif + printf("\tquit\n"); + printf("\tread [disk]\n"); + printf("\tscan\n"); + printf("\twrite\n"); + printf("\nENUM:\n\t"); + for(i=0;chunk_n[i];i++) + printf("%d = %s%s",i,chunk_n[i],i == 4 ? "\n\t" : " "); + printf("\n"); + + } + exit (0); +} diff --git a/release/libdisk/write_disk.c b/release/libdisk/write_disk.c new file mode 100644 index 0000000..e745917 --- /dev/null +++ b/release/libdisk/write_disk.c @@ -0,0 +1,233 @@ +/* + * ---------------------------------------------------------------------------- + * "THE BEER-WARE LICENSE" (Revision 42): + * <phk@login.dknet.dk> 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: write_disk.c,v 1.14 1995/06/11 19:29:38 rgrimes Exp $ + * + */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <fcntl.h> +#include <string.h> +#include <err.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/ioctl.h> +#include <sys/disklabel.h> +#include <sys/diskslice.h> +#include "libdisk.h" + +#define DOSPTYP_EXTENDED 5 +#define BBSIZE 8192 +#define SBSIZE 8192 +#define DEF_RPM 3600 +#define DEF_INTERLEAVE 1 + +#define WHERE(offset,disk) (disk->flags & DISK_ON_TRACK ? offset + 63 : offset) +int +Write_FreeBSD(int fd, struct disk *new, struct disk *old, struct chunk *c1) +{ + struct disklabel *dl; + struct chunk *c2; + int i,j; + void *p; + u_char buf[BBSIZE]; + + for(i=0;i<BBSIZE/512;i++) { + p = read_block(fd,WHERE(i + c1->offset,new)); + memcpy(buf+512*i,p,512); + free(p); + } + if(new->boot1) + memcpy(buf,new->boot1,512); + + if(new->boot2) + memcpy(buf+512,new->boot2,BBSIZE-512); + + dl = (struct disklabel *) (buf+512*LABELSECTOR+LABELOFFSET); + memset(dl,0,sizeof *dl); + + for(c2=c1->part;c2;c2=c2->next) { + if (c2->type == unused) continue; + if (!strcmp(c2->name,"X")) continue; + j = c2->name[5] - 'a'; + if (j < 0 || j >= MAXPARTITIONS || j == RAW_PART) { + warn("Weird parititon letter %c",c2->name[5]); + continue; + } + dl->d_partitions[j].p_size = c2->size; + dl->d_partitions[j].p_offset = c2->offset; + dl->d_partitions[j].p_fstype = c2->subtype; + } + + dl->d_bbsize = BBSIZE; + /* + * Add in defaults for superblock size, interleave, and rpms + */ + dl->d_sbsize = SBSIZE; + dl->d_interleave = DEF_INTERLEAVE; + dl->d_rpm = DEF_RPM; + + strcpy(dl->d_typename,c1->name); + + dl->d_secsize = 512; + dl->d_secperunit = new->chunks->size; +#if 0 + dl->d_secpercyl = new->real_cyl ? new->real_cyl : new->bios_cyl; + dl->d_ntracks = new->real_hd ? new->real_hd : new->bios_hd; + dl->d_nsectors = new->real_sect ? new->real_sect : new->bios_sect; +#else + dl->d_secpercyl = new->bios_cyl; + dl->d_ntracks = new->bios_hd; + dl->d_nsectors = new->bios_sect; +#endif + dl->d_secpercyl = dl->d_ntracks * dl->d_nsectors; + + dl->d_npartitions = MAXPARTITIONS; + + dl->d_type = new->name[0] == 's' ? DTYPE_SCSI : DTYPE_ESDI; + dl->d_partitions[RAW_PART].p_size = c1->size; + dl->d_partitions[RAW_PART].p_offset = c1->offset; + + if(new->flags & DISK_ON_TRACK) + for(i=0;i<MAXPARTITIONS;i++) + if (dl->d_partitions[i].p_size) + dl->d_partitions[i].p_offset += 63; + dl->d_magic = DISKMAGIC; + dl->d_magic2 = DISKMAGIC; + dl->d_checksum = dkcksum(dl); + + for(i=0;i<BBSIZE/512;i++) { + write_block(fd,WHERE(i + c1->offset,new),buf+512*i); + } + + return 0; +} + +int +Write_Extended(int fd, struct disk *new, struct disk *old, struct chunk *c1) +{ + return 0; +} + +int +Write_Disk(struct disk *d1) +{ + int fd,i,j; + struct disk *old = 0; + struct chunk *c1; + int ret = 0; + char device[64]; + u_char *mbr; + struct dos_partition *dp,work[NDOSPART]; + int s[4]; + + strcpy(device,"/dev/r"); + strcat(device,d1->name); + + fd = open(device,O_RDWR); + if (fd < 0) { + warn("open(%s) failed",device); + return 1; + } + + memset(s,0,sizeof s); + mbr = read_block(fd,WHERE(0,d1)); + dp = (struct dos_partition*) (mbr + DOSPARTOFF); + memcpy(work,dp,sizeof work); + dp = work; + free(mbr); + for (c1=d1->chunks->part; c1 ; c1 = c1->next) { + if (c1->type == unused) continue; + if (!strcmp(c1->name,"X")) continue; + j = c1->name[4] - '1'; + if (j < 0 || j > 3) + continue; + s[j]++; + if (c1->type == extended) + ret += Write_Extended(fd, d1,old,c1); + if (c1->type == freebsd) + ret += Write_FreeBSD(fd, d1,old,c1); + + dp[j].dp_start = c1->offset; + dp[j].dp_size = c1->size; + + i = c1->offset; + if (i >= 1024*d1->bios_sect*d1->bios_hd) { + dp[j].dp_ssect = 0xff; + dp[j].dp_shd = 0xff; + dp[j].dp_scyl = 0xff; + } else { + dp[j].dp_ssect = i % d1->bios_sect; + i -= dp[j].dp_ssect++; + i /= d1->bios_sect; + dp[j].dp_shd = i % d1->bios_hd; + i -= dp[j].dp_shd; + i /= d1->bios_hd; + dp[j].dp_scyl = i; + i -= dp[j].dp_scyl; + dp[j].dp_ssect |= i >> 2; + } + +#ifdef DEBUG + printf("S:%lu = (%x/%x/%x)", + c1->offset,dp[j].dp_scyl,dp[j].dp_shd,dp[j].dp_ssect); +#endif + + i = c1->end; + dp[j].dp_esect = i % d1->bios_sect; + i -= dp[j].dp_esect++; + i /= d1->bios_sect; + dp[j].dp_ehd = i % d1->bios_hd; + i -= dp[j].dp_ehd; + i /= d1->bios_hd; + if (i>1023) i = 1023; + dp[j].dp_ecyl = i; + i -= dp[j].dp_ecyl; + dp[j].dp_esect |= i >> 2; + +#ifdef DEBUG + printf(" E:%lu = (%x/%x/%x)\n", + c1->end,dp[j].dp_ecyl,dp[j].dp_ehd,dp[j].dp_esect); +#endif + + dp[j].dp_typ = c1->subtype; + if (c1->flags & CHUNK_ACTIVE) + dp[j].dp_flag = 0x80; + else + dp[j].dp_flag = 0; + } + j = 0; + for(i=0;i<NDOSPART;i++) { + if (!s[i]) + memset(dp+i,0,sizeof *dp); + if (dp[i].dp_flag) + j++; + } + if (!j) + for(i=0;i<NDOSPART;i++) + if (dp[i].dp_typ == 0xa5) + dp[i].dp_flag = 0x80; + + mbr = read_block(fd,WHERE(0,d1)); + if (d1->bootmgr) + memcpy(mbr,d1->bootmgr,DOSPARTOFF); + memcpy(mbr+DOSPARTOFF,dp,sizeof *dp * NDOSPART); + mbr[512-2] = 0x55; + mbr[512-1] = 0xaa; + write_block(fd,WHERE(0,d1),mbr); + + i = 1; + i = ioctl(fd,DIOCSYNCSLICEINFO,&i); + if (i != 0) + warn("ioctl(DIOCSYNCSLICEINFO)"); + close(fd); + return 0; +} + |