if ( flags != 0 ) // wxPATH_RMDIR_FULL or wxPATH_RMDIR_RECURSIVE
#endif // !__WINDOWS__
{
+#ifndef __WINDOWS__
+ if ( flags & wxPATH_RMDIR_RECURSIVE )
+ {
+ // When deleting the tree recursively, we are supposed to delete
+ // this directory itself even when it is a symlink -- but without
+ // following it. Do it here as wxRmdir() would simply follow if
+ // called for a symlink.
+ if ( wxFileName::Exists(dir, wxFILE_EXISTS_SYMLINK |
+ wxFILE_EXISTS_NO_FOLLOW) )
+ {
+ return wxRemoveFile(dir);
+ }
+ }
+#endif // !__WINDOWS__
+
wxString path(dir);
if ( path.Last() != wxFILE_SEP_PATH )
path += wxFILE_SEP_PATH;
wxString filename;
- // first delete all subdirectories
- bool cont = d.GetFirst(&filename, "", wxDIR_DIRS | wxDIR_HIDDEN);
+ // First delete all subdirectories: notice that we don't follow
+ // symbolic links, potentially leading outside this directory, to avoid
+ // unpleasant surprises.
+ bool cont = d.GetFirst(&filename, wxString(),
+ wxDIR_DIRS | wxDIR_HIDDEN | wxDIR_NO_FOLLOW);
while ( cont )
{
wxFileName::Rmdir(path + filename, flags);
#ifndef __WINDOWS__
if ( flags & wxPATH_RMDIR_RECURSIVE )
{
- // delete all files too
- cont = d.GetFirst(&filename, "", wxDIR_FILES | wxDIR_HIDDEN);
+ // Delete all files too and, for the same reasons as above, don't
+ // follow symlinks which could refer to the files outside of this
+ // directory and just delete the symlinks themselves.
+ cont = d.GetFirst(&filename, wxString(),
+ wxDIR_FILES | wxDIR_HIDDEN | wxDIR_NO_FOLLOW);
while ( cont )
{
::wxRemoveFile(path + filename);
wxFileName targetfn(wxFileName::CreateTempFileName(tempdir));
CPPUNIT_ASSERT(targetfn.FileExists());
- // Create a symlink to that file, and another to the home dir
+ // Create a symlink to that file
wxFileName linktofile(tempdir, "linktofile");
CPPUNIT_ASSERT_EQUAL(0, symlink(targetfn.GetFullPath().c_str(),
linktofile.GetFullPath().c_str()));
+ // ... and another to the temporary directory
const wxString linktodirName(tempdir + "/linktodir");
wxFileName linktodir(wxFileName::DirName(linktodirName));
CPPUNIT_ASSERT_EQUAL(0, symlink(tmpfn.GetFullPath().c_str(),
CPPUNIT_ASSERT(!wxFileName(tempdir, "linktofile").Exists());
CPPUNIT_ASSERT(linktofile.Exists());
- // Clean-up, and also tests removal of a dir containing a symlink-to-dir
+ // This is also a convenient place to test Rmdir() as we have things to
+ // remove.
+
+ // First, check that removing a symlink to a directory fails.
+ CPPUNIT_ASSERT( !wxFileName::Rmdir(linktodirName) );
+
+ // And recursively removing it only removes the symlink itself, not the
+ // directory.
+ CPPUNIT_ASSERT( wxFileName::Rmdir(linktodirName, wxPATH_RMDIR_RECURSIVE) );
+ CPPUNIT_ASSERT( tmpfn.Exists() );
+
+ // Finally removing the directory itself does remove everything.
CPPUNIT_ASSERT(tempdirfn.Rmdir(wxPATH_RMDIR_RECURSIVE));
+ CPPUNIT_ASSERT( !tempdirfn.Exists() );
}
#endif // __UNIX__