--- IO-AIO/AIO.xs 2018/08/14 14:03:14 1.266 +++ IO-AIO/AIO.xs 2022/09/25 16:30:51 1.297 @@ -5,6 +5,7 @@ #include "EXTERN.h" #include "perl.h" #include "XSUB.h" +#include "perliol.h" #if !defined mg_findext # define mg_findext(sv,type,vtbl) mg_find (sv, type) @@ -20,30 +21,6 @@ #include #include -#if HAVE_SYS_MKDEV_H -# include -#elif HAVE_SYS_SYSMACROS_H -# include -#endif - -#if _POSIX_MEMLOCK || _POSIX_MEMLOCK_RANGE || _POSIX_MAPPED_FILES -# include -#endif - -/* the incompetent fool that created musl keeps __linux__, refuses - * to implement any linux standard apis, and also has no way to test - * for his broken iplementation. don't complain to me if this fails - * for you. - */ -#if __linux__ && (defined __GLIBC__ || defined __UCLIBC__) -# include -# ifdef FS_IOC_FIEMAP -# include -# include -# define HAVE_FIEMAP 1 -# endif -#endif - /* perl namespace pollution */ #undef VERSION @@ -86,6 +63,7 @@ #undef dup2 #undef abort #undef pipe + #undef utime #define EIO_STRUCT_STAT struct _stati64 #define EIO_STRUCT_STATI64 @@ -94,6 +72,7 @@ #include #include + #include #include #include #include @@ -117,6 +96,42 @@ #include "config.h" +#if HAVE_SYS_MKDEV_H +# include +#elif HAVE_SYS_SYSMACROS_H +# include +#endif + +#if _POSIX_MEMLOCK || _POSIX_MEMLOCK_RANGE || _POSIX_MAPPED_FILES +# include +#endif + +#if HAVE_SYS_UIO_H +# include +#endif + +/* MUST be included before linux/fs.h, as the latter includes + * linux/mount.h, which is incompatible to sys/mount.h + */ +#if HAVE_SYS_MOUNT_H +# include +#endif + +/* the incompetent fool that created musl keeps __linux__, refuses + * to implement any linux standard apis, and also has no way to test + * for his broken implementation. don't complain to me if this fails + * for you. + */ +#if __linux__ && (defined __GLIBC__ || defined __UCLIBC__) +# include /* MUST be included after sys/mount.h */ +# ifdef FS_IOC_FIEMAP +# include +# include +# undef HAVE_FIEMAP +# define HAVE_FIEMAP 1 +# endif +#endif + #if HAVE_ST_XTIMENSEC # define ATIMENSEC PL_statcache.st_atimensec # define MTIMENSEC PL_statcache.st_mtimensec @@ -131,6 +146,23 @@ # define CTIMENSEC 0 #endif +#if HAVE_ST_BIRTHTIMENSEC +# define BTIMESEC PL_statcache.st_birthtime +# define BTIMENSEC PL_statcache.st_birthtimensec +#elif HAVE_ST_BIRTHTIMESPEC +# define BTIMESEC PL_statcache.st_birthtim.tv_sec +# define BTIMENSEC PL_statcache.st_birthtim.tv_nsec +#else +# define BTIMESEC 0 +# define BTIMENSEC 0 +#endif + +#if HAVE_ST_GEN +# define ST_GEN PL_statcache.st_gen +#else +# define ST_GEN 0 +#endif + #include "schmorp.h" #if HAVE_EVENTFD @@ -147,6 +179,8 @@ #endif typedef SV SV8; /* byte-sv, used for argument-checking */ +typedef char *octet_string; +typedef char *octet_string_ornull; typedef int aio_rfd; /* read file desriptor */ typedef int aio_wfd; /* write file descriptor */ @@ -205,6 +239,17 @@ # define PAGESIZE sysconf (_SC_PAGESIZE) #endif +/* solaris perl seems to declare a wrong syscall function that clashes with system includes */ +#ifdef __sun +# undef HAVE_SYSCALL +#endif + +#if HAVE_SYSCALL +#include +#else +# define syscall(nr,...) (errno = ENOSYS, -1) +#endif + /*****************************************************************************/ #if !_POSIX_MAPPED_FILES @@ -272,6 +317,7 @@ /*****************************************************************************/ /* helper: set scalar to foreign ptr with custom free */ +ecb_noinline static void sv_set_foreign (SV *sv, const MGVTBL *const vtbl, void *addr, IV length) { @@ -322,7 +368,7 @@ req->flags |= EIO_FLAG_PTR1_FREE; /* heuristic: start with 512 bytes (8 extents), and if that isn't enough, */ - /* increase in 3.5kb steps */ + /* increase in fixed steps */ if (count < 0) count = 8; @@ -385,11 +431,11 @@ { struct fiemap_extent *e = incmap->fm_extents + count; - if (e->fe_logical + e->fe_length >= end_offset) - goto done; - fiemap->fm_extents [fiemap->fm_mapped_extents++] = *e; + if (e->fe_logical >= end_offset) + goto done; + if (e->fe_flags & FIEMAP_EXTENT_LAST) goto done; @@ -406,6 +452,17 @@ /*****************************************************************************/ +static int close_fd; /* dummy fd to close fds via dup2 */ + +#if HAVE_STATX +static struct statx stx; +#define statx_offsetof(member) offsetof (struct statx, member) +#define eio__statx statx +#else +#define statx_offsetof(member) 0 +#define eio__statx(dir,path,flags,mask,stx) EIO_ENOSYS() +#endif + enum { FLAG_SV2_RO_OFF = 0x40, /* data was set readonly */ }; @@ -438,6 +495,7 @@ } /* must be called at most once */ +ecb_noinline static SV * req_sv (aio_req req, HV *stash) { @@ -456,6 +514,7 @@ return sv_bless (newRV_noinc (newSViv ((intptr_t)wd)), aio_wd_stash); } +ecb_noinline static aio_req SvAIO_REQ (SV *sv) { @@ -528,6 +587,7 @@ } } +ecb_noinline static void req_submit (eio_req *req) { @@ -798,6 +858,12 @@ PUSHs (sv_result); break; +#if 0 + case EIO_CLOSE: + PerlIOUnix_refcnt_dec (req->int1); + break; +#endif + case EIO_DUP2: /* EIO_DUP2 actually means aio_close(), so fudge result value */ if (req->result > 0) SvIV_set (sv_result, 0); @@ -858,7 +924,8 @@ eio_grp_cancel (grp); } -static void ecb_cold +ecb_cold +static void create_respipe (void) { if (s_epipe_renew (&respipe)) @@ -902,7 +969,8 @@ } } -static void ecb_cold +ecb_cold +static void reinit (void) { create_respipe (); @@ -920,6 +988,7 @@ return SvOK (cb_sv) ? s_get_cv_croak (cb_sv) : 0; } +ecb_noinline static aio_req ecb_noinline dreq (SV *callback) { @@ -951,8 +1020,10 @@ if (GIMME_V != G_VOID) \ XPUSHs (req_sv (req, aio_req_stash)); -ecb_inline void -req_set_path (aio_req req, SV *path, SV **wdsv, SV **pathsv, eio_wd *wd, void **ptr) +/* *wdsv, *pathsv, *wd and *ptr must be 0-initialized */ +ecb_inline +void +req_set_path (SV *path, SV **wdsv, SV **pathsv, eio_wd *wd, void **ptr) { if (expect_false (SvROK (path))) { @@ -987,13 +1058,15 @@ *ptr = SvPVbyte_nolen (*pathsv); } -static void ecb_noinline +ecb_noinline +static void req_set_path1 (aio_req req, SV *path) { - req_set_path (req, path, &req->sv1, &req->sv3, &req->wd, &req->ptr1); + req_set_path (path, &req->sv1, &req->sv3, &req->wd, &req->ptr1); } -static void ecb_noinline +ecb_noinline +static void req_set_fh_or_path (aio_req req, int type_path, int type_fh, SV *fh_or_path) { SV *rv = SvROK (fh_or_path) ? SvRV (fh_or_path) : fh_or_path; @@ -1032,6 +1105,34 @@ /*****************************************************************************/ +/* extract a ref-to-array of strings into a temporary c style string vector */ +static char ** +extract_stringvec (SV *sv, const char *croakmsg) +{ + if (!SvROK (sv) || SvTYPE (SvRV (sv)) != SVt_PVAV) + croak ("%s", croakmsg); + + AV *av = (AV *)SvRV (sv); + int i, nelem = av_len (av) + 1; + char **vecp = (char **)SvPVX (sv_2mortal (newSV (sizeof (char *) * (nelem + 1)))); + + for (i = 0; i < nelem; ++i) + { + SV **e = av_fetch (av, i, 0); + + if (e && *e) + vecp[i] = SvPVbyte_nolen (*e); + else + vecp[i] = ""; + } + + vecp[nelem] = 0; + + return vecp; +} + +/*****************************************************************************/ + XS(boot_IO__AIO) ecb_cold; MODULE = IO::AIO PACKAGE = IO::AIO @@ -1142,15 +1243,26 @@ const_iv (MAP_32BIT) const_iv (MAP_HUGETLB) const_iv (MAP_STACK) + const_iv (MAP_FIXED_NOREPLACE) + const_iv (MAP_SHARED_VALIDATE) + const_iv (MAP_SYNC) + const_iv (MAP_UNINITIALIZED) const_iv (MREMAP_MAYMOVE) const_iv (MREMAP_FIXED) - const_iv (F_DUPFD_CLOEXEC) - const_iv (MSG_CMSG_CLOEXEC) const_iv (SOCK_CLOEXEC) + const_iv (F_DUPFD_CLOEXEC) + + const_iv (F_ADD_SEALS) + const_iv (F_GET_SEALS) + const_iv (F_SEAL_SEAL) + const_iv (F_SEAL_SHRINK) + const_iv (F_SEAL_GROW) + const_iv (F_SEAL_WRITE) + const_iv (F_OFD_GETLK) const_iv (F_OFD_SETLK) const_iv (F_OFD_GETLKW) @@ -1236,6 +1348,12 @@ const_iv (EFD_NONBLOCK) const_iv (EFD_SEMAPHORE) + const_iv (MFD_CLOEXEC) + const_iv (MFD_ALLOW_SEALING) + const_iv (MFD_HUGETLB) + const_iv (MFD_HUGETLB_2MB) + const_iv (MFD_HUGETLB_1GB) + const_iv (CLOCK_REALTIME) const_iv (CLOCK_MONOTONIC) const_iv (CLOCK_BOOTTIME) @@ -1248,6 +1366,133 @@ const_iv (TFD_TIMER_ABSTIME) const_iv (TFD_TIMER_CANCEL_ON_SET) + const_iv (STATX_TYPE) + const_iv (STATX_MODE) + const_iv (STATX_NLINK) + const_iv (STATX_UID) + const_iv (STATX_GID) + const_iv (STATX_ATIME) + const_iv (STATX_MTIME) + const_iv (STATX_CTIME) + const_iv (STATX_INO) + const_iv (STATX_SIZE) + const_iv (STATX_BLOCKS) + const_iv (STATX_BASIC_STATS) + const_iv (STATX_ALL) + const_iv (STATX_BTIME) + const_iv (STATX_ATTR_COMPRESSED) + const_iv (STATX_ATTR_IMMUTABLE) + const_iv (STATX_ATTR_APPEND) + const_iv (STATX_ATTR_NODUMP) + const_iv (STATX_ATTR_ENCRYPTED) + const_iv (STATX_ATTR_AUTOMOUNT) + + const_iv (AT_FDCWD) + const_iv (AT_SYMLINK_NOFOLLOW) + const_iv (AT_EACCESS) + const_iv (AT_REMOVEDIR) + const_iv (AT_SYMLINK_FOLLOW) + const_iv (AT_NO_AUTOMOUNT) + const_iv (AT_EMPTY_PATH) + const_iv (AT_STATX_SYNC_TYPE) + const_iv (AT_STATX_AS_STAT) + const_iv (AT_STATX_FORCE_SYNC) + const_iv (AT_STATX_DONT_SYNC) + const_iv (AT_RECURSIVE) + + const_iv (OPEN_TREE_CLONE) + + const_iv (FSOPEN_CLOEXEC) + + const_iv (FSPICK_CLOEXEC) + const_iv (FSPICK_SYMLINK_NOFOLLOW) + const_iv (FSPICK_NO_AUTOMOUNT) + const_iv (FSPICK_EMPTY_PATH) + + const_iv (MOVE_MOUNT_F_SYMLINKS) + const_iv (MOVE_MOUNT_F_AUTOMOUNTS) + const_iv (MOVE_MOUNT_F_EMPTY_PATH) + const_iv (MOVE_MOUNT_T_SYMLINKS) + const_iv (MOVE_MOUNT_T_AUTOMOUNTS) + const_iv (MOVE_MOUNT_T_EMPTY_PATH) + + /* waitid */ + const_iv (P_PID) + const_iv (P_PIDFD) + const_iv (P_PGID) + const_iv (P_ALL) + + const_iv (FSCONFIG_SET_FLAG) + const_iv (FSCONFIG_SET_STRING) + const_iv (FSCONFIG_SET_BINARY) + const_iv (FSCONFIG_SET_PATH) + const_iv (FSCONFIG_SET_PATH_EMPTY) + const_iv (FSCONFIG_SET_FD) + const_iv (FSCONFIG_CMD_CREATE) + const_iv (FSCONFIG_CMD_RECONFIGURE) + + const_iv (MOUNT_ATTR_RDONLY) + const_iv (MOUNT_ATTR_NOSUID) + const_iv (MOUNT_ATTR_NODEV) + const_iv (MOUNT_ATTR_NOEXEC) + const_iv (MOUNT_ATTR__ATIME) + const_iv (MOUNT_ATTR_RELATIME) + const_iv (MOUNT_ATTR_NOATIME) + const_iv (MOUNT_ATTR_STRICTATIME) + const_iv (MOUNT_ATTR_NODIRATIME) + + /* sys/mount.h */ + const_iv (MS_RDONLY) + const_iv (MS_NOSUID) + const_iv (MS_NODEV) + const_iv (MS_NOEXEC) + const_iv (MS_SYNCHRONOUS) + const_iv (MS_REMOUNT) + const_iv (MS_MANDLOCK) + const_iv (MS_DIRSYNC) + const_iv (MS_NOATIME) + const_iv (MS_NODIRATIME) + const_iv (MS_BIND) + const_iv (MS_MOVE) + const_iv (MS_REC) + const_iv (MS_SILENT) + const_iv (MS_POSIXACL) + const_iv (MS_UNBINDABLE) + const_iv (MS_PRIVATE) + const_iv (MS_SLAVE) + const_iv (MS_SHARED) + const_iv (MS_RELATIME) + const_iv (MS_KERNMOUNT) + const_iv (MS_I_VERSION) + const_iv (MS_STRICTATIME) + const_iv (MS_LAZYTIME) + const_iv (MS_ACTIVE) + const_iv (MS_NOUSER) + const_iv (MS_RMT_MASK) + const_iv (MS_MGC_VAL) + const_iv (MS_MGC_MSK) + + const_iv (MNT_FORCE) + const_iv (MNT_DETACH) + const_iv (MNT_EXPIRE) + const_iv (UMOUNT_NOFOLLOW) + + const_iv (BLKROSET) + const_iv (BLKROGET) + const_iv (BLKRRPART) + const_iv (BLKGETSIZE) + const_iv (BLKFLSBUF) + const_iv (BLKRASET) + const_iv (BLKRAGET) + const_iv (BLKFRASET) + const_iv (BLKFRAGET) + const_iv (BLKSECTSET) + const_iv (BLKSECTGET) + const_iv (BLKSSZGET) + const_iv (BLKBSZGET) + const_iv (BLKBSZSET) + const_iv (BLKGETSIZE64) + /* these are libeio constants, and are independent of gendef0 */ const_eio (SEEK_SET) const_eio (SEEK_CUR) @@ -1255,6 +1500,7 @@ const_eio (MCL_FUTURE) const_eio (MCL_CURRENT) + const_eio (MCL_ONFAULT) const_eio (MS_ASYNC) const_eio (MS_INVALIDATE) @@ -1303,6 +1549,24 @@ newCONSTSUB (aio_stash, "PAGESIZE", newSViv (PAGESIZE)); + /* allocate dummy pipe fd for aio_close */ + { + int pipefd [2]; + + if ( +#ifdef _WIN32 + _pipe (pipefd, 1, _O_BINARY) < 0 +#else + pipe (pipefd) < 0 + || fcntl (pipefd [0], F_SETFD, FD_CLOEXEC) < 0 +#endif + || close (pipefd [1]) < 0 + ) + croak ("IO::AIO: unable to create dummy pipe for aio_close"); + + close_fd = pipefd [0]; + } + reinit (); } @@ -1434,33 +1698,38 @@ aio_close (SV *fh, SV *callback = &PL_sv_undef) PPCODE: { - static int close_fd = -1; /* dummy fd to close fds via dup2 */ int fd = s_fileno_croak (fh, 0); dREQ; +#if 0 + /* partially duplicate logic in s_fileno */ + SvGETMAGIC (fh); - if (expect_false (close_fd < 0)) - { - int pipefd [2]; + if (SvROK (fh)) + { + fh = SvRV (fh); + SvGETMAGIC (fh); + } - if ( -#ifdef _WIN32 - _pipe (pipefd, 1, _O_BINARY) < 0 -#else - pipe (pipefd) < 0 - || fcntl (pipefd [0], F_SETFD, FD_CLOEXEC) < 0 + if (SvTYPE (fh) == SVt_PVGV) + { + /* perl filehandle */ + PerlIOUnix_refcnt_inc (fd); + do_close ((GV *)fh, 1); + + req->type = EIO_CLOSE; + req->int1 = fd; + /*req->sv2 = newSVsv (fh);*/ /* since we stole the fd, no need to keep the fh */ + } + else #endif - || close (pipefd [1]) < 0 - ) - abort (); /*D*/ - - close_fd = pipefd [0]; + { + /* fd number */ + req->type = EIO_DUP2; + req->int1 = close_fd; + req->sv2 = newSVsv (fh); + req->int2 = fd; } - req->type = EIO_DUP2; - req->int1 = close_fd; - req->sv2 = newSVsv (fh); - req->int2 = fd; - REQ_SEND; } @@ -1643,28 +1912,36 @@ void st_xtime () ALIAS: - st_atime = 1 - st_mtime = 2 - st_ctime = 4 - st_xtime = 7 - PPCODE: - EXTEND (SP, 3); - if (ix & 1) PUSHs (newSVnv (PL_statcache.st_atime + 1e-9 * ATIMENSEC)); - if (ix & 2) PUSHs (newSVnv (PL_statcache.st_mtime + 1e-9 * MTIMENSEC)); - if (ix & 4) PUSHs (newSVnv (PL_statcache.st_ctime + 1e-9 * CTIMENSEC)); + st_atime = 0x01 + st_mtime = 0x02 + st_ctime = 0x04 + st_btime = 0x08 + st_xtime = 0x0f + PPCODE: + EXTEND (SP, 4); + if (ix & 0x01) PUSHs (newSVnv (PL_statcache.st_atime + 1e-9 * ATIMENSEC)); + if (ix & 0x02) PUSHs (newSVnv (PL_statcache.st_mtime + 1e-9 * MTIMENSEC)); + if (ix & 0x04) PUSHs (newSVnv (PL_statcache.st_ctime + 1e-9 * CTIMENSEC)); + if (ix & 0x08) PUSHs (newSVnv (BTIMESEC + 1e-9 * BTIMENSEC)); void st_xtimensec () ALIAS: - st_atimensec = 1 - st_mtimensec = 2 - st_ctimensec = 4 - st_xtimensec = 7 - PPCODE: - EXTEND (SP, 3); - if (ix & 1) PUSHs (newSViv (ATIMENSEC)); - if (ix & 2) PUSHs (newSViv (MTIMENSEC)); - if (ix & 4) PUSHs (newSViv (CTIMENSEC)); + st_atimensec = 0x01 + st_mtimensec = 0x02 + st_ctimensec = 0x04 + st_btimensec = 0x08 + st_xtimensec = 0x0f + st_btimesec = 0x10 + st_gen = 0x20 + PPCODE: + EXTEND (SP, 4); + if (ix & 0x01) PUSHs (newSViv (ATIMENSEC)); + if (ix & 0x02) PUSHs (newSViv (MTIMENSEC)); + if (ix & 0x04) PUSHs (newSViv (CTIMENSEC)); + if (ix & 0x08) PUSHs (newSViv (BTIMENSEC)); + if (ix & 0x10) PUSHs (newSVuv (BTIMESEC)); + if (ix & 0x20) PUSHs (newSVuv (ST_GEN)); UV major (UV dev) @@ -1791,7 +2068,7 @@ req->type = ix; req_set_path1 (req, oldpath); - req_set_path (req, newpath, &req->sv2, &req->sv4, &wd2, &req->ptr2); + req_set_path (newpath, &req->sv2, &req->sv4, &wd2, &req->ptr2); req->int3 = (long)wd2; REQ_SEND; @@ -1806,7 +2083,7 @@ req->type = EIO_RENAME; req_set_path1 (req, oldpath); - req_set_path (req, newpath, &req->sv2, &req->sv4, &wd2, &req->ptr2); + req_set_path (newpath, &req->sv2, &req->sv4, &wd2, &req->ptr2); req->int2 = flags; req->int3 = (long)wd2; @@ -2160,7 +2437,7 @@ RETVAL int -madvise (SV *scalar, STRLEN offset = 0, SV *length = &PL_sv_undef, IV advice_or_prot) +madvise (SV *scalar, IV offset = 0, SV *length = &PL_sv_undef, IV advice_or_prot) ALIAS: mprotect = 1 CODE: @@ -2191,7 +2468,7 @@ RETVAL int -munlock (SV *scalar, STRLEN offset = 0, SV *length = &PL_sv_undef) +munlock (SV *scalar, IV offset = 0, SV *length = &PL_sv_undef) CODE: { STRLEN svlen; @@ -2219,6 +2496,14 @@ RETVAL int +mlockall (int flags) + PROTOTYPE: $; + CODE: + RETVAL = eio_mlockall_sync (flags); + OUTPUT: + RETVAL + +int munlockall () CODE: #if _POSIX_MEMLOCK @@ -2230,6 +2515,184 @@ RETVAL int +statx (SV8 *pathname, int flags, UV mask) + CODE: +{ + /* undocumented, and might go away, and anyway, should use eio_statx */ + SV *wdsv = 0; + SV *pathsv = 0; + eio_wd wd = EIO_CWD; + void *ptr; + int res; + + req_set_path (pathname, &wdsv, &pathsv, &wd, &ptr); + RETVAL = eio__statx (!wd || wd->fd == EIO_CWD ? AT_FDCWD : wd->fd, ptr, flags, mask & STATX_ALL, &stx); + + SvREFCNT_dec (pathsv); + SvREFCNT_dec (wdsv); +} + OUTPUT: + RETVAL + +U32 +stx_mode () + PROTOTYPE: + CODE: +#if HAVE_STATX + RETVAL = stx.stx_mode; +#else + XSRETURN_UNDEF; +#endif + OUTPUT: + RETVAL + +#define STATX_OFFSET_mask statx_offsetof (stx_mask) +#define STATX_OFFSET_blksize statx_offsetof (stx_blksize) +#define STATX_OFFSET_nlink statx_offsetof (stx_nlink) +#define STATX_OFFSET_uid statx_offsetof (stx_uid) +#define STATX_OFFSET_gid statx_offsetof (stx_gid) +#define STATX_OFFSET_rdev_major statx_offsetof (stx_rdev_major) +#define STATX_OFFSET_rdev_minor statx_offsetof (stx_rdev_minor) +#define STATX_OFFSET_dev_major statx_offsetof (stx_dev_major) +#define STATX_OFFSET_dev_minor statx_offsetof (stx_dev_minor) +#define STATX_OFFSET_attributes statx_offsetof (stx_attributes) +#define STATX_OFFSET_ino statx_offsetof (stx_ino) +#define STATX_OFFSET_size statx_offsetof (stx_size) +#define STATX_OFFSET_blocks statx_offsetof (stx_blocks) +#define STATX_OFFSET_attributes_mask statx_offsetof (stx_attributes_mask) +#define STATX_OFFSET_atime statx_offsetof (stx_atime) +#define STATX_OFFSET_btime statx_offsetof (stx_btime) +#define STATX_OFFSET_ctime statx_offsetof (stx_ctime) +#define STATX_OFFSET_mtime statx_offsetof (stx_mtime) + +U32 +stx_mask () + PROTOTYPE: + ALIAS: + stx_mask = STATX_OFFSET_mask + stx_blksize = STATX_OFFSET_blksize + stx_nlink = STATX_OFFSET_nlink + stx_uid = STATX_OFFSET_uid + stx_gid = STATX_OFFSET_gid + stx_rdev_major = STATX_OFFSET_rdev_major + stx_rdev_minor = STATX_OFFSET_rdev_minor + stx_dev_major = STATX_OFFSET_dev_major + stx_dev_minor = STATX_OFFSET_dev_minor + CODE: +#if HAVE_STATX + RETVAL = *(__u32 *)((char *)&stx + ix); +#else + XSRETURN_UNDEF; +#endif + OUTPUT: + RETVAL + +VAL64 +stx_attributes () + PROTOTYPE: + ALIAS: + stx_attributes = STATX_OFFSET_attributes + stx_ino = STATX_OFFSET_ino + stx_size = STATX_OFFSET_size + stx_blocks = STATX_OFFSET_blocks + stx_attributes_mask = STATX_OFFSET_attributes_mask + CODE: +#if HAVE_STATX + RETVAL = *(__u64 *)((char *)&stx + ix); +#else + XSRETURN_UNDEF; +#endif + OUTPUT: + RETVAL + +NV +stx_atime () + PROTOTYPE: + ALIAS: + stx_atime = STATX_OFFSET_atime + stx_btime = STATX_OFFSET_btime + stx_ctime = STATX_OFFSET_ctime + stx_mtime = STATX_OFFSET_mtime + CODE: +#if HAVE_STATX + struct statx_timestamp *ts = (struct statx_timestamp *)((char *)&stx + ix); + RETVAL = ts->tv_sec + ts->tv_nsec * 1e-9; +#else + XSRETURN_UNDEF; +#endif + OUTPUT: + RETVAL + +VAL64 +stx_atimesec () + PROTOTYPE: + ALIAS: + stx_atimesec = STATX_OFFSET_atime + stx_btimesec = STATX_OFFSET_btime + stx_ctimesec = STATX_OFFSET_ctime + stx_mtimesec = STATX_OFFSET_mtime + CODE: +#if HAVE_STATX + struct statx_timestamp *ts = (struct statx_timestamp *)((char *)&stx + ix); + RETVAL = ts->tv_sec; +#else + XSRETURN_UNDEF; +#endif + OUTPUT: + RETVAL + +U32 +stx_atimensec () + PROTOTYPE: + ALIAS: + stx_atimensec = STATX_OFFSET_atime + stx_btimensec = STATX_OFFSET_btime + stx_ctimensec = STATX_OFFSET_ctime + stx_mtimensec = STATX_OFFSET_mtime + CODE: +#if HAVE_STATX + struct statx_timestamp *ts = (struct statx_timestamp *)((char *)&stx + ix); + RETVAL = ts->tv_nsec; +#else + RETVAL = 0; +#endif + OUTPUT: + RETVAL + +void +accept4 (aio_rfd rfh, SV *sockaddr, int salen, int flags) + PPCODE: +{ + SV *retval; +#if HAVE_ACCEPT4 + socklen_t salen_ = salen ? salen + 1 : 0; + + if (salen) + { + sv_upgrade (sockaddr, SVt_PV); + sv_grow (sockaddr, salen_); + } + + int res = accept4 (rfh, salen ? (struct sockaddr *)SvPVX (sockaddr) : 0, salen ? &salen_ : 0, flags); + + retval = newmortalFH (res, O_RDWR); + + if (res >= 0 && salen > 0) + { + if (salen_ > salen + 1) + salen_ = salen + 1; + + SvPOK_only (sockaddr); + SvCUR_set (sockaddr, salen_); + } +#else + errno = ENOSYS; + retval = &PL_sv_undef; +#endif + XPUSHs (retval); +} + +ssize_t splice (aio_rfd rfh, SV *off_in, aio_wfd wfh, SV *off_out, size_t length, unsigned int flags) CODE: { @@ -2247,7 +2710,7 @@ OUTPUT: RETVAL -int +ssize_t tee (aio_rfd rfh, aio_wfd wfh, size_t length, unsigned int flags) CODE: #if HAVE_LINUX_SPLICE @@ -2300,6 +2763,58 @@ } void +pidfd_open (int pid, unsigned int flags = 0) + PPCODE: +{ + /*GENDEF0_SYSCALL(pidfd_open,434)*/ + int fd = syscall (SYS_pidfd_open, pid, flags); + XPUSHs (newmortalFH (fd, O_RDWR)); +} + +int +pidfd_send_signal (SV *pidfh, int sig, SV *siginfo = &PL_sv_undef, unsigned int flags = 0) + PPCODE: +{ + int res; +#if HAVE_SIGINFO_T + siginfo_t si = { 0 }; + + if (SvOK (siginfo)) + { + HV *hv; + SV **svp; + + if (!SvROK (siginfo) || SvTYPE (SvRV (siginfo)) != SVt_PVHV) + croak ("siginfo argument must be a hashref with 'code', 'pid', 'uid' and 'value_int' or 'value_ptr' members, caught"); + + hv = (HV *)SvRV (siginfo); + + if ((svp = hv_fetchs (hv, "code" , 0))) si.si_code = SvIV (*svp); + if ((svp = hv_fetchs (hv, "pid" , 0))) si.si_pid = SvIV (*svp); + if ((svp = hv_fetchs (hv, "uid" , 0))) si.si_uid = SvIV (*svp); + if ((svp = hv_fetchs (hv, "value_int", 0))) si.si_value.sival_int = SvIV (*svp); + if ((svp = hv_fetchs (hv, "value_ptr", 0))) si.si_value.sival_ptr = (void *)SvIV (*svp); + } + + /*GENDEF0_SYSCALL(pidfd_send_signal,424)*/ + res = syscall (SYS_pidfd_send_signal, s_fileno_croak (pidfh, 0), sig, SvOK (siginfo) ? &si : 0, flags); +#else + res = (errno = ENOSYS, -1); +#endif + + XPUSHs (sv_2mortal (newSViv (res))); +} + +void +pidfd_getfd (SV *pidfh, int targetfd, unsigned int flags = 0) + PPCODE: +{ + /*GENDEF0_SYSCALL(pidfd_getfd,438)*/ + int fd = syscall (SYS_pidfd_getfd, s_fileno_croak (pidfh, 0), targetfd, flags); + XPUSHs (newmortalFH (fd, O_RDWR)); +} + +void eventfd (unsigned int initval = 0, int flags = 0) PPCODE: { @@ -2372,6 +2887,69 @@ #endif } +void +memfd_create (octet_string pathname, int flags = 0) + PPCODE: +{ + int fd; +#if HAVE_MEMFD_CREATE + fd = memfd_create (pathname, flags); +#else + fd = (errno = ENOSYS, -1); +#endif + + XPUSHs (newmortalFH (fd, O_RDWR)); +} + +int +fexecve (SV *fh, SV *args, SV *envs = &PL_sv_undef) + CODE: +{ + int fd = PerlIO_fileno (IoIFP (sv_2io (fh))); + char **envp, **argv; + argv = extract_stringvec (args, "IO::AIO::fexecve: args must be an array of strings"); + if (!SvOK (envs)) + { + extern char **environ; + envp = environ; + } + else + envp = extract_stringvec (envs, "IO::AIO::fexecve: envs must be an array of strings"); +#if _POSIX_VERSION >= 200809L + RETVAL = fexecve (fd, argv, envp); +#else + RETVAL = (errno = ENOSYS, -1); +#endif +} + OUTPUT: RETVAL + +int +mount (octet_string special, octet_string path, octet_string fstype, UV flags = 0, octet_string_ornull data = 0) + CODE: +#if HAVE_MOUNT + RETVAL = mount (special, path, fstype, flags, data); +#else + RETVAL = (errno = ENOSYS, -1); +#endif + OUTPUT: RETVAL + +int +umount (octet_string path, int flags = 0) + CODE: + if (flags) +#if HAVE_UMOUNT2 + RETVAL = umount2 (path, flags); +#else + RETVAL = (errno = ENOSYS, -1); +#endif + else +#if HAVE_MOUNT + RETVAL = umount (path); +#else + RETVAL = (errno = ENOSYS, -1); +#endif + OUTPUT: RETVAL + UV get_fdlimit () CODE: @@ -2414,7 +2992,7 @@ if (errno == EPERM) { - /* setlimit failed with EPERM - maybe we can't raise the hardlimit, or maybe */ + /* setrlimit failed with EPERM - maybe we can't raise the hardlimit, or maybe */ /* our limit overflows a system-wide limit */ /* try an adaptive algorithm, but do not lower the hardlimit */ rl.rlim_max = 0; @@ -2423,7 +3001,7 @@ rl.rlim_max |= bit; rl.rlim_cur = rl.rlim_max; - /* nevr decrease the hard limit */ + /* never decrease the hard limit */ if (rl.rlim_max < orig_rlim_max) break;