geometry.c
来自「LINUX lilo-22.7.1 源代码。」· C语言 代码 · 共 1,339 行 · 第 1/3 页
C
1,339 行
/* 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 0xFFFFFFC0; /* 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 0xFFFFFFF0; /* 4 bit partition mask */ if ( major == MAJOR_SATA || major == MAJOR_SATA2 ) return 0xFFFFFFE0; /* 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 0xFFFFFFF8; /* 3 bit partition mask */ return 0;}#endifstaticunsigned char max_partno[512] = {/* 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=0; if (major >= nelem(max_partno)) { fprintf(errstd,"Warning: Major Device (%d) > %d\n", major, nelem(max_partno)-1); } else if ( (ret=max_partno[major]) ) ret ^= 0xFFFFFFFF; return ret;}void do_disk(void){ DT_ENTRY *entry,*walk; struct stat st; char *disk,*bios,*sectors,*heads,*cylinders,*maxpart; int major; disk = cfg_get_strg(cf_options,"disk"); cfg_init(cf_disk); (void) cfg_parse(cf_disk); if (stat(disk,&st) < 0) { if (cfg_get_flag(cf_disk,"inaccessible")) { cfg_unset(cf_options,"disk"); return; } die("do_disk: 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 = alloc_t(DT_ENTRY); entry->device = st.st_rdev; major = MAJOR(st.st_rdev); 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) { if (major<nelem(max_partno)) { 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); } else { die("Implementation restriction: max-partitions on major device > %d", nelem(max_partno)-1); } } 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. */ DEVICE dev; int devs; for (devs = 0; devs < 2 && dev_open(&dev,MKDEV(major,increment*devs),O_BYPASS); devs++) if (exists(dev.name)) dev_close(&dev); else { dev_close(&dev); break; } return devs;}#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) die("LVM IOP %d not supported for booting\n", iop); close(lvmfd); lvmfd = dev_open(&dev, lbm->lv_dev, O_RDONLY);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?