Skip to content
Navigation Menu
Toggle navigation
Sign in
In this repository
All GitHub Enterprise
↵
Jump to
↵
No suggested jump to results
In this repository
All GitHub Enterprise
↵
Jump to
↵
In this organization
All GitHub Enterprise
↵
Jump to
↵
In this repository
All GitHub Enterprise
↵
Jump to
↵
Sign in
Reseting focus
You signed in with another tab or window.
Reload
to refresh your session.
You signed out in another tab or window.
Reload
to refresh your session.
You switched accounts on another tab or window.
Reload
to refresh your session.
Dismiss alert
{{ message }}
git-mirror
/
git
Public
Notifications
You must be signed in to change notification settings
Fork
0
Star
0
Code
Issues
0
Pull requests
0
Actions
Projects
0
Security
Insights
Additional navigation options
Code
Issues
Pull requests
Actions
Projects
Security
Insights
Files
9a8c2b6
Documentation
block-sha1
builtin
compat
contrib
ewah
git-gui
gitk-git
gitweb
mergetools
perl
po
ppc
t
templates
vcs-svn
xdiff
.gitattributes
.gitignore
.mailmap
COPYING
GIT-VERSION-GEN
INSTALL
LGPL-2.1
Makefile
README
RelNotes
abspath.c
aclocal.m4
advice.c
advice.h
alias.c
alloc.c
archive-tar.c
archive-zip.c
archive.c
archive.h
argv-array.c
argv-array.h
attr.c
attr.h
base85.c
bisect.c
bisect.h
blob.c
blob.h
branch.c
branch.h
builtin.h
bulk-checkin.c
bulk-checkin.h
bundle.c
bundle.h
cache-tree.c
cache-tree.h
cache.h
check-builtins.sh
check-racy.c
check_bindir
color.c
color.h
column.c
column.h
combine-diff.c
command-list.txt
commit-slab.h
commit.c
commit.h
config.c
config.mak.in
config.mak.uname
configure.ac
connect.c
connect.h
connected.c
connected.h
convert.c
convert.h
copy.c
credential-cache--daemon.c
credential-cache.c
credential-store.c
credential.c
credential.h
csum-file.c
csum-file.h
ctype.c
daemon.c
date.c
decorate.c
decorate.h
delta.h
diff-delta.c
diff-lib.c
diff-no-index.c
diff.c
diff.h
diffcore-break.c
diffcore-delta.c
diffcore-order.c
diffcore-pickaxe.c
diffcore-rename.c
diffcore.h
dir.c
dir.h
editor.c
entry.c
environment.c
exec_cmd.c
exec_cmd.h
fast-import.c
fetch-pack.c
fetch-pack.h
fmt-merge-msg.h
fsck.c
fsck.h
generate-cmdlist.sh
gettext.c
gettext.h
git-add--interactive.perl
git-am.sh
git-archimport.perl
git-bisect.sh
git-compat-util.h
git-cvsexportcommit.perl
git-cvsimport.perl
git-cvsserver.perl
git-difftool--helper.sh
git-difftool.perl
git-filter-branch.sh
git-instaweb.sh
git-merge-octopus.sh
git-merge-one-file.sh
git-merge-resolve.sh
git-mergetool--lib.sh
git-mergetool.sh
git-p4.py
git-parse-remote.sh
git-pull.sh
git-quiltimport.sh
git-rebase--am.sh
git-rebase--interactive.sh
git-rebase--merge.sh
git-rebase.sh
git-relink.perl
git-remote-testgit.sh
git-request-pull.sh
git-send-email.perl
git-sh-i18n.sh
git-sh-setup.sh
git-stash.sh
git-submodule.sh
git-svn.perl
git-web--browse.sh
git.c
git.rc
git.spec.in
gpg-interface.c
gpg-interface.h
graph.c
graph.h
grep.c
grep.h
hashmap.c
hashmap.h
help.c
help.h
hex.c
http-backend.c
http-fetch.c
http-push.c
http-walker.c
http.c
http.h
ident.c
imap-send.c
khash.h
kwset.c
kwset.h
levenshtein.c
levenshtein.h
line-log.c
line-log.h
line-range.c
line-range.h
list-objects.c
list-objects.h
ll-merge.c
ll-merge.h
lockfile.c
log-tree.c
log-tree.h
mailmap.c
mailmap.h
match-trees.c
merge-blobs.c
merge-blobs.h
merge-recursive.c
merge-recursive.h
merge.c
mergesort.c
mergesort.h
name-hash.c
notes-cache.c
notes-cache.h
notes-merge.c
notes-merge.h
notes-utils.c
notes-utils.h
notes.c
notes.h
object.c
object.h
pack-bitmap-write.c
pack-bitmap.c
pack-bitmap.h
pack-check.c
pack-objects.c
pack-objects.h
pack-revindex.c
pack-revindex.h
pack-write.c
pack.h
pager.c
parse-options-cb.c
parse-options.c
parse-options.h
patch-delta.c
patch-ids.c
patch-ids.h
path.c
pathspec.c
pathspec.h
pkt-line.c
pkt-line.h
preload-index.c
pretty.c
prio-queue.c
prio-queue.h
progress.c
progress.h
prompt.c
prompt.h
quote.c
quote.h
reachable.c
reachable.h
read-cache.c
reflog-walk.c
reflog-walk.h
refs.c
refs.h
remote-curl.c
remote-testsvn.c
remote.c
remote.h
replace_object.c
rerere.c
rerere.h
resolve-undo.c
resolve-undo.h
revision.c
revision.h
run-command.c
run-command.h
send-pack.c
send-pack.h
sequencer.c
sequencer.h
server-info.c
setup.c
sh-i18n--envsubst.c
sha1-array.c
sha1-array.h
sha1-lookup.c
sha1-lookup.h
sha1_file.c
sha1_name.c
shallow.c
shell.c
shortlog.h
show-index.c
sideband.c
sideband.h
sigchain.c
sigchain.h
strbuf.c
strbuf.h
streaming.c
streaming.h
string-list.c
string-list.h
submodule.c
submodule.h
symlinks.c
tag.c
tag.h
tar.h
test-chmtime.c
test-ctype.c
test-date.c
test-delta.c
test-dump-cache-tree.c
test-genrandom.c
test-hashmap.c
test-index-version.c
test-line-buffer.c
test-match-trees.c
test-mergesort.c
test-mktemp.c
test-parse-options.c
test-path-utils.c
test-prio-queue.c
test-read-cache.c
test-regex.c
test-revision-walking.c
test-run-command.c
test-scrap-cache-tree.c
test-sha1.c
test-sha1.sh
test-sigchain.c
test-string-list.c
test-subprocess.c
test-svn-fe.c
test-urlmatch-normalization.c
test-wildmatch.c
thread-utils.c
thread-utils.h
trace.c
transport-helper.c
transport.c
transport.h
tree-diff.c
tree-walk.c
tree-walk.h
tree.c
tree.h
unimplemented.sh
unix-socket.c
unix-socket.h
unpack-trees.c
unpack-trees.h
upload-pack.c
url.c
url.h
urlmatch.c
urlmatch.h
usage.c
userdiff.c
userdiff.h
utf8.c
utf8.h
varint.c
varint.h
version.c
version.h
versioncmp.c
walker.c
walker.h
wildmatch.c
wildmatch.h
wrap-for-bin.sh
wrapper.c
write_or_die.c
ws.c
wt-status.c
wt-status.h
xdiff-interface.c
xdiff-interface.h
zlib.c
Breadcrumbs
git
/
wrapper.c
Blame
Blame
Latest commit
History
History
495 lines (434 loc) · 10.6 KB
Breadcrumbs
git
/
wrapper.c
Top
File metadata and controls
Code
Blame
495 lines (434 loc) · 10.6 KB
Raw
/* * Various trivial helper wrappers around standard functions */ #include "cache.h" static void do_nothing(size_t size) { } static void (*try_to_free_routine)(size_t size) = do_nothing; static void memory_limit_check(size_t size) { static int limit = -1; if (limit == -1) { const char *env = getenv("GIT_ALLOC_LIMIT"); limit = env ? atoi(env) * 1024 : 0; } if (limit && size > limit) die("attempting to allocate %"PRIuMAX" over limit %d", (intmax_t)size, limit); } try_to_free_t set_try_to_free_routine(try_to_free_t routine) { try_to_free_t old = try_to_free_routine; if (!routine) routine = do_nothing; try_to_free_routine = routine; return old; } char *xstrdup(const char *str) { char *ret = strdup(str); if (!ret) { try_to_free_routine(strlen(str) + 1); ret = strdup(str); if (!ret) die("Out of memory, strdup failed"); } return ret; } void *xmalloc(size_t size) { void *ret; memory_limit_check(size); ret = malloc(size); if (!ret && !size) ret = malloc(1); if (!ret) { try_to_free_routine(size); ret = malloc(size); if (!ret && !size) ret = malloc(1); if (!ret) die("Out of memory, malloc failed (tried to allocate %lu bytes)", (unsigned long)size); } #ifdef XMALLOC_POISON memset(ret, 0xA5, size); #endif return ret; } void *xmallocz(size_t size) { void *ret; if (unsigned_add_overflows(size, 1)) die("Data too large to fit into virtual memory space."); ret = xmalloc(size + 1); ((char*)ret)[size] = 0; return ret; } /* * xmemdupz() allocates (len + 1) bytes of memory, duplicates "len" bytes of * "data" to the allocated memory, zero terminates the allocated memory, * and returns a pointer to the allocated memory. If the allocation fails, * the program dies. */ void *xmemdupz(const void *data, size_t len) { return memcpy(xmallocz(len), data, len); } char *xstrndup(const char *str, size_t len) { char *p = memchr(str, '\0', len); return xmemdupz(str, p ? p - str : len); } void *xrealloc(void *ptr, size_t size) { void *ret; memory_limit_check(size); ret = realloc(ptr, size); if (!ret && !size) ret = realloc(ptr, 1); if (!ret) { try_to_free_routine(size); ret = realloc(ptr, size); if (!ret && !size) ret = realloc(ptr, 1); if (!ret) die("Out of memory, realloc failed"); } return ret; } void *xcalloc(size_t nmemb, size_t size) { void *ret; memory_limit_check(size * nmemb); ret = calloc(nmemb, size); if (!ret && (!nmemb || !size)) ret = calloc(1, 1); if (!ret) { try_to_free_routine(nmemb * size); ret = calloc(nmemb, size); if (!ret && (!nmemb || !size)) ret = calloc(1, 1); if (!ret) die("Out of memory, calloc failed"); } return ret; } /* * Limit size of IO chunks, because huge chunks only cause pain. OS X * 64-bit is buggy, returning EINVAL if len >= INT_MAX; and even in * the absence of bugs, large chunks can result in bad latencies when * you decide to kill the process. */ #define MAX_IO_SIZE (8*1024*1024) /* * xread() is the same a read(), but it automatically restarts read() * operations with a recoverable error (EAGAIN and EINTR). xread() * DOES NOT GUARANTEE that "len" bytes is read even if the data is available. */ ssize_t xread(int fd, void *buf, size_t len) { ssize_t nr; if (len > MAX_IO_SIZE) len = MAX_IO_SIZE; while (1) { nr = read(fd, buf, len); if ((nr < 0) && (errno == EAGAIN || errno == EINTR)) continue; return nr; } } /* * xwrite() is the same a write(), but it automatically restarts write() * operations with a recoverable error (EAGAIN and EINTR). xwrite() DOES NOT * GUARANTEE that "len" bytes is written even if the operation is successful. */ ssize_t xwrite(int fd, const void *buf, size_t len) { ssize_t nr; if (len > MAX_IO_SIZE) len = MAX_IO_SIZE; while (1) { nr = write(fd, buf, len); if ((nr < 0) && (errno == EAGAIN || errno == EINTR)) continue; return nr; } } /* * xpread() is the same as pread(), but it automatically restarts pread() * operations with a recoverable error (EAGAIN and EINTR). xpread() DOES * NOT GUARANTEE that "len" bytes is read even if the data is available. */ ssize_t xpread(int fd, void *buf, size_t len, off_t offset) { ssize_t nr; if (len > MAX_IO_SIZE) len = MAX_IO_SIZE; while (1) { nr = pread(fd, buf, len, offset); if ((nr < 0) && (errno == EAGAIN || errno == EINTR)) continue; return nr; } } ssize_t read_in_full(int fd, void *buf, size_t count) { char *p = buf; ssize_t total = 0; while (count > 0) { ssize_t loaded = xread(fd, p, count); if (loaded < 0) return -1; if (loaded == 0) return total; count -= loaded; p += loaded; total += loaded; } return total; } ssize_t write_in_full(int fd, const void *buf, size_t count) { const char *p = buf; ssize_t total = 0; while (count > 0) { ssize_t written = xwrite(fd, p, count); if (written < 0) return -1; if (!written) { errno = ENOSPC; return -1; } count -= written; p += written; total += written; } return total; } ssize_t pread_in_full(int fd, void *buf, size_t count, off_t offset) { char *p = buf; ssize_t total = 0; while (count > 0) { ssize_t loaded = xpread(fd, p, count, offset); if (loaded < 0) return -1; if (loaded == 0) return total; count -= loaded; p += loaded; total += loaded; offset += loaded; } return total; } int xdup(int fd) { int ret = dup(fd); if (ret < 0) die_errno("dup failed"); return ret; } FILE *xfdopen(int fd, const char *mode) { FILE *stream = fdopen(fd, mode); if (stream == NULL) die_errno("Out of memory? fdopen failed"); return stream; } int xmkstemp(char *template) { int fd; char origtemplate[PATH_MAX]; strlcpy(origtemplate, template, sizeof(origtemplate)); fd = mkstemp(template); if (fd < 0) { int saved_errno = errno; const char *nonrelative_template; if (strlen(template) != strlen(origtemplate)) template = origtemplate; nonrelative_template = absolute_path(template); errno = saved_errno; die_errno("Unable to create temporary file '%s'", nonrelative_template); } return fd; } /* git_mkstemp() - create tmp file honoring TMPDIR variable */ int git_mkstemp(char *path, size_t len, const char *template) { const char *tmp; size_t n; tmp = getenv("TMPDIR"); if (!tmp) tmp = "/tmp"; n = snprintf(path, len, "%s/%s", tmp, template); if (len <= n) { errno = ENAMETOOLONG; return -1; } return mkstemp(path); } /* git_mkstemps() - create tmp file with suffix honoring TMPDIR variable. */ int git_mkstemps(char *path, size_t len, const char *template, int suffix_len) { const char *tmp; size_t n; tmp = getenv("TMPDIR"); if (!tmp) tmp = "/tmp"; n = snprintf(path, len, "%s/%s", tmp, template); if (len <= n) { errno = ENAMETOOLONG; return -1; } return mkstemps(path, suffix_len); } /* Adapted from libiberty's mkstemp.c. */ #undef TMP_MAX #define TMP_MAX 16384 int git_mkstemps_mode(char *pattern, int suffix_len, int mode) { static const char letters[] = "abcdefghijklmnopqrstuvwxyz" "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "0123456789"; static const int num_letters = 62; uint64_t value; struct timeval tv; char *template; size_t len; int fd, count; len = strlen(pattern); if (len < 6 + suffix_len) { errno = EINVAL; return -1; } if (strncmp(&pattern[len - 6 - suffix_len], "XXXXXX", 6)) { errno = EINVAL; return -1; } /* * Replace pattern's XXXXXX characters with randomness. * Try TMP_MAX different filenames. */ gettimeofday(&tv, NULL); value = ((size_t)(tv.tv_usec << 16)) ^ tv.tv_sec ^ getpid(); template = &pattern[len - 6 - suffix_len]; for (count = 0; count < TMP_MAX; ++count) { uint64_t v = value; /* Fill in the random bits. */ template[0] = letters[v % num_letters]; v /= num_letters; template[1] = letters[v % num_letters]; v /= num_letters; template[2] = letters[v % num_letters]; v /= num_letters; template[3] = letters[v % num_letters]; v /= num_letters; template[4] = letters[v % num_letters]; v /= num_letters; template[5] = letters[v % num_letters]; v /= num_letters; fd = open(pattern, O_CREAT | O_EXCL | O_RDWR, mode); if (fd >= 0) return fd; /* * Fatal error (EPERM, ENOSPC etc). * It doesn't make sense to loop. */ if (errno != EEXIST) break; /* * This is a random value. It is only necessary that * the next TMP_MAX values generated by adding 7777 to * VALUE are different with (module 2^32). */ value += 7777; } /* We return the null string if we can't find a unique file name. */ pattern[0] = '\0'; return -1; } int git_mkstemp_mode(char *pattern, int mode) { /* mkstemp is just mkstemps with no suffix */ return git_mkstemps_mode(pattern, 0, mode); } #ifdef NO_MKSTEMPS int gitmkstemps(char *pattern, int suffix_len) { return git_mkstemps_mode(pattern, suffix_len, 0600); } #endif int xmkstemp_mode(char *template, int mode) { int fd; char origtemplate[PATH_MAX]; strlcpy(origtemplate, template, sizeof(origtemplate)); fd = git_mkstemp_mode(template, mode); if (fd < 0) { int saved_errno = errno; const char *nonrelative_template; if (!template[0]) template = origtemplate; nonrelative_template = absolute_path(template); errno = saved_errno; die_errno("Unable to create temporary file '%s'", nonrelative_template); } return fd; } static int warn_if_unremovable(const char *op, const char *file, int rc) { if (rc < 0) { int err = errno; if (ENOENT != err) { warning("unable to %s %s: %s", op, file, strerror(errno)); errno = err; } } return rc; } int unlink_or_warn(const char *file) { return warn_if_unremovable("unlink", file, unlink(file)); } int rmdir_or_warn(const char *file) { return warn_if_unremovable("rmdir", file, rmdir(file)); } int remove_or_warn(unsigned int mode, const char *file) { return S_ISGITLINK(mode) ? rmdir_or_warn(file) : unlink_or_warn(file); } void warn_on_inaccessible(const char *path) { warning(_("unable to access '%s': %s"), path, strerror(errno)); } static int access_error_is_ok(int err, unsigned flag) { return err == ENOENT || err == ENOTDIR || ((flag & ACCESS_EACCES_OK) && err == EACCES); } int access_or_warn(const char *path, int mode, unsigned flag) { int ret = access(path, mode); if (ret && !access_error_is_ok(errno, flag)) warn_on_inaccessible(path); return ret; } int access_or_die(const char *path, int mode, unsigned flag) { int ret = access(path, mode); if (ret && !access_error_is_ok(errno, flag)) die_errno(_("unable to access '%s'"), path); return ret; } struct passwd *xgetpwuid_self(void) { struct passwd *pw; errno = 0; pw = getpwuid(getuid()); if (!pw) die(_("unable to look up current user in the passwd file: %s"), errno ? strerror(errno) : _("no such user")); return pw; }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
You can’t perform that action at this time.