[PATCH] If NO_MMAP is defined, fake mmap() and munmap()
[git.git] / compat / mmap.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <unistd.h>
4 #include <errno.h>
5 #include "../cache.h"
6
7 typedef struct fakemmapwritable {
8         void *start;
9         size_t length;
10         int fd;
11         off_t offset;
12         struct fakemmapwritable *next;
13 } fakemmapwritable;
14
15 static fakemmapwritable *writablelist = NULL;
16
17 void *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
65 int 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