Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / base / platform_file_win.cc
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "base/platform_file.h"
6
7 #include <io.h>
8
9 #include "base/files/file_path.h"
10 #include "base/logging.h"
11 #include "base/metrics/sparse_histogram.h"
12 #include "base/threading/thread_restrictions.h"
13
14 namespace base {
15
16 FILE* FdopenPlatformFile(PlatformFile file, const char* mode) {
17   if (file == kInvalidPlatformFileValue)
18     return NULL;
19   int fd = _open_osfhandle(reinterpret_cast<intptr_t>(file), 0);
20   if (fd < 0)
21     return NULL;
22   return _fdopen(fd, mode);
23 }
24
25 bool ClosePlatformFile(PlatformFile file) {
26   base::ThreadRestrictions::AssertIOAllowed();
27   return (CloseHandle(file) != 0);
28 }
29
30 int64 SeekPlatformFile(PlatformFile file,
31                        PlatformFileWhence whence,
32                        int64 offset) {
33   base::ThreadRestrictions::AssertIOAllowed();
34   if (file == kInvalidPlatformFileValue || offset < 0)
35     return -1;
36
37   LARGE_INTEGER distance, res;
38   distance.QuadPart = offset;
39   DWORD move_method = static_cast<DWORD>(whence);
40   if (!SetFilePointerEx(file, distance, &res, move_method))
41     return -1;
42   return res.QuadPart;
43 }
44
45 int ReadPlatformFile(PlatformFile file, int64 offset, char* data, int size) {
46   base::ThreadRestrictions::AssertIOAllowed();
47   if (file == kInvalidPlatformFileValue || size < 0)
48     return -1;
49
50   LARGE_INTEGER offset_li;
51   offset_li.QuadPart = offset;
52
53   OVERLAPPED overlapped = {0};
54   overlapped.Offset = offset_li.LowPart;
55   overlapped.OffsetHigh = offset_li.HighPart;
56
57   DWORD bytes_read;
58   if (::ReadFile(file, data, size, &bytes_read, &overlapped) != 0)
59     return bytes_read;
60   if (ERROR_HANDLE_EOF == GetLastError())
61     return 0;
62
63   return -1;
64 }
65
66 int ReadPlatformFileAtCurrentPos(PlatformFile file, char* data, int size) {
67   base::ThreadRestrictions::AssertIOAllowed();
68   if (file == kInvalidPlatformFileValue || size < 0)
69     return -1;
70
71   DWORD bytes_read;
72   if (::ReadFile(file, data, size, &bytes_read, NULL) != 0)
73     return bytes_read;
74   if (ERROR_HANDLE_EOF == GetLastError())
75     return 0;
76
77   return -1;
78 }
79
80 int ReadPlatformFileNoBestEffort(PlatformFile file, int64 offset, char* data,
81                                  int size) {
82   return ReadPlatformFile(file, offset, data, size);
83 }
84
85 int ReadPlatformFileCurPosNoBestEffort(PlatformFile file,
86                                        char* data, int size) {
87   return ReadPlatformFileAtCurrentPos(file, data, size);
88 }
89
90 int WritePlatformFile(PlatformFile file, int64 offset,
91                       const char* data, int size) {
92   base::ThreadRestrictions::AssertIOAllowed();
93   if (file == kInvalidPlatformFileValue)
94     return -1;
95
96   LARGE_INTEGER offset_li;
97   offset_li.QuadPart = offset;
98
99   OVERLAPPED overlapped = {0};
100   overlapped.Offset = offset_li.LowPart;
101   overlapped.OffsetHigh = offset_li.HighPart;
102
103   DWORD bytes_written;
104   if (::WriteFile(file, data, size, &bytes_written, &overlapped) != 0)
105     return bytes_written;
106
107   return -1;
108 }
109
110 int WritePlatformFileAtCurrentPos(PlatformFile file, const char* data,
111                                   int size) {
112   return WritePlatformFile(file, 0, data, size);
113 }
114
115 int WritePlatformFileCurPosNoBestEffort(PlatformFile file,
116                                         const char* data, int size) {
117   return WritePlatformFile(file, 0, data, size);
118 }
119
120 bool TruncatePlatformFile(PlatformFile file, int64 length) {
121   base::ThreadRestrictions::AssertIOAllowed();
122   if (file == kInvalidPlatformFileValue)
123     return false;
124
125   // Get the current file pointer.
126   LARGE_INTEGER file_pointer;
127   LARGE_INTEGER zero;
128   zero.QuadPart = 0;
129   if (::SetFilePointerEx(file, zero, &file_pointer, FILE_CURRENT) == 0)
130     return false;
131
132   LARGE_INTEGER length_li;
133   length_li.QuadPart = length;
134   // If length > file size, SetFilePointerEx() should extend the file
135   // with zeroes on all Windows standard file systems (NTFS, FATxx).
136   if (!::SetFilePointerEx(file, length_li, NULL, FILE_BEGIN))
137     return false;
138
139   // Set the new file length and move the file pointer to its old position.
140   // This is consistent with ftruncate()'s behavior, even when the file
141   // pointer points to a location beyond the end of the file.
142   return ((::SetEndOfFile(file) != 0) &&
143           (::SetFilePointerEx(file, file_pointer, NULL, FILE_BEGIN) != 0));
144 }
145
146 bool FlushPlatformFile(PlatformFile file) {
147   base::ThreadRestrictions::AssertIOAllowed();
148   return ((file != kInvalidPlatformFileValue) && ::FlushFileBuffers(file));
149 }
150
151 bool TouchPlatformFile(PlatformFile file, const base::Time& last_access_time,
152                        const base::Time& last_modified_time) {
153   base::ThreadRestrictions::AssertIOAllowed();
154   if (file == kInvalidPlatformFileValue)
155     return false;
156
157   FILETIME last_access_filetime = last_access_time.ToFileTime();
158   FILETIME last_modified_filetime = last_modified_time.ToFileTime();
159   return (::SetFileTime(file, NULL, &last_access_filetime,
160                         &last_modified_filetime) != 0);
161 }
162
163 bool GetPlatformFileInfo(PlatformFile file, PlatformFileInfo* info) {
164   base::ThreadRestrictions::AssertIOAllowed();
165   if (!info)
166     return false;
167
168   BY_HANDLE_FILE_INFORMATION file_info;
169   if (GetFileInformationByHandle(file, &file_info) == 0)
170     return false;
171
172   LARGE_INTEGER size;
173   size.HighPart = file_info.nFileSizeHigh;
174   size.LowPart = file_info.nFileSizeLow;
175   info->size = size.QuadPart;
176   info->is_directory =
177       (file_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
178   info->is_symbolic_link = false; // Windows doesn't have symbolic links.
179   info->last_modified = base::Time::FromFileTime(file_info.ftLastWriteTime);
180   info->last_accessed = base::Time::FromFileTime(file_info.ftLastAccessTime);
181   info->creation_time = base::Time::FromFileTime(file_info.ftCreationTime);
182   return true;
183 }
184
185 PlatformFileError LockPlatformFile(PlatformFile file) {
186   BOOL result = LockFile(file, 0, 0, MAXDWORD, MAXDWORD);
187   if (!result)
188     return LastErrorToPlatformFileError(GetLastError());
189   return PLATFORM_FILE_OK;
190 }
191
192 PlatformFileError UnlockPlatformFile(PlatformFile file) {
193   BOOL result = UnlockFile(file, 0, 0, MAXDWORD, MAXDWORD);
194   if (!result)
195     return LastErrorToPlatformFileError(GetLastError());
196   return PLATFORM_FILE_OK;
197 }
198
199 PlatformFileError LastErrorToPlatformFileError(DWORD last_error) {
200   switch (last_error) {
201     case ERROR_SHARING_VIOLATION:
202       return PLATFORM_FILE_ERROR_IN_USE;
203     case ERROR_FILE_EXISTS:
204       return PLATFORM_FILE_ERROR_EXISTS;
205     case ERROR_FILE_NOT_FOUND:
206     case ERROR_PATH_NOT_FOUND:
207       return PLATFORM_FILE_ERROR_NOT_FOUND;
208     case ERROR_ACCESS_DENIED:
209       return PLATFORM_FILE_ERROR_ACCESS_DENIED;
210     case ERROR_TOO_MANY_OPEN_FILES:
211       return PLATFORM_FILE_ERROR_TOO_MANY_OPENED;
212     case ERROR_OUTOFMEMORY:
213     case ERROR_NOT_ENOUGH_MEMORY:
214       return PLATFORM_FILE_ERROR_NO_MEMORY;
215     case ERROR_HANDLE_DISK_FULL:
216     case ERROR_DISK_FULL:
217     case ERROR_DISK_RESOURCES_EXHAUSTED:
218       return PLATFORM_FILE_ERROR_NO_SPACE;
219     case ERROR_USER_MAPPED_FILE:
220       return PLATFORM_FILE_ERROR_INVALID_OPERATION;
221     case ERROR_NOT_READY:
222     case ERROR_SECTOR_NOT_FOUND:
223     case ERROR_DEV_NOT_EXIST:
224     case ERROR_IO_DEVICE:
225     case ERROR_FILE_CORRUPT:
226     case ERROR_DISK_CORRUPT:
227       return PLATFORM_FILE_ERROR_IO;
228     default:
229       UMA_HISTOGRAM_SPARSE_SLOWLY("PlatformFile.UnknownErrors.Windows",
230                                   last_error);
231       return PLATFORM_FILE_ERROR_FAILED;
232   }
233 }
234
235 }  // namespace base