diff --git a/configure.ac b/configure.ac index 03f8b95b90cd7..de0852c6d9c21 100644 --- a/configure.ac +++ b/configure.ac @@ -620,6 +620,7 @@ lchown \ memcntl \ memmove \ mkstemp \ +mkstemps \ mmap \ nice \ nl_langinfo \ diff --git a/ext/standard/basic_functions.stub.php b/ext/standard/basic_functions.stub.php index 6fed9c8064a38..1e64e0e51bbb7 100755 --- a/ext/standard/basic_functions.stub.php +++ b/ext/standard/basic_functions.stub.php @@ -2803,7 +2803,7 @@ function rename(string $from, string $to, $context = null): bool {} function copy(string $from, string $to, $context = null): bool {} /** @refcount 1 */ -function tempnam(string $directory, string $prefix): string|false {} +function tempnam(string $directory, string $prefix, string $suffix = ""): string|false {} /** * @return resource|false diff --git a/ext/standard/basic_functions_arginfo.h b/ext/standard/basic_functions_arginfo.h index f325634e95cc1..f8dac8bc33d9a 100644 --- a/ext/standard/basic_functions_arginfo.h +++ b/ext/standard/basic_functions_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: decfa1e3d862d81880ea18150e2ba239bf15b8af */ + * Stub hash: 54b1473734103f0c4045e95eddc84bf2567f1a57 */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_set_time_limit, 0, 1, _IS_BOOL, 0) ZEND_ARG_TYPE_INFO(0, seconds, IS_LONG, 0) @@ -1304,6 +1304,7 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_tempnam, 0, 2, MAY_BE_STRING|MAY_BE_FALSE) ZEND_ARG_TYPE_INFO(0, directory, IS_STRING, 0) ZEND_ARG_TYPE_INFO(0, prefix, IS_STRING, 0) + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, suffix, IS_STRING, 0, "\"\"") ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_tmpfile, 0, 0, 0) diff --git a/ext/standard/file.c b/ext/standard/file.c index 5e835239a8ccd..8556ee700666f 100644 --- a/ext/standard/file.c +++ b/ext/standard/file.c @@ -692,29 +692,36 @@ PHP_FUNCTION(file) /* {{{ Create a unique filename in a directory */ PHP_FUNCTION(tempnam) { - char *dir, *prefix; - size_t dir_len, prefix_len; + char *dir, *prefix, *suffix = ""; + size_t dir_len, prefix_len, suffix_len = 0; zend_string *opened_path; int fd; - zend_string *p; + zend_string *p, *s; - ZEND_PARSE_PARAMETERS_START(2, 2) + ZEND_PARSE_PARAMETERS_START(2, 3) Z_PARAM_PATH(dir, dir_len) Z_PARAM_PATH(prefix, prefix_len) + Z_PARAM_OPTIONAL + Z_PARAM_PATH(suffix, suffix_len) ZEND_PARSE_PARAMETERS_END(); p = php_basename(prefix, prefix_len, NULL, 0); + s = php_basename(suffix, suffix_len, NULL, 0); if (ZSTR_LEN(p) >= 64) { ZSTR_VAL(p)[63] = '\0'; } + if (ZSTR_LEN(s) >= 64) { + ZSTR_VAL(s)[63] = '\0'; + } RETVAL_FALSE; - if ((fd = php_open_temporary_fd_ex(dir, ZSTR_VAL(p), &opened_path, PHP_TMP_FILE_OPEN_BASEDIR_CHECK_ALWAYS)) >= 0) { + if ((fd = php_open_temporary_fd_ex2(dir, ZSTR_VAL(p), ZSTR_VAL(s), &opened_path, PHP_TMP_FILE_OPEN_BASEDIR_CHECK_ALWAYS)) >= 0) { close(fd); RETVAL_STR(opened_path); } zend_string_release_ex(p, 0); + zend_string_release_ex(s, 0); } /* }}} */ diff --git a/ext/standard/tests/file/tempnam_variation10.phpt b/ext/standard/tests/file/tempnam_variation10.phpt new file mode 100644 index 0000000000000..68ac23bc71212 --- /dev/null +++ b/ext/standard/tests/file/tempnam_variation10.phpt @@ -0,0 +1,143 @@ +--TEST-- +Test tempnam() function: usage variations - provide optional suffix +--SKIPIF-- + +--FILE-- +$suffix) { + echo "-- Iteration $i --\n"; + try { + $file_name = tempnam("$file_path", $prefix, $suffix); + } catch (Error $e) { + echo $e->getMessage(), "\n"; + continue; + } + + /* creating the files in existing dir */ + if (file_exists($file_name)) { + echo "File name is => "; + print($file_name); + echo "\n"; + + echo "File permissions are => "; + printf("%o", fileperms($file_name) ); + echo "\n"; + + echo "File created in => "; + $file_dir = dirname($file_name); + + if ($file_dir == sys_get_temp_dir()) { + echo "temp dir\n"; + } + else if ($file_dir == $file_path) { + echo "directory specified\n"; + } + else { + echo "unknown location\n"; + } + + } + else { + echo "-- File is not created --\n"; + } + + unlink($file_name); +} + +rmdir($file_path); +?> +--CLEAN-- + +--EXPECTF-- +*** Testing tempnam() with suffixes *** +-- Iteration 0 -- +File name is => %s%eprefix-%r.{6}%r +File permissions are => 100600 +File created in => directory specified +-- Iteration 1 -- +File name is => %s%eprefix-%r.{6}%rsuffix +File permissions are => 100600 +File created in => directory specified +-- Iteration 2 -- +File name is => %s%eprefix-%r.{6}%r-suffix +File permissions are => 100600 +File created in => directory specified +-- Iteration 3 -- +File name is => %s%eprefix-%r.{6}%r.ext +File permissions are => 100600 +File created in => directory specified +-- Iteration 4 -- +File name is => %s%eprefix-%r.{6}%rdir +File permissions are => 100600 +File created in => directory specified +-- Iteration 5 -- +File name is => %s%eprefix-%r.{6}%rphp +File permissions are => 100600 +File created in => directory specified +-- Iteration 6 -- + +Deprecated: tempnam(): Passing null to parameter #3 ($suffix) of type string is deprecated in %s on line %d +File name is => %s%eprefix-%r.{6}%r +File permissions are => 100600 +File created in => directory specified +-- Iteration 7 -- +File name is => %s%eprefix-%r.{6}%r1 +File permissions are => 100600 +File created in => directory specified +-- Iteration 8 -- +File name is => %s%eprefix-%r.{6}%r0 +File permissions are => 100600 +File created in => directory specified +-- Iteration 9 -- +File name is => %s%eprefix-%r.{6}%r1 +File permissions are => 100600 +File created in => directory specified +-- Iteration 10 -- +File name is => %s%eprefix-%r.{6}%r +File permissions are => 100600 +File created in => directory specified +-- Iteration 11 -- +tempnam(): Argument #3 ($suffix) must be of type string, array given +-- Iteration 12 -- +File name is => %s%eprefix-%r.{6}%r +File permissions are => 100600 +File created in => directory specified +-- Iteration 13 -- +tempnam(): Argument #3 ($suffix) must not contain any null bytes diff --git a/main/php_open_temporary_file.c b/main/php_open_temporary_file.c index dcea78358486d..8426acdbadf0f 100644 --- a/main/php_open_temporary_file.c +++ b/main/php_open_temporary_file.c @@ -84,7 +84,7 @@ * SUCH DAMAGE. */ -static int php_do_open_temporary_file(const char *path, const char *pfx, zend_string **opened_path_p) +static int php_do_open_temporary_file(const char *path, const char *pfx, const char *sfx, zend_string **opened_path_p) { #ifdef PHP_WIN32 char *opened_path = NULL; @@ -97,7 +97,7 @@ static int php_do_open_temporary_file(const char *path, const char *pfx, zend_st char cwd[MAXPATHLEN]; cwd_state new_state; int fd = -1; -#ifndef HAVE_MKSTEMP +#ifndef HAVE_MKSTEMPS int open_flags = O_CREAT | O_TRUNC | O_RDWR #ifdef PHP_WIN32 | _O_BINARY @@ -135,7 +135,7 @@ static int php_do_open_temporary_file(const char *path, const char *pfx, zend_st trailing_slash = "/"; } - if (snprintf(opened_path, MAXPATHLEN, "%s%s%sXXXXXX", new_state.cwd, trailing_slash, pfx) >= MAXPATHLEN) { + if (snprintf(opened_path, MAXPATHLEN, "%s%s%sXXXXXX%s", new_state.cwd, trailing_slash, pfx, sfx) >= MAXPATHLEN) { efree(new_state.cwd); return -1; } @@ -175,8 +175,8 @@ static int php_do_open_temporary_file(const char *path, const char *pfx, zend_st free(cwdw); free(pfxw); -#elif defined(HAVE_MKSTEMP) - fd = mkstemp(opened_path); +#elif defined(HAVE_MKSTEMPS) + fd = mkstemps(opened_path, strlen(sfx)); #else if (mktemp(opened_path)) { fd = VCWD_OPEN(opened_path, open_flags); @@ -283,7 +283,7 @@ PHPAPI const char* php_get_temporary_directory(void) * This function should do its best to return a file pointer to a newly created * unique file, on every platform. */ -PHPAPI int php_open_temporary_fd_ex(const char *dir, const char *pfx, zend_string **opened_path_p, uint32_t flags) +PHPAPI int php_open_temporary_fd_ex2(const char *dir, const char *pfx, const char *sfx, zend_string **opened_path_p, uint32_t flags) { int fd; const char *temp_dir; @@ -291,6 +291,9 @@ PHPAPI int php_open_temporary_fd_ex(const char *dir, const char *pfx, zend_strin if (!pfx) { pfx = "tmp."; } + if (!sfx) { + sfx = ""; + } if (opened_path_p) { *opened_path_p = NULL; } @@ -302,7 +305,7 @@ PHPAPI int php_open_temporary_fd_ex(const char *dir, const char *pfx, zend_strin if (temp_dir && *temp_dir != '\0' && (!(flags & PHP_TMP_FILE_OPEN_BASEDIR_CHECK_ON_FALLBACK) || !php_check_open_basedir(temp_dir))) { - return php_do_open_temporary_file(temp_dir, pfx, opened_path_p); + return php_do_open_temporary_file(temp_dir, pfx, sfx, opened_path_p); } else { return -1; } @@ -313,7 +316,7 @@ PHPAPI int php_open_temporary_fd_ex(const char *dir, const char *pfx, zend_strin } /* Try the directory given as parameter. */ - fd = php_do_open_temporary_file(dir, pfx, opened_path_p); + fd = php_do_open_temporary_file(dir, pfx, sfx, opened_path_p); if (fd == -1) { /* Use default temporary directory. */ if (!(flags & PHP_TMP_FILE_SILENT)) { @@ -324,6 +327,11 @@ PHPAPI int php_open_temporary_fd_ex(const char *dir, const char *pfx, zend_strin return fd; } +PHPAPI int php_open_temporary_fd_ex(const char *dir, const char *pfx, zend_string **opened_path_p, uint32_t flags) +{ + return php_open_temporary_fd_ex2(dir, pfx, NULL, opened_path_p, flags); +} + PHPAPI int php_open_temporary_fd(const char *dir, const char *pfx, zend_string **opened_path_p) { return php_open_temporary_fd_ex(dir, pfx, opened_path_p, PHP_TMP_FILE_DEFAULT); diff --git a/main/php_open_temporary_file.h b/main/php_open_temporary_file.h index 1d8764a7487ed..42dfe5def4e19 100644 --- a/main/php_open_temporary_file.h +++ b/main/php_open_temporary_file.h @@ -31,6 +31,7 @@ BEGIN_EXTERN_C() PHPAPI FILE *php_open_temporary_file(const char *dir, const char *pfx, zend_string **opened_path_p); PHPAPI int php_open_temporary_fd_ex(const char *dir, const char *pfx, zend_string **opened_path_p, uint32_t flags); +PHPAPI int php_open_temporary_fd_ex2(const char *dir, const char *pfx, const char *sfx, zend_string **opened_path_p, uint32_t flags); PHPAPI int php_open_temporary_fd(const char *dir, const char *pfx, zend_string **opened_path_p); PHPAPI const char *php_get_temporary_directory(void); END_EXTERN_C()