Squashed commit of the following:
fs/nxffs: Add partial implementation of the truncate method: It extend files, but cannot yet shrink them. fs/smartfs: Add partial implementation of the truncate method: It extend files, but cannot yet shrink them. fs/fat: Add partial implementation of the truncate method: It extend files, but no yet shrink them. fs/nfs: Add support for the truncate method to the NFS file system.
This commit is contained in:
parent
e4652bd3dc
commit
39fe6a0dff
@ -87,6 +87,7 @@ static int fat_sync(FAR struct file *filep);
|
||||
static int fat_dup(FAR const struct file *oldp, FAR struct file *newp);
|
||||
static int fat_fstat(FAR const struct file *filep,
|
||||
FAR struct stat *buf);
|
||||
static int fat_truncate(FAR struct file *filep, off_t length);
|
||||
|
||||
static int fat_opendir(FAR struct inode *mountpt,
|
||||
FAR const char *relpath, FAR struct fs_dirent_s *dir);
|
||||
@ -139,7 +140,7 @@ const struct mountpt_operations fat_operations =
|
||||
fat_sync, /* sync */
|
||||
fat_dup, /* dup */
|
||||
fat_fstat, /* fstat */
|
||||
NULL, /* truncate */
|
||||
fat_truncate, /* truncate */
|
||||
|
||||
fat_opendir, /* opendir */
|
||||
NULL, /* closedir */
|
||||
@ -794,7 +795,7 @@ static ssize_t fat_write(FAR struct file *filep, FAR const char *buffer,
|
||||
ff->ff_sectorsincluster = fs->fs_fatsecperclus;
|
||||
}
|
||||
|
||||
/* The current sector can then be determined from the currentcluster
|
||||
/* The current sector can then be determined from the current cluster
|
||||
* and the file offset.
|
||||
*/
|
||||
|
||||
@ -1622,7 +1623,7 @@ errout_with_semaphore:
|
||||
*
|
||||
* Description:
|
||||
* Obtain information about an open file associated with the file
|
||||
* descriptor 'fd', and will write it to the area pointed to by 'buf'.
|
||||
* structure 'filep', and will write it to the area pointed to by 'buf'.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
@ -1687,6 +1688,240 @@ errout_with_semaphore:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: fat_truncate
|
||||
*
|
||||
* Description:
|
||||
* Set the length of the open, regular file associated with the file
|
||||
* structure 'filep' to 'length'.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int fat_truncate(FAR struct file *filep, off_t length)
|
||||
{
|
||||
FAR struct inode *inode;
|
||||
FAR struct fat_mountpt_s *fs;
|
||||
FAR struct fat_file_s *ff;
|
||||
int32_t cluster;
|
||||
off_t remaining;
|
||||
off_t oldsize;
|
||||
off_t pos;
|
||||
unsigned int zerosize;
|
||||
int sectndx;
|
||||
int ret;
|
||||
|
||||
DEBUGASSERT(filep->f_priv != NULL && filep->f_inode != NULL);
|
||||
|
||||
/* Recover our private data from the struct file instance */
|
||||
|
||||
ff = filep->f_priv;
|
||||
|
||||
/* Check for the forced mount condition */
|
||||
|
||||
if ((ff->ff_bflags & UMOUNT_FORCED) != 0)
|
||||
{
|
||||
return -EPIPE;
|
||||
}
|
||||
|
||||
inode = filep->f_inode;
|
||||
fs = inode->i_private;
|
||||
|
||||
DEBUGASSERT(fs != NULL);
|
||||
|
||||
/* Make sure that the mount is still healthy */
|
||||
|
||||
fat_semtake(fs);
|
||||
ret = fat_checkmount(fs);
|
||||
if (ret != OK)
|
||||
{
|
||||
goto errout_with_semaphore;
|
||||
}
|
||||
|
||||
/* Check if the file was opened for write access */
|
||||
|
||||
if ((ff->ff_oflags & O_WROK) == 0)
|
||||
{
|
||||
ret = -EACCES;
|
||||
goto errout_with_semaphore;
|
||||
}
|
||||
|
||||
/* Are we shrinking the file? Or extending it? */
|
||||
|
||||
oldsize = ff->ff_size;
|
||||
if (oldsize == length)
|
||||
{
|
||||
ret = OK;
|
||||
goto errout_with_semaphore;
|
||||
}
|
||||
else if (oldsize > length)
|
||||
{
|
||||
/* We are shrinking the file */
|
||||
/* REVISIT: Logic to shrink the file has not yet been implemented */
|
||||
|
||||
ret = -ENOSYS;
|
||||
goto errout_with_semaphore;
|
||||
}
|
||||
|
||||
/* Otherwise we are extending the file. This is essentially the same as a
|
||||
* write except that (1) we write zeros and (2) we don't update the file
|
||||
* position.
|
||||
*/
|
||||
|
||||
pos = ff->ff_size;
|
||||
|
||||
/* Get the first sector to write to. */
|
||||
|
||||
if (!ff->ff_currentsector)
|
||||
{
|
||||
/* Has the starting cluster been defined? */
|
||||
|
||||
if (ff->ff_startcluster == 0)
|
||||
{
|
||||
/* No.. we have to create a new cluster chain */
|
||||
|
||||
ff->ff_startcluster = fat_createchain(fs);
|
||||
ff->ff_currentcluster = ff->ff_startcluster;
|
||||
ff->ff_sectorsincluster = fs->fs_fatsecperclus;
|
||||
}
|
||||
|
||||
/* The current sector can then be determined from the current cluster
|
||||
* and the file offset.
|
||||
*/
|
||||
|
||||
ret = fat_currentsector(fs, ff, pos);
|
||||
if (ret < 0)
|
||||
{
|
||||
goto errout_with_semaphore;
|
||||
}
|
||||
}
|
||||
|
||||
/* Loop until either (1) the file has been fully extended with zeroed data
|
||||
* or (2) an error occurs. We assume we start with the current sector in
|
||||
* cache (ff_currentsector)
|
||||
*/
|
||||
|
||||
sectndx = pos & SEC_NDXMASK(fs);
|
||||
remaining = length - pos;
|
||||
|
||||
while (remaining > 0)
|
||||
{
|
||||
/* Check if the current write stream has incremented to the next
|
||||
* cluster boundary
|
||||
*/
|
||||
|
||||
if (ff->ff_sectorsincluster < 1)
|
||||
{
|
||||
/* Extend the current cluster by one (unless lseek was used to
|
||||
* move the file position back from the end of the file)
|
||||
*/
|
||||
|
||||
cluster = fat_extendchain(fs, ff->ff_currentcluster);
|
||||
|
||||
/* Verify the cluster number */
|
||||
|
||||
if (cluster < 0)
|
||||
{
|
||||
ret = cluster;
|
||||
goto errout_with_semaphore;
|
||||
}
|
||||
else if (cluster < 2 || cluster >= fs->fs_nclusters)
|
||||
{
|
||||
ret = -ENOSPC;
|
||||
goto errout_with_semaphore;
|
||||
}
|
||||
|
||||
/* Setup to zero the first sector from the new cluster */
|
||||
|
||||
ff->ff_currentcluster = cluster;
|
||||
ff->ff_sectorsincluster = fs->fs_fatsecperclus;
|
||||
ff->ff_currentsector = fat_cluster2sector(fs, cluster);
|
||||
}
|
||||
|
||||
/* Decide whether we are performing a read-modify-write
|
||||
* operation, in which case we have to read the existing sector
|
||||
* into the buffer first.
|
||||
*
|
||||
* There are two cases where we can avoid this read:
|
||||
*
|
||||
* - If we are performing a whole-sector clear that was rejected
|
||||
* by fat_hwwrite(), i.e. sectndx == 0 and remaining >= sector size.
|
||||
*
|
||||
* - If the clear is aligned to the beginning of the sector and
|
||||
* extends beyond the end of the file, i.e. sectndx == 0 and
|
||||
* file pos + remaining >= file size.
|
||||
*/
|
||||
|
||||
if (sectndx == 0 && (remaining >= fs->fs_hwsectorsize ||
|
||||
(pos + remaining) >= ff->ff_size))
|
||||
{
|
||||
/* Flush unwritten data in the sector cache. */
|
||||
|
||||
ret = fat_ffcacheflush(fs, ff);
|
||||
if (ret < 0)
|
||||
{
|
||||
goto errout_with_semaphore;
|
||||
}
|
||||
|
||||
/* Now mark the clean cache buffer as the current sector. */
|
||||
|
||||
ff->ff_cachesector = ff->ff_currentsector;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Read the current sector into memory (perhaps first flushing the
|
||||
* old, dirty sector to disk).
|
||||
*/
|
||||
|
||||
ret = fat_ffcacheread(fs, ff, ff->ff_currentsector);
|
||||
if (ret < 0)
|
||||
{
|
||||
goto errout_with_semaphore;
|
||||
}
|
||||
}
|
||||
|
||||
/* Copy the requested part of the sector from the user buffer */
|
||||
|
||||
zerosize = fs->fs_hwsectorsize - sectndx;
|
||||
if (zerosize > remaining)
|
||||
{
|
||||
/* We will not zero to the end of the sector. */
|
||||
|
||||
zerosize = remaining;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We will zero to the end of the buffer (or beyond). Bump up
|
||||
* the current sector number (actually the next sector number).
|
||||
*/
|
||||
|
||||
ff->ff_sectorsincluster--;
|
||||
ff->ff_currentsector++;
|
||||
}
|
||||
|
||||
/* Zero the data into the cached sector and make sure that the cached
|
||||
* sector is marked "dirty" so that it will be written back.
|
||||
*/
|
||||
|
||||
memset(&ff->ff_buffer[sectndx], 0, zerosize);
|
||||
ff->ff_bflags |= (FFBUFF_DIRTY | FFBUFF_VALID | FFBUFF_MODIFIED);
|
||||
|
||||
/* Set up for the next sector */
|
||||
|
||||
pos += zerosize;
|
||||
remaining -= zerosize;
|
||||
sectndx = pos & SEC_NDXMASK(fs);
|
||||
}
|
||||
|
||||
/* The truncation has completed without error. Update the file size */
|
||||
|
||||
ff->ff_size = length;
|
||||
ret = OK;
|
||||
|
||||
errout_with_semaphore:
|
||||
fat_semgive(fs);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: fat_readdir
|
||||
*
|
||||
|
@ -135,11 +135,15 @@ struct nfsstats nfsstats;
|
||||
* Private Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
static int nfs_filecreate(FAR struct nfsmount *nmp, struct nfsnode *np,
|
||||
FAR const char *relpath, mode_t mode);
|
||||
static int nfs_filetruncate(FAR struct nfsmount *nmp, struct nfsnode *np);
|
||||
static int nfs_fileopen(FAR struct nfsmount *nmp, struct nfsnode *np,
|
||||
FAR const char *relpath, int oflags, mode_t mode);
|
||||
static int nfs_filecreate(FAR struct nfsmount *nmp,
|
||||
FAR struct nfsnode *np, FAR const char *relpath,
|
||||
mode_t mode);
|
||||
static int nfs_filetruncate(FAR struct nfsmount *nmp,
|
||||
FAR struct nfsnode *np, uint32_t length);
|
||||
static int nfs_fileopen(FAR struct nfsmount *nmp,
|
||||
FAR struct nfsnode *np, FAR const char *relpath,
|
||||
int oflags, mode_t mode);
|
||||
|
||||
static int nfs_open(FAR struct file *filep, const char *relpath,
|
||||
int oflags, mode_t mode);
|
||||
static int nfs_close(FAR struct file *filep);
|
||||
@ -148,6 +152,7 @@ static ssize_t nfs_write(FAR struct file *filep, const char *buffer,
|
||||
size_t buflen);
|
||||
static int nfs_dup(FAR const struct file *oldp, FAR struct file *newp);
|
||||
static int nfs_fstat(FAR const struct file *filep, FAR struct stat *buf);
|
||||
static int nfs_truncate(FAR struct file *filep, off_t length);
|
||||
static int nfs_opendir(struct inode *mountpt, const char *relpath,
|
||||
struct fs_dirent_s *dir);
|
||||
static int nfs_readdir(struct inode *mountpt, struct fs_dirent_s *dir);
|
||||
@ -191,7 +196,7 @@ const struct mountpt_operations nfs_operations =
|
||||
NULL, /* sync */
|
||||
nfs_dup, /* dup */
|
||||
nfs_fstat, /* fstat */
|
||||
NULL, /* truncate */
|
||||
nfs_truncate, /* truncate */
|
||||
|
||||
nfs_opendir, /* opendir */
|
||||
NULL, /* closedir */
|
||||
@ -225,7 +230,7 @@ const struct mountpt_operations nfs_operations =
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int nfs_filecreate(FAR struct nfsmount *nmp, struct nfsnode *np,
|
||||
static int nfs_filecreate(FAR struct nfsmount *nmp, FAR struct nfsnode *np,
|
||||
FAR const char *relpath, mode_t mode)
|
||||
{
|
||||
struct file_handle fhandle;
|
||||
@ -408,7 +413,8 @@ static int nfs_filecreate(FAR struct nfsmount *nmp, struct nfsnode *np,
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int nfs_filetruncate(FAR struct nfsmount *nmp, struct nfsnode *np)
|
||||
static int nfs_filetruncate(FAR struct nfsmount *nmp,
|
||||
FAR struct nfsnode *np, uint32_t length)
|
||||
{
|
||||
FAR uint32_t *ptr;
|
||||
int reqlen;
|
||||
@ -436,7 +442,7 @@ static int nfs_filetruncate(FAR struct nfsmount *nmp, struct nfsnode *np)
|
||||
*ptr++ = nfs_false; /* Don't change uid */
|
||||
*ptr++ = nfs_false; /* Don't change gid */
|
||||
*ptr++ = nfs_true; /* Use the following size */
|
||||
*ptr++ = 0; /* Truncate to zero length */
|
||||
*ptr++ = length; /* Truncate to the specified length */
|
||||
*ptr++ = 0;
|
||||
*ptr++ = HTONL(NFSV3SATTRTIME_TOSERVER); /* Use the server's time */
|
||||
*ptr++ = HTONL(NFSV3SATTRTIME_TOSERVER); /* Use the server's time */
|
||||
@ -473,7 +479,7 @@ static int nfs_filetruncate(FAR struct nfsmount *nmp, struct nfsnode *np)
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int nfs_fileopen(FAR struct nfsmount *nmp, struct nfsnode *np,
|
||||
static int nfs_fileopen(FAR struct nfsmount *nmp, FAR struct nfsnode *np,
|
||||
FAR const char *relpath, int oflags, mode_t mode)
|
||||
{
|
||||
struct file_handle fhandle;
|
||||
@ -550,7 +556,7 @@ static int nfs_fileopen(FAR struct nfsmount *nmp, struct nfsnode *np,
|
||||
* the SETATTR call by setting the length to zero.
|
||||
*/
|
||||
|
||||
return nfs_filetruncate(nmp, np);
|
||||
return nfs_filetruncate(nmp, np, 0);
|
||||
}
|
||||
|
||||
return OK;
|
||||
@ -1202,7 +1208,7 @@ static int nfs_dup(FAR const struct file *oldp, FAR struct file *newp)
|
||||
*
|
||||
* Description:
|
||||
* Obtain information about an open file associated with the file
|
||||
* descriptor 'fd', and will write it to the area pointed to by 'buf'.
|
||||
* structure 'filep', and will write it to the area pointed to by 'buf'.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
@ -1271,6 +1277,50 @@ errout_with_semaphore:
|
||||
return -error;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nfs_truncate
|
||||
*
|
||||
* Description:
|
||||
* Set the length of the open, regular file associated with the file
|
||||
* structure 'filep' to 'length'.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int nfs_truncate(FAR struct file *filep, off_t length)
|
||||
{
|
||||
struct nfsmount *nmp;
|
||||
struct nfsnode *np;
|
||||
int error;
|
||||
|
||||
finfo("Truncate to %ld bytes\n", (long)length);
|
||||
DEBUGASSERT(filep->f_priv != NULL && filep->f_inode != NULL);
|
||||
|
||||
/* Recover our private data from the struct file instance */
|
||||
|
||||
nmp = (FAR struct nfsmount *)filep->f_inode->i_private;
|
||||
np = (FAR struct nfsnode *)filep->f_priv;
|
||||
|
||||
DEBUGASSERT(nmp != NULL);
|
||||
|
||||
/* Make sure that the mount is still healthy */
|
||||
|
||||
nfs_semtake(nmp);
|
||||
error = nfs_checkmount(nmp);
|
||||
if (error != OK)
|
||||
{
|
||||
ferr("ERROR: nfs_checkmount failed: %d\n", error);
|
||||
goto errout_with_semaphore;
|
||||
}
|
||||
|
||||
/* Then perform the SETATTR RPC to set the new file size */
|
||||
|
||||
error = nfs_filetruncate(nmp, np, length);
|
||||
|
||||
errout_with_semaphore:
|
||||
nfs_semgive(nmp);
|
||||
return -error;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nfs_opendir
|
||||
*
|
||||
|
@ -34,11 +34,14 @@
|
||||
############################################################################
|
||||
|
||||
ifeq ($(CONFIG_FS_NXFFS),y)
|
||||
|
||||
ASRCS +=
|
||||
CSRCS += nxffs_block.c nxffs_blockstats.c nxffs_cache.c nxffs_dirent.c \
|
||||
nxffs_dump.c nxffs_initialize.c nxffs_inode.c nxffs_ioctl.c \
|
||||
nxffs_open.c nxffs_pack.c nxffs_read.c nxffs_reformat.c \
|
||||
nxffs_stat.c nxffs_unlink.c nxffs_util.c nxffs_write.c
|
||||
|
||||
CSRCS += nxffs_block.c nxffs_blockstats.c nxffs_cache.c nxffs_dirent.c
|
||||
CSRCS += nxffs_dump.c nxffs_initialize.c nxffs_inode.c nxffs_ioctl.c
|
||||
CSRCS += nxffs_open.c nxffs_pack.c nxffs_read.c nxffs_reformat.c
|
||||
CSRCS += nxffs_stat.c nxffs_truncate.c nxffs_unlink.c nxffs_util.c
|
||||
CSRCS += nxffs_write.c
|
||||
|
||||
# Include NXFFS build support
|
||||
|
||||
|
@ -1,7 +1,8 @@
|
||||
/****************************************************************************
|
||||
* fs/nxffs/nxffs.h
|
||||
*
|
||||
* 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
|
||||
@ -870,6 +871,26 @@ int nxffs_wrinode(FAR struct nxffs_volume_s *volume,
|
||||
int nxffs_updateinode(FAR struct nxffs_volume_s *volume,
|
||||
FAR struct nxffs_entry_s *entry);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nxffs_wrextend
|
||||
*
|
||||
* Description:
|
||||
* Zero-extend a file.
|
||||
*
|
||||
* Input parameters
|
||||
* volume - Describes the NXFFS volume
|
||||
* entry - Describes the new inode entry
|
||||
* length - The new, extended length of the file
|
||||
*
|
||||
* Assumptions:
|
||||
* The caller holds the NXFFS semaphore.
|
||||
* The caller has verified that the file is writable.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int nxffs_wrextend(FAR struct nxffs_volume_s *volume,
|
||||
FAR struct nxffs_wrfile_s *wrfile, off_t length);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nxffs_wrreserve
|
||||
*
|
||||
@ -1091,12 +1112,16 @@ ssize_t nxffs_read(FAR struct file *filep, FAR char *buffer, size_t buflen);
|
||||
ssize_t nxffs_write(FAR struct file *filep, FAR const char *buffer,
|
||||
size_t buflen);
|
||||
int nxffs_ioctl(FAR struct file *filep, int cmd, unsigned long arg);
|
||||
|
||||
int nxffs_dup(FAR const struct file *oldp, FAR struct file *newp);
|
||||
int nxffs_fstat(FAR const struct file *filep, FAR struct stat *buf);
|
||||
int nxffs_truncate(FAR struct file *filep, off_t length);
|
||||
|
||||
int nxffs_opendir(FAR struct inode *mountpt, FAR const char *relpath,
|
||||
FAR struct fs_dirent_s *dir);
|
||||
int nxffs_readdir(FAR struct inode *mountpt, FAR struct fs_dirent_s *dir);
|
||||
int nxffs_rewinddir(FAR struct inode *mountpt, FAR struct fs_dirent_s *dir);
|
||||
|
||||
int nxffs_bind(FAR struct inode *blkdriver, FAR const void *data,
|
||||
FAR void **handle);
|
||||
int nxffs_unbind(FAR void *handle, FAR struct inode **blkdriver,
|
||||
|
@ -1,7 +1,7 @@
|
||||
/****************************************************************************
|
||||
* fs/nxffs/nxffs_dirent.c
|
||||
*
|
||||
* Copyright (C) 2011, 2017 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2011, 2017-2018 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* References: Linux/Documentation/filesystems/romfs.txt
|
||||
@ -47,6 +47,7 @@
|
||||
#include <errno.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <nuttx/semaphore.h>
|
||||
#include <nuttx/fs/fs.h>
|
||||
#include <nuttx/mtd/mtd.h>
|
||||
#include <nuttx/fs/dirent.h>
|
||||
|
@ -75,7 +75,7 @@ const struct mountpt_operations nxffs_operations =
|
||||
NULL, /* sync -- No buffered data */
|
||||
nxffs_dup, /* dup */
|
||||
nxffs_fstat, /* fstat */
|
||||
NULL, /* truncate */
|
||||
nxffs_truncate, /* truncate */
|
||||
|
||||
nxffs_opendir, /* opendir */
|
||||
NULL, /* closedir */
|
||||
|
@ -1,7 +1,7 @@
|
||||
/****************************************************************************
|
||||
* fs/nxffs/nxffs_ioctl.c
|
||||
*
|
||||
* Copyright (C) 2011, 2013, 2017 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2011, 2013, 2017-2018 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* References: Linux/Documentation/filesystems/romfs.txt
|
||||
@ -46,6 +46,7 @@
|
||||
#include <errno.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <nuttx/semaphore.h>
|
||||
#include <nuttx/fs/fs.h>
|
||||
#include <nuttx/fs/ioctl.h>
|
||||
#include <nuttx/mtd/mtd.h>
|
||||
|
@ -1,7 +1,7 @@
|
||||
/****************************************************************************
|
||||
* fs/nxffs/nxffs_read.c
|
||||
*
|
||||
* Copyright (C) 2011, 2013, 2017 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2011, 2013, 2017-2018 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* References: Linux/Documentation/filesystems/romfs.txt
|
||||
@ -48,6 +48,7 @@
|
||||
#include <errno.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <nuttx/semaphore.h>
|
||||
#include <nuttx/fs/fs.h>
|
||||
#include <nuttx/mtd/mtd.h>
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
/****************************************************************************
|
||||
* fs/nxffs/nxffs_stat.c
|
||||
*
|
||||
* Copyright (C) 2011, 2017 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2011, 2017-2018 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* References: Linux/Documentation/filesystems/romfs.txt
|
||||
@ -50,6 +50,7 @@
|
||||
#include <errno.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <nuttx/semaphore.h>
|
||||
#include <nuttx/fs/fs.h>
|
||||
#include <nuttx/mtd/mtd.h>
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
/****************************************************************************
|
||||
* fs/nxffs/nxffs_unlink.c
|
||||
*
|
||||
* Copyright (C) 2011, 2013, 2017 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2011, 2013, 2017-2018 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* References: Linux/Documentation/filesystems/romfs.txt
|
||||
@ -46,6 +46,7 @@
|
||||
#include <assert.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <nuttx/semaphore.h>
|
||||
#include <nuttx/fs/fs.h>
|
||||
#include <nuttx/mtd/mtd.h>
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
/****************************************************************************
|
||||
* fs/nxffs/nxffs_write.c
|
||||
*
|
||||
* Copyright (C) 2011, 2013, 2017 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2011, 2013, 2017-2018 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* References: Linux/Documentation/filesystems/romfs.txt
|
||||
@ -48,6 +48,7 @@
|
||||
#include <errno.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <nuttx/semaphore.h>
|
||||
#include <nuttx/fs/fs.h>
|
||||
#include <nuttx/mtd/mtd.h>
|
||||
|
||||
@ -327,7 +328,7 @@ static inline int nxffs_reverify(FAR struct nxffs_volume_s *volume,
|
||||
* volume - Describes the NXFFS volume
|
||||
* wrfile - Describes the open file to be written.
|
||||
* buffer - Address of buffer of data to be written.
|
||||
* buflen - The number of bytes remaimining to be written
|
||||
* buflen - The number of bytes remaining to be written
|
||||
*
|
||||
* Returned Value:
|
||||
* The number of bytes written is returned on success. Otherwise, a
|
||||
@ -414,6 +415,96 @@ static inline ssize_t nxffs_wrappend(FAR struct nxffs_volume_s *volume,
|
||||
return nbytestowrite;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nxffs_zappend
|
||||
*
|
||||
* Description:
|
||||
* Zero-extend FLASH data to the data block.
|
||||
*
|
||||
* Input Parameters:
|
||||
* volume - Describes the NXFFS volume
|
||||
* wrfile - Describes the open file to be written.
|
||||
* nzeros - The number of bytes of zeroed data to be written
|
||||
*
|
||||
* Returned Value:
|
||||
* The number of bytes written is returned on success. Otherwise, a
|
||||
* negated errno value is returned indicating the nature of the failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static inline ssize_t nxffs_zappend(FAR struct nxffs_volume_s *volume,
|
||||
FAR struct nxffs_wrfile_s *wrfile,
|
||||
off_t nzeros)
|
||||
{
|
||||
ssize_t maxsize;
|
||||
size_t nbytestoclear;
|
||||
ssize_t remaining;
|
||||
off_t offset;
|
||||
int ret;
|
||||
|
||||
/* Get the offset to the start of unwritten data */
|
||||
|
||||
offset = volume->iooffset + wrfile->datlen + SIZEOF_NXFFS_DATA_HDR;
|
||||
|
||||
/* Determine that maximum amount of data that can be written to this
|
||||
* block.
|
||||
*/
|
||||
|
||||
maxsize = volume->geo.blocksize - offset;
|
||||
DEBUGASSERT(maxsize > 0);
|
||||
|
||||
/* Write as many bytes as we can into the data buffer */
|
||||
|
||||
nbytestoclear = MIN(maxsize, nzeros);
|
||||
remaining = maxsize - nbytestoclear;
|
||||
|
||||
if (nbytestoclear > 0)
|
||||
{
|
||||
/* Copy the data into the volume write cache */
|
||||
|
||||
memset(&volume->cache[offset], 0, nbytestoclear);
|
||||
|
||||
/* Increment the number of bytes written to the data block */
|
||||
|
||||
wrfile->datlen += nbytestoclear;
|
||||
|
||||
/* Re-calculate the CRC */
|
||||
|
||||
offset = volume->iooffset + SIZEOF_NXFFS_DATA_HDR;
|
||||
wrfile->crc = crc32(&volume->cache[offset], wrfile->datlen);
|
||||
|
||||
/* And write the partial write block to FLASH -- unless the data
|
||||
* block is full. In that case, the block will be written below.
|
||||
*/
|
||||
|
||||
if (remaining > 0)
|
||||
{
|
||||
ret = nxffs_wrcache(volume);
|
||||
if (ret < 0)
|
||||
{
|
||||
ferr("ERROR: nxffs_wrcache failed: %d\n", -ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if the data block is now full */
|
||||
|
||||
if (remaining <= 0)
|
||||
{
|
||||
/* The data block is full, write the block to FLASH */
|
||||
|
||||
ret = nxffs_wrblkhdr(volume, wrfile);
|
||||
if (ret < 0)
|
||||
{
|
||||
ferr("ERROR: nxffs_wrblkdhr failed: %d\n", -ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
@ -534,6 +625,91 @@ errout:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nxffs_wrextend
|
||||
*
|
||||
* Description:
|
||||
* Zero-extend a file.
|
||||
*
|
||||
* Input parameters
|
||||
* volume - Describes the NXFFS volume
|
||||
* entry - Describes the new inode entry
|
||||
* length - The new, extended length of the file
|
||||
*
|
||||
* Assumptions:
|
||||
* The caller holds the NXFFS semaphore.
|
||||
* The caller has verified that the file is writable.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int nxffs_wrextend(FAR struct nxffs_volume_s *volume,
|
||||
FAR struct nxffs_wrfile_s *wrfile, off_t length)
|
||||
{
|
||||
ssize_t remaining;
|
||||
ssize_t nwritten;
|
||||
off_t oldsize;
|
||||
int ret;
|
||||
|
||||
finfo("Extend file to %ld bytes to offset %d\n", (long)length);
|
||||
DEBUGASSERT(volume != NULL && wrfile != NULL);
|
||||
|
||||
oldsize = wrfile->ofile.entry.datlen;
|
||||
DEBUGASSERT(length > oldsize);
|
||||
|
||||
/* Loop until we successfully appended all of the data to the file (or an
|
||||
* error occurs)
|
||||
*/
|
||||
|
||||
remaining = length - oldsize;
|
||||
while (remaining > 0)
|
||||
{
|
||||
/* Have we already allocated the data block? */
|
||||
|
||||
if (wrfile->doffset == 0)
|
||||
{
|
||||
/* No, allocate the data block now, re-packing if necessary. */
|
||||
|
||||
wrfile->datlen = 0;
|
||||
ret = nxffs_wralloc(volume, wrfile, remaining);
|
||||
if (ret < 0)
|
||||
{
|
||||
ferr("ERROR: Failed to allocate a data block: %d\n", -ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/* Seek to the FLASH block containing the data block */
|
||||
|
||||
nxffs_ioseek(volume, wrfile->doffset);
|
||||
|
||||
/* Verify that the FLASH data that was previously written is still intact */
|
||||
|
||||
ret = nxffs_reverify(volume, wrfile);
|
||||
if (ret < 0)
|
||||
{
|
||||
ferr("ERROR: Failed to verify FLASH data block: %d\n", -ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Append the data to the end of the data block and write the updated
|
||||
* block to flash.
|
||||
*/
|
||||
|
||||
nwritten = nxffs_zappend(volume, wrfile, remaining);
|
||||
if (nwritten < 0)
|
||||
{
|
||||
ferr("ERROR: Failed to zero extend FLASH data block: %d\n", -ret);
|
||||
return (int)nwritten;
|
||||
}
|
||||
|
||||
/* Decrement the number of bytes remaining to be written */
|
||||
|
||||
remaining -= nwritten;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nxffs_wrreserve
|
||||
*
|
||||
|
@ -209,12 +209,18 @@
|
||||
#define SMARTFS_ERASEDSTATE_16BIT (uint16_t) ((CONFIG_SMARTFS_ERASEDSTATE << 8) | \
|
||||
CONFIG_SMARTFS_ERASEDSTATE)
|
||||
|
||||
/* Size of temporary buffer used when a file is zero extended by ftruncate()
|
||||
* logic.
|
||||
*/
|
||||
|
||||
#define SMARTFS_TRUNCBUFFER_SIZE 512
|
||||
|
||||
#ifndef offsetof
|
||||
#define offsetof(type, member) ( (size_t) &( ( (type *) 0)->member))
|
||||
# define offsetof(type, member) ((size_t) & (((type *)0)->member))
|
||||
#endif
|
||||
|
||||
#define SMARTFS_NEXTSECTOR(h) ( *((uint16_t *) h->nextsector))
|
||||
#define SMARTFS_USED(h) ( *((uint16_t *) h->used))
|
||||
#define SMARTFS_NEXTSECTOR(h) (*((uint16_t *)h->nextsector))
|
||||
#define SMARTFS_USED(h) (*((uint16_t *)h->used))
|
||||
|
||||
#ifdef CONFIG_MTD_SMART_ENABLE_CRC
|
||||
#define CONFIG_SMARTFS_USE_SECTOR_BUFFER
|
||||
|
@ -83,6 +83,7 @@ static int smartfs_dup(FAR const struct file *oldp,
|
||||
FAR struct file *newp);
|
||||
static int smartfs_fstat(FAR const struct file *filep,
|
||||
FAR struct stat *buf);
|
||||
static int smartfs_truncate(FAR struct file *filep, off_t length);
|
||||
|
||||
static int smartfs_opendir(FAR struct inode *mountpt,
|
||||
FAR const char *relpath,
|
||||
@ -149,7 +150,7 @@ const struct mountpt_operations smartfs_operations =
|
||||
smartfs_sync, /* sync */
|
||||
smartfs_dup, /* dup */
|
||||
smartfs_fstat, /* fstat */
|
||||
NULL, /* truncate */
|
||||
smartfs_truncate, /* truncate */
|
||||
|
||||
smartfs_opendir, /* opendir */
|
||||
NULL, /* closedir */
|
||||
@ -618,22 +619,23 @@ static int smartfs_sync_internal(struct smartfs_mountpt_s *fs,
|
||||
{
|
||||
/* Update the header with the number of bytes written */
|
||||
|
||||
header = (struct smartfs_chain_header_s *) sf->buffer;
|
||||
if (*((uint16_t *) header->used) == SMARTFS_ERASEDSTATE_16BIT)
|
||||
header = (struct smartfs_chain_header_s *)sf->buffer;
|
||||
if (*((uint16_t *)header->used) == SMARTFS_ERASEDSTATE_16BIT)
|
||||
{
|
||||
*((uint16_t *) header->used) = sf->byteswritten;
|
||||
*((uint16_t *)header->used) = sf->byteswritten;
|
||||
}
|
||||
else
|
||||
{
|
||||
*((uint16_t *) header->used) += sf->byteswritten;
|
||||
*((uint16_t *)header->used) += sf->byteswritten;
|
||||
}
|
||||
|
||||
/* Write the entire sector to FLASH */
|
||||
|
||||
readwrite.logsector = sf->currsector;
|
||||
readwrite.offset = 0;
|
||||
readwrite.count = fs->fs_llformat.availbytes;
|
||||
readwrite.buffer = sf->buffer;
|
||||
readwrite.offset = 0;
|
||||
readwrite.count = fs->fs_llformat.availbytes;
|
||||
readwrite.buffer = sf->buffer;
|
||||
|
||||
ret = FS_IOCTL(fs, BIOC_WRITESECT, (unsigned long) &readwrite);
|
||||
if (ret < 0)
|
||||
{
|
||||
@ -657,9 +659,10 @@ static int smartfs_sync_internal(struct smartfs_mountpt_s *fs,
|
||||
/* Read the existing sector used bytes value */
|
||||
|
||||
readwrite.logsector = sf->currsector;
|
||||
readwrite.offset = 0;
|
||||
readwrite.buffer = (uint8_t *) fs->fs_rwbuffer;
|
||||
readwrite.count = sizeof(struct smartfs_chain_header_s);
|
||||
readwrite.offset = 0;
|
||||
readwrite.buffer = (uint8_t *) fs->fs_rwbuffer;
|
||||
readwrite.count = sizeof(struct smartfs_chain_header_s);
|
||||
|
||||
ret = FS_IOCTL(fs, BIOC_READSECT, (unsigned long) &readwrite);
|
||||
if (ret < 0)
|
||||
{
|
||||
@ -681,8 +684,9 @@ static int smartfs_sync_internal(struct smartfs_mountpt_s *fs,
|
||||
}
|
||||
|
||||
readwrite.offset = offsetof(struct smartfs_chain_header_s, used);
|
||||
readwrite.count = sizeof(uint16_t);
|
||||
readwrite.count = sizeof(uint16_t);
|
||||
readwrite.buffer = (uint8_t *) &fs->fs_rwbuffer[readwrite.offset];
|
||||
|
||||
ret = FS_IOCTL(fs, BIOC_WRITESECT, (unsigned long) &readwrite);
|
||||
if (ret < 0)
|
||||
{
|
||||
@ -774,7 +778,9 @@ static ssize_t smartfs_write(FAR struct file *filep, const char *buffer,
|
||||
/* Limit the write based on available data to write */
|
||||
|
||||
if (readwrite.count > buflen)
|
||||
readwrite.count = buflen;
|
||||
{
|
||||
readwrite.count = buflen;
|
||||
}
|
||||
|
||||
/* Limit the write based on current file length */
|
||||
|
||||
@ -1308,6 +1314,286 @@ static int smartfs_fstat(FAR const struct file *filep, FAR struct stat *buf)
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: smartfs_truncate
|
||||
*
|
||||
* Description:
|
||||
* Set the length of the open, regular file associated with the file
|
||||
* structure 'filep' to 'length'.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int smartfs_truncate(FAR struct file *filep, off_t length)
|
||||
{
|
||||
struct smart_read_write_s readwrite;
|
||||
FAR struct inode *inode;
|
||||
FAR struct smartfs_mountpt_s *fs;
|
||||
FAR struct smartfs_ofile_s *sf;
|
||||
FAR struct smartfs_chain_header_s *header;
|
||||
#ifndef CONFIG_SMARTFS_USE_SECTOR_BUFFER
|
||||
FAR uint8_t *buffer;
|
||||
#endif
|
||||
off_t remaining;
|
||||
off_t savepos;
|
||||
off_t oldsize;
|
||||
int ret;
|
||||
|
||||
DEBUGASSERT(filep->f_priv != NULL && filep->f_inode != NULL);
|
||||
|
||||
/* Recover our private data from the struct file instance */
|
||||
|
||||
sf = filep->f_priv;
|
||||
inode = filep->f_inode;
|
||||
fs = inode->i_private;
|
||||
|
||||
DEBUGASSERT(fs != NULL);
|
||||
|
||||
/* Take the semaphore */
|
||||
|
||||
smartfs_semtake(fs);
|
||||
|
||||
/* Test the permissions. Only allow truncation if the file was opened with
|
||||
* write flags.
|
||||
*/
|
||||
|
||||
if ((sf->oflags & O_WROK) == 0)
|
||||
{
|
||||
ret = -EACCES;
|
||||
goto errout_with_semaphore;
|
||||
}
|
||||
|
||||
/* Are we shrinking the file? Or extending it? */
|
||||
|
||||
oldsize = sf->entry.datlen;
|
||||
if (oldsize == length)
|
||||
{
|
||||
ret = OK;
|
||||
goto errout_with_semaphore;
|
||||
}
|
||||
else if (oldsize > length)
|
||||
{
|
||||
/* We are shrinking the file */
|
||||
/* REVISIT: Logic to shrink the file has not yet been implemented */
|
||||
|
||||
ret = -ENOSYS;
|
||||
goto errout_with_semaphore;
|
||||
}
|
||||
|
||||
/* Otherwise we are extending the file. This is essentially the same as a
|
||||
* write except that (1) we write zeros and (2) we don't update the file
|
||||
* position.
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_SMARTFS_USE_SECTOR_BUFFER
|
||||
/* In order to perform the writes we will have to have a sector buffer. If
|
||||
* SmartFS is not configured with a sector buffer then we will, then we
|
||||
* will, unfortunately, need to allocate one.
|
||||
*/
|
||||
|
||||
buffer = (FAR uint8_t *)kmm_malloc(SMARTFS_TRUNCBUFFER_SIZE);
|
||||
if (buffer == NULL)
|
||||
{
|
||||
ret = -ENOMEM;
|
||||
goto errout_with_semaphore;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Seek to the end of the file (remembering the current file position) */
|
||||
|
||||
savepos = sf->filepos;
|
||||
(void)smartfs_seek_internal(fs, sf, 0, SEEK_END);
|
||||
|
||||
/* Loop until either (1) the file has been fully extended with zeroed data
|
||||
* or (2) an error occurs. We assume we start with the current sector in
|
||||
* cache (ff_currentsector)
|
||||
*/
|
||||
|
||||
remaining = length - oldsize;
|
||||
while (remaining > 0)
|
||||
{
|
||||
/* We will fill up the current sector. Write data to the current
|
||||
* sector first.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_SMARTFS_USE_SECTOR_BUFFER
|
||||
readwrite.count = fs->fs_llformat.availbytes - sf->curroffset;
|
||||
if (readwrite.count > remaining)
|
||||
{
|
||||
readwrite.count = remaining;
|
||||
}
|
||||
|
||||
memset(&sf->buffer[sf->curroffset], 0, readwrite.count);
|
||||
sf->bflags |= SMARTFS_BFLAG_DIRTY;
|
||||
|
||||
#else /* CONFIG_SMARTFS_USE_SECTOR_BUFFER */
|
||||
readwrite.offset = sf->curroffset;
|
||||
readwrite.logsector = sf->currsector;
|
||||
readwrite.buffer = buffer;
|
||||
|
||||
/* Select max size that available in the current sector */
|
||||
|
||||
readwrite.count = fs->fs_llformat.availbytes - sf->curroffset;
|
||||
if (readwrite.count > remaining)
|
||||
{
|
||||
/* Limit the write to the size for our smaller working buffer*/
|
||||
|
||||
readwrite.count = SMARTFS_TRUNCBUFFER_SIZE;
|
||||
}
|
||||
|
||||
if (readwrite.count > remaining)
|
||||
{
|
||||
/* Futher limit the write to the remaining bytes to write */
|
||||
|
||||
readwrite.count = remaining;
|
||||
}
|
||||
|
||||
/* Perform the write */
|
||||
|
||||
if (readwrite.count > 0)
|
||||
{
|
||||
ret = FS_IOCTL(fs, BIOC_WRITESECT, (unsigned long) &readwrite);
|
||||
if (ret < 0)
|
||||
{
|
||||
ferr("ERROR: Error %d writing sector %d data\n",
|
||||
ret, sf->currsector);
|
||||
goto errout_with_buffer;
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_SMARTFS_USE_SECTOR_BUFFER */
|
||||
|
||||
/* Update our control variables */
|
||||
|
||||
sf->entry.datlen += readwrite.count;
|
||||
sf->byteswritten += readwrite.count;
|
||||
sf->curroffset += readwrite.count;
|
||||
remaining -= readwrite.count;
|
||||
|
||||
/* Test if we wrote a full sector of data */
|
||||
|
||||
#ifdef CONFIG_SMARTFS_USE_SECTOR_BUFFER
|
||||
if (sf->curroffset == fs->fs_llformat.availbytes && remaining)
|
||||
{
|
||||
/* First get a new chained sector */
|
||||
|
||||
ret = FS_IOCTL(fs, BIOC_ALLOCSECT, 0xFFFF);
|
||||
if (ret < 0)
|
||||
{
|
||||
ferr("ERROR: Error %d allocating new sector\n", ret);
|
||||
goto errout_with_buffer;
|
||||
}
|
||||
|
||||
/* Copy the new sector to the old one and chain it */
|
||||
|
||||
header = (struct smartfs_chain_header_s *) sf->buffer;
|
||||
*((uint16_t *) header->nextsector) = (uint16_t) ret;
|
||||
|
||||
/* Now sync the file to write this sector out */
|
||||
|
||||
ret = smartfs_sync_internal(fs, sf);
|
||||
if (ret != OK)
|
||||
{
|
||||
goto errout_with_buffer;
|
||||
}
|
||||
|
||||
/* Record the new sector in our tracking variables and reset the
|
||||
* offset to "zero".
|
||||
*/
|
||||
|
||||
if (sf->currsector == SMARTFS_NEXTSECTOR(header))
|
||||
{
|
||||
/* Error allocating logical sector! */
|
||||
|
||||
ferr("ERROR: Duplicate logical sector %d\n", sf->currsector);
|
||||
}
|
||||
|
||||
sf->bflags = SMARTFS_BFLAG_DIRTY;
|
||||
sf->currsector = SMARTFS_NEXTSECTOR(header);
|
||||
sf->curroffset = sizeof(struct smartfs_chain_header_s);
|
||||
memset(sf->buffer, CONFIG_SMARTFS_ERASEDSTATE, fs->fs_llformat.availbytes);
|
||||
header->type = SMARTFS_DIRENT_TYPE_FILE;
|
||||
}
|
||||
#else /* CONFIG_SMARTFS_USE_SECTOR_BUFFER */
|
||||
|
||||
if (sf->curroffset == fs->fs_llformat.availbytes)
|
||||
{
|
||||
/* Sync the file to write this sector out */
|
||||
|
||||
ret = smartfs_sync_internal(fs, sf);
|
||||
if (ret != OK)
|
||||
{
|
||||
goto errout_with_buffer;
|
||||
}
|
||||
|
||||
/* Allocate a new sector if needed */
|
||||
|
||||
if (remaining > 0)
|
||||
{
|
||||
/* Allocate a new sector */
|
||||
|
||||
ret = FS_IOCTL(fs, BIOC_ALLOCSECT, 0xFFFF);
|
||||
if (ret < 0)
|
||||
{
|
||||
ferr("ERROR: Error %d allocating new sector\n", ret);
|
||||
goto errout_with_buffer;
|
||||
}
|
||||
|
||||
/* Copy the new sector to the old one and chain it */
|
||||
|
||||
header = (struct smartfs_chain_header_s *)fs->fs_rwbuffer;
|
||||
*((uint16_t *) header->nextsector) = (uint16_t) ret;
|
||||
|
||||
readwrite.offset = offsetof(struct smartfs_chain_header_s,
|
||||
nextsector);
|
||||
readwrite.buffer = (uint8_t *) header->nextsector;
|
||||
readwrite.count = sizeof(uint16_t);
|
||||
|
||||
ret = FS_IOCTL(fs, BIOC_WRITESECT, (unsigned long) &readwrite);
|
||||
if (ret < 0)
|
||||
{
|
||||
ferr("ERROR: Error %d writing next sector\n", ret);
|
||||
goto errout_with_buffer;
|
||||
}
|
||||
|
||||
/* Record the new sector in our tracking variables and
|
||||
* reset the offset to "zero".
|
||||
*/
|
||||
|
||||
if (sf->currsector == SMARTFS_NEXTSECTOR(header))
|
||||
{
|
||||
/* Error allocating logical sector! */
|
||||
|
||||
ferr("ERROR: Duplicate logical sector %d\n", sf->currsector);
|
||||
}
|
||||
|
||||
sf->currsector = SMARTFS_NEXTSECTOR(header);
|
||||
sf->curroffset = sizeof(struct smartfs_chain_header_s);
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_SMARTFS_USE_SECTOR_BUFFER */
|
||||
}
|
||||
|
||||
/* The file was successfully extended with zeros */
|
||||
|
||||
ret = OK;
|
||||
|
||||
errout_with_buffer:
|
||||
/* Restore the original file position */
|
||||
|
||||
(void)smartfs_seek_internal(fs, sf, savepos, SEEK_SET);
|
||||
|
||||
/* Release the allocated buffer */
|
||||
|
||||
#ifdef CONFIG_SMARTFS_USE_SECTOR_BUFFER
|
||||
kmm_free(buffer);
|
||||
#endif
|
||||
|
||||
errout_with_semaphore:
|
||||
/* Relinquish exclusive access */
|
||||
|
||||
smartfs_semgive(fs);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: smartfs_opendir
|
||||
*
|
||||
|
@ -89,7 +89,7 @@ int file_truncate(FAR struct file *filep, off_t length)
|
||||
}
|
||||
|
||||
/* A NULL write() method is an indicator of a read-only file system (but
|
||||
* possible not the only indicator)
|
||||
* possible not the only indicator -- sufficient, but not necessary")
|
||||
*/
|
||||
|
||||
if (inode->u.i_mops->write == NULL)
|
||||
|
Loading…
Reference in New Issue
Block a user