2010-11-23 Adam Bergkvist <adam.bergkvist@ericsson.com>
[WebKit-https.git] / WebCore / platform / gtk / FileSystemGtk.cpp
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
28 #include <errno.h>
29 #include <fcntl.h>
30 #include <glib.h>
31 #include <glib/gstdio.h>
32 #include <unistd.h>
33 #include <wtf/text/CString.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. */
41 String filenameToString(const char* filename)
42 {
43     if (!filename)
44         return String();
45
46 #if OS(WINDOWS)
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
56 CString fileSystemRepresentation(const String& path)
57 {
58 #if OS(WINDOWS)
59     return path.utf8();
60 #else
61     char* filename = g_uri_unescape_string(path.utf8().data(), 0);
62     CString cfilename(filename);
63     g_free(filename);
64     return cfilename;
65 #endif
66 }
67
68 // Converts a string to something suitable to be displayed to the user.
69 String filenameForDisplay(const String& string)
70 {
71 #if OS(WINDOWS)
72     return string;
73 #else
74     CString filename = fileSystemRepresentation(string);
75     gchar* display = g_filename_to_utf8(filename.data(), 0, 0, 0, 0);
76     if (!display)
77         return string;
78
79     String displayString = String::fromUTF8(display);
80     g_free(display);
81
82     return displayString;
83 #endif
84 }
85
86 bool fileExists(const String& path)
87 {
88     bool result = false;
89     CString filename = fileSystemRepresentation(path);
90
91     if (!filename.isNull())
92         result = g_file_test(filename.data(), G_FILE_TEST_EXISTS);
93
94     return result;
95 }
96
97 bool deleteFile(const String& path)
98 {
99     bool result = false;
100     CString filename = fileSystemRepresentation(path);
101
102     if (!filename.isNull())
103         result = g_remove(filename.data()) == 0;
104
105     return result;
106 }
107
108 bool deleteEmptyDirectory(const String& path)
109 {
110     bool result = false;
111     CString filename = fileSystemRepresentation(path);
112
113     if (!filename.isNull())
114         result = g_rmdir(filename.data()) == 0;
115
116     return result;
117 }
118
119 bool getFileSize(const String& path, long long& resultSize)
120 {
121     CString filename = fileSystemRepresentation(path);
122     if (filename.isNull())
123         return false;
124
125     struct stat statResult;
126     gint result = g_stat(filename.data(), &statResult);
127     if (result != 0)
128         return false;
129
130     resultSize = statResult.st_size;
131     return true;
132 }
133
134 bool getFileModificationTime(const String& path, time_t& modifiedTime)
135 {
136     CString filename = fileSystemRepresentation(path);
137     if (filename.isNull())
138         return false;
139
140     struct stat statResult;
141     gint result = g_stat(filename.data(), &statResult);
142     if (result != 0)
143         return false;
144
145     modifiedTime = statResult.st_mtime;
146     return true;
147
148 }
149
150 String pathByAppendingComponent(const String& path, const String& component)
151 {
152     if (path.endsWith(G_DIR_SEPARATOR_S))
153         return path + component;
154     else
155         return path + G_DIR_SEPARATOR_S + component;
156 }
157
158 bool makeAllDirectories(const String& path)
159 {
160     CString filename = fileSystemRepresentation(path);
161     if (filename.isNull())
162         return false;
163
164     gint result = g_mkdir_with_parents(filename.data(), S_IRWXU);
165
166     return result == 0;
167 }
168
169 String homeDirectoryPath()
170 {
171     return filenameToString(g_get_home_dir());
172 }
173
174 String pathGetFileName(const String& pathName)
175 {
176     if (pathName.isEmpty())
177         return pathName;
178
179     CString tmpFilename = fileSystemRepresentation(pathName);
180     char* baseName = g_path_get_basename(tmpFilename.data());
181     String fileName = String::fromUTF8(baseName);
182     g_free(baseName);
183
184     return fileName;
185 }
186
187 String directoryName(const String& path)
188 {
189     /* No null checking needed */
190     GOwnPtr<char> dirname(g_path_get_dirname(fileSystemRepresentation(path).data()));
191     return String::fromUTF8(dirname.get());
192 }
193
194 Vector<String> listDirectory(const String& path, const String& filter)
195 {
196     Vector<String> entries;
197
198     CString filename = fileSystemRepresentation(path);
199     GDir* dir = g_dir_open(filename.data(), 0, 0);
200     if (!dir)
201         return entries;
202
203     GPatternSpec *pspec = g_pattern_spec_new((filter.utf8()).data());
204     while (const char* name = g_dir_read_name(dir)) {
205         if (!g_pattern_match_string(pspec, name))
206             continue;
207
208         GOwnPtr<gchar> entry(g_build_filename(filename.data(), name, NULL));
209         entries.append(filenameToString(entry.get()));
210     }
211     g_pattern_spec_free(pspec);
212     g_dir_close(dir);
213
214     return entries;
215 }
216
217 CString openTemporaryFile(const char* prefix, PlatformFileHandle& handle)
218 {
219     gchar* filename = g_strdup_printf("%sXXXXXX", prefix);
220     gchar* tempPath = g_build_filename(g_get_tmp_dir(), filename, NULL);
221     g_free(filename);
222
223     int fileDescriptor = g_mkstemp(tempPath);
224     if (!isHandleValid(fileDescriptor)) {
225         LOG_ERROR("Can't create a temporary file.");
226         g_free(tempPath);
227         return CString();
228     }
229     CString tempFilePath = tempPath;
230     g_free(tempPath);
231
232     handle = fileDescriptor;
233     return tempFilePath;
234 }
235
236 PlatformFileHandle openFile(const String& path, FileOpenMode mode)
237 {
238     CString fsRep = fileSystemRepresentation(path);
239
240     if (fsRep.isNull())
241         return invalidPlatformFileHandle;
242
243     int platformFlag = 0;
244     if (mode == OpenForRead)
245         platformFlag |= O_RDONLY;
246     else if (mode == OpenForWrite)
247         platformFlag |= (O_WRONLY | O_CREAT | O_TRUNC);
248
249     return g_open(fsRep.data(), platformFlag, 0666);
250 }
251
252 void closeFile(PlatformFileHandle& handle)
253 {
254     if (isHandleValid(handle)) {
255         close(handle);
256         handle = invalidPlatformFileHandle;
257     }
258 }
259
260 long long seekFile(PlatformFileHandle handle, long long offset, FileSeekOrigin origin)
261 {
262     // FIXME - Awaiting implementation, see https://bugs.webkit.org/show_bug.cgi?id=43878
263     return -1;
264 }
265
266 int writeToFile(PlatformFileHandle handle, const char* data, int length)
267 {
268     int totalBytesWritten = 0;
269     while (totalBytesWritten < length) {
270         int bytesWritten = write(handle, data, length - totalBytesWritten);
271         if (bytesWritten < 0)
272             return -1;
273         totalBytesWritten += bytesWritten;
274         data += bytesWritten;
275     }
276
277     return totalBytesWritten;
278 }
279
280 int readFromFile(PlatformFileHandle handle, char* data, int length)
281 {
282     do {
283         int bytesRead = read(handle, data, static_cast<size_t>(length));
284         if (bytesRead >= 0)
285             return bytesRead;
286     } while (errno == EINTR);
287
288     return -1;
289 }
290
291 bool unloadModule(PlatformModule module)
292 {
293     return g_module_close(module);
294 }
295 }