summaryrefslogtreecommitdiff
path: root/zen/recycler.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'zen/recycler.cpp')
-rw-r--r--zen/recycler.cpp69
1 files changed, 59 insertions, 10 deletions
diff --git a/zen/recycler.cpp b/zen/recycler.cpp
index 07803e50..2a82cd24 100644
--- a/zen/recycler.cpp
+++ b/zen/recycler.cpp
@@ -5,14 +5,13 @@
// **************************************************************************
#include "recycler.h"
-#include <stdexcept>
-#include <iterator>
+//#include <stdexcept>
+//#include <iterator>
#include <zen/file_handling.h>
#ifdef FFS_WIN
-#include <algorithm>
-#include <functional>
-#include <vector>
+//#include <algorithm>
+//#include <functional>
#include <zen/dll.h>
#include <zen/win.h> //includes "windows.h"
#include <zen/assert_static.h>
@@ -24,6 +23,9 @@
#include <zen/scope_guard.h>
#include <sys/stat.h>
#include <gio/gio.h>
+
+#elif defined FFS_MAC
+#include <CoreServices/CoreServices.h>
#endif
using namespace zen;
@@ -142,7 +144,7 @@ void zen::recycleOrDelete(const std::vector<Zstring>& filenames, CallbackRecycli
bool zen::recycleOrDelete(const Zstring& filename) //throw FileError
{
- if (!somethingExists(filename))
+ if (!somethingExists(filename)) //[!] do not optimize away, OS X needs this for reliable detection of "recycle bin missing"
return false; //neither file nor any other object with that name existing: no error situation, manual deletion relies on it!
#ifdef FFS_WIN
@@ -151,13 +153,13 @@ bool zen::recycleOrDelete(const Zstring& filename) //throw FileError
recycleOrDelete(filenames, nullptr); //throw FileError
#elif defined FFS_LINUX
- GFile* file = g_file_new_for_path(filename.c_str()); //never fails according to docu
+ GFile* file = ::g_file_new_for_path(filename.c_str()); //never fails according to docu
ZEN_ON_SCOPE_EXIT(g_object_unref(file);)
GError* error = nullptr;
- ZEN_ON_SCOPE_EXIT(if (error) g_error_free(error););
+ ZEN_ON_SCOPE_EXIT(if (error) ::g_error_free(error););
- if (!g_file_trash(file, nullptr, &error))
+ if (!::g_file_trash(file, nullptr, &error))
{
const std::wstring shortMsg = replaceCpy(_("Unable to move %x to the Recycle Bin!"), L"%x", fmtFileName(filename));
@@ -181,6 +183,53 @@ bool zen::recycleOrDelete(const Zstring& filename) //throw FileError
throw FileError(shortMsg + L"\n\n" + L"Glib Error Code " + numberTo<std::wstring>(error->code) + /* L", " +
g_quark_to_string(error->domain) + */ L": " + utfCvrtTo<std::wstring>(error->message));
}
+
+#elif defined FFS_MAC
+ //we cannot use FSPathMoveObjectToTrashSync directly since it follows symlinks!
+
+ assert_static(sizeof(Zchar) == sizeof(char));
+ const UInt8* filenameUtf8 = reinterpret_cast<const UInt8*>(filename.c_str());
+
+ auto throwFileError = [&](OSStatus oss)
+ {
+ std::wstring msg = replaceCpy(_("Unable to move %x to the Recycle Bin!"), L"%x", fmtFileName(filename)) + L"\n\n"
+ + L"Result Code " + numberTo<std::wstring>(oss);
+ const char* description = GetMacOSStatusCommentString(oss);
+ if (description) //found no documentation for proper use of GetMacOSStatusCommentString
+ msg += L": " + utfCvrtTo<std::wstring>(description);
+ throw FileError(msg);
+ };
+
+ FSRef objectRef;
+ OSStatus rv = ::FSPathMakeRefWithOptions(filenameUtf8, //const UInt8 *path,
+ kFSPathMakeRefDoNotFollowLeafSymlink, //OptionBits options,
+ &objectRef, //FSRef *ref,
+ nullptr); //Boolean *isDirectory
+ if (rv != noErr)
+ throwFileError(rv);
+
+ //deprecated since OS X 10.8!!! "trashItemAtURL" should be used instead
+ OSStatus rv2 = ::FSMoveObjectToTrashSync(&objectRef, //const FSRef *source,
+ nullptr, //FSRef *target,
+ kFSFileOperationDefaultOptions); //OptionBits options
+ if (rv2 != noErr)
+ {
+ //implement same behavior as in Windows: if recycler is not existing, delete permanently
+ if (rv2 == -120) //=="Directory not found or incomplete pathname." but should really be "recycle bin directory not found"!
+ {
+ struct stat fileInfo = {};
+ if (::lstat(filename.c_str(), &fileInfo) != 0)
+ return false;
+
+ if (S_ISLNK(fileInfo.st_mode) || S_ISREG(fileInfo.st_mode))
+ removeFile(filename); //throw FileError
+ else if (S_ISDIR(fileInfo.st_mode))
+ removeDirectory(filename); //throw FileError
+ return true;
+ }
+
+ throwFileError(rv2);
+ }
#endif
return true;
}
@@ -275,7 +324,7 @@ StatusRecycler zen::recycleBinStatus(const Zstring& pathName)
*/
}
-#elif defined FFS_LINUX
+#elif defined FFS_LINUX || defined FFS_MAC
/*
We really need access to a similar function to check whether a directory supports trashing and emit a warning if it does not!
bgstack15