Skip to content

Commit 613e8d7

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 fd73681 commit 613e8d7

File tree

5 files changed

+184
-2
lines changed

5 files changed

+184
-2
lines changed

ext/posix/config.m4

Lines changed: 1 addition & 1 deletion
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

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

ext/posix/posix.stub.php

Lines changed: 10 additions & 0 deletions
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

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

0 commit comments

Comments
 (0)