mirror of
https://github.com/apache/nuttx.git
synced 2026-05-22 22:20:01 +08:00
Squashed commit of the following:
fs: Add truncate() support for userfs
fs/unionfs: Add truncate() support to the unionfs
fs/tmpfs: Add ftruncate() support to tmpfs
syscall/: Add system call support for ftruncate()
net/route: Adding ftruncate() support eliminates an issue in file-based routing table management.
fs: Add basic framework to support truncate() and ftruncate(). The infrastructure is complete. Now, however, the actual implementation of ftruncate() will have to be done for each file system.
This commit is contained in:
@@ -1759,11 +1759,6 @@ o File system / Generic drivers (fs/, drivers/)
|
||||
intended for deeply embedded environments where there are
|
||||
not multiple users with varying levels of trust.
|
||||
|
||||
truncate - The standard way of setting a fixed file size.
|
||||
Often used with random access, data base files. There is no
|
||||
simple way of doing that now (other than just writing data
|
||||
to the file).
|
||||
|
||||
link, unlink, softlink, readlink - For symbolic links. Only
|
||||
the ROMFS file system currently supports hard and soft links,
|
||||
so this is not too important. The top-level, psuedo-file
|
||||
|
||||
+3
-1
@@ -1,7 +1,8 @@
|
||||
/****************************************************************************
|
||||
* fs/binfs/fs_binfs.c
|
||||
*
|
||||
* Copyright (C) 2011-2013, 2015, 2017 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2011-2013, 2015, 2017-2018 Gregory Nutt. All rights
|
||||
* reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -110,6 +111,7 @@ const struct mountpt_operations binfs_operations =
|
||||
NULL, /* sync */
|
||||
binfs_dup, /* dup */
|
||||
binfs_fstat, /* fstat */
|
||||
NULL, /* truncate */
|
||||
|
||||
binfs_opendir, /* opendir */
|
||||
NULL, /* closedir */
|
||||
|
||||
+3
-1
@@ -1,7 +1,8 @@
|
||||
/****************************************************************************
|
||||
* fs/fat/fs_fat32.c
|
||||
*
|
||||
* Copyright (C) 2007-2009, 2011-2015, 2017 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2007-2009, 2011-2015, 2017-2018 Gregory Nutt. All rights
|
||||
* reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* References:
|
||||
@@ -138,6 +139,7 @@ const struct mountpt_operations fat_operations =
|
||||
fat_sync, /* sync */
|
||||
fat_dup, /* dup */
|
||||
fat_fstat, /* fstat */
|
||||
NULL, /* truncate */
|
||||
|
||||
fat_opendir, /* opendir */
|
||||
NULL, /* closedir */
|
||||
|
||||
+2
-1
@@ -1,7 +1,7 @@
|
||||
/****************************************************************************
|
||||
* fs/nfs/nfs_vfsops.c
|
||||
*
|
||||
* Copyright (C) 2012-2013, 2015, 2017 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2012-2013, 2015, 2017-2018 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2012 Jose Pablo Rojas Vargas. All rights reserved.
|
||||
* Author: Jose Pablo Rojas Vargas <jrojas@nx-engineering.com>
|
||||
* Gregory Nutt <gnutt@nuttx.org>
|
||||
@@ -191,6 +191,7 @@ const struct mountpt_operations nfs_operations =
|
||||
NULL, /* sync */
|
||||
nfs_dup, /* dup */
|
||||
nfs_fstat, /* fstat */
|
||||
NULL, /* truncate */
|
||||
|
||||
nfs_opendir, /* opendir */
|
||||
NULL, /* closedir */
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
/****************************************************************************
|
||||
* fs/nxffs/nxffs_initialize.c
|
||||
*
|
||||
* Copyright (C) 2011, 2013, 2015, 2017 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2011, 2013, 2015, 2017-2018 Gregory Nutt. All rights
|
||||
* reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* References: Linux/Documentation/filesystems/romfs.txt
|
||||
@@ -74,6 +75,7 @@ const struct mountpt_operations nxffs_operations =
|
||||
NULL, /* sync -- No buffered data */
|
||||
nxffs_dup, /* dup */
|
||||
nxffs_fstat, /* fstat */
|
||||
NULL, /* truncate */
|
||||
|
||||
nxffs_opendir, /* opendir */
|
||||
NULL, /* closedir */
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/****************************************************************************
|
||||
* fs/procfs/fs_procfs.c
|
||||
*
|
||||
* Copyright (C) 2013-2017 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2013-2018 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -257,6 +257,7 @@ const struct mountpt_operations procfs_operations =
|
||||
NULL, /* sync */
|
||||
procfs_dup, /* dup */
|
||||
procfs_fstat, /* fstat */
|
||||
NULL, /* truncate */
|
||||
|
||||
procfs_opendir, /* opendir */
|
||||
procfs_closedir, /* closedir */
|
||||
|
||||
+3
-1
@@ -1,7 +1,8 @@
|
||||
/****************************************************************************
|
||||
* rm/romfs/fs_romfs.h
|
||||
*
|
||||
* Copyright (C) 2008-2009, 2011, 2017 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2008-2009, 2011, 2017-2018 Gregory Nutt. All rights
|
||||
* reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* References: Linux/Documentation/filesystems/romfs.txt
|
||||
@@ -122,6 +123,7 @@ const struct mountpt_operations romfs_operations =
|
||||
NULL, /* sync */
|
||||
romfs_dup, /* dup */
|
||||
romfs_fstat, /* fstat */
|
||||
NULL, /* truncate */
|
||||
|
||||
romfs_opendir, /* opendir */
|
||||
NULL, /* closedir */
|
||||
|
||||
@@ -149,6 +149,7 @@ const struct mountpt_operations smartfs_operations =
|
||||
smartfs_sync, /* sync */
|
||||
smartfs_dup, /* dup */
|
||||
smartfs_fstat, /* fstat */
|
||||
NULL, /* truncate */
|
||||
|
||||
smartfs_opendir, /* opendir */
|
||||
NULL, /* closedir */
|
||||
|
||||
+67
-4
@@ -1,7 +1,7 @@
|
||||
/****************************************************************************
|
||||
* fs/tmpfs/fs_tmpfs.c
|
||||
*
|
||||
* Copyright (C) 2015, 2017 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2015, 2017-2018 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -140,6 +140,7 @@ static off_t tmpfs_seek(FAR struct file *filep, off_t offset, int whence);
|
||||
static int tmpfs_ioctl(FAR struct file *filep, int cmd, unsigned long arg);
|
||||
static int tmpfs_dup(FAR const struct file *oldp, FAR struct file *newp);
|
||||
static int tmpfs_fstat(FAR const struct file *filep, FAR struct stat *buf);
|
||||
static int tmpfs_truncate(FAR struct file *filep, off_t length);
|
||||
|
||||
static int tmpfs_opendir(FAR struct inode *mountpt, FAR const char *relpath,
|
||||
FAR struct fs_dirent_s *dir);
|
||||
@@ -177,16 +178,21 @@ const struct mountpt_operations tmpfs_operations =
|
||||
tmpfs_write, /* write */
|
||||
tmpfs_seek, /* seek */
|
||||
tmpfs_ioctl, /* ioctl */
|
||||
|
||||
NULL, /* sync */
|
||||
tmpfs_dup, /* dup */
|
||||
tmpfs_fstat, /* fstat */
|
||||
tmpfs_truncate, /* truncate */
|
||||
|
||||
tmpfs_opendir, /* opendir */
|
||||
tmpfs_closedir, /* closedir */
|
||||
tmpfs_readdir, /* readdir */
|
||||
tmpfs_rewinddir, /* rewinddir */
|
||||
|
||||
tmpfs_bind, /* bind */
|
||||
tmpfs_unbind, /* unbind */
|
||||
tmpfs_statfs, /* statfs */
|
||||
|
||||
tmpfs_unlink, /* unlink */
|
||||
tmpfs_mkdir, /* mkdir */
|
||||
tmpfs_rmdir, /* rmdir */
|
||||
@@ -378,7 +384,7 @@ static int tmpfs_realloc_file(FAR struct tmpfs_file_s **tfo,
|
||||
size_t allocsize;
|
||||
size_t delta;
|
||||
|
||||
/* Check if the current allocation is sufficent */
|
||||
/* Check if the current allocation is sufficient */
|
||||
|
||||
objsize = SIZEOF_TMPFS_FILE(newsize);
|
||||
|
||||
@@ -1619,7 +1625,7 @@ static ssize_t tmpfs_write(FAR struct file *filep, FAR const char *buffer,
|
||||
|
||||
tmpfs_lock_file(tfo);
|
||||
|
||||
/* Handle attempts to read beyond the end of the file */
|
||||
/* Handle attempts to write beyond the end of the file */
|
||||
|
||||
startpos = filep->f_pos;
|
||||
nwritten = buflen;
|
||||
@@ -1691,7 +1697,7 @@ static off_t tmpfs_seek(FAR struct file *filep, off_t offset, int whence)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Attempts to set the position beyound the end of file will
|
||||
/* Attempts to set the position beyond the end of file will
|
||||
* work if the file is open for write access.
|
||||
*
|
||||
* REVISIT: This simple implementation has no per-open storage that
|
||||
@@ -1814,6 +1820,63 @@ static int tmpfs_fstat(FAR const struct file *filep, FAR struct stat *buf)
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: tmpfs_truncate
|
||||
****************************************************************************/
|
||||
|
||||
static int tmpfs_truncate(FAR struct file *filep, off_t length)
|
||||
{
|
||||
FAR struct tmpfs_file_s *tfo;
|
||||
size_t oldsize;
|
||||
int ret = OK;
|
||||
|
||||
finfo("filep: %p length: %ld\n", filep, (long)length);
|
||||
DEBUGASSERT(filep != NULL && length >= 0);
|
||||
|
||||
/* Recover our private data from the struct file instance */
|
||||
|
||||
tfo = filep->f_priv;
|
||||
|
||||
/* Get exclusive access to the file */
|
||||
|
||||
tmpfs_lock_file(tfo);
|
||||
|
||||
/* Get the old size of the file. Do nothing if the file size is not
|
||||
* changing.
|
||||
*/
|
||||
|
||||
oldsize = tfo->tfo_size;
|
||||
if (oldsize != length)
|
||||
{
|
||||
/* The size is changing.. up or down. Reallocate the file memory. */
|
||||
|
||||
ret = tmpfs_realloc_file(&tfo, (size_t)length);
|
||||
if (ret < 0)
|
||||
{
|
||||
goto errout_with_lock;
|
||||
}
|
||||
|
||||
filep->f_priv = tfo;
|
||||
|
||||
/* If the size has increased, then we need to zero the newly added
|
||||
* memory.
|
||||
*/
|
||||
|
||||
if (length > oldsize)
|
||||
{
|
||||
memset(&tfo->tfo_data[oldsize], 0, length - oldsize);
|
||||
}
|
||||
|
||||
ret = OK;
|
||||
}
|
||||
|
||||
/* Release the lock on the file */
|
||||
|
||||
errout_with_lock:
|
||||
tmpfs_unlock_file(tfo);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: tmpfs_opendir
|
||||
****************************************************************************/
|
||||
|
||||
+73
-20
@@ -1,7 +1,7 @@
|
||||
/****************************************************************************
|
||||
* fs/unionfs/fs_unionfs.c
|
||||
*
|
||||
* Copyright (C) 2015, 2017 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2015, 2017-2018 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -162,6 +162,7 @@ static int unionfs_dup(FAR const struct file *oldp,
|
||||
FAR struct file *newp);
|
||||
static int unionfs_fstat(FAR const struct file *filep,
|
||||
FAR struct stat *buf);
|
||||
static int unionfs_truncate(FAR struct file *filep, off_t length);
|
||||
|
||||
/* Operations on directories */
|
||||
|
||||
@@ -218,6 +219,7 @@ static const struct mountpt_operations g_unionfs_mops =
|
||||
unionfs_sync, /* sync */
|
||||
unionfs_dup, /* dup */
|
||||
unionfs_fstat, /* fstat */
|
||||
unionfs_truncate, /* truncate */
|
||||
|
||||
unionfs_opendir, /* opendir */
|
||||
unionfs_closedir, /* closedir */
|
||||
@@ -952,7 +954,7 @@ static int unionfs_close(FAR struct file *filep)
|
||||
|
||||
/* Perform the lower level close operation */
|
||||
|
||||
if (ops->close)
|
||||
if (ops->close != NULL)
|
||||
{
|
||||
ret = ops->close(&uf->uf_file);
|
||||
}
|
||||
@@ -1012,9 +1014,9 @@ static ssize_t unionfs_read(FAR struct file *filep, FAR char *buffer,
|
||||
DEBUGASSERT(um != NULL && um->um_node != NULL && um->um_node->u.i_mops != NULL);
|
||||
ops = um->um_node->u.i_mops;
|
||||
|
||||
/* Perform the lower level write operation */
|
||||
/* Perform the lower level read operation */
|
||||
|
||||
if (ops->read)
|
||||
if (ops->read != NULL)
|
||||
{
|
||||
ret = ops->read(&uf->uf_file, buffer, buflen);
|
||||
}
|
||||
@@ -1062,7 +1064,7 @@ static ssize_t unionfs_write(FAR struct file *filep, FAR const char *buffer,
|
||||
|
||||
/* Perform the lower level write operation */
|
||||
|
||||
if (ops->write)
|
||||
if (ops->write != NULL)
|
||||
{
|
||||
ret = ops->write(&uf->uf_file, buffer, buflen);
|
||||
}
|
||||
@@ -1109,7 +1111,7 @@ static off_t unionfs_seek(FAR struct file *filep, off_t offset, int whence)
|
||||
|
||||
/* Invoke the file seek method if available */
|
||||
|
||||
if (ops->seek)
|
||||
if (ops->seek != NULL)
|
||||
{
|
||||
offset = ops->seek(&uf->uf_file, offset, whence);
|
||||
}
|
||||
@@ -1185,7 +1187,7 @@ static int unionfs_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
|
||||
|
||||
/* Perform the lower level ioctl operation */
|
||||
|
||||
if (ops->ioctl)
|
||||
if (ops->ioctl != NULL)
|
||||
{
|
||||
ret = ops->ioctl(&uf->uf_file, cmd, arg);
|
||||
}
|
||||
@@ -1206,7 +1208,7 @@ static int unionfs_sync(FAR struct file *filep)
|
||||
FAR const struct mountpt_operations *ops;
|
||||
int ret = -EINVAL;
|
||||
|
||||
finfo("Entry\n");
|
||||
finfo("filep=%p\n", filep);
|
||||
|
||||
/* Recover the open file data from the struct file instance */
|
||||
|
||||
@@ -1232,7 +1234,7 @@ static int unionfs_sync(FAR struct file *filep)
|
||||
|
||||
/* Perform the lower level sync operation */
|
||||
|
||||
if (ops->sync)
|
||||
if (ops->sync != NULL)
|
||||
{
|
||||
ret = ops->sync(&uf->uf_file);
|
||||
}
|
||||
@@ -1254,7 +1256,7 @@ static int unionfs_dup(FAR const struct file *oldp, FAR struct file *newp)
|
||||
FAR const struct mountpt_operations *ops;
|
||||
int ret = -ENOMEM;
|
||||
|
||||
finfo("Entry\n");
|
||||
finfo("oldp=%p newp=%p\n", oldp, newp);
|
||||
|
||||
/* Recover the open file data from the struct file instance */
|
||||
|
||||
@@ -1293,7 +1295,7 @@ static int unionfs_dup(FAR const struct file *oldp, FAR struct file *newp)
|
||||
/* Then perform the lower lowel dup operation */
|
||||
|
||||
ret = OK;
|
||||
if (ops->dup)
|
||||
if (ops->dup != NULL)
|
||||
{
|
||||
ret = ops->dup(&oldpriv->uf_file, &newpriv->uf_file);
|
||||
if (ret < 0)
|
||||
@@ -1328,7 +1330,7 @@ static int unionfs_fstat(FAR const struct file *filep, FAR struct stat *buf)
|
||||
FAR const struct mountpt_operations *ops;
|
||||
int ret = -EPERM;
|
||||
|
||||
finfo("Entry\n");
|
||||
finfo("filep=%p buf=%p\n");
|
||||
|
||||
/* Recover the open file data from the struct file instance */
|
||||
|
||||
@@ -1354,7 +1356,7 @@ static int unionfs_fstat(FAR const struct file *filep, FAR struct stat *buf)
|
||||
|
||||
/* Perform the lower level write operation */
|
||||
|
||||
if (ops->fstat)
|
||||
if (ops->fstat != NULL)
|
||||
{
|
||||
ret = ops->fstat(&uf->uf_file, buf);
|
||||
}
|
||||
@@ -1363,6 +1365,57 @@ static int unionfs_fstat(FAR const struct file *filep, FAR struct stat *buf)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: unionfs_truncate
|
||||
*
|
||||
* Description:
|
||||
* Set the size of the file references by 'filep' to 'length'.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int unionfs_truncate(FAR struct file *filep, off_t length)
|
||||
{
|
||||
FAR struct unionfs_inode_s *ui;
|
||||
FAR struct unionfs_file_s *uf;
|
||||
FAR struct unionfs_mountpt_s *um;
|
||||
FAR const struct mountpt_operations *ops;
|
||||
int ret = -EPERM;
|
||||
|
||||
finfo("filep=%p length=%ld\n", filep, (long)length);
|
||||
|
||||
/* Recover the open file data from the struct file instance */
|
||||
|
||||
DEBUGASSERT(filep != NULL && filep->f_inode != NULL);
|
||||
ui = (FAR struct unionfs_inode_s *)filep->f_inode->i_private;
|
||||
|
||||
/* Get exclusive access to the file system data structures */
|
||||
|
||||
ret = unionfs_semtake(ui, false);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
DEBUGASSERT(ui != NULL && filep->f_priv != NULL);
|
||||
uf = (FAR struct unionfs_file_s *)filep->f_priv;
|
||||
|
||||
DEBUGASSERT(uf->uf_ndx == 0 || uf->uf_ndx == 1);
|
||||
um = &ui->ui_fs[uf->uf_ndx];
|
||||
|
||||
DEBUGASSERT(um != NULL && um->um_node != NULL && um->um_node->u.i_mops != NULL);
|
||||
ops = um->um_node->u.i_mops;
|
||||
|
||||
/* Perform the lower level write operation */
|
||||
|
||||
if (ops->truncate != NULL)
|
||||
{
|
||||
ret = ops->truncate(&uf->uf_file, length);
|
||||
}
|
||||
|
||||
unionfs_semgive(ui);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: unionfs_opendir
|
||||
****************************************************************************/
|
||||
@@ -1508,7 +1561,7 @@ static int unionfs_opendir(FAR struct inode *mountpt, FAR const char *relpath,
|
||||
errout_with_fs2open:
|
||||
ops = ui->ui_fs[1].um_node->u.i_mops;
|
||||
DEBUGASSERT(ops != NULL);
|
||||
if (ops->closedir)
|
||||
if (ops->closedir != NULL)
|
||||
{
|
||||
ret = ops->closedir(um->um_node, fu->fu_lower[1]);
|
||||
}
|
||||
@@ -1540,7 +1593,7 @@ static int unionfs_closedir(FAR struct inode *mountpt,
|
||||
int ret = OK;
|
||||
int i;
|
||||
|
||||
finfo("Entry\n");
|
||||
finfo("mountpt=%p dir=%p\n", mountpt, dir);
|
||||
|
||||
/* Recover the union file system data from the struct inode instance */
|
||||
|
||||
@@ -1569,7 +1622,7 @@ static int unionfs_closedir(FAR struct inode *mountpt,
|
||||
|
||||
/* Perform the lower level closedir operation */
|
||||
|
||||
if (ops->closedir)
|
||||
if (ops->closedir != NULL)
|
||||
{
|
||||
ret = ops->closedir(um->um_node, fu->fu_lower[i]);
|
||||
}
|
||||
@@ -1696,7 +1749,7 @@ static int unionfs_readdir(struct inode *mountpt, struct fs_dirent_s *dir)
|
||||
|
||||
/* Perform the lower level readdir operation */
|
||||
|
||||
if (ops->readdir)
|
||||
if (ops->readdir != NULL)
|
||||
{
|
||||
/* Loop if we discard duplicate directory entries in filey system 2 */
|
||||
|
||||
@@ -1873,7 +1926,7 @@ static int unionfs_rewinddir(struct inode *mountpt, struct fs_dirent_s *dir)
|
||||
FAR struct fs_unionfsdir_s *fu;
|
||||
int ret;
|
||||
|
||||
finfo("Entry\n");
|
||||
finfo("mountpt=%p dir=%p\n", mountpt, dir);
|
||||
|
||||
/* Recover the union file system data from the struct inode instance */
|
||||
|
||||
@@ -1937,7 +1990,7 @@ static int unionfs_unbind(FAR void *handle, FAR struct inode **blkdriver,
|
||||
{
|
||||
FAR struct unionfs_inode_s *ui;
|
||||
|
||||
finfo("Entry\n");
|
||||
finfo("handle=%p blkdriver=%p flags=%x\n", handle, blkdriver, flags);
|
||||
|
||||
/* Recover the union file system data from the struct inode instance */
|
||||
|
||||
@@ -1983,7 +2036,7 @@ static int unionfs_statfs(FAR struct inode *mountpt, FAR struct statfs *buf)
|
||||
uint32_t ratiob16;
|
||||
int ret;
|
||||
|
||||
finfo("Entry\n");
|
||||
finfo("mountpt=%p buf=%p\n", mountpt, buf);
|
||||
|
||||
/* Recover the union file system data from the struct inode instance */
|
||||
|
||||
|
||||
+82
-1
@@ -1,7 +1,7 @@
|
||||
/****************************************************************************
|
||||
* fs/userfs/fs_userfs.c
|
||||
*
|
||||
* Copyright (C) 2017 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2017-2018 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -118,6 +118,7 @@ static int userfs_sync(FAR struct file *filep);
|
||||
static int userfs_dup(FAR const struct file *oldp, FAR struct file *newp);
|
||||
static int userfs_fstat(FAR const struct file *filep,
|
||||
FAR struct stat *buf);
|
||||
static int userfs_truncate(FAR struct file *filep, off_t length);
|
||||
|
||||
static int userfs_opendir(FAR struct inode *mountpt,
|
||||
FAR const char *relpath, FAR struct fs_dirent_s *dir);
|
||||
@@ -167,6 +168,7 @@ const struct mountpt_operations userfs_operations =
|
||||
userfs_sync, /* sync */
|
||||
userfs_dup, /* dup */
|
||||
userfs_fstat, /* fstat */
|
||||
userfs_truncate, /* truncate */
|
||||
|
||||
userfs_opendir, /* opendir */
|
||||
userfs_closedir, /* closedir */
|
||||
@@ -909,6 +911,85 @@ static int userfs_fstat(FAR const struct file *filep, FAR struct stat *buf)
|
||||
return resp->ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: userfs_truncate
|
||||
*
|
||||
* Description:
|
||||
* Set the size of the regular file referred to by 'filep' to 'length'
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int userfs_truncate(FAR struct file *filep, off_t length)
|
||||
{
|
||||
FAR struct userfs_state_s *priv;
|
||||
FAR struct userfs_truncate_request_s *req;
|
||||
FAR struct userfs_truncate_response_s *resp;
|
||||
ssize_t nsent;
|
||||
ssize_t nrecvd;
|
||||
int ret;
|
||||
|
||||
DEBUGASSERT(filep != NULL &&
|
||||
filep->f_inode != NULL &&
|
||||
filep->f_inode->i_private != NULL);
|
||||
priv = filep->f_inode->i_private;
|
||||
|
||||
/* Get exclusive access */
|
||||
|
||||
ret = sem_wait(&priv->exclsem);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Construct and send the request to the server */
|
||||
|
||||
req = (FAR struct userfs_truncate_request_s *)priv->iobuffer;
|
||||
req->req = USERFS_REQ_FSTAT;
|
||||
req->openinfo = filep->f_priv;
|
||||
req->length = length;
|
||||
|
||||
nsent = psock_sendto(&priv->psock, priv->iobuffer,
|
||||
sizeof(struct userfs_truncate_request_s), 0,
|
||||
(FAR struct sockaddr *)&priv->server,
|
||||
sizeof(struct sockaddr_in));
|
||||
if (nsent < 0)
|
||||
{
|
||||
ferr("ERROR: psock_sendto failed: %d\n", (int)nsent);
|
||||
sem_post(&priv->exclsem);
|
||||
return (int)nsent;
|
||||
}
|
||||
|
||||
/* Then get the response from the server */
|
||||
|
||||
nrecvd = psock_recvfrom(&priv->psock, priv->iobuffer, IOBUFFER_SIZE(priv),
|
||||
0, NULL, NULL);
|
||||
sem_post(&priv->exclsem);
|
||||
|
||||
if (nrecvd < 0)
|
||||
{
|
||||
ferr("ERROR: psock_recvfrom failed: %d\n", (int)nrecvd);
|
||||
return (int)nrecvd;
|
||||
}
|
||||
|
||||
if (nrecvd != sizeof(struct userfs_truncate_response_s))
|
||||
{
|
||||
ferr("ERROR: Response size incorrect: %u\n", (unsigned int)nrecvd);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
resp = (FAR struct userfs_truncate_response_s *)priv->iobuffer;
|
||||
if (resp->resp != USERFS_RESP_FSTAT)
|
||||
{
|
||||
ferr("ERROR: Incorrect response: %u\n", resp->resp);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* Return the result of truncate operation */
|
||||
|
||||
DEBUGASSERT(buf != NULL);
|
||||
return resp->ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: userfs_opendir
|
||||
*
|
||||
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
############################################################################
|
||||
# fs/vfs/Make.defs
|
||||
#
|
||||
# Copyright (C) 2014-2015, 2017 Gregory Nutt. All rights reserved.
|
||||
# Copyright (C) 2014-2015, 2017-2018 Gregory Nutt. All rights reserved.
|
||||
# Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
@@ -79,7 +79,7 @@ CSRCS += fs_rmdir.c fs_statfs.c fs_stat.c fs_select.c fs_unlink.c fs_write.c
|
||||
# Certain interfaces are not available if there is no mountpoint support
|
||||
|
||||
ifneq ($(CONFIG_DISABLE_MOUNTPOINT),y)
|
||||
CSRCS += fs_fsync.c
|
||||
CSRCS += fs_fsync.c fs_truncate.c
|
||||
endif
|
||||
|
||||
# Support for positional file access
|
||||
|
||||
@@ -0,0 +1,200 @@
|
||||
/****************************************************************************
|
||||
* fs/vfs/fs_truncate.c
|
||||
*
|
||||
* Copyright (C) 2018 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <nuttx/fs/fs.h>
|
||||
|
||||
#include "inode/inode.h"
|
||||
|
||||
#ifndef CONFIG_DISABLE_MOUNTPOINT
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: file_truncate
|
||||
*
|
||||
* Description:
|
||||
* Equivalent to the standard ftruncate() function except that is accepts
|
||||
* a struct file instance instead of a file descriptor and it does not set
|
||||
* the errno variable.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int file_truncate(FAR struct file *filep, off_t length)
|
||||
{
|
||||
struct inode *inode;
|
||||
|
||||
/* Was this file opened for write access? */
|
||||
|
||||
if ((filep->f_oflags & O_WROK) == 0)
|
||||
{
|
||||
fwarn("WARNING: Cannot truncate a file opened read-only\n");
|
||||
return -EBADF;
|
||||
}
|
||||
|
||||
/* Is this inode 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 == NULL || !INODE_IS_MOUNTPT(inode) || inode->u.i_mops == NULL)
|
||||
{
|
||||
fwarn("WARNING: Not a (regular) file on a mounted file system.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* A NULL write() method is an indicator of a read-only file system (but
|
||||
* possible not the only indicator)
|
||||
*/
|
||||
|
||||
if (inode->u.i_mops->write == NULL)
|
||||
{
|
||||
fwarn("WARNING: File system is read-only\n");
|
||||
return -EROFS;
|
||||
}
|
||||
|
||||
/* Does the file system support the truncate method? It should if it is
|
||||
* a write-able file system.
|
||||
*/
|
||||
|
||||
if (inode->u.i_mops->truncate == NULL)
|
||||
{
|
||||
fwarn("WARNING: File system does not support the truncate() method\n");
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
/* Yes, then tell the file system to truncate this file */
|
||||
|
||||
return inode->u.i_mops->truncate(filep, length);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* 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
|
||||
* discarded. If it was previously shorter than length, it is unspecified
|
||||
* whether the file is changed or its size increased. If the file is
|
||||
* extended, the extended area appears as if it were zero-filled. If fd
|
||||
* references a shared memory object, ftruncate() sets the size of the
|
||||
* shared memory object to length. If the file is not a regular file or
|
||||
* a shared memory object, the result is unspecified.
|
||||
|
||||
* With ftruncate(), the file must be open for writing; for truncate(),
|
||||
* the process must have write permission for the file.
|
||||
*
|
||||
* ftruncate() does not modify the file offset for any open file
|
||||
* descriptions associated with the file.
|
||||
*
|
||||
* Input Parameters:
|
||||
* fd - A reference to an open, regular file or shared memory object
|
||||
* to be truncated.
|
||||
* length - The new length of the file or shared memory object.
|
||||
*
|
||||
* Returned Value:
|
||||
* Upon successful completion, ftruncate() return 0s. Otherwise a -1 is
|
||||
* returned, and errno is set to indicate the error.
|
||||
*
|
||||
* EINTR
|
||||
* - A signal was caught during execution.
|
||||
* EINVAL
|
||||
* - The length argument was less than 0.
|
||||
* EFBIG or EINVAL
|
||||
* - The length argument was greater than the maximum file size.
|
||||
* EIO
|
||||
* - An I/O error occurred while reading from or writing to a file
|
||||
* system.
|
||||
* EBADF or EINVAL
|
||||
* - the fd argument is not a file descriptor open for writing.
|
||||
* EFBIG
|
||||
* - The file is a regular file and length is greater than the offset
|
||||
* maximum established in the open file description associated with
|
||||
* fd.
|
||||
* EINVAL
|
||||
* - The fd argument references a file that was opened without write
|
||||
* permission.
|
||||
* EROFS
|
||||
* - The named file resides on a read-only file system.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int ftruncate(int fd, off_t length)
|
||||
{
|
||||
FAR struct file *filep;
|
||||
int ret;
|
||||
|
||||
/* Get the file structure corresponding to the file descriptor. */
|
||||
|
||||
ret = fs_getfilep(fd, &filep);
|
||||
if (ret < 0)
|
||||
{
|
||||
ferr("ERROR: Could no get file structure: %d\n", ret);
|
||||
goto errout;
|
||||
}
|
||||
|
||||
DEBUGASSERT(filep != NULL);
|
||||
|
||||
/* Perform the truncate operation */
|
||||
|
||||
ret = file_truncate(filep, length);
|
||||
if (ret >= 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
fwarn("WARNING: file_truncate() failed: %d\n", ret);
|
||||
|
||||
errout:
|
||||
set_errno(-ret);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
#endif /* !CONFIG_DISABLE_MOUNTPOINT */
|
||||
+26
-11
@@ -1,7 +1,7 @@
|
||||
/****************************************************************************
|
||||
* include/nuttx/fs/fs.h
|
||||
*
|
||||
* Copyright (C) 2007-2009, 2011-2013, 2015-2017 Gregory Nutt. All rights
|
||||
* Copyright (C) 2007-2009, 2011-2013, 2015-2018 Gregory Nutt. All rights
|
||||
* reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
@@ -280,7 +280,7 @@ struct mountpt_operations
|
||||
int oflags, mode_t mode);
|
||||
|
||||
/* The following methods must be identical in signature and position
|
||||
* because the struct file_operations and struct mountp_operations are
|
||||
* because the struct file_operations and struct mountpt_operations are
|
||||
* treated like unions.
|
||||
*/
|
||||
|
||||
@@ -301,6 +301,7 @@ struct mountpt_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 */
|
||||
|
||||
@@ -370,7 +371,7 @@ union inode_ops_u
|
||||
#endif
|
||||
};
|
||||
|
||||
/* This structure represents one inode in the Nuttx pseudo-file system */
|
||||
/* This structure represents one inode in the NuttX pseudo-file system */
|
||||
|
||||
struct inode
|
||||
{
|
||||
@@ -416,10 +417,10 @@ struct filelist
|
||||
*
|
||||
* When buffering us used, the following described the usage of the I/O buffer.
|
||||
* The buffer can be used for reading or writing -- but not both at the same time.
|
||||
* An fflush is implied between each change in directionof access.
|
||||
* An fflush is implied between each change in direction of access.
|
||||
*
|
||||
* The field fs_bufread determines whether the buffer is being used for reading or
|
||||
* for writing as fillows:
|
||||
* for writing as follows:
|
||||
*
|
||||
* BUFFER
|
||||
* +----------------------+ <- fs_bufstart Points to the beginning of the buffer.
|
||||
@@ -431,7 +432,7 @@ struct filelist
|
||||
* | | RD: Points to next char to return
|
||||
* +----------------------+
|
||||
* | WR: Available | <- fs_bufread Top+1 of buffered read data
|
||||
* | RD: Available | WR: =bufstart buffer used for writing.
|
||||
* | RD: Available | WR: bufstart buffer used for writing.
|
||||
* | | RD: Pointer to last buffered read char+1
|
||||
* +----------------------+
|
||||
* <- fs_bufend Points to end end of the buffer+1
|
||||
@@ -498,7 +499,7 @@ void fs_initialize(void);
|
||||
* Input parameters:
|
||||
* path - The path to the inode to create
|
||||
* fops - The file operations structure
|
||||
* mode - inmode priviledges (not used)
|
||||
* mode - inmode privileges (not used)
|
||||
* priv - Private, user data that will be associated with the inode.
|
||||
*
|
||||
* Returned Value:
|
||||
@@ -525,7 +526,7 @@ int register_driver(FAR const char *path,
|
||||
* Input parameters:
|
||||
* path - The path to the inode to create
|
||||
* bops - The block driver operations structure
|
||||
* mode - inmode priviledges (not used)
|
||||
* mode - inmode privileges (not used)
|
||||
* priv - Private, user data that will be associated with the inode.
|
||||
*
|
||||
* Returned Value:
|
||||
@@ -624,7 +625,7 @@ int file_dup2(FAR struct file *filep1, FAR struct file *filep2);
|
||||
* Name: fs_dupfd OR dup
|
||||
*
|
||||
* Description:
|
||||
* Clone a file descriptor 'fd' to an arbitray descriptor number (any value
|
||||
* Clone a file descriptor 'fd' to an arbitrary descriptor number (any value
|
||||
* greater than or equal to 'minfd'). If socket descriptors are
|
||||
* implemented, then this is called by dup() for the case of file
|
||||
* descriptors. If socket descriptors are not implemented, then this
|
||||
@@ -670,7 +671,7 @@ int file_dup(FAR struct file *filep, int minfd);
|
||||
* then this function IS dup2().
|
||||
*
|
||||
* This alternative naming is used when dup2 could operate on both file and
|
||||
* socket descritors to avoid drawing unused socket support into the link.
|
||||
* socket descriptors to avoid drawing unused socket support into the link.
|
||||
*
|
||||
* Returned Value:
|
||||
* fs_dupfd2 is sometimes an OS internal function and sometimes is a direct
|
||||
@@ -1021,10 +1022,24 @@ off_t file_seek(FAR struct file *filep, off_t offset, int whence);
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#if CONFIG_NFILE_DESCRIPTORS > 0
|
||||
#if CONFIG_NFILE_DESCRIPTORS > 0 && !defined(CONFIG_DISABLE_MOUNTPOINT)
|
||||
int file_fsync(FAR struct file *filep);
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: file_truncate
|
||||
*
|
||||
* Description:
|
||||
* Equivalent to the standard ftruncate() function except that is accepts
|
||||
* a struct file instance instead of a file descriptor and it does not set
|
||||
* the errno variable.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#if CONFIG_NFILE_DESCRIPTORS > 0 && !defined(CONFIG_DISABLE_MOUNTPOINT)
|
||||
int file_truncate(FAR struct file *filep, off_t length);
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: file_ioctl
|
||||
*
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/****************************************************************************
|
||||
* include/nuttx/fs/userfs.h
|
||||
*
|
||||
* Copyright (C) 2017 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2017-2018 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -140,6 +140,7 @@ enum userfs_req_e
|
||||
USERFS_REQ_SYNC,
|
||||
USERFS_REQ_DUP,
|
||||
USERFS_REQ_FSTAT,
|
||||
USERFS_REQ_TRUNCATE,
|
||||
USERFS_REQ_OPENDIR,
|
||||
USERFS_REQ_CLOSEDIR,
|
||||
USERFS_REQ_READDIR,
|
||||
@@ -216,6 +217,7 @@ struct userfs_operations_s
|
||||
int (*dup)(FAR void *volinfo, FAR void *oldinfo, FAR void **newinfo);
|
||||
int (*fstat)(FAR void *volinfo, FAR void *openinfo,
|
||||
FAR struct stat *buf);
|
||||
int (*truncate)(FAR void *volinfo, FAR void *openinfo, off_t length);
|
||||
int (*opendir)(FAR void *volinfo, FAR const char *relpath,
|
||||
FAR void **dir);
|
||||
int (*closedir)(FAR void *volinfo, FAR void *dir);
|
||||
@@ -355,7 +357,7 @@ struct userfs_dup_response_s
|
||||
struct userfs_fstat_request_s
|
||||
{
|
||||
uint8_t req; /* Must be USERFS_REQ_FSTAT */
|
||||
FAR void *openinfo; /* Open file info for the dup'ed file */
|
||||
FAR void *openinfo; /* Open file info as returned by open() */
|
||||
};
|
||||
|
||||
struct userfs_fstat_response_s
|
||||
@@ -365,6 +367,19 @@ struct userfs_fstat_response_s
|
||||
FAR struct stat buf; /* Returned file system status */
|
||||
};
|
||||
|
||||
struct userfs_truncate_request_s
|
||||
{
|
||||
uint8_t req; /* Must be USERFS_REQ_TRUNCATE */
|
||||
FAR void *openinfo; /* Open file info as returned by open() */
|
||||
off_t length; /* New length of the file */
|
||||
};
|
||||
|
||||
struct userfs_truncate_response_s
|
||||
{
|
||||
uint8_t resp; /* Must be USERFS_RESP_FSTAT */
|
||||
int ret; /* Result of the operation */
|
||||
};
|
||||
|
||||
struct userfs_opendir_request_s
|
||||
{
|
||||
uint8_t req; /* Must be USERFS_REQ_OPENDIR */
|
||||
|
||||
@@ -383,12 +383,13 @@
|
||||
# define SYS_mount (__SYS_mountpoint+0)
|
||||
# endif
|
||||
# define SYS_fsync (__SYS_mountpoint+1)
|
||||
# define SYS_mkdir (__SYS_mountpoint+2)
|
||||
# define SYS_rename (__SYS_mountpoint+3)
|
||||
# define SYS_rmdir (__SYS_mountpoint+4)
|
||||
# define SYS_umount2 (__SYS_mountpoint+5)
|
||||
# define SYS_unlink (__SYS_mountpoint+6)
|
||||
# define __SYS_shm (__SYS_mountpoint+7)
|
||||
# define SYS_ftruncate (__SYS_mountpoint+2)
|
||||
# define SYS_mkdir (__SYS_mountpoint+3)
|
||||
# define SYS_rename (__SYS_mountpoint+4)
|
||||
# define SYS_rmdir (__SYS_mountpoint+5)
|
||||
# define SYS_umount2 (__SYS_mountpoint+6)
|
||||
# define SYS_unlink (__SYS_mountpoint+7)
|
||||
# define __SYS_shm (__SYS_mountpoint+8)
|
||||
# else
|
||||
# define __SYS_shm __SYS_mountpoint
|
||||
# endif
|
||||
|
||||
+3
-1
@@ -1,7 +1,7 @@
|
||||
/****************************************************************************
|
||||
* include/unistd.h
|
||||
*
|
||||
* Copyright (C) 2007-2009, 2013-2014, 2016-2017 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2007-2009, 2013-2014, 2016-2018 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -164,6 +164,7 @@ ssize_t read(int fd, FAR void *buf, size_t nbytes);
|
||||
ssize_t write(int fd, FAR const void *buf, size_t nbytes);
|
||||
ssize_t pread(int fd, FAR void *buf, size_t nbytes, off_t offset);
|
||||
ssize_t pwrite(int fd, FAR const void *buf, size_t nbytes, off_t offset);
|
||||
int ftruncate(int fd, off_t length);
|
||||
|
||||
/* Check if a file descriptor corresponds to a terminal I/O file */
|
||||
|
||||
@@ -190,6 +191,7 @@ FAR char *getcwd(FAR char *buf, size_t size);
|
||||
int access(FAR const char *path, int amode);
|
||||
int rmdir(FAR const char *pathname);
|
||||
int unlink(FAR const char *pathname);
|
||||
int truncate(FAR const char *path, off_t length);
|
||||
|
||||
#ifdef CONFIG_PSEUDOFS_SOFTLINKS
|
||||
int link(FAR const char *path1, FAR const char *path2);
|
||||
|
||||
@@ -47,6 +47,10 @@ ifeq ($(CONFIG_LIBC_EXECFUNCS),y)
|
||||
CSRCS += lib_execl.c
|
||||
endif
|
||||
|
||||
ifneq ($(CONFIG_DISABLE_MOUNTPOINTS),y)
|
||||
CSRCS += lib_truncate.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_PIPES),y)
|
||||
CSRCS += lib_pipe.c
|
||||
endif
|
||||
|
||||
@@ -0,0 +1,134 @@
|
||||
/****************************************************************************
|
||||
* libc/unistd/lib_truncate.c
|
||||
*
|
||||
* Copyright (C) 2018 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
|
||||
#ifndef CONFIG_DISABLE_MOUNTPOINT
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: truncate
|
||||
*
|
||||
* Description:
|
||||
* The truncate() function causes the regular file named by path to have
|
||||
* a size of length bytes.
|
||||
*
|
||||
* If the file previously was larger than length, the extra data is
|
||||
* discarded. If it was previously shorter than length, it is unspecified
|
||||
* whether the file is changed or its size increased. If the file is
|
||||
* extended, the extended area appears as if it were zero-filled.
|
||||
|
||||
* With truncate(), the file must be open for writing; for truncate(),
|
||||
* the process must have write permission for the file.
|
||||
*
|
||||
* truncate() does not modify the file offset for any open file
|
||||
* descriptions associated with the file.
|
||||
*
|
||||
* Input Parameters:
|
||||
* path - The path to the regular file to be truncated.
|
||||
* length - The new length of the regular file.
|
||||
*
|
||||
* Returned Value:
|
||||
* Upon successful completion, truncate() return 0s. Otherwise a -1 is
|
||||
* returned, and errno is set to indicate the error.
|
||||
|
||||
* EINTR
|
||||
* - A signal was caught during execution.
|
||||
* EINVAL
|
||||
* - The length argument was less than 0.
|
||||
* EFBIG or EINVAL
|
||||
* - The length argument was greater than the maximum file size.
|
||||
* EIO
|
||||
* - An I/O error occurred while reading from or writing to a file
|
||||
* system.
|
||||
* EACCES
|
||||
* - A component of the path prefix denies search permission, or write
|
||||
* permission is denied on the file.
|
||||
* EISDIR
|
||||
* - The named file is a directory.
|
||||
* ELOOP
|
||||
* - Too many symbolic links were encountered in resolving path.
|
||||
* ENAMETOOLONG
|
||||
* - The length of the specified pathname exceeds PATH_MAX bytes, or
|
||||
* the length of a component of the pathname exceeds NAME_MAX bytes.
|
||||
* ENOENT
|
||||
* - A component of path does not name an existing file or path is an
|
||||
* empty string.
|
||||
* ENOTDIR
|
||||
* - A component of the path prefix of path is not a directory.
|
||||
* EROFS
|
||||
* - he named file resides on a read-only file system.
|
||||
* ENAMETOOLONG
|
||||
* - Pathname resolution of a symbolic link produced an intermediate
|
||||
* result whose length exceeds PATH_MAX.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int truncate(FAR const char *path, off_t length)
|
||||
{
|
||||
int fd;
|
||||
int ret;
|
||||
|
||||
DEBUGASSERT(path != NULL && length >= 0);
|
||||
|
||||
/* Open the regular file at 'path' for write-only access */
|
||||
|
||||
fd = open(path, O_WRONLY);
|
||||
if (fd < 0)
|
||||
{
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/* Then let ftruncate() do the work */
|
||||
|
||||
ret = ftruncate(fd, length);
|
||||
|
||||
close(fd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* !CONFIG_DISABLE_MOUNTPOINT */
|
||||
@@ -428,6 +428,34 @@ static inline int userfs_fstat_dispatch(FAR struct userfs_info_s *info,
|
||||
return nsent < 0 ? nsent : OK;
|
||||
}
|
||||
|
||||
static inline int userfs_truncate_dispatch(FAR struct userfs_info_s *info,
|
||||
FAR struct userfs_truncate_request_s *req, size_t reqlen)
|
||||
{
|
||||
struct userfs_truncate_response_s resp;
|
||||
ssize_t nsent;
|
||||
|
||||
/* Verify the request size */
|
||||
|
||||
if (reqlen != sizeof(struct userfs_truncate_request_s))
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Dispatch the request */
|
||||
|
||||
DEBUGASSERT(info->userops != NULL && info->userops->truncate != NULL);
|
||||
resp.ret = info->userops->truncate(info->volinfo, req->openinfo, req->length);
|
||||
|
||||
/* Send the response */
|
||||
|
||||
resp.resp = USERFS_RESP_FSTAT;
|
||||
nsent = sendto(info->sockfd, &resp,
|
||||
sizeof(struct userfs_truncate_response_s),
|
||||
0, (FAR struct sockaddr *)&info->client,
|
||||
sizeof(struct sockaddr_in));
|
||||
return nsent < 0 ? nsent : OK;
|
||||
}
|
||||
|
||||
static inline int userfs_opendir_dispatch(FAR struct userfs_info_s *info,
|
||||
FAR struct userfs_opendir_request_s *req, size_t reqlen)
|
||||
{
|
||||
@@ -1035,6 +1063,11 @@ int userfs_run(FAR const char *mountpt,
|
||||
(FAR struct userfs_fstat_request_s *)info->iobuffer, nread);
|
||||
break;
|
||||
|
||||
case USERFS_REQ_TRUNCATE:
|
||||
ret = userfs_truncate_dispatch(info,
|
||||
(FAR struct userfs_truncate_request_s *)info->iobuffer, nread);
|
||||
break;
|
||||
|
||||
case USERFS_REQ_OPENDIR:
|
||||
ret = userfs_opendir_dispatch(info,
|
||||
(FAR struct userfs_opendir_request_s *)info->iobuffer, nread);
|
||||
|
||||
@@ -42,18 +42,6 @@ config ROUTE_IPv4_FILEROUTE
|
||||
---help---
|
||||
Select to used a IPv4 routing table in a file in a mounted file system.
|
||||
|
||||
REVISIT: There is a problem with the current design. NuttX does not
|
||||
currently support truncate(). Therefore, it is not possible to delete
|
||||
entries from the routing table file.
|
||||
|
||||
In this current implementation, that leaves the last entry intact at
|
||||
the end of the file. An alternative design might include a tag on
|
||||
each record to indicate if the record is valid or not. That would work
|
||||
but would add complexity to the other routing table functions.
|
||||
|
||||
The existing 'delroute' implementation is available for testing purpose
|
||||
only if CONFIG_EXPERIMENTAL=y.
|
||||
|
||||
endchoice # IPv4 routing table
|
||||
|
||||
config ROUTE_MAX_IPv4_RAMROUTES
|
||||
@@ -111,18 +99,6 @@ config ROUTE_IPv6_FILEROUTE
|
||||
---help---
|
||||
Select to use a IPv6 routing table in a file in a mounted file system.
|
||||
|
||||
REVISIT: There is a problem with the current design. NuttX does not
|
||||
currently support truncate(). Therefore, it is not possible to delete
|
||||
entries from the routing table file.
|
||||
|
||||
In this current implementation, that leaves the last entry intact at
|
||||
the end of the file. An alternative design might include a tag on
|
||||
each record to indicate if the record is valid or not. That would work
|
||||
but would add complexity to the other routing table functions.
|
||||
|
||||
The existing 'delroute' implementation is available for testing purpose
|
||||
only if CONFIG_EXPERIMENTAL=y.
|
||||
|
||||
endchoice # IPv6 routing table
|
||||
|
||||
config ROUTE_MAX_IPv6_RAMROUTES
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/****************************************************************************
|
||||
* net/route/net_del_fileroute.c
|
||||
*
|
||||
* Copyright (C) 2017 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2017-2018 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -40,6 +40,7 @@
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
@@ -56,26 +57,6 @@
|
||||
|
||||
#if defined(CONFIG_ROUTE_IPv4_FILEROUTE) || defined(CONFIG_ROUTE_IPv6_FILEROUTE)
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/* REVISIT: There is a problem with this design. NuttX does not currently
|
||||
* support truncate(). Therefore, it is not possible to delete entries from
|
||||
* the routing table file.
|
||||
*
|
||||
* In this current implementation, that leaves the last entry intact at the
|
||||
* end of the file. An alternative design might include a tag on each
|
||||
* record to indicate if the record is valid or not. That would work but
|
||||
* would add complexity to the other routing table functions.
|
||||
*
|
||||
* The existing implementation is available only if CONFIG_EXPERIMENTAL=y.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_EXPERIMENTAL
|
||||
# warning The implementation of delroute is incomplete
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
****************************************************************************/
|
||||
@@ -117,7 +98,6 @@ struct route_match_ipv6_s
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_EXPERIMENTAL
|
||||
#ifdef CONFIG_ROUTE_IPv4_FILEROUTE
|
||||
static int net_match_ipv4(FAR struct net_route_ipv4_s *route, FAR void *arg)
|
||||
{
|
||||
@@ -187,7 +167,6 @@ static int net_match_ipv6(FAR struct net_route_ipv6_s *route, FAR void *arg)
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
#endif /* CONFIG_EXPERIMENTAL */
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
@@ -209,10 +188,10 @@ static int net_match_ipv6(FAR struct net_route_ipv6_s *route, FAR void *arg)
|
||||
#ifdef CONFIG_ROUTE_IPv4_FILEROUTE
|
||||
int net_delroute_ipv4(in_addr_t target, in_addr_t netmask)
|
||||
{
|
||||
#ifdef CONFIG_EXPERIMENTAL
|
||||
struct route_match_ipv4_s match;
|
||||
struct net_route_ipv4_s route;
|
||||
struct file fshandle;
|
||||
off_t filesize;
|
||||
ssize_t nwritten;
|
||||
ssize_t nread;
|
||||
off_t pos;
|
||||
@@ -231,7 +210,7 @@ int net_delroute_ipv4(in_addr_t target, in_addr_t netmask)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Get the size of the routing table entry (in entries) */
|
||||
/* Get the size of the routing table (in entries) */
|
||||
|
||||
nentries = net_routesize_ipv4();
|
||||
if (nentries < 0)
|
||||
@@ -312,7 +291,7 @@ int net_delroute_ipv4(in_addr_t target, in_addr_t netmask)
|
||||
}
|
||||
else if (nread == 0)
|
||||
{
|
||||
nerr("ERROR: Undexpected end of file\n");
|
||||
nerr("ERROR: Unexpected end of file\n");
|
||||
ret = -EINVAL;
|
||||
goto errout_with_fshandle;
|
||||
}
|
||||
@@ -341,29 +320,26 @@ int net_delroute_ipv4(in_addr_t target, in_addr_t netmask)
|
||||
/* Now truncate the one duplicate entry at the end of the file. This may
|
||||
* result in a zero length file.
|
||||
*/
|
||||
#warning Missing logic
|
||||
|
||||
ret = OK;
|
||||
filesize = (nentries - 1) * sizeof(struct net_route_ipv4_s);
|
||||
ret = file_truncate(&fshandle, filesize);
|
||||
|
||||
errout_with_fshandle:
|
||||
(void)net_closeroute_ipv4(&fshandle);
|
||||
(void)net_closeroute_ipv4(&fshandle)S;
|
||||
|
||||
errout_with_lock:
|
||||
(void)net_unlockroute_ipv4();
|
||||
return ret;
|
||||
#else
|
||||
return -ENOSYS;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ROUTE_IPv6_FILEROUTE
|
||||
int net_delroute_ipv6(net_ipv6addr_t target, net_ipv6addr_t netmask)
|
||||
{
|
||||
#ifdef CONFIG_EXPERIMENTAL
|
||||
struct route_match_ipv6_s match;
|
||||
struct net_route_ipv6_s route;
|
||||
struct file fshandle;
|
||||
off_t filesize;
|
||||
ssize_t nwritten;
|
||||
ssize_t nread;
|
||||
off_t pos;
|
||||
@@ -382,7 +358,7 @@ int net_delroute_ipv6(net_ipv6addr_t target, net_ipv6addr_t netmask)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Get the size of the routing table entry (in entries) */
|
||||
/* Get the size of the routing table (in entries) */
|
||||
|
||||
nentries = net_routesize_ipv6();
|
||||
if (nentries < 0)
|
||||
@@ -464,7 +440,7 @@ int net_delroute_ipv6(net_ipv6addr_t target, net_ipv6addr_t netmask)
|
||||
}
|
||||
else if (nread == 0)
|
||||
{
|
||||
nerr("ERROR: Undexpected end of file\n");
|
||||
nerr("ERROR: Unexpected end of file\n");
|
||||
ret = -EINVAL;
|
||||
goto errout_with_fshandle;
|
||||
}
|
||||
@@ -493,9 +469,9 @@ int net_delroute_ipv6(net_ipv6addr_t target, net_ipv6addr_t netmask)
|
||||
/* Now truncate the one duplicate entry at the end of the file. This may
|
||||
* result in a zero length file.
|
||||
*/
|
||||
#warning Missing logic
|
||||
|
||||
ret = OK;
|
||||
filesize = (nentries - 1) * sizeof(struct net_route_ipv6_s);
|
||||
ret = file_truncate(&fshandle, filesize);
|
||||
|
||||
errout_with_fshandle:
|
||||
(void)net_closeroute_ipv6(&fshandle);
|
||||
@@ -503,9 +479,6 @@ errout_with_fshandle:
|
||||
errout_with_lock:
|
||||
(void)net_unlockroute_ipv6();
|
||||
return ret;
|
||||
#else
|
||||
return -ENOSYS;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
"fstat","sys/stat.h","CONFIG_NFILE_DESCRIPTORS > 0","int","int","FAR struct stat*"
|
||||
"fstatfs","sys/statfs.h","CONFIG_NFILE_DESCRIPTORS > 0","int","int","FAR struct statfs*"
|
||||
"fsync","unistd.h","CONFIG_NFILE_DESCRIPTORS > 0 && !defined(CONFIG_DISABLE_MOUNTPOINT)","int","int"
|
||||
"ftruncate","unistd.h","CONFIG_NFILE_DESCRIPTORS > 0 && !defined(CONFIG_DISABLE_MOUNTPOINT)","int","int","off_t"
|
||||
"get_errno","errno.h","!defined(__DIRECT_ERRNO_ACCESS)","int"
|
||||
"get_errno_ptr","errno.h","defined(__DIRECT_ERRNO_ACCESS)","FAR int*"
|
||||
"getenv","stdlib.h","!defined(CONFIG_DISABLE_ENVIRON)","FAR char*","FAR const char*"
|
||||
|
||||
|
@@ -269,6 +269,7 @@ SYSCALL_LOOKUP(up_assert, 2, STUB_up_assert)
|
||||
SYSCALL_LOOKUP(mount, 5, STUB_mount)
|
||||
# endif
|
||||
SYSCALL_LOOKUP(fsync, 1, STUB_fsync)
|
||||
SYSCALL_LOOKUP(ftruncate, 2, STUB_ftruncate)
|
||||
SYSCALL_LOOKUP(mkdir, 2, STUB_mkdir)
|
||||
SYSCALL_LOOKUP(rename, 2, STUB_rename)
|
||||
SYSCALL_LOOKUP(rmdir, 1, STUB_rmdir)
|
||||
|
||||
@@ -258,6 +258,7 @@ uintptr_t STUB_sched_getstreams(int nbr);
|
||||
ssize_t sendfile(int outfd, int infd, FAR off_t *offset, size_t count);
|
||||
|
||||
uintptr_t STUB_fsync(int nbr, uintptr_t parm1);
|
||||
uintptr_t STUB_ftruncate(int nbr, uintptr_t parm1, uintptr_t parm2);
|
||||
uintptr_t STUB_mkdir(int nbr, uintptr_t parm1, uintptr_t parm2);
|
||||
uintptr_t STUB_mount(int nbr, uintptr_t parm1, uintptr_t parm2,
|
||||
uintptr_t parm3, uintptr_t parm4, uintptr_t parm5);
|
||||
|
||||
Reference in New Issue
Block a user