Version 4.3.0.0.beta1, tag libreoffice-4.3.0.0.beta1
[LibreOffice.git] / sal / osl / unx / uunxapi.cxx
blob6fb75a1d68e15cf93415e23d3e2793f8392883e8
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 const & 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 return 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 == "/assets" || fn.startsWith("/assets/"))
133 struct stat stat;
134 if (lo_apk_lstat(fn.getStr(), &stat) == -1)
135 return -1;
136 if (mode & W_OK)
138 errno = EACCES;
139 return -1;
141 return 0;
143 #endif
145 #ifdef MACOSX
146 fn = macxp_resolveAliasAndConvert(fn);
147 #endif
149 accessFilePathState *state = prepare_to_access_file_path(fn.getStr());
151 int result = access(fn.getStr(), mode);
153 done_accessing_file_path(fn.getStr(), state);
155 return result;
158 sal_Bool realpath_u(const rtl_uString* pustrFileName, rtl_uString** ppustrResolvedName)
160 rtl::OString fn = OUStringToOString(pustrFileName);
161 #ifdef ANDROID
162 if (fn == "/assets" || fn.startsWith("/assets/"))
164 if (access_u(pustrFileName, F_OK) == -1)
165 return sal_False;
167 rtl_uString silly(*pustrFileName);
168 rtl_uString_assign(ppustrResolvedName, &silly);
170 return sal_True;
172 #endif
174 #ifdef MACOSX
175 fn = macxp_resolveAliasAndConvert(fn);
176 #endif
178 accessFilePathState *state = prepare_to_access_file_path(fn.getStr());
180 char rp[PATH_MAX];
181 bool bRet = realpath(fn.getStr(), rp);
183 done_accessing_file_path(fn.getStr(), state);
185 if (bRet)
187 rtl::OUString resolved = rtl::OStringToOUString(rtl::OString(static_cast<sal_Char*>(rp)),
188 osl_getThreadTextEncoding());
190 rtl_uString_assign(ppustrResolvedName, resolved.pData);
192 return bRet;
195 int stat_c(const char* cpPath, struct stat* buf)
197 #ifdef ANDROID
198 if (strncmp(cpPath, "/assets", sizeof("/assets")-1) == 0 &&
199 (cpPath[sizeof("/assets")-1] == '\0' ||
200 cpPath[sizeof("/assets")-1] == '/'))
201 return lo_apk_lstat(cpPath, buf);
202 #endif
204 accessFilePathState *state = prepare_to_access_file_path(cpPath);
206 int result = stat(cpPath, buf);
208 done_accessing_file_path(cpPath, state);
210 return result;
213 int lstat_c(const char* cpPath, struct stat* buf)
215 #ifdef ANDROID
216 if (strncmp(cpPath, "/assets", sizeof("/assets")-1) == 0 &&
217 (cpPath[sizeof("/assets")-1] == '\0' ||
218 cpPath[sizeof("/assets")-1] == '/'))
219 return lo_apk_lstat(cpPath, buf);
220 #endif
222 accessFilePathState *state = prepare_to_access_file_path(cpPath);
224 int result = lstat(cpPath, buf);
226 done_accessing_file_path(cpPath, state);
228 return result;
231 int lstat_u(const rtl_uString* pustrPath, struct stat* buf)
233 rtl::OString fn = OUStringToOString(pustrPath);
235 #ifdef MACOSX
236 fn = macxp_resolveAliasAndConvert(fn);
237 #endif
239 return lstat_c(fn.getStr(), buf);
242 int mkdir_u(const rtl_uString* path, mode_t mode)
244 rtl::OString fn = OUStringToOString(path);
246 accessFilePathState *state = prepare_to_access_file_path(fn.getStr());
248 int result = mkdir(OUStringToOString(path).getStr(), mode);
250 done_accessing_file_path(fn.getStr(), state);
252 return result;
255 int open_c(const char *cpPath, int oflag, int mode)
257 accessFilePathState *state = prepare_to_access_file_path(cpPath);
259 int result = open(cpPath, oflag, mode);
261 #if defined(MACOSX) && MAC_OS_X_VERSION_MIN_REQUIRED >= 1070 && HAVE_FEATURE_MACOSX_SANDBOX
262 if (result != -1 && (oflag & O_CREAT) && (oflag & O_EXCL))
264 // A new file was created. Check if it is outside the sandbox.
265 // (In that case it must be one the user selected as export or
266 // save destination in a file dialog, otherwise we wouldn't
267 // have been able to crete it.) Create and store a security
268 // scoped bookmark for it so that we can access the file in
269 // the future, too. (For the "Recent Files" functionality.)
270 const char *sandbox = [NSHomeDirectory() UTF8String];
271 if (!(strncmp(sandbox, cpPath, strlen(sandbox)) == 0 &&
272 cpPath[strlen(sandbox)] == '/'))
274 NSURL *url = [NSURL fileURLWithPath:[NSString stringWithUTF8String:cpPath]];
275 NSData *data = [url bookmarkDataWithOptions:NSURLBookmarkCreationWithSecurityScope
276 includingResourceValuesForKeys:nil
277 relativeToURL:nil
278 error:nil];
279 if (data != NULL)
281 [userDefaults setObject:data
282 forKey:[@"bookmarkFor:" stringByAppendingString:[url absoluteString]]];
286 #endif
288 done_accessing_file_path(cpPath, state);
290 return result;
293 int utime_c(const char *cpPath, struct utimbuf *times)
295 accessFilePathState *state = prepare_to_access_file_path(cpPath);
297 int result = utime(cpPath, times);
299 done_accessing_file_path(cpPath, state);
301 return result;
304 int ftruncate_with_name(int fd, sal_uInt64 uSize, rtl_String* path)
306 /* When sandboxed on OS X, ftruncate(), even if it takes an
307 * already open file descriptor which was retuned from an open()
308 * call already checked by the sandbox, still requires a security
309 * scope bookmark for the file to be active in case the file is
310 * one that the sandbox doesn't otherwise allow access to. Luckily
311 * LibreOffice usually calls ftruncate() through the helpful C++
312 * abstraction layer that keeps the pathname around.
315 rtl::OString fn = rtl::OString(path);
317 #ifdef MACOSX
318 fn = macxp_resolveAliasAndConvert(fn);
319 #endif
321 accessFilePathState *state = prepare_to_access_file_path(fn.getStr());
323 int result = ftruncate(fd, uSize);
325 done_accessing_file_path(fn.getStr(), state);
327 return result;
330 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */