core/vul/vul_file.cxx
Go to the documentation of this file.
00001 // This is core/vul/vul_file.cxx
00002 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00003 #pragma implementation
00004 #endif
00005 //:
00006 // \file
00007 //
00008 // \author Andrew W. Fitzgibbon, Oxford RRG
00009 // \date   02 Nov 1998
00010 //
00011 // \verbatim
00012 //  Modifications
00013 //   08 Jan 2009  Peter Vanroose- simplified "delete_file_glob()" implementation
00014 // \endverbatim
00015 //
00016 //-----------------------------------------------------------------------------
00017 
00018 #include "vul_file.h"
00019 
00020 #include <sys/stat.h>
00021 #include <vcl_cstring.h>
00022 #include <vcl_cctype.h>
00023 #include <vcl_cstdlib.h>
00024 
00025 #if defined(VCL_WIN32) && !defined(__CYGWIN__)
00026 #include <direct.h> // for getcwd, mkdir
00027 #if defined(VCL_VC_8)
00028 #define getcwd _getcwd // getcwd is now "deprecated" by Visual Studio
00029 #define chdir  _chdir  // idem
00030 #define mkdir  _mkdir  // idem
00031 #endif
00032 #else
00033 #include <unistd.h>
00034 #endif
00035 
00036 #if defined(como4301) && defined(__linux__)
00037 # ifndef S_IFMT
00038 #  define S_IFMT 0170000
00039 # endif
00040 # ifndef S_IFDIR
00041 #  define S_IFDIR 0040000
00042 # endif
00043 #endif
00044 
00045 #include <vul/vul_user_info.h>
00046 
00047 vcl_string vul_file::get_cwd()
00048 {
00049   const int BIG = 65536;
00050   char buf[BIG];
00051   getcwd(buf,BIG-1);
00052   return buf;
00053 }
00054 
00055 bool vul_file::change_directory(char const* dirname)
00056 {
00057   return 0 == chdir(dirname);
00058 }
00059 
00060 bool vul_file::make_directory(char const* name)
00061 {
00062 #if defined(VCL_WIN32) && !defined(__CYGWIN__)
00063   return -1 != mkdir(name);
00064 #else
00065   return -1 != mkdir(name, 0755);
00066 #endif
00067 }
00068 
00069 bool vul_file::is_directory(char const* fn)
00070 {
00071   struct stat fs;
00072   return stat(fn, &fs) == 0
00073       && (fs.st_mode & S_IFMT) == S_IFDIR;
00074 }
00075 
00076 #if defined(VCL_WIN32) && !defined(__CYGWIN__)
00077 bool vul_file::is_drive(char const* fn)
00078 {
00079   // a drive string looks like "c:", "z:"
00080   return fn
00081       && vcl_isalpha(fn[0])
00082       && fn[1]==':'
00083       && fn[2]=='\0';
00084 }
00085 #endif
00086 
00087 //: Make a writable directory, including any necessary parents.
00088 // Returns true if successful, or if the directory already exists.
00089 // Implemented by calling itself recursively on the parent directory.
00090 bool vul_file::make_directory_path(char const* filename)
00091 {
00092 #if defined(VCL_WIN32) && !defined(__CYGWIN__)
00093   if (is_directory(filename) || is_drive(filename)) return true;
00094 #else
00095   if (is_directory(filename)) return true;
00096 #endif
00097   return make_directory_path(dirname(filename))
00098       && make_directory(filename);
00099 }
00100 
00101 
00102 unsigned long vul_file::size(char const* fn)
00103 {
00104   struct stat fs;
00105   if (stat(fn, &fs) == 0)
00106     return fs.st_size;
00107   else
00108     return 0L;
00109 }
00110 
00111 bool vul_file::exists(char const* fn)
00112 {
00113   struct stat fs;
00114   return stat(fn, &fs) == 0;
00115 }
00116 
00117 vcl_string vul_file::dirname(char const* fn)
00118 {
00119   vcl_string self(fn);
00120 
00121 #if defined(VCL_WIN32) && !defined(__CYGWIN__)
00122   vcl_string::size_type slash_index = self.find_last_of("\\/");
00123 #else
00124   vcl_string::size_type slash_index = self.rfind('/');
00125 #endif
00126   if (slash_index == vcl_string::npos)
00127     return ".";
00128 
00129 
00130   return self.substr(0, slash_index);
00131 }
00132 
00133 vcl_string vul_file::extension(char const* fn)
00134 {
00135   vcl_string self(fn);
00136 
00137   vcl_string::size_type dot_index = self.rfind('.');
00138   if (dot_index != vcl_string::npos)
00139     return self.substr(dot_index, vcl_string::npos);
00140   else
00141     return vcl_string();
00142 }
00143 
00144 vcl_string vul_file::strip_directory(char const* fn)
00145 {
00146    vcl_string self(fn);
00147 
00148 #if defined(VCL_WIN32) && !defined(__CYGWIN__)
00149    vcl_string::size_type slash_index = self.find_last_of("\\/");
00150 #else
00151    vcl_string::size_type slash_index = self.rfind('/');
00152 #endif
00153    if (slash_index != vcl_string::npos)
00154      self.erase(0, slash_index+1);
00155 
00156    return self;
00157 }
00158 
00159 vcl_string vul_file::strip_extension(char const* fn)
00160 {
00161   vcl_string self(fn);
00162 
00163   vcl_string::size_type dot_index = self.rfind('.');
00164   if (dot_index != vcl_string::npos)
00165     self.erase(dot_index, vcl_string::npos);
00166 
00167   return self;
00168 }
00169 
00170 vcl_string vul_file::basename(char const* fn, char const * suffix)
00171 {
00172   // First strip dir
00173   vcl_string self(fn);
00174 
00175 #if defined(VCL_WIN32) && !defined(__CYGWIN__)
00176   vcl_string::size_type slash_index = self.find_last_of("\\/");
00177 #else
00178   vcl_string::size_type slash_index = self.rfind('/');
00179 #endif
00180 
00181   if (slash_index != vcl_string::npos)
00182     self.erase(0, slash_index+1);
00183 
00184   // Now strip suffix if any
00185   if (suffix) {
00186     int start = self.size() - vcl_strlen(suffix);
00187     if (start >= 0)
00188       // egcs, 2.95, 2.96 have no method which can do
00189       //   self.compare(start, vcl_string::npos, suffix) == 0
00190       if (vcl_string(self.begin()+start, self.end()) == suffix)
00191         self.erase(start, vcl_string::npos);
00192   }
00193   return self;
00194 }
00195 
00196 
00197 #if defined(VCL_WIN32) && !defined(__CYGWIN__)
00198 //: replace instances of 'from' in 's' with 'to'
00199 static unsigned replace(char from, char to, vcl_string &s)
00200 {
00201   unsigned c = 0;
00202   for (unsigned i=0; i<s.size(); ++i)
00203     if (s[i] == from)
00204     {
00205       c++;
00206       s[i] = to;
00207     }
00208     return c;
00209 }
00210 #endif
00211 
00212 //: Delete 1 or more files using the Local OS preferred globbing.
00213 // E.g. \c delete_file_glob("*"); will delete all the files in the
00214 // current directory on most operating systems.
00215 // Takes Posix path separators i.e. '/'
00216 bool vul_file::delete_file_glob(vcl_string const& file_glob)
00217 {
00218 #if defined(VCL_WIN32) && !defined(__CYGWIN__)
00219   vcl_string command = "del " + file_glob;
00220   replace('/', '\\', command);
00221 #else
00222   vcl_string command = "/bin/rm -f " + file_glob;
00223 #endif
00224   return vcl_system(command.c_str())==0;
00225 }
00226 
00227 
00228 vcl_string vul_file::expand_tilde(char const* vul_filename)
00229 {
00230   if (!vul_filename || (vcl_strlen(vul_filename) == 0))
00231     return "";
00232 
00233 #if defined(VCL_WIN32) && !defined(__CYGWIN__)
00234   // ~ meaningless on win32
00235   return vcl_string(vul_filename);
00236 #else
00237 
00238   if (vul_filename[0] != '~')
00239     return vcl_string(vul_filename);
00240 
00241   //// ** Have a tilde, go for it
00242 
00243   // 1. Strip to directory only, and remove the tilde itself
00244   vcl_string fn(vul_filename);
00245   vcl_string dir;
00246   vcl_string::size_type first_slash =  fn.find('/');
00247   if (first_slash != vcl_string::npos) {
00248     dir = fn.substr(1, first_slash-1);
00249     fn = fn.substr(first_slash, vcl_string::npos);
00250   } else {
00251     dir = fn.substr(1, vcl_string::npos);
00252     fn = "";
00253   }
00254   // Now, from original to  (dir, vul_filename) is one of
00255   //  ~            ""     ""
00256   //  ~fre         "fre"  ""
00257   //  ~/fred       ""     "/fred"
00258   //  ~user/fred   "user" "/fred"
00259 
00260   if (dir.size() == 0) {
00261     // Was just ~, use getenv(HOME)
00262     char const * home_directory = getenv("HOME");
00263     if (!home_directory) home_directory = "";
00264     return vcl_string(home_directory) + fn;
00265   }
00266 
00267   // Was ~user, Check password list for match
00268   vul_user_info user(dir);
00269   if (!user.ok)
00270     return vcl_string(vul_filename);
00271 
00272   // Got user info
00273   return user.home_directory + fn;
00274 #endif
00275 }
00276 
00277 
00278 #if defined(VCL_WIN32) && VXL_USE_WIN_WCHAR_T
00279 #  include <vcl_cwchar.h>
00280 
00281 std::wstring
00282 vul_file::get_cwd(wchar_t* /*dummy*/)
00283 {
00284   const int BIG = 65536;
00285   wchar_t buf[BIG];
00286   buf[0] = L'\0';
00287   _wgetcwd(buf,BIG-1);
00288   return buf;
00289 }
00290 
00291 bool vul_file::change_directory(wchar_t const* dirname)
00292 {
00293   return 0 == _wchdir(dirname);
00294 }
00295 
00296 bool vul_file::make_directory(wchar_t const* name)
00297 {
00298   return -1 != _wmkdir(name);
00299 }
00300 
00301 bool vul_file::is_directory(wchar_t const* fn)
00302 {
00303   struct _stat fs;
00304   return _wstat(fn, &fs) == 0
00305       && (fs.st_mode & S_IFMT) == S_IFDIR;
00306 }
00307 
00308 bool vul_file::is_drive(wchar_t const* fn)
00309 {
00310   // a drive string looks like "c:", "z:"
00311   return fn
00312       && iswalpha(fn[0])
00313       && fn[1]==L':'
00314       && fn[2]==L'\0';
00315 }
00316 
00317 //: Make a writable directory, including any necessary parents.
00318 // Returns true if successful, or if the directory alredy exists.
00319 bool vul_file::make_directory_path(wchar_t const* filename)
00320 {
00321   if (is_directory(filename) || is_drive(filename)) return true;
00322 
00323   return make_directory_path(dirname(filename))
00324       && make_directory(filename);
00325 }
00326 
00327 bool vul_file::exists(wchar_t const* fn)
00328 {
00329   struct _stat fs;
00330   return _wstat(fn, &fs) == 0;
00331 }
00332 
00333 std::wstring vul_file::dirname(wchar_t const* fn)
00334 {
00335   std::wstring self(fn);
00336 
00337   std::wstring::size_type slash_index = self.find_last_of(L"\\/");
00338   if (slash_index == std::wstring::npos)
00339     return L".";
00340 
00341   return self.substr(0, slash_index);
00342 }
00343 
00344 std::wstring vul_file::extension(wchar_t const* fn)
00345 {
00346   std::wstring self(fn);
00347 
00348   std::wstring::size_type dot_index = self.rfind(L'.');
00349   if (dot_index != std::wstring::npos)
00350     return self.substr(dot_index, std::wstring::npos);
00351   else
00352     return std::wstring();
00353 }
00354 
00355 std::wstring vul_file::strip_directory(wchar_t const* fn)
00356 {
00357    std::wstring self(fn);
00358 
00359    std::wstring::size_type slash_index = self.find_last_of(L"\\/");
00360    if (slash_index != std::wstring::npos)
00361      self.erase(0, slash_index+1);
00362 
00363    return self;
00364 }
00365 
00366 std::wstring vul_file::strip_extension(wchar_t const* fn)
00367 {
00368   std::wstring self(fn);
00369 
00370   std::wstring::size_type dot_index = self.rfind(L'.');
00371   if (dot_index != std::wstring::npos)
00372     self.erase(dot_index, std::wstring::npos);
00373 
00374   return self;
00375 }
00376 
00377 std::wstring vul_file::basename(wchar_t const* fn, wchar_t const * suffix)
00378 {
00379   // First strip dir
00380   std::wstring self(fn);
00381 
00382   std::wstring::size_type slash_index = self.find_last_of(L"\\/");
00383 
00384   if (slash_index != std::wstring::npos)
00385     self.erase(0, slash_index+1);
00386 
00387   // Now strip suffix if any
00388   if (suffix) {
00389     int start = (int)self.size() - (int)wcslen(suffix);
00390     if (start >= 0)
00391       // egcs, 2.95, 2.96 have no method which can do
00392       //   self.compare(start, std::wstring::npos, suffix) == 0
00393       if (std::wstring(self.begin()+start, self.end()) == suffix)
00394         self.erase(start, std::wstring::npos);
00395   }
00396   return self;
00397 }
00398 
00399 #endif
00400