nuttx/fs/nxffs/nxffs.h
Marco Casaroli 6da4269c46 fs/vfs: Add ioctldir for volume ioctls via the mountpoint directory.
FIOC_REFORMAT, FIOC_OPTIMIZE, FIOC_INTEGRITY and FIOC_DUMP act on a volume,
not on any one file, but the only route into a file system has been the
per-file ioctl method.  A caller therefore has to open an unrelated file
just to name the volume it means.

For nxffs that is not merely awkward, it is a dead end.  nxffs_ioctl()
refuses FIOC_REFORMAT while any file on the volume is open:

    if (volume->ofiles)
      {
        ferr("ERROR: Open files\n");
        ret = -EBUSY;

and every open file is on that list (nxffs_open.c).  The descriptor used to
issue the command is itself such a file, so the check can never pass and
FIOC_REFORMAT is unreachable through the only interface that exposes it.

Add an optional ioctldir method to struct mountpt_operations, reached by
issuing the ioctl on a descriptor for the mountpoint directory:

    fd = open("/mnt/nxffs", O_RDONLY | O_DIRECTORY);
    ioctl(fd, FIOC_REFORMAT, 0);

It takes the same (mountpt, dir) pair as opendir/readdir/rewinddir, so it
reads as a member of the directory-operations family; the file system
recovers the volume from the mountpoint inode and may ignore dir.  The
member is placed at the end of the structure rather than beside the other
directory operations on purpose: every file system initialises
mountpt_operations positionally, so a member inserted mid-structure would
force all of them to add a slot for a method they do not implement.
Appending keeps the change to one file system.

dir_ioctl() gives that method the first chance at every command when the
directory belongs to a mounted volume and the file system provides one, and
falls back to its own handling of FIOC_FILEPATH and BIOC_FLUSH when the file
system answers -ENOTTY.  Trying the file system first is what lets a file
system override a command the VFS would otherwise answer generically; the
-ENOTTY fallback is what keeps the generic answers available to everyone
else.  A file system that leaves the method NULL is unaffected: the VFS
answers exactly as before.

The existing per-file method could not simply be reused for this.  It takes
a struct file, and every implementation that has an ioctl -- fat, romfs,
tmpfs, spiffs among them -- asserts on filep->f_priv and dereferences it,
so handing it a directory descriptor with no open file behind it would
fault.  Making the entry point separate keeps that contract intact and
makes support explicit rather than assumed.

nxffs implements it, which is what makes its FIOC_REFORMAT reachable.  The
per-file path is left in place and both share one implementation, so
nothing that works today stops working.  spiffs, which has the same shape
of volume commands, can follow.

Measured on sim:nxffs, with one file written to the volume and then the
same sequence of ioctls issued on a file descriptor, on a descriptor for the
mountpoint directory, and on a descriptor for a pseudo file system directory.
Before:

    FIOC_REFORMAT via file fd:  ret=-1 errno=16 (EBUSY, as expected)
    FIOC_REFORMAT via dir fd:   ret=-1 errno=25
    FIOC_FILEPATH via dir fd:   ret=0  "/mnt/nxffs//"
    BIOC_FLUSH    via dir fd:   ret=0
    bogus cmd     via dir fd:   ret=-1 errno=25
    FIOC_FILEPATH via /dev fd:  ret=0  "/dev//"
    bogus cmd     via /dev fd:  ret=-1 errno=25
    name still in the raw MTD image afterwards: yes

After:

    FIOC_REFORMAT via file fd:  ret=-1 errno=16 (EBUSY, as expected)
    FIOC_REFORMAT via dir fd:   ret=0
    FIOC_FILEPATH via dir fd:   ret=0  "/mnt/nxffs//"
    BIOC_FLUSH    via dir fd:   ret=0
    bogus cmd     via dir fd:   ret=-1 errno=25
    FIOC_FILEPATH via /dev fd:  ret=0  "/dev//"
    bogus cmd     via /dev fd:  ret=-1 errno=25
    name still in the raw MTD image afterwards: no

Only the FIOC_REFORMAT line on the directory descriptor changes, and the raw
MTD image confirms the volume really was erased.  FIOC_FILEPATH and
BIOC_FLUSH on a directory still answer even though nxffs is now consulted
ahead of them, an unrecognised command is still refused rather than
forwarded blindly, and a directory in the pseudo file system, which has no
ioctldir at all, is untouched.

Assisted-by: Claude Code:claude-opus-4-8
Assisted-by: Claude Code:claude-fable-5
Assisted-by: Claude Code:claude-opus-5
Signed-off-by: Marco Casaroli <marco.casaroli@gmail.com>
2026-07-25 07:28:22 -03:00

1124 lines
40 KiB
C

/****************************************************************************
* fs/nxffs/nxffs.h
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
#ifndef __FS_NXFFS_NXFFS_H
#define __FS_NXFFS_NXFFS_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <sys/param.h>
#include <sys/types.h>
#include <stdint.h>
#include <stdbool.h>
#include <nuttx/mtd/mtd.h>
#include <nuttx/fs/nxffs.h>
#include <nuttx/mutex.h>
#include <nuttx/semaphore.h>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* NXFFS Definitions ********************************************************/
/* General NXFFS organization. The following example assumes 4 logical
* blocks per FLASH erase block. The actual relationship is determined by
* the FLASH geometry reported by the MTD driver.
*
* ERASE LOGICAL Inodes begin with a inode header which may
* BLOCK BLOCK CONTENTS be marked as deleted, pending re-packing.
* n 4*n --+--------------+
* |BBBBBBBBBBBBBB| Logic block header
* |IIIIIIIIIIIIII| Inodes begin with a inode header
* |DDDDDDDDDDDDDD| Data block containing inode data block
* | (Inode Data) |
* 4*n+1 --+--------------+
* |BBBBBBBBBBBBBB| Logic block header
* |DDDDDDDDDDDDDD| Inodes may consist multiple data blocks
* | (Inode Data) |
* |IIIIIIIIIIIIII| Next inode header
* | | Possibly unused bytes at the end of block
* 4*n+2 --+--------------+
* |BBBBBBBBBBBBBB| Logic block header
* |DDDDDDDDDDDDDD|
* | (Inode Data) |
* 4*n+3 --+--------------+
* |BBBBBBBBBBBBBB| Logic block header
* |IIIIIIIIIIIIII| Next inode header
* |DDDDDDDDDDDDDD|
* | (Inode Data) |
* n+1 4*(n+1) --+--------------+
* |BBBBBBBBBBBBBB| Logic block header
* | | All FLASH is unused after the end of the
* | | final inode.
* --+--------------+
*
* General operation:
* Inodes are written starting at the beginning of FLASH. As inodes are
* deleted, they are marked as deleted but not removed. As new inodes are
* written, allocations proceed to toward the end of the FLASH -- thus,
* supporting wear leveling by using all FLASH blocks equally.
*
* When the FLASH becomes full (no more space at the end of the FLASH), a
* re-packing operation must be performed: All inodes marked deleted are
* finally removed and the remaining inodes are packed at the beginning of
* the FLASH. Allocations then continue at the freed FLASH memory at the
* end of the FLASH.
*
* BLOCK HEADER:
* The block header is used to determine if the block has every been
* formatted and also indicates bad blocks which should never be used.
*
* INODE HEADER:
* Each inode begins with an inode header that contains, among other
* things, the name of the inode, the offset to the first data block,
* and the length of the inode data.
*
* At present, the only kind of inode support is a file. So for now, the
* term file and inode are interchangeable.
*
* INODE DATA HEADER:
* Inode data is enclosed in a data header. For a given inode, there
* is at most one inode data block per logical block. If the inode data
* spans more than one logical block, then the inode data may be enclosed
* in multiple data blocks, one per logical block.
*
* NXFFS Limitations:
* 1. Since the files are contiguous in FLASH and since allocations always
* proceed toward the end of the FLASH, there can only be one file opened
* for writing at a time. Multiple files may be opened for reading.
* 2. Files may not be increased in size after they have been closed. The
* O_APPEND open flag is not supported.
* 3. Files are always written sequential. Seeking within a file opened for
* writing will not work.
* 4. There are no directories, however, '/' may be used within a file name
* string providing some illusion of directories.
* 5. Files may be opened for reading or for writing, but not both: The
* O_RDWR open flag is not supported.
* 6. The re-packing process occurs only during a write when the free FLASH
* memory at the end of the FLASH is exhausted. Thus, occasionally, file
* writing may take a long time.
* 7. Another limitation is that there can be only a single NXFFS volume
* mounted at any time. This has to do with the fact that we bind to
* an MTD driver (instead of a block driver) and bypass all of the normal
* mount operations.
*/
/* Values for logical block state. Basically, there are only two, perhaps
* three, states:
*
* BLOCK_STATE_GOOD - The block is not known to be bad.
* BLOCK_STATE_BAD - An error was found on the block and it is marked bad.
* Other values - The block is bad and has an invalid state.
*
* Care is taken so that the GOOD to BAD transition only involves burning
* bits from the erased to non-erased state.
*/
#define BLOCK_STATE_GOOD (CONFIG_NXFFS_ERASEDSTATE ^ 0x44)
#define BLOCK_STATE_BAD (CONFIG_NXFFS_ERASEDSTATE ^ 0x55)
/* Values for NXFFS inode state. Similar there are 2 (maybe 3) inode states:
*
* INODE_STATE_FILE - The inode is a valid usable, file
* INODE_STATE_DELETED - The inode has been deleted.
* Other values - The inode is bad and has an invalid state.
*
* Care is taken so that the VALID to DELETED transition only involves
* burning bits from the erased to non-erased state.
*/
#define INODE_STATE_FILE (CONFIG_NXFFS_ERASEDSTATE ^ 0x22)
#define INODE_STATE_DELETED (CONFIG_NXFFS_ERASEDSTATE ^ 0xaa)
/* Number of bytes in an the NXFFS magic sequences */
#define NXFFS_MAGICSIZE 4
/* When we allocate FLASH for a new inode data block, we will require that
* space is available to hold this minimum number of data bytes in addition
* to the size of the data block headeer.
*/
#define NXFFS_MINDATA 16
/* Internal definitions *****************************************************/
/* If we encounter this number of erased bytes, we assume that all of the
* flash beyond this point is erased.
*/
#define NXFFS_NERASED 128
/****************************************************************************
* Public Types
****************************************************************************/
/* This structure defines each packed block on the FLASH media */
struct nxffs_block_s
{
uint8_t magic[4]; /* 0-3: Magic number for valid block */
uint8_t state; /* 4: Block state: See BLOCK_STATE_* */
};
#define SIZEOF_NXFFS_BLOCK_HDR 5
/* This structure defines each packed NXFFS inode header on the FLASH media */
struct nxffs_inode_s
{
uint8_t magic[4]; /* 0-3: Magic number for valid inode */
uint8_t state; /* 4: Inode state: See INODE_STATE_* */
uint8_t namlen; /* 5: Length of the inode name */
uint8_t noffs[4]; /* 6-9: FLASH offset to the file name */
uint8_t doffs[4]; /* 10-13: FLASH offset to the first data block */
uint8_t utc[4]; /* 14-17: Creation time */
uint8_t crc[4]; /* 18-21: CRC32 */
uint8_t datlen[4]; /* 22-25: Length of data in bytes */
};
#define SIZEOF_NXFFS_INODE_HDR 26
/* This structure defines each packed NXFFS data header on the FLASH media */
struct nxffs_data_s
{
uint8_t magic[4]; /* 0-3: Magic number for valid data */
uint8_t crc[4]; /* 4-7: CRC32 */
uint8_t datlen[2]; /* 8-9: Length of data in bytes */
};
#define SIZEOF_NXFFS_DATA_HDR 10
/* This is an in-memory representation of the NXFFS inode as extracted from
* FLASH and with additional state information.
*/
struct nxffs_entry_s
{
off_t hoffset; /* FLASH offset to the inode header */
off_t noffset; /* FLASH offset to the inode name */
off_t doffset; /* FLASH offset to the first data header */
FAR char *name; /* inode name */
uint32_t utc; /* Time stamp */
uint32_t datlen; /* Length of inode data */
};
/* This structure describes int in-memory representation of the data block */
struct nxffs_blkentry_s
{
off_t hoffset; /* Offset to the block data header */
uint16_t datlen; /* Length of data following the header */
uint16_t foffset; /* Offset to start of data */
};
/* This structure describes the state of one open file. This structure
* is protected by the volume semaphore.
*/
struct nxffs_ofile_s
{
struct nxffs_ofile_s *flink; /* Supports a singly linked list */
int16_t crefs; /* Reference count */
mode_t oflags; /* Open mode */
struct nxffs_entry_s entry; /* Describes the NXFFS inode entry */
};
/* A file opened for writing require some additional information */
struct nxffs_wrfile_s
{
/* The following fields provide the common open file information. */
struct nxffs_ofile_s ofile;
/* The following fields are required to support the write operation */
bool truncate; /* Delete a file of the same name */
uint16_t datlen; /* Number of bytes written in data block */
off_t doffset; /* FLASH offset to the current data header */
uint32_t crc; /* Accumulated data block CRC */
};
/* This structure represents the overall state of on NXFFS instance. */
struct nxffs_volume_s
{
FAR struct mtd_dev_s *mtd; /* Supports FLASH access */
mutex_t lock; /* Used to assure thread-safe access */
sem_t wrsem; /* Enforces single writer restriction */
struct mtd_geometry_s geo; /* Device geometry */
uint8_t blkper; /* R/W blocks per erase block */
uint16_t iooffset; /* Next offset in read/write access (in ioblock) */
off_t inoffset; /* Offset to the first valid inode header */
off_t froffset; /* Offset to the first free byte */
off_t nblocks; /* Number of R/W blocks on volume */
off_t ioblock; /* Current block number being accessed */
off_t cblock; /* Starting block number in cache */
FAR struct nxffs_ofile_s *ofiles; /* A singly-linked list of open files */
FAR uint8_t *cache; /* On cached erase block for general I/O */
FAR uint8_t *pack; /* A full erase block to support packing */
};
/* This structure describes the state of the blocks on the NXFFS volume */
struct nxffs_blkstats_s
{
off_t nblocks; /* Total number of FLASH blocks */
off_t ngood; /* Number of good FLASH blocks found */
off_t nbad; /* Number of well-formatted FLASH blocks marked as bad */
off_t nunformat; /* Number of unformatted FLASH blocks */
off_t ncorrupt; /* Number of blocks with corrupted format info */
off_t nbadread; /* Number of blocks that could not be read */
};
/****************************************************************************
* Public Data
****************************************************************************/
/* The magic number that appears that the beginning of each NXFFS (logical)
* block
*/
extern const uint8_t g_blockmagic[NXFFS_MAGICSIZE];
/* The magic number that appears that the beginning of each NXFFS inode */
extern const uint8_t g_inodemagic[NXFFS_MAGICSIZE];
/* The magic number that appears that the beginning of each NXFFS inode
* data block.
*/
extern const uint8_t g_datamagic[NXFFS_MAGICSIZE];
/* If CONFIG_NXFFS_PREALLOCATED is defined, then this is the single, pre-
* allocated NXFFS volume instance.
*/
#ifdef CONFIG_NXFFS_PREALLOCATED
extern struct nxffs_volume_s g_volume;
#endif
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
/****************************************************************************
* Name: nxffs_limits
*
* Description:
* Recalculate file system limits: (1) the FLASH offset to the first,
* valid inode, and (2) the FLASH offset to the first, unused byte after
* the last inode (invalid or not).
*
* The first, lower limit must be recalculated: (1) initially, (2)
* whenever the first inode is deleted, or (3) whenever inode is moved
* as part of the file system packing operation.
*
* The second, upper limit must be (1) incremented whenever new file
* data is written, or (2) recalculated as part of the file system packing
* operation.
*
* Input Parameters:
* volume - Identifies the NXFFS volume
*
* Returned Value:
* Zero on success. Otherwise, a negated error is returned indicating the
* nature of the failure.
*
* Defined in nxffs_initialize.c
*
****************************************************************************/
int nxffs_limits(FAR struct nxffs_volume_s *volume);
/****************************************************************************
* Name: nxffs_rdle16
*
* Description:
* Get a (possibly unaligned) 16-bit little endian value.
*
* Input Parameters:
* val - A pointer to the first byte of the little endian value.
*
* Returned Value:
* A uint16_t representing the whole 16-bit integer value
*
* Defined in nxffs_util.c
*
****************************************************************************/
uint16_t nxffs_rdle16(FAR const uint8_t *val);
/****************************************************************************
* Name: nxffs_wrle16
*
* Description:
* Put a (possibly unaligned) 16-bit little endian value.
*
* Input Parameters:
* dest - A pointer to the first byte to save the little endian value.
* val - The 16-bit value to be saved.
*
* Returned Value:
* None
*
* Defined in nxffs_util.c
*
****************************************************************************/
void nxffs_wrle16(uint8_t *dest, uint16_t val);
/****************************************************************************
* Name: nxffs_rdle32
*
* Description:
* Get a (possibly unaligned) 32-bit little endian value.
*
* Input Parameters:
* val - A pointer to the first byte of the little endian value.
*
* Returned Value:
* A uint32_t representing the whole 32-bit integer value
*
* Defined in nxffs_util.c
*
****************************************************************************/
uint32_t nxffs_rdle32(FAR const uint8_t *val);
/****************************************************************************
* Name: nxffs_wrle32
*
* Description:
* Put a (possibly unaligned) 32-bit little endian value.
*
* Input Parameters:
* dest - A pointer to the first byte to save the little endian value.
* val - The 32-bit value to be saved.
*
* Returned Value:
* None
*
* Defined in nxffs_util.c
*
****************************************************************************/
void nxffs_wrle32(uint8_t *dest, uint32_t val);
/****************************************************************************
* Name: nxffs_erased
*
* Description:
* Check if a block of memory is in the erased state.
*
* Input Parameters:
* buffer - Address of the start of the memory to check.
* buflen - The number of bytes to check.
*
* Returned Value:
* The number of erased bytes found at the beginning of the memory region.
*
* Defined in nxffs_util.c
*
****************************************************************************/
size_t nxffs_erased(FAR const uint8_t *buffer, size_t buflen);
/****************************************************************************
* Name: nxffs_rdcache
*
* Description:
* Read one I/O block into the volume cache memory.
*
* Input Parameters:
* volume - Describes the current volume
* block - The first logical block to read
*
* Returned Value:
* Negated errnos are returned only in the case of MTD reported failures.
* Nothing in the volume data itself will generate errors.
*
* Defined in nxffs_cache.c
*
****************************************************************************/
int nxffs_rdcache(FAR struct nxffs_volume_s *volume, off_t block);
/****************************************************************************
* Name: nxffs_wrcache
*
* Description:
* Write one or more logical blocks from the volume cache memory.
*
* Input Parameters:
* volume - Describes the current volume
*
* Returned Value:
* Negated errnos are returned only in the case of MTD reported failures.
*
* Defined in nxffs_cache.c
*
****************************************************************************/
int nxffs_wrcache(FAR struct nxffs_volume_s *volume);
/****************************************************************************
* Name: nxffs_ioseek
*
* Description:
* Seek to a position in FLASH memory. This simply sets up the offsets
* and pointer values. This is a necessary step prior to using
* nxffs_getc().
*
* Input Parameters:
* volume - Describes the NXFFS volume
* offset - The physical offset in bytes from the beginning of the FLASH
* in bytes.
*
* Defined in nxffs_cache.c
*
****************************************************************************/
void nxffs_ioseek(FAR struct nxffs_volume_s *volume, off_t offset);
/****************************************************************************
* Name: nxffs_iotell
*
* Description:
* Report the current position.
*
* Input Parameters:
* volume - Describes the NXFFS volume
*
* Returned Value:
* The offset from the beginning of FLASH to the current seek position.
*
* Defined in nxffs_cache.c
*
****************************************************************************/
off_t nxffs_iotell(FAR struct nxffs_volume_s *volume);
/****************************************************************************
* Name: nxffs_getc
*
* Description:
* Get the next byte from FLASH. This function allows the data in the
* formatted FLASH blocks to be read as a continuous byte stream, skipping
* over bad blocks and block headers as necessary.
*
* Input Parameters:
* volume - Describes the NXFFS volume. The parameters ioblock and iooffset
* in the volume structure determine the behavior of nxffs_getc().
* reserve - If less than this much space is available at the end of the
* block, then skip to the next block.
*
* Returned Value:
* Zero is returned on success. Otherwise, a negated errno indicating the
* nature of the failure.
*
* Defined in nxffs_cache.c
*
****************************************************************************/
int nxffs_getc(FAR struct nxffs_volume_s *volume, uint16_t reserve);
/****************************************************************************
* Name: nxffs_freeentry
*
* Description:
* The inode values returned by nxffs_nextentry() include allocated memory
* (specifically, the file name string). This function should be called
* to dispose of that memory when the inode entry is no longer needed.
*
* Note that the nxffs_entry_s containing structure is not freed. The
* caller may call fs_heap_free upon return of this function if necessary
* to free the entry container.
*
* Input Parameters:
* entry - The entry to be freed.
*
* Returned Value:
* None
*
* Defined in nxffs_inode.c
*
****************************************************************************/
void nxffs_freeentry(FAR struct nxffs_entry_s *entry);
/****************************************************************************
* Name: nxffs_nextentry
*
* Description:
* Search for the next valid inode starting at the provided FLASH offset.
*
* Input Parameters:
* volume - Describes the NXFFS volume.
* offset - The FLASH memory offset to begin searching.
* entry - A pointer to memory provided by the caller in which to return
* the inode description.
*
* Returned Value:
* Zero is returned on success. Otherwise, a negated errno is returned
* that indicates the nature of the failure.
*
* Defined in nxffs_inode.c
*
****************************************************************************/
int nxffs_nextentry(FAR struct nxffs_volume_s *volume, off_t offset,
FAR struct nxffs_entry_s *entry);
/****************************************************************************
* Name: nxffs_findinode
*
* Description:
* Search for an inode with the provided name starting with the first
* valid inode and proceeding to the end FLASH or until the matching
* inode is found.
*
* Input Parameters:
* volume - Describes the NXFFS volume
* name - The name of the inode to find
* entry - The location to return information about the inode.
*
* Returned Value:
* Zero is returned on success. Otherwise, a negated errno is returned
* that indicates the nature of the failure.
*
* Defined in nxffs_inode.c
*
****************************************************************************/
int nxffs_findinode(FAR struct nxffs_volume_s *volume, FAR const char *name,
FAR struct nxffs_entry_s *entry);
/****************************************************************************
* Name: nxffs_inodeend
*
* Description:
* Return an *approximiate* FLASH offset to end of the inode data. The
* returned value is guaranteed to be be less then or equal to the offset
* of the thing-of-interest in FLASH. Parsing for interesting things
* can begin at that point.
*
* Assumption: The inode header has been verified by the caller and is
* known to contain valid data.
*
* Input Parameters:
* volume - Describes the NXFFS volume
* entry - Describes the inode.
*
* Returned Value:
* A FLASH offset to the (approximate) end of the inode data. No errors
* are detected.
*
* Defined in nxffs_inode.c
*
****************************************************************************/
off_t nxffs_inodeend(FAR struct nxffs_volume_s *volume,
FAR struct nxffs_entry_s *entry);
/****************************************************************************
* Name: nxffs_verifyblock
*
* Description:
* Assure that the provided (logical) block number is in the block cache
* and that it has a valid block header (i.e., proper magic and
* marked good)
*
* Input Parameters:
* volume - Describes the NXFFS volume
* block - The (logical) block number to load and verify.
*
* Returned Value:
* OK (zero( is returned on success. Otherwise, a negated errno value is
* returned indicating the nature of the failure:
*
* -EIO is returned if we failed to read the block. If we are using
* NAND memory, then this probably means that the block has
* uncorrectable bit errors.
* -ENOENT is returned if the block is a bad block.
*
* Defined in nxffs_block.c
*
****************************************************************************/
int nxffs_verifyblock(FAR struct nxffs_volume_s *volume, off_t block);
/****************************************************************************
* Name: nxffs_validblock
*
* Description:
* Find the next valid (logical) block in the volume.
*
* Input Parameters:
* volume - Describes the NXFFS volume
* block - On entry, this provides the starting block number. If the
* function is succesfful, then this memory location will hold the
* block number of the next valid block on return.
*
* Returned Value:
* Zero on success otherwise a negated errno value indicating the nature
* of the failure.
*
* Defined in nxffs_block.c
*
****************************************************************************/
int nxffs_validblock(FAR struct nxffs_volume_s *volume, FAR off_t *block);
/****************************************************************************
* Name: nxffs_blockstats
*
* Description:
* Analyze the NXFFS volume. This operation must be performed when the
* volume is first mounted in order to detect if the volume has been
* formatted and contains a usable NXFFS file system.
*
* Input Parameters:
* volume - Describes the current NXFFS volume.
* stats - On return, will hold nformation describing the state of the
* volume.
*
* Returned Value:
* Negated errnos are returned only in the case of MTD reported failures.
* Nothing in the volume data itself will generate errors.
*
* Defined in nxffs_blockstats.c
*
****************************************************************************/
int nxffs_blockstats(FAR struct nxffs_volume_s *volume,
FAR struct nxffs_blkstats_s *stats);
/****************************************************************************
* Name: nxffs_reformat
*
* Description:
* Erase and reformat the entire volume. Verify each block and mark
* improperly erased blocks as bad.
*
* Input Parameters:
* volume - Describes the NXFFS volume to be reformatted.
*
* Returned Value:
* Zero on success or a negated errno on a failure. Failures will be
* returned n the case of MTD reported failures o.
* Nothing in the volume data itself will generate errors.
*
* Defined in nxffs_reformat.c
*
****************************************************************************/
int nxffs_reformat(FAR struct nxffs_volume_s *volume);
/****************************************************************************
* Name: nxffs_blkinit
*
* Description:
* Initialize an NXFFS block to the erased state with the specified block
* status.
*
* Input Parameters:
* volume - Describes the NXFFS volume (needed for the blocksize).
* blkptr - Pointer to the logic block to initialize.
* state - Either BLOCK_STATE_GOOD or BLOCK_STATE_BAD.
*
* Returned Value:
* None.
*
****************************************************************************/
void nxffs_blkinit(FAR struct nxffs_volume_s *volume, FAR uint8_t *blkptr,
uint8_t state);
/****************************************************************************
* Name: nxffs_findofile
*
* Description:
* Search the list of already opened files to see if the inode of this
* name is one of the opened files.
*
* Input Parameters:
* volume - Describes the NXFFS volume.
* name - The name of the inode to check.
*
* Returned Value:
* If an inode of this name is found in the list of opened inodes, then
* a reference to the open file structure is returned. NULL is returned
* otherwise.
*
* Defined in nxffs_open.c
*
****************************************************************************/
FAR struct nxffs_ofile_s *nxffs_findofile(FAR struct nxffs_volume_s *volume,
FAR const char *name);
/****************************************************************************
* Name: nxffs_findwriter
*
* Description:
* Search the list of already opened files and return the open file
* instance for the write.
*
* Input Parameters:
* volume - Describes the NXFFS volume.
*
* Returned Value:
* If there is an active writer of the volume, its open file instance is
* returned. NULL is returned otherwise.
*
* Defined in nxffs_open.c
*
****************************************************************************/
FAR struct nxffs_wrfile_s *
nxffs_findwriter(FAR struct nxffs_volume_s *volume);
/****************************************************************************
* Name: nxffs_wrinode
*
* Description:
* Write the inode header (only to FLASH. This is done in two contexts:
*
* 1. When an inode is closed, or
* 2. As part of the file system packing logic when an inode is moved.
*
* Note that in either case, the inode name has already been written to
* FLASH.
*
* Input Parameters:
* volume - Describes the NXFFS volume
* entry - Describes the inode header to write
*
* Returned Value:
* Zero is returned on success; Otherwise, a negated errno value is
* returned indicating the nature of the failure.
*
* Defined in nxffs_open.c
*
****************************************************************************/
int nxffs_wrinode(FAR struct nxffs_volume_s *volume,
FAR struct nxffs_entry_s *entry);
/****************************************************************************
* Name: nxffs_updateinode
*
* Description:
* The packing logic has moved an inode. Check if any open files are using
* this inode and, if so, move the data in the open file structure as well.
*
* Input Parameters:
* volume - Describes the NXFFS volume
* entry - Describes the new inode entry
*
* Returned Value:
* Zero is returned on success; Otherwise, a negated errno value is
* returned indicating the nature of the failure.
*
****************************************************************************/
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.
*
****************************************************************************/
#ifdef __NO_TRUNCATE_SUPPORT__
int nxffs_wrextend(FAR struct nxffs_volume_s *volume,
FAR struct nxffs_wrfile_s *wrfile, off_t length);
#endif
/****************************************************************************
* Name: nxffs_wrreserve
*
* Description:
* Find a valid location for a file system object of 'size'. A valid
* location will have these properties:
*
* 1. It will lie in the free flash region.
* 2. It will have enough contiguous memory to hold the entire object
* 3. The memory at this location will be fully erased.
*
* This function will only perform the checks of 1) and 2). The
* end-of-filesystem offset, froffset, is update past this memory which,
* in effect, reserves the memory.
*
* Input Parameters:
* volume - Describes the NXFFS volume
* size - The size of the object to be reserved.
*
* Returned Value:
* Zero is returned on success. Otherwise, a negated errno value is
* returned indicating the nature of the failure. Of special interest
* the return error of -ENOSPC which means that the FLASH volume is
* full and should be repacked.
*
* On successful return the following are also valid:
*
* volume->ioblock - Read/write block number of the block containing the
* candidate object position
* volume->iooffset - The offset in the block to the candidate object
* position.
* volume->froffset - Updated offset to the first free FLASH block after
* the reserved memory.
*
* Defined in nxffs_write.c
*
****************************************************************************/
int nxffs_wrreserve(FAR struct nxffs_volume_s *volume, size_t size);
/****************************************************************************
* Name: nxffs_wrverify
*
* Description:
* Find a valid location for the object. A valid location will have
* these properties:
*
* 1. It will lie in the free flash region.
* 2. It will have enough contiguous memory to hold the entire header
* (excluding the file name which may lie in the next block).
* 3. The memory at this location will be fully erased.
*
* This function will only perform the check 3). On entry it assumes the
* following settings (left by nxffs_wrreserve()):
*
* volume->ioblock - Read/write block number of the block containing the
* candidate object position
* volume->iooffset - The offset in the block to the candidate object
* position.
*
* Input Parameters:
* volume - Describes the NXFFS volume
* size - The size of the object to be verified.
*
* Returned Value:
* Zero is returned on success. Otherwise, a negated errno value is
* returned indicating the nature of the failure. Of special interest
* the return error of -ENOSPC which means that the FLASH volume is
* full and should be repacked.
*
* On successful return the following are also valid:
*
* volume->ioblock - Read/write block number of the block containing the
* verified object position
* volume->iooffset - The offset in the block to the verified object
* position.
* volume->froffset - Updated offset to the first free FLASH block.
*
* Defined in nxffs_write.c
*
****************************************************************************/
int nxffs_wrverify(FAR struct nxffs_volume_s *volume, size_t size);
/****************************************************************************
* Name: nxffs_wrblkhdr
*
* Description:
* Write the block header information. This is done (1) whenever the end-
* block is encountered and (2) also when the file is closed in order to
* flush the final block of data to FLASH.
*
* Input Parameters:
* volume - Describes the state of the NXFFS volume
* wrfile - Describes the state of the open file
*
* Returned Value:
* Zero is returned on success; Otherwise, a negated errno value is
* returned to indicate the nature of the failure.
*
* Defined in nxffs_write.c
*
****************************************************************************/
int nxffs_wrblkhdr(FAR struct nxffs_volume_s *volume,
FAR struct nxffs_wrfile_s *wrfile);
/****************************************************************************
* Name: nxffs_nextblock
*
* Description:
* Search for the next valid data block starting at the provided
* FLASH offset.
*
* Input Parameters:
* volume - Describes the NXFFS volume.
* datlen - A memory location to return the data block length.
*
* Returned Value:
* Zero is returned on success. Otherwise, a negated errno is returned
* that indicates the nature of the failure.
*
* Defined in nxffs_read.c
*
****************************************************************************/
int nxffs_nextblock(FAR struct nxffs_volume_s *volume, off_t offset,
FAR struct nxffs_blkentry_s *blkentry);
/****************************************************************************
* Name: nxffs_rdblkhdr
*
* Description:
* Read and verify the data block header at the specified offset.
*
* Input Parameters:
* volume - Describes the current volume.
* offset - The byte offset from the beginning of FLASH where the data
* block header is expected.
* datlen - A memory location to return the data block length.
*
* Returned Value:
* Zero on success. Otherwise, a negated errno value is returned
* indicating the nature of the failure.
*
* Defined in nxffs_read.c
*
****************************************************************************/
int nxffs_rdblkhdr(FAR struct nxffs_volume_s *volume, off_t offset,
FAR uint16_t *datlen);
/****************************************************************************
* Name: nxffs_rminode
*
* Description:
* Remove an inode from FLASH. This is the internal implementation of
* the file system unlink operation.
*
* Input Parameters:
* volume - Describes the NXFFS volume.
* name - the name of the inode to be deleted.
*
* Returned Value:
* Zero is returned if the inode is successfully deleted. Otherwise, a
* negated errno value is returned indicating the nature of the failure.
*
****************************************************************************/
int nxffs_rminode(FAR struct nxffs_volume_s *volume, FAR const char *name);
/****************************************************************************
* Name: nxffs_pack
*
* Description:
* Pack and re-write the filesystem in order to free up memory at the end
* of FLASH.
*
* Input Parameters:
* volume - The volume to be packed.
*
* Returned Value:
* Zero on success; Otherwise, a negated errno value is returned to
* indicate the nature of the failure.
*
****************************************************************************/
int nxffs_pack(FAR struct nxffs_volume_s *volume);
/****************************************************************************
* Standard mountpoint operation methods
*
* Description:
* See include/nuttx/fs/fs.h
*
* - nxffs_open() and nxffs_close() are defined in nxffs_open.c
* - nxffs_read() is defined in nxffs_read.c
* - nxffs_write() is defined in nxffs_write.c
* - nxffs_ioctl() is defined in nxffs_ioctl.c
* - nxffs_dup() is defined in nxffs_open.c
* - nxffs_opendir(), nxffs_readdir(), and nxffs_rewindir() are defined in
* nxffs_dirent.c
* - nxffs_bind() and nxffs_unbind() are defined in nxffs_initialize.c
* - nxffs_stat() and nxffs_statfs() are defined in nxffs_stat.c
* - nxffs_unlink() is defined nxffs_unlink.c
*
****************************************************************************/
struct file; /* Forward references */
struct inode;
struct fs_dirent_s;
struct statfs;
struct stat;
int nxffs_open(FAR struct file *filep, FAR const char *relpath, int oflags,
mode_t mode);
int nxffs_close(FAR struct file *filep);
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_ioctldir(FAR struct inode *mountpt, FAR struct fs_dirent_s *dir,
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);
#ifdef __NO_TRUNCATE_SUPPORT__
int nxffs_truncate(FAR struct file *filep, off_t length);
#endif
int nxffs_opendir(FAR struct inode *mountpt, FAR const char *relpath,
FAR struct fs_dirent_s **dir);
int nxffs_closedir(FAR struct inode *mountpt,
FAR struct fs_dirent_s *dir);
int nxffs_readdir(FAR struct inode *mountpt,
FAR struct fs_dirent_s *dir,
FAR struct dirent *entry);
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,
unsigned int flags);
int nxffs_statfs(FAR struct inode *mountpt, FAR struct statfs *buf);
int nxffs_stat(FAR struct inode *mountpt, FAR const char *relpath,
FAR struct stat *buf);
int nxffs_unlink(FAR struct inode *mountpt, FAR const char *relpath);
#endif /* __FS_NXFFS_NXFFS_H */