1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2006 The Android Open Source Project 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#include "include/core/SkTypes.h" 9cb93a386Sopenharmony_ci#include "src/core/SkOSFile.h" 10cb93a386Sopenharmony_ci 11cb93a386Sopenharmony_ci#include <errno.h> 12cb93a386Sopenharmony_ci#include <stdio.h> 13cb93a386Sopenharmony_ci#include <sys/stat.h> 14cb93a386Sopenharmony_ci 15cb93a386Sopenharmony_ci#ifdef SK_BUILD_FOR_UNIX 16cb93a386Sopenharmony_ci#include <unistd.h> 17cb93a386Sopenharmony_ci#endif 18cb93a386Sopenharmony_ci 19cb93a386Sopenharmony_ci#ifdef _WIN32 20cb93a386Sopenharmony_ci#include <direct.h> 21cb93a386Sopenharmony_ci#include <io.h> 22cb93a386Sopenharmony_ci#include <vector> 23cb93a386Sopenharmony_ci#include "src/utils/SkUTF.h" 24cb93a386Sopenharmony_ci#endif 25cb93a386Sopenharmony_ci 26cb93a386Sopenharmony_ci#ifdef SK_BUILD_FOR_IOS 27cb93a386Sopenharmony_ci#include "src/ports/SkOSFile_ios.h" 28cb93a386Sopenharmony_ci#endif 29cb93a386Sopenharmony_ci 30cb93a386Sopenharmony_ci#ifdef _WIN32 31cb93a386Sopenharmony_cistatic bool is_ascii(const char* s) { 32cb93a386Sopenharmony_ci while (char v = *s++) { 33cb93a386Sopenharmony_ci if ((v & 0x80) != 0) { 34cb93a386Sopenharmony_ci return false; 35cb93a386Sopenharmony_ci } 36cb93a386Sopenharmony_ci } 37cb93a386Sopenharmony_ci return true; 38cb93a386Sopenharmony_ci} 39cb93a386Sopenharmony_ci 40cb93a386Sopenharmony_cistatic FILE* fopen_win(const char* utf8path, const char* perm) { 41cb93a386Sopenharmony_ci if (is_ascii(utf8path)) { 42cb93a386Sopenharmony_ci return fopen(utf8path, perm); 43cb93a386Sopenharmony_ci } 44cb93a386Sopenharmony_ci 45cb93a386Sopenharmony_ci const char* ptr = utf8path; 46cb93a386Sopenharmony_ci const char* end = utf8path + strlen(utf8path); 47cb93a386Sopenharmony_ci size_t n = 0; 48cb93a386Sopenharmony_ci while (ptr < end) { 49cb93a386Sopenharmony_ci SkUnichar u = SkUTF::NextUTF8(&ptr, end); 50cb93a386Sopenharmony_ci if (u < 0) { 51cb93a386Sopenharmony_ci return nullptr; // malformed UTF-8 52cb93a386Sopenharmony_ci } 53cb93a386Sopenharmony_ci n += SkUTF::ToUTF16(u); 54cb93a386Sopenharmony_ci } 55cb93a386Sopenharmony_ci std::vector<uint16_t> wchars(n + 1); 56cb93a386Sopenharmony_ci uint16_t* out = wchars.data(); 57cb93a386Sopenharmony_ci ptr = utf8path; 58cb93a386Sopenharmony_ci while (ptr < end) { 59cb93a386Sopenharmony_ci out += SkUTF::ToUTF16(SkUTF::NextUTF8(&ptr, end), out); 60cb93a386Sopenharmony_ci } 61cb93a386Sopenharmony_ci SkASSERT(out == &wchars[n]); 62cb93a386Sopenharmony_ci *out = 0; // final null 63cb93a386Sopenharmony_ci wchar_t wperms[4] = {(wchar_t)perm[0], (wchar_t)perm[1], (wchar_t)perm[2], (wchar_t)perm[3]}; 64cb93a386Sopenharmony_ci return _wfopen((wchar_t*)wchars.data(), wperms); 65cb93a386Sopenharmony_ci} 66cb93a386Sopenharmony_ci#endif 67cb93a386Sopenharmony_ci 68cb93a386Sopenharmony_ciFILE* sk_fopen(const char path[], SkFILE_Flags flags) { 69cb93a386Sopenharmony_ci char perm[4] = {0, 0, 0, 0}; 70cb93a386Sopenharmony_ci char* p = perm; 71cb93a386Sopenharmony_ci 72cb93a386Sopenharmony_ci if (flags & kRead_SkFILE_Flag) { 73cb93a386Sopenharmony_ci *p++ = 'r'; 74cb93a386Sopenharmony_ci } 75cb93a386Sopenharmony_ci if (flags & kWrite_SkFILE_Flag) { 76cb93a386Sopenharmony_ci *p++ = 'w'; 77cb93a386Sopenharmony_ci } 78cb93a386Sopenharmony_ci *p = 'b'; 79cb93a386Sopenharmony_ci 80cb93a386Sopenharmony_ci FILE* file = nullptr; 81cb93a386Sopenharmony_ci#ifdef _WIN32 82cb93a386Sopenharmony_ci file = fopen_win(path, perm); 83cb93a386Sopenharmony_ci#else 84cb93a386Sopenharmony_ci file = fopen(path, perm); 85cb93a386Sopenharmony_ci#endif 86cb93a386Sopenharmony_ci#ifdef SK_BUILD_FOR_IOS 87cb93a386Sopenharmony_ci // if not found in default path and read-only, try to open from bundle 88cb93a386Sopenharmony_ci if (!file && kRead_SkFILE_Flag == flags) { 89cb93a386Sopenharmony_ci SkString bundlePath; 90cb93a386Sopenharmony_ci if (ios_get_path_in_bundle(path, &bundlePath)) { 91cb93a386Sopenharmony_ci file = fopen(bundlePath.c_str(), perm); 92cb93a386Sopenharmony_ci } 93cb93a386Sopenharmony_ci } 94cb93a386Sopenharmony_ci#endif 95cb93a386Sopenharmony_ci 96cb93a386Sopenharmony_ci if (nullptr == file && (flags & kWrite_SkFILE_Flag)) { 97cb93a386Sopenharmony_ci SkDEBUGF("sk_fopen: fopen(\"%s\", \"%s\") returned nullptr (errno:%d): %s\n", 98cb93a386Sopenharmony_ci path, perm, errno, strerror(errno)); 99cb93a386Sopenharmony_ci } 100cb93a386Sopenharmony_ci return file; 101cb93a386Sopenharmony_ci} 102cb93a386Sopenharmony_ci 103cb93a386Sopenharmony_cisize_t sk_fgetsize(FILE* f) { 104cb93a386Sopenharmony_ci SkASSERT(f); 105cb93a386Sopenharmony_ci 106cb93a386Sopenharmony_ci long curr = ftell(f); // remember where we are 107cb93a386Sopenharmony_ci if (curr < 0) { 108cb93a386Sopenharmony_ci return 0; 109cb93a386Sopenharmony_ci } 110cb93a386Sopenharmony_ci 111cb93a386Sopenharmony_ci fseek(f, 0, SEEK_END); // go to the end 112cb93a386Sopenharmony_ci long size = ftell(f); // record the size 113cb93a386Sopenharmony_ci if (size < 0) { 114cb93a386Sopenharmony_ci size = 0; 115cb93a386Sopenharmony_ci } 116cb93a386Sopenharmony_ci 117cb93a386Sopenharmony_ci fseek(f, curr, SEEK_SET); // go back to our prev location 118cb93a386Sopenharmony_ci return size; 119cb93a386Sopenharmony_ci} 120cb93a386Sopenharmony_ci 121cb93a386Sopenharmony_cisize_t sk_fwrite(const void* buffer, size_t byteCount, FILE* f) { 122cb93a386Sopenharmony_ci SkASSERT(f); 123cb93a386Sopenharmony_ci return fwrite(buffer, 1, byteCount, f); 124cb93a386Sopenharmony_ci} 125cb93a386Sopenharmony_ci 126cb93a386Sopenharmony_civoid sk_fflush(FILE* f) { 127cb93a386Sopenharmony_ci SkASSERT(f); 128cb93a386Sopenharmony_ci fflush(f); 129cb93a386Sopenharmony_ci} 130cb93a386Sopenharmony_ci 131cb93a386Sopenharmony_civoid sk_fsync(FILE* f) { 132cb93a386Sopenharmony_ci#if !defined(_WIN32) && !defined(SK_BUILD_FOR_ANDROID) && !defined(__UCLIBC__) \ 133cb93a386Sopenharmony_ci && !defined(_NEWLIB_VERSION) 134cb93a386Sopenharmony_ci int fd = fileno(f); 135cb93a386Sopenharmony_ci fsync(fd); 136cb93a386Sopenharmony_ci#endif 137cb93a386Sopenharmony_ci} 138cb93a386Sopenharmony_ci 139cb93a386Sopenharmony_cisize_t sk_ftell(FILE* f) { 140cb93a386Sopenharmony_ci long curr = ftell(f); 141cb93a386Sopenharmony_ci if (curr < 0) { 142cb93a386Sopenharmony_ci return 0; 143cb93a386Sopenharmony_ci } 144cb93a386Sopenharmony_ci return curr; 145cb93a386Sopenharmony_ci} 146cb93a386Sopenharmony_ci 147cb93a386Sopenharmony_civoid sk_fclose(FILE* f) { 148cb93a386Sopenharmony_ci if (f) { 149cb93a386Sopenharmony_ci fclose(f); 150cb93a386Sopenharmony_ci } 151cb93a386Sopenharmony_ci} 152cb93a386Sopenharmony_ci 153cb93a386Sopenharmony_cibool sk_isdir(const char *path) { 154cb93a386Sopenharmony_ci struct stat status; 155cb93a386Sopenharmony_ci if (0 != stat(path, &status)) { 156cb93a386Sopenharmony_ci#ifdef SK_BUILD_FOR_IOS 157cb93a386Sopenharmony_ci // check the bundle directory if not in default path 158cb93a386Sopenharmony_ci SkString bundlePath; 159cb93a386Sopenharmony_ci if (ios_get_path_in_bundle(path, &bundlePath)) { 160cb93a386Sopenharmony_ci if (0 != stat(bundlePath.c_str(), &status)) { 161cb93a386Sopenharmony_ci return false; 162cb93a386Sopenharmony_ci } 163cb93a386Sopenharmony_ci } 164cb93a386Sopenharmony_ci#else 165cb93a386Sopenharmony_ci return false; 166cb93a386Sopenharmony_ci#endif 167cb93a386Sopenharmony_ci } 168cb93a386Sopenharmony_ci return SkToBool(status.st_mode & S_IFDIR); 169cb93a386Sopenharmony_ci} 170cb93a386Sopenharmony_ci 171cb93a386Sopenharmony_cibool sk_mkdir(const char* path) { 172cb93a386Sopenharmony_ci if (sk_isdir(path)) { 173cb93a386Sopenharmony_ci return true; 174cb93a386Sopenharmony_ci } 175cb93a386Sopenharmony_ci if (sk_exists(path)) { 176cb93a386Sopenharmony_ci fprintf(stderr, 177cb93a386Sopenharmony_ci "sk_mkdir: path '%s' already exists but is not a directory\n", 178cb93a386Sopenharmony_ci path); 179cb93a386Sopenharmony_ci return false; 180cb93a386Sopenharmony_ci } 181cb93a386Sopenharmony_ci 182cb93a386Sopenharmony_ci int retval; 183cb93a386Sopenharmony_ci#ifdef _WIN32 184cb93a386Sopenharmony_ci retval = _mkdir(path); 185cb93a386Sopenharmony_ci#else 186cb93a386Sopenharmony_ci retval = mkdir(path, 0777); 187cb93a386Sopenharmony_ci if (retval) { 188cb93a386Sopenharmony_ci perror("mkdir() failed with error: "); 189cb93a386Sopenharmony_ci } 190cb93a386Sopenharmony_ci#endif 191cb93a386Sopenharmony_ci return 0 == retval; 192cb93a386Sopenharmony_ci} 193