X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/8d7d6deac6086ebdd1a985518e3c4ab27ece7530..f369c7c2841c0534424f2c184783c1a2070012cf:/src/common/filename.cpp diff --git a/src/common/filename.cpp b/src/common/filename.cpp index 98af00ab43..d781b78685 100644 --- a/src/common/filename.cpp +++ b/src/common/filename.cpp @@ -75,6 +75,7 @@ #include "wx/intl.h" #include "wx/log.h" #include "wx/utils.h" + #include "wx/crt.h" #endif #include "wx/filename.h" @@ -92,7 +93,7 @@ #endif #if defined(__WXMAC__) - #include "wx/mac/private.h" // includes mac headers + #include "wx/osx/private.h" // includes mac headers #endif // utime() is POSIX so should normally be available on all Unices @@ -138,7 +139,9 @@ #endif -wxULongLong wxInvalidSize = (unsigned)-1; +#if wxUSE_LONGLONG +extern const wxULongLong wxInvalidSize = (unsigned)-1; +#endif // wxUSE_LONGLONG // ---------------------------------------------------------------------------- @@ -162,7 +165,7 @@ public: { m_hFile = ::CreateFile ( - filename, // name + filename.fn_str(), // name mode == Read ? GENERIC_READ // access mask : GENERIC_WRITE, FILE_SHARE_READ | // sharing mode @@ -175,9 +178,12 @@ public: if ( m_hFile == INVALID_HANDLE_VALUE ) { - wxLogSysError(_("Failed to open '%s' for %s"), - filename.c_str(), - mode == Read ? _("reading") : _("writing")); + if ( mode == Read ) + wxLogSysError(_("Failed to open '%s' for reading"), + filename.c_str()); + else + wxLogSysError(_("Failed to open '%s' for writing"), + filename.c_str()); } } @@ -284,6 +290,17 @@ static wxString wxGetVolumeString(const wxString& volume, wxPathFormat format) return path; } +// return true if the format used is the DOS/Windows one and the string looks +// like a UNC path +static bool IsUNCPath(const wxString& path, wxPathFormat format) +{ + return format == wxPATH_DOS && + path.length() >= 4 && // "\\a" can't be a UNC path + path[0u] == wxFILE_SEP_PATH_DOS && + path[1u] == wxFILE_SEP_PATH_DOS && + path[2u] != wxFILE_SEP_PATH_DOS; +} + // ============================================================================ // implementation // ============================================================================ @@ -307,9 +324,28 @@ void wxFileName::Assign(const wxString& volume, const wxString& name, const wxString& ext, bool hasExt, - wxPathFormat format ) + wxPathFormat format) { - SetPath( path, format ); + // we should ignore paths which look like UNC shares because we already + // have the volume here and the UNC notation (\\server\path) is only valid + // for paths which don't start with a volume, so prevent SetPath() from + // recognizing "\\foo\bar" in "c:\\foo\bar" as an UNC path + // + // note also that this is a rather ugly way to do what we want (passing + // some kind of flag telling to ignore UNC paths to SetPath() would be + // better) but this is the safest thing to do to avoid breaking backwards + // compatibility in 2.8 + if ( IsUNCPath(path, format) ) + { + // remove one of the 2 leading backslashes to ensure that it's not + // recognized as an UNC path by SetPath() + wxString pathNonUNC(path, 1, wxString::npos); + SetPath(pathNonUNC, format); + } + else // no UNC complications + { + SetPath(path, format); + } m_volume = volume; m_ext = ext; @@ -427,7 +463,7 @@ void wxFileName::Assign(const wxString& fullpathOrig, // always recognize fullpath as directory, even if it doesn't end with a // slash wxString fullpath = fullpathOrig; - if ( !wxEndsWithPathSeparator(fullpath) ) + if ( !fullpath.empty() && !wxEndsWithPathSeparator(fullpath) ) { fullpath += GetPathSeparator(format); } @@ -616,10 +652,10 @@ static int wxOpenWithDeleteOnClose(const wxString& filename) DWORD attributes = FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE; - HANDLE h = ::CreateFile(filename, access, 0, NULL, + HANDLE h = ::CreateFile(filename.fn_str(), access, 0, NULL, disposition, attributes, NULL); - return wxOpenOSFHandle(h, 0); + return wxOpenOSFHandle(h, wxO_BINARY); } #endif // wxOpenOSFHandle @@ -649,7 +685,7 @@ static bool wxTempOpen(wxFFile *file, const wxString& path, bool *deleteOnClose) return file->Open(path, _T("w+b")); #else // wx_fdopen int fd = wxTempOpen(path, deleteOnClose); - if (fd != -1) + if (fd == -1) return false; file->Attach(wx_fdopen(fd, "w+b")); return file->IsOpened(); @@ -711,7 +747,8 @@ static wxString wxCreateTempImpl( } #elif defined(__WINDOWS__) && !defined(__WXMICROWIN__) - if ( !::GetTempFileName(dir, name, 0, wxStringBuffer(path, MAX_PATH + 1)) ) + if ( !::GetTempFileName(dir.fn_str(), name.fn_str(), 0, + wxStringBuffer(path, MAX_PATH + 1)) ) { wxLogLastError(_T("GetTempFileName")); @@ -734,7 +771,7 @@ static wxString wxCreateTempImpl( path += _T("XXXXXX"); // we need to copy the path to the buffer in which mkstemp() can modify it - wxCharBuffer buf( wxConvFile.cWX2MB( path ) ); + wxCharBuffer buf(path.fn_str()); // cast is safe because the string length doesn't change int fdTemp = mkstemp( (char*)(const char*) buf ); @@ -1031,7 +1068,7 @@ wxString wxFileName::GetTempDir() // default #if defined(__DOS__) || defined(__OS2__) dir = _T("."); -#elif defined(__WXMAC__) +#elif defined(__WXMAC__) && !defined(__WXOSX_IPHONE__) dir = wxMacFindFolder(short(kOnSystemDisk), kTemporaryFolderType, kCreateFolder); #else dir = _T("/tmp"); @@ -1065,14 +1102,7 @@ bool wxFileName::Mkdir( const wxString& dir, int perm, int flags ) size_t count = dirs.GetCount(); for ( size_t i = 0; i < count; i++ ) { - if ( i > 0 || -#if defined(__WXMAC__) && !defined(__DARWIN__) - // relative pathnames are exactely the other way round under mac... - !filename.IsAbsolute() -#else - filename.IsAbsolute() -#endif - ) + if ( i > 0 || filename.IsAbsolute() ) currPath += wxFILE_SEP_PATH; currPath += dirs[i]; @@ -1131,7 +1161,7 @@ bool wxFileName::Normalize(int flags, format = GetFormat(format); - // make the path absolute + // set up the directory to use for making the path absolute later if ( (flags & wxPATH_NORM_ABSOLUTE) && !IsAbsolute(format) ) { if ( cwd.empty() ) @@ -1142,20 +1172,6 @@ bool wxFileName::Normalize(int flags, { curDir.AssignDir(cwd); } - - // the path may be not absolute because it doesn't have the volume name - // but in this case we shouldn't modify the directory components of it - // but just set the current volume - if ( !HasVolume() && curDir.HasVolume() ) - { - SetVolume(curDir.GetVolume()); - - if ( !m_relative ) - { - // yes, it was the case - we don't need curDir then - curDir.Clear(); - } - } } // handle ~ stuff under Unix only @@ -1166,8 +1182,18 @@ bool wxFileName::Normalize(int flags, wxString dir = dirs[0u]; if ( !dir.empty() && dir[0u] == _T('~') ) { + // to make the path absolute use the home directory curDir.AssignDir(wxGetUserHome(dir.c_str() + 1)); + // if we are expanding the tilde, then this path + // *should* be already relative (since we checked for + // the tilde only in the first char of the first dir); + // if m_relative==false, it's because it was initialized + // from a string which started with /~; in that case + // we reach this point but then need m_relative=true + // for relative->absolute expansion later + m_relative = true; + dirs.RemoveAt(0u); } } @@ -1176,14 +1202,34 @@ bool wxFileName::Normalize(int flags, // transform relative path into abs one if ( curDir.IsOk() ) { - wxArrayString dirsNew = curDir.GetDirs(); - size_t count = dirs.GetCount(); - for ( size_t n = 0; n < count; n++ ) + // this path may be relative because it doesn't have the volume name + // and still have m_relative=true; in this case we shouldn't modify + // our directory components but just set the current volume + if ( !HasVolume() && curDir.HasVolume() ) { - dirsNew.Add(dirs[n]); + SetVolume(curDir.GetVolume()); + + if ( !m_relative ) + { + // yes, it was the case - we don't need curDir then + curDir.Clear(); + } } - dirs = dirsNew; + // finally, prepend curDir to the dirs array + wxArrayString dirsNew = curDir.GetDirs(); + WX_PREPEND_ARRAY(dirs, dirsNew); + + // if we used e.g. tilde expansion previously and wxGetUserHome didn't + // return for some reason an absolute path, then curDir maybe not be absolute! + if ( curDir.IsAbsolute(format) ) + { + // we have prepended an absolute path and thus we are now an absolute + // file name too + m_relative = false; + } + // else if (flags & wxPATH_NORM_ABSOLUTE): + // should we warn the user that we didn't manage to make the path absolute? } // now deal with ".", ".." and the rest @@ -1215,11 +1261,6 @@ bool wxFileName::Normalize(int flags, } } - if ( (flags & wxPATH_NORM_CASE) && !IsCaseSensitive(format) ) - { - dir.MakeLower(); - } - m_dirs.Add(dir); } @@ -1229,37 +1270,34 @@ bool wxFileName::Normalize(int flags, wxString filename; if (GetShortcutTarget(GetFullPath(format), filename)) { - // Repeat this since we may now have a new path - if ( (flags & wxPATH_NORM_CASE) && !IsCaseSensitive(format) ) - { - filename.MakeLower(); - } m_relative = false; Assign(filename); } } #endif - if ( (flags & wxPATH_NORM_CASE) && !IsCaseSensitive(format) ) +#if defined(__WIN32__) + if ( (flags & wxPATH_NORM_LONG) && (format == wxPATH_DOS) ) { - // VZ: expand env vars here too? + Assign(GetLongPath()); + } +#endif // Win32 + // Change case (this should be kept at the end of the function, to ensure + // that the path doesn't change any more after we normalize its case) + if ( (flags & wxPATH_NORM_CASE) && !IsCaseSensitive(format) ) + { m_volume.MakeLower(); m_name.MakeLower(); m_ext.MakeLower(); - } - // we do have the path now - // - // NB: need to do this before (maybe) calling Assign() below - m_relative = false; - -#if defined(__WIN32__) - if ( (flags & wxPATH_NORM_LONG) && (format == wxPATH_DOS) ) - { - Assign(GetLongPath()); + // directory entries must be made lower case as well + count = m_dirs.GetCount(); + for ( size_t i = 0; i < count; i++ ) + { + m_dirs[i].MakeLower(); + } } -#endif // Win32 return true; } @@ -1757,13 +1795,13 @@ wxString wxFileName::GetShortPath() const wxString path(GetFullPath()); #if defined(__WXMSW__) && defined(__WIN32__) && !defined(__WXMICROWIN__) && !defined(__WXWINCE__) - DWORD sz = ::GetShortPathName(path, NULL, 0); + DWORD sz = ::GetShortPathName(path.fn_str(), NULL, 0); if ( sz != 0 ) { wxString pathOut; if ( ::GetShortPathName ( - path, + path.fn_str(), wxStringBuffer(pathOut, sz), sz ) != 0 ) @@ -1782,9 +1820,9 @@ wxString wxFileName::GetLongPath() const wxString pathOut, path = GetFullPath(); -#if defined(__WIN32__) && !defined(__WXMICROWIN__) +#if defined(__WIN32__) && !defined(__WXWINCE__) && !defined(__WXMICROWIN__) -#if wxUSE_DYNAMIC_LOADER +#if wxUSE_DYNLIB_CLASS typedef DWORD (WINAPI *GET_LONG_PATH_NAME)(const wxChar *, wxChar *, DWORD); // this is MT-safe as in the worst case we're going to resolve the function @@ -1821,12 +1859,12 @@ wxString wxFileName::GetLongPath() const if ( s_pfnGetLongPathName ) { - DWORD dwSize = (*s_pfnGetLongPathName)(path, NULL, 0); + DWORD dwSize = (*s_pfnGetLongPathName)(path.fn_str(), NULL, 0); if ( dwSize > 0 ) { if ( (*s_pfnGetLongPathName) ( - path, + path.fn_str(), wxStringBuffer(pathOut, dwSize), dwSize ) != 0 ) @@ -1835,7 +1873,7 @@ wxString wxFileName::GetLongPath() const } } } -#endif // wxUSE_DYNAMIC_LOADER +#endif // wxUSE_DYNLIB_CLASS // The OS didn't support GetLongPathName, or some other error. // We need to call FindFirstFile on each component in turn. @@ -1876,7 +1914,7 @@ wxString wxFileName::GetLongPath() const continue; } - hFind = ::FindFirstFile(tmpPath, &findFileData); + hFind = ::FindFirstFile(tmpPath.fn_str(), &findFileData); if (hFind == INVALID_HANDLE_VALUE) { // Error: most likely reason is that path doesn't exist, so @@ -1906,8 +1944,6 @@ wxPathFormat wxFileName::GetFormat( wxPathFormat format ) { #if defined(__WXMSW__) || defined(__OS2__) || defined(__DOS__) format = wxPATH_DOS; -#elif defined(__WXMAC__) && !defined(__DARWIN__) - format = wxPATH_MAC; #elif defined(__VMS) format = wxPATH_VMS; #else @@ -1933,23 +1969,18 @@ wxFileName::SplitVolume(const wxString& fullpathWithVolume, wxString fullpath = fullpathWithVolume; // special Windows UNC paths hack: transform \\share\path into share:path - if ( format == wxPATH_DOS ) + if ( IsUNCPath(fullpath, format) ) { - if ( fullpath.length() >= 4 && - fullpath[0u] == wxFILE_SEP_PATH_DOS && - fullpath[1u] == wxFILE_SEP_PATH_DOS ) - { - fullpath.erase(0, 2); + fullpath.erase(0, 2); - size_t posFirstSlash = - fullpath.find_first_of(GetPathTerminators(format)); - if ( posFirstSlash != wxString::npos ) - { - fullpath[posFirstSlash] = wxFILE_SEP_DSK; + size_t posFirstSlash = + fullpath.find_first_of(GetPathTerminators(format)); + if ( posFirstSlash != wxString::npos ) + { + fullpath[posFirstSlash] = wxFILE_SEP_DSK; - // UNC paths are always absolute, right? (FIXME) - fullpath.insert(posFirstSlash + 1, 1, wxFILE_SEP_PATH_DOS); - } + // UNC paths are always absolute, right? (FIXME) + fullpath.insert(posFirstSlash + 1, 1, wxFILE_SEP_PATH_DOS); } } @@ -2244,6 +2275,7 @@ bool wxFileName::GetTimes(wxDateTime *dtAccess, return true; } #elif defined(__UNIX_LIKE__) || defined(__WXMAC__) || defined(__OS2__) || (defined(__DOS__) && defined(__WATCOMC__)) + // no need to test for IsDir() here wxStructStat stBuf; if ( wxStat( GetFullPath().c_str(), &stBuf) == 0 ) { @@ -2275,6 +2307,8 @@ bool wxFileName::GetTimes(wxDateTime *dtAccess, // file size functions // ---------------------------------------------------------------------------- +#if wxUSE_LONGLONG + /* static */ wxULongLong wxFileName::GetSize(const wxString &filename) { @@ -2291,14 +2325,11 @@ wxULongLong wxFileName::GetSize(const wxString &filename) DWORD lpFileSizeHigh; DWORD ret = GetFileSize(f, &lpFileSizeHigh); - if (ret == INVALID_FILE_SIZE) + if ( ret == INVALID_FILE_SIZE && ::GetLastError() != NO_ERROR ) return wxInvalidSize; - // compose the low-order and high-order byte sizes - return wxULongLong(ret | (lpFileSizeHigh << sizeof(WORD)*2)); - -#else // ! __WIN32__ - + return wxULongLong(lpFileSizeHigh, ret); +#else // ! __WIN32__ wxStructStat st; #ifndef wxNEED_WX_UNISTD_H if (wxStat( filename.fn_str() , &st) != 0) @@ -2346,12 +2377,13 @@ wxString wxFileName::GetHumanReadableSize(const wxString &failmsg, int precision return GetHumanReadableSize(GetSize(), failmsg, precision); } +#endif // wxUSE_LONGLONG // ---------------------------------------------------------------------------- // Mac-specific functions // ---------------------------------------------------------------------------- -#ifdef __WXMAC__ +#if defined( __WXMAC__ ) && !defined( __WXOSX_IPHONE__ ) const short kMacExtensionMaxLength = 16 ; class MacDefaultExtensionRecord