geometry.c

来自「LINUX lilo-22.7 源代码。」· C语言 代码 · 共 1,345 行 · 第 1/3 页

C
1,345
字号
/* geometry.c  -  Device and file geometry computation *//*Copyright 1992-1998 Werner Almesberger.Copyright 1999-2005 John Coffman.All rights reserved.Licensed under the terms contained in the file 'COPYING' in the source directory.*//* Patched for linux-2.4.0 - Glibc-2.2 by Sergey Ostrovsky 11/16/2000 */#define _GNU_SOURCE#include <unistd.h>#include <stdio.h>#include <fcntl.h>#include <errno.h>#include <sys/types.h>#ifdef LCF_REISERFS#include <sys/statfs.h>#ifdef	_SYS_STATFS_H#define	_I386_STATFS_H	/* two versions of statfs is not good ... */#endif#endif#include <string.h>#include "config.h"#include "lilo.h"#include "common.h"#include "device.h"#include "raid.h"#include "geometry.h"#include "cfg.h"#include "md-int.h"#include "probe.h"#ifdef LCF_REISERFS#ifndef REISERFS_SUPER_MAGIC#define REISERFS_SUPER_MAGIC 0x52654973#endif#if 0#ifndef REISERFS_SUPER_MAGIC_STRING#define REISERFS_SUPER_MAGIC_STRING "ReIsErFs"#endif#endif#ifndef REISERFS_IOC_UNPACK#define REISERFS_IOC_UNPACK		_IOW(0xCD,1,long)#endif#ifndef REISER4_SUPER_MAGIC#define REISER4_SUPER_MAGIC  0x52345362 /* (*(__u32 *)"R4Sb"); */#endif#ifndef REISER4_IOC_UNPACK#define REISER4_IOC_UNPACK              _IOW(0xCD,1,long)#endif#endif#ifdef LCF_LVMstruct lv_bmap {    __u32 lv_block;    __u16 lv_dev;};#ifndef LV_BMAP#define LV_BMAP				_IOWR(0xfe, 0x30, char)#endif#ifndef LVM_GET_IOP_VERSION#define LVM_GET_IOP_VERSION		_IOR(0xfe, 0x98, char)#endif#endif#ifdef LCF_EVMSstruct evms_get_bmap_t {    __u64 rsector;    __u32 dev;    int status;};struct evms_version_t {    __u32 major;    __u32 minor;    __u32 patch;};#ifndef EVMS_GET_BMAP#define EVMS_GET_BMAP		_IOWR(MAJOR_EVMS, 0xC7, struct evms_get_bmap_t)#endif#ifndef EVMS_GET_IOCTL_VERSION#define EVMS_GET_IOCTL_VERSION	_IOR(MAJOR_EVMS, 0x0, struct evms_version_t)#endif#endif#ifndef HDIO_GETGEO#define HDIO_GETGEO HDIO_REQ#endiftypedef struct _st_buf {    struct _st_buf *next;    struct stat st;} ST_BUF;DT_ENTRY *disktab = NULL;int old_disktab = 0;void geo_init(char *name){    FILE *file;    char line[MAX_LINE+1];    char *here;    DT_ENTRY *entry;    int disk_section,items;    if (name) {	if ((file = fopen(name,"r")) == NULL)	    die("open %s: %s",name,strerror(errno));    }    else if ((file = fopen(DFL_DISKTAB,"r")) == NULL) return;    disk_section = !!disktab;    while (fgets(line,MAX_LINE,file)) {	here = strchr(line,'\n');	if (here) *here = 0;	here = strchr(line,'#');	if (here) *here = 0;	if (strspn(line," \t") != strlen(line)) {	    entry = alloc_t(DT_ENTRY);	    items = sscanf(line,"0x%x 0x%x %d %d %d %d",&entry->device,	      &entry->bios,&entry->sectors,&entry->heads,&entry->cylinders,	      &entry->start);	    if (items == 5) entry->start = -1;	    if (items < 5)		die("Invalid line in %s:\n\"%s\"",name ? name : DFL_DISKTAB,		  line);	    entry->next = disktab;	    disktab = entry;	    if (disk_section) die("DISKTAB and DISK are mutually exclusive");	    old_disktab = 1;	}    }    (void) fclose(file);}void do_partition(void){    DT_ENTRY *entry,*walk;    struct stat st;    char *partition,*start;    entry = alloc_t(DT_ENTRY);    *entry = *disktab;    entry->start = -1;    partition = cfg_get_strg(cf_partitions,"partition");    if (stat(partition,&st) < 0) die("stat %s: %s",partition,strerror(errno));    if (!S_ISBLK(st.st_mode) || ((st.st_rdev ^ disktab->device) & D_MASK(st.st_rdev)))	die("%s is not a valid partition device",partition);    entry->device = st.st_rdev;    cfg_init(cf_partition);    (void) cfg_parse(cf_partition);    start = cfg_get_strg(cf_partition,"start");    entry->start = start ? to_number(start) : -1;    for (walk = disktab; walk; walk = walk->next)	if (entry->device == walk->device)	    die("Duplicate geometry definition for %s",partition);    entry->next = disktab;    disktab = entry;    cfg_init(cf_partitions);}#if BETA_TESTint has_partitions_beta(dev_t dev){    int major = MAJOR(dev);        if (      major == MAJOR_HD || major == MAJOR_IDE2 ||      major == MAJOR_IDE3 || major == MAJOR_IDE4 ||#ifdef MAJOR_IDE5      major == MAJOR_IDE5 || #endif      major == MAJOR_IDE6 ||      (major >= MAJOR_IDE7 && major <= MAJOR_IDE10) ||      major == MAJOR_XT || major == MAJOR_ESDI || major == MAJOR_ACORN      	) return 0xFFC0;	/* 6 bit partition mask */          if (      major == MAJOR_SD || (major >= MAJOR_SD2 && major <= MAJOR_SD8) ||      major == MAJOR_AMI_HYP || major == MAJOR_HPT370 ||      (major >= MAJOR_EXPR && major <= MAJOR_EXPR+3) ||      (major >= MAJOR_I2O && major <= MAJOR_I2O+7) ||      (major >= MAJOR_SMART2 && major <= MAJOR_SMART2+7) ||      (major >= MAJOR_CISS && major <= MAJOR_CISS+7) ||      major == MAJOR_FTL || major == MAJOR_NFTL || major == MAJOR_DOC ||      (major >= MAJOR_SD9 && major <= MAJOR_SD16) ||      major == MAJOR_EMD        ) return 0xFFF0;	/* 4 bit partition mask */    if ( major == MAJOR_SATA || major == MAJOR_SATA2        )  return 0xFFE0;	/* 5 bit partition mask */    if ( major == MAJOR_IBM_iSER ||      (major >= MAJOR_DAC960 && major <= MAJOR_DAC960+7) ||      (major >= MAJOR_DAC960_8 && major <= MAJOR_DAC960_8+7)        )  return 0xFFF8;	/* 3 bit partition mask */    return 0;}#endifunsigned char max_partno[256] = {/*  0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F*/  0,  0,  0, 63,  0,  0,  0,  0, 15,  0,  0,  0,  0, 63,  0,  0,   /*  0x   */  0,  0,  0,  0,  0, 63, 63,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 63, 63,  0, 63,  0,  0,  0,  0,  0,  0,  0, 15,  0,  0,  0,#ifndef MAJOR_IDE5  7,  7,  7,  7,  7,  7,  7,  7,  0, 63,  0,  0, 15, 15, 15, 15,#else  7,  7,  7,  7,  7,  7,  7,  7, 63, 63,  0,  0, 15, 15, 15, 15,#endif  0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,   /*  4x   */ 15, 15, 15, 15, 15, 15, 15, 15, 63, 63, 63, 63,  0, 15,  0,  0,  0,  0,  0,  0, 15, 15,  0,  0, 15, 15, 15, 15, 15, 15, 15, 15,  7,  0, 15,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,/*  0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F*/ 15, 15, 15, 15, 15, 15, 15, 15,  7,  7,  7,  7,  7,  7,  7,  7,   /*  8x   */  0,  0,  0,  0,  0,  0,  0,  0,  0, 15,  0,  0,  0,  0,  0,  0, 31, 31,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,   /*  Cx   */  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0/*  0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F*/};int has_partitions(dev_t dev){   int major = MAJOR(dev);   int ret;      if (/***   	major < sizeof(max_partno) &&	***/   	(ret=max_partno[major])   					)  ret ^= 0xFFFF;   else ret = 0;      return ret;}void do_disk(void){    DT_ENTRY *entry,*walk;    struct stat st;    char *disk,*bios,*sectors,*heads,*cylinders,*maxpart;    int major;    entry = alloc_t(DT_ENTRY);    disk = cfg_get_strg(cf_options,"disk");    if (stat(disk,&st) < 0) die("stat %s: %s",disk,strerror(errno));    if (!S_ISBLK(st.st_mode) ||     	(has_partitions(st.st_rdev) && (MINOR(st.st_rdev) & P_MASK(st.st_rdev))))		die(" '%s' is not a whole disk device",disk);    entry->device = st.st_rdev;    major = MAJOR(st.st_rdev);    cfg_init(cf_disk);    (void) cfg_parse(cf_disk);    bios = cfg_get_strg(cf_disk,"bios");    sectors = cfg_get_strg(cf_disk,"sectors");    heads = cfg_get_strg(cf_disk,"heads");    cylinders = cfg_get_strg(cf_disk,"cylinders");    maxpart = cfg_get_strg(cf_disk,"max-partitions");    if (maxpart) {	int i = to_number(maxpart);	if (max_partno[major] && max_partno[major]!=i) die("Cannot alter 'max-partitions' for known disk  %s", disk);	max_partno[major] = i;	if (i!=7 && i!=15 && i!=31 && i!=63) die("disk=%s:  illegal value for max-partitions(%d)", disk, i);    }    entry->bios = bios ? to_number(bios) : -1;    if (!sectors && !heads) entry->sectors = entry->heads = -1;    else if (!(sectors && heads))	    die("Must specify SECTORS and HEADS together");	else {	    entry->sectors = to_number(sectors);	    entry->heads = to_number(heads);	}    if (cfg_get_flag(cf_disk,"inaccessible")) {	entry->heads = 0;	if (#if 0		cfg_get_strg(cf_disk,"bios") || #endif		cfg_get_strg(cf_disk,"sectors") ||	  cfg_get_strg(cf_disk,"heads") || cfg_get_strg(cf_disk,"cylinders"))	    die("No geometry variables allowed if INACCESSIBLE");    }    entry->cylinders = cylinders ? to_number(cylinders) : -1;    entry->start = 0;    for (walk = disktab; walk; walk = walk->next) {	if (entry->device == walk->device)	    die("Duplicate \"disk =\" definition for %s",disk);    }    entry->next = disktab;    disktab = entry;    if (verbose >= 6) {	printf("do_disk: %s %04X 0x%02X  %d:%d:%d\n",		disk, entry->device, entry->bios, entry->cylinders,		entry->heads, entry->sectors);    }    cfg_init(cf_partitions);    (void) cfg_parse(cf_partitions);    cfg_unset(cf_options,"disk");}static int exists(const char *name){    struct hd_geometry dummy;    int fd,yes;    char buff;    if ((fd = open(name,O_RDWR)) < 0) return 0; /* was O_RDONLY */    yes = read(fd,&buff,1) == 1 && ioctl(fd,HDIO_GETGEO,&dummy) >= 0;    (void) close(fd);    return yes;}#if 0static int scan_last_dev(ST_BUF *next,char *parent,int major,int increment){    DIR *dp;    struct dirent *dir;    char name[PATH_MAX+1];    ST_BUF st,*walk;    int max,this;    st.next = next;    max = 0;    if ((dp = opendir(parent)) == NULL)	die("opendir %s: %s",parent,strerror(errno));    while ((dir = readdir(dp))) {	sprintf(name,"%s/%s",parent,dir->d_name);	if (stat(name,&st.st) >= 0) {	    if (S_ISBLK(st.st.st_mode) && MAJOR(st.st.st_rdev) == major &&	      (MINOR(st.st.st_rdev) & (increment-1)) == 0) {		this = MINOR(st.st.st_rdev)/increment+1;		if (this > max && exists(name)) max = this;	    }	    if (S_ISDIR(st.st.st_mode) && strcmp(dir->d_name,".") &&	      strcmp(dir->d_name,"..")) {		for (walk = next; walk; walk = walk->next)		    if (stat_equal(&walk->st,&st.st)) break;		if (!walk) {		    this = scan_last_dev(&st,name,major,increment);		    if (this > max) max = this;		}	    }	}    }    (void) closedir(dp);    return max;}#endifstatic int last_dev(int major,int increment){/* * In version 12 to 18, LILO only relied on scan_last_dev (or last_dev). This * obviously didn't work if entries in /dev were missing. Versions 18 and 19 * added the probe loop, which seems to be okay, but which may probe for * invalid minor numbers. The IDE driver objects to that. Since last_dev is * only used to count IDE drives anyway, we try now only the first two devices * and forget about scan_last_dev. */#if 0    DEVICE dev;    int minor;    for (minor = 0; dev_open(&dev,(major << 8) | minor,O_BYPASS); minor += increment)	if (exists(dev.name)) dev_close(&dev);        else {	    dev_close(&dev);	    return minor/increment;	}    return scan_last_dev(NULL,DEV_DIR,major,increment);#else    DEVICE dev;    int devs;#if 0    for (devs = 0; devs < 2 && dev_open(&dev,(major << 8) | (increment*devs),      O_BYPASS); devs++)#else    for (devs = 0;	devs < 2 && dev_open(&dev,MKDEV(major,increment*devs),O_BYPASS);	    devs++)#endif	if (exists(dev.name)) dev_close(&dev);        else {	    dev_close(&dev);	    break;	}    return devs;#endif}#ifdef LCF_LVMvoid lvm_bmap(struct lv_bmap *lbm){    DEVICE dev;    static int lvmfd = -1;    static dev_t last_dev = 0;    if (lbm->lv_dev != last_dev) {	char lvm_char[] = "/dev/lvm";	unsigned short iop;	if (lvmfd != -1)	    close(lvmfd);	if ((lvmfd = open(lvm_char, lbm->lv_dev, O_RDONLY)) < 0)	    die("can't open LVM char device %s\n", lvm_char);	if (ioctl(lvmfd, LVM_GET_IOP_VERSION, &iop) < 0)	    die("LVM_GET_IOP_VERSION failed on %s\n", lvm_char);	if (iop < 10)

⌨️ 快捷键说明

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