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