henesyinit from p9f47575dc5 years agoHistory
445 lines · 7.8 KB · C
RawDownload
/* * prep.c - Make unit partition table */#include <u.h>#include <libc.h>#include <bio.h> int ropt;int changed;ulong size;ulong secsize;ulong secs; enum {	Maxpath=	4*NAMELEN,	Maxpart=	8,}; /* *  plan 9 partitions */typedef struct Partition Partition;struct Partition{	char name[NAMELEN+1];	ulong start;	ulong end;};int npart;Partition ptab[Maxpart+2]; char *secbuf;Biobuf in;ulong dosend;	/* end of any active dos partition */ void	error(char*, void*);int	rddiskinfo(char*);void	prepare(char*);int	read_table(int);void	print_table(char*);void	write_table(int);void	edit_table(void);void	rddosinfo(char*);  voidmain (int argc, char **argv){	if(Binit(&in, 0, OREAD) < 0){		fprint(2, "can't Binit\n");		exits("Binit");	}		 	if(argc < 1) {		fprint(2, "prep [-ra] special\n");		exits("usage");	} 	ARGBEGIN{	case 'r':	ropt++; break;	default:	fprint(2, "prep [-ra] special\n");			exits("usage");	}ARGEND;	if(argc != 1){		fprint(2, "prep [-ra] special\n");		exits("usage");	} 	prepare(argv[0]); 	if(changed) 		print("\n *** PARTITION TABLE HAS BEEN MODIFIED ***\n");} voiderror(char *s, void *x){	char buf1[256];	char buf[ERRLEN]; 	sprint(buf1, s, x);	errstr(buf);	fprint(2, "prep: %s: %s\n", buf1, buf);	exits(buf1);} intrddiskinfo(char *special){	Dir d;	char name[Maxpath];	int fd;	Partition *pp = ptab; 	sprint(name, "%sdisk", special);	if(dirstat(name, &d) < 0)		error("stating %s", name);	size = d.length;	sprint(name, "%spartition", special);	if(dirstat(name, &d) < 0)		error("stating %s", name);	secsize = d.length;	secs = size/secsize; 	npart = 2; 	strcpy(pp->name, "disk");	pp->start = 0;	pp->end = secs;	pp++; 	strcpy(pp->name, "partition");	pp->start = secs - 1;	pp->end = secs; 	fd = open(name, ORDWR);	if(fd < 0)		error("opening %s", name); 	print("sector = %d bytes, disk = %d sectors\n", secsize, size/secsize);	return fd;} voidprepare(char *special){	int i, fd;	char *line;	int delete = 0;	Partition *pp; 	fd = rddiskinfo(special);		rddosinfo(special); 	switch(read_table(fd)){	case -1:		break;	default:		print("Plan 9 partition table exists\n");		print_table(special);		print("(d)elete, (e)dit or (q)uit ?");		line = Brdline(&in, '\n');		if(line == 0)			exits("exists");		switch (*line) {			case 'd':				delete++;				break;			case 'e':				break;			default:				return;		}	} 	if(delete){		pp = &ptab[2];		for(i = 2; i < Maxpart+2; i++){			pp->name[0] = 0;			pp->start = 0;			pp->end = 0;			pp++;		}		npart = 2;	} 	if(npart == 2 && dosend && dosend < ptab[0].end){		strcpy(ptab[2].name, "dos");		ptab[2].start = 0;		ptab[2].end = dosend;	} 	print_table(special);	npart = 2;	print("\n");	for(;;) {		edit_table();		print("\n");		print_table(special);		print("\nOk:");		line = Brdline(&in, '\n');		if(line == 0)			return;		if (*line == '\n' || *line == 'y')			break;	}	write_table(fd);	close(fd);} voidedit_table(void){	int i, j;	Partition *pp;	char *line;	ulong sofar = 0; 	pp = &ptab[2];	for(i = 2; i < Maxpart+2; i++){		for(;;){			print(" %d name (%s [- to delete, * to quit]):", i, pp->name);			line = Brdline(&in, '\n');			if(pp->name[0] == 0){				pp->start = sofar;				pp->end = secs - 1;			}			if(line == 0 || *line == '*')				return;			line[Blinelen(&in)-1] = 0;			if(*line == '-'){				pp->name[0] = 0;				for(j = i; j < Maxpart+1; j++)					ptab[j] = ptab[j+1];			} else if(*line != 0){				strncpy(pp->name, line, NAMELEN);				break;			} else if(pp->name[0])				break;		} 		do {			print(" %d start (%d):", i, pp->start);			line = Brdline(&in, '\n');			if(line == 0)				return;			line[Blinelen(&in)-1] = 0;			if(*line != 0)  				pp->start = atoi(line);			if(pp->end == 0)				pp->end = pp->start;		}while(pp->start < 0 || pp->start >= ptab[0].end); 		do {			print(" %d length (%d):", i, pp->end-pp->start);			line = Brdline(&in, '\n');			if(line == 0)				return;			line[Blinelen(&in)-1] = 0;			if(*line != 0)  				pp->end = pp->start + atoi(line);		}while(pp->end < 0 || pp->end > ptab[0].end ||			pp->end < pp->start);		sofar = pp->end; 		npart = i+1;		pp++;	}}	intread_table(int fd){	int i;	int lines;	char *line[Maxpart+1];	char *field[3];	Partition *pp; 	if(secbuf == 0)		secbuf = sbrk(secsize+1); 	if((i = read(fd, secbuf, secsize)) < 0)		error("reading partition table", 0);	secbuf[i] = 0; 	setfields("\n");	lines = getfields(secbuf, line, Maxpart+1);	setfields(" \t"); 	if(strcmp(line[0], "plan9 partitions") != 0)		return -1; 	pp = &ptab[npart];	for(i = 1; i < lines; i++){		if(getfields(line[i], field, 3) != 3)			break;		if(strlen(field[0]) > NAMELEN)			break;		strcpy(pp->name, field[0]);		pp->start = strtoul(field[1], 0, 0);		pp->end = strtoul(field[2], 0, 0);		if(pp->start > pp->end || pp->start >= ptab[0].end)			break;		npart++;		pp++;	} 	return npart;} voidprint_table(char *special){	int i, j;	ulong s1, s2, e1, e2;	ulong ps;	Partition *pp;	char buf[2*NAMELEN];	char *basename;	char overlap[Maxpart+3];	char *op; 	basename = strrchr(special, '/');	if(basename == 0)		basename = special; 	print("\nNr Name                 Overlap       Start      End        %%     Size\n");	for(i = 0; i < npart; i++) {		pp = &ptab[i];		sprint(buf, "%s%s", basename, pp->name);		s1 = pp->start;		e1 = pp->end;		op = overlap;		for(j = 0; j < npart; j++){			s2 = ptab[j].start;			e2 = ptab[j].end;			if(s1 < e2 && e1 > s2)				*op++ = '0' + j;			else				*op++ = '-';		}		for(; j < Maxpart+2; j++)			*op++ = ' ';		*op = 0;		ps = pp->end - pp->start;		print("%2d %-20.20s %s %8d %8d %8d %8d\n", i, buf, overlap,			pp->start, pp->end, (ps*100)/secs, ps);	}} voidwrite_table(int fd){	int off;	int i;	Partition *pp; 	if(ropt)		return; 	if(seek(fd, 0, 0) < 0)		error("seeking table", 0); 	memset(secbuf, 0, secsize);	off = sprint(secbuf, "plan9 partitions\n");	for(i = 2; i < npart; i++){		pp = &ptab[i];		off += sprint(&secbuf[off], "%s %d %d\n", pp->name, pp->start, pp->end);	} 	if(write(fd, secbuf, secsize) < 0)		error("writing table", 0); 	changed = 1;} /* *  DOS boot sector and partition table */typedef struct DOSpart	DOSpart;struct DOSpart{	uchar flag;		/* active flag */	uchar shead;		/* starting head */	uchar scs[2];		/* starting cylinder/sector */	uchar type;		/* partition type */	uchar ehead;		/* ending head */	uchar ecs[2];		/* ending cylinder/sector */	uchar start[4];		/* starting sector */	uchar len[4];		/* length in sectors */};typedef struct DOSptab	DOSptab;struct DOSptab{	DOSpart p[4];	uchar magic[2];		/* 0x55 0xAA */};enum{	DOSactive=	0x80,	/* active partition */ 	DOS12=		1,	/* 12-bit FAT partiton */	DOS16=		4,	/* 16-bit FAT partiton */	DOSext=		5,	/* extended partiton */	DOShuge=	6,	/* "huge" partiton */ 	DOSmagic0=	0x55,	DOSmagic1=	0xAA,}; #define GL(p) ((p[3]<<24)|(p[2]<<16)|(p[1]<<8)|p[0]) voidrddosinfo(char *special){	char name[Maxpath];	int fd;	char *t;	DOSptab b;	DOSpart *dp;	ulong end; 	sprint(name, "%sdisk", special);	fd = open(name, OREAD);	if(fd < 0)		error("opening %s", name);	seek(fd, 446, 0);	if(read(fd, &b, sizeof(b)) != sizeof(b))		return;	close(fd);	if(b.magic[0] != DOSmagic0 || b.magic[1] != DOSmagic1)		return; 	print("\nDOS partition table exists\n");	print("\nNr Type           Start      Len\n");	for(dp = b.p; dp < &b.p[4]; dp++){		switch(dp->type){		case 0:			continue;		case DOS12:			t = "12 bit FAT";			break;		case DOS16:			t = "16 bit FAT";			break;		case DOSext:			t = "extended";			break;		case DOShuge:			t = "huge";			break;		default:			t = "unknown";			break;		}		print("%2d %-11.11s %8d %8d %s\n", dp-b.p, t, 			GL(dp->start), GL(dp->len),			dp->flag==DOSactive ? "Active" : "");		end = GL(dp->start) + GL(dp->len);		if(dp->flag == DOSactive && end > dosend)			dosend = end;	}	print("\n");}