📄 lsraid.c
字号:
free(disk); disk = NULL; } } return(disk);} /* find_add_disk() */static void maybe_add_device(LSRContext *ctxt, int major, int minor){ FILE *f; char *dev_base = NULL; static char *proc_name = NULL; LSRNamEnt *ent; if (!ctxt || !ctxt->devtable || !major) return; if (!proc_name) { proc_name = (char *)malloc(sizeof(char) * (PATH_MAX + 1)); if (!proc_name) { fprintf(stderr, "lsraid: Unable to allocate memory for information on device \"%s\": %s\n", ctxt->devtable[major][minor], strerror(errno)); return; } } proc_name[0] = '\0'; dev_base = strrchr(ctxt->devtable[major][minor], '/'); if ((dev_base == NULL) || (dev_base[1] == '\0')) return; /* Welcome to Hardcoded /proc Land */ if (strlen(dev_base) > (PATH_MAX - strlen("/proc/ide//media"))) return; sprintf(proc_name, "/proc/ide/%s/media", dev_base); f = fopen(proc_name, "r"); if (f) { if (fgets(proc_name, PATH_MAX + 1, f)) { /* IDE devices we don't want to probe */ if (!strcmp(proc_name, "cdrom") || !strcmp(proc_name, "tape")) { fclose(f); return; } } fclose(f); } ent = alloc_nament(); if (!ent) { fprintf(stderr, "lsraid: Unable to allocate memory for information on device \"%s\": %s\n", ctxt->devtable[major][minor], strerror(errno)); return; } ent->name = ctxt->devtable[major][minor]; /* Should we add MD_MAJOR devices to o_disks too? */ if (major == MD_MAJOR) list_add_tail(&ent->list, &ctxt->o_arrays); else list_add_tail(&ent->list, &ctxt->o_disks);} /* maybe_add_device() */static int load_partitions(LSRContext *ctxt){ FILE *proc; int major, minor, rc; char line[MAX_LINE_LENGTH], name[MAX_LINE_LENGTH]; struct stat stat_buf; if (!ctxt || !ctxt->devtable) return(-EINVAL); /* Here we are in wonderful Hardcoded /proc Land */ proc = fopen("/proc/partitions", "r"); if (!proc) return(-errno); while (1) { rc = 0; if ((fgets(line, MAX_LINE_LENGTH, proc)) == NULL) break; name[0] = 0; major = minor = 0; /* FIXME: I'm lazy. Can this be overrun? */ if (sscanf(line, "%d %d %*d %99[^ \t\n]", &major, &minor, name) < 3) continue; if (*name && major) { if (!ctxt->devtable[major]) { ctxt->devtable[major] = (char **)malloc(MINORS * sizeof(char *)); if (!ctxt->devtable[major]) { rc = -ENOMEM; break; } memset(ctxt->devtable[major], 0, MINORS * sizeof(char *)); } if (ctxt->devtable[major][minor]) continue; /* * This is all '/dev' specific. If it isn't found there, * it is going to fall back to /dev scanning (think * /dev/usb/disk1 or something in devfs). This heuristic * should probably check whatever devfs puts together * for 'hda1 in /proc/partitions', but I don't know what * devfs does, and I don't much care right now. */ ctxt->devtable[major][minor] = (char *)malloc((strlen(name) + strlen("/dev/") + 1) * sizeof(char)); if (!ctxt->devtable[major][minor]) continue; sprintf(ctxt->devtable[major][minor], "/dev/%s", name); rc = stat(ctxt->devtable[major][minor], &stat_buf); if ((rc != 0) && (!S_ISBLK(stat_buf.st_mode))) { free(ctxt->devtable[major][minor]); ctxt->devtable[major][minor] = NULL; } else if (ctxt->flags & LSR_DEV_SCAN) maybe_add_device(ctxt, major, minor); } } fclose(proc); return(rc);} /* load_partitions() */static LSRDir *alloc_dir(){ LSRDir *dir; dir = (LSRDir *)malloc(sizeof(LSRDir)); if (dir) { memset(dir, 0, sizeof(LSRDir)); INIT_LIST_HEAD(&dir->list); } return(dir);} /* alloc_dir() */static LSRDir *push_dir(struct list_head *dtree, char *name){ int len; LSRDir *dir, *pdir; if (!dtree) return(NULL); if (!list_empty(dtree)) pdir = list_entry(dtree->next, LSRDir, list); else pdir = NULL; if (!name) return(pdir); len = strlen(name); if (len > NAME_MAX) return(pdir); if (pdir) { len += strlen("/"); len += strlen(pdir->name); if (len > PATH_MAX) return(pdir); } dir = alloc_dir(); if (!dir) return(pdir); sprintf(dir->name, "%s/%s", pdir ? pdir->name : "", name); dir->dir = opendir(dir->name); if (!dir->dir) { free(dir); return(pdir); } list_add(&dir->list, dtree); return(dir);}static LSRDir *pop_dir(struct list_head *dtree){ struct list_head *top; LSRDir *dir; if (!dtree) return(NULL); if (list_empty(dtree)) return(NULL); top = dtree->next; dir = list_entry(top, LSRDir, list); closedir(dir->dir); list_del(&dir->list); free(dir); if (list_empty(dtree)) return(NULL); top = dtree->next; return(list_entry(top, LSRDir, list));} /* pop_dir() */static int scan_slash_dev(LSRContext *ctxt){ int rc, dirnamelen, major, minor; char name[PATH_MAX + 1]; struct list_head dtree; struct dirent *dirent; struct stat stat_buf; LSRDir *dir; if (!ctxt || !ctxt->devtable) return(-EINVAL); INIT_LIST_HEAD(&dtree); dir = push_dir(&dtree, "dev"); if (!dir) return(-ENOENT); dirnamelen = strlen(dir->name); rc = 0; while (!list_empty(&dtree)) { /* sanity */ if (!dir || !dir->dir) break; dirent = readdir(dir->dir); if (dirent == NULL) { dir = pop_dir(&dtree); if (dir) dirnamelen = strlen(dir->name); continue; } if (!strcmp(dirent->d_name, ".") || !strcmp(dirent->d_name, "..")) continue; if ((dirnamelen + strlen("/") + strlen(dirent->d_name)) > PATH_MAX) continue; sprintf(name, "%s/%s", dir->name, dirent->d_name); rc = lstat(name, &stat_buf); if (rc != 0) continue; if (S_ISDIR(stat_buf.st_mode)) { dir = push_dir(&dtree, dirent->d_name); if (dir) dirnamelen = strlen(dir->name); } else if (S_ISBLK(stat_buf.st_mode)) { major = major(stat_buf.st_rdev); minor = minor(stat_buf.st_rdev); if (!ctxt->devtable[major]) { ctxt->devtable[major] = (char **)malloc(MINORS * sizeof(char *)); if (!ctxt->devtable[major]) { /* FIXME: what error if any? rc = -ENOMEM; */ continue; } memset(ctxt->devtable[major], 0, MINORS * sizeof(char *)); } if (ctxt->devtable[major][minor]) continue; ctxt->devtable[major][minor] = (char *)malloc((strlen(name) + 1) * sizeof(char)); if (ctxt->devtable[major][minor]) strcpy(ctxt->devtable[major][minor], name); } } return(rc);} /* scan_slash_dev() *//* * We may want to build a raidtab, or at least we like pretty device * names. However, the raid superblock only stores major,minor, so we * have to look up the name. The algorithm is mostly brute. 99% of * devices will exist on the system, and hence will be in * /proc/partitions. If, however, a device has been removed or moved * such that the major,minor are not in /proc/partitions, we have to * scan /dev. Ewww. We scan it once in scan_slash_dev(). The device * table holds the devices we've already looked at, either from * /proc/partitions or /dev. * * This assumes the 8/8 major/minor. */static int find_device(LSRContext *ctxt, char **name, int major, int minor){ static int loaded_partitions = 0; static int scanned_dev = 0; int rc = 0; /* sanity */ if (!ctxt || !ctxt->devtable) return(-EINVAL); if (!name) return(-EINVAL); if (*name) return(-EEXIST); if (!major) return(-EINVAL); if (ctxt->devtable[major] && ctxt->devtable[major][minor]) goto out; if (!loaded_partitions) { load_partitions(ctxt); loaded_partitions = 1; if (ctxt->devtable[major] && ctxt->devtable[major][minor]) goto out; } if (!scanned_dev) { scan_slash_dev(ctxt); scanned_dev = 1; if (ctxt->devtable[major] && ctxt->devtable[major][minor]) goto out; } rc = -ENOENT;out: if (ctxt->devtable[major]) *name = ctxt->devtable[major][minor]; return(rc);} /* find_device() */static int scan_arrays(LSRContext *ctxt){ LSRNamEnt *ent; struct list_head *pos; list_for_each(pos, &ctxt->o_arrays) { ent = list_entry(pos, LSRNamEnt, list); ent->u.array = find_add_array(ctxt, ent->name, -1); } return(0);} /* scan_arrays *//* Ripped from md.c */#if 0 /* Currently unused */static int sb_equal(LSRDisk *disk1, LSRDisk *disk2){ int ret; mdp_super_t *tmp1, *tmp2; tmp1 = (mdp_super_t *)malloc(sizeof(*tmp1)); tmp2 = (mdp_super_t *)malloc(sizeof(*tmp2)); if (!tmp1 || !tmp2) { ret = 0; goto abort; } *tmp1 = disk1->sb; *tmp2 = disk2->sb; /* * nr_disks is not constant */ tmp1->nr_disks = 0; tmp2->nr_disks = 0; if (memcmp(tmp1, tmp2, MD_SB_GENERIC_CONSTANT_WORDS * 4)) ret = 0; else ret = 1;abort: if (tmp1) free(tmp1); if (tmp2) free(tmp2); return ret;}#endif /* Currently unused */static int scan_disks(LSRContext *ctxt){ LSRNamEnt *ent; struct list_head *pos; list_for_each(pos, &ctxt->o_disks) { ent = list_entry(pos, LSRNamEnt, list); ent->u.disk = find_add_disk(ctxt, ent->name, 0, 0); } return(0);} /* scan_disks() */static void clean_context(LSRContext *ctxt){ int i; struct list_head *pos, *n; LSRArray *array; LSRDisk *disk; LSRNamEnt *ent; list_for_each_safe(pos, n, &ctxt->disks) { disk = list_entry(pos, LSRDisk, d_list); free(disk); } list_for_each_safe(pos, n, &ctxt->arrays) { array = list_entry(pos, LSRArray, a_list); free(array); } list_for_each_safe(pos, n, &ctxt->o_disks) { ent = list_entry(pos, LSRNamEnt, list); free(ent); } list_for_each_safe(pos, n, &ctxt->o_arrays)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -