Linus Torvalds, Mon, Jul 17, 2006 19:56:04 +0200: > > So we could introduce a second mmap() which is normally the same as > > mmap(), except for windows, where it is a rename() and unlink() safe > > version of mmap() by reading the thing into RAM. Not very pretty. > > Well, not too ugly either. > > Imagine having a "map_packfile()" interface, and letting different targets > just implement their own version. That doesn't sound too bad, does it? > Maybe the patch below will at least help to identify the place where the interface could be used. It's a bit more than packfiles. I use it since march (I really meant to post it, but probably forgot). But careful, it has an ugly piece in git-compat-util.h, which probably makes the patch only useful on cygwin and nowhere else (is there any other platform which has NO_MMAP defined?). --- Makefile | 2 +- compat/realmmap.c | 26 ++++++++++++++++++++++++++ diff.c | 4 ++-- git-compat-util.h | 10 ++++++++-- sha1_file.c | 24 ++++++++++++------------ 5 files changed, 49 insertions(+), 17 deletions(-) diff --git a/Makefile b/Makefile index 01fb9cf..f16b466 100644 --- a/Makefile +++ b/Makefile @@ -432,7 +432,7 @@ ifdef NO_SETENV endif ifdef NO_MMAP COMPAT_CFLAGS += -DNO_MMAP - COMPAT_OBJS += compat/mmap.o + COMPAT_OBJS += compat/mmap.o compat/realmmap.o endif ifdef NO_IPV6 ALL_CFLAGS += -DNO_IPV6 diff --git a/compat/realmmap.c b/compat/realmmap.c new file mode 100644 index 0000000..8f26641 --- /dev/null +++ b/compat/realmmap.c @@ -0,0 +1,26 @@ +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <errno.h> +#include <sys/mman.h> +#include "../git-compat-util.h" + +#undef mmap +#undef munmap + +void *realmmap(void *start, size_t length, int prot , int flags, int fd, off_t offset) +{ + if (start != NULL || !(flags & MAP_PRIVATE)) { + errno = ENOTSUP; + return MAP_FAILED; + } + start = mmap(start, length, prot, flags, fd, offset); + return start; +} + +int realmunmap(void *start, size_t length) +{ + return munmap(start, length); +} + + diff --git a/diff.c b/diff.c index 8b44756..831bf82 100644 --- a/diff.c +++ b/diff.c @@ -1094,7 +1094,7 @@ int diff_populate_filespec(struct diff_f fd = open(s->path, O_RDONLY); if (fd < 0) goto err_empty; - s->data = mmap(NULL, s->size, PROT_READ, MAP_PRIVATE, fd, 0); + s->data = realmmap(NULL, s->size, PROT_READ, MAP_PRIVATE, fd, 0); close(fd); if (s->data == MAP_FAILED) goto err_empty; @@ -1126,7 +1126,7 @@ void diff_free_filespec_data(struct diff if (s->should_free) free(s->data); else if (s->should_munmap) - munmap(s->data, s->size); + realmunmap(s->data, s->size); s->should_free = s->should_munmap = 0; s->data = NULL; free(s->cnt_data); diff --git a/git-compat-util.h b/git-compat-util.h index 93f5580..503b8e4 100644 --- a/git-compat-util.h +++ b/git-compat-util.h @@ -46,22 +46,28 @@ extern void set_error_routine(void (*rou #ifdef NO_MMAP -#ifndef PROT_READ +#include <sys/mman.h> +/*#ifndef PROT_READ #define PROT_READ 1 #define PROT_WRITE 2 #define MAP_PRIVATE 1 #define MAP_FAILED ((void*)-1) -#endif +#endif*/ #define mmap gitfakemmap #define munmap gitfakemunmap extern void *gitfakemmap(void *start, size_t length, int prot , int flags, int fd, off_t offset); extern int gitfakemunmap(void *start, size_t length); +extern void *realmmap(void *start, size_t length, int prot , int flags, int fd, off_t offset); +extern int realmunmap(void *start, size_t length); + #else /* NO_MMAP */ #include <sys/mman.h> +#define realmmap mmap +#define realmunmap munmap #endif /* NO_MMAP */ #ifdef NO_SETENV diff --git a/sha1_file.c b/sha1_file.c index e666aec..38ab710 100644 --- a/sha1_file.c +++ b/sha1_file.c @@ -331,14 +331,14 @@ static void read_info_alternates(const c close(fd); return; } - map = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0); + map = realmmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0); close(fd); if (map == MAP_FAILED) return; link_alt_odb_entries(map, map + st.st_size, '\n', relative_base, depth); - munmap(map, st.st_size); + realmunmap(map, st.st_size); } void prepare_alt_odb(void) @@ -394,7 +394,7 @@ static int check_packed_git_idx(const ch return -1; } idx_size = st.st_size; - idx_map = mmap(NULL, idx_size, PROT_READ, MAP_PRIVATE, fd, 0); + idx_map = realmmap(NULL, idx_size, PROT_READ, MAP_PRIVATE, fd, 0); close(fd); if (idx_map == MAP_FAILED) return -1; @@ -439,7 +439,7 @@ static int unuse_one_packed_git(void) } if (!lru) return 0; - munmap(lru->pack_base, lru->pack_size); + realmunmap(lru->pack_base, lru->pack_size); lru->pack_base = NULL; return 1; } @@ -476,7 +476,7 @@ int use_packed_git(struct packed_git *p) } if (st.st_size != p->pack_size) die("packfile %s size mismatch.", p->pack_name); - map = mmap(NULL, p->pack_size, PROT_READ, MAP_PRIVATE, fd, 0); + map = realmmap(NULL, p->pack_size, PROT_READ, MAP_PRIVATE, fd, 0); close(fd); if (map == MAP_FAILED) die("packfile %s cannot be mapped.", p->pack_name); @@ -511,7 +511,7 @@ struct packed_git *add_packed_git(char * /* do we have a corresponding .pack file? */ strcpy(path + path_len - 4, ".pack"); if (stat(path, &st) || !S_ISREG(st.st_mode)) { - munmap(idx_map, idx_size); + realmunmap(idx_map, idx_size); return NULL; } /* ok, it looks sane as far as we can check without @@ -676,7 +676,7 @@ static void *map_sha1_file_internal(cons */ sha1_file_open_flag = 0; } - map = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0); + map = realmmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0); close(fd); if (map == MAP_FAILED) return NULL; @@ -1220,7 +1220,7 @@ int sha1_object_info(const unsigned char *sizep = size; } inflateEnd(&stream); - munmap(map, mapsize); + realmunmap(map, mapsize); return status; } @@ -1246,7 +1246,7 @@ void * read_sha1_file(const unsigned cha map = map_sha1_file_internal(sha1, &mapsize); if (map) { buf = unpack_sha1_file(map, mapsize, type, size); - munmap(map, mapsize); + realmunmap(map, mapsize); return buf; } reprepare_packed_git(); @@ -1543,7 +1543,7 @@ int write_sha1_to_fd(int fd, const unsig if (buf) { retval = write_buffer(fd, buf, objsize); - munmap(buf, objsize); + realmunmap(buf, objsize); return retval; } @@ -1726,7 +1726,7 @@ int index_fd(unsigned char *sha1, int fd buf = ""; if (size) - buf = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0); + buf = realmmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0); close(fd); if (buf == MAP_FAILED) return -1; @@ -1740,7 +1740,7 @@ int index_fd(unsigned char *sha1, int fd ret = 0; } if (size) - munmap(buf, size); + realmunmap(buf, size); return ret; } -- 1.4.1.gb944 - : send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html