michael@0: /* michael@0: * Copyright 2013 Google Inc. michael@0: * michael@0: * Use of this source code is governed by a BSD-style license that can be michael@0: * found in the LICENSE file. michael@0: */ michael@0: michael@0: #include "SkOSFile.h" michael@0: michael@0: #include "SkTFitsIn.h" michael@0: michael@0: #include michael@0: #include michael@0: #include michael@0: michael@0: typedef struct { michael@0: ULONGLONG fVolume; michael@0: ULONGLONG fLsbSize; michael@0: ULONGLONG fMsbSize; michael@0: } SkFILEID; michael@0: michael@0: static bool sk_ino(SkFILE* f, SkFILEID* id) { michael@0: int fileno = _fileno((FILE*)f); michael@0: if (fileno < 0) { michael@0: return false; michael@0: } michael@0: michael@0: HANDLE file = (HANDLE)_get_osfhandle(fileno); michael@0: if (INVALID_HANDLE_VALUE == file) { michael@0: return false; michael@0: } michael@0: michael@0: //TODO: call GetFileInformationByHandleEx on Vista and later with FileIdInfo. michael@0: BY_HANDLE_FILE_INFORMATION info; michael@0: if (0 == GetFileInformationByHandle(file, &info)) { michael@0: return false; michael@0: } michael@0: id->fVolume = info.dwVolumeSerialNumber; michael@0: id->fLsbSize = info.nFileIndexLow + (((ULONGLONG)info.nFileIndexHigh) << 32); michael@0: id->fMsbSize = 0; michael@0: michael@0: return true; michael@0: } michael@0: michael@0: bool sk_fidentical(SkFILE* a, SkFILE* b) { michael@0: SkFILEID aID, bID; michael@0: return sk_ino(a, &aID) && sk_ino(b, &bID) michael@0: && aID.fLsbSize == bID.fLsbSize michael@0: && aID.fMsbSize == bID.fMsbSize michael@0: && aID.fVolume == bID.fVolume; michael@0: } michael@0: michael@0: class SkAutoNullKernelHandle : SkNoncopyable { michael@0: public: michael@0: SkAutoNullKernelHandle(const HANDLE handle) : fHandle(handle) { } michael@0: ~SkAutoNullKernelHandle() { CloseHandle(fHandle); } michael@0: operator HANDLE() const { return fHandle; } michael@0: bool isValid() const { return NULL != fHandle; } michael@0: private: michael@0: HANDLE fHandle; michael@0: }; michael@0: typedef SkAutoNullKernelHandle SkAutoWinMMap; michael@0: michael@0: void sk_fmunmap(const void* addr, size_t) { michael@0: UnmapViewOfFile(addr); michael@0: } michael@0: michael@0: void* sk_fdmmap(int fileno, size_t* length) { michael@0: HANDLE file = (HANDLE)_get_osfhandle(fileno); michael@0: if (INVALID_HANDLE_VALUE == file) { michael@0: return NULL; michael@0: } michael@0: michael@0: LARGE_INTEGER fileSize; michael@0: if (0 == GetFileSizeEx(file, &fileSize)) { michael@0: //TODO: use SK_TRACEHR(GetLastError(), "Could not get file size.") to report. michael@0: return NULL; michael@0: } michael@0: if (!SkTFitsIn(fileSize.QuadPart)) { michael@0: return NULL; michael@0: } michael@0: michael@0: SkAutoWinMMap mmap(CreateFileMapping(file, NULL, PAGE_READONLY, 0, 0, NULL)); michael@0: if (!mmap.isValid()) { michael@0: //TODO: use SK_TRACEHR(GetLastError(), "Could not create file mapping.") to report. michael@0: return NULL; michael@0: } michael@0: michael@0: // Eventually call UnmapViewOfFile michael@0: void* addr = MapViewOfFile(mmap, FILE_MAP_READ, 0, 0, 0); michael@0: if (NULL == addr) { michael@0: //TODO: use SK_TRACEHR(GetLastError(), "Could not map view of file.") to report. michael@0: return NULL; michael@0: } michael@0: michael@0: *length = static_cast(fileSize.QuadPart); michael@0: return addr; michael@0: } michael@0: michael@0: int sk_fileno(SkFILE* f) { michael@0: return _fileno((FILE*)f); michael@0: } michael@0: michael@0: void* sk_fmmap(SkFILE* f, size_t* length) { michael@0: int fileno = sk_fileno(f); michael@0: if (fileno < 0) { michael@0: return NULL; michael@0: } michael@0: michael@0: return sk_fdmmap(fileno, length); michael@0: }