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.
This commit is contained in:
79
path.c
79
path.c
@ -157,6 +157,85 @@ int git_mkstemps(char *path, size_t len, const char *template, int suffix_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;
|
||||
|
Reference in New Issue
Block a user