2055 lines
46 KiB
C
2055 lines
46 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 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 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
|