summaryrefslogtreecommitdiffstats
path: root/release/libdisk
diff options
context:
space:
mode:
Diffstat (limited to 'release/libdisk')
-rw-r--r--release/libdisk/Makefile23
-rw-r--r--release/libdisk/blocks.c41
-rw-r--r--release/libdisk/change.c61
-rw-r--r--release/libdisk/chunk.c433
-rw-r--r--release/libdisk/create_chunk.c297
-rw-r--r--release/libdisk/disk.c327
-rw-r--r--release/libdisk/disklabel.c33
-rw-r--r--release/libdisk/libdisk.h315
-rw-r--r--release/libdisk/rules.c316
-rw-r--r--release/libdisk/tst01.c308
-rw-r--r--release/libdisk/write_disk.c233
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;
+}
+
OpenPOWER on IntegriCloud