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