LCOV - code coverage report
Current view: top level - sal/osl/unx - uunxapi.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 44 48 91.7 %
Date: 2015-06-13 12:38:46 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.hxx"
      23             : #include "system.hxx"
      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      301430 : inline rtl::OString OUStringToOString(const rtl_uString* s)
      33             : {
      34             :     return rtl::OUStringToOString(rtl::OUString(const_cast<rtl_uString*>(s)),
      35      301430 :                                   osl_getThreadTextEncoding());
      36             : }
      37             : 
      38             : #if HAVE_FEATURE_MACOSX_SANDBOX
      39             : 
      40             : #include <Foundation/Foundation.h>
      41             : #include <Security/Security.h>
      42             : #include <mach-o/dyld.h>
      43             : 
      44             : static NSUserDefaults *userDefaults = NULL;
      45             : static bool isSandboxed = false;
      46             : 
      47             : static void do_once()
      48             : {
      49             :     SecCodeRef code;
      50             :     OSStatus rc = SecCodeCopySelf(kSecCSDefaultFlags, &code);
      51             : 
      52             :     SecStaticCodeRef staticCode;
      53             :     if (rc == errSecSuccess)
      54             :         rc = SecCodeCopyStaticCode(code, kSecCSDefaultFlags, &staticCode);
      55             : 
      56             :     CFDictionaryRef signingInformation;
      57             :     if (rc == errSecSuccess)
      58             :         rc = SecCodeCopySigningInformation(staticCode, kSecCSRequirementInformation, &signingInformation);
      59             : 
      60             :     CFDictionaryRef entitlements = NULL;
      61             :     if (rc == errSecSuccess)
      62             :         entitlements = (CFDictionaryRef) CFDictionaryGetValue(signingInformation, kSecCodeInfoEntitlementsDict);
      63             : 
      64             :     if (entitlements != NULL)
      65             :         if (CFDictionaryGetValue(entitlements, CFSTR("com.apple.security.app-sandbox")) != NULL)
      66             :             isSandboxed = true;
      67             : 
      68             :     if (isSandboxed)
      69             :         userDefaults = [NSUserDefaults standardUserDefaults];
      70             : }
      71             : 
      72             : typedef struct {
      73             :     NSURL *scopeURL;
      74             :     NSAutoreleasePool *pool;
      75             : } accessFilePathState;
      76             : 
      77             : static accessFilePathState *
      78             : prepare_to_access_file_path( const char *cpFilePath )
      79             : {
      80             :     static pthread_once_t once = PTHREAD_ONCE_INIT;
      81             :     pthread_once(&once, &do_once);
      82             :     NSURL *fileURL = nil;
      83             :     NSData *data = nil;
      84             :     BOOL stale;
      85             :     accessFilePathState *state;
      86             : 
      87             :     if (!isSandboxed)
      88             :         return NULL;
      89             : 
      90             :     // If malloc() fails we are screwed anyway
      91             :     state = (accessFilePathState*) malloc(sizeof(accessFilePathState));
      92             : 
      93             :     state->pool = [[NSAutoreleasePool alloc] init];
      94             :     state->scopeURL = nil;
      95             : 
      96             :     if (userDefaults != nil)
      97             :         fileURL = [NSURL fileURLWithPath:[NSString stringWithUTF8String:cpFilePath]];
      98             : 
      99             :     if (fileURL != nil)
     100             :         data = [userDefaults dataForKey:[@"bookmarkFor:" stringByAppendingString:[fileURL absoluteString]]];
     101             : 
     102             :     if (data != nil)
     103             :         state->scopeURL = [NSURL URLByResolvingBookmarkData:data
     104             :                                                     options:NSURLBookmarkResolutionWithSecurityScope
     105             :                                               relativeToURL:nil
     106             :                                         bookmarkDataIsStale:&stale
     107             :                                                       error:nil];
     108             :     if (state->scopeURL != nil)
     109             :         [state->scopeURL startAccessingSecurityScopedResource];
     110             : 
     111             :     return state;
     112             : }
     113             : 
     114             : static void
     115             : done_accessing_file_path( const char * /*cpFilePath*/, accessFilePathState *state )
     116             : {
     117             :     if (!isSandboxed)
     118             :         return;
     119             : 
     120             :     int saved_errno = errno;
     121             : 
     122             :     if (state->scopeURL != nil)
     123             :         [state->scopeURL stopAccessingSecurityScopedResource];
     124             :     [state->pool release];
     125             :     free(state);
     126             : 
     127             :     errno = saved_errno;
     128             : }
     129             : 
     130             : #else
     131             : 
     132             : typedef void accessFilePathState;
     133             : 
     134             : #define prepare_to_access_file_path( cpFilePath ) NULL
     135             : 
     136             : #define done_accessing_file_path( cpFilePath, state ) ((void) cpFilePath, (void) state)
     137             : 
     138             : #endif
     139             : 
     140             : #ifdef MACOSX
     141             : /*
     142             :  * Helper function for resolving Mac native alias files (not the same as unix alias files)
     143             :  * and to return the resolved alias as rtl::OString
     144             :  */
     145             : static rtl::OString macxp_resolveAliasAndConvert(rtl::OString const & p)
     146             : {
     147             :     sal_Char path[PATH_MAX];
     148             :     if (p.getLength() < PATH_MAX)
     149             :     {
     150             :         strcpy(path, p.getStr());
     151             :         macxp_resolveAlias(path, PATH_MAX);
     152             :         return rtl::OString(path);
     153             :     }
     154             :     return p;
     155             : }
     156             : #endif /* MACOSX */
     157             : 
     158      212909 : int access_u(const rtl_uString* pustrPath, int mode)
     159             : {
     160      212909 :     rtl::OString fn = OUStringToOString(pustrPath);
     161             : #ifdef ANDROID
     162             :     if (fn == "/assets" || fn.startsWith("/assets/"))
     163             :     {
     164             :         struct stat stat;
     165             :         if (lo_apk_lstat(fn.getStr(), &stat) == -1)
     166             :             return -1;
     167             :         if (mode & W_OK)
     168             :         {
     169             :             errno = EACCES;
     170             :             return -1;
     171             :         }
     172             :         return 0;
     173             :     }
     174             : #endif
     175             : 
     176             : #ifdef MACOSX
     177             :     fn = macxp_resolveAliasAndConvert(fn);
     178             : #endif
     179             : 
     180      212909 :     accessFilePathState *state = prepare_to_access_file_path(fn.getStr());
     181             : 
     182      212909 :     int result = access(fn.getStr(), mode);
     183             : 
     184      212909 :     done_accessing_file_path(fn.getStr(), state);
     185             : 
     186      212909 :     return result;
     187             : }
     188             : 
     189        2165 : bool realpath_u(const rtl_uString* pustrFileName, rtl_uString** ppustrResolvedName)
     190             : {
     191        2165 :     rtl::OString fn = OUStringToOString(pustrFileName);
     192             : #ifdef ANDROID
     193             :     if (fn == "/assets" || fn.startsWith("/assets/"))
     194             :     {
     195             :         if (access_u(pustrFileName, F_OK) == -1)
     196             :             return false;
     197             : 
     198             :         rtl_uString silly(*pustrFileName);
     199             :         rtl_uString_assign(ppustrResolvedName, &silly);
     200             : 
     201             :         return true;
     202             :     }
     203             : #endif
     204             : 
     205             : #ifdef MACOSX
     206             :     fn = macxp_resolveAliasAndConvert(fn);
     207             : #endif
     208             : 
     209        2165 :     accessFilePathState *state = prepare_to_access_file_path(fn.getStr());
     210             : 
     211             :     char  rp[PATH_MAX];
     212        2165 :     bool  bRet = realpath(fn.getStr(), rp);
     213             : 
     214        2165 :     done_accessing_file_path(fn.getStr(), state);
     215             : 
     216        2165 :     if (bRet)
     217             :     {
     218             :         rtl::OUString resolved = rtl::OStringToOUString(rtl::OString(static_cast<sal_Char*>(rp)),
     219        2165 :                                                         osl_getThreadTextEncoding());
     220             : 
     221        2165 :         rtl_uString_assign(ppustrResolvedName, resolved.pData);
     222             :     }
     223        2165 :     return bRet;
     224             : }
     225             : 
     226        4616 : int stat_c(const char* cpPath, struct stat* buf)
     227             : {
     228             : #ifdef ANDROID
     229             :     if (strncmp(cpPath, "/assets", sizeof("/assets")-1) == 0 &&
     230             :         (cpPath[sizeof("/assets")-1] == '\0' ||
     231             :          cpPath[sizeof("/assets")-1] == '/'))
     232             :         return lo_apk_lstat(cpPath, buf);
     233             : #endif
     234             : 
     235        4616 :     accessFilePathState *state = prepare_to_access_file_path(cpPath);
     236             : 
     237        4616 :     int result = stat(cpPath, buf);
     238             : 
     239             :     done_accessing_file_path(cpPath, state);
     240             : 
     241        4616 :     return result;
     242             : }
     243             : 
     244      119322 : int lstat_c(const char* cpPath, struct stat* buf)
     245             : {
     246             : #ifdef ANDROID
     247             :     if (strncmp(cpPath, "/assets", sizeof("/assets")-1) == 0 &&
     248             :         (cpPath[sizeof("/assets")-1] == '\0' ||
     249             :          cpPath[sizeof("/assets")-1] == '/'))
     250             :         return lo_apk_lstat(cpPath, buf);
     251             : #endif
     252             : 
     253      119322 :     accessFilePathState *state = prepare_to_access_file_path(cpPath);
     254             : 
     255      119322 :     int result = lstat(cpPath, buf);
     256             : 
     257             :     done_accessing_file_path(cpPath, state);
     258             : 
     259      119322 :     return result;
     260             : }
     261             : 
     262       83014 : int lstat_u(const rtl_uString* pustrPath, struct stat* buf)
     263             : {
     264       83014 :     rtl::OString fn = OUStringToOString(pustrPath);
     265             : 
     266             : #ifdef MACOSX
     267             :     fn = macxp_resolveAliasAndConvert(fn);
     268             : #endif
     269             : 
     270       83014 :     return lstat_c(fn.getStr(), buf);
     271             : }
     272             : 
     273        1671 : int mkdir_u(const rtl_uString* path, mode_t mode)
     274             : {
     275        1671 :     rtl::OString fn = OUStringToOString(path);
     276             : 
     277        1671 :     accessFilePathState *state = prepare_to_access_file_path(fn.getStr());
     278             : 
     279        1671 :     int result = mkdir(OUStringToOString(path).getStr(), mode);
     280             : 
     281        1671 :     done_accessing_file_path(fn.getStr(), state);
     282             : 
     283        1671 :     return result;
     284             : }
     285             : 
     286      133443 : int open_c(const char *cpPath, int oflag, int mode)
     287             : {
     288      133443 :     accessFilePathState *state = prepare_to_access_file_path(cpPath);
     289             : 
     290      133443 :     int result = open(cpPath, oflag, mode);
     291             : 
     292             : #if HAVE_FEATURE_MACOSX_SANDBOX
     293             :     if (isSandboxed && result != -1 && (oflag & O_CREAT) && (oflag & O_EXCL))
     294             :     {
     295             :         // A new file was created. Check if it is outside the sandbox.
     296             :         // (In that case it must be one the user selected as export or
     297             :         // save destination in a file dialog, otherwise we wouldn't
     298             :         // have been able to create it.) Create and store a security
     299             :         // scoped bookmark for it so that we can access the file in
     300             :         // the future, too. (For the "Recent Files" functionality.)
     301             :         const char *sandbox = [NSHomeDirectory() UTF8String];
     302             :         if (!(strncmp(sandbox, cpPath, strlen(sandbox)) == 0 &&
     303             :               cpPath[strlen(sandbox)] == '/'))
     304             :         {
     305             :             NSURL *url = [NSURL fileURLWithPath:[NSString stringWithUTF8String:cpPath]];
     306             :             NSData *data = [url bookmarkDataWithOptions:NSURLBookmarkCreationWithSecurityScope
     307             :                          includingResourceValuesForKeys:nil
     308             :                                           relativeToURL:nil
     309             :                                                   error:nil];
     310             :             if (data != NULL)
     311             :             {
     312             :                 [userDefaults setObject:data
     313             :                                  forKey:[@"bookmarkFor:" stringByAppendingString:[url absoluteString]]];
     314             :             }
     315             :         }
     316             :     }
     317             : #endif
     318             : 
     319             :     done_accessing_file_path(cpPath, state);
     320             : 
     321      133443 :     return result;
     322             : }
     323             : 
     324           0 : int utime_c(const char *cpPath, struct utimbuf *times)
     325             : {
     326           0 :     accessFilePathState *state = prepare_to_access_file_path(cpPath);
     327             : 
     328           0 :     int result = utime(cpPath, times);
     329             : 
     330             :     done_accessing_file_path(cpPath, state);
     331             : 
     332           0 :     return result;
     333             : }
     334             : 
     335        1939 : int ftruncate_with_name(int fd, sal_uInt64 uSize, rtl_String* path)
     336             : {
     337             :     /* When sandboxed on OS X, ftruncate(), even if it takes an
     338             :      * already open file descriptor which was retuned from an open()
     339             :      * call already checked by the sandbox, still requires a security
     340             :      * scope bookmark for the file to be active in case the file is
     341             :      * one that the sandbox doesn't otherwise allow access to. Luckily
     342             :      * LibreOffice usually calls ftruncate() through the helpful C++
     343             :      * abstraction layer that keeps the pathname around.
     344             :      */
     345             : 
     346        1939 :     rtl::OString fn = rtl::OString(path);
     347             : 
     348             : #ifdef MACOSX
     349             :     fn = macxp_resolveAliasAndConvert(fn);
     350             : #endif
     351             : 
     352        1939 :     accessFilePathState *state = prepare_to_access_file_path(fn.getStr());
     353             : 
     354        1939 :     int result = ftruncate(fd, uSize);
     355             : 
     356        1939 :     done_accessing_file_path(fn.getStr(), state);
     357             : 
     358        1939 :     return result;
     359             : }
     360             : 
     361             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11