diff options
-rw-r--r-- | source/blender/blenlib/BLI_fileops.h | 1 | ||||
-rw-r--r-- | source/blender/blenlib/CMakeLists.txt | 7 | ||||
-rw-r--r-- | source/blender/blenlib/intern/storage.c | 32 | ||||
-rw-r--r-- | source/blender/blenlib/intern/storage_apple.mm | 96 | ||||
-rw-r--r-- | source/blender/editors/space_file/file_ops.c | 4 | ||||
-rw-r--r-- | source/blender/editors/space_file/filelist.c | 31 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_space_types.h | 3 |
7 files changed, 153 insertions, 21 deletions
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 + entry->typeflag = ED_path_extension_type(entry->redirection_path); + } + } #ifndef WIN32 /* Set linux-style dot files hidden too. */ diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h index d3cce8d1510..3020e5a1708 100644 --- a/source/blender/makesdna/DNA_space_types.h +++ b/source/blender/makesdna/DNA_space_types.h @@ -955,7 +955,10 @@ typedef struct FileDirEntry { /** ID type, in case typeflag has FILE_TYPE_BLENDERLIB set. */ int blentype; + /* Path to item that is relative to current folder root. */ char *relpath; + /** Optional argument for shortcuts, aliases etc. */ + char *redirection_path; /** TODO: make this a real ID pointer? */ void *poin; |