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

📄 vold.c

📁 linux下自动mount各种即插即用设备的一个小程序源码 文件包含内容: /vold.h /vold.c /split.h /split.c /disktype-6/disktype.c
💻 C
📖 第 1 页 / 共 2 页
字号:
#include "vold.h"#include <sys/types.h>	/* open, fork, mkdir, stat, geteuid */#include <sys/stat.h>	/* open, mkdir, stat */#include <fcntl.h>	/* open */#include <unistd.h>	/* geteuid */#include <unistd.h>	/* fork, stat, rmdir */#include <signal.h>	/* signal handlers */#include <stdlib.h>	/* exit */#include <sys/mount.h> /* mount */#include <mntent.h>	/* getmntent */#include <stdio.h>	/* printf, getmntent */#include <string.h>#include <getopt.h>/* config variables */
int check_delay = 5;		//delay between new partitions check in seconds
int background = 0;			//fork to background?
char pidfile[MAX_STRLEN + 1];		//pidfile of iMount
char configfilename[MAX_STRLEN + 1];	//config filename (defaults to vold.conf)
char volumeroot[MAX_STRLEN + 1];	//Volume root (defaults to /Volumes)
unsigned long defaultmountflags = 0;
int uuid_filecheck = 0;
/* internal variables */int done = 0;				//program quits if trueint debug = 0;extern scan_item* scan_list;extern vold_mount*	mount_list;/*	Tests if a specific device is available (i.e. "/dev/hda1")    returns 1 if the device exists, 0 else. 	PROBLEM: returns true on /dev/hda3 even if you only have one partition /dev/hda1 */int device_exists(char* device) {    int ret = 0;        if(device != NULL) {		ret = open(device, O_RDONLY);		if(ret == -1) {	    	ret = 0;		} else {	    	/* the device exists, now close it */	    	close(ret);	    	ret = 1;		}    }    return ret;}/* Structure describing a mount table entry.  */
/* struct mntent */
 /* {
/*    char *mnt_fsname;            Device or server for filesystem.  */
/*    char *mnt_dir;               Directory mounted on.  */
/*    char *mnt_type;              Type of filesystem: ufs, nfs, etc.  */
/*    char *mnt_opts;              Comma-separated options for fs.  */
/*    int mnt_freq;                Dump frequency (in days).  */
 /*   int mnt_passno;             Pass number for `fsck'.  */
  /* };*/
/*	Loads /proc/mounts and adds the entries to the mount_list and updates the scan_list */void load_mounts() {	FILE* fd;	struct mntent* m;	vold_mount* tmp;	scan_item* sdevice;	uuid_t uuid;	uuid_clear(uuid);		fd = fopen("/proc/mounts", "r+");	if(fd == NULL) {		errormsg("Cannot open /proc/mounts: %s", strerror(errno));		return;	}	debugmsg("Reading /proc/mounts");	debugmsg("%-30s %-30s %-8s %-30s %4s %4s", "<file system>", "<mount point>", "<type>", "<options>", "<dump>", "<pass>");	for(m = getmntent(fd); m != NULL; m = getmntent(fd)) {		/* ignore the "rootfs" entry */		if(strncmp("rootfs", m->mnt_fsname, 6) == 0) continue;				/* mark the device_item from the scan_list as mounted */		sdevice = sdevice_find(m->mnt_fsname);		if(sdevice == NULL) continue;	/* We do not scan for this device. Ignore and continue. */		sdevice->status = VOLD_MOUNTED;				/* now add the device if it doesn't already exist. */		if(vmount_find(m->mnt_fsname, NULL, NULL) == NULL) {			debugmsg("%-30s %-30s %-8s %-30s %2i %2i", m->mnt_fsname, m->mnt_dir, m->mnt_type, m->mnt_opts, m->mnt_freq, m->mnt_passno);			tmp = vmount_new();			if(tmp != NULL) {				tmp->fixed = 0;				SDUP(tmp->device, m->mnt_fsname);				SDUP(tmp->mountpoint, m->mnt_dir);				SDUP(tmp->fstype, m->mnt_type);				tmp->mountflags = 0;				SDUP(tmp->data, m->mnt_opts);				tmp->volumename = NULL;				uuid_clear(tmp->uuid);				tmp->next = NULL;								vmount_add(tmp);			} else {				errormsg("Not enough memory creating vmount struct");			}					}	}	if(m) free(m);		fclose(fd);}/*	Loads /etc/fstab and add the single entries to the mount_list (vmount structure) */void load_fstab() {	FILE* fd;	struct mntent* m;	vold_mount* tmp;	char* device = NULL;	char* label = NULL;	uuid_t uuid;	uuid_clear(uuid);		fd = fopen("/etc/fstab", "r+");	if(fd == NULL) {		errormsg("Cannot open /etc/fstab: %s", strerror(errno));		return;	}	debugmsg("Reading /etc/fstab");	debugmsg("%-30s %-30s %-8s %-30s %4s %4s", "<file system>", "<mount point>", "<type>", "<options>", "<dump>", "<pass>");	for(m = getmntent(fd); m != NULL; m = getmntent(fd)) {		/* test if device string contains "LABEL=" or "UUID=" and set vars... */		if(strncmp("LABEL=", m->mnt_fsname, MAX_STRLEN) == 0) {			SDUP(label, &m->mnt_fsname[5]);		} else if(strncmp("UUID=", m->mnt_fsname, MAX_STRLEN) == 0) {			uuid_parse( &m->mnt_fsname[4], uuid);		} else {			SDUP(device, m->mnt_fsname);		}				/* now add the device if it doesn't have the noauto flag and if it doesn't already exist */		tmp = vmount_find(device, uuid, label);		if(tmp != NULL) {			debugmsg("Device, UUID or Label conflicts with previously added vmount. Skipping the following entry");			debugmsg("%-30s %-30s %-8s %-30s %4i %4i", m->mnt_fsname, m->mnt_dir, m->mnt_type, m->mnt_opts, m->mnt_freq, m->mnt_passno);			debugmsg("-----");			tmp->fixed = 1;		} else {			/* TODO: how to deal with the noauto flag?? */			/* if(hasmntopt(m, "noauto") == NULL && vmount_find(device, uuid, label) == NULL) { */			debugmsg("%-30s %-30s %-8s %-30s %4i %4i", m->mnt_fsname, m->mnt_dir, m->mnt_type, m->mnt_opts, m->mnt_freq, m->mnt_passno);			tmp = vmount_new();			if(tmp != NULL) {				tmp->fixed = 1;				SDUP(tmp->device, device);				SDUP(tmp->mountpoint, m->mnt_dir);				SDUP(tmp->fstype, m->mnt_type);				tmp->mountflags = 0;				SDUP(tmp->data, m->mnt_opts);				SDUP(tmp->volumename, label);				uuid_copy(tmp->uuid, uuid);				tmp->next = NULL;								vmount_add(tmp);			} else {				errormsg("Not enough memory creating vmount struct");			}		}				/* cleanup */		if(label != NULL) free(label); label = NULL;		if(device != NULL) free(device); device = NULL;		uuid_clear(uuid);	}	if(m) free(m);		fclose(fd);}/*	Checks all devices for new (or lost) partitions and passes them over to handle_device. 	either check all periodic or the others */int scan_devices(int periodic) {    scan_item* tmp = scan_list;	hotplug_msg msg;	    debugmsg("Checking for new %sdevices....", periodic?"periodic ":"");        while(tmp) {		if(tmp->periodic == periodic) {			if(device_exists(tmp->device)) {				/* device exists, test if it has appeared just now */				if(tmp->status == VOLD_UNKNOWN)  {					msg.action = VOLD_ADD;					msg.vendor = NULL;					msg.model = NULL;					msg.device = tmp->device;					handle_device(&msg, tmp);				} else if(tmp->status == VOLD_MOUNTED) {					//logmsg("Not touching device '%s': Already mounted", tmp->device);										if( dir_mounted(tmp->device) == 0) {						/* device was unmounted by user */						debugmsg("Device was manually unmounted.");						msg.action = VOLD_REMOVE;						msg.vendor = NULL;						msg.model = NULL;						msg.device = tmp->device;						handle_device(&msg, tmp);					}				}			} else {				if(tmp->status == VOLD_MOUNTED) {					/* device disappeared illegally */					errormsg("POSSIBLE DATA LOSS! Device %s removed without umounting.", tmp->device);					msg.action = VOLD_REMOVE;					msg.vendor = NULL;					msg.model = NULL;					msg.device = tmp->device;					handle_device(&msg, tmp);				} else if(tmp->status == VOLD_IGNORED || tmp->status == VOLD_UNMOUNTED) {					/* device no more here, mark state unknown */					tmp->status = VOLD_UNKNOWN;				}			}		}		tmp = tmp->next;	}	return 0;}/*	Receives a hotplug message	ADD:	detects filesystem using Disktype and scans for uuid's from the filesystem, then calls mount_device with			the corresponding vmount struct. If mount is succesful adds/appends the			information to the mount_list (using vmount_find() vmount_add()). 	REMOVE:	calls unmount_device and removes the vmount entry */void handle_device(hotplug_msg* msg, scan_item* dev) {	int ret = 0;	vold_mount* vm = NULL;	DT_Info* info;	uuid_t uuid;	/* sanity */	if(msg == NULL || dev == NULL) return;		uuid_clear(uuid);		switch(msg->action) {		case VOLD_ADD:			debugmsg("---- New device '%s' found ------", msg->device);			info = DT_detect(msg->device, DFLAG_ALL);			if(info == NULL) {				errormsg("could not detect filesystem type. NOT mounting %s", msg->device);				errormsg("Disktype should be able to detect everything!! Mail me if you can read this.");				errormsg("---Device will be ignored until it is unplugged---");				dev->status = VOLD_IGNORED;				return;			}			if(info->type == DT_PARTMAP) {				/* partition map handling */						debugmsg("PARTITION:Detected fstype for device %s: '%s'", msg->device, info->fs.type_name);				debugmsg("TODO: implement Partition handling :-)");						/* TODO */						} else if(info->type == DT_FS && info->fs.type_name != NULL) {				/* single filesystem handling (for linux mountable devices) */				debugmsg("Detected fstype for device %s: '%s'", msg->device, info->fs.type_name);								/* check if we have a uuid (either direct or from disk) */				if(uuid_is_null(info->fs.uuid)) {					/* no uuid, check if fs has a uuid_file */					get_uuid_from_fs(info->fs.type_name, msg->device, uuid);				} else					uuid_copy(uuid, info->fs.uuid);									/* if there is a uuid we now have it in 'uuid' */								/* add or append? */				vm = vmount_find(msg->device, uuid, info->fs.volume_name);				if(vm != NULL) {					/* append */					debugmsg("vold_mount already exists, updating information");					//vm->fixed = 0;					SADD(vm->device, msg->device);					SADD(vm->fstype, info->fs.type_name);					SDUP(vm->volumename, info->fs.volume_name);					uuid_copy(vm->uuid, uuid);								} else {					/* add */					vm = vmount_new();					if(vm == NULL) {						errormsg("Not enough memory creating new vold_mount struct");						return;					}					debugmsg("vold_mount not found. This is a new partition not found in fstab");										vm->fixed = 0;					SDUP(vm->device, msg->device);					vm->mountpoint = NULL;					SDUP(vm->fstype, info->fs.type_name);					vm->mountflags = 0;					vm->data = NULL;					SDUP(vm->volumename, info->fs.volume_name);					SADD(vm->volumename, msg->model)					uuid_copy(vm->uuid, uuid);					vm->next = NULL;					vmount_add(vm);				}								ret = mount_device(vm);				switch(ret) {					case 0:						debugmsg("Mount succesful");						dev->status = VOLD_MOUNTED;						break;					default:						vmount_remove(vm);						logmsg("mount failed. Device ignored! (Error: %i)", ret);						dev->status = VOLD_IGNORED;				}			} else {				/* nothing to do */				errormsg("Device does not contain a partition table or a filesystem mountable by linux");				errormsg("infotype: %i fstype: %i, type_version_name: %s, volume_name: %s", info->type, info->fs.type, info->fs.type_version_name, info->fs.volume_name);			}						/* cleanup! */			remove_DT_Info(info);						debugmsg("-------------------------------------------");			break;		case VOLD_REMOVE:			debugmsg("---- Removing device '%s' ------", msg->device);			vm = vmount_find(msg->device, NULL, NULL);			ret = unmount_device(vm);			switch(ret) {				case 0:					debugmsg("Unmount succesful");					dev->status = VOLD_UNMOUNTED;					vmount_remove(vm);					break;				default:					logmsg("unmount failed. unmount_device returned error: %i", ret);					break;			}			debugmsg("-------------------------------------------");			break;		default:			break;	}}/*	Receives a vmount that contains all essential information to complete the other fields (device, fstype, and either	mountpoint or volumename have to be present). Checks if device is already mounted. Uses get_mountpoint to find a	suitable mountpoint. Mountpoint: defined in fstab or "/VOLUMES/[volumelabel]" */ int mount_device(vold_mount* vm) {    int ret;	if(vm == NULL) return -3;	/* check if vmount has all its essential fields filled */	if(vm->device == NULL || vm->fstype == NULL) return -1;		/* check if its a swap device */	if(strcmp(vm->fstype, "swap") == 0) {	  /* TODO: implement Swapon */	  errormsg("SWAP detected: **** NOT IMPLEMENTED ****");	  return -1;	}		/* check if it is already mounted */	if(dir_mounted(vm->device)) return -1;	get_mountpoint(vm);		if(vm->mountpoint == NULL) {		errormsg("Could not find a valid mountpoint for %s (%s)", vm->device, vm->fstype);		return -1;	}	logmsg("Mounting %s (%s) at %s, (mountflags: %i, data: %s)", vm->device, vm->fstype, vm->mountpoint, vm->mountflags, vm->data);	ret = mount(vm->device, vm->mountpoint, vm->fstype, vm->mountflags, vm->data);	if(ret == -1) {		errormsg("Could not mount %s under %s.", vm->device, vm->mountpoint);		errormsg("Reason: %s", strerror(errno));	}	    return ret;}/*	Unmounts the device */int unmount_device(vold_mount* vm) {	int ret = 0;		if(vm == NULL) return -3;		logmsg("Unmounting device %s at %s", vm->device, vm->mountpoint);	ret = umount(vm->mountpoint);		/* just for testing.. remove this, if every thing works. */	if(ret != 0) {		/* this can happen if the user has ummounted the device manually!!! */		debugmsg("unmount returned error: %s", strerror(errno));	}		if( dir_mounted(vm->mountpoint) == 0) {		/* device no more mounted, this is the really important point :-) */		ret = 0;		if(vm->fixed == 0) {			/* dont remove dir if we have a fixed mount */			if(rmdir(vm->mountpoint) != 0) {				errormsg("Cannot remove dir '%s' after unmounting: %s", vm->mountpoint, strerror(errno));			} else {				debugmsg("directory removed");

⌨️ 快捷键说明

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