1#ifndef GIT_COMPAT_UTIL_H
2#define GIT_COMPAT_UTIL_H
3
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
12#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
13
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
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
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
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
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
79#ifdef NO_UNSETENV
80#define unsetenv gitunsetenv
81extern void gitunsetenv(const char *);
82#endif
83
84#ifdef NO_STRCASESTR
85#define strcasestr gitstrcasestr
86extern char *gitstrcasestr(const char *haystack, const char *needle);
87#endif
88
89#ifdef NO_STRLCPY
90#define strlcpy gitstrlcpy
91extern size_t gitstrlcpy(char *, const char *, size_t);
92#endif
93
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
102static inline void *xmalloc(size_t size)
103{
104 void *ret = malloc(size);
105 if (!ret && !size)
106 ret = malloc(1);
107 if (!ret)
108 die("Out of memory, malloc failed");
109#ifdef XMALLOC_POISON
110 memset(ret, 0xA5, size);
111#endif
112 return ret;
113}
114
115static inline void *xrealloc(void *ptr, size_t size)
116{
117 void *ret = realloc(ptr, size);
118 if (!ret && !size)
119 ret = realloc(ptr, 1);
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);
128 if (!ret && (!nmemb || !size))
129 ret = calloc(1, 1);
130 if (!ret)
131 die("Out of memory, calloc failed");
132 return ret;
133}
134
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
157static inline int has_extension(const char *filename, const char *ext)
158{
159 size_t len = strlen(filename);
160 size_t extlen = strlen(ext);
161 return len > extlen && !memcmp(filename + len - extlen, ext, extlen);
162}
163
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