SkOSFile_win.cpp revision f5cc5b140c1c00c536e02b5cfbe158bb2d5c2c15
16cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com/* 26cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com * Copyright 2013 Google Inc. 36cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com * 46cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com * Use of this source code is governed by a BSD-style license that can be 56cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com * found in the LICENSE file. 66cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com */ 76cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com 86cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com#include "SkOSFile.h" 96cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com 10f5cc5b140c1c00c536e02b5cfbe158bb2d5c2c15bungeman@google.com#include "SkTFitsIn.h" 1111c9a55afd95078d14ab8cd7c1c5c0032af2a498bungeman@google.com 126cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com#include <io.h> 136cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com#include <stdio.h> 146cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com#include <sys/stat.h> 156cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com 166cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.comtypedef struct { 176cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com ULONGLONG fVolume; 186cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com ULONGLONG fLsbSize; 196cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com ULONGLONG fMsbSize; 206cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com} SkFILEID; 216cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com 226cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.comstatic bool sk_ino(SkFILE* f, SkFILEID* id) { 236cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com int fileno = _fileno((FILE*)f); 246cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com if (fileno < 0) { 256cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com return false; 266cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com } 276cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com 286cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com HANDLE file = (HANDLE)_get_osfhandle(fileno); 296cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com if (INVALID_HANDLE_VALUE == file) { 306cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com return false; 316cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com } 326cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com 336cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com //TODO: call GetFileInformationByHandleEx on Vista and later with FileIdInfo. 346cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com BY_HANDLE_FILE_INFORMATION info; 356cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com if (0 == GetFileInformationByHandle(file, &info)) { 366cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com return false; 376cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com } 386cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com id->fVolume = info.dwVolumeSerialNumber; 396cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com id->fLsbSize = info.nFileIndexLow + (((ULONGLONG)info.nFileIndexHigh) << 32); 406cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com id->fMsbSize = 0; 416cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com 426cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com return true; 436cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com} 446cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com 456cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.combool sk_fidentical(SkFILE* a, SkFILE* b) { 466cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com SkFILEID aID, bID; 476cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com return sk_ino(a, &aID) && sk_ino(b, &bID) 486cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com && aID.fLsbSize == bID.fLsbSize 496cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com && aID.fMsbSize == bID.fMsbSize 506cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com && aID.fVolume == bID.fVolume; 516cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com} 526cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com 536cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.comtemplate <typename HandleType, HandleType InvalidValue, BOOL (WINAPI * Close)(HandleType)> 546cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.comclass SkAutoTHandle : SkNoncopyable { 556cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.compublic: 566cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com SkAutoTHandle(HandleType handle) : fHandle(handle) { } 576cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com ~SkAutoTHandle() { Close(fHandle); } 586cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com operator HandleType() { return fHandle; } 596cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com bool isValid() { return InvalidValue != fHandle; } 606cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.comprivate: 616cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com HandleType fHandle; 626cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com}; 636cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.comtypedef SkAutoTHandle<HANDLE, INVALID_HANDLE_VALUE, CloseHandle> SkAutoWinFile; 646cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.comtypedef SkAutoTHandle<HANDLE, NULL, CloseHandle> SkAutoWinMMap; 656cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com 666cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.comvoid sk_fmunmap(const void* addr, size_t) { 676cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com UnmapViewOfFile(addr); 686cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com} 696cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com 7011c9a55afd95078d14ab8cd7c1c5c0032af2a498bungeman@google.comvoid* sk_fdmmap(int fileno, size_t* length) { 7111c9a55afd95078d14ab8cd7c1c5c0032af2a498bungeman@google.com HANDLE file = (HANDLE)_get_osfhandle(fileno); 7211c9a55afd95078d14ab8cd7c1c5c0032af2a498bungeman@google.com if (INVALID_HANDLE_VALUE == file) { 736cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com return NULL; 746cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com } 756cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com 7611c9a55afd95078d14ab8cd7c1c5c0032af2a498bungeman@google.com LARGE_INTEGER fileSize; 7711c9a55afd95078d14ab8cd7c1c5c0032af2a498bungeman@google.com if (0 == GetFileSizeEx(file, &fileSize)) { 7811c9a55afd95078d14ab8cd7c1c5c0032af2a498bungeman@google.com //TODO: use SK_TRACEHR(GetLastError(), "Could not get file size.") to report. 796cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com return NULL; 806cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com } 8111c9a55afd95078d14ab8cd7c1c5c0032af2a498bungeman@google.com if (!SkTFitsIn<size_t>(fileSize.QuadPart)) { 826cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com return NULL; 836cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com } 846cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com 856cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com SkAutoWinMMap mmap(CreateFileMapping(file, NULL, PAGE_READONLY, 0, 0, NULL)); 866cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com if (!mmap.isValid()) { 876cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com //TODO: use SK_TRACEHR(GetLastError(), "Could not create file mapping.") to report. 886cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com return NULL; 896cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com } 906cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com 916cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com // Eventually call UnmapViewOfFile 926cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com void* addr = MapViewOfFile(mmap, FILE_MAP_READ, 0, 0, 0); 936cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com if (NULL == addr) { 946cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com //TODO: use SK_TRACEHR(GetLastError(), "Could not map view of file.") to report. 956cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com return NULL; 966cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com } 976cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com 9811c9a55afd95078d14ab8cd7c1c5c0032af2a498bungeman@google.com *length = static_cast<size_t>(fileSize.QuadPart); 996cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com return addr; 1006cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com} 10111c9a55afd95078d14ab8cd7c1c5c0032af2a498bungeman@google.com 10211c9a55afd95078d14ab8cd7c1c5c0032af2a498bungeman@google.comint sk_fileno(SkFILE* f) { 10311c9a55afd95078d14ab8cd7c1c5c0032af2a498bungeman@google.com return _fileno((FILE*)f); 10411c9a55afd95078d14ab8cd7c1c5c0032af2a498bungeman@google.com} 10511c9a55afd95078d14ab8cd7c1c5c0032af2a498bungeman@google.com 10611c9a55afd95078d14ab8cd7c1c5c0032af2a498bungeman@google.comvoid* sk_fmmap(SkFILE* f, size_t* length) { 10711c9a55afd95078d14ab8cd7c1c5c0032af2a498bungeman@google.com int fileno = sk_fileno(f); 10811c9a55afd95078d14ab8cd7c1c5c0032af2a498bungeman@google.com if (fileno < 0) { 10911c9a55afd95078d14ab8cd7c1c5c0032af2a498bungeman@google.com return NULL; 11011c9a55afd95078d14ab8cd7c1c5c0032af2a498bungeman@google.com } 11111c9a55afd95078d14ab8cd7c1c5c0032af2a498bungeman@google.com 11211c9a55afd95078d14ab8cd7c1c5c0032af2a498bungeman@google.com return sk_fdmmap(fileno, length); 11311c9a55afd95078d14ab8cd7c1c5c0032af2a498bungeman@google.com} 114