From: Junio C Hamano Date: Mon, 8 Mar 2010 08:36:00 +0000 (-0800) Subject: Merge branch 'mm/mkstemps-mode-for-packfiles' into maint X-Git-Tag: v1.7.0.3~29 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/493e433277ee72b200e72f7a17e08266ed9497c5?ds=inline;hp=-c Merge branch 'mm/mkstemps-mode-for-packfiles' into maint * mm/mkstemps-mode-for-packfiles: Use git_mkstemp_mode instead of plain mkstemp to create object files git_mkstemps_mode: don't set errno to EINVAL on exit. Use git_mkstemp_mode and xmkstemp_mode in odb_mkstemp, not chmod later. git_mkstemp_mode, xmkstemp_mode: variants of gitmkstemps with mode argument. Move gitmkstemps to path.c Add a testcase for ACL with restrictive umask. --- 493e433277ee72b200e72f7a17e08266ed9497c5 diff --combined cache.h index d454b7e686,0319637723..4d89aa3da4 --- a/cache.h +++ b/cache.h @@@ -641,6 -641,10 +641,10 @@@ int git_mkstemp(char *path, size_t n, c int git_mkstemps(char *path, size_t n, const char *template, int suffix_len); + /* set default permissions by passing mode arguments to open(2) */ + int git_mkstemps_mode(char *pattern, int suffix_len, int mode); + int git_mkstemp_mode(char *pattern, int mode); + /* * NOTE NOTE NOTE!! * @@@ -775,7 -779,7 +779,7 @@@ extern const char *git_committer_info(i extern const char *fmt_ident(const char *name, const char *email, const char *date_str, int); extern const char *fmt_name(const char *name, const char *email); extern const char *git_editor(void); -extern const char *git_pager(void); +extern const char *git_pager(int stdout_is_tty); struct checkout { const char *base_dir; diff --combined path.c index e166d5380e,12ef731ace..aaa9345ebc --- a/path.c +++ b/path.c @@@ -157,6 -157,85 +157,85 @@@ int git_mkstemps(char *path, size_t len 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); + } + + int gitmkstemps(char *pattern, int suffix_len) + { + return git_mkstemps_mode(pattern, suffix_len, 0600); + } + int validate_headref(const char *path) { struct stat st; @@@ -610,7 -689,7 +689,7 @@@ int daemon_avoid_alias(const char *p /* * This resurrects the belts and suspenders paranoia check by HPA * done in <435560F7.4080006@zytor.com> thread, now enter_repo() - * does not do getcwd() based path canonicalizations. + * does not do getcwd() based path canonicalization. * * sl becomes true immediately after seeing '/' and continues to * be true as long as dots continue after that without intervening diff --combined sha1_file.c index 006321e009,3316f282c6..c23cc5e6e1 --- a/sha1_file.c +++ b/sha1_file.c @@@ -2206,7 -2206,7 +2206,7 @@@ int move_temp_to_file(const char *tmpfi } out: - if (set_shared_perm(filename, (S_IFREG|0444))) + if (adjust_shared_perm(filename)) return error("unable to set permission to '%s'", filename); return 0; } @@@ -2262,7 -2262,7 +2262,7 @@@ static int create_tmpfile(char *buffer } memcpy(buffer, filename, dirlen); strcpy(buffer + dirlen, "tmp_obj_XXXXXX"); - fd = mkstemp(buffer); + fd = git_mkstemp_mode(buffer, 0444); if (fd < 0 && dirlen && errno == ENOENT) { /* Make sure the directory exists */ memcpy(buffer, filename, dirlen); @@@ -2272,7 -2272,7 +2272,7 @@@ /* Try again */ strcpy(buffer + dirlen - 1, "/tmp_obj_XXXXXX"); - fd = mkstemp(buffer); + fd = git_mkstemp_mode(buffer, 0444); } return fd; } @@@ -2281,10 -2281,9 +2281,10 @@@ static int write_loose_object(const uns void *buf, unsigned long len, time_t mtime) { int fd, ret; - size_t size; - unsigned char *compressed; + unsigned char compressed[4096]; z_stream stream; + git_SHA_CTX c; + unsigned char parano_sha1[20]; char *filename; static char tmpfile[PATH_MAX]; @@@ -2302,40 -2301,36 +2302,40 @@@ /* Set it up */ memset(&stream, 0, sizeof(stream)); deflateInit(&stream, zlib_compression_level); - size = 8 + deflateBound(&stream, len+hdrlen); - compressed = xmalloc(size); - - /* Compress it */ stream.next_out = compressed; - stream.avail_out = size; + stream.avail_out = sizeof(compressed); + git_SHA1_Init(&c); /* First header.. */ stream.next_in = (unsigned char *)hdr; stream.avail_in = hdrlen; while (deflate(&stream, 0) == Z_OK) /* nothing */; + git_SHA1_Update(&c, hdr, hdrlen); /* Then the data itself.. */ stream.next_in = buf; stream.avail_in = len; - ret = deflate(&stream, Z_FINISH); + do { + unsigned char *in0 = stream.next_in; + ret = deflate(&stream, Z_FINISH); + git_SHA1_Update(&c, in0, stream.next_in - in0); + if (write_buffer(fd, compressed, stream.next_out - compressed) < 0) + die("unable to write sha1 file"); + stream.next_out = compressed; + stream.avail_out = sizeof(compressed); + } while (ret == Z_OK); + if (ret != Z_STREAM_END) die("unable to deflate new object %s (%d)", sha1_to_hex(sha1), ret); - ret = deflateEnd(&stream); if (ret != Z_OK) die("deflateEnd on object %s failed (%d)", sha1_to_hex(sha1), ret); + git_SHA1_Final(parano_sha1, &c); + if (hashcmp(sha1, parano_sha1) != 0) + die("confused by unstable object source data for %s", sha1_to_hex(sha1)); - size = stream.total_out; - - if (write_buffer(fd, compressed, size) < 0) - die("unable to write sha1 file"); close_sha1_file(fd); - free(compressed); if (mtime) { struct utimbuf utb; @@@ -2439,8 -2434,6 +2439,8 @@@ static int index_mem(unsigned char *sha return ret; } +#define SMALL_FILE_SIZE (32*1024) + int index_fd(unsigned char *sha1, int fd, struct stat *st, int write_object, enum object_type type, const char *path) { @@@ -2455,14 -2448,6 +2455,14 @@@ else ret = -1; strbuf_release(&sbuf); + } else if (size <= SMALL_FILE_SIZE) { + char *buf = xmalloc(size); + if (size == read_in_full(fd, buf, size)) + ret = index_mem(sha1, buf, size, write_object, type, + path); + else + ret = error("short read %s", strerror(errno)); + free(buf); } else if (size) { void *buf = xmmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0); ret = index_mem(sha1, buf, size, write_object, type, path);