2727 lines
59 KiB
C
Executable File
2727 lines
59 KiB
C
Executable File
/*
|
|
* Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
|
|
* Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without modification,
|
|
* are permitted provided that the following conditions are met:
|
|
*
|
|
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
|
* conditions and the following disclaimer.
|
|
*
|
|
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
|
* of conditions and the following disclaimer in the documentation and/or other materials
|
|
* provided with the distribution.
|
|
*
|
|
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
|
|
* to endorse or promote products derived from this software without specific prior written
|
|
* permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
|
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
|
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
|
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
|
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
#include "syscall_pub.h"
|
|
#ifdef LOSCFG_FS_VFS
|
|
#include "errno.h"
|
|
#include "unistd.h"
|
|
#include "fs/fd_table.h"
|
|
#include "fs/file.h"
|
|
#include "fs/fs.h"
|
|
#include "fs/fs_operation.h"
|
|
#include "sys/mount.h"
|
|
#include "los_task_pri.h"
|
|
#include "sys/utsname.h"
|
|
#include "sys/uio.h"
|
|
#include "poll.h"
|
|
#include "sys/prctl.h"
|
|
#include "epoll.h"
|
|
#ifdef LOSCFG_KERNEL_DYNLOAD
|
|
#include "los_exec_elf.h"
|
|
#endif
|
|
#include "los_syscall.h"
|
|
#include "dirent.h"
|
|
#include "user_copy.h"
|
|
#include "los_vm_map.h"
|
|
#include "los_memory.h"
|
|
#include "los_strncpy_from_user.h"
|
|
#include "capability_type.h"
|
|
#include "capability_api.h"
|
|
#include "sys/statfs.h"
|
|
|
|
#define HIGH_SHIFT_BIT 32
|
|
#define TIMESPEC_TIMES_NUM 2
|
|
|
|
static int CheckNewAttrTime(struct IATTR *attr, struct timespec times[TIMESPEC_TIMES_NUM])
|
|
{
|
|
int ret = ENOERR;
|
|
struct timespec stp = {0};
|
|
|
|
if (times) {
|
|
if (times[0].tv_nsec == UTIME_OMIT) {
|
|
attr->attr_chg_valid &= ~CHG_ATIME;
|
|
} else if (times[0].tv_nsec == UTIME_NOW) {
|
|
ret = clock_gettime(CLOCK_REALTIME, &stp);
|
|
if (ret < 0) {
|
|
return -get_errno();
|
|
}
|
|
attr->attr_chg_atime = (unsigned int)stp.tv_sec;
|
|
attr->attr_chg_valid |= CHG_ATIME;
|
|
} else {
|
|
attr->attr_chg_atime = (unsigned int)times[0].tv_sec;
|
|
attr->attr_chg_valid |= CHG_ATIME;
|
|
}
|
|
|
|
if (times[1].tv_nsec == UTIME_OMIT) {
|
|
attr->attr_chg_valid &= ~CHG_MTIME;
|
|
} else if (times[1].tv_nsec == UTIME_NOW) {
|
|
ret = clock_gettime(CLOCK_REALTIME, &stp);
|
|
if (ret < 0) {
|
|
return -get_errno();
|
|
}
|
|
attr->attr_chg_mtime = (unsigned int)stp.tv_sec;
|
|
attr->attr_chg_valid |= CHG_MTIME;
|
|
} else {
|
|
attr->attr_chg_mtime = (unsigned int)times[1].tv_sec;
|
|
attr->attr_chg_valid |= CHG_MTIME;
|
|
}
|
|
} else {
|
|
ret = clock_gettime(CLOCK_REALTIME, &stp);
|
|
if (ret < 0) {
|
|
return -get_errno();
|
|
}
|
|
attr->attr_chg_atime = (unsigned int)stp.tv_sec;
|
|
attr->attr_chg_mtime = (unsigned int)stp.tv_sec;
|
|
attr->attr_chg_valid |= CHG_ATIME;
|
|
attr->attr_chg_valid |= CHG_MTIME;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
static int GetFullpathNull(int fd, const char *path, char **filePath)
|
|
{
|
|
int ret;
|
|
char *fullPath = NULL;
|
|
struct file *file = NULL;
|
|
|
|
if ((fd != AT_FDCWD) && (path == NULL)) {
|
|
fd = GetAssociatedSystemFd(fd);
|
|
ret = fs_getfilep(fd, &file);
|
|
if (ret < 0) {
|
|
return -get_errno();
|
|
}
|
|
fullPath = file->f_path;
|
|
} else {
|
|
ret = GetFullpath(fd, path, &fullPath);
|
|
if (ret < 0) {
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
*filePath = fullPath;
|
|
return ret;
|
|
}
|
|
|
|
static int UserIovItemCheck(const struct iovec *iov, const int iovcnt)
|
|
{
|
|
int i;
|
|
for (i = 0; i < iovcnt; ++i) {
|
|
if (iov[i].iov_len == 0) {
|
|
continue;
|
|
}
|
|
|
|
if (!LOS_IsUserAddressRange((vaddr_t)(UINTPTR)iov[i].iov_base, iov[i].iov_len)) {
|
|
return i;
|
|
}
|
|
}
|
|
return iovcnt;
|
|
}
|
|
|
|
static int UserIovCopy(struct iovec **iovBuf, const struct iovec *iov, const int iovcnt, int *valid_iovcnt)
|
|
{
|
|
int ret;
|
|
int bufLen = iovcnt * sizeof(struct iovec);
|
|
if (bufLen < 0) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
*iovBuf = (struct iovec*)LOS_MemAlloc(OS_SYS_MEM_ADDR, bufLen);
|
|
if (*iovBuf == NULL) {
|
|
return -ENOMEM;
|
|
}
|
|
|
|
if (LOS_ArchCopyFromUser(*iovBuf, iov, bufLen) != 0) {
|
|
(void)LOS_MemFree(OS_SYS_MEM_ADDR, *iovBuf);
|
|
return -EFAULT;
|
|
}
|
|
|
|
ret = UserIovItemCheck(*iovBuf, iovcnt);
|
|
if (ret == 0) {
|
|
(void)LOS_MemFree(OS_SYS_MEM_ADDR, *iovBuf);
|
|
return -EFAULT;
|
|
}
|
|
|
|
*valid_iovcnt = ret;
|
|
return 0;
|
|
}
|
|
|
|
static int PollfdToSystem(struct pollfd *fds, nfds_t nfds, int **pollFdsBak)
|
|
{
|
|
if ((nfds != 0 && fds == NULL) || (pollFdsBak == NULL)) {
|
|
set_errno(EINVAL);
|
|
return -1;
|
|
}
|
|
if (nfds == 0) {
|
|
return 0;
|
|
}
|
|
int *pollFds = (int *)malloc(sizeof(int) * nfds);
|
|
if (pollFds == NULL) {
|
|
set_errno(ENOMEM);
|
|
return -1;
|
|
}
|
|
for (int i = 0; i < nfds; ++i) {
|
|
struct pollfd *p_fds = &fds[i];
|
|
pollFds[i] = p_fds->fd;
|
|
if (p_fds->fd < 0) {
|
|
set_errno(EBADF);
|
|
free(pollFds);
|
|
return -1;
|
|
}
|
|
p_fds->fd = GetAssociatedSystemFd(p_fds->fd);
|
|
}
|
|
*pollFdsBak = pollFds;
|
|
return 0;
|
|
}
|
|
|
|
static void RestorePollfd(struct pollfd *fds, nfds_t nfds, const int *pollFds)
|
|
{
|
|
if ((fds == NULL) || (pollFds == NULL)) {
|
|
return;
|
|
}
|
|
for (int i = 0; i < nfds; ++i) {
|
|
struct pollfd *p_fds = &fds[i];
|
|
p_fds->fd = pollFds[i];
|
|
}
|
|
}
|
|
|
|
static int UserPoll(struct pollfd *fds, nfds_t nfds, int timeout)
|
|
{
|
|
int *pollFds = NULL;
|
|
int ret = PollfdToSystem(fds, nfds, &pollFds);
|
|
if (ret < 0) {
|
|
return -1;
|
|
}
|
|
|
|
ret = poll(fds, nfds, timeout);
|
|
|
|
RestorePollfd(fds, nfds, pollFds);
|
|
|
|
free(pollFds);
|
|
return ret;
|
|
}
|
|
|
|
int SysClose(int fd)
|
|
{
|
|
int ret;
|
|
|
|
/* Process fd convert to system global fd */
|
|
int sysfd = DisassociateProcessFd(fd);
|
|
|
|
ret = close(sysfd);
|
|
if (ret < 0) {
|
|
AssociateSystemFd(fd, sysfd);
|
|
return -get_errno();
|
|
}
|
|
FreeProcessFd(fd);
|
|
return ret;
|
|
}
|
|
|
|
ssize_t SysRead(int fd, void *buf, size_t nbytes)
|
|
{
|
|
int ret;
|
|
|
|
if (nbytes == 0) {
|
|
return 0;
|
|
}
|
|
|
|
if (!LOS_IsUserAddressRange((vaddr_t)(UINTPTR)buf, nbytes)) {
|
|
return -EFAULT;
|
|
}
|
|
|
|
/* Process fd convert to system global fd */
|
|
fd = GetAssociatedSystemFd(fd);
|
|
|
|
ret = read(fd, buf, nbytes);
|
|
if (ret < 0) {
|
|
return -get_errno();
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
ssize_t SysWrite(int fd, const void *buf, size_t nbytes)
|
|
{
|
|
int ret;
|
|
|
|
if (nbytes == 0) {
|
|
return 0;
|
|
}
|
|
|
|
if (!LOS_IsUserAddressRange((vaddr_t)(UINTPTR)buf, nbytes)) {
|
|
return -EFAULT;
|
|
}
|
|
|
|
/* Process fd convert to system global fd */
|
|
int sysfd = GetAssociatedSystemFd(fd);
|
|
ret = write(sysfd, buf, nbytes);
|
|
if (ret < 0) {
|
|
return -get_errno();
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int SysOpen(const char *path, int oflags, ...)
|
|
{
|
|
int ret;
|
|
int procFd;
|
|
mode_t mode = DEFAULT_FILE_MODE; /* 0666: File read-write properties. */
|
|
char *pathRet = NULL;
|
|
|
|
if (path != NULL) {
|
|
ret = UserPathCopy(path, &pathRet);
|
|
if (ret != 0) {
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
procFd = AllocProcessFd();
|
|
if (procFd < 0) {
|
|
ret = -EMFILE;
|
|
goto ERROUT;
|
|
}
|
|
|
|
if (oflags & O_CLOEXEC) {
|
|
SetCloexecFlag(procFd);
|
|
}
|
|
|
|
if ((unsigned int)oflags & O_DIRECTORY) {
|
|
ret = do_opendir(pathRet, oflags);
|
|
} else {
|
|
#ifdef LOSCFG_FILE_MODE
|
|
va_list ap;
|
|
va_start(ap, oflags);
|
|
mode = va_arg(ap, int);
|
|
va_end(ap);
|
|
#endif
|
|
|
|
ret = do_open(AT_FDCWD, pathRet, oflags, mode);
|
|
}
|
|
|
|
if (ret < 0) {
|
|
ret = -get_errno();
|
|
goto ERROUT;
|
|
}
|
|
|
|
AssociateSystemFd(procFd, ret);
|
|
if (pathRet != NULL) {
|
|
LOS_MemFree(OS_SYS_MEM_ADDR, pathRet);
|
|
}
|
|
return procFd;
|
|
|
|
ERROUT:
|
|
if (pathRet != NULL) {
|
|
(void)LOS_MemFree(OS_SYS_MEM_ADDR, pathRet);
|
|
}
|
|
if (procFd >= 0) {
|
|
FreeProcessFd(procFd);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int SysCreat(const char *pathname, mode_t mode)
|
|
{
|
|
int ret = 0;
|
|
char *pathRet = NULL;
|
|
|
|
if (pathname != NULL) {
|
|
ret = UserPathCopy(pathname, &pathRet);
|
|
if (ret != 0) {
|
|
goto OUT;
|
|
}
|
|
}
|
|
|
|
int procFd = AllocProcessFd();
|
|
if (procFd < 0) {
|
|
ret = -EMFILE;
|
|
goto OUT;
|
|
}
|
|
|
|
ret = open((pathname ? pathRet : NULL), O_CREAT | O_TRUNC | O_WRONLY, mode);
|
|
if (ret < 0) {
|
|
FreeProcessFd(procFd);
|
|
ret = -get_errno();
|
|
} else {
|
|
AssociateSystemFd(procFd, ret);
|
|
ret = procFd;
|
|
}
|
|
|
|
OUT:
|
|
if (pathRet != NULL) {
|
|
(void)LOS_MemFree(OS_SYS_MEM_ADDR, pathRet);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int SysLink(const char *oldpath, const char *newpath)
|
|
{
|
|
int ret;
|
|
char *oldpathRet = NULL;
|
|
char *newpathRet = NULL;
|
|
|
|
if (oldpath != NULL) {
|
|
ret = UserPathCopy(oldpath, &oldpathRet);
|
|
if (ret != 0) {
|
|
goto OUT;
|
|
}
|
|
}
|
|
|
|
if (newpath != NULL) {
|
|
ret = UserPathCopy(newpath, &newpathRet);
|
|
if (ret != 0) {
|
|
goto OUT;
|
|
}
|
|
}
|
|
|
|
ret = link(oldpathRet, newpathRet);
|
|
if (ret < 0) {
|
|
ret = -get_errno();
|
|
}
|
|
|
|
OUT:
|
|
if (oldpathRet != NULL) {
|
|
(void)LOS_MemFree(OS_SYS_MEM_ADDR, oldpathRet);
|
|
}
|
|
if (newpathRet != NULL) {
|
|
(void)LOS_MemFree(OS_SYS_MEM_ADDR, newpathRet);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
ssize_t SysReadlink(const char *pathname, char *buf, size_t bufsize)
|
|
{
|
|
ssize_t ret;
|
|
char *pathRet = NULL;
|
|
|
|
if (bufsize == 0) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (pathname != NULL) {
|
|
ret = UserPathCopy(pathname, &pathRet);
|
|
if (ret != 0) {
|
|
goto OUT;
|
|
}
|
|
}
|
|
|
|
if (!LOS_IsUserAddressRange((vaddr_t)(UINTPTR)buf, bufsize)) {
|
|
ret = -EFAULT;
|
|
goto OUT;
|
|
}
|
|
|
|
ret = readlink(pathRet, buf, bufsize);
|
|
if (ret < 0) {
|
|
ret = -get_errno();
|
|
}
|
|
|
|
OUT:
|
|
if (pathRet != NULL) {
|
|
(void)LOS_MemFree(OS_SYS_MEM_ADDR, pathRet);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int SysSymlink(const char *target, const char *linkpath)
|
|
{
|
|
int ret;
|
|
char *targetRet = NULL;
|
|
char *pathRet = NULL;
|
|
|
|
if (target != NULL) {
|
|
ret = UserPathCopy(target, &targetRet);
|
|
if (ret != 0) {
|
|
goto OUT;
|
|
}
|
|
}
|
|
|
|
if (linkpath != NULL) {
|
|
ret = UserPathCopy(linkpath, &pathRet);
|
|
if (ret != 0) {
|
|
goto OUT;
|
|
}
|
|
}
|
|
|
|
ret = symlink(targetRet, pathRet);
|
|
if (ret < 0) {
|
|
ret = -get_errno();
|
|
}
|
|
|
|
OUT:
|
|
if (pathRet != NULL) {
|
|
(void)LOS_MemFree(OS_SYS_MEM_ADDR, pathRet);
|
|
}
|
|
|
|
if (targetRet != NULL) {
|
|
(void)LOS_MemFree(OS_SYS_MEM_ADDR, targetRet);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int SysUnlink(const char *pathname)
|
|
{
|
|
int ret;
|
|
char *pathRet = NULL;
|
|
|
|
if (pathname != NULL) {
|
|
ret = UserPathCopy(pathname, &pathRet);
|
|
if (ret != 0) {
|
|
goto OUT;
|
|
}
|
|
}
|
|
|
|
ret = do_unlink(AT_FDCWD, (pathname ? pathRet : NULL));
|
|
if (ret < 0) {
|
|
ret = -get_errno();
|
|
}
|
|
|
|
OUT:
|
|
if (pathRet != NULL) {
|
|
(void)LOS_MemFree(OS_SYS_MEM_ADDR, pathRet);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
#ifdef LOSCFG_KERNEL_DYNLOAD
|
|
int SysExecve(const char *fileName, char *const *argv, char *const *envp)
|
|
{
|
|
return LOS_DoExecveFile(fileName, argv, envp);
|
|
}
|
|
#endif
|
|
|
|
int SysFchdir(int fd)
|
|
{
|
|
int ret;
|
|
int sysFd;
|
|
struct file *file = NULL;
|
|
|
|
sysFd = GetAssociatedSystemFd(fd);
|
|
if (sysFd < 0) {
|
|
return -EBADF;
|
|
}
|
|
|
|
ret = fs_getfilep(sysFd, &file);
|
|
if (ret < 0) {
|
|
return -get_errno();
|
|
}
|
|
|
|
ret = chdir(file->f_path);
|
|
if (ret < 0) {
|
|
ret = -get_errno();
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int SysChdir(const char *path)
|
|
{
|
|
int ret;
|
|
char *pathRet = NULL;
|
|
|
|
if (path != NULL) {
|
|
ret = UserPathCopy(path, &pathRet);
|
|
if (ret != 0) {
|
|
goto OUT;
|
|
}
|
|
}
|
|
|
|
ret = chdir(path ? pathRet : NULL);
|
|
if (ret < 0) {
|
|
ret = -get_errno();
|
|
}
|
|
|
|
OUT:
|
|
if (pathRet != NULL) {
|
|
(void)LOS_MemFree(OS_SYS_MEM_ADDR, pathRet);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
off_t SysLseek(int fd, off_t offset, int whence)
|
|
{
|
|
/* Process fd convert to system global fd */
|
|
fd = GetAssociatedSystemFd(fd);
|
|
|
|
return _lseek(fd, offset, whence);
|
|
}
|
|
|
|
off64_t SysLseek64(int fd, int offsetHigh, int offsetLow, off64_t *result, int whence)
|
|
{
|
|
off64_t ret;
|
|
off64_t res;
|
|
int retVal;
|
|
|
|
/* Process fd convert to system global fd */
|
|
fd = GetAssociatedSystemFd(fd);
|
|
|
|
ret = _lseek64(fd, offsetHigh, offsetLow, &res, whence);
|
|
if (ret != 0) {
|
|
return ret;
|
|
}
|
|
|
|
retVal = LOS_ArchCopyToUser(result, &res, sizeof(off64_t));
|
|
if (retVal != 0) {
|
|
return -EFAULT;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
#ifdef LOSCFG_FS_NFS
|
|
static int NfsMountRef(const char *serverIpAndPath, const char *mountPath,
|
|
unsigned int uid, unsigned int gid) __attribute__((weakref("nfs_mount")));
|
|
|
|
static int NfsMount(const char *serverIpAndPath, const char *mountPath,
|
|
unsigned int uid, unsigned int gid)
|
|
{
|
|
int ret;
|
|
|
|
if ((serverIpAndPath == NULL) || (mountPath == NULL)) {
|
|
return -EINVAL;
|
|
}
|
|
ret = NfsMountRef(serverIpAndPath, mountPath, uid, gid);
|
|
if (ret < 0) {
|
|
ret = -get_errno();
|
|
}
|
|
return ret;
|
|
}
|
|
#endif
|
|
|
|
int SysMount(const char *source, const char *target, const char *filesystemtype, unsigned long mountflags,
|
|
const void *data)
|
|
{
|
|
int ret;
|
|
char *sourceRet = NULL;
|
|
char *targetRet = NULL;
|
|
char *dataRet = NULL;
|
|
char fstypeRet[FILESYSTEM_TYPE_MAX + 1] = {0};
|
|
|
|
if (!IsCapPermit(CAP_FS_MOUNT)) {
|
|
return -EPERM;
|
|
}
|
|
|
|
if (target != NULL) {
|
|
ret = UserPathCopy(target, &targetRet);
|
|
if (ret != 0) {
|
|
goto OUT;
|
|
}
|
|
}
|
|
|
|
if (filesystemtype != NULL) {
|
|
ret = LOS_StrncpyFromUser(fstypeRet, filesystemtype, FILESYSTEM_TYPE_MAX + 1);
|
|
if (ret < 0) {
|
|
goto OUT;
|
|
} else if (ret > FILESYSTEM_TYPE_MAX) {
|
|
ret = -ENODEV;
|
|
goto OUT;
|
|
}
|
|
|
|
if (strcmp(fstypeRet, "ramfs") && (source != NULL)) {
|
|
ret = UserPathCopy(source, &sourceRet);
|
|
if (ret != 0) {
|
|
goto OUT;
|
|
}
|
|
}
|
|
#ifdef LOSCFG_FS_NFS
|
|
if (strcmp(fstypeRet, "nfs") == 0) {
|
|
ret = NfsMount(sourceRet, targetRet, 0, 0);
|
|
goto OUT;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
if (data != NULL) {
|
|
ret = UserPathCopy(data, &dataRet);
|
|
if (ret != 0) {
|
|
goto OUT;
|
|
}
|
|
}
|
|
|
|
ret = mount(sourceRet, targetRet, (filesystemtype ? fstypeRet : NULL), mountflags, dataRet);
|
|
if (ret < 0) {
|
|
ret = -get_errno();
|
|
}
|
|
|
|
OUT:
|
|
if (sourceRet != NULL) {
|
|
(void)LOS_MemFree(OS_SYS_MEM_ADDR, sourceRet);
|
|
}
|
|
if (targetRet != NULL) {
|
|
(void)LOS_MemFree(OS_SYS_MEM_ADDR, targetRet);
|
|
}
|
|
if (dataRet != NULL) {
|
|
(void)LOS_MemFree(OS_SYS_MEM_ADDR, dataRet);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int SysUmount(const char *target)
|
|
{
|
|
int ret;
|
|
char *pathRet = NULL;
|
|
|
|
if (!IsCapPermit(CAP_FS_MOUNT)) {
|
|
return -EPERM;
|
|
}
|
|
|
|
if (target != NULL) {
|
|
ret = UserPathCopy(target, &pathRet);
|
|
if (ret != 0) {
|
|
goto OUT;
|
|
}
|
|
}
|
|
|
|
ret = umount(target ? pathRet : NULL);
|
|
if (ret < 0) {
|
|
ret = -get_errno();
|
|
}
|
|
|
|
OUT:
|
|
if (pathRet != NULL) {
|
|
(void)LOS_MemFree(OS_SYS_MEM_ADDR, pathRet);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int SysAccess(const char *path, int amode)
|
|
{
|
|
int ret;
|
|
char *pathRet = NULL;
|
|
|
|
if (path != NULL) {
|
|
ret = UserPathCopy(path, &pathRet);
|
|
if (ret != 0) {
|
|
goto OUT;
|
|
}
|
|
}
|
|
|
|
ret = access(pathRet, amode);
|
|
if (ret < 0) {
|
|
ret = -get_errno();
|
|
}
|
|
|
|
OUT:
|
|
if (pathRet != NULL) {
|
|
(void)LOS_MemFree(OS_SYS_MEM_ADDR, pathRet);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int SysRename(const char *oldpath, const char *newpath)
|
|
{
|
|
int ret;
|
|
char *pathOldRet = NULL;
|
|
char *pathNewRet = NULL;
|
|
|
|
if (oldpath != NULL) {
|
|
ret = UserPathCopy(oldpath, &pathOldRet);
|
|
if (ret != 0) {
|
|
goto OUT;
|
|
}
|
|
}
|
|
|
|
if (newpath != NULL) {
|
|
ret = UserPathCopy(newpath, &pathNewRet);
|
|
if (ret != 0) {
|
|
goto OUT;
|
|
}
|
|
}
|
|
|
|
ret = do_rename(AT_FDCWD, (oldpath ? pathOldRet : NULL), AT_FDCWD,
|
|
(newpath ? pathNewRet : NULL));
|
|
if (ret < 0) {
|
|
ret = -get_errno();
|
|
}
|
|
|
|
OUT:
|
|
if (pathOldRet != NULL) {
|
|
(void)LOS_MemFree(OS_SYS_MEM_ADDR, pathOldRet);
|
|
}
|
|
if (pathNewRet != NULL) {
|
|
(void)LOS_MemFree(OS_SYS_MEM_ADDR, pathNewRet);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int SysMkdir(const char *pathname, mode_t mode)
|
|
{
|
|
int ret;
|
|
char *pathRet = NULL;
|
|
|
|
if (pathname != NULL) {
|
|
ret = UserPathCopy(pathname, &pathRet);
|
|
if (ret != 0) {
|
|
goto OUT;
|
|
}
|
|
}
|
|
|
|
ret = do_mkdir(AT_FDCWD, (pathname ? pathRet : NULL), mode);
|
|
if (ret < 0) {
|
|
ret = -get_errno();
|
|
}
|
|
|
|
OUT:
|
|
if (pathRet != NULL) {
|
|
(void)LOS_MemFree(OS_SYS_MEM_ADDR, pathRet);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int SysRmdir(const char *pathname)
|
|
{
|
|
int ret;
|
|
char *pathRet = NULL;
|
|
|
|
if (pathname != NULL) {
|
|
ret = UserPathCopy(pathname, &pathRet);
|
|
if (ret != 0) {
|
|
goto OUT;
|
|
}
|
|
}
|
|
|
|
ret = do_rmdir(AT_FDCWD, (pathname ? pathRet : NULL));
|
|
if (ret < 0) {
|
|
ret = -get_errno();
|
|
}
|
|
|
|
OUT:
|
|
if (pathRet != NULL) {
|
|
(void)LOS_MemFree(OS_SYS_MEM_ADDR, pathRet);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int SysDup(int fd)
|
|
{
|
|
int sysfd = GetAssociatedSystemFd(fd);
|
|
/* Check if the param is valid, note that: socket fd is not support dup2 */
|
|
if ((sysfd < 0) || (sysfd >= CONFIG_NFILE_DESCRIPTORS)) {
|
|
return -EBADF;
|
|
}
|
|
|
|
int dupfd = AllocProcessFd();
|
|
if (dupfd < 0) {
|
|
return -EMFILE;
|
|
}
|
|
|
|
files_refer(sysfd);
|
|
AssociateSystemFd(dupfd, sysfd);
|
|
return dupfd;
|
|
}
|
|
|
|
void SysSync(void)
|
|
{
|
|
sync();
|
|
}
|
|
|
|
int SysUmount2(const char *target, int flags)
|
|
{
|
|
if (flags != 0) {
|
|
return -EINVAL;
|
|
}
|
|
return SysUmount(target);
|
|
}
|
|
|
|
int SysIoctl(int fd, int req, void *arg)
|
|
{
|
|
int ret;
|
|
unsigned int size = _IOC_SIZE((unsigned int)req);
|
|
unsigned int dir = _IOC_DIR((unsigned int)req);
|
|
if ((size == 0) && (dir != _IOC_NONE)) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
if ((dir != _IOC_NONE) && (((void *)(uintptr_t)arg) == NULL)) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
if ((dir & _IOC_READ) || (dir & _IOC_WRITE)) {
|
|
if (!LOS_IsUserAddressRange((uintptr_t)arg, size)) {
|
|
return -EFAULT;
|
|
}
|
|
}
|
|
|
|
/* Process fd convert to system global fd */
|
|
fd = GetAssociatedSystemFd(fd);
|
|
|
|
ret = ioctl(fd, req, arg);
|
|
if (ret < 0) {
|
|
return -get_errno();
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int SysFcntl(int fd, int cmd, void *arg)
|
|
{
|
|
/* Process fd convert to system global fd */
|
|
int sysfd = GetAssociatedSystemFd(fd);
|
|
|
|
int ret = VfsFcntl(fd, cmd, arg);
|
|
if (ret == CONTINE_NUTTX_FCNTL) {
|
|
ret = fcntl(sysfd, cmd, arg);
|
|
}
|
|
|
|
if (ret < 0) {
|
|
return -get_errno();
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
#ifdef LOSCFG_KERNEL_PIPE
|
|
int SysPipe(int pipefd[2]) /* 2 : pipe fds for read and write */
|
|
{
|
|
int ret;
|
|
int pipeFdIntr[2] = {0}; /* 2 : pipe fds for read and write */
|
|
|
|
int procFd0 = AllocProcessFd();
|
|
if (procFd0 < 0) {
|
|
return -EMFILE;
|
|
}
|
|
int procFd1 = AllocProcessFd();
|
|
if (procFd1 < 0) {
|
|
FreeProcessFd(procFd0);
|
|
return -EMFILE;
|
|
}
|
|
|
|
ret = pipe(pipeFdIntr);
|
|
if (ret < 0) {
|
|
FreeProcessFd(procFd0);
|
|
FreeProcessFd(procFd1);
|
|
return -get_errno();
|
|
}
|
|
int sysPipeFd0 = pipeFdIntr[0];
|
|
int sysPipeFd1 = pipeFdIntr[1];
|
|
|
|
AssociateSystemFd(procFd0, sysPipeFd0);
|
|
AssociateSystemFd(procFd1, sysPipeFd1);
|
|
|
|
pipeFdIntr[0] = procFd0;
|
|
pipeFdIntr[1] = procFd1;
|
|
|
|
ret = LOS_ArchCopyToUser(pipefd, pipeFdIntr, sizeof(pipeFdIntr));
|
|
if (ret != 0) {
|
|
FreeProcessFd(procFd0);
|
|
FreeProcessFd(procFd1);
|
|
close(sysPipeFd0);
|
|
close(sysPipeFd1);
|
|
return -EFAULT;
|
|
}
|
|
return ret;
|
|
}
|
|
#endif
|
|
|
|
int SysDup2(int fd1, int fd2)
|
|
{
|
|
int ret;
|
|
int sysfd1 = GetAssociatedSystemFd(fd1);
|
|
int sysfd2 = GetAssociatedSystemFd(fd2);
|
|
|
|
/* Check if the param is valid, note that: socket fd is not support dup2 */
|
|
if ((sysfd1 < 0) || (sysfd1 >= CONFIG_NFILE_DESCRIPTORS) || (CheckProcessFd(fd2) != OK)) {
|
|
return -EBADF;
|
|
}
|
|
|
|
/* Handle special circumstances */
|
|
if (fd1 == fd2) {
|
|
return fd2;
|
|
}
|
|
|
|
ret = AllocSpecifiedProcessFd(fd2);
|
|
if (ret != OK) {
|
|
return ret;
|
|
}
|
|
|
|
/* close the sysfd2 in need */
|
|
if (sysfd2 >= 0) {
|
|
ret = close(sysfd2);
|
|
if (ret < 0) {
|
|
AssociateSystemFd(fd2, sysfd2);
|
|
return -get_errno();
|
|
}
|
|
}
|
|
|
|
files_refer(sysfd1);
|
|
AssociateSystemFd(fd2, sysfd1);
|
|
|
|
/* if fd1 is not equal to fd2, the FD_CLOEXEC flag associated with fd2 shall be cleared */
|
|
ClearCloexecFlag(fd2);
|
|
return fd2;
|
|
}
|
|
|
|
static int SelectParamCheckCopy(fd_set *readfds, fd_set *writefds, fd_set *exceptfds, fd_set **fdsBuf)
|
|
{
|
|
fd_set *readfdsRet = NULL;
|
|
fd_set *writefdsRet = NULL;
|
|
fd_set *exceptfdsRet = NULL;
|
|
|
|
*fdsBuf = (fd_set *)LOS_MemAlloc(OS_SYS_MEM_ADDR, sizeof(fd_set) * 3); /* 3: three param need check and copy */
|
|
if (*fdsBuf == NULL) {
|
|
return -ENOMEM;
|
|
}
|
|
|
|
readfdsRet = *fdsBuf; /* LOS_MemAlloc 3 sizeof(fd_set) space,first use for readfds */
|
|
writefdsRet = *fdsBuf + 1; /* 1: LOS_MemAlloc 3 sizeof(fd_set) space,second use for writefds */
|
|
exceptfdsRet = *fdsBuf + 2; /* 2: LOS_MemAlloc 3 sizeof(fd_set) space,thired use for exceptfds */
|
|
|
|
if (readfds != NULL) {
|
|
if (LOS_ArchCopyFromUser(readfdsRet, readfds, sizeof(fd_set)) != 0) {
|
|
(void)LOS_MemFree(OS_SYS_MEM_ADDR, *fdsBuf);
|
|
return -EFAULT;
|
|
}
|
|
}
|
|
|
|
if (writefds != NULL) {
|
|
if (LOS_ArchCopyFromUser(writefdsRet, writefds, sizeof(fd_set)) != 0) {
|
|
(void)LOS_MemFree(OS_SYS_MEM_ADDR, *fdsBuf);
|
|
return -EFAULT;
|
|
}
|
|
}
|
|
|
|
if (exceptfds != NULL) {
|
|
if (LOS_ArchCopyFromUser(exceptfdsRet, exceptfds, sizeof(fd_set)) != 0) {
|
|
(void)LOS_MemFree(OS_SYS_MEM_ADDR, *fdsBuf);
|
|
return -EFAULT;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int SysSelect(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout)
|
|
{
|
|
int ret;
|
|
fd_set *fdsRet = NULL;
|
|
fd_set *readfdsRet = NULL;
|
|
fd_set *writefdsRet = NULL;
|
|
fd_set *exceptfdsRet = NULL;
|
|
struct timeval timeoutRet = {0};
|
|
|
|
ret = SelectParamCheckCopy(readfds, writefds, exceptfds, &fdsRet);
|
|
if (ret != 0) {
|
|
return ret;
|
|
}
|
|
|
|
readfdsRet = fdsRet; /* LOS_MemAlloc 3 sizeof(fd_set) space,first use for readfds */
|
|
writefdsRet = fdsRet + 1; /* 1: LOS_MemAlloc 3 sizeof(fd_set) space,second use for writefds */
|
|
exceptfdsRet = fdsRet + 2; /* 2: LOS_MemAlloc 3 sizeof(fd_set) space,thired use for exceptfds */
|
|
|
|
if (timeout != NULL) {
|
|
if (LOS_ArchCopyFromUser(&timeoutRet, timeout, sizeof(struct timeval)) != 0) {
|
|
goto ERROUT;
|
|
}
|
|
}
|
|
|
|
ret = do_select(nfds, (readfds ? readfdsRet : NULL), (writefds ? writefdsRet : NULL),
|
|
(exceptfds ? exceptfdsRet : NULL), (timeout ? (&timeoutRet) : NULL), UserPoll);
|
|
if (ret < 0) {
|
|
(void)LOS_MemFree(OS_SYS_MEM_ADDR, fdsRet);
|
|
return -get_errno();
|
|
}
|
|
|
|
if (readfds != NULL) {
|
|
if (LOS_ArchCopyToUser(readfds, readfdsRet, sizeof(fd_set)) != 0) {
|
|
goto ERROUT;
|
|
}
|
|
}
|
|
|
|
if (writefds != NULL) {
|
|
if (LOS_ArchCopyToUser(writefds, writefdsRet, sizeof(fd_set)) != 0) {
|
|
goto ERROUT;
|
|
}
|
|
}
|
|
|
|
if (exceptfds != 0) {
|
|
if (LOS_ArchCopyToUser(exceptfds, exceptfdsRet, sizeof(fd_set)) != 0) {
|
|
goto ERROUT;
|
|
}
|
|
}
|
|
|
|
(void)LOS_MemFree(OS_SYS_MEM_ADDR, fdsRet);
|
|
return ret;
|
|
|
|
ERROUT:
|
|
(void)LOS_MemFree(OS_SYS_MEM_ADDR, fdsRet);
|
|
return -EFAULT;
|
|
}
|
|
|
|
int SysTruncate(const char *path, off_t length)
|
|
{
|
|
int ret;
|
|
int fd = -1;
|
|
char *pathRet = NULL;
|
|
|
|
if (path != NULL) {
|
|
ret = UserPathCopy(path, &pathRet);
|
|
if (ret != 0) {
|
|
goto OUT;
|
|
}
|
|
}
|
|
|
|
fd = open((path ? pathRet : NULL), O_RDWR);
|
|
if (fd < 0) {
|
|
/* The errno value has already been set */
|
|
ret = -get_errno();
|
|
goto OUT;
|
|
}
|
|
|
|
ret = ftruncate(fd, length);
|
|
close(fd);
|
|
if (ret < 0) {
|
|
ret = -get_errno();
|
|
}
|
|
|
|
OUT:
|
|
if (pathRet != NULL) {
|
|
(void)LOS_MemFree(OS_SYS_MEM_ADDR, pathRet);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int SysTruncate64(const char *path, off64_t length)
|
|
{
|
|
int ret;
|
|
int fd = -1;
|
|
char *pathRet = NULL;
|
|
|
|
if (path != NULL) {
|
|
ret = UserPathCopy(path, &pathRet);
|
|
if (ret != 0) {
|
|
goto OUT;
|
|
}
|
|
}
|
|
|
|
fd = open((path ? pathRet : NULL), O_RDWR);
|
|
if (fd < 0) {
|
|
/* The errno value has already been set */
|
|
ret = -get_errno();
|
|
goto OUT;
|
|
}
|
|
|
|
ret = ftruncate64(fd, length);
|
|
close(fd);
|
|
if (ret < 0) {
|
|
ret = -get_errno();
|
|
}
|
|
|
|
OUT:
|
|
if (pathRet != NULL) {
|
|
(void)LOS_MemFree(OS_SYS_MEM_ADDR, pathRet);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int SysFtruncate(int fd, off_t length)
|
|
{
|
|
int ret;
|
|
|
|
/* Process fd convert to system global fd */
|
|
fd = GetAssociatedSystemFd(fd);
|
|
|
|
ret = ftruncate(fd, length);
|
|
if (ret < 0) {
|
|
return -get_errno();
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int SysStatfs(const char *path, struct statfs *buf)
|
|
{
|
|
int ret;
|
|
char *pathRet = NULL;
|
|
struct statfs bufRet = {0};
|
|
|
|
if (path != NULL) {
|
|
ret = UserPathCopy(path, &pathRet);
|
|
if (ret != 0) {
|
|
goto OUT;
|
|
}
|
|
}
|
|
|
|
ret = statfs((path ? pathRet : NULL), (buf ? (&bufRet) : NULL));
|
|
if (ret < 0) {
|
|
ret = -get_errno();
|
|
goto OUT;
|
|
}
|
|
|
|
ret = LOS_ArchCopyToUser(buf, &bufRet, sizeof(struct statfs));
|
|
if (ret != 0) {
|
|
ret = -EFAULT;
|
|
}
|
|
|
|
OUT:
|
|
if (pathRet != NULL) {
|
|
(void)LOS_MemFree(OS_SYS_MEM_ADDR, pathRet);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int SysStatfs64(const char *path, size_t sz, struct statfs *buf)
|
|
{
|
|
int ret;
|
|
char *pathRet = NULL;
|
|
struct statfs bufRet = {0};
|
|
|
|
if (path != NULL) {
|
|
ret = UserPathCopy(path, &pathRet);
|
|
if (ret != 0) {
|
|
goto OUT;
|
|
}
|
|
}
|
|
|
|
if (sz != sizeof(*buf)) {
|
|
ret = -EINVAL;
|
|
goto OUT;
|
|
}
|
|
|
|
ret = statfs((path ? pathRet : NULL), (buf ? (&bufRet) : NULL));
|
|
if (ret < 0) {
|
|
ret = -get_errno();
|
|
goto OUT;
|
|
}
|
|
|
|
ret = LOS_ArchCopyToUser(buf, &bufRet, sizeof(struct statfs));
|
|
if (ret != 0) {
|
|
ret = -EFAULT;
|
|
}
|
|
|
|
OUT:
|
|
if (pathRet != NULL) {
|
|
(void)LOS_MemFree(OS_SYS_MEM_ADDR, pathRet);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int SysStat(const char *path, struct kstat *buf)
|
|
{
|
|
int ret;
|
|
char *pathRet = NULL;
|
|
struct stat bufRet = {0};
|
|
|
|
if (path != NULL) {
|
|
ret = UserPathCopy(path, &pathRet);
|
|
if (ret != 0) {
|
|
goto OUT;
|
|
}
|
|
}
|
|
|
|
ret = stat((path ? pathRet : NULL), (buf ? (&bufRet) : NULL));
|
|
if (ret < 0) {
|
|
ret = -get_errno();
|
|
goto OUT;
|
|
}
|
|
|
|
ret = LOS_ArchCopyToUser(buf, &bufRet, sizeof(struct kstat));
|
|
if (ret != 0) {
|
|
ret = -EFAULT;
|
|
}
|
|
|
|
OUT:
|
|
if (pathRet != NULL) {
|
|
(void)LOS_MemFree(OS_SYS_MEM_ADDR, pathRet);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int SysLstat(const char *path, struct kstat *buffer)
|
|
{
|
|
int ret;
|
|
char *pathRet = NULL;
|
|
struct stat bufRet = {0};
|
|
|
|
if (path != NULL) {
|
|
ret = UserPathCopy(path, &pathRet);
|
|
if (ret != 0) {
|
|
goto OUT;
|
|
}
|
|
}
|
|
|
|
ret = stat((path ? pathRet : NULL), (buffer ? (&bufRet) : NULL));
|
|
if (ret < 0) {
|
|
ret = -get_errno();
|
|
goto OUT;
|
|
}
|
|
|
|
ret = LOS_ArchCopyToUser(buffer, &bufRet, sizeof(struct kstat));
|
|
if (ret != 0) {
|
|
ret = -EFAULT;
|
|
}
|
|
|
|
OUT:
|
|
if (pathRet != NULL) {
|
|
(void)LOS_MemFree(OS_SYS_MEM_ADDR, pathRet);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int SysFstat(int fd, struct kstat *buf)
|
|
{
|
|
int ret;
|
|
struct stat bufRet = {0};
|
|
struct file *filep = NULL;
|
|
|
|
/* Process fd convert to system global fd */
|
|
fd = GetAssociatedSystemFd(fd);
|
|
|
|
ret = fs_getfilep(fd, &filep);
|
|
if (ret < 0) {
|
|
return -get_errno();
|
|
}
|
|
|
|
if (filep->f_oflags & O_DIRECTORY) {
|
|
return -EBADF;
|
|
}
|
|
|
|
ret = stat(filep->f_path, (buf ? (&bufRet) : NULL));
|
|
if (ret < 0) {
|
|
return -get_errno();
|
|
}
|
|
|
|
ret = LOS_ArchCopyToUser(buf, &bufRet, sizeof(struct kstat));
|
|
if (ret != 0) {
|
|
return -EFAULT;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int SysStatx(int fd, const char *restrict path, int flag, unsigned mask, struct statx *restrict stx)
|
|
{
|
|
return -ENOSYS;
|
|
}
|
|
|
|
int SysFsync(int fd)
|
|
{
|
|
int ret;
|
|
struct file *filep = NULL;
|
|
|
|
/* Process fd convert to system global fd */
|
|
fd = GetAssociatedSystemFd(fd);
|
|
|
|
/* Get the file structure corresponding to the file descriptor. */
|
|
ret = fs_getfilep(fd, &filep);
|
|
if (ret < 0) {
|
|
/* The errno value has already been set */
|
|
return -get_errno();
|
|
}
|
|
|
|
if (filep->f_oflags & O_DIRECTORY) {
|
|
return -EBADF;
|
|
}
|
|
|
|
/* Perform the fsync operation */
|
|
ret = file_fsync(filep);
|
|
if (ret < 0) {
|
|
return -get_errno();
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
ssize_t SysReadv(int fd, const struct iovec *iov, int iovcnt)
|
|
{
|
|
int ret;
|
|
int valid_iovcnt = -1;
|
|
struct iovec *iovRet = NULL;
|
|
|
|
/* Process fd convert to system global fd */
|
|
fd = GetAssociatedSystemFd(fd);
|
|
if ((iov == NULL) || (iovcnt < 0) || (iovcnt > IOV_MAX)) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (iovcnt == 0) {
|
|
return 0;
|
|
}
|
|
|
|
ret = UserIovCopy(&iovRet, iov, iovcnt, &valid_iovcnt);
|
|
if (ret != 0) {
|
|
return ret;
|
|
}
|
|
|
|
if (valid_iovcnt <= 0) {
|
|
ret = -EFAULT;
|
|
goto OUT;
|
|
}
|
|
|
|
ret = vfs_readv(fd, iovRet, valid_iovcnt, NULL);
|
|
if (ret < 0) {
|
|
ret = -get_errno();
|
|
}
|
|
|
|
OUT:
|
|
(void)LOS_MemFree(OS_SYS_MEM_ADDR, iovRet);
|
|
return ret;
|
|
}
|
|
|
|
ssize_t SysWritev(int fd, const struct iovec *iov, int iovcnt)
|
|
{
|
|
int ret;
|
|
int valid_iovcnt = -1;
|
|
struct iovec *iovRet = NULL;
|
|
|
|
/* Process fd convert to system global fd */
|
|
int sysfd = GetAssociatedSystemFd(fd);
|
|
if ((iovcnt < 0) || (iovcnt > IOV_MAX)) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (iovcnt == 0) {
|
|
return 0;
|
|
}
|
|
|
|
if (iov == NULL) {
|
|
return -EFAULT;
|
|
}
|
|
|
|
ret = UserIovCopy(&iovRet, iov, iovcnt, &valid_iovcnt);
|
|
if (ret != 0) {
|
|
return ret;
|
|
}
|
|
|
|
if (valid_iovcnt != iovcnt) {
|
|
ret = -EFAULT;
|
|
goto OUT_FREE;
|
|
}
|
|
|
|
ret = writev(sysfd, iovRet, valid_iovcnt);
|
|
if (ret < 0) {
|
|
ret = -get_errno();
|
|
}
|
|
|
|
OUT_FREE:
|
|
(void)LOS_MemFree(OS_SYS_MEM_ADDR, iovRet);
|
|
return ret;
|
|
}
|
|
|
|
int SysPoll(struct pollfd *fds, nfds_t nfds, int timeout)
|
|
{
|
|
int ret;
|
|
struct pollfd *kfds = NULL;
|
|
|
|
if ((nfds >= MAX_POLL_NFDS) || (nfds == 0) || (fds == NULL)) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
kfds = (struct pollfd *)malloc(sizeof(struct pollfd) * nfds);
|
|
if (kfds != NULL) {
|
|
if (LOS_ArchCopyFromUser(kfds, fds, sizeof(struct pollfd) * nfds) != 0) {
|
|
ret = -EFAULT;
|
|
goto OUT_KFD;
|
|
}
|
|
}
|
|
|
|
int *pollFds = NULL;
|
|
ret = PollfdToSystem(kfds, nfds, &pollFds);
|
|
if (ret < 0) {
|
|
ret = -get_errno();
|
|
goto OUT_KFD;
|
|
}
|
|
|
|
ret = poll(kfds, nfds, timeout);
|
|
if (ret < 0) {
|
|
ret = -get_errno();
|
|
goto OUT;
|
|
}
|
|
|
|
if (kfds != NULL) {
|
|
RestorePollfd(kfds, nfds, pollFds);
|
|
if (LOS_ArchCopyToUser(fds, kfds, sizeof(struct pollfd) * nfds) != 0) {
|
|
ret = -EFAULT;
|
|
goto OUT;
|
|
}
|
|
}
|
|
|
|
OUT:
|
|
free(pollFds);
|
|
OUT_KFD:
|
|
free(kfds);
|
|
return ret;
|
|
}
|
|
|
|
int SysPrctl(int option, ...)
|
|
{
|
|
unsigned long name;
|
|
va_list ap;
|
|
errno_t err;
|
|
|
|
va_start(ap, option);
|
|
if (option != PR_SET_NAME) {
|
|
PRINT_ERR("%s: %d, no support option : 0x%x\n", __FUNCTION__, __LINE__, option);
|
|
err = EOPNOTSUPP;
|
|
goto ERROR;
|
|
}
|
|
|
|
name = va_arg(ap, unsigned long);
|
|
if (!LOS_IsUserAddress(name)) {
|
|
err = EFAULT;
|
|
goto ERROR;
|
|
}
|
|
|
|
err = OsSetTaskName(OsCurrTaskGet(), (const char *)(uintptr_t)name, TRUE);
|
|
if (err != LOS_OK) {
|
|
goto ERROR;
|
|
}
|
|
|
|
va_end(ap);
|
|
return ENOERR;
|
|
|
|
ERROR:
|
|
va_end(ap);
|
|
return -err;
|
|
}
|
|
|
|
ssize_t SysPread64(int fd, void *buf, size_t nbytes, off64_t offset)
|
|
{
|
|
int ret, retVal;
|
|
char *bufRet = NULL;
|
|
|
|
/* Process fd convert to system global fd */
|
|
fd = GetAssociatedSystemFd(fd);
|
|
|
|
if (nbytes == 0) {
|
|
ret = pread64(fd, buf, nbytes, offset);
|
|
if (ret < 0) {
|
|
return -get_errno();
|
|
} else {
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
bufRet = (char *)LOS_MemAlloc(OS_SYS_MEM_ADDR, nbytes);
|
|
if (bufRet == NULL) {
|
|
return -ENOMEM;
|
|
}
|
|
|
|
ret = pread64(fd, (buf ? bufRet : NULL), nbytes, offset);
|
|
if (ret < 0) {
|
|
(void)LOS_MemFree(OS_SYS_MEM_ADDR, bufRet);
|
|
return -get_errno();
|
|
}
|
|
|
|
retVal = LOS_ArchCopyToUser(buf, bufRet, ret);
|
|
if (retVal != 0) {
|
|
(void)LOS_MemFree(OS_SYS_MEM_ADDR, bufRet);
|
|
return -EFAULT;
|
|
}
|
|
|
|
(void)LOS_MemFree(OS_SYS_MEM_ADDR, bufRet);
|
|
return ret;
|
|
}
|
|
|
|
ssize_t SysPwrite64(int fd, const void *buf, size_t nbytes, off64_t offset)
|
|
{
|
|
int ret;
|
|
char *bufRet = NULL;
|
|
|
|
/* Process fd convert to system global fd */
|
|
fd = GetAssociatedSystemFd(fd);
|
|
|
|
if (nbytes == 0) {
|
|
ret = pwrite64(fd, buf, nbytes, offset);
|
|
if (ret < 0) {
|
|
return -get_errno();
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
bufRet = (char *)LOS_MemAlloc(OS_SYS_MEM_ADDR, nbytes);
|
|
if (bufRet == NULL) {
|
|
return -ENOMEM;
|
|
}
|
|
|
|
if (buf != NULL) {
|
|
ret = LOS_ArchCopyFromUser(bufRet, buf, nbytes);
|
|
if (ret != 0) {
|
|
(void)LOS_MemFree(OS_SYS_MEM_ADDR, bufRet);
|
|
return -EFAULT;
|
|
}
|
|
}
|
|
|
|
ret = pwrite64(fd, (buf ? bufRet : NULL), nbytes, offset);
|
|
if (ret < 0) {
|
|
(void)LOS_MemFree(OS_SYS_MEM_ADDR, bufRet);
|
|
return -get_errno();
|
|
}
|
|
|
|
(void)LOS_MemFree(OS_SYS_MEM_ADDR, bufRet);
|
|
return ret;
|
|
}
|
|
|
|
char *SysGetcwd(char *buf, size_t n)
|
|
{
|
|
char *ret = NULL;
|
|
char *bufRet = NULL;
|
|
size_t bufLen = n;
|
|
int retVal;
|
|
|
|
if (bufLen > PATH_MAX) {
|
|
bufLen = PATH_MAX;
|
|
}
|
|
|
|
bufRet = (char *)LOS_MemAlloc(OS_SYS_MEM_ADDR, bufLen);
|
|
if (bufRet == NULL) {
|
|
return (char *)(intptr_t)-ENOMEM;
|
|
}
|
|
(void)memset_s(bufRet, bufLen, 0, bufLen);
|
|
|
|
ret = getcwd((buf ? bufRet : NULL), bufLen);
|
|
if (ret == NULL) {
|
|
(void)LOS_MemFree(OS_SYS_MEM_ADDR, bufRet);
|
|
return (char *)(intptr_t)-get_errno();
|
|
}
|
|
|
|
retVal = LOS_ArchCopyToUser(buf, bufRet, bufLen);
|
|
if (retVal != 0) {
|
|
(void)LOS_MemFree(OS_SYS_MEM_ADDR, bufRet);
|
|
return (char *)(intptr_t)-EFAULT;
|
|
}
|
|
ret = buf;
|
|
|
|
(void)LOS_MemFree(OS_SYS_MEM_ADDR, bufRet);
|
|
return ret;
|
|
}
|
|
|
|
ssize_t SysSendFile(int outfd, int infd, off_t *offset, size_t count)
|
|
{
|
|
int ret, retVal;
|
|
off_t offsetRet;
|
|
|
|
retVal = LOS_ArchCopyFromUser(&offsetRet, offset, sizeof(off_t));
|
|
if (retVal != 0) {
|
|
return -EFAULT;
|
|
}
|
|
|
|
/* Process fd convert to system global fd */
|
|
outfd = GetAssociatedSystemFd(outfd);
|
|
infd = GetAssociatedSystemFd(infd);
|
|
|
|
ret = sendfile(outfd, infd, (offset ? (&offsetRet) : NULL), count);
|
|
if (ret < 0) {
|
|
return -get_errno();
|
|
}
|
|
|
|
retVal = LOS_ArchCopyToUser(offset, &offsetRet, sizeof(off_t));
|
|
if (retVal != 0) {
|
|
return -EFAULT;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int SysFtruncate64(int fd, off64_t length)
|
|
{
|
|
int ret;
|
|
|
|
/* Process fd convert to system global fd */
|
|
fd = GetAssociatedSystemFd(fd);
|
|
|
|
ret = ftruncate64(fd, length);
|
|
if (ret < 0) {
|
|
return -get_errno();
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int SysOpenat(int dirfd, const char *path, int oflags, ...)
|
|
{
|
|
int ret;
|
|
int procFd;
|
|
char *pathRet = NULL;
|
|
mode_t mode;
|
|
#ifdef LOSCFG_FILE_MODE
|
|
va_list ap;
|
|
|
|
va_start(ap, oflags);
|
|
mode = va_arg(ap, int);
|
|
va_end(ap);
|
|
#else
|
|
mode = 0666; /* 0666: File read-write properties. */
|
|
#endif
|
|
|
|
if (path != NULL) {
|
|
ret = UserPathCopy(path, &pathRet);
|
|
if (ret != 0) {
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
procFd = AllocProcessFd();
|
|
if (procFd < 0) {
|
|
ret = -EMFILE;
|
|
goto ERROUT;
|
|
}
|
|
|
|
if (oflags & O_CLOEXEC) {
|
|
SetCloexecFlag(procFd);
|
|
}
|
|
|
|
if (dirfd != AT_FDCWD) {
|
|
/* Process fd convert to system global fd */
|
|
dirfd = GetAssociatedSystemFd(dirfd);
|
|
}
|
|
|
|
ret = do_open(dirfd, (path ? pathRet : NULL), oflags, mode);
|
|
if (ret < 0) {
|
|
ret = -get_errno();
|
|
goto ERROUT;
|
|
}
|
|
|
|
AssociateSystemFd(procFd, ret);
|
|
if (pathRet != NULL) {
|
|
(void)LOS_MemFree(OS_SYS_MEM_ADDR, pathRet);
|
|
}
|
|
return procFd;
|
|
|
|
ERROUT:
|
|
if (pathRet != NULL) {
|
|
(void)LOS_MemFree(OS_SYS_MEM_ADDR, pathRet);
|
|
}
|
|
if (procFd >= 0) {
|
|
FreeProcessFd(procFd);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int SysMkdirat(int dirfd, const char *pathname, mode_t mode)
|
|
{
|
|
int ret;
|
|
char *pathRet = NULL;
|
|
|
|
if (pathname != NULL) {
|
|
ret = UserPathCopy(pathname, &pathRet);
|
|
if (ret != 0) {
|
|
goto OUT;
|
|
}
|
|
}
|
|
|
|
if (dirfd != AT_FDCWD) {
|
|
/* Process fd convert to system global fd */
|
|
dirfd = GetAssociatedSystemFd(dirfd);
|
|
}
|
|
|
|
ret = do_mkdir(dirfd, (pathname ? pathRet : NULL), mode);
|
|
if (ret < 0) {
|
|
ret = -get_errno();
|
|
}
|
|
|
|
OUT:
|
|
if (pathRet != NULL) {
|
|
(void)LOS_MemFree(OS_SYS_MEM_ADDR, pathRet);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int SysLinkat(int olddirfd, const char *oldpath, int newdirfd, const char *newpath, int flags)
|
|
{
|
|
int ret;
|
|
char *oldpathRet = NULL;
|
|
char *newpathRet = NULL;
|
|
|
|
if (oldpath != NULL) {
|
|
ret = UserPathCopy(oldpath, &oldpathRet);
|
|
if (ret != 0) {
|
|
goto OUT;
|
|
}
|
|
}
|
|
|
|
if (newpath != NULL) {
|
|
ret = UserPathCopy(newpath, &newpathRet);
|
|
if (ret != 0) {
|
|
goto OUT;
|
|
}
|
|
}
|
|
|
|
if (olddirfd != AT_FDCWD) {
|
|
/* Process fd convert to system global fd */
|
|
olddirfd = GetAssociatedSystemFd(olddirfd);
|
|
}
|
|
|
|
if (newdirfd != AT_FDCWD) {
|
|
/* Process fd convert to system global fd */
|
|
newdirfd = GetAssociatedSystemFd(newdirfd);
|
|
}
|
|
|
|
ret = linkat(olddirfd, oldpathRet, newdirfd, newpathRet, flags);
|
|
if (ret < 0) {
|
|
ret = -get_errno();
|
|
}
|
|
|
|
OUT:
|
|
if (oldpathRet != NULL) {
|
|
(void)LOS_MemFree(OS_SYS_MEM_ADDR, oldpathRet);
|
|
}
|
|
if (newpathRet != NULL) {
|
|
(void)LOS_MemFree(OS_SYS_MEM_ADDR, newpathRet);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int SysSymlinkat(const char *target, int dirfd, const char *linkpath)
|
|
{
|
|
int ret;
|
|
char *pathRet = NULL;
|
|
char *targetRet = NULL;
|
|
|
|
if (target != NULL) {
|
|
ret = UserPathCopy(target, &targetRet);
|
|
if (ret != 0) {
|
|
goto OUT;
|
|
}
|
|
}
|
|
|
|
if (linkpath != NULL) {
|
|
ret = UserPathCopy(linkpath, &pathRet);
|
|
if (ret != 0) {
|
|
goto OUT;
|
|
}
|
|
}
|
|
|
|
if (dirfd != AT_FDCWD) {
|
|
/* Process fd convert to system global fd */
|
|
dirfd = GetAssociatedSystemFd(dirfd);
|
|
}
|
|
|
|
ret = symlinkat(targetRet, dirfd, pathRet);
|
|
if (ret < 0) {
|
|
ret = -get_errno();
|
|
}
|
|
|
|
OUT:
|
|
if (pathRet != NULL) {
|
|
(void)LOS_MemFree(OS_SYS_MEM_ADDR, pathRet);
|
|
}
|
|
|
|
if (targetRet != NULL) {
|
|
(void)LOS_MemFree(OS_SYS_MEM_ADDR, targetRet);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
ssize_t SysReadlinkat(int dirfd, const char *pathname, char *buf, size_t bufsize)
|
|
{
|
|
ssize_t ret;
|
|
char *pathRet = NULL;
|
|
|
|
if (bufsize == 0) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (pathname != NULL) {
|
|
ret = UserPathCopy(pathname, &pathRet);
|
|
if (ret != 0) {
|
|
goto OUT;
|
|
}
|
|
}
|
|
|
|
if (dirfd != AT_FDCWD) {
|
|
/* Process fd convert to system global fd */
|
|
dirfd = GetAssociatedSystemFd(dirfd);
|
|
}
|
|
|
|
if (!LOS_IsUserAddressRange((vaddr_t)(UINTPTR)buf, bufsize)) {
|
|
ret = -EFAULT;
|
|
goto OUT;
|
|
}
|
|
|
|
ret = readlinkat(dirfd, pathRet, buf, bufsize);
|
|
if (ret < 0) {
|
|
ret = -get_errno();
|
|
}
|
|
|
|
OUT:
|
|
if (pathRet != NULL) {
|
|
(void)LOS_MemFree(OS_SYS_MEM_ADDR, pathRet);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int SysUnlinkat(int dirfd, const char *pathname, int flag)
|
|
{
|
|
int ret;
|
|
char *pathRet = NULL;
|
|
|
|
if (pathname != NULL) {
|
|
ret = UserPathCopy(pathname, &pathRet);
|
|
if (ret != 0) {
|
|
goto OUT;
|
|
}
|
|
}
|
|
|
|
if (dirfd != AT_FDCWD) {
|
|
/* Process fd convert to system global fd */
|
|
dirfd = GetAssociatedSystemFd(dirfd);
|
|
}
|
|
|
|
ret = unlinkat(dirfd, (pathname ? pathRet : NULL), flag);
|
|
if (ret < 0) {
|
|
ret = -get_errno();
|
|
}
|
|
|
|
OUT:
|
|
if (pathRet != NULL) {
|
|
(void)LOS_MemFree(OS_SYS_MEM_ADDR, pathRet);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int SysRenameat(int oldfd, const char *oldpath, int newdfd, const char *newpath)
|
|
{
|
|
int ret;
|
|
char *pathOldRet = NULL;
|
|
char *pathNewRet = NULL;
|
|
|
|
if (oldpath != NULL) {
|
|
ret = UserPathCopy(oldpath, &pathOldRet);
|
|
if (ret != 0) {
|
|
goto OUT;
|
|
}
|
|
}
|
|
|
|
if (newpath != NULL) {
|
|
ret = UserPathCopy(newpath, &pathNewRet);
|
|
if (ret != 0) {
|
|
goto OUT;
|
|
}
|
|
}
|
|
|
|
if (oldfd != AT_FDCWD) {
|
|
/* Process fd convert to system global fd */
|
|
oldfd = GetAssociatedSystemFd(oldfd);
|
|
}
|
|
if (newdfd != AT_FDCWD) {
|
|
/* Process fd convert to system global fd */
|
|
newdfd = GetAssociatedSystemFd(newdfd);
|
|
}
|
|
|
|
ret = do_rename(oldfd, (oldpath ? pathOldRet : NULL), newdfd, (newpath ? pathNewRet : NULL));
|
|
if (ret < 0) {
|
|
ret = -get_errno();
|
|
}
|
|
|
|
OUT:
|
|
if (pathOldRet != NULL) {
|
|
(void)LOS_MemFree(OS_SYS_MEM_ADDR, pathOldRet);
|
|
}
|
|
if (pathNewRet != NULL) {
|
|
(void)LOS_MemFree(OS_SYS_MEM_ADDR, pathNewRet);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int SysFallocate(int fd, int mode, off_t offset, off_t len)
|
|
{
|
|
int ret;
|
|
|
|
/* Process fd convert to system global fd */
|
|
fd = GetAssociatedSystemFd(fd);
|
|
|
|
ret = fallocate(fd, mode, offset, len);
|
|
if (ret < 0) {
|
|
return -get_errno();
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int SysFallocate64(int fd, int mode, off64_t offset, off64_t len)
|
|
{
|
|
int ret;
|
|
|
|
/* Process fd convert to system global fd */
|
|
fd = GetAssociatedSystemFd(fd);
|
|
|
|
ret = fallocate64(fd, mode, offset, len);
|
|
if (ret < 0) {
|
|
return -get_errno();
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
ssize_t SysPreadv(int fd, const struct iovec *iov, int iovcnt, long loffset, long hoffset)
|
|
{
|
|
off_t offsetflag;
|
|
offsetflag = (off_t)((unsigned long long)loffset | (((unsigned long long)hoffset) << HIGH_SHIFT_BIT));
|
|
|
|
int ret;
|
|
int valid_iovcnt = -1;
|
|
struct iovec *iovRet = NULL;
|
|
|
|
/* Process fd convert to system global fd */
|
|
fd = GetAssociatedSystemFd(fd);
|
|
if ((iov == NULL) || (iovcnt < 0) || (iovcnt > IOV_MAX)) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (iovcnt == 0) {
|
|
return 0;
|
|
}
|
|
|
|
ret = UserIovCopy(&iovRet, iov, iovcnt, &valid_iovcnt);
|
|
if (ret != 0) {
|
|
return ret;
|
|
}
|
|
|
|
if (valid_iovcnt <= 0) {
|
|
ret = -EFAULT;
|
|
goto OUT_FREE;
|
|
}
|
|
|
|
ret = preadv(fd, iovRet, valid_iovcnt, offsetflag);
|
|
if (ret < 0) {
|
|
ret = -get_errno();
|
|
}
|
|
|
|
OUT_FREE:
|
|
(void)(void)LOS_MemFree(OS_SYS_MEM_ADDR, iovRet);
|
|
return ret;
|
|
}
|
|
|
|
ssize_t SysPwritev(int fd, const struct iovec *iov, int iovcnt, long loffset, long hoffset)
|
|
{
|
|
off_t offsetflag;
|
|
offsetflag = (off_t)((unsigned long long)loffset | (((unsigned long long)hoffset) << HIGH_SHIFT_BIT));
|
|
int ret;
|
|
int valid_iovcnt = -1;
|
|
struct iovec *iovRet = NULL;
|
|
|
|
/* Process fd convert to system global fd */
|
|
fd = GetAssociatedSystemFd(fd);
|
|
if ((iov == NULL) || (iovcnt < 0) || (iovcnt > IOV_MAX)) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (iovcnt == 0) {
|
|
return 0;
|
|
}
|
|
|
|
ret = UserIovCopy(&iovRet, iov, iovcnt, &valid_iovcnt);
|
|
if (ret != 0) {
|
|
return ret;
|
|
}
|
|
|
|
if (valid_iovcnt != iovcnt) {
|
|
ret = -EFAULT;
|
|
goto OUT_FREE;
|
|
}
|
|
|
|
ret = pwritev(fd, iovRet, valid_iovcnt, offsetflag);
|
|
if (ret < 0) {
|
|
ret = -get_errno();
|
|
}
|
|
|
|
OUT_FREE:
|
|
(void)LOS_MemFree(OS_SYS_MEM_ADDR, iovRet);
|
|
return ret;
|
|
}
|
|
|
|
#ifdef LOSCFG_FS_FAT
|
|
int SysFormat(const char *dev, int sectors, int option)
|
|
{
|
|
int ret;
|
|
char *devRet = NULL;
|
|
|
|
if (!IsCapPermit(CAP_FS_FORMAT)) {
|
|
return -EPERM;
|
|
}
|
|
|
|
if (dev != NULL) {
|
|
ret = UserPathCopy(dev, &devRet);
|
|
if (ret != 0) {
|
|
goto OUT;
|
|
}
|
|
}
|
|
|
|
ret = format((dev ? devRet : NULL), sectors, option);
|
|
if (ret < 0) {
|
|
ret = -get_errno();
|
|
}
|
|
|
|
OUT:
|
|
if (devRet != NULL) {
|
|
(void)LOS_MemFree(OS_SYS_MEM_ADDR, devRet);
|
|
}
|
|
return ret;
|
|
}
|
|
#endif
|
|
|
|
int SysFstat64(int fd, struct kstat *buf)
|
|
{
|
|
int ret;
|
|
struct stat64 bufRet = {0};
|
|
|
|
/* Process fd convert to system global fd */
|
|
fd = GetAssociatedSystemFd(fd);
|
|
|
|
ret = fstat64(fd, (buf ? (&bufRet) : NULL));
|
|
if (ret < 0) {
|
|
return -get_errno();
|
|
}
|
|
|
|
ret = LOS_ArchCopyToUser(buf, &bufRet, sizeof(struct kstat));
|
|
if (ret != 0) {
|
|
return -EFAULT;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int SysFcntl64(int fd, int cmd, void *arg)
|
|
{
|
|
/* Process fd convert to system global fd */
|
|
int sysfd = GetAssociatedSystemFd(fd);
|
|
|
|
int ret = VfsFcntl(fd, cmd, arg);
|
|
if (ret == CONTINE_NUTTX_FCNTL) {
|
|
ret = fcntl64(sysfd, cmd, arg);
|
|
}
|
|
|
|
if (ret < 0) {
|
|
return -get_errno();
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int SysGetdents64(int fd, struct dirent *de_user, unsigned int count)
|
|
{
|
|
if (!LOS_IsUserAddressRange((VADDR_T)(UINTPTR)de_user, count)) {
|
|
return -EFAULT;
|
|
}
|
|
|
|
struct dirent *de_knl = NULL;
|
|
|
|
/* Process fd convert to system global fd */
|
|
fd = GetAssociatedSystemFd(fd);
|
|
|
|
int ret = do_readdir(fd, &de_knl, count);
|
|
if (ret < 0) {
|
|
return ret;
|
|
}
|
|
if (de_knl != NULL) {
|
|
int cpy_ret = LOS_ArchCopyToUser(de_user, de_knl, ret);
|
|
if (cpy_ret != 0)
|
|
{
|
|
return -EFAULT;
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
char *SysRealpath(const char *path, char *resolved_path)
|
|
{
|
|
char *pathRet = NULL;
|
|
char *resolved_pathRet = NULL;
|
|
char *result = NULL;
|
|
int ret;
|
|
|
|
if (resolved_path == NULL) {
|
|
return (char *)(intptr_t)-EINVAL;
|
|
}
|
|
|
|
if (path != NULL) {
|
|
ret = UserPathCopy(path, &pathRet);
|
|
if (ret != 0) {
|
|
result = (char *)(intptr_t)ret;
|
|
goto OUT;
|
|
}
|
|
}
|
|
|
|
resolved_pathRet = realpath((path ? pathRet : NULL), NULL);
|
|
if (resolved_pathRet == NULL) {
|
|
result = (char *)(intptr_t)-get_errno();
|
|
goto OUT;
|
|
}
|
|
|
|
ret = LOS_ArchCopyToUser(resolved_path, resolved_pathRet, strlen(resolved_pathRet) + 1);
|
|
if (ret != 0) {
|
|
result = (char *)(intptr_t)-EFAULT;
|
|
goto OUT;
|
|
}
|
|
result = resolved_path;
|
|
|
|
OUT:
|
|
if (pathRet != NULL) {
|
|
(void)LOS_MemFree(OS_SYS_MEM_ADDR, pathRet);
|
|
}
|
|
if (resolved_pathRet != NULL) {
|
|
(void)LOS_MemFree(OS_SYS_MEM_ADDR, resolved_pathRet);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
int SysUtimensat(int fd, const char *path, struct timespec times[TIMESPEC_TIMES_NUM], int flag)
|
|
{
|
|
int ret;
|
|
int timeLen;
|
|
struct IATTR attr = {0};
|
|
char *filePath = NULL;
|
|
|
|
timeLen = TIMESPEC_TIMES_NUM * sizeof(struct timespec);
|
|
CHECK_ASPACE(times, timeLen);
|
|
DUP_FROM_USER(times, timeLen);
|
|
ret = CheckNewAttrTime(&attr, times);
|
|
FREE_DUP(times);
|
|
if (ret < 0) {
|
|
goto OUT;
|
|
}
|
|
|
|
ret = GetFullpathNull(fd, path, &filePath);
|
|
if (ret < 0) {
|
|
goto OUT;
|
|
}
|
|
|
|
ret = chattr(filePath, &attr);
|
|
if (ret < 0) {
|
|
ret = -get_errno();
|
|
}
|
|
|
|
OUT:
|
|
PointerFree(filePath);
|
|
return ret;
|
|
}
|
|
|
|
int SysChmod(const char *pathname, mode_t mode)
|
|
{
|
|
int ret;
|
|
char *pathRet = NULL;
|
|
|
|
if (pathname != NULL) {
|
|
ret = UserPathCopy(pathname, &pathRet);
|
|
if (ret != 0) {
|
|
goto OUT;
|
|
}
|
|
}
|
|
|
|
ret = chmod(pathRet, mode);
|
|
if (ret < 0) {
|
|
ret = -get_errno();
|
|
}
|
|
|
|
OUT:
|
|
if (pathRet != NULL) {
|
|
(void)LOS_MemFree(OS_SYS_MEM_ADDR, pathRet);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int SysFchmodat(int fd, const char *path, mode_t mode, int flag)
|
|
{
|
|
int ret;
|
|
char *pathRet = NULL;
|
|
char *fullpath = NULL;
|
|
struct IATTR attr = {
|
|
.attr_chg_mode = mode,
|
|
.attr_chg_valid = CHG_MODE,
|
|
};
|
|
|
|
if (path != NULL) {
|
|
ret = UserPathCopy(path, &pathRet);
|
|
if (ret != 0) {
|
|
goto OUT;
|
|
}
|
|
}
|
|
|
|
if (fd != AT_FDCWD) {
|
|
/* Process fd convert to system global fd */
|
|
fd = GetAssociatedSystemFd(fd);
|
|
}
|
|
|
|
ret = vfs_normalize_pathat(fd, pathRet, &fullpath);
|
|
if (ret < 0) {
|
|
goto OUT;
|
|
}
|
|
|
|
ret = chattr(fullpath, &attr);
|
|
if (ret < 0) {
|
|
ret = -get_errno();
|
|
}
|
|
|
|
OUT:
|
|
PointerFree(pathRet);
|
|
PointerFree(fullpath);
|
|
|
|
return ret;
|
|
}
|
|
|
|
int SysFchmod(int fd, mode_t mode)
|
|
{
|
|
int ret;
|
|
int sysFd;
|
|
struct IATTR attr = {
|
|
.attr_chg_mode = mode,
|
|
.attr_chg_valid = CHG_MODE, /* change mode */
|
|
};
|
|
struct file *file = NULL;
|
|
|
|
sysFd = GetAssociatedSystemFd(fd);
|
|
if (sysFd < 0) {
|
|
return -EBADF;
|
|
}
|
|
|
|
ret = fs_getfilep(sysFd, &file);
|
|
if (ret < 0) {
|
|
return -get_errno();
|
|
}
|
|
|
|
ret = chattr(file->f_path, &attr);
|
|
if (ret < 0) {
|
|
return -get_errno();
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int SysFchownat(int fd, const char *path, uid_t owner, gid_t group, int flag)
|
|
{
|
|
int ret;
|
|
char *fullpath = NULL;
|
|
struct IATTR attr = {
|
|
.attr_chg_valid = 0,
|
|
};
|
|
|
|
ret = GetFullpath(fd, path, &fullpath);
|
|
if (ret < 0) {
|
|
goto OUT;
|
|
}
|
|
|
|
if (owner != (uid_t)-1) {
|
|
attr.attr_chg_uid = owner;
|
|
attr.attr_chg_valid |= CHG_UID;
|
|
}
|
|
if (group != (gid_t)-1) {
|
|
attr.attr_chg_gid = group;
|
|
attr.attr_chg_valid |= CHG_GID;
|
|
}
|
|
|
|
ret = chattr(fullpath, &attr);
|
|
if (ret < 0) {
|
|
ret = -get_errno();
|
|
}
|
|
|
|
OUT:
|
|
PointerFree(fullpath);
|
|
|
|
return ret;
|
|
}
|
|
|
|
int SysFchown(int fd, uid_t owner, gid_t group)
|
|
{
|
|
int ret;
|
|
int sysFd;
|
|
struct IATTR attr = {0};
|
|
attr.attr_chg_valid = 0;
|
|
struct file *file = NULL;
|
|
|
|
sysFd = GetAssociatedSystemFd(fd);
|
|
if (sysFd < 0) {
|
|
return -EBADF;
|
|
}
|
|
|
|
ret = fs_getfilep(sysFd, &file);
|
|
if (ret < 0) {
|
|
return -get_errno();
|
|
}
|
|
|
|
if (owner != (uid_t)-1) {
|
|
attr.attr_chg_uid = owner;
|
|
attr.attr_chg_valid |= CHG_UID;
|
|
}
|
|
if (group != (gid_t)-1) {
|
|
attr.attr_chg_gid = group;
|
|
attr.attr_chg_valid |= CHG_GID;
|
|
}
|
|
ret = chattr(file->f_path, &attr);
|
|
if (ret < 0) {
|
|
ret = -get_errno();
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int SysChown(const char *pathname, uid_t owner, gid_t group)
|
|
{
|
|
int ret;
|
|
char *pathRet = NULL;
|
|
|
|
if (pathname != NULL) {
|
|
ret = UserPathCopy(pathname, &pathRet);
|
|
if (ret != 0) {
|
|
goto OUT;
|
|
}
|
|
}
|
|
|
|
ret = chown(pathRet, owner, group);
|
|
if (ret < 0) {
|
|
ret = -get_errno();
|
|
}
|
|
|
|
OUT:
|
|
if (pathRet != NULL) {
|
|
(void)LOS_MemFree(OS_SYS_MEM_ADDR, pathRet);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int SysFstatat64(int dirfd, const char *restrict path, struct kstat *restrict buf, int flag)
|
|
{
|
|
int ret;
|
|
struct stat bufRet = {0};
|
|
char *pathRet = NULL;
|
|
char *fullpath = NULL;
|
|
|
|
if (path != NULL) {
|
|
ret = UserPathCopy(path, &pathRet);
|
|
if (ret != 0) {
|
|
goto OUT;
|
|
}
|
|
}
|
|
|
|
if (dirfd != AT_FDCWD) {
|
|
/* Process fd convert to system global fd */
|
|
dirfd = GetAssociatedSystemFd(dirfd);
|
|
}
|
|
|
|
ret = vfs_normalize_pathat(dirfd, pathRet, &fullpath);
|
|
if (ret < 0) {
|
|
goto OUT;
|
|
}
|
|
|
|
ret = stat(fullpath, &bufRet);
|
|
if (ret < 0) {
|
|
ret = -get_errno();
|
|
goto OUT;
|
|
}
|
|
|
|
ret = LOS_ArchCopyToUser(buf, &bufRet, sizeof(struct kstat));
|
|
if (ret != 0) {
|
|
ret = -EFAULT;
|
|
goto OUT;
|
|
}
|
|
|
|
OUT:
|
|
if (pathRet != NULL) {
|
|
LOS_MemFree(OS_SYS_MEM_ADDR, pathRet);
|
|
}
|
|
|
|
if (fullpath != NULL) {
|
|
free(fullpath);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int SysFaccessat(int fd, const char *filename, int amode, int flag)
|
|
{
|
|
int ret;
|
|
struct stat buf;
|
|
struct statfs fsBuf;
|
|
char *fullDirectory = NULL;
|
|
|
|
ret = GetFullpath(fd, filename, &fullDirectory);
|
|
if (ret < 0) {
|
|
goto OUT;
|
|
}
|
|
|
|
ret = statfs(fullDirectory, &fsBuf);
|
|
if (ret != 0) {
|
|
ret = -get_errno();
|
|
goto OUT;
|
|
}
|
|
|
|
if ((fsBuf.f_flags & MS_RDONLY) && ((unsigned int)amode & W_OK)) {
|
|
ret = -EROFS;
|
|
goto OUT;
|
|
}
|
|
|
|
ret = stat(fullDirectory, &buf);
|
|
if (ret != 0) {
|
|
ret = -get_errno();
|
|
goto OUT;
|
|
}
|
|
|
|
if (VfsPermissionCheck(buf.st_uid, buf.st_gid, buf.st_mode, amode)) {
|
|
ret = -EACCES;
|
|
}
|
|
|
|
OUT:
|
|
PointerFree(fullDirectory);
|
|
|
|
return ret;
|
|
}
|
|
|
|
int SysFstatfs(int fd, struct statfs *buf)
|
|
{
|
|
int ret;
|
|
struct file *filep = NULL;
|
|
struct statfs bufRet = {0};
|
|
|
|
/* Process fd convert to system global fd */
|
|
fd = GetAssociatedSystemFd(fd);
|
|
|
|
ret = fs_getfilep(fd, &filep);
|
|
if (ret < 0) {
|
|
ret = -get_errno();
|
|
return ret;
|
|
}
|
|
|
|
ret = statfs(filep->f_path, &bufRet);
|
|
if (ret < 0) {
|
|
ret = -get_errno();
|
|
return ret;
|
|
}
|
|
|
|
ret = LOS_ArchCopyToUser(buf, &bufRet, sizeof(struct statfs));
|
|
if (ret != 0) {
|
|
ret = -EFAULT;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int SysFstatfs64(int fd, size_t sz, struct statfs *buf)
|
|
{
|
|
int ret = 0;
|
|
|
|
if (sz != sizeof(struct statfs)) {
|
|
ret = -EINVAL;
|
|
return ret;
|
|
}
|
|
|
|
ret = SysFstatfs(fd, buf);
|
|
|
|
return ret;
|
|
}
|
|
|
|
int SysPpoll(struct pollfd *fds, nfds_t nfds, const struct timespec *tmo_p, const sigset_t *sigMask, int nsig)
|
|
{
|
|
int timeout, retVal;
|
|
sigset_t_l origMask = {0};
|
|
sigset_t_l set = {0};
|
|
|
|
CHECK_ASPACE(tmo_p, sizeof(struct timespec));
|
|
CPY_FROM_USER(tmo_p);
|
|
|
|
if (tmo_p != NULL) {
|
|
timeout = tmo_p->tv_sec * OS_SYS_US_PER_MS + tmo_p->tv_nsec / OS_SYS_NS_PER_MS;
|
|
if (timeout < 0) {
|
|
return -EINVAL;
|
|
}
|
|
} else {
|
|
timeout = -1;
|
|
}
|
|
|
|
if (sigMask != NULL) {
|
|
retVal = LOS_ArchCopyFromUser(&set, sigMask, sizeof(sigset_t));
|
|
if (retVal != 0) {
|
|
return -EFAULT;
|
|
}
|
|
(VOID)OsSigprocMask(SIG_SETMASK, &set, &origMask);
|
|
} else {
|
|
(VOID)OsSigprocMask(SIG_SETMASK, NULL, &origMask);
|
|
}
|
|
|
|
retVal = SysPoll(fds, nfds, timeout);
|
|
(VOID)OsSigprocMask(SIG_SETMASK, &origMask, NULL);
|
|
|
|
return retVal;
|
|
}
|
|
|
|
int SysPselect6(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
|
|
const struct timespec *timeout, const long data[2])
|
|
{
|
|
int ret;
|
|
int retVal;
|
|
sigset_t_l origMask;
|
|
sigset_t_l setl;
|
|
|
|
CHECK_ASPACE(readfds, sizeof(fd_set));
|
|
CHECK_ASPACE(writefds, sizeof(fd_set));
|
|
CHECK_ASPACE(exceptfds, sizeof(fd_set));
|
|
CHECK_ASPACE(timeout, sizeof(struct timeval));
|
|
|
|
CPY_FROM_USER(readfds);
|
|
CPY_FROM_USER(writefds);
|
|
CPY_FROM_USER(exceptfds);
|
|
DUP_FROM_USER(timeout, sizeof(struct timeval));
|
|
|
|
((struct timeval *)timeout)->tv_usec = timeout->tv_nsec / 1000; /* 1000, convert ns to us */
|
|
|
|
if (data != NULL) {
|
|
retVal = LOS_ArchCopyFromUser(&(setl.sig[0]), (int *)data[0], sizeof(sigset_t));
|
|
if (retVal != 0) {
|
|
ret = -EFAULT;
|
|
FREE_DUP(timeout);
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
OsSigprocMask(SIG_SETMASK, &setl, &origMask);
|
|
ret = do_select(nfds, readfds, writefds, exceptfds, (struct timeval *)timeout, UserPoll);
|
|
if (ret < 0) {
|
|
/* do not copy parameter back to user mode if do_select failed */
|
|
ret = -get_errno();
|
|
FREE_DUP(timeout);
|
|
return ret;
|
|
}
|
|
OsSigprocMask(SIG_SETMASK, &origMask, NULL);
|
|
|
|
CPY_TO_USER(readfds);
|
|
CPY_TO_USER(writefds);
|
|
CPY_TO_USER(exceptfds);
|
|
FREE_DUP(timeout);
|
|
|
|
return ret;
|
|
}
|
|
|
|
int SysEpollCreate(int size)
|
|
{
|
|
int ret;
|
|
int procFd;
|
|
|
|
if (size <= 0) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
ret = epoll_create(size);
|
|
if (ret < 0) {
|
|
ret = -get_errno();
|
|
}
|
|
|
|
procFd = AllocAndAssocProcessFd((INTPTR)(ret), MIN_START_FD);
|
|
if (procFd == -1) {
|
|
epoll_close(ret);
|
|
return -EMFILE;
|
|
}
|
|
|
|
return procFd;
|
|
}
|
|
|
|
int SysEpollCreate1(int flags)
|
|
{
|
|
int ret;
|
|
int procFd;
|
|
|
|
ret = epoll_create(flags);
|
|
if (ret < 0) {
|
|
ret = -get_errno();
|
|
}
|
|
|
|
procFd = AllocAndAssocProcessFd((INTPTR)(ret), MIN_START_FD);
|
|
if (procFd == -1) {
|
|
epoll_close(ret);
|
|
return -EMFILE;
|
|
}
|
|
|
|
return procFd;
|
|
}
|
|
|
|
int SysEpollCtl(int epfd, int op, int fd, struct epoll_event *ev)
|
|
{
|
|
int ret;
|
|
|
|
CHECK_ASPACE(ev, sizeof(struct epoll_event));
|
|
CPY_FROM_USER(ev);
|
|
|
|
fd = GetAssociatedSystemFd(fd);
|
|
epfd = GetAssociatedSystemFd(epfd);
|
|
if ((fd < 0) || (epfd < 0)) {
|
|
ret = -EBADF;
|
|
goto OUT;
|
|
}
|
|
|
|
ret = epoll_ctl(epfd, op, fd, ev);
|
|
if (ret < 0) {
|
|
ret =-EBADF;
|
|
goto OUT;
|
|
}
|
|
|
|
CPY_TO_USER(ev);
|
|
OUT:
|
|
return (ret == -1)? -get_errno():ret;
|
|
}
|
|
|
|
int SysEpollWait(int epfd, struct epoll_event *evs, int maxevents, int timeout)
|
|
{
|
|
int ret = 0;
|
|
|
|
CHECK_ASPACE(evs, sizeof(struct epoll_event));
|
|
CPY_FROM_USER(evs);
|
|
|
|
epfd = GetAssociatedSystemFd(epfd);
|
|
if (epfd < 0) {
|
|
ret = -EBADF;
|
|
goto OUT;
|
|
}
|
|
|
|
ret = epoll_wait(epfd, evs, maxevents, timeout);
|
|
if (ret < 0) {
|
|
ret = -get_errno();
|
|
}
|
|
|
|
CPY_TO_USER(evs);
|
|
OUT:
|
|
return (ret == -1) ? -get_errno() : ret;
|
|
}
|
|
|
|
int SysEpollPwait(int epfd, struct epoll_event *evs, int maxevents, int timeout, const sigset_t *mask)
|
|
{
|
|
sigset_t_l origMask;
|
|
sigset_t_l setl;
|
|
int ret = 0;
|
|
|
|
CHECK_ASPACE(mask, sizeof(sigset_t));
|
|
|
|
if (mask != NULL) {
|
|
ret = LOS_ArchCopyFromUser(&setl, mask, sizeof(sigset_t));
|
|
if (ret != 0) {
|
|
return -EFAULT;
|
|
}
|
|
}
|
|
|
|
CHECK_ASPACE(evs, sizeof(struct epoll_event));
|
|
CPY_FROM_USER(evs);
|
|
|
|
epfd = GetAssociatedSystemFd(epfd);
|
|
if (epfd < 0) {
|
|
ret = -EBADF;
|
|
goto OUT;
|
|
}
|
|
|
|
OsSigprocMask(SIG_SETMASK, &setl, &origMask);
|
|
ret = epoll_wait(epfd, evs, maxevents, timeout);
|
|
if (ret < 0) {
|
|
ret = -get_errno();
|
|
}
|
|
|
|
OsSigprocMask(SIG_SETMASK, &origMask, NULL);
|
|
|
|
CPY_TO_USER(evs);
|
|
OUT:
|
|
return (ret == -1) ? -get_errno() : ret;
|
|
}
|
|
|
|
#endif
|