• 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  *
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