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
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
);
127 int access_u(const rtl_uString
* pustrPath
, int mode
)
129 rtl::OString fn
= OUStringToOString(pustrPath
);
131 if (fn
== "/assets" || fn
.startsWith("/assets/"))
134 if (lo_apk_lstat(fn
.getStr(), &stat
) == -1)
146 fn
= macxp_resolveAliasAndConvert(fn
);
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
);
158 sal_Bool
realpath_u(const rtl_uString
* pustrFileName
, rtl_uString
** ppustrResolvedName
)
160 rtl::OString fn
= OUStringToOString(pustrFileName
);
162 if (fn
== "/assets" || fn
.startsWith("/assets/"))
164 if (access_u(pustrFileName
, F_OK
) == -1)
167 rtl_uString
silly(*pustrFileName
);
168 rtl_uString_assign(ppustrResolvedName
, &silly
);
175 fn
= macxp_resolveAliasAndConvert(fn
);
178 accessFilePathState
*state
= prepare_to_access_file_path(fn
.getStr());
181 bool bRet
= realpath(fn
.getStr(), rp
);
183 done_accessing_file_path(fn
.getStr(), state
);
187 rtl::OUString resolved
= rtl::OStringToOUString(rtl::OString(static_cast<sal_Char
*>(rp
)),
188 osl_getThreadTextEncoding());
190 rtl_uString_assign(ppustrResolvedName
, resolved
.pData
);
195 int stat_c(const char* cpPath
, struct stat
* buf
)
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
);
204 accessFilePathState
*state
= prepare_to_access_file_path(cpPath
);
206 int result
= stat(cpPath
, buf
);
208 done_accessing_file_path(cpPath
, state
);
213 int lstat_c(const char* cpPath
, struct stat
* buf
)
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
);
222 accessFilePathState
*state
= prepare_to_access_file_path(cpPath
);
224 int result
= lstat(cpPath
, buf
);
226 done_accessing_file_path(cpPath
, state
);
231 int lstat_u(const rtl_uString
* pustrPath
, struct stat
* buf
)
233 rtl::OString fn
= OUStringToOString(pustrPath
);
236 fn
= macxp_resolveAliasAndConvert(fn
);
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
);
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
281 [userDefaults setObject
:data
282 forKey
:[@
"bookmarkFor:" stringByAppendingString
:[url absoluteString
]]];
288 done_accessing_file_path(cpPath
, state
);
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
);
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
);
318 fn
= macxp_resolveAliasAndConvert(fn
);
321 accessFilePathState
*state
= prepare_to_access_file_path(fn
.getStr());
323 int result
= ftruncate(fd
, uSize
);
325 done_accessing_file_path(fn
.getStr(), state
);
330 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */