📄 format.c
字号:
#include <u.h>#include <libc.h>#include <ctype.h>#include <disk.h>/* * disk types (all MFM encoding) */typedef struct Type Type;struct Type{ char *name; int bytes; /* bytes/sector */ int sectors; /* sectors/track */ int heads; /* number of heads */ int tracks; /* tracks/disk */ int media; /* media descriptor byte */ int cluster; /* default cluster size */};Type floppytype[] ={ { "3½HD", 512, 18, 2, 80, 0xf0, 1, }, { "3½DD", 512, 9, 2, 80, 0xf9, 2, }, { "3½QD", 512, 36, 2, 80, 0xf9, 2, }, /* invented */ { "5¼HD", 512, 15, 2, 80, 0xf9, 1, }, { "5¼DD", 512, 9, 2, 40, 0xfd, 2, }, { "hard", 512, 0, 0, 0, 0xf8, 4, },};#define NTYPES (sizeof(floppytype)/sizeof(Type))typedef struct Dosboot Dosboot;struct Dosboot{ uchar magic[3]; /* really an x86 JMP instruction */ uchar version[8]; uchar sectsize[2]; uchar clustsize; uchar nresrv[2]; uchar nfats; uchar rootsize[2]; uchar volsize[2]; uchar mediadesc; uchar fatsize[2]; uchar trksize[2]; uchar nheads[2]; uchar nhidden[4]; uchar bigvolsize[4]; uchar driveno; uchar reserved0; uchar bootsig; uchar volid[4]; uchar label[11]; uchar type[8];};#define PUTSHORT(p, v) { (p)[1] = (v)>>8; (p)[0] = (v); }#define PUTLONG(p, v) { PUTSHORT((p), (v)); PUTSHORT((p)+2, (v)>>16); }#define GETSHORT(p) (((p)[1]<<8)|(p)[0])#define GETLONG(p) (((ulong)GETSHORT(p+2)<<16)|(ulong)GETSHORT(p))typedef struct Dosdir Dosdir;struct Dosdir{ uchar name[8]; uchar ext[3]; uchar attr; uchar reserved[10]; uchar time[2]; uchar date[2]; uchar start[2]; uchar length[4];};#define DRONLY 0x01#define DHIDDEN 0x02#define DSYSTEM 0x04#define DVLABEL 0x08#define DDIR 0x10#define DARCH 0x20/* * the boot program for the boot sector. */int nbootprog = 188; /* no. of bytes of boot program, including the first 0x3E */uchar bootprog[512] ={[0x000] 0xEB, 0x3C, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,[0x03E] 0xFA, 0xFC, 0x8C, 0xC8, 0x8E, 0xD8, 0x8E, 0xD0, 0xBC, 0x00, 0x7C, 0xBE, 0x77, 0x7C, 0xE8, 0x19, 0x00, 0x33, 0xC0, 0xCD, 0x16, 0xBB, 0x40, 0x00, 0x8E, 0xC3, 0xBB, 0x72, 0x00, 0xB8, 0x34, 0x12, 0x26, 0x89, 0x07, 0xEA, 0x00, 0x00, 0xFF, 0xFF, 0xEB, 0xD6, 0xAC, 0x0A, 0xC0, 0x74, 0x09, 0xB4, 0x0E, 0xBB, 0x07, 0x00, 0xCD, 0x10, 0xEB, 0xF2, 0xC3, 'N', 'o', 't', ' ', 'a', ' ', 'b', 'o', 'o', 't', 'a', 'b', 'l', 'e', ' ', 'd', 'i', 's', 'c', ' ', 'o', 'r', ' ', 'd', 'i', 's', 'c', ' ', 'e', 'r', 'r', 'o', 'r', '\r', '\n', 'P', 'r', 'e', 's', 's', ' ', 'a', 'l', 'm', 'o', 's', 't', ' ', 'a', 'n', 'y', ' ', 'k', 'e', 'y', ' ', 't', 'o', ' ', 'r', 'e', 'b', 'o', 'o', 't', '.', '.', '.', 0x00, 0x00, 0x00,[0x1F0] 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xAA,};char *dev;int clustersize;uchar *fat; /* the fat */int fatbits;int fatsecs;int fatlast; /* last cluster allocated */int clusters;int fatsecs;vlong volsecs;uchar *root; /* first block of root */int rootsecs;int rootfiles;int rootnext;int nresrv = 1;int chatty;vlong length;Type *t;int fflag;int hflag;int xflag;char *file;char *pbs;char *type;char *bootfile;int dos;enum{ Sof = 1, /* start of file */ Eof = 2, /* end of file */};void dosfs(int, int, Disk*, char*, int, char*[], int);ulong clustalloc(int);void addrname(uchar*, Dir*, char*, ulong);void sanitycheck(Disk*);voidusage(void){ fprint(2, "usage: disk/format [-df] [-b bootblock] [-c csize] [-l label] [-r nresrv] [-t type] disk [files ...]\n"); exits("usage");}voidfatal(char *fmt, ...){ char err[128]; va_list arg; va_start(arg, fmt); vsnprint(err, sizeof(err), fmt, arg); va_end(arg); fprint(2, "format: %s\n", err); if(fflag && file) remove(file); exits(err);}voidmain(int argc, char **argv){ int n, writepbs; int fd; char buf[512]; char label[11]; char *a; Disk *disk; dos = 0; type = nil; clustersize = 0; writepbs = 0; memmove(label, "CYLINDRICAL", sizeof(label)); ARGBEGIN { case 'c': clustersize = atoi(ARGF()); break; case 'd': dos = 1; writepbs = 1; break; case 'f': fflag = 1; break; case 'l': a = ARGF(); n = strlen(a); if(n > sizeof(label)) n = sizeof(label); memmove(label, a, n); while(n < sizeof(label)) label[n++] = ' '; break; case 'b': pbs = ARGF(); writepbs = 1; break; case 'r': nresrv = atoi(ARGF()); break; case 't': type = ARGF(); break; case 'v': chatty++; break; case 'x': xflag = 1; break; default: usage(); } ARGEND if(argc < 1) usage(); disk = opendisk(argv[0], 0, 0); if(disk == nil) { if(fflag) { if((fd = create(argv[0], ORDWR, 0666)) >= 0) { file = argv[0]; close(fd); disk = opendisk(argv[0], 0, 0); } } } if(disk == nil) fatal("opendisk: %r"); if(disk->type == Tfile) fflag = 1; if(type == nil) { switch(disk->type){ case Tfile: type = "3½HD"; break; case Tfloppy: seek(disk->ctlfd, 0, 0); n = read(disk->ctlfd, buf, 10); if(n <= 0 || n >= 10) fatal("reading floppy type"); buf[n] = 0; type = strdup(buf); if(type == nil) fatal("out of memory"); break; case Tsd: type = "hard"; break; default: type = "unknown"; break; } } if(!fflag && disk->type == Tfloppy) if(fprint(disk->ctlfd, "format %s", type) < 0) fatal("formatting floppy as %s: %r", type); if(disk->type != Tfloppy) sanitycheck(disk); /* check that everything will succeed */ dosfs(dos, writepbs, disk, label, argc-1, argv+1, 0); /* commit */ dosfs(dos, writepbs, disk, label, argc-1, argv+1, 1); print("used %lld bytes\n", fatlast*clustersize*disk->secsize); exits(0);}/* * Look for a partition table on sector 1, as would be the * case if we were erroneously formatting 9fat without -r 2. * If it's there and nresrv is not big enough, complain and exit. * I've blown away my partition table too many times. */voidsanitycheck(Disk *disk){ char buf[512]; int bad; if(xflag) return; bad = 0; if(dos && nresrv < 2 && seek(disk->fd, disk->secsize, 0) == disk->secsize && read(disk->fd, buf, sizeof(buf)) >= 5 && strncmp(buf, "part ", 5) == 0) { fprint(2, "there's a plan9 partition on the disk\n" "and you didn't specify -r 2 (or greater).\n" "either specify -r 2 or -x to disable this check.\n"); bad = 1; } if(disk->type == Tsd && disk->offset == 0LL) { fprint(2, "you're attempting to format your disk (/dev/sdXX/data)\n" "rather than a partition like /dev/sdXX/9fat;\n" "this is likely a mistake. specify -x to disable this check.\n"); bad = 1; } if(bad) exits("failed disk sanity check");}/* * Return the BIOS drive number for the disk. * 0x80 is the first fixed disk, 0x81 the next, etc. * We map sdC0=0x80, sdC1=0x81, sdD0=0x82, sdD1=0x83 */intgetdriveno(Disk *disk){ char buf[64], *p; if(disk->type != Tsd) return 0x80; /* first hard disk */ if(fd2path(disk->fd, buf, sizeof(buf)) < 0) return 0x80; /* * The name is of the format #SsdC0/foo * or /dev/sdC0/foo. * So that we can just look for /sdC0, turn * #SsdC0/foo into #/sdC0/foo. */ if(buf[0] == '#' && buf[1] == 'S') buf[1] = '/'; for(p=buf; *p; p++) if(p[0] == 's' && p[1] == 'd' && (p[2]=='C' || p[2]=='D') && (p[3]=='0' || p[3]=='1')) return 0x80 + (p[2]-'C')*2 + (p[3]-'0'); return 0x80;}longwriten(int fd, void *buf, long n){ /* write 8k at a time, to be nice to the disk subsystem */ long m, tot; for(tot=0; tot<n; tot+=m){ m = n - tot; if(m > 8192) m = 8192; if(write(fd, (uchar*)buf+tot, m) != m) break; } return tot;}voiddosfs(int dofat, int dopbs, Disk *disk, char *label, int argc, char *argv[], int commit){ char r[16]; Dosboot *b; uchar *buf, *pbsbuf, *p; Dir *d; int i, data, newclusters, npbs, n, sysfd; ulong x; vlong length; vlong secsize; if(dofat == 0 && dopbs == 0) return; for(t = floppytype; t < &floppytype[NTYPES]; t++) if(strcmp(type, t->name) == 0) break; if(t == &floppytype[NTYPES]) fatal("unknown floppy type %s", type); if(t->sectors == 0 && strcmp(type, "hard") == 0) { t->sectors = disk->s; t->heads = disk->h; t->tracks = disk->c; } if(t->sectors == 0 && dofat) fatal("cannot format fat with type %s: geometry unknown\n", type); if(fflag){ disk->size = t->bytes*t->sectors*t->heads*t->tracks; disk->secsize = t->bytes; disk->secs = disk->size / disk->secsize;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -