From 773ad9f330436a3c7484840bf3a542958fd14c96 Mon Sep 17 00:00:00 2001 From: phk Date: Fri, 28 Apr 1995 23:57:04 +0000 Subject: 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! --- lib/libdisk/Makefile | 11 ++ lib/libdisk/blocks.c | 33 ++++ lib/libdisk/change.c | 45 ++++++ lib/libdisk/chunk.c | 365 +++++++++++++++++++++++++++++++++++++++++++++ lib/libdisk/create_chunk.c | 26 ++++ lib/libdisk/disk.c | 183 +++++++++++++++++++++++ lib/libdisk/disklabel.c | 33 ++++ lib/libdisk/libdisk.h | 75 ++++++++++ lib/libdisk/tst01.c | 66 ++++++++ 9 files changed, 837 insertions(+) create mode 100644 lib/libdisk/Makefile create mode 100644 lib/libdisk/blocks.c create mode 100644 lib/libdisk/change.c create mode 100644 lib/libdisk/chunk.c create mode 100644 lib/libdisk/create_chunk.c create mode 100644 lib/libdisk/disk.c create mode 100644 lib/libdisk/disklabel.c create mode 100644 lib/libdisk/libdisk.h create mode 100644 lib/libdisk/tst01.c (limited to 'lib/libdisk') 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): + * 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 +#include +#include +#include +#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): + * 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 +#include +#include +#include +#include +#include +#include +#include +#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): + * 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 +#include +#include +#include +#include +#include +#include +#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'); + 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): + * 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 +#include +#include +#include +#include +#include +#include +#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): + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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;id_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): + * 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 +#include +#include +#include +#include +#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): + * 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 +#include +#include +#include +#include +#include +#include +#include +#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;idss_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