Welcome to mirror list, hosted at ThFree Co, Russian Federation.

map.c « win32 « src - github.com/mono/libgit2.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 3e6b3d87809f46f8680f1b65381fda00b22d8093 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
/*
 * Copyright (C) 2009-2011 the libgit2 contributors
 *
 * This file is part of libgit2, distributed under the GNU GPL v2 with
 * a Linking Exception. For full terms see the included COPYING file.
 */

#include "map.h"
#include <errno.h>


static DWORD get_page_size(void)
{
	static DWORD page_size;
	SYSTEM_INFO sys;

	if (!page_size) {
		GetSystemInfo(&sys);
		page_size = sys.dwAllocationGranularity;
	}

	return page_size;
}

int p_mmap(git_map *out, size_t len, int prot, int flags, int fd, git_off_t offset)
{
	HANDLE fh = (HANDLE)_get_osfhandle(fd);
	DWORD page_size = get_page_size();
	DWORD fmap_prot = 0;
	DWORD view_prot = 0;
	DWORD off_low = 0;
	DWORD off_hi = 0;
	git_off_t page_start;
	git_off_t page_offset;

	assert((out != NULL) && (len > 0));

	if ((out == NULL) || (len == 0)) {
		errno = EINVAL;
		return git__throw(GIT_ERROR, "Failed to mmap. No map or zero length");
	}

	out->data = NULL;
	out->len = 0;
	out->fmh = NULL;

	if (fh == INVALID_HANDLE_VALUE) {
		errno = EBADF;
		return git__throw(GIT_ERROR, "Failed to mmap. Invalid handle value");
	}

	if (prot & GIT_PROT_WRITE)
		fmap_prot |= PAGE_READWRITE;
	else if (prot & GIT_PROT_READ)
		fmap_prot |= PAGE_READONLY;
	else {
		errno = EINVAL;
		return git__throw(GIT_ERROR, "Failed to mmap. Invalid protection parameters");
	}

	if (prot & GIT_PROT_WRITE)
		view_prot |= FILE_MAP_WRITE;
	if (prot & GIT_PROT_READ)
		view_prot |= FILE_MAP_READ;

	if (flags & GIT_MAP_FIXED) {
		errno = EINVAL;
		return git__throw(GIT_ERROR, "Failed to mmap. FIXED not set");
	}

	page_start = (offset / page_size) * page_size;
	page_offset = offset - page_start;

	if (page_offset != 0) { /* offset must be multiple of page size */
		errno = EINVAL;
		return git__throw(GIT_ERROR, "Failed to mmap. Offset must be multiple of page size");
	}

	out->fmh = CreateFileMapping(fh, NULL, fmap_prot, 0, 0, NULL);
	if (!out->fmh || out->fmh == INVALID_HANDLE_VALUE) {
		/* errno = ? */
		out->fmh = NULL;
		return git__throw(GIT_ERROR, "Failed to mmap. Invalid handle value");
	}

	assert(sizeof(git_off_t) == 8);
	off_low = (DWORD)(page_start);
	off_hi = (DWORD)(page_start >> 32);
	out->data = MapViewOfFile(out->fmh, view_prot, off_hi, off_low, len);
	if (!out->data) {
		/* errno = ? */
		CloseHandle(out->fmh);
		out->fmh = NULL;
		return git__throw(GIT_ERROR, "Failed to mmap. No data written");
	}
	out->len = len;

	return GIT_SUCCESS;
}

int p_munmap(git_map *map)
{
	assert(map != NULL);

	if (!map)
		return git__throw(GIT_ERROR, "Failed to munmap. Map does not exist");

	if (map->data) {
		if (!UnmapViewOfFile(map->data)) {
			/* errno = ? */
			CloseHandle(map->fmh);
			map->data = NULL;
			map->fmh = NULL;
			return git__throw(GIT_ERROR, "Failed to munmap. Could not unmap view of file");
		}
		map->data = NULL;
	}

	if (map->fmh) {
		if (!CloseHandle(map->fmh)) {
			/* errno = ? */
			map->fmh = NULL;
			return git__throw(GIT_ERROR, "Failed to munmap. Could not close handle");
		}
		map->fmh = NULL;
	}

	return GIT_SUCCESS;
}