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>maint
							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 | ||||
|  |  | |||
|  | @ -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
	
	 David Aguilar
						David Aguilar