Line | Count | Source |
1 | | /* |
2 | | * Various trivial helper wrappers around standard functions |
3 | | */ |
4 | | |
5 | | #define DISABLE_SIGN_COMPARE_WARNINGS |
6 | | |
7 | | #include "git-compat-util.h" |
8 | | #include "abspath.h" |
9 | | #include "parse.h" |
10 | | #include "gettext.h" |
11 | | #include "strbuf.h" |
12 | | #include "trace2.h" |
13 | | |
14 | | #ifdef HAVE_RTLGENRANDOM |
15 | | /* This is required to get access to RtlGenRandom. */ |
16 | | #define SystemFunction036 NTAPI SystemFunction036 |
17 | | #include <ntsecapi.h> |
18 | | #undef SystemFunction036 |
19 | | #endif |
20 | | |
21 | | static int memory_limit_check(size_t size, int gentle) |
22 | 26.3k | { |
23 | 26.3k | static size_t limit = 0; |
24 | 26.3k | if (!limit) { |
25 | 6 | limit = git_env_ulong("GIT_ALLOC_LIMIT", 0); |
26 | 6 | if (!limit) |
27 | 6 | limit = SIZE_MAX; |
28 | 6 | } |
29 | 26.3k | if (size > limit) { |
30 | 0 | if (gentle) { |
31 | 0 | error("attempting to allocate %"PRIuMAX" over limit %"PRIuMAX, |
32 | 0 | (uintmax_t)size, (uintmax_t)limit); |
33 | 0 | return -1; |
34 | 0 | } else |
35 | 0 | die("attempting to allocate %"PRIuMAX" over limit %"PRIuMAX, |
36 | 0 | (uintmax_t)size, (uintmax_t)limit); |
37 | 0 | } |
38 | 26.3k | return 0; |
39 | 26.3k | } |
40 | | |
41 | | char *xstrdup(const char *str) |
42 | 0 | { |
43 | 0 | char *ret = strdup(str); |
44 | 0 | if (!ret) |
45 | 0 | die("Out of memory, strdup failed"); |
46 | 0 | return ret; |
47 | 0 | } |
48 | | |
49 | | static void *do_xmalloc(size_t size, int gentle) |
50 | 2.26k | { |
51 | 2.26k | void *ret; |
52 | | |
53 | 2.26k | if (memory_limit_check(size, gentle)) |
54 | 0 | return NULL; |
55 | 2.26k | ret = malloc(size); |
56 | 2.26k | if (!ret && !size) |
57 | 0 | ret = malloc(1); |
58 | 2.26k | if (!ret) { |
59 | 0 | if (!gentle) |
60 | 0 | die("Out of memory, malloc failed (tried to allocate %lu bytes)", |
61 | 0 | (unsigned long)size); |
62 | 0 | else { |
63 | 0 | error("Out of memory, malloc failed (tried to allocate %lu bytes)", |
64 | 0 | (unsigned long)size); |
65 | 0 | return NULL; |
66 | 0 | } |
67 | 0 | } |
68 | | #ifdef XMALLOC_POISON |
69 | | memset(ret, 0xA5, size); |
70 | | #endif |
71 | 2.26k | return ret; |
72 | 2.26k | } |
73 | | |
74 | | void *xmalloc(size_t size) |
75 | 577 | { |
76 | 577 | return do_xmalloc(size, 0); |
77 | 577 | } |
78 | | |
79 | | static void *do_xmallocz(size_t size, int gentle) |
80 | 1.68k | { |
81 | 1.68k | void *ret; |
82 | 1.68k | if (unsigned_add_overflows(size, 1)) { |
83 | 0 | if (gentle) { |
84 | 0 | error("Data too large to fit into virtual memory space."); |
85 | 0 | return NULL; |
86 | 0 | } else |
87 | 0 | die("Data too large to fit into virtual memory space."); |
88 | 0 | } |
89 | 1.68k | ret = do_xmalloc(size + 1, gentle); |
90 | 1.68k | if (ret) |
91 | 1.68k | ((char*)ret)[size] = 0; |
92 | 1.68k | return ret; |
93 | 1.68k | } |
94 | | |
95 | | void *xmallocz(size_t size) |
96 | 1.68k | { |
97 | 1.68k | return do_xmallocz(size, 0); |
98 | 1.68k | } |
99 | | |
100 | | void *xmallocz_gently(size_t size) |
101 | 0 | { |
102 | 0 | return do_xmallocz(size, 1); |
103 | 0 | } |
104 | | |
105 | | /* |
106 | | * xmemdupz() allocates (len + 1) bytes of memory, duplicates "len" bytes of |
107 | | * "data" to the allocated memory, zero terminates the allocated memory, |
108 | | * and returns a pointer to the allocated memory. If the allocation fails, |
109 | | * the program dies. |
110 | | */ |
111 | | void *xmemdupz(const void *data, size_t len) |
112 | 1.68k | { |
113 | 1.68k | return memcpy(xmallocz(len), data, len); |
114 | 1.68k | } |
115 | | |
116 | | char *xstrndup(const char *str, size_t len) |
117 | 0 | { |
118 | 0 | char *p = memchr(str, '\0', len); |
119 | 0 | return xmemdupz(str, p ? p - str : len); |
120 | 0 | } |
121 | | |
122 | | int xstrncmpz(const char *s, const char *t, size_t len) |
123 | 0 | { |
124 | 0 | int res = strncmp(s, t, len); |
125 | 0 | if (res) |
126 | 0 | return res; |
127 | 0 | return s[len] == '\0' ? 0 : 1; |
128 | 0 | } |
129 | | |
130 | | void *xrealloc(void *ptr, size_t size) |
131 | 22.4k | { |
132 | 22.4k | void *ret; |
133 | | |
134 | 22.4k | if (!size) { |
135 | 0 | free(ptr); |
136 | 0 | return xmalloc(0); |
137 | 0 | } |
138 | | |
139 | 22.4k | memory_limit_check(size, 0); |
140 | 22.4k | ret = realloc(ptr, size); |
141 | 22.4k | if (!ret) |
142 | 0 | die("Out of memory, realloc failed"); |
143 | 22.4k | return ret; |
144 | 22.4k | } |
145 | | |
146 | | void *xcalloc(size_t nmemb, size_t size) |
147 | 1.69k | { |
148 | 1.69k | void *ret; |
149 | | |
150 | 1.69k | if (unsigned_mult_overflows(nmemb, size)) |
151 | 0 | die("data too large to fit into virtual memory space"); |
152 | | |
153 | 1.69k | memory_limit_check(size * nmemb, 0); |
154 | 1.69k | ret = calloc(nmemb, size); |
155 | 1.69k | if (!ret && (!nmemb || !size)) |
156 | 0 | ret = calloc(1, 1); |
157 | 1.69k | if (!ret) |
158 | 0 | die("Out of memory, calloc failed"); |
159 | 1.69k | return ret; |
160 | 1.69k | } |
161 | | |
162 | | void xsetenv(const char *name, const char *value, int overwrite) |
163 | 0 | { |
164 | 0 | if (setenv(name, value, overwrite)) |
165 | 0 | die_errno(_("could not setenv '%s'"), name ? name : "(null)"); |
166 | 0 | } |
167 | | |
168 | | /** |
169 | | * xopen() is the same as open(), but it die()s if the open() fails. |
170 | | */ |
171 | | int xopen(const char *path, int oflag, ...) |
172 | 0 | { |
173 | 0 | mode_t mode = 0; |
174 | 0 | va_list ap; |
175 | | |
176 | | /* |
177 | | * va_arg() will have undefined behavior if the specified type is not |
178 | | * compatible with the argument type. Since integers are promoted to |
179 | | * ints, we fetch the next argument as an int, and then cast it to a |
180 | | * mode_t to avoid undefined behavior. |
181 | | */ |
182 | 0 | va_start(ap, oflag); |
183 | 0 | if (oflag & O_CREAT) |
184 | 0 | mode = va_arg(ap, int); |
185 | 0 | va_end(ap); |
186 | |
|
187 | 0 | for (;;) { |
188 | 0 | int fd = open(path, oflag, mode); |
189 | 0 | if (fd >= 0) |
190 | 0 | return fd; |
191 | 0 | if (errno == EINTR) |
192 | 0 | continue; |
193 | | |
194 | 0 | if ((oflag & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)) |
195 | 0 | die_errno(_("unable to create '%s'"), path); |
196 | 0 | else if ((oflag & O_RDWR) == O_RDWR) |
197 | 0 | die_errno(_("could not open '%s' for reading and writing"), path); |
198 | 0 | else if ((oflag & O_WRONLY) == O_WRONLY) |
199 | 0 | die_errno(_("could not open '%s' for writing"), path); |
200 | 0 | else |
201 | 0 | die_errno(_("could not open '%s' for reading"), path); |
202 | 0 | } |
203 | 0 | } |
204 | | |
205 | | static int handle_nonblock(int fd, short poll_events, int err) |
206 | 0 | { |
207 | 0 | struct pollfd pfd; |
208 | |
|
209 | 0 | if (err != EAGAIN && err != EWOULDBLOCK) |
210 | 0 | return 0; |
211 | | |
212 | 0 | pfd.fd = fd; |
213 | 0 | pfd.events = poll_events; |
214 | | |
215 | | /* |
216 | | * no need to check for errors, here; |
217 | | * a subsequent read/write will detect unrecoverable errors |
218 | | */ |
219 | 0 | poll(&pfd, 1, -1); |
220 | 0 | return 1; |
221 | 0 | } |
222 | | |
223 | | /* |
224 | | * xread() is the same a read(), but it automatically restarts read() |
225 | | * operations with a recoverable error (EAGAIN and EINTR). xread() |
226 | | * DOES NOT GUARANTEE that "len" bytes is read even if the data is available. |
227 | | */ |
228 | | ssize_t xread(int fd, void *buf, size_t len) |
229 | 0 | { |
230 | 0 | ssize_t nr; |
231 | 0 | if (len > MAX_IO_SIZE) |
232 | 0 | len = MAX_IO_SIZE; |
233 | 0 | while (1) { |
234 | 0 | nr = read(fd, buf, len); |
235 | 0 | if (nr < 0) { |
236 | 0 | if (errno == EINTR) |
237 | 0 | continue; |
238 | 0 | if (handle_nonblock(fd, POLLIN, errno)) |
239 | 0 | continue; |
240 | 0 | } |
241 | 0 | return nr; |
242 | 0 | } |
243 | 0 | } |
244 | | |
245 | | /* |
246 | | * xwrite() is the same a write(), but it automatically restarts write() |
247 | | * operations with a recoverable error (EAGAIN and EINTR). xwrite() DOES NOT |
248 | | * GUARANTEE that "len" bytes is written even if the operation is successful. |
249 | | */ |
250 | | ssize_t xwrite(int fd, const void *buf, size_t len) |
251 | 531 | { |
252 | 531 | ssize_t nr; |
253 | 531 | if (len > MAX_IO_SIZE) |
254 | 0 | len = MAX_IO_SIZE; |
255 | 531 | while (1) { |
256 | 531 | nr = write(fd, buf, len); |
257 | 531 | if (nr < 0) { |
258 | 0 | if (errno == EINTR) |
259 | 0 | continue; |
260 | 0 | if (handle_nonblock(fd, POLLOUT, errno)) |
261 | 0 | continue; |
262 | 0 | } |
263 | | |
264 | 531 | return nr; |
265 | 531 | } |
266 | 531 | } |
267 | | |
268 | | /* |
269 | | * xpread() is the same as pread(), but it automatically restarts pread() |
270 | | * operations with a recoverable error (EAGAIN and EINTR). xpread() DOES |
271 | | * NOT GUARANTEE that "len" bytes is read even if the data is available. |
272 | | */ |
273 | | ssize_t xpread(int fd, void *buf, size_t len, off_t offset) |
274 | 0 | { |
275 | 0 | ssize_t nr; |
276 | 0 | if (len > MAX_IO_SIZE) |
277 | 0 | len = MAX_IO_SIZE; |
278 | 0 | while (1) { |
279 | 0 | nr = pread(fd, buf, len, offset); |
280 | 0 | if ((nr < 0) && (errno == EAGAIN || errno == EINTR)) |
281 | 0 | continue; |
282 | 0 | return nr; |
283 | 0 | } |
284 | 0 | } |
285 | | |
286 | | ssize_t read_in_full(int fd, void *buf, size_t count) |
287 | 0 | { |
288 | 0 | char *p = buf; |
289 | 0 | ssize_t total = 0; |
290 | |
|
291 | 0 | while (count > 0) { |
292 | 0 | ssize_t loaded = xread(fd, p, count); |
293 | 0 | if (loaded < 0) |
294 | 0 | return -1; |
295 | 0 | if (loaded == 0) |
296 | 0 | return total; |
297 | 0 | count -= loaded; |
298 | 0 | p += loaded; |
299 | 0 | total += loaded; |
300 | 0 | } |
301 | | |
302 | 0 | return total; |
303 | 0 | } |
304 | | |
305 | | ssize_t write_in_full(int fd, const void *buf, size_t count) |
306 | 531 | { |
307 | 531 | const char *p = buf; |
308 | 531 | ssize_t total = 0; |
309 | | |
310 | 1.06k | while (count > 0) { |
311 | 531 | ssize_t written = xwrite(fd, p, count); |
312 | 531 | if (written < 0) |
313 | 0 | return -1; |
314 | 531 | if (!written) { |
315 | 0 | errno = ENOSPC; |
316 | 0 | return -1; |
317 | 0 | } |
318 | 531 | count -= written; |
319 | 531 | p += written; |
320 | 531 | total += written; |
321 | 531 | } |
322 | | |
323 | 531 | return total; |
324 | 531 | } |
325 | | |
326 | | ssize_t pread_in_full(int fd, void *buf, size_t count, off_t offset) |
327 | 0 | { |
328 | 0 | char *p = buf; |
329 | 0 | ssize_t total = 0; |
330 | |
|
331 | 0 | while (count > 0) { |
332 | 0 | ssize_t loaded = xpread(fd, p, count, offset); |
333 | 0 | if (loaded < 0) |
334 | 0 | return -1; |
335 | 0 | if (loaded == 0) |
336 | 0 | return total; |
337 | 0 | count -= loaded; |
338 | 0 | p += loaded; |
339 | 0 | total += loaded; |
340 | 0 | offset += loaded; |
341 | 0 | } |
342 | | |
343 | 0 | return total; |
344 | 0 | } |
345 | | |
346 | | int xdup(int fd) |
347 | 0 | { |
348 | 0 | int ret = dup(fd); |
349 | 0 | if (ret < 0) |
350 | 0 | die_errno("dup failed"); |
351 | 0 | return ret; |
352 | 0 | } |
353 | | |
354 | | /** |
355 | | * xfopen() is the same as fopen(), but it die()s if the fopen() fails. |
356 | | */ |
357 | | FILE *xfopen(const char *path, const char *mode) |
358 | 0 | { |
359 | 0 | for (;;) { |
360 | 0 | FILE *fp = fopen(path, mode); |
361 | 0 | if (fp) |
362 | 0 | return fp; |
363 | 0 | if (errno == EINTR) |
364 | 0 | continue; |
365 | | |
366 | 0 | if (*mode && mode[1] == '+') |
367 | 0 | die_errno(_("could not open '%s' for reading and writing"), path); |
368 | 0 | else if (*mode == 'w' || *mode == 'a') |
369 | 0 | die_errno(_("could not open '%s' for writing"), path); |
370 | 0 | else |
371 | 0 | die_errno(_("could not open '%s' for reading"), path); |
372 | 0 | } |
373 | 0 | } |
374 | | |
375 | | FILE *xfdopen(int fd, const char *mode) |
376 | 0 | { |
377 | 0 | FILE *stream = fdopen(fd, mode); |
378 | 0 | if (!stream) |
379 | 0 | die_errno("Out of memory? fdopen failed"); |
380 | 0 | return stream; |
381 | 0 | } |
382 | | |
383 | | FILE *fopen_for_writing(const char *path) |
384 | 0 | { |
385 | 0 | FILE *ret = fopen(path, "w"); |
386 | |
|
387 | 0 | if (!ret && errno == EPERM) { |
388 | 0 | if (!unlink(path)) |
389 | 0 | ret = fopen(path, "w"); |
390 | 0 | else |
391 | 0 | errno = EPERM; |
392 | 0 | } |
393 | 0 | return ret; |
394 | 0 | } |
395 | | |
396 | | static void warn_on_inaccessible(const char *path) |
397 | 0 | { |
398 | 0 | warning_errno(_("unable to access '%s'"), path); |
399 | 0 | } |
400 | | |
401 | | int warn_on_fopen_errors(const char *path) |
402 | 0 | { |
403 | 0 | if (errno != ENOENT && errno != ENOTDIR) { |
404 | 0 | warn_on_inaccessible(path); |
405 | 0 | return -1; |
406 | 0 | } |
407 | | |
408 | 0 | return 0; |
409 | 0 | } |
410 | | |
411 | | FILE *fopen_or_warn(const char *path, const char *mode) |
412 | 0 | { |
413 | 0 | FILE *fp = fopen(path, mode); |
414 | |
|
415 | 0 | if (fp) |
416 | 0 | return fp; |
417 | | |
418 | 0 | warn_on_fopen_errors(path); |
419 | 0 | return NULL; |
420 | 0 | } |
421 | | |
422 | | int xmkstemp(char *filename_template) |
423 | 0 | { |
424 | 0 | return xmkstemp_mode(filename_template, 0600); |
425 | 0 | } |
426 | | |
427 | | /* Adapted from libiberty's mkstemp.c. */ |
428 | | |
429 | | #undef TMP_MAX |
430 | 0 | #define TMP_MAX 16384 |
431 | | |
432 | | /* |
433 | | * Returns -1 on error, 0 if it created a directory, or an open file |
434 | | * descriptor to the created regular file. |
435 | | */ |
436 | | static int git_mkdstemps_mode(char *pattern, int suffix_len, int mode, bool dir) |
437 | 0 | { |
438 | 0 | static const char letters[] = |
439 | 0 | "abcdefghijklmnopqrstuvwxyz" |
440 | 0 | "ABCDEFGHIJKLMNOPQRSTUVWXYZ" |
441 | 0 | "0123456789"; |
442 | 0 | static const int num_letters = ARRAY_SIZE(letters) - 1; |
443 | 0 | static const char x_pattern[] = "XXXXXX"; |
444 | 0 | static const int num_x = ARRAY_SIZE(x_pattern) - 1; |
445 | 0 | char *filename_template; |
446 | 0 | size_t len; |
447 | 0 | int fd, count; |
448 | |
|
449 | 0 | len = strlen(pattern); |
450 | |
|
451 | 0 | if (len < num_x + suffix_len) { |
452 | 0 | errno = EINVAL; |
453 | 0 | return -1; |
454 | 0 | } |
455 | | |
456 | 0 | if (strncmp(&pattern[len - num_x - suffix_len], x_pattern, num_x)) { |
457 | 0 | errno = EINVAL; |
458 | 0 | return -1; |
459 | 0 | } |
460 | | |
461 | | /* |
462 | | * Replace pattern's XXXXXX characters with randomness. |
463 | | * Try TMP_MAX different filenames. |
464 | | */ |
465 | 0 | filename_template = &pattern[len - num_x - suffix_len]; |
466 | 0 | for (count = 0; count < TMP_MAX; ++count) { |
467 | 0 | int i; |
468 | 0 | uint64_t v; |
469 | 0 | if (csprng_bytes(&v, sizeof(v), 0) < 0) |
470 | 0 | return error_errno("unable to get random bytes for temporary file"); |
471 | | |
472 | | /* Fill in the random bits. */ |
473 | 0 | for (i = 0; i < num_x; i++) { |
474 | 0 | filename_template[i] = letters[v % num_letters]; |
475 | 0 | v /= num_letters; |
476 | 0 | } |
477 | |
|
478 | 0 | if (dir) |
479 | 0 | fd = mkdir(pattern, mode); |
480 | 0 | else |
481 | 0 | fd = open(pattern, O_CREAT | O_EXCL | O_RDWR, mode); |
482 | 0 | if (fd >= 0) |
483 | 0 | return fd; |
484 | | /* |
485 | | * Fatal error (EPERM, ENOSPC etc). |
486 | | * It doesn't make sense to loop. |
487 | | */ |
488 | 0 | if (errno != EEXIST) |
489 | 0 | break; |
490 | 0 | } |
491 | | /* We return the null string if we can't find a unique file name. */ |
492 | 0 | pattern[0] = '\0'; |
493 | 0 | return -1; |
494 | 0 | } |
495 | | |
496 | | char *git_mkdtemp(char *pattern) |
497 | 0 | { |
498 | 0 | return git_mkdstemps_mode(pattern, 0, 0700, true) ? NULL : pattern; |
499 | 0 | } |
500 | | |
501 | | int git_mkstemps_mode(char *pattern, int suffix_len, int mode) |
502 | 0 | { |
503 | 0 | return git_mkdstemps_mode(pattern, suffix_len, mode, false); |
504 | 0 | } |
505 | | |
506 | | int git_mkstemp_mode(char *pattern, int mode) |
507 | 0 | { |
508 | | /* mkstemp is just mkstemps with no suffix */ |
509 | 0 | return git_mkstemps_mode(pattern, 0, mode); |
510 | 0 | } |
511 | | |
512 | | int xmkstemp_mode(char *filename_template, int mode) |
513 | 0 | { |
514 | 0 | int fd; |
515 | 0 | char origtemplate[PATH_MAX]; |
516 | 0 | strlcpy(origtemplate, filename_template, sizeof(origtemplate)); |
517 | |
|
518 | 0 | fd = git_mkstemp_mode(filename_template, mode); |
519 | 0 | if (fd < 0) { |
520 | 0 | int saved_errno = errno; |
521 | 0 | const char *nonrelative_template; |
522 | |
|
523 | 0 | if (!filename_template[0]) |
524 | 0 | filename_template = origtemplate; |
525 | |
|
526 | 0 | nonrelative_template = absolute_path(filename_template); |
527 | 0 | errno = saved_errno; |
528 | 0 | die_errno("Unable to create temporary file '%s'", |
529 | 0 | nonrelative_template); |
530 | 0 | } |
531 | 0 | return fd; |
532 | 0 | } |
533 | | |
534 | | /* |
535 | | * Some platforms return EINTR from fsync. Since fsync is invoked in some |
536 | | * cases by a wrapper that dies on failure, do not expose EINTR to callers. |
537 | | */ |
538 | | static int fsync_loop(int fd) |
539 | 0 | { |
540 | 0 | int err; |
541 | |
|
542 | 0 | do { |
543 | 0 | err = fsync(fd); |
544 | 0 | } while (err < 0 && errno == EINTR); |
545 | 0 | return err; |
546 | 0 | } |
547 | | |
548 | | int git_fsync(int fd, enum fsync_action action) |
549 | 0 | { |
550 | 0 | switch (action) { |
551 | 0 | case FSYNC_WRITEOUT_ONLY: |
552 | 0 | trace2_counter_add(TRACE2_COUNTER_ID_FSYNC_WRITEOUT_ONLY, 1); |
553 | |
|
554 | | #ifdef __APPLE__ |
555 | | /* |
556 | | * On macOS, fsync just causes filesystem cache writeback but |
557 | | * does not flush hardware caches. |
558 | | */ |
559 | | return fsync_loop(fd); |
560 | | #endif |
561 | |
|
562 | 0 | #ifdef HAVE_SYNC_FILE_RANGE |
563 | | /* |
564 | | * On linux 2.6.17 and above, sync_file_range is the way to |
565 | | * issue a writeback without a hardware flush. An offset of |
566 | | * 0 and size of 0 indicates writeout of the entire file and the |
567 | | * wait flags ensure that all dirty data is written to the disk |
568 | | * (potentially in a disk-side cache) before we continue. |
569 | | */ |
570 | |
|
571 | 0 | return sync_file_range(fd, 0, 0, SYNC_FILE_RANGE_WAIT_BEFORE | |
572 | 0 | SYNC_FILE_RANGE_WRITE | |
573 | 0 | SYNC_FILE_RANGE_WAIT_AFTER); |
574 | 0 | #endif |
575 | | |
576 | | #ifdef fsync_no_flush |
577 | | return fsync_no_flush(fd); |
578 | | #endif |
579 | | |
580 | 0 | errno = ENOSYS; |
581 | 0 | return -1; |
582 | | |
583 | 0 | case FSYNC_HARDWARE_FLUSH: |
584 | 0 | trace2_counter_add(TRACE2_COUNTER_ID_FSYNC_HARDWARE_FLUSH, 1); |
585 | | |
586 | | /* |
587 | | * On macOS, a special fcntl is required to really flush the |
588 | | * caches within the storage controller. As of this writing, |
589 | | * this is a very expensive operation on Apple SSDs. |
590 | | */ |
591 | | #ifdef __APPLE__ |
592 | | return fcntl(fd, F_FULLFSYNC); |
593 | | #else |
594 | 0 | return fsync_loop(fd); |
595 | 0 | #endif |
596 | 0 | default: |
597 | 0 | BUG("unexpected git_fsync(%d) call", action); |
598 | 0 | } |
599 | 0 | } |
600 | | |
601 | | static int warn_if_unremovable(const char *op, const char *file, int rc) |
602 | 0 | { |
603 | 0 | int err; |
604 | 0 | if (!rc || errno == ENOENT) |
605 | 0 | return 0; |
606 | 0 | err = errno; |
607 | 0 | warning_errno("unable to %s '%s'", op, file); |
608 | 0 | errno = err; |
609 | 0 | return rc; |
610 | 0 | } |
611 | | |
612 | | int unlink_or_msg(const char *file, struct strbuf *err) |
613 | 0 | { |
614 | 0 | int rc = unlink(file); |
615 | |
|
616 | 0 | assert(err); |
617 | |
|
618 | 0 | if (!rc || errno == ENOENT) |
619 | 0 | return 0; |
620 | | |
621 | 0 | strbuf_addf(err, "unable to unlink '%s': %s", |
622 | 0 | file, strerror(errno)); |
623 | 0 | return -1; |
624 | 0 | } |
625 | | |
626 | | int unlink_or_warn(const char *file) |
627 | 0 | { |
628 | 0 | return warn_if_unremovable("unlink", file, unlink(file)); |
629 | 0 | } |
630 | | |
631 | | int rmdir_or_warn(const char *file) |
632 | 0 | { |
633 | 0 | return warn_if_unremovable("rmdir", file, rmdir(file)); |
634 | 0 | } |
635 | | |
636 | | static int access_error_is_ok(int err, unsigned flag) |
637 | 0 | { |
638 | 0 | return (is_missing_file_error(err) || |
639 | 0 | ((flag & ACCESS_EACCES_OK) && err == EACCES)); |
640 | 0 | } |
641 | | |
642 | | int access_or_warn(const char *path, int mode, unsigned flag) |
643 | 0 | { |
644 | 0 | int ret = access(path, mode); |
645 | 0 | if (ret && !access_error_is_ok(errno, flag)) |
646 | 0 | warn_on_inaccessible(path); |
647 | 0 | return ret; |
648 | 0 | } |
649 | | |
650 | | int access_or_die(const char *path, int mode, unsigned flag) |
651 | 0 | { |
652 | 0 | int ret = access(path, mode); |
653 | 0 | if (ret && !access_error_is_ok(errno, flag)) |
654 | 0 | die_errno(_("unable to access '%s'"), path); |
655 | 0 | return ret; |
656 | 0 | } |
657 | | |
658 | | char *xgetcwd(void) |
659 | 0 | { |
660 | 0 | struct strbuf sb = STRBUF_INIT; |
661 | 0 | if (strbuf_getcwd(&sb)) |
662 | 0 | die_errno(_("unable to get current working directory")); |
663 | 0 | return strbuf_detach(&sb, NULL); |
664 | 0 | } |
665 | | |
666 | | int xsnprintf(char *dst, size_t max, const char *fmt, ...) |
667 | 0 | { |
668 | 0 | va_list ap; |
669 | 0 | int len; |
670 | |
|
671 | 0 | va_start(ap, fmt); |
672 | 0 | len = vsnprintf(dst, max, fmt, ap); |
673 | 0 | va_end(ap); |
674 | |
|
675 | 0 | if (len < 0) |
676 | 0 | die(_("unable to format message: %s"), fmt); |
677 | 0 | if (len >= max) |
678 | 0 | BUG("attempt to snprintf into too-small buffer"); |
679 | 0 | return len; |
680 | 0 | } |
681 | | |
682 | | void write_file_buf(const char *path, const char *buf, size_t len) |
683 | 0 | { |
684 | 0 | int fd = xopen(path, O_WRONLY | O_CREAT | O_TRUNC, 0666); |
685 | 0 | if (write_in_full(fd, buf, len) < 0) |
686 | 0 | die_errno(_("could not write to '%s'"), path); |
687 | 0 | if (close(fd)) |
688 | 0 | die_errno(_("could not close '%s'"), path); |
689 | 0 | } |
690 | | |
691 | | void write_file(const char *path, const char *fmt, ...) |
692 | 0 | { |
693 | 0 | va_list params; |
694 | 0 | struct strbuf sb = STRBUF_INIT; |
695 | |
|
696 | 0 | va_start(params, fmt); |
697 | 0 | strbuf_vaddf(&sb, fmt, params); |
698 | 0 | va_end(params); |
699 | |
|
700 | 0 | strbuf_complete_line(&sb); |
701 | |
|
702 | 0 | write_file_buf(path, sb.buf, sb.len); |
703 | 0 | strbuf_release(&sb); |
704 | 0 | } |
705 | | |
706 | | void sleep_millisec(int millisec) |
707 | 0 | { |
708 | 0 | poll(NULL, 0, millisec); |
709 | 0 | } |
710 | | |
711 | | int xgethostname(char *buf, size_t len) |
712 | 0 | { |
713 | | /* |
714 | | * If the full hostname doesn't fit in buf, POSIX does not |
715 | | * specify whether the buffer will be null-terminated, so to |
716 | | * be safe, do it ourselves. |
717 | | */ |
718 | 0 | int ret = gethostname(buf, len); |
719 | 0 | if (!ret) |
720 | 0 | buf[len - 1] = 0; |
721 | 0 | return ret; |
722 | 0 | } |
723 | | |
724 | | int is_missing_file(const char *filename) |
725 | 0 | { |
726 | 0 | struct stat st; |
727 | |
|
728 | 0 | if (stat(filename, &st) < 0) { |
729 | 0 | if (errno == ENOENT) |
730 | 0 | return 1; |
731 | 0 | die_errno(_("could not stat %s"), filename); |
732 | 0 | } |
733 | | |
734 | 0 | return 0; |
735 | 0 | } |
736 | | |
737 | | int is_empty_or_missing_file(const char *filename) |
738 | 0 | { |
739 | 0 | struct stat st; |
740 | |
|
741 | 0 | if (stat(filename, &st) < 0) { |
742 | 0 | if (errno == ENOENT) |
743 | 0 | return 1; |
744 | 0 | die_errno(_("could not stat %s"), filename); |
745 | 0 | } |
746 | | |
747 | 0 | return !st.st_size; |
748 | 0 | } |
749 | | |
750 | | int open_nofollow(const char *path, int flags) |
751 | 0 | { |
752 | 0 | #ifdef O_NOFOLLOW |
753 | 0 | int ret = open(path, flags | O_NOFOLLOW); |
754 | | /* |
755 | | * NetBSD sets errno to EFTYPE when path is a symlink. The only other |
756 | | * time this errno occurs when O_REGULAR is used. Since we don't use |
757 | | * it anywhere we can avoid an lstat here. FreeBSD does the same with |
758 | | * EMLINK. |
759 | | */ |
760 | | # ifdef __NetBSD__ |
761 | | # define SYMLINK_ERRNO EFTYPE |
762 | | # elif defined(__FreeBSD__) |
763 | | # define SYMLINK_ERRNO EMLINK |
764 | | # endif |
765 | | # if SYMLINK_ERRNO |
766 | | if (ret < 0 && errno == SYMLINK_ERRNO) { |
767 | | errno = ELOOP; |
768 | | return -1; |
769 | | } |
770 | | # undef SYMLINK_ERRNO |
771 | | # endif |
772 | 0 | return ret; |
773 | | #else |
774 | | struct stat st; |
775 | | if (lstat(path, &st) < 0) |
776 | | return -1; |
777 | | if (S_ISLNK(st.st_mode)) { |
778 | | errno = ELOOP; |
779 | | return -1; |
780 | | } |
781 | | return open(path, flags); |
782 | | #endif |
783 | 0 | } |
784 | | |
785 | | int csprng_bytes(void *buf, size_t len, MAYBE_UNUSED unsigned flags) |
786 | 0 | { |
787 | | #if defined(HAVE_ARC4RANDOM) || defined(HAVE_ARC4RANDOM_LIBBSD) |
788 | | /* This function never returns an error. */ |
789 | | arc4random_buf(buf, len); |
790 | | return 0; |
791 | | #elif defined(HAVE_GETRANDOM) |
792 | | ssize_t res; |
793 | 0 | char *p = buf; |
794 | 0 | while (len) { |
795 | 0 | res = getrandom(p, len, 0); |
796 | 0 | if (res < 0) |
797 | 0 | return -1; |
798 | 0 | len -= res; |
799 | 0 | p += res; |
800 | 0 | } |
801 | 0 | return 0; |
802 | | #elif defined(HAVE_GETENTROPY) |
803 | | int res; |
804 | | char *p = buf; |
805 | | while (len) { |
806 | | /* getentropy has a maximum size of 256 bytes. */ |
807 | | size_t chunk = len < 256 ? len : 256; |
808 | | res = getentropy(p, chunk); |
809 | | if (res < 0) |
810 | | return -1; |
811 | | len -= chunk; |
812 | | p += chunk; |
813 | | } |
814 | | return 0; |
815 | | #elif defined(HAVE_RTLGENRANDOM) |
816 | | if (!RtlGenRandom(buf, len)) |
817 | | return -1; |
818 | | return 0; |
819 | | #elif defined(HAVE_OPENSSL_CSPRNG) |
820 | | switch (RAND_pseudo_bytes(buf, len)) { |
821 | | case 1: |
822 | | return 0; |
823 | | case 0: |
824 | | if (flags & CSPRNG_BYTES_INSECURE) |
825 | | return 0; |
826 | | errno = EIO; |
827 | | return -1; |
828 | | default: |
829 | | errno = ENOTSUP; |
830 | | return -1; |
831 | | } |
832 | | #else |
833 | | ssize_t res; |
834 | | char *p = buf; |
835 | | int fd, err; |
836 | | fd = open("/dev/urandom", O_RDONLY); |
837 | | if (fd < 0) |
838 | | return -1; |
839 | | while (len) { |
840 | | res = xread(fd, p, len); |
841 | | if (res < 0) { |
842 | | err = errno; |
843 | | close(fd); |
844 | | errno = err; |
845 | | return -1; |
846 | | } |
847 | | len -= res; |
848 | | p += res; |
849 | | } |
850 | | close(fd); |
851 | | return 0; |
852 | | #endif |
853 | 0 | } |
854 | | |
855 | | uint32_t git_rand(unsigned flags) |
856 | 0 | { |
857 | 0 | uint32_t result; |
858 | |
|
859 | 0 | if (csprng_bytes(&result, sizeof(result), flags) < 0) |
860 | 0 | die(_("unable to get random bytes")); |
861 | | |
862 | 0 | return result; |
863 | 0 | } |
864 | | |
865 | | static void mmap_limit_check(size_t length) |
866 | 0 | { |
867 | 0 | static size_t limit = 0; |
868 | 0 | if (!limit) { |
869 | 0 | limit = git_env_ulong("GIT_MMAP_LIMIT", 0); |
870 | 0 | if (!limit) |
871 | 0 | limit = SIZE_MAX; |
872 | 0 | } |
873 | 0 | if (length > limit) |
874 | 0 | die(_("attempting to mmap %"PRIuMAX" over limit %"PRIuMAX), |
875 | 0 | (uintmax_t)length, (uintmax_t)limit); |
876 | 0 | } |
877 | | |
878 | | void *xmmap_gently(void *start, size_t length, |
879 | | int prot, int flags, int fd, off_t offset) |
880 | 0 | { |
881 | 0 | void *ret; |
882 | |
|
883 | 0 | mmap_limit_check(length); |
884 | 0 | ret = mmap(start, length, prot, flags, fd, offset); |
885 | 0 | if (ret == MAP_FAILED && !length) |
886 | 0 | ret = NULL; |
887 | 0 | return ret; |
888 | 0 | } |
889 | | |
890 | | const char *mmap_os_err(void) |
891 | 0 | { |
892 | 0 | static const char blank[] = ""; |
893 | 0 | #if defined(__linux__) |
894 | 0 | if (errno == ENOMEM) { |
895 | | /* this continues an existing error message: */ |
896 | 0 | static const char enomem[] = |
897 | 0 | ", check sys.vm.max_map_count and/or RLIMIT_DATA"; |
898 | 0 | return enomem; |
899 | 0 | } |
900 | 0 | #endif /* OS-specific bits */ |
901 | 0 | return blank; |
902 | 0 | } |
903 | | |
904 | | void *xmmap(void *start, size_t length, |
905 | | int prot, int flags, int fd, off_t offset) |
906 | 0 | { |
907 | 0 | void *ret = xmmap_gently(start, length, prot, flags, fd, offset); |
908 | 0 | if (ret == MAP_FAILED) |
909 | 0 | die_errno(_("mmap failed%s"), mmap_os_err()); |
910 | 0 | return ret; |
911 | 0 | } |