blob: 7fec557987e307d6faae0789aea88a04f51fc294 [file] [log] [blame]
bungeman@google.com6cab1a42013-05-29 13:43:31 +00001/*
2 * Copyright 2013 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "SkOSFile.h"
9
bungeman@google.comf5cc5b12013-07-12 18:22:49 +000010#include "SkTFitsIn.h"
bungeman@google.com11c9a552013-06-03 17:10:35 +000011
bungeman@google.com6cab1a42013-05-29 13:43:31 +000012#include <io.h>
13#include <stdio.h>
14#include <sys/stat.h>
15
16typedef struct {
17 ULONGLONG fVolume;
18 ULONGLONG fLsbSize;
19 ULONGLONG fMsbSize;
20} SkFILEID;
21
22static bool sk_ino(SkFILE* f, SkFILEID* id) {
23 int fileno = _fileno((FILE*)f);
24 if (fileno < 0) {
25 return false;
26 }
27
28 HANDLE file = (HANDLE)_get_osfhandle(fileno);
29 if (INVALID_HANDLE_VALUE == file) {
30 return false;
31 }
32
33 //TODO: call GetFileInformationByHandleEx on Vista and later with FileIdInfo.
34 BY_HANDLE_FILE_INFORMATION info;
35 if (0 == GetFileInformationByHandle(file, &info)) {
36 return false;
37 }
38 id->fVolume = info.dwVolumeSerialNumber;
39 id->fLsbSize = info.nFileIndexLow + (((ULONGLONG)info.nFileIndexHigh) << 32);
40 id->fMsbSize = 0;
41
42 return true;
43}
44
45bool sk_fidentical(SkFILE* a, SkFILE* b) {
46 SkFILEID aID, bID;
47 return sk_ino(a, &aID) && sk_ino(b, &bID)
48 && aID.fLsbSize == bID.fLsbSize
49 && aID.fMsbSize == bID.fMsbSize
50 && aID.fVolume == bID.fVolume;
51}
52
53template <typename HandleType, HandleType InvalidValue, BOOL (WINAPI * Close)(HandleType)>
54class SkAutoTHandle : SkNoncopyable {
55public:
56 SkAutoTHandle(HandleType handle) : fHandle(handle) { }
57 ~SkAutoTHandle() { Close(fHandle); }
58 operator HandleType() { return fHandle; }
59 bool isValid() { return InvalidValue != fHandle; }
60private:
61 HandleType fHandle;
62};
63typedef SkAutoTHandle<HANDLE, INVALID_HANDLE_VALUE, CloseHandle> SkAutoWinFile;
64typedef SkAutoTHandle<HANDLE, NULL, CloseHandle> SkAutoWinMMap;
65
66void sk_fmunmap(const void* addr, size_t) {
67 UnmapViewOfFile(addr);
68}
69
bungeman@google.com11c9a552013-06-03 17:10:35 +000070void* sk_fdmmap(int fileno, size_t* length) {
bungeman@google.com6cab1a42013-05-29 13:43:31 +000071 HANDLE file = (HANDLE)_get_osfhandle(fileno);
72 if (INVALID_HANDLE_VALUE == file) {
73 return NULL;
74 }
75
bungeman@google.com11c9a552013-06-03 17:10:35 +000076 LARGE_INTEGER fileSize;
77 if (0 == GetFileSizeEx(file, &fileSize)) {
78 //TODO: use SK_TRACEHR(GetLastError(), "Could not get file size.") to report.
79 return NULL;
80 }
81 if (!SkTFitsIn<size_t>(fileSize.QuadPart)) {
82 return NULL;
83 }
84
bungeman@google.com6cab1a42013-05-29 13:43:31 +000085 SkAutoWinMMap mmap(CreateFileMapping(file, NULL, PAGE_READONLY, 0, 0, NULL));
86 if (!mmap.isValid()) {
87 //TODO: use SK_TRACEHR(GetLastError(), "Could not create file mapping.") to report.
88 return NULL;
89 }
90
91 // Eventually call UnmapViewOfFile
92 void* addr = MapViewOfFile(mmap, FILE_MAP_READ, 0, 0, 0);
93 if (NULL == addr) {
94 //TODO: use SK_TRACEHR(GetLastError(), "Could not map view of file.") to report.
95 return NULL;
96 }
97
bungeman@google.com11c9a552013-06-03 17:10:35 +000098 *length = static_cast<size_t>(fileSize.QuadPart);
bungeman@google.com6cab1a42013-05-29 13:43:31 +000099 return addr;
100}
bungeman@google.com11c9a552013-06-03 17:10:35 +0000101
102int sk_fileno(SkFILE* f) {
103 return _fileno((FILE*)f);
104}
105
106void* sk_fmmap(SkFILE* f, size_t* length) {
107 int fileno = sk_fileno(f);
108 if (fileno < 0) {
109 return NULL;
110 }
111
112 return sk_fdmmap(fileno, length);
113}