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