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 typedef struct {
     17     ULONGLONG fVolume;
     18     ULONGLONG fLsbSize;
     19     ULONGLONG fMsbSize;
     20 } SkFILEID;
     21 
     22 static bool sk_ino(SkFILE* f, SkFILEID* id) {
     23     int fileno = _fileno((FILE*)f);
     24     if (fileno < 0) {
     25         return false;
     26     }
     27 
     28     HANDLE file = (HANDLE)_get_osfhandle(fileno);
     29     if (INVALID_HANDLE_VALUE == file) {
     30         return false;
     31     }
     32 
     33     //TODO: call GetFileInformationByHandleEx on Vista and later with FileIdInfo.
     34     BY_HANDLE_FILE_INFORMATION info;
     35     if (0 == GetFileInformationByHandle(file, &info)) {
     36         return false;
     37     }
     38     id->fVolume = info.dwVolumeSerialNumber;
     39     id->fLsbSize = info.nFileIndexLow + (((ULONGLONG)info.nFileIndexHigh) << 32);
     40     id->fMsbSize = 0;
     41 
     42     return true;
     43 }
     44 
     45 bool sk_fidentical(SkFILE* a, SkFILE* b) {
     46     SkFILEID aID, bID;
     47     return sk_ino(a, &aID) && sk_ino(b, &bID)
     48            && aID.fLsbSize == bID.fLsbSize
     49            && aID.fMsbSize == bID.fMsbSize
     50            && aID.fVolume == bID.fVolume;
     51 }
     52 
     53 class SkAutoNullKernelHandle : SkNoncopyable {
     54 public:
     55     SkAutoNullKernelHandle(const HANDLE handle) : fHandle(handle) { }
     56     ~SkAutoNullKernelHandle() { CloseHandle(fHandle); }
     57     operator HANDLE() const { return fHandle; }
     58     bool isValid() const { return NULL != fHandle; }
     59 private:
     60     HANDLE fHandle;
     61 };
     62 typedef SkAutoNullKernelHandle SkAutoWinMMap;
     63 
     64 void sk_fmunmap(const void* addr, size_t) {
     65     UnmapViewOfFile(addr);
     66 }
     67 
     68 void* sk_fdmmap(int fileno, size_t* length) {
     69     HANDLE file = (HANDLE)_get_osfhandle(fileno);
     70     if (INVALID_HANDLE_VALUE == file) {
     71         return NULL;
     72     }
     73 
     74     LARGE_INTEGER fileSize;
     75     if (0 == GetFileSizeEx(file, &fileSize)) {
     76         //TODO: use SK_TRACEHR(GetLastError(), "Could not get file size.") to report.
     77         return NULL;
     78     }
     79     if (!SkTFitsIn<size_t>(fileSize.QuadPart)) {
     80         return NULL;
     81     }
     82 
     83     SkAutoWinMMap mmap(CreateFileMapping(file, NULL, PAGE_READONLY, 0, 0, NULL));
     84     if (!mmap.isValid()) {
     85         //TODO: use SK_TRACEHR(GetLastError(), "Could not create file mapping.") to report.
     86         return NULL;
     87     }
     88 
     89     // Eventually call UnmapViewOfFile
     90     void* addr = MapViewOfFile(mmap, FILE_MAP_READ, 0, 0, 0);
     91     if (NULL == addr) {
     92         //TODO: use SK_TRACEHR(GetLastError(), "Could not map view of file.") to report.
     93         return NULL;
     94     }
     95 
     96     *length = static_cast<size_t>(fileSize.QuadPart);
     97     return addr;
     98 }
     99 
    100 int sk_fileno(SkFILE* f) {
    101     return _fileno((FILE*)f);
    102 }
    103 
    104 void* sk_fmmap(SkFILE* f, size_t* length) {
    105     int fileno = sk_fileno(f);
    106     if (fileno < 0) {
    107         return NULL;
    108     }
    109 
    110     return sk_fdmmap(fileno, length);
    111 }
    112