c58ffe0b981ca9cb4224c568016d0d71fc9c51a1
[WebKit-https.git] / WebCore / platform / win / FileSystemWin.cpp
1 /*\r
2  * Copyright (C) 2007 Apple Inc. All rights reserved.\r
3  * Copyright (C) 2008 Collabora, Ltd. All rights reserved.
4  *\r
5  * Redistribution and use in source and binary forms, with or without\r
6  * modification, are permitted provided that the following conditions\r
7  * are met:\r
8  *\r
9  * 1.  Redistributions of source code must retain the above copyright\r
10  *     notice, this list of conditions and the following disclaimer. \r
11  * 2.  Redistributions in binary form must reproduce the above copyright\r
12  *     notice, this list of conditions and the following disclaimer in the\r
13  *     documentation and/or other materials provided with the distribution. \r
14  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of\r
15  *     its contributors may be used to endorse or promote products derived\r
16  *     from this software without specific prior written permission. \r
17  *\r
18  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY\r
19  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\r
20  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\r
21  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY\r
22  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\r
23  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\r
24  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\r
25  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\r
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\r
27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
28  */\r
29 \r
30 #include "config.h"\r
31 #include "FileSystem.h"\r
32 \r
33 #include "CString.h"\r
34 #include "NotImplemented.h"\r
35 #include "PlatformString.h"\r
36 \r
37 #include <windows.h>\r
38 #include <winbase.h>\r
39 #include <shlobj.h>\r
40 #include <shlwapi.h>\r
41 \r
42 namespace WebCore {\r
43 \r
44 bool fileSize(const String& path, long long& result)\r
45 {\r
46     struct _stat32i64 sb;\r
47     String filename = path;\r
48     int statResult = _wstat32i64(filename.charactersWithNullTermination(), &sb);\r
49     if (statResult != 0 || (sb.st_mode & S_IFMT) != S_IFREG)\r
50         return false;\r
51     result = sb.st_size;\r
52     return true;\r
53 }\r
54 \r
55 bool fileExists(const String& path) \r
56 {\r
57     struct _stat32i64 sb;\r
58     String filename = path;\r
59     return !_wstat32i64(filename.charactersWithNullTermination(), &sb);\r
60 }\r
61 \r
62 bool deleteFile(const String& path)\r
63 {\r
64     String filename = path;\r
65     return !!DeleteFileW(filename.charactersWithNullTermination());\r
66 }\r
67 \r
68 String pathByAppendingComponent(const String& path, const String& component)\r
69 {\r
70     Vector<UChar> buffer(MAX_PATH);\r
71 \r
72     if (path.length() + 1 > buffer.size())\r
73         return String();\r
74 \r
75     memcpy(buffer.data(), path.characters(), path.length() * sizeof(UChar));\r
76     buffer[path.length()] = '\0';\r
77 \r
78     String componentCopy = component;\r
79     if (!PathAppendW(buffer.data(), componentCopy.charactersWithNullTermination()))\r
80         return String();\r
81 \r
82     buffer.resize(wcslen(buffer.data()));\r
83 \r
84     return String::adopt(buffer);\r
85 }\r
86 \r
87 CString fileSystemRepresentation(const String&)\r
88 {\r
89     return "";\r
90 }\r
91 \r
92 bool makeAllDirectories(const String& path)\r
93 {\r
94     String fullPath = path;\r
95     if (SHCreateDirectoryEx(0, fullPath.charactersWithNullTermination(), 0) != ERROR_SUCCESS) {\r
96         DWORD error = GetLastError();\r
97         if (error != ERROR_FILE_EXISTS && error != ERROR_ALREADY_EXISTS) {\r
98             LOG_ERROR("Failed to create path %s", path.ascii().data());\r
99             return false;\r
100         }\r
101     }\r
102     return true;\r
103 }\r
104 \r
105 String homeDirectoryPath()\r
106 {\r
107     notImplemented();\r
108     return "";\r
109 }\r
110 \r
111 static String bundleName()\r
112 {\r
113     static bool initialized;\r
114     static String name = "WebKit";\r
115 \r
116     if (!initialized) {\r
117         initialized = true;\r
118 \r
119         if (CFBundleRef bundle = CFBundleGetMainBundle())
120             if (CFTypeRef bundleExecutable = CFBundleGetValueForInfoDictionaryKey(bundle, kCFBundleExecutableKey))
121                 if (CFGetTypeID(bundleExecutable) == CFStringGetTypeID())
122                     name = reinterpret_cast<CFStringRef>(bundleExecutable);\r
123     }\r
124 \r
125     return name;\r
126 }\r
127 \r
128 static String storageDirectory(DWORD pathIdentifier)
129 {
130     Vector<UChar> buffer(MAX_PATH);
131     if (FAILED(SHGetFolderPathW(0, pathIdentifier | CSIDL_FLAG_CREATE, 0, 0, buffer.data())))
132         return String();
133     buffer.resize(wcslen(buffer.data()));
134     String directory = String::adopt(buffer);
135
136     static const String companyNameDirectory = "Apple Computer\\";
137     directory = pathByAppendingComponent(directory, companyNameDirectory + bundleName());
138     if (!makeAllDirectories(directory))
139         return String();
140
141     return directory;
142 }\r
143 \r
144 static String cachedStorageDirectory(DWORD pathIdentifier)\r
145 {\r
146     static HashMap<DWORD, String> directories;\r
147 \r
148     HashMap<DWORD, String>::iterator it = directories.find(pathIdentifier);\r
149     if (it != directories.end())\r
150         return it->second;\r
151 \r
152     String directory = storageDirectory(pathIdentifier);\r
153     directories.add(pathIdentifier, directory);\r
154 \r
155     return directory;\r
156 }\r
157 \r
158
159 CString openTemporaryFile(const char* prefix, PlatformFileHandle& handle)
160 {
161     char tempPath[MAX_PATH];
162     int tempPathLength = ::GetTempPathA(_countof(tempPath), tempPath);
163     if (tempPathLength <= 0 || tempPathLength > _countof(tempPath))
164         return 0;
165
166     char tempFile[MAX_PATH];
167     if (::GetTempFileNameA(tempPath, prefix, 0, tempFile) > 0) {
168         HANDLE tempHandle = ::CreateFileA(tempFile, GENERIC_READ | GENERIC_WRITE, 0, 0, 
169             CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
170
171         if (isHandleValid(tempHandle)) {
172             handle = tempHandle;
173             return tempFile;
174         }
175     }
176     return 0;
177 }
178
179 void closeFile(PlatformFileHandle& handle)
180 {
181     if (isHandleValid(handle)) {
182         ::CloseHandle(handle);
183         handle = invalidPlatformFileHandle;
184     }
185 }
186
187 int writeToFile(PlatformFileHandle handle, const char* data, int length)
188 {
189     if (!isHandleValid(handle))
190         return -1;
191
192     DWORD bytesWritten;
193     bool success = WriteFile(handle, data, length, &bytesWritten, 0);
194
195     if (!success)
196         return -1;
197     return static_cast<int>(bytesWritten);
198 }
199 String localUserSpecificStorageDirectory()
200 {
201     return cachedStorageDirectory(CSIDL_LOCAL_APPDATA);
202 }
203
204 String roamingUserSpecificStorageDirectory()
205 {
206     return cachedStorageDirectory(CSIDL_APPDATA);
207 }
208
209 bool safeCreateFile(const String& path, CFDataRef data)
210 {
211     // Create a temporary file.
212     WCHAR tempDirPath[MAX_PATH];
213     if (!GetTempPathW(ARRAYSIZE(tempDirPath), tempDirPath))
214         return false;
215
216     WCHAR tempPath[MAX_PATH];
217     if (!GetTempFileNameW(tempDirPath, L"WEBKIT", 0, tempPath))
218         return false;
219
220     HANDLE tempFileHandle = CreateFileW(tempPath, GENERIC_READ | GENERIC_WRITE, 0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
221     if (tempFileHandle == INVALID_HANDLE_VALUE)
222         return false;
223
224     // Write the data to this temp file.
225     DWORD written;
226     if (!WriteFile(tempFileHandle, CFDataGetBytePtr(data), static_cast<DWORD>(CFDataGetLength(data)), &written, 0))
227         return false;
228
229     CloseHandle(tempFileHandle);
230
231     // Copy the temp file to the destination file.
232     String destination = path;
233     if (!MoveFileExW(tempPath, destination.charactersWithNullTermination(), MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED))
234         return false;
235
236     return true;
237 }
238 \r
239 } // namespace WebCore\r