Version 4.2.0.1, tag libreoffice-4.2.0.1
[LibreOffice.git] / sal / osl / unx / uunxapi.cxx
bloba9f3c5ff6d2adf67ae259cc7d8812e88a408cc8c
1 /* -*- Mode: ObjC; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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>
22 #include "uunxapi.h"
23 #include "system.h"
24 #include <limits.h>
25 #include <rtl/ustring.hxx>
26 #include <osl/thread.h>
28 #ifdef ANDROID
29 #include <osl/detail/android-bootstrap.h>
30 #endif
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];
47 typedef struct {
48 NSURL *scopeURL;
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);
57 NSURL *fileURL = nil;
58 NSData *data = nil;
59 BOOL stale;
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]];
71 if (fileURL != nil)
72 data = [userDefaults dataForKey:[@"bookmarkFor:" stringByAppendingString:[fileURL absoluteString]]];
74 if (data != nil)
75 state->scopeURL = [NSURL URLByResolvingBookmarkData:data
76 options:NSURLBookmarkResolutionWithSecurityScope
77 relativeToURL:nil
78 bookmarkDataIsStale:&stale
79 error:nil];
80 if (state->scopeURL != nil)
81 [state->scopeURL startAccessingSecurityScopedResource];
83 return state;
86 static void
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];
94 free(state);
96 errno = saved_errno;
99 #else
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)
107 #endif
109 #ifdef MACOSX
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);
123 return p;
125 #endif /* MACOSX */
127 int access_u(const rtl_uString* pustrPath, int mode)
129 rtl::OString fn = OUStringToOString(pustrPath);
130 #ifdef ANDROID
131 if (fn.startsWith("/assets") &&
132 (fn[sizeof("/assets")-1] == '\0' ||
133 fn[sizeof("/assets")-1] == '/'))
135 struct stat stat;
136 if (lo_apk_lstat(fn.getStr(), &stat) == -1)
137 return -1;
138 if (mode & W_OK)
140 errno = EACCES;
141 return -1;
143 return 0;
145 #endif
147 #ifdef MACOSX
148 fn = macxp_resolveAliasAndConvert(fn);
149 #endif
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);
157 return result;
160 sal_Bool realpath_u(const rtl_uString* pustrFileName, rtl_uString** ppustrResolvedName)
162 rtl::OString fn = OUStringToOString(pustrFileName);
163 #ifdef ANDROID
164 if (fn.startsWith("/assets") &&
165 (fn[sizeof("/assets")-1] == '\0' ||
166 fn[sizeof("/assets")-1] == '/'))
168 if (access_u(pustrFileName, F_OK) == -1)
169 return sal_False;
171 rtl_uString silly(*pustrFileName);
172 rtl_uString_assign(ppustrResolvedName, &silly);
174 return sal_True;
176 #endif
178 #ifdef MACOSX
179 fn = macxp_resolveAliasAndConvert(fn);
180 #endif
182 accessFilePathState *state = prepare_to_access_file_path(fn.getStr());
184 char rp[PATH_MAX];
185 bool bRet = realpath(fn.getStr(), rp);
187 done_accessing_file_path(fn.getStr(), state);
189 if (bRet)
191 rtl::OUString resolved = rtl::OStringToOUString(rtl::OString(static_cast<sal_Char*>(rp)),
192 osl_getThreadTextEncoding());
194 rtl_uString_assign(ppustrResolvedName, resolved.pData);
196 return bRet;
199 int stat_c(const char* cpPath, struct stat* buf)
201 #ifdef ANDROID
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);
206 #endif
208 accessFilePathState *state = prepare_to_access_file_path(cpPath);
210 int result = stat(cpPath, buf);
212 done_accessing_file_path(cpPath, state);
214 return result;
217 int lstat_c(const char* cpPath, struct stat* buf)
219 #ifdef ANDROID
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);
224 #endif
226 accessFilePathState *state = prepare_to_access_file_path(cpPath);
228 int result = lstat(cpPath, buf);
230 done_accessing_file_path(cpPath, state);
232 return result;
235 int lstat_u(const rtl_uString* pustrPath, struct stat* buf)
237 rtl::OString fn = OUStringToOString(pustrPath);
239 #ifdef MACOSX
240 fn = macxp_resolveAliasAndConvert(fn);
241 #endif
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);
256 return result;
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
281 relativeToURL:nil
282 error:nil];
283 if (data != NULL)
285 [userDefaults setObject:data
286 forKey:[@"bookmarkFor:" stringByAppendingString:[url absoluteString]]];
290 #endif
292 done_accessing_file_path(cpPath, state);
294 return result;
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);
305 return result;
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);
321 #ifdef MACOSX
322 fn = macxp_resolveAliasAndConvert(fn);
323 #endif
325 accessFilePathState *state = prepare_to_access_file_path(fn.getStr());
327 int result = ftruncate(fd, uSize);
329 done_accessing_file_path(fn.getStr(), state);
331 return result;
334 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */