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 16bf0b9ced0b93d9684b044e0880691768f9aa4394bungemanbool sk_exists(const char *path, SkFILE_Flags flags) { 17bf0b9ced0b93d9684b044e0880691768f9aa4394bungeman int mode = 0; // existence 18bf0b9ced0b93d9684b044e0880691768f9aa4394bungeman if (flags & kRead_SkFILE_Flag) { 19bf0b9ced0b93d9684b044e0880691768f9aa4394bungeman mode |= 4; // read 20bf0b9ced0b93d9684b044e0880691768f9aa4394bungeman } 21bf0b9ced0b93d9684b044e0880691768f9aa4394bungeman if (flags & kWrite_SkFILE_Flag) { 22bf0b9ced0b93d9684b044e0880691768f9aa4394bungeman mode |= 2; // write 23bf0b9ced0b93d9684b044e0880691768f9aa4394bungeman } 24bf0b9ced0b93d9684b044e0880691768f9aa4394bungeman return (0 == _access(path, mode)); 25bf0b9ced0b93d9684b044e0880691768f9aa4394bungeman} 26bf0b9ced0b93d9684b044e0880691768f9aa4394bungeman 276cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.comtypedef struct { 286cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com ULONGLONG fVolume; 296cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com ULONGLONG fLsbSize; 306cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com ULONGLONG fMsbSize; 316cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com} SkFILEID; 326cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com 336cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.comstatic bool sk_ino(SkFILE* f, SkFILEID* id) { 346cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com int fileno = _fileno((FILE*)f); 356cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com if (fileno < 0) { 366cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com return false; 376cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com } 386cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com 396cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com HANDLE file = (HANDLE)_get_osfhandle(fileno); 406cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com if (INVALID_HANDLE_VALUE == file) { 416cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com return false; 426cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com } 436cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com 446cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com //TODO: call GetFileInformationByHandleEx on Vista and later with FileIdInfo. 456cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com BY_HANDLE_FILE_INFORMATION info; 466cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com if (0 == GetFileInformationByHandle(file, &info)) { 476cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com return false; 486cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com } 496cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com id->fVolume = info.dwVolumeSerialNumber; 506cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com id->fLsbSize = info.nFileIndexLow + (((ULONGLONG)info.nFileIndexHigh) << 32); 516cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com id->fMsbSize = 0; 526cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com 536cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com return true; 546cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com} 556cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com 566cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.combool sk_fidentical(SkFILE* a, SkFILE* b) { 576cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com SkFILEID aID, bID; 586cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com return sk_ino(a, &aID) && sk_ino(b, &bID) 596cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com && aID.fLsbSize == bID.fLsbSize 606cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com && aID.fMsbSize == bID.fMsbSize 616cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com && aID.fVolume == bID.fVolume; 626cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com} 636cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com 648e13a159f3a54f761ab80b16377015e5a9077411commit-bot@chromium.orgclass SkAutoNullKernelHandle : SkNoncopyable { 656cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.compublic: 668e13a159f3a54f761ab80b16377015e5a9077411commit-bot@chromium.org SkAutoNullKernelHandle(const HANDLE handle) : fHandle(handle) { } 678e13a159f3a54f761ab80b16377015e5a9077411commit-bot@chromium.org ~SkAutoNullKernelHandle() { CloseHandle(fHandle); } 688e13a159f3a54f761ab80b16377015e5a9077411commit-bot@chromium.org operator HANDLE() const { return fHandle; } 6949f085dddff10473b6ebf832a974288300224e60bsalomon bool isValid() const { return SkToBool(fHandle); } 706cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.comprivate: 718e13a159f3a54f761ab80b16377015e5a9077411commit-bot@chromium.org HANDLE fHandle; 726cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com}; 738e13a159f3a54f761ab80b16377015e5a9077411commit-bot@chromium.orgtypedef SkAutoNullKernelHandle SkAutoWinMMap; 746cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com 756cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.comvoid sk_fmunmap(const void* addr, size_t) { 766cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com UnmapViewOfFile(addr); 776cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com} 786cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com 7911c9a55afd95078d14ab8cd7c1c5c0032af2a498bungeman@google.comvoid* sk_fdmmap(int fileno, size_t* length) { 8011c9a55afd95078d14ab8cd7c1c5c0032af2a498bungeman@google.com HANDLE file = (HANDLE)_get_osfhandle(fileno); 8111c9a55afd95078d14ab8cd7c1c5c0032af2a498bungeman@google.com if (INVALID_HANDLE_VALUE == file) { 826cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com return NULL; 836cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com } 846cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com 8511c9a55afd95078d14ab8cd7c1c5c0032af2a498bungeman@google.com LARGE_INTEGER fileSize; 8611c9a55afd95078d14ab8cd7c1c5c0032af2a498bungeman@google.com if (0 == GetFileSizeEx(file, &fileSize)) { 8711c9a55afd95078d14ab8cd7c1c5c0032af2a498bungeman@google.com //TODO: use SK_TRACEHR(GetLastError(), "Could not get file size.") to report. 886cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com return NULL; 896cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com } 9011c9a55afd95078d14ab8cd7c1c5c0032af2a498bungeman@google.com if (!SkTFitsIn<size_t>(fileSize.QuadPart)) { 916cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com return NULL; 926cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com } 936cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com 946cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com SkAutoWinMMap mmap(CreateFileMapping(file, NULL, PAGE_READONLY, 0, 0, NULL)); 956cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com if (!mmap.isValid()) { 966cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com //TODO: use SK_TRACEHR(GetLastError(), "Could not create file mapping.") to report. 976cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com return NULL; 986cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com } 996cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com 1006cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com // Eventually call UnmapViewOfFile 1016cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com void* addr = MapViewOfFile(mmap, FILE_MAP_READ, 0, 0, 0); 1026cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com if (NULL == addr) { 1036cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com //TODO: use SK_TRACEHR(GetLastError(), "Could not map view of file.") to report. 1046cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com return NULL; 1056cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com } 1066cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com 10711c9a55afd95078d14ab8cd7c1c5c0032af2a498bungeman@google.com *length = static_cast<size_t>(fileSize.QuadPart); 1086cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com return addr; 1096cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com} 11011c9a55afd95078d14ab8cd7c1c5c0032af2a498bungeman@google.com 11111c9a55afd95078d14ab8cd7c1c5c0032af2a498bungeman@google.comint sk_fileno(SkFILE* f) { 11211c9a55afd95078d14ab8cd7c1c5c0032af2a498bungeman@google.com return _fileno((FILE*)f); 11311c9a55afd95078d14ab8cd7c1c5c0032af2a498bungeman@google.com} 11411c9a55afd95078d14ab8cd7c1c5c0032af2a498bungeman@google.com 11511c9a55afd95078d14ab8cd7c1c5c0032af2a498bungeman@google.comvoid* sk_fmmap(SkFILE* f, size_t* length) { 11611c9a55afd95078d14ab8cd7c1c5c0032af2a498bungeman@google.com int fileno = sk_fileno(f); 11711c9a55afd95078d14ab8cd7c1c5c0032af2a498bungeman@google.com if (fileno < 0) { 11811c9a55afd95078d14ab8cd7c1c5c0032af2a498bungeman@google.com return NULL; 11911c9a55afd95078d14ab8cd7c1c5c0032af2a498bungeman@google.com } 12011c9a55afd95078d14ab8cd7c1c5c0032af2a498bungeman@google.com 12111c9a55afd95078d14ab8cd7c1c5c0032af2a498bungeman@google.com return sk_fdmmap(fileno, length); 12211c9a55afd95078d14ab8cd7c1c5c0032af2a498bungeman@google.com} 123