Home | History | Annotate | Download | only in wince
      1 /*
      2  * Copyright (C) 2007 Apple Inc. All rights reserved.
      3  * Copyright (C) 2008 Collabora, Ltd. All rights reserved.
      4  * Copyright (C) 2007-2009 Torch Mobile, Inc.
      5  *
      6  * Redistribution and use in source and binary forms, with or without
      7  * modification, are permitted provided that the following conditions
      8  * are met:
      9  *
     10  * 1.  Redistributions of source code must retain the above copyright
     11  *     notice, this list of conditions and the following disclaimer.
     12  * 2.  Redistributions in binary form must reproduce the above copyright
     13  *     notice, this list of conditions and the following disclaimer in the
     14  *     documentation and/or other materials provided with the distribution.
     15  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
     16  *     its contributors may be used to endorse or promote products derived
     17  *     from this software without specific prior written permission.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
     20  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     21  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     22  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
     23  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     24  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     25  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
     26  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     28  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29  */
     30 
     31 #include "config.h"
     32 #include "FileSystem.h"
     33 
     34 #include "CString.h"
     35 #include "PlatformString.h"
     36 
     37 #include <windows.h>
     38 #include <wincrypt.h>
     39 
     40 namespace WebCore {
     41 
     42 static bool getFileInfo(const String& path, BY_HANDLE_FILE_INFORMATION& fileInfo)
     43 {
     44     String filename = path;
     45     HANDLE hFile = CreateFile(filename.charactersWithNullTermination(), GENERIC_READ, FILE_SHARE_READ, 0
     46         , OPEN_EXISTING, FILE_FLAG_NO_BUFFERING, 0);
     47 
     48     if (hFile == INVALID_HANDLE_VALUE)
     49         return false;
     50 
     51     bool rtn = GetFileInformationByHandle(hFile, &fileInfo) ? true : false;
     52 
     53     CloseHandle(hFile);
     54     return rtn;
     55 }
     56 
     57 bool getFileSize(const String& path, long long& result)
     58 {
     59     BY_HANDLE_FILE_INFORMATION fileInformation;
     60     if (!getFileInfo(path, fileInformation))
     61         return false;
     62 
     63     ULARGE_INTEGER fileSize;
     64     fileSize.LowPart = fileInformation.nFileSizeLow;
     65     fileSize.HighPart = fileInformation.nFileSizeHigh;
     66 
     67     result = fileSize.QuadPart;
     68 
     69     return true;
     70 }
     71 
     72 bool getFileModificationTime(const String& path, time_t& result)
     73 {
     74     BY_HANDLE_FILE_INFORMATION fileInformation;
     75     if (!getFileInfo(path, fileInformation))
     76         return false;
     77 
     78     ULARGE_INTEGER t;
     79     memcpy(&t, &fileInformation.ftLastWriteTime, sizeof(t));
     80 
     81     result = t.QuadPart * 0.0000001 - 11644473600.0;
     82 
     83     return true;
     84 }
     85 
     86 bool fileExists(const String& path)
     87 {
     88     String filename = path;
     89     HANDLE hFile = CreateFile(filename.charactersWithNullTermination(), 0, FILE_SHARE_READ | FILE_SHARE_WRITE
     90         , 0, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING, 0);
     91 
     92     CloseHandle(hFile);
     93 
     94     return hFile != INVALID_HANDLE_VALUE;
     95 }
     96 
     97 bool deleteFile(const String& path)
     98 {
     99     String filename = path;
    100     return !!DeleteFileW(filename.charactersWithNullTermination());
    101 }
    102 
    103 
    104 bool deleteEmptyDirectory(const String& path)
    105 {
    106     String filename = path;
    107     return !!RemoveDirectoryW(filename.charactersWithNullTermination());
    108 }
    109 
    110 String pathByAppendingComponent(const String& path, const String& component)
    111 {
    112     if (component.isEmpty())
    113         return path;
    114 
    115     Vector<UChar, MAX_PATH> buffer;
    116 
    117     buffer.append(path.characters(), path.length());
    118 
    119     if (buffer.last() != L'\\' && buffer.last() != L'/'
    120         && component[0] != L'\\' && component[0] != L'/')
    121         buffer.append(L'\\');
    122 
    123     buffer.append(component.characters(), component.length());
    124 
    125     return String(buffer.data(), buffer.size());
    126 }
    127 
    128 CString fileSystemRepresentation(const String&)
    129 {
    130     return "";
    131 }
    132 
    133 bool makeAllDirectories(const String& path)
    134 {
    135     int lastDivPos = max(path.reverseFind('/'), path.reverseFind('\\'));
    136     int endPos = path.length();
    137     if (lastDivPos == path.length() - 1) {
    138         endPos -= 1;
    139         lastDivPos = max(path.reverseFind('/', lastDivPos), path.reverseFind('\\', lastDivPos));
    140     }
    141 
    142     if (lastDivPos > 0) {
    143         if (!makeAllDirectories(path.substring(0, lastDivPos)))
    144             return false;
    145     }
    146 
    147     String folder(path.substring(0, endPos));
    148     CreateDirectory(folder.charactersWithNullTermination(), 0);
    149 
    150     DWORD fileAttr = GetFileAttributes(folder.charactersWithNullTermination());
    151     return fileAttr != 0xFFFFFFFF && (fileAttr & FILE_ATTRIBUTE_DIRECTORY);
    152 }
    153 
    154 String homeDirectoryPath()
    155 {
    156     notImplemented();
    157     return "";
    158 }
    159 
    160 String pathGetFileName(const String& path)
    161 {
    162     return path.substring(max(path.reverseFind('/'), path.reverseFind('\\')) + 1);
    163 }
    164 
    165 String directoryName(const String& path)
    166 {
    167     notImplemented();
    168     return String();
    169 }
    170 
    171 CString openTemporaryFile(const char*, PlatformFileHandle& handle)
    172 {
    173     handle = INVALID_HANDLE_VALUE;
    174 
    175     wchar_t tempPath[MAX_PATH];
    176     int tempPathLength = ::GetTempPath(_countof(tempPath), tempPath);
    177     if (tempPathLength <= 0 || tempPathLength > _countof(tempPath))
    178         return CString();
    179 
    180     HCRYPTPROV hCryptProv = 0;
    181     if (!CryptAcquireContext(&hCryptProv, 0, 0, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
    182         return CString();
    183 
    184     String proposedPath;
    185     while (1) {
    186 
    187         wchar_t tempFile[] = L"XXXXXXXX.tmp"; // Use 8.3 style name (more characters aren't helpful due to 8.3 short file names)
    188         const int randomPartLength = 8;
    189         if (!CryptGenRandom(hCryptProv, randomPartLength * 2, reinterpret_cast<BYTE*>(tempFile)))
    190             break;
    191 
    192         // Limit to valid filesystem characters, also excluding others that could be problematic, like punctuation.
    193         // don't include both upper and lowercase since Windows file systems are typically not case sensitive.
    194         const char validChars[] = "0123456789abcdefghijklmnopqrstuvwxyz";
    195         for (int i = 0; i < randomPartLength; ++i)
    196             tempFile[i] = validChars[tempFile[i] % (sizeof(validChars) - 1)];
    197 
    198         ASSERT(wcslen(tempFile) * 2 == sizeof(tempFile) - 2);
    199 
    200         proposedPath = pathByAppendingComponent(String(tempPath), String(tempFile));
    201 
    202         // use CREATE_NEW to avoid overwriting an existing file with the same name
    203         handle = CreateFile(proposedPath.charactersWithNullTermination(), GENERIC_READ | GENERIC_WRITE, 0, 0, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0);
    204         if (!isHandleValid(handle) && GetLastError() == ERROR_ALREADY_EXISTS)
    205             continue;
    206 
    207         break;
    208     }
    209 
    210     CryptReleaseContext(hCryptProv, 0);
    211 
    212     if (!isHandleValid(handle))
    213         return CString();
    214 
    215     return proposedPath.latin1();
    216 }
    217 
    218 void closeFile(PlatformFileHandle& handle)
    219 {
    220     if (isHandleValid(handle)) {
    221         ::CloseHandle(handle);
    222         handle = invalidPlatformFileHandle;
    223     }
    224 }
    225 
    226 int writeToFile(PlatformFileHandle handle, const char* data, int length)
    227 {
    228     if (!isHandleValid(handle))
    229         return -1;
    230 
    231     DWORD bytesWritten;
    232     bool success = WriteFile(handle, data, length, &bytesWritten, 0);
    233 
    234     if (!success)
    235         return -1;
    236     return static_cast<int>(bytesWritten);
    237 }
    238 
    239 bool unloadModule(PlatformModule module)
    240 {
    241     return ::FreeLibrary(module);
    242 }
    243 
    244 String localUserSpecificStorageDirectory()
    245 {
    246     return String(L"\\");
    247 }
    248 
    249 String roamingUserSpecificStorageDirectory()
    250 {
    251     return String(L"\\");
    252 }
    253 
    254 Vector<String> listDirectory(const String& path, const String& filter)
    255 {
    256     Vector<String> entries;
    257 
    258     Vector<UChar, 256> pattern;
    259     pattern.append(path.characters(), path.length());
    260     if (pattern.last() != L'/' && pattern.last() != L'\\')
    261         pattern.append(L'\\');
    262 
    263     String root(pattern.data(), pattern.size());
    264     pattern.append(filter.characters(), filter.length());
    265     pattern.append(0);
    266 
    267     WIN32_FIND_DATA findData;
    268     HANDLE hFind = FindFirstFile(pattern.data(), &findData);
    269     if (INVALID_HANDLE_VALUE != hFind) {
    270         do {
    271             // FIXEME: should we also add the folders? This function
    272             // is so far only called by PluginDatabase.cpp to list
    273             // all plugins in a folder, where it's not supposed to list sub-folders.
    274             if (!(findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
    275                 entries.append(root + findData.cFileName);
    276         } while (FindNextFile(hFind, &findData));
    277         FindClose(hFind);
    278     }
    279 
    280     return entries;
    281 }
    282 
    283 }
    284