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

📄 device.c

📁 LINUX lilo-22.7.1 源代码。
💻 C
📖 第 1 页 / 共 3 页
字号:
/* device.c  -  Device access *//*Copyright 1992-1997 Werner Almesberger.Copyright 1999-2005 John Coffman.All rights reserved.Licensed under the terms contained in the file 'COPYING' in the source directory.*/#define DEBUG 0#define ATAKEYWORD 0#define _GNU_SOURCE#include <unistd.h>#include <stdlib.h>#include <stdio.h>#include <string.h>#include <ctype.h>#include <errno.h>#include <dirent.h>#include <limits.h>#include <time.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include "config.h"#include "lilo.h"#include "common.h"#include "temp.h"#include "device.h"#include "geometry.h"#include "partition.h"#include "cfg.h"#include "probe.h"#include "ata-u.h"typedef struct _cache_entry {    const char *name;    int number;    struct _cache_entry *next;} CACHE_ENTRY;typedef struct _st_buf {    struct _st_buf *next;    struct stat st;} ST_BUF;static CACHE_ENTRY *cache = NULL;#if 1int yesno(char *prompt, int expect){    char *line, *pr2;    int i;    size_t n;    int ret;    if (expect) pr2 = "[Y/n]";    else pr2 = "[N/y]";        fflush(stdout);    do {	fprintf(stderr, "%s%s", prompt, pr2);	fflush(stderr);	n = ret = 0;	line = NULL;	i = getline(&line, &n, stdin);	if (i<0) exit(1);	if (i==1) ret=expect|2;	if (i>1) {		if (*line=='y'||*line=='Y') ret=1;		if (*line=='n'||*line=='N') ret=2;	}	if (ret) break;	if (line) free(line);    } while(1);    return ret&1;}#endifstatic int scan_dir(ST_BUF *next,DEVICE *dev,char *parent,int number){    DIR *dp;    struct dirent *dir;    ST_BUF st,*walk;    char *start;    st.next = next;    if ((dp = opendir(parent)) == NULL)	die("opendir %s: %s",parent,strerror(errno));    *(start = strchr(parent,0)) = '/';    while ((dir = readdir(dp))) {	strcpy(start+1,dir->d_name);	if (stat(parent,&st.st) >= 0) {	    dev->st = st.st;	    if (S_ISBLK(dev->st.st_mode) && dev->st.st_rdev == number) {		(void) closedir(dp);		return 1;	    }	    if (S_ISDIR(dev->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 && scan_dir(&st,dev,parent,number)) {		    (void) closedir(dp);		    return 1;		}	    }	}    }    (void) closedir(dp);    *start = 0;    return 0;}static int lookup_dev(char *name,DEVICE *dev,int number){    CACHE_ENTRY **walk;    if (verbose>=5) printf("lookup_dev:  number=%04X\n", number);    for (walk = &cache; *walk; walk = &(*walk)->next)	if ((*walk)->number == number) {#if 0	    CACHE_ENTRY *here;	    if (stat((*walk)->name,&dev->st) >= 0)		if (S_ISBLK(dev->st.st_mode) && dev->st.st_rdev == number) {		    strcpy(name,(*walk)->name);		    return 1;		}	    here = *walk; /* remove entry from cache */	    if (verbose >= 2)		printf("Invalidating cache entry for %s (0x%04X)\n",here->name,		  here->number);	    *walk = here->next;	    free((char *) here->name);	    free(here);	    return 0;#else	    strcpy(name,(*walk)->name);	    return 1;#endif	}    return 0;}static int is_devfs(void){static int yesno = 0;    struct stat st;       if (!yesno) {	if (stat("/dev/.devfsd", &st) < 0)  yesno=1;	else yesno=2;    }      return yesno-1;}static void cache_add(const char *name,int number){    CACHE_ENTRY *entry;    entry = cache;    while (entry) {	if (strcmp(entry->name, name) == 0) {	    if (entry->number != number) die("cache_add: LILO internal error");	    return;	}	entry = entry->next;    }    if (verbose >= 5) printf("Caching device %s (0x%04X)\n",name,number);    entry = alloc_t(CACHE_ENTRY);    entry->name = stralloc(name);    entry->number = number;    entry->next = cache;    cache = entry;}int dev_open(DEVICE *dev,int number,int flags){    char name[PATH_MAX+1];    ST_BUF st;    int count;    if (lookup_dev(name,dev,number)) dev->delete = 0;    else {	if (stat(DEV_DIR,&st.st) < 0)	    die("stat " DEV_DIR ": %s",strerror(errno));	st.next = NULL;	dev->delete = !scan_dir(&st,dev,strcpy(name,DEV_DIR),number);	if (dev->delete) {	    for (count = 0; count <= MAX_TMP_DEV; count++) {#ifdef LCF_USE_TMPDIR		if (!strncmp(TMP_DEV,"/tmp/",5) && getenv("TMPDIR")) {		    strcpy(name,getenv("TMPDIR"));		    sprintf(name+strlen(name),TMP_DEV+4,count);		}		else#endif		    sprintf(name,TMP_DEV,count);		if (stat(name,&dev->st) < 0) break;	    }	    if (count > MAX_TMP_DEV)		die("Failed to create a temporary device");	    if (mknod(name,0600 | S_IFBLK,number) < 0)		die("mknod %s: %s",name,strerror(errno));	    if (stat(name,&dev->st) < 0)		die("stat %s: %s",name,strerror(errno));	    if (verbose > 1)		printf("Created temporary device %s (0x%04X)\n",name,number);	    temp_register(name);	}	else cache_add(name,number);    }#if BETA_TEST	if (verbose >= 3) printf("stat-ing %s\n", name);	fflush(stdout);	stat(name, &st.st);#endif    if (flags == O_BYPASS) dev->fd = -1;    else if ((dev->fd = open(name,flags)) < 0)	    die("open %s: %s",name,strerror(errno));    dev->name = stralloc(name);    return dev->fd;}void dev_close(DEVICE *dev){    if (dev->fd != -1)	if (close(dev->fd) < 0) die("close %s: %s",dev->name,strerror(errno));    if (dev->delete) {	if (verbose > 1)	    printf("Removed temporary device %s (0x%04X)\n",dev->name,	      (unsigned int) dev->st.st_rdev);	(void) remove(dev->name);	temp_unregister(dev->name);    }    free(dev->name);}#define MAX 15void cache_scsi (char *name, int major){    char tem[80], format[80];    int i, j, dev;        for (i=15; i>=0; i--) {	dev = MKDEV(major,(i<<4));#if 0	if (is_devfs()) {	    sprintf(tem,"/dev/scsi/host%d/bus0/target0/lun0/", i);	    strcat(strcpy(format,tem),"disc");	    cache_add(format, dev);	    strcat(strcpy(format,tem),"part%d");	}	else#endif	{	    strcpy(format, name);	    format[7] += i;	    cache_add(format, dev);	    strcat(format, "%d");	}	for (j = MAX; j; j--) {	    sprintf(tem, format, j);	    cache_add(tem, dev | j);	}    }}void cache_ide (char *name, int major){    char tem[80], tem2[80];    char format[80];    char *disc;    int i, dev, minor, host, bus, target;        i = name[7] - 'a';    target = i&1;    minor = target<<6;    i >>= 1;    bus = i&1;    host = i&(-2);    if (is_devfs()) {	sprintf(tem2,"/dev/ide/host%d/bus%d/target%d/lun0/", host, bus, target);	strcat(strcpy(format,tem2), "part%d");	disc = strcat(tem2, "disc");    }    else {        strcat(strcpy(format, name), "%d");        disc = name;    }    dev = MKDEV(major,minor);    for (i = MAX; i; i--) {	sprintf(tem, format, i);	cache_add(tem, dev | i);    }    cache_add(disc, dev);}void preload_dev_cache(void){    char tmp[80];    int i;    int vsave;    vsave = verbose;#if !BETA_TEST    if (verbose>0) verbose--;#endif    if (is_devfs()) {	cache_add("/dev/floppy/0", 0x0200);	cache_add("/dev/floppy/1", 0x0201);    }    else {	cache_add("/dev/fd0", 0x0200);	cache_add("/dev/fd1", 0x0201);    }    #if 1    cache_ide("/dev/hdt", MAJOR_IDE10);    cache_ide("/dev/hds", MAJOR_IDE10);    cache_ide("/dev/hdr", MAJOR_IDE9);    cache_ide("/dev/hdq", MAJOR_IDE9);    cache_ide("/dev/hdp", MAJOR_IDE8);    cache_ide("/dev/hdo", MAJOR_IDE8);    cache_ide("/dev/hdn", MAJOR_IDE7);    cache_ide("/dev/hdm", MAJOR_IDE7);        cache_ide("/dev/hdl", MAJOR_IDE6);    cache_ide("/dev/hdk", MAJOR_IDE6);#ifdef MAJOR_IDE5    cache_ide("/dev/hdj", MAJOR_IDE5);    cache_ide("/dev/hdi", MAJOR_IDE5);#endif#endif        for (i = MAX; i >= 0; i--) {	sprintf(tmp, is_devfs() ? "/dev/md/%d" : "/dev/md%d", i);	cache_add(tmp, MKDEV(MAJOR_MD,i));    }    if (!is_devfs()) cache_scsi("/dev/sda", MAJOR_SD);        cache_ide("/dev/hdh", MAJOR_IDE4);    cache_ide("/dev/hdg", MAJOR_IDE4);    cache_ide("/dev/hdf", MAJOR_IDE3);    cache_ide("/dev/hde", MAJOR_IDE3);    for (i = 0; i <= 7; i++) {	sprintf(tmp, is_devfs() ? "/dev/loop/%d" : "/dev/loop%d", i);	cache_add(tmp,0x700+i);    }    cache_ide("/dev/hdd", MAJOR_IDE2);    cache_ide("/dev/hdc", MAJOR_IDE2);    cache_ide("/dev/hdb", MAJOR_HD);    cache_ide("/dev/hda", MAJOR_HD);        verbose = vsave;}#undef MAX#define NDEVICE 256static unsigned short idevices[NDEVICE];static int maxdev = 0;/* return 0 if device has not been backed up,		*//*	  1 if it has been backed up			*/static int dev_listed(unsigned short dev){    int i;/* scan the device list */    for (i=0; i<maxdev; i++) {	if (dev==idevices[i]) return 1;		/* already backed up */    }        if (maxdev < NDEVICE-1) idevices[maxdev++] = dev;    return 0;	/* new to the list, not listed if too many devices */}/* make a backup, returning the timestamp of the backup file *//* 0 if no timestamp returned, and no backup file created */int make_backup(char *backup_file, int force_backup, BOOT_SECTOR *bsect,	int device, char *id){    struct stat st;    char temp_name[PATH_MAX+1];    int bck_file;    int timestamp=0;    char *filename = "boot";    char *cp = NULL;    int force = 0;    if ((cp=cfg_get_strg(cf_options,"force-backup"))) force=1;    else cp=cfg_get_strg(cf_options,"backup");    if (!backup_file) {	backup_file = cp;	force_backup = force;    }    if (backup_file && stat(backup_file, &st) >= 0) {/* file or directory exists */    	if (S_ISDIR(st.st_mode)) {    	    if (strcmp(backup_file,"/")==0) backup_file = "";	    sprintf(temp_name, "%s/%s.%04X", backup_file, filename, device);	    backup_file = temp_name;	}    /* test for /dev/null */	else if (S_ISCHR(st.st_mode) && st.st_rdev==0x0103) return 0;	else if (!S_ISREG(st.st_mode))	    die("make_backup: %s not a directory or regular file", backup_file);    }/* could not stat it, or it was a directory, or it was a regular file */    if (backup_file) {	char *name, *dir, suffix[16];		backup_file = strcpy(temp_name, backup_file);	sprintf(suffix, "%04X", device);	dir = strrchr(backup_file, '/');

⌨️ 快捷键说明

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