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 538e13a159f3a54f761ab80b16377015e5a9077411commit-bot@chromium.orgclass SkAutoNullKernelHandle : SkNoncopyable { 546cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.compublic: 558e13a159f3a54f761ab80b16377015e5a9077411commit-bot@chromium.org SkAutoNullKernelHandle(const HANDLE handle) : fHandle(handle) { } 568e13a159f3a54f761ab80b16377015e5a9077411commit-bot@chromium.org ~SkAutoNullKernelHandle() { CloseHandle(fHandle); } 578e13a159f3a54f761ab80b16377015e5a9077411commit-bot@chromium.org operator HANDLE() const { return fHandle; } 588e13a159f3a54f761ab80b16377015e5a9077411commit-bot@chromium.org bool isValid() const { return NULL != fHandle; } 596cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.comprivate: 608e13a159f3a54f761ab80b16377015e5a9077411commit-bot@chromium.org HANDLE fHandle; 616cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com}; 628e13a159f3a54f761ab80b16377015e5a9077411commit-bot@chromium.orgtypedef SkAutoNullKernelHandle SkAutoWinMMap; 636cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com 646cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.comvoid sk_fmunmap(const void* addr, size_t) { 656cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com UnmapViewOfFile(addr); 666cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com} 676cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com 6811c9a55afd95078d14ab8cd7c1c5c0032af2a498bungeman@google.comvoid* sk_fdmmap(int fileno, size_t* length) { 6911c9a55afd95078d14ab8cd7c1c5c0032af2a498bungeman@google.com HANDLE file = (HANDLE)_get_osfhandle(fileno); 7011c9a55afd95078d14ab8cd7c1c5c0032af2a498bungeman@google.com if (INVALID_HANDLE_VALUE == file) { 716cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com return NULL; 726cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com } 736cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com 7411c9a55afd95078d14ab8cd7c1c5c0032af2a498bungeman@google.com LARGE_INTEGER fileSize; 7511c9a55afd95078d14ab8cd7c1c5c0032af2a498bungeman@google.com if (0 == GetFileSizeEx(file, &fileSize)) { 7611c9a55afd95078d14ab8cd7c1c5c0032af2a498bungeman@google.com //TODO: use SK_TRACEHR(GetLastError(), "Could not get file size.") to report. 776cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com return NULL; 786cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com } 7911c9a55afd95078d14ab8cd7c1c5c0032af2a498bungeman@google.com if (!SkTFitsIn<size_t>(fileSize.QuadPart)) { 806cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com return NULL; 816cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com } 826cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com 836cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com SkAutoWinMMap mmap(CreateFileMapping(file, NULL, PAGE_READONLY, 0, 0, NULL)); 846cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com if (!mmap.isValid()) { 856cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com //TODO: use SK_TRACEHR(GetLastError(), "Could not create file mapping.") to report. 866cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com return NULL; 876cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com } 886cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com 896cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com // Eventually call UnmapViewOfFile 906cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com void* addr = MapViewOfFile(mmap, FILE_MAP_READ, 0, 0, 0); 916cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com if (NULL == addr) { 926cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com //TODO: use SK_TRACEHR(GetLastError(), "Could not map view of file.") to report. 936cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com return NULL; 946cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com } 956cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com 9611c9a55afd95078d14ab8cd7c1c5c0032af2a498bungeman@google.com *length = static_cast<size_t>(fileSize.QuadPart); 976cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com return addr; 986cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com} 9911c9a55afd95078d14ab8cd7c1c5c0032af2a498bungeman@google.com 10011c9a55afd95078d14ab8cd7c1c5c0032af2a498bungeman@google.comint sk_fileno(SkFILE* f) { 10111c9a55afd95078d14ab8cd7c1c5c0032af2a498bungeman@google.com return _fileno((FILE*)f); 10211c9a55afd95078d14ab8cd7c1c5c0032af2a498bungeman@google.com} 10311c9a55afd95078d14ab8cd7c1c5c0032af2a498bungeman@google.com 10411c9a55afd95078d14ab8cd7c1c5c0032af2a498bungeman@google.comvoid* sk_fmmap(SkFILE* f, size_t* length) { 10511c9a55afd95078d14ab8cd7c1c5c0032af2a498bungeman@google.com int fileno = sk_fileno(f); 10611c9a55afd95078d14ab8cd7c1c5c0032af2a498bungeman@google.com if (fileno < 0) { 10711c9a55afd95078d14ab8cd7c1c5c0032af2a498bungeman@google.com return NULL; 10811c9a55afd95078d14ab8cd7c1c5c0032af2a498bungeman@google.com } 10911c9a55afd95078d14ab8cd7c1c5c0032af2a498bungeman@google.com 11011c9a55afd95078d14ab8cd7c1c5c0032af2a498bungeman@google.com return sk_fdmmap(fileno, length); 11111c9a55afd95078d14ab8cd7c1c5c0032af2a498bungeman@google.com} 112