?? device.c
字號:
/* 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 + -