📄 vold.c
字号:
} } } return(ret);}/* Fills in a valid mountpoint (if != NULL). If we already have a mountpoint (from fstab) believe the user and return. Otherwise try to create one with volumename or device in which case we have to test if we can really use it */void get_mountpoint(vold_mount* vm) { char target[MAX_STRLEN + 1]; char* devicename; char* tmp; if(vm == NULL) return; if(vm->mountpoint != NULL) { /* we already ha a mountpoint, believe the user! */ return; } /* no fixed mount. mounting automatic */ if(vm->volumename != NULL && strlen(vm->volumename) > 0) { /* we have a volume label. now strip illegal chars ('/') */ debugmsg("stripping illegal char '/' from volume label: '%s'", vm->volumename); tmp = strstr(vm->volumename, "/"); while(tmp != NULL) { *tmp = '_'; tmp = strstr(vm->volumename, "/"); } debugmsg("legal volume label after stripping: '%s'", vm->volumename); snprintf(target, MAX_STRLEN, "%s/%s", volumeroot, vm->volumename); } else { /* no volume label, create a generic mountpoint (/Volumes/sda1)*/ devicename = strrchr(vm->device, '/'); snprintf(target, MAX_STRLEN, "%s%s", volumeroot, devicename); debugmsg("device has no label, mountpoint: %s", target); } target[MAX_STRLEN] = '\0'; /* validate mountpoint: check if folder exists, not already used by another device etc. returns a valid mountpoint (and creates directory automatically) */ vm->mountpoint = validate_mountpoint(target, 0); /* vm->mountflags = defaultmountflags; */ }/* Checks if target can be used as mountpoint. If not adds a number to it and recursively calls itself to check again. final target is either target or "target X" with 0 < X <= 255 */char* validate_mountpoint(char* target, int recursion_level) { struct stat buf; char real_target[MAX_STRLEN + 1]; char* new_target; if(target == NULL || recursion_level > 255) return NULL; if(recursion_level != 0) { /* we are in recursion mode. add the recursion suffix to name */ snprintf(real_target, MAX_STRLEN, "%s #%i", target, recursion_level); real_target[MAX_STRLEN] = '\0'; } else { snprintf(real_target, MAX_STRLEN, "%s", target); real_target[MAX_STRLEN] = '\0'; } if( stat(real_target, &buf) == 0) { /* target exists */ if(S_ISDIR(buf.st_mode) && !dir_mounted(real_target)) { /* good, use directory as mountpoint */ } else { /* either dir already used by another mount or something else -> try new mountpoint */ debugmsg("validate: not selecting %s: dir already used", real_target); debugmsg("isdir: %s, ismounted: %s", S_ISDIR(buf.st_mode)?"yes":"no", dir_mounted(real_target)?"yes":"no"); new_target = validate_mountpoint(target, recursion_level + 1); return(new_target); } } else { /* target does not exist. very good, now mkdir and return */ umask(0); if( mkdir(real_target, S_IRWXU | S_IRWXG | S_IRWXO) != 0 ) { /* could not create mountpoint, try to find another */ debugmsg("validate: not selecting %s: cannot create dir", real_target); debugmsg("reason: %s", strerror(errno)); new_target = validate_mountpoint(target, recursion_level + 1); return(new_target); } } return strdup(real_target);}/* Tests if device is mounted. It doesn't matter whether device contains a device ('/dev/sda') or a mountpoint ('/mnt/cdrom') */int dir_mounted(char* device) { FILE* fd; struct mntent* m; int ret = 0; if(device == NULL) return 0; fd = fopen("/proc/mounts", "r+"); if(fd == NULL) { errormsg("Cannot open /proc/mounts: %s", strerror(errno)); return 0; } for(m = getmntent(fd); m != NULL; m = getmntent(fd)) { if( strncmp(device, m->mnt_fsname, MAX_STRLEN) == 0 || strncmp(device, m->mnt_dir, MAX_STRLEN) == 0) { /* device is already mounted */ ret = 1; break; } } if(m) free(m); fclose(fd); return ret;}/* returns 1 if it could find a uuid */int get_uuid_from_fs(char* fstype, char* device, uuid_t uuid) { /* TODO */ return 0;}/* reads the config file */void loadconfigfile(char* filename) { FILE* configfile; char line[MAX_STRLEN + 1]; char* p; int argc; char* argv[128]; char* linecopy; int linecount = 0; if( !(configfile = fopen(filename, "r")) ) { fprintf(stderr, "*WARNING* config file %s not found. Using defaults\n", filename); return; } while( !feof(configfile) ) { linecount++; fgets(line, sizeof line, configfile); if( (p = strpbrk(line, "#\r\n"))) *p = 0; linecopy = strdup(line); argc = splitline(argv, (sizeof argv)/(sizeof argv[0]), linecopy); exec_config(argc, argv, linecount); } fclose(configfile);}#define BEGIN_CONFIG(option, argcmin) \if(!strcmp(argv[0], option)) {\ if(argc < argcmin) {\ fprintf(stderr, "LINE %i "option": to few arguments\n", linecount); \ return; \ }#define CONFIG_OPTION(option,argcmin) \} else if(!strcmp(argv[0], option)) {\ if(argc < argcmin) {\ fprintf(stderr, "LINE %i "option": to few arguments\n", linecount); \ return; \ }#define END_CONFIG }int option_true(char* option) { if(strspn(&option[0], "1tTyYjJ")) { return 1; } return 0;}/* config file executor - returns number of arguments parsed, -1 on error */void exec_config(int argc, char* argv[], int linecount) { int ivar1; if(!argc) return; BEGIN_CONFIG("volumeroot", 1) strncpy(volumeroot, argv[1], MAX_STRLEN); CONFIG_OPTION("check_delay", 1) check_delay = atoi(argv[1]); CONFIG_OPTION("default_mntopts", 1) /* TODO */ CONFIG_OPTION("scan", 1) ivar1 = 0; if(argc > 2) { ivar1 = option_true(argv[2]); } sdevice_add(sdevice_new(argv[1], ivar1)); CONFIG_OPTION("uuid_filecheck", 1) uuid_filecheck = option_true(argv[1]); CONFIG_OPTION("background", 1) background = option_true(argv[1]); CONFIG_OPTION("debug", 1) debug = option_true(argv[1]); CONFIG_OPTION("include", 1) loadconfigfile(argv[1]); END_CONFIG }/* read the commandline arguments */void getconfig(int argc, char* argv[]) { int c = 0, opt_index = 0; int cmd_debug = -1; int cmd_background = -1; char cmd_pidfile[MAX_STRLEN + 1] = ""; static struct option long_options[] = { { "debug", 0, 0, 'd'}, { "background", 0, 0, 'b' }, { "configfile", 1, 0, 'c' }, { "help", 0, 0, 'h' }, { "pidfile", 1, 0, 'p' }, { 0, 0, 0, 0 } }; /* first of all read in the command line - needed to see what configfile to read etc */ while (c != -1) { c = getopt_long(argc, argv, "dbc:hp:", long_options, &opt_index); switch(c) { case 0: /* we got a long only option */ /* this time we don't have any */// if(!strcmp("ppp-pidfile", long_options[opt_index].name))// strncpy(cmd_ppp_pidfile, optarg, MAX_STRLEN); break; case 'd': cmd_debug = 1; break; case 'b': cmd_background = 1; break; case 'c': /* no cmd_configfilename here of course! */ strncpy(configfilename, optarg, MAX_STRLEN); break; case 'h': showversion(); showhelp(); quit(0); break; case 'p': strncpy(cmd_pidfile, optarg, MAX_STRLEN); break; case '?': showhelp(); quit(1); break; } } if(optind < argc) { fprintf(stderr, "unrecognized options: "); while(optind < argc) fprintf(stderr, "%s ", argv[optind++]); fprintf(stderr, "\n"); showhelp(); quit(1); } /* now read the configfile */ loadconfigfile(configfilename); /* now let the commandline override the options from the configfile! */ if(strcmp("", cmd_pidfile)) strncpy(pidfile, cmd_pidfile, MAX_STRLEN); if(cmd_debug != -1) debug = cmd_debug; if(cmd_background != -1) background= cmd_background;}/* shows a help message */void showhelp() { printf("usage: vold [-dbh] [-c configfile] [-p pidfile] \n"); printf("\noptions:\n" " -d --debug debug mode\n" " -b --background fork() to background - deamonize and stay silent\n" " -h --help display this help message\n" " -c --configfile [file] read configuration from 'file' (defaults to\n" " "VOLD_ROOT VOLD_CONFIGFILE")\n" " --pidfile pidfile to use (defaults to "VOLD_PIDFILE")\n" );}/* shows the version and welcome message */void showversion() { printf("vold - GNU/Linux Volume Daemon V"VOLD_VERSION"."VOLD_SUBVERSION" - written by Clemens Wacha\n\n");}/* writes pid file to /var/run/vold.pid */void writepidfile(char* filename) { FILE* fpid = NULL; if( (fpid = fopen(filename, "r")) ) { errormsg("The pid file '%s' does already exist!", filename); errormsg("Use --pidfile to choose another filename\n"); quit(1); } if( !(fpid = fopen(filename, "w")) ) { errormsg("Can't create pid file\n"); quit(1); } fprintf(fpid, "%i\n", getpid() ); fflush(fpid); fclose(fpid); debugmsg("writing pidfile done\n");}/* signal handler */void signal_handler(int signum) { debugmsg("\ngot signal - quitting\n"); done = 1;}void check_on_signal(int signum) { logmsg("Got SIGUSR1. Scanning on demand..."); vmount_list(); scan_devices(0);}/* cleanup stuff */void quit(int errorlevel) { sdevice_free(scan_list); vmount_free(mount_list); exit(errorlevel);}int main(int argc, char* argv[]) { int pid; uid_t uid; /* install signals */ signal(SIGTERM, signal_handler); signal(SIGINT, signal_handler); signal(SIGUSR1, check_on_signal); showversion(); uid = geteuid(); if(uid != 0) { errormsg("You are NOT root! Only root can run this program"); exit(1); } /* initial setup */ snprintf(configfilename, MAX_STRLEN, "%s%s",VOLD_ROOT,VOLD_CONFIGFILE); strncpy(pidfile, VOLD_PIDFILE, MAX_STRLEN); strncpy(volumeroot, VOLD_VOLUMEROOT, MAX_STRLEN); getconfig(argc, argv); /* begin fork stuff */ if(background) { pid = fork(); switch(pid) { case -1: errormsg("Cannot fork to background - Exiting\n\n"); quit(1); break; case 0: writepidfile(pidfile); //update pidfile break; default: /* quit father process */ quit(0); break; } } /* end fork stuff */ load_mounts(); load_fstab(); scan_devices(0); debugmsg("Greetings! - Entering Main Loop"); while(!done) { scan_devices(1); sleep(check_delay); } remove(pidfile); quit(0); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -