Skip to content

Commit 80e33b5

Browse files
committed
Support optional suffix arg in tempnam
1 parent b24b351 commit 80e33b5

7 files changed

+167
-15
lines changed

configure.ac

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -618,6 +618,7 @@ lchown \
618618
memcntl \
619619
memmove \
620620
mkstemp \
621+
mkstemps \
621622
mmap \
622623
nice \
623624
nl_langinfo \

ext/standard/basic_functions.stub.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2799,7 +2799,7 @@ function rename(string $from, string $to, $context = null): bool {}
27992799
function copy(string $from, string $to, $context = null): bool {}
28002800

28012801
/** @refcount 1 */
2802-
function tempnam(string $directory, string $prefix): string|false {}
2802+
function tempnam(string $directory, string $prefix, string $suffix = ""): string|false {}
28032803

28042804
/**
28052805
* @return resource|false

ext/standard/basic_functions_arginfo.h

Lines changed: 2 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ext/standard/file.c

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -692,29 +692,36 @@ PHP_FUNCTION(file)
692692
/* {{{ Create a unique filename in a directory */
693693
PHP_FUNCTION(tempnam)
694694
{
695-
char *dir, *prefix;
696-
size_t dir_len, prefix_len;
695+
char *dir, *prefix, *suffix = "";
696+
size_t dir_len, prefix_len, suffix_len = 0;
697697
zend_string *opened_path;
698698
int fd;
699-
zend_string *p;
699+
zend_string *p, *s;
700700

701-
ZEND_PARSE_PARAMETERS_START(2, 2)
701+
ZEND_PARSE_PARAMETERS_START(2, 3)
702702
Z_PARAM_PATH(dir, dir_len)
703703
Z_PARAM_PATH(prefix, prefix_len)
704+
Z_PARAM_OPTIONAL
705+
Z_PARAM_PATH(suffix, suffix_len)
704706
ZEND_PARSE_PARAMETERS_END();
705707

706708
p = php_basename(prefix, prefix_len, NULL, 0);
709+
s = php_basename(suffix, suffix_len, NULL, 0);
707710
if (ZSTR_LEN(p) > 64) {
708711
ZSTR_VAL(p)[63] = '\0';
709712
}
713+
if (ZSTR_LEN(s) > 64) {
714+
ZSTR_VAL(s)[63] = '\0';
715+
}
710716

711717
RETVAL_FALSE;
712718

713-
if ((fd = php_open_temporary_fd_ex(dir, ZSTR_VAL(p), &opened_path, PHP_TMP_FILE_OPEN_BASEDIR_CHECK_ALWAYS)) >= 0) {
719+
if ((fd = php_open_temporary_fd_ex2(dir, ZSTR_VAL(p), ZSTR_VAL(s), &opened_path, PHP_TMP_FILE_OPEN_BASEDIR_CHECK_ALWAYS)) >= 0) {
714720
close(fd);
715721
RETVAL_STR(opened_path);
716722
}
717723
zend_string_release_ex(p, 0);
724+
zend_string_release_ex(s, 0);
718725
}
719726
/* }}} */
720727

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
--TEST--
2+
Test tempnam() function: usage variations - provide optional suffix
3+
--SKIPIF--
4+
<?php
5+
if(substr(PHP_OS, 0, 3) == "WIN")
6+
die("skip Do not run on Windows");
7+
?>
8+
--FILE--
9+
<?php
10+
/* Passing the optional $suffix arg */
11+
12+
echo "*** Testing tempnam() with suffixes ***\n";
13+
$file_path = __DIR__."/tempnamVar9";
14+
mkdir($file_path);
15+
$prefix = "prefix-";
16+
17+
/* An array of suffixes */
18+
$names_arr = array(
19+
"",
20+
"suffix",
21+
"-suffix",
22+
".ext",
23+
/* suffix with path separators should get basename to be consistent
24+
* with the prefix behavior */
25+
"/no/such/file/dir",
26+
"php/php",
27+
NULL,
28+
1,
29+
0,
30+
TRUE,
31+
FALSE,
32+
array(),
33+
" ",
34+
"\0",
35+
);
36+
37+
for ($i=0; $i<count($names_arr); $i++) {
38+
echo "-- Iteration $i --\n";
39+
try {
40+
$file_name = tempnam("$file_path", $prefix, $names_arr[$i]);
41+
} catch (Error $e) {
42+
echo $e->getMessage(), "\n";
43+
continue;
44+
}
45+
46+
/* creating the files in existing dir */
47+
if (file_exists($file_name)) {
48+
echo "File name is => ";
49+
print($file_name);
50+
echo "\n";
51+
52+
echo "File permissions are => ";
53+
printf("%o", fileperms($file_name) );
54+
echo "\n";
55+
56+
echo "File created in => ";
57+
$file_dir = dirname($file_name);
58+
59+
if ($file_dir == sys_get_temp_dir()) {
60+
echo "temp dir\n";
61+
}
62+
else if ($file_dir == $file_path) {
63+
echo "directory specified\n";
64+
}
65+
else {
66+
echo "unknown location\n";
67+
}
68+
69+
}
70+
else {
71+
echo "-- File is not created --\n";
72+
}
73+
74+
unlink($file_name);
75+
}
76+
77+
rmdir($file_path);
78+
?>
79+
--EXPECTF--
80+
*** Testing tempnam() with suffixes ***
81+
-- Iteration 0 --
82+
File name is => %s%eprefix-%r.{6}%r
83+
File permissions are => 100600
84+
File created in => directory specified
85+
-- Iteration 1 --
86+
File name is => %s%eprefix-%r.{6}%rsuffix
87+
File permissions are => 100600
88+
File created in => directory specified
89+
-- Iteration 2 --
90+
File name is => %s%eprefix-%r.{6}%r-suffix
91+
File permissions are => 100600
92+
File created in => directory specified
93+
-- Iteration 3 --
94+
File name is => %s%eprefix-%r.{6}%r.ext
95+
File permissions are => 100600
96+
File created in => directory specified
97+
-- Iteration 4 --
98+
File name is => %s%eprefix-%r.{6}%rdir
99+
File permissions are => 100600
100+
File created in => directory specified
101+
-- Iteration 5 --
102+
File name is => %s%eprefix-%r.{6}%rphp
103+
File permissions are => 100600
104+
File created in => directory specified
105+
-- Iteration 6 --
106+
107+
Deprecated: tempnam(): Passing null to parameter #3 ($suffix) of type string is deprecated in %s on line %d
108+
File name is => %s%eprefix-%r.{6}%r
109+
File permissions are => 100600
110+
File created in => directory specified
111+
-- Iteration 7 --
112+
File name is => %s%eprefix-%r.{6}%r1
113+
File permissions are => 100600
114+
File created in => directory specified
115+
-- Iteration 8 --
116+
File name is => %s%eprefix-%r.{6}%r0
117+
File permissions are => 100600
118+
File created in => directory specified
119+
-- Iteration 9 --
120+
File name is => %s%eprefix-%r.{6}%r1
121+
File permissions are => 100600
122+
File created in => directory specified
123+
-- Iteration 10 --
124+
File name is => %s%eprefix-%r.{6}%r
125+
File permissions are => 100600
126+
File created in => directory specified
127+
-- Iteration 11 --
128+
tempnam(): Argument #3 ($suffix) must be of type string, array given
129+
-- Iteration 12 --
130+
File name is => %s%eprefix-%r.{6}%r
131+
File permissions are => 100600
132+
File created in => directory specified
133+
-- Iteration 13 --
134+
tempnam(): Argument #3 ($suffix) must not contain any null bytes

main/php_open_temporary_file.c

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@
8484
* SUCH DAMAGE.
8585
*/
8686

87-
static int php_do_open_temporary_file(const char *path, const char *pfx, zend_string **opened_path_p)
87+
static int php_do_open_temporary_file(const char *path, const char *pfx, const char *sfx, zend_string **opened_path_p)
8888
{
8989
#ifdef PHP_WIN32
9090
char *opened_path = NULL;
@@ -97,7 +97,7 @@ static int php_do_open_temporary_file(const char *path, const char *pfx, zend_st
9797
char cwd[MAXPATHLEN];
9898
cwd_state new_state;
9999
int fd = -1;
100-
#ifndef HAVE_MKSTEMP
100+
#ifndef HAVE_MKSTEMPS
101101
int open_flags = O_CREAT | O_TRUNC | O_RDWR
102102
#ifdef PHP_WIN32
103103
| _O_BINARY
@@ -135,7 +135,7 @@ static int php_do_open_temporary_file(const char *path, const char *pfx, zend_st
135135
trailing_slash = "/";
136136
}
137137

138-
if (snprintf(opened_path, MAXPATHLEN, "%s%s%sXXXXXX", new_state.cwd, trailing_slash, pfx) >= MAXPATHLEN) {
138+
if (snprintf(opened_path, MAXPATHLEN, "%s%s%sXXXXXX%s", new_state.cwd, trailing_slash, pfx, sfx) >= MAXPATHLEN) {
139139
efree(new_state.cwd);
140140
return -1;
141141
}
@@ -175,8 +175,8 @@ static int php_do_open_temporary_file(const char *path, const char *pfx, zend_st
175175

176176
free(cwdw);
177177
free(pfxw);
178-
#elif defined(HAVE_MKSTEMP)
179-
fd = mkstemp(opened_path);
178+
#elif defined(HAVE_MKSTEMPS)
179+
fd = mkstemps(opened_path, strlen(sfx));
180180
#else
181181
if (mktemp(opened_path)) {
182182
fd = VCWD_OPEN(opened_path, open_flags);
@@ -283,14 +283,17 @@ PHPAPI const char* php_get_temporary_directory(void)
283283
* This function should do its best to return a file pointer to a newly created
284284
* unique file, on every platform.
285285
*/
286-
PHPAPI int php_open_temporary_fd_ex(const char *dir, const char *pfx, zend_string **opened_path_p, uint32_t flags)
286+
PHPAPI int php_open_temporary_fd_ex2(const char *dir, const char *pfx, const char *sfx, zend_string **opened_path_p, uint32_t flags)
287287
{
288288
int fd;
289289
const char *temp_dir;
290290

291291
if (!pfx) {
292292
pfx = "tmp.";
293293
}
294+
if (!sfx) {
295+
sfx = "";
296+
}
294297
if (opened_path_p) {
295298
*opened_path_p = NULL;
296299
}
@@ -302,7 +305,7 @@ PHPAPI int php_open_temporary_fd_ex(const char *dir, const char *pfx, zend_strin
302305
if (temp_dir &&
303306
*temp_dir != '\0' &&
304307
(!(flags & PHP_TMP_FILE_OPEN_BASEDIR_CHECK_ON_FALLBACK) || !php_check_open_basedir(temp_dir))) {
305-
return php_do_open_temporary_file(temp_dir, pfx, opened_path_p);
308+
return php_do_open_temporary_file(temp_dir, pfx, sfx, opened_path_p);
306309
} else {
307310
return -1;
308311
}
@@ -313,7 +316,7 @@ PHPAPI int php_open_temporary_fd_ex(const char *dir, const char *pfx, zend_strin
313316
}
314317

315318
/* Try the directory given as parameter. */
316-
fd = php_do_open_temporary_file(dir, pfx, opened_path_p);
319+
fd = php_do_open_temporary_file(dir, pfx, sfx, opened_path_p);
317320
if (fd == -1) {
318321
/* Use default temporary directory. */
319322
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
324327
return fd;
325328
}
326329

330+
PHPAPI int php_open_temporary_fd_ex(const char *dir, const char *pfx, zend_string **opened_path_p, uint32_t flags)
331+
{
332+
return php_open_temporary_fd_ex2(dir, pfx, NULL, opened_path_p, flags);
333+
}
334+
327335
PHPAPI int php_open_temporary_fd(const char *dir, const char *pfx, zend_string **opened_path_p)
328336
{
329337
return php_open_temporary_fd_ex(dir, pfx, opened_path_p, PHP_TMP_FILE_DEFAULT);

main/php_open_temporary_file.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
BEGIN_EXTERN_C()
3232
PHPAPI FILE *php_open_temporary_file(const char *dir, const char *pfx, zend_string **opened_path_p);
3333
PHPAPI int php_open_temporary_fd_ex(const char *dir, const char *pfx, zend_string **opened_path_p, uint32_t flags);
34+
PHPAPI int php_open_temporary_fd_ex2(const char *dir, const char *pfx, const char *sfx, zend_string **opened_path_p, uint32_t flags);
3435
PHPAPI int php_open_temporary_fd(const char *dir, const char *pfx, zend_string **opened_path_p);
3536
PHPAPI const char *php_get_temporary_directory(void);
3637
END_EXTERN_C()

0 commit comments

Comments
 (0)