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:
Michael Wetherell 2006-10-23 13:10:12 +00:00
parent 693b31be84
commit b70a2866d5
3 changed files with 346 additions and 35 deletions

View File

@ -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 );

View 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_

View File

@ -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
// ----------------------------------------------------------------------------