📄 mmounter.c
字号:
string dirname = getOption(device, "mountbase", MOUNTBASE)+"/"+generateFriendlyMountPoint(device, label, fs); if(exists(dirname) && !rm(dirname)) { unsigned int count = 1; while(exists(dirname+"-"+itoa(count)) && !rm(dirname+"-"+itoa(count))) count++; dirname += "-"+itoa(count); } return dirname;}bool ejectDevice(const string & device){ string eject = getOption(device,"eject"); if(eject=="") return false; vector<string> args; args.push_back(device); return (run(eject, args)==0);}bool mountDevice(const string & device, const string & fs, const string & label, string & dirname){ vector<string> args; dirname = generateMountPoint(device, label, fs); mkdir(dirname.c_str(),0); symlink(".", (dirname+string("/"FINGERPRINT)).c_str()); args.push_back(device); args.push_back(dirname); args.push_back("-t"); args.push_back(fs); args.push_back("-o"); args.push_back(getOption(device, "options", "defaults")); if(getOption(device, "options."+fs)!="") { args.push_back("-o"); args.push_back(getOption(device, "options."+fs)); } if(run(getOption(device, "mount", MOUNT),args)!=0) { rm(dirname); dirname = ""; return false; } else return true;}bool linkMountedDevice(const string & device, const string & label, const string & fs, const string & mountpoint, string & dirname){ dirname = generateMountPoint(device, label, fs); if(symlink(mountpoint.c_str(), dirname.c_str())==0) return true; else { dirname = ""; return false; }}bool umountDevice(const string & path){ string device = ""; if(!findMountedDevice(path, device) || getOption(device, "userdisk", "no")!="yes") return false; vector<string> args; args.push_back(device); if(run(getOption(device, "umount", UMOUNT),args)!=0) return false; else return true;}bool cleanUnusedMountPoints(const string & device){ string dirname = getOption(device, "mountbase", MOUNTBASE); DIR * dir = opendir(dirname.c_str()); if(!dir) return false; while(struct dirent * entry = readdir(dir)) { if(isSymlink(dirname+string("/")+string(entry->d_name)+string("/"FINGERPRINT))) { DIAGNOSTIC("cleaning " << entry->d_name << endl); rm(dirname+string("/")+string(entry->d_name)); } } closedir(dir); return true;}void addToCache(const string & device, const string & mountpoint){ string dirname = getOption(device, "cache", CACHEDIR)+"/"+basename(device); mkdir(dirname.c_str(), 0777); symlink(device.c_str(),(dirname+string("/device")).c_str()); symlink(mountpoint.c_str(),(dirname+string("/mountpoint")).c_str());}void removeFromCache(const string & device){ string dirname = getOption(device, "cache", CACHEDIR)+"/"+basename(device); rm(dirname+string("/device")); rm(dirname+string("/mountpoint")); rm(dirname);}bool checkIfCached(const string & device, string & mountpoint){ string dirname = getOption(device, "cache", CACHEDIR)+"/"+basename(device); if(isSymlink(dirname+string("/mountpoint"))&&(resolveLinks(dirname+string("/device"))==resolveLinks(device))) { mountpoint = resolveLinks(dirname+string("/mountpoint")); return true; } else return false;}void * workingThread(void * p){ string * device = (string*)p; string current_dir, current_fs, current_volid, ignored=""; bool mmounted = false; int delay; if(*device == "*") return NULL; DIAGNOSTIC("Polling " << (*device) << " (" << getOption(*device, "type","unknown") << ")" << endl); cleanUnusedMountPoints(*device); monitoringDevice(*device); delay = atoi(getOption(*device, "delay", "10").c_str()); if(delay<=0) delay = 10; while(running) { if(readable(*device)) { string mounted_on = ""; bool is_mounted = checkIfDeviceMounted(resolveLinks(*device), mounted_on); string fs="", labelname="", eject=""; if(!mmounted) // reset cached values { current_dir = ""; current_fs = ""; current_volid = ""; } if(is_mounted) // device is currently mounted { if(!mmounted) mmounted |= checkIfCached(*device, current_dir); if(!mmounted) // we didn't mount it -> try to symlink to it { if(getFSTypeAndVolumeName(*device, fs, labelname)) { mmounted = linkMountedDevice(*device, labelname, fs, mounted_on, current_dir); current_fs = fs; current_volid = labelname; } } else { if(resolveLinks(mounted_on)!=resolveLinks(current_dir)) // it's no longer mounted where we mounted it -> forget we mounted it { removeFromCache(*device); mmounted = false; rm(current_dir); } } ignored = ""; } else // device is not currently mounted { if(mmounted) // we thought it was -> eject it and cleanup mount point/symlink { removeFromCache(*device); mmounted = false; rm(current_dir); if(!ejectDevice(*device)) // try to eject it ignored = current_fs+"/"+current_volid; // ignore this disk so that we won't try to mount it back else ignored = ""; // the disk has been successfully ejected } else { if(getFSTypeAndVolumeName(*device, fs, labelname)) // mmm... seems we could mount it... { if(fs+"/"+labelname!=ignored) // check that we are not ignoring this disk { mmounted = mountDevice(*device, fs, labelname, current_dir); // try to mount it if(!mmounted) // failed to mount it ejectDevice(*device); else addToCache(*device, current_dir); ignored = ""; // the disk we were ignoring has been removed current_fs = fs; current_volid = labelname; } } else // FS couldn't be detected, shut up (device could be offline or containing an unknown FS (audio CD...) { ignored = ""; // the disk we were ignoring has been removed } } } } sleep(delay); } if(mmounted) { //umount(current_dir.c_str()); rm(current_dir); } DIAGNOSTIC("Stopping polling " << *device << endl); delete device; return NULL;}void * sourcePartitionFile(void * p){ string * filename = (string *)p; int delay = 10; vector<pthread_t> threads; DIAGNOSTIC("Sourcing " << *filename << endl); delay = atoi(getOption("<"+*filename, "delay", "10").c_str()); if(delay<=0) delay = 10; while(running) { FILE * input = fopen(filename->c_str(), "r"); if(input) { char line[MAXPATHLEN+1]; while (fgets(line, sizeof(line), input)) { int ma, mi, sz; char ptname[MAXPATHLEN+1]; char * s; if (sscanf (line, " %d %d %d %[^\n]\n", &ma, &mi, &sz, ptname) != 4) continue; //skip extended partitions (heuristic: size 1) if (sz == 1) continue; // skip entire disk (minor 0, 64, ... on ide; 0, 16, ... on sd) // heuristic: partition name ends in a digit for(s = ptname; *s; s++); if (isdigit(s[-1])) if(!isDeviceMonitored(resolveLinks("/dev/"+string(ptname)))) { pthread_t thread; DIAGNOSTIC("partition found: " << ptname << endl); if(pthread_create(&thread, NULL, workingThread, new string("/dev/"+string(ptname)))) threads.push_back(thread); } } fclose(input); } sleep(delay); } if(filename) delete(filename); for(size_t i=0; i<threads.size(); i++) { if(threads[i]) pthread_join(threads[i], NULL); } return NULL;}void * listeningThread(void *){ struct my_msgbuf * msg = (struct my_msgbuf*)malloc(sizeof(struct my_msgbuf)+MAXPATHLEN); while(running) { if(msgrcv(msg_queue, (struct msgbuf*)msg, MAXPATHLEN, 0, MSG_NOERROR)!=-1) switch(msg->mtype) { case MMOUNTER_UMOUNT: umountDevice(msg->mtext); break; default: DIAGNOSTIC("unknown command !" << endl); } } free(msg);}int go(CONFFile conf){ config = &conf; vector<string> devices = config->listSections(); vector<pthread_t> threads; pthread_t listeningthread; pthread_t thread; size_t i; pthread_create(&listeningthread, NULL, listeningThread, NULL); for(i=0; i<devices.size(); i++) cleanUnusedMountPoints(devices[i]); for(i=0; i<devices.size(); i++) { if(devices[i]!="*") { if(devices[i][0]=='<') // we have to autodetect partitions { if(pthread_create(&thread, NULL, sourcePartitionFile, new string(devices[i].substr(1)))==0) // strip the leading '<' threads.push_back(thread); } else { if(pthread_create(&thread, NULL, workingThread, new string(devices[i]))==0) threads.push_back(thread); } } } for(size_t i=0; i<threads.size(); i++) { if(threads[i]) pthread_join(threads[i], NULL); } return 0;}int main(int argc, const char * * argv){ int c; string config = ""; while((c = getopt (argc, (char*const*)argv, "Vgc:")) != -1) switch(c) { case 'V': cout << VERSION << endl; return 0; case 'g': debug = true; break; case 'c': config = string(optarg); break; case '?': cerr << "usage:" << endl << "\t" << argv[0] << " [-V]" << endl << "\t" << argv[0] << " [-g] [-c configfile]" << endl; return 1; } rundaemon &= !debug; if(rundaemon) { if(fork()) return 0; setpgrp(); close(0); close(1); ofstream varrunpid(PIDFILE); varrunpid << getpid() << endl; } getlabel["ext2"] = ext2_getlabel; getlabel["ext3"] = ext2_getlabel; getlabel["hfs"] = hfs_getlabel; getlabel["vfat"] = vfat_getlabel; getlabel["iso9660"] = iso9660_getlabel; getlabel["ntfs"] = ntfs_getlabel; signal(SIGTERM, sigterm); signal(SIGINT, sigterm); if(config=="") config = ETCMMOUNTERCONF; msg_queue = msgget(ftok(config.c_str(), 0), IPC_CREAT | 0666); // create a world-accessible msg queue if(msg_queue==-1) DIAGNOSTIC("could not create message queue" << endl); int result = go(CONFFile(config.c_str())); if(msg_queue!=-1) msgctl(msg_queue, IPC_RMID, NULL); return result;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -