LCOV - code coverage report
Current view: top level - sal/osl/unx - uunxapi.cxx (source / functions) Hit Total Coverage
Test: commit 0e63ca4fde4e446f346e35849c756a30ca294aab Lines: 44 48 91.7 %
Date: 2014-04-11 Functions: 9 10 90.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: ObjC; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       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/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      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 .
      18             :  */
      19             : 
      20             : #include <config_features.h>
      21             : 
      22             : #include "uunxapi.h"
      23             : #include "system.h"
      24             : #include <limits.h>
      25             : #include <rtl/ustring.hxx>
      26             : #include <osl/thread.h>
      27             : 
      28             : #ifdef ANDROID
      29             : #include <osl/detail/android-bootstrap.h>
      30             : #endif
      31             : 
      32      185293 : inline rtl::OString OUStringToOString(const rtl_uString* s)
      33             : {
      34             :     return rtl::OUStringToOString(rtl::OUString(const_cast<rtl_uString*>(s)),
      35      185293 :                                   osl_getThreadTextEncoding());
      36             : }
      37             : 
      38             : #if defined(MACOSX) && MAC_OS_X_VERSION_MIN_REQUIRED >= 1070 && HAVE_FEATURE_MACOSX_SANDBOX
      39             : 
      40             : static NSUserDefaults *userDefaults = NULL;
      41             : 
      42             : static void get_user_defaults()
      43             : {
      44             :     userDefaults = [NSUserDefaults standardUserDefaults];
      45             : }
      46             : 
      47             : typedef struct {
      48             :     NSURL *scopeURL;
      49             :     NSAutoreleasePool *pool;
      50             : } accessFilePathState;
      51             : 
      52             : static accessFilePathState *
      53             : prepare_to_access_file_path( const char *cpFilePath )
      54             : {
      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;
      61             : 
      62             :     // If malloc() fails we are screwed anyway
      63             :     state = (accessFilePathState*) malloc(sizeof(accessFilePathState));
      64             : 
      65             :     state->pool = [[NSAutoreleasePool alloc] init];
      66             :     state->scopeURL = nil;
      67             : 
      68             :     if (userDefaults != nil)
      69             :         fileURL = [NSURL fileURLWithPath:[NSString stringWithUTF8String:cpFilePath]];
      70             : 
      71             :     if (fileURL != nil)
      72             :         data = [userDefaults dataForKey:[@"bookmarkFor:" stringByAppendingString:[fileURL absoluteString]]];
      73             : 
      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];
      82             : 
      83             :     return state;
      84             : }
      85             : 
      86             : static void
      87             : done_accessing_file_path( const char * /*cpFilePath*/, accessFilePathState *state )
      88             : {
      89             :     int saved_errno = errno;
      90             : 
      91             :     if (state->scopeURL != nil)
      92             :         [state->scopeURL stopAccessingSecurityScopedResource];
      93             :     [state->pool release];
      94             :     free(state);
      95             : 
      96             :     errno = saved_errno;
      97             : }
      98             : 
      99             : #else
     100             : 
     101             : typedef void accessFilePathState;
     102             : 
     103             : #define prepare_to_access_file_path( cpFilePath ) NULL
     104             : 
     105             : #define done_accessing_file_path( cpFilePath, state ) ((void) cpFilePath, (void) state)
     106             : 
     107             : #endif
     108             : 
     109             : #ifdef MACOSX
     110             : /*
     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
     113             :  */
     114             : static rtl::OString macxp_resolveAliasAndConvert(rtl::OString const & p)
     115             : {
     116             :     sal_Char path[PATH_MAX];
     117             :     if (p.getLength() < PATH_MAX)
     118             :     {
     119             :         strcpy(path, p.getStr());
     120             :         macxp_resolveAlias(path, PATH_MAX);
     121             :         return rtl::OString(path);
     122             :     }
     123             :     return p;
     124             : }
     125             : #endif /* MACOSX */
     126             : 
     127      133904 : int access_u(const rtl_uString* pustrPath, int mode)
     128             : {
     129      133904 :     rtl::OString fn = OUStringToOString(pustrPath);
     130             : #ifdef ANDROID
     131             :     if (fn == "/assets" || fn.startsWith("/assets/"))
     132             :     {
     133             :         struct stat stat;
     134             :         if (lo_apk_lstat(fn.getStr(), &stat) == -1)
     135             :             return -1;
     136             :         if (mode & W_OK)
     137             :         {
     138             :             errno = EACCES;
     139             :             return -1;
     140             :         }
     141             :         return 0;
     142             :     }
     143             : #endif
     144             : 
     145             : #ifdef MACOSX
     146             :     fn = macxp_resolveAliasAndConvert(fn);
     147             : #endif
     148             : 
     149      133904 :     accessFilePathState *state = prepare_to_access_file_path(fn.getStr());
     150             : 
     151      133904 :     int result = access(fn.getStr(), mode);
     152             : 
     153      133904 :     done_accessing_file_path(fn.getStr(), state);
     154             : 
     155      133904 :     return result;
     156             : }
     157             : 
     158        2166 : sal_Bool realpath_u(const rtl_uString* pustrFileName, rtl_uString** ppustrResolvedName)
     159             : {
     160        2166 :     rtl::OString fn = OUStringToOString(pustrFileName);
     161             : #ifdef ANDROID
     162             :     if (fn == "/assets" || fn.startsWith("/assets/"))
     163             :     {
     164             :         if (access_u(pustrFileName, F_OK) == -1)
     165             :             return sal_False;
     166             : 
     167             :         rtl_uString silly(*pustrFileName);
     168             :         rtl_uString_assign(ppustrResolvedName, &silly);
     169             : 
     170             :         return sal_True;
     171             :     }
     172             : #endif
     173             : 
     174             : #ifdef MACOSX
     175             :     fn = macxp_resolveAliasAndConvert(fn);
     176             : #endif
     177             : 
     178        2166 :     accessFilePathState *state = prepare_to_access_file_path(fn.getStr());
     179             : 
     180             :     char  rp[PATH_MAX];
     181        2166 :     bool  bRet = realpath(fn.getStr(), rp);
     182             : 
     183        2166 :     done_accessing_file_path(fn.getStr(), state);
     184             : 
     185        2166 :     if (bRet)
     186             :     {
     187             :         rtl::OUString resolved = rtl::OStringToOUString(rtl::OString(static_cast<sal_Char*>(rp)),
     188        2166 :                                                         osl_getThreadTextEncoding());
     189             : 
     190        2166 :         rtl_uString_assign(ppustrResolvedName, resolved.pData);
     191             :     }
     192        2166 :     return bRet;
     193             : }
     194             : 
     195        3345 : int stat_c(const char* cpPath, struct stat* buf)
     196             : {
     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
     203             : 
     204        3345 :     accessFilePathState *state = prepare_to_access_file_path(cpPath);
     205             : 
     206        3345 :     int result = stat(cpPath, buf);
     207             : 
     208             :     done_accessing_file_path(cpPath, state);
     209             : 
     210        3345 :     return result;
     211             : }
     212             : 
     213       70461 : int lstat_c(const char* cpPath, struct stat* buf)
     214             : {
     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
     221             : 
     222       70461 :     accessFilePathState *state = prepare_to_access_file_path(cpPath);
     223             : 
     224       70461 :     int result = lstat(cpPath, buf);
     225             : 
     226             :     done_accessing_file_path(cpPath, state);
     227             : 
     228       70461 :     return result;
     229             : }
     230             : 
     231       45953 : int lstat_u(const rtl_uString* pustrPath, struct stat* buf)
     232             : {
     233       45953 :     rtl::OString fn = OUStringToOString(pustrPath);
     234             : 
     235             : #ifdef MACOSX
     236             :     fn = macxp_resolveAliasAndConvert(fn);
     237             : #endif
     238             : 
     239       45953 :     return lstat_c(fn.getStr(), buf);
     240             : }
     241             : 
     242        1635 : int mkdir_u(const rtl_uString* path, mode_t mode)
     243             : {
     244        1635 :     rtl::OString fn = OUStringToOString(path);
     245             : 
     246        1635 :     accessFilePathState *state = prepare_to_access_file_path(fn.getStr());
     247             : 
     248        1635 :     int result = mkdir(OUStringToOString(path).getStr(), mode);
     249             : 
     250        1635 :     done_accessing_file_path(fn.getStr(), state);
     251             : 
     252        1635 :     return result;
     253             : }
     254             : 
     255      107832 : int open_c(const char *cpPath, int oflag, int mode)
     256             : {
     257      107832 :     accessFilePathState *state = prepare_to_access_file_path(cpPath);
     258             : 
     259      107832 :     int result = open(cpPath, oflag, mode);
     260             : 
     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))
     263             :     {
     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)] == '/'))
     273             :         {
     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)
     280             :             {
     281             :                 [userDefaults setObject:data
     282             :                                  forKey:[@"bookmarkFor:" stringByAppendingString:[url absoluteString]]];
     283             :             }
     284             :         }
     285             :     }
     286             : #endif
     287             : 
     288             :     done_accessing_file_path(cpPath, state);
     289             : 
     290      107832 :     return result;
     291             : }
     292             : 
     293           0 : int utime_c(const char *cpPath, struct utimbuf *times)
     294             : {
     295           0 :     accessFilePathState *state = prepare_to_access_file_path(cpPath);
     296             : 
     297           0 :     int result = utime(cpPath, times);
     298             : 
     299             :     done_accessing_file_path(cpPath, state);
     300             : 
     301           0 :     return result;
     302             : }
     303             : 
     304        1129 : int ftruncate_with_name(int fd, sal_uInt64 uSize, rtl_String* path)
     305             : {
     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.
     313             :      */
     314             : 
     315        1129 :     rtl::OString fn = rtl::OString(path);
     316             : 
     317             : #ifdef MACOSX
     318             :     fn = macxp_resolveAliasAndConvert(fn);
     319             : #endif
     320             : 
     321        1129 :     accessFilePathState *state = prepare_to_access_file_path(fn.getStr());
     322             : 
     323        1129 :     int result = ftruncate(fd, uSize);
     324             : 
     325        1129 :     done_accessing_file_path(fn.getStr(), state);
     326             : 
     327        1129 :     return result;
     328             : }
     329             : 
     330             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10