Blender V5.0
storage_apple.mm
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2020 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
10
11#import <Foundation/Foundation.h>
12#include <string>
13#include <sys/xattr.h>
14
15#include "BLI_fileops.h"
16#include "BLI_path_utils.hh"
17#include "BLI_string.h"
18
19/* Extended file attribute used by OneDrive to mark placeholder files. */
20static const char *ONEDRIVE_RECALLONOPEN_ATTRIBUTE = "com.microsoft.OneDrive.RecallOnOpen";
21
22bool BLI_file_alias_target(const char *filepath,
23 /* False alarm by clang-tidy: #getFileSystemRepresentation
24 * changes the return value argument. */
25 /* NOLINTNEXTLINE: readability-non-const-parameter. */
26 char r_targetpath[FILE_MAXDIR])
27{
28 /* clang-format off */
29 @autoreleasepool {
30 /* clang-format on */
31 NSError *error = nil;
32 NSURL *shortcutURL = [[NSURL alloc] initFileURLWithFileSystemRepresentation:filepath
33 isDirectory:NO
34 relativeToURL:nil];
35
36 /* Note, NSURLBookmarkResolutionWithoutMounting keeps blender from crashing when an alias can't
37 * be mounted */
38 NSURL *targetURL = [NSURL URLByResolvingAliasFileAtURL:shortcutURL
39 options:NSURLBookmarkResolutionWithoutUI |
40 NSURLBookmarkResolutionWithoutMounting
41 error:&error];
42 const BOOL isSame = [shortcutURL isEqual:targetURL] and
43 ([[[shortcutURL path] stringByStandardizingPath]
44 isEqualToString:[[targetURL path] stringByStandardizingPath]]);
45
46 if (targetURL == nil) {
47 return false;
48 }
49 if (isSame) {
50 [targetURL getFileSystemRepresentation:r_targetpath maxLength:FILE_MAXDIR];
51 return false;
52 }
53 /* Note that the `if` condition may also change the value of `r_targetpath`. */
54 if (![targetURL getFileSystemRepresentation:r_targetpath maxLength:FILE_MAXDIR]) {
55 return false;
56 }
57 }
58
59 return true;
60}
61
69static bool find_attribute(const std::string &attributes, const char *search_attribute)
70{
71 /* Attributes is a list of consecutive null-terminated strings. */
72 const char *end = attributes.data() + attributes.size();
73 for (const char *item = attributes.data(); item < end; item += strlen(item) + 1) {
74 if (STREQ(item, search_attribute)) {
75 return true;
76 }
77 }
78
79 return false;
80}
81
88static bool test_onedrive_file_is_placeholder(const char *path)
89{
90 /* NOTE: Currently only checking for the "com.microsoft.OneDrive.RecallOnOpen" extended file
91 * attribute. In theory this attribute can also be set on files that aren't located inside a
92 * OneDrive folder. Maybe additional checks are required? */
93
94 /* Get extended file attributes */
95 ssize_t size = listxattr(path, nullptr, 0, XATTR_NOFOLLOW);
96 if (size < 1) {
97 return false;
98 }
99
100 std::string attributes(size, '\0');
101 size = listxattr(path, attributes.data(), size, XATTR_NOFOLLOW);
102 /* In case listxattr() has failed the second time it's called. */
103 if (size < 1) {
104 return false;
105 }
106
107 /* Check for presence of 'com.microsoft.OneDrive.RecallOnOpen' attribute. */
109}
110
117static bool test_file_is_offline(const char *path)
118{
119 /* Logic for additional cloud storage providers could be added in the future. */
121}
122
124{
125 int ret = 0;
126
127 /* clang-format off */
128 @autoreleasepool {
129 /* clang-format on */
130 NSURL *fileURL = [[[NSURL alloc] initFileURLWithFileSystemRepresentation:path
131 isDirectory:NO
132 relativeToURL:nil] autorelease];
133
134 /* Querying NSURLIsReadableKey and NSURLIsWritableKey keys for OneDrive placeholder files
135 * triggers their unwanted download. */
136 NSArray *resourceKeys = nullptr;
137 const bool is_offline = test_file_is_offline(path);
138
139 if (is_offline) {
140 resourceKeys = @[ NSURLIsSymbolicLinkKey, NSURLIsAliasFileKey, NSURLIsHiddenKey ];
141 }
142 else {
143 resourceKeys = @[
144 NSURLIsSymbolicLinkKey,
145 NSURLIsAliasFileKey,
146 NSURLIsHiddenKey,
147 NSURLIsReadableKey,
148 NSURLIsWritableKey
149 ];
150 }
151
152 NSDictionary *resourceKeyValues = [fileURL resourceValuesForKeys:resourceKeys error:nil];
153
154 const bool is_symlink = [resourceKeyValues[(void)(@"@%"), NSURLIsSymbolicLinkKey] boolValue];
155 const bool is_alias = [resourceKeyValues[(void)(@"@%"), NSURLIsAliasFileKey] boolValue] &&
156 !is_symlink;
157 const bool is_hidden = [resourceKeyValues[(void)(@"@%"), NSURLIsHiddenKey] boolValue];
158 const bool is_readable = is_offline ||
159 [resourceKeyValues[(void)(@"@%"), NSURLIsReadableKey] boolValue];
160 const bool is_writable = is_offline ||
161 [resourceKeyValues[(void)(@"@%"), NSURLIsWritableKey] boolValue];
162
163 if (is_symlink) {
165 }
166 if (is_alias) {
168 }
169 if (is_hidden) {
171 }
172 if (is_readable && !is_writable) {
174 }
175 if (!is_readable) {
177 }
178 if (is_offline) {
180 }
181 }
182
183 return (eFileAttributes)ret;
184}
185
186char *BLI_current_working_dir(char *dir, const size_t maxncpy)
187{
188 /* Can't just copy to the *dir pointer, as [path getCString gets grumpy. */
189 char path_expanded[PATH_MAX];
190 @autoreleasepool {
191 NSString *path = [[NSFileManager defaultManager] currentDirectoryPath];
192 const size_t length = maxncpy > PATH_MAX ? PATH_MAX : maxncpy;
193 [path getCString:path_expanded maxLength:length encoding:NSUTF8StringEncoding];
194 BLI_strncpy(dir, path_expanded, maxncpy);
195 return dir;
196 }
197}
198
199bool BLI_change_working_dir(const char *dir)
200{
201 @autoreleasepool {
202 NSString *path = [[NSString alloc] initWithUTF8String:dir];
203 if ([[NSFileManager defaultManager] changeCurrentDirectoryPath:path] == YES) {
204 return true;
205 }
206 return false;
207 }
208}
File and directory operations.
eFileAttributes
@ FILE_ATTR_ALIAS
@ FILE_ATTR_HIDDEN
@ FILE_ATTR_READONLY
@ FILE_ATTR_SYMLINK
@ FILE_ATTR_SYSTEM
@ FILE_ATTR_OFFLINE
#define PATH_MAX
Definition BLI_fileops.h:26
#define FILE_MAXDIR
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, size_t dst_maxncpy) ATTR_NONNULL(1
#define STREQ(a, b)
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
CCL_NAMESPACE_BEGIN struct Options options
float length(VecOp< float, D >) RET
static void error(const char *str)
return ret
bool BLI_change_working_dir(const char *dir)
eFileAttributes BLI_file_attributes(const char *path)
static const char * ONEDRIVE_RECALLONOPEN_ATTRIBUTE
bool BLI_file_alias_target(const char *filepath, char r_targetpath[FILE_MAXDIR])
static bool test_onedrive_file_is_placeholder(const char *path)
static bool test_file_is_offline(const char *path)
char * BLI_current_working_dir(char *dir, const size_t maxncpy)
static bool find_attribute(const std::string &attributes, const char *search_attribute)