]> git.proxmox.com Git - libgit2.git/blame - src/win32/map.c
error-handling: On-disk config file backend
[libgit2.git] / src / win32 / map.c
CommitLineData
bb742ede 1/*
5e0de328 2 * Copyright (C) 2009-2012 the libgit2 contributors
bb742ede
VM
3 *
4 * This file is part of libgit2, distributed under the GNU GPL v2 with
5 * a Linking Exception. For full terms see the included COPYING file.
6 */
79ca2edc
RJ
7
8#include "map.h"
9#include <errno.h>
10
11
12static DWORD get_page_size(void)
13{
14 static DWORD page_size;
15 SYSTEM_INFO sys;
16
17 if (!page_size) {
18 GetSystemInfo(&sys);
19 page_size = sys.dwAllocationGranularity;
20 }
21
22 return page_size;
23}
24
f79026b4 25int p_mmap(git_map *out, size_t len, int prot, int flags, int fd, git_off_t offset)
79ca2edc
RJ
26{
27 HANDLE fh = (HANDLE)_get_osfhandle(fd);
28 DWORD page_size = get_page_size();
29 DWORD fmap_prot = 0;
30 DWORD view_prot = 0;
31 DWORD off_low = 0;
87d9869f 32 DWORD off_hi = 0;
f0bde7fa
AB
33 git_off_t page_start;
34 git_off_t page_offset;
79ca2edc
RJ
35
36 assert((out != NULL) && (len > 0));
37
38 if ((out == NULL) || (len == 0)) {
39 errno = EINVAL;
7c8b597e 40 return git__throw(GIT_ERROR, "Failed to mmap. No map or zero length");
79ca2edc
RJ
41 }
42
43 out->data = NULL;
44 out->len = 0;
45 out->fmh = NULL;
46
47 if (fh == INVALID_HANDLE_VALUE) {
48 errno = EBADF;
7c8b597e 49 return git__throw(GIT_ERROR, "Failed to mmap. Invalid handle value");
79ca2edc
RJ
50 }
51
52 if (prot & GIT_PROT_WRITE)
53 fmap_prot |= PAGE_READWRITE;
54 else if (prot & GIT_PROT_READ)
55 fmap_prot |= PAGE_READONLY;
56 else {
57 errno = EINVAL;
7c8b597e 58 return git__throw(GIT_ERROR, "Failed to mmap. Invalid protection parameters");
79ca2edc
RJ
59 }
60
61 if (prot & GIT_PROT_WRITE)
62 view_prot |= FILE_MAP_WRITE;
63 if (prot & GIT_PROT_READ)
64 view_prot |= FILE_MAP_READ;
65
66 if (flags & GIT_MAP_FIXED) {
67 errno = EINVAL;
7c8b597e 68 return git__throw(GIT_ERROR, "Failed to mmap. FIXED not set");
79ca2edc
RJ
69 }
70
71 page_start = (offset / page_size) * page_size;
72 page_offset = offset - page_start;
73
87d9869f 74 if (page_offset != 0) { /* offset must be multiple of page size */
79ca2edc 75 errno = EINVAL;
7c8b597e 76 return git__throw(GIT_ERROR, "Failed to mmap. Offset must be multiple of page size");
79ca2edc
RJ
77 }
78
79 out->fmh = CreateFileMapping(fh, NULL, fmap_prot, 0, 0, NULL);
80 if (!out->fmh || out->fmh == INVALID_HANDLE_VALUE) {
81 /* errno = ? */
82 out->fmh = NULL;
7c8b597e 83 return git__throw(GIT_ERROR, "Failed to mmap. Invalid handle value");
79ca2edc
RJ
84 }
85
f0bde7fa 86 assert(sizeof(git_off_t) == 8);
79ca2edc 87 off_low = (DWORD)(page_start);
90d4d2f0 88 off_hi = (DWORD)(page_start >> 32);
79ca2edc
RJ
89 out->data = MapViewOfFile(out->fmh, view_prot, off_hi, off_low, len);
90 if (!out->data) {
91 /* errno = ? */
92 CloseHandle(out->fmh);
93 out->fmh = NULL;
7c8b597e 94 return git__throw(GIT_ERROR, "Failed to mmap. No data written");
79ca2edc
RJ
95 }
96 out->len = len;
97
98 return GIT_SUCCESS;
99}
100
f79026b4 101int p_munmap(git_map *map)
79ca2edc
RJ
102{
103 assert(map != NULL);
104
105 if (!map)
7c8b597e 106 return git__throw(GIT_ERROR, "Failed to munmap. Map does not exist");
79ca2edc
RJ
107
108 if (map->data) {
109 if (!UnmapViewOfFile(map->data)) {
110 /* errno = ? */
111 CloseHandle(map->fmh);
112 map->data = NULL;
113 map->fmh = NULL;
7c8b597e 114 return git__throw(GIT_ERROR, "Failed to munmap. Could not unmap view of file");
79ca2edc
RJ
115 }
116 map->data = NULL;
117 }
118
119 if (map->fmh) {
120 if (!CloseHandle(map->fmh)) {
121 /* errno = ? */
122 map->fmh = NULL;
7c8b597e 123 return git__throw(GIT_ERROR, "Failed to munmap. Could not close handle");
79ca2edc
RJ
124 }
125 map->fmh = NULL;
126 }
127
128 return GIT_SUCCESS;
129}
130
131