X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/94268cae217d847157eebc3b1815f19395060661..091e74e76b63f04a4058995c5dcc6f5b8b6db362:/src/common/filefn.cpp?ds=sidebyside diff --git a/src/common/filefn.cpp b/src/common/filefn.cpp index bdfd37b1a7..636e3d9aac 100644 --- a/src/common/filefn.cpp +++ b/src/common/filefn.cpp @@ -152,11 +152,49 @@ WXDLLEXPORT int wxOpen( const wxChar *pathname, int flags, mode_t mode ) #endif // wxNEED_WX_UNISTD_H +#if wxUSE_UNICODE && defined __BORLANDC__ \ + && __BORLANDC__ >= 0x550 && __BORLANDC__ <= 0x551 + +// BCC 5.5 and 5.5.1 have a bug in _wopen where files are created read only +// regardless of the mode parameter. This hack works around the problem by +// setting the mode with _wchmod. +// +int wxOpen(const wchar_t *pathname, int flags, mode_t mode) +{ + int moreflags = 0; + + // we only want to fix the mode when the file is actually created, so + // when creating first try doing it O_EXCL so we can tell if the file + // was already there. + if ((flags & O_CREAT) && !(flags & O_EXCL) && (mode & wxS_IWUSR) != 0) + moreflags = O_EXCL; + + int fd = _wopen(pathname, flags | moreflags, mode); + + // the file was actually created and needs fixing + if (fd != -1 && (flags & O_CREAT) != 0 && (mode & wxS_IWUSR) != 0) + { + close(fd); + _wchmod(pathname, mode); + fd = _wopen(pathname, flags & ~(O_EXCL | O_CREAT)); + } + // the open failed, but it may have been because the added O_EXCL stopped + // the opening of an existing file, so try again without. + else if (fd == -1 && moreflags != 0) + { + fd = _wopen(pathname, flags & ~O_CREAT); + } + + return fd; +} + +#endif + // ---------------------------------------------------------------------------- // wxPathList // ---------------------------------------------------------------------------- -void wxPathList::Add(const wxString& path) +bool wxPathList::Add(const wxString& path) { // add a path separator to force wxFileName to interpret it always as a directory // (i.e. if we are called with '/home/user' we want to consider it a folder and @@ -164,11 +202,17 @@ void wxPathList::Add(const wxString& path) wxFileName fn(path + wxFileName::GetPathSeparator()); // add only normalized relative/absolute paths - fn.Normalize(wxPATH_NORM_DOTS|wxPATH_NORM_TILDE|wxPATH_NORM_LONG|wxPATH_NORM_ENV_VARS); + // NB: we won't do wxPATH_NORM_DOTS in order to avoid problems when trying to + // normalize paths which starts with ".." (which can be normalized only if + // we use also wxPATH_NORM_ABSOLUTE - which we don't want to use). + if (!fn.Normalize(wxPATH_NORM_TILDE|wxPATH_NORM_LONG|wxPATH_NORM_ENV_VARS)) + return false; wxString toadd = fn.GetPath(); if (Index(toadd) == wxNOT_FOUND) wxArrayString::Add(toadd); // do not add duplicates + + return true; } void wxPathList::Add(const wxArrayString &arr) @@ -207,21 +251,17 @@ void wxPathList::AddEnvList (const wxString& WXUNUSED_IN_WINCE(envVariable)) // Given a full filename (with path), ensure that that file can // be accessed again USING FILENAME ONLY by adding the path // to the list if not already there. -void wxPathList::EnsureFileAccessible (const wxString& path) +bool wxPathList::EnsureFileAccessible (const wxString& path) { - wxString path_only(wxPathOnly(path)); - if ( !path_only.empty() ) - { - if ( Index(path_only) == wxNOT_FOUND ) - Add(path_only); - } + return Add(wxPathOnly(path)); } -// deprecated ! +#if WXWIN_COMPATIBILITY_2_6 bool wxPathList::Member (const wxString& path) const { return Index(path) != wxNOT_FOUND; } +#endif wxString wxPathList::FindValidPath (const wxString& file) const { @@ -230,8 +270,13 @@ wxString wxPathList::FindValidPath (const wxString& file) const wxFileName fn(file); wxString strend; - // NB: normalize without making absolute ! - fn.Normalize(wxPATH_NORM_DOTS|wxPATH_NORM_TILDE|wxPATH_NORM_LONG|wxPATH_NORM_ENV_VARS); + // NB: normalize without making absolute otherwise calling this function with + // e.g. "b/c.txt" would result in removing the directory 'b' and the for loop + // below would only add to the paths of this list the 'c.txt' part when doing + // the existence checks... + // NB: we don't use wxPATH_NORM_DOTS here, too (see wxPathList::Add for more info) + if (!fn.Normalize(wxPATH_NORM_TILDE|wxPATH_NORM_LONG|wxPATH_NORM_ENV_VARS)) + return wxEmptyString; wxASSERT_MSG(!fn.IsDir(), wxT("Cannot search for directories; only for files")); if (fn.IsAbsolute()) @@ -1013,6 +1058,51 @@ wxConcatFiles (const wxString& file1, const wxString& file2, const wxString& fil #endif } +// helper of generic implementation of wxCopyFile() +#if !(defined(__WIN32__) || defined(__OS2__) || defined(__PALMOS__)) && \ + wxUSE_FILE + +static bool +wxDoCopyFile(wxFile& fileIn, + const wxStructStat& fbuf, + const wxString& filenameDst, + bool overwrite) +{ + // reset the umask as we want to create the file with exactly the same + // permissions as the original one + wxCHANGE_UMASK(0); + + // create file2 with the same permissions than file1 and open it for + // writing + + wxFile fileOut; + if ( !fileOut.Create(filenameDst, overwrite, fbuf.st_mode & 0777) ) + return false; + + // copy contents of file1 to file2 + char buf[4096]; + for ( ;; ) + { + ssize_t count = fileIn.Read(buf, WXSIZEOF(buf)); + if ( count == wxInvalidOffset ) + return false; + + // end of file? + if ( !count ) + break; + + if ( fileOut.Write(buf, count) < (size_t)count ) + return false; + } + + // we can expect fileIn to be closed successfully, but we should ensure + // that fileOut was closed as some write errors (disk full) might not be + // detected before doing this + return fileIn.Close() && fileOut.Close(); +} + +#endif // generic implementation of wxCopyFile + // Copy files bool wxCopyFile (const wxString& file1, const wxString& file2, bool overwrite) @@ -1030,7 +1120,7 @@ wxCopyFile (const wxString& file1, const wxString& file2, bool overwrite) return false; } #elif defined(__OS2__) - if ( ::DosCopy((PSZ)file1.c_str(), (PSZ)file2.c_str(), overwrite ? DCPY_EXISTING : 0) != 0 ) + if ( ::DosCopy(file1.c_str(), file2.c_str(), overwrite ? DCPY_EXISTING : 0) != 0 ) return false; #elif defined(__PALMOS__) // TODO with http://www.palmos.com/dev/support/docs/protein_books/Memory_Databases_Files/ @@ -1062,39 +1152,49 @@ wxCopyFile (const wxString& file1, const wxString& file2, bool overwrite) return false; } - // reset the umask as we want to create the file with exactly the same - // permissions as the original one - wxCHANGE_UMASK(0); - - // create file2 with the same permissions than file1 and open it for - // writing + wxDoCopyFile(fileIn, fbuf, file2, overwrite); - wxFile fileOut; - if ( !fileOut.Create(file2, overwrite, fbuf.st_mode & 0777) ) - return false; +#if defined(__WXMAC__) || defined(__WXCOCOA__) + // copy the resource fork of the file too if it's present + wxString pathRsrcOut; + wxFile fileRsrcIn; - // copy contents of file1 to file2 - char buf[4096]; - size_t count; - for ( ;; ) { - count = fileIn.Read(buf, WXSIZEOF(buf)); - if ( fileIn.Error() ) - return false; + // suppress error messages from this block as resource forks don't have + // to exist + wxLogNull noLog; + + // it's not enough to check for file existence: it always does on HFS + // but is empty for files without resources + if ( fileRsrcIn.Open(file1 + wxT("/..namedfork/rsrc")) && + fileRsrcIn.Length() > 0 ) + { + // we must be using HFS or another filesystem with resource fork + // support, suppose that destination file system also is HFS[-like] + pathRsrcOut = file2 + wxT("/..namedfork/rsrc"); + } + else // check if we have resource fork in separate file (non-HFS case) + { + wxFileName fnRsrc(file1); + fnRsrc.SetName(wxT("._") + fnRsrc.GetName()); - // end of file? - if ( !count ) - break; + fileRsrcIn.Close(); + if ( fileRsrcIn.Open( fnRsrc.GetFullPath() ) ) + { + fnRsrc = file2; + fnRsrc.SetName(wxT("._") + fnRsrc.GetName()); - if ( fileOut.Write(buf, count) < count ) - return false; + pathRsrcOut = fnRsrc.GetFullPath(); + } + } } - // we can expect fileIn to be closed successfully, but we should ensure - // that fileOut was closed as some write errors (disk full) might not be - // detected before doing this - if ( !fileIn.Close() || !fileOut.Close() ) - return false; + if ( !pathRsrcOut.empty() ) + { + if ( !wxDoCopyFile(fileRsrcIn, fbuf, pathRsrcOut, overwrite) ) + return false; + } +#endif // wxMac || wxCocoa #if !defined(__VISAGECPP__) && !defined(__WXMAC__) || defined(__UNIX__) // no chmod in VA. Should be some permission API for HPFS386 partitions @@ -1223,9 +1323,9 @@ bool wxRmdir(const wxString& dir, int WXUNUSED(flags)) #if defined(__VMS__) return false; //to be changed since rmdir exists in VMS7.x #elif defined(__OS2__) - return (::DosDeleteDir((PSZ)dir.c_str()) == 0); + return (::DosDeleteDir(dir.c_str()) == 0); #elif defined(__WXWINCE__) - return (CreateDirectory(dir, NULL) != 0); + return (RemoveDirectory(dir) != 0); #elif defined(__WXPALMOS__) // TODO with VFSFileRename() return false; @@ -1235,9 +1335,9 @@ bool wxRmdir(const wxString& dir, int WXUNUSED(flags)) } // does the path exists? (may have or not '/' or '\\' at the end) -bool wxDirExists(const wxChar *pszPathName) +bool wxDirExists(const wxString& pathName) { - wxString strPath(pszPathName); + wxString strPath(pathName); #if defined(__WINDOWS__) || defined(__OS2__) // Windows fails to find directory named "c:\dir\" even if "c:\dir" exists, @@ -1281,7 +1381,7 @@ bool wxDirExists(const wxChar *pszPathName) return wxStat(strPath.c_str(), &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(pszPathName, &st) == 0 && (st.st_mode == S_IFDIR); + return wxStat(strPath.c_str(), &st) == 0 && (st.st_mode == S_IFDIR); #endif #endif // __WIN32__/!__WIN32__ @@ -1530,7 +1630,15 @@ wxString wxGetCwd() bool wxSetWorkingDirectory(const wxString& d) { #if defined(__OS2__) - return (::DosSetCurrentDir((PSZ)d.c_str()) == 0); + if (d[1] == ':') + { + ::DosSetDefaultDisk(1 + wxToupper(d[0]) - _T('A')); + // do not call DosSetCurrentDir when just changing drive, + // since it requires e.g. "d:." instead of "d:"! + if (d.length() == 2) + return true; + } + return (::DosSetCurrentDir(d.c_str()) == 0); #elif defined(__UNIX__) || defined(__WXMAC__) || defined(__DOS__) return (chdir(wxFNSTRINGCAST d.fn_str()) == 0); #elif defined(__WINDOWS__) @@ -1772,7 +1880,7 @@ int WXDLLEXPORT wxParseCommonDialogsFilter(const wxString& filterStr, return filters.GetCount(); } -#if defined( __WINDOWS__ ) +#if defined(__WINDOWS__) && !(defined(__UNIX__) || defined(__OS2__)) static bool wxCheckWin32Permission(const wxString& path, DWORD access) { // quoting the MSDN: "To obtain a handle to a directory, call the @@ -1911,7 +2019,7 @@ wxFileKind wxGetFileKind(FILE *fp) #if defined(wxFILEKIND_STUB) || wxONLY_WATCOM_EARLIER_THAN(1,4) (void)fp; return wxFILE_KIND_DISK; -#elif defined(__WINDOWS__) && !defined(__CYGWIN__) && !defined(__WATCOMC__) +#elif defined(__WINDOWS__) && !defined(__CYGWIN__) && !defined(__WATCOMC__) && !defined(__WINE__) return fp ? wxGetFileKind(_fileno(fp)) : wxFILE_KIND_UNKNOWN; #else return fp ? wxGetFileKind(fileno(fp)) : wxFILE_KIND_UNKNOWN;