mirror of
https://github.com/openharmony/third_party_NuttX.git
synced 2026-07-01 08:17:34 -04:00
Description:vfs refactoring
Feature or Bugfix:Feature Binary Source:Huawei PrivateCode(Yes/No):Yes Change-Id: I175d2648bc6f9078c34de2c0a5c93fda10b86c47 ChangeID:13306420
This commit is contained in:
committed by
mamingshuai
parent
eabbc1eb3d
commit
70bdb2590c
+1
-1
@@ -62,7 +62,7 @@
|
||||
|
||||
struct bchlib_s
|
||||
{
|
||||
struct inode *inode; /* I-node of the block driver */
|
||||
struct Vnode *vnode; /* I-node of the block driver */
|
||||
uint32_t sectsize; /* The size of one sector on the device */
|
||||
unsigned long long nsectors; /* Number of sectors supported by the device */
|
||||
unsigned long long sector; /* The current sector in the buffer */
|
||||
|
||||
Executable → Regular
+43
-55
@@ -68,7 +68,7 @@ static ssize_t bch_write(struct file *filep, const char *buffer,
|
||||
static int bch_ioctl(struct file *filep, int cmd,
|
||||
unsigned long arg);
|
||||
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
|
||||
static int bch_unlink(struct inode *inode);
|
||||
static int bch_unlink(struct Vnode *vnode);
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
@@ -77,17 +77,13 @@ static int bch_unlink(struct inode *inode);
|
||||
|
||||
const struct file_operations_vfs bch_fops =
|
||||
{
|
||||
bch_open, /* open */
|
||||
bch_close, /* close */
|
||||
bch_read, /* read */
|
||||
bch_write, /* write */
|
||||
bch_seek, /* seek */
|
||||
bch_ioctl, /* ioctl */
|
||||
NULL, /* mmap */
|
||||
#ifndef CONFIG_DISABLE_POLL
|
||||
NULL, /* poll */
|
||||
#endif
|
||||
bch_unlink, /* unlink */
|
||||
.open = bch_open, /* open */
|
||||
.close = bch_close, /* close */
|
||||
.read = bch_read, /* read */
|
||||
.write = bch_write, /* write */
|
||||
.seek = bch_seek, /* seek */
|
||||
.ioctl = bch_ioctl, /* ioctl */
|
||||
.unlink = bch_unlink, /* unlink */
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
@@ -101,14 +97,13 @@ const struct file_operations_vfs bch_fops =
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int bch_open(FAR struct file *filep)
|
||||
static int bch_open(struct file *filep)
|
||||
{
|
||||
FAR struct inode *inode = filep->f_inode;
|
||||
FAR struct bchlib_s *bch;
|
||||
struct Vnode *vnode = filep->f_vnode;
|
||||
struct bchlib_s *bch;
|
||||
int ret = OK;
|
||||
|
||||
DEBUGASSERT(inode && inode->i_private);
|
||||
bch = (FAR struct bchlib_s *)inode->i_private;
|
||||
bch = (struct bchlib_s *)((struct drv_data *)vnode->data)->priv;
|
||||
|
||||
/* Increment the reference count */
|
||||
|
||||
@@ -133,14 +128,13 @@ static int bch_open(FAR struct file *filep)
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int bch_close(FAR struct file *filep)
|
||||
static int bch_close(struct file *filep)
|
||||
{
|
||||
FAR struct inode *inode = filep->f_inode;
|
||||
FAR struct bchlib_s *bch;
|
||||
struct Vnode *vnode = filep->f_vnode;
|
||||
struct bchlib_s *bch;
|
||||
int ret = OK;
|
||||
|
||||
DEBUGASSERT(inode && inode->i_private);
|
||||
bch = (FAR struct bchlib_s *)inode->i_private;
|
||||
bch = (struct bchlib_s *)((struct drv_data *)vnode->data)->priv;
|
||||
|
||||
/* Flush any dirty pages remaining in the cache */
|
||||
|
||||
@@ -168,7 +162,7 @@ static int bch_close(FAR struct file *filep)
|
||||
{
|
||||
/* Tear the driver down now. */
|
||||
|
||||
ret = bchlib_teardown((FAR void *)bch);
|
||||
ret = bchlib_teardown((void *)bch);
|
||||
|
||||
/* bchlib_teardown() would only fail if there are outstanding
|
||||
* references on the device. Since we know that is not true, it
|
||||
@@ -193,16 +187,14 @@ static int bch_close(FAR struct file *filep)
|
||||
* Name: bch_seek
|
||||
****************************************************************************/
|
||||
|
||||
static off_t bch_seek(FAR struct file *filep, off_t offset, int whence)
|
||||
static off_t bch_seek(struct file *filep, off_t offset, int whence)
|
||||
{
|
||||
FAR struct inode *inode = filep->f_inode;
|
||||
FAR struct bchlib_s *bch;
|
||||
struct Vnode *vnode = filep->f_vnode;
|
||||
struct bchlib_s *bch;
|
||||
loff_t newpos;
|
||||
int ret;
|
||||
|
||||
DEBUGASSERT(inode && inode->i_private);
|
||||
|
||||
bch = (FAR struct bchlib_s *)inode->i_private;
|
||||
bch = (struct bchlib_s *)((struct drv_data *)vnode->data)->priv;
|
||||
bchlib_semtake(bch);
|
||||
|
||||
/* Determine the new, requested file position */
|
||||
@@ -259,14 +251,13 @@ static off_t bch_seek(FAR struct file *filep, off_t offset, int whence)
|
||||
* Name: bch_read
|
||||
****************************************************************************/
|
||||
|
||||
static ssize_t bch_read(FAR struct file *filep, FAR char *buffer, size_t len)
|
||||
static ssize_t bch_read(struct file *filep, char *buffer, size_t len)
|
||||
{
|
||||
FAR struct inode *inode = filep->f_inode;
|
||||
FAR struct bchlib_s *bch;
|
||||
struct Vnode *vnode = filep->f_vnode;
|
||||
struct bchlib_s *bch;
|
||||
int ret;
|
||||
|
||||
DEBUGASSERT(inode && inode->i_private);
|
||||
bch = (FAR struct bchlib_s *)inode->i_private;
|
||||
bch = (struct bchlib_s *)((struct drv_data *)vnode->data)->priv;
|
||||
|
||||
bchlib_semtake(bch);
|
||||
ret = bchlib_read(bch, buffer, filep->f_pos, len);
|
||||
@@ -283,14 +274,13 @@ static ssize_t bch_read(FAR struct file *filep, FAR char *buffer, size_t len)
|
||||
* Name: bch_write
|
||||
****************************************************************************/
|
||||
|
||||
static ssize_t bch_write(FAR struct file *filep, FAR const char *buffer, size_t len)
|
||||
static ssize_t bch_write(struct file *filep, const char *buffer, size_t len)
|
||||
{
|
||||
FAR struct inode *inode = filep->f_inode;
|
||||
FAR struct bchlib_s *bch;
|
||||
struct Vnode *vnode = filep->f_vnode;
|
||||
struct bchlib_s *bch;
|
||||
int ret = -EACCES;
|
||||
|
||||
DEBUGASSERT(inode && inode->i_private);
|
||||
bch = (FAR struct bchlib_s *)inode->i_private;
|
||||
bch = (struct bchlib_s *)((struct drv_data *)vnode->data)->priv;
|
||||
|
||||
if (!bch->readonly)
|
||||
{
|
||||
@@ -315,14 +305,14 @@ static ssize_t bch_write(FAR struct file *filep, FAR const char *buffer, size_t
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int bch_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
|
||||
static int bch_ioctl(struct file *filep, int cmd, unsigned long arg)
|
||||
{
|
||||
FAR struct inode *inode = filep->f_inode;
|
||||
FAR struct bchlib_s *bch;
|
||||
struct Vnode *vnode = filep->f_vnode;
|
||||
struct bchlib_s *bch;
|
||||
struct block_operations *bop = NULL;
|
||||
int ret = -ENOTTY;
|
||||
|
||||
DEBUGASSERT(inode && inode->i_private);
|
||||
bch = (FAR struct bchlib_s *)inode->i_private;
|
||||
bch = (struct bchlib_s *)((struct drv_data *)vnode->data)->priv;
|
||||
|
||||
/* Process the call according to the command */
|
||||
|
||||
@@ -332,8 +322,8 @@ static int bch_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
|
||||
|
||||
case DIOC_GETPRIV:
|
||||
{
|
||||
FAR struct bchlib_s **bchr =
|
||||
(FAR struct bchlib_s **)((uintptr_t)arg);
|
||||
struct bchlib_s **bchr =
|
||||
(struct bchlib_s **)((uintptr_t)arg);
|
||||
|
||||
bchlib_semtake(bch);
|
||||
if (!bchr || bch->refs == MAX_OPENCNT)
|
||||
@@ -362,8 +352,6 @@ static int bch_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
|
||||
|
||||
default:
|
||||
{
|
||||
struct inode *bchinode = bch->inode;
|
||||
|
||||
/* Does the block driver support the ioctl method? */
|
||||
|
||||
los_disk *disk = bch->disk;
|
||||
@@ -380,9 +368,10 @@ static int bch_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
|
||||
}
|
||||
if (disk->disk_status == STAT_INUSED)
|
||||
{
|
||||
if (bchinode->u.i_bops->ioctl != NULL)
|
||||
bop = (struct block_operations *)(((struct drv_data *)vnode->data)->ops);
|
||||
if (bop != NULL && bop->ioctl != NULL)
|
||||
{
|
||||
ret = bchinode->u.i_bops->ioctl(bchinode, cmd, arg);
|
||||
ret = bop->ioctl(bch->vnode, cmd, arg);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -405,13 +394,12 @@ static int bch_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int bch_unlink(FAR struct inode *inode)
|
||||
int bch_unlink(struct Vnode *vnode)
|
||||
{
|
||||
FAR struct bchlib_s *bch;
|
||||
struct bchlib_s *bch;
|
||||
int ret = OK;
|
||||
|
||||
DEBUGASSERT(inode && inode->i_private);
|
||||
bch = (FAR struct bchlib_s *)inode->i_private;
|
||||
bch = (struct bchlib_s *)((struct drv_data *)vnode->data)->priv;
|
||||
|
||||
/* Get exclusive access to the BCH device */
|
||||
|
||||
@@ -429,7 +417,7 @@ static int bch_unlink(FAR struct inode *inode)
|
||||
{
|
||||
/* Tear the driver down now. */
|
||||
|
||||
ret = bchlib_teardown((FAR void *)bch);
|
||||
ret = bchlib_teardown((void *)bch);
|
||||
|
||||
/* bchlib_teardown() would only fail if there are outstanding
|
||||
* references on the device. Since we know that is not true, it
|
||||
|
||||
Executable → Regular
+12
-10
@@ -60,9 +60,9 @@
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int bchlib_setup(const char *blkdev, bool readonly, FAR void **handle)
|
||||
int bchlib_setup(const char *blkdev, bool readonly, void **handle)
|
||||
{
|
||||
FAR struct bchlib_s *bch;
|
||||
struct bchlib_s *bch;
|
||||
struct geometry geo;
|
||||
los_part *part;
|
||||
int ret;
|
||||
@@ -71,26 +71,28 @@ int bchlib_setup(const char *blkdev, bool readonly, FAR void **handle)
|
||||
|
||||
/* Allocate the BCH state structure */
|
||||
|
||||
bch = (FAR struct bchlib_s *)zalloc(sizeof(struct bchlib_s));
|
||||
bch = (struct bchlib_s *)zalloc(sizeof(struct bchlib_s));
|
||||
if (!bch)
|
||||
{
|
||||
PRINTK("ERROR: Failed to allocate BCH structure\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
|
||||
/* Open the block driver */
|
||||
|
||||
ret = open_blockdriver(blkdev, readonly ? MS_RDONLY : 0, &bch->inode);
|
||||
ret = open_blockdriver(blkdev, readonly ? MS_RDONLY : 0, &bch->vnode);
|
||||
if (ret < 0)
|
||||
{
|
||||
PRINTK("ERROR: Failed to open driver %s: %d\n", blkdev, -ret);
|
||||
goto errout_with_bch;
|
||||
}
|
||||
|
||||
DEBUGASSERT(bch->inode && bch->inode->u.i_bops && bch->inode->u.i_bops->geometry);
|
||||
struct drv_data *drv = (struct drv_data *)bch->vnode->data;
|
||||
struct block_operations *bops = (struct block_operations *)drv->ops;
|
||||
|
||||
ret = bch->inode->u.i_bops->geometry(bch->inode, &geo);
|
||||
DEBUGASSERT(bch->vnode && bops && bops->geometry);
|
||||
|
||||
ret = bops->geometry(bch->vnode, &geo);
|
||||
if (ret < 0)
|
||||
{
|
||||
PRINTK("ERROR: geometry failed: %d\n", -ret);
|
||||
@@ -104,7 +106,7 @@ int bchlib_setup(const char *blkdev, bool readonly, FAR void **handle)
|
||||
goto errout_with_bch;
|
||||
}
|
||||
|
||||
if (!readonly && (!bch->inode->u.i_bops->write || !geo.geo_writeenabled))
|
||||
if (!readonly && (!bops->write || !geo.geo_writeenabled))
|
||||
{
|
||||
PRINTK("ERROR: write access not supported\n");
|
||||
ret = -EACCES;
|
||||
@@ -121,7 +123,7 @@ int bchlib_setup(const char *blkdev, bool readonly, FAR void **handle)
|
||||
bch->dirty = false;
|
||||
bch->unlinked = false;
|
||||
|
||||
part = los_part_find(bch->inode);
|
||||
part = los_part_find(bch->vnode);
|
||||
if (part != NULL)
|
||||
{
|
||||
bch->sectstart = part->sector_start;
|
||||
@@ -137,7 +139,7 @@ int bchlib_setup(const char *blkdev, bool readonly, FAR void **handle)
|
||||
|
||||
/* Allocate the sector I/O buffer */
|
||||
|
||||
bch->buffer = (FAR uint8_t *)malloc(bch->sectsize);
|
||||
bch->buffer = (uint8_t *)malloc(bch->sectsize);
|
||||
if (!bch->buffer)
|
||||
{
|
||||
PRINTK("ERROR: Failed to allocate sector buffer\n");
|
||||
|
||||
Executable → Regular
+4
-3
@@ -40,6 +40,7 @@
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
#include <debug.h>
|
||||
#include "fs/fs.h"
|
||||
#include "bch.h"
|
||||
|
||||
/****************************************************************************
|
||||
@@ -55,9 +56,9 @@
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int bchlib_teardown(FAR void *handle)
|
||||
int bchlib_teardown(void *handle)
|
||||
{
|
||||
FAR struct bchlib_s *bch = (FAR struct bchlib_s *)handle;
|
||||
struct bchlib_s *bch = (struct bchlib_s *)handle;
|
||||
|
||||
DEBUGASSERT(handle);
|
||||
|
||||
@@ -74,7 +75,7 @@ int bchlib_teardown(FAR void *handle)
|
||||
|
||||
/* Close the block driver */
|
||||
|
||||
(void)close_blockdriver(bch->inode);
|
||||
(void)close_blockdriver(bch->vnode);
|
||||
|
||||
/* Free the BCH state structure */
|
||||
|
||||
|
||||
Executable → Regular
+13
-13
@@ -51,7 +51,7 @@
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
static ssize_t fifo_map(FAR struct file* filep, FAR LosVmMapRegion *region)
|
||||
static ssize_t fifo_map(struct file* filep, LosVmMapRegion *region)
|
||||
{
|
||||
PRINTK("%s %d, mmap is not support\n", __FUNCTION__, __LINE__);
|
||||
return 0;
|
||||
@@ -59,16 +59,16 @@ static ssize_t fifo_map(FAR struct file* filep, FAR LosVmMapRegion *region)
|
||||
|
||||
static const struct file_operations_vfs fifo_fops =
|
||||
{
|
||||
pipecommon_open, /* open */
|
||||
pipecommon_close, /* close */
|
||||
pipecommon_read, /* read */
|
||||
pipecommon_write, /* write */
|
||||
NULL, /* seek */
|
||||
NULL, /* ioctl */
|
||||
fifo_map, /* mmap */
|
||||
NULL, /* poll */
|
||||
.open = pipecommon_open, /* open */
|
||||
.close = pipecommon_close, /* close */
|
||||
.read = pipecommon_read, /* read */
|
||||
.write = pipecommon_write, /* write */
|
||||
.seek = NULL, /* seek */
|
||||
.ioctl = NULL, /* ioctl */
|
||||
.mmap = fifo_map, /* mmap */
|
||||
.poll = NULL, /* poll */
|
||||
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
|
||||
pipecommon_unlink, /* unlink */
|
||||
.unlink = pipecommon_unlink, /* unlink */
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -110,9 +110,9 @@ static const struct file_operations_vfs fifo_fops =
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int mkfifo(FAR const char *pathname, mode_t mode)
|
||||
int mkfifo(const char *pathname, mode_t mode)
|
||||
{
|
||||
FAR struct pipe_dev_s *dev;
|
||||
struct pipe_dev_s *dev = NULL;
|
||||
int ret;
|
||||
size_t bufsize = 1024;
|
||||
|
||||
@@ -139,7 +139,7 @@ int mkfifo(FAR const char *pathname, mode_t mode)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ret = register_driver(pathname, &fifo_fops, mode, (FAR void *)dev);
|
||||
ret = register_driver(pathname, &fifo_fops, mode, (void *)dev);
|
||||
if (ret != 0)
|
||||
{
|
||||
pipecommon_freedev(dev);
|
||||
|
||||
Executable → Regular
+31
-24
@@ -47,6 +47,7 @@
|
||||
|
||||
#include <fs/fs.h>
|
||||
|
||||
#include "fs/vnode.h"
|
||||
#include "pipe_common.h"
|
||||
#include "stdio.h"
|
||||
#if CONFIG_DEV_PIPE_SIZE > 0
|
||||
@@ -65,16 +66,16 @@
|
||||
* Private Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
static int pipe_close(FAR struct file *filep);
|
||||
static int pipe_close(struct file *filep);
|
||||
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
|
||||
static int pipe_unlink(FAR struct inode *priv);
|
||||
int pipe_unlink(struct Vnode *priv);
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
static ssize_t pipe_map(FAR struct file* filep, FAR LosVmMapRegion *region)
|
||||
static ssize_t pipe_map(struct file* filep, LosVmMapRegion *region)
|
||||
{
|
||||
PRINTK("%s %d, mmap is not support\n", __FUNCTION__, __LINE__);
|
||||
return 0;
|
||||
@@ -82,16 +83,16 @@ static ssize_t pipe_map(FAR struct file* filep, FAR LosVmMapRegion *region)
|
||||
|
||||
static const struct file_operations_vfs pipe_fops =
|
||||
{
|
||||
pipecommon_open, /* open */
|
||||
pipe_close, /* close */
|
||||
pipecommon_read, /* read */
|
||||
pipecommon_write, /* write */
|
||||
NULL, /* seek */
|
||||
NULL, /* ioctl */
|
||||
pipe_map, /* mmap */
|
||||
pipecommon_poll, /* poll */
|
||||
.open = pipecommon_open, /* open */
|
||||
.close = pipe_close, /* close */
|
||||
.read = pipecommon_read, /* read */
|
||||
.write = pipecommon_write, /* write */
|
||||
.seek = NULL, /* seek */
|
||||
.ioctl = NULL, /* ioctl */
|
||||
.mmap = pipe_map, /* mmap */
|
||||
.poll = pipecommon_poll, /* poll */
|
||||
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
|
||||
pipe_unlink, /* unlink */
|
||||
.unlink = pipe_unlink, /* unlink */
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -145,10 +146,10 @@ static inline void pipe_free(int pipeno)
|
||||
* Name: pipe_close
|
||||
****************************************************************************/
|
||||
|
||||
static int pipe_close(FAR struct file *filep)
|
||||
static int pipe_close(struct file *filep)
|
||||
{
|
||||
FAR struct inode *inode = filep->f_inode;
|
||||
FAR struct pipe_dev_s *dev = inode->i_private;
|
||||
struct Vnode *vnode = filep->f_vnode;
|
||||
struct pipe_dev_s *dev = (struct pipe_dev_s *)((struct drv_data *)vnode->data)->priv;
|
||||
int ret;
|
||||
|
||||
if (dev == NULL)
|
||||
@@ -159,7 +160,7 @@ static int pipe_close(FAR struct file *filep)
|
||||
/* Perform common close operations */
|
||||
|
||||
ret = pipecommon_close(filep);
|
||||
if (ret == 0 && inode->i_crefs == 1)
|
||||
if (ret == 0 && vnode->useCount <= 1)
|
||||
{
|
||||
/* Release the pipe when there are no further open references to it. */
|
||||
|
||||
@@ -174,9 +175,9 @@ static int pipe_close(FAR struct file *filep)
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
|
||||
static int pipe_unlink(FAR struct inode *priv)
|
||||
int pipe_unlink(struct Vnode *vnode)
|
||||
{
|
||||
FAR struct pipe_dev_s *dev = priv->i_private;
|
||||
struct pipe_dev_s *dev = ((struct drv_data *)vnode->data)->priv;
|
||||
uint8_t pipeno = 0;
|
||||
int ret;
|
||||
|
||||
@@ -185,8 +186,8 @@ static int pipe_unlink(FAR struct inode *priv)
|
||||
pipeno = dev->d_pipeno;
|
||||
}
|
||||
/* Perform common close operations */
|
||||
ret = pipecommon_unlink(priv);
|
||||
if (ret == 0 && priv->i_crefs == 1)
|
||||
ret = pipecommon_unlink(vnode);
|
||||
if (ret == 0)
|
||||
{
|
||||
(void)sem_wait(&g_pipesem);
|
||||
g_pipecreated &= ~(1 << pipeno);
|
||||
@@ -198,7 +199,6 @@ static int pipe_unlink(FAR struct inode *priv)
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
@@ -207,7 +207,7 @@ static int pipe_unlink(FAR struct inode *priv)
|
||||
* Name: pipe2
|
||||
*
|
||||
* Description:
|
||||
* pipe() creates a pair of file descriptors, pointing to a pipe inode,
|
||||
* pipe() creates a pair of file descriptors, pointing to a pipe vnode,
|
||||
* and places them in the array pointed to by 'fd'. fd[0] is for reading,
|
||||
* fd[1] is for writing.
|
||||
*
|
||||
@@ -228,11 +228,12 @@ static int pipe_unlink(FAR struct inode *priv)
|
||||
|
||||
int pipe(int fd[2])
|
||||
{
|
||||
FAR struct pipe_dev_s *dev = NULL;
|
||||
struct pipe_dev_s *dev = NULL;
|
||||
char devname[16];
|
||||
int pipeno;
|
||||
int errcode;
|
||||
int ret;
|
||||
struct file *filep = NULL;
|
||||
size_t bufsize = 1024;
|
||||
|
||||
/* Get exclusive access to the pipe allocation data */
|
||||
@@ -276,7 +277,7 @@ int pipe(int fd[2])
|
||||
|
||||
/* Register the pipe device */
|
||||
|
||||
ret = register_driver(devname, &pipe_fops, 0660, (FAR void *)dev);
|
||||
ret = register_driver(devname, &pipe_fops, 0660, (void *)dev);
|
||||
if (ret != 0)
|
||||
{
|
||||
(void)sem_post(&g_pipesem);
|
||||
@@ -309,6 +310,12 @@ int pipe(int fd[2])
|
||||
goto errout_with_wrfd;
|
||||
}
|
||||
|
||||
ret = fs_getfilep(fd[0], &filep);
|
||||
filep->ops = &pipe_fops;
|
||||
|
||||
ret = fs_getfilep(fd[1], &filep);
|
||||
filep->ops = &pipe_fops;
|
||||
|
||||
return OK;
|
||||
|
||||
errout_with_wrfd:
|
||||
|
||||
Executable → Regular
+50
-52
@@ -66,6 +66,8 @@
|
||||
#include "user_copy.h"
|
||||
#ifdef LOSCFG_KERNEL_PIPE
|
||||
|
||||
#include "fs/vnode.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
@@ -94,7 +96,7 @@ static void pipecommon_semtake(sem_t *sem);
|
||||
* Name: pipecommon_semtake
|
||||
****************************************************************************/
|
||||
|
||||
static void pipecommon_semtake(FAR sem_t *sem)
|
||||
static void pipecommon_semtake(sem_t *sem)
|
||||
{
|
||||
int ret;
|
||||
|
||||
@@ -112,7 +114,7 @@ static void pipecommon_semtake(FAR sem_t *sem)
|
||||
* Name: pipecommon_pollnotify
|
||||
****************************************************************************/
|
||||
|
||||
static void pipecommon_pollnotify(FAR struct pipe_dev_s *dev,
|
||||
static void pipecommon_pollnotify(struct pipe_dev_s *dev,
|
||||
pollevent_t eventset)
|
||||
{
|
||||
if (eventset & POLLERR)
|
||||
@@ -131,9 +133,9 @@ static void pipecommon_pollnotify(FAR struct pipe_dev_s *dev,
|
||||
* Name: pipecommon_allocdev
|
||||
****************************************************************************/
|
||||
|
||||
FAR struct pipe_dev_s *pipecommon_allocdev(size_t bufsize, const char *name)
|
||||
struct pipe_dev_s *pipecommon_allocdev(size_t bufsize, const char *name)
|
||||
{
|
||||
FAR struct pipe_dev_s *dev;
|
||||
struct pipe_dev_s *dev = NULL;
|
||||
int ret;
|
||||
|
||||
if (bufsize > CONFIG_DEV_PIPE_MAXSIZE)
|
||||
@@ -143,7 +145,7 @@ FAR struct pipe_dev_s *pipecommon_allocdev(size_t bufsize, const char *name)
|
||||
|
||||
/* Allocate a private structure to manage the pipe */
|
||||
|
||||
dev = (FAR struct pipe_dev_s *)malloc(sizeof(struct pipe_dev_s));
|
||||
dev = (struct pipe_dev_s *)malloc(sizeof(struct pipe_dev_s));
|
||||
if (dev)
|
||||
{
|
||||
/* Initialize the private structure */
|
||||
@@ -173,7 +175,7 @@ FAR struct pipe_dev_s *pipecommon_allocdev(size_t bufsize, const char *name)
|
||||
* Name: pipecommon_freedev
|
||||
****************************************************************************/
|
||||
|
||||
void pipecommon_freedev(FAR struct pipe_dev_s *dev)
|
||||
void pipecommon_freedev(struct pipe_dev_s *dev)
|
||||
{
|
||||
sem_destroy(&dev->d_bfsem);
|
||||
sem_destroy(&dev->d_rdsem);
|
||||
@@ -185,10 +187,10 @@ void pipecommon_freedev(FAR struct pipe_dev_s *dev)
|
||||
* Name: pipecommon_open
|
||||
****************************************************************************/
|
||||
|
||||
int pipecommon_open(FAR struct file *filep)
|
||||
int pipecommon_open(struct file *filep)
|
||||
{
|
||||
FAR struct inode *inode = filep->f_inode;
|
||||
FAR struct pipe_dev_s *dev = inode->i_private;
|
||||
struct Vnode *vnode = filep->f_vnode;
|
||||
struct pipe_dev_s *dev = (struct pipe_dev_s *)((struct drv_data *)vnode->data)->priv;
|
||||
int sval;
|
||||
int ret;
|
||||
|
||||
@@ -213,9 +215,9 @@ int pipecommon_open(FAR struct file *filep)
|
||||
* is first opened.
|
||||
*/
|
||||
|
||||
if (inode->i_crefs == 1 && dev->d_buffer == NULL)
|
||||
if (vnode->useCount == 1 && dev->d_buffer == NULL)
|
||||
{
|
||||
dev->d_buffer = (FAR uint8_t *)malloc(dev->d_bufsize);
|
||||
dev->d_buffer = (uint8_t *)malloc(dev->d_bufsize);
|
||||
if (!dev->d_buffer)
|
||||
{
|
||||
(void)sem_post(&dev->d_bfsem);
|
||||
@@ -285,6 +287,8 @@ int pipecommon_open(FAR struct file *filep)
|
||||
}
|
||||
}
|
||||
|
||||
vnode->useCount++;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -292,13 +296,13 @@ int pipecommon_open(FAR struct file *filep)
|
||||
* Name: pipecommon_close
|
||||
****************************************************************************/
|
||||
|
||||
int pipecommon_close(FAR struct file *filep)
|
||||
int pipecommon_close(struct file *filep)
|
||||
{
|
||||
FAR struct inode *inode = filep->f_inode;
|
||||
FAR struct pipe_dev_s *dev = inode->i_private;
|
||||
struct Vnode *vnode = filep->f_vnode;
|
||||
struct pipe_dev_s *dev = (struct pipe_dev_s *)((struct drv_data *)vnode->data)->priv;
|
||||
int sval;
|
||||
|
||||
if (dev == NULL || filep->f_inode->i_crefs <= 0)
|
||||
if (dev == NULL || filep->f_vnode->useCount <= 1)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -314,9 +318,9 @@ int pipecommon_close(FAR struct file *filep)
|
||||
* still outstanding references to the pipe.
|
||||
*/
|
||||
|
||||
/* Check if the decremented inode reference count would go to zero */
|
||||
/* Check if the decremented vnode reference count would go to zero */
|
||||
|
||||
if (inode->i_crefs > 1)
|
||||
if (vnode->useCount > 1)
|
||||
{
|
||||
/* More references.. If opened for writing, decrement the count of
|
||||
* writers on the pipe instance.
|
||||
@@ -380,6 +384,8 @@ int pipecommon_close(FAR struct file *filep)
|
||||
dev->d_nreaders = 0;
|
||||
}
|
||||
|
||||
vnode->useCount--;
|
||||
|
||||
sem_post(&dev->d_bfsem);
|
||||
return OK;
|
||||
}
|
||||
@@ -388,11 +394,11 @@ int pipecommon_close(FAR struct file *filep)
|
||||
* Name: pipecommon_read
|
||||
****************************************************************************/
|
||||
|
||||
ssize_t pipecommon_read(FAR struct file *filep, FAR char *buffer, size_t len)
|
||||
ssize_t pipecommon_read(struct file *filep, char *buffer, size_t len)
|
||||
{
|
||||
FAR struct inode *inode = filep->f_inode;
|
||||
FAR struct pipe_dev_s *dev = inode->i_private;
|
||||
ssize_t nread = 0;
|
||||
struct Vnode *vnode = filep->f_vnode;
|
||||
struct pipe_dev_s *dev = (struct pipe_dev_s *)((struct drv_data *)vnode->data)->priv;
|
||||
ssize_t nread;
|
||||
int sval;
|
||||
int ret;
|
||||
volatile int num;
|
||||
@@ -548,11 +554,11 @@ ssize_t pipecommon_read(FAR struct file *filep, FAR char *buffer, size_t len)
|
||||
* Name: pipecommon_write
|
||||
****************************************************************************/
|
||||
|
||||
ssize_t pipecommon_write(FAR struct file *filep, FAR const char *buffer,
|
||||
ssize_t pipecommon_write(struct file *filep, const char *buffer,
|
||||
size_t len)
|
||||
{
|
||||
FAR struct inode *inode = filep->f_inode;
|
||||
FAR struct pipe_dev_s *dev = inode->i_private;
|
||||
struct Vnode *vnode = filep->f_vnode;
|
||||
struct pipe_dev_s *dev = (struct pipe_dev_s *)((struct drv_data *)vnode->data)->priv;
|
||||
ssize_t nwritten = 0;
|
||||
ssize_t last;
|
||||
int nxtwrndx;
|
||||
@@ -710,13 +716,13 @@ ssize_t pipecommon_write(FAR struct file *filep, FAR const char *buffer,
|
||||
* Name: pipecommon_poll
|
||||
****************************************************************************/
|
||||
|
||||
int pipecommon_poll(FAR struct file *filep, poll_table *table)
|
||||
int pipecommon_poll(struct file *filep, poll_table *table)
|
||||
{
|
||||
FAR struct inode *inode = filep->f_inode;
|
||||
FAR struct pipe_dev_s *dev = inode->i_private;
|
||||
struct Vnode *vnode = filep->f_vnode;
|
||||
struct pipe_dev_s *dev = (struct pipe_dev_s *)((struct drv_data *)vnode->data)->priv;
|
||||
pollevent_t eventset;
|
||||
pipe_ndx_t nbytes;
|
||||
int ret = OK;
|
||||
int ret;
|
||||
|
||||
if (dev == NULL || table == NULL)
|
||||
{
|
||||
@@ -787,7 +793,7 @@ int pipecommon_poll(FAR struct file *filep, poll_table *table)
|
||||
* Name: pipecommon_ioctl
|
||||
****************************************************************************/
|
||||
|
||||
int pipecommon_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
|
||||
int pipecommon_ioctl(struct file *filep, int cmd, unsigned long arg)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
@@ -797,38 +803,30 @@ int pipecommon_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
|
||||
int pipecommon_unlink(FAR struct inode *inode)
|
||||
int pipecommon_unlink(struct Vnode *vnode)
|
||||
{
|
||||
FAR struct pipe_dev_s *dev;
|
||||
struct pipe_dev_s *dev = NULL;
|
||||
|
||||
if (inode == NULL || inode->i_private == NULL)
|
||||
if (vnode == NULL || vnode->data == NULL)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
dev = ((struct drv_data *)vnode->data)->priv;
|
||||
if (dev == NULL)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
dev = (FAR struct pipe_dev_s *)inode->i_private;
|
||||
|
||||
/* Are the any open references to the driver? */
|
||||
|
||||
if (inode->i_crefs == 1)
|
||||
if (dev->d_buffer)
|
||||
{
|
||||
/* No.. free the buffer (if there is one) */
|
||||
|
||||
if (dev->d_buffer)
|
||||
{
|
||||
free(dev->d_buffer);
|
||||
}
|
||||
|
||||
/* And free the device structure. */
|
||||
unregister_driver(dev->name);
|
||||
pipecommon_freedev(dev);
|
||||
}
|
||||
else
|
||||
{
|
||||
PRINTK("Device busy!\n");
|
||||
return -EBUSY;
|
||||
free(dev->d_buffer);
|
||||
}
|
||||
|
||||
/* And free the device structure. */
|
||||
unregister_driver(dev->name);
|
||||
pipecommon_freedev(dev);
|
||||
|
||||
return OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -161,7 +161,7 @@ ssize_t pipecommon_write(FAR struct file *, FAR const char *, size_t);
|
||||
int pipecommon_ioctl(FAR struct file *filep, int cmd, unsigned long arg);
|
||||
int pipecommon_poll(FAR struct file *filep, poll_table *fds);
|
||||
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
|
||||
int pipecommon_unlink(FAR struct inode *priv);
|
||||
int pipecommon_unlink(struct Vnode *vnode);
|
||||
#endif
|
||||
int pipe_init(void);
|
||||
|
||||
|
||||
Executable → Regular
+39
-53
@@ -61,8 +61,8 @@
|
||||
|
||||
struct fb_chardev_s
|
||||
{
|
||||
FAR struct fb_vtable_s *vtable; /* Framebuffer interface */
|
||||
FAR void *fbmem; /* Start of frame buffer memory */
|
||||
struct fb_vtable_s *vtable; /* Framebuffer interface */
|
||||
void *fbmem; /* Start of frame buffer memory */
|
||||
size_t fblen; /* Size of the framebuffer */
|
||||
uint8_t plane; /* Video plan number */
|
||||
uint8_t bpp; /* Bits per pixel */
|
||||
@@ -75,15 +75,13 @@ static struct fb_chardev_s *g_fb_dev[FB_DEV_MAXNUM] = {NULL};
|
||||
* Private Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
static int fb_open(FAR struct file *filep);
|
||||
static int fb_close(FAR struct file *filep);
|
||||
static ssize_t fb_read(FAR struct file *filep, FAR char *buffer,
|
||||
size_t buflen);
|
||||
static ssize_t fb_write(FAR struct file *filep, FAR const char *buffer,
|
||||
size_t buflen);
|
||||
static off_t fb_seek(FAR struct file *filep, off_t offset, int whence);
|
||||
static int fb_ioctl(FAR struct file *filep, int cmd, unsigned long arg);
|
||||
static ssize_t fb_mmap(FAR struct file* filep, FAR LosVmMapRegion *region);
|
||||
static int fb_open(struct file *filep);
|
||||
static int fb_close(struct file *filep);
|
||||
static ssize_t fb_read(struct file *filep, char *buffer, size_t buflen);
|
||||
static ssize_t fb_write(struct file *filep, const char *buffer, size_t buflen);
|
||||
static off_t fb_seek(struct file *filep, off_t offset, int whence);
|
||||
static int fb_ioctl(struct file *filep, int cmd, unsigned long arg);
|
||||
static ssize_t fb_mmap(struct file* filep, LosVmMapRegion *region);
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
@@ -110,13 +108,13 @@ static const struct file_operations_vfs fb_fops =
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
static ssize_t fb_mmap(FAR struct file *filep, FAR LosVmMapRegion *region)
|
||||
static ssize_t fb_mmap(struct file *filep, LosVmMapRegion *region)
|
||||
{
|
||||
int ret = -EINVAL;
|
||||
struct fb_chardev_s *fb;
|
||||
struct fb_vtable_s *vtable;
|
||||
|
||||
fb = (struct fb_chardev_s *)filep->f_inode->i_private;
|
||||
fb = (struct fb_chardev_s *)((struct drv_data *)filep->f_vnode->data)->priv;
|
||||
if (fb == NULL)
|
||||
{
|
||||
return -ENODEV;
|
||||
@@ -144,14 +142,14 @@ static ssize_t fb_mmap(FAR struct file *filep, FAR LosVmMapRegion *region)
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int fb_open(FAR struct file *filep)
|
||||
static int fb_open(struct file *filep)
|
||||
{
|
||||
DEBUGASSERT(filep != NULL && filep->f_inode != NULL);
|
||||
DEBUGASSERT(filep != NULL && filep->f_vnode != NULL);
|
||||
struct fb_chardev_s *fb;
|
||||
struct fb_vtable_s *vtable;
|
||||
int ret = -EINVAL;
|
||||
|
||||
fb = (struct fb_chardev_s *)filep->f_inode->i_private;
|
||||
fb = (struct fb_chardev_s *)((struct drv_data *)filep->f_vnode->data)->priv;
|
||||
if (fb == NULL)
|
||||
{
|
||||
return -ENODEV;
|
||||
@@ -179,14 +177,14 @@ static int fb_open(FAR struct file *filep)
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int fb_close(FAR struct file *filep)
|
||||
static int fb_close(struct file *filep)
|
||||
{
|
||||
DEBUGASSERT(filep != NULL && filep->f_inode != NULL);
|
||||
DEBUGASSERT(filep != NULL && filep->f_vnode != NULL);
|
||||
struct fb_chardev_s *fb;
|
||||
struct fb_vtable_s *vtable;
|
||||
int ret = -EINVAL;
|
||||
|
||||
fb = (struct fb_chardev_s *)filep->f_inode->i_private;
|
||||
fb = (struct fb_chardev_s *)((struct drv_data *)filep->f_vnode->data)->priv;
|
||||
if (fb == NULL)
|
||||
{
|
||||
return -ENODEV;
|
||||
@@ -210,10 +208,9 @@ static int fb_close(FAR struct file *filep)
|
||||
* Name: fb_read
|
||||
****************************************************************************/
|
||||
|
||||
static ssize_t fb_read(FAR struct file *filep, FAR char *buffer, size_t len)
|
||||
static ssize_t fb_read(struct file *filep, char *buffer, size_t len)
|
||||
{
|
||||
FAR struct inode *inode;
|
||||
FAR struct fb_chardev_s *fb;
|
||||
struct fb_chardev_s *fb = NULL;
|
||||
size_t start;
|
||||
size_t end;
|
||||
size_t size;
|
||||
@@ -221,10 +218,8 @@ static ssize_t fb_read(FAR struct file *filep, FAR char *buffer, size_t len)
|
||||
|
||||
/* Get the framebuffer instance */
|
||||
|
||||
DEBUGASSERT(filep != NULL && filep->f_inode != NULL);
|
||||
inode = filep->f_inode;
|
||||
fb = (FAR struct fb_chardev_s *)inode->i_private;
|
||||
|
||||
DEBUGASSERT(filep != NULL && filep->f_vnode != NULL);
|
||||
fb = (struct fb_chardev_s *)((struct drv_data *)filep->f_vnode->data)->priv;
|
||||
/* Get the start and size of the transfer */
|
||||
|
||||
start = filep->f_pos;
|
||||
@@ -256,11 +251,10 @@ static ssize_t fb_read(FAR struct file *filep, FAR char *buffer, size_t len)
|
||||
* Name: fb_write
|
||||
****************************************************************************/
|
||||
|
||||
static ssize_t fb_write(FAR struct file *filep, FAR const char *buffer,
|
||||
static ssize_t fb_write(struct file *filep, const char *buffer,
|
||||
size_t len)
|
||||
{
|
||||
FAR struct inode *inode;
|
||||
FAR struct fb_chardev_s *fb;
|
||||
struct fb_chardev_s *fb = NULL;
|
||||
size_t start;
|
||||
size_t end;
|
||||
size_t size;
|
||||
@@ -268,10 +262,8 @@ static ssize_t fb_write(FAR struct file *filep, FAR const char *buffer,
|
||||
|
||||
/* Get the framebuffer instance */
|
||||
|
||||
DEBUGASSERT(filep != NULL && filep->f_inode != NULL);
|
||||
inode = filep->f_inode;
|
||||
fb = (FAR struct fb_chardev_s *)inode->i_private;
|
||||
|
||||
DEBUGASSERT(filep != NULL && filep->f_vnode != NULL);
|
||||
fb = (struct fb_chardev_s *)((struct drv_data *)filep->f_vnode->data)->priv;
|
||||
/* Get the start and size of the transfer */
|
||||
|
||||
start = filep->f_pos;
|
||||
@@ -309,19 +301,16 @@ static ssize_t fb_write(FAR struct file *filep, FAR const char *buffer,
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static off_t fb_seek(FAR struct file *filep, off_t offset, int whence)
|
||||
static off_t fb_seek(struct file *filep, off_t offset, int whence)
|
||||
{
|
||||
FAR struct inode *inode;
|
||||
FAR struct fb_chardev_s *fb;
|
||||
struct fb_chardev_s *fb = NULL;
|
||||
off_t newpos;
|
||||
int ret;
|
||||
|
||||
/* Get the framebuffer instance */
|
||||
|
||||
DEBUGASSERT(filep != NULL && filep->f_inode != NULL);
|
||||
inode = filep->f_inode;
|
||||
fb = (FAR struct fb_chardev_s *)inode->i_private;
|
||||
|
||||
DEBUGASSERT(filep != NULL && filep->f_vnode != NULL);
|
||||
fb = (struct fb_chardev_s *)((struct drv_data *)filep->f_vnode->data)->priv;
|
||||
/* Determine the new, requested file position */
|
||||
|
||||
switch (whence)
|
||||
@@ -378,25 +367,22 @@ static off_t fb_seek(FAR struct file *filep, off_t offset, int whence)
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int fb_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
|
||||
static int fb_ioctl(struct file *filep, int cmd, unsigned long arg)
|
||||
{
|
||||
FAR struct inode *inode;
|
||||
FAR struct fb_chardev_s *fb;
|
||||
struct fb_chardev_s *fb = NULL;
|
||||
int ret;
|
||||
|
||||
/* Get the framebuffer instance */
|
||||
|
||||
DEBUGASSERT(filep != NULL && filep->f_inode != NULL);
|
||||
inode = filep->f_inode;
|
||||
fb = (FAR struct fb_chardev_s *)inode->i_private;
|
||||
|
||||
DEBUGASSERT(filep != NULL && filep->f_vnode != NULL);
|
||||
fb = (struct fb_chardev_s *)((struct drv_data *)filep->f_vnode->data)->priv;
|
||||
/* Process the IOCTL command */
|
||||
|
||||
switch (cmd)
|
||||
{
|
||||
case FIOC_MMAP: /* Get color plane info */
|
||||
{
|
||||
FAR void **ppv = (FAR void **)((uintptr_t)arg);
|
||||
void **ppv = (void **)((uintptr_t)arg);
|
||||
uintptr_t fbmem = (uintptr_t)fb->fbmem;
|
||||
|
||||
/* Return the address corresponding to the start of frame buffer. */
|
||||
@@ -532,7 +518,7 @@ static int fb_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
|
||||
ret = fb->vtable->getplaneinfo(fb->vtable, fb->plane, &pinfo);
|
||||
if (ret >= 0)
|
||||
{
|
||||
nx_notify_rectangle((FAR NX_PLANEINFOTYPE *)&pinfo, &rect);
|
||||
nx_notify_rectangle((NX_PLANEINFOTYPE *)&pinfo, &rect);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -739,7 +725,7 @@ static int fb_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
|
||||
|
||||
int fb_register(int display, int plane)
|
||||
{
|
||||
FAR struct fb_chardev_s *fb;
|
||||
struct fb_chardev_s *fb = NULL;
|
||||
struct fb_videoinfo_s vinfo;
|
||||
struct fb_planeinfo_s pinfo;
|
||||
#ifdef CONFIG_FB_OVERLAY
|
||||
@@ -754,7 +740,7 @@ int fb_register(int display, int plane)
|
||||
|
||||
/* Allocate a framebuffer state instance */
|
||||
|
||||
fb = (FAR struct fb_chardev_s *)malloc(sizeof(struct fb_chardev_s));
|
||||
fb = (struct fb_chardev_s *)malloc(sizeof(struct fb_chardev_s));
|
||||
if (fb == NULL)
|
||||
{
|
||||
return -ENOMEM;
|
||||
@@ -837,7 +823,7 @@ int fb_register(int display, int plane)
|
||||
(void)snprintf(devname, 16, "/dev/fb%d.%d", display, plane);
|
||||
}
|
||||
|
||||
ret = register_driver(devname, &fb_fops, 0666, (FAR void *)fb);
|
||||
ret = register_driver(devname, &fb_fops, 0666, (void *)fb);
|
||||
if (ret < 0)
|
||||
{
|
||||
gerr("ERROR: register_driver() failed: %d\n", ret);
|
||||
@@ -855,7 +841,7 @@ errout_with_fb:
|
||||
|
||||
int fb_unregister(int display)
|
||||
{
|
||||
FAR struct fb_chardev_s *fb;
|
||||
struct fb_chardev_s *fb = NULL;
|
||||
|
||||
if (display < 0 || display >= FB_DEV_MAXNUM)
|
||||
return -EINVAL;
|
||||
|
||||
Executable → Regular
+19
-60
@@ -38,19 +38,12 @@
|
||||
****************************************************************************/
|
||||
|
||||
#include "vfs_config.h"
|
||||
|
||||
#include "dirent.h"
|
||||
#include "errno.h"
|
||||
|
||||
#include "stdlib.h"
|
||||
#include "fs/fs.h"
|
||||
#include "fs/dirent_fs.h"
|
||||
|
||||
#include "inode/inode.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
#include "fs/vnode.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
@@ -73,90 +66,56 @@
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int closedir(FAR DIR *dirp)
|
||||
int closedir(DIR *dirp)
|
||||
{
|
||||
struct fs_dirent_s *idir = (struct fs_dirent_s *)dirp;
|
||||
#ifndef CONFIG_DISABLE_MOUNTPOINT
|
||||
struct inode *inode;
|
||||
#endif
|
||||
struct Vnode *vnode = NULL;
|
||||
int ret;
|
||||
|
||||
/* Verify that we were provided with a valid directory structure */
|
||||
|
||||
if (!idir || idir->fd_status != DIRENT_MAGIC)
|
||||
{
|
||||
ret = EBADF;
|
||||
ret = -EBADF;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* A special case is when we enumerate an "empty", unused inode. That is
|
||||
* an inode in the pseudo-filesystem that has no operations and no children.
|
||||
* This is a "dangling" directory entry that has lost its childre.
|
||||
*/
|
||||
|
||||
if (idir->fd_root)
|
||||
{
|
||||
/* This is the 'root' inode of the directory. This means different
|
||||
/* This is the 'root' vnode of the directory. This means different
|
||||
* things wih different filesystems.
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_DISABLE_MOUNTPOINT
|
||||
inode = idir->fd_root;
|
||||
|
||||
/* The way that we handle the close operation depends on what kind of
|
||||
* root inode we have open.
|
||||
*/
|
||||
|
||||
if (INODE_IS_MOUNTPT(inode) && !DIRENT_ISPSEUDONODE(idir->fd_flags))
|
||||
vnode = idir->fd_root;
|
||||
/* Perform the closedir() operation */
|
||||
if (vnode->vop && vnode->vop->Closedir)
|
||||
{
|
||||
/* The node is a file system mointpoint. Verify that the
|
||||
* mountpoint supports the closedir() method (not an error if it
|
||||
* does not)
|
||||
*/
|
||||
|
||||
if (inode->u.i_mops && inode->u.i_mops->closedir)
|
||||
ret = vnode->vop->Closedir(vnode, idir);
|
||||
if (ret < 0)
|
||||
{
|
||||
/* Perform the closedir() operation */
|
||||
|
||||
ret = inode->u.i_mops->closedir(inode, idir);
|
||||
if (ret < 0)
|
||||
{
|
||||
ret = -ret;
|
||||
goto errout_with_inode;
|
||||
}
|
||||
goto errout_with_vnode;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
/* The node is part of the root pseudo file system, release
|
||||
* our contained reference to the 'next' inode.
|
||||
*/
|
||||
|
||||
if (idir->u.pseudo.fd_next)
|
||||
{
|
||||
inode_release(idir->u.pseudo.fd_next);
|
||||
}
|
||||
ret = -ENOSYS;
|
||||
goto errout_with_vnode;
|
||||
}
|
||||
|
||||
/* Release our references on the contained 'root' inode */
|
||||
|
||||
inode_release(idir->fd_root);
|
||||
VnodeHold();
|
||||
vnode->useCount--;
|
||||
VnodeDrop();
|
||||
}
|
||||
|
||||
/* Then release the container */
|
||||
|
||||
idir->fd_status = 0;
|
||||
free(idir);
|
||||
|
||||
return OK;
|
||||
|
||||
#ifndef CONFIG_DISABLE_MOUNTPOINT
|
||||
errout_with_inode:
|
||||
inode_release(inode);
|
||||
errout_with_vnode:
|
||||
free(idir);
|
||||
#endif
|
||||
|
||||
errout:
|
||||
set_errno(ret);
|
||||
set_errno(-ret);
|
||||
return VFS_ERROR;
|
||||
}
|
||||
|
||||
Executable → Regular
+102
-365
@@ -39,153 +39,15 @@
|
||||
****************************************************************************/
|
||||
|
||||
#include "vfs_config.h"
|
||||
|
||||
#include "dirent.h"
|
||||
#include "string.h"
|
||||
#include "assert.h"
|
||||
#include "errno.h"
|
||||
|
||||
#include "stdlib.h"
|
||||
#include "fs/fs.h"
|
||||
#include "fs/dirent_fs.h"
|
||||
|
||||
#include "inode/inode.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: open_mountpoint
|
||||
*
|
||||
* Description:
|
||||
* Handle the case where the inode to be opened is within a mountpoint.
|
||||
*
|
||||
* Input Parameters:
|
||||
* inode -- the inode of the mountpoint to open
|
||||
* relpath -- the relative path within the mountpoint to open
|
||||
* dir -- the dirent structure to be initialized
|
||||
*
|
||||
* Returned Value:
|
||||
* On success, OK is returned; Otherwise, a positive errno is returned.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef CONFIG_DISABLE_MOUNTPOINT
|
||||
static inline int open_mountpoint(FAR struct inode *inode,
|
||||
FAR const char *relpath,
|
||||
FAR struct fs_dirent_s *dir)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* The inode itself as the 'root' of mounted volume. The actually
|
||||
* directory is at relpath into the* mounted filesystem.
|
||||
*
|
||||
* Verify that the mountpoint inode supports the opendir() method
|
||||
*/
|
||||
|
||||
if (!inode->u.i_mops || !inode->u.i_mops->opendir)
|
||||
{
|
||||
return ENOSYS;
|
||||
}
|
||||
|
||||
/* Take reference to the mountpoint inode. Note that we do not use
|
||||
* inode_addref() because we already hold the tree semaphore.
|
||||
*/
|
||||
|
||||
inode->i_crefs++;
|
||||
|
||||
/* Perform the opendir() operation */
|
||||
|
||||
ret = inode->u.i_mops->opendir(inode, relpath, dir);
|
||||
if (ret < 0)
|
||||
{
|
||||
/* We now need to back off our reference to the inode. We can't
|
||||
* call inode_release() to do that unless we release the tree
|
||||
* semaphore. The following should be safe because: (1) after the
|
||||
* reference count was incremented above it should be >=1 so it should
|
||||
* not decrement below zero, and (2) we hold the tree semaphore so no
|
||||
* other thread should be able to change the reference count.
|
||||
*/
|
||||
|
||||
inode->i_crefs--;
|
||||
DEBUGASSERT(inode->i_crefs >= 0);
|
||||
|
||||
/* Negate the error value so that it can be used to set errno */
|
||||
|
||||
return -ret;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: open_pseudodir
|
||||
*
|
||||
* Description:
|
||||
* Handle the case where the inode to be opened is within the top-level
|
||||
* pseudo-file system.
|
||||
*
|
||||
* Input Parameters:
|
||||
* inode -- the inode of the mountpoint to open
|
||||
* dir -- the dirent structure to be initialized
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void open_pseudodir(FAR struct inode *inode, FAR struct fs_dirent_s *dir)
|
||||
{
|
||||
/* We have a valid pseudo-filesystem node. Take two references on the
|
||||
* inode -- one for the parent (fd_root) and one for the child (fd_next).
|
||||
* Note that we do not call inode_addref because we are holding the tree
|
||||
* semaphore and that would result in deadlock.
|
||||
*/
|
||||
|
||||
inode->i_crefs++;
|
||||
inode->i_child->i_crefs++;
|
||||
dir->fd_root = inode; /* Save the inode where we start */
|
||||
dir->u.pseudo.fd_next = inode->i_child; /* This is the next node to use for readdir() */
|
||||
|
||||
/* Flag the inode as belonging to the pseudo-filesystem */
|
||||
|
||||
#ifndef CONFIG_DISABLE_MOUNTPOINT
|
||||
DIRENT_SETPSEUDONODE(dir->fd_flags);
|
||||
#endif
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: open_emptydir
|
||||
*
|
||||
* Description:
|
||||
* Handle the case where the inode to be opened is an empty, directory node
|
||||
* within the top-level pseudo-file system. That is, it has no operations
|
||||
* and, therefore, it must be a directory node. But is has no children
|
||||
* to be enumerated either.
|
||||
*
|
||||
* Input Parameters:
|
||||
* dir -- the dirent structure to be initialized
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static inline void open_emptydir(FAR struct fs_dirent_s *dir)
|
||||
{
|
||||
/* We have a valid, but empty pseudo-filesystem node. fd_next is NULL
|
||||
* meaning that we are already at the end of the list of its children.
|
||||
* fd_root is NULL so that if the directory is rewound, it will still be
|
||||
* at the end of the list.
|
||||
*/
|
||||
/* Flag the inode as belonging to the pseudo-filesystem */
|
||||
|
||||
#ifndef CONFIG_DISABLE_MOUNTPOINT
|
||||
DIRENT_SETPSEUDONODE(dir->fd_flags);
|
||||
#endif
|
||||
}
|
||||
#include "fs/vnode.h"
|
||||
#include "fs/path_cache.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
@@ -217,141 +79,72 @@ static inline void open_emptydir(FAR struct fs_dirent_s *dir)
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
FAR DIR *opendir(FAR const char *path)
|
||||
DIR *opendir(const char *path)
|
||||
{
|
||||
FAR struct inode *inode;
|
||||
FAR struct fs_dirent_s *dir;
|
||||
FAR const char *relpath;
|
||||
struct Vnode *vp = NULL;
|
||||
struct fs_dirent_s *dir = NULL;
|
||||
int ret;
|
||||
char *fullpath;
|
||||
char *fullpath_bak;
|
||||
|
||||
/* If we are given 'nothing' then we will interpret this as
|
||||
* request for the root inode.
|
||||
*/
|
||||
|
||||
ret = vfs_normalize_path((const char *)NULL, path, &fullpath);
|
||||
if (ret < 0)
|
||||
{
|
||||
ret = -ret;
|
||||
goto errout;
|
||||
}
|
||||
fullpath_bak = fullpath;
|
||||
|
||||
inode_semtake();
|
||||
|
||||
/* 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);
|
||||
|
||||
/* Did we get an inode? */
|
||||
|
||||
if (inode == NULL)
|
||||
VnodeHold();
|
||||
ret = VnodeLookup(path, &vp, 0);
|
||||
if (vp == NULL || ret != OK)
|
||||
{
|
||||
/* 'path' does not exist. */
|
||||
|
||||
ret = ENOTDIR;
|
||||
goto errout_with_semaphore;
|
||||
VnodeDrop();
|
||||
goto errout;
|
||||
}
|
||||
if (vp->type != VNODE_TYPE_DIR)
|
||||
{
|
||||
ret = -ENOTDIR;
|
||||
PRINT_ERR("opendir (%s) failed, err=%d\n", path, ret);
|
||||
VnodeDrop();
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* Allocate a type DIR -- which is little more than an inode
|
||||
* container.
|
||||
*/
|
||||
vp->useCount++;
|
||||
VnodeDrop();
|
||||
|
||||
dir = (FAR struct fs_dirent_s *)zalloc(sizeof(struct fs_dirent_s));
|
||||
/* Allocate a type DIR -- which is little more than an vp container. */
|
||||
dir = (struct fs_dirent_s *)calloc(1, sizeof(struct fs_dirent_s));
|
||||
if (!dir)
|
||||
{
|
||||
/* Insufficient memory to complete the operation. */
|
||||
|
||||
ret = ENOMEM;
|
||||
goto errout_with_semaphore;
|
||||
ret = -ENOMEM;
|
||||
goto errout_with_count;
|
||||
}
|
||||
|
||||
/* Populate the DIR structure and return it to the caller. The way that
|
||||
* we do this depends on whenever this is a "normal" pseudo-file-system
|
||||
* inode or a file system mountpoint.
|
||||
* vp or a file system mountpoint.
|
||||
*/
|
||||
|
||||
dir->fd_position = 0; /* This is the position in the read stream */
|
||||
|
||||
/* The node is part of the root pseudo file system. Does the inode
|
||||
* have a child? If so that the child would be the 'root' of a list
|
||||
* of nodes under the directory.
|
||||
*/
|
||||
|
||||
FAR struct inode *child = inode->i_child;
|
||||
if (!*relpath && child)
|
||||
if (vp->vop != NULL && vp->vop->Opendir != NULL)
|
||||
{
|
||||
/* It looks we have a valid pseudo-filesystem directory node. */
|
||||
|
||||
open_pseudodir(inode, dir);
|
||||
}
|
||||
|
||||
#ifndef CONFIG_DISABLE_MOUNTPOINT
|
||||
if (INODE_IS_MOUNTPT(inode))
|
||||
{
|
||||
/* Yes, the node is a file system mountpoint */
|
||||
|
||||
dir->fd_root = inode; /* Save the inode where we start */
|
||||
|
||||
/* Open the directory at the relative path */
|
||||
|
||||
ret = open_mountpoint(inode, relpath, dir);
|
||||
if (ret != OK)
|
||||
{
|
||||
goto errout_with_direntry;
|
||||
}
|
||||
ret = vp->vop->Opendir(vp, dir);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
|
||||
if (!*relpath && child == NULL)
|
||||
{
|
||||
if (inode->u.i_ops == NULL)
|
||||
{
|
||||
/* This is a dangling node with no children and no operations. Set
|
||||
* up to enumerate an empty directory.
|
||||
*/
|
||||
|
||||
open_emptydir(dir);
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = ENOTDIR;
|
||||
goto errout_with_direntry;
|
||||
}
|
||||
ret = -ENOSYS;
|
||||
}
|
||||
else if (*relpath)
|
||||
if (ret < 0)
|
||||
{
|
||||
ret = ENOENT;
|
||||
goto errout_with_direntry;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
dir->fd_status = DIRENT_MAGIC;
|
||||
inode_semgive();
|
||||
free(fullpath_bak);
|
||||
dir->fd_root = vp;
|
||||
|
||||
return ((DIR *)dir);
|
||||
|
||||
/* Nasty goto's make error handling simpler */
|
||||
|
||||
errout_with_direntry:
|
||||
free(dir);
|
||||
|
||||
errout_with_semaphore:
|
||||
inode_semgive();
|
||||
free(fullpath_bak);
|
||||
|
||||
errout_with_count:
|
||||
VnodeHold();
|
||||
vp->useCount--;
|
||||
VnodeDrop();
|
||||
errout:
|
||||
set_errno(ret);
|
||||
set_errno(-ret);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -359,170 +152,114 @@ int do_opendir(const char *path, int oflags)
|
||||
{
|
||||
int ret;
|
||||
int fd;
|
||||
FAR struct inode *inode = NULL;
|
||||
FAR struct fs_dirent_s *dir = NULL;
|
||||
FAR const char *relpath = NULL;
|
||||
|
||||
struct Vnode *vp = NULL;
|
||||
struct file *filep = NULL;
|
||||
struct fs_dirent_s *dir = NULL;
|
||||
char *fullpath = NULL;
|
||||
FAR struct file *filep = NULL;
|
||||
FAR struct inode *child = NULL;
|
||||
struct inode_search_s desc;
|
||||
char *relativepath = NULL;
|
||||
|
||||
/* If we are given 'nothing' then we will interpret this as
|
||||
* request for the root inode.
|
||||
*/
|
||||
if (path == NULL || *path == 0)
|
||||
{
|
||||
ret = -EINVAL;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
ret = vfs_normalize_path((const char *)NULL, path, &fullpath);
|
||||
ret = get_path_from_fd(AT_FDCWD, &relativepath);
|
||||
if (ret < 0)
|
||||
{
|
||||
ret = -ret;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* We don't know what to do with relative pathes */
|
||||
|
||||
if (*fullpath != '/')
|
||||
ret = vfs_normalize_path((const char *)relativepath, path, &fullpath);
|
||||
if (relativepath)
|
||||
{
|
||||
ret = ENOTDIR;
|
||||
goto errout_with_path;
|
||||
free(relativepath);
|
||||
}
|
||||
|
||||
/* Get an inode for this file */
|
||||
|
||||
SETUP_SEARCH(&desc, fullpath, false);
|
||||
ret = inode_find(&desc);
|
||||
if (ret < 0)
|
||||
{
|
||||
PRINTK("ERROR: Failed to find %s\n", fullpath);
|
||||
|
||||
/* 'path' does not exist. */
|
||||
|
||||
ret = ENOTDIR;
|
||||
goto errout_with_path;
|
||||
goto errout;
|
||||
}
|
||||
inode = desc.node;
|
||||
relpath = desc.relpath;
|
||||
|
||||
/* Associate the inode with a file structure */
|
||||
VnodeHold();
|
||||
/* Get an vnode for this file */
|
||||
ret = VnodeLookup(path, &vp, 0);
|
||||
if (ret < 0)
|
||||
{
|
||||
PRINT_ERR("Failed to find vnode %s\n", path);
|
||||
VnodeDrop();
|
||||
goto errout;
|
||||
}
|
||||
if (vp->type != VNODE_TYPE_DIR)
|
||||
{
|
||||
ret = -ENOTDIR;
|
||||
PRINT_ERR("opendir (%s) failed, err=%d\n", path, ret);
|
||||
VnodeDrop();
|
||||
goto errout;
|
||||
}
|
||||
vp->useCount++;
|
||||
VnodeDrop();
|
||||
|
||||
fd = files_allocate(inode, oflags, 0, NULL, 3); /* 3: file start fd */
|
||||
/* Associate the vnode with a file structure */
|
||||
fd = files_allocate(vp, oflags, 0, NULL, 3); /* 3: file start fd */
|
||||
if (fd < 0)
|
||||
{
|
||||
ret = EMFILE;
|
||||
goto errout_with_inode;
|
||||
ret = -EMFILE;
|
||||
goto errout_with_vnode;
|
||||
}
|
||||
|
||||
/* Get the file structure corresponding to the file descriptor. */
|
||||
|
||||
ret = fs_getfilep(fd, &filep);
|
||||
if (ret < 0)
|
||||
{
|
||||
ret = EPERM;
|
||||
|
||||
/* The errno value has already been set */
|
||||
ret = -EPERM;
|
||||
goto errout_with_fd;
|
||||
}
|
||||
|
||||
/* Perform the driver open operation. NOTE that the open method may be
|
||||
* called many times. The driver/mountpoint logic should handled this
|
||||
* because it may also be closed that many times.
|
||||
*/
|
||||
filep->f_path = (char *)fullpath; /* The mem will free in close(fd); */
|
||||
|
||||
ret = OK;
|
||||
filep->f_path = fullpath; /* The mem will free in close(fd); */
|
||||
filep->f_relpath = relpath;
|
||||
|
||||
/* Allocate a type DIR -- which is little more than an inode
|
||||
* container.
|
||||
*/
|
||||
|
||||
dir = (FAR struct fs_dirent_s *)zalloc(sizeof(struct fs_dirent_s));
|
||||
if (!dir)
|
||||
/* Allocate a type DIR -- which is little more than an vnode container. */
|
||||
dir = (struct fs_dirent_s *)zalloc(sizeof(struct fs_dirent_s));
|
||||
if (dir == NULL)
|
||||
{
|
||||
/* Insufficient memory to complete the operation. */
|
||||
|
||||
ret = ENOMEM;
|
||||
ret = -ENOMEM;
|
||||
goto errout_with_fd;
|
||||
}
|
||||
|
||||
/* Populate the DIR structure and return it to the caller. The way that
|
||||
* we do this depends on whenever this is a "normal" pseudo-file-system
|
||||
* inode or a file system mountpoint.
|
||||
*/
|
||||
|
||||
dir->fd_position = 0; /* This is the position in the read stream */
|
||||
|
||||
/* The node is part of the root pseudo file system. Does the inode
|
||||
* have a child? If so that the child would be the 'root' of a list
|
||||
* of nodes under the directory.
|
||||
*/
|
||||
|
||||
child = inode->i_child;
|
||||
if (!*relpath && child)
|
||||
/* Open the directory at the relative path */
|
||||
if (vp->vop != NULL && vp->vop->Opendir != NULL)
|
||||
{
|
||||
/* It looks we have a valid pseudo-filesystem directory node. */
|
||||
|
||||
open_pseudodir(inode, dir);
|
||||
}
|
||||
|
||||
#ifndef CONFIG_DISABLE_MOUNTPOINT
|
||||
if (INODE_IS_MOUNTPT(inode))
|
||||
{
|
||||
/* Yes, the node is a file system mountpoint */
|
||||
|
||||
dir->fd_root = inode; /* Save the inode where we start */
|
||||
|
||||
/* Open the directory at the relative path */
|
||||
|
||||
ret = open_mountpoint(inode, relpath, dir);
|
||||
if (ret != OK)
|
||||
{
|
||||
goto errout_with_direntry;
|
||||
}
|
||||
ret = vp->vop->Opendir(vp, dir);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
|
||||
if (!*relpath && child == NULL)
|
||||
{
|
||||
if (inode->u.i_ops == NULL)
|
||||
{
|
||||
/* This is a dangling node with no children and no operations. Set
|
||||
* up to enumerate an empty directory.
|
||||
*/
|
||||
|
||||
open_emptydir(dir);
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = ENOTDIR;
|
||||
goto errout_with_direntry;
|
||||
}
|
||||
}
|
||||
else if (*relpath)
|
||||
{
|
||||
ret = ENOENT;
|
||||
goto errout_with_direntry;
|
||||
ret = -ENOSYS;
|
||||
}
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
free(dir);
|
||||
goto errout_with_fd;
|
||||
}
|
||||
|
||||
dir->fd_root = vp;
|
||||
dir->fd_status = DIRENT_MAGIC;
|
||||
filep->f_dir = (struct fs_dirent_s *)dir;
|
||||
filep->f_dir = dir;
|
||||
|
||||
return fd;
|
||||
|
||||
/* Nasty goto's make error handling simpler */
|
||||
|
||||
errout_with_direntry:
|
||||
free(dir);
|
||||
|
||||
errout_with_fd:
|
||||
files_release(fd);
|
||||
|
||||
errout_with_inode:
|
||||
inode_release(inode);
|
||||
|
||||
errout_with_path:
|
||||
free(fullpath);
|
||||
|
||||
errout_with_vnode:
|
||||
VnodeHold();
|
||||
vp->useCount--;
|
||||
VnodeDrop();
|
||||
errout:
|
||||
set_errno(ret);
|
||||
return -1;
|
||||
if (fullpath)
|
||||
{
|
||||
free(fullpath);
|
||||
}
|
||||
set_errno(-ret);
|
||||
return VFS_ERROR;
|
||||
}
|
||||
|
||||
Executable → Regular
+47
-221
@@ -39,151 +39,14 @@
|
||||
****************************************************************************/
|
||||
|
||||
#include "vfs_config.h"
|
||||
|
||||
#include "string.h"
|
||||
#include "dirent.h"
|
||||
#include "errno.h"
|
||||
#include "unistd.h"
|
||||
|
||||
#include "fs/fs.h"
|
||||
#include "fs/dirent_fs.h"
|
||||
|
||||
#include "inode/inode.h"
|
||||
#include "sys/statfs.h"
|
||||
#include "user_copy.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: readpseudodir
|
||||
****************************************************************************/
|
||||
|
||||
static inline int readpseudodir(struct fs_dirent_s *idir)
|
||||
{
|
||||
FAR struct inode *prev;
|
||||
int ret;
|
||||
|
||||
/* Check if we are at the end of the list */
|
||||
|
||||
if (!idir->u.pseudo.fd_next)
|
||||
{
|
||||
/* End of file and error conditions are not distinguishable with
|
||||
* readdir. Here we return -ENOENT to signal the end of the
|
||||
* directory.
|
||||
*/
|
||||
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
/* Copy the inode name into the dirent structure */
|
||||
ret = strncpy_s(idir->fd_dir[0].d_name, NAME_MAX + 1, idir->u.pseudo.fd_next->i_name, NAME_MAX);
|
||||
if (ret != EOK)
|
||||
{
|
||||
return -ENAMETOOLONG;
|
||||
}
|
||||
|
||||
/* If the node has file operations, we will say that it is a file. */
|
||||
|
||||
idir->fd_dir[0].d_type = 0;
|
||||
if (idir->u.pseudo.fd_next->u.i_ops)
|
||||
{
|
||||
#ifndef CONFIG_DISABLE_MOUNTPOINT
|
||||
if (INODE_IS_BLOCK(idir->u.pseudo.fd_next))
|
||||
{
|
||||
idir->fd_dir[0].d_type |= DT_BLK;
|
||||
}
|
||||
if (INODE_IS_MOUNTPT(idir->u.pseudo.fd_next))
|
||||
{
|
||||
idir->fd_dir[0].d_type |= DT_DIR;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
idir->fd_dir[0].d_type |= DT_CHR;
|
||||
}
|
||||
}
|
||||
|
||||
/* If the node has child node(s) or no operations, then we will say that
|
||||
* it is a directory rather than a special file. NOTE: that the node can
|
||||
* be both!
|
||||
*/
|
||||
|
||||
if (idir->u.pseudo.fd_next->i_child || !idir->u.pseudo.fd_next->u.i_ops)
|
||||
{
|
||||
idir->fd_dir[0].d_type |= DT_DIR;
|
||||
}
|
||||
|
||||
/* Now get the inode to vist next time that readdir() is called */
|
||||
|
||||
inode_semtake();
|
||||
|
||||
prev = idir->u.pseudo.fd_next;
|
||||
idir->u.pseudo.fd_next = prev->i_peer; /* The next node to visit */
|
||||
|
||||
if (idir->u.pseudo.fd_next)
|
||||
{
|
||||
/* Increment the reference count on this next node */
|
||||
|
||||
idir->u.pseudo.fd_next->i_crefs++;
|
||||
}
|
||||
|
||||
inode_semgive();
|
||||
|
||||
if (prev)
|
||||
{
|
||||
inode_release(prev);
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: handlezpfsdir
|
||||
* Description:
|
||||
* The handlezpfsdir() function handle with the inode with zpfs magic
|
||||
*
|
||||
* Input Parameters:
|
||||
* idir -- the pointer of one dir
|
||||
*
|
||||
* Returned Value:
|
||||
* none
|
||||
****************************************************************************/
|
||||
#ifdef LOSCFG_FS_ZPFS
|
||||
static inline void handlezpfsdir(struct fs_dirent_s *idir)
|
||||
{
|
||||
struct statfs buf;
|
||||
int ret;
|
||||
/* Maybe there are two or more zpfs nodes together, so we need one loop */
|
||||
do
|
||||
{
|
||||
if (!idir->u.pseudo.fd_next || !INODE_IS_MOUNTPT(idir->u.pseudo.fd_next) ||
|
||||
!idir->u.pseudo.fd_next->u.i_mops || !idir->u.pseudo.fd_next->u.i_mops->statfs)
|
||||
{
|
||||
return;
|
||||
}
|
||||
ret = idir->u.pseudo.fd_next->u.i_mops->statfs(idir->u.pseudo.fd_next, &buf);
|
||||
if (ret != OK || buf.f_type != ZPFS_MAGIC)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (readpseudodir(idir) == OK)
|
||||
{
|
||||
idir->fd_position++;
|
||||
}
|
||||
} while (1);
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: do_readdir
|
||||
*
|
||||
@@ -206,96 +69,63 @@ static inline void handlezpfsdir(struct fs_dirent_s *idir)
|
||||
****************************************************************************/
|
||||
static struct dirent *__readdir(DIR *dirp, int *lencnt)
|
||||
{
|
||||
FAR struct fs_dirent_s *idir = (struct fs_dirent_s *)dirp;
|
||||
struct inode *inode_ptr = NULL;
|
||||
struct fs_dirent_s *idir = (struct fs_dirent_s *)dirp;
|
||||
struct Vnode *vnode_ptr = NULL;
|
||||
int ret = 0;
|
||||
int file_cnt = 0;
|
||||
|
||||
/* Verify that we were provided with a valid directory structure */
|
||||
|
||||
if (!idir || idir->fd_status != DIRENT_MAGIC)
|
||||
if (!idir)
|
||||
{
|
||||
ret = EBADF;
|
||||
ret = -EBADF;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* A special case is when we enumerate an "empty", unused inode. That is
|
||||
* an inode in the pseudo-filesystem that has no operations and no children.
|
||||
* This is a "dangling" directory entry that has lost its children.
|
||||
*/
|
||||
|
||||
inode_ptr = idir->fd_root;
|
||||
if (inode_ptr == NULL)
|
||||
vnode_ptr = idir->fd_root;
|
||||
if (vnode_ptr == NULL)
|
||||
{
|
||||
/* End of file and error conditions are not distinguishable
|
||||
* with readdir. We return NULL to signal either case.
|
||||
*/
|
||||
|
||||
ret = ENOENT;
|
||||
ret = -ENOENT;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* The way we handle the readdir depends on the type of inode
|
||||
* that we are dealing with.
|
||||
*/
|
||||
if (DIRENT_ISPSEUDONODE(idir->fd_flags))
|
||||
{
|
||||
#ifdef LOSCFG_FS_ZPFS
|
||||
/* if the current node has the zpfs magic, we continue to skip the node */
|
||||
handlezpfsdir(idir);
|
||||
#endif
|
||||
/* The node is part of the root pseudo file system */
|
||||
|
||||
ret = readpseudodir(idir);
|
||||
if (ret == OK)
|
||||
{
|
||||
idir->fd_position++;
|
||||
idir->fd_dir[0].d_off = idir->fd_position;
|
||||
idir->fd_dir[0].d_reclen = (uint16_t)sizeof(struct dirent);
|
||||
*lencnt = sizeof(struct dirent);
|
||||
return &(idir->fd_dir[0]);
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef CONFIG_DISABLE_MOUNTPOINT
|
||||
if (INODE_IS_MOUNTPT(inode_ptr))
|
||||
{
|
||||
/* The node is a file system mointpoint. Verify that the mountpoint
|
||||
* supports the readdir() method
|
||||
*/
|
||||
if (!inode_ptr->u.i_mops || !inode_ptr->u.i_mops->readdir)
|
||||
{
|
||||
ret = EACCES;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* Perform the readdir() operation */
|
||||
/* Perform the readdir() operation */
|
||||
#ifdef LOSCFG_ENABLE_READ_BUFFER
|
||||
idir->read_cnt = MAX_DIRENT_NUM;
|
||||
idir->read_cnt = MAX_DIRENT_NUM;
|
||||
#else
|
||||
idir->read_cnt = 1;
|
||||
idir->read_cnt = 1;
|
||||
#endif
|
||||
file_cnt = inode_ptr->u.i_mops->readdir(inode_ptr, idir);
|
||||
if (file_cnt > 0)
|
||||
{
|
||||
*lencnt = file_cnt * sizeof(struct dirent);
|
||||
return &(idir->fd_dir[0]);
|
||||
}
|
||||
|
||||
if (vnode_ptr->vop != NULL && vnode_ptr->vop->Readdir != NULL)
|
||||
{
|
||||
file_cnt = vnode_ptr->vop->Readdir(vnode_ptr, idir);
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = -ENOSYS;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
if (file_cnt > 0)
|
||||
{
|
||||
*lencnt = file_cnt * sizeof(struct dirent);
|
||||
return &(idir->fd_dir[0]);
|
||||
}
|
||||
#endif
|
||||
|
||||
errout:
|
||||
if (ret != OK)
|
||||
if (ret < 0)
|
||||
{
|
||||
if (ret < 0)
|
||||
{
|
||||
ret = -ret;
|
||||
}
|
||||
set_errno(ret);
|
||||
}
|
||||
else if (file_cnt <= 0)
|
||||
{
|
||||
set_errno(ENOENT);
|
||||
}
|
||||
|
||||
return (struct dirent *)NULL;
|
||||
}
|
||||
|
||||
@@ -323,33 +153,30 @@ errout:
|
||||
* EBADF - Invalid directory stream descriptor dir
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
FAR struct dirent *readdir(DIR *dirp)
|
||||
struct dirent *readdir(DIR *dirp)
|
||||
{
|
||||
int ret;
|
||||
int old_err = get_errno();
|
||||
int lencnt = 0;
|
||||
int dirent_len = 0;
|
||||
struct dirent *de = NULL;
|
||||
FAR struct fs_dirent_s *idir = (struct fs_dirent_s *)dirp;
|
||||
int dirlen;
|
||||
struct fs_dirent_s *idir = (struct fs_dirent_s *)dirp;
|
||||
|
||||
#ifdef LOSCFG_ENABLE_READ_BUFFER
|
||||
dirlen = MAX_DIRENT_NUM;
|
||||
#else
|
||||
dirlen = 1;
|
||||
#endif
|
||||
if (idir->cur_pos != 0 && idir->cur_pos < dirlen && idir->cur_pos < idir->end_pos)
|
||||
if (idir->cur_pos != 0 && idir->cur_pos < MAX_DIRENT_NUM && idir->cur_pos < idir->end_pos)
|
||||
{
|
||||
de = &(idir->fd_dir[idir->cur_pos]);
|
||||
if (idir->cur_pos == dirlen)
|
||||
|
||||
if (idir->cur_pos == MAX_DIRENT_NUM)
|
||||
{
|
||||
idir->cur_pos = 0;
|
||||
}
|
||||
idir->cur_pos++;
|
||||
|
||||
return de;
|
||||
} else {
|
||||
de = __readdir(dirp, &lencnt);
|
||||
idir->end_pos = lencnt / sizeof(struct dirent);
|
||||
}
|
||||
else
|
||||
{
|
||||
de = __readdir(dirp, &dirent_len);
|
||||
idir->end_pos = dirent_len / sizeof(struct dirent);
|
||||
idir->cur_pos = 1;
|
||||
|
||||
if (de == NULL)
|
||||
@@ -372,18 +199,18 @@ FAR struct dirent *readdir(DIR *dirp)
|
||||
int do_readdir(int fd, struct dirent **de, unsigned int count)
|
||||
{
|
||||
struct dirent *de_src = NULL;
|
||||
int lencnt = 0;
|
||||
int de_len = 0;
|
||||
/* Did we get a valid file descriptor? */
|
||||
|
||||
#if CONFIG_NFILE_DESCRIPTORS > 0
|
||||
FAR struct file *filep = NULL;
|
||||
struct file *filep = NULL;
|
||||
|
||||
if (de == NULL)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if ((unsigned int)fd >= CONFIG_NFILE_DESCRIPTORS)
|
||||
if ((fd < 3) || (unsigned int)fd >= CONFIG_NFILE_DESCRIPTORS)
|
||||
{
|
||||
return -EBADF;
|
||||
}
|
||||
@@ -401,7 +228,8 @@ int do_readdir(int fd, struct dirent **de, unsigned int count)
|
||||
}
|
||||
|
||||
/* Then let do_readdir do all of the work */
|
||||
de_src = __readdir(filep->f_dir, &lencnt);
|
||||
|
||||
de_src = __readdir(filep->f_dir, &de_len);
|
||||
if (de_src == NULL)
|
||||
{
|
||||
/* Special case: ret = -ENOENT is end of file */
|
||||
@@ -409,10 +237,8 @@ int do_readdir(int fd, struct dirent **de, unsigned int count)
|
||||
}
|
||||
*de = de_src;
|
||||
|
||||
lencnt = (lencnt != 0) ? lencnt : sizeof(*de_src);
|
||||
return lencnt;
|
||||
return de_len;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
return OK;
|
||||
}
|
||||
|
||||
Executable → Regular
+13
-71
@@ -38,49 +38,11 @@
|
||||
****************************************************************************/
|
||||
|
||||
#include "vfs_config.h"
|
||||
|
||||
#include "dirent.h"
|
||||
#include "errno.h"
|
||||
|
||||
#include "fs/fs.h"
|
||||
#include "fs/dirent_fs.h"
|
||||
|
||||
#include "inode/inode.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: rewindpseudodir
|
||||
****************************************************************************/
|
||||
|
||||
static inline void rewindpseudodir(struct fs_dirent_s *idir)
|
||||
{
|
||||
struct inode *prev;
|
||||
|
||||
inode_semtake();
|
||||
|
||||
/* Reset the position to the beginning */
|
||||
|
||||
prev = idir->u.pseudo.fd_next; /* (Save to delete later) */
|
||||
idir->u.pseudo.fd_next = idir->fd_root->i_child; /* The next node to visit */
|
||||
idir->fd_position = 0; /* Reset position */
|
||||
|
||||
/* Increment the reference count on the root=next node. We
|
||||
* should now have two references on the inode.
|
||||
*/
|
||||
|
||||
idir->fd_root->i_child->i_crefs++;
|
||||
inode_semgive();
|
||||
|
||||
/* Then release the reference to the old next inode */
|
||||
|
||||
if (prev != NULL)
|
||||
{
|
||||
inode_release(prev);
|
||||
}
|
||||
}
|
||||
#include "fs/vnode.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
@@ -102,19 +64,10 @@ static inline void rewindpseudodir(struct fs_dirent_s *idir)
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void rewinddir(FAR DIR *dirp)
|
||||
void rewinddir(DIR *dirp)
|
||||
{
|
||||
struct fs_dirent_s *idir = (struct fs_dirent_s *)dirp;
|
||||
#ifndef CONFIG_DISABLE_MOUNTPOINT
|
||||
struct inode *inode_ptr;
|
||||
#endif
|
||||
|
||||
/* Verify that we were provided with a valid directory structure,
|
||||
* A special case is when we enumerate an "empty", unused inode (fd_root
|
||||
* == 0). That is an inode in the pseudo-filesystem that has no
|
||||
* operations and no children. This is a "dangling" directory entry that
|
||||
* has lost its children.
|
||||
*/
|
||||
struct Vnode *vnode_ptr = NULL;
|
||||
|
||||
if (!idir || !idir->fd_root || idir->fd_status != DIRENT_MAGIC)
|
||||
{
|
||||
@@ -122,34 +75,23 @@ void rewinddir(FAR DIR *dirp)
|
||||
return;
|
||||
}
|
||||
|
||||
/* The way we handle the readdir depends on the type of inode
|
||||
/* The way we handle the readdir depends on the type of vnode
|
||||
* that we are dealing with.
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_DISABLE_MOUNTPOINT
|
||||
inode_ptr = idir->fd_root;
|
||||
if (INODE_IS_MOUNTPT(inode_ptr))
|
||||
vnode_ptr = idir->fd_root;
|
||||
if (vnode_ptr->vop != NULL && vnode_ptr->vop->Rewinddir != NULL)
|
||||
{
|
||||
/* The node is a file system mointpoint. Verify that the mountpoint
|
||||
* supports the rewinddir() method
|
||||
*/
|
||||
/* Perform the rewinddir() operation */
|
||||
|
||||
if (inode_ptr->u.i_mops && inode_ptr->u.i_mops->rewinddir)
|
||||
{
|
||||
/* Perform the rewinddir() operation */
|
||||
|
||||
(void)inode_ptr->u.i_mops->rewinddir(inode_ptr, idir);
|
||||
}
|
||||
|
||||
/* Reset position for telldir() */
|
||||
|
||||
idir->fd_position = 0;
|
||||
vnode_ptr->vop->Rewinddir(vnode_ptr, idir);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
/* The node is part of the root pseudo file system */
|
||||
|
||||
rewindpseudodir(idir);
|
||||
set_errno(ENOSYS);
|
||||
}
|
||||
|
||||
/* Reset position for telldir() */
|
||||
|
||||
idir->fd_position = 0;
|
||||
}
|
||||
|
||||
Executable → Regular
+8
-95
@@ -38,85 +38,23 @@
|
||||
****************************************************************************/
|
||||
|
||||
#include "vfs_config.h"
|
||||
|
||||
#include "sys/types.h"
|
||||
#include "dirent.h"
|
||||
#include "errno.h"
|
||||
|
||||
#include "fs/fs.h"
|
||||
#include "fs/dirent_fs.h"
|
||||
|
||||
#include "inode/inode.h"
|
||||
#include "fs/vnode.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: seekpseudodir
|
||||
****************************************************************************/
|
||||
|
||||
static inline void seekpseudodir(struct fs_dirent_s *idir, off_t offset)
|
||||
{
|
||||
struct inode *curr;
|
||||
struct inode *prev;
|
||||
off_t pos;
|
||||
|
||||
/* Determine a starting point for the seek. If the seek
|
||||
* is "forward" from the current position, then we will
|
||||
* start at the current poisition. Otherwise, we will
|
||||
* "rewind" to the root dir.
|
||||
*/
|
||||
|
||||
if (offset < idir->fd_position)
|
||||
{
|
||||
pos = 0;
|
||||
curr = idir->fd_root->i_child;
|
||||
}
|
||||
else
|
||||
{
|
||||
pos = idir->fd_position;
|
||||
curr = idir->u.pseudo.fd_next;
|
||||
}
|
||||
|
||||
/* Traverse the peer list starting at the 'root' of the
|
||||
* the list until we find the node at 'offset". If devices
|
||||
* are being registered and unregistered, then this can
|
||||
* be a very unpredictable operation.
|
||||
*/
|
||||
|
||||
inode_semtake();
|
||||
for (; curr && pos != offset; pos++, curr = curr->i_peer);
|
||||
|
||||
/* Now get the inode to vist next time that readdir() is called */
|
||||
|
||||
prev = idir->u.pseudo.fd_next;
|
||||
idir->u.pseudo.fd_next = curr; /* The next node to visit (might be null) */
|
||||
idir->fd_position = pos; /* Might be beyond the last dirent */
|
||||
|
||||
if (curr)
|
||||
{
|
||||
/* Increment the reference count on this next node */
|
||||
|
||||
curr->i_crefs++;
|
||||
}
|
||||
|
||||
inode_semgive();
|
||||
|
||||
if (prev)
|
||||
{
|
||||
inode_release(prev);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: seekmountptdir
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef CONFIG_DISABLE_MOUNTPOINT
|
||||
static inline void seekmountptdir(struct fs_dirent_s *idir, off_t offset)
|
||||
{
|
||||
struct inode *inode;
|
||||
struct Vnode *vnode;
|
||||
off_t pos;
|
||||
|
||||
/* Determine a starting point for the seek. If the seek
|
||||
@@ -125,14 +63,14 @@ static inline void seekmountptdir(struct fs_dirent_s *idir, off_t offset)
|
||||
* "rewind" to the root dir.
|
||||
*/
|
||||
|
||||
inode = idir->fd_root;
|
||||
vnode = idir->fd_root;
|
||||
if (offset < idir->fd_position)
|
||||
{
|
||||
if (inode->u.i_mops && inode->u.i_mops->rewinddir)
|
||||
if (vnode->vop != NULL && vnode->vop->Rewinddir != NULL)
|
||||
{
|
||||
/* Perform the rewinddir() operation */
|
||||
|
||||
inode->u.i_mops->rewinddir(inode, idir);
|
||||
vnode->vop->Rewinddir(vnode, idir);
|
||||
pos = 0;
|
||||
}
|
||||
else
|
||||
@@ -157,8 +95,8 @@ static inline void seekmountptdir(struct fs_dirent_s *idir, off_t offset)
|
||||
|
||||
while (pos < offset)
|
||||
{
|
||||
if (!inode->u.i_mops || !inode->u.i_mops->readdir ||
|
||||
inode->u.i_mops->readdir(inode, idir) <= 0)
|
||||
if (!vnode->vop || !vnode->vop->Readdir ||
|
||||
vnode->vop->Readdir(vnode, idir) <= 0)
|
||||
{
|
||||
/* We can't read the next entry and there is no way to return
|
||||
* an error indication.
|
||||
@@ -175,7 +113,6 @@ static inline void seekmountptdir(struct fs_dirent_s *idir, off_t offset)
|
||||
/* If we get here the directory position has been successfully set */
|
||||
idir->fd_position = pos;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
@@ -203,13 +140,6 @@ void seekdir(DIR *dirp, long offset)
|
||||
{
|
||||
struct fs_dirent_s *idir = (struct fs_dirent_s *)dirp;
|
||||
|
||||
/* Verify that we were provided with a valid directory structure,
|
||||
* A special case is when we enumerate an "empty", unused inode (fd_root
|
||||
* == 0). That is an inode in the pseudo-filesystem that has no
|
||||
* operations and no children. This is a "dangling" directory entry that
|
||||
* has lost its children.
|
||||
*/
|
||||
|
||||
if (!idir || !idir->fd_root || idir->fd_status != DIRENT_MAGIC)
|
||||
{
|
||||
set_errno(EBADF);
|
||||
@@ -222,22 +152,5 @@ void seekdir(DIR *dirp, long offset)
|
||||
return;
|
||||
}
|
||||
|
||||
/* The way we handle the readdir depends on the type of inode
|
||||
* that we are dealing with.
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_DISABLE_MOUNTPOINT
|
||||
if (INODE_IS_MOUNTPT(idir->fd_root))
|
||||
{
|
||||
/* The node is a file system mointpoint */
|
||||
|
||||
seekmountptdir(idir, offset);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
/* The node is part of the root pseudo file system */
|
||||
|
||||
seekpseudodir(idir, offset);
|
||||
}
|
||||
seekmountptdir(idir, offset);
|
||||
}
|
||||
|
||||
Executable → Regular
-1
@@ -45,7 +45,6 @@
|
||||
#include "fs/fs.h"
|
||||
#include "fs/dirent_fs.h"
|
||||
|
||||
#include "inode/inode.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
|
||||
+14
-17
@@ -169,7 +169,9 @@ static char *unique_chardev(void)
|
||||
|
||||
int block_proxy(FAR const char *blkdev, int oflags)
|
||||
{
|
||||
FAR char *chardev;
|
||||
struct file *filep = NULL;
|
||||
struct Vnode *vnode = NULL;
|
||||
char *chardev;
|
||||
bool readonly;
|
||||
int ret;
|
||||
int fd;
|
||||
@@ -211,23 +213,21 @@ int block_proxy(FAR const char *blkdev, int oflags)
|
||||
goto errout_with_bchdev;
|
||||
}
|
||||
|
||||
/* Unlink the character device name. The driver instance will persist,
|
||||
* provided that CONFIG_DISABLE_PSEUDOFS_OPERATIONS=y (otherwise, we have
|
||||
* a problem here!)
|
||||
*/
|
||||
|
||||
ret = unlink(chardev);
|
||||
ret = fs_getfilep(fd, &filep);
|
||||
if (ret < 0)
|
||||
{
|
||||
ret = -errno;
|
||||
PRINTK("ERROR: Failed to unlink %s: %d\n", chardev, ret);
|
||||
files_release(fd);
|
||||
ret = -get_errno();
|
||||
goto errout_with_bchdev;
|
||||
}
|
||||
|
||||
ret = unregister_driver(chardev);
|
||||
if (ret < 0 && ret != -EBUSY)
|
||||
{
|
||||
PRINTK("ERROR: Failed to unregister %s: %d\n", chardev, ret);
|
||||
}
|
||||
vnode = filep->f_vnode;
|
||||
VnodeHold();
|
||||
vnode->type = VNODE_TYPE_BCHR;
|
||||
VnodeDrop();
|
||||
|
||||
/* Block char device is no need for file mapping */
|
||||
(void)remove_mapping(chardev);
|
||||
|
||||
/* Free the allocate character driver name and return the open file
|
||||
* descriptor.
|
||||
@@ -238,10 +238,7 @@ int block_proxy(FAR const char *blkdev, int oflags)
|
||||
return fd;
|
||||
|
||||
errout_with_bchdev:
|
||||
(void)bchdev_unregister(chardev);
|
||||
(void)unlink(chardev);
|
||||
(void)unregister_driver(chardev);
|
||||
|
||||
errout_with_chardev:
|
||||
(void)free(chardev);
|
||||
(void)sem_destroy(&g_devno_sem);
|
||||
|
||||
Executable → Regular
+24
-23
@@ -39,11 +39,9 @@
|
||||
|
||||
#include "fs/fs.h"
|
||||
#include "vfs_config.h"
|
||||
|
||||
#include "debug.h"
|
||||
#include "errno.h"
|
||||
|
||||
#include "inode/inode.h"
|
||||
#include "fs/vnode.h"
|
||||
#include "disk.h"
|
||||
|
||||
/****************************************************************************
|
||||
@@ -54,56 +52,57 @@
|
||||
* Name: close_blockdriver
|
||||
*
|
||||
* Description:
|
||||
* Call the close method and release the inode
|
||||
* Call the close method and release the vnode
|
||||
*
|
||||
* Input Parameters:
|
||||
* inode - reference to the inode of a block driver opened by open_blockdriver
|
||||
* vnode - reference to the vnode of a block driver opened by open_blockdriver
|
||||
*
|
||||
* Returned Value:
|
||||
* Returns zero on success or a negated errno on failure:
|
||||
*
|
||||
* EINVAL - inode is NULL
|
||||
* ENOTBLK - The inode is not a block driver
|
||||
* EINVAL - vnode is NULL
|
||||
* ENOTBLK - The vnode is not a block driver
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int close_blockdriver(FAR struct inode *inode_ptr)
|
||||
int close_blockdriver(struct Vnode *vnode_ptr)
|
||||
{
|
||||
#ifdef VFS_IMPL_LATER
|
||||
int ret = 0; /* Assume success */
|
||||
los_part *part = NULL;
|
||||
los_disk *disk = NULL;
|
||||
|
||||
/* Sanity checks */
|
||||
|
||||
if (!inode_ptr || !inode_ptr->u.i_bops)
|
||||
if (!vnode_ptr || !vnode_ptr->u.i_bops)
|
||||
{
|
||||
ret = -EINVAL;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* Verify that the inode is a block driver. */
|
||||
/* Verify that the vnode is a block driver. */
|
||||
|
||||
if (!INODE_IS_BLOCK(inode_ptr))
|
||||
if (!INODE_IS_BLOCK(vnode_ptr))
|
||||
{
|
||||
fdbg("inode is not a block driver\n");
|
||||
fdbg("vnode is not a block driver\n");
|
||||
ret = -ENOTBLK;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
part = los_part_find(inode_ptr);
|
||||
part = los_part_find(vnode_ptr);
|
||||
if (part != NULL)
|
||||
{
|
||||
disk = get_disk(part->disk_id);
|
||||
if (disk == NULL)
|
||||
{
|
||||
ret = -EINVAL;
|
||||
goto errout_with_inode;
|
||||
goto errout_with_vnode;
|
||||
}
|
||||
|
||||
if (pthread_mutex_lock(&disk->disk_mutex) != ENOERR)
|
||||
{
|
||||
PRINT_ERR("%s %d, mutex lock fail!\n", __FUNCTION__, __LINE__);
|
||||
inode_release(inode_ptr);
|
||||
vnode_release(vnode_ptr);
|
||||
return -1;
|
||||
}
|
||||
if (disk->disk_status == STAT_INUSED)
|
||||
@@ -113,34 +112,36 @@ int close_blockdriver(FAR struct inode *inode_ptr)
|
||||
* if needed.
|
||||
*/
|
||||
|
||||
if (inode_ptr->u.i_bops->close != NULL)
|
||||
if (vnode_ptr->u.i_bops->close != NULL)
|
||||
{
|
||||
ret = inode_ptr->u.i_bops->close(inode_ptr);
|
||||
ret = vnode_ptr->u.i_bops->close(vnode_ptr);
|
||||
}
|
||||
}
|
||||
|
||||
if (pthread_mutex_unlock(&disk->disk_mutex) != ENOERR)
|
||||
{
|
||||
PRINT_ERR("%s %d, mutex unlock fail!\n", __FUNCTION__, __LINE__);
|
||||
inode_release(inode_ptr);
|
||||
vnode_release(vnode_ptr);
|
||||
return -1;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((inode_ptr->i_flags & FSNODEFLAG_DELETED) == 0 && inode_ptr->u.i_bops->close != NULL)
|
||||
if ((vnode_ptr->i_flags & FSNODEFLAG_DELETED) == 0 && vnode_ptr->u.i_bops->close != NULL)
|
||||
{
|
||||
ret = inode_ptr->u.i_bops->close(inode_ptr);
|
||||
ret = vnode_ptr->u.i_bops->close(vnode_ptr);
|
||||
}
|
||||
}
|
||||
|
||||
errout_with_inode:
|
||||
errout_with_vnode:
|
||||
|
||||
/* Then release the reference on the inode */
|
||||
/* Then release the reference on the vnode */
|
||||
|
||||
inode_release(inode_ptr);
|
||||
vnode_release(vnode_ptr);
|
||||
|
||||
errout:
|
||||
return ret;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
Executable → Regular
Executable → Regular
+46
-4
@@ -39,15 +39,12 @@
|
||||
|
||||
#include "vfs_config.h"
|
||||
|
||||
#include "driver/driver.h"
|
||||
#include "sys/types.h"
|
||||
#include "sys/mount.h"
|
||||
#include "debug.h"
|
||||
#include "errno.h"
|
||||
|
||||
#include "fs/fs.h"
|
||||
|
||||
#include "inode/inode.h"
|
||||
#include "driver/driver.h"
|
||||
#include "string.h"
|
||||
|
||||
/****************************************************************************
|
||||
@@ -75,7 +72,51 @@
|
||||
* support write access
|
||||
*
|
||||
****************************************************************************/
|
||||
int find_blockdriver(const char *pathname, int mountflags, struct Vnode **vpp)
|
||||
{
|
||||
int ret;
|
||||
struct Vnode *vp = NULL;
|
||||
|
||||
/* Sanity checks */
|
||||
|
||||
/* Find the vnode registered with this pathname */
|
||||
VnodeHold();
|
||||
ret = VnodeLookup(pathname, &vp, V_DUMMY);
|
||||
if (ret < 0)
|
||||
{
|
||||
ret = -EACCES;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* Verify that the vnode is a block driver. */
|
||||
if (vp->type != VNODE_TYPE_BLK)
|
||||
{
|
||||
fdbg("%s is not a block driver\n", pathname);
|
||||
ret = -ENOTBLK;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* Make sure that the vnode supports the requested access */
|
||||
|
||||
struct block_operations *i_bops = (struct block_operations *)((struct drv_data *)vp->data)->ops;
|
||||
|
||||
if (i_bops == NULL || i_bops->read == NULL || (i_bops->write == NULL && (mountflags & MS_RDONLY) == 0))
|
||||
{
|
||||
fdbg("%s does not support requested access\n", pathname);
|
||||
ret = -EACCES;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
*vpp = vp;
|
||||
VnodeDrop();
|
||||
return OK;
|
||||
|
||||
errout:
|
||||
VnodeDrop();
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef VFS_IMPL_LATER
|
||||
int find_blockdriver(FAR const char *pathname, int mountflags,
|
||||
FAR struct inode **ppinode)
|
||||
{
|
||||
@@ -132,3 +173,4 @@ errout_with_inode:
|
||||
errout:
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
Executable → Regular
+28
-26
@@ -38,14 +38,13 @@
|
||||
****************************************************************************/
|
||||
|
||||
#include "vfs_config.h"
|
||||
|
||||
#include "debug.h"
|
||||
#include "errno.h"
|
||||
#include "fs/fs.h"
|
||||
|
||||
#include "inode/inode.h"
|
||||
#include "fs/vnode.h"
|
||||
#include "driver/driver.h"
|
||||
#include "disk.h"
|
||||
#include <linux/kernel.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
@@ -55,29 +54,32 @@
|
||||
* Name: open_blockdriver
|
||||
*
|
||||
* Description:
|
||||
* Return the inode of the block driver specified by 'pathname'
|
||||
* Return the vnode of the block driver specified by 'pathname'
|
||||
*
|
||||
* Input Parameters:
|
||||
* pathname - the full path to the block driver to be opened
|
||||
* mountflags - if MS_RDONLY is not set, then driver must support write
|
||||
* operations (see include/sys/mount.h)
|
||||
* ppinode - address of the location to return the inode reference
|
||||
* ppvnode - address of the location to return the vnode reference
|
||||
*
|
||||
* Returned Value:
|
||||
* Returns zero on success or a negated errno on failure:
|
||||
*
|
||||
* EINVAL - pathname or pinode is NULL
|
||||
* EINVAL - pathname or pvnode is NULL
|
||||
* ENOENT - No block driver of this name is registered
|
||||
* ENOTBLK - The inode associated with the pathname is not a block driver
|
||||
* ENOTBLK - The vnode associated with the pathname is not a block driver
|
||||
* EACCESS - The MS_RDONLY option was not set but this driver does not
|
||||
* support write access
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int open_blockdriver(FAR const char *pathname, int mountflags,
|
||||
FAR struct inode **ppinode)
|
||||
|
||||
extern int find_blockdriver(const char *pathname, int mountflags, struct Vnode **vpp);
|
||||
|
||||
int open_blockdriver(const char *pathname, int mountflags,
|
||||
struct Vnode **ppvnode)
|
||||
{
|
||||
FAR struct inode *inode_ptr = NULL;
|
||||
struct Vnode *vnode_ptr = NULL;
|
||||
los_part *part = NULL;
|
||||
los_disk *disk = NULL;
|
||||
int ret;
|
||||
@@ -85,18 +87,18 @@ int open_blockdriver(FAR const char *pathname, int mountflags,
|
||||
/* Minimal sanity checks */
|
||||
|
||||
#ifdef CONFIG_DEBUG
|
||||
if (ppinode == NULL)
|
||||
if (ppvnode == NULL)
|
||||
{
|
||||
ret = -EINVAL;
|
||||
goto errout;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Find the inode associated with this block driver name. find_blockdriver
|
||||
/* Find the vnode associated with this block driver name. find_blockdriver
|
||||
* will perform all additional error checking.
|
||||
*/
|
||||
|
||||
ret = find_blockdriver(pathname, mountflags, &inode_ptr);
|
||||
ret = find_blockdriver(pathname, mountflags, &vnode_ptr);
|
||||
if (ret < 0)
|
||||
{
|
||||
fdbg("Failed to file %s block driver\n", pathname);
|
||||
@@ -108,33 +110,35 @@ int open_blockdriver(FAR const char *pathname, int mountflags,
|
||||
* if needed.
|
||||
*/
|
||||
|
||||
part = los_part_find(inode_ptr);
|
||||
struct drv_data* drv = (struct drv_data*)vnode_ptr->data;
|
||||
struct block_operations *ops = (struct block_operations *)drv->ops;
|
||||
|
||||
part = los_part_find(vnode_ptr);
|
||||
if (part != NULL)
|
||||
{
|
||||
disk = get_disk(part->disk_id);
|
||||
if (disk == NULL)
|
||||
{
|
||||
ret = -EINVAL;
|
||||
goto errout_with_inode;
|
||||
goto errout_with_vnode;
|
||||
}
|
||||
|
||||
if (pthread_mutex_lock(&disk->disk_mutex) != ENOERR)
|
||||
{
|
||||
PRINT_ERR("%s %d, mutex lock fail!\n", __FUNCTION__, __LINE__);
|
||||
inode_release(inode_ptr);
|
||||
return -1;
|
||||
}
|
||||
if (disk->disk_status == STAT_INUSED)
|
||||
{
|
||||
|
||||
if (inode_ptr->u.i_bops->open != NULL)
|
||||
if (ops->open != NULL)
|
||||
{
|
||||
ret = inode_ptr->u.i_bops->open(inode_ptr);
|
||||
ret = ops->open(vnode_ptr);
|
||||
if (ret < 0)
|
||||
{
|
||||
fdbg("%s driver open failed\n", pathname);
|
||||
(void)pthread_mutex_unlock(&disk->disk_mutex);
|
||||
goto errout_with_inode;
|
||||
goto errout_with_vnode;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -142,29 +146,27 @@ int open_blockdriver(FAR const char *pathname, int mountflags,
|
||||
if (pthread_mutex_unlock(&disk->disk_mutex) != ENOERR)
|
||||
{
|
||||
PRINT_ERR("%s %d, mutex unlock fail!\n", __FUNCTION__, __LINE__);
|
||||
inode_release(inode_ptr);
|
||||
return -1;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((inode_ptr->i_flags & FSNODEFLAG_DELETED) == 0 && inode_ptr->u.i_bops->open != NULL)
|
||||
if (ops->open != NULL)
|
||||
{
|
||||
ret = inode_ptr->u.i_bops->open(inode_ptr);
|
||||
ret = ops->open(vnode_ptr);
|
||||
if (ret < 0)
|
||||
{
|
||||
fdbg("%s driver open failed\n", pathname);
|
||||
goto errout_with_inode;
|
||||
goto errout_with_vnode;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*ppinode = inode_ptr;
|
||||
*ppvnode = vnode_ptr;
|
||||
return OK;
|
||||
|
||||
errout_with_inode:
|
||||
inode_release(inode_ptr);
|
||||
errout_with_vnode:
|
||||
errout:
|
||||
return ret;
|
||||
}
|
||||
|
||||
Executable → Regular
+32
-29
@@ -38,14 +38,16 @@
|
||||
****************************************************************************/
|
||||
|
||||
#include "vfs_config.h"
|
||||
|
||||
#include "sys/types.h"
|
||||
#include "errno.h"
|
||||
|
||||
#include "fs/fs.h"
|
||||
|
||||
#include "inode/inode.h"
|
||||
#include "fs/vnode.h"
|
||||
#include "string.h"
|
||||
#include "fs/vfs_util.h"
|
||||
#include "fs/path_cache.h"
|
||||
#include "fs/vnode.h"
|
||||
#include "limits.h"
|
||||
|
||||
|
||||
#ifndef CONFIG_DISABLE_MOUNTPOINT
|
||||
|
||||
@@ -57,62 +59,63 @@
|
||||
* Name: register_blockdriver
|
||||
*
|
||||
* Description:
|
||||
* Register a block driver inode the pseudo file system.
|
||||
* Register a block driver vnode the pseudo file system.
|
||||
*
|
||||
* Input parameters:
|
||||
* path - The path to the inode to create
|
||||
* path - The path to the vnode to create
|
||||
* bops - The block driver operations structure
|
||||
* mode - inmode priviledges (not used)
|
||||
* priv - Private, user data that will be associated with the inode.
|
||||
* priv - Private, user data that will be associated with the vnode.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero on success (with the inode point in 'inode'); A negated errno
|
||||
* Zero on success (with the vnode point in 'vnode'); A negated errno
|
||||
* value is returned on a failure (all error values returned by
|
||||
* inode_reserve):
|
||||
* vnode_reserve):
|
||||
*
|
||||
* EINVAL - 'path' is invalid for this operation
|
||||
* EEXIST - An inode already exists at 'path'
|
||||
* EEXIST - An vnode already exists at 'path'
|
||||
* ENOMEM - Failed to allocate in-memory resources for the operation
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int register_blockdriver(FAR const char *path,
|
||||
FAR const struct block_operations *bops,
|
||||
mode_t mode, FAR void *priv)
|
||||
int register_blockdriver(const char *path,
|
||||
const struct block_operations *bops,
|
||||
mode_t mode, void *priv)
|
||||
{
|
||||
FAR struct inode *node;
|
||||
struct Vnode *vp = NULL;
|
||||
int ret;
|
||||
|
||||
if (path == NULL || strlen(path) >= PATH_MAX || strncmp("/dev/", path, DEV_PATH_LEN) != 0)
|
||||
{
|
||||
return EINVAL;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Insert an inode for the device driver -- we need to hold the inode
|
||||
/* Insert an vnode for the device driver -- we need to hold the vnode
|
||||
* semaphore to prevent access to the tree while we this. This is because
|
||||
* we will have a momentarily bad true until we populate the inode with
|
||||
* we will have a momentarily bad true until we populate the vnode with
|
||||
* valid data.
|
||||
*/
|
||||
|
||||
inode_semtake();
|
||||
ret = inode_reserve(path, &node);
|
||||
struct drv_data *data = (struct drv_data *)zalloc(sizeof(struct drv_data));
|
||||
|
||||
data->ops = (void *)bops;
|
||||
data->mode = mode;
|
||||
data->priv = priv;
|
||||
|
||||
VnodeHold();
|
||||
ret = VnodeLookup(path, &vp, V_CREATE | V_CACHE | V_DUMMY);
|
||||
if (ret >= 0)
|
||||
{
|
||||
/* We have it, now populate it with block driver specific information. */
|
||||
|
||||
INODE_SET_BLOCK(node);
|
||||
|
||||
node->u.i_bops = bops;
|
||||
#ifdef LOSCFG_FILE_MODE
|
||||
node->i_mode = mode;
|
||||
#endif
|
||||
node->i_private = priv;
|
||||
ret = OK;
|
||||
vp->type = VNODE_TYPE_BLK;
|
||||
vp->data = data;
|
||||
vp->mode = mode;
|
||||
ret = OK;
|
||||
}
|
||||
|
||||
inode_semgive();
|
||||
VnodeDrop();
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* !CONFIG_DISABLE_MOUNTPOINT */
|
||||
|
||||
|
||||
Executable → Regular
+38
-28
@@ -38,14 +38,14 @@
|
||||
****************************************************************************/
|
||||
|
||||
#include "vfs_config.h"
|
||||
|
||||
#include "sys/types.h"
|
||||
#include "errno.h"
|
||||
|
||||
#include "fs/fs.h"
|
||||
|
||||
#include "inode/inode.h"
|
||||
#include "fs/vnode.h"
|
||||
#include "string.h"
|
||||
#include "fs/vfs_util.h"
|
||||
#include "fs/path_cache.h"
|
||||
#include "limits.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
@@ -55,29 +55,29 @@
|
||||
* Name: register_driver
|
||||
*
|
||||
* Description:
|
||||
* Register a character driver inode the pseudo file system.
|
||||
* Register a character driver vnode the pseudo file system.
|
||||
*
|
||||
* Input Parameters:
|
||||
* path - The path to the inode to create
|
||||
* path - The path to the vnode to create
|
||||
* fops - The file operations structure
|
||||
* mode - inmode priviledges (not used)
|
||||
* priv - Private, user data that will be associated with the inode.
|
||||
* priv - Private, user data that will be associated with the vnode.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero on success (with the inode point in 'inode'); A negated errno
|
||||
* Zero on success (with the vnode point in 'vnode'); A negated errno
|
||||
* value is returned on a failure (all error values returned by
|
||||
* inode_reserve):
|
||||
* vnode_reserve):
|
||||
*
|
||||
* EINVAL - 'path' is invalid for this operation
|
||||
* EEXIST - An inode already exists at 'path'
|
||||
* EEXIST - An vnode already exists at 'path'
|
||||
* ENOMEM - Failed to allocate in-memory resources for the operation
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int register_driver(FAR const char *path, FAR const struct file_operations_vfs *fops,
|
||||
mode_t mode, FAR void *priv)
|
||||
int register_driver(const char *path, const struct file_operations_vfs *fops,
|
||||
mode_t mode, void *priv)
|
||||
{
|
||||
FAR struct inode *node;
|
||||
struct Vnode *vnode = NULL;
|
||||
int ret;
|
||||
|
||||
if (path == NULL || strlen(path) >= PATH_MAX || strncmp("/dev/", path, DEV_PATH_LEN) != 0)
|
||||
@@ -85,28 +85,38 @@ int register_driver(FAR const char *path, FAR const struct file_operations_vfs *
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Insert a dummy node -- we need to hold the inode semaphore because we
|
||||
VnodeHold();
|
||||
ret = VnodeLookup(path, &vnode, 0);
|
||||
if (ret == 0)
|
||||
{
|
||||
VnodeDrop();
|
||||
return -EEXIST;
|
||||
}
|
||||
|
||||
/* Insert a dummy node -- we need to hold the vnode semaphore because we
|
||||
* will have a momentarily bad structure.
|
||||
*/
|
||||
|
||||
inode_semtake();
|
||||
ret = inode_reserve(path, &node);
|
||||
if (ret >= 0)
|
||||
struct drv_data *data = (struct drv_data *)zalloc(sizeof(struct drv_data));
|
||||
|
||||
data->ops = (void *)fops;
|
||||
data->mode = mode;
|
||||
data->priv = priv;
|
||||
|
||||
ret = VnodeLookup(path, &vnode, V_CREATE | V_CACHE | V_DUMMY);
|
||||
if (ret == OK)
|
||||
{
|
||||
/* We have it, now populate it with driver specific information.
|
||||
* NOTE that the initial reference count on the new inode is zero.
|
||||
* NOTE that the initial reference count on the new vnode is zero.
|
||||
*/
|
||||
|
||||
INODE_SET_DRIVER(node);
|
||||
|
||||
node->u.i_ops = fops;
|
||||
#ifdef LOSCFG_FILE_MODE
|
||||
node->i_mode = mode & (S_IRWXU|S_IRWXG|S_IRWXO);
|
||||
#endif
|
||||
node->i_private = priv;
|
||||
ret = OK;
|
||||
vnode->type = VNODE_TYPE_CHR;
|
||||
vnode->data = data;
|
||||
vnode->mode = mode;
|
||||
vnode->fop = (struct file_operations_vfs *)fops;
|
||||
ret = OK;
|
||||
}
|
||||
|
||||
inode_semgive();
|
||||
VnodeDrop();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
Executable → Regular
+1
-6
@@ -59,15 +59,10 @@
|
||||
|
||||
int unregister_blockdriver(const char *path)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (path == NULL || strlen(path) >= PATH_MAX || strncmp("/dev/", path, DEV_PATH_LEN) != 0)
|
||||
{
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
inode_semtake();
|
||||
ret = inode_remove(path);
|
||||
inode_semgive();
|
||||
return ret;
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
Executable → Regular
+5
-14
@@ -41,7 +41,7 @@
|
||||
|
||||
#include "fs/fs.h"
|
||||
|
||||
#include "inode/inode.h"
|
||||
#include "fs/vnode.h"
|
||||
#include "string.h"
|
||||
#include "errno.h"
|
||||
|
||||
@@ -53,21 +53,12 @@
|
||||
* Name: unregister_driver
|
||||
*
|
||||
* Description:
|
||||
* Remove the character driver inode at 'path' from the pseudo-file system
|
||||
* Remove the character driver vnode at 'path' from the pseudo-file system
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int unregister_driver(FAR const char *path)
|
||||
int unregister_driver(const char *path)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (path == NULL || strlen(path) >= PATH_MAX || strncmp("/dev/", path, DEV_PATH_LEN) != 0)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
inode_semtake();
|
||||
ret = inode_remove(path);
|
||||
inode_semgive();
|
||||
return ret;
|
||||
(void)path;
|
||||
return 0;
|
||||
}
|
||||
|
||||
Executable → Regular
+109
-113
@@ -39,18 +39,17 @@
|
||||
****************************************************************************/
|
||||
#include "unistd.h"
|
||||
#include "vfs_config.h"
|
||||
|
||||
#include "sys/types.h"
|
||||
#include "string.h"
|
||||
#include "dirent.h"
|
||||
#include "semaphore.h"
|
||||
#include "assert.h"
|
||||
#include "errno.h"
|
||||
|
||||
#include "fs/fs.h"
|
||||
#include "fs/file.h"
|
||||
#include "stdio.h"
|
||||
#include "stdlib.h"
|
||||
#include "inode/inode.h"
|
||||
#include "fs/vnode.h"
|
||||
#include "los_mux.h"
|
||||
#include "fs/fd_table.h"
|
||||
#ifdef LOSCFG_NET_LWIP_SACK
|
||||
@@ -105,6 +104,20 @@ static void clear_bit(int i, void *addr)
|
||||
*addri = old;
|
||||
}
|
||||
|
||||
bool get_bit(int i)
|
||||
{
|
||||
unsigned int *p = NULL;
|
||||
unsigned int mask;
|
||||
|
||||
p = ((unsigned int *)bitmap) + (i >> 5); /* Gets the location in the bitmap */
|
||||
mask = 1 << (i & 0x1f); /* Gets the mask for the current bit int bitmap */
|
||||
if (!(~(*p) & mask)){
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
@@ -113,7 +126,7 @@ static void clear_bit(int i, void *addr)
|
||||
* Name: _files_semtake
|
||||
****************************************************************************/
|
||||
|
||||
static void _files_semtake(FAR struct filelist *list)
|
||||
static void _files_semtake(struct filelist *list)
|
||||
{
|
||||
/* Take the semaphore (perhaps waiting) */
|
||||
|
||||
@@ -137,71 +150,72 @@ static void _files_semtake(FAR struct filelist *list)
|
||||
* Name: _files_close
|
||||
*
|
||||
* Description:
|
||||
* Close an inode (if open)
|
||||
* Close an vnode (if open)
|
||||
*
|
||||
* Assumuptions:
|
||||
* Caller holds the list semaphore because the file descriptor will be freed.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int _files_close(FAR struct file *filep)
|
||||
static int _files_close(struct file *filep)
|
||||
{
|
||||
struct inode *inode = filep->f_inode;
|
||||
struct Vnode *vnode = filep->f_vnode;
|
||||
int ret = OK;
|
||||
|
||||
/* Check if the struct file is open (i.e., assigned an inode) */
|
||||
|
||||
if (inode)
|
||||
/* Check if the struct file is open (i.e., assigned an vnode) */
|
||||
if (filep->f_oflags & O_DIRECTORY)
|
||||
{
|
||||
if (filep->f_oflags & O_DIRECTORY)
|
||||
ret = closedir(filep->f_dir);
|
||||
if (ret != OK)
|
||||
{
|
||||
ret = closedir(filep->f_dir);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Close the file, driver, or mountpoint. */
|
||||
if (filep->ops && filep->ops->close)
|
||||
{
|
||||
/* Perform the close operation */
|
||||
|
||||
ret = filep->ops->close(filep);
|
||||
if (ret != OK)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Close the file, driver, or mountpoint. */
|
||||
|
||||
if (inode->u.i_ops && inode->u.i_ops->close)
|
||||
{
|
||||
/* Perform the close operation */
|
||||
|
||||
ret = inode->u.i_ops->close(filep);
|
||||
if (ret != OK)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Drop file caches */
|
||||
|
||||
(void)remove_mapping_nolock(filep->f_path, filep);
|
||||
|
||||
/* And release the inode */
|
||||
|
||||
inode_release(inode);
|
||||
|
||||
/* Release the path of file */
|
||||
|
||||
free(filep->f_path);
|
||||
|
||||
/* Release the file descriptor */
|
||||
|
||||
filep->f_magicnum = 0;
|
||||
filep->f_oflags = 0;
|
||||
filep->f_pos = 0;
|
||||
filep->f_path = NULL;
|
||||
filep->f_priv = NULL;
|
||||
filep->f_inode = NULL;
|
||||
filep->f_refcount = 0;
|
||||
filep->f_mapping = NULL;
|
||||
filep->f_dir = NULL;
|
||||
VnodeHold();
|
||||
vnode->useCount--;
|
||||
VnodeDrop();
|
||||
}
|
||||
|
||||
/* Block char device is removed when close */
|
||||
if (vnode->type == VNODE_TYPE_BCHR)
|
||||
{
|
||||
VnodeHold();
|
||||
ret = VnodeFree(vnode);
|
||||
if (ret < 0)
|
||||
{
|
||||
PRINTK("Removing bchar device %s failed\n", filep->f_path);
|
||||
}
|
||||
VnodeDrop();
|
||||
}
|
||||
/* Release the path of file */
|
||||
|
||||
free(filep->f_path);
|
||||
|
||||
/* Release the file descriptor */
|
||||
|
||||
filep->f_magicnum = 0;
|
||||
filep->f_oflags = 0;
|
||||
filep->f_pos = 0;
|
||||
filep->f_path = NULL;
|
||||
filep->f_priv = NULL;
|
||||
filep->f_vnode = NULL;
|
||||
filep->f_refcount = 0;
|
||||
filep->f_mapping = NULL;
|
||||
filep->f_dir = NULL;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -228,7 +242,7 @@ void files_initialize(void)
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void files_initlist(FAR struct filelist *list)
|
||||
void files_initlist(struct filelist *list)
|
||||
{
|
||||
DEBUGASSERT(list);
|
||||
|
||||
@@ -245,7 +259,7 @@ void files_initlist(FAR struct filelist *list)
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void files_releaselist(FAR struct filelist *list)
|
||||
void files_releaselist(struct filelist *list)
|
||||
{
|
||||
int i;
|
||||
|
||||
@@ -270,7 +284,7 @@ void files_releaselist(FAR struct filelist *list)
|
||||
* Name: file_dup2
|
||||
*
|
||||
* Description:
|
||||
* Assign an inode to a specific files structure. This is the heart of
|
||||
* Assign an vnode to a specific files structure. This is the heart of
|
||||
* dup2.
|
||||
*
|
||||
* Equivalent to the non-standard fs_dupfd2() function except that it
|
||||
@@ -283,20 +297,19 @@ void files_releaselist(FAR struct filelist *list)
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int file_dup2(FAR struct file *filep1, FAR struct file *filep2)
|
||||
int file_dup2(struct file *filep1, struct file *filep2)
|
||||
{
|
||||
FAR struct filelist *list = NULL;
|
||||
FAR struct inode *inode_ptr = NULL;
|
||||
struct filelist *list = NULL;
|
||||
struct Vnode *vnode_ptr = NULL;
|
||||
char *fullpath = NULL;
|
||||
const char *relpath = NULL;
|
||||
int err;
|
||||
int len;
|
||||
int ret;
|
||||
struct inode_search_s desc;
|
||||
|
||||
if (!filep1 || !filep1->f_inode || !filep2)
|
||||
if (!filep1 || !filep1->f_vnode || !filep2)
|
||||
{
|
||||
err = EBADF;
|
||||
err = -EBADF;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
@@ -314,8 +327,8 @@ int file_dup2(FAR struct file *filep1, FAR struct file *filep2)
|
||||
_files_semtake(list);
|
||||
}
|
||||
|
||||
/* If there is already an inode contained in the new file structure,
|
||||
* close the file and release the inode.
|
||||
/* If there is already an vnode contained in the new file structure,
|
||||
* close the file and release the vnode.
|
||||
*/
|
||||
|
||||
ret = _files_close(filep2);
|
||||
@@ -340,26 +353,18 @@ int file_dup2(FAR struct file *filep1, FAR struct file *filep2)
|
||||
goto errout_with_ret;
|
||||
}
|
||||
|
||||
/* Increment the reference count on the contained inode */
|
||||
/* Increment the reference count on the contained vnode */
|
||||
|
||||
inode_ptr = filep1->f_inode;
|
||||
vnode_ptr = filep1->f_vnode;
|
||||
|
||||
/* Then clone the file structure */
|
||||
|
||||
filep2->f_oflags = filep1->f_oflags;
|
||||
filep2->f_pos = filep1->f_pos;
|
||||
filep2->f_inode = inode_ptr;
|
||||
filep2->f_vnode = vnode_ptr;
|
||||
filep2->f_priv = filep1->f_priv;
|
||||
|
||||
(void)strncpy_s(fullpath, len + 1, filep1->f_path, len);
|
||||
SETUP_SEARCH(&desc, fullpath, false);
|
||||
if (inode_find(&desc) < 0)
|
||||
{
|
||||
ret = -EACCES;
|
||||
free(fullpath);
|
||||
goto errout_with_ret;
|
||||
}
|
||||
relpath = desc.relpath;
|
||||
filep2->f_path = fullpath;
|
||||
filep2->f_relpath = relpath;
|
||||
|
||||
@@ -367,18 +372,14 @@ int file_dup2(FAR struct file *filep1, FAR struct file *filep2)
|
||||
* can maintain the correct open counts.
|
||||
*/
|
||||
|
||||
if (inode_ptr->u.i_ops)
|
||||
if (vnode_ptr->vop)
|
||||
{
|
||||
#ifndef CONFIG_DISABLE_MOUNTPOINT
|
||||
if (INODE_IS_MOUNTPT(inode_ptr))
|
||||
if (vnode_ptr->originMount)
|
||||
{
|
||||
/* Dup the open file on the in the new file structure */
|
||||
|
||||
if (inode_ptr->u.i_mops->dup)
|
||||
{
|
||||
ret = inode_ptr->u.i_mops->dup(filep1, filep2);
|
||||
}
|
||||
else
|
||||
if (vnode_ptr == NULL)
|
||||
{
|
||||
ret = -ENOSYS;
|
||||
}
|
||||
@@ -388,9 +389,9 @@ int file_dup2(FAR struct file *filep1, FAR struct file *filep2)
|
||||
{
|
||||
/* (Re-)open the pseudo file or device driver */
|
||||
|
||||
if (inode_ptr->u.i_ops->open)
|
||||
if (vnode_ptr->vop->Open)
|
||||
{
|
||||
ret = inode_ptr->u.i_ops->open(filep2);
|
||||
ret = vnode_ptr->vop->Open(vnode_ptr, 0, 0, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -402,7 +403,7 @@ int file_dup2(FAR struct file *filep1, FAR struct file *filep2)
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
goto errout_with_inode;
|
||||
goto errout_with_vnode;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -414,13 +415,12 @@ int file_dup2(FAR struct file *filep1, FAR struct file *filep2)
|
||||
|
||||
/* Handle various error conditions */
|
||||
|
||||
errout_with_inode:
|
||||
errout_with_vnode:
|
||||
|
||||
inode_release(filep2->f_inode);
|
||||
free(filep2->f_path);
|
||||
filep2->f_oflags = 0;
|
||||
filep2->f_pos = 0;
|
||||
filep2->f_inode = NULL;
|
||||
filep2->f_vnode = NULL;
|
||||
filep2->f_priv = NULL;
|
||||
filep2->f_path = NULL;
|
||||
filep2->f_relpath = NULL;
|
||||
@@ -451,9 +451,9 @@ static inline unsigned int files_magic_generate(void)
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int files_allocate(FAR struct inode *inode_ptr, int oflags, off_t pos,void* priv, int minfd)
|
||||
int files_allocate(struct Vnode *vnode_ptr, int oflags, off_t pos, void *priv, int minfd)
|
||||
{
|
||||
FAR struct filelist *list = NULL;
|
||||
struct filelist *list = NULL;
|
||||
unsigned int *p = NULL;
|
||||
unsigned int mask;
|
||||
unsigned int i;
|
||||
@@ -481,7 +481,7 @@ int files_allocate(FAR struct inode *inode_ptr, int oflags, off_t pos,void* priv
|
||||
set_bit(i, bitmap);
|
||||
list->fl_files[i].f_oflags = oflags;
|
||||
list->fl_files[i].f_pos = pos;
|
||||
list->fl_files[i].f_inode = inode_ptr;
|
||||
list->fl_files[i].f_vnode = vnode_ptr;
|
||||
list->fl_files[i].f_priv = priv;
|
||||
list->fl_files[i].f_refcount = 1;
|
||||
list->fl_files[i].f_mapping = NULL;
|
||||
@@ -500,19 +500,18 @@ int files_allocate(FAR struct inode *inode_ptr, int oflags, off_t pos,void* priv
|
||||
i++;
|
||||
}
|
||||
|
||||
|
||||
_files_semgive(list);
|
||||
return VFS_ERROR;
|
||||
}
|
||||
|
||||
static int files_close_internal(int fd, LosProcessCB *processCB)
|
||||
{
|
||||
FAR struct filelist *list = NULL;
|
||||
int ret = OK;
|
||||
int ret = OK;
|
||||
struct file *filep = NULL;
|
||||
struct filelist *list = NULL;
|
||||
struct files_struct *process_files = NULL;
|
||||
|
||||
/* 0,1,2 fd is not opened in system, no need to close them */
|
||||
|
||||
if ((fd >= STDIN_FILENO) && (fd <= STDERR_FILENO))
|
||||
{
|
||||
return OK;
|
||||
@@ -525,9 +524,9 @@ static int files_close_internal(int fd, LosProcessCB *processCB)
|
||||
list = sched_getfiles();
|
||||
DEBUGASSERT(list != NULL);
|
||||
|
||||
/* If the file was properly opened, there should be an inode assigned */
|
||||
/* If the file was properly opened, there should be an vnode assigned */
|
||||
|
||||
if (fd < 0 || fd >= CONFIG_NFILE_DESCRIPTORS || !list->fl_files[fd].f_inode)
|
||||
if (fd < 0 || fd >= CONFIG_NFILE_DESCRIPTORS || !list->fl_files[fd].f_vnode)
|
||||
{
|
||||
return -EBADF;
|
||||
}
|
||||
@@ -542,20 +541,18 @@ static int files_close_internal(int fd, LosProcessCB *processCB)
|
||||
_files_semgive(list);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (list->fl_files[fd].f_mapping)
|
||||
{
|
||||
OsFileCacheFlush(list->fl_files[fd].f_mapping);
|
||||
dec_mapping(list->fl_files[fd].f_mapping);
|
||||
}
|
||||
list->fl_files[fd].f_refcount--;
|
||||
|
||||
/* The filep->f_refcount may not be zero here, when the filep is shared in parent-child processes.
|
||||
so, upon closing the filep in current process, relevant region must be released immediately */
|
||||
|
||||
OsVmmFileRegionFree(&list->fl_files[fd], processCB);
|
||||
filep = &list->fl_files[fd];
|
||||
|
||||
OsVmmFileRegionFree(filep, processCB);
|
||||
|
||||
list->fl_files[fd].f_refcount--;
|
||||
if (list->fl_files[fd].f_refcount == 0)
|
||||
{
|
||||
dec_mapping_nolock(filep->f_mapping);
|
||||
ret = _files_close(&list->fl_files[fd]);
|
||||
if (ret == OK)
|
||||
{
|
||||
@@ -594,7 +591,7 @@ int files_close(int fd)
|
||||
|
||||
void files_release(int fd)
|
||||
{
|
||||
FAR struct filelist *list = NULL;
|
||||
struct filelist *list = NULL;
|
||||
|
||||
list = sched_getfiles();
|
||||
DEBUGASSERT(list);
|
||||
@@ -605,7 +602,7 @@ void files_release(int fd)
|
||||
|
||||
list->fl_files[fd].f_magicnum = 0;
|
||||
list->fl_files[fd].f_oflags = 0;
|
||||
list->fl_files[fd].f_inode = NULL;
|
||||
list->fl_files[fd].f_vnode = NULL;
|
||||
list->fl_files[fd].f_pos = 0;
|
||||
list->fl_files[fd].f_refcount = 0;
|
||||
list->fl_files[fd].f_path = NULL;
|
||||
@@ -613,15 +610,14 @@ void files_release(int fd)
|
||||
list->fl_files[fd].f_priv = NULL;
|
||||
list->fl_files[fd].f_mapping = NULL;
|
||||
list->fl_files[fd].f_dir = NULL;
|
||||
|
||||
clear_bit(fd, bitmap);
|
||||
_files_semgive(list);
|
||||
}
|
||||
}
|
||||
|
||||
struct inode * files_get_openfile(int fd)
|
||||
struct Vnode *files_get_openfile(int fd)
|
||||
{
|
||||
FAR struct filelist *list = NULL;
|
||||
struct filelist *list = NULL;
|
||||
unsigned int *p = NULL;
|
||||
unsigned int mask;
|
||||
|
||||
@@ -635,12 +631,12 @@ struct inode * files_get_openfile(int fd)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return list->fl_files[fd].f_inode;
|
||||
return list->fl_files[fd].f_vnode;
|
||||
}
|
||||
|
||||
int alloc_fd(int minfd)
|
||||
{
|
||||
FAR struct filelist *list = NULL;
|
||||
struct filelist *list = NULL;
|
||||
unsigned int *p = NULL;
|
||||
unsigned int mask;
|
||||
unsigned int i;
|
||||
@@ -679,16 +675,16 @@ void clear_fd(int fd)
|
||||
clear_bit(fd, bitmap);
|
||||
}
|
||||
|
||||
int close_files(struct inode *inode)
|
||||
int close_files(struct Vnode *vnode)
|
||||
{
|
||||
int fd = 0;
|
||||
int ret = 0;
|
||||
FAR struct inode *open_file_inode = NULL;
|
||||
struct Vnode *open_file_vnode = NULL;
|
||||
|
||||
for (fd = FILE_START_FD; fd < CONFIG_NFILE_DESCRIPTORS; fd++)
|
||||
{
|
||||
open_file_inode = files_get_openfile(fd);
|
||||
if (open_file_inode && (open_file_inode == inode))
|
||||
open_file_vnode = files_get_openfile(fd);
|
||||
if (open_file_vnode && (open_file_vnode == vnode))
|
||||
{
|
||||
ret = files_close(fd);
|
||||
if (ret < 0)
|
||||
|
||||
Executable → Regular
-48
@@ -429,54 +429,6 @@ void inode_release(FAR struct inode *inode);
|
||||
|
||||
int foreach_inode(foreach_inode_t handler, FAR void *arg);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: files_initialize
|
||||
*
|
||||
* Description:
|
||||
* This is called from the FS initialization logic to configure the files.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void weak_function files_initialize(void);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: files_allocate
|
||||
*
|
||||
* Description:
|
||||
* Allocate a struct files instance and associate it with an inode instance.
|
||||
* Returns the file descriptor == index into the files array.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int files_allocate(FAR struct inode *inode, int oflags, off_t pos,void *priv, int minfd);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: files_close
|
||||
*
|
||||
* Description:
|
||||
* Close an inode (if open)
|
||||
*
|
||||
* Assumuptions:
|
||||
* Caller holds the list semaphore because the file descriptor will be freed.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int files_close(int fd);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: files_release
|
||||
*
|
||||
* Assumuptions:
|
||||
* Similar to files_close(). Called only from open() logic on error
|
||||
* conditions.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void files_release(int fd);
|
||||
|
||||
int vfs_normalize_path(const char *directory, const char *filename, char **pathname);
|
||||
int vfs_normalize_pathat(int fd, const char *filename, char **pathname);
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus
|
||||
}
|
||||
|
||||
Executable → Regular
+21
-16
@@ -49,7 +49,8 @@
|
||||
|
||||
#include "fs/fs.h"
|
||||
|
||||
#include "inode/inode.h"
|
||||
#include "fs/vnode.h"
|
||||
#include "limits.h"
|
||||
|
||||
#ifndef CONFIG_DISABLE_MOUNTPOINT
|
||||
|
||||
@@ -68,17 +69,17 @@
|
||||
struct enum_mountpoint_s
|
||||
{
|
||||
foreach_mountpoint_t handler;
|
||||
FAR void *arg;
|
||||
void *arg;
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
static int mountpoint_filter(FAR struct inode *node,
|
||||
FAR char dirpath[PATH_MAX], FAR void *arg)
|
||||
#ifdef VFS_IMPL_LATER
|
||||
static int mountpoint_filter(struct Vnode *node,
|
||||
char dirpath[PATH_MAX], void *arg)
|
||||
{
|
||||
FAR struct enum_mountpoint_s *info = (FAR struct enum_mountpoint_s *)arg;
|
||||
struct enum_mountpoint_s *info = (struct enum_mountpoint_s *)arg;
|
||||
struct statfs statbuf;
|
||||
int pathlen;
|
||||
int namlen;
|
||||
@@ -86,7 +87,7 @@ static int mountpoint_filter(FAR struct inode *node,
|
||||
|
||||
DEBUGASSERT(node && info && info->handler);
|
||||
|
||||
/* Check if the inode is a mountpoint. Mountpoints must support statfs.
|
||||
/* Check if the vnode is a mountpoint. Mountpoints must support statfs.
|
||||
* If this one does not for some reason, then it will be ignored.
|
||||
*
|
||||
* The root node is a special case: It has no operations (u.i_mops == NULL)
|
||||
@@ -94,8 +95,8 @@ static int mountpoint_filter(FAR struct inode *node,
|
||||
|
||||
if (INODE_IS_MOUNTPT(node) && node->u.i_mops && node->u.i_mops->statfs)
|
||||
{
|
||||
/* Yes... get the full path to the inode by concatenating the inode
|
||||
* name and the path to the directory containing the inode.
|
||||
/* Yes... get the full path to the vnode by concatenating the vnode
|
||||
* name and the path to the directory containing the vnode.
|
||||
*/
|
||||
|
||||
pathlen = strlen(dirpath);
|
||||
@@ -108,9 +109,9 @@ static int mountpoint_filter(FAR struct inode *node,
|
||||
return -ENAMETOOLONG;
|
||||
}
|
||||
|
||||
/* Append the inode name to the directory path */
|
||||
/* Append the vnode name to the directory path */
|
||||
|
||||
ret = snprintf_s(&dirpath[pathlen], PATH_MAX - pathlen, PATH_MAX - pathlen - 1, "%s/", node->i_name);
|
||||
ret = snprintf_s(&dirpath[pathlen], PATH_MAX - pathlen, PATH_MAX - pathlen - 1, "/%s", node->i_name);
|
||||
if (ret < 0)
|
||||
{
|
||||
return -ENAMETOOLONG;
|
||||
@@ -137,6 +138,7 @@ static int mountpoint_filter(FAR struct inode *node,
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
@@ -150,8 +152,8 @@ static int mountpoint_filter(FAR struct inode *node,
|
||||
* terminated when the callback 'handler' returns a non-zero value, or when
|
||||
* all of the mountpoints have been visited.
|
||||
*
|
||||
* This is just a front end "filter" to foreach_inode() that forwards only
|
||||
* mountpoint inodes. It is intended to support the mount() command to
|
||||
* This is just a front end "filter" to foreach_vnode() that forwards only
|
||||
* mountpoint vnodes. It is intended to support the mount() command to
|
||||
* when the mount command is used to enumerate mounts.
|
||||
*
|
||||
* NOTE 1: Use with caution... The pseudo-file system is locked throughout
|
||||
@@ -162,16 +164,19 @@ static int mountpoint_filter(FAR struct inode *node,
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int foreach_mountpoint(foreach_mountpoint_t handler, FAR void *arg)
|
||||
int foreach_mountpoint(foreach_mountpoint_t handler, void *arg)
|
||||
{
|
||||
#ifdef VFS_IMPL_LATER
|
||||
struct enum_mountpoint_s info;
|
||||
|
||||
/* Let foreach_inode do the real work */
|
||||
/* Let foreach_vnode do the real work */
|
||||
|
||||
info.handler = handler;
|
||||
info.arg = arg;
|
||||
|
||||
return foreach_inode(mountpoint_filter, (FAR void *)&info);
|
||||
return foreach_vnode(mountpoint_filter, (void *)&info);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
+62
-155
@@ -40,15 +40,14 @@
|
||||
|
||||
#include "vfs_config.h"
|
||||
|
||||
#include "driver/driver.h"
|
||||
#include "sys/mount.h"
|
||||
#include "string.h"
|
||||
#include "errno.h"
|
||||
#include "assert.h"
|
||||
#include "debug.h"
|
||||
|
||||
#include "fs/fs.h"
|
||||
|
||||
#include "inode/inode.h"
|
||||
#include "fs/vnode.h"
|
||||
#include "stdlib.h"
|
||||
#include "driver/driver.h"
|
||||
#ifdef LOSCFG_DRIVERS_MTD
|
||||
@@ -58,10 +57,15 @@
|
||||
#include "errcode_fat.h"
|
||||
#endif
|
||||
#include "los_tables.h"
|
||||
|
||||
#ifdef LOSCFG_FS_ZPFS
|
||||
#include "vfs_zpfs.h"
|
||||
#ifdef LOSCFG_DRIVERS_RANDOM
|
||||
#include "hisoc/random.h"
|
||||
#else
|
||||
#include "stdlib.h"
|
||||
#endif
|
||||
#include "fs/vfs_util.h"
|
||||
#include "fs/path_cache.h"
|
||||
#include "fs/mount.h"
|
||||
|
||||
|
||||
/* At least one filesystem must be defined, or this file will not compile.
|
||||
* It may be desire-able to make filesystems dynamically registered at
|
||||
@@ -122,6 +126,7 @@ static const struct fsmap_t *mount_findfs(const char *filesystemtype)
|
||||
return (const struct fsmap_t *)NULL;
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
@@ -155,23 +160,20 @@ int mount(const char *source, const char *target,
|
||||
const void *data)
|
||||
{
|
||||
int ret;
|
||||
void *fshandle = NULL;
|
||||
int errcode = 0;
|
||||
char *fullpath = NULL;
|
||||
char *fullpath_bak = NULL;
|
||||
|
||||
struct inode *blkdrvr_inode = NULL;
|
||||
struct inode *mountpt_inode = NULL;
|
||||
struct Mount* mnt = NULL;
|
||||
struct Vnode *device = NULL;
|
||||
struct Vnode *mountpt_vnode = NULL;
|
||||
const struct fsmap_t *fsmap = NULL;
|
||||
const struct mountpt_operations *mops = NULL;
|
||||
|
||||
const struct MountOps *mops = NULL;
|
||||
LIST_HEAD *mount_list = NULL;
|
||||
#ifdef LOSCFG_DRIVERS_MTD
|
||||
mtd_partition *partition = NULL;
|
||||
#endif
|
||||
|
||||
if (filesystemtype == NULL)
|
||||
{
|
||||
errcode = EINVAL;
|
||||
errcode = -EINVAL;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
@@ -179,23 +181,12 @@ int mount(const char *source, const char *target,
|
||||
|
||||
DEBUGASSERT(target && filesystemtype);
|
||||
|
||||
ret = vfs_normalize_path((const char *)NULL, target, &fullpath);
|
||||
if (ret < 0)
|
||||
{
|
||||
PRINT_ERR("Failed to get fullpath,target: %s\n", target);
|
||||
errcode = -ret;
|
||||
goto errout;
|
||||
}
|
||||
fullpath_bak = fullpath;
|
||||
|
||||
/* Find the specified filesystem. Try the block driver file systems first */
|
||||
|
||||
if ((fsmap = mount_findfs(filesystemtype)) == NULL ||
|
||||
(fsmap->is_bdfs && !source))
|
||||
if ((fsmap = mount_findfs(filesystemtype)) == NULL || (fsmap->is_bdfs && !source))
|
||||
{
|
||||
PRINT_ERR("Failed to find file system %s\n", filesystemtype);
|
||||
errcode = ENODEV;
|
||||
free(fullpath_bak);
|
||||
errcode = -ENODEV;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
@@ -209,135 +200,77 @@ int mount(const char *source, const char *target,
|
||||
|
||||
/* Find the block driver */
|
||||
|
||||
ret = find_blockdriver(source, mountflags, &blkdrvr_inode);
|
||||
ret = find_blockdriver(source, mountflags, &device);
|
||||
if (ret < 0)
|
||||
{
|
||||
PRINT_ERR("Failed to find block driver %s\n", source);
|
||||
errcode = -ret;
|
||||
free(fullpath_bak);
|
||||
errcode = ret;
|
||||
goto errout;
|
||||
}
|
||||
}
|
||||
|
||||
/* Insert a dummy node -- we need to hold the inode semaphore
|
||||
* to do this because we will have a momentarily bad structure.
|
||||
*/
|
||||
VnodeHold();
|
||||
ret = VnodeLookup(target, &mountpt_vnode, 0);
|
||||
|
||||
inode_semtake();
|
||||
#ifdef LOSCFG_FS_ZPFS
|
||||
if (strcmp(filesystemtype, ZPFS_NAME) == 0)
|
||||
{
|
||||
ret = ZpfsPrepare(source, fullpath, &mountpt_inode, true);
|
||||
if (ret < 0)
|
||||
{
|
||||
errcode = -ret;
|
||||
goto errout_with_semaphore;
|
||||
}
|
||||
data = (const void *)mountpt_inode->i_private;
|
||||
}
|
||||
else
|
||||
{
|
||||
#endif
|
||||
mountpt_inode = inode_search((const char **)&fullpath, (struct inode **)NULL, (struct inode **)NULL, \
|
||||
(const char **)NULL);
|
||||
/* The mount point must be an existed vnode. */
|
||||
|
||||
/* The mount point must be an existed inode. */
|
||||
|
||||
if (mountpt_inode == NULL)
|
||||
if (ret != OK)
|
||||
{
|
||||
PRINT_ERR("Failed to find valid mountpoint %s\n", target);
|
||||
errcode = EINVAL;
|
||||
goto errout_with_semaphore;
|
||||
errcode = -EINVAL;
|
||||
goto errout_with_lock;
|
||||
}
|
||||
|
||||
/* The mount point must be a dangling node with no children and
|
||||
* no operations. If this inode is mounted, or it has children
|
||||
* (except "/"), or it has operations, it cannot be mounted.
|
||||
*/
|
||||
|
||||
if (INODE_IS_MOUNTPT(mountpt_inode) || (mountpt_inode->i_child && strcmp(target, "/")) || mountpt_inode->u.i_ops)
|
||||
if (mountpt_vnode->flag & VNODE_FLAG_MOUNT_ORIGIN)
|
||||
{
|
||||
PRINT_ERR("Can't to mount to this inode %s\n", target);
|
||||
errcode = EINVAL;
|
||||
goto errout_with_semaphore;
|
||||
PRINT_ERR("can't mount to %s, already mounted.\n", target);
|
||||
errcode = -EINVAL;
|
||||
goto errout_with_lock;
|
||||
}
|
||||
#ifdef LOSCFG_FS_ZPFS
|
||||
}
|
||||
#endif
|
||||
|
||||
mountpt_inode ->mountflags = mountflags;
|
||||
|
||||
/* Bind the block driver to an instance of the file system. The file
|
||||
* system returns a reference to some opaque, fs-dependent structure
|
||||
* that encapsulates this binding.
|
||||
*/
|
||||
|
||||
if (mops->bind == NULL)
|
||||
if (mops->Mount == NULL)
|
||||
{
|
||||
/* The filesystem does not support the bind operation ??? */
|
||||
|
||||
fdbg("ERROR: Filesystem does not support bind\n");
|
||||
errcode = EINVAL;
|
||||
PRINTK("ERROR: Filesystem does not support bind\n");
|
||||
errcode = -ENOSYS;
|
||||
goto errout_with_mountpt;
|
||||
}
|
||||
|
||||
/* Increment reference count for the reference we pass to the file system */
|
||||
|
||||
if (blkdrvr_inode != NULL)
|
||||
{
|
||||
blkdrvr_inode->i_crefs++;
|
||||
|
||||
/* On failure, the bind method returns -errorcode */
|
||||
|
||||
if (blkdrvr_inode->e_status != STAT_UNMOUNTED)
|
||||
{
|
||||
fdbg("ERROR: The node is busy\n");
|
||||
errcode = EBUSY;
|
||||
blkdrvr_inode->i_crefs--;
|
||||
goto errout_with_mountpt;
|
||||
}
|
||||
}
|
||||
#ifdef LOSCFG_DRIVERS_MTD
|
||||
if (fsmap->is_mtd_support && (blkdrvr_inode != NULL))
|
||||
if (fsmap->is_mtd_support && (device != NULL))
|
||||
{
|
||||
partition = (mtd_partition *)blkdrvr_inode->i_private;
|
||||
partition = (mtd_partition *)((struct drv_data *)device->data)->priv;
|
||||
partition->mountpoint_name = (char *)zalloc(strlen(target) + 1);
|
||||
if (partition->mountpoint_name == NULL)
|
||||
{
|
||||
errcode = ENOMEM;
|
||||
blkdrvr_inode->i_crefs--;
|
||||
errcode = -ENOMEM;
|
||||
goto errout_with_mountpt;
|
||||
}
|
||||
|
||||
(void)strncpy_s(partition->mountpoint_name, strlen(target) + 1, target, strlen(target));
|
||||
partition->mountpoint_name[strlen(target)] = '\0';
|
||||
}
|
||||
#endif
|
||||
mountpt_inode ->mountflags = mountflags;
|
||||
ret = mops->bind(blkdrvr_inode, data, &fshandle, fullpath_bak);
|
||||
#ifdef LOSCFG_FS_FAT_VIRTUAL_PARTITION
|
||||
if (ret >= VIRERR_BASE)
|
||||
{
|
||||
errcode = ret;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
|
||||
mnt = MountAlloc(mountpt_vnode, (struct MountOps*)mops);
|
||||
|
||||
ret = mops->Mount(mnt, device, data);
|
||||
if (ret != 0)
|
||||
{
|
||||
/* The inode is unhappy with the blkdrvr for some reason. Back out
|
||||
/* The vnode is unhappy with the blkdrvr for some reason. Back out
|
||||
* the count for the reference we failed to pass and exit with an
|
||||
* error.
|
||||
*/
|
||||
|
||||
fdbg("ERROR: Bind method failed: %d\n", ret);
|
||||
if (blkdrvr_inode != NULL)
|
||||
{
|
||||
blkdrvr_inode->i_crefs--;
|
||||
}
|
||||
|
||||
errcode = -ret;
|
||||
errcode = ret;
|
||||
#ifdef LOSCFG_DRIVERS_MTD
|
||||
if (fsmap->is_mtd_support && (blkdrvr_inode != NULL) && (partition != NULL))
|
||||
if (fsmap->is_mtd_support && (device != NULL) && (partition != NULL))
|
||||
{
|
||||
free(partition->mountpoint_name);
|
||||
partition->mountpoint_name = NULL;
|
||||
@@ -345,68 +278,42 @@ int mount(const char *source, const char *target,
|
||||
#endif
|
||||
goto errout_with_mountpt;
|
||||
}
|
||||
mnt->vnodeBeCovered->flag |= VNODE_FLAG_MOUNT_NEW;
|
||||
mnt->vnodeCovered->flag |= VNODE_FLAG_MOUNT_ORIGIN;
|
||||
mnt->ops = mops;
|
||||
mnt->mountFlags = mountflags;
|
||||
|
||||
/* We have it, now populate it with driver specific information. */
|
||||
//* We have it, now populate it with driver specific information. */
|
||||
|
||||
INODE_SET_MOUNTPT(mountpt_inode);
|
||||
mount_list = GetMountList();
|
||||
LOS_ListAdd(mount_list, &mnt->mountList);
|
||||
|
||||
mountpt_inode->u.i_mops = mops;
|
||||
mountpt_inode->i_private = fshandle;
|
||||
#ifdef LOSCFG_FILE_MODE
|
||||
struct stat statinfo = {0};
|
||||
if ((g_root_inode != mountpt_inode) && (stat(target, &statinfo) == 0))
|
||||
if (!strcmp("/", target))
|
||||
{
|
||||
mountpt_inode->i_mode = statinfo.st_mode;
|
||||
mountpt_inode->i_uid = statinfo.st_uid;
|
||||
mountpt_inode->i_gid = statinfo.st_gid;
|
||||
ChangeRoot(mnt->vnodeCovered);
|
||||
}
|
||||
|
||||
#endif
|
||||
VnodeDrop();
|
||||
|
||||
if (blkdrvr_inode)
|
||||
{
|
||||
blkdrvr_inode->e_status = STAT_MOUNTED;
|
||||
}
|
||||
inode_semgive();
|
||||
|
||||
/* We can release our reference to the blkdrver_inode, if the filesystem
|
||||
* wants to retain the blockdriver inode (which it should), then it must
|
||||
* have called inode_addref(). There is one reference on mountpt_inode
|
||||
/* We can release our reference to the blkdrver_vnode, if the filesystem
|
||||
* wants to retain the blockdriver vnode (which it should), then it must
|
||||
* have called vnode_addref(). There is one reference on mountpt_vnode
|
||||
* that will persist until umount() is called.
|
||||
*/
|
||||
|
||||
if (blkdrvr_inode != NULL)
|
||||
{
|
||||
inode_release(blkdrvr_inode);
|
||||
}
|
||||
|
||||
free(fullpath_bak);
|
||||
|
||||
#ifdef LOSCFG_FS_FAT_VIRTUAL_PARTITION
|
||||
if (errcode >= VIRERR_BASE)
|
||||
{
|
||||
set_errno(errcode);
|
||||
}
|
||||
#endif
|
||||
|
||||
return OK;
|
||||
|
||||
/* A lot of goto's! But they make the error handling much simpler */
|
||||
|
||||
errout_with_mountpt:
|
||||
(void)inode_remove(fullpath);
|
||||
|
||||
errout_with_semaphore:
|
||||
inode_semgive();
|
||||
if (blkdrvr_inode != NULL)
|
||||
if (mnt)
|
||||
{
|
||||
inode_release(blkdrvr_inode);
|
||||
free(mnt);
|
||||
}
|
||||
free(fullpath_bak);
|
||||
|
||||
errout_with_lock:
|
||||
VnodeDrop();
|
||||
errout:
|
||||
set_errno(errcode);
|
||||
set_errno(-errcode);
|
||||
return VFS_ERROR;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_FS_READABLE */
|
||||
|
||||
Regular → Executable
+73
-123
@@ -42,35 +42,12 @@
|
||||
#include "sys/mount.h"
|
||||
#include "errno.h"
|
||||
#include "fs/fs.h"
|
||||
|
||||
#include "inode/inode.h"
|
||||
#include "fs/vnode.h"
|
||||
#include "stdlib.h"
|
||||
|
||||
#include "unistd.h"
|
||||
#include "string.h"
|
||||
#include "disk.h"
|
||||
|
||||
#ifdef LOSCFG_FS_ZPFS
|
||||
#include "vfs_zpfs.h"
|
||||
#endif
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Variables
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Data
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
#include "fs_other.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
@@ -94,15 +71,26 @@
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
BOOL fs_in_use(struct Mount *mnt, const char *target)
|
||||
{
|
||||
char cwd[PATH_MAX];
|
||||
char *pret = getcwd(cwd, PATH_MAX);
|
||||
if (pret != NULL)
|
||||
{
|
||||
if (!strncmp(target, cwd, strlen(target)))
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
return VnodeInUseIter(mnt->vnodeCovered);
|
||||
}
|
||||
|
||||
int umount(const char *target)
|
||||
{
|
||||
FAR struct inode *mountpt_inode = NULL;
|
||||
FAR struct inode *blkdrvr_inode = NULL;
|
||||
int errcode = OK;
|
||||
int status;
|
||||
char *fullpath = NULL;
|
||||
const char *relpath = NULL;
|
||||
struct inode_search_s desc;
|
||||
struct Vnode *mountpt_vnode = NULL;
|
||||
struct Vnode *blkdrvr_vnode = NULL;
|
||||
struct Vnode *covered_vnode = NULL;
|
||||
struct Mount *mnt = NULL;
|
||||
int ret;
|
||||
#ifdef LOSCFG_FS_ZPFS
|
||||
bool isZpfs = false;
|
||||
@@ -113,117 +101,87 @@ int umount(const char *target)
|
||||
|
||||
if (target == NULL)
|
||||
{
|
||||
errcode = EFAULT;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* Get a absolute path*/
|
||||
|
||||
errcode = vfs_normalize_path((const char *)NULL, target, &fullpath);
|
||||
if (errcode < 0)
|
||||
{
|
||||
errcode = -errcode;
|
||||
ret = -EFAULT;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* Find the mountpt */
|
||||
SETUP_SEARCH(&desc, fullpath, false);
|
||||
ret = inode_find(&desc);
|
||||
if (ret < 0)
|
||||
VnodeHold();
|
||||
ret = VnodeLookup(target, &mountpt_vnode, 0);
|
||||
if (ret != OK || !mountpt_vnode)
|
||||
{
|
||||
errcode = EACCES;
|
||||
free(fullpath);
|
||||
goto errout;
|
||||
}
|
||||
mountpt_inode = desc.node;
|
||||
relpath = desc.relpath;
|
||||
|
||||
/* Verify that the inode is a mountpoint */
|
||||
|
||||
if (!INODE_IS_MOUNTPT(mountpt_inode))
|
||||
/* Verify that the vnode is a mountpoint */
|
||||
if (!mountpt_vnode || !(mountpt_vnode->flag & VNODE_FLAG_MOUNT_ORIGIN))
|
||||
{
|
||||
errcode = EINVAL;
|
||||
goto errout_with_mountpt;
|
||||
ret = -EINVAL;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* Verfy the path is a mountpoint path or file path*/
|
||||
|
||||
if ((relpath != NULL) && strlen(relpath))
|
||||
/* Get mount point covered vnode and mount structure */
|
||||
mnt = mountpt_vnode->originMount;
|
||||
if (!mnt)
|
||||
{
|
||||
errcode = EPERM;
|
||||
goto errout_with_mountpt;
|
||||
ret = -EINVAL;
|
||||
goto errout;
|
||||
}
|
||||
covered_vnode = mnt->vnodeBeCovered;
|
||||
if (!covered_vnode || !(covered_vnode->flag & VNODE_FLAG_MOUNT_NEW))
|
||||
{
|
||||
ret = -EINVAL;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* Unbind the block driver from the file system (destroying any fs
|
||||
* private data.
|
||||
*/
|
||||
|
||||
if (mountpt_inode->u.i_mops->unbind == NULL)
|
||||
if (mnt->ops == NULL || mnt->ops->Unmount == NULL)
|
||||
{
|
||||
/* The filesystem does not support the unbind operation ??? */
|
||||
|
||||
errcode = EINVAL;
|
||||
goto errout_with_mountpt;
|
||||
ret = -EINVAL;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
inode_semtake(); /* Hold the semaphore through the unbind logic */
|
||||
|
||||
#ifdef LOSCFG_FS_ZPFS
|
||||
if (IsZpfsFileSystem(mountpt_inode))
|
||||
if (IsZpfsFileSystem(mountpt_vnode))
|
||||
{
|
||||
isZpfs = true;
|
||||
zpfsInode.i_private = mountpt_inode->i_private;
|
||||
zpfsInode.u.i_ops = mountpt_inode->u.i_ops;
|
||||
zpfsInode.i_flags = mountpt_inode->i_flags;
|
||||
zpfsInode.i_private = mountpt_vnode->i_private;
|
||||
zpfsInode.u.i_ops = mountpt_vnode->u.i_ops;
|
||||
zpfsInode.i_flags = mountpt_vnode->i_flags;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (mountpt_inode->i_crefs == 1)
|
||||
/* Release the vnode under the mount point */
|
||||
if (fs_in_use(mnt, target))
|
||||
{
|
||||
status = mountpt_inode->u.i_mops->unbind(mountpt_inode->i_private, &blkdrvr_inode);
|
||||
if (status < 0)
|
||||
{
|
||||
/* The inode is unhappy with the blkdrvr for some reason */
|
||||
|
||||
errcode = -status;
|
||||
goto errout_with_semaphore;
|
||||
}
|
||||
else if (status > 0)
|
||||
{
|
||||
errcode = EBUSY;
|
||||
goto errout_with_semaphore;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
errcode = EBUSY;
|
||||
goto errout_with_semaphore;
|
||||
}
|
||||
/* Successfully unbound */
|
||||
|
||||
mountpt_inode->i_private = NULL;
|
||||
mountpt_inode->u.i_ops= (const struct file_operations_vfs *)NULL;
|
||||
mountpt_inode->i_flags = 0;
|
||||
|
||||
inode_release(mountpt_inode);
|
||||
|
||||
/* Successfully unbound, remove the mountpoint inode from
|
||||
* the inode tree. The inode will not be deleted yet because
|
||||
* there is still at least reference on it (from the mount)
|
||||
*/
|
||||
|
||||
if (blkdrvr_inode)
|
||||
{
|
||||
blkdrvr_inode->e_status = STAT_UNMOUNTED;
|
||||
ret = -EBUSY;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
inode_semgive();
|
||||
ret = VnodeFreeAll(mnt);
|
||||
if (ret != OK)
|
||||
{
|
||||
goto errout;
|
||||
}
|
||||
/* Umount the filesystem */
|
||||
ret = mnt->ops->Unmount(mnt, &blkdrvr_vnode);
|
||||
if (ret != OK)
|
||||
{
|
||||
goto errout;
|
||||
}
|
||||
|
||||
VnodeFree(mountpt_vnode);
|
||||
LOS_ListDelete(&mnt->mountList);
|
||||
free(mnt);
|
||||
|
||||
/* Did the unbind method return a contained block driver */
|
||||
|
||||
if (blkdrvr_inode)
|
||||
if (blkdrvr_vnode)
|
||||
{
|
||||
inode_release(blkdrvr_inode);
|
||||
; /* block driver operations after umount */
|
||||
}
|
||||
|
||||
#ifdef LOSCFG_FS_ZPFS
|
||||
@@ -232,23 +190,16 @@ int umount(const char *target)
|
||||
ZpfsCleanUp((void*)&zpfsInode, fullpath);
|
||||
}
|
||||
#endif
|
||||
covered_vnode->newMount = NULL;
|
||||
covered_vnode->flag &= ~(VNODE_FLAG_MOUNT_NEW);
|
||||
VnodeDrop();
|
||||
|
||||
free(fullpath);
|
||||
return OK;
|
||||
|
||||
/* A lot of goto's! But they make the error handling much simpler */
|
||||
|
||||
errout_with_semaphore:
|
||||
inode_semgive();
|
||||
errout_with_mountpt:
|
||||
mountpt_inode->i_crefs--;
|
||||
if (blkdrvr_inode)
|
||||
{
|
||||
inode_release(blkdrvr_inode);
|
||||
}
|
||||
free(fullpath);
|
||||
errout:
|
||||
set_errno(errcode);
|
||||
VnodeDrop();
|
||||
set_errno(-ret);
|
||||
return VFS_ERROR;
|
||||
}
|
||||
|
||||
@@ -261,4 +212,3 @@ int umount2(const char* __target, int __flags)
|
||||
}
|
||||
return umount(__target);
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Executable → Regular
+3
@@ -101,6 +101,9 @@ struct nfsmount
|
||||
uint16_t nm_wsize; /* Max size of write RPC */
|
||||
uint16_t nm_readdirsize; /* Size of a readdir RPC */
|
||||
uint16_t nm_buflen; /* Size of I/O buffer */
|
||||
mode_t nm_permission;
|
||||
uint nm_gid;
|
||||
uint nm_uid;
|
||||
|
||||
/* Set aside memory on the stack to hold the largest call message. NOTE
|
||||
* that for the case of the write call message, it is the reply message that
|
||||
|
||||
Executable → Regular
+2
@@ -81,6 +81,7 @@ struct nfsnode
|
||||
uint8_t n_fhsize; /* Size in bytes of the file handle */
|
||||
uint8_t n_flags; /* Node flags */
|
||||
uint16_t n_mode; /* File mode for fstat() */
|
||||
time_t n_atime; /* File access time */
|
||||
time_t n_mtime; /* File modification time */
|
||||
time_t n_ctime; /* File creation time */
|
||||
nfsfh_t n_fhandle; /* NFS File Handle */
|
||||
@@ -88,6 +89,7 @@ struct nfsnode
|
||||
int n_oflags; /* Flags provided when file was opened */
|
||||
loff_t n_fpos; /* NFS File position */
|
||||
struct file *n_filep; /* File pointer from VFS */
|
||||
char *n_name;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
Executable → Regular
+27
-28
@@ -57,11 +57,11 @@
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
static inline int nfs_pathsegment(FAR const char **path, FAR char *buffer,
|
||||
FAR char *terminator)
|
||||
static inline int nfs_pathsegment(const char **path, char *buffer,
|
||||
char *terminator)
|
||||
{
|
||||
FAR const char *src = *path;
|
||||
FAR char *dest = buffer;
|
||||
const char *src = *path;
|
||||
char *dest = buffer;
|
||||
int nbytes = 0;
|
||||
char ch;
|
||||
|
||||
@@ -177,8 +177,8 @@ int nfs_checkmount(struct nfsmount *nmp)
|
||||
****************************************************************************/
|
||||
|
||||
int nfs_request(struct nfsmount *nmp, int procnum,
|
||||
FAR void *request, size_t reqlen,
|
||||
FAR void *response, size_t resplen)
|
||||
void *request, size_t reqlen,
|
||||
void *response, size_t resplen)
|
||||
{
|
||||
struct rpcclnt *clnt = nmp->nm_rpcclnt;
|
||||
struct nfs_reply_header replyh;
|
||||
@@ -189,7 +189,7 @@ tryagain:
|
||||
request, reqlen, response, resplen);
|
||||
if (error != 0)
|
||||
{
|
||||
ferr("ERROR: rpcclnt_request failed: %d\n", error);
|
||||
PRINTK("ERROR: rpcclnt_request failed: %d\n", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
@@ -213,11 +213,10 @@ tryagain:
|
||||
goto tryagain;
|
||||
}
|
||||
|
||||
ferr("ERROR: NFS error %d from server\n", error);
|
||||
PRINTK("ERROR: NFS error %d from server\n", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
finfo("NFS_SUCCESS\n");
|
||||
return OK;
|
||||
}
|
||||
|
||||
@@ -235,12 +234,12 @@ tryagain:
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int nfs_lookup(struct nfsmount *nmp, FAR const char *filename,
|
||||
FAR struct file_handle *fhandle,
|
||||
FAR struct nfs_fattr *obj_attributes,
|
||||
FAR struct nfs_fattr *dir_attributes)
|
||||
int nfs_lookup(struct nfsmount *nmp, const char *filename,
|
||||
struct file_handle *fhandle,
|
||||
struct nfs_fattr *obj_attributes,
|
||||
struct nfs_fattr *dir_attributes)
|
||||
{
|
||||
FAR uint32_t *ptr;
|
||||
uint32_t *ptr = NULL;
|
||||
uint32_t value;
|
||||
int reqlen;
|
||||
int namelen;
|
||||
@@ -259,7 +258,7 @@ int nfs_lookup(struct nfsmount *nmp, FAR const char *filename,
|
||||
|
||||
/* Initialize the request */
|
||||
|
||||
ptr = (FAR uint32_t *)&nmp->nm_msgbuffer.lookup.lookup;
|
||||
ptr = (uint32_t *)&nmp->nm_msgbuffer.lookup.lookup;
|
||||
reqlen = 0;
|
||||
|
||||
/* Copy the variable length, directory file handle */
|
||||
@@ -283,8 +282,8 @@ int nfs_lookup(struct nfsmount *nmp, FAR const char *filename,
|
||||
|
||||
nfs_statistics(NFSPROC_LOOKUP);
|
||||
error = nfs_request(nmp, NFSPROC_LOOKUP,
|
||||
(FAR void *)&nmp->nm_msgbuffer.lookup, reqlen,
|
||||
(FAR void *)nmp->nm_iobuffer, nmp->nm_buflen);
|
||||
(void *)&nmp->nm_msgbuffer.lookup, reqlen,
|
||||
(void *)nmp->nm_iobuffer, nmp->nm_buflen);
|
||||
|
||||
if (error)
|
||||
{
|
||||
@@ -297,7 +296,7 @@ int nfs_lookup(struct nfsmount *nmp, FAR const char *filename,
|
||||
* may differ in size whereas struct rpc_reply_lookup uses a fixed size.
|
||||
*/
|
||||
|
||||
ptr = (FAR uint32_t *)&((FAR struct rpc_reply_lookup *)nmp->nm_iobuffer)->lookup;
|
||||
ptr = (uint32_t *)&((struct rpc_reply_lookup *)nmp->nm_iobuffer)->lookup;
|
||||
|
||||
/* Get the length of the file handle */
|
||||
|
||||
@@ -355,12 +354,12 @@ int nfs_lookup(struct nfsmount *nmp, FAR const char *filename,
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int nfs_findnode(struct nfsmount *nmp, FAR const char *relpath,
|
||||
FAR struct file_handle *fhandle,
|
||||
FAR struct nfs_fattr *obj_attributes,
|
||||
FAR struct nfs_fattr *dir_attributes)
|
||||
int nfs_findnode(struct nfsmount *nmp, const char *relpath,
|
||||
struct file_handle *fhandle,
|
||||
struct nfs_fattr *obj_attributes,
|
||||
struct nfs_fattr *dir_attributes)
|
||||
{
|
||||
FAR const char *path = relpath;
|
||||
const char *path = relpath;
|
||||
char buffer[NAME_MAX + 1];
|
||||
char terminator;
|
||||
uint32_t tmp;
|
||||
@@ -464,11 +463,11 @@ int nfs_findnode(struct nfsmount *nmp, FAR const char *relpath,
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int nfs_finddir(struct nfsmount *nmp, FAR const char *relpath,
|
||||
FAR struct file_handle *fhandle,
|
||||
FAR struct nfs_fattr *attributes, FAR char *filename)
|
||||
int nfs_finddir(struct nfsmount *nmp, const char *relpath,
|
||||
struct file_handle *fhandle,
|
||||
struct nfs_fattr *attributes, char *filename)
|
||||
{
|
||||
FAR const char *path = relpath;
|
||||
const char *path = relpath;
|
||||
uint32_t tmp;
|
||||
char terminator;
|
||||
int error;
|
||||
@@ -553,7 +552,7 @@ int nfs_finddir(struct nfsmount *nmp, FAR const char *relpath,
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void nfs_attrupdate(FAR struct nfsnode *np, FAR struct nfs_fattr *attributes)
|
||||
void nfs_attrupdate(struct nfsnode *np, struct nfs_fattr *attributes)
|
||||
{
|
||||
struct timespec ts;
|
||||
|
||||
|
||||
-3560
File diff suppressed because it is too large
Load Diff
Executable → Regular
+35
-35
@@ -134,16 +134,16 @@ static struct rpcstats rpcstats;
|
||||
* Private Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
static int rpcclnt_send(FAR struct rpcclnt *rpc, int procid, int prog,
|
||||
FAR void *call, int reqlen);
|
||||
static int rpcclnt_receive(FAR struct rpcclnt *rpc, struct sockaddr *aname,
|
||||
static int rpcclnt_send(struct rpcclnt *rpc, int procid, int prog,
|
||||
void *call, int reqlen);
|
||||
static int rpcclnt_receive(struct rpcclnt *rpc, struct sockaddr *aname,
|
||||
int proc, int program, void *reply, size_t resplen);
|
||||
static int rpcclnt_reply(FAR struct rpcclnt *rpc, int procid, int prog,
|
||||
static int rpcclnt_reply(struct rpcclnt *rpc, int procid, int prog,
|
||||
void *reply, size_t resplen);
|
||||
static uint32_t rpcclnt_newxid(void);
|
||||
static void rpcclnt_fmtheader(FAR struct rpc_call_header *ch,
|
||||
static void rpcclnt_fmtheader(struct rpc_call_header *ch,
|
||||
uint32_t xid, int procid, int prog, int vers, size_t reqlen);
|
||||
static int rpcclnt_reconnect(FAR struct rpcclnt *rpc, struct sockaddr *saddr);
|
||||
static int rpcclnt_reconnect(struct rpcclnt *rpc, struct sockaddr *saddr);
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
@@ -160,8 +160,8 @@ static int rpcclnt_reconnect(FAR struct rpcclnt *rpc, struct sockaddr *saddr);
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int rpcclnt_send(FAR struct rpcclnt *rpc, int procid, int prog,
|
||||
FAR void *call, int reqlen)
|
||||
static int rpcclnt_send(struct rpcclnt *rpc, int procid, int prog,
|
||||
void *call, int reqlen)
|
||||
{
|
||||
ssize_t nbytes;
|
||||
int ret = OK;
|
||||
@@ -196,8 +196,8 @@ static int rpcclnt_send(FAR struct rpcclnt *rpc, int procid, int prog,
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int rpcclnt_receive(FAR struct rpcclnt *rpc, FAR struct sockaddr *aname,
|
||||
int proc, int program, FAR void *reply,
|
||||
static int rpcclnt_receive(struct rpcclnt *rpc, struct sockaddr *aname,
|
||||
int proc, int program, void *reply,
|
||||
size_t resplen)
|
||||
{
|
||||
ssize_t nbytes;
|
||||
@@ -261,8 +261,8 @@ retry:
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int rpcclnt_receive(FAR struct rpcclnt *rpc, FAR struct sockaddr *aname,
|
||||
int proc, int program, FAR void *reply,
|
||||
static int rpcclnt_receive(struct rpcclnt *rpc, struct sockaddr *aname,
|
||||
int proc, int program, void *reply,
|
||||
size_t resplen)
|
||||
{
|
||||
ssize_t nbytes;
|
||||
@@ -350,8 +350,8 @@ static int rpcclnt_receive(FAR struct rpcclnt *rpc, FAR struct sockaddr *aname,
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int rpcclnt_reply(FAR struct rpcclnt *rpc, int procid, int prog,
|
||||
FAR void *reply, size_t resplen)
|
||||
static int rpcclnt_reply(struct rpcclnt *rpc, int procid, int prog,
|
||||
void *reply, size_t resplen)
|
||||
{
|
||||
int error;
|
||||
|
||||
@@ -378,8 +378,8 @@ static int rpcclnt_reply(FAR struct rpcclnt *rpc, int procid, int prog,
|
||||
|
||||
else
|
||||
{
|
||||
FAR struct rpc_reply_header *replyheader =
|
||||
(FAR struct rpc_reply_header *)reply;
|
||||
struct rpc_reply_header *replyheader =
|
||||
(struct rpc_reply_header *)reply;
|
||||
|
||||
if (replyheader->rp_direction != rpc_reply)
|
||||
{
|
||||
@@ -501,7 +501,7 @@ static int rpcclnt_alivecheck(struct rpcclnt *rpc)
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void rpcclnt_fmtheader(FAR struct rpc_call_header *ch,
|
||||
static void rpcclnt_fmtheader(struct rpc_call_header *ch,
|
||||
uint32_t xid, int prog, int vers, int procid, size_t reqlen)
|
||||
{
|
||||
unsigned int high = 0;
|
||||
@@ -545,7 +545,7 @@ static void rpcclnt_fmtheader(FAR struct rpc_call_header *ch,
|
||||
ch->rpc_verf.authlen = 0;
|
||||
}
|
||||
|
||||
static int rpcclnt_reconnect(FAR struct rpcclnt *rpc, struct sockaddr *saddr)
|
||||
static int rpcclnt_reconnect(struct rpcclnt *rpc, struct sockaddr *saddr)
|
||||
{
|
||||
int errval;
|
||||
int error;
|
||||
@@ -732,15 +732,15 @@ int rpcclnt_connect(struct rpcclnt *rpc)
|
||||
request.sdata.pmap.port = 0;
|
||||
|
||||
error = rpcclnt_request(rpc, PMAPPROC_GETPORT, PMAPPROG, PMAPVERS,
|
||||
(FAR void *)&request.sdata, sizeof(struct call_args_pmap),
|
||||
(FAR void *)&response.rdata, sizeof(struct rpc_reply_pmap));
|
||||
(void *)&request.sdata, sizeof(struct call_args_pmap),
|
||||
(void *)&response.rdata, sizeof(struct rpc_reply_pmap));
|
||||
if (error != 0)
|
||||
{
|
||||
ferr("ERROR: rpcclnt_request failed: %d\n", error);
|
||||
goto bad;
|
||||
}
|
||||
|
||||
sa = (FAR struct sockaddr_in *)saddr;
|
||||
sa = (struct sockaddr_in *)saddr;
|
||||
sa->sin_port = htons(fxdr_unsigned(uint32_t, response.rdata.pmap.port));
|
||||
|
||||
error = rpcclnt_reconnect(rpc, saddr);
|
||||
@@ -768,9 +768,9 @@ int rpcclnt_connect(struct rpcclnt *rpc)
|
||||
request.mountd.mount.len = txdr_unsigned(sizeof(request.mountd.mount.rpath));
|
||||
|
||||
error = rpcclnt_request(rpc, RPCMNT_MOUNT, RPCPROG_MNT, RPCMNT_VER3,
|
||||
(FAR void *)&request.mountd,
|
||||
(void *)&request.mountd,
|
||||
sizeof(struct call_args_mount),
|
||||
(FAR void *)&response.mdata,
|
||||
(void *)&response.mdata,
|
||||
sizeof(struct rpc_reply_mount));
|
||||
if (error != 0)
|
||||
{
|
||||
@@ -807,9 +807,9 @@ int rpcclnt_connect(struct rpcclnt *rpc)
|
||||
request.sdata.pmap.port = 0;
|
||||
|
||||
error = rpcclnt_request(rpc, PMAPPROC_GETPORT, PMAPPROG, PMAPVERS,
|
||||
(FAR void *)&request.sdata,
|
||||
(void *)&request.sdata,
|
||||
sizeof(struct call_args_pmap),
|
||||
(FAR void *)&response.rdata,
|
||||
(void *)&response.rdata,
|
||||
sizeof(struct rpc_reply_pmap));
|
||||
if (error != 0)
|
||||
{
|
||||
@@ -878,7 +878,7 @@ int rpcclnt_umount(struct rpcclnt *rpc)
|
||||
int error;
|
||||
|
||||
saddr = rpc->rc_name;
|
||||
sa = (FAR struct sockaddr_in *)saddr;
|
||||
sa = (struct sockaddr_in *)saddr;
|
||||
|
||||
/* Do the RPC to get a dynamic bounding with the server using ppmap.
|
||||
* Get port number for MOUNTD.
|
||||
@@ -899,9 +899,9 @@ int rpcclnt_umount(struct rpcclnt *rpc)
|
||||
request.sdata.pmap.port = 0;
|
||||
|
||||
error = rpcclnt_request(rpc, PMAPPROC_GETPORT, PMAPPROG, PMAPVERS,
|
||||
(FAR void *)&request.sdata,
|
||||
(void *)&request.sdata,
|
||||
sizeof(struct call_args_pmap),
|
||||
(FAR void *)&response.rdata,
|
||||
(void *)&response.rdata,
|
||||
sizeof(struct rpc_reply_pmap));
|
||||
if (error != 0)
|
||||
{
|
||||
@@ -926,9 +926,9 @@ int rpcclnt_umount(struct rpcclnt *rpc)
|
||||
request.mountd.umount.len = txdr_unsigned(sizeof(request.mountd.umount.rpath));
|
||||
|
||||
error = rpcclnt_request(rpc, RPCMNT_UMOUNT, RPCPROG_MNT, RPCMNT_VER3,
|
||||
(FAR void *)&request.mountd,
|
||||
(void *)&request.mountd,
|
||||
sizeof(struct call_args_umount),
|
||||
(FAR void *)&response.mdata,
|
||||
(void *)&response.mdata,
|
||||
sizeof(struct rpc_reply_umount));
|
||||
if (error != 0)
|
||||
{
|
||||
@@ -960,9 +960,9 @@ bad:
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int rpcclnt_request(FAR struct rpcclnt *rpc, int procnum, int prog,
|
||||
int version, FAR void *request, size_t reqlen,
|
||||
FAR void *response, size_t resplen)
|
||||
int rpcclnt_request(struct rpcclnt *rpc, int procnum, int prog,
|
||||
int version, void *request, size_t reqlen,
|
||||
void *response, size_t resplen)
|
||||
{
|
||||
struct rpc_reply_header *replymsg;
|
||||
uint32_t tmp;
|
||||
@@ -983,7 +983,7 @@ int rpcclnt_request(FAR struct rpcclnt *rpc, int procnum, int prog,
|
||||
|
||||
/* Initialize the RPC header fields */
|
||||
|
||||
rpcclnt_fmtheader((FAR struct rpc_call_header *)request,
|
||||
rpcclnt_fmtheader((struct rpc_call_header *)request,
|
||||
rpc->xid, prog, version, procnum, reqlen);
|
||||
|
||||
/* Send the RPC call messsages and receive the RPC response. For UDP-RPC, A limited
|
||||
@@ -1081,7 +1081,7 @@ int rpcclnt_request(FAR struct rpcclnt *rpc, int procnum, int prog,
|
||||
|
||||
/* Break down the RPC header and check if it is OK */
|
||||
|
||||
replymsg = (FAR struct rpc_reply_header *)response;
|
||||
replymsg = (struct rpc_reply_header *)response;
|
||||
|
||||
tmp = fxdr_unsigned(uint32_t, replymsg->type);
|
||||
if (tmp == RPC_MSGDENIED)
|
||||
|
||||
+649
-541
File diff suppressed because it is too large
Load Diff
+3
-1
@@ -177,9 +177,11 @@ struct tmpfs_file_s
|
||||
struct tmpfs_s
|
||||
{
|
||||
/* The root directory */
|
||||
|
||||
FAR struct tmpfs_dirent_s tfs_root;
|
||||
struct tmpfs_sem_s tfs_exclsem;
|
||||
mode_t permission;
|
||||
uint gid;
|
||||
uint uid;
|
||||
};
|
||||
|
||||
/* This is the type used the tmpfs_statfs_callout to accumulate memory usage */
|
||||
|
||||
Executable → Regular
-1
@@ -48,7 +48,6 @@
|
||||
# include "net/net.h"
|
||||
#endif
|
||||
|
||||
#include "inode/inode.h"
|
||||
#include "mqueue.h"
|
||||
|
||||
/****************************************************************************
|
||||
|
||||
+1
-1
@@ -44,7 +44,7 @@
|
||||
#include "sched.h"
|
||||
|
||||
#include "fs/fs.h"
|
||||
#include "inode/inode.h"
|
||||
#include "fs/vnode.h"
|
||||
#include "net/net.h"
|
||||
|
||||
/****************************************************************************
|
||||
|
||||
+1
-2
@@ -43,8 +43,7 @@
|
||||
#include "errno.h"
|
||||
#include "unistd.h"
|
||||
#include "sched.h"
|
||||
|
||||
#include "inode/inode.h"
|
||||
#include "fs/vnode.h"
|
||||
|
||||
/* This logic in this applies only when both socket and file descriptors are
|
||||
* in that case, this function descriminates which type of dup2 is being
|
||||
|
||||
Executable → Regular
+16
-28
@@ -47,7 +47,7 @@
|
||||
#include "fs/fs.h"
|
||||
#include "fs/file.h"
|
||||
|
||||
#include "inode/inode.h"
|
||||
#include "fs/vnode.h"
|
||||
#include "stdlib.h"
|
||||
#include "string.h"
|
||||
#if CONFIG_NFILE_DESCRIPTORS > 0
|
||||
@@ -74,19 +74,18 @@
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int file_dup(FAR struct file *filep, int minfd)
|
||||
int file_dup(struct file *filep, int minfd)
|
||||
{
|
||||
int fd2;
|
||||
int ret;
|
||||
int err,len;
|
||||
int err,len,rellen;
|
||||
struct file *filep2 = NULL;
|
||||
char *fullpath = NULL;
|
||||
const char *relpath = NULL;
|
||||
struct inode_search_s desc;
|
||||
char *relpath = NULL;
|
||||
|
||||
/* Verify that fd is a valid, open file descriptor */
|
||||
|
||||
if ((filep->f_inode == NULL) || (filep->f_path == NULL))
|
||||
if ((filep->f_vnode == NULL) || (filep->f_path == NULL))
|
||||
{
|
||||
set_errno(EBADF);
|
||||
return VFS_ERROR;
|
||||
@@ -100,12 +99,11 @@ int file_dup(FAR struct file *filep, int minfd)
|
||||
return VFS_ERROR;
|
||||
}
|
||||
|
||||
/* Then allocate a new file descriptor for the inode */
|
||||
/* Then allocate a new file descriptor for the vnode */
|
||||
|
||||
fd2 = files_allocate(filep->f_inode, filep->f_oflags, filep->f_pos, filep->f_priv, minfd);
|
||||
fd2 = files_allocate(filep->f_vnode, filep->f_oflags, filep->f_pos, filep->f_priv, minfd);
|
||||
if (fd2 < 0)
|
||||
{
|
||||
inode_release(filep->f_inode);
|
||||
free(fullpath);
|
||||
set_errno(EMFILE);
|
||||
return VFS_ERROR;
|
||||
@@ -114,39 +112,29 @@ int file_dup(FAR struct file *filep, int minfd)
|
||||
ret = fs_getfilep(fd2, &filep2);
|
||||
|
||||
(void)strncpy_s(fullpath, len + 1, filep->f_path, len);
|
||||
SETUP_SEARCH(&desc, fullpath, false);
|
||||
if (inode_find(&desc) < 0)
|
||||
if (filep->f_relpath != NULL)
|
||||
{
|
||||
ret = -EACCES;
|
||||
goto errout_with_inode;
|
||||
rellen = strlen(filep->f_relpath);
|
||||
relpath = (char *)zalloc(rellen + 1);
|
||||
(void)strncpy_s(relpath, rellen + 1, filep->f_relpath, rellen);
|
||||
}
|
||||
relpath = desc.relpath;
|
||||
filep2->f_path = fullpath;
|
||||
filep2->f_relpath = relpath;
|
||||
|
||||
if (filep->f_inode->u.i_mops && filep->f_inode->u.i_mops->dup)
|
||||
{
|
||||
ret = filep->f_inode->u.i_mops->dup(filep, filep2);
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = -ENOSYS;
|
||||
}
|
||||
filep2->f_priv = filep->f_priv;
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
goto errout_with_inode;
|
||||
goto errout_with_vnode;
|
||||
}
|
||||
|
||||
return fd2;
|
||||
|
||||
errout_with_inode:
|
||||
errout_with_vnode:
|
||||
clear_fd(fd2);
|
||||
inode_release(filep2->f_inode);
|
||||
free(fullpath);
|
||||
filep2->f_oflags = 0;
|
||||
filep2->f_pos = 0;
|
||||
filep2->f_inode = NULL;
|
||||
filep2->f_vnode = NULL;
|
||||
filep2->f_priv = NULL;
|
||||
filep2->f_path = NULL;
|
||||
filep2->f_relpath = NULL;
|
||||
@@ -175,7 +163,7 @@ errout_with_inode:
|
||||
|
||||
int fs_dupfd(int fd, int minfd)
|
||||
{
|
||||
FAR struct file *filep;
|
||||
struct file *filep;
|
||||
|
||||
/* Get the file structure corresponding to the file descriptor. */
|
||||
|
||||
|
||||
Executable → Regular
+4
-4
@@ -44,7 +44,7 @@
|
||||
#include "unistd.h"
|
||||
#include "sched.h"
|
||||
|
||||
#include "inode/inode.h"
|
||||
#include "fs/vnode.h"
|
||||
|
||||
#if CONFIG_NFILE_DESCRIPTORS > 0
|
||||
|
||||
@@ -82,8 +82,8 @@ int fs_dupfd2(int fd1, int fd2)
|
||||
int dup2(int fd1, int fd2)
|
||||
#endif
|
||||
{
|
||||
FAR struct file *filep1;
|
||||
FAR struct file *filep2;
|
||||
struct file *filep1;
|
||||
struct file *filep2;
|
||||
int ret;
|
||||
|
||||
/* Get the file structures corresponding to the file descriptors. */
|
||||
@@ -103,7 +103,7 @@ int dup2(int fd1, int fd2)
|
||||
|
||||
/* Verify that fd1 is a valid, open file descriptor */
|
||||
|
||||
if (filep1->f_inode == NULL)
|
||||
if (filep1->f_vnode == NULL)
|
||||
{
|
||||
set_errno(EBADF);
|
||||
return VFS_ERROR;
|
||||
|
||||
Executable → Regular
+5
-5
@@ -45,7 +45,7 @@
|
||||
#include "errno.h"
|
||||
#include "assert.h"
|
||||
#include "fs/fs.h"
|
||||
#include "inode/inode.h"
|
||||
#include "fs/vnode.h"
|
||||
|
||||
#if defined(LOSCFG_NET_LWIP_SACK)
|
||||
#include "lwip/sockets.h"
|
||||
@@ -81,14 +81,14 @@
|
||||
****************************************************************************/
|
||||
|
||||
#if CONFIG_NFILE_DESCRIPTORS > 0
|
||||
int file_vfcntl(FAR struct file *filep, int cmd, va_list ap)
|
||||
int file_vfcntl(struct file *filep, int cmd, va_list ap)
|
||||
{
|
||||
int err = 0;
|
||||
int ret = OK;
|
||||
|
||||
/* Was this file opened ? */
|
||||
|
||||
if (!filep || !filep->f_inode)
|
||||
if (!filep || !filep->f_vnode)
|
||||
{
|
||||
err = EBADF;
|
||||
goto errout;
|
||||
@@ -257,7 +257,7 @@ errout:
|
||||
|
||||
int fcntl(int fd, int cmd, ...)
|
||||
{
|
||||
FAR struct file *filep;
|
||||
struct file *filep = NULL;
|
||||
va_list ap;
|
||||
int ret;
|
||||
int val = 0;
|
||||
@@ -319,7 +319,7 @@ int fcntl(int fd, int cmd, ...)
|
||||
|
||||
int fcntl64(int fd, int cmd, ...)
|
||||
{
|
||||
FAR struct file *filep = NULL;
|
||||
struct file *filep = NULL;
|
||||
va_list va_ap;
|
||||
int reval;
|
||||
int va_val = 0;
|
||||
|
||||
Executable → Regular
+7
-13
@@ -48,9 +48,7 @@
|
||||
#include "fs/fs.h"
|
||||
|
||||
|
||||
#include "inode/inode.h"
|
||||
|
||||
#ifndef CONFIG_DISABLE_MOUNTPOINT
|
||||
#include "fs/vnode.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
@@ -66,9 +64,8 @@
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int file_fsync(FAR struct file *filep)
|
||||
int file_fsync(struct file *filep)
|
||||
{
|
||||
struct inode *inode;
|
||||
int ret;
|
||||
|
||||
/* Was this file opened for write access? */
|
||||
@@ -79,14 +76,12 @@ int file_fsync(FAR struct file *filep)
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* Is this inode a registered mountpoint? Does it support the
|
||||
/* Is this vnode a registered mountpoint? Does it support the
|
||||
* sync operations may be relevant to device drivers but only
|
||||
* the mountpoint operations vtable contains a sync method.
|
||||
*/
|
||||
|
||||
inode = filep->f_inode;
|
||||
if (!inode || !INODE_IS_MOUNTPT(inode) ||
|
||||
!inode->u.i_mops || !inode->u.i_mops->sync)
|
||||
if (!filep || !filep->ops || !filep->ops->fsync)
|
||||
{
|
||||
ret = EINVAL;
|
||||
goto errout;
|
||||
@@ -94,7 +89,7 @@ int file_fsync(FAR struct file *filep)
|
||||
|
||||
/* Yes, then tell the mountpoint to sync this file */
|
||||
|
||||
ret = inode->u.i_mops->sync(filep);
|
||||
ret = filep->ops->fsync(filep);
|
||||
if (ret >= 0)
|
||||
{
|
||||
return OK;
|
||||
@@ -111,13 +106,13 @@ errout:
|
||||
* Name: fsync
|
||||
*
|
||||
* Description:
|
||||
* This func simply binds inode sync methods to the sync system call.
|
||||
* This func simply binds vnode sync methods to the sync system call.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int fsync(int fd)
|
||||
{
|
||||
FAR struct file *filep;
|
||||
struct file *filep = NULL;
|
||||
|
||||
/* Get the file structure corresponding to the file descriptor. */
|
||||
|
||||
@@ -133,4 +128,3 @@ int fsync(int fd)
|
||||
return file_fsync(filep);
|
||||
}
|
||||
|
||||
#endif /* !CONFIG_DISABLE_MOUNTPOINT */
|
||||
|
||||
Executable → Regular
+9
-5
@@ -41,9 +41,12 @@
|
||||
#include "sys/types.h"
|
||||
|
||||
#include "errno.h"
|
||||
#include "unistd.h"
|
||||
#include "console.h"
|
||||
#include "sched.h"
|
||||
|
||||
#include "inode/inode.h"
|
||||
#include "sys/types.h"
|
||||
#include "fs/vnode.h"
|
||||
#include "vfs_config.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
@@ -67,7 +70,7 @@
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int fs_getfilep_normal(int fd, FAR struct file **filep)
|
||||
static int fs_getfilep_normal(int fd, struct file **filep)
|
||||
{
|
||||
struct filelist *list;
|
||||
|
||||
@@ -102,12 +105,13 @@ int fs_getfilep_normal(int fd, FAR struct file **filep)
|
||||
return OK;
|
||||
}
|
||||
|
||||
int fs_getfilep(int fd, FAR struct file **filep)
|
||||
int fs_getfilep(int fd, struct file **filep)
|
||||
{
|
||||
int ret = fs_getfilep_normal(fd, filep);
|
||||
if (ret < 0)
|
||||
{
|
||||
set_errno(-ret);
|
||||
return VFS_ERROR;
|
||||
}
|
||||
return ret;
|
||||
return OK;
|
||||
}
|
||||
|
||||
Executable → Regular
+6
-8
@@ -49,7 +49,7 @@
|
||||
# include "net/net.h"
|
||||
#endif
|
||||
|
||||
#include "inode/inode.h"
|
||||
#include "fs/vnode.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
@@ -94,8 +94,7 @@ int ioctl(int fd, int req, ...)
|
||||
UINTPTR arg = 0;
|
||||
va_list ap;
|
||||
#if CONFIG_NFILE_DESCRIPTORS > 0
|
||||
FAR struct file *filep;
|
||||
FAR struct inode *inode;
|
||||
struct file *filep;
|
||||
int ret = OK;
|
||||
#endif
|
||||
|
||||
@@ -149,12 +148,11 @@ int ioctl(int fd, int req, ...)
|
||||
|
||||
/* Is a driver registered? Does it support the ioctl method? */
|
||||
|
||||
inode = filep->f_inode;
|
||||
if (inode && inode->u.i_ops && inode->u.i_ops->ioctl)
|
||||
if (filep->ops && filep->ops->ioctl)
|
||||
{
|
||||
/* Yes, then let it perform the ioctl */
|
||||
|
||||
ret = (int)inode->u.i_ops->ioctl(filep, req, arg);
|
||||
ret = (int) filep->ops->ioctl(filep, req, arg);
|
||||
if (ret < 0)
|
||||
{
|
||||
err = -ret;
|
||||
@@ -163,7 +161,7 @@ int ioctl(int fd, int req, ...)
|
||||
}
|
||||
else
|
||||
{
|
||||
err = EBADF;
|
||||
err = ENOSYS;
|
||||
ret = VFS_ERROR;
|
||||
goto errout;
|
||||
}
|
||||
@@ -173,5 +171,5 @@ int ioctl(int fd, int req, ...)
|
||||
|
||||
errout:
|
||||
set_errno(err);
|
||||
return ret;
|
||||
return VFS_ERROR;
|
||||
}
|
||||
|
||||
Executable → Regular
+22
-23
@@ -44,7 +44,7 @@
|
||||
#include "sched.h"
|
||||
#include "assert.h"
|
||||
#include "errno.h"
|
||||
#include "inode/inode.h"
|
||||
#include "fs/vnode.h"
|
||||
|
||||
#if CONFIG_NFILE_DESCRIPTORS > 0
|
||||
|
||||
@@ -70,36 +70,37 @@
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
off_t file_seek(FAR struct file *filep, off_t offset, int whence)
|
||||
off_t file_seek(struct file *filep, off_t offset, int whence)
|
||||
{
|
||||
FAR struct inode *inode;
|
||||
int ret;
|
||||
struct Vnode *vnode;
|
||||
int err = OK;
|
||||
off_t pos;
|
||||
|
||||
DEBUGASSERT(filep);
|
||||
inode = filep->f_inode;
|
||||
vnode = filep->f_vnode;
|
||||
|
||||
if (!inode)
|
||||
if (!vnode)
|
||||
{
|
||||
err = EBADF;
|
||||
err = -EBADF;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* Invoke the file seek method if available */
|
||||
|
||||
if (inode->u.i_ops && inode->u.i_ops->seek)
|
||||
if (filep->ops != NULL && filep->ops->seek != NULL)
|
||||
{
|
||||
ret = inode->u.i_ops->seek(filep, offset, whence);
|
||||
if (ret < 0)
|
||||
pos = filep->ops->seek(filep, offset, whence);
|
||||
if (pos < 0)
|
||||
{
|
||||
err = -ret;
|
||||
err = pos;
|
||||
goto errout;
|
||||
}
|
||||
else
|
||||
{
|
||||
filep->f_pos = pos;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* No... Just set the common file position value */
|
||||
|
||||
{ /* No... Just set the common file position value */
|
||||
switch (whence)
|
||||
{
|
||||
case SEEK_CUR:
|
||||
@@ -114,25 +115,24 @@ off_t file_seek(FAR struct file *filep, off_t offset, int whence)
|
||||
}
|
||||
else
|
||||
{
|
||||
err = EINVAL;
|
||||
err = -EINVAL;
|
||||
goto errout;
|
||||
}
|
||||
break;
|
||||
|
||||
case SEEK_END:
|
||||
err = ENOSYS;
|
||||
err = -ENOSYS;
|
||||
goto errout;
|
||||
|
||||
default:
|
||||
err = EINVAL;
|
||||
err = -EINVAL;
|
||||
goto errout;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (off_t)filep->f_pos;
|
||||
|
||||
errout:
|
||||
set_errno(err);
|
||||
set_errno(-err);
|
||||
return (off_t)VFS_ERROR;
|
||||
}
|
||||
|
||||
@@ -175,7 +175,7 @@ errout:
|
||||
|
||||
off_t lseek(int fd, off_t offset, int whence)
|
||||
{
|
||||
FAR struct file *filep;
|
||||
struct file *filep;
|
||||
|
||||
/* Get the file structure corresponding to the file descriptor. */
|
||||
|
||||
@@ -190,5 +190,4 @@ off_t lseek(int fd, off_t offset, int whence)
|
||||
|
||||
return file_seek(filep, offset, whence);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
Executable → Regular
+21
-21
@@ -44,7 +44,7 @@
|
||||
#include "sched.h"
|
||||
#include "assert.h"
|
||||
#include "errno.h"
|
||||
#include "inode/inode.h"
|
||||
#include "fs/vnode.h"
|
||||
|
||||
#if CONFIG_NFILE_DESCRIPTORS > 0
|
||||
|
||||
@@ -70,37 +70,38 @@
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
off64_t file_seek64(FAR struct file *filep, off64_t offset, int whence)
|
||||
off64_t file_seek64(struct file *filep, off64_t offset, int whence)
|
||||
{
|
||||
FAR struct inode *inode = NULL;
|
||||
off64_t ret;
|
||||
struct Vnode *vnode = NULL;
|
||||
int err = OK;
|
||||
off64_t pos;
|
||||
|
||||
DEBUGASSERT(filep);
|
||||
inode = filep->f_inode;
|
||||
vnode = filep->f_vnode;
|
||||
|
||||
if (inode == NULL)
|
||||
if (vnode == NULL)
|
||||
{
|
||||
err = EBADF;
|
||||
err = -EBADF;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* Invoke the file seek method if available */
|
||||
|
||||
if (INODE_IS_MOUNTPT(inode) && inode->u.i_mops && inode->u.i_mops->seek64)
|
||||
if (filep->ops != NULL && filep->ops->seek != NULL)
|
||||
{
|
||||
ret = inode->u.i_mops->seek64(filep, offset, whence);
|
||||
if (ret < 0)
|
||||
pos = filep->ops->seek(filep, offset, whence);
|
||||
if (pos < 0)
|
||||
{
|
||||
err = -(int)ret;
|
||||
err = pos;
|
||||
goto errout;
|
||||
}
|
||||
filep->f_pos = ret;
|
||||
else
|
||||
{
|
||||
filep->f_pos = pos;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* No... Just set the common file position value */
|
||||
|
||||
{ /* No... Just set the common file position value */
|
||||
switch (whence)
|
||||
{
|
||||
case SEEK_CUR:
|
||||
@@ -115,17 +116,17 @@ off64_t file_seek64(FAR struct file *filep, off64_t offset, int whence)
|
||||
}
|
||||
else
|
||||
{
|
||||
err = EINVAL;
|
||||
err = -EINVAL;
|
||||
goto errout;
|
||||
}
|
||||
break;
|
||||
|
||||
case SEEK_END:
|
||||
err = ENOSYS;
|
||||
err = -ENOSYS;
|
||||
goto errout;
|
||||
|
||||
default:
|
||||
err = EINVAL;
|
||||
err = -EINVAL;
|
||||
goto errout;
|
||||
}
|
||||
}
|
||||
@@ -133,7 +134,7 @@ off64_t file_seek64(FAR struct file *filep, off64_t offset, int whence)
|
||||
return filep->f_pos;
|
||||
|
||||
errout:
|
||||
set_errno(err);
|
||||
set_errno(-err);
|
||||
return (off64_t)VFS_ERROR;
|
||||
}
|
||||
|
||||
@@ -176,7 +177,7 @@ errout:
|
||||
|
||||
off64_t lseek64(int fd, off64_t offset, int whence)
|
||||
{
|
||||
FAR struct file *filep;
|
||||
struct file *filep;
|
||||
|
||||
/* Get the file structure corresponding to the file descriptor. */
|
||||
|
||||
@@ -191,5 +192,4 @@ off64_t lseek64(int fd, off64_t offset, int whence)
|
||||
|
||||
return file_seek64(filep, offset, whence);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
Executable → Regular
+69
-158
@@ -43,47 +43,24 @@
|
||||
#include "sys/stat.h"
|
||||
#include "fs/fs.h"
|
||||
#include "stdlib.h"
|
||||
#include "inode/inode.h"
|
||||
#include "fs/vnode.h"
|
||||
#include "string.h"
|
||||
#include "fs_other.h"
|
||||
#include "capability_api.h"
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#undef FS_HAVE_WRITABLE_MOUNTPOINT
|
||||
#if !defined(CONFIG_DISABLE_MOUNTPOINT) && defined(CONFIG_FS_WRITABLE) && \
|
||||
CONFIG_NFILE_STREAMS > 0
|
||||
# define FS_HAVE_WRITABLE_MOUNTPOINT 1
|
||||
#endif
|
||||
|
||||
#undef FS_HAVE_PSEUDOFS_OPERATIONS
|
||||
#if !defined(CONFIG_DISABLE_PSEUDOFS_OPERATIONS) && CONFIG_NFILE_STREAMS > 0
|
||||
# define FS_HAVE_PSEUDOFS_OPERATIONS 1
|
||||
#endif
|
||||
|
||||
#undef FS_HAVE_MKDIR
|
||||
#if defined(FS_HAVE_WRITABLE_MOUNTPOINT) || defined(FS_HAVE_PSEUDOFS_OPERATIONS)
|
||||
# define FS_HAVE_MKDIR 1
|
||||
#endif
|
||||
|
||||
#ifdef FS_HAVE_MKDIR
|
||||
#include "fs/path_cache.h"
|
||||
#include "fs/vfs_util.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
int do_mkdir(int dirfd, const char *pathname, mode_t mode)
|
||||
{
|
||||
FAR struct inode *inode;
|
||||
FAR struct inode *pathnode;
|
||||
const char *relpath = NULL;
|
||||
int errcode;
|
||||
int ret;
|
||||
char *fullpath = NULL;
|
||||
char *relativepath = NULL;
|
||||
struct inode_search_s desc;
|
||||
uint c_uid = OsCurrUserGet()->effUserID;
|
||||
uint c_gid = OsCurrUserGet()->effGid;
|
||||
struct Vnode *parentVnode = NULL;
|
||||
struct Vnode *vnode = NULL;
|
||||
int ret;
|
||||
char *fullpath = NULL;
|
||||
char *relativepath = NULL;
|
||||
char *dirname = NULL;
|
||||
|
||||
mode &= ~GetUmask();
|
||||
mode &= (S_IRWXU|S_IRWXG|S_IRWXO);
|
||||
@@ -92,7 +69,6 @@ int do_mkdir(int dirfd, const char *pathname, mode_t mode)
|
||||
ret = get_path_from_fd(dirfd, &relativepath);
|
||||
if (ret < 0)
|
||||
{
|
||||
errcode = -ret;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
@@ -104,145 +80,82 @@ int do_mkdir(int dirfd, const char *pathname, mode_t mode)
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
errcode = -ret;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* Find the inode that includes this path */
|
||||
SETUP_SEARCH(&desc, fullpath, false);
|
||||
ret = inode_find(&desc);
|
||||
inode = desc.node;
|
||||
relpath = desc.relpath;
|
||||
|
||||
if ((ret >= 0) && (inode != NULL))
|
||||
if (!strncmp(fullpath, "/dev", 4) || !strncmp(fullpath, "/proc", 5))
|
||||
{
|
||||
if (!strlen(relpath))
|
||||
// virtual root create virtual dir
|
||||
VnodeHold();
|
||||
ret = VnodeLookup(fullpath, &vnode, V_DUMMY|V_CREATE);
|
||||
if (ret != OK)
|
||||
{
|
||||
/* Find the inode that exactly match this path. */
|
||||
|
||||
errcode = EEXIST;
|
||||
goto errout_with_inode;
|
||||
goto errout_with_lock;
|
||||
}
|
||||
|
||||
/* If the path doesn't include the existed rootfs dirs,
|
||||
* then make a pseudo dir.
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
|
||||
if (((inode == g_root_inode) && !IsInRootfs(relpath)) || (!INODE_IS_MOUNTPT(g_root_inode)))
|
||||
{
|
||||
if (VfsPermissionCheck(desc.parent->i_uid, desc.parent->i_gid, desc.parent->i_mode, EXEC_OP | WRITE_OP))
|
||||
{
|
||||
errcode = EACCES;
|
||||
goto errout_with_inode;
|
||||
}
|
||||
/* Create a pseudo inode. */
|
||||
inode_semtake();
|
||||
|
||||
ret = inode_reserve(fullpath, &pathnode);
|
||||
if (ret < 0)
|
||||
{
|
||||
errcode = -ret;
|
||||
inode_semgive();
|
||||
goto errout_with_inode;
|
||||
}
|
||||
pathnode->i_mode = mode;
|
||||
pathnode->i_uid = c_uid;
|
||||
pathnode->i_gid = c_gid;
|
||||
inode_semgive();
|
||||
}
|
||||
else
|
||||
#endif
|
||||
|
||||
/* An inode was found that includes this path and possibly refers to a
|
||||
* mountpoint.
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_DISABLE_MOUNTPOINT
|
||||
/* Check if the inode is a valid mountpoint. */
|
||||
|
||||
if (!INODE_IS_MOUNTPT(inode) || !inode->u.i_mops)
|
||||
{
|
||||
/* The inode is not a mountpoint */
|
||||
|
||||
errcode = EEXIST;
|
||||
goto errout_with_inode;
|
||||
}
|
||||
|
||||
/* Perform the mkdir operation using the relative path
|
||||
* at the mountpoint.
|
||||
*/
|
||||
|
||||
else if (inode->u.i_mops->mkdir)
|
||||
{
|
||||
ret = inode->u.i_mops->mkdir(inode, relpath, mode);
|
||||
if (ret < 0)
|
||||
{
|
||||
errcode = -ret;
|
||||
goto errout_with_inode;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
errcode = ENOSYS;
|
||||
goto errout_with_inode;
|
||||
}
|
||||
|
||||
/* Release our reference on the inode */
|
||||
|
||||
inode_release(inode);
|
||||
#else
|
||||
/* But mountpoints are not supported in this configuration */
|
||||
|
||||
errcode = EEXIST;
|
||||
goto errout_with_inode;
|
||||
#endif
|
||||
vnode->mode = mode | S_IFDIR;
|
||||
vnode->type = VNODE_TYPE_DIR;
|
||||
VnodeDrop();
|
||||
goto out;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
|
||||
/* No inode exists that contains this path. Create a new inode in the
|
||||
* pseudo-filesystem at this location.
|
||||
*/
|
||||
dirname = strrchr(fullpath, '/') + 1;
|
||||
|
||||
VnodeHold();
|
||||
ret = VnodeLookup(fullpath, &parentVnode, 0);
|
||||
if (ret == OK)
|
||||
{
|
||||
ret = -EEXIST;
|
||||
goto errout_with_lock;
|
||||
}
|
||||
|
||||
if (parentVnode == NULL)
|
||||
{
|
||||
ret = -ENOENT;
|
||||
goto errout_with_lock;
|
||||
}
|
||||
parentVnode->useCount++;
|
||||
|
||||
if (VfsVnodePermissionCheck(parentVnode, WRITE_OP))
|
||||
{
|
||||
ret = -EACCES;
|
||||
goto errout_with_count;
|
||||
}
|
||||
|
||||
if ((parentVnode->vop != NULL) && (parentVnode->vop->Mkdir != NULL))
|
||||
{
|
||||
ret = parentVnode->vop->Mkdir(parentVnode, dirname, mode, &vnode);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Create an inode in the pseudo-filesystem at this path.
|
||||
* NOTE that the new inode will be created with a reference
|
||||
* count of zero.
|
||||
*/
|
||||
inode_semtake();
|
||||
ret = inode_reserve(fullpath, &inode);
|
||||
if (ret < 0)
|
||||
{
|
||||
errcode = -ret;
|
||||
free(fullpath);
|
||||
inode_semgive();
|
||||
goto errout;
|
||||
}
|
||||
inode->i_mode = mode;
|
||||
inode->i_uid = c_uid;
|
||||
inode->i_gid = c_gid;
|
||||
inode_semgive();
|
||||
ret = -ENOSYS;
|
||||
}
|
||||
#else
|
||||
else
|
||||
{
|
||||
errcode = ENXIO;
|
||||
free(fullpath);
|
||||
goto errout;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
goto errout_with_count;
|
||||
}
|
||||
|
||||
struct PathCache *dt = PathCacheAlloc(parentVnode, vnode, dirname, strlen(dirname));
|
||||
if (dt == NULL) {
|
||||
// alloc name cache failed is not a critical problem, let it go.
|
||||
PRINT_ERR("alloc path cache %s failed\n", dirname);
|
||||
}
|
||||
parentVnode->useCount--;
|
||||
VnodeDrop();
|
||||
out:
|
||||
/* Directory successfully created */
|
||||
|
||||
free(fullpath);
|
||||
|
||||
return OK;
|
||||
|
||||
errout_with_inode:
|
||||
inode_release(inode);
|
||||
free(fullpath);
|
||||
errout_with_count:
|
||||
parentVnode->useCount--;
|
||||
errout_with_lock:
|
||||
VnodeDrop();
|
||||
errout:
|
||||
set_errno(errcode);
|
||||
set_errno(-ret);
|
||||
if (fullpath)
|
||||
{
|
||||
free(fullpath);
|
||||
}
|
||||
return VFS_ERROR;
|
||||
}
|
||||
|
||||
@@ -273,5 +186,3 @@ int mkdirat(int dirfd, const char *pathname, mode_t mode)
|
||||
{
|
||||
return do_mkdir(dirfd, pathname, mode);
|
||||
}
|
||||
|
||||
#endif /* FS_HAVE_MKDIR */
|
||||
|
||||
+201
-161
@@ -50,10 +50,12 @@
|
||||
#endif
|
||||
#include "stdlib.h"
|
||||
#include "fs/fs.h"
|
||||
|
||||
#include "inode/inode.h"
|
||||
#include "fs/vnode.h"
|
||||
#include "driver/blockproxy.h"
|
||||
#include "fs_other.h"
|
||||
#include "fs/vfs_util.h"
|
||||
#include "fs/path_cache.h"
|
||||
#include "unistd.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
@@ -97,7 +99,7 @@ static int oflag_convert_mode(int oflags)
|
||||
|
||||
int get_path_from_fd(int fd, char **path)
|
||||
{
|
||||
FAR struct file *file = NULL;
|
||||
struct file *file = NULL;
|
||||
char *copypath = NULL;
|
||||
|
||||
if (fd == AT_FDCWD)
|
||||
@@ -111,7 +113,7 @@ int get_path_from_fd(int fd, char **path)
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
if ((file == NULL) || (file->f_inode == NULL) || (file->f_path == NULL))
|
||||
if ((file == NULL) || (file->f_vnode == NULL) || (file->f_path == NULL))
|
||||
{
|
||||
return -EBADF;
|
||||
}
|
||||
@@ -141,39 +143,190 @@ int get_path_from_fd(int fd, char **path)
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
int do_open(int dirfd, const char *path, int oflags, ...)
|
||||
static int do_creat(struct Vnode **node, char *fullpath, mode_t mode)
|
||||
{
|
||||
int ret;
|
||||
struct Vnode *parentNode = *node;
|
||||
char *name = strrchr(fullpath, '/') + 1;
|
||||
|
||||
if (parentNode->vop != NULL && parentNode->vop->Create != NULL)
|
||||
{
|
||||
ret = parentNode->vop->Create(parentNode, name, mode, node);
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = -ENOSYS;
|
||||
}
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct PathCache *dt = PathCacheAlloc(parentNode, *node, name, strlen(name));
|
||||
if (dt == NULL)
|
||||
{
|
||||
// alloc name cache failed is not a critical problem, let it go.
|
||||
PRINT_ERR("alloc path cache %s failed\n", name);
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
|
||||
int fp_open(char *fullpath, int oflags, mode_t mode)
|
||||
{
|
||||
FAR struct file *filep = NULL;
|
||||
FAR struct inode *inode = NULL;
|
||||
FAR const char *relpath = NULL;
|
||||
char *fullpath = NULL;
|
||||
char *relativepath = NULL;
|
||||
struct inode_search_s desc;
|
||||
#if defined(LOSCFG_FILE_MODE) || !defined(CONFIG_DISABLE_MOUNTPOINT)
|
||||
mode_t mode = DEFAULT_FILE_MODE;
|
||||
#endif
|
||||
int ret;
|
||||
int fd;
|
||||
int acc_mode;
|
||||
#ifdef LOSCFG_FILE_MODE
|
||||
/* If the file is opened for creation, then get the mode bits */
|
||||
int accmode;
|
||||
struct file *filep = NULL;
|
||||
struct Vnode *vnode = NULL;
|
||||
|
||||
if ((oflags & (O_WRONLY | O_CREAT)) != 0)
|
||||
VnodeHold();
|
||||
ret = VnodeLookup(fullpath, &vnode, 0);
|
||||
if (ret == OK)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, oflags);
|
||||
mode = va_arg(ap, int);
|
||||
va_end(ap);
|
||||
mode &= ~GetUmask();
|
||||
mode &= (S_IRWXU|S_IRWXG|S_IRWXO);
|
||||
/* if file exist */
|
||||
if (vnode->type == VNODE_TYPE_BCHR)
|
||||
{
|
||||
ret = -EINVAL;
|
||||
goto errout_without_count;
|
||||
}
|
||||
if (vnode->type == VNODE_TYPE_BLK) {
|
||||
fd = block_proxy(fullpath, oflags);
|
||||
VnodeDrop();
|
||||
if (fd < 0)
|
||||
{
|
||||
ret = fd;
|
||||
goto errout_without_count;
|
||||
}
|
||||
return fd;
|
||||
}
|
||||
if ((oflags & O_CREAT) && (oflags & O_EXCL))
|
||||
{
|
||||
ret = -EEXIST;
|
||||
VnodeDrop();
|
||||
goto errout_without_count;
|
||||
}
|
||||
if (vnode->type == VNODE_TYPE_DIR)
|
||||
{
|
||||
ret = -EISDIR;
|
||||
VnodeDrop();
|
||||
goto errout_without_count;
|
||||
}
|
||||
accmode = oflag_convert_mode(oflags);
|
||||
if (VfsVnodePermissionCheck(vnode, accmode))
|
||||
{
|
||||
ret = -EACCES;
|
||||
VnodeDrop();
|
||||
goto errout_without_count;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((ret != OK) && (oflags & O_CREAT) && vnode)
|
||||
{
|
||||
/* if file not exist, but parent dir of the file is exist */
|
||||
if (VfsVnodePermissionCheck(vnode, WRITE_OP))
|
||||
{
|
||||
ret = -EACCES;
|
||||
VnodeDrop();
|
||||
goto errout_without_count;
|
||||
}
|
||||
ret = do_creat(&vnode, fullpath, mode);
|
||||
if (ret != OK)
|
||||
{
|
||||
VnodeDrop();
|
||||
goto errout_without_count;
|
||||
}
|
||||
}
|
||||
|
||||
if (ret != OK)
|
||||
{
|
||||
/* found nothing */
|
||||
VnodeDrop();
|
||||
goto errout_without_count;
|
||||
}
|
||||
vnode->useCount++;
|
||||
VnodeDrop();
|
||||
|
||||
if (oflags & O_TRUNC)
|
||||
{
|
||||
if (vnode->useCount > 1)
|
||||
{
|
||||
ret = -EBUSY;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
if (vnode->vop->Truncate)
|
||||
{
|
||||
ret = vnode->vop->Truncate(vnode, 0);
|
||||
if (ret != OK)
|
||||
{
|
||||
goto errout;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = -ENOSYS;
|
||||
goto errout;
|
||||
}
|
||||
}
|
||||
|
||||
fd = files_allocate(vnode, oflags, 0, NULL, 3); /* 3: file start fd */
|
||||
if (fd < 0)
|
||||
{
|
||||
ret = -EMFILE;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* Get the file structure corresponding to the file descriptor. */
|
||||
ret = fs_getfilep(fd, &filep);
|
||||
if (ret < 0)
|
||||
{
|
||||
files_release(fd);
|
||||
ret = -get_errno();
|
||||
goto errout;
|
||||
}
|
||||
|
||||
filep->f_vnode = vnode;
|
||||
filep->ops = vnode->fop;
|
||||
filep->f_path = fullpath;
|
||||
|
||||
if (filep->ops && filep->ops->open)
|
||||
{
|
||||
ret = filep->ops->open(filep);
|
||||
}
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
files_release(fd);
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* we do not bother to handle the NULL scenario, if so, page-cache feature will not be used
|
||||
* when we do the file fault */
|
||||
add_mapping(filep, fullpath);
|
||||
|
||||
return fd;
|
||||
|
||||
errout:
|
||||
VnodeHold();
|
||||
vnode->useCount--;
|
||||
VnodeDrop();
|
||||
errout_without_count:
|
||||
set_errno(-ret);
|
||||
return VFS_ERROR;
|
||||
}
|
||||
|
||||
int do_open(int dirfd, const char *path, int oflags, mode_t mode)
|
||||
{
|
||||
int ret;
|
||||
int fd;
|
||||
char *fullpath = NULL;
|
||||
char *relativepath = NULL;
|
||||
|
||||
/* Get relative path by dirfd*/
|
||||
ret = get_path_from_fd(dirfd, &relativepath);
|
||||
if (ret < 0)
|
||||
{
|
||||
ret = -ret;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
@@ -182,132 +335,26 @@ int do_open(int dirfd, const char *path, int oflags, ...)
|
||||
{
|
||||
free(relativepath);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
ret = EACCES;
|
||||
free(fullpath);
|
||||
goto errout;
|
||||
}
|
||||
inode = desc.node;
|
||||
relpath = desc.relpath;
|
||||
|
||||
#if !defined(CONFIG_DISABLE_MOUNTPOINT)
|
||||
#ifdef LOSCFG_FS_VFS_BLOCK_DEVICE
|
||||
if (INODE_IS_BLOCK(inode))
|
||||
{
|
||||
fd = block_proxy(path, oflags);
|
||||
if (fd < 0)
|
||||
{
|
||||
ret = fd;
|
||||
goto errout_with_inode;
|
||||
}
|
||||
|
||||
inode_release(inode);
|
||||
free(fullpath);
|
||||
return fd;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Verify that the inode is valid and either a "normal" character driver or a
|
||||
* mountpoint. We specifically exclude block drivers and and "special"
|
||||
* inodes (semaphores, message queues, shared memory).
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_DISABLE_MOUNTPOINT
|
||||
if ((!INODE_IS_DRIVER(inode) && !INODE_IS_MOUNTPT(inode)) || !inode->u.i_ops)
|
||||
#else
|
||||
if (!INODE_IS_DRIVER(inode) || !inode->u.i_ops)
|
||||
#endif
|
||||
{
|
||||
ret = ENXIO;
|
||||
goto errout_with_inode;
|
||||
}
|
||||
|
||||
/* Associate the inode with a file structure */
|
||||
|
||||
fd = files_allocate(inode, oflags, 0, NULL, 3); /* 3: file start fd */
|
||||
fd = fp_open(fullpath, oflags, mode);
|
||||
if (fd < 0)
|
||||
{
|
||||
ret = EMFILE;
|
||||
goto errout_with_inode;
|
||||
ret = -get_errno();
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* Get the file structure corresponding to the file descriptor. */
|
||||
|
||||
ret = fs_getfilep(fd, &filep);
|
||||
if (ret < 0)
|
||||
{
|
||||
ret = EPERM;
|
||||
|
||||
/* The errno value has already been set */
|
||||
goto errout_with_fd;
|
||||
}
|
||||
|
||||
/* Perform the driver open operation. NOTE that the open method may be
|
||||
* called many times. The driver/mountpoint logic should handled this
|
||||
* because it may also be closed that many times.
|
||||
*/
|
||||
|
||||
ret = OK;
|
||||
filep->f_path = fullpath; /* The mem will free in close(fd); */
|
||||
filep->f_relpath = relpath;
|
||||
|
||||
acc_mode = oflag_convert_mode(oflags);
|
||||
if (inode->u.i_ops->open)
|
||||
{
|
||||
#ifndef CONFIG_DISABLE_MOUNTPOINT
|
||||
if (INODE_IS_MOUNTPT(inode))
|
||||
{
|
||||
if (VfsPermissionCheck(inode->i_uid, inode->i_gid, inode->i_mode, EXEC_OP))
|
||||
{
|
||||
ret = EACCES;
|
||||
goto errout_with_fd;
|
||||
}
|
||||
ret = inode->u.i_mops->open(filep, relpath, oflags, mode);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
if (VfsPermissionCheck(inode->i_uid, inode->i_gid, inode->i_mode, acc_mode))
|
||||
{
|
||||
ret = EACCES;
|
||||
goto errout_with_fd;
|
||||
}
|
||||
ret = inode->u.i_ops->open(filep);
|
||||
}
|
||||
}
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
ret = -ret;
|
||||
goto errout_with_fd;
|
||||
}
|
||||
|
||||
/* we do not bother to handle the NULL scenario, if so, page-cache feature will not be used
|
||||
* when we do the file fault */
|
||||
|
||||
add_mapping(filep, fullpath);
|
||||
|
||||
return fd;
|
||||
|
||||
errout_with_fd:
|
||||
files_release(fd);
|
||||
errout_with_inode:
|
||||
inode_release(inode);
|
||||
free(fullpath);
|
||||
errout:
|
||||
set_errno(ret);
|
||||
if (fullpath)
|
||||
{
|
||||
free(fullpath);
|
||||
}
|
||||
set_errno(-ret);
|
||||
return VFS_ERROR;
|
||||
}
|
||||
|
||||
@@ -320,43 +367,36 @@ errout:
|
||||
|
||||
int open(const char *path, int oflags, ...)
|
||||
{
|
||||
mode_t mode = 0666; /* File read-write properties. */
|
||||
mode_t mode = DEFAULT_FILE_MODE; /* File read-write properties. */
|
||||
#ifdef LOSCFG_FILE_MODE
|
||||
va_list ap;
|
||||
va_start(ap, oflags);
|
||||
mode = va_arg(ap, int);
|
||||
va_end(ap);
|
||||
|
||||
if ((oflags & (O_WRONLY | O_CREAT)) != 0)
|
||||
{
|
||||
mode &= ~GetUmask();
|
||||
mode &= (S_IRWXU|S_IRWXG|S_IRWXO);
|
||||
}
|
||||
#endif
|
||||
|
||||
return do_open(AT_FDCWD, path, oflags, mode);
|
||||
}
|
||||
|
||||
int open64 (const char *__path, int __oflag, ...)
|
||||
{
|
||||
mode_t mode = 0666; /* File read-write properties. */
|
||||
mode_t mode = DEFAULT_FILE_MODE; /* File read-write properties. */
|
||||
#ifdef LOSCFG_FILE_MODE
|
||||
va_list ap;
|
||||
va_start(ap, __oflag);
|
||||
mode = va_arg(ap, int);
|
||||
va_end(ap);
|
||||
if ((__oflag & (O_WRONLY | O_CREAT)) != 0)
|
||||
{
|
||||
mode &= ~GetUmask();
|
||||
mode &= (S_IRWXU|S_IRWXG|S_IRWXO);
|
||||
}
|
||||
#endif
|
||||
return open (__path, ((unsigned int)__oflag) | O_LARGEFILE, mode);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: openat
|
||||
*
|
||||
* Description: open by dirfd
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int openat(int dirfd, const char * path, int oflags, ...)
|
||||
{
|
||||
mode_t mode = 0666; /* File read-write properties. */
|
||||
#ifdef LOSCFG_FILE_MODE
|
||||
va_list ap;
|
||||
va_start(ap, oflags);
|
||||
mode = va_arg(ap, int);
|
||||
va_end(ap);
|
||||
#endif
|
||||
return do_open(dirfd, path, oflags, mode);
|
||||
}
|
||||
|
||||
Executable → Regular
+3
-6
@@ -45,7 +45,7 @@
|
||||
#include "errno.h"
|
||||
#include "debug.h"
|
||||
#include "fs/fs.h"
|
||||
#include "inode/inode.h"
|
||||
#include "fs/vnode.h"
|
||||
#include "stdlib.h"
|
||||
#include "stdio.h"
|
||||
#include "console.h"
|
||||
@@ -226,14 +226,11 @@ static int wait_sem_time(poll_wait_head wait, const struct timespec *time_ptr)
|
||||
|
||||
static int file_poll(struct file *filep, poll_table *wait)
|
||||
{
|
||||
struct inode *inode = NULL;
|
||||
int ret = -ENOSYS;
|
||||
|
||||
inode = filep->f_inode;
|
||||
|
||||
if (inode != NULL && inode->u.i_ops != NULL && inode->u.i_ops->poll != NULL)
|
||||
if (filep->ops != NULL && filep->ops->poll != NULL)
|
||||
{
|
||||
ret = inode->u.i_ops->poll(filep, wait);
|
||||
ret = filep->ops->poll(filep, wait);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
Executable → Regular
+7
-12
@@ -48,7 +48,7 @@
|
||||
#include "assert.h"
|
||||
#include "errno.h"
|
||||
#include "user_copy.h"
|
||||
#include "inode/inode.h"
|
||||
#include "fs/vnode.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
@@ -77,14 +77,10 @@
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
ssize_t file_read(FAR struct file *filep, FAR void *buf, size_t nbytes)
|
||||
ssize_t file_read(struct file *filep, void *buf, size_t nbytes)
|
||||
{
|
||||
FAR struct inode *inode = NULL;
|
||||
int ret = -EBADF;
|
||||
|
||||
DEBUGASSERT(filep);
|
||||
inode = filep->f_inode;
|
||||
|
||||
if (buf == NULL)
|
||||
{
|
||||
ret = -EFAULT;
|
||||
@@ -103,14 +99,14 @@ ssize_t file_read(FAR struct file *filep, FAR void *buf, size_t nbytes)
|
||||
* method?
|
||||
*/
|
||||
|
||||
else if (inode && inode->u.i_ops && inode->u.i_ops->read)
|
||||
else if (filep->ops && filep->ops->read)
|
||||
{
|
||||
/* Yes.. then let it perform the read. NOTE that for the case of the
|
||||
* mountpoint, we depend on the read methods being identical in
|
||||
* signature and position in the operations vtable.
|
||||
*/
|
||||
|
||||
ret = (int)inode->u.i_ops->read(filep, (char *)buf, (size_t)nbytes);
|
||||
ret = (int)filep->ops->read(filep, (char *)buf, (size_t)nbytes);
|
||||
}
|
||||
|
||||
/* If an error occurred, set errno and return -1 (ERROR) */
|
||||
@@ -143,12 +139,12 @@ ssize_t file_read(FAR struct file *filep, FAR void *buf, size_t nbytes)
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
ssize_t read(int fd, FAR void *buf, size_t nbytes)
|
||||
ssize_t read(int fd, void *buf, size_t nbytes)
|
||||
{
|
||||
/* Did we get a valid file descriptor? */
|
||||
|
||||
#if CONFIG_NFILE_DESCRIPTORS > 0
|
||||
FAR struct file *filep = NULL;
|
||||
struct file *filep = NULL;
|
||||
|
||||
if ((unsigned int)fd >= CONFIG_NFILE_DESCRIPTORS)
|
||||
#endif
|
||||
@@ -158,7 +154,7 @@ ssize_t read(int fd, FAR void *buf, size_t nbytes)
|
||||
*/
|
||||
|
||||
#if defined(LOSCFG_NET_LWIP_SACK)
|
||||
FAR void *bufbak = buf;
|
||||
void *bufbak = buf;
|
||||
ssize_t ret;
|
||||
if (LOS_IsUserAddress((VADDR_T)(uintptr_t)buf))
|
||||
{
|
||||
@@ -208,7 +204,6 @@ ssize_t read(int fd, FAR void *buf, size_t nbytes)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* The descriptor is in a valid range to file descriptor... do the
|
||||
* read. First, get the file structure.
|
||||
*/
|
||||
|
||||
Executable → Regular
+155
-213
@@ -40,253 +40,197 @@
|
||||
#include "vfs_config.h"
|
||||
|
||||
#include "stdio.h"
|
||||
#include "unistd.h"
|
||||
#include "errno.h"
|
||||
#include "fs/fs.h"
|
||||
#include "stdlib.h"
|
||||
#include "inode/inode.h"
|
||||
#include "fs/vnode.h"
|
||||
#include "fs_other.h"
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#undef FS_HAVE_WRITABLE_MOUNTPOINT
|
||||
#if !defined(CONFIG_DISABLE_MOUNTPOINT) && defined(CONFIG_FS_WRITABLE) && \
|
||||
CONFIG_NFILE_STREAMS > 0
|
||||
# define FS_HAVE_WRITABLE_MOUNTPOINT 1
|
||||
#endif
|
||||
|
||||
#undef FS_HAVE_PSEUDOFS_OPERATIONS
|
||||
#if !defined(CONFIG_DISABLE_PSEUDOFS_OPERATIONS) && CONFIG_NFILE_STREAMS > 0
|
||||
# define FS_HAVE_PSEUDOFS_OPERATIONS 1
|
||||
#endif
|
||||
|
||||
#undef FS_HAVE_RENAME
|
||||
#if defined(FS_HAVE_WRITABLE_MOUNTPOINT) || defined(FS_HAVE_PSEUDOFS_OPERATIONS)
|
||||
# define FS_HAVE_RENAME 1
|
||||
#endif
|
||||
|
||||
#ifdef FS_HAVE_RENAME
|
||||
|
||||
#include "limits.h"
|
||||
#include "fs/fs_operation.h"
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
int do_rename(int oldfd, FAR const char *oldpath, int newfd, FAR const char *newpath)
|
||||
static int check_rename_target(struct Vnode *old_vnode, struct Vnode *old_parent_vnode,
|
||||
struct Vnode *new_vnode, struct Vnode *new_parent_vnode)
|
||||
{
|
||||
FAR struct inode *oldinode;
|
||||
FAR struct inode *newinode;
|
||||
const char *oldrelpath = NULL;
|
||||
char *fulloldpath = NULL;
|
||||
char *fulloldpath_bak = NULL;
|
||||
char *fullnewpath = NULL;
|
||||
char *fullnewpath_bak = NULL;
|
||||
#ifndef CONFIG_DISABLE_MOUNTPOINT
|
||||
const char *newrelpath = NULL;
|
||||
#endif
|
||||
int errcode = ENOERR;
|
||||
int ret;
|
||||
struct inode_search_s old_desc, new_desc;
|
||||
|
||||
/* Ignore paths that are interpreted as the root directory which has no name
|
||||
* and cannot be moved
|
||||
*/
|
||||
|
||||
if (!oldpath || *oldpath == '\0' ||
|
||||
!newpath || *newpath == '\0')
|
||||
if (old_vnode == NULL || old_parent_vnode == NULL ||
|
||||
new_parent_vnode == NULL || new_parent_vnode->type != VNODE_TYPE_DIR)
|
||||
{
|
||||
errcode = EINVAL;
|
||||
return -ENOENT;
|
||||
}
|
||||
if (old_vnode->type != VNODE_TYPE_DIR && old_vnode->type != VNODE_TYPE_REG)
|
||||
{
|
||||
return -EACCES;
|
||||
}
|
||||
if (new_vnode != NULL && new_vnode->type != old_vnode->type)
|
||||
{
|
||||
if (new_vnode->type == VNODE_TYPE_DIR)
|
||||
{
|
||||
return -EISDIR;
|
||||
}
|
||||
return -ENOTDIR;
|
||||
}
|
||||
if (new_vnode != NULL && new_vnode->useCount != 0)
|
||||
{
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
if (VfsVnodePermissionCheck(old_parent_vnode, WRITE_OP)
|
||||
|| VfsVnodePermissionCheck(new_parent_vnode, WRITE_OP))
|
||||
{
|
||||
return -EACCES;
|
||||
}
|
||||
|
||||
if (old_parent_vnode->originMount != new_parent_vnode->originMount)
|
||||
{
|
||||
return -EXDEV;
|
||||
}
|
||||
if ((old_vnode->flag & VNODE_FLAG_MOUNT_NEW)
|
||||
|| (old_vnode->flag & VNODE_FLAG_MOUNT_ORIGIN))
|
||||
{
|
||||
return -EBUSY;
|
||||
}
|
||||
if (new_vnode != NULL && ((new_vnode->flag & VNODE_FLAG_MOUNT_NEW)
|
||||
|| (new_vnode->flag & VNODE_FLAG_MOUNT_ORIGIN)))
|
||||
{
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int check_path_invalid(const char *fulloldpath, const char *fullnewpath)
|
||||
{
|
||||
char cwd[PATH_MAX];
|
||||
char *pret = getcwd(cwd, PATH_MAX);
|
||||
ssize_t len = strlen(fulloldpath);
|
||||
if (pret != NULL)
|
||||
{
|
||||
if (!strcmp(fulloldpath, cwd))
|
||||
{
|
||||
return -EBUSY;
|
||||
}
|
||||
}
|
||||
|
||||
if (strncmp(fulloldpath, fullnewpath, len))
|
||||
{
|
||||
return OK;
|
||||
}
|
||||
|
||||
if (fullnewpath[len] != '/')
|
||||
{
|
||||
return OK;
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
int do_rename(int oldfd, const char *oldpath, int newfd, const char *newpath)
|
||||
{
|
||||
struct Vnode *old_parent_vnode = NULL;
|
||||
struct Vnode *new_parent_vnode = NULL;
|
||||
struct Vnode *old_vnode = NULL;
|
||||
struct Vnode *new_vnode = NULL;
|
||||
char *fulloldpath = NULL;
|
||||
char *fullnewpath = NULL;
|
||||
char *oldname = NULL;
|
||||
char *newname = NULL;
|
||||
int ret;
|
||||
if (!oldpath || *oldpath == '\0' || !newpath || *newpath == '\0')
|
||||
{
|
||||
ret = -EINVAL;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
ret = vfs_normalize_pathat(oldfd, oldpath, &fulloldpath);
|
||||
if (ret < 0)
|
||||
{
|
||||
errcode = -ret;
|
||||
goto errout;
|
||||
}
|
||||
fulloldpath_bak = fulloldpath;
|
||||
{
|
||||
goto errout;
|
||||
}
|
||||
|
||||
ret = vfs_normalize_pathat(newfd, newpath, &fullnewpath);
|
||||
if (ret < 0)
|
||||
{
|
||||
errcode = -ret;
|
||||
goto errout_with_path;
|
||||
}
|
||||
fullnewpath_bak = fullnewpath;
|
||||
{
|
||||
goto errout_with_oldpath;
|
||||
}
|
||||
oldname = strrchr(fulloldpath, '/') + 1;
|
||||
newname = strrchr(fullnewpath, '/') + 1;
|
||||
ret = check_path_invalid(fulloldpath, fullnewpath);
|
||||
if (ret != OK)
|
||||
{
|
||||
goto errout_with_newpath;
|
||||
}
|
||||
|
||||
/* Get an inode that includes the oldpath */
|
||||
SETUP_SEARCH(&old_desc, fulloldpath, false);
|
||||
ret = inode_find(&old_desc);
|
||||
VnodeHold();
|
||||
ret = VnodeLookup(fulloldpath, &old_vnode, 0);
|
||||
if (ret < 0)
|
||||
{
|
||||
errcode = EACCES;
|
||||
free(fullnewpath_bak);
|
||||
goto errout_with_path;
|
||||
goto errout_with_vnode;
|
||||
}
|
||||
oldinode = old_desc.node;
|
||||
oldrelpath = old_desc.relpath;
|
||||
|
||||
#ifndef CONFIG_DISABLE_MOUNTPOINT
|
||||
/* Verify that the old inode is a valid mountpoint. */
|
||||
|
||||
if (INODE_IS_MOUNTPT(oldinode) && oldinode->u.i_mops)
|
||||
old_parent_vnode = old_vnode->parent;
|
||||
ret = VnodeLookup(fullnewpath, &new_vnode, 0);
|
||||
if (ret == OK)
|
||||
{
|
||||
/* Get an inode for the new relpath -- it should like on the same
|
||||
* mountpoint
|
||||
*/
|
||||
SETUP_SEARCH(&new_desc, fullnewpath, false);
|
||||
ret = inode_find(&new_desc);
|
||||
if (ret < 0)
|
||||
{
|
||||
errcode = EACCES;
|
||||
goto errout_with_oldinode;
|
||||
}
|
||||
newinode = new_desc.node;
|
||||
newrelpath = new_desc.relpath;
|
||||
|
||||
/* Verify that the two paths lie on the same mountpoint inode */
|
||||
|
||||
if (oldinode != newinode)
|
||||
{
|
||||
errcode = EXDEV;
|
||||
goto errout_with_newinode;
|
||||
}
|
||||
|
||||
/* Perform the rename operation using the relative paths
|
||||
* at the common mountpoint.
|
||||
*/
|
||||
|
||||
if (oldinode->u.i_mops->rename)
|
||||
{
|
||||
ret = oldinode->u.i_mops->rename(oldinode, oldrelpath, newrelpath);
|
||||
if (ret < 0)
|
||||
{
|
||||
errcode = -ret;
|
||||
goto errout_with_newinode;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
errcode = ENOSYS;
|
||||
goto errout_with_newinode;
|
||||
}
|
||||
|
||||
/* Successfully renamed */
|
||||
|
||||
inode_release(newinode);
|
||||
new_parent_vnode = new_vnode->parent;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
|
||||
{
|
||||
/* Create a new, empty inode at the destination location */
|
||||
if (VfsPermissionCheck(old_desc.parent->i_uid, old_desc.parent->i_gid,
|
||||
old_desc.parent->i_mode, EXEC_OP | WRITE_OP))
|
||||
{
|
||||
ret = EACCES;
|
||||
goto errout_with_oldinode;
|
||||
}
|
||||
SETUP_SEARCH(&new_desc, fullnewpath, false);
|
||||
ret = inode_find(&new_desc);
|
||||
if (ret < 0)
|
||||
{
|
||||
errcode = EACCES;
|
||||
goto errout_with_oldinode;
|
||||
}
|
||||
newinode = new_desc.node;
|
||||
newrelpath = new_desc.relpath;
|
||||
|
||||
if (VfsPermissionCheck(new_desc.parent->i_uid, new_desc.parent->i_gid,
|
||||
new_desc.parent->i_mode, EXEC_OP | WRITE_OP))
|
||||
{
|
||||
ret = EACCES;
|
||||
goto errout_with_oldinode;
|
||||
}
|
||||
inode_semtake();
|
||||
ret = inode_reserve(fullnewpath, &newinode);
|
||||
if (ret < 0)
|
||||
{
|
||||
/* It is an error if a node at newpath already exists in the tree
|
||||
* OR if we fail to allocate memory for the new inode (and possibly
|
||||
* any new intermediate path segments).
|
||||
*/
|
||||
|
||||
inode_semgive();
|
||||
errcode = EEXIST;
|
||||
goto errout_with_oldinode;
|
||||
}
|
||||
|
||||
/* Copy the inode state from the old inode to the newly allocated inode */
|
||||
|
||||
newinode->i_child = oldinode->i_child; /* Link to lower level inode */
|
||||
newinode->i_flags = oldinode->i_flags; /* Flags for inode */
|
||||
newinode->u.i_ops = oldinode->u.i_ops; /* Inode operations */
|
||||
#ifdef LOSCFG_FILE_MODE
|
||||
newinode->i_mode = oldinode->i_mode; /* Access mode flags */
|
||||
#endif
|
||||
newinode->i_private = oldinode->i_private; /* Per inode driver private data */
|
||||
|
||||
/* We now have two copies of the inode. One with a reference count of
|
||||
* zero (the new one), and one that may have multiple references
|
||||
* including one by this logic (the old one)
|
||||
*
|
||||
* Remove the old inode. Because we hold a reference count on the
|
||||
* inode, it will not be deleted now. It will be deleted when all of
|
||||
* the references to to the inode have been released (perhaps when
|
||||
* inode_release() is called below). inode_remove() should return
|
||||
* -EBUSY to indicate that the inode was not deleted now.
|
||||
*/
|
||||
|
||||
ret = inode_remove(fulloldpath);
|
||||
if (ret < 0 && ret != -EBUSY)
|
||||
{
|
||||
/* Remove the new node we just recreated */
|
||||
|
||||
(void)inode_remove(fullnewpath);
|
||||
inode_semgive();
|
||||
|
||||
errcode = -ret;
|
||||
goto errout_with_oldinode;
|
||||
}
|
||||
|
||||
/* Remove all of the children from the unlinked inode */
|
||||
|
||||
oldinode->i_child = NULL;
|
||||
inode_semgive();
|
||||
new_parent_vnode = new_vnode;
|
||||
new_vnode = NULL;
|
||||
}
|
||||
#else
|
||||
ret = check_rename_target(old_vnode, old_parent_vnode, new_vnode, new_parent_vnode);
|
||||
if (ret != OK)
|
||||
{
|
||||
errcode = ENXIO;
|
||||
goto errout_with_oldinode;
|
||||
goto errout_with_vnode;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* rename file page cache mapping if necessary */
|
||||
if (old_vnode == new_vnode)
|
||||
{
|
||||
VnodeDrop();
|
||||
free(fulloldpath);
|
||||
free(fullnewpath);
|
||||
return OK;
|
||||
}
|
||||
if (!old_vnode->vop || !old_vnode->vop->Rename)
|
||||
{
|
||||
ret = -ENOSYS;
|
||||
goto errout_with_vnode;
|
||||
}
|
||||
ret = old_vnode->vop->Rename(old_vnode, new_parent_vnode, oldname, newname);
|
||||
if (ret < 0)
|
||||
{
|
||||
goto errout_with_vnode;
|
||||
}
|
||||
VnodeFree(new_vnode);
|
||||
VnodePathCacheFree(old_vnode);
|
||||
PathCacheAlloc(new_parent_vnode, old_vnode, newname, strlen(newname));
|
||||
VnodeDrop();
|
||||
ret = update_file_path(fulloldpath, fullnewpath);
|
||||
if (ret != OK)
|
||||
{
|
||||
PRINT_ERR("rename change file path failed, something bad might happped.\n");
|
||||
}
|
||||
/* Successfully renamed */
|
||||
|
||||
rename_mapping(fulloldpath, fullnewpath);
|
||||
|
||||
/* Successfully renamed */
|
||||
|
||||
inode_release(oldinode);
|
||||
free(fulloldpath_bak);
|
||||
free(fullnewpath_bak);
|
||||
free(fulloldpath);
|
||||
free(fullnewpath);
|
||||
|
||||
return OK;
|
||||
|
||||
#ifndef CONFIG_DISABLE_MOUNTPOINT
|
||||
errout_with_newinode:
|
||||
inode_release(newinode);
|
||||
#endif
|
||||
errout_with_oldinode:
|
||||
inode_release(oldinode);
|
||||
free(fullnewpath_bak);
|
||||
errout_with_path:
|
||||
free(fulloldpath_bak);
|
||||
errout_with_vnode:
|
||||
VnodeDrop();
|
||||
errout_with_newpath:
|
||||
free(fullnewpath);
|
||||
errout_with_oldpath:
|
||||
free(fulloldpath);
|
||||
errout:
|
||||
set_errno(errcode);
|
||||
set_errno(-ret);
|
||||
return VFS_ERROR;
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
* Name: rename
|
||||
*
|
||||
@@ -294,7 +238,7 @@ errout:
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int rename(FAR const char *oldpath, FAR const char *newpath)
|
||||
int rename(const char *oldpath, const char *newpath)
|
||||
{
|
||||
return do_rename(AT_FDCWD, oldpath, AT_FDCWD, newpath);
|
||||
}
|
||||
@@ -306,9 +250,7 @@ int rename(FAR const char *oldpath, FAR const char *newpath)
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int renameat(int oldfd, FAR const char *oldpath, int newdfd, FAR const char *newpath)
|
||||
int renameat(int oldfd, const char *oldpath, int newdfd, const char *newpath)
|
||||
{
|
||||
return do_rename(oldfd, oldpath, newdfd, newpath);
|
||||
}
|
||||
|
||||
#endif /* FS_HAVE_RENAME */
|
||||
|
||||
Executable → Regular
+93
-126
@@ -43,32 +43,50 @@
|
||||
#include "errno.h"
|
||||
#include "fs/fs.h"
|
||||
#include "stdlib.h"
|
||||
#include "inode/inode.h"
|
||||
#include "fs/vnode.h"
|
||||
#include "sys/stat.h"
|
||||
#include "string.h"
|
||||
#include "fs_other.h"
|
||||
#include "limits.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
static int check_target(struct Vnode *vnode, char *name) {
|
||||
if (vnode == NULL)
|
||||
{
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
#undef FS_HAVE_WRITABLE_MOUNTPOINT
|
||||
#if !defined(CONFIG_DISABLE_MOUNTPOINT) && defined(CONFIG_FS_WRITABLE) && \
|
||||
CONFIG_NFILE_STREAMS > 0
|
||||
# define FS_HAVE_WRITABLE_MOUNTPOINT 1
|
||||
#endif
|
||||
if (vnode->type != VNODE_TYPE_DIR)
|
||||
{
|
||||
return -ENOTDIR;
|
||||
}
|
||||
|
||||
#undef FS_HAVE_PSEUDOFS_OPERATIONS
|
||||
#if !defined(CONFIG_DISABLE_PSEUDOFS_OPERATIONS) && CONFIG_NFILE_STREAMS > 0
|
||||
# define FS_HAVE_PSEUDOFS_OPERATIONS 1
|
||||
#endif
|
||||
if (vnode->useCount > 0)
|
||||
{
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
#undef FS_HAVE_RMDIR
|
||||
#if defined(FS_HAVE_WRITABLE_MOUNTPOINT) || defined(FS_HAVE_PSEUDOFS_OPERATIONS)
|
||||
# define FS_HAVE_RMDIR 1
|
||||
#endif
|
||||
|
||||
#ifdef FS_HAVE_RMDIR
|
||||
if ((vnode->flag & VNODE_FLAG_MOUNT_NEW)
|
||||
|| (vnode->flag & VNODE_FLAG_MOUNT_ORIGIN))
|
||||
{
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
char cwd[PATH_MAX];
|
||||
char *pret = getcwd(cwd, PATH_MAX);
|
||||
if (pret != NULL)
|
||||
{
|
||||
struct Vnode *cwdnode = NULL;
|
||||
int ret = VnodeLookup(cwd, &cwdnode, 0);
|
||||
if (ret == OK && (cwdnode == vnode))
|
||||
{
|
||||
return -EBUSY;
|
||||
}
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
@@ -80,143 +98,94 @@
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int do_rmdir(int dirfd, FAR const char *pathname)
|
||||
int do_rmdir(int dirfd, const char *pathname)
|
||||
{
|
||||
FAR struct inode *inode;
|
||||
const char *relpath = NULL;
|
||||
int errcode;
|
||||
struct Vnode *vnode = NULL;
|
||||
char *fullpath = NULL;
|
||||
char *relativepath = NULL;
|
||||
char *name = NULL;
|
||||
int ret;
|
||||
struct inode_search_s desc;
|
||||
|
||||
/* Get relative path by dirfd*/
|
||||
ret = get_path_from_fd(dirfd, &relativepath);
|
||||
if (ret < 0)
|
||||
{
|
||||
errcode = ret;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
ret = vfs_normalize_path((const char *)relativepath, pathname, &fullpath);
|
||||
if (relativepath)
|
||||
{
|
||||
ret = vfs_normalize_path((const char *)relativepath, pathname, &fullpath);
|
||||
free(relativepath);
|
||||
}
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
errcode = -ret;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* Get an inode for this file. inode_find() automatically increments the
|
||||
* reference count on the inode if one is found.
|
||||
*/
|
||||
SETUP_SEARCH(&desc, fullpath, false);
|
||||
ret = inode_find(&desc);
|
||||
if (ret < 0)
|
||||
{
|
||||
free(fullpath);
|
||||
errcode = EACCES;
|
||||
goto errout;
|
||||
}
|
||||
inode = desc.node;
|
||||
relpath = desc.relpath;
|
||||
|
||||
#ifndef CONFIG_DISABLE_MOUNTPOINT
|
||||
/* Check if the inode is a valid mountpoint. */
|
||||
|
||||
if (INODE_IS_MOUNTPT(inode) && inode->u.i_mops)
|
||||
{
|
||||
/* Perform the rmdir operation using the relative path
|
||||
* from the mountpoint.
|
||||
*/
|
||||
|
||||
if (inode->u.i_mops->rmdir)
|
||||
if (ret < 0)
|
||||
{
|
||||
if (!strlen(relpath))
|
||||
{
|
||||
errcode = EPERM;
|
||||
goto errout_with_inode;
|
||||
}
|
||||
goto errout;
|
||||
}
|
||||
|
||||
ret = inode->u.i_mops->rmdir(inode, relpath);
|
||||
if (ret < 0)
|
||||
{
|
||||
errcode = -ret;
|
||||
goto errout_with_inode;
|
||||
}
|
||||
name = strrchr(fullpath, '/');
|
||||
VnodeHold();
|
||||
ret = VnodeLookup(fullpath, &vnode, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
name = strrchr(pathname, '/');
|
||||
VnodeHold();
|
||||
if (name == NULL)
|
||||
{
|
||||
name = (char *)pathname;
|
||||
}
|
||||
else
|
||||
{
|
||||
errcode = ENOSYS;
|
||||
goto errout_with_inode;
|
||||
name++;
|
||||
}
|
||||
ret = VnodeLookup(pathname, &vnode, 0);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
|
||||
/* If this is a "dangling" pseudo-directory node (i.e., it has no
|
||||
* operations) then rmdir should remove the node.
|
||||
*/
|
||||
|
||||
if (!inode->u.i_ops)
|
||||
if (ret != OK)
|
||||
{
|
||||
/* If the directory inode has children, however, then it cannot be
|
||||
* removed.
|
||||
*/
|
||||
|
||||
if (inode->i_child)
|
||||
{
|
||||
errcode = ENOTEMPTY;
|
||||
goto errout_with_inode;
|
||||
}
|
||||
|
||||
/* Remove the inode. NOTE: Because we hold a reference count on the
|
||||
* inode, it will not be deleted now. But probably when inode_release()
|
||||
* is called below. inode_remove should return -EBUSY to indicate that
|
||||
* the inode was not deleted now.
|
||||
*/
|
||||
if (VfsPermissionCheck(desc.parent->i_uid, desc.parent->i_gid, desc.parent->i_mode, EXEC_OP | WRITE_OP))
|
||||
{
|
||||
errcode = EACCES;
|
||||
goto errout_with_inode;
|
||||
}
|
||||
inode_semtake();
|
||||
ret = inode_remove(fullpath);
|
||||
inode_semgive();
|
||||
|
||||
if (ret < 0 && ret != -EBUSY)
|
||||
{
|
||||
errcode = -ret;
|
||||
goto errout_with_inode;
|
||||
}
|
||||
goto errout_with_lock;
|
||||
}
|
||||
else
|
||||
|
||||
ret = check_target(vnode, name);
|
||||
if (ret != OK) {
|
||||
PRINT_ERR("rmdir failed err = %d\n", ret);
|
||||
goto errout_with_lock;
|
||||
}
|
||||
|
||||
if (VfsVnodePermissionCheck(vnode->parent, WRITE_OP)) {
|
||||
ret = -EACCES;
|
||||
goto errout_with_lock;
|
||||
}
|
||||
|
||||
if (vnode && vnode->vop && vnode->vop->Rmdir) {
|
||||
ret = vnode->vop->Rmdir(vnode->parent, vnode, name);
|
||||
} else {
|
||||
ret = -ENOSYS;
|
||||
}
|
||||
if (ret < 0) {
|
||||
goto errout_with_lock;
|
||||
}
|
||||
VnodeFree(vnode);
|
||||
VnodeDrop();
|
||||
|
||||
/* Successfully unlinked */
|
||||
if (fullpath)
|
||||
{
|
||||
errcode = ENOTDIR;
|
||||
goto errout_with_inode;
|
||||
free(fullpath);
|
||||
}
|
||||
#else
|
||||
{
|
||||
errcode = ENXIO;
|
||||
goto errout_with_inode;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Successfully removed the directory */
|
||||
|
||||
inode_release(inode);
|
||||
free(fullpath);
|
||||
return OK;
|
||||
|
||||
errout_with_inode:
|
||||
inode_release(inode);
|
||||
free(fullpath);
|
||||
errout_with_lock:
|
||||
VnodeDrop();
|
||||
|
||||
errout:
|
||||
set_errno(errcode);
|
||||
if (fullpath)
|
||||
{
|
||||
free(fullpath);
|
||||
}
|
||||
|
||||
set_errno(-ret);
|
||||
return VFS_ERROR;
|
||||
}
|
||||
|
||||
@@ -227,9 +196,7 @@ errout:
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int rmdir(FAR const char *pathname)
|
||||
int rmdir(const char *pathname)
|
||||
{
|
||||
return do_rmdir(AT_FDCWD, pathname);
|
||||
}
|
||||
|
||||
#endif /* FS_HAVE_RMDIR */
|
||||
|
||||
Executable → Regular
-1
@@ -54,7 +54,6 @@
|
||||
#include "los_signal.h"
|
||||
#include "los_syscall.h"
|
||||
|
||||
#include "inode/inode.h"
|
||||
#ifndef CONFIG_DISABLE_POLL
|
||||
|
||||
|
||||
|
||||
Executable → Regular
+23
-170
@@ -43,99 +43,8 @@
|
||||
#include "sys/stat.h"
|
||||
#include "string.h"
|
||||
#include "stdlib.h"
|
||||
#include "inode/inode.h"
|
||||
#include "fs/vnode.h"
|
||||
#include "fs_other.h"
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: statpseudo
|
||||
****************************************************************************/
|
||||
|
||||
static inline int statpseudo(FAR struct inode *inode, FAR struct stat *buf)
|
||||
{
|
||||
/* Most of the stat entries just do not apply */
|
||||
|
||||
(void)memset_s(buf, sizeof(struct stat), 0, sizeof(struct stat));
|
||||
|
||||
buf->st_mode |= inode->i_mode;
|
||||
buf->st_uid = inode->i_uid;
|
||||
buf->st_gid = inode->i_gid;
|
||||
if (INODE_IS_SPECIAL(inode))
|
||||
{
|
||||
#if defined(CONFIG_FS_NAMED_SEMAPHORES)
|
||||
if (INODE_IS_NAMEDSEM(inode))
|
||||
{
|
||||
buf->st_mode = S_IFSEM;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
#if !defined(CONFIG_DISABLE_MQUEUE)
|
||||
if (INODE_IS_MQUEUE(inode))
|
||||
{
|
||||
buf->st_mode = S_IFMQ;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
#if defined(CONFIG_FS_SHM)
|
||||
if (INODE_IS_SHM(inode))
|
||||
{
|
||||
buf->st_mode = S_IFSHM;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
}
|
||||
}
|
||||
else if (inode->u.i_ops)
|
||||
{
|
||||
/* Determine the type of the inode */
|
||||
|
||||
if (INODE_IS_MOUNTPT(inode))
|
||||
{
|
||||
buf->st_mode |= S_IFDIR;
|
||||
}
|
||||
else if (INODE_IS_BLOCK(inode))
|
||||
{
|
||||
/* What is if also has child inodes? */
|
||||
|
||||
buf->st_mode |= S_IFBLK;
|
||||
}
|
||||
else /* if (INODE_IS_DRIVER(inode)) */
|
||||
{
|
||||
/* What is it if it also has child inodes? */
|
||||
|
||||
buf->st_mode |= S_IFCHR;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If it has no operations, then it must just be a intermediate
|
||||
* node in the inode tree. It is something like a directory.
|
||||
* We'll say that all pseudo-directories are read-able but not
|
||||
* write-able.
|
||||
*/
|
||||
|
||||
buf->st_mode |= S_IFDIR | inode->i_mode;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: statroot
|
||||
****************************************************************************/
|
||||
|
||||
static inline int statroot(FAR struct stat *buf)
|
||||
{
|
||||
/* There is no inode associated with the fake root directory */
|
||||
|
||||
(void)memset_s(buf, sizeof(struct stat), 0, sizeof(struct stat));
|
||||
buf->st_mode = S_IFDIR | S_IROTH | S_IRGRP | S_IRUSR;
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Global Functions
|
||||
****************************************************************************/
|
||||
@@ -156,120 +65,64 @@ static inline int statroot(FAR struct stat *buf)
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int stat(FAR const char *path, FAR struct stat *buf)
|
||||
int stat(const char *path, struct stat *buf)
|
||||
{
|
||||
FAR struct inode *inode;
|
||||
const char *relpath = NULL;
|
||||
int ret = OK;
|
||||
char *fullpath = NULL;
|
||||
struct inode_search_s desc;
|
||||
struct Vnode *vp = NULL;
|
||||
int ret;
|
||||
|
||||
/* Sanity checks */
|
||||
|
||||
if (!path || !buf)
|
||||
{
|
||||
ret = EFAULT;
|
||||
ret = -EFAULT;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
if (!path[0])
|
||||
{
|
||||
ret = ENOENT;
|
||||
ret = -ENOENT;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
ret = vfs_normalize_path((const char *)NULL, path, &fullpath);
|
||||
/* Get an vnode for this file */
|
||||
VnodeHold();
|
||||
ret = VnodeLookup(path, &vp, 0);
|
||||
if (ret < 0)
|
||||
{
|
||||
ret = -ret;
|
||||
VnodeDrop();
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* Check for the fake root directory (which has no inode) */
|
||||
|
||||
if (strcmp(fullpath, "/") == 0)
|
||||
{
|
||||
free(fullpath);
|
||||
return statroot(buf);
|
||||
}
|
||||
|
||||
/* Get an inode for this file */
|
||||
SETUP_SEARCH(&desc, fullpath, false);
|
||||
ret = inode_find(&desc);
|
||||
if (ret < 0)
|
||||
{
|
||||
ret = EACCES;
|
||||
goto errout_with_path;
|
||||
}
|
||||
inode = desc.node;
|
||||
relpath = desc.relpath;
|
||||
|
||||
/* The way we handle the stat depends on the type of inode that we
|
||||
/* The way we handle the stat depends on the type of vnode that we
|
||||
* are dealing with.
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_DISABLE_MOUNTPOINT
|
||||
if (INODE_IS_MOUNTPT(inode))
|
||||
if (vp->vop != NULL && vp->vop->Getattr != NULL)
|
||||
{
|
||||
/* The node is a file system mointpoint. Verify that the mountpoint
|
||||
* supports the stat() method
|
||||
*/
|
||||
|
||||
if (inode->u.i_mops && inode->u.i_mops->stat)
|
||||
{
|
||||
/* Perform the stat() operation */
|
||||
|
||||
ret = inode->u.i_mops->stat(inode, relpath, buf);
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = ENOSYS;
|
||||
}
|
||||
vp->useCount++;
|
||||
VnodeDrop();
|
||||
ret = vp->vop->Getattr(vp, buf);
|
||||
VnodeHold();
|
||||
vp->useCount--;
|
||||
VnodeDrop();
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
if (strlen(relpath) > 0)
|
||||
{
|
||||
ret = ENOENT;
|
||||
goto errout_with_inode;
|
||||
}
|
||||
/* The node is part of the root pseudo file system */
|
||||
|
||||
if (VfsPermissionCheck(desc.parent->i_uid, desc.parent->i_gid, desc.parent->i_mode, EXEC_OP))
|
||||
{
|
||||
ret = EACCES;
|
||||
goto errout_with_inode;
|
||||
}
|
||||
ret = statpseudo(inode, buf);
|
||||
VnodeDrop();
|
||||
ret = -ENOSYS;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* Check if the stat operation was successful */
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
ret = -ret;
|
||||
goto errout_with_inode;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* Successfully stat'ed the file */
|
||||
|
||||
inode_release(inode);
|
||||
free(fullpath);
|
||||
return OK;
|
||||
|
||||
/* Failure conditions always set the errno appropriately */
|
||||
|
||||
errout_with_inode:
|
||||
inode_release(inode);
|
||||
errout_with_path:
|
||||
free(fullpath);
|
||||
errout:
|
||||
set_errno(ret);
|
||||
set_errno(-ret);
|
||||
return VFS_ERROR;
|
||||
}
|
||||
|
||||
int isatty(int fd)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
Executable → Regular
+28
-93
@@ -42,23 +42,9 @@
|
||||
#include "sys/statfs.h"
|
||||
#include "string.h"
|
||||
#include "sched.h"
|
||||
|
||||
#include "inode/inode.h"
|
||||
#include "fs/vnode.h"
|
||||
#include "errno.h"
|
||||
#include "stdlib.h"
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: statpseudo
|
||||
****************************************************************************/
|
||||
|
||||
static inline int statpseudofs(FAR struct inode *inode, FAR struct statfs *buf)
|
||||
{
|
||||
(void)memset_s(buf, sizeof(struct statfs), 0, sizeof(struct statfs));
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
@@ -81,113 +67,62 @@ static inline int statpseudofs(FAR struct inode *inode, FAR struct statfs *buf)
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int statfs(FAR const char *path, FAR struct statfs *buf)
|
||||
int statfs(const char *path, struct statfs *buf)
|
||||
{
|
||||
FAR struct inode *inode;
|
||||
int ret = OK;
|
||||
char *fullpath = NULL;
|
||||
struct inode_search_s desc;
|
||||
struct Vnode *vnode = NULL;
|
||||
struct Mount *mnt = NULL;
|
||||
int ret = OK;
|
||||
|
||||
/* Sanity checks */
|
||||
|
||||
if (!path || !buf)
|
||||
{
|
||||
ret = EFAULT;
|
||||
ret = -EFAULT;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
if (!path[0])
|
||||
{
|
||||
ret = ENOENT;
|
||||
ret = -ENOENT;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
ret = vfs_normalize_path((const char *)NULL, path, &fullpath);
|
||||
/* Get an vnode for this file */
|
||||
VnodeHold();
|
||||
ret = VnodeLookup(path, &vnode, 0);
|
||||
if (ret < 0)
|
||||
{
|
||||
ret = -ret;
|
||||
VnodeDrop();
|
||||
goto errout;
|
||||
}
|
||||
vnode->useCount++;
|
||||
VnodeDrop();
|
||||
|
||||
/* Get an inode for this file */
|
||||
SETUP_SEARCH(&desc, fullpath, false);
|
||||
ret = inode_find(&desc);
|
||||
if (ret < 0)
|
||||
mnt = vnode->originMount;
|
||||
if (mnt == NULL || mnt->ops == NULL || mnt->ops->Statfs == NULL)
|
||||
{
|
||||
ret = EACCES;
|
||||
free(fullpath);
|
||||
goto errout;
|
||||
}
|
||||
inode = desc.node;
|
||||
|
||||
/* 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->stat && inode->u.i_mops->statfs)
|
||||
{
|
||||
struct stat *statbuf = LOS_MemAlloc(m_aucSysMem0, sizeof(struct stat));
|
||||
if (statbuf == NULL)
|
||||
{
|
||||
ret = ENOMEM;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Check whether the path is available or not */
|
||||
|
||||
ret = inode->u.i_mops->stat(inode, desc.relpath, statbuf);
|
||||
if (ret == 0)
|
||||
{
|
||||
/* Perform the statfs() operation */
|
||||
|
||||
(void)memset_s((void *)buf, sizeof(struct statfs), 0, sizeof(struct statfs));
|
||||
ret = inode->u.i_mops->statfs(inode, buf);
|
||||
}
|
||||
(VOID)LOS_MemFree(m_aucSysMem0, statbuf);
|
||||
}
|
||||
}
|
||||
ret = -ENOSYS;
|
||||
goto errout_with_useCount;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
/* The node is part of the root pseudo file system */
|
||||
|
||||
if (strlen(desc.relpath) > 0)
|
||||
ret = mnt->ops->Statfs(mnt, buf);
|
||||
if (ret < 0)
|
||||
{
|
||||
ret = ENOENT;
|
||||
goto errout_with_inode;
|
||||
goto errout_with_useCount;
|
||||
}
|
||||
|
||||
ret = statpseudofs(inode, buf);
|
||||
}
|
||||
|
||||
/* Check if the statfs operation was successful */
|
||||
VnodeHold();
|
||||
vnode->useCount--;
|
||||
VnodeDrop();
|
||||
|
||||
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_with_useCount:
|
||||
VnodeHold();
|
||||
vnode->useCount--;
|
||||
VnodeDrop();
|
||||
errout:
|
||||
set_errno(ret);
|
||||
set_errno(-ret);
|
||||
return VFS_ERROR;
|
||||
}
|
||||
|
||||
Executable → Regular
+8
-8
@@ -45,7 +45,7 @@
|
||||
#include "assert.h"
|
||||
#include "errno.h"
|
||||
|
||||
#include "inode/inode.h"
|
||||
#include "fs/vnode.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Name: file_truncate
|
||||
@@ -56,9 +56,9 @@
|
||||
* the errno variable.
|
||||
*
|
||||
****************************************************************************/
|
||||
static int file_truncate(FAR struct file *filep, off_t length)
|
||||
static int file_truncate(struct file *filep, off_t length)
|
||||
{
|
||||
FAR struct inode *inode = NULL;
|
||||
struct Vnode *vnode = NULL;
|
||||
int ret;
|
||||
int err;
|
||||
|
||||
@@ -70,13 +70,13 @@ static int file_truncate(FAR struct file *filep, off_t length)
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* Is this inode a registered mountpoint? Does it support the
|
||||
/* Is this vnode a registered mountpoint? Does it support the
|
||||
* truncate operations may be relevant to device drivers but only
|
||||
* the mountpoint operations vtable contains a truncate method.
|
||||
*/
|
||||
|
||||
inode = filep->f_inode;
|
||||
if (!inode || !inode->u.i_mops || !inode->u.i_mops->truncate)
|
||||
vnode = filep->f_vnode;
|
||||
if (!vnode || !vnode->vop || !vnode->vop->Truncate)
|
||||
{
|
||||
err = EBADF;
|
||||
goto errout;
|
||||
@@ -86,7 +86,7 @@ static int file_truncate(FAR struct file *filep, off_t length)
|
||||
* a write-able file system.
|
||||
*/
|
||||
|
||||
ret = inode->u.i_mops->truncate(filep, length);
|
||||
ret = vnode->vop->Truncate(vnode, length);
|
||||
if (ret < 0)
|
||||
{
|
||||
err = -ret;
|
||||
@@ -136,7 +136,7 @@ errout:
|
||||
int ftruncate(int fd, off_t length)
|
||||
{
|
||||
#if CONFIG_NFILE_DESCRIPTORS > 0
|
||||
FAR struct file *filep = NULL;
|
||||
struct file *filep = NULL;
|
||||
#endif
|
||||
|
||||
/* Did we get a valid file descriptor? */
|
||||
|
||||
Executable → Regular
+43
-63
@@ -45,7 +45,7 @@
|
||||
#include "assert.h"
|
||||
#include "errno.h"
|
||||
|
||||
#include "inode/inode.h"
|
||||
#include "fs/vnode.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Name: file_truncate
|
||||
@@ -57,55 +57,53 @@
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int file_truncate64(FAR struct file *filep, off64_t length)
|
||||
static int file_truncate64(struct file *filep, off64_t length)
|
||||
{
|
||||
FAR struct inode *inode = NULL;
|
||||
int ret;
|
||||
int err;
|
||||
|
||||
/* Was this file opened for write access? */
|
||||
|
||||
if (((unsigned int)(filep->f_oflags) & O_ACCMODE) == O_RDONLY)
|
||||
{
|
||||
err = EACCES;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* Is this inode a registered mountpoint? Does it support the
|
||||
struct Vnode *vnode = NULL;
|
||||
int err;
|
||||
|
||||
/* Was this file opened for write access? */
|
||||
|
||||
if (((unsigned int)(filep->f_oflags) & O_ACCMODE) == O_RDONLY)
|
||||
{
|
||||
err = -EACCES;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* Is this vnode a registered mountpoint? Does it support the
|
||||
* truncate operations may be relevant to device drivers but only
|
||||
* the mountpoint operations vtable contains a truncate method.
|
||||
*/
|
||||
|
||||
inode = filep->f_inode;
|
||||
if (!inode || !inode->u.i_mops || !inode->u.i_mops->truncate64)
|
||||
{
|
||||
err = EBADF;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* Does the file system support the truncate method? It should if it is
|
||||
|
||||
vnode = filep->f_vnode;
|
||||
if (!vnode || !vnode->vop || !vnode->vop->Truncate64)
|
||||
{
|
||||
err = -ENOSYS;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* Does the file system support the truncate method? It should if it is
|
||||
* a write-able file system.
|
||||
*/
|
||||
|
||||
ret = inode->u.i_mops->truncate64(filep, length);
|
||||
if (ret < 0)
|
||||
{
|
||||
err = -ret;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
errout:
|
||||
set_errno(err);
|
||||
return VFS_ERROR;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ftruncate
|
||||
*
|
||||
* Description:
|
||||
* The ftruncate() function causes the regular file referenced by fd to
|
||||
|
||||
err = vnode->vop->Truncate64(vnode, length);
|
||||
if (err < 0)
|
||||
{
|
||||
goto errout;
|
||||
}
|
||||
|
||||
return OK;
|
||||
|
||||
errout:
|
||||
set_errno(-err);
|
||||
return VFS_ERROR;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ftruncate
|
||||
*
|
||||
* Description:
|
||||
* The ftruncate() function causes the regular file referenced by fd to
|
||||
* have a size of length bytes.
|
||||
*
|
||||
* If the file previously was larger than length, the extra data is
|
||||
@@ -137,7 +135,7 @@ errout:
|
||||
int ftruncate64(int fd, off64_t length)
|
||||
{
|
||||
#if CONFIG_NFILE_DESCRIPTORS > 0
|
||||
FAR struct file *filep = NULL;
|
||||
struct file *filep = NULL;
|
||||
#endif
|
||||
|
||||
/* Did we get a valid file descriptor? */
|
||||
@@ -173,21 +171,3 @@ int ftruncate64(int fd, off64_t length)
|
||||
return file_truncate64(filep, length);
|
||||
#endif
|
||||
}
|
||||
|
||||
int truncate64(const char *path, off64_t length)
|
||||
{
|
||||
int fd;
|
||||
int ret;
|
||||
|
||||
fd = open(path, O_RDWR);
|
||||
if (fd == VFS_ERROR)
|
||||
{
|
||||
/* The errno value has already been set */
|
||||
return VFS_ERROR;
|
||||
}
|
||||
|
||||
ret = ftruncate64(fd, length);
|
||||
close(fd);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
Executable → Regular
+63
-161
@@ -44,32 +44,31 @@
|
||||
#include "fs/fs.h"
|
||||
#include "fcntl.h"
|
||||
|
||||
#include "inode/inode.h"
|
||||
#include "fs/vnode.h"
|
||||
#include "stdlib.h"
|
||||
#include "fs_other.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
static int check_target(struct Vnode *vnode)
|
||||
{
|
||||
if (vnode->type == VNODE_TYPE_DIR)
|
||||
{
|
||||
return -EISDIR;
|
||||
}
|
||||
|
||||
#undef FS_HAVE_WRITABLE_MOUNTPOINT
|
||||
#if !defined(CONFIG_DISABLE_MOUNTPOINT) && defined(CONFIG_FS_WRITABLE) && \
|
||||
CONFIG_NFILE_STREAMS > 0
|
||||
# define FS_HAVE_WRITABLE_MOUNTPOINT 1
|
||||
#endif
|
||||
|
||||
#undef FS_HAVE_PSEUDOFS_OPERATIONS
|
||||
#if !defined(CONFIG_DISABLE_PSEUDOFS_OPERATIONS) && CONFIG_NFILE_STREAMS > 0
|
||||
# define FS_HAVE_PSEUDOFS_OPERATIONS 1
|
||||
#endif
|
||||
|
||||
#undef FS_HAVE_UNLINK
|
||||
#if defined(FS_HAVE_WRITABLE_MOUNTPOINT) || defined(FS_HAVE_PSEUDOFS_OPERATIONS)
|
||||
# define FS_HAVE_UNLINK 1
|
||||
#endif
|
||||
|
||||
#ifdef FS_HAVE_UNLINK
|
||||
if (vnode->useCount > 0)
|
||||
{
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
if (VfsVnodePermissionCheck(vnode->parent, WRITE_OP))
|
||||
{
|
||||
return -EACCES;
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
@@ -81,177 +80,82 @@
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int do_unlink(int dirfd, FAR const char *pathname)
|
||||
int do_unlink(int dirfd, const char *pathname)
|
||||
{
|
||||
FAR struct inode *inode;
|
||||
const char *relpath = NULL;
|
||||
int errcode;
|
||||
int ret;
|
||||
char *fullpath = NULL;
|
||||
char *relativepath = NULL;
|
||||
struct inode_search_s desc;
|
||||
struct Vnode *vnode = NULL;
|
||||
int ret;
|
||||
char *name = NULL;
|
||||
char *fullpath = NULL;
|
||||
char *relativepath = NULL;
|
||||
|
||||
/* Get relative path by dirfd*/
|
||||
ret = get_path_from_fd(dirfd, &relativepath);
|
||||
if (ret < 0)
|
||||
{
|
||||
errcode = ret;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
errcode = vfs_normalize_path((const char *)relativepath, pathname, &fullpath);
|
||||
ret = vfs_normalize_path((const char *)relativepath, pathname, &fullpath);
|
||||
if (relativepath)
|
||||
{
|
||||
free(relativepath);
|
||||
}
|
||||
|
||||
if (errcode < 0)
|
||||
{
|
||||
errcode = -errcode;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* Get an inode for this file */
|
||||
SETUP_SEARCH(&desc, fullpath, false);
|
||||
ret = inode_find(&desc);
|
||||
if (ret < 0)
|
||||
{
|
||||
errcode = EACCES;
|
||||
free(fullpath);
|
||||
goto errout;
|
||||
}
|
||||
inode = desc.node;
|
||||
relpath = desc.relpath;
|
||||
|
||||
#ifndef CONFIG_DISABLE_MOUNTPOINT
|
||||
/* Check if the inode is a valid mountpoint. */
|
||||
|
||||
if (INODE_IS_MOUNTPT(inode) && inode->u.i_mops)
|
||||
VnodeHold();
|
||||
ret = VnodeLookup(fullpath, &vnode, 0);
|
||||
if (ret < 0)
|
||||
{
|
||||
/* Perform the unlink operation using the relative path at the
|
||||
* mountpoint.
|
||||
*/
|
||||
goto errout_with_lock;
|
||||
}
|
||||
|
||||
if (inode->u.i_mops->unlink)
|
||||
{
|
||||
ret = inode->u.i_mops->unlink(inode, relpath);
|
||||
if (ret < 0)
|
||||
{
|
||||
errcode = -ret;
|
||||
goto errout_with_inode;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
errcode = ENOSYS;
|
||||
goto errout_with_inode;
|
||||
}
|
||||
ret = check_target(vnode);
|
||||
if (ret < 0)
|
||||
{
|
||||
goto errout_with_lock;
|
||||
}
|
||||
name = strrchr(fullpath, '/') + 1;
|
||||
|
||||
if (vnode && vnode->vop && vnode->vop->Unlink)
|
||||
{
|
||||
ret = vnode->vop->Unlink(vnode->parent, vnode, name);
|
||||
}
|
||||
else if (vnode && vnode->fop && vnode->fop->unlink)
|
||||
{
|
||||
ret = vnode->fop->unlink(vnode);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
|
||||
/* If this is a "dangling" pseudo-file node (i.e., it has no operations)
|
||||
* or a soft link, then rm should remove the node.
|
||||
*/
|
||||
|
||||
if (!INODE_IS_SPECIAL(inode) && inode->u.i_ops)
|
||||
{
|
||||
/* If this is a pseudo-file node (i.e., it has no operations)
|
||||
* then rmdir should remove the node.
|
||||
*/
|
||||
|
||||
inode_semtake();
|
||||
if (VfsPermissionCheck(desc.parent->i_uid, desc.parent->i_gid, desc.parent->i_mode, EXEC_OP | WRITE_OP))
|
||||
{
|
||||
errcode = EACCES;
|
||||
goto errout_with_inode;
|
||||
}
|
||||
|
||||
/* Refuse to unlink the inode if it has children. I.e., if it is
|
||||
* functioning as a directory and the directory is not empty.
|
||||
*/
|
||||
|
||||
if (inode->i_child != NULL)
|
||||
{
|
||||
errcode = ENOTEMPTY;
|
||||
inode_semgive();
|
||||
goto errout_with_inode;
|
||||
}
|
||||
|
||||
/* Notify the driver that it has been unlinked. If there are no
|
||||
* open references to the driver instance, then the driver should
|
||||
* release all resources because it is no longer accessible.
|
||||
*/
|
||||
|
||||
if (INODE_IS_DRIVER(inode) && inode->u.i_ops->unlink)
|
||||
{
|
||||
/* Notify the character driver that it has been unlinked */
|
||||
|
||||
ret = inode->u.i_ops->unlink(inode);
|
||||
if (ret < 0)
|
||||
{
|
||||
errcode = -ret;
|
||||
inode_semgive();
|
||||
goto errout_with_inode;
|
||||
}
|
||||
}
|
||||
#ifndef CONFIG_DISABLE_MOUNTPOINT
|
||||
else if (INODE_IS_BLOCK(inode) && inode->u.i_bops->unlink)
|
||||
{
|
||||
/* Notify the block driver that it has been unlinked */
|
||||
|
||||
ret = inode->u.i_bops->unlink(inode);
|
||||
if (ret < 0)
|
||||
{
|
||||
errcode = -ret;
|
||||
inode_semgive();
|
||||
goto errout_with_inode;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
inode_semgive();
|
||||
errcode = EACCES;
|
||||
goto errout_with_inode;
|
||||
}
|
||||
|
||||
inode_semgive();
|
||||
}
|
||||
else if (!INODE_IS_SPECIAL(inode) && (inode->u.i_ops == NULL))
|
||||
{
|
||||
/* It is a "dangling" pseudo-file node with no operations */
|
||||
|
||||
errcode = EISDIR;
|
||||
goto errout_with_inode;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
errcode = ENXIO;
|
||||
goto errout_with_inode;
|
||||
ret = -ENOSYS;
|
||||
}
|
||||
|
||||
/* Thie file is being deleted, page-caches of the file will no longer be used,
|
||||
* so drop all the page-caches for the file at this moment, and then remove mapping
|
||||
* between the file and pagecache.
|
||||
*/
|
||||
|
||||
(void)remove_mapping(fullpath, NULL);
|
||||
if (ret != OK)
|
||||
{
|
||||
goto errout_with_lock;
|
||||
}
|
||||
|
||||
VnodeFree(vnode);
|
||||
VnodeDrop();
|
||||
(void)remove_mapping(fullpath);
|
||||
/* Successfully unlinked */
|
||||
|
||||
inode_release(inode);
|
||||
free(fullpath);
|
||||
return OK;
|
||||
|
||||
errout_with_inode:
|
||||
inode_release(inode);
|
||||
free(fullpath);
|
||||
errout_with_lock:
|
||||
VnodeDrop();
|
||||
|
||||
errout:
|
||||
set_errno(errcode);
|
||||
if (fullpath)
|
||||
{
|
||||
free(fullpath);
|
||||
}
|
||||
set_errno(-ret);
|
||||
|
||||
return VFS_ERROR;
|
||||
}
|
||||
|
||||
@@ -262,7 +166,7 @@ errout:
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int unlink(FAR const char *pathname)
|
||||
int unlink(const char *pathname)
|
||||
{
|
||||
return do_unlink(AT_FDCWD, pathname);
|
||||
}
|
||||
@@ -273,9 +177,9 @@ int unlink(FAR const char *pathname)
|
||||
* Description: Remove a file managed a mountpoint by dirfd
|
||||
*
|
||||
****************************************************************************/
|
||||
extern int do_rmdir(int dirfd, FAR const char *pathname);
|
||||
extern int do_rmdir(int dirfd, const char *pathname);
|
||||
|
||||
int unlinkat(int dirfd, FAR const char *pathname, int flag)
|
||||
int unlinkat(int dirfd, const char *pathname, int flag)
|
||||
{
|
||||
/* Now flag only support 0 && AT_REMOVEDIR */
|
||||
if ((flag & ~AT_REMOVEDIR) != 0)
|
||||
@@ -286,5 +190,3 @@ int unlinkat(int dirfd, FAR const char *pathname, int flag)
|
||||
|
||||
return do_unlink(dirfd, pathname);
|
||||
}
|
||||
|
||||
#endif /* FS_HAVE_UNLINK */
|
||||
|
||||
Executable → Regular
+8
-11
@@ -48,7 +48,7 @@
|
||||
#include "sys/socket.h"
|
||||
#include "console.h"
|
||||
#include "user_copy.h"
|
||||
#include "inode/inode.h"
|
||||
#include "fs/vnode.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
@@ -79,10 +79,8 @@
|
||||
* values).
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
ssize_t file_write(FAR struct file *filep, FAR const void *buf, size_t nbytes)
|
||||
ssize_t file_write(struct file *filep, const void *buf, size_t nbytes)
|
||||
{
|
||||
FAR struct inode *inode;
|
||||
int ret;
|
||||
int err;
|
||||
|
||||
@@ -102,8 +100,7 @@ ssize_t file_write(FAR struct file *filep, FAR const void *buf, size_t nbytes)
|
||||
|
||||
/* Is a driver registered? Does it support the write method? */
|
||||
|
||||
inode = filep->f_inode;
|
||||
if (!inode || !inode->u.i_ops || !inode->u.i_ops->write)
|
||||
if (!filep->ops || !filep->ops->write)
|
||||
{
|
||||
err = EBADF;
|
||||
goto errout;
|
||||
@@ -111,7 +108,7 @@ ssize_t file_write(FAR struct file *filep, FAR const void *buf, size_t nbytes)
|
||||
|
||||
/* Yes, then let the driver perform the write */
|
||||
|
||||
ret = inode->u.i_ops->write(filep, (const char *)buf, nbytes);
|
||||
ret = filep->ops->write(filep, (const char *)buf, nbytes);
|
||||
if (ret < 0)
|
||||
{
|
||||
err = -ret;
|
||||
@@ -161,7 +158,7 @@ errout:
|
||||
* specified in buf, the value specified in count, or the current
|
||||
* file offset is not suitably aligned.
|
||||
* EIO
|
||||
* A low-level I/O error occurred while modifying the inode.
|
||||
* A low-level I/O error occurred while modifying the vnode.
|
||||
* ENOSPC
|
||||
* The device containing the file referred to by fd has no room for
|
||||
* the data.
|
||||
@@ -173,10 +170,10 @@ errout:
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
ssize_t write(int fd, FAR const void *buf, size_t nbytes)
|
||||
ssize_t write(int fd, const void *buf, size_t nbytes)
|
||||
{
|
||||
#if CONFIG_NFILE_DESCRIPTORS > 0
|
||||
FAR struct file *filep;
|
||||
struct file *filep;
|
||||
#endif
|
||||
|
||||
/* Did we get a valid file descriptor? */
|
||||
@@ -188,7 +185,7 @@ ssize_t write(int fd, FAR const void *buf, size_t nbytes)
|
||||
/* Write to a socket descriptor is equivalent to send with flags == 0 */
|
||||
|
||||
#if defined(LOSCFG_NET_LWIP_SACK)
|
||||
FAR const void *bufbak = buf;
|
||||
const void *bufbak = buf;
|
||||
ssize_t ret;
|
||||
if (LOS_IsUserAddress((VADDR_T)(uintptr_t)buf))
|
||||
{
|
||||
|
||||
Executable → Regular
+17
-14
@@ -46,7 +46,6 @@
|
||||
#include "sys/types.h"
|
||||
#include "stdint.h"
|
||||
#include "dirent.h"
|
||||
|
||||
#include "fs/fs.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
@@ -132,7 +131,7 @@ struct fs_cromfsdir_s
|
||||
struct tmpfs_directory_s; /* Forward reference */
|
||||
struct fs_tmpfsdir_s
|
||||
{
|
||||
FAR struct tmpfs_directory_s *tf_tdo; /* Directory being enumerated */
|
||||
struct tmpfs_directory_s *tf_tdo; /* Directory being enumerated */
|
||||
unsigned int tf_index; /* Directory index */
|
||||
};
|
||||
|
||||
@@ -147,12 +146,12 @@ struct fs_binfsdir_s
|
||||
|
||||
#ifdef CONFIG_FS_NXFFS
|
||||
/* NXFFS is the tiny NuttX wear-leveling FLASH file system. The state value is
|
||||
* the offset in FLASH memory to the next inode entry.
|
||||
* the offset in FLASH memory to the next vnode entry.
|
||||
*/
|
||||
|
||||
struct fs_nxffsdir_s
|
||||
{
|
||||
off_t nx_offset; /* Offset to the next inode */
|
||||
off_t nx_offset; /* Offset to the next vnode */
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -203,8 +202,8 @@ struct fs_unionfsdir_s
|
||||
uint8_t fu_ndx; /* Index of file system being enumerated */
|
||||
bool fu_eod; /* True: At end of directory */
|
||||
bool fu_prefix[2]; /* True: Fake directory in prefix */
|
||||
FAR char *fu_relpath; /* Path being enumerated */
|
||||
FAR struct fs_dirent_s *fu_lower[2]; /* dirent struct used by contained file system */
|
||||
char *fu_relpath; /* Path being enumerated */
|
||||
struct fs_dirent_s *fu_lower[2]; /* dirent struct used by contained file system */
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -215,7 +214,7 @@ struct fs_unionfsdir_s
|
||||
|
||||
struct fs_userfsdir_s
|
||||
{
|
||||
FAR void *fs_dir; /* Opaque pointer to UserFS DIR */
|
||||
void *fs_dir; /* Opaque pointer to UserFS DIR */
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -226,21 +225,21 @@ struct fs_userfsdir_s
|
||||
|
||||
struct fs_hostfsdir_s
|
||||
{
|
||||
FAR void *fs_dir; /* Opaque pointer to host DIR */
|
||||
void *fs_dir; /* Opaque pointer to host DIR */
|
||||
};
|
||||
#endif
|
||||
|
||||
struct fs_dirent_s
|
||||
{
|
||||
/* This is the node that was opened by opendir. The type of the inode
|
||||
/* This is the node that was opened by opendir. The type of the vnode
|
||||
* determines the way that the readdir() operations are performed. For the
|
||||
* pseudo root pseudo-file system, it is also used to support rewind.
|
||||
*
|
||||
* We hold a reference on this inode so we know that it will persist until
|
||||
* closedir() is called (although inodes linked to this inode may change).
|
||||
* We hold a reference on this vnode so we know that it will persist until
|
||||
* closedir() is called (although vnodes linked to this vnode may change).
|
||||
*/
|
||||
|
||||
struct inode *fd_root;
|
||||
struct Vnode *fd_root;
|
||||
|
||||
/* At present, only mountpoints require special handling flags */
|
||||
|
||||
@@ -252,6 +251,10 @@ struct fs_dirent_s
|
||||
|
||||
off_t fd_position;
|
||||
|
||||
/* This keeps track of the internal offset for some FSs */
|
||||
off_t fd_int_offset;
|
||||
|
||||
|
||||
/* Retained control information depends on the type of file system that
|
||||
* provides is provides the mountpoint. Ideally this information should
|
||||
* be hidden behind an opaque, file-system-dependent void *, but we put
|
||||
@@ -282,7 +285,7 @@ struct fs_dirent_s
|
||||
struct fs_binfsdir_s binfs;
|
||||
#endif
|
||||
#ifdef CONFIG_FS_PROCFS
|
||||
FAR void *procfs;
|
||||
void *procfs;
|
||||
#endif
|
||||
#ifdef CONFIG_FS_NXFFS
|
||||
struct fs_nxffsdir_s nxffs;
|
||||
@@ -297,7 +300,7 @@ struct fs_dirent_s
|
||||
struct fs_spiffsdir_s spiffs;
|
||||
#endif
|
||||
#ifdef CONFIG_FS_LITTLEFS
|
||||
FAR void *littlefs;
|
||||
void *littlefs;
|
||||
#endif
|
||||
#ifdef CONFIG_FS_UNIONFS
|
||||
struct fs_unionfsdir_s unionfs;
|
||||
|
||||
Executable → Regular
+8
-38
@@ -67,9 +67,9 @@ extern "C" {
|
||||
|
||||
#ifndef CONFIG_DISABLE_MOUNTPOINT
|
||||
struct statfs; /* Forward reference */
|
||||
typedef int (*foreach_mountpoint_t)(FAR const char *mountpoint,
|
||||
FAR struct statfs *statbuf,
|
||||
FAR void *arg);
|
||||
typedef int (*foreach_mountpoint_t)(const char *mountpoint,
|
||||
struct statfs *statbuf,
|
||||
void *arg);
|
||||
#endif
|
||||
|
||||
struct filelist *sched_getfiles(void);
|
||||
@@ -110,6 +110,8 @@ ssize_t sendfile(int outfd, int infd, off_t *offset, size_t count);
|
||||
*/
|
||||
|
||||
extern int get_path_from_fd(int fd, char **path);
|
||||
extern int get_path_from_dirfd(int fd, char **path);
|
||||
bool get_bit(int i);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: foreach_mountpoint
|
||||
@@ -119,8 +121,8 @@ extern int get_path_from_fd(int fd, char **path);
|
||||
* terminated when the callback 'handler' returns a non-zero value, or when
|
||||
* all of the mountpoints have been visited.
|
||||
*
|
||||
* This is just a front end "filter" to foreach_inode() that forwards only
|
||||
* mountpoint inodes. It is intended to support the mount() command to
|
||||
* This is just a front end "filter" to foreach_vnode() that forwards only
|
||||
* mountpoint vnodes. It is intended to support the mount() command to
|
||||
* when the mount command is used to enumerate mounts.
|
||||
*
|
||||
* NOTE 1: Use with caution... The pseudo-file system is locked throughout
|
||||
@@ -136,39 +138,7 @@ extern int get_path_from_fd(int fd, char **path);
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef CONFIG_DISABLE_MOUNTPOINT
|
||||
int foreach_mountpoint(foreach_mountpoint_t handler, FAR void *arg);
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: find_blockdriver
|
||||
*
|
||||
* Description:
|
||||
* Return the inode of the block driver specified by 'pathname'
|
||||
*
|
||||
* Input Parameters:
|
||||
* pathname - The full path to the block driver to be located
|
||||
* mountflags - If MS_RDONLY is not set, then driver must support write
|
||||
* operations (see include/sys/mount.h)
|
||||
* ppinode - Address of the location to return the inode reference
|
||||
*
|
||||
* Returned Value:
|
||||
* Returns zero on success or a negated errno on failure:
|
||||
*
|
||||
* EINVAL - Pathname or pinode is NULL.
|
||||
* ENOENT - No block driver of this name is registered
|
||||
* ENOTBLK - The inode associated with the pathname is not a block driver
|
||||
* EACCESS - The MS_RDONLY option was not set but this driver does not
|
||||
* support write access
|
||||
*
|
||||
* Attention:
|
||||
* The parameter pathname is a full path, which begin with '/'.
|
||||
* The parameter ppinode must point a valid memory, which size must be enough for storing struct inode.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#if CONFIG_NFILE_DESCRIPTORS > 0
|
||||
int find_blockdriver(FAR const char *pathname, int mountflags,
|
||||
FAR struct inode **ppinode);
|
||||
int foreach_mountpoint(foreach_mountpoint_t handler, void *arg);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
Executable → Regular
+271
-210
@@ -58,6 +58,7 @@
|
||||
#include "los_atomic.h"
|
||||
#include "semaphore.h"
|
||||
#include "los_spinlock.h"
|
||||
#include "mount.h"
|
||||
|
||||
#ifndef CONFIG_DISABLE_MQUEUE
|
||||
#include "mqueue.h"
|
||||
@@ -158,8 +159,9 @@ extern "C" {
|
||||
#define CHG_MTIME 32
|
||||
#define CHG_CTIME 64
|
||||
|
||||
struct IATTR {
|
||||
/* This structure is used for record inode attr. */
|
||||
struct IATTR
|
||||
{
|
||||
/* This structure is used for record vnode attr. */
|
||||
unsigned int attr_chg_valid;
|
||||
unsigned int attr_chg_flags;
|
||||
unsigned attr_chg_mode;
|
||||
@@ -174,7 +176,7 @@ struct IATTR {
|
||||
/* Forward references */
|
||||
|
||||
struct file;
|
||||
struct inode;
|
||||
struct Vnode;
|
||||
struct stat;
|
||||
struct statfs;
|
||||
struct pollfd;
|
||||
@@ -188,25 +190,30 @@ struct file_operations_vfs
|
||||
{
|
||||
/* The device driver open method differs from the mountpoint open method */
|
||||
|
||||
int (*open)(FAR struct file *filep);
|
||||
int (*open)(struct file *filep);
|
||||
|
||||
/* The following methods must be identical in signature and position because
|
||||
* the struct file_operations and struct mountp_operations are treated like
|
||||
* unions.
|
||||
*/
|
||||
|
||||
int (*close)(FAR struct file *filep);
|
||||
ssize_t (*read)(FAR struct file *filep, FAR char *buffer, size_t buflen);
|
||||
ssize_t (*write)(FAR struct file *filep, FAR const char *buffer, size_t buflen);
|
||||
off_t (*seek)(FAR struct file *filep, off_t offset, int whence);
|
||||
int (*ioctl)(FAR struct file *filep, int cmd, unsigned long arg);
|
||||
int (*mmap)(FAR struct file* filep, struct VmMapRegion *region);
|
||||
int (*close)(struct file *filep);
|
||||
ssize_t (*read)(struct file *filep, char *buffer, size_t buflen);
|
||||
ssize_t (*write)(struct file *filep, const char *buffer, size_t buflen);
|
||||
off_t (*seek)(struct file *filep, off_t offset, int whence);
|
||||
int (*ioctl)(struct file *filep, int cmd, unsigned long arg);
|
||||
int (*mmap)(struct file* filep, struct VmMapRegion *region);
|
||||
/* The two structures need not be common after this point */
|
||||
|
||||
#ifndef CONFIG_DISABLE_POLL
|
||||
int (*poll)(FAR struct file *filep, poll_table *fds);
|
||||
int (*poll)(struct file *filep, poll_table *fds);
|
||||
#endif
|
||||
int (*unlink)(FAR struct inode *inode);
|
||||
int (*stat)(struct file *filep, struct stat* st);
|
||||
int (*fallocate)(struct file* filep, int mode, off_t offset, off_t len);
|
||||
int (*fallocate64)(struct file *filep, int mode, off64_t offset, off64_t len);
|
||||
int (*fsync)(struct file *filep);
|
||||
ssize_t (*readpage)(struct file *filep, char *buffer, size_t buflen);
|
||||
int (*unlink)(struct Vnode *vnode);
|
||||
};
|
||||
|
||||
/* This structure provides information about the state of a block driver */
|
||||
@@ -214,31 +221,119 @@ struct file_operations_vfs
|
||||
#ifndef CONFIG_DISABLE_MOUNTPOINT
|
||||
struct geometry
|
||||
{
|
||||
bool geo_available; /* true: The device is available */
|
||||
bool geo_mediachanged; /* true: The media has changed since last query */
|
||||
bool geo_writeenabled; /* true: It is okay to write to this device */
|
||||
bool geo_available; /* true: The device is available */
|
||||
bool geo_mediachanged; /* true: The media has changed since last query */
|
||||
bool geo_writeenabled; /* true: It is okay to write to this device */
|
||||
unsigned long long geo_nsectors; /* Number of sectors on the device */
|
||||
size_t geo_sectorsize; /* Size of one sector */
|
||||
size_t geo_sectorsize; /* Size of one sector */
|
||||
};
|
||||
|
||||
/* This structure is provided by block devices when they register with the
|
||||
* system. It is used by file systems to perform filesystem transfers. It
|
||||
* differs from the normal driver vtable in several ways -- most notably in
|
||||
* that it deals in struct inode vs. struct filep.
|
||||
* that it deals in struct Vnode vs. struct filep.
|
||||
*/
|
||||
|
||||
struct inode;
|
||||
struct Vnode;
|
||||
struct block_operations
|
||||
{
|
||||
int (*open)(FAR struct inode *inode);
|
||||
int (*close)(FAR struct inode *inode);
|
||||
ssize_t (*read)(FAR struct inode *inode, FAR unsigned char *buffer,
|
||||
int (*open)(struct Vnode *vnode);
|
||||
int (*close)(struct Vnode *vnode);
|
||||
ssize_t (*read)(struct Vnode *vnode, unsigned char *buffer,
|
||||
unsigned long long start_sector, unsigned int nsectors);
|
||||
ssize_t (*write)(FAR struct inode *inode, FAR const unsigned char *buffer,
|
||||
ssize_t (*write)(struct Vnode *vnode, const unsigned char *buffer,
|
||||
unsigned long long start_sector, unsigned int nsectors);
|
||||
int (*geometry)(FAR struct inode *inode, FAR struct geometry *geometry);
|
||||
int (*ioctl)(FAR struct inode *inode, int cmd, unsigned long arg);
|
||||
int (*unlink)(FAR struct inode *inode);
|
||||
int (*geometry)(struct Vnode *vnode, struct geometry *geometry);
|
||||
int (*ioctl)(struct Vnode *vnode, int cmd, unsigned long arg);
|
||||
int (*unlink)(struct Vnode *vnode);
|
||||
};
|
||||
|
||||
struct mountpt_operations2
|
||||
{
|
||||
/* The mountpoint open method differs from the driver open method
|
||||
* because it receives (1) the vnode that contains the mountpoint
|
||||
* private data, (2) the relative path into the mountpoint, and (3)
|
||||
* information to manage privileges.
|
||||
*/
|
||||
|
||||
int (*open)(struct file *filep, const char *relpath,
|
||||
int oflags, mode_t mode);
|
||||
|
||||
/* The following methods must be identical in signature and position
|
||||
* because the struct file_operations and struct mountpt_operations are
|
||||
* treated like unions.
|
||||
*/
|
||||
|
||||
int (*close)(struct file *filep);
|
||||
ssize_t (*read)(struct file *filep, char *buffer, size_t buflen);
|
||||
ssize_t (*write)(struct file *filep, const char *buffer,
|
||||
size_t buflen);
|
||||
off_t (*seek)(struct file *filep, off_t offset, int whence);
|
||||
int (*ioctl)(struct file *filep, int cmd, unsigned long arg);
|
||||
int (*mmap)(struct file* filep, LosVmMapRegion *region);
|
||||
/* The two structures need not be common after this point. The following
|
||||
* are extended methods needed to deal with the unique needs of mounted
|
||||
* file systems.
|
||||
*
|
||||
* Additional open-file-specific mountpoint operations:
|
||||
*/
|
||||
|
||||
int (*sync)(struct file *filep);
|
||||
int (*dup)(const struct file *oldp, struct file *newp);
|
||||
int (*fstat)(const struct file *filep, struct stat *buf);
|
||||
int (*truncate)(struct file *filep, off_t length);
|
||||
|
||||
/* Directory operations */
|
||||
|
||||
int (*opendir)(struct Vnode *mountpt, const char *relpath,
|
||||
struct fs_dirent_s *dir);
|
||||
int (*closedir)(struct Vnode *mountpt,
|
||||
struct fs_dirent_s *dir);
|
||||
int (*readdir)(struct Vnode *mountpt,
|
||||
struct fs_dirent_s *dir);
|
||||
int (*rewinddir)(struct Vnode *mountpt,
|
||||
struct fs_dirent_s *dir);
|
||||
|
||||
/* General volume-related mountpoint operations: */
|
||||
|
||||
int (*bind)(struct Vnode *blkdriver, const void *data, void **handle, const char *realpath);
|
||||
int (*unbind)(void *handle, struct Vnode **blkdriver);
|
||||
int (*statfs)(struct Vnode *mountpt, struct statfs *buf);
|
||||
int (*virstatfs)(struct Vnode *mountpt, const char* relpath, struct statfs *buf);
|
||||
|
||||
/* Operations on paths */
|
||||
|
||||
int (*unlink)(struct Vnode *mountpt, const char *relpath);
|
||||
int (*mkdir)(struct Vnode *mountpt, const char *relpath,
|
||||
mode_t mode);
|
||||
int (*rmdir)(struct Vnode *mountpt, const char *relpath);
|
||||
int (*rename)(struct Vnode *mountpt, const char *oldrelpath,
|
||||
const char *newrelpath);
|
||||
int (*stat)(struct Vnode *mountpt, const char *relpath,
|
||||
struct stat *buf);
|
||||
int (*utime)(struct Vnode *mountpt, const char *relpath,
|
||||
const struct tm *times);
|
||||
int (*chattr)(struct Vnode *mountpt, const char *relpath,
|
||||
struct IATTR *attr);
|
||||
loff_t (*seek64)(struct file *filep, loff_t offset, int whence);
|
||||
int (*getlabel)(void *handle, char* label);
|
||||
int (*fallocate)(struct file *filep, int mode, off_t offset, off_t len);
|
||||
int (*fallocate64)(struct file *filep, int mode, off64_t offset, off64_t len);
|
||||
int (*truncate64)(struct file *filep, off64_t length);
|
||||
int (*fscheck)(struct Vnode *mountpt, const char *relpath,
|
||||
struct fs_dirent_s *dir);
|
||||
int (*map_pages)(LosVmMapRegion *region, LosVmPgFault *pgFault);
|
||||
ssize_t (*writepage)(struct file *filep, const char *buffer, size_t buflen);
|
||||
/* NOTE: More operations will be needed here to support: disk usage
|
||||
* stats file stat(), file attributes, file truncation, etc.
|
||||
*/
|
||||
};
|
||||
|
||||
struct drv_data
|
||||
{
|
||||
const void *ops;
|
||||
mode_t mode;
|
||||
void *priv;
|
||||
};
|
||||
|
||||
/* This structure is provided by a filesystem to describe a mount point.
|
||||
@@ -260,94 +355,12 @@ struct page_mapping {
|
||||
|
||||
/* map: full_path(owner) <-> mapping */
|
||||
struct file_map {
|
||||
LOS_DL_LIST head;
|
||||
LosMux lock; /* lock to protect this mapping */
|
||||
struct page_mapping mapping;
|
||||
char *owner; /* owner: full path of file */
|
||||
};
|
||||
|
||||
|
||||
struct mountpt_operations
|
||||
{
|
||||
/* The mountpoint open method differs from the driver open method
|
||||
* because it receives (1) the inode that contains the mountpoint
|
||||
* private data, (2) the relative path into the mountpoint, and (3)
|
||||
* information to manage privileges.
|
||||
*/
|
||||
|
||||
int (*open)(FAR struct file *filep, FAR const char *relpath,
|
||||
int oflags, mode_t mode);
|
||||
|
||||
/* The following methods must be identical in signature and position
|
||||
* because the struct file_operations and struct mountpt_operations are
|
||||
* treated like unions.
|
||||
*/
|
||||
|
||||
int (*close)(FAR struct file *filep);
|
||||
ssize_t (*read)(FAR struct file *filep, FAR char *buffer, size_t buflen);
|
||||
ssize_t (*write)(FAR struct file *filep, FAR const char *buffer,
|
||||
size_t buflen);
|
||||
off_t (*seek)(FAR struct file *filep, off_t offset, int whence);
|
||||
int (*ioctl)(FAR struct file *filep, int cmd, unsigned long arg);
|
||||
int (*mmap)(FAR struct file* filep, LosVmMapRegion *region);
|
||||
/* The two structures need not be common after this point. The following
|
||||
* are extended methods needed to deal with the unique needs of mounted
|
||||
* file systems.
|
||||
*
|
||||
* Additional open-file-specific mountpoint operations:
|
||||
*/
|
||||
|
||||
int (*sync)(FAR struct file *filep);
|
||||
int (*dup)(FAR const struct file *oldp, FAR struct file *newp);
|
||||
int (*fstat)(FAR const struct file *filep, FAR struct stat *buf);
|
||||
int (*truncate)(FAR struct file *filep, off_t length);
|
||||
|
||||
/* Directory operations */
|
||||
|
||||
int (*opendir)(FAR struct inode *mountpt, FAR const char *relpath,
|
||||
FAR struct fs_dirent_s *dir);
|
||||
int (*closedir)(FAR struct inode *mountpt,
|
||||
FAR struct fs_dirent_s *dir);
|
||||
int (*readdir)(FAR struct inode *mountpt,
|
||||
FAR struct fs_dirent_s *dir);
|
||||
int (*rewinddir)(FAR struct inode *mountpt,
|
||||
FAR struct fs_dirent_s *dir);
|
||||
|
||||
/* General volume-related mountpoint operations: */
|
||||
|
||||
int (*bind)(FAR struct inode *blkdriver, FAR const void *data,
|
||||
FAR void **handle, FAR const char *realpath);
|
||||
int (*unbind)(FAR void *handle, FAR struct inode **blkdriver);
|
||||
int (*statfs)(FAR struct inode *mountpt, FAR struct statfs *buf);
|
||||
int (*virstatfs)(struct inode *mountpt, const char* relpath, struct statfs *buf);
|
||||
|
||||
/* Operations on paths */
|
||||
|
||||
int (*unlink)(FAR struct inode *mountpt, FAR const char *relpath);
|
||||
int (*mkdir)(FAR struct inode *mountpt, FAR const char *relpath,
|
||||
mode_t mode);
|
||||
int (*rmdir)(FAR struct inode *mountpt, FAR const char *relpath);
|
||||
int (*rename)(FAR struct inode *mountpt, FAR const char *oldrelpath,
|
||||
FAR const char *newrelpath);
|
||||
int (*stat)(FAR struct inode *mountpt, FAR const char *relpath,
|
||||
FAR struct stat *buf);
|
||||
int (*utime)(FAR struct inode *mountpt, FAR const char *relpath,
|
||||
FAR const struct tm *times);
|
||||
int (*chattr)(FAR struct inode *mountpt, FAR const char *relpath,
|
||||
struct IATTR *attr);
|
||||
loff_t (*seek64)(FAR struct file *filep, loff_t offset, int whence);
|
||||
int (*getlabel)(FAR void *handle, FAR char* label);
|
||||
int (*fallocate)(FAR struct file *filep, int mode, off_t offset, off_t len);
|
||||
int (*fallocate64)(FAR struct file *filep, int mode, off64_t offset, off64_t len);
|
||||
int (*truncate64)(FAR struct file *filep, off64_t length);
|
||||
int (*fscheck)(FAR struct inode *mountpt, FAR const char *relpath,
|
||||
FAR struct fs_dirent_s *dir);
|
||||
int (*map_pages)(LosVmMapRegion *region, LosVmPgFault *pgFault);
|
||||
ssize_t (*readpage)(struct file *filep, char *buffer, size_t buflen);
|
||||
ssize_t (*writepage)(struct file *filep, const char *buffer, size_t buflen);
|
||||
/* NOTE: More operations will be needed here to support: disk usage
|
||||
* stats file stat(), file attributes, file truncation, etc.
|
||||
*/
|
||||
LOS_DL_LIST head;
|
||||
LosMux lock; /* lock to protect this mapping */
|
||||
struct page_mapping mapping;
|
||||
int name_len;
|
||||
char *rename;
|
||||
char owner[0]; /* owner: full path of file */
|
||||
};
|
||||
#endif /* CONFIG_DISABLE_MOUNTPOINT */
|
||||
|
||||
@@ -366,7 +379,7 @@ typedef struct virtual_partition_info
|
||||
struct fsmap_t
|
||||
{
|
||||
const char *fs_filesystemtype;
|
||||
const struct mountpt_operations *fs_mops;
|
||||
const struct MountOps *fs_mops;
|
||||
const BOOL is_mtd_support;
|
||||
const BOOL is_bdfs;
|
||||
};
|
||||
@@ -391,25 +404,10 @@ struct fsmap_t _l LOS_HAL_TABLE_ENTRY(fsmap) = \
|
||||
*/
|
||||
|
||||
/* These are the various kinds of operations that can be associated with
|
||||
* an inode.
|
||||
* an vnode.
|
||||
*/
|
||||
|
||||
union inode_ops_u
|
||||
{
|
||||
FAR const struct file_operations_vfs *i_ops; /* Driver operations for inode */
|
||||
#ifndef CONFIG_DISABLE_MOUNTPOINT
|
||||
FAR const struct block_operations *i_bops; /* Block driver operations */
|
||||
FAR const struct mountpt_operations *i_mops; /* Operations on a mountpoint */
|
||||
#endif
|
||||
#ifdef CONFIG_FS_NAMED_SEMAPHORES
|
||||
FAR struct nsem_inode_s *i_nsem; /* Named semaphore */
|
||||
#endif
|
||||
#ifndef CONFIG_DISABLE_MQUEUE
|
||||
FAR struct mqueue_inode_s *i_mqueue; /* POSIX message queue */
|
||||
#endif
|
||||
};
|
||||
|
||||
/* This structure represents one inode in the NuttX pseudo-file system */
|
||||
/* This structure represents one vnode in the NuttX pseudo-file system */
|
||||
|
||||
typedef enum mount_status
|
||||
{
|
||||
@@ -417,36 +415,19 @@ typedef enum mount_status
|
||||
STAT_MOUNTED,
|
||||
} MOUNT_STATE;
|
||||
|
||||
struct inode
|
||||
{
|
||||
FAR struct inode *i_peer; /* Link to same level inode */
|
||||
FAR struct inode *i_child; /* Link to lower level inode */
|
||||
int16_t i_crefs; /* References to inode */
|
||||
uint16_t i_flags; /* Flags for inode */
|
||||
unsigned long mountflags; /* Flags for mount */
|
||||
union inode_ops_u u; /* Inode operations */
|
||||
#ifdef LOSCFG_FILE_MODE
|
||||
unsigned int i_uid;
|
||||
unsigned int i_gid;
|
||||
mode_t i_mode; /* Access mode flags */
|
||||
#endif
|
||||
FAR void *i_private; /* Per inode driver private data */
|
||||
MOUNT_STATE e_status;
|
||||
char i_name[1]; /* Name of inode (variable) */
|
||||
};
|
||||
|
||||
#define FSNODE_SIZE(n) (sizeof(struct inode) + (n))
|
||||
#define FSNODE_SIZE(n) (sizeof(struct Vnode) + (n))
|
||||
|
||||
/* This is the underlying representation of an open file. A file
|
||||
* descriptor is an index into an array of such types. The type associates
|
||||
* the file descriptor to the file state and to a set of inode operations.
|
||||
* the file descriptor to the file state and to a set of vnode operations.
|
||||
*/
|
||||
|
||||
struct file
|
||||
{
|
||||
unsigned int f_magicnum; /* file magic number */
|
||||
int f_oflags; /* Open mode flags */
|
||||
FAR struct inode *f_inode; /* Driver interface */
|
||||
struct Vnode *f_vnode; /* Driver interface */
|
||||
loff_t f_pos; /* File position */
|
||||
unsigned long f_refcount; /* reference count */
|
||||
char *f_path; /* File fullpath */
|
||||
@@ -454,6 +435,8 @@ struct file
|
||||
const char *f_relpath; /* realpath */
|
||||
struct page_mapping *f_mapping; /* mapping file to memory */
|
||||
void *f_dir; /* DIR struct for iterate the directory if open a directory */
|
||||
const struct file_operations_vfs *ops;
|
||||
int fd;
|
||||
};
|
||||
|
||||
/* This defines a list of files indexed by the file descriptor */
|
||||
@@ -502,10 +485,10 @@ struct file_struct
|
||||
sem_t fs_sem; /* For thread safety */
|
||||
pid_t fs_holder; /* Holder of sem */
|
||||
int fs_counts; /* Number of times sem is held */
|
||||
FAR unsigned char *fs_bufstart; /* Pointer to start of buffer */
|
||||
FAR unsigned char *fs_bufend; /* Pointer to 1 past end of buffer */
|
||||
FAR unsigned char *fs_bufpos; /* Current position in buffer */
|
||||
FAR unsigned char *fs_bufread; /* Pointer to 1 past last buffered read char. */
|
||||
unsigned char *fs_bufstart; /* Pointer to start of buffer */
|
||||
unsigned char *fs_bufend; /* Pointer to 1 past end of buffer */
|
||||
unsigned char *fs_bufpos; /* Current position in buffer */
|
||||
unsigned char *fs_bufread; /* Pointer to 1 past last buffered read char. */
|
||||
#endif
|
||||
uint16_t fs_oflags; /* Open mode flags */
|
||||
uint8_t fs_flags; /* Stream flags */
|
||||
@@ -539,21 +522,21 @@ void fs_initialize(void);
|
||||
* Name: register_driver
|
||||
*
|
||||
* Description:
|
||||
* Register a character driver inode the pseudo file system.
|
||||
* Register a character driver vnode the pseudo file system.
|
||||
*
|
||||
* Input Parameters:
|
||||
* path - The path to the inode to create
|
||||
* path - The path to the vnode to create
|
||||
* fops - The file operations structure
|
||||
* mode - Access privileges (not used)
|
||||
* priv - Private, user data that will be associated with the inode.
|
||||
* priv - Private, user data that will be associated with the vnode.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero on success (with the inode point in 'inode'); A negated errno
|
||||
* Zero on success (with the vnode point in 'vnode'); A negated errno
|
||||
* value is returned on a failure (all error values returned by
|
||||
* inode_reserve):
|
||||
* vnode_reserve):
|
||||
*
|
||||
* EINVAL - 'path' is invalid for this operation
|
||||
* EEXIST - An inode already exists at 'path'
|
||||
* EEXIST - An vnode already exists at 'path'
|
||||
* ENOMEM - Failed to allocate in-memory resources for the operation
|
||||
*
|
||||
* Attention:
|
||||
@@ -565,15 +548,15 @@ void fs_initialize(void);
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int register_driver(FAR const char *path,
|
||||
FAR const struct file_operations_vfs *fops, mode_t mode,
|
||||
FAR void *priv);
|
||||
int register_driver(const char *path,
|
||||
const struct file_operations_vfs *fops, mode_t mode,
|
||||
void *priv);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: register_blockdriver
|
||||
*
|
||||
* Description:
|
||||
* Register a block driver inode the pseudo file system.
|
||||
* Register a block driver vnode the pseudo file system.
|
||||
*
|
||||
* Attention:
|
||||
* This function should be called after los_vfs_init has been called.
|
||||
@@ -583,38 +566,38 @@ int register_driver(FAR const char *path,
|
||||
* The bops must pointed the right functions, otherwise the system will crash when the device is being operated.
|
||||
*
|
||||
* Input Parameters:
|
||||
* path - The path to the inode to create
|
||||
* path - The path to the vnode to create
|
||||
* bops - The block driver operations structure
|
||||
* mode - Access privileges (not used)
|
||||
* priv - Private, user data that will be associated with the inode.
|
||||
* priv - Private, user data that will be associated with the vnode.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero on success (with the inode point in 'inode'); A negated errno
|
||||
* Zero on success (with the vnode point in 'vnode'); A negated errno
|
||||
* value is returned on a failure (all error values returned by
|
||||
* inode_reserve):
|
||||
* vnode_reserve):
|
||||
*
|
||||
* EINVAL - 'path' is invalid for this operation
|
||||
* EEXIST - An inode already exists at 'path'
|
||||
* EEXIST - An vnode already exists at 'path'
|
||||
* ENOMEM - Failed to allocate in-memory resources for the operation
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef CONFIG_DISABLE_MOUNTPOINT
|
||||
int register_blockdriver(FAR const char *path,
|
||||
FAR const struct block_operations *bops,
|
||||
mode_t mode, FAR void *priv);
|
||||
int register_blockdriver(const char *path,
|
||||
const struct block_operations *bops,
|
||||
mode_t mode, void *priv);
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: unregister_driver
|
||||
*
|
||||
* Description:
|
||||
* Remove the character driver inode at 'path' from the pseudo-file system
|
||||
* Remove the character driver vnode at 'path' from the pseudo-file system
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero on success (with the inode point in 'inode'); A negated errno
|
||||
* Zero on success (with the vnode point in 'vnode'); A negated errno
|
||||
* value is returned on a failure (all error values returned by
|
||||
* inode_reserve):
|
||||
* vnode_reserve):
|
||||
*
|
||||
* EBUSY - Resource is busy ,not permit for this operation.
|
||||
* ENOENT - 'path' is invalid for this operation.
|
||||
@@ -626,21 +609,21 @@ int register_blockdriver(FAR const char *path,
|
||||
* The block device node referred by parameter path must be really exist.
|
||||
****************************************************************************/
|
||||
|
||||
int unregister_driver(FAR const char *path);
|
||||
int unregister_driver(const char *path);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: unregister_blockdriver
|
||||
*
|
||||
* Description:
|
||||
* Remove the block driver inode at 'path' from the pseudo-file system
|
||||
* Remove the block driver vnode at 'path' from the pseudo-file system
|
||||
*
|
||||
* Input Parameters:
|
||||
* path - The path that the inode to be destroyed.
|
||||
* path - The path that the vnode to be destroyed.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero on success (with the inode point in 'inode'); A negated errno
|
||||
* Zero on success (with the vnode point in 'vnode'); A negated errno
|
||||
* value is returned on a failure (all error values returned by
|
||||
* inode_reserve):
|
||||
* vnode_reserve):
|
||||
*
|
||||
* EBUSY - Resource is busy ,not permit for this operation.
|
||||
* ENOENT - 'path' is invalid for this operation.
|
||||
@@ -653,7 +636,7 @@ int unregister_driver(FAR const char *path);
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int unregister_blockdriver(FAR const char *path);
|
||||
int unregister_blockdriver(const char *path);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: files_initlist
|
||||
@@ -664,7 +647,7 @@ int unregister_blockdriver(FAR const char *path);
|
||||
****************************************************************************/
|
||||
|
||||
#if CONFIG_NFILE_DESCRIPTORS > 0
|
||||
void files_initlist(FAR struct filelist *list);
|
||||
void files_initlist(struct filelist *list);
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
@@ -676,14 +659,14 @@ void files_initlist(FAR struct filelist *list);
|
||||
****************************************************************************/
|
||||
|
||||
#if CONFIG_NFILE_DESCRIPTORS > 0
|
||||
void files_releaselist(FAR struct filelist *list);
|
||||
void files_releaselist(struct filelist *list);
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: file_dup2
|
||||
*
|
||||
* Description:
|
||||
* Assign an inode to a specific files structure. This is the heart of
|
||||
* Assign an vnode to a specific files structure. This is the heart of
|
||||
* dup2.
|
||||
*
|
||||
* Equivalent to the non-standard fs_dupfd2() function except that it
|
||||
@@ -697,7 +680,7 @@ void files_releaselist(FAR struct filelist *list);
|
||||
****************************************************************************/
|
||||
|
||||
#if CONFIG_NFILE_DESCRIPTORS > 0
|
||||
int file_dup2(FAR struct file *filep1, FAR struct file *filep2);
|
||||
int file_dup2(struct file *filep1, struct file *filep2);
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
@@ -738,7 +721,7 @@ int fs_dupfd(int fd, int minfd);
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int file_dup(FAR struct file *filep, int minfd);
|
||||
int file_dup(struct file *filep, int minfd);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: fs_dupfd2 OR dup2
|
||||
@@ -768,49 +751,79 @@ int fs_dupfd2(int fd1, int fd2);
|
||||
* Name: open_blockdriver
|
||||
*
|
||||
* Description:
|
||||
* Return the inode of the block driver specified by 'pathname'
|
||||
* Return the vnode of the block driver specified by 'pathname'
|
||||
*
|
||||
* Input Parameters:
|
||||
* pathname - the full path to the block driver to be opened
|
||||
* mountflags - if MS_RDONLY is not set, then driver must support write
|
||||
* operations (see include/sys/mount.h)
|
||||
* ppinode - address of the location to return the inode reference
|
||||
* ppvnode - address of the location to return the vnode reference
|
||||
*
|
||||
* Returned Value:
|
||||
* Returns zero on success or a negated errno on failure:
|
||||
*
|
||||
* EINVAL - pathname or pinode is NULL
|
||||
* EINVAL - pathname or pvnode is NULL
|
||||
* ENOENT - No block driver of this name is registered
|
||||
* ENOTBLK - The inode associated with the pathname is not a block driver
|
||||
* ENOTBLK - The vnode associated with the pathname is not a block driver
|
||||
* EACCESS - The MS_RDONLY option was not set but this driver does not
|
||||
* support write access
|
||||
*
|
||||
* Aattention:
|
||||
* The parameter path must point a valid string, which end with the terminating null byte.
|
||||
* The total length of parameter path must less than the value defined by PATH_MAX.
|
||||
* The parameter ppinode must point a valid memory, which size must be enough for storing struct inode.
|
||||
* The parameter ppvnode must point a valid memory, which size must be enough for storing struct Vnode.
|
||||
|
||||
****************************************************************************/
|
||||
|
||||
#if CONFIG_NFILE_DESCRIPTORS > 0
|
||||
int open_blockdriver(FAR const char *pathname, int mountflags,
|
||||
FAR struct inode **ppinode);
|
||||
int open_blockdriver(const char *pathname, int mountflags,
|
||||
struct Vnode **ppvnode);
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: find_blockdriver
|
||||
*
|
||||
* Description:
|
||||
* Return the inode of the block driver specified by 'pathname'
|
||||
*
|
||||
* Input Parameters:
|
||||
* pathname - The full path to the block driver to be located
|
||||
* mountflags - If MS_RDONLY is not set, then driver must support write
|
||||
* operations (see include/sys/mount.h)
|
||||
* ppinode - Address of the location to return the inode reference
|
||||
*
|
||||
* Returned Value:
|
||||
* Returns zero on success or a negated errno on failure:
|
||||
*
|
||||
* ENOENT - No block driver of this name is registered
|
||||
* ENOTBLK - The inode associated with the pathname is not a block driver
|
||||
* EACCESS - The MS_RDONLY option was not set but this driver does not
|
||||
* support write access
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int find_blockdriver(const char *pathname, int mountflags,
|
||||
struct Vnode **vpp);
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
* Name: close_blockdriver
|
||||
*
|
||||
* Description:
|
||||
* Call the close method and release the inode
|
||||
* Call the close method and release the vnode
|
||||
*
|
||||
* Input Parameters:
|
||||
* inode - reference to the inode of a block driver opened by open_blockdriver
|
||||
* vnode - reference to the vnode of a block driver opened by open_blockdriver
|
||||
*
|
||||
* Returned Value:
|
||||
* Returns zero on success or a negated errno on failure:
|
||||
*
|
||||
* EINVAL - inode is NULL
|
||||
* ENOTBLK - The inode is not a block driver
|
||||
* EINVAL - vnode is NULL
|
||||
* ENOTBLK - The vnode is not a block driver
|
||||
*
|
||||
* Attention:
|
||||
* This function should be called after open_blockdriver has been called.
|
||||
@@ -818,7 +831,7 @@ int open_blockdriver(FAR const char *pathname, int mountflags,
|
||||
****************************************************************************/
|
||||
|
||||
#if CONFIG_NFILE_DESCRIPTORS > 0
|
||||
int close_blockdriver(FAR struct inode *inode);
|
||||
int close_blockdriver(struct Vnode *vnode);
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
@@ -865,7 +878,7 @@ int fs_ioctl(int fd, int req, unsigned long arg);
|
||||
|
||||
#if CONFIG_NFILE_STREAMS > 0
|
||||
struct tcb_s; /* Forward reference */
|
||||
FAR struct file_struct *fs_fdopen(int fd, int oflags);
|
||||
struct file_struct *fs_fdopen(int fd, int oflags);
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
@@ -878,7 +891,7 @@ FAR struct file_struct *fs_fdopen(int fd, int oflags);
|
||||
****************************************************************************/
|
||||
|
||||
#if CONFIG_NFILE_STREAMS > 0
|
||||
int lib_flushall(FAR struct streamlist *list);
|
||||
int lib_flushall(struct streamlist *list);
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
@@ -912,7 +925,7 @@ ssize_t lib_sendfile(int outfd, int infd, off_t *offset, size_t count);
|
||||
****************************************************************************/
|
||||
|
||||
#if CONFIG_NFILE_DESCRIPTORS > 0
|
||||
int fs_getfilep(int fd, FAR struct file **filep);
|
||||
int fs_getfilep(int fd, struct file **filep);
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
@@ -939,7 +952,7 @@ int fs_getfilep(int fd, FAR struct file **filep);
|
||||
****************************************************************************/
|
||||
|
||||
#if CONFIG_NFILE_DESCRIPTORS > 0
|
||||
ssize_t file_read(FAR struct file *filep, FAR void *buf, size_t nbytes);
|
||||
ssize_t file_read(struct file *filep, void *buf, size_t nbytes);
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
@@ -953,7 +966,7 @@ ssize_t file_read(FAR struct file *filep, FAR void *buf, size_t nbytes);
|
||||
****************************************************************************/
|
||||
|
||||
#if CONFIG_NFILE_DESCRIPTORS > 0
|
||||
ssize_t file_write(FAR struct file *filep, FAR const void *buf, size_t nbytes);
|
||||
ssize_t file_write(struct file *filep, const void *buf, size_t nbytes);
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
@@ -967,7 +980,7 @@ ssize_t file_write(FAR struct file *filep, FAR const void *buf, size_t nbytes);
|
||||
****************************************************************************/
|
||||
|
||||
#if CONFIG_NFILE_DESCRIPTORS > 0
|
||||
ssize_t file_pread(FAR struct file *filep, FAR void *buf, size_t nbytes,
|
||||
ssize_t file_pread(struct file *filep, void *buf, size_t nbytes,
|
||||
off_t offset);
|
||||
#endif
|
||||
|
||||
@@ -982,7 +995,7 @@ ssize_t file_pread(FAR struct file *filep, FAR void *buf, size_t nbytes,
|
||||
****************************************************************************/
|
||||
|
||||
#if CONFIG_NFILE_DESCRIPTORS > 0
|
||||
ssize_t file_pwrite(FAR struct file *filep, FAR const void *buf,
|
||||
ssize_t file_pwrite(struct file *filep, const void *buf,
|
||||
size_t nbytes, off_t offset);
|
||||
#endif
|
||||
|
||||
@@ -997,7 +1010,7 @@ ssize_t file_pwrite(FAR struct file *filep, FAR const void *buf,
|
||||
****************************************************************************/
|
||||
|
||||
#if CONFIG_NFILE_DESCRIPTORS > 0
|
||||
off_t file_seek(FAR struct file *filep, off_t offset, int whence);
|
||||
off_t file_seek(struct file *filep, off_t offset, int whence);
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
@@ -1011,7 +1024,7 @@ off_t file_seek(FAR struct file *filep, off_t offset, int whence);
|
||||
****************************************************************************/
|
||||
|
||||
#if CONFIG_NFILE_DESCRIPTORS > 0
|
||||
int file_fsync(FAR struct file *filep);
|
||||
int file_fsync(struct file *filep);
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
@@ -1034,7 +1047,7 @@ int file_fsync(FAR struct file *filep);
|
||||
****************************************************************************/
|
||||
|
||||
#if CONFIG_NFILE_DESCRIPTORS > 0
|
||||
int file_vfcntl(FAR struct file *filep, int cmd, va_list ap);
|
||||
int file_vfcntl(struct file *filep, int cmd, va_list ap);
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
@@ -1048,9 +1061,57 @@ int file_vfcntl(FAR struct file *filep, int cmd, va_list ap);
|
||||
****************************************************************************/
|
||||
|
||||
#if CONFIG_NFILE_DESCRIPTORS > 0
|
||||
off64_t file_seek64(FAR struct file *filep, off64_t offset, int whence);
|
||||
off64_t file_seek64(struct file *filep, off64_t offset, int whence);
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: files_allocate
|
||||
*
|
||||
* Description:
|
||||
* Allocate a struct files instance and associate it with an vnode instance.
|
||||
* Returns the file descriptor == index into the files array.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int files_allocate(struct Vnode *vnode, int oflags, off_t pos,void *priv, int minfd);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: files_close
|
||||
*
|
||||
* Description:
|
||||
* Close an vnode (if open)
|
||||
*
|
||||
* Assumuptions:
|
||||
* Caller holds the list semaphore because the file descriptor will be freed.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int files_close(int fd);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: files_release
|
||||
*
|
||||
* Assumuptions:
|
||||
* Similar to files_close(). Called only from open() logic on error
|
||||
* conditions.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void files_release(int fd);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: files_initialize
|
||||
*
|
||||
* Description:
|
||||
* This is called from the FS initialization logic to configure the files.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void weak_function files_initialize(void);
|
||||
|
||||
int vfs_normalize_path(const char *directory, const char *filename, char **pathname);
|
||||
int vfs_normalize_pathat(int fd, const char *filename, char **pathname);
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user