• Main Page
  • Related Pages
  • Modules
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

src/Directory.cpp

00001 /*
00002  *   This file is part of the Standard Portable Library (SPL).
00003  *
00004  *   SPL is free software: you can redistribute it and/or modify
00005  *   it under the terms of the GNU General Public License as published by
00006  *   the Free Software Foundation, either version 3 of the License, or
00007  *   (at your option) any later version.
00008  *
00009  *   SPL is distributed in the hope that it will be useful,
00010  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  *   GNU General Public License for more details.
00013  *
00014  *   You should have received a copy of the GNU General Public License
00015  *   along with SPL.  If not, see <http://www.gnu.org/licenses/>.
00016  */
00017 #if defined(_WIN32) || defined(_WIN64)
00018 #include <spl/configwin32.h>
00019 #include <spl/cleanwindows.h>
00020 #else
00021 #include <spl/autoconf/config.h>
00022 #endif
00023 
00024 #ifdef HAVE_SYS_TYPES_H
00025 #include <sys/types.h>
00026 #endif
00027 
00028 #include <spl/Environment.h>
00029 #include <spl/io/Directory.h>
00030 #include <spl/io/File.h>
00031 #include <spl/io/WinPerm.h>
00032 
00033 #include <stdio.h>
00034 
00035 #ifdef HAVE_FCNTL_H
00036 #include <fcntl.h>
00037 #endif
00038 #ifdef HAVE_SYS_TYPES_H
00039 #include <sys/types.h>
00040 #endif
00041 #ifdef HAVE_IO_H
00042 #include <io.h>
00043 #endif
00044 #ifdef HAVE_DIRECT_H
00045 #include <direct.h>
00046 #endif
00047 #ifdef HAVE_DIRENT_H
00048 #include <dirent.h>
00049 #endif
00050 #ifdef HAVE_SYS_STAT_H
00051 #include <sys/stat.h>
00052 #endif
00053 #ifdef HAVE_UNISTD_H
00054 #include <unistd.h>
00055 #endif
00056 #ifdef HAVE_SYS_STAT_H
00057 #include <sys/stat.h>
00058 #endif
00059 
00060 #ifdef WIN32
00061 char Directory::m_seperator = '\\';
00062 #include <spl/cleanwindows.h>
00063 #else
00064 char Directory::m_seperator = '/';
00065 #endif
00066 
00067 #ifdef WIN32
00068 extern bool EncodePermissions(const Permissions& perm, _WinPerms &wperm);
00069 #else
00070 extern void EncodePermissions(const Permissions& perm, mode_t& mode);
00071 #endif
00072 
00073 Vector<StringPtr> Directory::ListFiles(const String& directory, const String& filter)
00074 {
00075         Vector<StringPtr> list;
00076 
00077 #ifdef WIN32
00078     struct _finddata_t c_file;
00079 
00080 #if _MSC_VER >= 1400
00081     intptr_t hFile;
00082 #else
00083     long hFile;
00084 #endif
00085 
00086         char odir[512];
00087 
00088         _getcwd(odir, 512);
00089 
00090         if ( 0 != _chdir(directory.GetChars()) )
00091         {
00092                 return list;
00093         }
00094 
00095     /* Find first .c file in current directory */
00096     if( (hFile = _findfirst( filter.GetChars(), &c_file )) == -1L )
00097         {
00098                 return list;
00099         }
00100 
00101         list.Add( StringPtr(new String(c_file.name)) );
00102         while( _findnext( hFile, &c_file ) == 0 )
00103         {
00104                 list.Add( StringPtr(new String(c_file.name)) );
00105         }
00106         _findclose( hFile );
00107 
00108         if (0 != _chdir(odir))
00109         {
00110                 throw new IOException("Cannot change directory to " + String(odir));
00111         }
00112 
00113 #else
00114 
00115         DIR *dp;
00116         struct dirent *ep;
00117 
00118         dp = opendir (directory.GetChars());
00119         if (dp != NULL)
00120         {
00121                 while (ep = readdir (dp))
00122                 {
00123                         list.Add( StringPtr(new String(ep->d_name)) );
00124                 }
00125                 closedir (dp);
00126         }
00127 
00128 #endif
00129         return list;
00130 }
00131 
00132 void Directory::ChangeWorkingDirectory(const String& directory)
00133 {
00134 #ifdef WIN32
00135         if ( 0 != _chdir(directory.GetChars()) )
00136         {
00137                 throw new InvalidArgumentException(Environment::LastErrorMessage());
00138         }
00139 #else
00140         if ( 0 != chdir(directory.GetChars()) )
00141         {
00142                 throw new InvalidArgumentException(Environment::LastErrorMessage());
00143         }
00144 #endif
00145 }
00146 
00147 StringPtr Directory::GetWorkingDirectory()
00148 {
00149         char workingDir[512];
00150 
00151 #ifdef _WINDOWS
00152         return StringPtr(new String(_getcwd(workingDir, 512)));
00153 #else
00154         return StringPtr(new String(getcwd(workingDir, 512)));
00155 #endif
00156 }
00157 
00158 Directory::Directory(const String& directory)
00159 : m_raw(directory), m_parts()
00160 {
00161         char sep[2];
00162         sep[0] = m_seperator;
00163         sep[1] = '\0';
00164         m_parts = m_raw.Split(sep);
00165         if (m_parts->Count() > 0)
00166         {
00167                 StringPtr fileName = m_parts->ElementAt(m_parts->Count() - 1);
00168                 if (fileName->Length() == 0 || File::Exists(fileName))
00169                 {
00170                         m_parts->RemoveAt(m_parts->Count() - 1);
00171                 }
00172         }
00173 }
00174 
00175 Directory::~Directory()
00176 {
00177 }
00178 
00179 Directory::Directory( const Directory& dir )
00180 : m_raw(), m_parts()
00181 {
00182         *this = dir;
00183 }
00184 
00185 Directory& Directory::operator =(const Directory& dir)
00186 {
00187         m_parts->Clear();
00188 
00189         char sep[2];
00190         sep[0] = m_seperator;
00191         sep[1] = '\0';
00192         m_raw = dir.m_raw;
00193         m_parts = dir.m_parts;
00194 
00195         return *this;
00196 }
00197 
00198 Directory Directory::Parent() const
00199 {
00200         StringBuffer buf(m_raw.Length());
00201         for (int x = 0; x < m_parts->Count() - 1; x++)
00202         {
00203                 buf.Append(m_parts->ElementAt(x));
00204                 buf.Append(Directory::SeperatorChar());
00205         }
00206 
00207         return Directory(buf.ToString());
00208 }
00209 
00210 int32 Directory::HashCode() const
00211 {
00212         return m_raw.HashCode();
00213 }
00214 
00215 bool Directory::Equals( const IComparable& a ) const
00216 {
00217         if (a.MajicNumber() != MajicNumber())
00218         {
00219                 return false;
00220         }
00221         const Directory& dir = static_cast<const Directory &>(a);
00222         return m_raw.Equals( dir.m_raw );
00223 }
00224 
00225 int Directory::Compare( const IComparable& a ) const
00226 {
00227         if (a.MajicNumber() != MajicNumber())
00228         {
00229                 return 1;
00230         }
00231         const Directory& dir = static_cast<const Directory &>(a);
00232         return m_raw.Compare( dir.m_raw );
00233 }
00234 
00235 int32 Directory::MajicNumber() const
00236 {
00237         return 0x00F1;
00238 }
00239 
00240 StringPtr Directory::RemoveTrailingSeperator(const String& path)
00241 {
00242         if (path.CharAt(path.Length() - 1) == m_seperator)
00243         {
00244                 return path.Substring(0, path.Length() - 1);
00245         }
00246         return StringPtr(new String(path));
00247 }
00248 
00249 StringPtr Directory::ToString() const
00250 {
00251         StringBuffer buf(m_raw.Length());
00252 
00253         for (int x = 0; x < m_parts->Count(); x++)
00254         {
00255                 buf.Append(m_parts->ElementAt(x));
00256                 buf.Append(Directory::SeperatorChar());
00257         }
00258 
00259         return buf.ToString();
00260 }
00261 
00262 bool Directory::IsDirectory(const String &path)
00263 {
00264 #ifdef _WINDOWS
00265 
00266         struct _stat stbuf;
00267 
00268         if (_stat(RemoveTrailingSeperator(path)->GetChars(), &stbuf) != 0)
00269         {
00270                 return false;
00271         }
00272 
00273         return (stbuf.st_mode & _S_IFDIR) != 0;
00274 
00275 #else
00276 
00277         struct stat stbuf;
00278 
00279         if(stat(path.GetChars(), &stbuf) != 0)
00280         {
00281                 return false;
00282         }
00283         return S_ISDIR(stbuf.st_mode);
00284 
00285 #endif
00286 }
00287 
00288 void Directory::Delete(const String& path)
00289 {
00290 #ifdef WIN32
00291 
00292         if(::RemoveDirectory(RemoveTrailingSeperator(path)->GetChars()) != TRUE)
00293         {
00294                 throw new IOException(Environment::LastErrorMessage());
00295         }
00296 
00297 #else
00298 
00299         if(::rmdir(path.GetChars()) != 0)
00300         {
00301                 throw new IOException(Environment::LastErrorMessage());
00302         }
00303 
00304 #endif
00305 }
00306 
00307 void Directory::Rename(const String& oldname, const String& newname)
00308 {
00309         if (rename(oldname.GetChars(), newname.GetChars()) != 0)
00310         {
00311                 throw new IOException(Environment::LastErrorMessage());
00312         }
00313 }
00314 
00315 void Directory::Create(const String& path, const Permissions& perm)
00316 {
00317         if(path.Length() < 1)
00318         {
00319                 throw new InvalidArgumentException("Path is required");
00320         }
00321 
00322 #ifdef _WINDOWS
00323 
00324         SECURITY_ATTRIBUTES sa;
00325         _WinPerms wperm;
00326 
00327         EncodePermissions(perm, wperm);
00328 
00329         sa.nLength = sizeof(SECURITY_ATTRIBUTES);
00330         sa.lpSecurityDescriptor = wperm.pdesc;
00331         sa.bInheritHandle = FALSE;
00332 
00333         if (::CreateDirectory(RemoveTrailingSeperator(path)->GetChars(), &sa) != TRUE)
00334         {
00335                 throw new IOException(Environment::LastErrorMessage());
00336         }
00337 
00338 #else
00339 
00340         mode_t mode;
00341         EncodePermissions(perm, mode);
00342 
00343         if(::mkdir(path.GetChars(), mode) != 0)
00344         {
00345                 throw new IOException(Environment::LastErrorMessage());
00346         }
00347 
00348 #endif
00349 }
00350 
00351 #ifdef DEBUG
00352 void Directory::ValidateMem() const
00353 {
00354         m_raw.ValidateMem();
00355         m_parts.ValidateMem();
00356 }
00357 
00358 void Directory::CheckMem() const
00359 {
00360         m_raw.ValidateMem();
00361         m_parts.CheckMem();
00362 }
00363 #endif