1#include <stdio.h>
2#include <stdlib.h>
3#include <unistd.h>
4#include <errno.h>
5#include "../cache.h"
6
7typedef struct fakemmapwritable {
8 void *start;
9 size_t length;
10 int fd;
11 off_t offset;
12 struct fakemmapwritable *next;
13} fakemmapwritable;
14
15static fakemmapwritable *writablelist = NULL;
16
17void *gitfakemmap(void *start, size_t length, int prot , int flags, int fd, off_t offset)
18{
19 int n = 0;
20
21 if(start != NULL)
22 die("Invalid usage of gitfakemmap.");
23
24 if(lseek(fd, offset, SEEK_SET)<0) {
25 errno = EINVAL;
26 return MAP_FAILED;
27 }
28
29 start = xmalloc(length);
30 if(start == NULL) {
31 errno = ENOMEM;
32 return MAP_FAILED;
33 }
34
35 while(n < length) {
36 int count = read(fd, start+n, length-n);
37
38 if(count == 0) {
39 memset(start+n, 0, length-n);
40 break;
41 }
42
43 if(count < 0) {
44 free(start);
45 errno = EACCES;
46 return MAP_FAILED;
47 }
48
49 n += count;
50 }
51
52 if(prot & PROT_WRITE) {
53 fakemmapwritable *next = xmalloc(sizeof(fakemmapwritable));
54 next->start = start;
55 next->length = length;
56 next->fd = dup(fd);
57 next->offset = offset;
58 next->next = writablelist;
59 writablelist = next;
60 }
61
62 return start;
63}
64
65int gitfakemunmap(void *start, size_t length)
66{
67 fakemmapwritable *writable = writablelist, *before = NULL;
68
69 while(writable && (writable->start > start + length
70 || writable->start + writable->length < start)) {
71 before = writable;
72 writable = writable->next;
73 }
74
75 if(writable) {
76 /* need to write back the contents */
77 int n = 0;
78
79 if(writable->start != start || writable->length != length)
80 die("fakemmap does not support partial write back.");
81
82 if(lseek(writable->fd, writable->offset, SEEK_SET) < 0) {
83 free(start);
84 errno = EBADF;
85 return -1;
86 }
87
88 while(n < length) {
89 int count = write(writable->fd, start + n, length - n);
90
91 if(count < 0) {
92 errno = EINVAL;
93 return -1;
94 }
95
96 n += count;
97 }
98
99 close(writable->fd);
100
101 if(before)
102 before->next = writable->next;
103 else
104 writablelist = writable->next;
105
106 free(writable);
107 }
108
109 free(start);
110
111 return 0;
112}
113