📄 partition.c
字号:
/* * Rule format: * * +------+------+------+------+ * |drive |offset|expect| set | * +------+------+------+------+ * 0 1 2 3 */static void add_rule(unsigned char bios,unsigned char offset, unsigned char expect,unsigned char set){ int i; if (curr_prt_map == PRTMAP_SIZE) cfg_error("Too many change rules (more than %s)",PRTMAP_SIZE); if (verbose >= 3) printf(" Adding rule: disk 0x%02x, offset 0x%x, 0x%02x -> 0x%02x\n", bios,PART_TABLE_OFFSET+offset,expect,set); prt_map[curr_prt_map] = (set << 24) | (expect << 16) | (offset << 8) | bios; for (i = 0; i < curr_prt_map; i++) { if (prt_map[i] == prt_map[curr_prt_map]) die("Repeated rule: disk 0x%02x, offset 0x%x, 0x%02x -> 0x%02x", bios,PART_TABLE_OFFSET+offset,expect,set); if ((prt_map[i] & 0xffff) == ((offset << 8) | bios) && (prt_map[i] >> 24) == expect) die("Redundant rule: disk 0x%02x, offset 0x%x: 0x%02x -> 0x%02x " "-> 0x%02x",bios,PART_TABLE_OFFSET+offset, (prt_map[i] >> 16) & 0xff,expect,set); } curr_prt_map++;}#endifstatic int has_partition;static CHANGE_RULE *may_change(unsigned char sys_ind){ CHANGE_RULE *cr = change_rules; while (cr) { if (cr->normal == sys_ind || cr->hidden == sys_ind) return cr; cr = cr->next; } return NULL;}void do_cr_auto(void){ GEOMETRY geo; struct stat st; char *table, *table2, *other; int partition, pfd, i, j; struct partition part_table[PART_MAX]; if (autoauto) has_partition = 0; other = cfg_get_strg(cf_top, "other"); if (verbose > 4) printf("do_cr_auto: other=%s has_partition=%d\n", other, has_partition);#if 0 i = other[strlen(other)-1] - '0'; if (i>PART_MAX || i<1) return;#endif table = cfg_get_strg(cf_other,"table"); table2 = boot_mbr(other, 1); /* get possible default */ if (!table) table = table2; if (!table && autoauto) return; if (table && autoauto && !table2) cfg_error("TABLE may not be specified"); if (has_partition) cfg_error("AUTOMATIC must be before PARTITION"); if (!table) cfg_error("TABLE must be set to use AUTOMATIC"); /* */ if (stat(table,&st) < 0) die("stat %s: %s",table,strerror(errno)); geo_get(&geo,st.st_rdev & D_MASK(st.st_rdev),-1,1); partition = st.st_rdev & P_MASK(st.st_rdev); if (!S_ISBLK(st.st_mode) || partition) cfg_error("\"%s\" doesn't contain a primary partition table",table); pfd = open(table, O_RDONLY); if (pfd<0) die("Cannot open %s", table); if (lseek(pfd, PART_TABLE_OFFSET, SEEK_SET)!=PART_TABLE_OFFSET) die("Cannot seek to partition table of %s", table); if (read(pfd, part_table, sizeof(part_table))!=sizeof(part_table)) die("Cannot read Partition Table of %s", table); close(pfd); partition = other[strlen(other)-1] - '0'; if (verbose > 3) printf("partition = %d\n", partition); for (j=i=0; i<PART_MAX; i++) if (may_change(part_table[i].sys_ind)) j++; if (j>1)#if defined(LCF_REWRITE_TABLE) && !defined(LCF_READONLY) for (i=0; i<PART_MAX; i++) { CHANGE_RULE *cr; if ((cr=may_change(part_table[i].sys_ind))) { j = i*PARTITION_ENTRY + PART_TYPE_ENT_OFF; if (autoauto && !nowarn) { fflush(stdout); fprintf(errstd, "Warning: CHANGE AUTOMATIC assumed after \"other=%s\"\n", other); autoauto = 0; /* suppress further warnings */ } if (i == partition-1) add_rule(geo.device, j, cr->hidden, cr->normal); else add_rule(geo.device, j, cr->normal, cr->hidden); } }#else if (!nowarn) fprintf(errstd, "Warning: This LILO is compiled without REWRITE_TABLE;\n" " unable to generate CHANGE/AUTOMATIC change-rules\n");#endif}void do_cr_part(void){ GEOMETRY geo; struct stat st; char *tmp; int partition,part_base; tmp = cfg_get_strg(cf_change,"partition"); if (stat(tmp,&st) < 0) die("stat %s: %s",tmp,strerror(errno)); geo_get(&geo,st.st_rdev & D_MASK(st.st_rdev),-1,1); partition = st.st_rdev & P_MASK(st.st_rdev); if (!S_ISBLK(st.st_mode) || !partition || partition > PART_MAX) cfg_error("\"%s\" isn't a primary partition",tmp); part_base = (partition-1)*PARTITION_ENTRY; has_partition = 1; cfg_init(cf_change_dsc); (void) cfg_parse(cf_change_dsc); tmp = cfg_get_strg(cf_change_dsc,"set"); if (tmp) {#if defined(LCF_REWRITE_TABLE) && !defined(LCF_READONLY) CHANGE_RULE *walk; char *here; int hidden; here = (void*)NULL; /* quiet GCC */ hidden = 0; /* quiet GCC */ if (strlen(tmp) < 7 || !(here = strrchr(tmp,'_')) || ((hidden = strcasecmp(here+1,"normal")) && strcasecmp(here+1,"hidden"))) cfg_error("Type name must end with _normal or _hidden"); *here = 0; for (walk = change_rules; walk; walk = walk->next) if (!strcasecmp(walk->type,tmp)) break; if (!walk) cfg_error("Unrecognized type name"); add_rule(geo.device,part_base+PART_TYPE_ENT_OFF,hidden ? walk->normal : walk->hidden,hidden ? walk->hidden : walk->normal);#else die("This LILO is compiled without REWRITE_TABLE and doesn't support " "the SET option");#endif } if (cfg_get_flag(cf_change_dsc,"activate")) {#if defined(LCF_REWRITE_TABLE) && !defined(LCF_READONLY) add_rule(geo.device,part_base+PART_ACT_ENT_OFF,0x00,0x80); if (cfg_get_flag(cf_change_dsc,"deactivate")) cfg_error("ACTIVATE and DEACTIVATE are incompatible");#else die("This LILO is compiled without REWRITE_TABLE and doesn't support " "the ACTIVATE option");#endif } if (cfg_get_flag(cf_change_dsc,"deactivate"))#if defined(LCF_REWRITE_TABLE) && !defined(LCF_READONLY) add_rule(geo.device,part_base+PART_ACT_ENT_OFF,0x80,0x00);#else die("This LILO is compiled without REWRITE_TABLE and doesn't support " "the DEACTIVATE option");#endif cfg_unset(cf_change,"partition");}void do_change(void){ cfg_init(cf_change); has_partition = 0; (void) cfg_parse(cf_change);}void preload_types(void){#if 0 /* don't know if it makes sense to add these too */ add_type("Netware", 0x64, 0x74); add_type("OS2_BM", 0x0a, 0x1a);#endif add_type("OS2_HPFS", 0x07, 0x17); add_type("FAT16_lba", PART_FAT16_LBA, -1); add_type("FAT32_lba", PART_FAT32_LBA, -1); add_type("FAT32", PART_FAT32, -1); add_type("NTFS", PART_NTFS, -1); add_type("DOS16_big", PART_DOS16_BIG, -1); add_type("DOS16_small", PART_DOS16_SMALL, -1); add_type("DOS12", PART_DOS12, -1);}#define PART_BEGIN 0x1be#define PART_NUM 4#define PART_SIZE 16#define PART_ACTIVE 0x80#define PART_INACTIVE 0void do_activate(char *where, char *which){ struct stat st; int fd,number,count; unsigned char flag, ptype; if ((fd = open(where, !which ? O_RDONLY : O_RDWR)) < 0) die("open %s: %s",where,strerror(errno)); if (fstat(fd,&st) < 0) die("stat %s: %s",where,strerror(errno)); if (!S_ISBLK(st.st_mode)) die("%s: not a block device",where); if (verbose >= 1) { printf("st.st_dev = %04X, st.st_rdev = %04X\n", (int)st.st_dev, (int)st.st_rdev); } if ((st.st_rdev & has_partitions(st.st_rdev)) != st.st_rdev) die("%s is not a master device with a primary partition table", where); if (!which) { /* one argument: display active partition */ for (count = 1; count <= PART_NUM; count++) { if (lseek(fd,PART_BEGIN+(count-1)*PART_SIZE,0) < 0) die("lseek: %s",strerror(errno)); if (read(fd,&flag,1) != 1) die("read: %s",strerror(errno)); if (flag == PART_ACTIVE) { printf("%s%d\n",where,count); exit(0); } } die("No active partition found on %s",where); } number = to_number(which); if (number < 1 || number > 4) die("%s: not a valid partition number (1-4)",which); for (count = 1; count <= PART_NUM; count++) { if (lseek(fd,PART_BEGIN+(count-1)*PART_SIZE+4,0) < 0) die("lseek: %s",strerror(errno)); if (read(fd,&ptype,1) != 1) die("read: %s",strerror(errno)); if (count == number && ptype==0) die("Cannot activate an empty partition"); } if (test) { printf("The partition table of %s has *NOT* been updated\n",where); } else for (count = 1; count <= PART_NUM; count++) { if (lseek(fd,PART_BEGIN+(count-1)*PART_SIZE,0) < 0) die("lseek: %s",strerror(errno)); flag = count == number ? PART_ACTIVE : PART_INACTIVE; if (write(fd,&flag,1) != 1) die("write: %s",strerror(errno)); } exit(0);}void do_install_mbr(char *where, char *what){ int fd, i;#ifndef LCF_BUILTIN int nfd;#endif struct stat st; char buf[SECTOR_SIZE]; if (!what) what = DFL_MBR; if ((fd=open(where,O_RDWR)) < 0) die("Cannot open %s: %s", where,strerror(errno)); if (fstat(fd,&st) < 0) die("stat: %s : %s", where,strerror(errno)); if (!S_ISBLK(st.st_mode)) die("%s not a block device",where); if (st.st_rdev != (st.st_rdev & has_partitions(st.st_rdev))) die("%s is not a master device with a primary parition table",where); if (read(fd,buf,SECTOR_SIZE) != SECTOR_SIZE) die("read %s: %s",where, strerror(errno));#ifndef LCF_BUILTIN if ((nfd=open(what,O_RDONLY)) < 0) die("Cannot open %s: %s",what,strerror(errno)); if (read(nfd,buf,MAX_BOOT_SIZE) != MAX_BOOT_SIZE) die("read %s: %s",what,strerror(errno));#else memcpy(buf, Mbr.data, MAX_BOOT_SIZE);#endif *(unsigned short*)&buf[BOOT_SIG_OFFSET] = BOOT_SIGNATURE; if (zflag) { char *p = buf+MAX_BOOT_SIZE; for (i=0; i<8; i++) *p++ = 0; } else if (*(int*)&buf[PART_TABLE_OFFSET - 6] == 0) { i = st.st_rdev; i %= 271; /* modulo a prime number; eg, 2551, 9091 */ srand(time(NULL)); /* seed the random number generator */ while (i--) rand(); *(int*)&buf[PART_TABLE_OFFSET - 6] = rand(); /* insert serial number */ if (*(short*)&buf[PART_TABLE_OFFSET - 2] == 0) *(short*)&buf[PART_TABLE_OFFSET - 2] = MAGIC_SERIAL; } if (lseek(fd,0,SEEK_SET) != 0) die("seek %s; %s", where, strerror(errno)); if (!test) { if (write(fd,buf,SECTOR_SIZE) != SECTOR_SIZE) die("write %s: %s",where,strerror(errno)); } close(fd);#ifndef LCF_BUILTIN close(nfd);#endif printf("The Master Boot Record of %s has %sbeen updated.\n", where, test ? "*NOT* " : ""); sync(); exit(0);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -