compat: add a mkstemps() compatibility function
mkstemps() is a BSD extension so provide an implementation for cross-platform use. Signed-off-by: David Aguilar <davvid@gmail.com> Tested-by: Johannes Sixt <j6t@kdbg.org> (Windows) Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
parent
33fd7169ed
commit
0620b39b3b
19
Makefile
19
Makefile
@ -52,6 +52,8 @@ all::
|
||||
#
|
||||
# Define NO_MKDTEMP if you don't have mkdtemp in the C library.
|
||||
#
|
||||
# Define NO_MKSTEMPS if you don't have mkstemps in the C library.
|
||||
#
|
||||
# Define NO_SYS_SELECT_H if you don't have sys/select.h.
|
||||
#
|
||||
# Define NO_SYMLINK_HEAD if you never want .git/HEAD to be a symbolic link.
|
||||
@ -636,10 +638,12 @@ EXTLIBS =
|
||||
|
||||
ifeq ($(uname_S),Linux)
|
||||
NO_STRLCPY = YesPlease
|
||||
NO_MKSTEMPS = YesPlease
|
||||
THREADED_DELTA_SEARCH = YesPlease
|
||||
endif
|
||||
ifeq ($(uname_S),GNU/kFreeBSD)
|
||||
NO_STRLCPY = YesPlease
|
||||
NO_MKSTEMPS = YesPlease
|
||||
THREADED_DELTA_SEARCH = YesPlease
|
||||
endif
|
||||
ifeq ($(uname_S),UnixWare)
|
||||
@ -651,6 +655,7 @@ ifeq ($(uname_S),UnixWare)
|
||||
SHELL_PATH = /usr/local/bin/bash
|
||||
NO_IPV6 = YesPlease
|
||||
NO_HSTRERROR = YesPlease
|
||||
NO_MKSTEMPS = YesPlease
|
||||
BASIC_CFLAGS += -Kthread
|
||||
BASIC_CFLAGS += -I/usr/local/include
|
||||
BASIC_LDFLAGS += -L/usr/local/lib
|
||||
@ -674,6 +679,7 @@ ifeq ($(uname_S),SCO_SV)
|
||||
SHELL_PATH = /usr/bin/bash
|
||||
NO_IPV6 = YesPlease
|
||||
NO_HSTRERROR = YesPlease
|
||||
NO_MKSTEMPS = YesPlease
|
||||
BASIC_CFLAGS += -I/usr/local/include
|
||||
BASIC_LDFLAGS += -L/usr/local/lib
|
||||
NO_STRCASESTR = YesPlease
|
||||
@ -702,6 +708,7 @@ ifeq ($(uname_S),SunOS)
|
||||
NO_MEMMEM = YesPlease
|
||||
NO_HSTRERROR = YesPlease
|
||||
NO_MKDTEMP = YesPlease
|
||||
NO_MKSTEMPS = YesPlease
|
||||
OLD_ICONV = UnfortunatelyYes
|
||||
ifeq ($(uname_R),5.8)
|
||||
NO_UNSETENV = YesPlease
|
||||
@ -724,6 +731,7 @@ ifeq ($(uname_O),Cygwin)
|
||||
NO_D_INO_IN_DIRENT = YesPlease
|
||||
NO_STRCASESTR = YesPlease
|
||||
NO_MEMMEM = YesPlease
|
||||
NO_MKSTEMPS = YesPlease
|
||||
NO_SYMLINK_HEAD = YesPlease
|
||||
NEEDS_LIBICONV = YesPlease
|
||||
NO_FAST_WORKING_DIRECTORY = UnfortunatelyYes
|
||||
@ -767,11 +775,13 @@ ifeq ($(uname_S),NetBSD)
|
||||
BASIC_LDFLAGS += -L/usr/pkg/lib $(CC_LD_DYNPATH)/usr/pkg/lib
|
||||
THREADED_DELTA_SEARCH = YesPlease
|
||||
USE_ST_TIMESPEC = YesPlease
|
||||
NO_MKSTEMPS = YesPlease
|
||||
endif
|
||||
ifeq ($(uname_S),AIX)
|
||||
NO_STRCASESTR=YesPlease
|
||||
NO_MEMMEM = YesPlease
|
||||
NO_MKDTEMP = YesPlease
|
||||
NO_MKSTEMPS = YesPlease
|
||||
NO_STRLCPY = YesPlease
|
||||
NO_NSEC = YesPlease
|
||||
FREAD_READS_DIRECTORIES = UnfortunatelyYes
|
||||
@ -787,12 +797,14 @@ endif
|
||||
ifeq ($(uname_S),GNU)
|
||||
# GNU/Hurd
|
||||
NO_STRLCPY=YesPlease
|
||||
NO_MKSTEMPS = YesPlease
|
||||
endif
|
||||
ifeq ($(uname_S),IRIX64)
|
||||
NO_IPV6=YesPlease
|
||||
NO_SETENV=YesPlease
|
||||
NO_STRCASESTR=YesPlease
|
||||
NO_MEMMEM = YesPlease
|
||||
NO_MKSTEMPS = YesPlease
|
||||
NO_STRLCPY = YesPlease
|
||||
NO_SOCKADDR_STORAGE=YesPlease
|
||||
SHELL_PATH=/usr/gnu/bin/bash
|
||||
@ -805,6 +817,7 @@ ifeq ($(uname_S),HP-UX)
|
||||
NO_SETENV=YesPlease
|
||||
NO_STRCASESTR=YesPlease
|
||||
NO_MEMMEM = YesPlease
|
||||
NO_MKSTEMPS = YesPlease
|
||||
NO_STRLCPY = YesPlease
|
||||
NO_MKDTEMP = YesPlease
|
||||
NO_UNSETENV = YesPlease
|
||||
@ -834,6 +847,7 @@ ifneq (,$(findstring MINGW,$(uname_S)))
|
||||
NO_C99_FORMAT = YesPlease
|
||||
NO_STRTOUMAX = YesPlease
|
||||
NO_MKDTEMP = YesPlease
|
||||
NO_MKSTEMPS = YesPlease
|
||||
SNPRINTF_RETURNS_BOGUS = YesPlease
|
||||
NO_SVN_TESTS = YesPlease
|
||||
NO_PERL_MAKEMAKER = YesPlease
|
||||
@ -853,6 +867,7 @@ ifneq (,$(findstring MINGW,$(uname_S)))
|
||||
endif
|
||||
ifneq (,$(findstring arm,$(uname_M)))
|
||||
ARM_SHA1 = YesPlease
|
||||
NO_MKSTEMPS = YesPlease
|
||||
endif
|
||||
|
||||
-include config.mak.autogen
|
||||
@ -1011,6 +1026,10 @@ ifdef NO_MKDTEMP
|
||||
COMPAT_CFLAGS += -DNO_MKDTEMP
|
||||
COMPAT_OBJS += compat/mkdtemp.o
|
||||
endif
|
||||
ifdef NO_MKSTEMPS
|
||||
COMPAT_CFLAGS += -DNO_MKSTEMPS
|
||||
COMPAT_OBJS += compat/mkstemps.o
|
||||
endif
|
||||
ifdef NO_UNSETENV
|
||||
COMPAT_CFLAGS += -DNO_UNSETENV
|
||||
COMPAT_OBJS += compat/unsetenv.o
|
||||
|
70
compat/mkstemps.c
Normal file
70
compat/mkstemps.c
Normal file
@ -0,0 +1,70 @@
|
||||
#include "../git-compat-util.h"
|
||||
|
||||
/* Adapted from libiberty's mkstemp.c. */
|
||||
|
||||
#undef TMP_MAX
|
||||
#define TMP_MAX 16384
|
||||
|
||||
int gitmkstemps(char *pattern, int suffix_len)
|
||||
{
|
||||
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, 0600);
|
||||
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';
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
@ -46,6 +46,7 @@ NO_STRTOUMAX=@NO_STRTOUMAX@
|
||||
NO_SETENV=@NO_SETENV@
|
||||
NO_UNSETENV=@NO_UNSETENV@
|
||||
NO_MKDTEMP=@NO_MKDTEMP@
|
||||
NO_MKSTEMPS=@NO_MKSTEMPS@
|
||||
NO_ICONV=@NO_ICONV@
|
||||
OLD_ICONV=@OLD_ICONV@
|
||||
NO_DEFLATE_BOUND=@NO_DEFLATE_BOUND@
|
||||
|
@ -677,6 +677,13 @@ GIT_CHECK_FUNC(mkdtemp,
|
||||
[NO_MKDTEMP=YesPlease])
|
||||
AC_SUBST(NO_MKDTEMP)
|
||||
#
|
||||
# Define NO_MKSTEMPS if you don't have mkstemps in the C library.
|
||||
GIT_CHECK_FUNC(mkstemps,
|
||||
[NO_MKSTEMPS=],
|
||||
[NO_MKSTEMPS=YesPlease])
|
||||
AC_SUBST(NO_MKSTEMPS)
|
||||
#
|
||||
#
|
||||
# Define NO_MMAP if you want to avoid mmap.
|
||||
#
|
||||
# Define NO_ICONV if your libc does not properly support iconv.
|
||||
|
@ -232,6 +232,11 @@ extern int gitsetenv(const char *, const char *, int);
|
||||
extern char *gitmkdtemp(char *);
|
||||
#endif
|
||||
|
||||
#ifdef NO_MKSTEMPS
|
||||
#define mkstemps gitmkstemps
|
||||
extern int gitmkstemps(char *, int);
|
||||
#endif
|
||||
|
||||
#ifdef NO_UNSETENV
|
||||
#define unsetenv gitunsetenv
|
||||
extern void gitunsetenv(const char *);
|
||||
|
Loading…
Reference in New Issue
Block a user