📄 sfdisk.c
字号:
z->partno = pno;}#define BSD_DISKMAGIC (0x82564557UL)#define BSD_MAXPARTITIONS 16#define BSD_FS_UNUSED 0typedef unsigned char u8;typedef unsigned short u16;typedef unsigned int u32;struct bsd_disklabel { u32 d_magic; char d_junk1[4]; char d_typename[16]; char d_packname[16]; char d_junk2[92]; u32 d_magic2; char d_junk3[2]; u16 d_npartitions; /* number of partitions in following */ char d_junk4[8]; struct bsd_partition { /* the partition table */ u32 p_size; /* number of sectors in partition */ u32 p_offset; /* starting sector */ u32 p_fsize; /* filesystem basic fragment size */ u8 p_fstype; /* filesystem type, see below */ u8 p_frag; /* filesystem fragments per block */ u16 p_cpg; /* filesystem cylinders per group */ } d_partitions[BSD_MAXPARTITIONS]; /* actually may be more */};static voidbsd_partition(char *dev, int fd, struct part_desc *ep, struct disk_desc *z) { struct bsd_disklabel *l; struct bsd_partition *bp, *bp0; unsigned long start = ep->start; struct sector *s; struct part_desc *partitions = &(z->partitions[0]); int pno = z->partno; if (!(s = get_sector(dev,fd,start+1))) return; l = (struct bsd_disklabel *) (s->data); if (l->d_magic != BSD_DISKMAGIC || l->d_magic2 != BSD_DISKMAGIC) return; bp = bp0 = &l->d_partitions[0]; while (bp - bp0 < BSD_MAXPARTITIONS && bp - bp0 < l->d_npartitions) { if (pno+1 >= SIZE(z->partitions)) { do_warn(_("too many partitions - ignoring those " "past nr (%d)\n"), pno-1); break; } if (bp->p_fstype != BSD_FS_UNUSED) { partitions[pno].start = bp->p_offset; partitions[pno].size = bp->p_size; partitions[pno].sector = start+1; partitions[pno].offset = (char *)bp - (char *)bp0; partitions[pno].ep = 0; partitions[pno].ptype = BSD_TYPE; pno++; } bp++; } z->partno = pno;}#define MAKE_VERSION(p,q,r) (65536*(p) + 256*(q) + (r))static intlinux_version_code(void) { struct utsname my_utsname; int p, q, r; if (uname(&my_utsname) == 0) { p = atoi(strtok(my_utsname.release, ".")); q = atoi(strtok(NULL, ".")); r = atoi(strtok(NULL, ".")); return MAKE_VERSION(p,q,r); } return 0;}static intmsdos_partition(char *dev, int fd, unsigned long start, struct disk_desc *z) { int i; char *cp; struct partition pt; struct sector *s; struct part_desc *partitions = &(z->partitions[0]); int pno = z->partno; int bsd_later = (linux_version_code() >= MAKE_VERSION(2,3,40)); if (!(s = get_sector(dev, fd, start))) return 0; if (!msdos_signature(s)) return 0; cp = s->data + 0x1be; copy_to_part(cp,&pt); /* If I am not mistaken, recent kernels will hide this from us, so we will never actually see traces of a Disk Manager */ if (pt.sys_type == DM6_PARTITION || pt.sys_type == EZD_PARTITION || pt.sys_type == DM6_AUX1PARTITION || pt.sys_type == DM6_AUX3PARTITION) { do_warn(_("detected Disk Manager - unable to handle that\n")); return 0; } { unsigned int sig = *(unsigned short *)(s->data + 2); if (sig <= 0x1ae && *(unsigned short *)(s->data + sig) == 0x55aa && (1 & *(unsigned char *)(s->data + sig + 2))) { do_warn(_("DM6 signature found - giving up\n")); return 0; } } for (pno=0; pno<4; pno++,cp += sizeof(struct partition)) { partitions[pno].sector = start; partitions[pno].offset = cp - s->data; copy_to_part(cp,&pt); partitions[pno].start = start + pt.start_sect; partitions[pno].size = pt.nr_sects; partitions[pno].ep = 0; partitions[pno].p = pt; } z->partno = pno; for (i=0; i<4; i++) { if (is_extended(partitions[i].p.sys_type)) { if (!partitions[i].size) { do_warn(_("strange..., an extended partition of size 0?\n")); continue; } extended_partition(dev, fd, &partitions[i], z); } if (!bsd_later && is_bsd(partitions[i].p.sys_type)) { if (!partitions[i].size) { do_warn(_("strange..., a BSD partition of size 0?\n")); continue; } bsd_partition(dev, fd, &partitions[i], z); } } if (bsd_later) { for (i=0; i<4; i++) { if (is_bsd(partitions[i].p.sys_type)) { if (!partitions[i].size) { do_warn(_("strange..., a BSD partition of size 0?\n")); continue; } bsd_partition(dev, fd, &partitions[i], z); } } } return 1;}static intosf_partition(char *dev, int fd, unsigned long start, struct disk_desc *z) { return 0;}static intsun_partition(char *dev, int fd, unsigned long start, struct disk_desc *z) { return 0;}static intamiga_partition(char *dev, int fd, unsigned long start, struct disk_desc *z) { return 0;}static voidget_partitions(char *dev, int fd, struct disk_desc *z) { z->partno = 0; if (!msdos_partition(dev, fd, 0, z) && !osf_partition(dev, fd, 0, z) && !sun_partition(dev, fd, 0, z) && !amiga_partition(dev, fd, 0, z)) { do_warn(_(" %s: unrecognized partition table type\n"), dev); return; }}static intwrite_partitions(char *dev, int fd, struct disk_desc *z) { struct sector *s; struct part_desc *partitions = &(z->partitions[0]), *p; int pno = z->partno; if (no_write) { do_warn(_("-n flag was given: Nothing changed\n")); exit(0); } for (p = partitions; p < partitions+pno; p++) { s = get_sector(dev, fd, p->sector); if (!s) return 0; s->to_be_written = 1; if (p->ptype == DOS_TYPE) { copy_from_part(&(p->p), s->data + p->offset); s->data[510] = 0x55; s->data[511] = 0xaa; } } if (save_sector_file) { if (!save_sectors(dev, fd)) { fatal(_("Failed saving the old sectors - aborting\n")); return 0; } } if (!write_sectors(dev, fd)) { error(_("Failed writing the partition on %s\n"), dev); return 0; } return 1;}/* * F. The standard input *//* * Input format: * <start> <size> <type> <bootable> <c,h,s> <c,h,s> * Fields are separated by whitespace or comma or semicolon possibly * followed by whitespace; initial and trailing whitespace is ignored. * Numbers can be octal, decimal or hexadecimal, decimal is default * The <c,h,s> parts can (and probably should) be omitted. * Bootable is specified as [*|-], with as default not-bootable. * Type is given in hex, without the 0x prefix, or is [E|S|L|X], where * L (LINUX_NATIVE (83)) is the default, S is LINUX_SWAP (82), and E * is EXTENDED_PARTITION (5), X is LINUX_EXTENDED (85). * The default value of start is the first nonassigned sector/cylinder/... * The default value of size is as much as possible (until next * partition or end-of-disk). * .: end of chain of extended partitions. * * On interactive input an empty line means: all defaults. * Otherwise empty lines are ignored. */int eof, eob;struct dumpfld { int fldno; char *fldname; int is_bool;} dumpflds[] = { { 0, "start", 0 }, { 1, "size", 0 }, { 2, "Id", 0 }, { 3, "bootable", 1 }, { 4, "bh", 0 }, { 5, "bs", 0 }, { 6, "bc", 0 }, { 7, "eh", 0 }, { 8, "es", 0 }, { 9, "ec", 0 }};/* * Read a line, split it into fields * * (some primitive handwork, but a more elaborate parser seems * unnecessary) */#define RD_EOF (-1)#define RD_CMD (-2)static intread_stdin(unsigned char **fields, unsigned char *line, int fieldssize, int linesize) { unsigned char *lp, *ip; int c, fno; /* boolean true and empty string at start */ line[0] = '*'; line[1] = 0; for (fno=0; fno < fieldssize; fno++) fields[fno] = line + 1; fno = 0; /* read a line from stdin */ lp = fgets(line+2, linesize, stdin); if (lp == NULL) { eof = 1; return RD_EOF; } if (!(lp = index(lp, '\n'))) fatal(_("long or incomplete input line - quitting\n")); *lp = 0; /* remove comments, if any */ if ((lp = index(line+2, '#')) != 0) *lp = 0; /* recognize a few commands - to be expanded */ if (!strcmp(line+2, "unit: sectors")) { specified_format = F_SECTOR; return RD_CMD; } /* dump style? - then bad input is fatal */ if ((ip = index(line+2, ':')) != 0) { struct dumpfld *d; nxtfld: ip++; while(isspace(*ip)) ip++; if (*ip == 0) return fno; for(d = dumpflds; d-dumpflds < SIZE(dumpflds); d++) { if (!strncmp(ip, d->fldname, strlen(d->fldname))) { ip += strlen(d->fldname); while(isspace(*ip)) ip++; if (d->is_bool) fields[d->fldno] = line; else if (*ip == '=') { while(isspace(*++ip)) ; fields[d->fldno] = ip; while(isalnum(*ip)) /* 0x07FF */ ip++; } else fatal(_("input error: `=' expected after %s field\n"), d->fldname); if (fno <= d->fldno) fno = d->fldno + 1; if (*ip == 0) return fno; if (*ip != ',' && *ip != ';') fatal(_("input error: unexpected character %c after %s field\n"), *ip, d->fldname); *ip = 0; goto nxtfld; } } fatal(_("unrecognized input: %s\n"), ip); } /* split line into fields */ lp = ip = line+2; fields[fno++] = lp; while((c = *ip++) != 0) { if (!lp[-1] && (c == '\t' || c == ' ')) ; else if (c == '\t' || c == ' ' || c == ',' || c == ';') { *lp++ = 0; if (fno < fieldssize) fields[fno++] = lp; continue; } else *lp++ = c; } if (lp == fields[fno-1]) fno--; return fno;}/* read a number, use default if absent *//* a sign gives an offset from the default */static intget_ul(char *u, unsigned long *up, unsigned long def, int base) { char *nu; int sign = 0; unsigned long val; if (*u == '+') { sign = 1; u++; } else if (*u == '-') { sign = -1; u++; } if (*u) { errno = 0; val = strtoul(u, &nu, base); if (errno == ERANGE) { do_warn(_("number too big\n")); return -1; } if (*nu) { do_warn(_("trailing junk after number\n")); return -1; } if (sign == 1) val = def + val; else if (sign == -1) val = def - val; *up = val; } else *up = def; return 0;}/* There are two common ways to structure extended partitions: as nested boxes, and as a chain. Sometimes the partitions must be given in order. Sometimes all logical partitions must lie inside the outermost extended partition.NESTED: every partition is contained in the surrounding partitions and is disjoint from all others.CHAINED: every data partition is contained in the surrounding partitions and disjoint from all others, but extended partitions may lie outside (insofar as allowed by all_logicals_inside_outermost_extended).ONESECTOR: all data partitions are mutually disjoint; extended partitions each use one sector only (except perhaps for the outermost one).*/int partitions_in_order = 0;int all_logicals_inside_outermost_extended = 1;enum { NESTED, CHAINED, ONESECTOR } boxes = NESTED;/* find the default value for <start> - assuming entire units */static unsigned longfirst_free(int pno, int is_extended, struct part_desc *ep, int format, unsigned long mid, struct disk_desc *z) { unsigned long ff, fff; unsigned long unit = unitsize(format); struct part_desc *partitions = &(z->partitions[0]), *pp = 0; /* if containing ep undefined, look at its container */ if (ep && ep->p.sys_type == EMPTY_PARTITION) ep = ep->ep; if (ep) { if (boxes == NESTED || (boxes == CHAINED && !is_extended)) pp = ep; else if (all_logicals_inside_outermost_extended) pp = outer_extended_partition(ep); }#if 0 ff = pp ? (pp->start + unit - 1) / unit : 0;#else /* rounding up wastes almost an entire cylinder - round down and leave it to compute_start_sect() to fix the difference */ ff = pp ? pp->start / unit : 0;#endif /* MBR and 1st sector of an extended partition are never free */ if (unit == 1) ff++; again: for(pp = partitions; pp < partitions+pno; pp++) { if (!is_parent(pp, ep) && pp->size > 0) { if ((partitions_in_order || pp->start / unit <= ff || (mid && pp->start / unit <= mid)) && (fff = (pp->start + pp->size + unit - 1) / unit) > ff) { ff = fff; goto again; } } } return ff;}/* find the default value for <size> - assuming entire units */static unsigned longmax_length(int pno, int is_extended, struct part_desc *ep, int format, unsigned long start, struct disk_desc *z) { unsigned long fu; unsigned long unit = unitsize(format); struct part_desc *partitions = &(z->partitions[0]), *pp = 0; /* if containing ep undefined, look at its container */ if (ep && ep->p.sys_type == EMPTY_PARTITION) ep = ep->ep; if (ep) { if (boxes == NESTED || (boxes == CHAINED && !is_extended)) pp = ep; else if (all_logicals_inside_outermost_extended)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -