1 /*
2 * Copyright (C) 2007, 2009 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 "GOwnPtr.h"
26 #include "PlatformString.h"
27 #include "CString.h"
28
29 #include <glib.h>
30 #include <glib/gstdio.h>
31
32 #include <unistd.h>
33
34 namespace WebCore {
35
36 /* On linux file names are just raw bytes, so also strings that cannot be encoded in any way
37 * are valid file names. This mean that we cannot just store a file name as-is in a String
38 * but we have to escape it.
39 * On Windows the GLib file name encoding is always UTF-8 so we can optimize this case. */
filenameToString(const char * filename)40 String filenameToString(const char* filename)
41 {
42 if (!filename)
43 return String();
44
45 #if OS(WINDOWS)
46 return String::fromUTF8(filename);
47 #else
48 gchar* escapedString = g_uri_escape_string(filename, "/:", false);
49 String string(escapedString);
50 g_free(escapedString);
51 return string;
52 #endif
53 }
54
filenameFromString(const String & string)55 char* filenameFromString(const String& string)
56 {
57 #if OS(WINDOWS)
58 return g_strdup(string.utf8().data());
59 #else
60 return g_uri_unescape_string(string.utf8().data(), 0);
61 #endif
62 }
63
64 // Converts a string to something suitable to be displayed to the user.
filenameForDisplay(const String & string)65 String filenameForDisplay(const String& string)
66 {
67 #if OS(WINDOWS)
68 return string;
69 #else
70 gchar* filename = filenameFromString(string);
71 gchar* display = g_filename_to_utf8(filename, 0, 0, 0, 0);
72 g_free(filename);
73 if (!display)
74 return string;
75
76 String displayString = String::fromUTF8(display);
77 g_free(display);
78
79 return displayString;
80 #endif
81 }
82
fileExists(const String & path)83 bool fileExists(const String& path)
84 {
85 bool result = false;
86 gchar* filename = filenameFromString(path);
87
88 if (filename) {
89 result = g_file_test(filename, G_FILE_TEST_EXISTS);
90 g_free(filename);
91 }
92
93 return result;
94 }
95
deleteFile(const String & path)96 bool deleteFile(const String& path)
97 {
98 bool result = false;
99 gchar* filename = filenameFromString(path);
100
101 if (filename) {
102 result = g_remove(filename) == 0;
103 g_free(filename);
104 }
105
106 return result;
107 }
108
deleteEmptyDirectory(const String & path)109 bool deleteEmptyDirectory(const String& path)
110 {
111 bool result = false;
112 gchar* filename = filenameFromString(path);
113
114 if (filename) {
115 result = g_rmdir(filename) == 0;
116 g_free(filename);
117 }
118
119 return result;
120 }
121
getFileSize(const String & path,long long & resultSize)122 bool getFileSize(const String& path, long long& resultSize)
123 {
124 gchar* filename = filenameFromString(path);
125 if (!filename)
126 return false;
127
128 struct stat statResult;
129 gint result = g_stat(filename, &statResult);
130 g_free(filename);
131 if (result != 0)
132 return false;
133
134 resultSize = statResult.st_size;
135 return true;
136 }
137
getFileModificationTime(const String & path,time_t & modifiedTime)138 bool getFileModificationTime(const String& path, time_t& modifiedTime)
139 {
140 gchar* filename = filenameFromString(path);
141 if (!filename)
142 return false;
143
144 struct stat statResult;
145 gint result = g_stat(filename, &statResult);
146 g_free(filename);
147 if (result != 0)
148 return false;
149
150 modifiedTime = statResult.st_mtime;
151 return true;
152
153 }
154
pathByAppendingComponent(const String & path,const String & component)155 String pathByAppendingComponent(const String& path, const String& component)
156 {
157 if (path.endsWith(G_DIR_SEPARATOR_S))
158 return path + component;
159 else
160 return path + G_DIR_SEPARATOR_S + component;
161 }
162
makeAllDirectories(const String & path)163 bool makeAllDirectories(const String& path)
164 {
165 gchar* filename = filenameFromString(path);
166 if (!filename)
167 return false;
168
169 gint result = g_mkdir_with_parents(filename, S_IRWXU);
170 g_free(filename);
171
172 return result == 0;
173 }
174
homeDirectoryPath()175 String homeDirectoryPath()
176 {
177 return filenameToString(g_get_home_dir());
178 }
179
pathGetFileName(const String & pathName)180 String pathGetFileName(const String& pathName)
181 {
182 if (pathName.isEmpty())
183 return pathName;
184
185 char* tmpFilename = filenameFromString(pathName);
186 char* baseName = g_path_get_basename(tmpFilename);
187 String fileName = String::fromUTF8(baseName);
188 g_free(baseName);
189 g_free(tmpFilename);
190
191 return fileName;
192 }
193
directoryName(const String & path)194 String directoryName(const String& path)
195 {
196 /* No null checking needed */
197 GOwnPtr<char> tmpFilename(filenameFromString(path));
198 GOwnPtr<char> dirname(g_path_get_dirname(tmpFilename.get()));
199 return String::fromUTF8(dirname.get());
200 }
201
listDirectory(const String & path,const String & filter)202 Vector<String> listDirectory(const String& path, const String& filter)
203 {
204 Vector<String> entries;
205
206 gchar* filename = filenameFromString(path);
207 GDir* dir = g_dir_open(filename, 0, 0);
208 if (!dir)
209 return entries;
210
211 GPatternSpec *pspec = g_pattern_spec_new((filter.utf8()).data());
212 while (const char* name = g_dir_read_name(dir)) {
213 if (!g_pattern_match_string(pspec, name))
214 continue;
215
216 gchar* entry = g_build_filename(filename, name, NULL);
217 entries.append(filenameToString(entry));
218 g_free(entry);
219 }
220 g_dir_close(dir);
221 g_free(filename);
222
223 return entries;
224 }
225
openTemporaryFile(const char * prefix,PlatformFileHandle & handle)226 CString openTemporaryFile(const char* prefix, PlatformFileHandle& handle)
227 {
228 gchar* filename = g_strdup_printf("%sXXXXXX", prefix);
229 gchar* tempPath = g_build_filename(g_get_tmp_dir(), filename, NULL);
230 g_free(filename);
231
232 int fileDescriptor = g_mkstemp(tempPath);
233 if (!isHandleValid(fileDescriptor)) {
234 LOG_ERROR("Can't create a temporary file.");
235 g_free(tempPath);
236 return CString();
237 }
238 CString tempFilePath = tempPath;
239 g_free(tempPath);
240
241 handle = fileDescriptor;
242 return tempFilePath;
243 }
244
closeFile(PlatformFileHandle & handle)245 void closeFile(PlatformFileHandle& handle)
246 {
247 if (isHandleValid(handle)) {
248 close(handle);
249 handle = invalidPlatformFileHandle;
250 }
251 }
252
writeToFile(PlatformFileHandle handle,const char * data,int length)253 int writeToFile(PlatformFileHandle handle, const char* data, int length)
254 {
255 int totalBytesWritten = 0;
256 while (totalBytesWritten < length) {
257 int bytesWritten = write(handle, data, length - totalBytesWritten);
258 if (bytesWritten < 0)
259 return -1;
260 totalBytesWritten += bytesWritten;
261 }
262
263 return totalBytesWritten;
264 }
265
unloadModule(PlatformModule module)266 bool unloadModule(PlatformModule module)
267 {
268 return g_module_close(module);
269 }
270 }
271