Skip to content

Commit d0fcce3

Browse files
committed
ext/posix: adding posix_mkfifoat/posix_mknodat.
The additional directory file descriptor argument allows to operate from a relative path perspective but those new calls can still work with absolute paths.
1 parent 4bc7ea3 commit d0fcce3

File tree

5 files changed

+175
-2
lines changed

5 files changed

+175
-2
lines changed

ext/posix/config.m4

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ if test "$PHP_POSIX" = "yes"; then
88
AC_DEFINE(HAVE_POSIX, 1, [whether to include POSIX-like functions])
99
PHP_NEW_EXTENSION(posix, posix.c, $ext_shared,, -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1)
1010

11-
AC_CHECK_FUNCS(seteuid setegid setsid getsid getpgid ctermid mkfifo mknod setrlimit getrlimit getgroups initgroups getgrgid_r eaccess)
11+
AC_CHECK_FUNCS(seteuid setegid setsid getsid getpgid ctermid mkfifo mknod setrlimit getrlimit getgroups initgroups getgrgid_r eaccess mkfifoat mknodat)
1212

1313
dnl Check for makedev. If it's defined as a macro, AC_CHECK_FUNCS won't work.
1414
dnl Required headers are included by the AC_HEADER_MAJOR logic.

ext/posix/posix.c

+98
Original file line numberDiff line numberDiff line change
@@ -1303,3 +1303,101 @@ PHP_FUNCTION(posix_fpathconf)
13031303
RETURN_LONG(ret);
13041304
}
13051305
#endif
1306+
1307+
#ifdef HAVE_MKFIFOAT
1308+
PHP_FUNCTION(posix_mkfifoat)
1309+
{
1310+
zend_string *path;
1311+
zend_long mode, fd = 0;
1312+
zval *z_fd;
1313+
int result;
1314+
1315+
ZEND_PARSE_PARAMETERS_START(3, 3)
1316+
Z_PARAM_ZVAL(z_fd)
1317+
Z_PARAM_PATH_STR(path)
1318+
Z_PARAM_LONG(mode)
1319+
ZEND_PARSE_PARAMETERS_END();
1320+
1321+
if (Z_TYPE_P(z_fd) == IS_RESOURCE) {
1322+
if (!php_posix_stream_get_fd(z_fd, &fd)) {
1323+
RETURN_FALSE;
1324+
}
1325+
} else {
1326+
if (!zend_parse_arg_long(z_fd, &fd, /* is_null */ NULL, /* check_null */ false, /* arg_num */ 1)) {
1327+
zend_argument_type_error(1, "must be of type int|resource, %s given",
1328+
zend_zval_value_name(z_fd));
1329+
RETURN_THROWS();
1330+
}
1331+
}
1332+
1333+
if (php_check_open_basedir_ex(ZSTR_VAL(path), 0)) {
1334+
RETURN_FALSE;
1335+
}
1336+
1337+
result = mkfifoat(fd, ZSTR_VAL(path), mode);
1338+
if (result < 0) {
1339+
POSIX_G(last_error) = errno;
1340+
RETURN_FALSE;
1341+
}
1342+
1343+
RETURN_TRUE;
1344+
}
1345+
#endif
1346+
1347+
#ifdef HAVE_MKNODAT
1348+
PHP_FUNCTION(posix_mknodat)
1349+
{
1350+
zend_string *path;
1351+
zend_long mode, fd = 0;
1352+
zend_long major = 0, minor = 0;
1353+
zval *z_fd;
1354+
int result;
1355+
dev_t php_dev = 0;
1356+
1357+
ZEND_PARSE_PARAMETERS_START(3, 5)
1358+
Z_PARAM_ZVAL(z_fd)
1359+
Z_PARAM_PATH_STR(path)
1360+
Z_PARAM_LONG(mode)
1361+
Z_PARAM_OPTIONAL
1362+
Z_PARAM_LONG(major)
1363+
Z_PARAM_LONG(minor)
1364+
ZEND_PARSE_PARAMETERS_END();
1365+
1366+
if (Z_TYPE_P(z_fd) == IS_RESOURCE) {
1367+
if (!php_posix_stream_get_fd(z_fd, &fd)) {
1368+
RETURN_FALSE;
1369+
}
1370+
} else {
1371+
if (!zend_parse_arg_long(z_fd, &fd, /* is_null */ NULL, /* check_null */ false, /* arg_num */ 1)) {
1372+
zend_argument_type_error(1, "must be of type int|resource, %s given",
1373+
zend_zval_value_name(z_fd));
1374+
RETURN_THROWS();
1375+
}
1376+
}
1377+
1378+
if (php_check_open_basedir_ex(ZSTR_VAL(path), 0)) {
1379+
RETURN_FALSE;
1380+
}
1381+
1382+
if ((mode & S_IFCHR) || (mode & S_IFBLK)) {
1383+
if (major == 0) {
1384+
zend_argument_value_error(4, "cannot be 0 for the POSIX_S_IFCHR and POSIX_S_IFBLK modes");
1385+
RETURN_THROWS();
1386+
} else {
1387+
#ifdef HAVE_MAKEDEV
1388+
php_dev = makedev(major, minor);
1389+
#else
1390+
zend_value_error("Cannot create a block or character device, creating a normal file instead");
1391+
#endif
1392+
}
1393+
}
1394+
1395+
result = mknodat(fd, ZSTR_VAL(path), mode, php_dev);
1396+
if (result < 0) {
1397+
POSIX_G(last_error) = errno;
1398+
RETURN_FALSE;
1399+
}
1400+
1401+
RETURN_TRUE;
1402+
}
1403+
#endif

ext/posix/posix.stub.php

+10
Original file line numberDiff line numberDiff line change
@@ -454,3 +454,13 @@ function posix_pathconf(string $path, int $name): int|false {}
454454
/** @param resource|int $file_descriptor */
455455
function posix_fpathconf($file_descriptor, int $name): int|false {}
456456
#endif
457+
458+
#ifdef HAVE_MKFIFOAT
459+
/** @param resource|int $file_descriptor */
460+
function posix_mkfifoat($file_descriptor, string $path, int $permissions): bool {}
461+
#endif
462+
463+
#ifdef HAVE_MKNODAT
464+
/** @param resource|int $file_descriptor */
465+
function posix_mknodat($file_descriptor, string $path, int $flags, int $major = 0, int $minor = 0): bool {}
466+
#endif

ext/posix/posix_arginfo.h

+31-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
--TEST--
2+
posix_mknodat/posix_mkfifoat support
3+
--EXTENSIONS--
4+
posix
5+
--SKIPIF--
6+
<?php
7+
if (!function_exists('posix_mknodat')) die('skip posix_mknodat() not found');
8+
?>
9+
--FILE--
10+
<?php
11+
12+
$fd = fopen(__DIR__, "r");
13+
var_dump(posix_mknodat($fd, '', POSIX_S_IFBLK | 0777, 1, 0));
14+
var_dump(posix_mknodat($fd, __DIR__ . '', POSIX_S_IFBLK | 0777, 1, 0));
15+
try {
16+
posix_mknodat($fd, __DIR__ . '/dev/', POSIX_S_IFBLK | 0777, 0, 0);
17+
} catch (\ValueError $e) {
18+
echo $e->getMessage() . PHP_EOL;
19+
}
20+
var_dump(posix_mkfifoat($fd, '', POSIX_S_IFBLK | 0777));
21+
var_dump(posix_mkfifoat($fd, __DIR__ . '', POSIX_S_IFBLK | 0777));
22+
try {
23+
posix_mkfifoat(new stdClass(), '/dev/', POSIX_S_IFBLK | 0777);
24+
} catch (TypeError $e) {
25+
echo $e->getMessage();
26+
}
27+
fclose($fd);
28+
?>
29+
--EXPECT--
30+
bool(false)
31+
bool(false)
32+
posix_mknodat(): Argument #4 ($major) cannot be 0 for the POSIX_S_IFCHR and POSIX_S_IFBLK modes
33+
bool(false)
34+
bool(false)
35+
posix_mkfifoat(): Argument #1 ($file_descriptor) must be of type int|resource, stdClass given

0 commit comments

Comments
 (0)