• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  * Portions Copyright (c) 2010 Motorola Mobility, Inc.  All rights reserved.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public License
18  * along with this library; see the file COPYING.LIB.  If not, write to
19  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20  * Boston, MA 02110-1301, USA.
21  */
22 
23 #include "config.h"
24 #include "FileSystem.h"
25 
26 #include "GOwnPtr.h"
27 #include "PlatformString.h"
28 #include "UUID.h"
29 #include <gio/gio.h>
30 #include <glib.h>
31 #include <glib/gstdio.h>
32 #include <wtf/gobject/GRefPtr.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. */
filenameToString(const char * filename)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     GOwnPtr<gchar> escapedString(g_uri_escape_string(filename, "/:", false));
50     return escapedString.get();
51 #endif
52 }
53 
fileSystemRepresentation(const String & path)54 CString fileSystemRepresentation(const String& path)
55 {
56 #if OS(WINDOWS)
57     return path.utf8();
58 #else
59     GOwnPtr<gchar> filename(g_uri_unescape_string(path.utf8().data(), 0));
60     return filename.get();
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     CString filename = fileSystemRepresentation(string);
71     GOwnPtr<gchar> display(g_filename_to_utf8(filename.data(), 0, 0, 0, 0));
72     if (!display)
73         return string;
74 
75     return String::fromUTF8(display.get());
76 #endif
77 }
78 
fileExists(const String & path)79 bool fileExists(const String& path)
80 {
81     bool result = false;
82     CString filename = fileSystemRepresentation(path);
83 
84     if (!filename.isNull())
85         result = g_file_test(filename.data(), G_FILE_TEST_EXISTS);
86 
87     return result;
88 }
89 
deleteFile(const String & path)90 bool deleteFile(const String& path)
91 {
92     bool result = false;
93     CString filename = fileSystemRepresentation(path);
94 
95     if (!filename.isNull())
96         result = g_remove(filename.data()) == 0;
97 
98     return result;
99 }
100 
deleteEmptyDirectory(const String & path)101 bool deleteEmptyDirectory(const String& path)
102 {
103     bool result = false;
104     CString filename = fileSystemRepresentation(path);
105 
106     if (!filename.isNull())
107         result = g_rmdir(filename.data()) == 0;
108 
109     return result;
110 }
111 
getFileSize(const String & path,long long & resultSize)112 bool getFileSize(const String& path, long long& resultSize)
113 {
114     CString filename = fileSystemRepresentation(path);
115     if (filename.isNull())
116         return false;
117 
118     struct stat statResult;
119     gint result = g_stat(filename.data(), &statResult);
120     if (result != 0)
121         return false;
122 
123     resultSize = statResult.st_size;
124     return true;
125 }
126 
getFileModificationTime(const String & path,time_t & modifiedTime)127 bool getFileModificationTime(const String& path, time_t& modifiedTime)
128 {
129     CString filename = fileSystemRepresentation(path);
130     if (filename.isNull())
131         return false;
132 
133     struct stat statResult;
134     gint result = g_stat(filename.data(), &statResult);
135     if (result != 0)
136         return false;
137 
138     modifiedTime = statResult.st_mtime;
139     return true;
140 
141 }
142 
pathByAppendingComponent(const String & path,const String & component)143 String pathByAppendingComponent(const String& path, const String& component)
144 {
145     if (path.endsWith(G_DIR_SEPARATOR_S))
146         return path + component;
147     else
148         return path + G_DIR_SEPARATOR_S + component;
149 }
150 
makeAllDirectories(const String & path)151 bool makeAllDirectories(const String& path)
152 {
153     CString filename = fileSystemRepresentation(path);
154     if (filename.isNull())
155         return false;
156 
157     gint result = g_mkdir_with_parents(filename.data(), S_IRWXU);
158 
159     return result == 0;
160 }
161 
homeDirectoryPath()162 String homeDirectoryPath()
163 {
164     return filenameToString(g_get_home_dir());
165 }
166 
pathGetFileName(const String & pathName)167 String pathGetFileName(const String& pathName)
168 {
169     if (pathName.isEmpty())
170         return pathName;
171 
172     CString tmpFilename = fileSystemRepresentation(pathName);
173     GOwnPtr<gchar> baseName(g_path_get_basename(tmpFilename.data()));
174     return String::fromUTF8(baseName.get());
175 }
176 
applicationDirectoryPath()177 CString applicationDirectoryPath()
178 {
179 #if OS(LINUX)
180     // Handle the /proc filesystem case.
181     char pathFromProc[PATH_MAX] = {0};
182     if (readlink("/proc/self/exe", pathFromProc, sizeof(pathFromProc) - 1) == -1)
183         return CString();
184 
185     GOwnPtr<char> dirname(g_path_get_dirname(pathFromProc));
186     return dirname.get();
187 #elif OS(UNIX)
188     // If the above fails, check the PATH env variable.
189     GOwnPtr<char> currentExePath(g_find_program_in_path(g_get_prgname()));
190     if (!currentExePath.get())
191         return CString();
192 
193     GOwnPtr<char> dirname(g_path_get_dirname(currentExePath.get()));
194     return dirname.get();
195 #else
196     return CString();
197 #endif
198 }
199 
directoryName(const String & path)200 String directoryName(const String& path)
201 {
202     /* No null checking needed */
203     GOwnPtr<char> dirname(g_path_get_dirname(fileSystemRepresentation(path).data()));
204     return String::fromUTF8(dirname.get());
205 }
206 
listDirectory(const String & path,const String & filter)207 Vector<String> listDirectory(const String& path, const String& filter)
208 {
209     Vector<String> entries;
210 
211     CString filename = fileSystemRepresentation(path);
212     GDir* dir = g_dir_open(filename.data(), 0, 0);
213     if (!dir)
214         return entries;
215 
216     GPatternSpec *pspec = g_pattern_spec_new((filter.utf8()).data());
217     while (const char* name = g_dir_read_name(dir)) {
218         if (!g_pattern_match_string(pspec, name))
219             continue;
220 
221         GOwnPtr<gchar> entry(g_build_filename(filename.data(), name, NULL));
222         entries.append(filenameToString(entry.get()));
223     }
224     g_pattern_spec_free(pspec);
225     g_dir_close(dir);
226 
227     return entries;
228 }
229 
openTemporaryFile(const String & prefix,PlatformFileHandle & handle)230 String openTemporaryFile(const String& prefix, PlatformFileHandle& handle)
231 {
232     GOwnPtr<gchar> filename(g_strdup_printf("%s%s", prefix.utf8().data(), createCanonicalUUIDString().utf8().data()));
233     GOwnPtr<gchar> tempPath(g_build_filename(g_get_tmp_dir(), filename.get(), NULL));
234     GRefPtr<GFile> file = adoptGRef(g_file_new_for_path(tempPath.get()));
235 
236     handle = g_file_create_readwrite(file.get(), G_FILE_CREATE_NONE, 0, 0);
237     if (!isHandleValid(handle))
238         return String();
239     return String::fromUTF8(tempPath.get());
240 }
241 
openFile(const String & path,FileOpenMode mode)242 PlatformFileHandle openFile(const String& path, FileOpenMode mode)
243 {
244     CString fsRep = fileSystemRepresentation(path);
245     if (fsRep.isNull())
246         return invalidPlatformFileHandle;
247 
248     GRefPtr<GFile> file = adoptGRef(g_file_new_for_path(fsRep.data()));
249     GFileIOStream* ioStream = 0;
250     if (mode == OpenForRead)
251         ioStream = g_file_open_readwrite(file.get(), 0, 0);
252     else if (mode == OpenForWrite) {
253         if (g_file_test(fsRep.data(), static_cast<GFileTest>(G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR)))
254             ioStream = g_file_open_readwrite(file.get(), 0, 0);
255         else
256             ioStream = g_file_create_readwrite(file.get(), G_FILE_CREATE_NONE, 0, 0);
257     }
258 
259     return ioStream;
260 }
261 
closeFile(PlatformFileHandle & handle)262 void closeFile(PlatformFileHandle& handle)
263 {
264     if (!isHandleValid(handle))
265         return;
266 
267     g_io_stream_close(G_IO_STREAM(handle), 0, 0);
268     g_object_unref(handle);
269     handle = invalidPlatformFileHandle;
270 }
271 
seekFile(PlatformFileHandle handle,long long offset,FileSeekOrigin origin)272 long long seekFile(PlatformFileHandle handle, long long offset, FileSeekOrigin origin)
273 {
274     GSeekType seekType = G_SEEK_SET;
275     switch (origin) {
276     case SeekFromBeginning:
277         seekType = G_SEEK_SET;
278         break;
279     case SeekFromCurrent:
280         seekType = G_SEEK_CUR;
281         break;
282     case SeekFromEnd:
283         seekType = G_SEEK_END;
284         break;
285     default:
286         ASSERT_NOT_REACHED();
287     }
288 
289     if (!g_seekable_seek(G_SEEKABLE(g_io_stream_get_input_stream(G_IO_STREAM(handle))),
290                          offset, seekType, 0, 0))
291         return -1;
292     return g_seekable_tell(G_SEEKABLE(g_io_stream_get_input_stream(G_IO_STREAM(handle))));
293 }
294 
writeToFile(PlatformFileHandle handle,const char * data,int length)295 int writeToFile(PlatformFileHandle handle, const char* data, int length)
296 {
297     gsize bytesWritten;
298     g_output_stream_write_all(g_io_stream_get_output_stream(G_IO_STREAM(handle)),
299                               data, length, &bytesWritten, 0, 0);
300     return bytesWritten;
301 }
302 
readFromFile(PlatformFileHandle handle,char * data,int length)303 int readFromFile(PlatformFileHandle handle, char* data, int length)
304 {
305     GOwnPtr<GError> error;
306     do {
307         gssize bytesRead = g_input_stream_read(g_io_stream_get_input_stream(G_IO_STREAM(handle)),
308                                                data, length, 0, &error.outPtr());
309         if (bytesRead >= 0)
310             return bytesRead;
311     } while (error && error->code == G_FILE_ERROR_INTR);
312     return -1;
313 }
314 
unloadModule(PlatformModule module)315 bool unloadModule(PlatformModule module)
316 {
317     return g_module_close(module);
318 }
319 }
320