1 /* -*- Mode: ObjC; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <config_features.h>
25 #include <rtl/ustring.hxx>
26 #include <osl/thread.h>
29 #include <osl/detail/android-bootstrap.h>
32 inline rtl::OString
OUStringToOString(const rtl_uString
* s
)
34 return rtl::OUStringToOString(rtl::OUString(const_cast<rtl_uString
*>(s
)),
35 osl_getThreadTextEncoding());
38 #if defined(MACOSX) && MAC_OS_X_VERSION_MIN_REQUIRED >= 1070 && HAVE_FEATURE_MACOSX_SANDBOX
40 static NSUserDefaults
*userDefaults
= NULL
;
42 static void get_user_defaults()
44 userDefaults
= [NSUserDefaults standardUserDefaults
];
49 NSAutoreleasePool
*pool
;
50 } accessFilePathState
;
52 static accessFilePathState
*
53 prepare_to_access_file_path( const char *cpFilePath
)
55 static pthread_once_t once
= PTHREAD_ONCE_INIT
;
56 pthread_once(&once
, &get_user_defaults
);
60 accessFilePathState
*state
;
62 // If malloc() fails we are screwed anyway
63 state
= (accessFilePathState
*) malloc(sizeof(accessFilePathState
));
65 state
->pool
= [[NSAutoreleasePool alloc
] init
];
66 state
->scopeURL
= nil
;
68 if (userDefaults
!= nil
)
69 fileURL
= [NSURL fileURLWithPath
:[NSString stringWithUTF8String
:cpFilePath
]];
72 data
= [userDefaults dataForKey
:[@
"bookmarkFor:" stringByAppendingString
:[fileURL absoluteString
]]];
75 state
->scopeURL
= [NSURL URLByResolvingBookmarkData
:data
76 options
:NSURLBookmarkResolutionWithSecurityScope
78 bookmarkDataIsStale
:&stale
80 if (state
->scopeURL
!= nil
)
81 [state
->scopeURL startAccessingSecurityScopedResource
];
87 done_accessing_file_path( const char * /*cpFilePath*/, accessFilePathState
*state
)
89 int saved_errno
= errno
;
91 if (state
->scopeURL
!= nil
)
92 [state
->scopeURL stopAccessingSecurityScopedResource
];
93 [state
->pool release
];
101 typedef void accessFilePathState
;
103 #define prepare_to_access_file_path( cpFilePath ) NULL
105 #define done_accessing_file_path( cpFilePath, state ) ((void) cpFilePath, (void) state)
111 * Helper function for resolving Mac native alias files (not the same as unix alias files)
112 * and to return the resolved alias as rtl::OString
114 static rtl::OString
macxp_resolveAliasAndConvert(rtl::OString p
)
116 sal_Char path
[PATH_MAX
];
117 if (p
.getLength() < PATH_MAX
)
119 strcpy(path
, p
.getStr());
120 macxp_resolveAlias(path
, PATH_MAX
);
121 p
= rtl::OString(path
);
127 int access_u(const rtl_uString
* pustrPath
, int mode
)
129 rtl::OString fn
= OUStringToOString(pustrPath
);
131 if (fn
.startsWith("/assets") &&
132 (fn
[sizeof("/assets")-1] == '\0' ||
133 fn
[sizeof("/assets")-1] == '/'))
136 if (lo_apk_lstat(fn
.getStr(), &stat
) == -1)
148 fn
= macxp_resolveAliasAndConvert(fn
);
151 accessFilePathState
*state
= prepare_to_access_file_path(fn
.getStr());
153 int result
= access(fn
.getStr(), mode
);
155 done_accessing_file_path(fn
.getStr(), state
);
160 sal_Bool
realpath_u(const rtl_uString
* pustrFileName
, rtl_uString
** ppustrResolvedName
)
162 rtl::OString fn
= OUStringToOString(pustrFileName
);
164 if (fn
.startsWith("/assets") &&
165 (fn
[sizeof("/assets")-1] == '\0' ||
166 fn
[sizeof("/assets")-1] == '/'))
168 if (access_u(pustrFileName
, F_OK
) == -1)
171 rtl_uString
silly(*pustrFileName
);
172 rtl_uString_assign(ppustrResolvedName
, &silly
);
179 fn
= macxp_resolveAliasAndConvert(fn
);
182 accessFilePathState
*state
= prepare_to_access_file_path(fn
.getStr());
185 bool bRet
= realpath(fn
.getStr(), rp
);
187 done_accessing_file_path(fn
.getStr(), state
);
191 rtl::OUString resolved
= rtl::OStringToOUString(rtl::OString(static_cast<sal_Char
*>(rp
)),
192 osl_getThreadTextEncoding());
194 rtl_uString_assign(ppustrResolvedName
, resolved
.pData
);
199 int stat_c(const char* cpPath
, struct stat
* buf
)
202 if (strncmp(cpPath
, "/assets", sizeof("/assets")-1) == 0 &&
203 (cpPath
[sizeof("/assets")-1] == '\0' ||
204 cpPath
[sizeof("/assets")-1] == '/'))
205 return lo_apk_lstat(cpPath
, buf
);
208 accessFilePathState
*state
= prepare_to_access_file_path(cpPath
);
210 int result
= stat(cpPath
, buf
);
212 done_accessing_file_path(cpPath
, state
);
217 int lstat_c(const char* cpPath
, struct stat
* buf
)
220 if (strncmp(cpPath
, "/assets", sizeof("/assets")-1) == 0 &&
221 (cpPath
[sizeof("/assets")-1] == '\0' ||
222 cpPath
[sizeof("/assets")-1] == '/'))
223 return lo_apk_lstat(cpPath
, buf
);
226 accessFilePathState
*state
= prepare_to_access_file_path(cpPath
);
228 int result
= lstat(cpPath
, buf
);
230 done_accessing_file_path(cpPath
, state
);
235 int lstat_u(const rtl_uString
* pustrPath
, struct stat
* buf
)
237 rtl::OString fn
= OUStringToOString(pustrPath
);
240 fn
= macxp_resolveAliasAndConvert(fn
);
243 return lstat_c(fn
.getStr(), buf
);
246 int mkdir_u(const rtl_uString
* path
, mode_t mode
)
248 rtl::OString fn
= OUStringToOString(path
);
250 accessFilePathState
*state
= prepare_to_access_file_path(fn
.getStr());
252 int result
= mkdir(OUStringToOString(path
).getStr(), mode
);
254 done_accessing_file_path(fn
.getStr(), state
);
259 int open_c(const char *cpPath
, int oflag
, int mode
)
261 accessFilePathState
*state
= prepare_to_access_file_path(cpPath
);
263 int result
= open(cpPath
, oflag
, mode
);
265 #if defined(MACOSX) && MAC_OS_X_VERSION_MIN_REQUIRED >= 1070 && HAVE_FEATURE_MACOSX_SANDBOX
266 if (result
!= -1 && (oflag
& O_CREAT
) && (oflag
& O_EXCL
))
268 // A new file was created. Check if it is outside the sandbox.
269 // (In that case it must be one the user selected as export or
270 // save destination in a file dialog, otherwise we wouldn't
271 // have been able to crete it.) Create and store a security
272 // scoped bookmark for it so that we can access the file in
273 // the future, too. (For the "Recent Files" functionality.)
274 const char *sandbox
= [NSHomeDirectory() UTF8String
];
275 if (!(strncmp(sandbox
, cpPath
, strlen(sandbox
)) == 0 &&
276 cpPath
[strlen(sandbox
)] == '/'))
278 NSURL
*url
= [NSURL fileURLWithPath
:[NSString stringWithUTF8String
:cpPath
]];
279 NSData
*data
= [url bookmarkDataWithOptions
:NSURLBookmarkCreationWithSecurityScope
280 includingResourceValuesForKeys
:nil
285 [userDefaults setObject
:data
286 forKey
:[@
"bookmarkFor:" stringByAppendingString
:[url absoluteString
]]];
292 done_accessing_file_path(cpPath
, state
);
297 int utime_c(const char *cpPath
, struct utimbuf
*times
)
299 accessFilePathState
*state
= prepare_to_access_file_path(cpPath
);
301 int result
= utime(cpPath
, times
);
303 done_accessing_file_path(cpPath
, state
);
308 int ftruncate_with_name(int fd
, sal_uInt64 uSize
, rtl_String
* path
)
310 /* When sandboxed on OS X, ftruncate(), even if it takes an
311 * already open file descriptor which was retuned from an open()
312 * call already checked by the sandbox, still requires a security
313 * scope bookmark for the file to be active in case the file is
314 * one that the sandbox doesn't otherwise allow access to. Luckily
315 * LibreOffice usually calls ftruncate() through the helpful C++
316 * abstraction layer that keeps the pathname around.
319 rtl::OString fn
= rtl::OString(path
);
322 fn
= macxp_resolveAliasAndConvert(fn
);
325 accessFilePathState
*state
= prepare_to_access_file_path(fn
.getStr());
327 int result
= ftruncate(fd
, uSize
);
329 done_accessing_file_path(fn
.getStr(), state
);
334 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */