From 0597e7f977c87d107e24bf3e95ebfa3d60efc249 Mon Sep 17 00:00:00 2001
From: Vadim Zeitlin <vadim@wxwidgets.org>
Date: Sat, 7 Apr 2007 18:23:57 +0000
Subject: [PATCH] add support for resources forks in wxCopyFile() (modified
 patch 1620336)

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@45308 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
---
 docs/changes.txt           |   1 +
 docs/latex/wx/function.tex |   6 ++-
 src/common/filefn.cpp      | 108 ++++++++++++++++++++++++++++---------
 3 files changed, 87 insertions(+), 28 deletions(-)

diff --git a/docs/changes.txt b/docs/changes.txt
index 564cb53174..d9141a11c5 100644
--- a/docs/changes.txt
+++ b/docs/changes.txt
@@ -117,6 +117,7 @@ wxMac:
 
 - Fix duplicate (empty) help menu in non-English programs (Andreas Jacobs)
 - Allow accelerators to be used with buttons too (Ryan Wilcox)
+- Support resource forks in wxCopyFile() (Hank Schultz)
 
 wxMSW:
 
diff --git a/docs/latex/wx/function.tex b/docs/latex/wx/function.tex
index 30bb2dd121..c6db80094d 100644
--- a/docs/latex/wx/function.tex
+++ b/docs/latex/wx/function.tex
@@ -1178,10 +1178,12 @@ true if successful.
 \func{bool}{wxCopyFile}{\param{const wxString\& }{file1}, \param{const wxString\& }{file2}, \param{bool }{overwrite = true}}
 
 Copies {\it file1} to {\it file2}, returning true if successful. If
-{\it overwrite} parameter is true (default), the destination file is overwritten
-if it exists, but if {\it overwrite} is false, the functions fails in this
+{\it overwrite} parameter is \true (default), the destination file is overwritten
+if it exists, but if {\it overwrite} is \false, the functions fails in this
 case.
 
+This function supports resources forks under Mac OS.
+
 
 \membersection{::wxGetCwd}\label{wxgetcwd}
 
diff --git a/src/common/filefn.cpp b/src/common/filefn.cpp
index 3d2807acc1..636e3d9aac 100644
--- a/src/common/filefn.cpp
+++ b/src/common/filefn.cpp
@@ -158,7 +158,7 @@ WXDLLEXPORT int wxOpen( const wxChar *pathname, int flags, mode_t mode )
 // 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;
@@ -1058,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)
@@ -1107,38 +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);
+    wxDoCopyFile(fileIn, fbuf, file2, overwrite);
 
-    // create file2 with the same permissions than file1 and open it for
-    // writing
-
-    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];
-    for ( ;; )
     {
-        ssize_t count = fileIn.Read(buf, WXSIZEOF(buf));
-        if ( count == wxInvalidOffset )
-            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) < (size_t)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
-- 
2.50.0

