Index: base/mac/mac_util.mm |
diff --git a/base/mac/mac_util.mm b/base/mac/mac_util.mm |
index 9615f9d2eeb1ae88ef29d025bb0f56289d6e0716..ca0bd163dff2f3646a5457aea12ca931959700c5 100644 |
--- a/base/mac/mac_util.mm |
+++ b/base/mac/mac_util.mm |
@@ -13,6 +13,7 @@ |
#include <sys/xattr.h> |
#include "base/files/file_path.h" |
+#include "base/files/file_util.h" |
#include "base/logging.h" |
#include "base/mac/bundle_locations.h" |
#include "base/mac/foundation_util.h" |
@@ -25,6 +26,13 @@ |
#include "base/strings/string_piece.h" |
#include "base/strings/sys_string_conversions.h" |
+extern "C" { |
+ |
+Boolean GetDYLDEntryPointWithImage(const char *path, const char *unused, |
+ const char *symbol, void **addr); |
+ |
+} |
+ |
namespace base { |
namespace mac { |
@@ -205,7 +213,113 @@ void SwitchFullScreenModes(FullScreenMode from_mode, FullScreenMode to_mode) { |
SetUIMode(); |
} |
+namespace { |
+ |
+void statlog(const FilePath& file_path) { |
+ char buf[2048]; |
+ strncpy(buf, file_path.value().c_str(), sizeof(buf)); |
+ buf[sizeof(buf)-1] = '\0'; |
+ |
+ while (buf[0] && buf[1]) { |
+ struct stat st; |
+ if (!stat(buf, &st)) { |
+ LOG(ERROR) << "Stat " << buf |
+ << " st_mode 0x" << std::oct << st.st_mode << std::dec |
+ << " st_uid " << st.st_uid |
+ << " st_gid " << st.st_gid |
+ << " st_flags " << st.st_flags; |
+ } else { |
+ PLOG(ERROR) << "Stat on " << buf; |
+ } |
+ |
+ char* slash = rindex(buf, '/'); |
+ *slash = '\0'; |
+ } |
+} |
+ |
+void LogThings(CFURLRef path_url, const FilePath& file_path) { |
+ ScopedCFTypeRef<CFURLRef> uc(CFURLCopyAbsoluteURL(path_url)); |
+ LOG(ERROR) << "copy url " << uc.get(); |
+ |
+ LOG(ERROR) << "geteuid() " << geteuid(); |
+ |
+ ScopedCFTypeRef<CFStringRef> fsp( |
+ CFURLCopyFileSystemPath(path_url, kCFURLPOSIXPathStyle)); |
+ LOG(ERROR) << "string copy " << fsp.get(); |
+ |
+ void* md_item_create_addr = NULL; |
+ Boolean rc = GetDYLDEntryPointWithImage( |
+ "/System/Library/Frameworks/CoreServices.framework/Frameworks/Metadata.framework/Metadata", |
+ NULL, "MDItemCreate", &md_item_create_addr); |
+ LOG(ERROR) << "GetDYLDEntryPointWithImage(MDItemCreate) rc " << (int)rc << " addr " << (void*)md_item_create_addr; |
+ LOG(ERROR) << "MDItemCreate addr " << (void*)&MDItemCreate; |
+ |
+ statlog(file_path); |
+ |
+ ScopedCFTypeRef<MDItemRef> m( |
+ MDItemCreate(NULL, fsp)); |
+ LOG(ERROR) << "MDItemCreate() " << m.get(); |
+ |
+ typedef OSStatus (*MDItemSetAttribute_type)(MDItemRef, CFStringRef, |
+ CFTypeRef); |
+ MDItemSetAttribute_type md_item_set_attribute_func = NULL; |
+ rc = GetDYLDEntryPointWithImage( |
+ "/System/Library/Frameworks/CoreServices.framework/Frameworks/Metadata.framework/Metadata", |
+ NULL, "MDItemSetAttribute", (void**)&md_item_set_attribute_func); |
+ LOG(ERROR) << "GetDYLDEntryPointWithImage(MDItemSetAttribute) rc " << (int)rc << " addr " << (void*)md_item_set_attribute_func; |
+ |
+ int irc = md_item_set_attribute_func( |
+ m, CFSTR("com_apple_backup_excludeItem"), CFSTR("com.apple.backupd")); |
+ LOG(ERROR) << "md_item_set_attribute_func() " << irc; |
+ |
+ // http://www.liquidx.net/blog/2005/09/30/metadata-spotlight-possible/ |
+ // int MDItemSetAttribute(MDItemRef item, CFStringRef attribute, CFTypeRef value); |
+ |
+ char attr[1024]; |
+ const char kExcludeAttrName[] = "com.apple.metadata:com_apple_backup_excludeItem"; |
+ ssize_t len = getxattr(file_path.value().c_str(), kExcludeAttrName, attr, sizeof(attr), 0, 0); |
+ LOG(ERROR) << "getxattr() len " << len; |
+} |
+ |
+} // namespace |
+ |
bool SetFileBackupExclusion(const FilePath& file_path) { |
+#if 0 |
+ char kExcludeAttr[] = { |
+ 0x62, 0x70, 0x6C, 0x69, 0x73, 0x74, 0x30, 0x30, 0x5F, 0x10, 0x11, 0x63, 0x6F, 0x6D, 0x2E, 0x61, |
+ 0x70, 0x70, 0x6C, 0x65, 0x2E, 0x62, 0x61, 0x63, 0x6B, 0x75, 0x70, 0x64, 0x08, 0x00, 0x00, 0x00, |
+ 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, |
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, |
+ }; |
+ const char kExcludeAttrName[] = "com.apple.metadata:com_apple_backup_excludeItem"; |
+ int status = setxattr(file_path.value().c_str(), kExcludeAttrName, kExcludeAttr, sizeof(kExcludeAttr), 0, 0); |
+ if (status != 0) { |
+ PLOG(ERROR) << "setting attribute"; |
+ return false; |
+ } |
+ |
+ char attr[1024]; |
+ ssize_t len = getxattr(file_path.value().c_str(), kExcludeAttrName, attr, sizeof(attr), 0, 0); |
+ if (len < 0) { |
+ PLOG(ERROR) << "getting attribute"; |
+ return false; |
+ } |
+ LOG(ERROR) << "len " << len; |
+ |
+ char namebuf[2048]; |
+ len = listxattr(file_path.value().c_str(), namebuf, sizeof(namebuf), 0); |
+ if (len < 0) { |
+ PLOG(ERROR) << "getting attribute"; |
+ return false; |
+ } |
+ char* b = namebuf; |
+ namebuf[sizeof(namebuf)-1] = '\0'; |
+ for (ssize_t i = 0; i < len; ) { |
+ LOG(ERROR) << "item " << (b+i); |
+ i += strlen(b+i) + 1; |
+ } |
+ return true; |
+#else |
NSString* file_path_ns = |
[NSString stringWithUTF8String:file_path.value().c_str()]; |
NSURL* file_url = [NSURL fileURLWithPath:file_path_ns]; |
@@ -216,14 +330,47 @@ bool SetFileBackupExclusion(const FilePath& file_path) { |
// can be used in non-root (or admin as above) mode. We use false so that |
// non-root (or admin) users don't get their TimeMachine drive filled up with |
// unnecessary backups. |
+ LogThings(base::mac::NSToCFCast(file_url), file_path); |
OSStatus os_err = |
CSBackupSetItemExcluded(base::mac::NSToCFCast(file_url), TRUE, FALSE); |
if (os_err != noErr) { |
OSSTATUS_DLOG(WARNING, os_err) |
<< "Failed to set backup exclusion for file '" |
<< file_path.value().c_str() << "'"; |
+ CHECK(base::PathExists(file_path)); |
+ |
+ CFStringRef r = CFURLGetString(base::mac::NSToCFCast(file_url)); |
+ const char* cs = CFStringGetCStringPtr(r, kCFStringEncodingUTF8); |
+ CHECK(cs); |
+ OSSTATUS_DLOG(WARNING, os_err) |
+ << "Failed to set backup exclusion for file '" |
+ << cs << "'"; |
+#if 0 |
+ os_err = |
+ CSBackupSetItemExcluded(base::mac::NSToCFCast(file_url), 1, 0); |
+ if (os_err != noErr) { |
+ OSSTATUS_DLOG(WARNING, os_err) |
+ << "Failed to set backup exclusion for file '" |
+ << file_path.value().c_str() << "'"; |
+ os_err = |
+ CSBackupSetItemExcluded(base::mac::NSToCFCast(file_url), 1, 1); |
+ if (os_err != noErr) { |
+ OSSTATUS_DLOG(WARNING, os_err) |
+ << "Failed to set backup exclusion for file '" |
+ << file_path.value().c_str() << "'"; |
+ os_err = |
+ CSBackupSetItemExcluded(base::mac::NSToCFCast(file_url), 0, 0); |
+ if (os_err != noErr) { |
+ OSSTATUS_DLOG(WARNING, os_err) |
+ << "Failed to set backup exclusion for file '" |
+ << file_path.value().c_str() << "'"; |
+ } |
+ } |
+ } |
+#endif |
} |
return os_err == noErr; |
+#endif |
} |
bool CheckLoginItemStatus(bool* is_hidden) { |