• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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