📄 part.c
字号:
/* part 1.47 - Partition table editor Author: Kees J. Bot * 13 Mar 1992 * Needs about 22k heap+stack. */#define nil 0#include <sys/types.h>#include <stdio.h>#include <termcap.h>#include <errno.h>#include <unistd.h>#include <stddef.h>#include <stdlib.h>#include <string.h>#include <signal.h>#include <fcntl.h>#include <time.h>#include <dirent.h>#include <limits.h>#include <sys/stat.h>#include <sys/wait.h>#include <sys/ioctl.h>#include <minix/config.h>#include <minix/const.h>#include <minix/partition.h>#include <ibm/partition.h>#include <termios.h>#if !__minix_vmd#define div64u(i, j) ((i) / (j))#endif/* Template: ----first---- --geom/last-- ------sectors----- Device Cyl Head Sec Cyl Head Sec Base Size Kb /dev/hd0 977 5 17 /dev/hd0:2 0 0 2 976 4 16 2 83043 41521Num Sort Type 1* hd1 81 MINIX 0 0 3 33 4 9 3 2880 1440 2 hd2 81 MINIX 33 4 10 178 2 2 2883 12284 6142 3 hd3 81 MINIX 178 2 3 976 4 16 15167 67878 33939 4 hd4 00 None 0 0 0 0 0 -1 0 0 0 */#define MAXSIZE 99999999L /* Will 100 G be enough this year? */#define SECTOR_SIZE 512#define DEV_FD0 0x200 /* Device number of /dev/fd0 */#define DEV_HD0 0x300 /* Device number of /dev/hd0 */#define arraysize(a) (sizeof(a) / sizeof((a)[0]))#define arraylimit(a) ((a) + arraysize(a))void report(const char *label){ fprintf(stderr, "part: %s: %s\n", label, strerror(errno));}void fatal(const char *label){ report(label); exit(1);}struct termios termios;void save_ttyflags(void)/* Save tty attributes for later restoration. */{ if (tcgetattr(0, &termios) < 0) fatal("");}void restore_ttyflags(void)/* Reset the tty flags to how we got 'em. */{ if (tcsetattr(0, TCSANOW, &termios) < 0) fatal("");}void tty_raw(void)/* Set the terminal to raw mode, no signals, no echoing. */{ struct termios rawterm; rawterm= termios; rawterm.c_lflag &= ~(ICANON|ISIG|ECHO); rawterm.c_iflag &= ~(ICRNL); if (tcsetattr(0, TCSANOW, &rawterm) < 0) fatal("");}#define ctrl(c) ((c) == '?' ? '\177' : ((c) & '\37'))char t_cd[16], t_cm[32], t_so[16], t_se[16], t_md[16], t_me[16];int t_li, t_co;#define STATUSROW 10void init_tty(void)/* Get terminal capabilities and set the tty to "editor" mode. */{ char *term; static char termbuf[1024]; char *tp; if ((term= getenv("TERM")) == nil || tgetent(termbuf, term) != 1) { fprintf(stderr, "part: Can't get terminal capabilities\n"); exit(1); } if (tgetstr("cd", (tp= t_cd, &tp)) == nil || tgetstr("cm", (tp= t_cm, &tp)) == nil) { fprintf(stderr, "part: This terminal is too dumb\n"); exit(1); } t_li= tgetnum("li"); t_co= tgetnum("co"); (void) tgetstr("so", (tp= t_so, &tp)); (void) tgetstr("se", (tp= t_se, &tp)); (void) tgetstr("md", (tp= t_md, &tp)); (void) tgetstr("me", (tp= t_me, &tp)); save_ttyflags(); tty_raw();}void putchr(int c){ putchar(c);}void putstr(char *s){ int c; while ((c= *s++) != 0) putchr(c);}void set_cursor(int row, int col){ tputs(tgoto(t_cm, col, row), 1, putchr);}int statusrow= STATUSROW;int stat_ktl= 1;int need_help= 1;void stat_start(int serious)/* Prepare for printing on a fresh status line, possibly highlighted. */{ set_cursor(statusrow++, 0); tputs(t_cd, 1, putchr); if (serious) tputs(t_so, 1, putchr);}void stat_end(int ktl)/* Closing bracket for stat_start. Sets "keystrokes to live" of message. */{ tputs(t_se, 1, putchr); stat_ktl= ktl; need_help= 1;}void stat_reset(void)/* Reset the statusline pointer and clear old messages if expired. */{ if (stat_ktl > 0 && --stat_ktl == 0) { statusrow= STATUSROW; need_help= 1; } if (need_help && statusrow < (24-2)) { if (statusrow > STATUSROW) stat_start(0); stat_start(0); putstr("Type '+' or '-' to change, 'r' to read, '?' for more help, '!' for advice"); } statusrow= STATUSROW; need_help= 0;}void clear_screen(void){ set_cursor(0, 0); tputs(t_cd, 1, putchr); stat_ktl= 1; stat_reset();}void reset_tty(void)/* Reset the tty to cooked mode. */{ restore_ttyflags(); set_cursor(statusrow, 0); tputs(t_cd, 1, putchr);}void *alloc(size_t n){ void *m; if ((m= malloc(n)) == nil) { reset_tty(); fatal(""); } return m;}#ifndef makedev /* Missing in sys/types.h */#define minor(dev) (((dev) >> MINOR) & BYTE)#define major(dev) (((dev) >> MAJOR) & BYTE)#define makedev(major, minor) \ ((dev_t) (((major) << MAJOR) | ((minor) << MINOR)))#endiftypedef enum parttype { DUNNO, SUBPART, PRIMARY } parttype_t;typedef struct device { struct device *next, *prev; /* Circular dequeue. */ dev_t rdev; /* Device number (sorting only). */ char *name; /* E.g. /dev/hd0 */ char *subname; /* E.g. /dev/hd0:2 */ char part[6]; /* E.g. hd2a */ parttype_t parttype;} device_t;device_t *firstdev= nil, *curdev;void newdevice(char *name, int scanning)/* Add a device to the device list. If scanning is set then we are reading * /dev, so insert the device in device number order and make /dev/hd0 current. */{ device_t *new, *nextdev, *prevdev; char *base; int max, len; struct stat st; st.st_rdev= 0; if (scanning) { if (stat(name, &st) < 0 || !S_ISBLK(st.st_mode)) return; switch (major(st.st_rdev)) { case 0: case 1: case 15: return; case 2: if (minor(st.st_rdev) >= 4) return; break; default: if (minor(st.st_rdev) >= 0x80 || minor(st.st_rdev) % 5 != 0) return; } /* Interesting device found. */ } else { (void) stat(name, &st); } new= alloc(sizeof(*new)); new->rdev= st.st_rdev; new->name= alloc((strlen(name) + 1) * sizeof(new->name[0])); strcpy(new->name, name); new->subname= new->name; new->parttype= DUNNO; if (major(st.st_rdev) == major(DEV_FD0)) { new->parttype= SUBPART; } else if (st.st_rdev >= DEV_HD0 && minor(st.st_rdev) < 128 && minor(st.st_rdev) % 5 == 0) { new->parttype= PRIMARY; } if ((base= strrchr(name, '/')) == nil) base= name; else base++; max= new->parttype == SUBPART ? 4 : 5; len= strlen(base); strcpy(new->part, len < max ? base : base + len - max); if (firstdev == nil) { firstdev= new; new->next= new->prev= new; curdev= firstdev; return; } nextdev= firstdev; while (new->rdev >= nextdev->rdev && (nextdev= nextdev->next) != firstdev) {} prevdev= nextdev->prev; new->next= nextdev; nextdev->prev= new; new->prev= prevdev; prevdev->next= new; if (new->rdev < firstdev->rdev) firstdev= new; if (new->rdev == DEV_HD0) curdev= new; if (curdev->rdev != DEV_HD0) curdev= firstdev;}void getdevices(void)/* Get all block devices from /dev that look interesting. */{ DIR *d; struct dirent *e; char name[5 + NAME_MAX + 1]; if ((d= opendir("/dev")) == nil) fatal("/dev"); while ((e= readdir(d)) != nil) { strcpy(name, "/dev/"); strcpy(name + 5, e->d_name); newdevice(name, 1); } (void) closedir(d);}/* One featureful master bootstrap. */unsigned char bootstrap[] = {0353,0001,0000,0061,0300,0216,0330,0216,0300,0372,0216,0320,0274,0000,0174,0373,0275,0276,0007,0211,0346,0126,0277,0000,0006,0271,0000,0001,0374,0363,0245,0352,0044,0006,0000,0000,0264,0002,0315,0026,0250,0010,0164,0033,0350,0071,0001,0174,0007,0060,0344,0315,0026,0242,0205,0007,0054,0060,0074,0012,0163,0363,0120,0350,0046,0001,0205,0007,0130,0353,0012,0240,0002,0006,0204,0300,0165,0003,0351,0147,0000,0230,0262,0005,0366,0362,0262,0200,0000,0302,0210,0340,0120,0350,0234,0000,0163,0003,0351,0147,0000,0130,0054,0001,0175,0003,0351,0141,0000,0276,0276,0175,0211,0357,0271,0040,0000,0363,0245,0200,0301,0004,0211,0356,0215,0174,0020,0070,0154,0004,0164,0016,0213,0135,0010,0053,0134,0010,0213,0135,0012,0033,0134,0012,0163,0014,0212,0044,0206,0144,0020,0210,0044,0106,0071,0376,0162,0364,0211,0376,0201,0376,0356,0007,0162,0326,0342,0322,0211,0356,0264,0020,0366,0344,0001,0306,0200,0174,0004,0001,0162,0026,0353,0021,0204,0322,0175,0041,0211,0356,0200,0174,0004,0000,0164,0013,0366,0004,0200,0164,0006,0350,0070,0000,0162,0053,0303,0203,0306,0020,0201,0376,0376,0007,0162,0346,0350,0215,0000,0211,0007,0376,0302,0204,0322,0174,0023,0315,0021,0321,0340,0321,0340,0200,0344,0003,0070,0342,0167,0355,0350,0011,0000,0162,0350,0303,0350,0003,0000,0162,0146,0303,0211,0356,0214,0134,0010,0214,0134,0012,0277,0003,0000,0122,0006,0127,0264,0010,0315,0023,0137,0007,0200,0341,0077,0376,0306,0210,0310,0366,0346,0211,0303,0213,0104,0010,0213,0124,0012,0367,0363,0222,0210,0325,0366,0361,0060,0322,0321,0352,0321,0352,0010,0342,0210,0321,0376,0301,0132,0210,0306,0273,0000,0174,0270,0001,0002,0315,0023,0163,0020,0200,0374,0200,0164,0011,0117,0174,0006,0060,0344,0315,0023,0163,0270,0371,0303,0201,0076,0376,0175,0125,0252,0165,0001,0303,0350,0013,0000,0243,0007,0353,0005,0350,0004,0000,0227,0007,0353,0376,0136,0255,0126,0211,0306,0254,0204,0300,0164,0011,0264,0016,0273,0001,0000,0315,0020,0353,0362,0303,0057,0144,0145,0166,0057,0150,0144,0077,0010,0000,0015,0012,0000,0116,0157,0156,0145,0040,0141,0143,0164,0151,0166,0145,0015,0012,0000,0122,0145,0141,0144,0040,0145,0162,0162,0157,0162,0040,0000,0116,0157,0164,0040,0142,0157,0157,0164,0141,0142,0154,0145,0040,0000,0000,};int dirty= 0;unsigned char bootblock[SECTOR_SIZE];struct part_entry table[1 + NR_PARTITIONS];int existing[1 + NR_PARTITIONS];unsigned long offset= 0, extbase= 0, extsize;int submerged= 0;char sort_index[1 + NR_PARTITIONS];unsigned cylinders= 1, heads= 1, sectors= 1, secpcyl= 1;unsigned alt_cyls= 1, alt_heads= 1, alt_secs= 1;int precise= 0;int device= -1;unsigned long sortbase(struct part_entry *pe){ return pe->sysind == NO_PART ? -1 : pe->lowsec;}void sort(void)/* Let the sort_index array show the order partitions are sorted in. */{ int i, j; int idx[1 + NR_PARTITIONS]; for (i= 1; i <= NR_PARTITIONS; i++) idx[i]= i; for (i= 1; i <= NR_PARTITIONS; i++) { for (j= 1; j <= NR_PARTITIONS-1; j++) { int sj= idx[j], sj1= idx[j+1]; if (sortbase(&table[sj]) > sortbase(&table[sj1])) { idx[j]= sj1; idx[j+1]= sj; } } } for (i= 1; i <= NR_PARTITIONS; i++) sort_index[idx[i]]= i;}void dos2chs(unsigned char *dos, unsigned *chs)/* Extract cylinder, head and sector from the three bytes DOS uses to address * a sector. Note that bits 8 & 9 of the cylinder number come from bit 6 & 7 * of the sector byte. The sector number is rebased to count from 0. */{ chs[0]= ((dos[1] & 0xC0) << 2) | dos[2]; chs[1]= dos[0]; chs[2]= (dos[1] & 0x3F) - 1;}void abs2dos(unsigned char *dos, unsigned long pos)/* Translate a sector offset to three DOS bytes. */{ unsigned h, c, s; c= pos / secpcyl; h= (pos % secpcyl) / sectors; s= pos % sectors + 1; dos[0]= h; dos[1]= s | ((c >> 2) & 0xC0); dos[2]= c & 0xFF;}void recompute0(void)/* Recompute the partition size for the device after a geometry change. */{ if (device < 0) { cylinders= heads= sectors= 1; memset(table, 0, sizeof(table)); } else if (!precise && offset == 0) { table[0].lowsec= 0; table[0].size= (unsigned long) cylinders * heads * sectors; } table[0].sysind= device < 0 ? NO_PART : MINIX_PART; secpcyl= heads * sectors;}void guess_geometry(void)/* With a bit of work one can deduce the disk geometry from the partition * table. This may be necessary if the driver gets it wrong. (If partition * tables didn't have C/H/S numbers we would not care at all...) */{ int i, n; struct part_entry *pe; unsigned chs[3]; unsigned long sec; unsigned h, s; unsigned char HS[256][8]; /* Bit map off all possible H/S */ alt_cyls= alt_heads= alt_secs= 0; /* Initially all possible H/S combinations are possible. HS[h][0] * bit 0 is used to rule out a head value. */ for (h= 1; h <= 255; h++) { for (s= 0; s < 8; s++) HS[h][s]= 0xFF; } for (i= 0; i < 2*NR_PARTITIONS; i++) { pe= &(table+1)[i >> 1]; if (pe->sysind == NO_PART) continue; /* Get the end or start sector numbers (in that order). */ if ((i & 1) == 0) { dos2chs(&pe->last_head, chs); sec= pe->lowsec + pe->size - 1; } else { dos2chs(&pe->start_head, chs); sec= pe->lowsec; } if (chs[0] >= alt_cyls) alt_cyls= chs[0]+1; /* Which H/S combinations can be ruled out? */ for (h= 1; h <= 255; h++) { if (HS[h][0] == 0) continue; n = 0; for (s= 1; s <= 63; s++) { if ((chs[0] * h + chs[1]) * s + chs[2] != sec) { HS[h][s/8] &= ~(1 << (s%8)); } if (HS[h][s/8] & (1 << (s%8))) n++; } if (n == 0) HS[h][0]= 0; } } /* See if only one remains. */ i= 0; for (h= 1; h <= 255; h++) { if (HS[h][0] == 0) continue; for (s= 1; s <= 63; s++) { if (HS[h][s/8] & (1 << (s%8))) { i++; alt_heads= h; alt_secs= s; } } } /* Forget it if more than one choice... */ if (i > 1) alt_cyls= alt_heads= alt_secs= 0;}void geometry(void)/* Find out the geometry of the device by querying the driver, or by looking * at the partition table. These numbers are crosschecked to make sure that * the geometry is correct. Master bootstraps other than the Minix one use * the CHS numbers in the partition table to load the bootstrap of the active * partition. */{ struct stat dst; int err= 0; struct partition geometry; if (submerged) { /* Geometry already known. */ sort(); return; } precise= 0; cylinders= 0; recompute0(); if (device < 0) return; /* Try to guess the geometry from the partition table. */ guess_geometry(); /* Try to get the geometry from the driver. */ (void) fstat(device, &dst); if (S_ISBLK(dst.st_mode) || S_ISCHR(dst.st_mode)) { /* Try to get the drive's geometry from the driver. */ if (ioctl(device, DIOCGETP, &geometry) < 0) err= errno; else { table[0].lowsec= div64u(geometry.base, SECTOR_SIZE); table[0].size= div64u(geometry.size, SECTOR_SIZE); cylinders= geometry.cylinders; heads= geometry.heads;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -