2 * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
3 * Copyright (C) 2008 Collabora, Ltd. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
15 * its contributors may be used to endorse or promote products derived
16 * from this software without specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
19 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
22 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #include "FileSystem.h"
34 #include "NotImplemented.h"
35 #include "PlatformString.h"
44 static bool statFile(String path, struct _stat64& st)
46 ASSERT_ARG(path, !path.isNull());
47 return !_wstat64(path.charactersWithNullTermination(), &st) && (st.st_mode & _S_IFMT) == _S_IFREG;
50 bool getFileSize(const String& path, long long& result)
53 if (!statFile(path, sb))
59 bool getFileModificationTime(const String& path, time_t& result)
62 if (!statFile(path, st))
68 bool fileExists(const String& path)
71 return statFile(path, st);
74 bool deleteFile(const String& path)
76 String filename = path;
77 return !!DeleteFileW(filename.charactersWithNullTermination());
80 bool deleteEmptyDirectory(const String& path)
82 String filename = path;
83 return !!RemoveDirectoryW(filename.charactersWithNullTermination());
86 String pathByAppendingComponent(const String& path, const String& component)
88 Vector<UChar> buffer(MAX_PATH);
90 if (path.length() + 1 > buffer.size())
93 memcpy(buffer.data(), path.characters(), path.length() * sizeof(UChar));
94 buffer[path.length()] = '\0';
96 String componentCopy = component;
97 if (!PathAppendW(buffer.data(), componentCopy.charactersWithNullTermination()))
100 buffer.resize(wcslen(buffer.data()));
102 return String::adopt(buffer);
105 CString fileSystemRepresentation(const String&)
110 bool makeAllDirectories(const String& path)
112 String fullPath = path;
113 if (SHCreateDirectoryEx(0, fullPath.charactersWithNullTermination(), 0) != ERROR_SUCCESS) {
114 DWORD error = GetLastError();
115 if (error != ERROR_FILE_EXISTS && error != ERROR_ALREADY_EXISTS) {
116 LOG_ERROR("Failed to create path %s", path.ascii().data());
123 String homeDirectoryPath()
129 String pathGetFileName(const String& path)
131 return String(PathFindFileName(String(path).charactersWithNullTermination()));
134 static String bundleName()
136 static bool initialized;
137 static String name = "WebKit";
142 if (CFBundleRef bundle = CFBundleGetMainBundle())
143 if (CFTypeRef bundleExecutable = CFBundleGetValueForInfoDictionaryKey(bundle, kCFBundleExecutableKey))
144 if (CFGetTypeID(bundleExecutable) == CFStringGetTypeID())
145 name = reinterpret_cast<CFStringRef>(bundleExecutable);
151 static String storageDirectory(DWORD pathIdentifier)
153 Vector<UChar> buffer(MAX_PATH);
154 if (FAILED(SHGetFolderPathW(0, pathIdentifier | CSIDL_FLAG_CREATE, 0, 0, buffer.data())))
156 buffer.resize(wcslen(buffer.data()));
157 String directory = String::adopt(buffer);
159 static const String companyNameDirectory = "Apple Computer\\";
160 directory = pathByAppendingComponent(directory, companyNameDirectory + bundleName());
161 if (!makeAllDirectories(directory))
167 static String cachedStorageDirectory(DWORD pathIdentifier)
169 static HashMap<DWORD, String> directories;
171 HashMap<DWORD, String>::iterator it = directories.find(pathIdentifier);
172 if (it != directories.end())
175 String directory = storageDirectory(pathIdentifier);
176 directories.add(pathIdentifier, directory);
182 CString openTemporaryFile(const char* prefix, PlatformFileHandle& handle)
184 char tempPath[MAX_PATH];
185 int tempPathLength = ::GetTempPathA(_countof(tempPath), tempPath);
186 if (tempPathLength <= 0 || tempPathLength > _countof(tempPath))
189 char tempFile[MAX_PATH];
190 if (::GetTempFileNameA(tempPath, prefix, 0, tempFile) > 0) {
191 HANDLE tempHandle = ::CreateFileA(tempFile, GENERIC_READ | GENERIC_WRITE, 0, 0,
192 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
194 if (isHandleValid(tempHandle)) {
202 void closeFile(PlatformFileHandle& handle)
204 if (isHandleValid(handle)) {
205 ::CloseHandle(handle);
206 handle = invalidPlatformFileHandle;
210 int writeToFile(PlatformFileHandle handle, const char* data, int length)
212 if (!isHandleValid(handle))
216 bool success = WriteFile(handle, data, length, &bytesWritten, 0);
220 return static_cast<int>(bytesWritten);
223 bool unloadModule(PlatformModule module)
225 return ::FreeLibrary(module);
228 String localUserSpecificStorageDirectory()
230 return cachedStorageDirectory(CSIDL_LOCAL_APPDATA);
233 String roamingUserSpecificStorageDirectory()
235 return cachedStorageDirectory(CSIDL_APPDATA);
238 bool safeCreateFile(const String& path, CFDataRef data)
240 // Create a temporary file.
241 WCHAR tempDirPath[MAX_PATH];
242 if (!GetTempPathW(ARRAYSIZE(tempDirPath), tempDirPath))
245 WCHAR tempPath[MAX_PATH];
246 if (!GetTempFileNameW(tempDirPath, L"WEBKIT", 0, tempPath))
249 HANDLE tempFileHandle = CreateFileW(tempPath, GENERIC_READ | GENERIC_WRITE, 0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
250 if (tempFileHandle == INVALID_HANDLE_VALUE)
253 // Write the data to this temp file.
255 if (!WriteFile(tempFileHandle, CFDataGetBytePtr(data), static_cast<DWORD>(CFDataGetLength(data)), &written, 0))
258 CloseHandle(tempFileHandle);
260 // Copy the temp file to the destination file.
261 String destination = path;
262 if (!MoveFileExW(tempPath, destination.charactersWithNullTermination(), MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED))
268 } // namespace WebCore