Skip to content

Commit 0620b39

Browse files
davvidgitster
authored andcommitted
compat: add a mkstemps() compatibility function
mkstemps() is a BSD extension so provide an implementation for cross-platform use. Signed-off-by: David Aguilar <[email protected]> Tested-by: Johannes Sixt <[email protected]> (Windows) Signed-off-by: Junio C Hamano <[email protected]>
1 parent 33fd716 commit 0620b39

File tree

5 files changed

+102
-0
lines changed

5 files changed

+102
-0
lines changed

Makefile

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ all::
5252
#
5353
# Define NO_MKDTEMP if you don't have mkdtemp in the C library.
5454
#
55+
# Define NO_MKSTEMPS if you don't have mkstemps in the C library.
56+
#
5557
# Define NO_SYS_SELECT_H if you don't have sys/select.h.
5658
#
5759
# Define NO_SYMLINK_HEAD if you never want .git/HEAD to be a symbolic link.
@@ -636,10 +638,12 @@ EXTLIBS =
636638

637639
ifeq ($(uname_S),Linux)
638640
NO_STRLCPY = YesPlease
641+
NO_MKSTEMPS = YesPlease
639642
THREADED_DELTA_SEARCH = YesPlease
640643
endif
641644
ifeq ($(uname_S),GNU/kFreeBSD)
642645
NO_STRLCPY = YesPlease
646+
NO_MKSTEMPS = YesPlease
643647
THREADED_DELTA_SEARCH = YesPlease
644648
endif
645649
ifeq ($(uname_S),UnixWare)
@@ -651,6 +655,7 @@ ifeq ($(uname_S),UnixWare)
651655
SHELL_PATH = /usr/local/bin/bash
652656
NO_IPV6 = YesPlease
653657
NO_HSTRERROR = YesPlease
658+
NO_MKSTEMPS = YesPlease
654659
BASIC_CFLAGS += -Kthread
655660
BASIC_CFLAGS += -I/usr/local/include
656661
BASIC_LDFLAGS += -L/usr/local/lib
@@ -674,6 +679,7 @@ ifeq ($(uname_S),SCO_SV)
674679
SHELL_PATH = /usr/bin/bash
675680
NO_IPV6 = YesPlease
676681
NO_HSTRERROR = YesPlease
682+
NO_MKSTEMPS = YesPlease
677683
BASIC_CFLAGS += -I/usr/local/include
678684
BASIC_LDFLAGS += -L/usr/local/lib
679685
NO_STRCASESTR = YesPlease
@@ -702,6 +708,7 @@ ifeq ($(uname_S),SunOS)
702708
NO_MEMMEM = YesPlease
703709
NO_HSTRERROR = YesPlease
704710
NO_MKDTEMP = YesPlease
711+
NO_MKSTEMPS = YesPlease
705712
OLD_ICONV = UnfortunatelyYes
706713
ifeq ($(uname_R),5.8)
707714
NO_UNSETENV = YesPlease
@@ -724,6 +731,7 @@ ifeq ($(uname_O),Cygwin)
724731
NO_D_INO_IN_DIRENT = YesPlease
725732
NO_STRCASESTR = YesPlease
726733
NO_MEMMEM = YesPlease
734+
NO_MKSTEMPS = YesPlease
727735
NO_SYMLINK_HEAD = YesPlease
728736
NEEDS_LIBICONV = YesPlease
729737
NO_FAST_WORKING_DIRECTORY = UnfortunatelyYes
@@ -767,11 +775,13 @@ ifeq ($(uname_S),NetBSD)
767775
BASIC_LDFLAGS += -L/usr/pkg/lib $(CC_LD_DYNPATH)/usr/pkg/lib
768776
THREADED_DELTA_SEARCH = YesPlease
769777
USE_ST_TIMESPEC = YesPlease
778+
NO_MKSTEMPS = YesPlease
770779
endif
771780
ifeq ($(uname_S),AIX)
772781
NO_STRCASESTR=YesPlease
773782
NO_MEMMEM = YesPlease
774783
NO_MKDTEMP = YesPlease
784+
NO_MKSTEMPS = YesPlease
775785
NO_STRLCPY = YesPlease
776786
NO_NSEC = YesPlease
777787
FREAD_READS_DIRECTORIES = UnfortunatelyYes
@@ -787,12 +797,14 @@ endif
787797
ifeq ($(uname_S),GNU)
788798
# GNU/Hurd
789799
NO_STRLCPY=YesPlease
800+
NO_MKSTEMPS = YesPlease
790801
endif
791802
ifeq ($(uname_S),IRIX64)
792803
NO_IPV6=YesPlease
793804
NO_SETENV=YesPlease
794805
NO_STRCASESTR=YesPlease
795806
NO_MEMMEM = YesPlease
807+
NO_MKSTEMPS = YesPlease
796808
NO_STRLCPY = YesPlease
797809
NO_SOCKADDR_STORAGE=YesPlease
798810
SHELL_PATH=/usr/gnu/bin/bash
@@ -805,6 +817,7 @@ ifeq ($(uname_S),HP-UX)
805817
NO_SETENV=YesPlease
806818
NO_STRCASESTR=YesPlease
807819
NO_MEMMEM = YesPlease
820+
NO_MKSTEMPS = YesPlease
808821
NO_STRLCPY = YesPlease
809822
NO_MKDTEMP = YesPlease
810823
NO_UNSETENV = YesPlease
@@ -834,6 +847,7 @@ ifneq (,$(findstring MINGW,$(uname_S)))
834847
NO_C99_FORMAT = YesPlease
835848
NO_STRTOUMAX = YesPlease
836849
NO_MKDTEMP = YesPlease
850+
NO_MKSTEMPS = YesPlease
837851
SNPRINTF_RETURNS_BOGUS = YesPlease
838852
NO_SVN_TESTS = YesPlease
839853
NO_PERL_MAKEMAKER = YesPlease
@@ -853,6 +867,7 @@ ifneq (,$(findstring MINGW,$(uname_S)))
853867
endif
854868
ifneq (,$(findstring arm,$(uname_M)))
855869
ARM_SHA1 = YesPlease
870+
NO_MKSTEMPS = YesPlease
856871
endif
857872

858873
-include config.mak.autogen
@@ -1011,6 +1026,10 @@ ifdef NO_MKDTEMP
10111026
COMPAT_CFLAGS += -DNO_MKDTEMP
10121027
COMPAT_OBJS += compat/mkdtemp.o
10131028
endif
1029+
ifdef NO_MKSTEMPS
1030+
COMPAT_CFLAGS += -DNO_MKSTEMPS
1031+
COMPAT_OBJS += compat/mkstemps.o
1032+
endif
10141033
ifdef NO_UNSETENV
10151034
COMPAT_CFLAGS += -DNO_UNSETENV
10161035
COMPAT_OBJS += compat/unsetenv.o

compat/mkstemps.c

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
#include "../git-compat-util.h"
2+
3+
/* Adapted from libiberty's mkstemp.c. */
4+
5+
#undef TMP_MAX
6+
#define TMP_MAX 16384
7+
8+
int gitmkstemps(char *pattern, int suffix_len)
9+
{
10+
static const char letters[] =
11+
"abcdefghijklmnopqrstuvwxyz"
12+
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
13+
"0123456789";
14+
static const int num_letters = 62;
15+
uint64_t value;
16+
struct timeval tv;
17+
char *template;
18+
size_t len;
19+
int fd, count;
20+
21+
len = strlen(pattern);
22+
23+
if (len < 6 + suffix_len) {
24+
errno = EINVAL;
25+
return -1;
26+
}
27+
28+
if (strncmp(&pattern[len - 6 - suffix_len], "XXXXXX", 6)) {
29+
errno = EINVAL;
30+
return -1;
31+
}
32+
33+
/*
34+
* Replace pattern's XXXXXX characters with randomness.
35+
* Try TMP_MAX different filenames.
36+
*/
37+
gettimeofday(&tv, NULL);
38+
value = ((size_t)(tv.tv_usec << 16)) ^ tv.tv_sec ^ getpid();
39+
template = &pattern[len - 6 - suffix_len];
40+
for (count = 0; count < TMP_MAX; ++count) {
41+
uint64_t v = value;
42+
/* Fill in the random bits. */
43+
template[0] = letters[v % num_letters]; v /= num_letters;
44+
template[1] = letters[v % num_letters]; v /= num_letters;
45+
template[2] = letters[v % num_letters]; v /= num_letters;
46+
template[3] = letters[v % num_letters]; v /= num_letters;
47+
template[4] = letters[v % num_letters]; v /= num_letters;
48+
template[5] = letters[v % num_letters]; v /= num_letters;
49+
50+
fd = open(pattern, O_CREAT | O_EXCL | O_RDWR, 0600);
51+
if (fd > 0)
52+
return fd;
53+
/*
54+
* Fatal error (EPERM, ENOSPC etc).
55+
* It doesn't make sense to loop.
56+
*/
57+
if (errno != EEXIST)
58+
break;
59+
/*
60+
* This is a random value. It is only necessary that
61+
* the next TMP_MAX values generated by adding 7777 to
62+
* VALUE are different with (module 2^32).
63+
*/
64+
value += 7777;
65+
}
66+
/* We return the null string if we can't find a unique file name. */
67+
pattern[0] = '\0';
68+
errno = EINVAL;
69+
return -1;
70+
}

config.mak.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ NO_STRTOUMAX=@NO_STRTOUMAX@
4646
NO_SETENV=@NO_SETENV@
4747
NO_UNSETENV=@NO_UNSETENV@
4848
NO_MKDTEMP=@NO_MKDTEMP@
49+
NO_MKSTEMPS=@NO_MKSTEMPS@
4950
NO_ICONV=@NO_ICONV@
5051
OLD_ICONV=@OLD_ICONV@
5152
NO_DEFLATE_BOUND=@NO_DEFLATE_BOUND@

configure.ac

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -677,6 +677,13 @@ GIT_CHECK_FUNC(mkdtemp,
677677
[NO_MKDTEMP=YesPlease])
678678
AC_SUBST(NO_MKDTEMP)
679679
#
680+
# Define NO_MKSTEMPS if you don't have mkstemps in the C library.
681+
GIT_CHECK_FUNC(mkstemps,
682+
[NO_MKSTEMPS=],
683+
[NO_MKSTEMPS=YesPlease])
684+
AC_SUBST(NO_MKSTEMPS)
685+
#
686+
#
680687
# Define NO_MMAP if you want to avoid mmap.
681688
#
682689
# Define NO_ICONV if your libc does not properly support iconv.

git-compat-util.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,11 @@ extern int gitsetenv(const char *, const char *, int);
232232
extern char *gitmkdtemp(char *);
233233
#endif
234234

235+
#ifdef NO_MKSTEMPS
236+
#define mkstemps gitmkstemps
237+
extern int gitmkstemps(char *, int);
238+
#endif
239+
235240
#ifdef NO_UNSETENV
236241
#define unsetenv gitunsetenv
237242
extern void gitunsetenv(const char *);

0 commit comments

Comments
 (0)