index-pack usage of mmap() is unacceptably slower on many OSes other than Linux
[git/git.git] / git-compat-util.h
CommitLineData
4050c0df
JH
1#ifndef GIT_COMPAT_UTIL_H
2#define GIT_COMPAT_UTIL_H
3
8f1d2e6f
JH
4#ifndef FLEX_ARRAY
5#if defined(__GNUC__) && (__GNUC__ < 3)
6#define FLEX_ARRAY 0
7#else
8#define FLEX_ARRAY /* empty */
9#endif
10#endif
11
b4f2a6ac
JH
12#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
13
4050c0df
JH
14#include <unistd.h>
15#include <stdio.h>
16#include <sys/stat.h>
17#include <fcntl.h>
18#include <stddef.h>
19#include <stdlib.h>
20#include <stdarg.h>
21#include <string.h>
22#include <errno.h>
23#include <limits.h>
24#include <sys/param.h>
25#include <netinet/in.h>
26#include <sys/types.h>
27#include <dirent.h>
28
d0c2449f
JH
29/* On most systems <limits.h> would have given us this, but
30 * not on some systems (e.g. GNU/Hurd).
31 */
32#ifndef PATH_MAX
33#define PATH_MAX 4096
34#endif
35
4050c0df
JH
36#ifdef __GNUC__
37#define NORETURN __attribute__((__noreturn__))
38#else
39#define NORETURN
40#ifndef __attribute__
41#define __attribute__(x)
42#endif
43#endif
44
45/* General helper functions */
46extern void usage(const char *err) NORETURN;
47extern void die(const char *err, ...) NORETURN __attribute__((format (printf, 1, 2)));
48extern int error(const char *err, ...) __attribute__((format (printf, 1, 2)));
49
39a3f5ea
PB
50extern void set_usage_routine(void (*routine)(const char *err) NORETURN);
51extern void set_die_routine(void (*routine)(const char *err, va_list params) NORETURN);
52extern void set_error_routine(void (*routine)(const char *err, va_list params));
53
4050c0df
JH
54#ifdef NO_MMAP
55
56#ifndef PROT_READ
57#define PROT_READ 1
58#define PROT_WRITE 2
59#define MAP_PRIVATE 1
60#define MAP_FAILED ((void*)-1)
61#endif
62
63#define mmap gitfakemmap
64#define munmap gitfakemunmap
65extern void *gitfakemmap(void *start, size_t length, int prot , int flags, int fd, off_t offset);
66extern int gitfakemunmap(void *start, size_t length);
67
68#else /* NO_MMAP */
69
70#include <sys/mman.h>
71
72#endif /* NO_MMAP */
73
74#ifdef NO_SETENV
75#define setenv gitsetenv
76extern int gitsetenv(const char *, const char *, int);
77#endif
78
731043fd
JR
79#ifdef NO_UNSETENV
80#define unsetenv gitunsetenv
81extern void gitunsetenv(const char *);
82#endif
83
4050c0df
JH
84#ifdef NO_STRCASESTR
85#define strcasestr gitstrcasestr
86extern char *gitstrcasestr(const char *haystack, const char *needle);
87#endif
88
817151e6
PE
89#ifdef NO_STRLCPY
90#define strlcpy gitstrlcpy
91extern size_t gitstrlcpy(char *, const char *, size_t);
92#endif
93
9befac47
SP
94static inline char* xstrdup(const char *str)
95{
96 char *ret = strdup(str);
97 if (!ret)
98 die("Out of memory, strdup failed");
99 return ret;
100}
101
4050c0df
JH
102static inline void *xmalloc(size_t size)
103{
104 void *ret = malloc(size);
4e7a2ecc
JH
105 if (!ret && !size)
106 ret = malloc(1);
4050c0df
JH
107 if (!ret)
108 die("Out of memory, malloc failed");
aa5481c1
JH
109#ifdef XMALLOC_POISON
110 memset(ret, 0xA5, size);
111#endif
4050c0df
JH
112 return ret;
113}
114
115static inline void *xrealloc(void *ptr, size_t size)
116{
117 void *ret = realloc(ptr, size);
4e7a2ecc
JH
118 if (!ret && !size)
119 ret = realloc(ptr, 1);
4050c0df
JH
120 if (!ret)
121 die("Out of memory, realloc failed");
122 return ret;
123}
124
125static inline void *xcalloc(size_t nmemb, size_t size)
126{
127 void *ret = calloc(nmemb, size);
4e7a2ecc
JH
128 if (!ret && (!nmemb || !size))
129 ret = calloc(1, 1);
4050c0df
JH
130 if (!ret)
131 die("Out of memory, calloc failed");
132 return ret;
133}
134
1c15afb9
JH
135static inline ssize_t xread(int fd, void *buf, size_t len)
136{
137 ssize_t nr;
138 while (1) {
139 nr = read(fd, buf, len);
140 if ((nr < 0) && (errno == EAGAIN || errno == EINTR))
141 continue;
142 return nr;
143 }
144}
145
146static inline ssize_t xwrite(int fd, const void *buf, size_t len)
147{
148 ssize_t nr;
149 while (1) {
150 nr = write(fd, buf, len);
151 if ((nr < 0) && (errno == EAGAIN || errno == EINTR))
152 continue;
153 return nr;
154 }
155}
156
5bb1cda5 157static inline int has_extension(const char *filename, const char *ext)
83a2b841 158{
5bb1cda5
RS
159 size_t len = strlen(filename);
160 size_t extlen = strlen(ext);
83a2b841
RS
161 return len > extlen && !memcmp(filename + len - extlen, ext, extlen);
162}
163
4050c0df
JH
164/* Sane ctype - no locale, and works with signed chars */
165#undef isspace
166#undef isdigit
167#undef isalpha
168#undef isalnum
169#undef tolower
170#undef toupper
171extern unsigned char sane_ctype[256];
172#define GIT_SPACE 0x01
173#define GIT_DIGIT 0x02
174#define GIT_ALPHA 0x04
175#define sane_istest(x,mask) ((sane_ctype[(unsigned char)(x)] & (mask)) != 0)
176#define isspace(x) sane_istest(x,GIT_SPACE)
177#define isdigit(x) sane_istest(x,GIT_DIGIT)
178#define isalpha(x) sane_istest(x,GIT_ALPHA)
179#define isalnum(x) sane_istest(x,GIT_ALPHA | GIT_DIGIT)
180#define tolower(x) sane_case((unsigned char)(x), 0x20)
181#define toupper(x) sane_case((unsigned char)(x), 0)
182
183static inline int sane_case(int x, int high)
184{
185 if (sane_istest(x, GIT_ALPHA))
186 x = (x & ~0x20) | high;
187 return x;
188}
189
190#endif