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
|
||||
INSTALL = install
|
||||
RANLIB = ranlib
|
||||
AR = ar cr
|
||||
|
||||
prefix=/usr/local
|
||||
libdir=$(prefix)/lib
|
||||
@ -21,6 +22,8 @@ CFLAGS = -g -O2 -Wall
|
||||
LIBS = -L. -lgit2 -lz
|
||||
OS = unix
|
||||
|
||||
CRYPTO_LIB = -lcrypto
|
||||
|
||||
EXTRA_LIBS =
|
||||
EXTRA_SRC =
|
||||
EXTRA_OBJ =
|
||||
@ -32,6 +35,8 @@ ifneq (,$(findstring CYGWIN,$(uname_S)))
|
||||
endif
|
||||
|
||||
SRC_C = $(wildcard src/*.c)
|
||||
OS_SRC = $(wildcard src/$(OS)/*.c)
|
||||
SRC_C += $(OS_SRC)
|
||||
OBJS = $(patsubst %.c,%.o,$(SRC_C))
|
||||
HDRS = $(wildcard src/*.h)
|
||||
PUBLIC_HEADERS = $(wildcard src/git/*.h)
|
||||
@ -46,7 +51,7 @@ TEST_RUN = $(patsubst %.exe,%.run,$(TEST_EXE))
|
||||
|
||||
ifndef NO_OPENSSL
|
||||
SHA1_HEADER = <openssl/sha.h>
|
||||
EXTRA_LIBS += -lcrypto
|
||||
EXTRA_LIBS += $(CRYPTO_LIB)
|
||||
else
|
||||
SHA1_HEADER = "sha1/sha1.h"
|
||||
EXTRA_SRC += src/sha1/sha1.c
|
||||
@ -68,8 +73,7 @@ all:: $(GIT_LIB)
|
||||
clean:
|
||||
rm -f $(GIT_LIB)
|
||||
rm -f libgit2.pc
|
||||
rm -f src/*.o
|
||||
rm -f src/sha1/*.o
|
||||
rm -f src/*.o src/sha1/*.o src/unix/*.o
|
||||
rm -f tests/*.o tests/*.exe tests/*.toc
|
||||
rm -rf trash-*.exe
|
||||
rm -rf apidocs
|
||||
@ -111,7 +115,7 @@ uninstall:
|
||||
$(OBJS): $(HDRS)
|
||||
$(GIT_LIB): $(OBJS)
|
||||
rm -f $(GIT_LIB)
|
||||
$(AR) cr $(GIT_LIB) $(OBJS)
|
||||
$(AR) $(GIT_LIB) $(OBJS)
|
||||
$(RANLIB) $(GIT_LIB)
|
||||
|
||||
T_HDR = tests/test_lib.h tests/test_helpers.h
|
||||
|
@ -23,14 +23,15 @@
|
||||
#ifdef GIT_WIN32
|
||||
|
||||
# include <io.h>
|
||||
# include <winsock2.h>
|
||||
# include <windows.h>
|
||||
|
||||
#define snprintf _snprintf
|
||||
|
||||
typedef int ssize_t;
|
||||
|
||||
#else
|
||||
|
||||
# include <unistd.h>
|
||||
# include <sys/mman.h>
|
||||
# include <arpa/inet.h>
|
||||
|
||||
#endif
|
||||
|
@ -106,18 +106,16 @@ void gitfo_free_buf(gitfo_buf *obj)
|
||||
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 (out->data == (void*)-1)
|
||||
if (git__mmap(out, len, GIT_PROT_READ, GIT_MAP_SHARED, fd, begin) < 0)
|
||||
return git_os_error();
|
||||
out->len = len;
|
||||
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 */
|
||||
|
@ -10,6 +10,7 @@
|
||||
#define _FILE_OFFSET_BITS 64
|
||||
|
||||
#include "common.h"
|
||||
#include "map.h"
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <time.h>
|
||||
@ -29,11 +30,6 @@ typedef struct { /* file io buffer */
|
||||
size_t len; /* data length */
|
||||
} 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_open(const char *path, int flags);
|
||||
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.
|
||||
*/
|
||||
extern int gitfo_map_ro(
|
||||
gitfo_map *out,
|
||||
git_map *out,
|
||||
git_file fd,
|
||||
off_t begin,
|
||||
size_t len);
|
||||
@ -75,7 +71,7 @@ extern int gitfo_map_ro(
|
||||
* Release the memory associated with a previous memory mapping.
|
||||
* @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).
|
||||
|
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. */
|
||||
git_file idx_fd;
|
||||
gitfo_map idx_map;
|
||||
git_map idx_map;
|
||||
uint32_t *im_fanout;
|
||||
unsigned char *im_oid;
|
||||
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