From 14f8a6c2dd9f3590cb54cb8f8edd74e4b84f6cd5 Mon Sep 17 00:00:00 2001 From: dongjiuzhu1 Date: Sat, 4 Feb 2023 09:00:49 +0800 Subject: [PATCH] fs: support openat/fchmodat/mkfifoat/fstatat/...at api Refs to: https://linux.die.net/man/2/openat Signed-off-by: dongjiuzhu1 --- include/fcntl.h | 13 ++++ include/stdio.h | 2 + include/sys/stat.h | 8 +++ include/sys/time.h | 2 + include/unistd.h | 10 ++++ libs/libc/libc.h | 4 ++ libs/libc/misc/Make.defs | 2 + libs/libc/misc/lib_fchmodat.c | 83 ++++++++++++++++++++++++++ libs/libc/misc/lib_fstatat.c | 84 ++++++++++++++++++++++++++ libs/libc/misc/lib_getfullpath.c | 93 +++++++++++++++++++++++++++++ libs/libc/misc/lib_mkdirat.c | 76 ++++++++++++++++++++++++ libs/libc/misc/lib_mkfifo.c | 46 +++++++++++++++ libs/libc/misc/lib_mknod.c | 47 +++++++++++++++ libs/libc/misc/lib_openat.c | 87 +++++++++++++++++++++++++++ libs/libc/misc/lib_utimensat.c | 83 ++++++++++++++++++++++++++ libs/libc/stdio/Make.defs | 1 + libs/libc/stdio/lib_renameat.c | 88 +++++++++++++++++++++++++++ libs/libc/unistd/Make.defs | 2 + libs/libc/unistd/lib_access.c | 48 +++++++++++++++ libs/libc/unistd/lib_fchownat.c | 85 +++++++++++++++++++++++++++ libs/libc/unistd/lib_linkat.c | 98 +++++++++++++++++++++++++++++++ libs/libc/unistd/lib_readlinkat.c | 84 ++++++++++++++++++++++++++ libs/libc/unistd/lib_symlinkat.c | 81 +++++++++++++++++++++++++ libs/libc/unistd/lib_unlinkat.c | 85 +++++++++++++++++++++++++++ libs/libc/unistd/lib_utimes.c | 18 ++++++ 25 files changed, 1230 insertions(+) create mode 100644 libs/libc/misc/lib_fchmodat.c create mode 100644 libs/libc/misc/lib_fstatat.c create mode 100644 libs/libc/misc/lib_getfullpath.c create mode 100644 libs/libc/misc/lib_mkdirat.c create mode 100644 libs/libc/misc/lib_openat.c create mode 100644 libs/libc/misc/lib_utimensat.c create mode 100644 libs/libc/stdio/lib_renameat.c create mode 100644 libs/libc/unistd/lib_fchownat.c create mode 100644 libs/libc/unistd/lib_linkat.c create mode 100644 libs/libc/unistd/lib_readlinkat.c create mode 100644 libs/libc/unistd/lib_symlinkat.c create mode 100644 libs/libc/unistd/lib_unlinkat.c diff --git a/include/fcntl.h b/include/fcntl.h index 907180be927..c0f8449e985 100644 --- a/include/fcntl.h +++ b/include/fcntl.h @@ -112,6 +112,18 @@ #define FD_CLOEXEC 1 +/* The flag for openat, faccessat, ... */ + +#define AT_FDCWD -100 /* Special value used to indicate openat should use the current + * working directory. + */ +#define AT_SYMLINK_NOFOLLOW 0x0100 /* Do not follow symbolic links. */ +#define AT_EACCESS 0x0200 /* Test access permitted for effective IDs, not real IDs. */ +#define AT_REMOVEDIR 0x0200 /* Remove directory instead of unlinking file. */ +#define AT_SYMLINK_FOLLOW 0x0400 /* Follow symbolic links. */ +#define AT_NO_AUTOMOUNT 0x0800 /* Suppress terminal automount traversal */ +#define AT_EMPTY_PATH 0x1000 /* Allow empty relative pathname */ + /* These are the notifications that can be received from F_NOTIFY (linux) */ #define DN_ACCESS 0 /* A file was accessed */ @@ -185,6 +197,7 @@ extern "C" /* POSIX-like File System Interfaces */ int open(FAR const char *path, int oflag, ...); +int openat(int dirfd, FAR const char *path, int oflag, ...); int fcntl(int fd, int cmd, ...); int posix_fallocate(int fd, off_t offset, off_t len); diff --git a/include/stdio.h b/include/stdio.h index 92a863d3469..268406f9505 100644 --- a/include/stdio.h +++ b/include/stdio.h @@ -188,6 +188,8 @@ int putc(int c, FAR FILE *stream); int putchar(int c); int puts(FAR const IPTR char *s); int rename(FAR const char *oldpath, FAR const char *newpath); +int renameat(int olddirfd, FAR const char *oldpath, + int newdirfd, FAR const char *newpath); int sprintf(FAR char *buf, FAR const IPTR char *fmt, ...) printf_like(2, 3); int asprintf(FAR char **ptr, FAR const IPTR char *fmt, ...) diff --git a/include/sys/stat.h b/include/sys/stat.h index 53b8772c4eb..7a11316cd65 100644 --- a/include/sys/stat.h +++ b/include/sys/stat.h @@ -171,15 +171,23 @@ extern "C" #endif int mkdir(FAR const char *pathname, mode_t mode); +int mkdirat(int dirfd, FAR const char *pathname, mode_t mode); int mkfifo(FAR const char *pathname, mode_t mode); +int mkfifoat(int dirfd, FAR const char *pathname, mode_t mode); int mknod(FAR const char *path, mode_t mode, dev_t dev); +int mknodat(int dirfd, FAR const char *path, mode_t mode, dev_t dev); int stat(FAR const char *path, FAR struct stat *buf); int lstat(FAR const char *path, FAR struct stat *buf); int fstat(int fd, FAR struct stat *buf); +int fstatat(int dirfd, FAR const char *path, FAR struct stat *buf, + int flags); int chmod(FAR const char *path, mode_t mode); int lchmod(FAR const char *path, mode_t mode); int fchmod(int fd, mode_t mode); +int fchmodat(int dirfd, FAR const char *path, mode_t mode, int flags); int utimens(FAR const char *path, const struct timespec times[2]); +int utimensat(int dirfd, FAR const char *path, + const struct timespec times[2], int flags); int lutimens(FAR const char *path, const struct timespec times[2]); int futimens(int fd, const struct timespec times[2]); diff --git a/include/sys/time.h b/include/sys/time.h index 94fede2ecce..0069de9eaa3 100644 --- a/include/sys/time.h +++ b/include/sys/time.h @@ -373,6 +373,8 @@ int setitimer(int which, FAR const struct itimerval *value, int utimes(FAR const char *path, const struct timeval times[2]); int lutimes(FAR const char *path, const struct timeval times[2]); +int futimesat(int dirfd, FAR const char *path, + const struct timeval times[2]); /**************************************************************************** * Name: futimes diff --git a/include/unistd.h b/include/unistd.h index d219b3cf64a..0ee4275de9c 100644 --- a/include/unistd.h +++ b/include/unistd.h @@ -368,14 +368,24 @@ FAR char *getcwd(FAR char *buf, size_t size); /* File path operations */ int access(FAR const char *path, int amode); +int faccessat(int dirfd, FAR const char *path, int mode, int flags); int rmdir(FAR const char *pathname); int unlink(FAR const char *pathname); +int unlinkat(int dirfd, FAR const char *pathname, int flags); int truncate(FAR const char *path, off_t length); int link(FAR const char *path1, FAR const char *path2); +int linkat(int olddirfd, FAR const char *path1, + int newdirfd, FAR const char *path2, int flags); int symlink(FAR const char *path1, FAR const char *path2); +int symlinkat(FAR const char *path1, int dirfd, + FAR const char *path2); ssize_t readlink(FAR const char *path, FAR char *buf, size_t bufsize); +ssize_t readlinkat(int dirfd, FAR const char *path, FAR char *buf, + size_t bufsize); int chown(FAR const char *path, uid_t owner, gid_t group); int lchown(FAR const char *path, uid_t owner, gid_t group); +int fchownat(int dirfd, FAR const char *path, uid_t owner, + gid_t group, int flags); /* Execution of programs from files */ diff --git a/libs/libc/libc.h b/libs/libc/libc.h index 1f537493ef5..2678ef75d96 100644 --- a/libs/libc/libc.h +++ b/libs/libc/libc.h @@ -81,6 +81,10 @@ FAR char *__dtoa(double d, int mode, int ndigits, FAR int *decpt, FAR int *sign, FAR char **rve); #endif +/* Defined in lib_getfullpath.c */ + +int lib_getfullpath(int dirfd, FAR const char *path, FAR char *fullpath); + /* Defined in lib_fopen.c */ int lib_mode2oflags(FAR const char *mode); diff --git a/libs/libc/misc/Make.defs b/libs/libc/misc/Make.defs index 136d9823d79..3a52b25b119 100644 --- a/libs/libc/misc/Make.defs +++ b/libs/libc/misc/Make.defs @@ -23,6 +23,8 @@ CSRCS += lib_mknod.c lib_umask.c lib_utsname.c lib_getrandom.c CSRCS += lib_xorshift128.c lib_tea_encrypt.c lib_tea_decrypt.c CSRCS += lib_cxx_initialize.c lib_impure.c lib_memfd.c lib_mutex.c +CSRCS += lib_fchmodat.c lib_fstatat.c lib_getfullpath.c lib_openat.c +CSRCS += lib_mkdirat.c lib_utimensat.c # Support for platforms that do not have long long types diff --git a/libs/libc/misc/lib_fchmodat.c b/libs/libc/misc/lib_fchmodat.c new file mode 100644 index 00000000000..7ebb47c966e --- /dev/null +++ b/libs/libc/misc/lib_fchmodat.c @@ -0,0 +1,83 @@ +/**************************************************************************** + * libs/libc/misc/lib_fchmodat.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +#include "libc.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: fchmodat + * + * Description: + * The fchmodat() system call operates in exactly the same way as chmod(), + * except for the differences described here. + * + * If the pathname given in pathname is relative, then it is interpreted + * relative to the directory referred to by the file descriptor dirfd + * (rather than relative to the current working directory of the calling + * process) + * + * If pathname is relative and dirfd is the special value AT_FDCWD, then + * pathname is interpreted relative to the current working directory of + * the calling process (like chmod()). + * + * If pathname is absolute, then dirfd is ignored. + * + * Input Parameters: + * dirfd - The file descriptor of directory. + * path - A pointer to the path. + * mode - The access mode. + * flags - Ignored. + * + * Returned Value: + * Return zero on success, or -1 if an error occurred (in which case, + * errno is set appropriately). + * + ****************************************************************************/ + +int fchmodat(int dirfd, FAR const char *path, mode_t mode, int flags) +{ + char fullpath[PATH_MAX]; + int ret; + + ret = lib_getfullpath(dirfd, path, fullpath); + if (ret < 0) + { + set_errno(-ret); + return ERROR; + } + + if ((flags & AT_SYMLINK_NOFOLLOW) != 0) + { + return lchmod(fullpath, mode); + } + + return chmod(fullpath, mode); +} diff --git a/libs/libc/misc/lib_fstatat.c b/libs/libc/misc/lib_fstatat.c new file mode 100644 index 00000000000..af64110f3d1 --- /dev/null +++ b/libs/libc/misc/lib_fstatat.c @@ -0,0 +1,84 @@ +/**************************************************************************** + * libs/libc/misc/lib_fstatat.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +#include "libc.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: fstatat + * + * Description: + * The fstatat() system call operates in exactly the same way as stat(), + * except for the differences described here. + * + * If the pathname given in pathname is relative, then it is interpreted + * relative to the directory referred to by the file descriptor dirfd + * (rather than relative to the current working directory of the calling + * process) + * + * If pathname is relative and dirfd is the special value AT_FDCWD, then + * pathname is interpreted relative to the current working directory of + * the calling process (like stat()). + * + * If pathname is absolute, then dirfd is ignored. + * + * Input Parameters: + * dirfd - The file descriptor of directory. + * path - A pointer to the path. + * buf - The buf to get file status. + * flags - Ignored. + * + * Returned Value: + * Return zero on success, or -1 if an error occurred (in which case, + * errno is set appropriately). + * + ****************************************************************************/ + +int fstatat(int dirfd, FAR const char *path, FAR struct stat *buf, + int flags) +{ + char fullpath[PATH_MAX]; + int ret; + + ret = lib_getfullpath(dirfd, path, fullpath); + if (ret < 0) + { + set_errno(-ret); + return ERROR; + } + + if ((flags & AT_SYMLINK_NOFOLLOW) != 0) + { + return lstat(fullpath, buf); + } + + return stat(fullpath, buf); +} diff --git a/libs/libc/misc/lib_getfullpath.c b/libs/libc/misc/lib_getfullpath.c new file mode 100644 index 00000000000..1cd454c38e6 --- /dev/null +++ b/libs/libc/misc/lib_getfullpath.c @@ -0,0 +1,93 @@ +/**************************************************************************** + * libs/libc/misc/lib_getfullpath.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include "libc.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: lib_getfullpath + * + * Description: + * Given the directory path from dirfd. + * + ****************************************************************************/ + +int lib_getfullpath(int dirfd, FAR const char *path, FAR char *fullpath) +{ + if (path == NULL || fullpath == NULL) + { + return -EINVAL; + } + else if (path[0] == '/') + { + /* The path is absolute, then dirfd is ignored. */ + + strlcpy(fullpath, path, PATH_MAX); + return 0; + } + + if (dirfd == AT_FDCWD) + { + /* The dirfd is the special value AT_FDCWD, then pathname is + * interpreted relative to the current working directory of the + * calling process. + */ + + FAR char *pwd = ""; + +#ifndef CONFIG_DISABLE_ENVIRON + pwd = getenv("PWD"); + if (pwd == NULL) + { + pwd = CONFIG_LIBC_HOMEDIR; + } +#endif + + sprintf(fullpath, "%s/%s", pwd, path); + return 0; + } + else + { + int ret; + + /* Get real directory path by dirfd */ + + ret = fcntl(dirfd, F_GETPATH, fullpath); + if (ret >= 0) + { + strlcat(fullpath, path, PATH_MAX); + } + + return 0; + } +} diff --git a/libs/libc/misc/lib_mkdirat.c b/libs/libc/misc/lib_mkdirat.c new file mode 100644 index 00000000000..9932f900eed --- /dev/null +++ b/libs/libc/misc/lib_mkdirat.c @@ -0,0 +1,76 @@ +/**************************************************************************** + * libs/libc/misc/lib_mkdirat.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include "libc.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: mkdirat + * + * Description: + * The mkdirat() system call operates in exactly the same way as mkdir(), + * except for the differences described here. + * + * If the pathname given in pathname is relative, then it is interpreted + * relative to the directory referred to by the file descriptor dirfd + * (rather than relative to the current working directory of the calling + * process) + * + * If pathname is relative and dirfd is the special value AT_FDCWD, then + * pathname is interpreted relative to the current working directory of + * the calling process (like mkdir()). + * + * If pathname is absolute, then dirfd is ignored. + * + * Input Parameters: + * dirfd - The file descriptor of directory. + * path - a pointer to the path + * amode - the access mode + * + * Returned Value: + * Return zero on success, or -1 if an error occurred (in which case, + * errno is set appropriately). + * + ****************************************************************************/ + +int mkdirat(int dirfd, FAR const char *path, mode_t mode) +{ + char fullpath[PATH_MAX]; + int ret; + + ret = lib_getfullpath(dirfd, path, fullpath); + if (ret < 0) + { + set_errno(-ret); + return ERROR; + } + + return mkdir(fullpath, mode); +} diff --git a/libs/libc/misc/lib_mkfifo.c b/libs/libc/misc/lib_mkfifo.c index f237ff55c23..5999fb39f40 100644 --- a/libs/libc/misc/lib_mkfifo.c +++ b/libs/libc/misc/lib_mkfifo.c @@ -30,6 +30,8 @@ #include +#include "libc.h" + #if defined(CONFIG_PIPES) && CONFIG_DEV_FIFO_SIZE > 0 /**************************************************************************** @@ -79,4 +81,48 @@ int mkfifo(FAR const char *pathname, mode_t mode) return ret; } +/**************************************************************************** + * Name: mkfifoat + * + * Description: + * The mkfifoat() system call operates in exactly the same way as mkfifo(), + * except for the differences described here. + * + * If the pathname given in pathname is relative, then it is interpreted + * relative to the directory referred to by the file descriptor dirfd + * (rather than relative to the current working directory of the calling + * process) + * + * If pathname is relative and dirfd is the special value AT_FDCWD, then + * pathname is interpreted relative to the current working directory of + * the calling process (like mkfifo()). + * + * If pathname is absolute, then dirfd is ignored. + * + * Input Parameters: + * dirfd - The file descriptor of directory. + * path - a pointer to the path. + * mode - the access mode. + * + * Returned Value: + * Return zero on success, or -1 if an error occurred (in which case, + * errno is set appropriately). + * + ****************************************************************************/ + +int mkfifoat(int dirfd, FAR const char *path, mode_t mode) +{ + char fullpath[PATH_MAX]; + int ret; + + ret = lib_getfullpath(dirfd, path, fullpath); + if (ret < 0) + { + set_errno(-ret); + return ERROR; + } + + return mkfifo(fullpath, mode); +} + #endif /* CONFIG_PIPES && CONFIG_DEV_FIFO_SIZE > 0 */ diff --git a/libs/libc/misc/lib_mknod.c b/libs/libc/misc/lib_mknod.c index 538fefdd214..205300a91b5 100644 --- a/libs/libc/misc/lib_mknod.c +++ b/libs/libc/misc/lib_mknod.c @@ -27,6 +27,8 @@ #include #include +#include "libc.h" + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -97,3 +99,48 @@ int mknod(FAR const char *path, mode_t mode, dev_t dev) return ret; } + +/**************************************************************************** + * Name: mknodat + * + * Description: + * The mknodat() system call operates in exactly the same way as mknod(), + * except for the differences described here. + * + * If the pathname given in pathname is relative, then it is interpreted + * relative to the directory referred to by the file descriptor dirfd + * (rather than relative to the current working directory of the calling + * process) + * + * If pathname is relative and dirfd is the special value AT_FDCWD, then + * pathname is interpreted relative to the current working directory of + * the calling process (like mknod()). + * + * If pathname is absolute, then dirfd is ignored. + * + * Input Parameters: + * dirfd - The file descriptor of directory. + * path - a pointer to the path. + * mode - the access mode. + * dev - Ignored. + * + * Returned Value: + * Return zero on success, or -1 if an error occurred (in which case, + * errno is set appropriately). + * + ****************************************************************************/ + +int mknodat(int dirfd, FAR const char *path, mode_t mode, dev_t dev) +{ + char fullpath[PATH_MAX]; + int ret; + + ret = lib_getfullpath(dirfd, path, fullpath); + if (ret < 0) + { + set_errno(-ret); + return ERROR; + } + + return mknod(fullpath, mode, dev); +} diff --git a/libs/libc/misc/lib_openat.c b/libs/libc/misc/lib_openat.c new file mode 100644 index 00000000000..20be9bb916f --- /dev/null +++ b/libs/libc/misc/lib_openat.c @@ -0,0 +1,87 @@ +/**************************************************************************** + * libs/libc/misc/lib_openat.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +#include "libc.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: openat + * + * Description: + * The openat() system call operates in exactly the same way as open(), + * except for the differences: + * If the pathname given in pathname is relative, then it is interpreted + * relative to the directory referred to by the file descriptor dirfd + * (rather than relative to the current working directory of the calling + * process). + * + * If pathname is relative and dirfd is the special value AT_FDCWD, then + * pathname is interpreted relative to the current working directory of + * the calling process. + * + * If pathname is absolute, then dirfd is ignored. + * + * Input Parameters: + * dirfd - The file descriptor of directory. + * path - a pointer to the path + * oflags - the flag of open. + * amode - the access mode + * + * Returned Value: + * Return the new file descriptor (a nonnegative integer), or -1 if an + * error occurred (in which case, errno is set appropriately). + * + ****************************************************************************/ + +int openat(int dirfd, FAR const char *path, int oflags, ...) +{ + char fullpath[PATH_MAX]; + mode_t mode = 0; + int ret; + + ret = lib_getfullpath(dirfd, path, fullpath); + if (ret < 0) + { + set_errno(-ret); + return ERROR; + } + + if ((oflags & O_CREAT) != 0) + { + va_list ap; + + va_start(ap, oflags); + mode = va_arg(ap, mode_t); + va_end(ap); + } + + return open(fullpath, oflags, mode); +} diff --git a/libs/libc/misc/lib_utimensat.c b/libs/libc/misc/lib_utimensat.c new file mode 100644 index 00000000000..2fed37d87fe --- /dev/null +++ b/libs/libc/misc/lib_utimensat.c @@ -0,0 +1,83 @@ +/**************************************************************************** + * libs/libc/misc/lib_utimensat.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +#include "libc.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: utimensat + * + * Description: + * The utimensat() system call operates in exactly the same way as + * utimens(), except for the differences described here. + * + * If the pathname given in pathname is relative, then it is interpreted + * relative to the directory referred to by the file descriptor dirfd + * (rather than relative to the current working directory of the calling + * process) + * + * If pathname is relative and dirfd is the special value AT_FDCWD, then + * pathname is interpreted relative to the current working directory of + * the calling process (like utimens()). + * + * If pathname is absolute, then dirfd is ignored. + * + * Input Parameters: + * dirfd - The file descriptor of directory. + * path - a pointer to the path. + * flags - the access mode. + * + * Returned Value: + * Return zero on success, or -1 if an error occurred (in which case, + * errno is set appropriately). + * + ****************************************************************************/ + +int utimensat(int dirfd, FAR const char *path, + const struct timespec times[2], int flags) +{ + char fullpath[PATH_MAX]; + int ret; + + ret = lib_getfullpath(dirfd, path, fullpath); + if (ret < 0) + { + set_errno(-ret); + return ERROR; + } + + if ((flags & AT_SYMLINK_NOFOLLOW) != 0) + { + return lutimens(fullpath, times); + } + + return utimens(fullpath, times); +} diff --git a/libs/libc/stdio/Make.defs b/libs/libc/stdio/Make.defs index 57d169fc683..47aa9601ea3 100644 --- a/libs/libc/stdio/Make.defs +++ b/libs/libc/stdio/Make.defs @@ -27,6 +27,7 @@ CSRCS += lib_vsnprintf.c lib_dprintf.c lib_vdprintf.c lib_vprintf.c CSRCS += lib_perror.c lib_putchar.c lib_getchar.c lib_puts.c CSRCS += lib_sscanf.c lib_vsscanf.c lib_libvscanf.c lib_libvsprintf.c CSRCS += lib_remove.c lib_tempnam.c lib_tmpnam.c lib_ultoa_invert.c +CSRCS += lib_renameat.c ifeq ($(CONFIG_LIBC_FLOATINGPOINT),y) CSRCS += lib_dtoa_engine.c lib_dtoa_data.c diff --git a/libs/libc/stdio/lib_renameat.c b/libs/libc/stdio/lib_renameat.c new file mode 100644 index 00000000000..12bd24cd41a --- /dev/null +++ b/libs/libc/stdio/lib_renameat.c @@ -0,0 +1,88 @@ +/**************************************************************************** + * libs/libc/stdio/lib_renameat.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include "libc.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: renameat + * + * Description: + * The renameat() system call operates in exactly the same way as rename(), + * except for the differences described here. + * + * If the pathname given in oldpath is relative, then it is interpreted + * relative to the directory referred to by the file descriptor olddirfd + * (rather than relative to the current working directory of the calling + * process, as is done by rename() for a relative pathname). + * + * If oldpath is relative and olddirfd is the special value AT_FDCWD, then + * oldpath is interpreted relative to the current working directory of the + * calling process (like rename()). + * + * If oldpath is absolute, then olddirfd is ignored. + * + * The interpretation of newpath is as for oldpath, except that a relative + * pathname is interpreted relative to the directory referred to by the + * file descriptor newdirfd. + * + * Input Parameters: + * olddirfd - The file descriptor of old directory. + * oldpath - A pointer to the old path + * newdirfd - The file descriptor of new directory. + * newpath - A pointer to the new path + * + * Returned Value: + * Return zero on success, or -1 if an error occurred (in which case, + * errno is set appropriately). + * + ****************************************************************************/ + +int renameat(int olddirfd, FAR const char *oldpath, + int newdirfd, FAR const char *newpath) +{ + char oldfullpath[PATH_MAX]; + char newfullpath[PATH_MAX]; + int ret; + + ret = lib_getfullpath(olddirfd, oldpath, oldfullpath); + if (ret >= 0) + { + ret = lib_getfullpath(newdirfd, newpath, newfullpath); + } + + if (ret < 0) + { + set_errno(-ret); + return ERROR; + } + + return rename(oldfullpath, newfullpath); +} diff --git a/libs/libc/unistd/Make.defs b/libs/libc/unistd/Make.defs index 1bd870eefba..a6ef457e3cf 100644 --- a/libs/libc/unistd/Make.defs +++ b/libs/libc/unistd/Make.defs @@ -29,6 +29,8 @@ CSRCS += lib_usleep.c lib_seteuid.c lib_setegid.c lib_geteuid.c lib_getegid.c CSRCS += lib_setreuid.c lib_setregid.c lib_getrusage.c lib_utime.c lib_utimes.c CSRCS += lib_setrlimit.c lib_getrlimit.c lib_setpriority.c lib_getpriority.c CSRCS += lib_futimes.c lib_lutimes.c lib_gethostname.c lib_sethostname.c +CSRCS += lib_fchownat.c lib_linkat.c lib_readlinkat.c lib_symlinkat.c +CSRCS += lib_unlinkat.c ifneq ($(CONFIG_SCHED_USER_IDENTITY),y) CSRCS += lib_setuid.c lib_setgid.c lib_getuid.c lib_getgid.c diff --git a/libs/libc/unistd/lib_access.c b/libs/libc/unistd/lib_access.c index c46083896c4..da35dbc9928 100644 --- a/libs/libc/unistd/lib_access.c +++ b/libs/libc/unistd/lib_access.c @@ -24,9 +24,12 @@ #include +#include #include #include +#include "libc.h" + /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ @@ -99,3 +102,48 @@ int access(FAR const char *path, int amode) return 0; } + +/**************************************************************************** + * Name: faccessat + * + * Description: + * The faccessat() system call operates in exactly the same way as + * access(), except for the differences described here. + * + * If the pathname given in pathname is relative, then it is interpreted + * relative to the directory referred to by the file descriptor dirfd + * (rather than relative to the current working directory of the calling + * process) + * + * If pathname is relative and dirfd is the special value AT_FDCWD, then + * pathname is interpreted relative to the current working directory of + * the calling process (like access()). + * + * If pathname is absolute, then dirfd is ignored. + * + * Input Parameters: + * dirfd - The file descriptor of directory. + * path - A pointer to the path. + * amode - The access mode. + * flags - Ignored. + * + * Returned Value: + * Return zero on success, or -1 if an error occurred (in which case, + * errno is set appropriately). + * + ****************************************************************************/ + +int faccessat(int dirfd, FAR const char *path, int amode, int flags) +{ + char fullpath[PATH_MAX]; + int ret; + + ret = lib_getfullpath(dirfd, path, fullpath); + if (ret < 0) + { + set_errno(-ret); + return ERROR; + } + + return access(fullpath, amode); +} diff --git a/libs/libc/unistd/lib_fchownat.c b/libs/libc/unistd/lib_fchownat.c new file mode 100644 index 00000000000..db3b26c91ac --- /dev/null +++ b/libs/libc/unistd/lib_fchownat.c @@ -0,0 +1,85 @@ +/**************************************************************************** + * libs/libc/unistd/lib_fchownat.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +#include "libc.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: fchownat + * + * Description: + * The fchownat() system call operates in exactly the same way as chown(), + * except for the differences described here. + * + * If the pathname given in pathname is relative, then it is interpreted + * relative to the directory referred to by the file descriptor dirfd + * (rather than relative to the current working directory of the calling + * process) + * + * If pathname is relative and dirfd is the special value AT_FDCWD, then + * pathname is interpreted relative to the current working directory of + * the calling process (like chown()). + * + * If pathname is absolute, then dirfd is ignored. + * + * Input Parameters: + * dirfd - The file descriptor of directory. + * path - A pointer to the path. + * owner - The owner to set. + * group - The group to set. + * flags - Ignored. + * + * Returned Value: + * Return zero on success, or -1 if an error occurred (in which case, + * errno is set appropriately). + * + ****************************************************************************/ + +int fchownat(int dirfd, FAR const char *path, uid_t owner, + gid_t group, int flags) +{ + char fullpath[PATH_MAX]; + int ret; + + ret = lib_getfullpath(dirfd, path, fullpath); + if (ret < 0) + { + set_errno(-ret); + return ERROR; + } + + if ((flags & AT_SYMLINK_NOFOLLOW) != 0) + { + return lchown(fullpath, owner, group); + } + + return chown(fullpath, owner, group); +} diff --git a/libs/libc/unistd/lib_linkat.c b/libs/libc/unistd/lib_linkat.c new file mode 100644 index 00000000000..4c2a8530ccb --- /dev/null +++ b/libs/libc/unistd/lib_linkat.c @@ -0,0 +1,98 @@ +/**************************************************************************** + * libs/libc/unistd/lib_linkat.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include "libc.h" + +#ifdef CONFIG_PSEUDOFS_SOFTLINKS + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: linkat + * + * Description: + * The linkat() system call operates in exactly the same way as link(), + * except for the differences described here. + * + * If the pathname given in pathname is relative, then it is interpreted + * relative to the directory referred to by the file descriptor dirfd + * (rather than relative to the current working directory of the calling + * process) + * If the pathname given in path1 is relative, then it is interpreted + * relative to the directory referred to by the file descriptor olddirfd + * (rather than relative to the current working directory of the calling + * process, as is done by link() for a relative pathname). + * + * If path1 is relative and olddirfd is the special value AT_FDCWD, then + * oldpath is interpreted relative to the current working directory of the + * calling process (like link()). + * + * If path1 is absolute, then olddirfd is ignored. + * + * The interpretation of path2 is as for path1, except that a relative + * pathname is interpreted relative to the directory referred to by the + * file descriptor newdirfd. + * + * Input Parameters: + * olddirfd - The file descriptor of directory. + * path1 - Points to a pathname naming an existing file. + * newdirfd - The file descriptor of directory. + * path2 - Points to a pathname naming the new directory entry to be + * created. + * flags - ignored. + * + * Returned Value: + * Return zero on success, or -1 if an error occurred (in which case, + * errno is set appropriately). + * + ****************************************************************************/ + +int linkat(int olddirfd, FAR const char *path1, + int newdirfd, FAR const char *path2, int flags) +{ + char oldfullpath[PATH_MAX]; + char newfullpath[PATH_MAX]; + int ret; + + ret = lib_getfullpath(olddirfd, path1, oldfullpath); + if (ret >= 0) + { + ret = lib_getfullpath(newdirfd, path2, newfullpath); + } + + if (ret < 0) + { + set_errno(-ret); + return ERROR; + } + + return link(oldfullpath, newfullpath); +} + +#endif /* CONFIG_PSEUDOFS_SOFTLINKS */ diff --git a/libs/libc/unistd/lib_readlinkat.c b/libs/libc/unistd/lib_readlinkat.c new file mode 100644 index 00000000000..fe911dd6195 --- /dev/null +++ b/libs/libc/unistd/lib_readlinkat.c @@ -0,0 +1,84 @@ +/**************************************************************************** + * libs/libc/unistd/lib_readlinkat.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include "libc.h" + +#ifdef CONFIG_PSEUDOFS_SOFTLINKS + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: readlinkat + * + * Description: + * The readlinkat() system call operates in exactly the same way as + * readlink(), except for the differences described here. + * + * If the pathname given in pathname is relative, then it is interpreted + * relative to the directory referred to by the file descriptor dirfd + * (rather than relative to the current working directory of the calling + * process) + * + * If pathname is relative and dirfd is the special value AT_FDCWD, then + * pathname is interpreted relative to the current working directory of + * the calling process (like readlink()). + * + * If pathname is absolute, then dirfd is ignored. + * + * Input Parameters: + * dirfd - The file descriptor of directory. + * path - The full path to the symbolic link + * buf - The user-provided buffer in which to return the path to the + * link target. + * bufsize - The size of 'buf' + * + * Returned Value: + * Upon successful completion, readlinkat() will return the count of bytes + * placed in the buffer. Otherwise, it will return a value of -1, leave the + * buffer unchanged, and set errno to indicate the error. + * + ****************************************************************************/ + +ssize_t readlinkat(int dirfd, FAR const char *path, FAR char *buf, + size_t bufsize) +{ + char fullpath[PATH_MAX]; + int ret; + + ret = lib_getfullpath(dirfd, path, fullpath); + if (ret < 0) + { + set_errno(-ret); + return ERROR; + } + + return readlink(fullpath, buf, bufsize); +} + +#endif /* CONFIG_PSEUDOFS_SOFTLINKS */ diff --git a/libs/libc/unistd/lib_symlinkat.c b/libs/libc/unistd/lib_symlinkat.c new file mode 100644 index 00000000000..33d6698eed0 --- /dev/null +++ b/libs/libc/unistd/lib_symlinkat.c @@ -0,0 +1,81 @@ +/**************************************************************************** + * libs/libc/unistd/lib_symlinkat.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include "libc.h" + +#ifdef CONFIG_PSEUDOFS_SOFTLINKS + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: symlinkat + * + * Description: + * The symlinkat() system call operates in exactly the same way as + * symlink(), except for the differences described here. + * + * If the pathname given in pathname is relative, then it is interpreted + * relative to the directory referred to by the file descriptor dirfd + * (rather than relative to the current working directory of the calling + * process) + * + * If pathname is relative and dirfd is the special value AT_FDCWD, then + * pathname is interpreted relative to the current working directory of + * the calling process (like symlink()). + * + * If pathname is absolute, then dirfd is ignored. + * + * Input Parameters: + * path1 - Points to a pathname naming an existing file. + * dirfd - The file descriptor of directory. + * path2 - Points to a pathname naming the new directory entry to be + * created. + * + * Returned Value: + * Return zero on success, or -1 if an error occurred (in which case, + * errno is set appropriately). + * + ****************************************************************************/ + +int symlinkat(FAR const char *path1, int dirfd, FAR const char *path2) +{ + char fullpath[PATH_MAX]; + int ret; + + ret = lib_getfullpath(dirfd, path2, fullpath); + if (ret < 0) + { + set_errno(-ret); + return ERROR; + } + + return symlink(path1, fullpath); +} + +#endif /* CONFIG_PSEUDOFS_SOFTLINKS */ diff --git a/libs/libc/unistd/lib_unlinkat.c b/libs/libc/unistd/lib_unlinkat.c new file mode 100644 index 00000000000..4ceb3c8950f --- /dev/null +++ b/libs/libc/unistd/lib_unlinkat.c @@ -0,0 +1,85 @@ +/**************************************************************************** + * libs/libc/unistd/lib_unlinkat.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +#include "libc.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: unlinkat + * + * Description: + * The unlinkat() system call operates in exactly the same way as unlink(), + * except for the differences described here. + * + * If the pathname given in pathname is relative, then it is interpreted + * relative to the directory referred to by the file descriptor dirfd + * (rather than relative to the current working directory of the calling + * process) + * + * If pathname is relative and dirfd is the special value AT_FDCWD, then + * pathname is interpreted relative to the current working directory of + * the calling process (like unlink()). + * + * If pathname is absolute, then dirfd is ignored. + * + * If the AT_REMOVEDIR flag is specified, then performs the equivalent + * of rmdir on path. + * + * Input Parameters: + * dirfd - The file descriptor of directory. + * path - A pointer to the path. + * flags - A bit mask. + * + * Returned Value: + * Return zero on success, or -1 if an error occurred (in which case, + * errno is set appropriately). + * + ****************************************************************************/ + +int unlinkat(int dirfd, FAR const char *path, int flags) +{ + char fullpath[PATH_MAX]; + int ret; + + ret = lib_getfullpath(dirfd, path, fullpath); + if (ret < 0) + { + set_errno(-ret); + return ERROR; + } + + if ((flags & AT_REMOVEDIR) != 0) + { + return rmdir(fullpath); + } + + return unlink(fullpath); +} diff --git a/libs/libc/unistd/lib_utimes.c b/libs/libc/unistd/lib_utimes.c index 5cb03af414c..d115aec7c51 100644 --- a/libs/libc/unistd/lib_utimes.c +++ b/libs/libc/unistd/lib_utimes.c @@ -22,9 +22,12 @@ * Included Files ****************************************************************************/ +#include #include #include +#include "libc.h" + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -45,3 +48,18 @@ int utimes(FAR const char *path, const struct timeval tv[2]) return utimens(path, times); } + +int futimesat(int dirfd, FAR const char *path, const struct timeval tv[2]) +{ + char fullpath[PATH_MAX]; + int ret; + + ret = lib_getfullpath(dirfd, path, fullpath); + if (ret < 0) + { + set_errno(-ret); + return ERROR; + } + + return utimes(fullpath, tv); +}