Home | History | Annotate | Download | only in ports
      1 /*
      2  * Copyright 2013 Google Inc.
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 
      8 #include "SkOSFile.h"
      9 
     10 #include "SkTFitsIn.h"
     11 
     12 #include <io.h>
     13 #include <stdio.h>
     14 #include <sys/stat.h>
     15 
     16 bool sk_exists(const char *path, SkFILE_Flags flags) {
     17     int mode = 0; // existence
     18     if (flags & kRead_SkFILE_Flag) {
     19         mode |= 4; // read
     20     }
     21     if (flags & kWrite_SkFILE_Flag) {
     22         mode |= 2; // write
     23     }
     24     return (0 == _access(path, mode));
     25 }
     26 
     27 typedef struct {
     28     ULONGLONG fVolume;
     29     ULONGLONG fLsbSize;
     30     ULONGLONG fMsbSize;
     31 } SkFILEID;
     32 
     33 static bool sk_ino(SkFILE* f, SkFILEID* id) {
     34     int fileno = _fileno((FILE*)f);
     35     if (fileno < 0) {
     36         return false;
     37     }
     38 
     39     HANDLE file = (HANDLE)_get_osfhandle(fileno);
     40     if (INVALID_HANDLE_VALUE == file) {
     41         return false;
     42     }
     43 
     44     //TODO: call GetFileInformationByHandleEx on Vista and later with FileIdInfo.
     45     BY_HANDLE_FILE_INFORMATION info;
     46     if (0 == GetFileInformationByHandle(file, &info)) {
     47         return false;
     48     }
     49     id->fVolume = info.dwVolumeSerialNumber;
     50     id->fLsbSize = info.nFileIndexLow + (((ULONGLONG)info.nFileIndexHigh) << 32);
     51     id->fMsbSize = 0;
     52 
     53     return true;
     54 }
     55 
     56 bool sk_fidentical(SkFILE* a, SkFILE* b) {
     57     SkFILEID aID, bID;
     58     return sk_ino(a, &aID) && sk_ino(b, &bID)
     59            && aID.fLsbSize == bID.fLsbSize
     60            && aID.fMsbSize == bID.fMsbSize
     61            && aID.fVolume == bID.fVolume;
     62 }
     63 
     64 class SkAutoNullKernelHandle : SkNoncopyable {
     65 public:
     66     SkAutoNullKernelHandle(const HANDLE handle) : fHandle(handle) { }
     67     ~SkAutoNullKernelHandle() { CloseHandle(fHandle); }
     68     operator HANDLE() const { return fHandle; }
     69     bool isValid() const { return SkToBool(fHandle); }
     70 private:
     71     HANDLE fHandle;
     72 };
     73 typedef SkAutoNullKernelHandle SkAutoWinMMap;
     74 
     75 void sk_fmunmap(const void* addr, size_t) {
     76     UnmapViewOfFile(addr);
     77 }
     78 
     79 void* sk_fdmmap(int fileno, size_t* length) {
     80     HANDLE file = (HANDLE)_get_osfhandle(fileno);
     81     if (INVALID_HANDLE_VALUE == file) {
     82         return NULL;
     83     }
     84 
     85     LARGE_INTEGER fileSize;
     86     if (0 == GetFileSizeEx(file, &fileSize)) {
     87         //TODO: use SK_TRACEHR(GetLastError(), "Could not get file size.") to report.
     88         return NULL;
     89     }
     90     if (!SkTFitsIn<size_t>(fileSize.QuadPart)) {
     91         return NULL;
     92     }
     93 
     94     SkAutoWinMMap mmap(CreateFileMapping(file, NULL, PAGE_READONLY, 0, 0, NULL));
     95     if (!mmap.isValid()) {
     96         //TODO: use SK_TRACEHR(GetLastError(), "Could not create file mapping.") to report.
     97         return NULL;
     98     }
     99 
    100     // Eventually call UnmapViewOfFile
    101     void* addr = MapViewOfFile(mmap, FILE_MAP_READ, 0, 0, 0);
    102     if (NULL == addr) {
    103         //TODO: use SK_TRACEHR(GetLastError(), "Could not map view of file.") to report.
    104         return NULL;
    105     }
    106 
    107     *length = static_cast<size_t>(fileSize.QuadPart);
    108     return addr;
    109 }
    110 
    111 int sk_fileno(SkFILE* f) {
    112     return _fileno((FILE*)f);
    113 }
    114 
    115 void* sk_fmmap(SkFILE* f, size_t* length) {
    116     int fileno = sk_fileno(f);
    117     if (fileno < 0) {
    118         return NULL;
    119     }
    120 
    121     return sk_fdmmap(fileno, length);
    122 }
    123