summaryrefslogtreecommitdiff
path: root/wrapper.c
diff options
context:
space:
mode:
Diffstat (limited to 'wrapper.c')
-rw-r--r--wrapper.c210
1 files changed, 106 insertions, 104 deletions
diff --git a/wrapper.c b/wrapper.c
index fd8ead3..8d7dd31 100644
--- a/wrapper.c
+++ b/wrapper.c
@@ -3,16 +3,17 @@
*/
#include "cache.h"
-static void try_to_free_builtin(size_t size)
+static void do_nothing(size_t size)
{
- release_pack_memory(size, -1);
}
-static void (*try_to_free_routine)(size_t size) = try_to_free_builtin;
+static void (*try_to_free_routine)(size_t size) = do_nothing;
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;
}
@@ -108,21 +109,6 @@ void *xcalloc(size_t nmemb, size_t size)
return ret;
}
-void *xmmap(void *start, size_t length,
- int prot, int flags, int fd, off_t offset)
-{
- void *ret = mmap(start, length, prot, flags, fd, offset);
- if (ret == MAP_FAILED) {
- if (!length)
- return NULL;
- release_pack_memory(length, fd);
- ret = mmap(start, length, prot, flags, fd, offset);
- if (ret == MAP_FAILED)
- die_errno("Out of memory? mmap failed");
- }
- return ret;
-}
-
/*
* xread() is the same a read(), but it automatically restarts read()
* operations with a recoverable error (EAGAIN and EINTR). xread()
@@ -219,111 +205,127 @@ int xmkstemp(char *template)
return fd;
}
-int xmkstemp_mode(char *template, int mode)
+/* git_mkstemp() - create tmp file honoring TMPDIR variable */
+int git_mkstemp(char *path, size_t len, const char *template)
{
- int fd;
-
- fd = git_mkstemp_mode(template, mode);
- if (fd < 0)
- die_errno("Unable to create temporary file");
- return fd;
+ 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);
}
-/*
- * zlib wrappers to make sure we don't silently miss errors
- * at init time.
- */
-void git_inflate_init(z_streamp strm)
+/* 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 *err;
-
- switch (inflateInit(strm)) {
- case Z_OK:
- return;
-
- case Z_MEM_ERROR:
- err = "out of memory";
- break;
- case Z_VERSION_ERROR:
- err = "wrong version";
- break;
- default:
- err = "error";
+ 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;
}
- die("inflateInit: %s (%s)", err, strm->msg ? strm->msg : "no message");
+ return mkstemps(path, suffix_len);
}
-void git_inflate_end(z_streamp strm)
+/* Adapted from libiberty's mkstemp.c. */
+
+#undef TMP_MAX
+#define TMP_MAX 16384
+
+int git_mkstemps_mode(char *pattern, int suffix_len, int mode)
{
- if (inflateEnd(strm) != Z_OK)
- error("inflateEnd: %s", strm->msg ? strm->msg : "failed");
+ 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_inflate(z_streamp strm, int flush)
+int git_mkstemp_mode(char *pattern, int mode)
{
- int ret = inflate(strm, flush);
- const char *err;
-
- switch (ret) {
- /* Out of memory is fatal. */
- case Z_MEM_ERROR:
- die("inflate: out of memory");
-
- /* Data corruption errors: we may want to recover from them (fsck) */
- case Z_NEED_DICT:
- err = "needs dictionary"; break;
- case Z_DATA_ERROR:
- err = "data stream error"; break;
- case Z_STREAM_ERROR:
- err = "stream consistency error"; break;
- default:
- err = "unknown error"; break;
-
- /* Z_BUF_ERROR: normal, needs more space in the output buffer */
- case Z_BUF_ERROR:
- case Z_OK:
- case Z_STREAM_END:
- return ret;
- }
- error("inflate: %s (%s)", err, strm->msg ? strm->msg : "no message");
- return ret;
+ /* mkstemp is just mkstemps with no suffix */
+ return git_mkstemps_mode(pattern, 0, mode);
}
-int odb_mkstemp(char *template, size_t limit, const char *pattern)
+int gitmkstemps(char *pattern, int suffix_len)
{
- int fd;
- /*
- * we let the umask do its job, don't try to be more
- * restrictive except to remove write permission.
- */
- int mode = 0444;
- snprintf(template, limit, "%s/%s",
- get_object_directory(), pattern);
- fd = git_mkstemp_mode(template, mode);
- if (0 <= fd)
- return fd;
-
- /* slow path */
- /* some mkstemp implementations erase template on failure */
- snprintf(template, limit, "%s/%s",
- get_object_directory(), pattern);
- safe_create_leading_directories(template);
- return xmkstemp_mode(template, mode);
+ return git_mkstemps_mode(pattern, suffix_len, 0600);
}
-int odb_pack_keep(char *name, size_t namesz, unsigned char *sha1)
+int xmkstemp_mode(char *template, int mode)
{
int fd;
- snprintf(name, namesz, "%s/pack/pack-%s.keep",
- get_object_directory(), sha1_to_hex(sha1));
- fd = open(name, O_RDWR|O_CREAT|O_EXCL, 0600);
- if (0 <= fd)
- return fd;
-
- /* slow path */
- safe_create_leading_directories(name);
- return open(name, O_RDWR|O_CREAT|O_EXCL, 0600);
+ fd = git_mkstemp_mode(template, mode);
+ if (fd < 0)
+ die_errno("Unable to create temporary file");
+ return fd;
}
static int warn_if_unremovable(const char *op, const char *file, int rc)