Home | History | Annotate | Download | only in ports
      1 /*
      2  * Copyright 2006 The Android Open Source Project
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 
      8 #include "SkOSFile.h"
      9 #include "SkTypes.h"
     10 
     11 #include <errno.h>
     12 #include <stdio.h>
     13 #include <sys/stat.h>
     14 
     15 #ifdef SK_BUILD_FOR_UNIX
     16 #include <unistd.h>
     17 #endif
     18 
     19 #ifdef _WIN32
     20 #include <direct.h>
     21 #include <io.h>
     22 #endif
     23 
     24 #ifdef SK_BUILD_FOR_IOS
     25 #import <CoreFoundation/CoreFoundation.h>
     26 
     27 static FILE* ios_open_from_bundle(const char path[], const char* perm) {
     28     // Get a reference to the main bundle
     29     CFBundleRef mainBundle = CFBundleGetMainBundle();
     30 
     31     // Get a reference to the file's URL
     32     CFStringRef pathRef = CFStringCreateWithCString(NULL, path, kCFStringEncodingUTF8);
     33     CFURLRef imageURL = CFBundleCopyResourceURL(mainBundle, pathRef, NULL, NULL);
     34     CFRelease(pathRef);
     35     if (!imageURL) {
     36         return nullptr;
     37     }
     38 
     39     // Convert the URL reference into a string reference
     40     CFStringRef imagePath = CFURLCopyFileSystemPath(imageURL, kCFURLPOSIXPathStyle);
     41     CFRelease(imageURL);
     42 
     43     // Get the system encoding method
     44     CFStringEncoding encodingMethod = CFStringGetSystemEncoding();
     45 
     46     // Convert the string reference into a C string
     47     const char *finalPath = CFStringGetCStringPtr(imagePath, encodingMethod);
     48     FILE* fileHandle = fopen(finalPath, perm);
     49     CFRelease(imagePath);
     50     return fileHandle;
     51 }
     52 #endif
     53 
     54 
     55 FILE* sk_fopen(const char path[], SkFILE_Flags flags) {
     56     char    perm[4];
     57     char*   p = perm;
     58 
     59     if (flags & kRead_SkFILE_Flag) {
     60         *p++ = 'r';
     61     }
     62     if (flags & kWrite_SkFILE_Flag) {
     63         *p++ = 'w';
     64     }
     65     *p++ = 'b';
     66     *p = 0;
     67 
     68     //TODO: on Windows fopen is just ASCII or the current code page,
     69     //convert to utf16 and use _wfopen
     70     FILE* file = nullptr;
     71 #ifdef SK_BUILD_FOR_IOS
     72     // if read-only, try to open from bundle first
     73     if (kRead_SkFILE_Flag == flags) {
     74         file = ios_open_from_bundle(path, perm);
     75     }
     76     // otherwise just read from the Documents directory (default)
     77     if (!file) {
     78 #endif
     79         file = fopen(path, perm);
     80 #ifdef SK_BUILD_FOR_IOS
     81     }
     82 #endif
     83     if (nullptr == file && (flags & kWrite_SkFILE_Flag)) {
     84         SkDEBUGF(("sk_fopen: fopen(\"%s\", \"%s\") returned NULL (errno:%d): %s\n",
     85                   path, perm, errno, strerror(errno)));
     86     }
     87     return file;
     88 }
     89 
     90 size_t sk_fgetsize(FILE* f) {
     91     SkASSERT(f);
     92 
     93     long curr = ftell(f); // remember where we are
     94     if (curr < 0) {
     95         return 0;
     96     }
     97 
     98     fseek(f, 0, SEEK_END); // go to the end
     99     long size = ftell(f); // record the size
    100     if (size < 0) {
    101         size = 0;
    102     }
    103 
    104     fseek(f, curr, SEEK_SET); // go back to our prev location
    105     return size;
    106 }
    107 
    108 size_t sk_fwrite(const void* buffer, size_t byteCount, FILE* f) {
    109     SkASSERT(f);
    110     return fwrite(buffer, 1, byteCount, f);
    111 }
    112 
    113 void sk_fflush(FILE* f) {
    114     SkASSERT(f);
    115     fflush(f);
    116 }
    117 
    118 void sk_fsync(FILE* f) {
    119 #if !defined(_WIN32) && !defined(SK_BUILD_FOR_ANDROID) && !defined(__UCLIBC__) \
    120         && !defined(_NEWLIB_VERSION)
    121     int fd = fileno(f);
    122     fsync(fd);
    123 #endif
    124 }
    125 
    126 size_t sk_ftell(FILE* f) {
    127     long curr = ftell(f);
    128     if (curr < 0) {
    129         return 0;
    130     }
    131     return curr;
    132 }
    133 
    134 void sk_fclose(FILE* f) {
    135     if (f) {
    136         fclose(f);
    137     }
    138 }
    139 
    140 bool sk_isdir(const char *path) {
    141     struct stat status;
    142     if (0 != stat(path, &status)) {
    143         return false;
    144     }
    145     return SkToBool(status.st_mode & S_IFDIR);
    146 }
    147 
    148 bool sk_mkdir(const char* path) {
    149     if (sk_isdir(path)) {
    150         return true;
    151     }
    152     if (sk_exists(path)) {
    153         fprintf(stderr,
    154                 "sk_mkdir: path '%s' already exists but is not a directory\n",
    155                 path);
    156         return false;
    157     }
    158 
    159     int retval;
    160 #ifdef _WIN32
    161     retval = _mkdir(path);
    162 #else
    163     retval = mkdir(path, 0777);
    164 #endif
    165     if (0 == retval) {
    166         return true;
    167     } else {
    168         fprintf(stderr, "sk_mkdir: error %d creating dir '%s'\n", errno, path);
    169         return false;
    170     }
    171 }
    172