From fd72e3042517f3c95ab2d707e1074f4d393b5f9a Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Mon, 20 Jul 2009 13:36:52 -0400 Subject: first pass at implementing *at funcs Tested basic functionality with coreutils and things seem to work. At least gives us a basis to jump from. Signed-off-by: Mike Frysinger --- libc/misc/dirent/opendir.c | 68 ++++++++++++++++++++++++---------- libc/sysdeps/linux/common/faccessat.c | 16 ++++++++ libc/sysdeps/linux/common/fchmodat.c | 16 ++++++++ libc/sysdeps/linux/common/fchownat.c | 16 ++++++++ libc/sysdeps/linux/common/fstatat.c | 27 ++++++++++++++ libc/sysdeps/linux/common/fstatat64.c | 31 ++++++++++++++++ libc/sysdeps/linux/common/futimesat.c | 16 ++++++++ libc/sysdeps/linux/common/linkat.c | 16 ++++++++ libc/sysdeps/linux/common/mkdirat.c | 16 ++++++++ libc/sysdeps/linux/common/mkfifoat.c | 19 ++++++++++ libc/sysdeps/linux/common/mknodat.c | 25 +++++++++++++ libc/sysdeps/linux/common/openat.c | 18 +++++++++ libc/sysdeps/linux/common/openat64.c | 25 +++++++++++++ libc/sysdeps/linux/common/readlinkat.c | 16 ++++++++ libc/sysdeps/linux/common/renameat.c | 16 ++++++++ libc/sysdeps/linux/common/symlinkat.c | 16 ++++++++ libc/sysdeps/linux/common/unlinkat.c | 16 ++++++++ libc/sysdeps/linux/common/utimensat.c | 16 ++++++++ 18 files changed, 370 insertions(+), 19 deletions(-) create mode 100644 libc/sysdeps/linux/common/faccessat.c create mode 100644 libc/sysdeps/linux/common/fchmodat.c create mode 100644 libc/sysdeps/linux/common/fchownat.c create mode 100644 libc/sysdeps/linux/common/fstatat.c create mode 100644 libc/sysdeps/linux/common/fstatat64.c create mode 100644 libc/sysdeps/linux/common/futimesat.c create mode 100644 libc/sysdeps/linux/common/linkat.c create mode 100644 libc/sysdeps/linux/common/mkdirat.c create mode 100644 libc/sysdeps/linux/common/mkfifoat.c create mode 100644 libc/sysdeps/linux/common/mknodat.c create mode 100644 libc/sysdeps/linux/common/openat.c create mode 100644 libc/sysdeps/linux/common/openat64.c create mode 100644 libc/sysdeps/linux/common/readlinkat.c create mode 100644 libc/sysdeps/linux/common/renameat.c create mode 100644 libc/sysdeps/linux/common/symlinkat.c create mode 100644 libc/sysdeps/linux/common/unlinkat.c create mode 100644 libc/sysdeps/linux/common/utimensat.c (limited to 'libc') diff --git a/libc/misc/dirent/opendir.c b/libc/misc/dirent/opendir.c index 50e4082da..fa07d0052 100644 --- a/libc/misc/dirent/opendir.c +++ b/libc/misc/dirent/opendir.c @@ -12,14 +12,55 @@ #include #include #include +#include #include "dirstream.h" -/* libc_hidden_proto(opendir) */ -/* libc_hidden_proto(open) */ -/* libc_hidden_proto(fcntl) */ -/* libc_hidden_proto(close) */ -/* libc_hidden_proto(stat) */ -/* libc_hidden_proto(fstat) */ +static DIR *fd_to_DIR(int fd, __blksize_t size) +{ + DIR *ptr; + + ptr = malloc(sizeof(*ptr)); + if (!ptr) + return NULL; + + ptr->dd_fd = fd; + ptr->dd_nextloc = ptr->dd_size = ptr->dd_nextoff = 0; + ptr->dd_max = size; + if (ptr->dd_max < 512) + ptr->dd_max = 512; + + ptr->dd_buf = calloc(1, ptr->dd_max); + if (!ptr->dd_buf) { + free(ptr); + return NULL; + } + __pthread_mutex_init(&ptr->dd_lock, NULL); + + return ptr; +} + +DIR *fdopendir(int fd) +{ + int flags; + struct stat st; + + if (fstat(fd, &st)) + return NULL; + if (!S_ISDIR(st.st_mode)) { + __set_errno(ENOTDIR); + return NULL; + } + + flags = fcntl(fd, F_GETFL); + if (flags == -1) + return NULL; + if ((flags & O_ACCMODE) == O_WRONLY) { + __set_errno(EINVAL); + return NULL; + } + + return fd_to_DIR(fd, st.st_blksize); +} /* opendir just makes an open() call - it return NULL if it fails * (open sets errno), otherwise it returns a DIR * pointer. @@ -61,23 +102,12 @@ close_and_ret: __set_errno(saved_errno); return NULL; } - if (!(ptr = malloc(sizeof(*ptr)))) - goto nomem_close_and_ret; - ptr->dd_fd = fd; - ptr->dd_nextloc = ptr->dd_size = ptr->dd_nextoff = 0; - ptr->dd_max = statbuf.st_blksize; - if (ptr->dd_max < 512) - ptr->dd_max = 512; - - if (!(ptr->dd_buf = calloc(1, ptr->dd_max))) { - free(ptr); -nomem_close_and_ret: + ptr = fd_to_DIR(fd, statbuf.st_blksize); + if (!ptr) { close(fd); __set_errno(ENOMEM); - return NULL; } - __pthread_mutex_init(&(ptr->dd_lock), NULL); return ptr; } libc_hidden_def(opendir) diff --git a/libc/sysdeps/linux/common/faccessat.c b/libc/sysdeps/linux/common/faccessat.c new file mode 100644 index 000000000..09ca129a2 --- /dev/null +++ b/libc/sysdeps/linux/common/faccessat.c @@ -0,0 +1,16 @@ +/* + * faccessat() for uClibc + * + * Copyright (C) 2009 Analog Devices Inc. + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +#ifdef __NR_faccessat +_syscall4(int, faccessat, int, fd, const char *, file, int, type, int, flag) +#else +/* should add emulation with faccess() and /proc/self/fd/ ... */ +#endif diff --git a/libc/sysdeps/linux/common/fchmodat.c b/libc/sysdeps/linux/common/fchmodat.c new file mode 100644 index 000000000..7d4dd4e2c --- /dev/null +++ b/libc/sysdeps/linux/common/fchmodat.c @@ -0,0 +1,16 @@ +/* + * fchmodat() for uClibc + * + * Copyright (C) 2009 Analog Devices Inc. + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +#ifdef __NR_fchmodat +_syscall4(int, fchmodat, int, fd, const char *, file, mode_t, mode, int, flag) +#else +/* should add emulation with fchmod() and /proc/self/fd/ ... */ +#endif diff --git a/libc/sysdeps/linux/common/fchownat.c b/libc/sysdeps/linux/common/fchownat.c new file mode 100644 index 000000000..707164d1f --- /dev/null +++ b/libc/sysdeps/linux/common/fchownat.c @@ -0,0 +1,16 @@ +/* + * fchownat() for uClibc + * + * Copyright (C) 2009 Analog Devices Inc. + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +#ifdef __NR_fchownat +_syscall5(int, fchownat, int, fd, const char *, file, uid_t, owner, gid_t, group, int, flag) +#else +/* should add emulation with fchown() and /proc/self/fd/ ... */ +#endif diff --git a/libc/sysdeps/linux/common/fstatat.c b/libc/sysdeps/linux/common/fstatat.c new file mode 100644 index 000000000..149c1890d --- /dev/null +++ b/libc/sysdeps/linux/common/fstatat.c @@ -0,0 +1,27 @@ +/* + * fstatat() for uClibc + * + * Copyright (C) 2009 Analog Devices Inc. + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include "xstatconv.h" + +#ifdef __NR_fstatat64 +int fstatat(int fd, const char *file, struct stat *buf, int flag) +{ + int ret; + struct kernel_stat kbuf; + + ret = INLINE_SYSCALL(fstatat64, 4, fd, file, &kbuf, flag); + if (ret == 0) + __xstat_conv(&kbuf, buf); + + return ret; +} +#else +/* should add emulation with fstat() and /proc/self/fd/ ... */ +#endif diff --git a/libc/sysdeps/linux/common/fstatat64.c b/libc/sysdeps/linux/common/fstatat64.c new file mode 100644 index 000000000..5ae1fadba --- /dev/null +++ b/libc/sysdeps/linux/common/fstatat64.c @@ -0,0 +1,31 @@ +/* + * fstatat64() for uClibc + * + * Copyright (C) 2009 Analog Devices Inc. + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include "xstatconv.h" + +#ifdef __UCLIBC_HAS_LFS__ + +#ifdef __NR_fstatat64 +int fstatat64(int fd, const char *file, struct stat64 *buf, int flag) +{ + int ret; + struct kernel_stat64 kbuf; + + ret = INLINE_SYSCALL(fstatat64, 4, fd, file, &kbuf, flag); + if (ret == 0) + __xstat64_conv(&kbuf, buf); + + return ret; +} +#else +/* should add emulation with fstat64() and /proc/self/fd/ ... */ +#endif + +#endif diff --git a/libc/sysdeps/linux/common/futimesat.c b/libc/sysdeps/linux/common/futimesat.c new file mode 100644 index 000000000..bd73eae7e --- /dev/null +++ b/libc/sysdeps/linux/common/futimesat.c @@ -0,0 +1,16 @@ +/* + * futimesat() for uClibc + * + * Copyright (C) 2009 Analog Devices Inc. + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +#ifdef __NR_futimesat +_syscall3(int, futimesat, int, fd, const char *, file, const struct timeval *, tvp) +#else +/* should add emulation with futimes() and /proc/self/fd/ ... */ +#endif diff --git a/libc/sysdeps/linux/common/linkat.c b/libc/sysdeps/linux/common/linkat.c new file mode 100644 index 000000000..9abe9ec71 --- /dev/null +++ b/libc/sysdeps/linux/common/linkat.c @@ -0,0 +1,16 @@ +/* + * linkat() for uClibc + * + * Copyright (C) 2009 Analog Devices Inc. + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +#ifdef __NR_linkat +_syscall5(int, linkat, int, fromfd, const char *, from, int, tofd, const char *, to, int, flags) +#else +/* should add emulation with link() and /proc/self/fd/ ... */ +#endif diff --git a/libc/sysdeps/linux/common/mkdirat.c b/libc/sysdeps/linux/common/mkdirat.c new file mode 100644 index 000000000..4da9468e1 --- /dev/null +++ b/libc/sysdeps/linux/common/mkdirat.c @@ -0,0 +1,16 @@ +/* + * mkdirat() for uClibc + * + * Copyright (C) 2009 Analog Devices Inc. + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +#ifdef __NR_mkdirat +_syscall3(int, mkdirat, int, fd, const char *, path, mode_t, mode) +#else +/* should add emulation with mkdir() and /proc/self/fd/ ... */ +#endif diff --git a/libc/sysdeps/linux/common/mkfifoat.c b/libc/sysdeps/linux/common/mkfifoat.c new file mode 100644 index 000000000..e442fe22f --- /dev/null +++ b/libc/sysdeps/linux/common/mkfifoat.c @@ -0,0 +1,19 @@ +/* + * mkfifoat() for uClibc + * + * Copyright (C) 2009 Analog Devices Inc. + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +#ifdef __NR_mknodat +int mkfifoat(int fd, const char *path, mode_t mode) +{ + return mknodat(fd, path, mode | S_IFIFO, 0); +} +#else +/* should add emulation with mkfifo() and /proc/self/fd/ ... */ +#endif diff --git a/libc/sysdeps/linux/common/mknodat.c b/libc/sysdeps/linux/common/mknodat.c new file mode 100644 index 000000000..93b9e6e75 --- /dev/null +++ b/libc/sysdeps/linux/common/mknodat.c @@ -0,0 +1,25 @@ +/* + * mknodat() for uClibc + * + * Copyright (C) 2009 Analog Devices Inc. + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +#ifdef __NR_mknodat +int mknodat(int fd, const char *path, mode_t mode, dev_t dev) +{ + unsigned long long int k_dev; + + /* We must convert the value to dev_t type used by the kernel. */ + k_dev = (dev) & ((1ULL << 32) - 1); + + return INLINE_SYSCALL(mknodat, 4, fd, path, mode, (unsigned int)k_dev); +} +libc_hidden_def(mknodat) +#else +/* should add emulation with mknod() and /proc/self/fd/ ... */ +#endif diff --git a/libc/sysdeps/linux/common/openat.c b/libc/sysdeps/linux/common/openat.c new file mode 100644 index 000000000..33bd606a1 --- /dev/null +++ b/libc/sysdeps/linux/common/openat.c @@ -0,0 +1,18 @@ +/* + * openat() for uClibc + * + * Copyright (C) 2009 Analog Devices Inc. + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define openat __xx_openat +#include +#include +#undef openat + +#ifdef __NR_openat +_syscall4(int, openat, int, fd, const char *, file, int, oflag, mode_t, mode) +#else +/* should add emulation with open() and /proc/self/fd/ ... */ +#endif diff --git a/libc/sysdeps/linux/common/openat64.c b/libc/sysdeps/linux/common/openat64.c new file mode 100644 index 000000000..75711aad6 --- /dev/null +++ b/libc/sysdeps/linux/common/openat64.c @@ -0,0 +1,25 @@ +/* + * openat() for uClibc + * + * Copyright (C) 2009 Analog Devices Inc. + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define openat64 __xx_openat +#include +#include +#undef openat64 + +#ifdef __UCLIBC_HAS_LFS__ + +#ifdef __NR_openat +int openat64(int fd, const char *file, int oflag, mode_t mode) +{ + return openat(fd, file, oflag | O_LARGEFILE, mode); +} +#else +/* should add emulation with open() and /proc/self/fd/ ... */ +#endif + +#endif diff --git a/libc/sysdeps/linux/common/readlinkat.c b/libc/sysdeps/linux/common/readlinkat.c new file mode 100644 index 000000000..d0a98e115 --- /dev/null +++ b/libc/sysdeps/linux/common/readlinkat.c @@ -0,0 +1,16 @@ +/* + * readlinkat() for uClibc + * + * Copyright (C) 2009 Analog Devices Inc. + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +#ifdef __NR_readlinkat +_syscall4(ssize_t, readlinkat, int, fd, const char *, path, char *, buf, size_t, len) +#else +/* should add emulation with readlink() and /proc/self/fd/ ... */ +#endif diff --git a/libc/sysdeps/linux/common/renameat.c b/libc/sysdeps/linux/common/renameat.c new file mode 100644 index 000000000..a898f7b86 --- /dev/null +++ b/libc/sysdeps/linux/common/renameat.c @@ -0,0 +1,16 @@ +/* + * renameat() for uClibc + * + * Copyright (C) 2009 Analog Devices Inc. + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +#ifdef __NR_renameat +_syscall4(int, renameat, int, oldfd, const char *, old, int, newfd, const char *, new) +#else +/* should add emulation with rename() and /proc/self/fd/ ... */ +#endif diff --git a/libc/sysdeps/linux/common/symlinkat.c b/libc/sysdeps/linux/common/symlinkat.c new file mode 100644 index 000000000..6381b3319 --- /dev/null +++ b/libc/sysdeps/linux/common/symlinkat.c @@ -0,0 +1,16 @@ +/* + * symlinkat() for uClibc + * + * Copyright (C) 2009 Analog Devices Inc. + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +#ifdef __NR_symlinkat +_syscall3(int, symlinkat, const char *, from, int, tofd, const char *, to) +#else +/* should add emulation with symlink() and /proc/self/fd/ ... */ +#endif diff --git a/libc/sysdeps/linux/common/unlinkat.c b/libc/sysdeps/linux/common/unlinkat.c new file mode 100644 index 000000000..0eaf2b670 --- /dev/null +++ b/libc/sysdeps/linux/common/unlinkat.c @@ -0,0 +1,16 @@ +/* + * unlinkat() for uClibc + * + * Copyright (C) 2009 Analog Devices Inc. + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +#ifdef __NR_unlinkat +_syscall3(int, unlinkat, int, fd, const char *, file, int, flag) +#else +/* should add emulation with unlink() and /proc/self/fd/ ... */ +#endif diff --git a/libc/sysdeps/linux/common/utimensat.c b/libc/sysdeps/linux/common/utimensat.c new file mode 100644 index 000000000..3c5af8586 --- /dev/null +++ b/libc/sysdeps/linux/common/utimensat.c @@ -0,0 +1,16 @@ +/* + * utimensat() for uClibc + * + * Copyright (C) 2009 Analog Devices Inc. + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +#ifdef __NR_utimensat +_syscall4(int, utimensat, int, fd, const char *, path, const struct timespec *, times, int, flags) +#else +/* should add emulation with utimens() and /proc/self/fd/ ... */ +#endif -- cgit v1.2.3