summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorphk <phk@FreeBSD.org>1995-04-28 23:57:04 +0000
committerphk <phk@FreeBSD.org>1995-04-28 23:57:04 +0000
commit773ad9f330436a3c7484840bf3a542958fd14c96 (patch)
tree52b9513433e8fa4d94139f8ec002668ef2560b11
parente31775a1086bdadc2cd01b0eed72cb217fb1e9e8 (diff)
downloadFreeBSD-src-773ad9f330436a3c7484840bf3a542958fd14c96.zip
FreeBSD-src-773ad9f330436a3c7484840bf3a542958fd14c96.tar.gz
This is a revision 0.00 of the backend stuff for the fdisk/disklabel stuff
in the new sysinstall. If you want to give a helping hand, then send email to phk@FreeBSD.ORG. DO NOT COMMIT TO THIS DIRECTORY!
-rw-r--r--lib/libdisk/Makefile11
-rw-r--r--lib/libdisk/blocks.c33
-rw-r--r--lib/libdisk/change.c45
-rw-r--r--lib/libdisk/chunk.c365
-rw-r--r--lib/libdisk/create_chunk.c26
-rw-r--r--lib/libdisk/disk.c183
-rw-r--r--lib/libdisk/disklabel.c33
-rw-r--r--lib/libdisk/libdisk.h75
-rw-r--r--lib/libdisk/tst01.c66
-rw-r--r--release/libdisk/Makefile11
-rw-r--r--release/libdisk/blocks.c33
-rw-r--r--release/libdisk/change.c45
-rw-r--r--release/libdisk/chunk.c365
-rw-r--r--release/libdisk/create_chunk.c26
-rw-r--r--release/libdisk/disk.c183
-rw-r--r--release/libdisk/disklabel.c33
-rw-r--r--release/libdisk/libdisk.h75
-rw-r--r--release/libdisk/tst01.c66
18 files changed, 1674 insertions, 0 deletions
diff --git a/lib/libdisk/Makefile b/lib/libdisk/Makefile
new file mode 100644
index 0000000..e4396f5
--- /dev/null
+++ b/lib/libdisk/Makefile
@@ -0,0 +1,11 @@
+.PATH: /usr/src/sbin/disklabel
+OBJS= tst01.o blocks.o disklabel.o dkcksum.o chunk.o disk.o change.o \
+ create_chunk.o
+CFLAGS+= -Wall
+
+test: tst01
+ cp tst01 /0
+ ./tst01 sd0
+
+tst01: ${OBJS}
+ cc ${CFLAGS} -static -o tst01 ${OBJS}
diff --git a/lib/libdisk/blocks.c b/lib/libdisk/blocks.c
new file mode 100644
index 0000000..65d0dae
--- /dev/null
+++ b/lib/libdisk/blocks.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 "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;
+}
+
diff --git a/lib/libdisk/change.c b/lib/libdisk/change.c
new file mode 100644
index 0000000..17dd782
--- /dev/null
+++ b/lib/libdisk/change.c
@@ -0,0 +1,45 @@
+/*
+ * ----------------------------------------------------------------------------
+ * "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 <fcntl.h>
+#include <string.h>
+#include <err.h>
+#include <sys/types.h>
+#include <sys/queue.h>
+#include "libdisk.h"
+
+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;
+}
+
+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);
+}
diff --git a/lib/libdisk/chunk.c b/lib/libdisk/chunk.c
new file mode 100644
index 0000000..088b5ab
--- /dev/null
+++ b/lib/libdisk/chunk.c
@@ -0,0 +1,365 @@
+/*
+ * ----------------------------------------------------------------------------
+ * "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 <string.h>
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <err.h>
+#include "libdisk.h"
+
+CHAR_N;
+#define new_chunk() malloc(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;
+ break;
+ 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) {
+ for(c2=c1->part;c2;c2=c2->next)
+ if (c2->type == type)
+ if (Chunk_Inside(c2,&ct))
+ return c2;
+ }
+ }
+ return 0;
+ break;
+ default:
+ err(1,"Mumble!");
+ }
+}
+
+void
+Free_Chunk(struct chunk *c1)
+{
+ /* XXX remove all chunks which "ref" us */
+ if(!c1) return;
+ 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;
+ 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;
+
+ ct = new_chunk();
+ if (!ct) err(1,"malloc failed");
+ ct->offset = offset;
+ ct->size = size;
+ ct->end = offset + size - 1;
+ ct->type = type;
+ ct->name = strdup(name);
+ ct->next = 0;
+ ct->part = 0;
+ ct->subtype = subtype;
+ ct->flags = flags;
+
+ if(type==freebsd || type==extended) {
+ cs = new_chunk();
+ if (!cs) err(1,"malloc failed");
+ memset(cs,0,sizeof *cs);
+ cs->offset = offset;
+ cs->size = size;
+ cs->end = offset + size - 1;
+ cs->type = unused;
+ cs->name = strdup("-");
+ cs->next = 0;
+ cs->part = 0;
+ ct->part = cs;
+ }
+
+ if (c2->type != unused)
+ return __LINE__;
+ if (Chunk_Inside(c2,ct)) {
+ if (c2->end > ct->end) {
+ cs = new_chunk();
+ if (!cs) err(1,"malloc failed");
+ *cs = *c2;
+ 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 (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;
+ }
+ c2->end = ct->offset - 1;
+ c2->size -= ct->size;
+ ct->next = c2->next;
+ c2->next = ct;
+ return 0;
+ }
+ return __LINE__;
+}
+
+
+int
+Add_Chunk(struct disk *d, u_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->offset = c1->offset = offset;
+ c2->size = c1->size = size;
+ c2->end = c1->end = end;
+ c1->name = strdup(name);
+ c2->name = strdup(name);
+ c1->type = type;
+ c2->type = unused;
+ c1->flags = flags;
+ c1->subtype = subtype;
+ return 0;
+ }
+ c1 = 0;
+ if(!c1 && (type == freebsd || type == fat || type == foo))
+ c1 = Find_Mother_Chunk(d->chunks,offset,end,extended);
+ if(!c1 && (type == freebsd || type == fat || type == foo))
+ 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))
+ return Insert_Chunk(c2,offset,size,name,type,subtype,flags);
+ }
+ return __LINE__;
+}
+
+void
+Print_Chunk(struct chunk *c1,int offset)
+{
+ int i;
+ if(!c1) return;
+ for(i=0;i<offset;i++) putchar('>');
+ for(;i<10;i++) putchar(' ');
+ printf("%10lu %10lu %10lu %-8s %d %-8s %d %lx\n",
+ c1->offset, c1->size, c1->end, c1->name,
+ c1->type, chunk_n[c1->type],c1->subtype,c1->flags);
+ 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, u_long offset, u_long end, chunk_e type)
+{
+ struct chunk *c1=0,*c2,*c3;
+
+ if(type == whole)
+ return 1;
+ if(!c1 && (type == freebsd || type == fat || type == foo))
+ c1 = Find_Mother_Chunk(d->chunks,offset,end,extended);
+ if(!c1 && (type == freebsd || type == fat || type == foo))
+ 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 1;
+ for(c2=c1->part;c2;c2=c2->next) {
+ if (c2->offset == offset &&
+ c2->end == end &&
+ c2->type == type) {
+ 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;
+ }
+ return 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->offset, c1->end, c1->type);
+ return 1;
+ }
+ if(c3->type == unused) {
+ c2 = new_chunk();
+ *c2 = *c1;
+ c1->next = c2;
+ 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;
+}
diff --git a/lib/libdisk/create_chunk.c b/lib/libdisk/create_chunk.c
new file mode 100644
index 0000000..6664820
--- /dev/null
+++ b/lib/libdisk/create_chunk.c
@@ -0,0 +1,26 @@
+/*
+ * ----------------------------------------------------------------------------
+ * "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 <string.h>
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <err.h>
+#include "libdisk.h"
+
+int
+Create_Chunk(struct disk *d, u_long offset, u_long size, chunk_e type, int subtype, u_long flags)
+{
+ return Add_Chunk(d,offset,size,"X",type,subtype,flags);
+}
diff --git a/lib/libdisk/disk.c b/lib/libdisk/disk.c
new file mode 100644
index 0000000..5ff2a21
--- /dev/null
+++ b/lib/libdisk/disk.c
@@ -0,0 +1,183 @@
+/*
+ * ----------------------------------------------------------------------------
+ * "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 <fcntl.h>
+#include <string.h>
+#include <err.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/disklabel.h>
+#include <sys/diskslice.h>
+#include <sys/queue.h>
+#include "libdisk.h"
+
+#define DOSPTYP_EXTENDED 5
+#define DOSPTYP_ONTRACK 84
+
+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;
+ char device[64];
+ struct disk *d;
+
+ strcpy(device,"/dev/r");
+ strcat(device,name);
+
+ fd = open(device,O_RDONLY);
+ if (fd < 0) {
+ warn("open(%s) failed",device);
+ return 0;
+ }
+ i = ioctl(fd,DIOCGSLICEINFO,&ds);
+ if (i < 0) {
+ warn("DIOCSLICEINFO(%s) failed",device);
+ close(fd);
+ return 0;
+ }
+
+ d = (struct disk *)malloc(sizeof *d);
+ if(!d) err(1,"malloc failed");
+
+ memset(d,0,sizeof *d);
+
+ d->name = strdup(name);
+
+ if (!size)
+ size = ds.dss_slices[WHOLE_DISK_SLICE].ds_size;
+
+ Add_Chunk(d, 0, size, name,whole,0,0);
+
+ for(i=2;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;
+ sprintf(sname,"%ss%d",name,i-1);
+ switch (ds.dss_slices[i].ds_type) {
+ case 0xa5:
+ ce = freebsd;
+ break;
+ case 0x1:
+ case 0x6:
+ ce = fat;
+ break;
+ case DOSPTYP_EXTENDED:
+ ce = extended;
+ break;
+ default:
+ ce = foo;
+ subtype = -ds.dss_slices[i].ds_type;
+ break;
+ }
+ flags |= CHUNK_ALIGN;
+ Add_Chunk(d,ds.dss_slices[i].ds_offset,
+ ds.dss_slices[i].ds_size, sname,ce,subtype,flags);
+ if (ds.dss_slices[i].ds_type == 0xa5) {
+ struct disklabel *dl;
+ int j;
+
+ dl = read_disklabel(fd,
+ ds.dss_slices[i].ds_offset + LABELSECTOR);
+ if(dl) {
+ for(j=0; j < dl->d_npartitions; j++) {
+ char pname[20];
+ sprintf(pname,"%s%c",sname,j+'a');
+ if (j == 2)
+ continue;
+ if (!dl->d_partitions[j].p_size)
+ continue;
+ Add_Chunk(d,
+ dl->d_partitions[j].p_offset,
+ dl->d_partitions[j].p_size,
+ pname,part,0,0);
+ }
+ }
+ free(dl);
+ }
+ }
+ close(fd);
+ return d;
+}
+
+void
+Debug_Disk(struct disk *d)
+{
+ printf("Debug_Disk(%s)",d->name);
+ printf(" flags=%lx",d->flags);
+ printf(" real_geom=%lu/%lu/%lu",d->real_cyl,d->real_hd,d->real_sect);
+ printf(" bios_geom=%lu/%lu/%lu\n",d->bios_cyl,d->bios_hd,d->bios_sect);
+ Debug_Chunk(d->chunks);
+}
+
+void
+Free_Disk(struct disk *d)
+{
+ if(d->chunks)
+ Free_Chunk(d->chunks);
+ if(d->name)
+ free(d->name);
+ 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);
+ return d2;
+}
+
+void
+Collapse_Disk(struct disk *d)
+{
+
+ while(Collapse_Chunk(d,d->chunks))
+ ;
+}
+
+int
+Aligned(struct disk *d, u_long offset)
+{
+ if (offset % d->bios_sect)
+ return 0;
+ return 1;
+}
+
+u_long
+Prev_Aligned(struct disk *d, u_long offset)
+{
+ return (offset / d->bios_sect) * d->bios_sect;
+}
+
+u_long
+Next_Aligned(struct disk *d, u_long offset)
+{
+ return Prev_Aligned(d,offset + d->bios_sect);
+}
diff --git a/lib/libdisk/disklabel.c b/lib/libdisk/disklabel.c
new file mode 100644
index 0000000..9714e6c
--- /dev/null
+++ b/lib/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/lib/libdisk/libdisk.h b/lib/libdisk/libdisk.h
new file mode 100644
index 0000000..04c5a2f
--- /dev/null
+++ b/lib/libdisk/libdisk.h
@@ -0,0 +1,75 @@
+
+typedef enum {whole, foo, fat, freebsd, extended, part, unused, reserved} chunk_e;
+#define CHAR_N static char *chunk_n[] = { \
+ "whole","foo","fat","freebsd","extended","part","unused","reserved"};
+
+struct disk {
+ char *name;
+ u_long flags;
+#define DISK_ON_TRACK 1
+#define DISK_REAL_GEOM 2
+ u_long real_cyl;
+ u_long real_hd;
+ u_long real_sect;
+ u_long bios_cyl;
+ u_long bios_hd;
+ u_long bios_sect;
+ struct chunk *chunks;
+};
+
+struct chunk {
+ struct chunk *next;
+ struct chunk *part;
+ u_long offset;
+ u_long size;
+ u_long end;
+ char *name;
+ chunk_e type;
+ int subtype;
+#define SUBTYPE_BSD_FS 1
+#define SUBTYPE_BSD_SWAP 2
+#define SUBTYPE_BSD_UNUSED 3
+ u_long flags;
+#define CHUNK_PAST_1024 1
+ /* this chunk cannot be booted from */
+#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
+};
+
+struct disk *Open_Disk(char *devname);
+void Free_Disk(struct disk *disk);
+void Debug_Disk(struct disk *disk);
+struct disk *Clone_Disk(struct disk *disk);
+
+struct disk *Set_Phys_Geom(struct disk *disk, u_long cyl, u_long heads, u_long sects);
+void Set_Bios_Geom(struct disk *disk, u_long cyl, u_long heads, u_long sects);
+
+int Delete_Chunk(struct disk *disk, u_long offset, u_long end, chunk_e type);
+void Collapse_Disk(struct disk *disk);
+int Collapse_Chunk(struct disk *disk, struct chunk *chunk);
+
+int Create_Chunk(struct disk *disk, u_long offset, u_long size, chunk_e type, int subtype, u_long flags);
+
+/* Implementation details */
+
+struct disk *Int_Open_Disk(char *devname, u_long maxsize);
+
+void Debug_Chunk(struct chunk *);
+void Free_Chunk(struct chunk *);
+struct chunk * Clone_Chunk(struct chunk *);
+int Add_Chunk(struct disk *, u_long , u_long , char *, chunk_e, int , u_long);
+void Bios_Limit_Chunk(struct chunk *, u_long);
+void * read_block(int, daddr_t );
+struct disklabel * read_disklabel(int, daddr_t);
+u_short dkcksum(struct disklabel *);
+int Aligned(struct disk *d, u_long offset);
+u_long Next_Aligned(struct disk *d, u_long offset);
+u_long Prev_Aligned(struct disk *d, u_long offset);
+struct chunk * Find_Mother_Chunk(struct chunk *, u_long , u_long , chunk_e);
+
+#define dprintf printf
diff --git a/lib/libdisk/tst01.c b/lib/libdisk/tst01.c
new file mode 100644
index 0000000..bcc1344
--- /dev/null
+++ b/lib/libdisk/tst01.c
@@ -0,0 +1,66 @@
+/*
+ * ----------------------------------------------------------------------------
+ * "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 <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/disklabel.h>
+#include <sys/diskslice.h>
+#include <sys/queue.h>
+#include "libdisk.h"
+
+void
+fprint_diskslices(FILE *fi, struct diskslices *ds)
+{
+ int i;
+
+ printf("@%p: struct diskslices\n",ds);
+ printf("\tdss_first_bsd_slice = %d\n",ds->dss_first_bsd_slice);
+ printf("\tdss_nslices = %d\n",ds->dss_nslices);
+ for(i=0;i<ds->dss_nslices;i++) {
+ printf("\tdss_slices[%d] = struct diskslice",i);
+ if (i == 0)
+ printf(" /* FreeBSD compatibility slice */\n");
+ else if (i == 1)
+ printf(" /* Whole disk slice */\n");
+ else if (i < 6)
+ printf(" /* Primary MBR slice %d */\n",i-1);
+ else
+ printf("\n");
+ printf("\t\tds_offset = %lu\n",ds->dss_slices[i].ds_offset);
+ printf("\t\tds_size = %lu\n",ds->dss_slices[i].ds_size);
+ printf("\t\tds_type = %u\n",ds->dss_slices[i].ds_type);
+ printf("\t\tds_openmask = %u\n",ds->dss_slices[i].ds_openmask);
+ }
+}
+
+int
+main(int argc, char **argv)
+{
+ int i;
+ struct disk *d;
+
+ for(i=1;i<argc;i++) {
+ d = Open_Disk(argv[i]);
+ if (!d) continue;
+ Debug_Disk(d);
+ Delete_Chunk(d,0,4108599,freebsd);
+ Debug_Disk(d);
+ printf("Create=%d\n",Create_Chunk(d,0,32768,fat,0,0));
+ printf("Create=%d\n",Create_Chunk(d,192512,409600,freebsd,0,0));
+ printf("Create=%d\n",Create_Chunk(d,192512,409600,part,0,0));
+ Debug_Disk(d);
+ }
+ exit (0);
+}
diff --git a/release/libdisk/Makefile b/release/libdisk/Makefile
new file mode 100644
index 0000000..e4396f5
--- /dev/null
+++ b/release/libdisk/Makefile
@@ -0,0 +1,11 @@
+.PATH: /usr/src/sbin/disklabel
+OBJS= tst01.o blocks.o disklabel.o dkcksum.o chunk.o disk.o change.o \
+ create_chunk.o
+CFLAGS+= -Wall
+
+test: tst01
+ cp tst01 /0
+ ./tst01 sd0
+
+tst01: ${OBJS}
+ cc ${CFLAGS} -static -o tst01 ${OBJS}
diff --git a/release/libdisk/blocks.c b/release/libdisk/blocks.c
new file mode 100644
index 0000000..65d0dae
--- /dev/null
+++ b/release/libdisk/blocks.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 "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;
+}
+
diff --git a/release/libdisk/change.c b/release/libdisk/change.c
new file mode 100644
index 0000000..17dd782
--- /dev/null
+++ b/release/libdisk/change.c
@@ -0,0 +1,45 @@
+/*
+ * ----------------------------------------------------------------------------
+ * "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 <fcntl.h>
+#include <string.h>
+#include <err.h>
+#include <sys/types.h>
+#include <sys/queue.h>
+#include "libdisk.h"
+
+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;
+}
+
+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);
+}
diff --git a/release/libdisk/chunk.c b/release/libdisk/chunk.c
new file mode 100644
index 0000000..088b5ab
--- /dev/null
+++ b/release/libdisk/chunk.c
@@ -0,0 +1,365 @@
+/*
+ * ----------------------------------------------------------------------------
+ * "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 <string.h>
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <err.h>
+#include "libdisk.h"
+
+CHAR_N;
+#define new_chunk() malloc(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;
+ break;
+ 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) {
+ for(c2=c1->part;c2;c2=c2->next)
+ if (c2->type == type)
+ if (Chunk_Inside(c2,&ct))
+ return c2;
+ }
+ }
+ return 0;
+ break;
+ default:
+ err(1,"Mumble!");
+ }
+}
+
+void
+Free_Chunk(struct chunk *c1)
+{
+ /* XXX remove all chunks which "ref" us */
+ if(!c1) return;
+ 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;
+ 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;
+
+ ct = new_chunk();
+ if (!ct) err(1,"malloc failed");
+ ct->offset = offset;
+ ct->size = size;
+ ct->end = offset + size - 1;
+ ct->type = type;
+ ct->name = strdup(name);
+ ct->next = 0;
+ ct->part = 0;
+ ct->subtype = subtype;
+ ct->flags = flags;
+
+ if(type==freebsd || type==extended) {
+ cs = new_chunk();
+ if (!cs) err(1,"malloc failed");
+ memset(cs,0,sizeof *cs);
+ cs->offset = offset;
+ cs->size = size;
+ cs->end = offset + size - 1;
+ cs->type = unused;
+ cs->name = strdup("-");
+ cs->next = 0;
+ cs->part = 0;
+ ct->part = cs;
+ }
+
+ if (c2->type != unused)
+ return __LINE__;
+ if (Chunk_Inside(c2,ct)) {
+ if (c2->end > ct->end) {
+ cs = new_chunk();
+ if (!cs) err(1,"malloc failed");
+ *cs = *c2;
+ 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 (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;
+ }
+ c2->end = ct->offset - 1;
+ c2->size -= ct->size;
+ ct->next = c2->next;
+ c2->next = ct;
+ return 0;
+ }
+ return __LINE__;
+}
+
+
+int
+Add_Chunk(struct disk *d, u_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->offset = c1->offset = offset;
+ c2->size = c1->size = size;
+ c2->end = c1->end = end;
+ c1->name = strdup(name);
+ c2->name = strdup(name);
+ c1->type = type;
+ c2->type = unused;
+ c1->flags = flags;
+ c1->subtype = subtype;
+ return 0;
+ }
+ c1 = 0;
+ if(!c1 && (type == freebsd || type == fat || type == foo))
+ c1 = Find_Mother_Chunk(d->chunks,offset,end,extended);
+ if(!c1 && (type == freebsd || type == fat || type == foo))
+ 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))
+ return Insert_Chunk(c2,offset,size,name,type,subtype,flags);
+ }
+ return __LINE__;
+}
+
+void
+Print_Chunk(struct chunk *c1,int offset)
+{
+ int i;
+ if(!c1) return;
+ for(i=0;i<offset;i++) putchar('>');
+ for(;i<10;i++) putchar(' ');
+ printf("%10lu %10lu %10lu %-8s %d %-8s %d %lx\n",
+ c1->offset, c1->size, c1->end, c1->name,
+ c1->type, chunk_n[c1->type],c1->subtype,c1->flags);
+ 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, u_long offset, u_long end, chunk_e type)
+{
+ struct chunk *c1=0,*c2,*c3;
+
+ if(type == whole)
+ return 1;
+ if(!c1 && (type == freebsd || type == fat || type == foo))
+ c1 = Find_Mother_Chunk(d->chunks,offset,end,extended);
+ if(!c1 && (type == freebsd || type == fat || type == foo))
+ 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 1;
+ for(c2=c1->part;c2;c2=c2->next) {
+ if (c2->offset == offset &&
+ c2->end == end &&
+ c2->type == type) {
+ 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;
+ }
+ return 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->offset, c1->end, c1->type);
+ return 1;
+ }
+ if(c3->type == unused) {
+ c2 = new_chunk();
+ *c2 = *c1;
+ c1->next = c2;
+ 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;
+}
diff --git a/release/libdisk/create_chunk.c b/release/libdisk/create_chunk.c
new file mode 100644
index 0000000..6664820
--- /dev/null
+++ b/release/libdisk/create_chunk.c
@@ -0,0 +1,26 @@
+/*
+ * ----------------------------------------------------------------------------
+ * "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 <string.h>
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <err.h>
+#include "libdisk.h"
+
+int
+Create_Chunk(struct disk *d, u_long offset, u_long size, chunk_e type, int subtype, u_long flags)
+{
+ return Add_Chunk(d,offset,size,"X",type,subtype,flags);
+}
diff --git a/release/libdisk/disk.c b/release/libdisk/disk.c
new file mode 100644
index 0000000..5ff2a21
--- /dev/null
+++ b/release/libdisk/disk.c
@@ -0,0 +1,183 @@
+/*
+ * ----------------------------------------------------------------------------
+ * "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 <fcntl.h>
+#include <string.h>
+#include <err.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/disklabel.h>
+#include <sys/diskslice.h>
+#include <sys/queue.h>
+#include "libdisk.h"
+
+#define DOSPTYP_EXTENDED 5
+#define DOSPTYP_ONTRACK 84
+
+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;
+ char device[64];
+ struct disk *d;
+
+ strcpy(device,"/dev/r");
+ strcat(device,name);
+
+ fd = open(device,O_RDONLY);
+ if (fd < 0) {
+ warn("open(%s) failed",device);
+ return 0;
+ }
+ i = ioctl(fd,DIOCGSLICEINFO,&ds);
+ if (i < 0) {
+ warn("DIOCSLICEINFO(%s) failed",device);
+ close(fd);
+ return 0;
+ }
+
+ d = (struct disk *)malloc(sizeof *d);
+ if(!d) err(1,"malloc failed");
+
+ memset(d,0,sizeof *d);
+
+ d->name = strdup(name);
+
+ if (!size)
+ size = ds.dss_slices[WHOLE_DISK_SLICE].ds_size;
+
+ Add_Chunk(d, 0, size, name,whole,0,0);
+
+ for(i=2;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;
+ sprintf(sname,"%ss%d",name,i-1);
+ switch (ds.dss_slices[i].ds_type) {
+ case 0xa5:
+ ce = freebsd;
+ break;
+ case 0x1:
+ case 0x6:
+ ce = fat;
+ break;
+ case DOSPTYP_EXTENDED:
+ ce = extended;
+ break;
+ default:
+ ce = foo;
+ subtype = -ds.dss_slices[i].ds_type;
+ break;
+ }
+ flags |= CHUNK_ALIGN;
+ Add_Chunk(d,ds.dss_slices[i].ds_offset,
+ ds.dss_slices[i].ds_size, sname,ce,subtype,flags);
+ if (ds.dss_slices[i].ds_type == 0xa5) {
+ struct disklabel *dl;
+ int j;
+
+ dl = read_disklabel(fd,
+ ds.dss_slices[i].ds_offset + LABELSECTOR);
+ if(dl) {
+ for(j=0; j < dl->d_npartitions; j++) {
+ char pname[20];
+ sprintf(pname,"%s%c",sname,j+'a');
+ if (j == 2)
+ continue;
+ if (!dl->d_partitions[j].p_size)
+ continue;
+ Add_Chunk(d,
+ dl->d_partitions[j].p_offset,
+ dl->d_partitions[j].p_size,
+ pname,part,0,0);
+ }
+ }
+ free(dl);
+ }
+ }
+ close(fd);
+ return d;
+}
+
+void
+Debug_Disk(struct disk *d)
+{
+ printf("Debug_Disk(%s)",d->name);
+ printf(" flags=%lx",d->flags);
+ printf(" real_geom=%lu/%lu/%lu",d->real_cyl,d->real_hd,d->real_sect);
+ printf(" bios_geom=%lu/%lu/%lu\n",d->bios_cyl,d->bios_hd,d->bios_sect);
+ Debug_Chunk(d->chunks);
+}
+
+void
+Free_Disk(struct disk *d)
+{
+ if(d->chunks)
+ Free_Chunk(d->chunks);
+ if(d->name)
+ free(d->name);
+ 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);
+ return d2;
+}
+
+void
+Collapse_Disk(struct disk *d)
+{
+
+ while(Collapse_Chunk(d,d->chunks))
+ ;
+}
+
+int
+Aligned(struct disk *d, u_long offset)
+{
+ if (offset % d->bios_sect)
+ return 0;
+ return 1;
+}
+
+u_long
+Prev_Aligned(struct disk *d, u_long offset)
+{
+ return (offset / d->bios_sect) * d->bios_sect;
+}
+
+u_long
+Next_Aligned(struct disk *d, u_long offset)
+{
+ return Prev_Aligned(d,offset + d->bios_sect);
+}
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..04c5a2f
--- /dev/null
+++ b/release/libdisk/libdisk.h
@@ -0,0 +1,75 @@
+
+typedef enum {whole, foo, fat, freebsd, extended, part, unused, reserved} chunk_e;
+#define CHAR_N static char *chunk_n[] = { \
+ "whole","foo","fat","freebsd","extended","part","unused","reserved"};
+
+struct disk {
+ char *name;
+ u_long flags;
+#define DISK_ON_TRACK 1
+#define DISK_REAL_GEOM 2
+ u_long real_cyl;
+ u_long real_hd;
+ u_long real_sect;
+ u_long bios_cyl;
+ u_long bios_hd;
+ u_long bios_sect;
+ struct chunk *chunks;
+};
+
+struct chunk {
+ struct chunk *next;
+ struct chunk *part;
+ u_long offset;
+ u_long size;
+ u_long end;
+ char *name;
+ chunk_e type;
+ int subtype;
+#define SUBTYPE_BSD_FS 1
+#define SUBTYPE_BSD_SWAP 2
+#define SUBTYPE_BSD_UNUSED 3
+ u_long flags;
+#define CHUNK_PAST_1024 1
+ /* this chunk cannot be booted from */
+#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
+};
+
+struct disk *Open_Disk(char *devname);
+void Free_Disk(struct disk *disk);
+void Debug_Disk(struct disk *disk);
+struct disk *Clone_Disk(struct disk *disk);
+
+struct disk *Set_Phys_Geom(struct disk *disk, u_long cyl, u_long heads, u_long sects);
+void Set_Bios_Geom(struct disk *disk, u_long cyl, u_long heads, u_long sects);
+
+int Delete_Chunk(struct disk *disk, u_long offset, u_long end, chunk_e type);
+void Collapse_Disk(struct disk *disk);
+int Collapse_Chunk(struct disk *disk, struct chunk *chunk);
+
+int Create_Chunk(struct disk *disk, u_long offset, u_long size, chunk_e type, int subtype, u_long flags);
+
+/* Implementation details */
+
+struct disk *Int_Open_Disk(char *devname, u_long maxsize);
+
+void Debug_Chunk(struct chunk *);
+void Free_Chunk(struct chunk *);
+struct chunk * Clone_Chunk(struct chunk *);
+int Add_Chunk(struct disk *, u_long , u_long , char *, chunk_e, int , u_long);
+void Bios_Limit_Chunk(struct chunk *, u_long);
+void * read_block(int, daddr_t );
+struct disklabel * read_disklabel(int, daddr_t);
+u_short dkcksum(struct disklabel *);
+int Aligned(struct disk *d, u_long offset);
+u_long Next_Aligned(struct disk *d, u_long offset);
+u_long Prev_Aligned(struct disk *d, u_long offset);
+struct chunk * Find_Mother_Chunk(struct chunk *, u_long , u_long , chunk_e);
+
+#define dprintf printf
diff --git a/release/libdisk/tst01.c b/release/libdisk/tst01.c
new file mode 100644
index 0000000..bcc1344
--- /dev/null
+++ b/release/libdisk/tst01.c
@@ -0,0 +1,66 @@
+/*
+ * ----------------------------------------------------------------------------
+ * "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 <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/disklabel.h>
+#include <sys/diskslice.h>
+#include <sys/queue.h>
+#include "libdisk.h"
+
+void
+fprint_diskslices(FILE *fi, struct diskslices *ds)
+{
+ int i;
+
+ printf("@%p: struct diskslices\n",ds);
+ printf("\tdss_first_bsd_slice = %d\n",ds->dss_first_bsd_slice);
+ printf("\tdss_nslices = %d\n",ds->dss_nslices);
+ for(i=0;i<ds->dss_nslices;i++) {
+ printf("\tdss_slices[%d] = struct diskslice",i);
+ if (i == 0)
+ printf(" /* FreeBSD compatibility slice */\n");
+ else if (i == 1)
+ printf(" /* Whole disk slice */\n");
+ else if (i < 6)
+ printf(" /* Primary MBR slice %d */\n",i-1);
+ else
+ printf("\n");
+ printf("\t\tds_offset = %lu\n",ds->dss_slices[i].ds_offset);
+ printf("\t\tds_size = %lu\n",ds->dss_slices[i].ds_size);
+ printf("\t\tds_type = %u\n",ds->dss_slices[i].ds_type);
+ printf("\t\tds_openmask = %u\n",ds->dss_slices[i].ds_openmask);
+ }
+}
+
+int
+main(int argc, char **argv)
+{
+ int i;
+ struct disk *d;
+
+ for(i=1;i<argc;i++) {
+ d = Open_Disk(argv[i]);
+ if (!d) continue;
+ Debug_Disk(d);
+ Delete_Chunk(d,0,4108599,freebsd);
+ Debug_Disk(d);
+ printf("Create=%d\n",Create_Chunk(d,0,32768,fat,0,0));
+ printf("Create=%d\n",Create_Chunk(d,192512,409600,freebsd,0,0));
+ printf("Create=%d\n",Create_Chunk(d,192512,409600,part,0,0));
+ Debug_Disk(d);
+ }
+ exit (0);
+}
OpenPOWER on IntegriCloud