⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 partition.c

📁 LINUX lilo-22.7 源代码。
💻 C
📖 第 1 页 / 共 2 页
字号:
/* partition.c  -  Partition table handling *//*Copyright 1992-1998 Werner Almesberger.Copyright 1999-2004 John Coffman.All rights reserved.Licensed under the terms contained in the file 'COPYING' in the source directory.*/#define _GNU_SOURCE#include <stdlib.h>#include <stdio.h>#include <string.h>#include <ctype.h>#include <fcntl.h>#include <errno.h>#include <sys/stat.h>#include <sys/types.h>#include <limits.h>#include <time.h>#include <dirent.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"#if __GLIBC__ < 2 || __GLIBC_MINOR__ < 1#if defined(_syscall5) && defined(__NR__llseek)              _syscall5(int,  _llseek,  unsigned int,  fd, unsigned int, hi,           unsigned int, lo, lloff_t *, res, unsigned int, wh);       int _llseek(unsigned int fd,  unsigned  int  offset_high,           unsigned  int  offset_low,  lloff_t * result, unsigned int whence);       lloff_t lseek64(unsigned int fd, lloff_t offs, unsigned int whence)       { lloff_t res;       	   return _llseek(fd, offs>>32, offs, &res, whence) < 0  ?       			 (lloff_t)(-1) : res;       }#else/* last ditch attempt on small disks, and very old systems */# warning "*****************************************"# warning "***** no 64 bit lseek is available ******"# warning "***** using 23 bit sector addresses *****"# warning "*****************************************"# define lseek64 lseek#endif#endifstaticint anywhere(void *buf, unsigned char *str){    int k, n;    void *s;        k = strlen(str);    n = SECTOR_SIZE-k;    s = memchr(buf, *str, n);    while(s) {	if (!strncmp(s, str, k)) return 1;	s++;	n = SECTOR_SIZE - k - (int)(s-buf);	s = memchr(s, *str, n);    }    return 0;}/* 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=PTW_OKAY;	/* say ok, unless we recognize a problem partition */if ( !(do_md_install && extra==X_MBR_ONLY) ) {    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=PTW_XFS;    /* check for NTFS */    else if (	!strncmp("NTFS", bs.par_d.system, 4)		|| anywhere(bs.sector,"NTLDR")  ) ret=PTW_NTFS;/* check for HPFS */    else if (	!strncmp("OS2", bs.par_d.system, 3)		|| anywhere(bs.sector,"OS2LDR")  ) ret=PTW_OS2;/* 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=PTW_DOS;#if 0/* this, it turns out is from Windows 98, so no caution here on NT */    		if (anywhere(bs.sector,"WINBOOT SYS")) ret+=PTW_NTFS;#endif    }    /* check for SWAP -- last check, as 'bs' is overwritten */    else if (*(int*)bs.sector == 0xFFFFFFFEU) {	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=PTW_SWAP;    }/* didn't recognize the superblock type, so assume it is okay */        else ret=PTW_OKAY;        close(fd);} /* raid install with X_MBR_ONLY in use */    if (verbose>=6) printf("part_nowrite: %d\n", ret);            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 int second, base;    struct partition part_table[PART_MAX];    int mask, i, pe, Linux, dos, mbr;    unsigned short boot_sig;    BOOT_PARAMS_1 bs;        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 1    if (type) {	if (lseek(fd, 0L, SEEK_SET) != 0 ||	    read(fd, &bs, sizeof(bs)) != sizeof(bs) ) pdie("bs read");	if (*(int*)bs.signature==EX_MAG_HL) mbr = bs.stage;	else mbr = STAGE_MBR;    } else mbr = STAGE_MBR;#endif    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 (lseek64(fd, LLSECTORSIZE*(base+second) + PART_TABLE_OFFSET, SEEK_SET) < 0)            die("secondary lseek64 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;    }#if 1    if (type && pe>0 && pe<=(mbr==STAGE_MBR2?63:PART_MAX)    	     && !(part_table[part].boot_ind&0x80) && !nowarn)	fprintf(errstd,"Warning: Partition %d on %s is not marked Active.\n",		pe, dev.name);#endif    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 (!nowarn) fprintf(errstd,"Warning: partition type 0x%02X"" on device 0x%04X is a dangerous place for\n"							"    a boot sector.",			part_table[part].sys_ind, dev_nr);	if (dos && !nowarn) fprintf(errstd,"  A DOS/Windows/OS2 system may be rendered unbootable."		"\n  The backup copy of this boot sector should be retained.");	if (!nowarn) fprintf(errstd,"\n");#if 0	if (!dos && !cfg_get_flag(cf_options,"ignore-table"))	    die("You may proceed by using either '-P ignore' or 'ignore-table'");#else	if (!yesno("\nProceed? ", 0)) exit(0);#endif    }    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,SEEK_SET) < 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 int 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)/* * 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;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -