Refactor wxFileName existence checking code.
Merge FileExists() and DirExists() together in a single wxFileSystemObjectExists() helper in preparation for adding a function checking for the existence of any kind of file system object. There should be no changes for MSW/Unix but OS/2 file detection was changed slightly to always use DosQueryPathInfo() instead of using it only for the directories and stat() for files. Not sure if this is the right thing to do there but it seems like the code should work. Also add a simple unit test for these functions. See #953. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@70599 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
parent
06bfd04527
commit
901504c383
@ -148,6 +148,12 @@
|
|||||||
#define MAX_PATH _MAX_PATH
|
#define MAX_PATH _MAX_PATH
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef S_ISREG
|
||||||
|
#define S_ISREG(mode) ((mode) & S_IFREG)
|
||||||
|
#endif
|
||||||
|
#ifndef S_ISDIR
|
||||||
|
#define S_ISDIR(mode) ((mode) & S_IFDIR)
|
||||||
|
#endif
|
||||||
|
|
||||||
#if wxUSE_LONGLONG
|
#if wxUSE_LONGLONG
|
||||||
extern const wxULongLong wxInvalidSize = (unsigned)-1;
|
extern const wxULongLong wxInvalidSize = (unsigned)-1;
|
||||||
@ -593,46 +599,23 @@ wxFileName wxFileName::DirName(const wxString& dir, wxPathFormat format)
|
|||||||
// existence tests
|
// existence tests
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
bool wxFileName::FileExists() const
|
namespace
|
||||||
{
|
{
|
||||||
return wxFileName::FileExists( GetFullPath() );
|
|
||||||
}
|
|
||||||
|
|
||||||
/* static */
|
// Flags for wxFileSystemObjectExists() asking it to check for:
|
||||||
bool wxFileName::FileExists( const wxString &filePath )
|
enum
|
||||||
{
|
{
|
||||||
#if defined(__WIN32__) && !defined(__WXMICROWIN__)
|
wxFileSystemObject_File = 1, // file existence
|
||||||
// we must use GetFileAttributes() instead of the ANSI C functions because
|
wxFileSystemObject_Dir = 2, // directory existence
|
||||||
// it can cope with network (UNC) paths unlike them
|
wxFileSystemObject_Other = 4, // existence of something else, e.g.
|
||||||
DWORD ret = ::GetFileAttributes(filePath.t_str());
|
// device, socket, FIFO under Unix
|
||||||
|
wxFileSystemObject_Any = 7 // existence of anything at all
|
||||||
|
};
|
||||||
|
|
||||||
return (ret != INVALID_FILE_ATTRIBUTES) && !(ret & FILE_ATTRIBUTE_DIRECTORY);
|
#if defined(__WINDOWS__) && !defined(__WXMICROWIN__)
|
||||||
#else // !__WIN32__
|
|
||||||
#ifndef S_ISREG
|
|
||||||
#define S_ISREG(mode) ((mode) & S_IFREG)
|
|
||||||
#endif
|
|
||||||
wxStructStat st;
|
|
||||||
|
|
||||||
return (wxStat( filePath, &st) == 0 && S_ISREG(st.st_mode))
|
void RemoveTrailingSeparatorsFromPath(wxString& strPath)
|
||||||
#ifdef __OS2__
|
|
||||||
|| (errno == EACCES) // if access is denied something with that name
|
|
||||||
// exists and is opened in exclusive mode.
|
|
||||||
#endif
|
|
||||||
;
|
|
||||||
#endif // __WIN32__/!__WIN32__
|
|
||||||
}
|
|
||||||
|
|
||||||
bool wxFileName::DirExists() const
|
|
||||||
{
|
{
|
||||||
return wxFileName::DirExists( GetPath() );
|
|
||||||
}
|
|
||||||
|
|
||||||
/* static */
|
|
||||||
bool wxFileName::DirExists( const wxString &dirPath )
|
|
||||||
{
|
|
||||||
wxString strPath(dirPath);
|
|
||||||
|
|
||||||
#if defined(__WINDOWS__) || defined(__OS2__)
|
|
||||||
// Windows fails to find directory named "c:\dir\" even if "c:\dir" exists,
|
// Windows fails to find directory named "c:\dir\" even if "c:\dir" exists,
|
||||||
// so remove all trailing backslashes from the path - but don't do this for
|
// so remove all trailing backslashes from the path - but don't do this for
|
||||||
// the paths "d:\" (which are different from "d:"), for just "\" or for
|
// the paths "d:\" (which are different from "d:"), for just "\" or for
|
||||||
@ -649,38 +632,104 @@ bool wxFileName::DirExists( const wxString &dirPath )
|
|||||||
|
|
||||||
strPath.Truncate(len - 1);
|
strPath.Truncate(len - 1);
|
||||||
}
|
}
|
||||||
#endif // __WINDOWS__
|
}
|
||||||
|
|
||||||
#ifdef __OS2__
|
#endif // __WINDOWS__ || __OS2__
|
||||||
|
|
||||||
|
bool wxFileSystemObjectExists(const wxString& path, int flags)
|
||||||
|
{
|
||||||
|
// Should the existence of file/directory with this name be accepted, i.e.
|
||||||
|
// result in the true return value from this function?
|
||||||
|
const bool acceptFile = flags & wxFileSystemObject_File;
|
||||||
|
const bool acceptDir = flags & wxFileSystemObject_Dir;
|
||||||
|
|
||||||
|
wxString strPath(path);
|
||||||
|
|
||||||
|
#if defined(__WINDOWS__) && !defined(__WXMICROWIN__)
|
||||||
|
if ( acceptDir )
|
||||||
|
{
|
||||||
|
// Ensure that the path doesn't have any trailing separators when
|
||||||
|
// checking for directories.
|
||||||
|
RemoveTrailingSeparatorsFromPath(strPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
// we must use GetFileAttributes() instead of the ANSI C functions because
|
||||||
|
// it can cope with network (UNC) paths unlike them
|
||||||
|
DWORD ret = ::GetFileAttributes(path.t_str());
|
||||||
|
|
||||||
|
if ( ret == INVALID_FILE_ATTRIBUTES )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if ( ret & FILE_ATTRIBUTE_DIRECTORY )
|
||||||
|
return acceptDir;
|
||||||
|
|
||||||
|
// Anything else must be a file (perhaps we should check for
|
||||||
|
// FILE_ATTRIBUTE_REPARSE_POINT?)
|
||||||
|
return acceptFile;
|
||||||
|
#elif defined(__OS2__)
|
||||||
|
if ( acceptDir )
|
||||||
|
{
|
||||||
// OS/2 can't handle "d:", it wants either "d:\" or "d:."
|
// OS/2 can't handle "d:", it wants either "d:\" or "d:."
|
||||||
if (strPath.length() == 2 && strPath[1u] == wxT(':'))
|
if (strPath.length() == 2 && strPath[1u] == wxT(':'))
|
||||||
strPath << wxT('.');
|
strPath << wxT('.');
|
||||||
#endif
|
}
|
||||||
|
|
||||||
#if defined(__WIN32__) && !defined(__WXMICROWIN__)
|
|
||||||
// stat() can't cope with network paths
|
|
||||||
DWORD ret = ::GetFileAttributes(strPath.t_str());
|
|
||||||
|
|
||||||
return (ret != INVALID_FILE_ATTRIBUTES) && (ret & FILE_ATTRIBUTE_DIRECTORY);
|
|
||||||
#elif defined(__OS2__)
|
|
||||||
FILESTATUS3 Info = {{0}};
|
FILESTATUS3 Info = {{0}};
|
||||||
APIRET rc = ::DosQueryPathInfo((PSZ)(WXSTRINGCAST strPath), FIL_STANDARD,
|
APIRET rc = ::DosQueryPathInfo((PSZ)(WXSTRINGCAST strPath), FIL_STANDARD,
|
||||||
(void*) &Info, sizeof(FILESTATUS3));
|
(void*) &Info, sizeof(FILESTATUS3));
|
||||||
|
|
||||||
return ((rc == NO_ERROR) && (Info.attrFile & FILE_DIRECTORY)) ||
|
if ( rc == NO_ERROR )
|
||||||
(rc == ERROR_SHARING_VIOLATION);
|
{
|
||||||
// If we got a sharing violation, there must be something with this name.
|
if ( Info.attrFile & FILE_DIRECTORY )
|
||||||
#else // !__WIN32__
|
return acceptDir;
|
||||||
|
else
|
||||||
|
return acceptFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We consider that the path must exist if we get a sharing violation for
|
||||||
|
// it but we don't know what is it in this case.
|
||||||
|
if ( rc == ERROR_SHARING_VIOLATION )
|
||||||
|
return flags & wxFileSystemObject_Other;
|
||||||
|
|
||||||
|
// Any other error (usually ERROR_PATH_NOT_FOUND), means there is nothing
|
||||||
|
// there.
|
||||||
|
return false;
|
||||||
|
#else // Non-MSW, non-OS/2
|
||||||
wxStructStat st;
|
wxStructStat st;
|
||||||
#ifndef __VISAGECPP__
|
if ( wxStat(strPath, &st) != 0 )
|
||||||
return wxStat(strPath, &st) == 0 && ((st.st_mode & S_IFMT) == S_IFDIR);
|
return false;
|
||||||
#else
|
|
||||||
// S_IFMT not supported in VA compilers.. st_mode is a 2byte value only
|
|
||||||
return wxStat(strPath, &st) == 0 && (st.st_mode == S_IFDIR);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif // __WIN32__/!__WIN32__
|
if ( S_ISREG(st.st_mode) )
|
||||||
|
return acceptFile;
|
||||||
|
if ( S_ISDIR(st.st_mode) )
|
||||||
|
return acceptDir;
|
||||||
|
|
||||||
|
return flags & wxFileSystemObject_Other;
|
||||||
|
#endif // Platforms
|
||||||
|
}
|
||||||
|
|
||||||
|
} // anonymous namespace
|
||||||
|
|
||||||
|
bool wxFileName::FileExists() const
|
||||||
|
{
|
||||||
|
return wxFileName::FileExists( GetFullPath() );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* static */
|
||||||
|
bool wxFileName::FileExists( const wxString &filePath )
|
||||||
|
{
|
||||||
|
return wxFileSystemObjectExists(filePath, wxFileSystemObject_File);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool wxFileName::DirExists() const
|
||||||
|
{
|
||||||
|
return wxFileName::DirExists( GetPath() );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* static */
|
||||||
|
bool wxFileName::DirExists( const wxString &dirPath )
|
||||||
|
{
|
||||||
|
return wxFileSystemObjectExists(dirPath, wxFileSystemObject_Dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
@ -134,6 +134,7 @@ private:
|
|||||||
CPPUNIT_TEST( TestVolumeUniqueName );
|
CPPUNIT_TEST( TestVolumeUniqueName );
|
||||||
CPPUNIT_TEST( TestCreateTempFileName );
|
CPPUNIT_TEST( TestCreateTempFileName );
|
||||||
CPPUNIT_TEST( TestGetTimes );
|
CPPUNIT_TEST( TestGetTimes );
|
||||||
|
CPPUNIT_TEST( TestExists );
|
||||||
CPPUNIT_TEST_SUITE_END();
|
CPPUNIT_TEST_SUITE_END();
|
||||||
|
|
||||||
void TestConstruction();
|
void TestConstruction();
|
||||||
@ -151,6 +152,7 @@ private:
|
|||||||
void TestVolumeUniqueName();
|
void TestVolumeUniqueName();
|
||||||
void TestCreateTempFileName();
|
void TestCreateTempFileName();
|
||||||
void TestGetTimes();
|
void TestGetTimes();
|
||||||
|
void TestExists();
|
||||||
|
|
||||||
DECLARE_NO_COPY_CLASS(FileNameTestCase)
|
DECLARE_NO_COPY_CLASS(FileNameTestCase)
|
||||||
};
|
};
|
||||||
@ -647,3 +649,21 @@ void FileNameTestCase::TestGetTimes()
|
|||||||
CPPUNIT_ASSERT(dtMod.IsEqualUpTo(wxDateTime::Now(), wxTimeSpan(0,1)));
|
CPPUNIT_ASSERT(dtMod.IsEqualUpTo(wxDateTime::Now(), wxTimeSpan(0,1)));
|
||||||
CPPUNIT_ASSERT(dtAccess.IsEqualUpTo(wxDateTime::Now(), wxTimeSpan(0,1)));
|
CPPUNIT_ASSERT(dtAccess.IsEqualUpTo(wxDateTime::Now(), wxTimeSpan(0,1)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FileNameTestCase::TestExists()
|
||||||
|
{
|
||||||
|
wxFileName fn(wxFileName::CreateTempFileName("filenametest"));
|
||||||
|
CPPUNIT_ASSERT( fn.IsOk() );
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT( fn.FileExists() );
|
||||||
|
CPPUNIT_ASSERT( !wxFileName::DirExists(fn.GetFullPath()) );
|
||||||
|
|
||||||
|
wxFileName dirTemp(wxFileName::DirName(wxFileName::GetTempDir()));
|
||||||
|
CPPUNIT_ASSERT( !dirTemp.FileExists() );
|
||||||
|
CPPUNIT_ASSERT( dirTemp.DirExists() );
|
||||||
|
|
||||||
|
#ifdef __UNIX__
|
||||||
|
CPPUNIT_ASSERT( !wxFileName::FileExists("/dev/null") );
|
||||||
|
CPPUNIT_ASSERT( !wxFileName::DirExists("/dev/null") );
|
||||||
|
#endif // __UNIX__
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user