wxFileName::CreateTempFileName changes. Open the tempfiles read/write. Allow
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
This commit is contained in:
parent
693b31be84
commit
b70a2866d5
@ -32,6 +32,10 @@
|
||||
class WXDLLIMPEXP_BASE wxFile;
|
||||
#endif
|
||||
|
||||
#if wxUSE_FFILE
|
||||
class WXDLLIMPEXP_BASE wxFFile;
|
||||
#endif
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// constants
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -266,15 +270,30 @@ public:
|
||||
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)
|
||||
void AssignTempFileName(const wxString& prefix, wxFile *fileTemp = NULL);
|
||||
void AssignTempFileName(const wxString& prefix, wxFile *fileTemp);
|
||||
static wxString CreateTempFileName(const wxString& prefix,
|
||||
wxFile *fileTemp = NULL);
|
||||
wxFile *fileTemp);
|
||||
#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 );
|
||||
|
56
include/wx/private/filename.h
Normal file
56
include/wx/private/filename.h
Normal file
@ -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_
|
@ -74,14 +74,13 @@
|
||||
#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/private/filename.h"
|
||||
#include "wx/tokenzr.h"
|
||||
#include "wx/config.h" // for wxExpandEnvVars
|
||||
#include "wx/file.h"
|
||||
#include "wx/dynlib.h"
|
||||
|
||||
#if defined(__WIN32__) && defined(__MINGW32__)
|
||||
@ -583,30 +582,118 @@ wxString wxFileName::GetHomeDir()
|
||||
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
|
||||
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
/* static */
|
||||
wxString
|
||||
wxFileName::CreateTempFileName(const wxString& prefix, wxFile *fileTemp)
|
||||
|
||||
#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;
|
||||
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
|
||||
SplitPath(prefix, &dir, &name, NULL /* extension */);
|
||||
wxFileName::SplitPath(prefix, &dir, &name, NULL /* extension */);
|
||||
|
||||
if (dir.empty())
|
||||
{
|
||||
@ -625,12 +712,12 @@ wxFileName::CreateTempFileName(const wxString& prefix, wxFile *fileTemp)
|
||||
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;
|
||||
while (FileExists(path))
|
||||
while (wxFileName::FileExists(path))
|
||||
{
|
||||
path = dir + wxT("\\") + name ;
|
||||
path << i;
|
||||
@ -708,12 +795,28 @@ wxFileName::CreateTempFileName(const wxString& prefix, wxFile *fileTemp)
|
||||
{
|
||||
path = wxConvFile.cMB2WX( (const char*) buf );
|
||||
|
||||
#if wxUSE_FILE
|
||||
// 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);
|
||||
}
|
||||
@ -725,7 +828,7 @@ wxFileName::CreateTempFileName(const wxString& prefix, wxFile *fileTemp)
|
||||
path += _T("XXXXXX");
|
||||
|
||||
wxCharBuffer buf = wxConvFile.cWX2MB( path );
|
||||
if ( !mktemp( (const char*) buf ) )
|
||||
if ( !mktemp( (char*)(const char*) buf ) )
|
||||
{
|
||||
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);
|
||||
if ( !FileExists(pathTry) )
|
||||
if ( !wxFileName::FileExists(pathTry) )
|
||||
{
|
||||
break;
|
||||
}
|
||||
@ -765,20 +868,33 @@ wxFileName::CreateTempFileName(const wxString& prefix, wxFile *fileTemp)
|
||||
{
|
||||
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()...
|
||||
//
|
||||
// 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)
|
||||
@ -794,8 +910,128 @@ wxFileName::CreateTempFileName(const wxString& prefix, wxFile *fileTemp)
|
||||
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
|
||||
|
||||
|
||||
#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
|
||||
// ----------------------------------------------------------------------------
|
||||
|
Loading…
Reference in New Issue
Block a user