]> git.saurik.com Git - wxWidgets.git/commitdiff
wxFileName::CreateTempFileName changes. Open the tempfiles read/write. Allow
authorMichael Wetherell <mike.wetherell@ntlworld.com>
Mon, 23 Oct 2006 13:10:12 +0000 (13:10 +0000)
committerMichael Wetherell <mike.wetherell@ntlworld.com>
Mon, 23 Oct 2006 13:10:12 +0000 (13:10 +0000)
self delting temp files to be created, where the OS supports it. Add support
for opening wxFFile temp files.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@42277 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

include/wx/filename.h
include/wx/private/filename.h [new file with mode: 0644]
src/common/filename.cpp

index 801529327d78525e3ad5830ece7f7ead3548e2da..762237b5ae93f92ee8c89ce5a6fa16cee7183835 100644 (file)
 class WXDLLIMPEXP_BASE wxFile;
 #endif
 
 class WXDLLIMPEXP_BASE wxFile;
 #endif
 
+#if wxUSE_FFILE
+class WXDLLIMPEXP_BASE wxFFile;
+#endif
+
 // ----------------------------------------------------------------------------
 // constants
 // ----------------------------------------------------------------------------
 // ----------------------------------------------------------------------------
 // constants
 // ----------------------------------------------------------------------------
@@ -266,15 +270,30 @@ public:
     void AssignHomeDir();
     static wxString GetHomeDir();
 
     void AssignHomeDir();
     static wxString GetHomeDir();
 
+#if wxUSE_FILE || wxUSE_FFILE
+        // get a temp file name starting with the specified prefix
+    void AssignTempFileName(const wxString& prefix);
+    static wxString CreateTempFileName(const wxString& prefix);
+#endif // wxUSE_FILE
+
 #if wxUSE_FILE
         // get a temp file name starting with the specified prefix and open the
         // file passed to us using this name for writing (atomically if
         // possible)
 #if wxUSE_FILE
         // get a temp file name starting with the specified prefix and open the
         // file passed to us using this name for writing (atomically if
         // possible)
-    void AssignTempFileName(const wxString& prefix, wxFile *fileTemp = NULL);
+    void AssignTempFileName(const wxString& prefix, wxFile *fileTemp);
     static wxString CreateTempFileName(const wxString& prefix,
     static wxString CreateTempFileName(const wxString& prefix,
-                                       wxFile *fileTemp = NULL);
+                                       wxFile *fileTemp);
 #endif // wxUSE_FILE
 
 #endif // wxUSE_FILE
 
+#if wxUSE_FFILE
+        // get a temp file name starting with the specified prefix and open the
+        // file passed to us using this name for writing (atomically if
+        // possible)
+    void AssignTempFileName(const wxString& prefix, wxFFile *fileTemp);
+    static wxString CreateTempFileName(const wxString& prefix,
+                                       wxFFile *fileTemp);
+#endif // wxUSE_FFILE
+
     // directory creation and removal.
     bool Mkdir( int perm = 0777, int flags = 0);
     static bool Mkdir( const wxString &dir, int perm = 0777, int flags = 0 );
     // directory creation and removal.
     bool Mkdir( int perm = 0777, int flags = 0);
     static bool Mkdir( const wxString &dir, int perm = 0777, int flags = 0 );
diff --git a/include/wx/private/filename.h b/include/wx/private/filename.h
new file mode 100644 (file)
index 0000000..ac2bbd3
--- /dev/null
@@ -0,0 +1,56 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        include/wx/private/filename.h
+// Purpose:     Internal declarations for src/common/filename.cpp
+// Author:      Mike Wetherell
+// Modified by:
+// Created:     2006-10-22
+// RCS-ID:      $Id$
+// Copyright:   (c) 2006 Mike Wetherell
+// Licence:     wxWindows licence
+/////////////////////////////////////////////////////////////////////////////
+
+#ifndef _WX_PRIVATE_FILENAME_H_
+#define _WX_PRIVATE_FILENAME_H_
+
+#include "wx/file.h"
+#include "wx/ffile.h"
+
+// Self deleting temp files aren't supported on all platforms. Therefore
+// rather than let these be in the API, they can be used internally to
+// implement classes (e.g. wxTempFileStream), that will do the clean up when
+// the OS doesn't support it.
+
+// Same usage as wxFileName::CreateTempFileName() with the extra parameter
+// deleteOnClose. *deleteOnClose true on entry requests a file created with a
+// delete on close flag, on exit the value of *deleteOnClose indicates whether
+// available.
+
+#if wxUSE_FILE
+wxString wxCreateTempFileName(const wxString& prefix,
+                              wxFile *fileTemp,
+                              bool *deleteOnClose = NULL);
+#endif
+
+#if wxUSE_FFILE
+wxString wxCreateTempFileName(const wxString& prefix,
+                              wxFFile *fileTemp,
+                              bool *deleteOnClose = NULL);
+#endif
+
+// Returns an open temp file, if possible either an unlinked open file or one
+// that will delete on close. Only returns the filename if neither was
+// possible, so that the caller can delete the file when done.
+
+#if wxUSE_FILE
+bool wxCreateTempFile(const wxString& prefix,
+                      wxFile *fileTemp,
+                      wxString *name);
+#endif
+
+#if wxUSE_FFILE
+bool wxCreateTempFile(const wxString& prefix,
+                      wxFFile *fileTemp,
+                      wxString *name);
+#endif
+
+#endif // _WX_PRIVATE_FILENAME_H_
index b4ea82e56a960adea19bb2f8e4d83f6a000657de..c6e42ca2329dc86dc92bb2c67cb2c81505684bbf 100644 (file)
     #include "wx/dynarray.h"
     #include "wx/intl.h"
     #include "wx/log.h"
     #include "wx/dynarray.h"
     #include "wx/intl.h"
     #include "wx/log.h"
-    #include "wx/file.h"
     #include "wx/utils.h"
 #endif
 
 #include "wx/filename.h"
     #include "wx/utils.h"
 #endif
 
 #include "wx/filename.h"
+#include "wx/private/filename.h"
 #include "wx/tokenzr.h"
 #include "wx/config.h"          // for wxExpandEnvVars
 #include "wx/tokenzr.h"
 #include "wx/config.h"          // for wxExpandEnvVars
-#include "wx/file.h"
 #include "wx/dynlib.h"
 
 #if defined(__WIN32__) && defined(__MINGW32__)
 #include "wx/dynlib.h"
 
 #if defined(__WIN32__) && defined(__MINGW32__)
@@ -583,30 +582,118 @@ wxString wxFileName::GetHomeDir()
     return ::wxGetHomeDir();
 }
 
     return ::wxGetHomeDir();
 }
 
-#if wxUSE_FILE
 
 
-void wxFileName::AssignTempFileName(const wxString& prefix, wxFile *fileTemp)
+// ----------------------------------------------------------------------------
+// CreateTempFileName
+// ----------------------------------------------------------------------------
+
+#if wxUSE_FILE || wxUSE_FFILE
+
+
+#if !defined wx_fdopen && defined HAVE_FDOPEN
+    #define wx_fdopen fdopen
+#endif
+
+// NB: GetTempFileName() under Windows creates the file, so using
+//     O_EXCL there would fail
+#ifdef __WINDOWS__
+    #define wxOPEN_EXCL 0
+#else
+    #define wxOPEN_EXCL O_EXCL
+#endif
+
+
+#ifdef wxOpenOSFHandle
+#define WX_HAVE_DELETE_ON_CLOSE
+// On Windows create a file with the FILE_FLAGS_DELETE_ON_CLOSE flags.
+//
+static int wxOpenWithDeleteOnClose(const wxString& filename)
 {
 {
-    wxString tempname = CreateTempFileName(prefix, fileTemp);
-    if ( tempname.empty() )
-    {
-        // error, failed to get temp file name
-        Clear();
-    }
-    else // ok
-    {
-        Assign(tempname);
-    }
+    DWORD access = GENERIC_READ | GENERIC_WRITE;
+
+    DWORD disposition = OPEN_ALWAYS;
+
+    DWORD attributes = FILE_ATTRIBUTE_TEMPORARY |
+                       FILE_FLAG_DELETE_ON_CLOSE;
+
+    HANDLE h = ::CreateFile(filename, access, 0, NULL,
+                            disposition, attributes, NULL);
+
+    return wxOpenOSFHandle(h, 0);
 }
 }
+#endif // wxOpenOSFHandle
 
 
-/* static */
-wxString
-wxFileName::CreateTempFileName(const wxString& prefix, wxFile *fileTemp)
+
+// Helper to open the file
+//
+static int wxTempOpen(const wxString& path, bool *deleteOnClose)
+{
+#ifdef WX_HAVE_DELETE_ON_CLOSE
+    if (*deleteOnClose)
+        return wxOpenWithDeleteOnClose(path);
+#endif
+
+    *deleteOnClose = false;
+
+    return wxOpen(path, wxO_BINARY | O_RDWR | O_CREAT | wxOPEN_EXCL, 0600);
+}
+
+
+#if wxUSE_FFILE
+// Helper to open the file and attach it to the wxFFile
+//
+static bool wxTempOpen(wxFFile *file, const wxString& path, bool *deleteOnClose)
 {
 {
+#ifndef wx_fdopen
+    *deleteOnClose = false;
+    return file->Open(path, _T("w+b"));
+#else // wx_fdopen
+    int fd = wxTempOpen(path, deleteOnClose);
+    if (fd != -1)
+        return false;
+    file->Attach(wx_fdopen(fd, "w+b"));
+    return file->IsOpened();
+#endif // wx_fdopen
+}
+#endif // wxUSE_FFILE
+
+
+#if !wxUSE_FILE
+    #define WXFILEARGS(x, y) y
+#elif !wxUSE_FFILE
+    #define WXFILEARGS(x, y) x
+#else
+    #define WXFILEARGS(x, y) x, y
+#endif
+
+
+// Implementation of wxFileName::CreateTempFileName().
+//
+static wxString wxCreateTempImpl(
+        const wxString& prefix,
+        WXFILEARGS(wxFile *fileTemp, wxFFile *ffileTemp),
+        bool *deleteOnClose = NULL)
+{
+#if wxUSE_FILE && wxUSE_FFILE
+    wxASSERT(fileTemp == NULL || ffileTemp == NULL);
+#endif
     wxString path, dir, name;
     wxString path, dir, name;
+    bool wantDeleteOnClose = false;
+
+    if (deleteOnClose)
+    {
+        // set the result to false initially
+        wantDeleteOnClose = *deleteOnClose;
+        *deleteOnClose = false;
+    }
+    else
+    {
+        // easier if it alwasys points to something
+        deleteOnClose = &wantDeleteOnClose;
+    }
 
     // use the directory specified by the prefix
 
     // use the directory specified by the prefix
-    SplitPath(prefix, &dir, &name, NULL /* extension */);
+    wxFileName::SplitPath(prefix, &dir, &name, NULL /* extension */);
 
     if (dir.empty())
     {
 
     if (dir.empty())
     {
@@ -625,12 +712,12 @@ wxFileName::CreateTempFileName(const wxString& prefix, wxFile *fileTemp)
     if (dir.empty())
     {
         // FIXME. Create \temp dir?
     if (dir.empty())
     {
         // FIXME. Create \temp dir?
-        if (DirExists(wxT("\\temp")))
+        if (wxFileName::DirExists(wxT("\\temp")))
             dir = wxT("\\temp");
     }
     path = dir + wxT("\\") + name;
     int i = 1;
             dir = wxT("\\temp");
     }
     path = dir + wxT("\\") + name;
     int i = 1;
-    while (FileExists(path))
+    while (wxFileName::FileExists(path))
     {
         path = dir + wxT("\\") + name ;
         path << i;
     {
         path = dir + wxT("\\") + name ;
         path << i;
@@ -708,12 +795,28 @@ wxFileName::CreateTempFileName(const wxString& prefix, wxFile *fileTemp)
     {
         path = wxConvFile.cMB2WX( (const char*) buf );
 
     {
         path = wxConvFile.cMB2WX( (const char*) buf );
 
+    #if wxUSE_FILE
         // avoid leaking the fd
         if ( fileTemp )
         {
             fileTemp->Attach(fdTemp);
         }
         else
         // avoid leaking the fd
         if ( fileTemp )
         {
             fileTemp->Attach(fdTemp);
         }
         else
+    #endif
+
+    #if wxUSE_FFILE
+        if ( ffileTemp )
+        {
+        #ifdef wx_fdopen
+            ffileTemp->Attach(wx_fdopen(fdTemp, "r+b"));
+        #else
+            ffileTemp->Open(path, _T("r+b"));
+            close(fdTemp);
+        #endif
+        }
+        else
+    #endif
+
         {
             close(fdTemp);
         }
         {
             close(fdTemp);
         }
@@ -725,7 +828,7 @@ wxFileName::CreateTempFileName(const wxString& prefix, wxFile *fileTemp)
     path += _T("XXXXXX");
 
     wxCharBuffer buf = wxConvFile.cWX2MB( path );
     path += _T("XXXXXX");
 
     wxCharBuffer buf = wxConvFile.cWX2MB( path );
-    if ( !mktemp( (const char*) buf ) )
+    if ( !mktemp( (char*)(const char*) buf ) )
     {
         path.clear();
     }
     {
         path.clear();
     }
@@ -746,7 +849,7 @@ wxFileName::CreateTempFileName(const wxString& prefix, wxFile *fileTemp)
     {
         // 3 hex digits is enough for numTries == 1000 < 4096
         pathTry = path + wxString::Format(_T("%.03x"), (unsigned int) n);
     {
         // 3 hex digits is enough for numTries == 1000 < 4096
         pathTry = path + wxString::Format(_T("%.03x"), (unsigned int) n);
-        if ( !FileExists(pathTry) )
+        if ( !wxFileName::FileExists(pathTry) )
         {
             break;
         }
         {
             break;
         }
@@ -765,20 +868,33 @@ wxFileName::CreateTempFileName(const wxString& prefix, wxFile *fileTemp)
     {
         wxLogSysError(_("Failed to create a temporary file name"));
     }
     {
         wxLogSysError(_("Failed to create a temporary file name"));
     }
-    else if ( fileTemp && !fileTemp->IsOpened() )
+    else
     {
     {
+        bool ok = true;
+
         // open the file - of course, there is a race condition here, this is
         // why we always prefer using mkstemp()...
         // open the file - of course, there is a race condition here, this is
         // why we always prefer using mkstemp()...
-        //
-        // NB: GetTempFileName() under Windows creates the file, so using
-        //     write_excl there would fail
-        if ( !fileTemp->Open(path,
-#if defined(__WINDOWS__) && !defined(__WXMICROWIN__)
-                             wxFile::write,
-#else
-                             wxFile::write_excl,
-#endif
-                             wxS_IRUSR | wxS_IWUSR) )
+    #if wxUSE_FILE
+        if ( fileTemp && !fileTemp->IsOpened() )
+        {
+            *deleteOnClose = wantDeleteOnClose;
+            int fd = wxTempOpen(path, deleteOnClose);
+            if (fd != -1)
+                fileTemp->Attach(fd);
+            else
+                ok = false;
+        }
+    #endif
+
+    #if wxUSE_FFILE
+        if ( ffileTemp && !ffileTemp->IsOpened() )
+        {
+            *deleteOnClose = wantDeleteOnClose;
+            ok = wxTempOpen(ffileTemp, path, deleteOnClose);
+        }
+    #endif
+
+        if ( !ok )
         {
             // FIXME: If !ok here should we loop and try again with another
             //        file name?  That is the standard recourse if open(O_EXCL)
         {
             // FIXME: If !ok here should we loop and try again with another
             //        file name?  That is the standard recourse if open(O_EXCL)
@@ -794,8 +910,128 @@ wxFileName::CreateTempFileName(const wxString& prefix, wxFile *fileTemp)
     return path;
 }
 
     return path;
 }
 
+
+static bool wxCreateTempImpl(
+        const wxString& prefix,
+        WXFILEARGS(wxFile *fileTemp, wxFFile *ffileTemp),
+        wxString *name)
+{
+    bool deleteOnClose = true;
+
+    *name = wxCreateTempImpl(prefix,
+                             WXFILEARGS(fileTemp, ffileTemp),
+                             &deleteOnClose);
+
+    bool ok = !name->empty();
+
+    if (deleteOnClose)
+        name->clear();
+#ifdef __UNIX__
+    else if (ok && wxRemoveFile(*name))
+        name->clear();
+#endif
+
+    return ok;
+}
+
+
+static void wxAssignTempImpl(
+        wxFileName *fn,
+        const wxString& prefix,
+        WXFILEARGS(wxFile *fileTemp, wxFFile *ffileTemp))
+{
+    wxString tempname;
+    tempname = wxCreateTempImpl(prefix, WXFILEARGS(fileTemp, ffileTemp));
+
+    if ( tempname.empty() )
+    {
+        // error, failed to get temp file name
+        fn->Clear();
+    }
+    else // ok
+    {
+        fn->Assign(tempname);
+    }
+}
+
+
+void wxFileName::AssignTempFileName(const wxString& prefix)
+{
+    wxAssignTempImpl(this, prefix, WXFILEARGS(NULL, NULL));
+}
+
+/* static */
+wxString wxFileName::CreateTempFileName(const wxString& prefix)
+{
+    return wxCreateTempImpl(prefix, WXFILEARGS(NULL, NULL));
+}
+
+#endif // wxUSE_FILE || wxUSE_FFILE
+
+
+#if wxUSE_FILE
+
+wxString wxCreateTempFileName(const wxString& prefix,
+                              wxFile *fileTemp,
+                              bool *deleteOnClose)
+{
+    return wxCreateTempImpl(prefix, WXFILEARGS(fileTemp, NULL), deleteOnClose);
+}
+
+bool wxCreateTempFile(const wxString& prefix,
+                      wxFile *fileTemp,
+                      wxString *name)
+{
+    return wxCreateTempImpl(prefix, WXFILEARGS(fileTemp, NULL), name);
+}
+
+void wxFileName::AssignTempFileName(const wxString& prefix, wxFile *fileTemp)
+{
+    wxAssignTempImpl(this, prefix, WXFILEARGS(fileTemp, NULL));
+}
+
+/* static */
+wxString
+wxFileName::CreateTempFileName(const wxString& prefix, wxFile *fileTemp)
+{
+    return wxCreateTempFileName(prefix, fileTemp);
+}
+
 #endif // wxUSE_FILE
 
 #endif // wxUSE_FILE
 
+
+#if wxUSE_FFILE
+
+wxString wxCreateTempFileName(const wxString& prefix,
+                              wxFFile *fileTemp,
+                              bool *deleteOnClose)
+{
+    return wxCreateTempImpl(prefix, WXFILEARGS(NULL, fileTemp), deleteOnClose);
+}
+
+bool wxCreateTempFile(const wxString& prefix,
+                      wxFFile *fileTemp,
+                      wxString *name)
+{
+    return wxCreateTempImpl(prefix, WXFILEARGS(NULL, fileTemp), name);
+
+}
+
+void wxFileName::AssignTempFileName(const wxString& prefix, wxFFile *fileTemp)
+{
+    wxAssignTempImpl(this, prefix, WXFILEARGS(NULL, fileTemp));
+}
+
+/* static */
+wxString
+wxFileName::CreateTempFileName(const wxString& prefix, wxFFile *fileTemp)
+{
+    return wxCreateTempFileName(prefix, fileTemp);
+}
+
+#endif // wxUSE_FFILE
+
+
 // ----------------------------------------------------------------------------
 // directory operations
 // ----------------------------------------------------------------------------
 // ----------------------------------------------------------------------------
 // directory operations
 // ----------------------------------------------------------------------------