00001 /** @file rutz/unixcall.cc thin wrappers around unix system calls */ 00002 00003 /////////////////////////////////////////////////////////////////////// 00004 // 00005 // Copyright (c) 1999-2004 California Institute of Technology 00006 // Copyright (c) 2004-2007 University of Southern California 00007 // Rob Peters <rjpeters at usc dot edu> 00008 // 00009 // created: Wed Nov 17 15:05:41 1999 00010 // commit: $Id: unixcall.cc 14376 2011-01-11 02:44:34Z pez $ 00011 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/rutz/unixcall.cc $ 00012 // 00013 // -------------------------------------------------------------------- 00014 // 00015 // This file is part of GroovX. 00016 // [http://ilab.usc.edu/rjpeters/groovx/] 00017 // 00018 // GroovX is free software; you can redistribute it and/or modify it 00019 // under the terms of the GNU General Public License as published by 00020 // the Free Software Foundation; either version 2 of the License, or 00021 // (at your option) any later version. 00022 // 00023 // GroovX is distributed in the hope that it will be useful, but 00024 // WITHOUT ANY WARRANTY; without even the implied warranty of 00025 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00026 // General Public License for more details. 00027 // 00028 // You should have received a copy of the GNU General Public License 00029 // along with GroovX; if not, write to the Free Software Foundation, 00030 // Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. 00031 // 00032 /////////////////////////////////////////////////////////////////////// 00033 00034 #ifndef GROOVX_RUTZ_UNIXCALL_CC_UTC20050626084019_DEFINED 00035 #define GROOVX_RUTZ_UNIXCALL_CC_UTC20050626084019_DEFINED 00036 00037 #include <cctype> 00038 #include "unixcall.h" 00039 00040 #include "rutz/arrays.h" 00041 #include "rutz/error.h" 00042 #include "rutz/fstring.h" 00043 #include "rutz/sfmt.h" 00044 00045 #include <cerrno> // for ::errno 00046 #include <cstdio> // for ::rename(), ::remove() 00047 #include <cstdlib> // for ::atoi() 00048 #include <cstring> // for ::strerror() 00049 #include <dirent.h> // for ::opendir(), ::readdir() 00050 #include <sys/stat.h> // for ::chmod(), ::stat() 00051 #include <unistd.h> // for ::getcwd() (POSIX) 00052 00053 #include "rutz/trace.h" 00054 #include "rutz/debug.h" 00055 GVX_DBG_REGISTER 00056 00057 namespace 00058 { 00059 void throwErrno(const char* where, const rutz::file_pos& pos) 00060 { 00061 throw rutz::error(rutz::sfmt("in \"%s\": %s", where, 00062 ::strerror(errno)), pos); 00063 } 00064 00065 class ErrnoSaver 00066 { 00067 public: 00068 ErrnoSaver() : saved(errno) 00069 { 00070 errno = 0; 00071 } 00072 00073 ~ErrnoSaver() 00074 { 00075 errno = saved; 00076 } 00077 00078 const int saved; 00079 }; 00080 } 00081 00082 void rutz::unixcall::chmod(const char* path, mode_t mode) 00083 { 00084 GVX_TRACE("rutz::unixcall::chmod"); 00085 00086 ErrnoSaver saver; 00087 00088 if ( ::chmod(path, mode) != 0 ) 00089 throwErrno("chmod", SRC_POS); 00090 } 00091 00092 void rutz::unixcall::rename(const char* oldpath, const char* newpath) 00093 { 00094 GVX_TRACE("rutz::unixcall::rename"); 00095 00096 ErrnoSaver saver; 00097 00098 if ( ::rename(oldpath, newpath) != 0 ) 00099 throwErrno("rename", SRC_POS); 00100 } 00101 00102 void rutz::unixcall::remove(const char* pathname) 00103 { 00104 GVX_TRACE("rutz::unixcall::remove"); 00105 00106 errno = 0; 00107 00108 if ( ::remove(pathname) != 0 ) 00109 throwErrno("rutz::unixcall::remove", SRC_POS); 00110 } 00111 00112 rutz::fstring rutz::unixcall::getcwd() 00113 { 00114 GVX_TRACE("rutz::unixcall::getcwd"); 00115 00116 ErrnoSaver saver; 00117 00118 const int INIT_SIZE = 256; 00119 rutz::dynamic_block<char> buf(INIT_SIZE); 00120 00121 while ( ::getcwd(&buf[0], buf.size()) == 0 ) 00122 { 00123 if (errno == ERANGE) 00124 { 00125 errno = 0; 00126 buf.resize(buf.size() * 2); 00127 } 00128 else 00129 { 00130 throwErrno("getcwd", SRC_POS); 00131 } 00132 } 00133 00134 return rutz::fstring(&buf[0]); 00135 } 00136 00137 pid_t rutz::unixcall::get_file_user_pid(const char* fname) 00138 { 00139 GVX_TRACE("rutz::unixcall::get_file_user_pid"); 00140 DIR* const proc_dir = opendir("/proc"); 00141 00142 if (proc_dir == 0) 00143 return 0; 00144 00145 struct stat target_statbuf; 00146 if (stat(fname, &target_statbuf) != 0) 00147 return 0; 00148 00149 const pid_t my_pid = getpid(); 00150 00151 struct dirent* proc_dent = 0; 00152 00153 while ((proc_dent = readdir(proc_dir)) != 0) 00154 { 00155 if (proc_dent == 0) 00156 break; 00157 00158 if (!isdigit(proc_dent->d_name[0])) 00159 continue; 00160 00161 const pid_t pid = atoi(proc_dent->d_name); 00162 00163 if (pid == my_pid) 00164 continue; 00165 00166 const rutz::fstring fd_dirname = 00167 rutz::sfmt("/proc/%s/fd", proc_dent->d_name); 00168 00169 DIR* const fd_dir = opendir(fd_dirname.c_str()); 00170 00171 if (fd_dir == 0) 00172 continue; 00173 00174 struct dirent* fd_dent = 0; 00175 00176 while ((fd_dent = readdir(fd_dir)) != 0) 00177 { 00178 if (!isdigit(fd_dent->d_name[0])) 00179 continue; 00180 00181 const rutz::fstring fd_fname = 00182 rutz::sfmt("%s/%s", fd_dirname.c_str(), fd_dent->d_name); 00183 00184 struct stat fd_statbuf; 00185 if (stat(fd_fname.c_str(), &fd_statbuf) != 0) 00186 continue; 00187 00188 if (fd_statbuf.st_dev == target_statbuf.st_dev && 00189 fd_statbuf.st_ino == target_statbuf.st_ino) 00190 return pid; 00191 } 00192 00193 closedir(fd_dir); 00194 } 00195 00196 closedir(proc_dir); 00197 00198 return 0; 00199 } 00200 00201 static const char __attribute__((used)) vcid_groovx_rutz_unixcall_cc_utc20050626084019[] = "$Id: unixcall.cc 14376 2011-01-11 02:44:34Z pez $ $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/rutz/unixcall.cc $"; 00202 #endif // !GROOVX_RUTZ_UNIXCALL_CC_UTC20050626084019_DEFINED