kernel_liteos_a/syscall/fs_syscall.c

2259 lines
50 KiB
C

/*
* 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.
*/
#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"
#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 "fs_other.h"
#include "fs_file.h"
#include "capability_type.h"
#include "capability_api.h"
#define HIGH_SHIFT_BIT 32
static int UserPathCopy(const char *userPath, char **pathBuf)
{
int ret;
*pathBuf = (char *)LOS_MemAlloc(OS_SYS_MEM_ADDR, PATH_MAX + 1);
if (*pathBuf == NULL) {
return -ENOMEM;
}
ret = LOS_StrncpyFromUser(*pathBuf, userPath, PATH_MAX + 1);
if (ret < 0) {
(void)LOS_MemFree(OS_SYS_MEM_ADDR, *pathBuf);
*pathBuf = NULL;
return ret;
} else if (ret > PATH_MAX) {
(void)LOS_MemFree(OS_SYS_MEM_ADDR, *pathBuf);
*pathBuf = NULL;
return -ENAMETOOLONG;
}
(*pathBuf)[ret] = '\0';
return 0;
}
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;
}
static int FcntlDupFd(int sysfd, void *arg)
{
int leastFd = (intptr_t)arg;
if ((sysfd < 0) || (sysfd >= CONFIG_NFILE_DESCRIPTORS)) {
return -EBADF;
}
if (CheckProcessFd(leastFd) != OK) {
return -EINVAL;
}
int procFd = AllocLowestProcessFd(leastFd);
if (procFd < 0) {
return -EMFILE;
}
files_refer(sysfd);
AssociateSystemFd(procFd, sysfd);
return procFd;
}
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 */
fd = GetAssociatedSystemFd(fd);
ret = write(fd, 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) {
goto ERROUT_PATH_FREE;
}
}
procFd = AllocProcessFd();
if (procFd < 0) {
ret = -EMFILE;
goto ERROUT;
}
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 (ret >= 0) {
AssociateSystemFd(procFd, ret);
ret = procFd;
} else {
FreeProcessFd(procFd);
}
ERROUT_PATH_FREE:
if (pathRet != NULL) {
LOS_MemFree(OS_SYS_MEM_ADDR, pathRet);
}
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 *pathRet = NULL;
if (linkpath != NULL) {
ret = UserPathCopy(linkpath, &pathRet);
if (ret != 0) {
goto OUT;
}
}
ret = symlink(target, pathRet);
if (ret < 0) {
ret = -get_errno();
}
OUT:
if (pathRet != NULL) {
(void)LOS_MemFree(OS_SYS_MEM_ADDR, pathRet);
}
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 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)
{
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 (off_t)-get_errno();
}
/* libc seekdir function should set the whence to SEEK_SET, so we can discard
* the whence argument here */
if (filep->f_oflags & O_DIRECTORY) {
/* defensive coding */
if (filep->f_dir == NULL) {
return (off_t)-EINVAL;
}
if (offset == 0) {
rewinddir(filep->f_dir);
} else {
seekdir(filep->f_dir, offset);
}
ret = telldir(filep->f_dir);
if (ret < 0) {
return (off_t)-get_errno();
}
return ret;
}
/* Then let file_seek do the real work */
ret = file_seek(filep, offset, whence);
if (ret < 0) {
return -get_errno();
}
return ret;
}
off64_t SysLseek64(int fd, int offsetHigh, int offsetLow, off64_t *result, int whence)
{
off64_t ret;
int retVal;
struct file *filep = NULL;
off64_t offset = ((off64_t)((UINT64)offsetHigh << 32)) + (uint)offsetLow; /* 32: offsetHigh is high 32 bits */
/* 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 (off64_t)-get_errno();
}
/* libc seekdir function should set the whence to SEEK_SET, so we can discard
* the whence argument here */
if (filep->f_oflags & O_DIRECTORY) {
/* defensive coding */
if (filep->f_dir == NULL) {
return (off64_t)-EINVAL;
}
if (offsetLow == 0) {
rewinddir(filep->f_dir);
} else {
seekdir(filep->f_dir, offsetLow);
}
ret = telldir(filep->f_dir);
if (ret < 0) {
return (off64_t)-get_errno();
}
goto out;
}
/* Then let file_seek do the real work */
ret = file_seek64(filep, offset, whence);
if (ret < 0) {
return (off64_t)-get_errno();
}
out:
retVal = LOS_ArchCopyToUser(result, &ret, 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 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
}
ret = mount(sourceRet, targetRet, (filesystemtype ? fstypeRet : NULL), mountflags, data);
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);
}
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;
struct stat buf;
struct statfs fsBuf;
char *pathRet = NULL;
if (path != NULL) {
ret = UserPathCopy(path, &pathRet);
if (ret != 0) {
goto OUT;
}
}
ret = statfs((path ? pathRet : NULL), &fsBuf);
if (ret != 0) {
ret = -get_errno();
if (ret != -ENOSYS) {
goto OUT;
} else {
/* dev has no statfs ops, need devfs to handle this in feature */
ret = LOS_OK;
}
}
if ((fsBuf.f_flags & MS_RDONLY) && ((unsigned int)amode & W_OK)) {
ret = -EROFS;
goto OUT;
}
ret = stat((path ? pathRet : NULL), &buf);
if (ret != 0) {
ret = -get_errno();
goto OUT;
}
if (VfsPermissionCheck(buf.st_uid, buf.st_gid, buf.st_mode, amode)) {
ret = -EACCES;
}
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 */
fd = GetAssociatedSystemFd(fd);
if (cmd == F_DUPFD) {
return FcntlDupFd(fd, arg);
}
int ret = fcntl(fd, 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);
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 stat *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 stat));
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 stat *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 stat));
if (ret != 0) {
ret = -EFAULT;
}
OUT:
if (pathRet != NULL) {
(void)LOS_MemFree(OS_SYS_MEM_ADDR, pathRet);
}
return ret;
}
int SysFstat(int fd, struct stat *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 stat));
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)) {
ret = vfs_readv(fd, iov, iovcnt, NULL);
return -get_errno();
}
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 */
fd = GetAssociatedSystemFd(fd);
if ((iov == NULL) || (iovcnt <= 0) || (iovcnt > IOV_MAX)) {
ret = writev(fd, iov, iovcnt);
return -get_errno();
}
ret = UserIovCopy(&iovRet, iov, iovcnt, &valid_iovcnt);
if (ret != 0) {
return ret;
}
if (valid_iovcnt != iovcnt) {
ret = -EFAULT;
goto OUT_FREE;
}
ret = writev(fd, 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;
int retVal;
bufRet = (char *)LOS_MemAlloc(OS_SYS_MEM_ADDR, n);
if (bufRet == NULL) {
return (char *)(intptr_t)-ENOMEM;
}
(void)memset_s(bufRet, n, 0, n);
ret = getcwd((buf ? bufRet : NULL), n);
if (ret == NULL) {
(void)LOS_MemFree(OS_SYS_MEM_ADDR, bufRet);
return (char *)(intptr_t)-get_errno();
}
retVal = LOS_ArchCopyToUser(buf, bufRet, n);
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 (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;
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(target, dirfd, pathRet);
if (ret < 0) {
ret = -get_errno();
}
OUT:
if (pathRet != NULL) {
(void)LOS_MemFree(OS_SYS_MEM_ADDR, pathRet);
}
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)) {
ret = preadv(fd, iov, iovcnt, offsetflag);
return -get_errno();
}
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)) {
ret = pwritev(fd, iov, iovcnt, offsetflag);
return -get_errno();
}
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 stat64 *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 stat64));
if (ret != 0) {
return -EFAULT;
}
return ret;
}
int SysFcntl64(int fd, int cmd, void *arg)
{
/* Process fd convert to system global fd */
fd = GetAssociatedSystemFd(fd);
if (cmd == F_DUPFD) {
return FcntlDupFd(fd, arg);
}
int ret = fcntl64(fd, 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 SysChmod(const char *pathname, mode_t mode)
{
struct IATTR attr = {0};
attr.attr_chg_mode = mode;
attr.attr_chg_valid = CHG_MODE; /* change mode */
int ret;
char *pathRet = NULL;
if (pathname != NULL) {
ret = UserPathCopy(pathname, &pathRet);
if (ret != 0) {
goto OUT;
}
}
ret = chattr((pathname ? pathRet : NULL), &attr);
if (ret < 0) {
ret = -get_errno();
}
OUT:
if (pathRet != NULL) {
(void)LOS_MemFree(OS_SYS_MEM_ADDR, pathRet);
}
return ret;
}
int SysChown(const char *pathname, uid_t owner, gid_t group)
{
struct IATTR attr = {0};
attr.attr_chg_valid = 0;
int ret;
char *pathRet = NULL;
if (pathname != NULL) {
ret = UserPathCopy(pathname, &pathRet);
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((pathname ? pathRet : NULL), &attr);
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 stat *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 stat));
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;
}
#endif