[Bf-blender-cvs] [afb1a64ccb8] master: Fix T60682: adds macOS alias redirection for directories

Brecht Van Lommel noreply at git.blender.org
Thu Mar 26 19:58:21 CET 2020


Commit: afb1a64ccb81b7ed792f64151986f40f53af8da5
Author: Brecht Van Lommel
Date:   Thu Mar 26 17:52:41 2020 +0100
Branches: master
https://developer.blender.org/rBafb1a64ccb81b7ed792f64151986f40f53af8da5

Fix T60682: adds macOS alias redirection for directories

This adds support for macOS aliases in addition to symlinks. It also adds
support for hidden, readonly and system file attributes.

Contributed by Ankit (ankitm) with modifications by me.

Differential Revision: https://developer.blender.org/D6679

===================================================================

M	source/blender/blenlib/BLI_fileops.h
M	source/blender/blenlib/CMakeLists.txt
M	source/blender/blenlib/intern/storage.c
A	source/blender/blenlib/intern/storage_apple.mm
M	source/blender/editors/space_file/file_ops.c
M	source/blender/editors/space_file/filelist.c
M	source/blender/makesdna/DNA_space_types.h

===================================================================

diff --git a/source/blender/blenlib/BLI_fileops.h b/source/blender/blenlib/BLI_fileops.h
index 89f7d01ffd6..4eb6f184a76 100644
--- a/source/blender/blenlib/BLI_fileops.h
+++ b/source/blender/blenlib/BLI_fileops.h
@@ -147,6 +147,7 @@ int BLI_access(const char *filename, int mode) ATTR_WARN_UNUSED_RESULT ATTR_NONN
 
 bool BLI_file_is_writable(const char *file) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
 bool BLI_file_touch(const char *file) ATTR_NONNULL();
+bool BLI_file_alias_target(char *target, const char *filepath);
 
 #if 0 /* UNUSED */
 int BLI_file_gzip(const char *from, const char *to) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
diff --git a/source/blender/blenlib/CMakeLists.txt b/source/blender/blenlib/CMakeLists.txt
index 1de0c192a20..5f5145cab70 100644
--- a/source/blender/blenlib/CMakeLists.txt
+++ b/source/blender/blenlib/CMakeLists.txt
@@ -277,6 +277,13 @@ if(WIN32)
   )
 endif()
 
+
+if(APPLE)
+  list(APPEND SRC
+    intern/storage_apple.mm
+  )
+endif()
+
 if(UNIX AND NOT APPLE)
   list(APPEND LIB
     bf_intern_libc_compat
diff --git a/source/blender/blenlib/intern/storage.c b/source/blender/blenlib/intern/storage.c
index da80777e6d6..7274a15661a 100644
--- a/source/blender/blenlib/intern/storage.c
+++ b/source/blender/blenlib/intern/storage.c
@@ -226,11 +226,12 @@ size_t BLI_file_size(const char *path)
   return stats.st_size;
 }
 
+#ifndef __APPLE__
 eFileAttributes BLI_file_attributes(const char *path)
 {
   int ret = 0;
 
-#ifdef WIN32
+#  ifdef WIN32
   wchar_t wline[FILE_MAXDIR];
   BLI_strncpy_wchar_from_utf8(wline, path, ARRAY_SIZE(wline));
   DWORD attr = GetFileAttributesW(wline);
@@ -265,19 +266,9 @@ eFileAttributes BLI_file_attributes(const char *path)
     ret |= FILE_ATTR_REPARSE_POINT;
   }
 
-#endif
-
-#ifdef __APPLE__
-
-  /* TODO:
-   * If Hidden (Invisible) set FILE_ATTR_HIDDEN
-   * If Locked set FILE_ATTR_READONLY
-   * If Restricted set FILE_ATTR_RESTRICTED
-   */
-
-#endif
+#  endif
 
-#ifdef __linux__
+#  ifdef __linux__
   UNUSED_VARS(path);
 
   /* TODO:
@@ -285,10 +276,23 @@ eFileAttributes BLI_file_attributes(const char *path)
    * If Archived set FILE_ATTR_ARCHIVE
    */
 
-#endif
+#  endif
 
   return ret;
 }
+#endif
+
+/**
+ * Returns the target path of a file-based redirection, like Mac Alias or Win32 Shortcut file.
+ */
+#ifndef __APPLE__
+bool BLI_file_alias_target(char UNUSED(target[FILE_MAXDIR]), const char *UNUSED(filepath))
+{
+  /* TODO: Find target in Win32 Shortcut - Shell Link (.lnk) file.
+   * Format: https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-shllink/ */
+  return false;
+}
+#endif
 
 /**
  * Returns the st_mode from stat-ing the specified path name, or 0 if stat fails
diff --git a/source/blender/blenlib/intern/storage_apple.mm b/source/blender/blenlib/intern/storage_apple.mm
new file mode 100644
index 00000000000..7cb8ca28e24
--- /dev/null
+++ b/source/blender/blenlib/intern/storage_apple.mm
@@ -0,0 +1,96 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2020 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup bli
+ *
+ * macOS specific implementations for storage.c.
+ */
+
+#import <Foundation/Foundation.h>
+
+#include "BLI_fileops.h"
+#include "BLI_path_util.h"
+
+bool BLI_file_alias_target(char targetpath[FILE_MAXDIR], const char *filepath)
+{
+  @autoreleasepool {
+    NSError *error = nil;
+    NSURL *shortcutURL = [[NSURL alloc] initFileURLWithFileSystemRepresentation:filepath
+                                                                    isDirectory:NO
+                                                                  relativeToURL:nil];
+    NSURL *targetURL = [NSURL URLByResolvingAliasFileAtURL:shortcutURL
+                                                   options:NSURLBookmarkResolutionWithoutUI
+                                                     error:&error];
+    BOOL isSame = [shortcutURL isEqual:targetURL] and
+                  ([[[shortcutURL path] stringByStandardizingPath]
+                      isEqualToString:[[targetURL path] stringByStandardizingPath]]);
+
+    if (targetURL == nil) {
+      return false;
+    }
+    else if (isSame) {
+      [targetURL getFileSystemRepresentation:targetpath maxLength:FILE_MAXDIR];
+      return false;
+    }
+    else if (![targetURL getFileSystemRepresentation:targetpath maxLength:FILE_MAXDIR]) {
+      return false;
+    }
+
+    NSNumber *targetIsDirectory = 0;
+    [targetURL getResourceValue:&targetIsDirectory forKey:NSURLIsDirectoryKey error:nil];
+  }
+
+  return true;
+}
+
+eFileAttributes BLI_file_attributes(const char *path)
+{
+  int ret = 0;
+
+  @autoreleasepool {
+    NSURL *fileURL = [[NSURL alloc] initFileURLWithFileSystemRepresentation:path
+                                                                isDirectory:NO
+                                                              relativeToURL:nil];
+    NSArray *resourceKeys =
+        @[ NSURLIsAliasFileKey, NSURLIsHiddenKey, NSURLIsReadableKey, NSURLIsWritableKey ];
+
+    NSDictionary *resourceKeyValues = [fileURL resourceValuesForKeys:resourceKeys error:nil];
+
+    const bool is_alias = [resourceKeyValues[(void)(@"@%"), NSURLIsAliasFileKey] boolValue];
+    const bool is_hidden = [resourceKeyValues[(void)(@"@%"), NSURLIsHiddenKey] boolValue];
+    const bool is_readable = [resourceKeyValues[(void)(@"@%"), NSURLIsReadableKey] boolValue];
+    const bool is_writable = [resourceKeyValues[(void)(@"@%"), NSURLIsWritableKey] boolValue];
+
+    if (is_alias) {
+      ret |= FILE_ATTR_ALIAS;
+    }
+    if (is_hidden) {
+      ret |= FILE_ATTR_HIDDEN;
+    }
+    if (is_readable && !is_writable) {
+      ret |= FILE_ATTR_READONLY;
+    }
+    if (is_readable) {
+      ret |= FILE_ATTR_SYSTEM;
+    }
+  }
+
+  return (eFileAttributes)ret;
+}
diff --git a/source/blender/editors/space_file/file_ops.c b/source/blender/editors/space_file/file_ops.c
index a34fcba99be..5258892d55d 100644
--- a/source/blender/editors/space_file/file_ops.c
+++ b/source/blender/editors/space_file/file_ops.c
@@ -1634,7 +1634,9 @@ static int file_exec(bContext *C, wmOperator *exec_op)
       BLI_path_append(sfile->params->dir, sizeof(sfile->params->dir) - 1, file->relpath);
       BLI_add_slash(sfile->params->dir);
     }
-
+    if (file->redirection_path) {
+      STRNCPY(sfile->params->dir, file->redirection_path);
+    }
     ED_file_change_dir(C);
   }
   /* opening file - sends events now, so things get handled on windowqueue level */
diff --git a/source/blender/editors/space_file/filelist.c b/source/blender/editors/space_file/filelist.c
index caab1ac74d0..dec38501d38 100644
--- a/source/blender/editors/space_file/filelist.c
+++ b/source/blender/editors/space_file/filelist.c
@@ -210,12 +210,13 @@ typedef struct FileListInternEntry {
   int blentype;
 
   char *relpath;
+  /** Optional argument for shortcuts, aliases etc. */
+  char *redirection_path;
   /** not strictly needed, but used during sorting, avoids to have to recompute it there... */
   char *name;
 
   /** Defined in BLI_fileops.h */
   eFileAttributes attributes;
-
   BLI_stat_t st;
 } FileListInternEntry;
 
@@ -961,12 +962,12 @@ ImBuf *filelist_getimage(struct FileList *filelist, const int index)
   return file->image;
 }
 
-static ImBuf *filelist_geticon_image_ex(const unsigned int typeflag, const char *relpath)
+static ImBuf *filelist_geticon_image_ex(FileDirEntry *file)
 {
   ImBuf *ibuf = NULL;
 
-  if (typeflag & FILE_TYPE_DIR) {
-    if (FILENAME_IS_PARENT(relpath)) {
+  if (file->typeflag & FILE_TYPE_DIR) {
+    if (FILENAME_IS_PARENT(file->relpath)) {
       ibuf = gSpecialFileImages[SPECIAL_IMG_PARENT];
     }
     else {
@@ -983,8 +984,7 @@ static ImBuf *filelist_geticon_image_ex(const unsigned int typeflag, const char
 ImBuf *filelist_geticon_image(struct FileList *filelist, const int index)
 {
   FileDirEntry *file = filelist_geticon_get_file(filelist, index);
-
-  return filelist_geticon_image_ex(file->typeflag, file->relpath);
+  return filelist_geticon_image_ex(file);
 }
 
 static int filelist_geticon_ex(FileDirEntry *file,
@@ -1170,6 +1170,9 @@ static void filelist_entry_clear(FileDirEntry *entry)
   if (entry->relpath) {
     MEM_freeN(entry->relpath);
   }
+  if (entry->redirection_path) {
+    MEM_freeN(entry->redirection_path);
+  }
   if (entry->image) {
     IMB_freeImBuf(entry->image);
   }
@@ -1239,6 +1242,9 @@ static void filelist_intern_entry_free(FileListInternEntry *entry)
   if (entry->relpath) {
     MEM_freeN(entry->relpath);
   }
+  if (entry->redirection_path) {
+    MEM_freeN(entry->redirection_path);
+  }
   if (entry->name) {
     MEM_freeN(entry->name);
   }
@@ -1690,6 +1696,9 @@ static FileDirEntry *filelist_file_create_entry(FileList *filelist, const int in
   ret->blentype = entry->blentype;
   ret->typeflag = entry->typeflag;
   ret->attributes = entry->attributes;
+  if (entry->redirection_path) {
+    ret->redirection_path = BLI_strdup(entry->redirection_path);
+  }
   BLI_addtail(&cache->cached_entries, ret);
   return ret;
 }
@@ -2523,6 +2532,16 @@ static int filelist_readjob_list_dir(const char *root,
 
       /* Set file attributes. */
       entry->attributes = BLI_file_attributes(path);
+      if (entry->attributes & FILE_ATTR_ALIAS) {
+        entry->redirection_path = MEM_callocN(FILE_MAXDIR, __func__);
+        if (BLI_file_alias_target(entry->redirection_path, path)) {
+          if (BLI_is_dir(entry->redirection_path)) {
+            entry->typeflag = FILE_TYPE_DIR;
+          }
+          else
+         

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list