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

📄 mount_by_label.c

📁 Util-linux 软件包包含许多工具。其中比较重要的是加载、卸载、格式化、分区和管理硬盘驱动器
💻 C
字号:
#ifndef HAVE_BLKID/* * mount_by_label.c - aeb * * 1999-02-22 Arkadiusz Mi秌iewicz <misiek@pld.ORG.PL> * - added Native Language Support * 2000-01-20 James Antill <james@and.org> * - Added error message if /proc/partitions cannot be opened * 2000-05-09 Erik Troan <ewt@redhat.com> * - Added cache for UUID and disk labels * 2000-11-07 Nathan Scott <nathans@sgi.com> * - Added XFS support * 2001-11-22 Kirby Bohling <kbohling@birddog.com> * - Added support of labels on LVM * 2002-03-21 Christoph Hellwig <hch@infradead.org> * - Added JFS support * 2002-07-11 Christoph Hellwig <hch@infradead.org> * - Added JFS v2 format support * 2002-07-26 Luciano Chavez <lnx1138@us.ibm.com> * - Added EVMS support */#include <stdio.h>#include <string.h>#include <ctype.h>#include <fcntl.h>#include <unistd.h>#include <errno.h>#include <sys/types.h>   /* needed for opendir */#include <dirent.h>#include "sundries.h"		/* for xstrdup */#include "linux_fs.h"#include "get_label_uuid.h"#include "mount_by_label.h"#include "nls.h"#define PROC_PARTITIONS "/proc/partitions"#define DEVLABELDIR	"/dev"#define VG_DIR          "/proc/lvm/VGs"#define EVMS_VOLUME_NAME_SIZE  127#define PROC_EVMS_VOLUMES "/proc/evms/volumes"static struct uuidCache_s {	struct uuidCache_s *next;	char uuid[16];	char *label;	char *device;} *uuidCache = NULL;static voiduuidcache_addentry(char *device, char *label, char *uuid) {	struct uuidCache_s *last;	if (!uuidCache) {		last = uuidCache = malloc(sizeof(*uuidCache));	} else {		for (last = uuidCache; last->next; last = last->next);		last->next = malloc(sizeof(*uuidCache));		last = last->next;	}	last->next = NULL;	last->device = device;	last->label = label;	memcpy(last->uuid, uuid, sizeof(last->uuid));}/* LVM support - Kirby Bohling */static voiduuidcache_init_lvm(void) {	char buffer[PATH_MAX];	char lvm_device[PATH_MAX];	DIR *vg_dir, *lv_list;	struct dirent *vg_iter, *lv_iter;	char uuid[16], *label;	vg_dir = opendir(VG_DIR);	if (vg_dir == NULL)	/* to be expected */		return;	seekdir(vg_dir, 2);	while ((vg_iter = readdir(vg_dir)) != 0) {		sprintf(buffer, "%s/%s/LVs", VG_DIR, vg_iter->d_name);		lv_list = opendir(buffer);		if (lv_list == NULL) {			perror("mount (init_lvm)");			continue;		}		seekdir(lv_list, 2);		while ((lv_iter = readdir(lv_list)) != 0) {			/* Now we have the file.. could open it and read out			 * where the device is, read the first line, second			 * field... Instead we guess.			 */			sprintf(lvm_device, "%s/%s/%s", DEVLABELDIR,				vg_iter->d_name, lv_iter->d_name);			if (!get_label_uuid(lvm_device, &label, uuid))				uuidcache_addentry(xstrdup(lvm_device),						   label, uuid);		}		closedir(lv_list);	}	closedir(vg_dir);}static intuuidcache_init_evms(void) {	FILE *procvol;	char *label;	char uuid[16];	char volname[EVMS_VOLUME_NAME_SIZE+1];	char line[EVMS_VOLUME_NAME_SIZE+80];	procvol = fopen(PROC_EVMS_VOLUMES, "r");	if (!procvol)		return 0;	while (fgets(line, sizeof(line), procvol)) {		if (sscanf(line, "%*d %*d %*d %*s %*s %[^\n]", volname) == 1) {			if (!get_label_uuid(volname, &label, uuid))				uuidcache_addentry(xstrdup(volname), label, uuid);		}	}		fclose(procvol);		return 1;}/* * xvm is a proprietary sgi volume manager, it goes into /proc/partitions * like this: * *   4     0    2210817 xvm/local/vol/myvolume/data/block *   4     1    2210817 xvm/local/vol/myvolume/rt/block *   4     2    2210817 xvm/local/vol/myvolume/log/block *   4     3    2210818 xvm/local/vol/discs3/data/block * * The heuristics here are that the device should start with "xvm," * but should not end in "log/block" or "rt/block" - those are * special devices for the xfs filesystem external log & realtime device. *//* Return 1 if this looks like an xvm device that should be scanned */static intis_xvm(char *ptname){	int len;	/* if it doesn't start with "xvm," we're done. */	if (strncmp(ptname, "xvm", 3))		return 0;	len = strlen(ptname);	/*	 * check for "log/block" or "rt/block" on the end,	 * these are special - don't scan.	 */	if (!strncmp(ptname+(len-9), "log/block", 9) ||	    !strncmp(ptname+(len-8), "rt/block", 8))	    	return 0;	return 1;}static voiduuidcache_init(void) {	char line[100];	char *s;	int ma, mi, sz;	static char ptname[100];	FILE *procpt;	char uuid[16], *label;	char device[110];	int firstPass;	int handleOnFirst;#if 0	char iobuf[32*1024];	/* For setvbuf */#endif	if (uuidCache)		return;	if (uuidcache_init_evms())		return;	procpt = fopen(PROC_PARTITIONS, "r");	if (!procpt) {		static int warn = 0;		if (!warn++)		    error (_("mount: could not open %s, so UUID and LABEL "			     "conversion cannot be done.\n"),		       PROC_PARTITIONS);		return;	}#if 0/* Ugly kludge - the contents of /proc/partitions change in time,   and this causes failures when the file is not read in one go.   In particular, one cannot use stdio on /proc/partitions.   Doing this ourselves is not easy either, since stat returns 0   so the size is unknown. We might try increasing buffer sizes   until a single read gets all. For now only pick a largish buffer size. *//* All these troubles are mainly caused by people who patch the kernel   to keep statistics in /proc/partitions. Of course, statistics belong   in some /proc/diskstats, not in some /proc file that happened to   exist already. */	setvbuf(procpt, iobuf, _IOFBF, sizeof(iobuf));#endif	for (firstPass = 1; firstPass >= 0; firstPass--) {	    fseek(procpt, 0, SEEK_SET);	    while (fgets(line, sizeof(line), procpt)) {		if (sscanf (line, " %d %d %d %[^\n ]",			    &ma, &mi, &sz, ptname) != 4)			continue;		/* skip extended partitions (heuristic: size 1) */		if (sz == 1)			continue;		/* look only at md devices on first pass */		handleOnFirst = !strncmp(ptname, "md", 2);		if (firstPass != handleOnFirst)			continue;		/* skip entire disk (minor 0, 64, ... on ide;		   0, 16, ... on sd) */		/* heuristic: partition name ends in a digit */		/* devfs has .../disc and .../part1 etc. */		for(s = ptname; *s; s++);		if (isdigit(s[-1]) || is_xvm(ptname)) {					/*		 * Note: this is a heuristic only - there is no reason		 * why these devices should live in /dev.		 * Perhaps this directory should be specifiable by option.		 * One might for example have /devlabel with links to /dev		 * for the devices that may be accessed in this way.		 * (This is useful, if the cdrom on /dev/hdc must not		 * be accessed.)		 */			sprintf(device, "%s/%s", DEVLABELDIR, ptname);			if (!get_label_uuid(device, &label, uuid))				uuidcache_addentry(xstrdup(device), label, uuid);		}	    }	}	fclose(procpt);	uuidcache_init_lvm();}#define UUID   1#define VOL    2static const char *get_spec_by_x(int n, const char *t) {	struct uuidCache_s *uc;	uuidcache_init();	uc = uuidCache;	while(uc) {		switch (n) {		case UUID:			if (!memcmp(t, uc->uuid, sizeof(uc->uuid)))				return xstrdup(uc->device);			break;		case VOL:			if (!strcmp(t, uc->label))				return xstrdup(uc->device);			break;		}		uc = uc->next;	}	return NULL;}static u_charfromhex(char c) {	if (isdigit(c))		return (c - '0');	else if (islower(c))		return (c - 'a' + 10);	else		return (c - 'A' + 10);}const char *get_spec_by_uuid(const char *s) {	u_char uuid[16];	int i;	if (strlen(s) != 36 ||	    s[8] != '-' || s[13] != '-' || s[18] != '-' || s[23] != '-')		goto bad_uuid;	for (i=0; i<16; i++) {	    if (*s == '-') s++;	    if (!isxdigit(s[0]) || !isxdigit(s[1]))		    goto bad_uuid;	    uuid[i] = ((fromhex(s[0])<<4) | fromhex(s[1]));	    s += 2;	}	return get_spec_by_x(UUID, uuid); bad_uuid:	die(EX_USAGE, _("mount: bad UUID"));	return NULL;		/* just for gcc */}const char *get_spec_by_volume_label(const char *s) {	return get_spec_by_x(VOL, s);}const char *get_volume_label_by_spec(const char *spec) {        struct uuidCache_s *uc;        uuidcache_init();        uc = uuidCache;	while(uc) {		if (!strcmp(spec, uc->device))			return uc->label; 		uc = uc->next;	}	return NULL;}/* * second_occurrence_of_vol_label() * As labels are user defined they are not necessarily  * system-wide unique. Make sure that they are. */const char *second_occurrence_of_vol_label (const char *label) {  	struct uuidCache_s *last;        int occurrences = 0;        uuidcache_init();        for (last = uuidCache; last; last = last->next) {		if (!strcmp(last->label, label)) {			occurrences++;			if (occurrences == 2)				return last->device;		}        }                return NULL;}          #endif

⌨️ 快捷键说明

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