Home | History | Annotate | Download | only in base
      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 
     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 
    107 bool ClosePlatformFile(PlatformFile file) {
    108   base::ThreadRestrictions::AssertIOAllowed();
    109   return (CloseHandle(file) != 0);
    110 }
    111 
    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 
    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 
    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 
    179 bool FlushPlatformFile(PlatformFile file) {
    180   base::ThreadRestrictions::AssertIOAllowed();
    181   return ((file != kInvalidPlatformFileValue) && ::FlushFileBuffers(file));
    182 }
    183 
    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 
    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