add OpenHarmony 1.0 baseline
This commit is contained in:
201
fs/vfs/operation/fs_chattr.c
Executable file
201
fs/vfs/operation/fs_chattr.c
Executable file
@@ -0,0 +1,201 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
|
||||
* Copyright (c) 2020, 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.
|
||||
*/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include "fs/fs.h"
|
||||
|
||||
#include "errno.h"
|
||||
#include "string.h"
|
||||
#include "stdlib.h"
|
||||
#include "capability_api.h"
|
||||
#include "inode/inode.h"
|
||||
#include "sys/stat.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Static Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: pseudo_chattr
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero on success; -EPERM on failure:
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int pseudo_chattr(struct inode *inode, struct IATTR *attr)
|
||||
{
|
||||
unsigned int valid;
|
||||
mode_t tmp_mode;
|
||||
uint c_uid = OsCurrUserGet()->effUserID;
|
||||
uint c_gid = OsCurrUserGet()->effGid;
|
||||
valid = attr->attr_chg_valid;
|
||||
inode_semtake();
|
||||
|
||||
tmp_mode = inode->i_mode;
|
||||
if (valid & CHG_UID) {
|
||||
if (((c_uid != inode->i_uid) || (attr->attr_chg_uid != inode->i_uid)) && (!IsCapPermit(CAP_CHOWN))) {
|
||||
inode_semgive();
|
||||
return -EPERM;
|
||||
} else {
|
||||
inode->i_uid = attr->attr_chg_uid;
|
||||
}
|
||||
}
|
||||
|
||||
if (valid & CHG_GID) {
|
||||
if (((c_gid != inode->i_gid) || (attr->attr_chg_gid != inode->i_gid)) && (!IsCapPermit(CAP_CHOWN))) {
|
||||
inode_semgive();
|
||||
return -EPERM;
|
||||
} else {
|
||||
inode->i_gid = attr->attr_chg_gid;
|
||||
}
|
||||
}
|
||||
|
||||
if (valid & CHG_MODE) {
|
||||
if (!IsCapPermit(CAP_FOWNER) && (c_uid != inode->i_uid)) {
|
||||
inode_semgive();
|
||||
return -EPERM;
|
||||
} else {
|
||||
attr->attr_chg_mode &= ~S_IFMT; /* delete file type */
|
||||
tmp_mode &= S_IFMT;
|
||||
tmp_mode = attr->attr_chg_mode | tmp_mode; /* add old file type */
|
||||
}
|
||||
}
|
||||
inode->i_mode = tmp_mode;
|
||||
inode_semgive();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: chattr
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero on success; -1 on failure with errno set:
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int chattr(const char *pathname, struct IATTR *attr)
|
||||
{
|
||||
struct inode *inode = NULL;
|
||||
const char *relpath = NULL;
|
||||
int error;
|
||||
int ret;
|
||||
char *fullpath = NULL;
|
||||
char *relativepath = NULL;
|
||||
int dirfd = AT_FDCWD;
|
||||
struct stat statBuff;
|
||||
struct inode_search_s desc;
|
||||
|
||||
if (pathname == NULL || attr == NULL) {
|
||||
set_errno(EINVAL);
|
||||
return VFS_ERROR;
|
||||
}
|
||||
|
||||
ret = get_path_from_fd(dirfd, &relativepath); /* Get absolute path by dirfd */
|
||||
if (ret < 0) {
|
||||
error = -ret;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
ret = vfs_normalize_path((const char *)relativepath, pathname, &fullpath);
|
||||
if (relativepath) {
|
||||
free(relativepath);
|
||||
}
|
||||
|
||||
if (ret < 0) {
|
||||
error = -ret;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
ret = stat(fullpath, &statBuff);
|
||||
if (ret < 0) {
|
||||
free(fullpath);
|
||||
return VFS_ERROR;
|
||||
}
|
||||
|
||||
SETUP_SEARCH(&desc, fullpath, false);
|
||||
ret = inode_find(&desc);
|
||||
if (ret < 0) {
|
||||
error = EACCES;
|
||||
free(fullpath);
|
||||
goto errout;
|
||||
}
|
||||
inode = desc.node;
|
||||
relpath = desc.relpath;
|
||||
|
||||
if (inode) {
|
||||
#ifndef CONFIG_DISABLE_MOUNTPOINT /* Check inode is not mount and has i_ops or like /dev dir */
|
||||
if ((!INODE_IS_MOUNTPT(inode)) && ((inode->u.i_ops != NULL) || S_ISDIR(statBuff.st_mode))) {
|
||||
ret = pseudo_chattr(inode, attr);
|
||||
if (ret < 0) {
|
||||
error = -ret;
|
||||
goto err_free_inode;
|
||||
}
|
||||
} else if (INODE_IS_MOUNTPT(inode) && (inode->u.i_mops->chattr)) /* Inode is match the relpath */
|
||||
{
|
||||
if (!strlen(relpath)) {
|
||||
error = EEXIST;
|
||||
goto err_free_inode;
|
||||
}
|
||||
|
||||
ret = inode->u.i_mops->chattr(inode, relpath, attr);
|
||||
if (ret < 0) {
|
||||
error = -ret;
|
||||
goto err_free_inode;
|
||||
}
|
||||
} else {
|
||||
error = ENOSYS;
|
||||
goto err_free_inode;
|
||||
}
|
||||
inode_release(inode); /* Release inode */
|
||||
#else
|
||||
error = EEXIST;
|
||||
goto err_free_inode;
|
||||
#endif
|
||||
} else {
|
||||
error = ENXIO;
|
||||
free(fullpath);
|
||||
goto errout;
|
||||
}
|
||||
|
||||
free(fullpath);
|
||||
return OK;
|
||||
|
||||
err_free_inode:
|
||||
inode_release(inode);
|
||||
free(fullpath);
|
||||
errout:
|
||||
set_errno(error);
|
||||
return VFS_ERROR;
|
||||
}
|
||||
134
fs/vfs/operation/fs_check.c
Executable file
134
fs/vfs/operation/fs_check.c
Executable file
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
|
||||
* Copyright (c) 2020, 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.
|
||||
*/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include "errno.h"
|
||||
#include "stdlib.h"
|
||||
#include "string.h"
|
||||
#include "dirent.h"
|
||||
#include "unistd.h"
|
||||
#include "sys/select.h"
|
||||
#include "sys/stat.h"
|
||||
#include "sys/prctl.h"
|
||||
#include "fs/dirent_fs.h"
|
||||
#include "inode/inode.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Name: fscheck
|
||||
****************************************************************************/
|
||||
FAR int fscheck(FAR const char *path)
|
||||
{
|
||||
FAR struct inode *inode = NULL;
|
||||
FAR struct fs_dirent_s *dir = NULL;
|
||||
FAR const char *relpath = NULL;
|
||||
int ret;
|
||||
char *fullpath = NULL;
|
||||
char *fullpath_bak = NULL;
|
||||
|
||||
ret = vfs_normalize_path((const char *)NULL, path, &fullpath);
|
||||
if (ret < 0) {
|
||||
ret = -ret;
|
||||
goto errout;
|
||||
}
|
||||
fullpath_bak = fullpath;
|
||||
|
||||
inode_semtake();
|
||||
|
||||
if (!fullpath || *fullpath == 0) {
|
||||
ret = EINVAL;
|
||||
goto errout_with_semaphore;
|
||||
} else {
|
||||
/* We don't know what to do with relative pathes */
|
||||
|
||||
if (*fullpath != '/') {
|
||||
ret = ENOTDIR;
|
||||
goto errout_with_semaphore;
|
||||
}
|
||||
|
||||
/* Find the node matching the path. */
|
||||
|
||||
inode = inode_search((FAR
|
||||
const char **)&fullpath, (FAR struct inode **)NULL, (FAR struct inode **)NULL, &relpath);
|
||||
}
|
||||
|
||||
if (!inode) {
|
||||
/* 'path' is not a directory.*/
|
||||
|
||||
ret = ENOTDIR;
|
||||
goto errout_with_semaphore;
|
||||
}
|
||||
|
||||
dir = (FAR struct fs_dirent_s *)zalloc(sizeof(struct fs_dirent_s));
|
||||
if (!dir) {
|
||||
/* Insufficient memory to complete the operation.*/
|
||||
|
||||
ret = ENOMEM;
|
||||
goto errout_with_semaphore;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_DISABLE_MOUNTPOINT
|
||||
if (INODE_IS_MOUNTPT(inode)) {
|
||||
if (!inode->u.i_mops || !inode->u.i_mops->fscheck) {
|
||||
ret = ENOSYS;
|
||||
goto errout_with_direntry;
|
||||
}
|
||||
|
||||
/* Perform the fscheck() operation */
|
||||
|
||||
ret = inode->u.i_mops->fscheck(inode, relpath, dir);
|
||||
if (ret != OK) {
|
||||
ret = -ret;
|
||||
goto errout_with_direntry;
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
ret = EINVAL;
|
||||
goto errout_with_direntry;
|
||||
}
|
||||
inode_semgive();
|
||||
free(dir);
|
||||
free(fullpath_bak);
|
||||
return 0;
|
||||
|
||||
errout_with_direntry:
|
||||
free(dir);
|
||||
|
||||
errout_with_semaphore:
|
||||
inode_semgive();
|
||||
free(fullpath_bak);
|
||||
errout:
|
||||
set_errno(ret);
|
||||
return -1;
|
||||
}
|
||||
149
fs/vfs/operation/fs_fallocate.c
Executable file
149
fs/vfs/operation/fs_fallocate.c
Executable file
@@ -0,0 +1,149 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
|
||||
* Copyright (c) 2020, 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.
|
||||
*/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include "vfs_config.h"
|
||||
#include "sys/types.h"
|
||||
#include "assert.h"
|
||||
#include "errno.h"
|
||||
#include "fcntl.h"
|
||||
#include "sched.h"
|
||||
#include "unistd.h"
|
||||
|
||||
#include "inode/inode.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Name: file_fallocate
|
||||
****************************************************************************/
|
||||
|
||||
static ssize_t file_fallocate(FAR struct file *filep, int mode, off_t offset, off_t len)
|
||||
{
|
||||
FAR struct inode *inode = NULL;
|
||||
int ret;
|
||||
int err;
|
||||
|
||||
if (len <= 0) {
|
||||
err = EINVAL;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* Was this file opened for write access? */
|
||||
|
||||
if (((unsigned int)(filep->f_oflags) & O_ACCMODE) == O_RDONLY) {
|
||||
err = EACCES;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* Is a driver registered? Does it support the fallocate method? */
|
||||
|
||||
inode = filep->f_inode;
|
||||
if (!inode || !inode->u.i_mops || !inode->u.i_mops->fallocate) {
|
||||
err = EBADF;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* Yes, then let the driver perform the fallocate */
|
||||
|
||||
ret = inode->u.i_mops->fallocate(filep, mode, offset, len);
|
||||
if (ret < 0) {
|
||||
err = -ret;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
errout:
|
||||
set_errno(err);
|
||||
return VFS_ERROR;
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
* Name: fallocate
|
||||
*
|
||||
* Description:
|
||||
* The fallocate() function prepares or allocates a contiguous data area to the file.
|
||||
* Thus the write file is guaranteed be contiguous and no allocation delay until the
|
||||
* size reaches that size at least unless any other changes to the volume is performed.
|
||||
*
|
||||
* Parameters:
|
||||
* fp Pointer to the open file object.
|
||||
* mode Operation mode. only support FALLOC_FL_KEEP_SIZE.
|
||||
* offset offset of the file to allocated.
|
||||
* len The size to allocate for the file.
|
||||
*
|
||||
* Returned Value:
|
||||
* On success, allocate contiguous data area to the file . On error, -1 is returned, and errno is set appro-
|
||||
* priately:
|
||||
*
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
int fallocate(int fd, int mode, off_t offset, off_t len)
|
||||
{
|
||||
#if CONFIG_NFILE_DESCRIPTORS > 0
|
||||
FAR struct file *filep = NULL;
|
||||
#endif
|
||||
|
||||
/* Did we get a valid file descriptor? */
|
||||
|
||||
#if CONFIG_NFILE_DESCRIPTORS > 0
|
||||
if ((unsigned int)fd >= CONFIG_NFILE_DESCRIPTORS)
|
||||
#endif
|
||||
{
|
||||
set_errno(EBADF);
|
||||
return VFS_ERROR;
|
||||
}
|
||||
|
||||
#if CONFIG_NFILE_DESCRIPTORS > 0
|
||||
|
||||
/* The descriptor is in the right range to be a file descriptor... write to the file.*/
|
||||
|
||||
int ret = fs_getfilep(fd, &filep);
|
||||
if (ret < 0)
|
||||
{
|
||||
/* The errno value has already been set */
|
||||
return VFS_ERROR;
|
||||
}
|
||||
|
||||
if (filep->f_oflags & O_DIRECTORY)
|
||||
{
|
||||
set_errno(EBADF);
|
||||
return VFS_ERROR;
|
||||
}
|
||||
|
||||
/* Perform the fallocate operation using the file descriptor as an index */
|
||||
|
||||
return file_fallocate(filep, mode, offset, len);
|
||||
#endif
|
||||
}
|
||||
152
fs/vfs/operation/fs_fallocate64.c
Executable file
152
fs/vfs/operation/fs_fallocate64.c
Executable file
@@ -0,0 +1,152 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
|
||||
* Copyright (c) 2020, 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.
|
||||
*/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include "vfs_config.h"
|
||||
#include "sys/types.h"
|
||||
#include "assert.h"
|
||||
#include "errno.h"
|
||||
#include "fcntl.h"
|
||||
#include "sched.h"
|
||||
#include "unistd.h"
|
||||
|
||||
#include "inode/inode.h"
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
* Name: file_fallocate
|
||||
****************************************************************************/
|
||||
|
||||
ssize_t file_fallocate64(FAR struct file *filep, int mode, off64_t offset, off64_t len)
|
||||
{
|
||||
FAR struct inode *inode = NULL;
|
||||
int ret;
|
||||
int err;
|
||||
|
||||
if (len <= 0) {
|
||||
err = EINVAL;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* Was this file opened for write access? */
|
||||
|
||||
if (((unsigned int)(filep->f_oflags) & O_ACCMODE) == O_RDONLY) {
|
||||
err = EACCES;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* Is a driver registered? Does it support the fallocate method? */
|
||||
|
||||
inode = filep->f_inode;
|
||||
if (!inode || !inode->u.i_mops || !inode->u.i_mops->fallocate64) {
|
||||
err = EBADF;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* Yes, then let the driver perform the fallocate */
|
||||
|
||||
ret = inode->u.i_mops->fallocate64(filep, mode, offset, len);
|
||||
if (ret < 0) {
|
||||
err = -ret;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
errout:
|
||||
set_errno(err);
|
||||
return VFS_ERROR;
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
* Name: fallocate
|
||||
*
|
||||
* Description:
|
||||
* The fallocate() function prepares or allocates a contiguous data area to the file.
|
||||
* Thus the write file is guaranteed be contiguous and no allocation delay until the
|
||||
* size reaches that size at least unless any other changes to the volume is performed.
|
||||
*
|
||||
* Parameters:
|
||||
* fp Pointer to the open file object.
|
||||
* mode Operation mode. only support FALLOC_FL_KEEP_SIZE.
|
||||
* offset offset of the file to allocated.
|
||||
* len The size to allocate for the file.
|
||||
*
|
||||
* Returned Value:
|
||||
* On success, allocate contiguous data area to the file . On error, -1 is returned, and errno is set appro-
|
||||
* priately:
|
||||
*
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
int fallocate64(int fd, int mode, off64_t offset, off64_t len)
|
||||
{
|
||||
#if CONFIG_NFILE_DESCRIPTORS > 0
|
||||
FAR struct file *filep = NULL;
|
||||
#endif
|
||||
|
||||
/* Did we get a valid file descriptor? */
|
||||
|
||||
#if CONFIG_NFILE_DESCRIPTORS > 0
|
||||
if ((unsigned int)fd >= CONFIG_NFILE_DESCRIPTORS)
|
||||
#endif
|
||||
{
|
||||
set_errno(EBADF);
|
||||
return VFS_ERROR;
|
||||
}
|
||||
|
||||
#if CONFIG_NFILE_DESCRIPTORS > 0
|
||||
|
||||
/* The descriptor is in the right range to be a file descriptor... write
|
||||
* to the file.
|
||||
*/
|
||||
|
||||
int ret = fs_getfilep(fd, &filep);
|
||||
if (ret < 0)
|
||||
{
|
||||
/* The errno value has already been set */
|
||||
return VFS_ERROR;
|
||||
}
|
||||
|
||||
if (filep->f_oflags & O_DIRECTORY)
|
||||
{
|
||||
set_errno(EBADF);
|
||||
return VFS_ERROR;
|
||||
}
|
||||
|
||||
/* Perform the fallocate operation using the file descriptor as an index */
|
||||
|
||||
return file_fallocate64(filep, mode, offset, len);
|
||||
#endif
|
||||
}
|
||||
300
fs/vfs/operation/fs_file.c
Executable file
300
fs/vfs/operation/fs_file.c
Executable file
@@ -0,0 +1,300 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
|
||||
* Copyright (c) 2020, 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 "fs_file.h"
|
||||
#include "los_process_pri.h"
|
||||
#include "fs/fd_table.h"
|
||||
#include "fs/file.h"
|
||||
#include "fs/fs.h"
|
||||
|
||||
static void FileTableLock(struct fd_table_s *fdt)
|
||||
{
|
||||
/* Take the semaphore (perhaps waiting) */
|
||||
while (sem_wait(&fdt->ft_sem) != 0) {
|
||||
/*
|
||||
* The only case that an error should occur here is if the wait was
|
||||
* awakened by a signal.
|
||||
*/
|
||||
LOS_ASSERT(get_errno() == EINTR);
|
||||
}
|
||||
}
|
||||
|
||||
static void FileTableUnLock(struct fd_table_s *fdt)
|
||||
{
|
||||
int ret = sem_post(&fdt->ft_sem);
|
||||
if (ret == -1) {
|
||||
PRINTK("sem_post error, errno %d \n", get_errno());
|
||||
}
|
||||
}
|
||||
|
||||
static int AssignProcessFd(const struct fd_table_s *fdt, int minFd)
|
||||
{
|
||||
if (fdt == NULL) {
|
||||
return VFS_ERROR;
|
||||
}
|
||||
|
||||
/* search unused fd from table */
|
||||
for (int i = minFd; i < fdt->max_fds; i++) {
|
||||
if (!FD_ISSET(i, fdt->proc_fds)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return VFS_ERROR;
|
||||
}
|
||||
|
||||
static struct fd_table_s *GetFdTable(void)
|
||||
{
|
||||
struct fd_table_s *fdt = NULL;
|
||||
struct files_struct *procFiles = OsCurrProcessGet()->files;
|
||||
|
||||
if (procFiles == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fdt = procFiles->fdt;
|
||||
if ((fdt == NULL) || (fdt->ft_fds == NULL)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return fdt;
|
||||
}
|
||||
|
||||
static bool IsValidProcessFd(struct fd_table_s *fdt, int procFd)
|
||||
{
|
||||
if (fdt == NULL) {
|
||||
return false;
|
||||
}
|
||||
if ((procFd < 0) || (procFd >= fdt->max_fds)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void AssociateSystemFd(int procFd, int sysFd)
|
||||
{
|
||||
struct fd_table_s *fdt = GetFdTable();
|
||||
|
||||
if (!IsValidProcessFd(fdt, procFd)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (sysFd < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
FileTableLock(fdt);
|
||||
fdt->ft_fds[procFd].sysFd = sysFd;
|
||||
FileTableUnLock(fdt);
|
||||
}
|
||||
|
||||
int CheckProcessFd(int procFd)
|
||||
{
|
||||
struct fd_table_s *fdt = GetFdTable();
|
||||
|
||||
if (!IsValidProcessFd(fdt, procFd)) {
|
||||
return VFS_ERROR;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int GetAssociatedSystemFd(int procFd)
|
||||
{
|
||||
struct fd_table_s *fdt = GetFdTable();
|
||||
|
||||
if (!IsValidProcessFd(fdt, procFd)) {
|
||||
return VFS_ERROR;
|
||||
}
|
||||
|
||||
FileTableLock(fdt);
|
||||
if (fdt->ft_fds[procFd].sysFd < 0) {
|
||||
FileTableUnLock(fdt);
|
||||
return VFS_ERROR;
|
||||
}
|
||||
int sysFd = fdt->ft_fds[procFd].sysFd;
|
||||
FileTableUnLock(fdt);
|
||||
|
||||
return sysFd;
|
||||
}
|
||||
|
||||
/* Occupy the procFd, there are three circumstances:
|
||||
* 1.procFd is already associated, we need disassociate procFd with relevant sysfd.
|
||||
* 2.procFd is not allocated, we occupy it immediately.
|
||||
* 3.procFd is in open(), close(), dup() process, we return EBUSY immediately.
|
||||
*/
|
||||
int AllocSpecifiedProcessFd(int procFd)
|
||||
{
|
||||
struct fd_table_s *fdt = GetFdTable();
|
||||
|
||||
if (!IsValidProcessFd(fdt, procFd)) {
|
||||
return -EBADF;
|
||||
}
|
||||
|
||||
FileTableLock(fdt);
|
||||
if (fdt->ft_fds[procFd].sysFd >= 0) {
|
||||
/* Disassociate procFd */
|
||||
fdt->ft_fds[procFd].sysFd = -1;
|
||||
FileTableUnLock(fdt);
|
||||
return OK;
|
||||
}
|
||||
|
||||
if (FD_ISSET(procFd, fdt->proc_fds)) {
|
||||
/* procFd in race condition */
|
||||
FileTableUnLock(fdt);
|
||||
return -EBUSY;
|
||||
} else {
|
||||
/* Unused procFd */
|
||||
FD_SET(procFd, fdt->proc_fds);
|
||||
}
|
||||
|
||||
FileTableUnLock(fdt);
|
||||
return OK;
|
||||
}
|
||||
|
||||
void FreeProcessFd(int procFd)
|
||||
{
|
||||
struct fd_table_s *fdt = GetFdTable();
|
||||
|
||||
if (!IsValidProcessFd(fdt, procFd)) {
|
||||
return;
|
||||
}
|
||||
|
||||
FileTableLock(fdt);
|
||||
FD_CLR(procFd, fdt->proc_fds);
|
||||
fdt->ft_fds[procFd].sysFd = -1;
|
||||
FileTableUnLock(fdt);
|
||||
}
|
||||
|
||||
int DisassociateProcessFd(int procFd)
|
||||
{
|
||||
struct fd_table_s *fdt = GetFdTable();
|
||||
|
||||
if (!IsValidProcessFd(fdt, procFd)) {
|
||||
return VFS_ERROR;
|
||||
}
|
||||
|
||||
FileTableLock(fdt);
|
||||
if (fdt->ft_fds[procFd].sysFd < 0) {
|
||||
FileTableUnLock(fdt);
|
||||
return VFS_ERROR;
|
||||
}
|
||||
int sysFd = fdt->ft_fds[procFd].sysFd;
|
||||
if (procFd >= MIN_START_FD) {
|
||||
fdt->ft_fds[procFd].sysFd = -1;
|
||||
}
|
||||
FileTableUnLock(fdt);
|
||||
|
||||
return sysFd;
|
||||
}
|
||||
|
||||
int AllocProcessFd(void)
|
||||
{
|
||||
return AllocLowestProcessFd(MIN_START_FD);
|
||||
}
|
||||
|
||||
int AllocLowestProcessFd(int minFd)
|
||||
{
|
||||
struct fd_table_s *fdt = GetFdTable();
|
||||
|
||||
if (fdt == NULL) {
|
||||
return VFS_ERROR;
|
||||
}
|
||||
|
||||
/* minFd should be a positive number,and 0,1,2 had be distributed to stdin,stdout,stderr */
|
||||
if (minFd < MIN_START_FD) {
|
||||
minFd = MIN_START_FD;
|
||||
}
|
||||
|
||||
FileTableLock(fdt);
|
||||
|
||||
int procFd = AssignProcessFd(fdt, minFd);
|
||||
if (procFd == VFS_ERROR) {
|
||||
FileTableUnLock(fdt);
|
||||
return VFS_ERROR;
|
||||
}
|
||||
|
||||
// occupy the fd set
|
||||
FD_SET(procFd, fdt->proc_fds);
|
||||
FileTableUnLock(fdt);
|
||||
|
||||
return procFd;
|
||||
}
|
||||
|
||||
int AllocAndAssocProcessFd(int sysFd, int minFd)
|
||||
{
|
||||
struct fd_table_s *fdt = GetFdTable();
|
||||
|
||||
if (fdt == NULL) {
|
||||
return VFS_ERROR;
|
||||
}
|
||||
|
||||
/* minFd should be a positive number,and 0,1,2 had be distributed to stdin,stdout,stderr */
|
||||
if (minFd < MIN_START_FD) {
|
||||
minFd = MIN_START_FD;
|
||||
}
|
||||
|
||||
FileTableLock(fdt);
|
||||
|
||||
int procFd = AssignProcessFd(fdt, minFd);
|
||||
if (procFd == VFS_ERROR) {
|
||||
FileTableUnLock(fdt);
|
||||
return VFS_ERROR;
|
||||
}
|
||||
|
||||
// occupy the fd set
|
||||
FD_SET(procFd, fdt->proc_fds);
|
||||
fdt->ft_fds[procFd].sysFd = sysFd;
|
||||
FileTableUnLock(fdt);
|
||||
|
||||
return procFd;
|
||||
}
|
||||
|
||||
int AllocAndAssocSystemFd(int procFd, int minFd)
|
||||
{
|
||||
struct fd_table_s *fdt = GetFdTable();
|
||||
|
||||
if (!IsValidProcessFd(fdt, procFd)) {
|
||||
return VFS_ERROR;
|
||||
}
|
||||
|
||||
int sysFd = alloc_fd(minFd);
|
||||
if (sysFd < 0) {
|
||||
return VFS_ERROR;
|
||||
}
|
||||
|
||||
FileTableLock(fdt);
|
||||
fdt->ft_fds[procFd].sysFd = sysFd;
|
||||
FileTableUnLock(fdt);
|
||||
|
||||
return sysFd;
|
||||
}
|
||||
|
||||
314
fs/vfs/operation/fs_file_mapping.c
Executable file
314
fs/vfs/operation/fs_file_mapping.c
Executable file
@@ -0,0 +1,314 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
|
||||
* Copyright (c) 2020, 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 "fs/fs.h"
|
||||
#include "fs/fs_operation.h"
|
||||
#include "fs_other.h"
|
||||
#include "unistd.h"
|
||||
#include "los_mux.h"
|
||||
#include "los_list.h"
|
||||
#include "los_atomic.h"
|
||||
#include "los_vm_filemap.h"
|
||||
|
||||
static struct file_map g_file_mapping = {0};
|
||||
|
||||
uint init_file_mapping()
|
||||
{
|
||||
uint ret;
|
||||
|
||||
LOS_ListInit(&g_file_mapping.head);
|
||||
|
||||
ret = LOS_MuxInit(&g_file_mapping.lock, NULL);
|
||||
if (ret != LOS_OK) {
|
||||
PRINT_ERR("Create mutex for file map of page cache failed, (ret=%u)\n", ret);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct page_mapping *find_mapping_nolock(const char *fullpath)
|
||||
{
|
||||
struct file_map *fmap = NULL;
|
||||
|
||||
LOS_DL_LIST_FOR_EACH_ENTRY(fmap, &g_file_mapping.head, struct file_map, head) {
|
||||
if (!strcmp(fmap->owner, fullpath)) {
|
||||
return &fmap->mapping;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void add_mapping(struct file *filep, const char *fullpath)
|
||||
{
|
||||
void *tmp = NULL;
|
||||
struct file_map *fmap = NULL;
|
||||
int fmap_len = sizeof(struct file_map);
|
||||
int path_len;
|
||||
struct page_mapping *mapping = NULL;
|
||||
status_t retval;
|
||||
|
||||
if (filep == NULL || fullpath == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
(VOID)LOS_MuxLock(&g_file_mapping.lock, LOS_WAIT_FOREVER);
|
||||
|
||||
path_len = strlen(fullpath) + 1;
|
||||
mapping = find_mapping_nolock(fullpath);
|
||||
if (mapping) {
|
||||
LOS_AtomicInc(&mapping->ref);
|
||||
filep->f_mapping = mapping;
|
||||
mapping->host = filep;
|
||||
(VOID)LOS_MuxUnlock(&g_file_mapping.lock);
|
||||
return;
|
||||
}
|
||||
|
||||
(VOID)LOS_MuxUnlock(&g_file_mapping.lock);
|
||||
|
||||
fmap = (struct file_map *)LOS_MemAlloc(m_aucSysMem0, fmap_len);
|
||||
|
||||
/* page-cache as a optimization feature, just return when out of memory */
|
||||
|
||||
if (!fmap) {
|
||||
PRINT_WARN("%s-%d: Mem alloc failed. fmap length(%d)\n",
|
||||
__FUNCTION__, __LINE__, fmap_len);
|
||||
return;
|
||||
}
|
||||
tmp = LOS_MemAlloc(m_aucSysMem0, path_len);
|
||||
|
||||
/* page-cache as a optimization feature, just return when out of memory */
|
||||
|
||||
if (!tmp) {
|
||||
PRINT_WARN("%s-%d: Mem alloc failed. fmap length(%d), fmap(%p), path length(%d)\n",
|
||||
__FUNCTION__, __LINE__, fmap_len, fmap, path_len);
|
||||
LOS_MemFree(m_aucSysMem0, fmap);
|
||||
return;
|
||||
}
|
||||
|
||||
(void)memset_s(fmap, fmap_len, 0, fmap_len);
|
||||
fmap->owner = tmp;
|
||||
LOS_AtomicSet(&fmap->mapping.ref, 1);
|
||||
(void)strcpy_s(fmap->owner, path_len, fullpath);
|
||||
|
||||
LOS_ListInit(&fmap->mapping.page_list);
|
||||
LOS_SpinInit(&fmap->mapping.list_lock);
|
||||
retval = LOS_MuxInit(&fmap->mapping.mux_lock, NULL);
|
||||
if (retval != LOS_OK) {
|
||||
PRINT_ERR("%s %d, Create mutex for mapping.mux_lock failed, status: %d\n", __FUNCTION__, __LINE__, retval);
|
||||
}
|
||||
(VOID)LOS_MuxLock(&g_file_mapping.lock, LOS_WAIT_FOREVER);
|
||||
LOS_ListTailInsert(&g_file_mapping.head, &fmap->head);
|
||||
(VOID)LOS_MuxUnlock(&g_file_mapping.lock);
|
||||
|
||||
filep->f_mapping = &fmap->mapping;
|
||||
filep->f_mapping->host = filep;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
struct page_mapping *find_mapping(const char *fullpath)
|
||||
{
|
||||
struct page_mapping *mapping = NULL;
|
||||
|
||||
if (fullpath == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
(VOID)LOS_MuxLock(&g_file_mapping.lock, LOS_WAIT_FOREVER);
|
||||
|
||||
mapping = find_mapping_nolock(fullpath);
|
||||
if (mapping) {
|
||||
LOS_AtomicInc(&mapping->ref);
|
||||
}
|
||||
|
||||
(VOID)LOS_MuxUnlock(&g_file_mapping.lock);
|
||||
|
||||
return mapping;
|
||||
}
|
||||
|
||||
void dec_mapping(struct page_mapping *mapping)
|
||||
{
|
||||
if (mapping == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
(VOID)LOS_MuxLock(&g_file_mapping.lock, LOS_WAIT_FOREVER);
|
||||
if (LOS_AtomicRead(&mapping->ref) > 0) {
|
||||
LOS_AtomicDec(&mapping->ref);
|
||||
}
|
||||
(VOID)LOS_MuxUnlock(&g_file_mapping.lock);
|
||||
}
|
||||
|
||||
void clear_file_mapping_nolock(const struct page_mapping *mapping)
|
||||
{
|
||||
unsigned int i = 3; /* file start fd */
|
||||
struct file *filp = NULL;
|
||||
|
||||
while (i < CONFIG_NFILE_DESCRIPTORS) {
|
||||
filp = &tg_filelist.fl_files[i];
|
||||
if (filp->f_mapping == mapping) {
|
||||
filp->f_mapping = NULL;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
int remove_mapping_nolock(const char *fullpath, const struct file *ex_filp)
|
||||
{
|
||||
int fd;
|
||||
struct file *filp = NULL;
|
||||
struct file_map *fmap = NULL;
|
||||
struct page_mapping *mapping = NULL;
|
||||
struct inode *node = NULL;
|
||||
|
||||
if (fullpath == NULL) {
|
||||
set_errno(EINVAL);
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
/* file start fd */
|
||||
|
||||
for (fd = 3; fd < CONFIG_NFILE_DESCRIPTORS; fd++) {
|
||||
node = files_get_openfile(fd);
|
||||
if (node == NULL) {
|
||||
continue;
|
||||
}
|
||||
filp = &tg_filelist.fl_files[fd];
|
||||
|
||||
/* ex_filp NULL: do not exclude any file, just matching the file name ; ex_filp not NULL: exclude it.
|
||||
* filp != ex_filp includes the two scenarios.
|
||||
*/
|
||||
|
||||
if (filp != ex_filp) {
|
||||
if (filp->f_path == NULL) {
|
||||
continue;
|
||||
}
|
||||
if ((strcmp(filp->f_path, fullpath) == 0)) {
|
||||
PRINT_WARN("%s is open(fd=%d), remove cache failed.\n", fullpath, fd);
|
||||
set_errno(EBUSY);
|
||||
return EBUSY;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
(VOID)LOS_MuxLock(&g_file_mapping.lock, LOS_WAIT_FOREVER);
|
||||
|
||||
mapping = find_mapping_nolock(fullpath);
|
||||
if (!mapping) {
|
||||
/* this scenario is a normal case */
|
||||
|
||||
goto out;
|
||||
}
|
||||
|
||||
(VOID)LOS_MuxDestroy(&mapping->mux_lock);
|
||||
clear_file_mapping_nolock(mapping);
|
||||
OsFileCacheRemove(mapping);
|
||||
fmap = LOS_DL_LIST_ENTRY(mapping,
|
||||
struct file_map, mapping);
|
||||
LOS_ListDelete(&fmap->head);
|
||||
LOS_MemFree(m_aucSysMem0, fmap);
|
||||
|
||||
out:
|
||||
(VOID)LOS_MuxUnlock(&g_file_mapping.lock);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int remove_mapping(const char *fullpath, const struct file *ex_filp)
|
||||
{
|
||||
int ret;
|
||||
struct filelist *f_list = NULL;
|
||||
|
||||
f_list = &tg_filelist;
|
||||
ret = sem_wait(&f_list->fl_sem);
|
||||
if (ret < 0) {
|
||||
PRINTK("sem_wait error, ret=%d\n", ret);
|
||||
return VFS_ERROR;
|
||||
}
|
||||
|
||||
ret = remove_mapping_nolock(fullpath, ex_filp);
|
||||
|
||||
(void)sem_post(&f_list->fl_sem);
|
||||
return OK;
|
||||
}
|
||||
|
||||
void rename_mapping(const char *src_path, const char *dst_path)
|
||||
{
|
||||
int ret;
|
||||
void *tmp = NULL;
|
||||
int path_len;
|
||||
struct file_map *fmap = NULL;
|
||||
struct page_mapping *mapping = NULL;
|
||||
|
||||
if (src_path == NULL || dst_path == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
path_len = strlen(dst_path) + 1;
|
||||
|
||||
/* protect the whole list in case of this node been deleted just after we found it */
|
||||
|
||||
(VOID)LOS_MuxLock(&g_file_mapping.lock, LOS_WAIT_FOREVER);
|
||||
|
||||
mapping = find_mapping_nolock(src_path);
|
||||
if (!mapping) {
|
||||
/* this scenario is a normal case */
|
||||
|
||||
goto out;
|
||||
}
|
||||
|
||||
fmap = LOS_DL_LIST_ENTRY(mapping,
|
||||
struct file_map, mapping);
|
||||
|
||||
tmp = LOS_MemAlloc(m_aucSysMem0, path_len);
|
||||
if (!tmp) {
|
||||
/* in this extremly low-memory situation, un-referenced page caches can be recycled by Pagecache LRU */
|
||||
|
||||
PRINT_ERR("%s-%d: Mem alloc failed, path length(%d)\n", __FUNCTION__, __LINE__, path_len);
|
||||
goto out;
|
||||
}
|
||||
ret = strcpy_s(tmp, path_len, dst_path);
|
||||
if (ret != 0) {
|
||||
(VOID)LOS_MemFree(m_aucSysMem0, tmp);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* whole list is locked, so we don't protect this node here */
|
||||
|
||||
(VOID)LOS_MemFree(m_aucSysMem0, fmap->owner);
|
||||
fmap->owner = tmp;
|
||||
|
||||
out:
|
||||
(VOID)LOS_MuxUnlock(&g_file_mapping.lock);
|
||||
return;
|
||||
}
|
||||
|
||||
160
fs/vfs/operation/fs_getlabel.c
Executable file
160
fs/vfs/operation/fs_getlabel.c
Executable file
@@ -0,0 +1,160 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
|
||||
* Copyright (c) 2020, 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.
|
||||
*/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include "vfs_config.h"
|
||||
|
||||
#include "sys/mount.h"
|
||||
#include "errno.h"
|
||||
#include "fs/fs.h"
|
||||
|
||||
#include "inode/inode.h"
|
||||
#include "stdlib.h"
|
||||
|
||||
#include "string.h"
|
||||
#include "disk.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Variables
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Variables
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: getlabel()
|
||||
*
|
||||
* Description:
|
||||
* getlabel() get the volume label of partition(disk) from FAT filesystem by
|
||||
* the 'target' path
|
||||
*
|
||||
* Parameters:
|
||||
* target : the path which is the mount point of FAT filesystem device.
|
||||
* label : the string var pointer, by which passed out label string.
|
||||
*
|
||||
* Return:
|
||||
* Zero is returned on success; -1 is returned on an error and errno is
|
||||
* set appropriately:
|
||||
*
|
||||
* ENOMEM There is no memory for allocated space for var.
|
||||
* EFAULT The pointer 'target' does not pass in corretly.
|
||||
* ENOENT The pointer 'target' pointed to a wrong location.
|
||||
* EPERM The pointer 'target' does not point to a mount inode.
|
||||
* EINVAL The pointer 'label' does not pass in correctly.
|
||||
* EACCES The filesystem which 'target' point to is not supported.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int getlabel(const char *target, char *label)
|
||||
{
|
||||
FAR struct inode *mountpt_inode = NULL;
|
||||
int errcode = OK;
|
||||
int status;
|
||||
char *fullpath = NULL;
|
||||
struct inode_search_s desc;
|
||||
int ret;
|
||||
/* Verify required pointer arguments */
|
||||
|
||||
if (target == NULL || label == NULL) {
|
||||
errcode = EFAULT;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* Get a absolute path */
|
||||
|
||||
errcode = vfs_normalize_path((const char *)NULL, target, &fullpath);
|
||||
if (errcode < 0) {
|
||||
errcode = -errcode;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* Find the mountpt */
|
||||
SETUP_SEARCH(&desc, fullpath, false);
|
||||
ret = inode_find(&desc);
|
||||
if (ret < 0) {
|
||||
errcode = EACCES;
|
||||
goto errout_with_fullpath;
|
||||
}
|
||||
mountpt_inode = desc.node;
|
||||
|
||||
/* Verfy the path is a mountpoint path or file path */
|
||||
|
||||
if (!INODE_IS_MOUNTPT(mountpt_inode) && !INODE_IS_BLOCK(mountpt_inode)) {
|
||||
errcode = EPERM;
|
||||
goto errout_with_release;
|
||||
}
|
||||
|
||||
if (mountpt_inode->u.i_mops && mountpt_inode->u.i_mops->getlabel) {
|
||||
status = mountpt_inode->u.i_mops->getlabel(mountpt_inode->i_private, label);
|
||||
if (status < 0) {
|
||||
/* The inode is unhappy with the blkdrvr for some reason */
|
||||
|
||||
errcode = -status;
|
||||
goto errout_with_release;
|
||||
}
|
||||
inode_release(mountpt_inode);
|
||||
free(fullpath);
|
||||
return OK;
|
||||
} else {
|
||||
errcode = EACCES;
|
||||
goto errout_with_release;
|
||||
}
|
||||
|
||||
/* A lot of goto's! But they make the error handling much simpler */
|
||||
|
||||
errout_with_release:
|
||||
inode_release(mountpt_inode);
|
||||
errout_with_fullpath:
|
||||
free(fullpath);
|
||||
errout:
|
||||
set_errno(errcode);
|
||||
return VFS_ERROR;
|
||||
}
|
||||
75
fs/vfs/operation/fs_init.c
Executable file
75
fs/vfs/operation/fs_init.c
Executable file
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
|
||||
* Copyright (c) 2020, 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 "los_printf.h"
|
||||
#include "fs/fs.h"
|
||||
#include "inode/inode.h"
|
||||
#include "unistd.h"
|
||||
#include "fcntl.h"
|
||||
#include "sys/statfs.h"
|
||||
#include "linux/spinlock.h"
|
||||
#include "disk_pri.h"
|
||||
|
||||
void los_vfs_init(void)
|
||||
{
|
||||
int err;
|
||||
uint retval;
|
||||
static bool g_vfs_init = false;
|
||||
struct inode *dev = NULL;
|
||||
|
||||
if (g_vfs_init) {
|
||||
return;
|
||||
}
|
||||
|
||||
spin_lock_init(&g_diskSpinlock);
|
||||
spin_lock_init(&g_diskFatBlockSpinlock);
|
||||
files_initlist(&tg_filelist);
|
||||
fs_initialize();
|
||||
if ((err = inode_reserve("/", &g_root_inode)) < 0) {
|
||||
PRINT_ERR("los_vfs_init failed error %d\n", -err);
|
||||
return;
|
||||
}
|
||||
g_root_inode->i_mode |= S_IFDIR | S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
|
||||
|
||||
if ((err = inode_reserve("/dev", &dev)) < 0) {
|
||||
PRINT_ERR("los_vfs_init failed error %d\n", -err);
|
||||
return;
|
||||
}
|
||||
dev->i_mode |= S_IFDIR | S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
|
||||
|
||||
retval = init_file_mapping();
|
||||
if (retval != LOS_OK) {
|
||||
PRINT_ERR("Page cache file map init failed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
g_vfs_init = true;
|
||||
}
|
||||
691
fs/vfs/operation/fs_other.c
Executable file
691
fs/vfs/operation/fs_other.c
Executable file
@@ -0,0 +1,691 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
|
||||
* Copyright (c) 2020, 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 "fs_other.h"
|
||||
#include "errno.h"
|
||||
#include "stdlib.h"
|
||||
#include "string.h"
|
||||
#include "dirent.h"
|
||||
#include "unistd.h"
|
||||
#include "sys/select.h"
|
||||
#include "sys/stat.h"
|
||||
#include "sys/prctl.h"
|
||||
#include "fs/fd_table.h"
|
||||
#include "fs/fs.h"
|
||||
#include "linux/spinlock.h"
|
||||
#include "los_process_pri.h"
|
||||
#include "los_task_pri.h"
|
||||
#include "inode/inode.h"
|
||||
#include "capability_api.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#define MAX_DIR_ENT 1024
|
||||
|
||||
int fstat(int fd, struct stat *buf)
|
||||
{
|
||||
struct file *filep = NULL;
|
||||
|
||||
int ret = fs_getfilep(fd, &filep);
|
||||
if (ret < 0) {
|
||||
return VFS_ERROR;
|
||||
}
|
||||
|
||||
return stat(filep->f_path, buf);
|
||||
}
|
||||
|
||||
int fstat64(int fd, struct stat64 *buf)
|
||||
{
|
||||
struct file *filep = NULL;
|
||||
|
||||
int ret = fs_getfilep(fd, &filep);
|
||||
if (ret < 0) {
|
||||
return VFS_ERROR;
|
||||
}
|
||||
|
||||
return stat64(filep->f_path, buf);
|
||||
}
|
||||
|
||||
int lstat(const char *path, struct stat *buffer)
|
||||
{
|
||||
return stat(path, buffer);
|
||||
}
|
||||
|
||||
int VfsPermissionCheck(uint fuid, uint fgid, mode_t fileMode, int accMode)
|
||||
{
|
||||
uint uid = OsCurrUserGet()->effUserID;
|
||||
mode_t tmpMode = fileMode;
|
||||
|
||||
if (uid == fuid) {
|
||||
tmpMode >>= USER_MODE_SHIFT;
|
||||
} else if (LOS_CheckInGroups(fgid)) {
|
||||
tmpMode >>= GROUP_MODE_SHIFT;
|
||||
}
|
||||
|
||||
tmpMode &= (READ_OP | WRITE_OP | EXEC_OP);
|
||||
|
||||
if ((accMode & tmpMode) == accMode) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
tmpMode = 0;
|
||||
if (S_ISDIR(fileMode)) {
|
||||
if ((accMode & EXEC_OP) && (IsCapPermit(CAP_DAC_READ_SEARCH))) {
|
||||
tmpMode |= EXEC_OP;
|
||||
}
|
||||
} else {
|
||||
if ((accMode & EXEC_OP) && (IsCapPermit(CAP_DAC_EXECUTE)) && (fileMode & MODE_IXUGO)) {
|
||||
tmpMode |= EXEC_OP;
|
||||
}
|
||||
}
|
||||
|
||||
if ((accMode & WRITE_OP) && IsCapPermit(CAP_DAC_WRITE)) {
|
||||
tmpMode |= WRITE_OP;
|
||||
}
|
||||
|
||||
if ((accMode & READ_OP) && IsCapPermit(CAP_DAC_READ_SEARCH)) {
|
||||
tmpMode |= READ_OP;
|
||||
}
|
||||
|
||||
if ((accMode & tmpMode) == accMode) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifdef VFS_USING_WORKDIR
|
||||
int SetWorkDir(char *dir, size_t len)
|
||||
{
|
||||
errno_t ret;
|
||||
uint lock_flags;
|
||||
LosProcessCB *curr = OsCurrProcessGet();
|
||||
|
||||
spin_lock_irqsave(&curr->files->workdir_lock, lock_flags);
|
||||
ret = strncpy_s(curr->files->workdir, PATH_MAX, dir, len);
|
||||
curr->files->workdir[PATH_MAX - 1] = '\0';
|
||||
spin_unlock_irqrestore(&curr->files->workdir_lock, lock_flags);
|
||||
if (ret != EOK) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
int chdir(const char *path)
|
||||
{
|
||||
int ret;
|
||||
char *fullpath = NULL;
|
||||
char *fullpath_bak = NULL;
|
||||
struct stat statBuff;
|
||||
|
||||
if (!path) {
|
||||
set_errno(EFAULT);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!strlen(path)) {
|
||||
set_errno(ENOENT);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (strlen(path) > PATH_MAX) {
|
||||
set_errno(ENAMETOOLONG);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = vfs_normalize_path((const char *)NULL, path, &fullpath);
|
||||
if (ret < 0) {
|
||||
set_errno(-ret);
|
||||
return -1; /* build path failed */
|
||||
}
|
||||
fullpath_bak = fullpath;
|
||||
ret = stat(fullpath, &statBuff);
|
||||
if (ret < 0) {
|
||||
free(fullpath_bak);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!S_ISDIR(statBuff.st_mode)) {
|
||||
set_errno(ENOTDIR);
|
||||
free(fullpath_bak);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (VfsPermissionCheck(statBuff.st_uid, statBuff.st_gid, statBuff.st_mode, EXEC_OP)) {
|
||||
set_errno(EACCES);
|
||||
free(fullpath_bak);
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef VFS_USING_WORKDIR
|
||||
ret = SetWorkDir(fullpath, strlen(fullpath));
|
||||
if (ret != 0)
|
||||
{
|
||||
PRINT_ERR("chdir path error!\n");
|
||||
ret = -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* release normalize directory path name */
|
||||
|
||||
free(fullpath_bak);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* this function is a POSIX compliant version, which will return current
|
||||
* working directory.
|
||||
*
|
||||
* @param buf the returned current directory.
|
||||
* @param size the buffer size.
|
||||
*
|
||||
* @return the returned current directory.
|
||||
*/
|
||||
|
||||
char *getcwd(char *buf, size_t n)
|
||||
{
|
||||
#ifdef VFS_USING_WORKDIR
|
||||
int ret;
|
||||
unsigned int len;
|
||||
UINTPTR lock_flags;
|
||||
LosProcessCB *curr = OsCurrProcessGet();
|
||||
#endif
|
||||
if (buf == NULL) {
|
||||
set_errno(EINVAL);
|
||||
return buf;
|
||||
}
|
||||
#ifdef VFS_USING_WORKDIR
|
||||
spin_lock_irqsave(&curr->files->workdir_lock, lock_flags);
|
||||
len = strlen(curr->files->workdir);
|
||||
if (n <= len)
|
||||
{
|
||||
set_errno(ERANGE);
|
||||
spin_unlock_irqrestore(&curr->files->workdir_lock, lock_flags);
|
||||
return NULL;
|
||||
}
|
||||
ret = memcpy_s(buf, n, curr->files->workdir, len + 1);
|
||||
if (ret != EOK)
|
||||
{
|
||||
set_errno(ENAMETOOLONG);
|
||||
spin_unlock_irqrestore(&curr->files->workdir_lock, lock_flags);
|
||||
return NULL;
|
||||
}
|
||||
spin_unlock_irqrestore(&curr->files->workdir_lock, lock_flags);
|
||||
#else
|
||||
PRINT_ERR("NO_WORKING_DIR\n");
|
||||
#endif
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
int chmod(const char *path, mode_t mode)
|
||||
{
|
||||
int result;
|
||||
struct stat buf;
|
||||
|
||||
result = stat(path, &buf);
|
||||
if (result != ENOERR) {
|
||||
return VFS_ERROR;
|
||||
}
|
||||
|
||||
/* no access/permission control for files now, just return OK if stat is okay*/
|
||||
return OK;
|
||||
}
|
||||
|
||||
int access(const char *path, int amode)
|
||||
{
|
||||
int result;
|
||||
struct stat buf;
|
||||
|
||||
result = stat(path, &buf);
|
||||
|
||||
if (result != ENOERR) {
|
||||
return VFS_ERROR;
|
||||
}
|
||||
|
||||
/* no access/permission control for files now, just return OK if stat is okay*/
|
||||
return OK;
|
||||
}
|
||||
|
||||
bool IS_MOUNTPT(const char *dev)
|
||||
{
|
||||
struct inode *node = NULL;
|
||||
bool ret = 0;
|
||||
struct inode_search_s desc;
|
||||
|
||||
SETUP_SEARCH(&desc, dev, false);
|
||||
if (inode_find(&desc) < 0) {
|
||||
return 0;
|
||||
}
|
||||
node = desc.node;
|
||||
|
||||
ret = INODE_IS_MOUNTPT(node);
|
||||
inode_release(node);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct dirent **scandir_get_file_list(const char *dir, int *num, int(*filter)(const struct dirent *))
|
||||
{
|
||||
DIR *od = NULL;
|
||||
int listSize = MAX_DIR_ENT;
|
||||
int n = *num;
|
||||
struct dirent **list = NULL;
|
||||
struct dirent **newList = NULL;
|
||||
struct dirent *ent = NULL;
|
||||
struct dirent *p = NULL;
|
||||
int err;
|
||||
|
||||
od = opendir(dir);
|
||||
if (od == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
list = (struct dirent **)malloc(listSize * sizeof(struct dirent *));
|
||||
if (list == NULL) {
|
||||
(void)closedir(od);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (ent = readdir(od); ent != NULL; ent = readdir(od)) {
|
||||
if (filter && !filter(ent)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (n == listSize) {
|
||||
listSize += MAX_DIR_ENT;
|
||||
newList = (struct dirent **)malloc(listSize * sizeof(struct dirent *));
|
||||
if (newList == NULL) {
|
||||
break;
|
||||
}
|
||||
|
||||
err = memcpy_s(newList, listSize * sizeof(struct dirent *), list, n * sizeof(struct dirent *));
|
||||
if (err != EOK) {
|
||||
free(newList);
|
||||
break;
|
||||
}
|
||||
free(list);
|
||||
list = newList;
|
||||
}
|
||||
|
||||
p = (struct dirent *)malloc(sizeof(struct dirent));
|
||||
if (p == NULL) {
|
||||
break;
|
||||
}
|
||||
|
||||
(void)memcpy_s((void *)p, sizeof(struct dirent), (void *)ent, sizeof(struct dirent));
|
||||
list[n] = p;
|
||||
|
||||
n++;
|
||||
}
|
||||
|
||||
if (closedir(od) < 0) {
|
||||
while (n--) {
|
||||
free(list[n]);
|
||||
}
|
||||
free(list);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
*num = n;
|
||||
return list;
|
||||
}
|
||||
|
||||
int scandir(const char *dir, struct dirent ***namelist,
|
||||
int(*filter)(const struct dirent *),
|
||||
int(*compar)(const struct dirent **,
|
||||
const struct dirent **))
|
||||
{
|
||||
int n = 0;
|
||||
struct dirent **list = NULL;
|
||||
|
||||
if ((dir == NULL) || (namelist == NULL)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
list = scandir_get_file_list(dir, &n, filter);
|
||||
if (list == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Change to return to the array size */
|
||||
|
||||
*namelist = (struct dirent **)malloc(n * sizeof(struct dirent *));
|
||||
if (*namelist == NULL && n > 0) {
|
||||
*namelist = list;
|
||||
} else if (*namelist != NULL) {
|
||||
(void)memcpy_s(*namelist, n * sizeof(struct dirent *), list, n * sizeof(struct dirent *));
|
||||
free(list);
|
||||
} else {
|
||||
free(list);
|
||||
}
|
||||
|
||||
/* Sort array */
|
||||
|
||||
if (compar && *namelist) {
|
||||
qsort((void *)*namelist, (size_t)n, sizeof(struct dirent *), (int (*)(const void *, const void *))*compar);
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
int alphasort(const struct dirent **a, const struct dirent **b)
|
||||
{
|
||||
return strcoll((*a)->d_name, (*b)->d_name);
|
||||
}
|
||||
|
||||
char *rindex(const char *s, int c)
|
||||
{
|
||||
if (s == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Don't bother tracing - strrchr can do that */
|
||||
return (char *)strrchr(s, c);
|
||||
}
|
||||
|
||||
int (*sd_sync_fn)(int) = NULL;
|
||||
|
||||
int (*nand_sync_fn)(void) = NULL;
|
||||
|
||||
void set_sd_sync_fn(int (*sync_fn)(int))
|
||||
{
|
||||
sd_sync_fn = sync_fn;
|
||||
}
|
||||
|
||||
void sync(void)
|
||||
{
|
||||
#ifdef LOSCFG_FS_FAT_CACHE
|
||||
if (sd_sync_fn != NULL)
|
||||
{
|
||||
(void)sd_sync_fn(0);
|
||||
(void)sd_sync_fn(1);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static char *ls_get_fullpath(const char *path, struct dirent *pdirent)
|
||||
{
|
||||
char *fullpath = NULL;
|
||||
int ret = 0;
|
||||
|
||||
if (path[1] != '\0') {
|
||||
/* 2: The position of the path character: / and the end character /0 */
|
||||
|
||||
fullpath = (char *)malloc(strlen(path) + strlen(pdirent->d_name) + 2);
|
||||
if (fullpath == NULL) {
|
||||
goto exit_with_nomem;
|
||||
}
|
||||
|
||||
/* 2: The position of the path character: / and the end character /0 */
|
||||
|
||||
ret = snprintf_s(fullpath, strlen(path) + strlen(pdirent->d_name) + 2,
|
||||
strlen(path) + strlen(pdirent->d_name) + 1, "%s/%s", path, pdirent->d_name);
|
||||
if (ret < 0) {
|
||||
free(fullpath);
|
||||
set_errno(ENAMETOOLONG);
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
/* 2: The position of the path character: / and the end character /0 */
|
||||
|
||||
fullpath = (char *)malloc(strlen(pdirent->d_name) + 2);
|
||||
if (fullpath == NULL) {
|
||||
goto exit_with_nomem;
|
||||
}
|
||||
|
||||
/* 2: The position of the path character: / and the end character /0 */
|
||||
|
||||
ret = snprintf_s(fullpath, strlen(pdirent->d_name) + 2, strlen(pdirent->d_name) + 1,
|
||||
"/%s", pdirent->d_name);
|
||||
if (ret < 0) {
|
||||
free(fullpath);
|
||||
set_errno(ENAMETOOLONG);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return fullpath;
|
||||
|
||||
exit_with_nomem:
|
||||
set_errno(ENOSPC);
|
||||
return (char *)NULL;
|
||||
}
|
||||
|
||||
static void PrintFileInfo64(const struct stat64 *stat64Info, const char *name)
|
||||
{
|
||||
mode_t mode;
|
||||
char str[UGO_NUMS][UGO_NUMS + 1] = {0};
|
||||
char dirFlag;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < UGO_NUMS; i++) {
|
||||
mode = stat64Info->st_mode >> (USER_MODE_SHIFT - i * UGO_NUMS);
|
||||
str[i][0] = (mode & READ_OP) ? 'r' : '-';
|
||||
str[i][1] = (mode & WRITE_OP) ? 'w' : '-';
|
||||
str[i][UGO_NUMS - 1] = (mode & EXEC_OP) ? 'x' : '-';
|
||||
}
|
||||
|
||||
dirFlag = (S_ISDIR(stat64Info->st_mode)) ? 'd' : '-';
|
||||
|
||||
PRINTK("%c%s%s%s %-8lld u:%-5d g:%-5d %-10s\n", dirFlag,
|
||||
str[0], str[1], str[UGO_NUMS - 1], stat64Info->st_size, stat64Info->st_uid, stat64Info->st_gid, name);
|
||||
}
|
||||
|
||||
static void PrintFileInfo(const struct stat *statInfo, const char *name)
|
||||
{
|
||||
mode_t mode;
|
||||
char str[UGO_NUMS][UGO_NUMS + 1] = {0};
|
||||
char dirFlag;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < UGO_NUMS; i++) {
|
||||
mode = statInfo->st_mode >> (USER_MODE_SHIFT - i * UGO_NUMS);
|
||||
str[i][0] = (mode & READ_OP) ? 'r' : '-';
|
||||
str[i][1] = (mode & WRITE_OP) ? 'w' : '-';
|
||||
str[i][UGO_NUMS - 1] = (mode & EXEC_OP) ? 'x' : '-';
|
||||
}
|
||||
|
||||
dirFlag = (S_ISDIR(statInfo->st_mode)) ? 'd' : '-';
|
||||
|
||||
PRINTK("%c%s%s%s %-8lld u:%-5d g:%-5d %-10s\n", dirFlag,
|
||||
str[0], str[1], str[UGO_NUMS - 1], statInfo->st_size, statInfo->st_uid, statInfo->st_gid, name);
|
||||
}
|
||||
|
||||
void ls(const char *pathname)
|
||||
{
|
||||
struct stat64 stat64_info;
|
||||
struct stat stat_info;
|
||||
struct dirent *pdirent = NULL;
|
||||
char *path = NULL;
|
||||
char *fullpath = NULL;
|
||||
char *fullpath_bak = NULL;
|
||||
int ret;
|
||||
DIR *d = NULL;
|
||||
|
||||
if (pathname == NULL) {
|
||||
#ifdef VFS_USING_WORKDIR
|
||||
UINTPTR lock_flags;
|
||||
LosProcessCB *curr = OsCurrProcessGet();
|
||||
|
||||
/* open current working directory */
|
||||
|
||||
spin_lock_irqsave(&curr->files->workdir_lock, lock_flags);
|
||||
path = strdup(curr->files->workdir);
|
||||
spin_unlock_irqrestore(&curr->files->workdir_lock, lock_flags);
|
||||
#else
|
||||
path = strdup("/");
|
||||
#endif
|
||||
if (path == NULL) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
ret = vfs_normalize_path(NULL, pathname, &path);
|
||||
if (ret < 0) {
|
||||
set_errno(-ret);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* list all directory and file*/
|
||||
|
||||
d = opendir(path);
|
||||
if (d == NULL) {
|
||||
perror("ls error");
|
||||
} else {
|
||||
PRINTK("Directory %s:\n", path);
|
||||
do {
|
||||
pdirent = readdir(d);
|
||||
if (pdirent == NULL) {
|
||||
break;
|
||||
} else {
|
||||
if (!strcmp(pdirent->d_name, ".") || !strcmp(pdirent->d_name, "..")) {
|
||||
continue;
|
||||
}
|
||||
(void)memset_s(&stat_info, sizeof(struct stat), 0, sizeof(struct stat));
|
||||
fullpath = ls_get_fullpath(path, pdirent);
|
||||
if (fullpath == NULL) {
|
||||
free(path);
|
||||
(void)closedir(d);
|
||||
return;
|
||||
}
|
||||
|
||||
fullpath_bak = fullpath;
|
||||
if (stat64(fullpath, &stat64_info) == 0) {
|
||||
PrintFileInfo64(&stat64_info, pdirent->d_name);
|
||||
} else if (stat(fullpath, &stat_info) == 0) {
|
||||
PrintFileInfo(&stat_info, pdirent->d_name);
|
||||
} else
|
||||
PRINTK("BAD file: %s\n", pdirent->d_name);
|
||||
free(fullpath_bak);
|
||||
}
|
||||
} while (1);
|
||||
|
||||
(void)closedir(d);
|
||||
}
|
||||
free(path);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
char *realpath(const char *path, char *resolved_path)
|
||||
{
|
||||
int ret, result;
|
||||
char *new_path = NULL;
|
||||
struct stat buf;
|
||||
|
||||
ret = vfs_normalize_path(NULL, path, &new_path);
|
||||
if (ret < 0) {
|
||||
ret = -ret;
|
||||
set_errno(ret);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
result = stat(new_path, &buf);
|
||||
|
||||
if (resolved_path == NULL) {
|
||||
if (result != ENOERR) {
|
||||
free(new_path);
|
||||
return NULL;
|
||||
}
|
||||
return new_path;
|
||||
}
|
||||
|
||||
ret = strcpy_s(resolved_path, PATH_MAX, new_path);
|
||||
if (ret != EOK) {
|
||||
ret = -ret;
|
||||
set_errno(ret);
|
||||
free(new_path);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
free(new_path);
|
||||
if (result != ENOERR) {
|
||||
return NULL;
|
||||
}
|
||||
return resolved_path;
|
||||
}
|
||||
|
||||
void lsfd(void)
|
||||
{
|
||||
FAR struct filelist *f_list = NULL;
|
||||
unsigned int i = 3; /* file start fd */
|
||||
int ret;
|
||||
FAR struct inode *node = NULL;
|
||||
|
||||
f_list = &tg_filelist;
|
||||
|
||||
PRINTK(" fd filename\n");
|
||||
ret = sem_wait(&f_list->fl_sem);
|
||||
if (ret < 0) {
|
||||
PRINTK("sem_wait error, ret=%d\n", ret);
|
||||
return;
|
||||
}
|
||||
|
||||
while (i < CONFIG_NFILE_DESCRIPTORS) {
|
||||
node = files_get_openfile(i);
|
||||
if (node) {
|
||||
PRINTK("%5d %s\n", i, f_list->fl_files[i].f_path);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
(void)sem_post(&f_list->fl_sem);
|
||||
}
|
||||
|
||||
mode_t GetUmask(void)
|
||||
{
|
||||
return OsCurrProcessGet()->umask;
|
||||
}
|
||||
|
||||
mode_t SysUmask(mode_t mask)
|
||||
{
|
||||
UINT32 intSave;
|
||||
mode_t umask;
|
||||
mode_t oldUmask;
|
||||
umask = mask & UMASK_FULL;
|
||||
SCHEDULER_LOCK(intSave);
|
||||
oldUmask = OsCurrProcessGet()->umask;
|
||||
OsCurrProcessGet()->umask = umask;
|
||||
SCHEDULER_UNLOCK(intSave);
|
||||
return oldUmask;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
#endif /* __cplusplus */
|
||||
50
fs/vfs/operation/fs_preadv.c
Executable file
50
fs/vfs/operation/fs_preadv.c
Executable file
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
|
||||
* Copyright (c) 2020, 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.
|
||||
*/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include "sys/types.h"
|
||||
#include "sys/uio.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
ssize_t preadv(int fd, const struct iovec *iov, int iovcnt, off_t offset)
|
||||
{
|
||||
return vfs_readv(fd, iov, iovcnt, &offset);
|
||||
}
|
||||
50
fs/vfs/operation/fs_pwritev.c
Executable file
50
fs/vfs/operation/fs_pwritev.c
Executable file
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
|
||||
* Copyright (c) 2020, 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.
|
||||
*/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include "sys/types.h"
|
||||
#include "sys/uio.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
ssize_t pwritev(int fd, const struct iovec *iov, int iovcnt, off_t offset)
|
||||
{
|
||||
return vfs_writev(fd, iov, iovcnt, &offset);
|
||||
}
|
||||
134
fs/vfs/operation/fs_readv.c
Executable file
134
fs/vfs/operation/fs_readv.c
Executable file
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
|
||||
* Copyright (c) 2020, 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 "sys/types.h"
|
||||
#include "sys/uio.h"
|
||||
#include "unistd.h"
|
||||
#include "string.h"
|
||||
#include "stdlib.h"
|
||||
#include "fs/fs.h"
|
||||
#include "inode/inode.h"
|
||||
#include "user_copy.h"
|
||||
|
||||
static char *pread_buf_and_check(int fd, const struct iovec *iov, int iovcnt, ssize_t *totalbytesread, off_t *offset)
|
||||
{
|
||||
char *buf = NULL;
|
||||
size_t buflen = 0;
|
||||
int i;
|
||||
|
||||
if ((iov == NULL) || (iovcnt > IOV_MAX)) {
|
||||
*totalbytesread = VFS_ERROR;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < iovcnt; ++i) {
|
||||
if (SSIZE_MAX - buflen < iov[i].iov_len) {
|
||||
set_errno(EINVAL);
|
||||
return NULL;
|
||||
}
|
||||
buflen += iov[i].iov_len;
|
||||
}
|
||||
|
||||
if (buflen == 0) {
|
||||
*totalbytesread = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
buf = (char *)LOS_VMalloc(buflen * sizeof(char));
|
||||
if (buf == NULL) {
|
||||
set_errno(ENOMEM);
|
||||
*totalbytesread = VFS_ERROR;
|
||||
return buf;
|
||||
}
|
||||
|
||||
*totalbytesread = (offset == NULL) ? read(fd, buf, buflen)
|
||||
: pread(fd, buf, buflen, *offset);
|
||||
if ((*totalbytesread == VFS_ERROR) || (*totalbytesread == 0)) {
|
||||
LOS_VFree(buf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
ssize_t vfs_readv(int fd, const struct iovec *iov, int iovcnt, off_t *offset)
|
||||
{
|
||||
int i;
|
||||
int ret;
|
||||
char *buf = NULL;
|
||||
char *curbuf = NULL;
|
||||
ssize_t bytestoread;
|
||||
ssize_t totalbytesread = 0;
|
||||
ssize_t bytesleft;
|
||||
|
||||
buf = pread_buf_and_check(fd, iov, iovcnt, &totalbytesread, offset);
|
||||
if (buf == NULL) {
|
||||
return totalbytesread;
|
||||
}
|
||||
|
||||
curbuf = buf;
|
||||
bytesleft = totalbytesread;
|
||||
for (i = 0; i < iovcnt; ++i) {
|
||||
bytestoread = iov[i].iov_len;
|
||||
if (bytestoread == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (bytesleft <= bytestoread) {
|
||||
ret = LOS_CopyFromKernel(iov[i].iov_base, bytesleft, curbuf, bytesleft);
|
||||
bytesleft = ret;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = LOS_CopyFromKernel(iov[i].iov_base, bytestoread, curbuf, bytestoread);
|
||||
if (ret != 0) {
|
||||
bytesleft = bytesleft - (bytestoread - ret);
|
||||
goto out;
|
||||
}
|
||||
bytesleft -= bytestoread;
|
||||
curbuf += bytestoread;
|
||||
}
|
||||
|
||||
out:
|
||||
LOS_VFree(buf);
|
||||
if ((i == 0) && (ret == iov[i].iov_len)) {
|
||||
/* failed in the first iovec copy, and 0 bytes copied */
|
||||
set_errno(EFAULT);
|
||||
return VFS_ERROR;
|
||||
}
|
||||
|
||||
return totalbytesread - bytesleft;
|
||||
}
|
||||
|
||||
ssize_t readv(int fd, const struct iovec *iov, int iovcnt)
|
||||
{
|
||||
return vfs_readv(fd, iov, iovcnt, NULL);
|
||||
}
|
||||
173
fs/vfs/operation/fs_utime.c
Executable file
173
fs/vfs/operation/fs_utime.c
Executable file
@@ -0,0 +1,173 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
|
||||
* Copyright (c) 2020, 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.
|
||||
*/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include "errno.h"
|
||||
#include "vfs_config.h"
|
||||
#include "sys/stat.h"
|
||||
#include "inode/inode.h"
|
||||
#include "string.h"
|
||||
#include "stdlib.h"
|
||||
#include "utime.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Global Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: utime
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero on success; -1 on failure with errno set:
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int utime_pseudo(FAR struct inode *pinode, FAR const struct utimbuf *ptimes)
|
||||
{
|
||||
return ENOSYS;
|
||||
}
|
||||
|
||||
int utime(FAR const char *path, FAR const struct utimbuf *ptimes)
|
||||
{
|
||||
FAR struct inode *pinode = NULL;
|
||||
const char *relpath = NULL;
|
||||
int ret = OK;
|
||||
char *fullpath = NULL;
|
||||
time_t cur_sec;
|
||||
struct tm *set_tm = NULL;
|
||||
struct inode_search_s desc;
|
||||
|
||||
/* Sanity checks */
|
||||
|
||||
if (path == NULL) {
|
||||
ret = EINVAL;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
if (!path[0]) {
|
||||
ret = ENOENT;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
ret = vfs_normalize_path((const char *)NULL, path, &fullpath);
|
||||
if (ret < 0) {
|
||||
ret = -ret;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* Check for the fake root directory (which has no inode) */
|
||||
|
||||
if (strcmp(fullpath, "/") == 0) {
|
||||
ret = EACCES;
|
||||
goto errout_with_path;
|
||||
}
|
||||
|
||||
/* Get an inode for this file */
|
||||
SETUP_SEARCH(&desc, fullpath, false);
|
||||
ret = inode_find(&desc);
|
||||
if (ret < 0) {
|
||||
/* This name does not refer to a psudeo-inode and there is no
|
||||
* mountpoint that includes in this path.
|
||||
*/
|
||||
|
||||
ret = EACCES;
|
||||
goto errout_with_path;
|
||||
}
|
||||
pinode = desc.node;
|
||||
|
||||
/* The way we handle the utime depends on the type of inode that we
|
||||
* are dealing with.
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_DISABLE_MOUNTPOINT
|
||||
if (INODE_IS_MOUNTPT(pinode)) {
|
||||
/* The node is a file system mointpoint. Verify that the mountpoint
|
||||
* supports the utime() method.
|
||||
*/
|
||||
|
||||
if (pinode->u.i_mops && pinode->u.i_mops->utime) {
|
||||
if (ptimes == NULL) {
|
||||
/*get current seconds*/
|
||||
|
||||
cur_sec = time(NULL);
|
||||
set_tm = localtime(&cur_sec); /* transform seconds to struct tm */
|
||||
} else {
|
||||
set_tm = gmtime(&ptimes->modtime); /* transform seconds to struct tm */
|
||||
}
|
||||
|
||||
/* Perform the utime() operation */
|
||||
|
||||
if (set_tm == NULL) {
|
||||
ret = EINVAL;
|
||||
goto errout_with_inode;
|
||||
}
|
||||
ret = pinode->u.i_mops->utime(pinode, relpath, set_tm);
|
||||
} else {
|
||||
ret = ENOSYS;
|
||||
goto errout_with_inode;
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
/* The node is part of the root pseudo file system */
|
||||
|
||||
ret = utime_pseudo(pinode, ptimes);
|
||||
goto errout_with_inode;
|
||||
}
|
||||
|
||||
/* Check if the stat operation was successful */
|
||||
|
||||
if (ret < 0) {
|
||||
ret = -ret;
|
||||
goto errout_with_inode;
|
||||
}
|
||||
|
||||
/* Successfully stat'ed the file */
|
||||
|
||||
inode_release(pinode);
|
||||
free(fullpath);
|
||||
return OK;
|
||||
|
||||
/* Failure conditions always set the errno appropriately */
|
||||
|
||||
errout_with_inode:
|
||||
inode_release(pinode);
|
||||
errout_with_path:
|
||||
free(fullpath);
|
||||
errout:
|
||||
if (ret != 0) {
|
||||
set_errno(ret);
|
||||
}
|
||||
return VFS_ERROR;
|
||||
}
|
||||
153
fs/vfs/operation/fs_virstatfs.c
Executable file
153
fs/vfs/operation/fs_virstatfs.c
Executable file
@@ -0,0 +1,153 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
|
||||
* Copyright (c) 2020, 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.
|
||||
*/
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include "vfs_config.h"
|
||||
|
||||
#include "sys/statfs.h"
|
||||
#include "string.h"
|
||||
#include "sched.h"
|
||||
|
||||
#include "inode/inode.h"
|
||||
#include "errno.h"
|
||||
#include "stdlib.h"
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: statpseudo
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef LOSCFG_FS_FAT_VIRTUAL_PARTITION
|
||||
int virstatfs(FAR const char *path, FAR struct statfs *buf)
|
||||
{
|
||||
FAR struct inode *inode;
|
||||
FAR const char *relpath = NULL;
|
||||
int ret = OK;
|
||||
char *fullpath = NULL;
|
||||
struct inode_search_s desc;
|
||||
|
||||
/* Sanity checks */
|
||||
|
||||
if (!path || !buf)
|
||||
{
|
||||
ret = EFAULT;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
if (!path[0])
|
||||
{
|
||||
ret = ENOENT;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
ret = vfs_normalize_path((const char *)NULL, path, &fullpath);
|
||||
if (ret < 0)
|
||||
{
|
||||
ret = -ret;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* Get an inode for this file */
|
||||
SETUP_SEARCH(&desc, fullpath, false);
|
||||
ret = inode_find(&desc);
|
||||
if (ret < 0)
|
||||
{
|
||||
/* This name does not refer to a psudeo-inode and there is no
|
||||
* mountpoint that includes in this path.
|
||||
*/
|
||||
|
||||
ret = EACCES;
|
||||
free(fullpath);
|
||||
goto errout;
|
||||
}
|
||||
inode = desc.node;
|
||||
relpath = desc.relpath;
|
||||
|
||||
/* The way we handle the statfs depends on the type of inode that we
|
||||
* are dealing with.
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_DISABLE_MOUNTPOINT
|
||||
if (INODE_IS_MOUNTPT(inode))
|
||||
{
|
||||
/* The node is a file system mointpoint. Verify that the mountpoint
|
||||
* supports the statfs() method
|
||||
*/
|
||||
|
||||
if (inode->u.i_mops && inode->u.i_mops->virstatfs)
|
||||
{
|
||||
/* Perform the statfs() operation */
|
||||
|
||||
ret = inode->u.i_mops->virstatfs(inode, relpath, buf);
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = EINVAL;
|
||||
goto errout_with_inode;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
ret = EINVAL;
|
||||
goto errout_with_inode;
|
||||
}
|
||||
|
||||
/* Check if the statfs operation was successful */
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
ret = -ret;
|
||||
goto errout_with_inode;
|
||||
}
|
||||
|
||||
/* Successfully statfs'ed the file */
|
||||
|
||||
inode_release(inode);
|
||||
free(fullpath);
|
||||
return OK;
|
||||
|
||||
/* Failure conditions always set the errno appropriately */
|
||||
|
||||
errout_with_inode:
|
||||
inode_release(inode);
|
||||
free(fullpath);
|
||||
errout:
|
||||
set_errno(ret);
|
||||
return VFS_ERROR;
|
||||
}
|
||||
#endif
|
||||
127
fs/vfs/operation/fs_writev.c
Executable file
127
fs/vfs/operation/fs_writev.c
Executable file
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
|
||||
* Copyright (c) 2020, 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 "sys/types.h"
|
||||
#include "sys/uio.h"
|
||||
#include "unistd.h"
|
||||
#include "string.h"
|
||||
#include "stdlib.h"
|
||||
#include "fs/fs.h"
|
||||
#include "inode/inode.h"
|
||||
#include "user_copy.h"
|
||||
|
||||
static int iov_trans_to_buf(char *buf, ssize_t totallen, const struct iovec *iov, int iovcnt)
|
||||
{
|
||||
int i;
|
||||
size_t ret, writepart;
|
||||
size_t bytestowrite;
|
||||
char *writebuf = NULL;
|
||||
char *curbuf = buf;
|
||||
|
||||
for (i = 0; i < iovcnt; ++i) {
|
||||
writebuf = (char *)iov[i].iov_base;
|
||||
bytestowrite = iov[i].iov_len;
|
||||
if (bytestowrite == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (totallen == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
bytestowrite = (totallen < bytestowrite) ? totallen : bytestowrite;
|
||||
ret = LOS_CopyToKernel(curbuf, bytestowrite, writebuf, bytestowrite);
|
||||
if (ret != 0) {
|
||||
if (ret == bytestowrite) {
|
||||
set_errno(EFAULT);
|
||||
return VFS_ERROR;
|
||||
} else {
|
||||
writepart = bytestowrite - ret;
|
||||
curbuf += writepart;
|
||||
totallen -= writepart;
|
||||
break;
|
||||
}
|
||||
}
|
||||
curbuf += bytestowrite;
|
||||
totallen -= bytestowrite;
|
||||
}
|
||||
|
||||
return (int)((intptr_t)curbuf - (intptr_t)buf);
|
||||
}
|
||||
|
||||
ssize_t vfs_writev(int fd, const struct iovec *iov, int iovcnt, off_t *offset)
|
||||
{
|
||||
int i, ret;
|
||||
char *buf = NULL;
|
||||
size_t buflen = 0;
|
||||
size_t bytestowrite;
|
||||
ssize_t totalbyteswritten;
|
||||
size_t totallen;
|
||||
|
||||
if ((iov == NULL) || (iovcnt > IOV_MAX)) {
|
||||
return VFS_ERROR;
|
||||
}
|
||||
|
||||
for (i = 0; i < iovcnt; ++i) {
|
||||
if (SSIZE_MAX - buflen < iov[i].iov_len) {
|
||||
set_errno(EINVAL);
|
||||
return VFS_ERROR;
|
||||
}
|
||||
buflen += iov[i].iov_len;
|
||||
}
|
||||
|
||||
if (buflen == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
totallen = buflen * sizeof(char);
|
||||
buf = (char *)LOS_VMalloc(totallen);
|
||||
if (buf == NULL) {
|
||||
return VFS_ERROR;
|
||||
}
|
||||
|
||||
ret = iov_trans_to_buf(buf, totallen, iov, iovcnt);
|
||||
if (ret <= 0) {
|
||||
LOS_VFree(buf);
|
||||
return VFS_ERROR;
|
||||
}
|
||||
|
||||
bytestowrite = (ssize_t)ret;
|
||||
totalbyteswritten = (offset == NULL) ? write(fd, buf, bytestowrite)
|
||||
: pwrite(fd, buf, bytestowrite, *offset);
|
||||
LOS_VFree(buf);
|
||||
return totalbyteswritten;
|
||||
}
|
||||
|
||||
ssize_t writev(int fd, const struct iovec *iov, int iovcnt)
|
||||
{
|
||||
return vfs_writev(fd, iov, iovcnt, NULL);
|
||||
}
|
||||
343
fs/vfs/operation/fullpath.c
Executable file
343
fs/vfs/operation/fullpath.c
Executable file
@@ -0,0 +1,343 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
|
||||
* Copyright (c) 2020, 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 "stdio.h"
|
||||
#include "stdlib.h"
|
||||
#include "string.h"
|
||||
#include "errno.h"
|
||||
#include "limits.h"
|
||||
#include "los_process_pri.h"
|
||||
#include "fs/fd_table.h"
|
||||
#include "fs/file.h"
|
||||
|
||||
#ifdef LOSCFG_SHELL
|
||||
#include "shell.h"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#ifdef LOSCFG_SHELL
|
||||
#define TEMP_PATH_MAX (PATH_MAX + SHOW_MAX_LEN)
|
||||
#else
|
||||
#define TEMP_PATH_MAX PATH_MAX
|
||||
#endif
|
||||
|
||||
static unsigned int vfs_strnlen(const char *str, size_t maxlen)
|
||||
{
|
||||
const char *p = NULL;
|
||||
|
||||
for (p = str; ((maxlen-- != 0) && (*p != '\0')); ++p) {}
|
||||
|
||||
return p - str;
|
||||
}
|
||||
|
||||
/* abandon the redundant '/' in the path, only keep one. */
|
||||
|
||||
static char *str_path(char *path)
|
||||
{
|
||||
char *dest = path;
|
||||
char *src = path;
|
||||
|
||||
while (*src != '\0') {
|
||||
if (*src == '/') {
|
||||
*dest++ = *src++;
|
||||
while (*src == '/') {
|
||||
src++;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
*dest++ = *src++;
|
||||
}
|
||||
*dest = '\0';
|
||||
return path;
|
||||
}
|
||||
|
||||
static void str_remove_path_end_slash(char *dest, const char *fullpath)
|
||||
{
|
||||
if ((*dest == '.') && (*(dest - 1) == '/')) {
|
||||
*dest = '\0';
|
||||
dest--;
|
||||
}
|
||||
if ((dest != fullpath) && (*dest == '/')) {
|
||||
*dest = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
static char *str_normalize_path(char *fullpath)
|
||||
{
|
||||
char *dest = fullpath;
|
||||
char *src = fullpath;
|
||||
|
||||
/* 2: The position of the path character: / and the end character /0 */
|
||||
|
||||
while (*src != '\0') {
|
||||
if (*src == '.') {
|
||||
if (*(src + 1) == '/') {
|
||||
src += 2;
|
||||
continue;
|
||||
} else if (*(src + 1) == '.') {
|
||||
if ((*(src + 2) == '/') || (*(src + 2) == '\0')) {
|
||||
src += 2;
|
||||
} else {
|
||||
while ((*src != '\0') && (*src != '/')) {
|
||||
*dest++ = *src++;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
*dest++ = *src++;
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
*dest++ = *src++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((dest - 1) != fullpath) {
|
||||
dest--;
|
||||
}
|
||||
|
||||
while ((dest > fullpath) && (*(dest - 1) != '/')) {
|
||||
dest--;
|
||||
}
|
||||
|
||||
if (*src == '/') {
|
||||
src++;
|
||||
}
|
||||
}
|
||||
|
||||
*dest = '\0';
|
||||
|
||||
/* remove '/' in the end of path if exist */
|
||||
|
||||
dest--;
|
||||
|
||||
str_remove_path_end_slash(dest, fullpath);
|
||||
return dest;
|
||||
}
|
||||
|
||||
static int vfs_normalize_path_parame_check(const char *filename, char **pathname)
|
||||
{
|
||||
int namelen;
|
||||
char *name = NULL;
|
||||
|
||||
if (pathname == NULL) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* check parameters */
|
||||
|
||||
if (filename == NULL) {
|
||||
*pathname = NULL;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
namelen = vfs_strnlen(filename, PATH_MAX);
|
||||
if (!namelen) {
|
||||
*pathname = NULL;
|
||||
return -EINVAL;
|
||||
} else if (namelen >= PATH_MAX) {
|
||||
*pathname = NULL;
|
||||
return -ENAMETOOLONG;
|
||||
}
|
||||
|
||||
for (name = (char *)filename + namelen; ((name != filename) && (*name != '/')); name--) {
|
||||
if (strlen(name) > NAME_MAX) {
|
||||
*pathname = NULL;
|
||||
return -ENAMETOOLONG;
|
||||
}
|
||||
}
|
||||
|
||||
return namelen;
|
||||
}
|
||||
|
||||
static char *vfs_not_absolute_path(const char *directory, const char *filename, char **pathname, int namelen)
|
||||
{
|
||||
int ret;
|
||||
char *fullpath = NULL;
|
||||
|
||||
/* 2: The position of the path character: / and the end character /0 */
|
||||
|
||||
if ((namelen > 1) && (filename[0] == '.') && (filename[1] == '/')) {
|
||||
filename += 2;
|
||||
}
|
||||
|
||||
fullpath = (char *)malloc(strlen(directory) + namelen + 2);
|
||||
if (fullpath == NULL) {
|
||||
*pathname = NULL;
|
||||
set_errno(ENOMEM);
|
||||
return (char *)NULL;
|
||||
}
|
||||
|
||||
/* join path and file name */
|
||||
|
||||
ret = snprintf_s(fullpath, strlen(directory) + namelen + 2, strlen(directory) + namelen + 1,
|
||||
"%s/%s", directory, filename);
|
||||
if (ret < 0) {
|
||||
*pathname = NULL;
|
||||
free(fullpath);
|
||||
set_errno(ENAMETOOLONG);
|
||||
return (char *)NULL;
|
||||
}
|
||||
|
||||
return fullpath;
|
||||
}
|
||||
|
||||
static char *vfs_normalize_fullpath(const char *directory, const char *filename, char **pathname, int namelen)
|
||||
{
|
||||
char *fullpath = NULL;
|
||||
|
||||
if (filename[0] != '/') {
|
||||
/* not a absolute path */
|
||||
|
||||
fullpath = vfs_not_absolute_path(directory, filename, pathname, namelen);
|
||||
if (fullpath == NULL) {
|
||||
return (char *)NULL;
|
||||
}
|
||||
} else {
|
||||
/* it's a absolute path, use it directly */
|
||||
|
||||
fullpath = strdup(filename); /* copy string */
|
||||
|
||||
if (fullpath == NULL) {
|
||||
*pathname = NULL;
|
||||
set_errno(ENOMEM);
|
||||
return (char *)NULL;
|
||||
}
|
||||
if (filename[1] == '/') {
|
||||
*pathname = NULL;
|
||||
free(fullpath);
|
||||
set_errno(EINVAL);
|
||||
return (char *)NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return fullpath;
|
||||
}
|
||||
|
||||
int vfs_normalize_path(const char *directory, const char *filename, char **pathname)
|
||||
{
|
||||
char *fullpath = NULL;
|
||||
int namelen;
|
||||
#ifdef VFS_USING_WORKDIR
|
||||
UINTPTR lock_flags;
|
||||
LosProcessCB *curr = OsCurrProcessGet();
|
||||
BOOL dir_flags = (directory == NULL) ? TRUE : FALSE;
|
||||
#endif
|
||||
|
||||
namelen = vfs_normalize_path_parame_check(filename, pathname);
|
||||
if (namelen < 0) {
|
||||
return namelen;
|
||||
}
|
||||
|
||||
#ifdef VFS_USING_WORKDIR
|
||||
if (directory == NULL)
|
||||
{
|
||||
spin_lock_irqsave(&curr->files->workdir_lock, lock_flags);
|
||||
directory = curr->files->workdir;
|
||||
}
|
||||
#else
|
||||
if ((directory == NULL) && (filename[0] != '/')) {
|
||||
PRINT_ERR("NO_WORKING_DIR\n");
|
||||
*pathname = NULL;
|
||||
return -EINVAL;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* 2: The position of the path character: / and the end character /0 */
|
||||
|
||||
if ((filename[0] != '/') && (strlen(directory) + namelen + 2 > TEMP_PATH_MAX)) {
|
||||
#ifdef VFS_USING_WORKDIR
|
||||
if (dir_flags == TRUE)
|
||||
{
|
||||
spin_unlock_irqrestore(&curr->files->workdir_lock, lock_flags);
|
||||
}
|
||||
#endif
|
||||
return -ENAMETOOLONG;
|
||||
}
|
||||
|
||||
fullpath = vfs_normalize_fullpath(directory, filename, pathname, namelen);
|
||||
#ifdef VFS_USING_WORKDIR
|
||||
if (dir_flags == TRUE)
|
||||
{
|
||||
spin_unlock_irqrestore(&curr->files->workdir_lock, lock_flags);
|
||||
}
|
||||
#endif
|
||||
if (fullpath == NULL) {
|
||||
return -get_errno();
|
||||
}
|
||||
|
||||
(void)str_path(fullpath);
|
||||
(void)str_normalize_path(fullpath);
|
||||
if (strlen(fullpath) >= PATH_MAX) {
|
||||
*pathname = NULL;
|
||||
free(fullpath);
|
||||
return -ENAMETOOLONG;
|
||||
}
|
||||
|
||||
*pathname = fullpath;
|
||||
return ENOERR;
|
||||
}
|
||||
|
||||
int vfs_normalize_pathat(int dirfd, const char *filename, char **pathname)
|
||||
{
|
||||
/* Get path by dirfd*/
|
||||
char *relativeoldpath = NULL;
|
||||
char *fullpath = NULL;
|
||||
int ret = 0;
|
||||
|
||||
ret = get_path_from_fd(dirfd, &relativeoldpath);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = vfs_normalize_path((const char *)relativeoldpath, filename, &fullpath);
|
||||
if (relativeoldpath) {
|
||||
free(relativeoldpath);
|
||||
}
|
||||
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
*pathname = fullpath;
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
#endif /* __cplusplus */
|
||||
Reference in New Issue
Block a user