os.cxx
Go to the documentation of this file.
00001 /** 00002 * @file os.cxx 00003 * @brief Operating system dependent functions. 00004 * 00005 * Copyright (c) 2011 University of Pennsylvania. All rights reserved.<br /> 00006 * See https://www.cbica.upenn.edu/sbia/software/license.html or COPYING file. 00007 * 00008 * Contact: SBIA Group <sbia-software at uphs.upenn.edu> 00009 */ 00010 00011 00012 #include <basis/config.h> // platform macros - must be first 00013 #include <basis/except.h> // to throw exceptions 00014 00015 #include <vector> 00016 #include <stdlib.h> // malloc(), free() 00017 #include <string.h> // strncmp() 00018 00019 #if WINDOWS 00020 # include <direct.h> // _getcwd() 00021 # include <windows.h> // GetModuleFileName() 00022 #else 00023 # include <unistd.h> // getcwd(), rmdir() 00024 # include <dirent.h> // opendir() 00025 # include <sys/stat.h> // mkdir() 00026 #endif 00027 #if MACOS 00028 # include <mach-o/dyld.h> // _NSGetExecutablePath() 00029 #endif 00030 00031 #include <basis/os.h> 00032 #include <basis/os/path.h> 00033 00034 00035 // acceptable in .cxx file 00036 using namespace std; 00037 00038 00039 namespace basis { namespace os { 00040 00041 00042 // --------------------------------------------------------------------------- 00043 string getcwd() 00044 { 00045 string wd; 00046 #if WINDOWS 00047 char* buffer = _getcwd(NULL, 0); 00048 #else 00049 char* buffer = ::getcwd(NULL, 0); 00050 #endif 00051 if (buffer) { 00052 wd = buffer; 00053 free(buffer); 00054 } 00055 return wd; 00056 } 00057 00058 // --------------------------------------------------------------------------- 00059 string exepath() 00060 { 00061 string path; 00062 #if LINUX 00063 path = path::realpath("/proc/self/exe"); 00064 #elif WINDOWS 00065 LPTSTR buffer = NULL; 00066 LPTSTR newbuf = NULL; 00067 DWORD buflen = 256; 00068 DWORD retval = 0; 00069 00070 for (;;) { 00071 newbuf = static_cast<LPTSTR>(realloc(buffer, buflen * sizeof(TCHAR))); 00072 if (!newbuf) break; 00073 buffer = newbuf; 00074 retval = GetModuleFileName(NULL, buffer, buflen); 00075 if (retval == 0 || retval < buflen) break; 00076 buflen += 256; 00077 retval = 0; 00078 } 00079 00080 if (retval > 0) { 00081 # ifdef UNICODE 00082 int n = WideCharToMultiByte(CP_UTF8, 0, buffer, -1, NULL, 0, NULL, NULL); 00083 char* mbpath = static_cast<char*>(malloc(n)); 00084 if (mbpath) { 00085 WideCharToMultiByte(CP_UTF8, 0, buffer, -1, mbpath, n, NULL, NULL); 00086 path = mbpath; 00087 free(mbpath); 00088 } 00089 # else 00090 path = buffer; 00091 # endif 00092 } 00093 00094 free (buffer); 00095 #elif MACOS 00096 char* buffer = NULL; 00097 char* newbuf = NULL; 00098 uint32_t buflen = 256; 00099 00100 buffer = reinterpret_cast<char*>(malloc(buflen * sizeof(char))); 00101 if (buffer) { 00102 if (_NSGetExecutablePath(buffer, &buflen) == 0) { 00103 path = buffer; 00104 } else { 00105 newbuf = reinterpret_cast<char*>(realloc(buffer, buflen * sizeof(char))); 00106 if (newbuf) { 00107 buffer = newbuf; 00108 if (_NSGetExecutablePath(buffer, &buflen) == 0) { 00109 path = buffer; 00110 } 00111 } 00112 } 00113 } 00114 00115 free(buffer); 00116 #else 00117 // functionality not supported on this (unknown) platform 00118 #endif 00119 return path::normpath(path); 00120 } 00121 00122 // --------------------------------------------------------------------------- 00123 string exename() 00124 { 00125 string exec_path = exepath(); 00126 if (exec_path.empty()) return ""; 00127 #if WINDOWS 00128 string head, ext; 00129 path::splitext(exec_path, head, ext); 00130 if (ext == ".exe" || ext == ".com") exec_path = head; 00131 #endif 00132 return path::basename(exec_path); 00133 } 00134 00135 // --------------------------------------------------------------------------- 00136 string exedir() 00137 { 00138 string path = exepath(); 00139 return path.empty() ? "" : path::dirname(path); 00140 } 00141 00142 // --------------------------------------------------------------------------- 00143 string readlink(const string& path) 00144 { 00145 string value; 00146 #if UNIX 00147 char* buffer = NULL; 00148 char* newbuf = NULL; 00149 size_t buflen = 256; 00150 for (;;) { 00151 newbuf = reinterpret_cast<char*>(realloc(buffer, buflen * sizeof(char))); 00152 if (!newbuf) break; 00153 buffer = newbuf; 00154 int n = ::readlink(path.c_str(), buffer, buflen); 00155 if (n < 0) break; 00156 if (static_cast<size_t>(n) < buflen) { 00157 buffer[n] = '\0'; 00158 value = buffer; 00159 break; 00160 } 00161 buflen += 256; 00162 } 00163 free(buffer); 00164 #endif 00165 return value; 00166 } 00167 00168 // --------------------------------------------------------------------------- 00169 // common implementation of mkdir() and makedirs() 00170 static inline bool makedir(const string& path, bool parent) 00171 { 00172 if (path.empty()) return true; // cwd already exists 00173 if (path::isfile(path)) return false; 00174 vector<string> dirs; 00175 string dir(path); 00176 if (parent) { 00177 while (!dir.empty() && !path::exists(dir)) { 00178 dirs.push_back(dir); 00179 dir = path::dirname(dir); 00180 } 00181 } else if (!path::exists(dir)) { 00182 dirs.push_back(dir); 00183 } 00184 for (vector<string>::reverse_iterator it = dirs.rbegin(); it != dirs.rend(); ++it) { 00185 #if WINDOWS 00186 if (CreateDirectory(it->c_str(), NULL) == FALSE) return false; 00187 #else 00188 if (::mkdir(it->c_str(), 0755) != 0) return false; 00189 #endif 00190 } 00191 return true; 00192 } 00193 00194 // --------------------------------------------------------------------------- 00195 bool mkdir(const string& path) 00196 { 00197 return makedir(path, false); 00198 } 00199 00200 // --------------------------------------------------------------------------- 00201 bool makedirs(const string& path) 00202 { 00203 return makedir(path, true); 00204 } 00205 00206 // --------------------------------------------------------------------------- 00207 // common implementation of rmdir() and rmtree() 00208 static inline bool removedir(const string& path, bool recursive) 00209 { 00210 // remove files and subdirectories - recursive implementation 00211 if (recursive && !emptydir(path)) return false; 00212 // remove this directory 00213 #if WINDOWS 00214 return (::SetFileAttributes(path.c_str(), FILE_ATTRIBUTE_NORMAL) == TRUE) && 00215 (::RemoveDirectory(path.c_str()) == TRUE); 00216 #else 00217 return ::rmdir(path.c_str()) == 0; 00218 #endif 00219 } 00220 00221 // --------------------------------------------------------------------------- 00222 bool rmdir(const string& path) 00223 { 00224 return removedir(path, false); 00225 } 00226 00227 // --------------------------------------------------------------------------- 00228 bool rmtree(const string& path) 00229 { 00230 return removedir(path, true); 00231 } 00232 00233 // --------------------------------------------------------------------------- 00234 bool emptydir(const string& path) 00235 { 00236 bool ok = true; 00237 string subpath; // either subdirectory or file path 00238 00239 #if WINDOWS 00240 WIN32_FIND_DATA info; 00241 HANDLE hFile = ::FindFirstFile(path::join(path, "*.*").c_str(), &info); 00242 if (hFile != INVALID_HANDLE_VALUE) { 00243 do { 00244 // skip '.' and '..' 00245 if (strncmp(info.cFileName, ".", 2) == 0 || strncmp(info.cFileName, "..", 3) == 0) { 00246 continue; 00247 } 00248 // remove subdirectory or file, respectively 00249 subpath = path::join(path, info.cFileName); 00250 if(info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { 00251 if (!removedir(subpath, true)) ok = false; 00252 } else { 00253 if (::SetFileAttributes(subpath.c_str(), FILE_ATTRIBUTE_NORMAL) == FALSE || 00254 ::DeleteFile(subpath.c_str()) == FALSE) ok = false; 00255 } 00256 } while (::FindNextFile(hFile, &info) == TRUE); 00257 ::FindClose(hFile); 00258 } 00259 #else 00260 struct dirent *p = NULL; 00261 DIR *d = opendir(path.c_str()); 00262 if (d != NULL) { 00263 while ((p = readdir(d)) != NULL) { 00264 // skip '.' and '..' 00265 if (strncmp(p->d_name, ".", 2) == 0 || strncmp(p->d_name, "..", 3) == 0) { 00266 continue; 00267 } 00268 // remove subdirectory or file, respectively 00269 subpath = path::join(path, p->d_name); 00270 if (path::isdir(subpath)) { 00271 if (!rmtree(subpath)) ok = false; 00272 } else { 00273 if (unlink(subpath.c_str()) != 0) ok = false; 00274 } 00275 } 00276 closedir(d); 00277 } 00278 #endif 00279 return ok; 00280 } 00281 00282 00283 } // namespace os 00284 00285 } // namespace basis