X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/088a36424c40d28296e80969095fa8f335b4def9..f5ef4d69b7fd4fb89203cd3cf9dd1e42fda7831f:/src/common/filename.cpp diff --git a/src/common/filename.cpp b/src/common/filename.cpp index 8a713ba7a4..bc4b31b23f 100644 --- a/src/common/filename.cpp +++ b/src/common/filename.cpp @@ -33,7 +33,7 @@ http://msdn.microsoft.com/en-us/library/aa365248(VS.85).aspx. - wxPATH_MAC: Mac OS 8/9 and Mac OS X under CodeWarrior 7 format, absolute file + wxPATH_MAC: Mac OS 8/9 only, not used any longer, absolute file names have the form volume:dir1:...:dirN:filename and the relative file names are either @@ -77,7 +77,7 @@ #endif #ifndef WX_PRECOMP - #ifdef __WXMSW__ + #ifdef __WINDOWS__ #include "wx/msw/wrapwin.h" // For GetShort/LongPathName #endif #include "wx/dynarray.h" @@ -98,7 +98,7 @@ #include "wx/msw/gccpriv.h" #endif -#ifdef __WXMSW__ +#ifdef __WINDOWS__ #include "wx/msw/private.h" #endif @@ -118,19 +118,6 @@ #include #endif -#ifdef __MWERKS__ -#ifdef __MACH__ -#include -#include -#include -#include -#else -#include -#include -#include -#endif -#endif - #ifdef __WATCOMC__ #include #include @@ -148,18 +135,17 @@ #define MAX_PATH _MAX_PATH #endif +#ifndef S_ISREG + #define S_ISREG(mode) ((mode) & S_IFREG) +#endif +#ifndef S_ISDIR + #define S_ISDIR(mode) ((mode) & S_IFDIR) +#endif #if wxUSE_LONGLONG extern const wxULongLong wxInvalidSize = (unsigned)-1; #endif // wxUSE_LONGLONG -#ifdef __WIN32__ - // this define is missing from VC6 headers - #ifndef INVALID_FILE_ATTRIBUTES - #define INVALID_FILE_ATTRIBUTES ((DWORD)-1) - #endif -#endif // __WIN32__ - namespace { @@ -188,7 +174,7 @@ public: // access time (see #10567) m_hFile = ::CreateFile ( - filename.fn_str(), // name + filename.t_str(), // name mode == ReadAttr ? FILE_READ_ATTRIBUTES // access mask : FILE_WRITE_ATTRIBUTES, FILE_SHARE_READ | // sharing mode @@ -600,98 +586,143 @@ wxFileName wxFileName::DirName(const wxString& dir, wxPathFormat format) // existence tests // ---------------------------------------------------------------------------- -bool wxFileName::FileExists() const +namespace { - return wxFileName::FileExists( GetFullPath() ); -} -/* static */ -bool wxFileName::FileExists( const wxString &filePath ) +// Flags for wxFileSystemObjectExists() asking it to check for: +enum { -#if defined(__WXPALMOS__) - return false; -#elif defined(__WIN32__) && !defined(__WXMICROWIN__) - // we must use GetFileAttributes() instead of the ANSI C functions because - // it can cope with network (UNC) paths unlike them - DWORD ret = ::GetFileAttributes(filePath.fn_str()); - - return (ret != INVALID_FILE_ATTRIBUTES) && !(ret & FILE_ATTRIBUTE_DIRECTORY); -#else // !__WIN32__ - #ifndef S_ISREG - #define S_ISREG(mode) ((mode) & S_IFREG) - #endif - wxStructStat st; + wxFileSystemObject_File = 1, // file existence + wxFileSystemObject_Dir = 2, // directory existence + wxFileSystemObject_Other = 4, // existence of something else, e.g. + // device, socket, FIFO under Unix + wxFileSystemObject_Any = 7 // existence of anything at all +}; - return (wxStat( filePath, &st) == 0 && S_ISREG(st.st_mode)) -#ifdef __OS2__ - || (errno == EACCES) // if access is denied something with that name - // exists and is opened in exclusive mode. -#endif - ; -#endif // __WIN32__/!__WIN32__ -} +#if defined(__WINDOWS__) && !defined(__WXMICROWIN__) -bool wxFileName::DirExists() const +void RemoveTrailingSeparatorsFromPath(wxString& strPath) { - return wxFileName::DirExists( GetPath() ); -} - -/* static */ -bool wxFileName::DirExists( const wxString &dirPath ) -{ - wxString strPath(dirPath); - -#if defined(__WINDOWS__) || defined(__OS2__) // Windows fails to find directory named "c:\dir\" even if "c:\dir" exists, // so remove all trailing backslashes from the path - but don't do this for // the paths "d:\" (which are different from "d:"), for just "\" or for // windows unique volume names ("\\?\Volume{GUID}\") - while ( wxEndsWithPathSeparator(strPath) ) + while ( wxEndsWithPathSeparator( strPath ) ) { size_t len = strPath.length(); if ( len == 1 || (len == 3 && strPath[len - 2] == wxT(':')) || - (len == wxMSWUniqueVolumePrefixLength && - wxFileName::IsMSWUniqueVolumeNamePath(strPath))) + (len == wxMSWUniqueVolumePrefixLength && + wxFileName::IsMSWUniqueVolumeNamePath(strPath))) { break; } strPath.Truncate(len - 1); } -#endif // __WINDOWS__ +} + +#endif // __WINDOWS__ || __OS2__ + +bool wxFileSystemObjectExists(const wxString& path, int flags) +{ + // Should the existence of file/directory with this name be accepted, i.e. + // result in the true return value from this function? + const bool acceptFile = (flags & wxFileSystemObject_File) != 0; + const bool acceptDir = (flags & wxFileSystemObject_Dir) != 0; + + wxString strPath(path); + +#if defined(__WINDOWS__) && !defined(__WXMICROWIN__) + if ( acceptDir ) + { + // Ensure that the path doesn't have any trailing separators when + // checking for directories. + RemoveTrailingSeparatorsFromPath(strPath); + } -#ifdef __OS2__ - // OS/2 can't handle "d:", it wants either "d:\" or "d:." - if (strPath.length() == 2 && strPath[1u] == wxT(':')) - strPath << wxT('.'); -#endif + // we must use GetFileAttributes() instead of the ANSI C functions because + // it can cope with network (UNC) paths unlike them + DWORD ret = ::GetFileAttributes(path.t_str()); -#if defined(__WXPALMOS__) - return false; -#elif defined(__WIN32__) && !defined(__WXMICROWIN__) - // stat() can't cope with network paths - DWORD ret = ::GetFileAttributes(strPath.fn_str()); + if ( ret == INVALID_FILE_ATTRIBUTES ) + return false; + + if ( ret & FILE_ATTRIBUTE_DIRECTORY ) + return acceptDir; - return (ret != INVALID_FILE_ATTRIBUTES) && (ret & FILE_ATTRIBUTE_DIRECTORY); + // Anything else must be a file (perhaps we should check for + // FILE_ATTRIBUTE_REPARSE_POINT?) + return acceptFile; #elif defined(__OS2__) + if ( acceptDir ) + { + // OS/2 can't handle "d:", it wants either "d:\" or "d:." + if (strPath.length() == 2 && strPath[1u] == wxT(':')) + strPath << wxT('.'); + } + FILESTATUS3 Info = {{0}}; APIRET rc = ::DosQueryPathInfo((PSZ)(WXSTRINGCAST strPath), FIL_STANDARD, - (void*) &Info, sizeof(FILESTATUS3)); + (void*) &Info, sizeof(FILESTATUS3)); + + if ( rc == NO_ERROR ) + { + if ( Info.attrFile & FILE_DIRECTORY ) + return acceptDir; + else + return acceptFile; + } - return ((rc == NO_ERROR) && (Info.attrFile & FILE_DIRECTORY)) || - (rc == ERROR_SHARING_VIOLATION); - // If we got a sharing violation, there must be something with this name. -#else // !__WIN32__ + // We consider that the path must exist if we get a sharing violation for + // it but we don't know what is it in this case. + if ( rc == ERROR_SHARING_VIOLATION ) + return flags & wxFileSystemObject_Other; + // Any other error (usually ERROR_PATH_NOT_FOUND), means there is nothing + // there. + return false; +#else // Non-MSW, non-OS/2 wxStructStat st; -#ifndef __VISAGECPP__ - return wxStat(strPath, &st) == 0 && ((st.st_mode & S_IFMT) == S_IFDIR); -#else - // S_IFMT not supported in VA compilers.. st_mode is a 2byte value only - return wxStat(strPath, &st) == 0 && (st.st_mode == S_IFDIR); -#endif + if ( wxStat(strPath, &st) != 0 ) + return false; + + if ( S_ISREG(st.st_mode) ) + return acceptFile; + if ( S_ISDIR(st.st_mode) ) + return acceptDir; + + return flags & wxFileSystemObject_Other; +#endif // Platforms +} + +} // anonymous namespace -#endif // __WIN32__/!__WIN32__ +bool wxFileName::FileExists() const +{ + return wxFileName::FileExists( GetFullPath() ); +} + +/* static */ +bool wxFileName::FileExists( const wxString &filePath ) +{ + return wxFileSystemObjectExists(filePath, wxFileSystemObject_File); +} + +bool wxFileName::DirExists() const +{ + return wxFileName::DirExists( GetPath() ); +} + +/* static */ +bool wxFileName::DirExists( const wxString &dirPath ) +{ + return wxFileSystemObjectExists(dirPath, wxFileSystemObject_Dir); +} + +/* static */ +bool wxFileName::Exists(const wxString& path) +{ + return wxFileSystemObjectExists(path, wxFileSystemObject_Any); } // ---------------------------------------------------------------------------- @@ -816,7 +847,7 @@ static bool wxTempOpen(wxFFile *file, const wxString& path, bool *deleteOnClose) int fd = wxTempOpen(path, deleteOnClose); if (fd == -1) return false; - file->Attach(wx_fdopen(fd, "w+b")); + file->Attach(wx_fdopen(fd, "w+b"), path); return file->IsOpened(); #endif // wx_fdopen } @@ -876,8 +907,8 @@ static wxString wxCreateTempImpl( } #elif defined(__WINDOWS__) && !defined(__WXMICROWIN__) - if ( !::GetTempFileName(dir.fn_str(), name.fn_str(), 0, - wxStringBuffer(path, MAX_PATH + 1)) ) + if (!::GetTempFileName(dir.t_str(), name.t_str(), 0, + wxStringBuffer(path, MAX_PATH + 1))) { wxLogLastError(wxT("GetTempFileName")); @@ -927,7 +958,7 @@ static wxString wxCreateTempImpl( if ( ffileTemp ) { #ifdef wx_fdopen - ffileTemp->Attach(wx_fdopen(fdTemp, "r+b")); + ffileTemp->Attach(wx_fdopen(fdTemp, "r+b"), path); #else ffileTemp->Open(path, wxT("r+b")); close(fdTemp); @@ -957,7 +988,7 @@ static wxString wxCreateTempImpl( } #else // !HAVE_MKTEMP (includes __DOS__) // generate the unique file name ourselves - #if !defined(__DOS__) && !defined(__PALMOS__) && (!defined(__MWERKS__) || defined(__DARWIN__) ) + #if !defined(__DOS__) path << (unsigned int)getpid(); #endif @@ -1274,7 +1305,7 @@ bool wxFileName::Rmdir(int flags) const bool wxFileName::Rmdir(const wxString& dir, int flags) { -#ifdef __WXMSW__ +#ifdef __WINDOWS__ if ( flags & wxPATH_RMDIR_RECURSIVE ) { // SHFileOperation needs double null termination string @@ -1287,7 +1318,11 @@ bool wxFileName::Rmdir(const wxString& dir, int flags) SHFILEOPSTRUCT fileop; wxZeroMemory(fileop); fileop.wFunc = FO_DELETE; + #if defined(__CYGWIN__) && defined(wxUSE_UNICODE) + fileop.pFrom = path.wc_str(); + #else fileop.pFrom = path.fn_str(); + #endif fileop.fFlags = FOF_SILENT | FOF_NOCONFIRMATION; #ifndef __WXWINCE__ // FOF_NOERRORUI is not defined in WinCE @@ -1306,9 +1341,9 @@ bool wxFileName::Rmdir(const wxString& dir, int flags) return true; } else if ( flags & wxPATH_RMDIR_FULL ) -#else // !__WXMSW__ +#else // !__WINDOWS__ if ( flags != 0 ) // wxPATH_RMDIR_FULL or wxPATH_RMDIR_RECURSIVE -#endif // !__WXMSW__ +#endif // !__WINDOWS__ { wxString path(dir); if ( path.Last() != wxFILE_SEP_PATH ) @@ -1329,7 +1364,7 @@ bool wxFileName::Rmdir(const wxString& dir, int flags) cont = d.GetNext(&filename); } -#ifndef __WXMSW__ +#ifndef __WINDOWS__ if ( flags & wxPATH_RMDIR_RECURSIVE ) { // delete all files too @@ -1340,7 +1375,7 @@ bool wxFileName::Rmdir(const wxString& dir, int flags) cont = d.GetNext(&filename); } } -#endif // !__WXMSW__ +#endif // !__WINDOWS__ } return ::wxRmdir(dir); @@ -1451,15 +1486,24 @@ bool wxFileName::Normalize(int flags, if ( dir == wxT("..") ) { - if ( m_dirs.IsEmpty() ) + if ( m_dirs.empty() ) { - wxLogError(_("The path '%s' contains too many \"..\"!"), - GetFullPath().c_str()); - return false; - } + // We have more ".." than directory components so far. + // Don't treat this as an error as the path could have been + // entered by user so try to handle it reasonably: if the + // path is absolute, just ignore the extra ".." because + // "/.." is the same as "/". Otherwise, i.e. for relative + // paths, keep ".." unchanged because removing it would + // modify the file a relative path refers to. + if ( !m_relative ) + continue; - m_dirs.RemoveAt(m_dirs.GetCount() - 1); - continue; + } + else // Normal case, go one step up. + { + m_dirs.pop_back(); + continue; + } } } @@ -1737,8 +1781,16 @@ bool wxFileName::SameAs(const wxFileName& filepath, wxPathFormat format) const if ( fn1.GetFullPath() == fn2.GetFullPath() ) return true; - // TODO: compare inodes for Unix, this works even when filenames are - // different but files are the same (symlinks) (VZ) +#if defined(__UNIX__) + wxStructStat st1, st2; + if ( wxStat(fn1.GetFullPath(), &st1) == 0 && + wxStat(fn2.GetFullPath(), &st2) == 0 ) + { + if ( st1.st_ino == st2.st_ino && st1.st_dev == st2.st_dev ) + return true; + } + //else: It's not an error if one or both files don't exist. +#endif // defined __UNIX__ return false; } @@ -2057,14 +2109,14 @@ wxString wxFileName::GetShortPath() const { wxString path(GetFullPath()); -#if defined(__WXMSW__) && defined(__WIN32__) && !defined(__WXMICROWIN__) && !defined(__WXWINCE__) - DWORD sz = ::GetShortPathName(path.fn_str(), NULL, 0); +#if defined(__WINDOWS__) && defined(__WIN32__) && !defined(__WXMICROWIN__) && !defined(__WXWINCE__) + DWORD sz = ::GetShortPathName(path.t_str(), NULL, 0); if ( sz != 0 ) { wxString pathOut; if ( ::GetShortPathName ( - path.fn_str(), + path.t_str(), wxStringBuffer(pathOut, sz), sz ) != 0 ) @@ -2122,12 +2174,12 @@ wxString wxFileName::GetLongPath() const if ( s_pfnGetLongPathName ) { - DWORD dwSize = (*s_pfnGetLongPathName)(path.fn_str(), NULL, 0); + DWORD dwSize = (*s_pfnGetLongPathName)(path.t_str(), NULL, 0); if ( dwSize > 0 ) { if ( (*s_pfnGetLongPathName) ( - path.fn_str(), + path.t_str(), wxStringBuffer(pathOut, dwSize), dwSize ) != 0 ) @@ -2179,7 +2231,7 @@ wxString wxFileName::GetLongPath() const continue; } - hFind = ::FindFirstFile(tmpPath.fn_str(), &findFileData); + hFind = ::FindFirstFile(tmpPath.t_str(), &findFileData); if (hFind == INVALID_HANDLE_VALUE) { // Error: most likely reason is that path doesn't exist, so @@ -2207,7 +2259,7 @@ wxPathFormat wxFileName::GetFormat( wxPathFormat format ) { if (format == wxPATH_NATIVE) { -#if defined(__WXMSW__) || defined(__OS2__) || defined(__DOS__) +#if defined(__WINDOWS__) || defined(__OS2__) || defined(__DOS__) format = wxPATH_DOS; #elif defined(__VMS) format = wxPATH_VMS; @@ -2601,12 +2653,14 @@ bool wxFileName::GetTimes(wxDateTime *dtAccess, wxStructStat stBuf; if ( wxStat( GetFullPath(), &stBuf) == 0 ) { + // Android defines st_*time fields as unsigned long, but time_t as long, + // hence the static_casts. if ( dtAccess ) - dtAccess->Set(stBuf.st_atime); + dtAccess->Set(static_cast(stBuf.st_atime)); if ( dtMod ) - dtMod->Set(stBuf.st_mtime); + dtMod->Set(static_cast(stBuf.st_mtime)); if ( dtCreate ) - dtCreate->Set(stBuf.st_ctime); + dtCreate->Set(static_cast(stBuf.st_ctime)); return true; } @@ -2637,10 +2691,7 @@ wxULongLong wxFileName::GetSize(const wxString &filename) if (!wxFileExists(filename)) return wxInvalidSize; -#if defined(__WXPALMOS__) - // TODO - return wxInvalidSize; -#elif defined(__WIN32__) +#if defined(__WIN32__) wxFileHandle f(filename, wxFileHandle::ReadAttr); if (!f.IsOk()) return wxInvalidSize;