POSIX-2008
view release on metacpan or search on metacpan
/* vim: set ts=2 sw=2 sts=2 expandtab:
*/
#define PACKNAME "POSIX::2008"
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#define PERL_NO_GET_CONTEXT
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
/* ppport.h says we don't need caller_cx but a few cpantesters report
* "undefined symbol: caller_cx".
*/
#define NEED_caller_cx
#define NEED_croak_xs_usage
#include "ppport.h"
#include "2008.h"
#if defined(PERL_IMPLICIT_SYS)
#undef dup
#undef open
#undef close
#undef stat
#undef fstat
#undef lstat
#undef readlink
# if !defined(_WIN32) || defined(__CYGWIN__)
#undef abort
#undef access
#undef chdir
#undef fchdir
#undef chmod
#undef fchmod
#undef chown
#undef fchown
#undef fdopen
#undef fdopendir
#undef getegid
#undef geteuid
#undef getgid
#undef gethostname
#undef getuid
#undef isatty
#undef killpg
#undef link
#undef mkdir
#undef read
#undef rename
#undef rmdir
#undef setgid
#undef setuid
#undef symlink
#undef unlink
#undef write
# endif
#endif
#ifdef PSX2008_HAS_COMPLEX_H
#include <complex.h>
#endif
#include <ctype.h>
#ifdef I_DIRENT
#include <dirent.h>
#endif
#ifdef PSX2008_HAS_DLFCN_H
#include <dlfcn.h>
#endif
#include <errno.h>
#ifdef I_FLOAT
#include <float.h>
#endif
#ifdef I_FCNTL
#include <fcntl.h>
#endif
#include <fenv.h>
#ifdef PSX2008_HAS_FNMATCH_H
#include <fnmatch.h>
#endif
#ifdef I_INTTYPES
#include <inttypes.h>
#endif
#ifdef PSX2008_HAS_LIBGEN_H
#include <libgen.h>
#endif
#ifdef I_LIMITS
#include <limits.h>
#endif
#ifdef I_NETDB
#include <netdb.h>
#endif
#ifdef I_MATH
#include <math.h>
#endif
#ifdef PSX2008_HAS_NL_TYPES_H
#include <nl_types.h>
## I/O-related functions
########################
#ifdef PSX2008_HAS_CHDIR
SysRetTrue
chdir(SV *what);
CODE:
SvGETMAGIC(what);
if (!SvOK(what)) {
SETERRNO(ENOENT, RMS$_DNF);
RETVAL = -1;
}
else if (SvPOK(what)) {
const char *path = SvPV_nomg_const_nolen(what);
RETVAL = chdir(path);
}
else {
#ifdef PSX2008_HAS_FCHDIR
int fd = _psx_fileno_nomg(aTHX_ what);
RETVAL = fchdir(fd);
#else
SETERRNO(ENOSYS, SS$_UNSUPPORTED);
RETVAL = -1;
#endif
}
OUTPUT:
RETVAL
#endif
#ifdef PSX2008_HAS_CHMOD
SysRetTrue
chmod(SV *what, mode_t mode);
CODE:
SvGETMAGIC(what);
if (!SvOK(what)) {
SETERRNO(ENOENT, RMS$_FNF);
RETVAL = -1;
}
else if (SvPOK(what)) {
const char *path = SvPV_nomg_const_nolen(what);
RETVAL = chmod(path, mode);
}
else {
#ifdef PSX2008_HAS_FCHMOD
int fd = _psx_fileno_nomg(aTHX_ what);
RETVAL = fchmod(fd, mode);
#else
SETERRNO(ENOSYS, SS$_UNSUPPORTED);
RETVAL = -1;
#endif
}
OUTPUT:
RETVAL
#endif
#ifdef PSX2008_HAS_CHOWN
SysRetTrue
chown(SV *what, uid_t owner, gid_t group);
CODE:
SvGETMAGIC(what);
if (!SvOK(what)) {
SETERRNO(ENOENT, RMS$_FNF);
RETVAL = -1;
}
else if (SvPOK(what)) {
const char *path = SvPV_nomg_const_nolen(what);
RETVAL = chown(path, owner, group);
}
else {
#ifdef PSX2008_HAS_FCHOWN
int fd = _psx_fileno_nomg(aTHX_ what);
RETVAL = fchown(fd, owner, group);
#else
SETERRNO(ENOSYS, SS$_UNSUPPORTED);
RETVAL = -1;
#endif
}
OUTPUT:
RETVAL
#endif
#ifdef PSX2008_HAS_CONFSTR
void
confstr(int name);
INIT:
SETERRNO(0, 0);
PPCODE:
{
Size_t len = confstr(name, NULL, 0);
if (!len && errno)
PUSHs(&PL_sv_undef);
else {
SV *bufsv = sv_2mortal(newSV(len + !len));
char *cbuf = SvPVX(bufsv);
(void)confstr(name, cbuf, len);
cbuf[len] = '\0';
SvCUR_set(bufsv, len - !!len);
SvPOK_only(bufsv);
SvTAINTED_on(bufsv);
PUSHs(bufsv);
}
}
#endif
#ifdef PSX2008_HAS_PATHCONF
void
pathconf(SV *what, int name);
PPCODE:
{
long rv = -1;
SvGETMAGIC(what);
SETERRNO(0, 0); /* SvGETMAGIC() might have set errno. */
if (UNLIKELY(!SvOK(what)))
SETERRNO(ENOENT, RMS_FNF);
else if (SvPOK(what)) {
const char *path = SvPV_nomg_const_nolen(what);
rv = pathconf(path, name);
}
else {
#ifdef PSX2008_HAS_FPATHCONF
int fd = _psx_fileno_nomg(aTHX_ what);
SETERRNO(0, 0); /* _psx_fileno() might have set errno. */
rv = fpathconf(fd, name);
#else
SETERRNO(ENOSYS, SS$_UNSUPPORTED);
#endif
}
if (rv < 0 && errno != 0)
PUSHs(&PL_sv_undef);
else
PUSH_INT_OR_PV(rv);
}
#endif
#ifdef PSX2008_HAS_SYSCONF
void
sysconf(int name);
PPCODE:
{
long rv;
SETERRNO(0, 0);
rv = sysconf(name);
if (rv < 0 && errno != 0)
PUSHs(&PL_sv_undef);
else
PUSH_INT_OR_PV(rv);
}
#endif
#ifdef PSX2008_HAS_TRUNCATE
SysRetTrue
truncate(SV *what, Off_t length);
CODE:
SvGETMAGIC(what);
if (!SvOK(what)) {
SETERRNO(ENOENT, RMS_FNF);
RETVAL = -1;
}
else if (SvPOK(what)) {
const char *path = SvPV_nomg_const_nolen(what);
RETVAL = truncate(path, length);
}
else {
#ifdef PSX2008_HAS_FTRUNCATE
int fd = _psx_fileno_nomg(aTHX_ what);
RETVAL = ftruncate(fd, length);
#else
SETERRNO(ENOSYS, SS$_UNSUPPORTED);
RETVAL = -1;
#endif
}
OUTPUT:
RETVAL
#endif
#ifdef PSX2008_HAS_LCHOWN
SysRetTrue
lchown(const char *path, uid_t owner, gid_t group);
#endif
#ifdef PSX2008_HAS_ACCESS
SysRetTrue
access(const char *path, int mode);
#endif
#ifdef PSX2008_HAS_FDATASYNC
SysRetTrue
fdatasync(psx_fd_t fd);
#endif
#ifdef PSX2008_HAS_FSYNC
SysRetTrue
fsync(psx_fd_t fd);
#endif
#ifdef PSX2008_HAS_STAT
void
stat(SV *what);
INIT:
int rv = -1;
struct stat buf;
PPCODE:
SvGETMAGIC(what);
if (!SvOK(what))
SETERRNO(ENOENT, RMS_FNF);
else if (SvPOK(what)) {
const char *path = SvPV_nomg_const_nolen(what);
rv = stat(path, &buf);
}
else {
#ifdef PSX2008_HAS_FSTAT
int fd = _psx_fileno_nomg(aTHX_ what);
rv = fstat(fd, &buf);
#else
SETERRNO(ENOSYS, SS$_UNSUPPORTED);
#endif
}
RETURN_STAT_BUF(rv, buf);
#endif
#ifdef PSX2008_HAS_LSTAT
void
lstat(const char *path);
INIT:
int rv;
struct stat buf;
PPCODE:
rv = lstat(path, &buf);
RETURN_STAT_BUF(rv, buf);
#endif
#ifdef PSX2008_HAS_STATVFS
#endif
#if defined(PSX2008_HAS_FDOPENDIR)
void
fdopendir(IV fd);
PPCODE:
{
SV *rv = NULL;
if (UNLIKELY(fd < 0 || fd > PERL_INT_MAX))
SETERRNO(EBADF, RMS_IFI);
else
rv = _psx_fd_to_handle(aTHX_ fd, NULL);
PUSHs(rv ? rv : &PL_sv_undef);
}
#endif
##
## POSIX::open(), read() and write() return "0 but true" for 0, which
## is not quite what you would expect. We return a real 0.
##
#ifdef PSX2008_HAS_CREAT
SysRet0
creat(const char *path, mode_t mode=0666)
#endif
#ifdef PSX2008_HAS_OPEN
SysRet0
open(const char *path, int oflag=O_RDONLY, mode_t mode=0666);
#endif
#ifdef PSX2008_HAS_CLOSE
SysRetTrue
close(SV *fd);
CODE:
RETVAL = _psx_close(aTHX_ fd);
OUTPUT:
RETVAL
#endif
#ifdef PSX2008_HAS_FACCESSAT
SysRetTrue
faccessat(psx_fd_t dirfd, const char *path, int amode, int flags=0);
#endif
#ifdef PSX2008_HAS_FCHMODAT
SysRetTrue
fchmodat(psx_fd_t dirfd, const char *path, mode_t mode, int flags=0);
#endif
#ifdef PSX2008_HAS_FCHOWNAT
SysRetTrue
fchownat(psx_fd_t dirfd, \
const char *path, uid_t owner, gid_t group, int flags=0);
#endif
#ifdef PSX2008_HAS_FSTATAT
void
fstatat(psx_fd_t dirfd, const char *path, int flags=0);
INIT:
int rv;
struct stat buf;
PPCODE:
rv = fstatat(dirfd, path, &buf, flags);
RETURN_STAT_BUF(rv, buf);
#endif
#ifdef PSX2008_HAS_LINKAT
SysRetTrue
linkat(psx_fd_t olddirfd, const char *oldpath, \
psx_fd_t newdirfd, const char *newpath, int flags=0);
#endif
#ifdef PSX2008_HAS_MKDIRAT
SysRetTrue
mkdirat(psx_fd_t dirfd, const char *path, mode_t mode);
#endif
#ifdef PSX2008_HAS_MKFIFOAT
SysRetTrue
mkfifoat(psx_fd_t dirfd, const char *path, mode_t mode);
#endif
#ifdef PSX2008_HAS_MKNODAT
SysRetTrue
mknodat(psx_fd_t dirfd, const char *path, mode_t mode, dev_t dev);
#endif
#ifdef PSX2008_HAS_OPENAT
void
openat(SV *dirfdsv, const char *path, int flags=O_RDONLY, mode_t mode=0666);
PPCODE:
{
SV *rv = _openat50c(aTHX_ dirfdsv, path, flags, mode, NULL);
PUSHs(rv ? rv : &PL_sv_undef);
}
#endif
#ifdef PSX2008_HAS_OPENAT2
void
openat2(SV *dirfdsv, const char *path, HV *how);
PPCODE:
{
SV *rv = _openat50c(aTHX_ dirfdsv, path, 0, 0, how);
PUSHs(rv ? rv : &PL_sv_undef);
}
( run in 1.527 second using v1.01-cache-2.11-cpan-92ad3014f07 )