📄 fdisk.c
字号:
return n<4; } /* * secondary partitions can be inserted between two primary * partitions only if there is an empty primary slot. * otherwise, we can put a new secondary partition next * to a secondary partition no problem. */ n = 0; for(i=0; i<edit->npart; i++){ p = (Dospart*)edit->part[i]; if(p->primary) n++; pend = p->end; if(i+1<edit->npart){ q = (Dospart*)edit->part[i+1]; qstart = q->start; }else{ qstart = edit->end; q = nil; } if(start < pend || start >= qstart) continue; /* we go between these two */ if(p->primary==0 || (q && q->primary==0)) return 1; } /* not next to a secondary, need a new primary */ return n<4;}static voidautopart(Edit *edit){ char *err; int active, i; vlong bigstart, bigsize, start; Dospart *p; for(i=0; i<edit->npart; i++) if(((Dospart*)edit->part[i])->type == Type9) return; /* look for the biggest gap in which we can put a primary partition */ start = 0; bigsize = 0; SET(bigstart); for(i=0; i<edit->npart; i++) { p = (Dospart*)edit->part[i]; if(p->start > start && p->start - start > bigsize && haveroom(edit, 1, start)) { bigsize = p->start - start; bigstart = start; } start = p->end; } if(edit->end - start > bigsize && haveroom(edit, 1, start)) { bigsize = edit->end - start; bigstart = start; } if(bigsize < 1) { fprint(2, "couldn't find space or partition slot for plan 9 partition\n"); return; } /* set new partition active only if no others are */ active = Active; for(i=0; i<edit->npart; i++) if(((Dospart*)edit->part[i])->primary && (((Dospart*)edit->part[i])->active & Active)) active = 0; /* add new plan 9 partition */ bigsize *= sec2cyl; bigstart *= sec2cyl; if(bigstart == 0) { bigstart += edit->disk->s; bigsize -= edit->disk->s; } p = mkpart(nil, 1, bigstart, bigsize, nil); p->active = active; p->changed = 1; p->type = Type9; edit->changed = 1; if(err = addpart(edit, p)) { fprint(2, "error adding plan9 partition: %s\n", err); return; }}typedef struct Name Name;struct Name { char *name; Name *link;};Name *namelist;static voidplan9print(Dospart *part, int fd){ int i, ok; char *name, *vname; Name *n; vlong start, end; char *sep; vname = types[part->type].name; if(vname==nil || strcmp(vname, "")==0) { part->ctlname = ""; return; } start = mbroffset+part->lba; end = start+part->size; /* avoid names like plan90 */ i = strlen(vname) - 1; if(vname[i] >= '0' && vname[i] <= '9') sep = "."; else sep = ""; i = 0; name = emalloc(strlen(vname)+10); sprint(name, "%s", vname); do { ok = 1; for(n=namelist; n; n=n->link) { if(strcmp(name, n->name) == 0) { i++; sprint(name, "%s%s%d", vname, sep, i); ok = 0; } } } while(ok == 0); n = emalloc(sizeof(*n)); n->name = name; n->link = namelist; namelist = n; part->ctlname = name; if(fd >= 0) print("part %s %lld %lld\n", name, start, end);}static voidfreenamelist(void){ Name *n, *next; for(n=namelist; n; n=next) { next = n->link; free(n); } namelist = nil;}static voidcmdprintctl(Edit *edit, int ctlfd){ int i; freenamelist(); for(i=0; i<edit->npart; i++) plan9print((Dospart*)edit->part[i], -1); ctldiff(edit, ctlfd);}static char*cmdokname(Edit*, char *name){ char *q; if(name[0] != 'p' && name[0] != 's') return "name must be pN or sN"; strtol(name+1, &q, 10); if(*q != '\0') return "name must be pN or sN"; return nil;}#define GB (1024*1024*1024)#define MB (1024*1024)#define KB (1024)static voidcmdsum(Edit *edit, Part *vp, vlong a, vlong b){ char *name, *ty; char buf[3]; char *suf; Dospart *p; vlong sz, div; p = (Dospart*)vp; buf[0] = p && p->changed ? '\'' : ' '; buf[1] = p && (p->active & Active) ? '*' : ' '; buf[2] = '\0'; name = p ? p->name : "empty"; ty = p ? typestr0(p->type) : ""; sz = (b-a)*edit->disk->secsize*sec2cyl; if(sz >= 1*GB){ suf = "GB"; div = GB; }else if(sz >= 1*MB){ suf = "MB"; div = MB; }else if(sz >= 1*KB){ suf = "KB"; div = KB; }else{ suf = "B "; div = 1; } if(div == 1) print("%s %-12s %*lld %-*lld (%lld cylinders, %lld %s) %s\n", buf, name, edit->disk->width, a, edit->disk->width, b, b-a, sz, suf, ty); else print("%s %-12s %*lld %-*lld (%lld cylinders, %lld.%.2d %s) %s\n", buf, name, edit->disk->width, a, edit->disk->width, b, b-a, sz/div, (int)(((sz%div)*100)/div), suf, ty);}static char*cmdadd(Edit *edit, char *name, vlong start, vlong end){ Dospart *p; if(!haveroom(edit, name[0]=='p', start)) return "no room for partition"; start *= sec2cyl; end *= sec2cyl; if(start == 0 || name[0] != 'p') start += edit->disk->s; p = mkpart(name, name[0]=='p', start, end-start, nil); p->changed = 1; p->type = Type9; return addpart(edit, p);}static char*cmddel(Edit *edit, Part *p){ return delpart(edit, p);}static char*cmdwrite(Edit *edit){ wrpart(edit); return nil;}static char *help = "A name - set partition active\n" "P - print table in ctl format\n" "R - restore disk back to initial configuration and exit\n" "e - show empty dos partitions\n" "t name [type] - set partition type\n";static char*cmdhelp(Edit*){ print("%s\n", help); return nil;}static char*cmdactive(Edit *edit, int nf, char **f){ int i; Dospart *p, *ip; if(nf != 2) return "args"; if(f[1][0] != 'p') return "cannot set secondary partition active"; if((p = (Dospart*)findpart(edit, f[1])) == nil) return "unknown partition"; for(i=0; i<edit->npart; i++) { ip = (Dospart*)edit->part[i]; if(ip->active & Active) { ip->active &= ~Active; ip->changed = 1; edit->changed = 1; } } if((p->active & Active) == 0) { p->active |= Active; p->changed = 1; edit->changed = 1; } return nil;}static char*strupr(char *s){ char *p; for(p=s; *p; p++) *p = toupper(*p); return s;}static voiddumplist(void){ int i, n; n = 0; for(i=0; i<256; i++) { if(types[i].desc) { print("%-16s", types[i].desc); if(n++%4 == 3) print("\n"); } } if(n%4) print("\n");}static char*cmdtype(Edit *edit, int nf, char **f){ char *q; Dospart *p; int i; if(nf < 2) return "args"; if((p = (Dospart*)findpart(edit, f[1])) == nil) return "unknown partition"; if(nf == 2) { for(;;) { fprint(2, "new partition type [? for list]: "); q = getline(edit); if(q[0] == '?') dumplist(); else break; } } else q = f[2]; strupr(q); for(i=0; i<256; i++) if(types[i].desc && strcmp(types[i].desc, q) == 0) break; if(i < 256 && p->type != i) { p->type = i; p->changed = 1; edit->changed = 1; } return nil;}static char*cmdext(Edit *edit, int nf, char **f){ switch(f[0][0]) { case 'A': return cmdactive(edit, nf, f); case 't': return cmdtype(edit, nf, f); case 'R': recover(edit); return nil; default: return "unknown command"; }}static intDfmt(Fmt *f){ char buf[60]; uchar *p; int c, h, s; p = va_arg(f->args, uchar*); h = p[0]; c = p[2]; c |= (p[1]&0xC0)<<2; s = (p[1] & 0x3F); sprint(buf, "%d/%d/%d", c, h, s); return fmtstrcpy(f, buf);}static voidwritechs(Disk *disk, uchar *p, vlong lba){ int c, h, s; s = lba % disk->s; h = (lba / disk->s) % disk->h; c = lba / (disk->s * disk->h); if(c >= 1024) { c = 1023; h = disk->h - 1; s = disk->s - 1; } p[0] = h; p[1] = ((s+1) & 0x3F) | ((c>>2) & 0xC0); p[2] = c;}static voidwrtentry(Disk *disk, Tentry *tp, int type, u32int xbase, u32int lba, u32int end){ tp->type = type; writechs(disk, &tp->starth, lba); writechs(disk, &tp->endh, end-1); putle32(tp->xlba, lba-xbase); putle32(tp->xsize, end-lba);}static intwrextend(Edit *edit, int i, vlong xbase, vlong startlba, vlong *endlba){ int ni; Table table; Tentry *tp, *ep; Dospart *p; Disk *disk; if(i == edit->npart){ *endlba = edit->disk->secs; Finish: if(startlba < *endlba){ disk = edit->disk; diskread(disk, &table, sizeof table, mbroffset+startlba, Toffset); tp = table.entry; ep = tp+NTentry; for(; tp<ep; tp++) memset(tp, 0, sizeof *tp); table.magic[0] = Magic0; table.magic[1] = Magic1; if(diskwrite(edit->disk, &table, sizeof table, mbroffset+startlba, Toffset) < 0) recover(edit); } return i; } p = (Dospart*)edit->part[i]; if(p->primary){ *endlba = (vlong)p->start*sec2cyl; goto Finish; } disk = edit->disk; diskread(disk, &table, sizeof table, mbroffset+startlba, Toffset); tp = table.entry; ep = tp+NTentry; ni = wrextend(edit, i+1, xbase, p->end*sec2cyl, endlba); *tp = p->Tentry; wrtentry(disk, tp, p->type, startlba, startlba+disk->s, p->end*sec2cyl); tp++; if(p->end*sec2cyl != *endlba){ memset(tp, 0, sizeof *tp); wrtentry(disk, tp, TypeEXTENDED, xbase, p->end*sec2cyl, *endlba); tp++; } for(; tp<ep; tp++) memset(tp, 0, sizeof *tp); table.magic[0] = Magic0; table.magic[1] = Magic1; if(diskwrite(edit->disk, &table, sizeof table, mbroffset+startlba, Toffset) < 0) recover(edit); return ni;} static voidwrpart(Edit *edit){ int i, ni, t; Table table; Tentry *tp, *ep; Disk *disk; vlong s, endlba; Dospart *p; disk = edit->disk; diskread(disk, &table, sizeof table, mbroffset, Toffset); tp = table.entry; ep = tp+NTentry; for(i=0; i<edit->npart && tp<ep; ) { p = (Dospart*)edit->part[i]; if(p->start == 0) s = disk->s; else s = p->start*sec2cyl; if(p->primary) { *tp = p->Tentry; wrtentry(disk, tp, p->type, 0, s, p->end*sec2cyl); tp++; i++; } else { ni = wrextend(edit, i, p->start*sec2cyl, p->start*sec2cyl, &endlba); memset(tp, 0, sizeof *tp); if(endlba >= 1024*sec2cyl) t = TypeEXTHUGE; else t = TypeEXTENDED; wrtentry(disk, tp, t, 0, s, endlba); tp++; i = ni; } } for(; tp<ep; tp++) memset(tp, 0, sizeof(*tp)); if(i != edit->npart) sysfatal("cannot happen #1"); if(diskwrite(disk, &table, sizeof table, mbroffset, Toffset) < 0) recover(edit); /* bring parts up to date */ freenamelist(); for(i=0; i<edit->npart; i++) plan9print((Dospart*)edit->part[i], -1); if(ctldiff(edit, disk->ctlfd) < 0) fprint(2, "?warning: partitions could not be updated in devsd\n");}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -