Merge branch 'bw/diff-metainfo-color' into maint
[git] / wrapper.c
1 /*
2  * Various trivial helper wrappers around standard functions
3  */
4 #include "cache.h"
5
6 static void try_to_free_builtin(size_t size)
7 {
8         release_pack_memory(size, -1);
9 }
10
11 static void (*try_to_free_routine)(size_t size) = try_to_free_builtin;
12
13 void set_try_to_free_routine(void (*routine)(size_t))
14 {
15         try_to_free_routine = (routine) ? routine : try_to_free_builtin;
16 }
17
18 char *xstrdup(const char *str)
19 {
20         char *ret = strdup(str);
21         if (!ret) {
22                 try_to_free_routine(strlen(str) + 1);
23                 ret = strdup(str);
24                 if (!ret)
25                         die("Out of memory, strdup failed");
26         }
27         return ret;
28 }
29
30 void *xmalloc(size_t size)
31 {
32         void *ret = malloc(size);
33         if (!ret && !size)
34                 ret = malloc(1);
35         if (!ret) {
36                 try_to_free_routine(size);
37                 ret = malloc(size);
38                 if (!ret && !size)
39                         ret = malloc(1);
40                 if (!ret)
41                         die("Out of memory, malloc failed");
42         }
43 #ifdef XMALLOC_POISON
44         memset(ret, 0xA5, size);
45 #endif
46         return ret;
47 }
48
49 void *xmallocz(size_t size)
50 {
51         void *ret;
52         if (size + 1 < size)
53                 die("Data too large to fit into virtual memory space.");
54         ret = xmalloc(size + 1);
55         ((char*)ret)[size] = 0;
56         return ret;
57 }
58
59 /*
60  * xmemdupz() allocates (len + 1) bytes of memory, duplicates "len" bytes of
61  * "data" to the allocated memory, zero terminates the allocated memory,
62  * and returns a pointer to the allocated memory. If the allocation fails,
63  * the program dies.
64  */
65 void *xmemdupz(const void *data, size_t len)
66 {
67         return memcpy(xmallocz(len), data, len);
68 }
69
70 char *xstrndup(const char *str, size_t len)
71 {
72         char *p = memchr(str, '\0', len);
73         return xmemdupz(str, p ? p - str : len);
74 }
75
76 void *xrealloc(void *ptr, size_t size)
77 {
78         void *ret = realloc(ptr, size);
79         if (!ret && !size)
80                 ret = realloc(ptr, 1);
81         if (!ret) {
82                 try_to_free_routine(size);
83                 ret = realloc(ptr, size);
84                 if (!ret && !size)
85                         ret = realloc(ptr, 1);
86                 if (!ret)
87                         die("Out of memory, realloc failed");
88         }
89         return ret;
90 }
91
92 void *xcalloc(size_t nmemb, size_t size)
93 {
94         void *ret = calloc(nmemb, size);
95         if (!ret && (!nmemb || !size))
96                 ret = calloc(1, 1);
97         if (!ret) {
98                 try_to_free_routine(nmemb * size);
99                 ret = calloc(nmemb, size);
100                 if (!ret && (!nmemb || !size))
101                         ret = calloc(1, 1);
102                 if (!ret)
103                         die("Out of memory, calloc failed");
104         }
105         return ret;
106 }
107
108 void *xmmap(void *start, size_t length,
109         int prot, int flags, int fd, off_t offset)
110 {
111         void *ret = mmap(start, length, prot, flags, fd, offset);
112         if (ret == MAP_FAILED) {
113                 if (!length)
114                         return NULL;
115                 release_pack_memory(length, fd);
116                 ret = mmap(start, length, prot, flags, fd, offset);
117                 if (ret == MAP_FAILED)
118                         die_errno("Out of memory? mmap failed");
119         }
120         return ret;
121 }
122
123 /*
124  * xread() is the same a read(), but it automatically restarts read()
125  * operations with a recoverable error (EAGAIN and EINTR). xread()
126  * DOES NOT GUARANTEE that "len" bytes is read even if the data is available.
127  */
128 ssize_t xread(int fd, void *buf, size_t len)
129 {
130         ssize_t nr;
131         while (1) {
132                 nr = read(fd, buf, len);
133                 if ((nr < 0) && (errno == EAGAIN || errno == EINTR))
134                         continue;
135                 return nr;
136         }
137 }
138
139 /*
140  * xwrite() is the same a write(), but it automatically restarts write()
141  * operations with a recoverable error (EAGAIN and EINTR). xwrite() DOES NOT
142  * GUARANTEE that "len" bytes is written even if the operation is successful.
143  */
144 ssize_t xwrite(int fd, const void *buf, size_t len)
145 {
146         ssize_t nr;
147         while (1) {
148                 nr = write(fd, buf, len);
149                 if ((nr < 0) && (errno == EAGAIN || errno == EINTR))
150                         continue;
151                 return nr;
152         }
153 }
154
155 ssize_t read_in_full(int fd, void *buf, size_t count)
156 {
157         char *p = buf;
158         ssize_t total = 0;
159
160         while (count > 0) {
161                 ssize_t loaded = xread(fd, p, count);
162                 if (loaded <= 0)
163                         return total ? total : loaded;
164                 count -= loaded;
165                 p += loaded;
166                 total += loaded;
167         }
168
169         return total;
170 }
171
172 ssize_t write_in_full(int fd, const void *buf, size_t count)
173 {
174         const char *p = buf;
175         ssize_t total = 0;
176
177         while (count > 0) {
178                 ssize_t written = xwrite(fd, p, count);
179                 if (written < 0)
180                         return -1;
181                 if (!written) {
182                         errno = ENOSPC;
183                         return -1;
184                 }
185                 count -= written;
186                 p += written;
187                 total += written;
188         }
189
190         return total;
191 }
192
193 int xdup(int fd)
194 {
195         int ret = dup(fd);
196         if (ret < 0)
197                 die_errno("dup failed");
198         return ret;
199 }
200
201 FILE *xfdopen(int fd, const char *mode)
202 {
203         FILE *stream = fdopen(fd, mode);
204         if (stream == NULL)
205                 die_errno("Out of memory? fdopen failed");
206         return stream;
207 }
208
209 int xmkstemp(char *template)
210 {
211         int fd;
212
213         fd = mkstemp(template);
214         if (fd < 0)
215                 die_errno("Unable to create temporary file");
216         return fd;
217 }
218
219 int xmkstemp_mode(char *template, int mode)
220 {
221         int fd;
222
223         fd = git_mkstemp_mode(template, mode);
224         if (fd < 0)
225                 die_errno("Unable to create temporary file");
226         return fd;
227 }
228
229 /*
230  * zlib wrappers to make sure we don't silently miss errors
231  * at init time.
232  */
233 void git_inflate_init(z_streamp strm)
234 {
235         const char *err;
236
237         switch (inflateInit(strm)) {
238         case Z_OK:
239                 return;
240
241         case Z_MEM_ERROR:
242                 err = "out of memory";
243                 break;
244         case Z_VERSION_ERROR:
245                 err = "wrong version";
246                 break;
247         default:
248                 err = "error";
249         }
250         die("inflateInit: %s (%s)", err, strm->msg ? strm->msg : "no message");
251 }
252
253 void git_inflate_end(z_streamp strm)
254 {
255         if (inflateEnd(strm) != Z_OK)
256                 error("inflateEnd: %s", strm->msg ? strm->msg : "failed");
257 }
258
259 int git_inflate(z_streamp strm, int flush)
260 {
261         int ret = inflate(strm, flush);
262         const char *err;
263
264         switch (ret) {
265         /* Out of memory is fatal. */
266         case Z_MEM_ERROR:
267                 die("inflate: out of memory");
268
269         /* Data corruption errors: we may want to recover from them (fsck) */
270         case Z_NEED_DICT:
271                 err = "needs dictionary"; break;
272         case Z_DATA_ERROR:
273                 err = "data stream error"; break;
274         case Z_STREAM_ERROR:
275                 err = "stream consistency error"; break;
276         default:
277                 err = "unknown error"; break;
278
279         /* Z_BUF_ERROR: normal, needs more space in the output buffer */
280         case Z_BUF_ERROR:
281         case Z_OK:
282         case Z_STREAM_END:
283                 return ret;
284         }
285         error("inflate: %s (%s)", err, strm->msg ? strm->msg : "no message");
286         return ret;
287 }
288
289 int odb_mkstemp(char *template, size_t limit, const char *pattern)
290 {
291         int fd;
292         /*
293          * we let the umask do its job, don't try to be more
294          * restrictive except to remove write permission.
295          */
296         int mode = 0444;
297         snprintf(template, limit, "%s/%s",
298                  get_object_directory(), pattern);
299         fd = git_mkstemp_mode(template, mode);
300         if (0 <= fd)
301                 return fd;
302
303         /* slow path */
304         /* some mkstemp implementations erase template on failure */
305         snprintf(template, limit, "%s/%s",
306                  get_object_directory(), pattern);
307         safe_create_leading_directories(template);
308         return xmkstemp_mode(template, mode);
309 }
310
311 int odb_pack_keep(char *name, size_t namesz, unsigned char *sha1)
312 {
313         int fd;
314
315         snprintf(name, namesz, "%s/pack/pack-%s.keep",
316                  get_object_directory(), sha1_to_hex(sha1));
317         fd = open(name, O_RDWR|O_CREAT|O_EXCL, 0600);
318         if (0 <= fd)
319                 return fd;
320
321         /* slow path */
322         safe_create_leading_directories(name);
323         return open(name, O_RDWR|O_CREAT|O_EXCL, 0600);
324 }
325
326 int unlink_or_warn(const char *file)
327 {
328         int rc = unlink(file);
329
330         if (rc < 0) {
331                 int err = errno;
332                 if (ENOENT != err) {
333                         warning("unable to unlink %s: %s",
334                                 file, strerror(errno));
335                         errno = err;
336                 }
337         }
338         return rc;
339 }
340