mirror of
https://git.proxmox.com/git/libgit2
synced 2025-06-28 21:57:29 +00:00
win32: Add routines to abstract memory-mapped file functions
In particular, the git__mmap() and git__munmap() routines provide the interface to platform specific memory-mapped file facilities. We provide implementations for unix and win32, which can be found in their own sub-directories. Signed-off-by: Ramsay Jones <ramsay@ramsay1.demon.co.uk> Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
This commit is contained in:
parent
7a6cf81537
commit
79ca2edcd4
12
Makefile
12
Makefile
@ -11,6 +11,7 @@ all::
|
|||||||
DOXYGEN = doxygen
|
DOXYGEN = doxygen
|
||||||
INSTALL = install
|
INSTALL = install
|
||||||
RANLIB = ranlib
|
RANLIB = ranlib
|
||||||
|
AR = ar cr
|
||||||
|
|
||||||
prefix=/usr/local
|
prefix=/usr/local
|
||||||
libdir=$(prefix)/lib
|
libdir=$(prefix)/lib
|
||||||
@ -21,6 +22,8 @@ CFLAGS = -g -O2 -Wall
|
|||||||
LIBS = -L. -lgit2 -lz
|
LIBS = -L. -lgit2 -lz
|
||||||
OS = unix
|
OS = unix
|
||||||
|
|
||||||
|
CRYPTO_LIB = -lcrypto
|
||||||
|
|
||||||
EXTRA_LIBS =
|
EXTRA_LIBS =
|
||||||
EXTRA_SRC =
|
EXTRA_SRC =
|
||||||
EXTRA_OBJ =
|
EXTRA_OBJ =
|
||||||
@ -32,6 +35,8 @@ ifneq (,$(findstring CYGWIN,$(uname_S)))
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
SRC_C = $(wildcard src/*.c)
|
SRC_C = $(wildcard src/*.c)
|
||||||
|
OS_SRC = $(wildcard src/$(OS)/*.c)
|
||||||
|
SRC_C += $(OS_SRC)
|
||||||
OBJS = $(patsubst %.c,%.o,$(SRC_C))
|
OBJS = $(patsubst %.c,%.o,$(SRC_C))
|
||||||
HDRS = $(wildcard src/*.h)
|
HDRS = $(wildcard src/*.h)
|
||||||
PUBLIC_HEADERS = $(wildcard src/git/*.h)
|
PUBLIC_HEADERS = $(wildcard src/git/*.h)
|
||||||
@ -46,7 +51,7 @@ TEST_RUN = $(patsubst %.exe,%.run,$(TEST_EXE))
|
|||||||
|
|
||||||
ifndef NO_OPENSSL
|
ifndef NO_OPENSSL
|
||||||
SHA1_HEADER = <openssl/sha.h>
|
SHA1_HEADER = <openssl/sha.h>
|
||||||
EXTRA_LIBS += -lcrypto
|
EXTRA_LIBS += $(CRYPTO_LIB)
|
||||||
else
|
else
|
||||||
SHA1_HEADER = "sha1/sha1.h"
|
SHA1_HEADER = "sha1/sha1.h"
|
||||||
EXTRA_SRC += src/sha1/sha1.c
|
EXTRA_SRC += src/sha1/sha1.c
|
||||||
@ -68,8 +73,7 @@ all:: $(GIT_LIB)
|
|||||||
clean:
|
clean:
|
||||||
rm -f $(GIT_LIB)
|
rm -f $(GIT_LIB)
|
||||||
rm -f libgit2.pc
|
rm -f libgit2.pc
|
||||||
rm -f src/*.o
|
rm -f src/*.o src/sha1/*.o src/unix/*.o
|
||||||
rm -f src/sha1/*.o
|
|
||||||
rm -f tests/*.o tests/*.exe tests/*.toc
|
rm -f tests/*.o tests/*.exe tests/*.toc
|
||||||
rm -rf trash-*.exe
|
rm -rf trash-*.exe
|
||||||
rm -rf apidocs
|
rm -rf apidocs
|
||||||
@ -111,7 +115,7 @@ uninstall:
|
|||||||
$(OBJS): $(HDRS)
|
$(OBJS): $(HDRS)
|
||||||
$(GIT_LIB): $(OBJS)
|
$(GIT_LIB): $(OBJS)
|
||||||
rm -f $(GIT_LIB)
|
rm -f $(GIT_LIB)
|
||||||
$(AR) cr $(GIT_LIB) $(OBJS)
|
$(AR) $(GIT_LIB) $(OBJS)
|
||||||
$(RANLIB) $(GIT_LIB)
|
$(RANLIB) $(GIT_LIB)
|
||||||
|
|
||||||
T_HDR = tests/test_lib.h tests/test_helpers.h
|
T_HDR = tests/test_lib.h tests/test_helpers.h
|
||||||
|
@ -23,14 +23,15 @@
|
|||||||
#ifdef GIT_WIN32
|
#ifdef GIT_WIN32
|
||||||
|
|
||||||
# include <io.h>
|
# include <io.h>
|
||||||
# include <winsock2.h>
|
# include <windows.h>
|
||||||
|
|
||||||
|
#define snprintf _snprintf
|
||||||
|
|
||||||
typedef int ssize_t;
|
typedef int ssize_t;
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
# include <unistd.h>
|
# include <unistd.h>
|
||||||
# include <sys/mman.h>
|
|
||||||
# include <arpa/inet.h>
|
# include <arpa/inet.h>
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -106,18 +106,16 @@ void gitfo_free_buf(gitfo_buf *obj)
|
|||||||
obj->data = NULL;
|
obj->data = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int gitfo_map_ro(gitfo_map *out, git_file fd, off_t begin, size_t len)
|
int gitfo_map_ro(git_map *out, git_file fd, off_t begin, size_t len)
|
||||||
{
|
{
|
||||||
out->data = mmap(NULL, len, PROT_READ, MAP_SHARED, fd, begin);
|
if (git__mmap(out, len, GIT_PROT_READ, GIT_MAP_SHARED, fd, begin) < 0)
|
||||||
if (out->data == (void*)-1)
|
|
||||||
return git_os_error();
|
return git_os_error();
|
||||||
out->len = len;
|
|
||||||
return GIT_SUCCESS;
|
return GIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
void gitfo_free_map(gitfo_map *out)
|
void gitfo_free_map(git_map *out)
|
||||||
{
|
{
|
||||||
munmap(out->data, out->len);
|
git__munmap(out);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* cached diskio */
|
/* cached diskio */
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
#define _FILE_OFFSET_BITS 64
|
#define _FILE_OFFSET_BITS 64
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
#include "map.h"
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
@ -29,11 +30,6 @@ typedef struct { /* file io buffer */
|
|||||||
size_t len; /* data length */
|
size_t len; /* data length */
|
||||||
} gitfo_buf;
|
} gitfo_buf;
|
||||||
|
|
||||||
typedef struct { /* memory mapped buffer */
|
|
||||||
void *data; /* data bytes */
|
|
||||||
size_t len; /* data length */
|
|
||||||
} gitfo_map;
|
|
||||||
|
|
||||||
extern int gitfo_exists(const char *path);
|
extern int gitfo_exists(const char *path);
|
||||||
extern int gitfo_open(const char *path, int flags);
|
extern int gitfo_open(const char *path, int flags);
|
||||||
extern int gitfo_creat(const char *path, int mode);
|
extern int gitfo_creat(const char *path, int mode);
|
||||||
@ -66,7 +62,7 @@ extern void gitfo_free_buf(gitfo_buf *obj);
|
|||||||
* - GIT_EOSERR on an unspecified OS related error.
|
* - GIT_EOSERR on an unspecified OS related error.
|
||||||
*/
|
*/
|
||||||
extern int gitfo_map_ro(
|
extern int gitfo_map_ro(
|
||||||
gitfo_map *out,
|
git_map *out,
|
||||||
git_file fd,
|
git_file fd,
|
||||||
off_t begin,
|
off_t begin,
|
||||||
size_t len);
|
size_t len);
|
||||||
@ -75,7 +71,7 @@ extern int gitfo_map_ro(
|
|||||||
* Release the memory associated with a previous memory mapping.
|
* Release the memory associated with a previous memory mapping.
|
||||||
* @param map the mapping description previously configured.
|
* @param map the mapping description previously configured.
|
||||||
*/
|
*/
|
||||||
extern void gitfo_free_map(gitfo_map *map);
|
extern void gitfo_free_map(git_map *map);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Walk each directory entry, except '.' and '..', calling fn(state).
|
* Walk each directory entry, except '.' and '..', calling fn(state).
|
||||||
|
31
src/map.h
Normal file
31
src/map.h
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
#ifndef INCLUDE_map_h__
|
||||||
|
#define INCLUDE_map_h__
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* git__mmap() prot values */
|
||||||
|
#define GIT_PROT_NONE 0x0
|
||||||
|
#define GIT_PROT_READ 0x1
|
||||||
|
#define GIT_PROT_WRITE 0x2
|
||||||
|
#define GIT_PROT_EXEC 0x4
|
||||||
|
|
||||||
|
/* git__mmmap() flags values */
|
||||||
|
#define GIT_MAP_FILE 0
|
||||||
|
#define GIT_MAP_SHARED 1
|
||||||
|
#define GIT_MAP_PRIVATE 2
|
||||||
|
#define GIT_MAP_TYPE 0xf
|
||||||
|
#define GIT_MAP_FIXED 0x10
|
||||||
|
|
||||||
|
typedef struct { /* memory mapped buffer */
|
||||||
|
void *data; /* data bytes */
|
||||||
|
size_t len; /* data length */
|
||||||
|
#ifdef GIT_WIN32
|
||||||
|
HANDLE fmh; /* file mapping handle */
|
||||||
|
#endif
|
||||||
|
} git_map;
|
||||||
|
|
||||||
|
extern int git__mmap(git_map *out, size_t len, int prot, int flags, int fd, off_t offset);
|
||||||
|
extern int git__munmap(git_map *map);
|
||||||
|
|
||||||
|
#endif /* INCLUDE_map_h__ */
|
@ -43,7 +43,7 @@ struct git_pack {
|
|||||||
|
|
||||||
/** The .idx file, mapped into memory. */
|
/** The .idx file, mapped into memory. */
|
||||||
git_file idx_fd;
|
git_file idx_fd;
|
||||||
gitfo_map idx_map;
|
git_map idx_map;
|
||||||
uint32_t *im_fanout;
|
uint32_t *im_fanout;
|
||||||
unsigned char *im_oid;
|
unsigned char *im_oid;
|
||||||
uint32_t *im_crc;
|
uint32_t *im_crc;
|
||||||
|
61
src/unix/map.c
Normal file
61
src/unix/map.c
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
|
||||||
|
#include "map.h"
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
|
||||||
|
int git__mmap(git_map *out, size_t len, int prot, int flags, int fd, off_t offset)
|
||||||
|
{
|
||||||
|
int mprot = 0;
|
||||||
|
int mflag = 0;
|
||||||
|
|
||||||
|
assert((out != NULL) && (len > 0));
|
||||||
|
|
||||||
|
if ((out == NULL) || (len == 0)) {
|
||||||
|
errno = EINVAL;
|
||||||
|
return GIT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
out->data = NULL;
|
||||||
|
out->len = 0;
|
||||||
|
|
||||||
|
if (prot & GIT_PROT_WRITE)
|
||||||
|
mprot = PROT_WRITE;
|
||||||
|
else if (prot & GIT_PROT_READ)
|
||||||
|
mprot = PROT_READ;
|
||||||
|
else {
|
||||||
|
errno = EINVAL;
|
||||||
|
return GIT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((flags & GIT_MAP_TYPE) == GIT_MAP_SHARED)
|
||||||
|
mflag = MAP_SHARED;
|
||||||
|
else if ((flags & GIT_MAP_TYPE) == GIT_MAP_PRIVATE)
|
||||||
|
mflag = MAP_PRIVATE;
|
||||||
|
|
||||||
|
if (flags & GIT_MAP_FIXED) {
|
||||||
|
errno = EINVAL;
|
||||||
|
return GIT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
out->data = mmap(NULL, len, mprot, mflag, fd, offset);
|
||||||
|
if (!out->data || out->data == MAP_FAILED)
|
||||||
|
return git_os_error();
|
||||||
|
out->len = len;
|
||||||
|
|
||||||
|
return GIT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int git__munmap(git_map *map)
|
||||||
|
{
|
||||||
|
assert(map != NULL);
|
||||||
|
|
||||||
|
if (!map)
|
||||||
|
return GIT_ERROR;
|
||||||
|
|
||||||
|
munmap(map->data, map->len);
|
||||||
|
|
||||||
|
return GIT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
125
src/win32/map.c
Normal file
125
src/win32/map.c
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
|
||||||
|
#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 git__mmap(git_map *out, size_t len, int prot, int flags, int fd, 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;
|
||||||
|
off_t page_start;
|
||||||
|
off_t page_offset;
|
||||||
|
|
||||||
|
assert((out != NULL) && (len > 0));
|
||||||
|
|
||||||
|
if ((out == NULL) || (len == 0)) {
|
||||||
|
errno = EINVAL;
|
||||||
|
return GIT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
out->data = NULL;
|
||||||
|
out->len = 0;
|
||||||
|
out->fmh = NULL;
|
||||||
|
|
||||||
|
if (fh == INVALID_HANDLE_VALUE) {
|
||||||
|
errno = EBADF;
|
||||||
|
return GIT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prot & GIT_PROT_WRITE)
|
||||||
|
fmap_prot |= PAGE_READWRITE;
|
||||||
|
else if (prot & GIT_PROT_READ)
|
||||||
|
fmap_prot |= PAGE_READONLY;
|
||||||
|
else {
|
||||||
|
errno = EINVAL;
|
||||||
|
return GIT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
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_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
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_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
out->fmh = CreateFileMapping(fh, NULL, fmap_prot, 0, 0, NULL);
|
||||||
|
if (!out->fmh || out->fmh == INVALID_HANDLE_VALUE) {
|
||||||
|
/* errno = ? */
|
||||||
|
out->fmh = NULL;
|
||||||
|
return GIT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
off_low = (DWORD)(page_start);
|
||||||
|
if (sizeof(off_t) > 4)
|
||||||
|
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_ERROR;
|
||||||
|
}
|
||||||
|
out->len = len;
|
||||||
|
|
||||||
|
return GIT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int git__munmap(git_map *map)
|
||||||
|
{
|
||||||
|
assert(map != NULL);
|
||||||
|
|
||||||
|
if (!map)
|
||||||
|
return GIT_ERROR;
|
||||||
|
|
||||||
|
if (map->data) {
|
||||||
|
if (!UnmapViewOfFile(map->data)) {
|
||||||
|
/* errno = ? */
|
||||||
|
CloseHandle(map->fmh);
|
||||||
|
map->data = NULL;
|
||||||
|
map->fmh = NULL;
|
||||||
|
return GIT_ERROR;
|
||||||
|
}
|
||||||
|
map->data = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (map->fmh) {
|
||||||
|
if (!CloseHandle(map->fmh)) {
|
||||||
|
/* errno = ? */
|
||||||
|
map->fmh = NULL;
|
||||||
|
return GIT_ERROR;
|
||||||
|
}
|
||||||
|
map->fmh = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return GIT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user