📄 mmounter.c
字号:
// This program is free software; you can redistribute it and/or modify// it under the terms of the GNU General Public License as published by// the Free Software Foundation; either version 2 of the License, or// (at your option) any later version.//// This program is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the// GNU Library General Public License for more details.//// You should have received a copy of the GNU General Public License// along with this program; if not, write to the Free Software// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA./* * $Id: mmounter.C,v 1.3 2000/10/03 20:43:58 lyonel Exp $ * * Copyright (c) 2000, Lyonel VINCENT <vincentl@ec-lyon.fr> * */#include "CONFFile.h"#include <linux/cdrom.h>#include <sys/ioctl.h>#include <sys/param.h>#include <sys/stat.h>#include <sys/types.h>#include <sys/ipc.h>#include <sys/msg.h>#include <sys/wait.h>#include <dirent.h>#include <unistd.h>#include <errno.h>#include <fcntl.h>#include <stdio.h>#include <mntent.h>#include <pthread.h>#include <signal.h>#include <fstream.h>#include <map>#include "cmds.h"#include "getlabel.h"using namespace std; // to access vector, string, etc.#include "config.h"/* * globals */CONFFile * config = NULL;map<string, getlabelfunc> getlabel;vector<string> monitored_devices;bool running = true;bool debug = false;bool rundaemon = true;extern char **environ;int msg_queue = -1;/* * utility classes */struct Mutex{ Mutex() { pthread_mutex_init(&pmutex, NULL); } ~Mutex() { pthread_mutex_destroy(&pmutex); } void lock() { pthread_mutex_lock(&pmutex); } void unlock() { pthread_mutex_unlock(&pmutex); } pthread_mutex_t pmutex;};struct Lock{ Lock(Mutex & m): mutex(m) { mutex.lock(); } ~Lock() { mutex.unlock(); } Mutex & mutex;};/* * mutexes */Mutex mtab_m, deviceprobe_m, stderr_m, devices_m;/* * utility functions */void sigterm(int){ running = false; DIAGNOSTIC("Shutting down" << endl); signal(SIGTERM, sigterm); signal(SIGINT, sigterm);}int run(const string & prog, vector<string> args = vector<string>() ){ pid_t pid; int status; if (prog == "") return 1; pid = fork(); if (pid == -1) return -1; if (pid == 0) // child { size_t i; const char * * argv = new (const char *)[args.size()+2]; argv[0] = (char*)prog.c_str(); DIAGNOSTIC("exec-ing " << prog); for(i=0; i<args.size(); i++) { argv[i+1] = (char*)args[i].c_str(); DIAGNOSTIC(" " << args[i]); } argv[i+1] = NULL; DIAGNOSTIC(endl); execve(argv[0], (char * const *)argv, environ); delete[] argv; exit(127); } do // father { if (waitpid(pid, &status, 0) == -1) { if (errno != EINTR) return -1; } else return status; } while(true);}bool readable(const string & s){ int fd = open(s.c_str(),O_RDONLY | O_NONBLOCK); if(fd==-1) return false; else close(fd); return access(s.c_str(), R_OK) == 0;}bool exists(const string & s){ return access(s.c_str(), F_OK) == 0;}bool isSymlink(const string & s){ struct stat buf; if(lstat(s.c_str(), &buf)==0) { return S_ISLNK(buf.st_mode); } else return false;}bool isDirectory(const string & s){ struct stat buf; if(stat(s.c_str(), &buf)==0) { return S_ISDIR(buf.st_mode); } else return false;}string resolveLinks(const string & s){ char buffer[MAXPATHLEN+1]; if(realpath(s.c_str(), buffer)) return string(buffer); else return s;}string unEscape(const string & s){ string result =""; for(size_t i = 0; i<s.length(); i++) { if((s[i]=='\\')&&(s[i+1]=='0')) { result += char(8*(s[i+2]-'0')+(s[i+3]-'0')); i += 3; } else result += s[i]; } return result;}string basename(const string & line){ size_t pos = line.rfind('/'); if(pos!=string::npos) return line.substr(pos+1); else return line;}string normalizeFilename(string line){ size_t pos; while((pos = line.rfind('/'))!=string::npos) line[pos] = ' '; while((pos = line.rfind('*'))!=string::npos) line[pos] = ' '; while(line[0]==' ') line = line.substr(1); // remove leading blanks while(line[line.length()-1]==' ') line = line.substr(0,line.length()-1); // remove ending blanks if(line=="") line = "unnamed"; return line;}string itoa(size_t i){ char buffer[10]; strcpy(buffer, ""); snprintf(buffer, sizeof(buffer), "%d", i); return string(buffer);}string getOption(const string & section, const string & valuename, const string & def=""){ return config->getValue(section, valuename, config->getValue("*", valuename, def));}bool isDeviceMonitored(const string & device){ size_t i; vector<string> sections = config->listSections(); for(i=0; i<sections.size(); i++) if(resolveLinks(sections[i])==device) return true; { Lock l(devices_m); for(i=0; i<monitored_devices.size(); i++) if(resolveLinks(monitored_devices[i])==device) return true; } return false;}void monitoringDevice(const string & device){ Lock l(devices_m); monitored_devices.push_back(device);}bool checkIfDeviceMounted(const string & device, string & mounted_on){ Lock l(mtab_m); bool result = false; struct mntent * entry = NULL; FILE * mtab = setmntent(ETCMTAB, "r"); mounted_on = ""; if(!mtab) return false; while(entry = getmntent(mtab)) { if(resolveLinks(string(entry->mnt_fsname))==device) { result = true; mounted_on = unEscape(string(entry->mnt_dir)); break; } } endmntent(mtab); return result;}bool findMountedDevice(const string & path, string & device){ // path can be either the device or the mount point (or, of course a symlink to one of them) string dir = ""; device = ""; Lock l(devices_m); for(int i=0; i<monitored_devices.size(); i++) { if(resolveLinks(monitored_devices[i])==resolveLinks(path)) { device = monitored_devices[i]; return true; } if(checkIfDeviceMounted(resolveLinks(monitored_devices[i]), dir) && (resolveLinks(path)==resolveLinks(dir))) { device = monitored_devices[i]; return true; } } return false;}bool mediaChanged(const string & device){ Lock l(deviceprobe_m); // just in case int fd = open(device.c_str(), O_RDONLY | O_NONBLOCK); if(fd<0) return false; int status=ioctl(fd, CDROM_MEDIA_CHANGED); close(fd); return status==1;}bool canProbeMedia(const string & device){ int fd = open(device.c_str(), O_RDONLY | O_NONBLOCK); if(fd<0) return true; int status=ioctl(fd, CDROM_DRIVE_STATUS, CDSL_CURRENT); close(fd); return (status<0)||(status==CDS_DISC_OK);}bool getFSTypeAndVolumeName(const string & device, string & fs, string & label){ char buffer[MAXPATHLEN+1]; Lock l(deviceprobe_m); // just in case vector<string> filesystems = CONFFile::split(getOption(device, "fs", FS)); if(!canProbeMedia(device)) return false; for(size_t i=0; i<filesystems.size(); i++) if(getlabel[filesystems[i]]) { int fd = open(device.c_str(), O_RDONLY | O_NONBLOCK); if(fd>=0) if(getlabel[filesystems[i]](fd, buffer)) { fs = filesystems[i]; label = string(buffer); DIAGNOSTIC("found " << label << " (" << fs << ") in " << device << endl); close(fd); return true; } close(fd); } return false;}bool rm(const string & path){ if(isSymlink(path)) return unlink(path.c_str())==0; else if(isDirectory(path)) { rm(path+string("/"FINGERPRINT)); return rmdir(path.c_str())==0; } return false; // cowardly refusing to delete anything others may have created}string generateFriendlyMountPoint(const string & device, const string & label, const string & fs){ string format = getOption(device, "mountpoint", MOUNTPOINT); string result = ""; map<char, string> escapes; escapes['v'] = label; escapes['f'] = fs; escapes['t'] = getOption(device, "type", DEFAULTTYPE); escapes['d'] = basename(device); escapes['\\'] = string("\\"); for(size_t i=0; i<format.length(); i++) if(format[i]=='\\') // we found a format escape { DIAGNOSTIC("found escape: " << format[i+1] << endl); result += escapes[format[i+1]]; i++; } else result += format[i]; DIAGNOSTIC("result=" << result << endl); return normalizeFilename(result);}string generateMountPoint(const string & device, const string & label, const string & fs){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -