1 /*
2 * Copyright (C) 2007 Holger Hans Peter Freyther
3 * Copyright (C) 2008 Collabora, Ltd.
4 * Copyright (C) 2008 Apple Inc. All rights reserved.
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
15 *
16 * You should have received a copy of the GNU Library General Public License
17 * along with this library; see the file COPYING.LIB. If not, write to
18 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
20 */
21
22 #include "config.h"
23 #include "FileSystem.h"
24
25 #include "guriescape.h"
26 #include "NotImplemented.h"
27 #include "PlatformString.h"
28 #include "CString.h"
29
30 #include <glib.h>
31 #include <glib/gstdio.h>
32
33 #include <unistd.h>
34
35 namespace WebCore {
36
37 /* On linux file names are just raw bytes, so also strings that cannot be encoded in any way
38 * are valid file names. This mean that we cannot just store a file name as-is in a String
39 * but we have to escape it.
40 * On Windows the GLib file name encoding is always UTF-8 so we can optimize this case. */
filenameToString(const char * filename)41 String filenameToString(const char* filename)
42 {
43 if (!filename)
44 return String();
45
46 #if PLATFORM(WIN_OS)
47 return String::fromUTF8(filename);
48 #else
49 gchar* escapedString = g_uri_escape_string(filename, "/:", false);
50 String string(escapedString);
51 g_free(escapedString);
52 return string;
53 #endif
54 }
55
filenameFromString(const String & string)56 char* filenameFromString(const String& string)
57 {
58 #if PLATFORM(WIN_OS)
59 return g_strdup(string.utf8().data());
60 #else
61 return g_uri_unescape_string(string.utf8().data(), 0);
62 #endif
63 }
64
65 // Converts a string to something suitable to be displayed to the user.
filenameForDisplay(const String & string)66 String filenameForDisplay(const String& string)
67 {
68 #if PLATFORM(WIN_OS)
69 return string;
70 #else
71 gchar* filename = filenameFromString(string);
72 gchar* display = g_filename_to_utf8(filename, 0, 0, 0, 0);
73 g_free(filename);
74 if (!display)
75 return string;
76
77 String displayString = String::fromUTF8(display);
78 g_free(display);
79
80 return displayString;
81 #endif
82 }
83
fileExists(const String & path)84 bool fileExists(const String& path)
85 {
86 bool result = false;
87 gchar* filename = filenameFromString(path);
88
89 if (filename) {
90 result = g_file_test(filename, G_FILE_TEST_EXISTS);
91 g_free(filename);
92 }
93
94 return result;
95 }
96
deleteFile(const String & path)97 bool deleteFile(const String& path)
98 {
99 bool result = false;
100 gchar* filename = filenameFromString(path);
101
102 if (filename) {
103 result = g_remove(filename) == 0;
104 g_free(filename);
105 }
106
107 return result;
108 }
109
deleteEmptyDirectory(const String & path)110 bool deleteEmptyDirectory(const String& path)
111 {
112 bool result = false;
113 gchar* filename = filenameFromString(path);
114
115 if (filename) {
116 result = g_rmdir(filename) == 0;
117 g_free(filename);
118 }
119
120 return result;
121 }
122
getFileSize(const String & path,long long & resultSize)123 bool getFileSize(const String& path, long long& resultSize)
124 {
125 gchar* filename = filenameFromString(path);
126 if (!filename)
127 return false;
128
129 struct stat statResult;
130 gint result = g_stat(filename, &statResult);
131 g_free(filename);
132 if (result != 0)
133 return false;
134
135 resultSize = statResult.st_size;
136 return true;
137 }
138
getFileModificationTime(const String & path,time_t & modifiedTime)139 bool getFileModificationTime(const String& path, time_t& modifiedTime)
140 {
141 gchar* filename = filenameFromString(path);
142 if (!filename)
143 return false;
144
145 struct stat statResult;
146 gint result = g_stat(filename, &statResult);
147 g_free(filename);
148 if (result != 0)
149 return false;
150
151 modifiedTime = statResult.st_mtime;
152 return true;
153
154 }
155
pathByAppendingComponent(const String & path,const String & component)156 String pathByAppendingComponent(const String& path, const String& component)
157 {
158 if (path.endsWith(G_DIR_SEPARATOR_S))
159 return path + component;
160 else
161 return path + G_DIR_SEPARATOR_S + component;
162 }
163
makeAllDirectories(const String & path)164 bool makeAllDirectories(const String& path)
165 {
166 gchar* filename = filenameFromString(path);
167 if (!filename)
168 return false;
169
170 gint result = g_mkdir_with_parents(filename, S_IRWXU);
171 g_free(filename);
172
173 return result == 0;
174 }
175
homeDirectoryPath()176 String homeDirectoryPath()
177 {
178 return filenameToString(g_get_home_dir());
179 }
180
pathGetFileName(const String & pathName)181 String pathGetFileName(const String& pathName)
182 {
183 char* tmpFilename = filenameFromString(pathName);
184 char* baseName = g_path_get_basename(tmpFilename);
185 String fileName = String::fromUTF8(baseName);
186 g_free(baseName);
187 g_free(tmpFilename);
188
189 return fileName;
190 }
191
directoryName(const String & path)192 String directoryName(const String& path)
193 {
194 notImplemented();
195 return String();
196 }
197
listDirectory(const String & path,const String & filter)198 Vector<String> listDirectory(const String& path, const String& filter)
199 {
200 Vector<String> entries;
201
202 gchar* filename = filenameFromString(path);
203 GDir* dir = g_dir_open(filename, 0, 0);
204 if (!dir)
205 return entries;
206
207 GPatternSpec *pspec = g_pattern_spec_new((filter.utf8()).data());
208 while (const char* name = g_dir_read_name(dir)) {
209 if (!g_pattern_match_string(pspec, name))
210 continue;
211
212 gchar* entry = g_build_filename(filename, name, NULL);
213 entries.append(filenameToString(entry));
214 g_free(entry);
215 }
216 g_dir_close(dir);
217 g_free(filename);
218
219 return entries;
220 }
221
openTemporaryFile(const char * prefix,PlatformFileHandle & handle)222 CString openTemporaryFile(const char* prefix, PlatformFileHandle& handle)
223 {
224 gchar* filename = g_strdup_printf("%sXXXXXX", prefix);
225 gchar* tempPath = g_build_filename(g_get_tmp_dir(), filename, NULL);
226 g_free(filename);
227
228 int fileDescriptor = g_mkstemp(tempPath);
229 if (!isHandleValid(fileDescriptor)) {
230 LOG_ERROR("Can't create a temporary file.");
231 g_free(tempPath);
232 return 0;
233 }
234 CString tempFilePath = tempPath;
235 g_free(tempPath);
236
237 handle = fileDescriptor;
238 return tempFilePath;
239 }
240
closeFile(PlatformFileHandle & handle)241 void closeFile(PlatformFileHandle& handle)
242 {
243 if (isHandleValid(handle)) {
244 close(handle);
245 handle = invalidPlatformFileHandle;
246 }
247 }
248
writeToFile(PlatformFileHandle handle,const char * data,int length)249 int writeToFile(PlatformFileHandle handle, const char* data, int length)
250 {
251 int totalBytesWritten = 0;
252 while (totalBytesWritten < length) {
253 int bytesWritten = write(handle, data, length - totalBytesWritten);
254 if (bytesWritten < 0)
255 return -1;
256 totalBytesWritten += bytesWritten;
257 }
258
259 return totalBytesWritten;
260 }
261
unloadModule(PlatformModule module)262 bool unloadModule(PlatformModule module)
263 {
264 return g_module_close(module);
265 }
266 }
267