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
ios_open_from_bundle(const char path[],const char * perm)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
sk_fopen(const char path[],SkFILE_Flags flags)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
sk_fgetsize(FILE * f)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
sk_fwrite(const void * buffer,size_t byteCount,FILE * f)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
sk_fflush(FILE * f)113 void sk_fflush(FILE* f) {
114 SkASSERT(f);
115 fflush(f);
116 }
117
sk_fsync(FILE * f)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
sk_ftell(FILE * f)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
sk_fclose(FILE * f)134 void sk_fclose(FILE* f) {
135 if (f) {
136 fclose(f);
137 }
138 }
139
sk_isdir(const char * path)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
sk_mkdir(const char * path)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