diff --git a/TODO b/TODO index b880f2f23de..3d92fd7ee2c 100644 --- a/TODO +++ b/TODO @@ -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 diff --git a/fs/binfs/fs_binfs.c b/fs/binfs/fs_binfs.c index f084710792c..5aa26300b8d 100644 --- a/fs/binfs/fs_binfs.c +++ b/fs/binfs/fs_binfs.c @@ -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 * * 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 */ diff --git a/fs/fat/fs_fat32.c b/fs/fat/fs_fat32.c index bbc0d0aa648..165af5e4709 100644 --- a/fs/fat/fs_fat32.c +++ b/fs/fat/fs_fat32.c @@ -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 * * 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 */ diff --git a/fs/nfs/nfs_vfsops.c b/fs/nfs/nfs_vfsops.c index 0a246aa0a86..94f73b04b2f 100644 --- a/fs/nfs/nfs_vfsops.c +++ b/fs/nfs/nfs_vfsops.c @@ -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 * Gregory Nutt @@ -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 */ diff --git a/fs/nxffs/nxffs_initialize.c b/fs/nxffs/nxffs_initialize.c index f2518569fe8..eba886971d2 100644 --- a/fs/nxffs/nxffs_initialize.c +++ b/fs/nxffs/nxffs_initialize.c @@ -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 * * 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 */ diff --git a/fs/procfs/fs_procfs.c b/fs/procfs/fs_procfs.c index 33f838102f2..e269d873e3a 100644 --- a/fs/procfs/fs_procfs.c +++ b/fs/procfs/fs_procfs.c @@ -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 * * 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 */ diff --git a/fs/romfs/fs_romfs.c b/fs/romfs/fs_romfs.c index 8b4d1171099..c76e1407282 100644 --- a/fs/romfs/fs_romfs.c +++ b/fs/romfs/fs_romfs.c @@ -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 * * 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 */ diff --git a/fs/smartfs/smartfs_smart.c b/fs/smartfs/smartfs_smart.c index 3516c4b28f6..9c376f10d5b 100644 --- a/fs/smartfs/smartfs_smart.c +++ b/fs/smartfs/smartfs_smart.c @@ -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 */ diff --git a/fs/tmpfs/fs_tmpfs.c b/fs/tmpfs/fs_tmpfs.c index 3725bd0cc43..fe5a44be13b 100644 --- a/fs/tmpfs/fs_tmpfs.c +++ b/fs/tmpfs/fs_tmpfs.c @@ -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 * * 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 ****************************************************************************/ diff --git a/fs/unionfs/fs_unionfs.c b/fs/unionfs/fs_unionfs.c index 97717860b06..0c61c2e7a0c 100644 --- a/fs/unionfs/fs_unionfs.c +++ b/fs/unionfs/fs_unionfs.c @@ -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 * * 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 */ diff --git a/fs/userfs/fs_userfs.c b/fs/userfs/fs_userfs.c index 9741e5740ed..bf91d58c1ec 100644 --- a/fs/userfs/fs_userfs.c +++ b/fs/userfs/fs_userfs.c @@ -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 * * 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 * diff --git a/fs/vfs/Make.defs b/fs/vfs/Make.defs index d80dca771d2..a306b9297b8 100644 --- a/fs/vfs/Make.defs +++ b/fs/vfs/Make.defs @@ -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 # # 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 diff --git a/fs/vfs/fs_truncate.c b/fs/vfs/fs_truncate.c new file mode 100644 index 00000000000..b5f521732d3 --- /dev/null +++ b/fs/vfs/fs_truncate.c @@ -0,0 +1,200 @@ +/**************************************************************************** + * fs/vfs/fs_truncate.c + * + * Copyright (C) 2018 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include +#include + +#include + +#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 */ diff --git a/include/nuttx/fs/fs.h b/include/nuttx/fs/fs.h index 7058c8ca952..bb3b989ab4a 100644 --- a/include/nuttx/fs/fs.h +++ b/include/nuttx/fs/fs.h @@ -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 * @@ -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 * diff --git a/include/nuttx/fs/userfs.h b/include/nuttx/fs/userfs.h index 8eee64efc65..29ad9d3d915 100644 --- a/include/nuttx/fs/userfs.h +++ b/include/nuttx/fs/userfs.h @@ -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 * * 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 */ diff --git a/include/sys/syscall.h b/include/sys/syscall.h index 9708993d195..c79dca741bc 100644 --- a/include/sys/syscall.h +++ b/include/sys/syscall.h @@ -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 diff --git a/include/unistd.h b/include/unistd.h index a812533aada..93d5f63f3cb 100644 --- a/include/unistd.h +++ b/include/unistd.h @@ -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 * * 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); diff --git a/libc/unistd/Make.defs b/libc/unistd/Make.defs index 3234a9f7fc5..aa166bd0644 100644 --- a/libc/unistd/Make.defs +++ b/libc/unistd/Make.defs @@ -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 diff --git a/libc/unistd/lib_truncate.c b/libc/unistd/lib_truncate.c new file mode 100644 index 00000000000..bde28a30225 --- /dev/null +++ b/libc/unistd/lib_truncate.c @@ -0,0 +1,134 @@ +/**************************************************************************** + * libc/unistd/lib_truncate.c + * + * Copyright (C) 2018 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include +#include + +#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 */ diff --git a/libc/userfs/lib_userfs.c b/libc/userfs/lib_userfs.c index 63512055708..8f04c21f1d9 100644 --- a/libc/userfs/lib_userfs.c +++ b/libc/userfs/lib_userfs.c @@ -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); diff --git a/net/route/Kconfig b/net/route/Kconfig index 21026f61ce9..8c291a9edb6 100644 --- a/net/route/Kconfig +++ b/net/route/Kconfig @@ -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 diff --git a/net/route/net_del_fileroute.c b/net/route/net_del_fileroute.c index 6f57033762a..745acfa7e1c 100644 --- a/net/route/net_del_fileroute.c +++ b/net/route/net_del_fileroute.c @@ -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 * * Redistribution and use in source and binary forms, with or without @@ -40,6 +40,7 @@ #include #include +#include #include #include #include @@ -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 diff --git a/syscall/syscall.csv b/syscall/syscall.csv index efd9ce73b48..ccec8647eda 100644 --- a/syscall/syscall.csv +++ b/syscall/syscall.csv @@ -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*" diff --git a/syscall/syscall_lookup.h b/syscall/syscall_lookup.h index 54b9a8ccddc..e9a920c4e39 100644 --- a/syscall/syscall_lookup.h +++ b/syscall/syscall_lookup.h @@ -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) diff --git a/syscall/syscall_stublookup.c b/syscall/syscall_stublookup.c index 9a366f28abc..3db4ab90a0d 100644 --- a/syscall/syscall_stublookup.c +++ b/syscall/syscall_stublookup.c @@ -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);