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 template <typename HandleType, HandleType InvalidValue, BOOL (WINAPI * Close)(HandleType)>
     54 class SkAutoTHandle : SkNoncopyable {
     55 public:
     56     SkAutoTHandle(HandleType handle) : fHandle(handle) { }
     57     ~SkAutoTHandle() { Close(fHandle); }
     58     operator HandleType() { return fHandle; }
     59     bool isValid() { return InvalidValue != fHandle; }
     60 private:
     61     HandleType fHandle;
     62 };
     63 typedef SkAutoTHandle<HANDLE, INVALID_HANDLE_VALUE, CloseHandle> SkAutoWinFile;
     64 typedef SkAutoTHandle<HANDLE, NULL, CloseHandle> SkAutoWinMMap;
     65 
     66 void sk_fmunmap(const void* addr, size_t) {
     67     UnmapViewOfFile(addr);
     68 }
     69 
     70 void* sk_fdmmap(int fileno, size_t* length) {
     71     HANDLE file = (HANDLE)_get_osfhandle(fileno);
     72     if (INVALID_HANDLE_VALUE == file) {
     73         return NULL;
     74     }
     75 
     76     LARGE_INTEGER fileSize;
     77     if (0 == GetFileSizeEx(file, &fileSize)) {
     78         //TODO: use SK_TRACEHR(GetLastError(), "Could not get file size.") to report.
     79         return NULL;
     80     }
     81     if (!SkTFitsIn<size_t>(fileSize.QuadPart)) {
     82         return NULL;
     83     }
     84 
     85     SkAutoWinMMap mmap(CreateFileMapping(file, NULL, PAGE_READONLY, 0, 0, NULL));
     86     if (!mmap.isValid()) {
     87         //TODO: use SK_TRACEHR(GetLastError(), "Could not create file mapping.") to report.
     88         return NULL;
     89     }
     90 
     91     // Eventually call UnmapViewOfFile
     92     void* addr = MapViewOfFile(mmap, FILE_MAP_READ, 0, 0, 0);
     93     if (NULL == addr) {
     94         //TODO: use SK_TRACEHR(GetLastError(), "Could not map view of file.") to report.
     95         return NULL;
     96     }
     97 
     98     *length = static_cast<size_t>(fileSize.QuadPart);
     99     return addr;
    100 }
    101 
    102 int sk_fileno(SkFILE* f) {
    103     return _fileno((FILE*)f);
    104 }
    105 
    106 void* sk_fmmap(SkFILE* f, size_t* length) {
    107     int fileno = sk_fileno(f);
    108     if (fileno < 0) {
    109         return NULL;
    110     }
    111 
    112     return sk_fdmmap(fileno, length);
    113 }
    114