📄 partition.c
字号:
/* partition.c - Partition table handling *//*Copyright 1992-1998 Werner Almesberger.Copyright 1999-2002 John Coffman.All rights reserved.Licensed under the terms contained in the file 'COPYING' in the source directory.*/#include <stdlib.h>#include <unistd.h>#include <stdio.h>#include <string.h>#include <ctype.h>#include <fcntl.h>#include <errno.h>#include <a.out.h>#include <sys/stat.h>#include <sys/types.h>#include <linux/unistd.h>#include <limits.h>#include <linux/fs.h>#include <time.h>#include "config.h"#include "lilo.h"#include "common.h"#include "cfg.h"#include "device.h"#include "geometry.h"#include "partition.h"#include "boot.h"#include "loader.h" _syscall5(int, _llseek, uint, fd, ulong, hi, ulong, lo, loff_t *, res, uint, wh); int _llseek(unsigned int fd, unsigned long offset_high, unsigned long offset_low, loff_t * result, unsigned int whence); loff_t llseek(unsigned int fd, loff_t offs, unsigned int whence) { loff_t res; return _llseek(fd, offs>>32, offs, &res, whence) < 0 ? (loff_t)(-1) : res; }/* identify partitions which would be destroyed if the boot block is overwritten: known problems occur for: XFS NTFS DOS FAT (relocation will fix)*/int part_nowrite(char* device){ int fd; BOOT_SECTOR bs; int ret=0; /* say ok, unless we recognize a problem partition */ if ((fd = open(device, O_RDONLY)) < 0) pdie("part_nowrite check:"); if (read(fd, bs.sector, sizeof(bs)) != SECTOR_SIZE) pdie("part_nowrite: read:"); /* check for XFS */ if (!strncmp("XFSB", bs.sector, 4)) ret=2; /* check for NTFS */ else if ( !strncmp("NTFS", bs.par_d.system, 4) || strstr(bs.sector,"NTLDR") ) ret=2;/* check for DOS FAT */ else if ( (bs.par_d.bpb.media_descriptor >= 0xF8 || bs.par_d.bpb.media_descriptor == 0xF0) && *(short*)bs.par_d.bpb.bytes_per_sector == SECTOR_SIZE && (bs.par_d.bpb.number_of_FATs==1 || bs.par_d.bpb.number_of_FATs==2) /* sectors_per_cluster is a power of 2, meaning only 1 bit is on */ && bs.par_d.bpb.sectors_per_cluster && (bs.par_d.bpb.sectors_per_cluster & (bs.par_d.bpb.sectors_per_cluster-1))==0 ) ret=1; /* check for SWAP -- last check, as 'bs' is overwritten */ else if (*(long*)bs.sector == 0xFFFFFFFEUL) { if (lseek(fd, (PAGE_SIZE)-SECTOR_SIZE, SEEK_SET) != (PAGE_SIZE)-SECTOR_SIZE) pdie("part_nowrite lseek:"); if (SECTOR_SIZE != read(fd, bs.sector, sizeof(bs)) ) pdie("part_nowrite swap check:"); if (!strncmp(bs.sector+SECTOR_SIZE-10,"SWAPSPACE2",10) || !strncmp(bs.sector+SECTOR_SIZE-10,"SWAP-SPACE",10) ) ret=2; }/* didn't recognize the superblock type, so assume it is okay */ else ret=0; close(fd);/* check for override (-F) command line flag */ if (ret==2 && force_fs) { fprintf(errstd, "WARNING: '-F' override used. Filesystem on %s may be destroyed.\n", device); ret=0; } return ret;}void part_verify(int dev_nr,int type){ GEOMETRY geo; DEVICE dev; char backup_file[PATH_MAX+1]; int fd, bck_file, part, size, lin_3d, cyl; unsigned long second, base; struct partition part_table[PART_MAX]; int mask, i, pe, Linux, dos; unsigned short boot_sig; if (!has_partitions(dev_nr) || !(mask = P_MASK(dev_nr)) || !(dev_nr & mask)#if 0 || (dev_nr & mask) > PART_MAX#endif ) return; if (verbose >= 4) printf("part_verify: dev_nr=%04x, type=%d\n", dev_nr, type); geo_get(&geo,dev_nr & ~mask,-1,1); fd = dev_open(&dev,dev_nr & ~mask,cfg_get_flag(cf_options,"fix-table") && !test ? O_RDWR : O_RDONLY); part = (pe = dev_nr & mask)-1; if (lseek(fd, PART_TABLE_OFFSET, SEEK_SET) < 0) pdie("lseek partition table"); if (!(size = read(fd,(char *) part_table, sizeof(struct partition)* PART_MAX))) die("Short read on partition table"); if (size < 0) pdie("read partition table"); if ( read(fd, &boot_sig, sizeof(boot_sig)) != sizeof(boot_sig) || boot_sig != BOOT_SIGNATURE ) die("read boot signature failed"); if (verbose>=5) printf("part_verify: part#=%d\n", pe); second=base=0; for (i=0; i<PART_MAX; i++) { if (is_extd_part(part_table[i].sys_ind)) { if (!base) base = part_table[i].start_sect; else die("invalid partition table: second extended partition found"); } } i=5; while (i<=pe && base) { if (llseek(fd, LLSECTORSIZE*(base+second) + PART_TABLE_OFFSET, SEEK_SET) < 0) die("secondary llseek failed"); if (read(fd, part_table, sizeof(part_table)) != sizeof(part_table)) die("secondary read pt failed"); if ( read(fd, &boot_sig, sizeof(boot_sig)) != sizeof(boot_sig) || boot_sig != BOOT_SIGNATURE ) die("read second boot signature failed"); if (is_extd_part(part_table[1].sys_ind)) second=part_table[1].start_sect; else base = 0; i++; part=0; } i = part_table[part].sys_ind; Linux = i == PART_LINUX_MINIX || i == PART_LINUX_NATIVE || is_extd_part(i); i &= ~HIDDEN_OFF; dos = i == PART_DOS12 || i == PART_DOS16_SMALL || i == PART_DOS16_BIG || i == PART_FAT32 || i == PART_FAT32_LBA || i == PART_FAT16_LBA ; if (type && !Linux) { fflush(stdout); if (!dos || !nowarn) fprintf(errstd,"Device 0x%04X: Partition type 0x%02X does not seem " "suitable for a LILO boot sector\n",dev_nr,part_table[part].sys_ind); if (dos && !nowarn) fprintf(errstd,"but DOS/Windows/OS2 FAT partitions are now usable.\n"); if (!dos && !cfg_get_flag(cf_options,"ignore-table")) exit(1); } cyl = part_table[part].cyl+((part_table[part].sector >> 6) << 8); lin_3d = (part_table[part].sector & 63)-1+(part_table[part].head+ cyl*geo.heads)*geo.sectors; if (pe <= PART_MAX && (lin_3d > part_table[part].start_sect || (lin_3d < part_table[part].start_sect && cyl != BIOS_MAX_CYLS-1)) && !nowarn) { fflush(stdout); fprintf(errstd,"Device 0x%04X: Inconsistent partition table, %d%s entry\n", dev_nr & ~mask,part+1,!part ? "st" : part == 1 ? "nd" : part == 2 ? "rd" : "th"); fprintf(errstd," CHS address in PT: %d:%d:%d --> LBA (%d)\n", cyl, part_table[part].head, part_table[part].sector & 63, lin_3d); cyl = part_table[part].start_sect/geo.sectors/geo.heads; fprintf(errstd," LBA address in PT: %d --> CHS (%d:%d:%d)\n", part_table[part].start_sect, cyl, part_table[part].head = (part_table[part].start_sect/geo.sectors) % geo.heads, part_table[part].sector = (part_table[part].start_sect % geo.sectors)+1 ); if (cyl >= BIOS_MAX_CYLS) cyl = BIOS_MAX_CYLS-1; part_table[part].sector |= (cyl >> 8)<<6; part_table[part].cyl = cyl & 0xff; if (!cfg_get_flag(cf_options,"fix-table") && !cfg_get_flag(cf_options, "ignore-table")) die("Either FIX-TABLE or IGNORE-TABLE must be specified\n" "If not sure, first try IGNORE-TABLE (-P ignore)"); if (test || cfg_get_flag(cf_options,"ignore-table")) fprintf(errstd,"The partition table is *NOT* being adjusted.\n"); else { sprintf(backup_file,BACKUP_DIR "/part.%04X",dev_nr & ~mask); if ((bck_file = creat(backup_file,0644)) < 0) die("creat %s: %s",backup_file,strerror(errno)); if (!(size = write(bck_file,(char *) part_table, sizeof(struct partition)*PART_MAX))) die("Short write on %s",backup_file); if (size < 0) pdie(backup_file); if (close(bck_file) < 0) die("close %s: %s",backup_file,strerror(errno)); if (verbose > 0) printf("Backup copy of partition table in %s\n",backup_file); printf("Writing modified partition table to device 0x%04X\n", dev_nr & ~mask); if (lseek(fd,PART_TABLE_OFFSET,0) < 0) pdie("lseek partition table"); if (!(size = write(fd,(char *) part_table,sizeof(struct partition)* PART_MAX))) die("Short write on partition table"); if (size < 0) pdie("write partition table"); } } dev_close(&dev);}CHANGE_RULE *change_rules = NULL;void do_cr_reset(void){ CHANGE_RULE *next; while (change_rules) { next = change_rules->next; free((char *) change_rules->type); free(change_rules); change_rules = next; }}static unsigned char cvt_byte(const char *s){ char *end; unsigned long value; value = strtoul(s,&end,0); if (value > 255 || *end) cfg_error("\"%s\" is not a byte value",s); return value;}static void add_type(const char *type,int normal,int hidden){ CHANGE_RULE *rule; for (rule = change_rules; rule; rule = rule->next) if (!strcasecmp(rule->type,type)) die("Duplicate type name: \"%s\"",type); rule = alloc_t(CHANGE_RULE); rule->type = stralloc(type); rule->normal = normal == -1 ? hidden ^ HIDDEN_OFF : normal; rule->hidden = hidden == -1 ? normal ^ HIDDEN_OFF : hidden; rule->next = change_rules; change_rules = rule;}void do_cr_type(void){ const char *normal,*hidden; cfg_init(cf_change_rule); (void) cfg_parse(cf_change_rule); normal = cfg_get_strg(cf_change_rule,"normal"); hidden = cfg_get_strg(cf_change_rule,"hidden"); if (normal) add_type(cfg_get_strg(cf_change_rules,"type"),cvt_byte(normal), hidden ? cvt_byte(hidden) : -1); else { if (!hidden) cfg_error("At least one of NORMAL and HIDDEN must be present"); add_type(cfg_get_strg(cf_change_rules,"type"),cvt_byte(hidden),-1); } cfg_unset(cf_change_rules,"type");}void do_cr(void){ cfg_init(cf_change_rules); (void) cfg_parse(cf_change_rules);}#if defined(LCF_REWRITE_TABLE) && !defined(LCF_READONLY)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -