• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2006-2008 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 "base/file_path.h"
8 #include "base/logging.h"
9 #include "base/threading/thread_restrictions.h"
10 
11 namespace base {
12 
CreatePlatformFile(const FilePath & name,int flags,bool * created,PlatformFileError * error_code)13 PlatformFile CreatePlatformFile(const FilePath& name,
14                                 int flags,
15                                 bool* created,
16                                 PlatformFileError* error_code) {
17   base::ThreadRestrictions::AssertIOAllowed();
18 
19   DWORD disposition = 0;
20 
21   if (flags & PLATFORM_FILE_OPEN)
22     disposition = OPEN_EXISTING;
23 
24   if (flags & PLATFORM_FILE_CREATE) {
25     DCHECK(!disposition);
26     disposition = CREATE_NEW;
27   }
28 
29   if (flags & PLATFORM_FILE_OPEN_ALWAYS) {
30     DCHECK(!disposition);
31     disposition = OPEN_ALWAYS;
32   }
33 
34   if (flags & PLATFORM_FILE_CREATE_ALWAYS) {
35     DCHECK(!disposition);
36     disposition = CREATE_ALWAYS;
37   }
38 
39   if (flags & PLATFORM_FILE_TRUNCATE) {
40     DCHECK(!disposition);
41     DCHECK(flags & PLATFORM_FILE_WRITE);
42     disposition = TRUNCATE_EXISTING;
43   }
44 
45   if (!disposition) {
46     NOTREACHED();
47     return NULL;
48   }
49 
50   DWORD access = (flags & PLATFORM_FILE_READ) ? GENERIC_READ : 0;
51   if (flags & PLATFORM_FILE_WRITE)
52     access |= GENERIC_WRITE;
53   if (flags & PLATFORM_FILE_WRITE_ATTRIBUTES)
54     access |= FILE_WRITE_ATTRIBUTES;
55 
56   DWORD sharing = (flags & PLATFORM_FILE_EXCLUSIVE_READ) ? 0 : FILE_SHARE_READ;
57   if (!(flags & PLATFORM_FILE_EXCLUSIVE_WRITE))
58     sharing |= FILE_SHARE_WRITE;
59 
60   DWORD create_flags = 0;
61   if (flags & PLATFORM_FILE_ASYNC)
62     create_flags |= FILE_FLAG_OVERLAPPED;
63   if (flags & PLATFORM_FILE_TEMPORARY)
64     create_flags |= FILE_ATTRIBUTE_TEMPORARY;
65   if (flags & PLATFORM_FILE_HIDDEN)
66     create_flags |= FILE_ATTRIBUTE_HIDDEN;
67   if (flags & PLATFORM_FILE_DELETE_ON_CLOSE)
68     create_flags |= FILE_FLAG_DELETE_ON_CLOSE;
69 
70   HANDLE file = CreateFile(name.value().c_str(), access, sharing, NULL,
71                            disposition, create_flags, NULL);
72 
73   if (created && (INVALID_HANDLE_VALUE != file)) {
74     if (flags & (PLATFORM_FILE_OPEN_ALWAYS))
75       *created = (ERROR_ALREADY_EXISTS != GetLastError());
76     else if (flags & (PLATFORM_FILE_CREATE_ALWAYS | PLATFORM_FILE_CREATE))
77       *created = true;
78   }
79 
80   if (error_code) {
81     if (file != kInvalidPlatformFileValue)
82       *error_code = PLATFORM_FILE_OK;
83     else {
84       DWORD last_error = GetLastError();
85       switch (last_error) {
86         case ERROR_SHARING_VIOLATION:
87           *error_code = PLATFORM_FILE_ERROR_IN_USE;
88           break;
89         case ERROR_FILE_EXISTS:
90           *error_code = PLATFORM_FILE_ERROR_EXISTS;
91           break;
92         case ERROR_FILE_NOT_FOUND:
93           *error_code = PLATFORM_FILE_ERROR_NOT_FOUND;
94           break;
95         case ERROR_ACCESS_DENIED:
96           *error_code = PLATFORM_FILE_ERROR_ACCESS_DENIED;
97           break;
98         default:
99           *error_code = PLATFORM_FILE_ERROR_FAILED;
100       }
101     }
102   }
103 
104   return file;
105 }
106 
ClosePlatformFile(PlatformFile file)107 bool ClosePlatformFile(PlatformFile file) {
108   base::ThreadRestrictions::AssertIOAllowed();
109   return (CloseHandle(file) != 0);
110 }
111 
ReadPlatformFile(PlatformFile file,int64 offset,char * data,int size)112 int ReadPlatformFile(PlatformFile file, int64 offset, char* data, int size) {
113   base::ThreadRestrictions::AssertIOAllowed();
114   if (file == kInvalidPlatformFileValue)
115     return -1;
116 
117   LARGE_INTEGER offset_li;
118   offset_li.QuadPart = offset;
119 
120   OVERLAPPED overlapped = {0};
121   overlapped.Offset = offset_li.LowPart;
122   overlapped.OffsetHigh = offset_li.HighPart;
123 
124   DWORD bytes_read;
125   if (::ReadFile(file, data, size, &bytes_read, &overlapped) != 0)
126     return bytes_read;
127   else if (ERROR_HANDLE_EOF == GetLastError())
128     return 0;
129 
130   return -1;
131 }
132 
WritePlatformFile(PlatformFile file,int64 offset,const char * data,int size)133 int WritePlatformFile(PlatformFile file, int64 offset,
134                       const char* data, int size) {
135   base::ThreadRestrictions::AssertIOAllowed();
136   if (file == kInvalidPlatformFileValue)
137     return -1;
138 
139   LARGE_INTEGER offset_li;
140   offset_li.QuadPart = offset;
141 
142   OVERLAPPED overlapped = {0};
143   overlapped.Offset = offset_li.LowPart;
144   overlapped.OffsetHigh = offset_li.HighPart;
145 
146   DWORD bytes_written;
147   if (::WriteFile(file, data, size, &bytes_written, &overlapped) != 0)
148     return bytes_written;
149 
150   return -1;
151 }
152 
TruncatePlatformFile(PlatformFile file,int64 length)153 bool TruncatePlatformFile(PlatformFile file, int64 length) {
154   base::ThreadRestrictions::AssertIOAllowed();
155   if (file == kInvalidPlatformFileValue)
156     return false;
157 
158   // Get the current file pointer.
159   LARGE_INTEGER file_pointer;
160   LARGE_INTEGER zero;
161   zero.QuadPart = 0;
162   if (::SetFilePointerEx(file, zero, &file_pointer, FILE_CURRENT) == 0)
163     return false;
164 
165   LARGE_INTEGER length_li;
166   length_li.QuadPart = length;
167   // If length > file size, SetFilePointerEx() should extend the file
168   // with zeroes on all Windows standard file systems (NTFS, FATxx).
169   if (!::SetFilePointerEx(file, length_li, NULL, FILE_BEGIN))
170     return false;
171 
172   // Set the new file length and move the file pointer to its old position.
173   // This is consistent with ftruncate()'s behavior, even when the file
174   // pointer points to a location beyond the end of the file.
175   return ((::SetEndOfFile(file) != 0) &&
176           (::SetFilePointerEx(file, file_pointer, NULL, FILE_BEGIN) != 0));
177 }
178 
FlushPlatformFile(PlatformFile file)179 bool FlushPlatformFile(PlatformFile file) {
180   base::ThreadRestrictions::AssertIOAllowed();
181   return ((file != kInvalidPlatformFileValue) && ::FlushFileBuffers(file));
182 }
183 
TouchPlatformFile(PlatformFile file,const base::Time & last_access_time,const base::Time & last_modified_time)184 bool TouchPlatformFile(PlatformFile file, const base::Time& last_access_time,
185                        const base::Time& last_modified_time) {
186   base::ThreadRestrictions::AssertIOAllowed();
187   if (file == kInvalidPlatformFileValue)
188     return false;
189 
190   FILETIME last_access_filetime = last_access_time.ToFileTime();
191   FILETIME last_modified_filetime = last_modified_time.ToFileTime();
192   return (::SetFileTime(file, NULL, &last_access_filetime,
193                         &last_modified_filetime) != 0);
194 }
195 
GetPlatformFileInfo(PlatformFile file,PlatformFileInfo * info)196 bool GetPlatformFileInfo(PlatformFile file, PlatformFileInfo* info) {
197   base::ThreadRestrictions::AssertIOAllowed();
198   if (!info)
199     return false;
200 
201   BY_HANDLE_FILE_INFORMATION file_info;
202   if (GetFileInformationByHandle(file, &file_info) == 0)
203     return false;
204 
205   LARGE_INTEGER size;
206   size.HighPart = file_info.nFileSizeHigh;
207   size.LowPart = file_info.nFileSizeLow;
208   info->size = size.QuadPart;
209   info->is_directory =
210       file_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY != 0;
211   info->is_symbolic_link = false; // Windows doesn't have symbolic links.
212   info->last_modified = base::Time::FromFileTime(file_info.ftLastWriteTime);
213   info->last_accessed = base::Time::FromFileTime(file_info.ftLastAccessTime);
214   info->creation_time = base::Time::FromFileTime(file_info.ftCreationTime);
215   return true;
216 }
217 
218 }  // namespace disk_cache
219