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