diff options
author | Corinna Vinschen <corinna@vinschen.de> | 2008-04-23 11:13:52 +0000 |
---|---|---|
committer | Corinna Vinschen <corinna@vinschen.de> | 2008-04-23 11:13:52 +0000 |
commit | c57b57e5c43ab112e50d5e214b8cef61f8027946 (patch) | |
tree | 79031d6d1a4253b66d59bafa1745cc604f995a17 /winsup/cygwin/syscalls.cc | |
parent | ca48eb65e9f332484b1fe00ae373a1121091cbfb (diff) | |
download | cygnal-c57b57e5c43ab112e50d5e214b8cef61f8027946.tar.gz cygnal-c57b57e5c43ab112e50d5e214b8cef61f8027946.tar.bz2 cygnal-c57b57e5c43ab112e50d5e214b8cef61f8027946.zip |
* cygwin.din: Sort.
(faccessat): Export.
(fchmodat): Export.
(fchownat): Export.
(fstatat): Export.
(futimesat): Export.
(linkat): Export.
(mkdirat): Export.
(mkfifoat): Export.
(mknodat): Export.
(openat): Export.
(readlinkat): Export.
(renameat): Export.
(symlinkat): Export.
(unlinkat): Export.
* path.cc (readlink): Align definition to POSIX.
* syscalls.cc (gen_full_path_at): New static function.
(faccessat): Implement.
(fchmodat): Implement.
(fchownat): Implement.
(fstatat): Implement.
(futimesat): Implement.
(linkat): Implement.
(mkdirat): Implement.
(mkfifoat): Implement.
(mknodat): Implement.
(openat): Implement.
(readlinkat): Implement.
(renameat): Implement.
(symlinkat): Implement.
(unlinkat): Implement.
* include/cygwin/version.h: Bump API minor number.
Diffstat (limited to 'winsup/cygwin/syscalls.cc')
-rw-r--r-- | winsup/cygwin/syscalls.cc | 276 |
1 files changed, 276 insertions, 0 deletions
diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc index 28533a58b..1a2572186 100644 --- a/winsup/cygwin/syscalls.cc +++ b/winsup/cygwin/syscalls.cc @@ -61,6 +61,7 @@ details. */ #include "cpuid.h" #include "registry.h" #include "environ.h" +#include "tls_pbuf.h" #undef _close #undef _lseek @@ -3490,3 +3491,278 @@ pclose (FILE *fp) return status; } + +/* Preliminary(?) implementation of the openat family of functions. */ + +static int +gen_full_path_at (char *path_ret, int dirfd, const char *pathname) +{ + if (!*pathname) + { + set_errno (ENOENT); + return -1; + } + if (strlen (pathname) >= PATH_MAX) + { + set_errno (ENAMETOOLONG); + return -1; + } + if (isdirsep (*pathname)) + stpcpy (path_ret, pathname); + else + { + char *p; + + if (dirfd == AT_FDCWD) + p = stpcpy (path_ret, cygheap->cwd.posix); + else + { + cygheap_fdget cfd (dirfd); + if (cfd < 0) + return -1; + if (!cfd->pc.isdir ()) + { + set_errno (ENOTDIR); + return -1; + } + p = stpcpy (path_ret, cfd->get_name ()); + } + if (!p) + { + set_errno (ENOTDIR); + return -1; + } + if (p[-1] != '/') + *p++ = '/'; + stpcpy (p, pathname); + } + return 0; +} + +extern "C" int +openat (int dirfd, const char *pathname, int flags, ...) +{ + myfault efault; + if (efault.faulted (EFAULT)) + return -1; + tmp_pathbuf tp; + char *path = tp.c_get (); + if (gen_full_path_at (path, dirfd, pathname)) + return -1; + + va_list ap; + mode_t mode; + + va_start (ap, flags); + mode = va_arg (ap, mode_t); + va_end (ap); + return open (path, flags, mode); +} + +extern "C" int +faccessat (int dirfd, const char *pathname, int mode, int flags) +{ + myfault efault; + if (efault.faulted (EFAULT)) + return -1; + + int res = -1; + tmp_pathbuf tp; + char *path = tp.c_get (); + if (!gen_full_path_at (path, dirfd, pathname)) + { + if (flags & ~(F_OK|R_OK|W_OK|X_OK)) + set_errno (EINVAL); + else + { + fhandler_base *fh = build_fh_name (path, NULL, + (flags & AT_SYMLINK_NOFOLLOW) + ? PC_SYM_NOFOLLOW : PC_SYM_FOLLOW, + stat_suffixes); + if (fh) + { + res = fh->fhaccess (mode); + delete fh; + } + } + } + debug_printf ("returning %d", res); + return res; +} + +extern "C" int +fchmodat (int dirfd, const char *pathname, mode_t mode, int flags) +{ + myfault efault; + if (efault.faulted (EFAULT)) + return -1; + tmp_pathbuf tp; + char *path = tp.c_get (); + if (gen_full_path_at (path, dirfd, pathname)) + return -1; + return chmod (path, mode); +} + +extern "C" int +fchownat (int dirfd, const char *pathname, __uid32_t uid, __gid32_t gid, + int flags) +{ + myfault efault; + if (efault.faulted (EFAULT)) + return -1; + tmp_pathbuf tp; + char *path = tp.c_get (); + if (gen_full_path_at (path, dirfd, pathname)) + return -1; + return chown_worker (path, (flags & AT_SYMLINK_NOFOLLOW) + ? PC_SYM_NOFOLLOW : PC_SYM_FOLLOW, uid, gid); +} + +extern "C" int +fstatat (int dirfd, const char *pathname, struct __stat64 *st, int flags) +{ + myfault efault; + if (efault.faulted (EFAULT)) + return -1; + tmp_pathbuf tp; + char *path = tp.c_get (); + if (gen_full_path_at (path, dirfd, pathname)) + return -1; + return (flags & AT_SYMLINK_NOFOLLOW) ? lstat64 (path, st) : stat64 (path, st); +} + +extern "C" int +futimesat (int dirfd, const char *pathname, const struct timeval *times) +{ + myfault efault; + if (efault.faulted (EFAULT)) + return -1; + tmp_pathbuf tp; + char *path = tp.c_get (); + if (gen_full_path_at (path, dirfd, pathname)) + return -1; + return utimes (path, times); +} + +extern "C" int +linkat (int olddirfd, const char *oldpathname, + int newdirfd, const char *newpathname, + int flags) +{ + myfault efault; + if (efault.faulted (EFAULT)) + return -1; + tmp_pathbuf tp; + char *oldpath = tp.c_get (); + if (gen_full_path_at (oldpath, olddirfd, oldpathname)) + return -1; + char *newpath = tp.c_get (); + if (gen_full_path_at (newpath, newdirfd, newpathname)) + return -1; + if (flags & AT_SYMLINK_FOLLOW) + { + path_conv old_name (oldpath, PC_SYM_FOLLOW | PC_POSIX, stat_suffixes); + if (old_name.error) + { + set_errno (old_name.error); + return -1; + } + strcpy (oldpath, old_name.normalized_path); + } + return link (oldpath, newpath); +} + +extern "C" int +mkdirat (int dirfd, const char *pathname, mode_t mode) +{ + myfault efault; + if (efault.faulted (EFAULT)) + return -1; + tmp_pathbuf tp; + char *path = tp.c_get (); + if (gen_full_path_at (path, dirfd, pathname)) + return -1; + return mkdir (path, mode); +} + +extern "C" int +mkfifoat (int dirfd, const char *pathname, mode_t mode) +{ + myfault efault; + if (efault.faulted (EFAULT)) + return -1; + tmp_pathbuf tp; + char *path = tp.c_get (); + if (gen_full_path_at (path, dirfd, pathname)) + return -1; + return mkfifo (path, mode); +} + +extern "C" int +mknodat (int dirfd, const char *pathname, mode_t mode, __dev32_t dev) +{ + myfault efault; + if (efault.faulted (EFAULT)) + return -1; + tmp_pathbuf tp; + char *path = tp.c_get (); + if (gen_full_path_at (path, dirfd, pathname)) + return -1; + return mknod32 (path, mode, dev); +} + +extern "C" ssize_t +readlinkat (int dirfd, const char *pathname, char *buf, size_t bufsize) +{ + myfault efault; + if (efault.faulted (EFAULT)) + return -1; + tmp_pathbuf tp; + char *path = tp.c_get (); + if (gen_full_path_at (path, dirfd, pathname)) + return -1; + return readlink (path, buf, bufsize); +} + +extern "C" int +renameat (int olddirfd, const char *oldpathname, + int newdirfd, const char *newpathname) +{ + myfault efault; + if (efault.faulted (EFAULT)) + return -1; + tmp_pathbuf tp; + char *oldpath = tp.c_get (); + if (gen_full_path_at (oldpath, olddirfd, oldpathname)) + return -1; + char *newpath = tp.c_get (); + if (gen_full_path_at (newpath, newdirfd, newpathname)) + return -1; + return rename (oldpath, newpath); +} + +extern "C" int +symlinkat (const char *oldpath, int newdirfd, const char *newpathname) +{ + myfault efault; + if (efault.faulted (EFAULT)) + return -1; + tmp_pathbuf tp; + char *newpath = tp.c_get (); + if (gen_full_path_at (newpath, newdirfd, newpathname)) + return -1; + return symlink (oldpath, newpath); +} + +extern "C" int +unlinkat (int dirfd, const char *pathname, int flags) +{ + myfault efault; + if (efault.faulted (EFAULT)) + return -1; + tmp_pathbuf tp; + char *path = tp.c_get (); + if (gen_full_path_at (path, dirfd, pathname)) + return -1; + return (flags & AT_REMOVEDIR) ? rmdir (path) : unlink (path); +} |