mirror of
https://github.com/elua/elua.git
synced 2025-01-25 01:02:54 +08:00
commit
660b29e7a1
@ -18,6 +18,7 @@ return {
|
||||
dhcp = true,
|
||||
xmodem = true,
|
||||
mmcfs = { spi = 0, cs_port = 6, cs_pin = 0 },
|
||||
niffs = { linear_area = true },
|
||||
},
|
||||
config = {
|
||||
vtmr = { num = 4, freq = 4 },
|
||||
|
@ -355,7 +355,7 @@ end )
|
||||
-- Add uIP files manually because not all of them are included in the build ([TODO] why?)
|
||||
local uip_files = " " .. utils.prepend_path( "uip_arp.c uip.c uiplib.c dhcpc.c psock.c resolv.c uip-neighbor.c", "src/uip" )
|
||||
|
||||
addi{ { 'inc', 'inc/newlib', 'inc/remotefs', 'src/platform', 'src/lua' }, { 'src/modules', 'src/platform/' .. platform, 'src/platform/' .. platform .. '/cpus' }, "src/uip", "src/fatfs" }
|
||||
addi{ { 'inc', 'inc/newlib', 'inc/remotefs', 'src/platform', 'src/lua' }, { 'src/modules', 'src/platform/' .. platform, 'src/platform/' .. platform .. '/cpus' }, "src/uip", "src/fatfs", "inc/niffs" }
|
||||
addm( "LUA_OPTIMIZE_MEMORY=" .. ( comp.optram and "2" or "0" ) )
|
||||
addcf( { '-Os','-fomit-frame-pointer' } )
|
||||
|
||||
|
@ -201,6 +201,14 @@ function init()
|
||||
components.romfs = { macro = 'BUILD_ROMFS' }
|
||||
-- WOFS
|
||||
components.wofs = { macro = "BUILD_WOFS" }
|
||||
-- NIFFS
|
||||
components.niffs = {
|
||||
macro = "BUILD_NIFFS",
|
||||
attrs = {
|
||||
linear_area = at.make_optional( at.bool_attr( 'NIFFS_LINEAR_AREA' ) )
|
||||
}
|
||||
}
|
||||
|
||||
-- All done
|
||||
return components
|
||||
end
|
||||
|
@ -39,6 +39,7 @@ local elua_generic_modules = {
|
||||
term = { guards = { "BUILD_TERM" } },
|
||||
tmr = { guards = { "NUM_TIMER > 0" } },
|
||||
uart = { guards = { "NUM_UART > 0" } },
|
||||
fs = { guards = { "BUILD_NIFFS" } }
|
||||
}
|
||||
|
||||
-- All generic modules (Lua and eLua) in a single table
|
||||
|
24
inc/niffs/nffs.h
Normal file
24
inc/niffs/nffs.h
Normal file
@ -0,0 +1,24 @@
|
||||
// Filesystem implementation
|
||||
#include "romfs.h"
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include "romfiles.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "ioctl.h"
|
||||
#include <fcntl.h>
|
||||
#include "platform.h"
|
||||
#include "platform_conf.h"
|
||||
#include "niffs.h"
|
||||
|
||||
#ifndef NFFS_H_
|
||||
#define NFFS_H_
|
||||
|
||||
int nffs_init( void );
|
||||
int nffs_format(s32_t linear_bytes);
|
||||
int nffs_mount();
|
||||
int nffs_unmount();
|
||||
int nffs_check();
|
||||
int nffs_info(s32_t *total, s32_t *used, u8_t *overflow, s32_t *lin_total, s32_t *lin_used, s32_t *lin_free);
|
||||
|
||||
#endif /* NFFS_H_ */
|
457
inc/niffs/niffs.h
Normal file
457
inc/niffs/niffs.h
Normal file
@ -0,0 +1,457 @@
|
||||
/*
|
||||
* niffs.h
|
||||
*
|
||||
* Created on: Feb 2, 2015
|
||||
* Author: petera
|
||||
*/
|
||||
|
||||
#ifndef NIFFS_H_
|
||||
#define NIFFS_H_
|
||||
|
||||
#include "niffs_config.h"
|
||||
|
||||
#define NIFFS_SEEK_SET (0)
|
||||
#define NIFFS_SEEK_CUR (1)
|
||||
#define NIFFS_SEEK_END (2)
|
||||
|
||||
/* Any write to the filehandle is appended to end of the file */
|
||||
#define NIFFS_O_APPEND (1<<0)
|
||||
/* If the opened file exists, it will be truncated to zero length before opened */
|
||||
#define NIFFS_O_TRUNC (1<<1)
|
||||
/* If the opened file does not exist, it will be created before opened */
|
||||
#define NIFFS_O_CREAT (1<<2)
|
||||
/* The opened file may only be read */
|
||||
#define NIFFS_O_RDONLY (1<<3)
|
||||
/* The opened file may only be writted */
|
||||
#define NIFFS_O_WRONLY (1<<4)
|
||||
/* The opened file may be both read and written */
|
||||
#define NIFFS_O_RDWR (NIFFS_O_RDONLY | NIFFS_O_WRONLY)
|
||||
/* Any writes to the filehandle will never be cached */
|
||||
#define NIFFS_O_DIRECT (1<<5)
|
||||
/* If O_CREAT and O_EXCL are set, open() fails if the file exists. */
|
||||
#define NIFFS_O_EXCL (1<<6)
|
||||
/* If O_CREAT and O_LINEAR is enabled, along with config NIFFS_LINEAR_AREA,
|
||||
the created file will be put in the linear area */
|
||||
#define NIFFS_O_LINEAR (1<<7)
|
||||
|
||||
#ifndef NIFFS_ERR_BASE
|
||||
#define NIFFS_ERR_BASE (11000)
|
||||
#endif
|
||||
|
||||
#define NIFFS_OK 0
|
||||
#define ERR_NIFFS_BAD_CONF -(NIFFS_ERR_BASE + 1)
|
||||
#define ERR_NIFFS_NOT_A_FILESYSTEM -(NIFFS_ERR_BASE + 2)
|
||||
#define ERR_NIFFS_BAD_SECTOR -(NIFFS_ERR_BASE + 3)
|
||||
#define ERR_NIFFS_DELETING_FREE_PAGE -(NIFFS_ERR_BASE + 4)
|
||||
#define ERR_NIFFS_DELETING_DELETED_PAGE -(NIFFS_ERR_BASE + 5)
|
||||
#define ERR_NIFFS_MOVING_FREE_PAGE -(NIFFS_ERR_BASE + 6)
|
||||
#define ERR_NIFFS_MOVING_DELETED_PAGE -(NIFFS_ERR_BASE + 7)
|
||||
#define ERR_NIFFS_MOVING_TO_UNFREE_PAGE -(NIFFS_ERR_BASE + 8)
|
||||
#define ERR_NIFFS_MOVING_TO_SAME_PAGE -(NIFFS_ERR_BASE + 9)
|
||||
#define ERR_NIFFS_MOVING_BAD_FLAG -(NIFFS_ERR_BASE + 10)
|
||||
#define ERR_NIFFS_NO_FREE_PAGE -(NIFFS_ERR_BASE + 11)
|
||||
#define ERR_NIFFS_SECTOR_UNFORMATTABLE -(NIFFS_ERR_BASE + 12)
|
||||
#define ERR_NIFFS_NULL_PTR -(NIFFS_ERR_BASE + 13)
|
||||
#define ERR_NIFFS_NO_FREE_ID -(NIFFS_ERR_BASE + 14)
|
||||
#define ERR_NIFFS_WR_PHDR_UNFREE_PAGE -(NIFFS_ERR_BASE + 15)
|
||||
#define ERR_NIFFS_WR_PHDR_BAD_ID -(NIFFS_ERR_BASE + 16)
|
||||
#define ERR_NIFFS_NAME_CONFLICT -(NIFFS_ERR_BASE + 17)
|
||||
#define ERR_NIFFS_FULL -(NIFFS_ERR_BASE + 18)
|
||||
#define ERR_NIFFS_OUT_OF_FILEDESCS -(NIFFS_ERR_BASE + 19)
|
||||
#define ERR_NIFFS_FILE_NOT_FOUND -(NIFFS_ERR_BASE + 20)
|
||||
#define ERR_NIFFS_FILEDESC_CLOSED -(NIFFS_ERR_BASE + 21)
|
||||
#define ERR_NIFFS_FILEDESC_BAD -(NIFFS_ERR_BASE + 22)
|
||||
#define ERR_NIFFS_INCOHERENT_ID -(NIFFS_ERR_BASE + 23)
|
||||
#define ERR_NIFFS_PAGE_NOT_FOUND -(NIFFS_ERR_BASE + 24)
|
||||
#define ERR_NIFFS_END_OF_FILE -(NIFFS_ERR_BASE + 25)
|
||||
#define ERR_NIFFS_MODIFY_BEYOND_FILE -(NIFFS_ERR_BASE + 26)
|
||||
#define ERR_NIFFS_TRUNCATE_BEYOND_FILE -(NIFFS_ERR_BASE + 27)
|
||||
#define ERR_NIFFS_NO_GC_CANDIDATE -(NIFFS_ERR_BASE + 28)
|
||||
#define ERR_NIFFS_PAGE_DELETED -(NIFFS_ERR_BASE + 29)
|
||||
#define ERR_NIFFS_PAGE_FREE -(NIFFS_ERR_BASE + 30)
|
||||
#define ERR_NIFFS_MOUNTED -(NIFFS_ERR_BASE + 31)
|
||||
#define ERR_NIFFS_NOT_MOUNTED -(NIFFS_ERR_BASE + 32)
|
||||
#define ERR_NIFFS_NOT_WRITABLE -(NIFFS_ERR_BASE + 33)
|
||||
#define ERR_NIFFS_NOT_READABLE -(NIFFS_ERR_BASE + 34)
|
||||
#define ERR_NIFFS_FILE_EXISTS -(NIFFS_ERR_BASE + 35)
|
||||
#define ERR_NIFFS_OVERFLOW -(NIFFS_ERR_BASE + 36)
|
||||
#define ERR_NIFFS_LINEAR_FILE -(NIFFS_ERR_BASE + 37)
|
||||
#define ERR_NIFFS_LINEAR_NO_SPACE -(NIFFS_ERR_BASE + 38)
|
||||
|
||||
typedef int (* niffs_hal_erase_f)(u8_t *addr, u32_t len);
|
||||
typedef int (* niffs_hal_write_f)(u8_t *addr, const u8_t *src, u32_t len);
|
||||
// dummy type, for posix compliance
|
||||
typedef u16_t niffs_mode;
|
||||
// niffs file descriptor flags
|
||||
typedef u8_t niffs_fd_flags;
|
||||
// niffs file type
|
||||
typedef u8_t niffs_file_type;
|
||||
|
||||
/* file descriptor */
|
||||
typedef struct {
|
||||
// object id
|
||||
niffs_obj_id obj_id;
|
||||
// page index for object index
|
||||
niffs_page_ix obj_pix;
|
||||
// file type
|
||||
niffs_file_type type;
|
||||
// file descriptor offset
|
||||
u32_t offs;
|
||||
// page index for current file desc offset
|
||||
niffs_page_ix cur_pix;
|
||||
// file descriptor flags
|
||||
niffs_fd_flags flags;
|
||||
} niffs_file_desc;
|
||||
|
||||
/* fs struct */
|
||||
typedef struct {
|
||||
/* static cfg */
|
||||
// physical address where fs resides
|
||||
u8_t *phys_addr;
|
||||
// number of logical sectors
|
||||
u32_t sectors;
|
||||
// logical sector size in bytes
|
||||
u32_t sector_size;
|
||||
// logical page size in bytes
|
||||
u32_t page_size;
|
||||
#if NIFFS_LINEAR_AREA
|
||||
// number of linear sectors
|
||||
u32_t lin_sectors;
|
||||
#endif
|
||||
|
||||
// work buffer
|
||||
u8_t *buf;
|
||||
// work buffer length
|
||||
u32_t buf_len;
|
||||
|
||||
// HAL write function
|
||||
niffs_hal_write_f hal_wr;
|
||||
// HAL erase function
|
||||
niffs_hal_erase_f hal_er;
|
||||
|
||||
/* dynamics */
|
||||
// pages per sector
|
||||
u32_t pages_per_sector;
|
||||
// last seen free page index
|
||||
niffs_page_ix last_free_pix;
|
||||
// whether mounted or not
|
||||
u8_t mounted;
|
||||
// number of free pages
|
||||
u32_t free_pages;
|
||||
// number of deleted pages
|
||||
u32_t dele_pages;
|
||||
// file descriptor array
|
||||
niffs_file_desc *descs;
|
||||
// number of file descriptors
|
||||
u32_t descs_len;
|
||||
// max erase count
|
||||
niffs_erase_cnt max_era;
|
||||
} niffs;
|
||||
|
||||
/* niffs file status struct */
|
||||
typedef struct {
|
||||
// file object id
|
||||
niffs_obj_id obj_id;
|
||||
// file size
|
||||
u32_t size;
|
||||
// file name
|
||||
u8_t name[NIFFS_NAME_LEN];
|
||||
// file type
|
||||
niffs_file_type type;
|
||||
} niffs_stat;
|
||||
|
||||
/* niffs file directory entry struct */
|
||||
struct niffs_dirent {
|
||||
// file object id
|
||||
niffs_obj_id obj_id;
|
||||
// file name
|
||||
u8_t name[NIFFS_NAME_LEN];
|
||||
// file size
|
||||
u32_t size;
|
||||
// file index header whereabouts
|
||||
niffs_page_ix pix;
|
||||
// file type
|
||||
niffs_file_type type;
|
||||
};
|
||||
|
||||
/* niffs file directory struct */
|
||||
typedef struct {
|
||||
// the actual fs
|
||||
niffs *fs;
|
||||
// current search page index
|
||||
niffs_page_ix pix;
|
||||
} niffs_DIR;
|
||||
|
||||
/* niffs fs info struct */
|
||||
typedef struct {
|
||||
/* total amount of bytes in filesystem (linear parts excluded) */
|
||||
s32_t total_bytes;
|
||||
/* used bytes in filesystem (linear parts excluded) */
|
||||
s32_t used_bytes;
|
||||
/* If non-zero, this means you should delete some files and run a check.
|
||||
This can happen if filesystem loses power repeatedly during
|
||||
garbage collection or check. */
|
||||
u8_t overflow;
|
||||
|
||||
/* total amount of sectors in the linear part of filesystem */
|
||||
s32_t lin_total_sectors;
|
||||
/* used sectors in the linear part of filesystem */
|
||||
s32_t lin_used_sectors;
|
||||
/* maximum free consecutive area in the linear part of filesystem */
|
||||
s32_t lin_max_conseq_free;
|
||||
} niffs_info;
|
||||
|
||||
/**
|
||||
* Initializes and configures the file system.
|
||||
* The file system needs a ram work buffer being at least a logical page size
|
||||
* big. In some cases, this needs to be extended. NIFFS will return
|
||||
* ERR_NIFFS_BAD_CONF on bad configurations. If NIFFS_DBG is enabled, a
|
||||
* descriptive message will also tell you what's wrong.
|
||||
*
|
||||
* @param fs the file system struct
|
||||
* @param phys_addr the starting address of the filesystem on flash
|
||||
* @param sectors number of sectors comprised by the filesystem
|
||||
* @param sector_size logical sector size
|
||||
* @param page_size logical page size
|
||||
* @param buf ram work buffer
|
||||
* @param buf_len ram work buffer length
|
||||
* @param descs ram file descriptor buffer
|
||||
* @param file_desc_len number of file descriptors in buffer
|
||||
* @param erase_f HAL erase function
|
||||
* @param write_f HAL write function
|
||||
* @param lin_sectors Ignored if NIFFS_LINEAR_AREA is 0. Otherwise, allocates
|
||||
* lin_sectors of space for the linear area. This space
|
||||
* will be allotted after the dynamic fs.
|
||||
*/
|
||||
int NIFFS_init(niffs *fs,
|
||||
u8_t *phys_addr,
|
||||
u32_t sectors,
|
||||
u32_t sector_size,
|
||||
u32_t page_size,
|
||||
u8_t *buf,
|
||||
u32_t buf_len,
|
||||
niffs_file_desc *descs,
|
||||
u32_t file_desc_len,
|
||||
niffs_hal_erase_f erase_f,
|
||||
niffs_hal_write_f write_f,
|
||||
u32_t lin_sectors
|
||||
);
|
||||
|
||||
/**
|
||||
* Mounts the filesystem
|
||||
* @param fs the file system struct
|
||||
*/
|
||||
int NIFFS_mount(niffs *fs);
|
||||
|
||||
/**
|
||||
* Returns some general info
|
||||
* @param fs the file system struct
|
||||
* @param total will be populated with total amount of bytes in filesystem
|
||||
* @param used will be populated with used bytes in filesystem
|
||||
* @param overflow if !0, this means you should delete some files and run a check.
|
||||
* This can happen if filesystem loses power repeatedly during
|
||||
* garbage collection or check.
|
||||
*/
|
||||
int NIFFS_info(niffs *fs, niffs_info *i);
|
||||
|
||||
/**
|
||||
* Creates a new file.
|
||||
* @param fs the file system struct
|
||||
* @param name the name of the new file
|
||||
* @param mode ignored, for posix compliance
|
||||
*/
|
||||
int NIFFS_creat(niffs *fs, const char *name, niffs_mode mode);
|
||||
|
||||
#if NIFFS_LINEAR_AREA
|
||||
/**
|
||||
* Creates a new file in the linear area.
|
||||
* @param fs the file system struct
|
||||
* @param name the name of the new file
|
||||
* @param resv_size Hint to the filesystem how large this file will be in
|
||||
* bytes. May be 0 if not known.
|
||||
* As linear files cannot be chunked up by pages, they
|
||||
* will be placed after each other on medium. For example,
|
||||
* when creating linear file A it will be placed on
|
||||
* sector x. If creating linear file B directly afterwards,
|
||||
* B will be placed on sector x+1. This constricts file A
|
||||
* to grow one sector only. However, if A is created with
|
||||
* resv_size of 10 sectors, B will be created on sector
|
||||
* x+10, giving A room to grow 10 sectors instead.
|
||||
* @return file descriptor with flags O_LINEAR | O_RDWR | O_APPEND or error
|
||||
*/
|
||||
int NIFFS_mknod_linear(niffs *fs, const char *name, u32_t resv_size);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Opens/creates a file.
|
||||
* @param fs the file system struct
|
||||
* @param path the path of the new file
|
||||
* @param flags the flags for the open command, can be combinations of
|
||||
* NIFFS_O_APPEND, NIFFS_O_TRUNC, NIFFS_O_CREAT, NIFFS_O_RDONLY,
|
||||
* NIFFS_O_WRONLY, NIFFS_O_RDWR, NIFFS_O_DIRECT, NIFFS_O_LINEAR
|
||||
* @param mode ignored, for posix compliance
|
||||
* @return file descriptor or error
|
||||
*
|
||||
* Note: when creating files with NIFFS_O_LINEAR, NIFFS_O_APPEND is
|
||||
* automatically set. Linear files cannot be modified, only appended.
|
||||
*/
|
||||
int NIFFS_open(niffs *fs, const char *name, u8_t flags, niffs_mode mode);
|
||||
|
||||
/**
|
||||
* Returns a pointer directly to the flash where data resides, and how many
|
||||
* bytes which can be read.
|
||||
* This function does not advance the file descriptor offset, so NIFFS_lseek
|
||||
* should be called prior to NIFFS_read_ptr.
|
||||
* @param fs the file system struct
|
||||
* @param fd the filehandle
|
||||
* @param ptr ptr which is populated with adress to data
|
||||
* @param len populated with valid data length
|
||||
*/
|
||||
int NIFFS_read_ptr(niffs *fs, int fd, u8_t **ptr, u32_t *len);
|
||||
|
||||
/**
|
||||
* Reads from given filehandle.
|
||||
* NB: consider using NIFFS_read_ptr instead. This will basically copy from your
|
||||
* internal flash to your ram. If you're only interested in reading data and not
|
||||
* modifying it, this will basically waste cycles and ram on memcpy.
|
||||
* @param fs the file system struct
|
||||
* @param fd the filehandle
|
||||
* @param buf where to put read data
|
||||
* @param len how much to read
|
||||
* @returns number of bytes read, or error
|
||||
*/
|
||||
int NIFFS_read(niffs *fs, int fd, u8_t *dst, u32_t len);
|
||||
|
||||
/**
|
||||
* Moves the read/write file offset
|
||||
* @param fs the file system struct
|
||||
* @param fh the filehandle
|
||||
* @param offs how much/where to move the offset
|
||||
* @param whence if NIFFS_SEEK_SET, the file offset shall be set to offset bytes
|
||||
* if NIFFS_SEEK_CUR, the file offset shall be set to its current location plus offset
|
||||
* if NIFFS_SEEK_END, the file offset shall be set to the size of the file plus offset
|
||||
*/
|
||||
int NIFFS_lseek(niffs *fs, int fd, s32_t offs, int whence);
|
||||
|
||||
/**
|
||||
* Removes a file by name
|
||||
* @param fs the file system struct
|
||||
* @param name the name of the file to remove
|
||||
*/
|
||||
int NIFFS_remove(niffs *fs, const char *name);
|
||||
|
||||
/**
|
||||
* Removes a file by filehandle
|
||||
* @param fs the file system struct
|
||||
* @param fd the filehandle of the file to remove
|
||||
*/
|
||||
int NIFFS_fremove(niffs *fs, int fd);
|
||||
|
||||
/**
|
||||
* Writes to given filehandle.
|
||||
* @param fs the file system struct
|
||||
* @param fd the filehandle
|
||||
* @param buf the data to write
|
||||
* @param len how much to write
|
||||
* @returns number of bytes written or error
|
||||
*/
|
||||
int NIFFS_write(niffs *fs, int fd, const u8_t *data, u32_t len);
|
||||
|
||||
/**
|
||||
* Flushes all pending write operations from cache for given file
|
||||
* @param fs the file system struct
|
||||
* @param fd the filehandle of the file to flush
|
||||
*/
|
||||
int NIFFS_fflush(niffs *fs, int fd);
|
||||
|
||||
/**
|
||||
* Gets file status by name
|
||||
* @param fs the file system struct
|
||||
* @param path the name of the file to stat
|
||||
* @param s the stat struct to populate
|
||||
*/
|
||||
int NIFFS_stat(niffs *fs, const char *name, niffs_stat *s);
|
||||
|
||||
/**
|
||||
* Gets file status by filehandle
|
||||
* @param fs the file system struct
|
||||
* @param fd the filehandle of the file to stat
|
||||
* @param s the stat struct to populate
|
||||
*/
|
||||
int NIFFS_fstat(niffs *fs, int fd, niffs_stat *s);
|
||||
|
||||
/**
|
||||
* Gets current position in stream
|
||||
* @param fs the file system struct
|
||||
* @param fd the filehandle of the file to return position from
|
||||
*/
|
||||
int NIFFS_ftell(niffs *fs, int fd);
|
||||
|
||||
/**
|
||||
* Closes a filehandle. If there are pending write operations, these are finalized before closing.
|
||||
* @param fs the file system struct
|
||||
* @param fd the filehandle of the file to close
|
||||
*/
|
||||
int NIFFS_close(niffs *fs, int fd);
|
||||
|
||||
/**
|
||||
* Renames a file.
|
||||
* @param fs the file system struct
|
||||
* @param old name of file to rename
|
||||
* @param new new name of file
|
||||
*/
|
||||
int NIFFS_rename(niffs *fs, const char *old_name, const char *new_name);
|
||||
|
||||
/**
|
||||
* Opens a directory stream corresponding to the given name.
|
||||
* The stream is positioned at the first entry in the directory.
|
||||
* The name argument is ignored as hydrogen builds always correspond
|
||||
* to a flat file structure - no directories.
|
||||
* @param fs the file system struct
|
||||
* @param name the name of the directory
|
||||
* @param d pointer the directory stream to be populated
|
||||
*/
|
||||
niffs_DIR *NIFFS_opendir(niffs *fs, const char *name, niffs_DIR *d);
|
||||
|
||||
/**
|
||||
* Closes a directory stream
|
||||
* @param d the directory stream to close
|
||||
*/
|
||||
int NIFFS_closedir(niffs_DIR *d);
|
||||
|
||||
/**
|
||||
* Reads a directory into given niffs_dirent struct.
|
||||
* @param d pointer to the directory stream
|
||||
* @param e the dirent struct to be populated
|
||||
* @returns null if error or end of stream, else given dirent is returned
|
||||
*/
|
||||
struct niffs_dirent *NIFFS_readdir(niffs_DIR *d, struct niffs_dirent *e);
|
||||
|
||||
/**
|
||||
* Unmounts the file system. All file handles will be flushed of any
|
||||
* cached writes and closed.
|
||||
* @param fs the file system struct
|
||||
*/
|
||||
int NIFFS_unmount(niffs *fs);
|
||||
|
||||
/**
|
||||
* Formats the entire filesystem.
|
||||
* @param fs the file system struct
|
||||
*/
|
||||
int NIFFS_format(niffs *fs);
|
||||
|
||||
/**
|
||||
* Runs a consistency check on given filesystem and mends any aborted operations.
|
||||
* @param fs the file system struct
|
||||
*/
|
||||
int NIFFS_chk(niffs *fs);
|
||||
|
||||
#ifdef NIFFS_DUMP
|
||||
/**
|
||||
* Prints out a visualization of the filesystem.
|
||||
* @param fs the file system struct
|
||||
*/
|
||||
void NIFFS_dump(niffs *fs);
|
||||
#endif
|
||||
|
||||
#endif /* NIFFS_H_ */
|
200
inc/niffs/niffs_config.h
Normal file
200
inc/niffs/niffs_config.h
Normal file
@ -0,0 +1,200 @@
|
||||
/*
|
||||
* niffs_config.h
|
||||
*
|
||||
* Created on: Feb 3, 2015
|
||||
* Author: petera
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef NIFFS_CONFIG_H_
|
||||
#define NIFFS_CONFIG_H_
|
||||
|
||||
#include "lua.h"
|
||||
#include "lualib.h"
|
||||
#include "lauxlib.h"
|
||||
#include "platform.h"
|
||||
#include "lrotable.h"
|
||||
#include "common.h"
|
||||
#include "sermux.h"
|
||||
#include "platform_conf.h"
|
||||
#include "utils.h"
|
||||
#include "elua_int.h"
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
//#define u8_t uint8_t
|
||||
//#define i16_t int16_t
|
||||
|
||||
//typedef int16_t Int16;
|
||||
//typedef u16 UInt16;
|
||||
//typedef u32 UInt32;
|
||||
//typedef int32_t Int32;
|
||||
|
||||
//typedef u8 u8_t;
|
||||
//typedef u16 u16_t;
|
||||
//typedef u32 u32_t;
|
||||
//typedef s32 s32_t;
|
||||
|
||||
#define u8_t uint8_t
|
||||
#define u16_t uint16_t
|
||||
#define u32_t uint32_t
|
||||
#define s32_t int32_t
|
||||
|
||||
//#define NIFFS_DEBUG 1
|
||||
//#define NIFFS_DBG(...) if (NIFFS_DEBUG) printf(__VA_ARGS__)
|
||||
|
||||
#ifdef NIFFS_TEST_MAKE
|
||||
#include "niffs_test_config.h"
|
||||
#endif
|
||||
|
||||
// for testing
|
||||
#ifndef TESTATIC
|
||||
#define TESTATIC static
|
||||
#endif
|
||||
|
||||
// define for getting niffs debug output
|
||||
#ifndef NIFFS_DBG
|
||||
#define NIFFS_DBG(_f, ...)
|
||||
#endif
|
||||
|
||||
// define NIFFS_DUMP to be able to visualize filesystem with NIFFS_dump
|
||||
//#define NIFFS_DUMP
|
||||
#ifdef NIFFS_DUMP
|
||||
#ifndef NIFFS_DUMP_OUT
|
||||
// used to output in NIFFS_dump
|
||||
#define NIFFS_DUMP_OUT(_f, ...)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// max macro
|
||||
#ifndef NIFFS_MAX
|
||||
#define NIFFS_MAX(x, y) UMAX(x,y)
|
||||
#endif
|
||||
|
||||
// min macro
|
||||
#ifndef NIFFS_MIN
|
||||
#define NIFFS_MIN(x, y) UMIN(x,y)
|
||||
#endif
|
||||
|
||||
// define for assertions within niffs
|
||||
#ifndef NIFFS_ASSERT
|
||||
#define NIFFS_ASSERT(x)
|
||||
#endif
|
||||
|
||||
// define maximum name length
|
||||
#ifndef NIFFS_NAME_LEN
|
||||
#define NIFFS_NAME_LEN (16)
|
||||
#endif
|
||||
|
||||
// Enable or disable linear area features.
|
||||
// Files in the linear area are not divided by page headers but are linear on
|
||||
// medium. To create a linear file, pass NIFFS_O_CREAT and NIFFS_O_CREAT_LINEAR
|
||||
// when creating the file with open.
|
||||
// To have more control over the linear file, NIFFS_mknod_linear can also be
|
||||
// called, see corresponding function for more info.
|
||||
// The linear area is not wear leveled. Once a linear file is deleted,
|
||||
// corresponding sectors are immediately erased.
|
||||
// This implies that each linear file will at least occupy one sector, even if
|
||||
// the size is 0.
|
||||
// Linear files can only be appended, never modified. Defragmentation of the
|
||||
// linear area is up to the user.
|
||||
#ifndef NIFFS_LINEAR_AREA
|
||||
#define NIFFS_LINEAR_AREA (1)
|
||||
#endif
|
||||
|
||||
// define number of bits used for object ids, used for uniquely identify a file
|
||||
#ifndef NIFFS_OBJ_ID_BITS
|
||||
#define NIFFS_OBJ_ID_BITS (16)
|
||||
#endif
|
||||
|
||||
// define number of bits used for span indices, used for uniquely identify part of a file
|
||||
#ifndef NIFFS_SPAN_IX_BITS
|
||||
#define NIFFS_SPAN_IX_BITS (16)
|
||||
#endif
|
||||
|
||||
// word align for target flash, e.g. stm32f1 can only write 16-bit words at a time
|
||||
// from SiM33U1xx-SiM3C1xx-RM.pdf p.380 para.21.4.2 "Writes to WRDATA must be half-word aligned"
|
||||
#ifndef NIFFS_WORD_ALIGN
|
||||
#define NIFFS_WORD_ALIGN (4)
|
||||
#endif
|
||||
|
||||
// garbage collection uses a score system to select sector to erase:
|
||||
// sector_score = sector_erase_difference * F1 + free_pages * F2 + deleted_pages * F3 + busy_pages * F4
|
||||
// sector with highest score is selected for garbage collection
|
||||
|
||||
// F1: garbage collection score factor for sector erase difference
|
||||
#ifndef NIFFS_GC_SCORE_ERASE_CNT_DIFF
|
||||
#define NIFFS_GC_SCORE_ERASE_CNT_DIFF (100)
|
||||
#endif
|
||||
// F2: garbage collection score factor for percentage of free pages in sector
|
||||
#ifndef NIFFS_GC_SCORE_FREE
|
||||
#define NIFFS_GC_SCORE_FREE (-4)
|
||||
#endif
|
||||
// F3: garbage collection score factor for percentage of deleted pages in sector
|
||||
#ifndef NIFFS_GC_SCORE_DELE
|
||||
#define NIFFS_GC_SCORE_DELE (2)
|
||||
#endif
|
||||
// F4: garbage collection score factor for percentage of busy/written pages in sector
|
||||
#ifndef NIFFS_GC_SCORE_BUSY
|
||||
#define NIFFS_GC_SCORE_BUSY (-2)
|
||||
#endif
|
||||
|
||||
// formula for selecting sector to garbage collect
|
||||
// free, dele and busy is the percentage (0-99) of each type
|
||||
#ifndef NIFFS_GC_SCORE
|
||||
#define NIFFS_GC_SCORE(era_cnt_diff, free, dele, busy) \
|
||||
((era_cnt_diff) * NIFFS_GC_SCORE_ERASE_CNT_DIFF) + \
|
||||
((free) * NIFFS_GC_SCORE_FREE) + \
|
||||
((dele) * NIFFS_GC_SCORE_DELE) + \
|
||||
((busy) * NIFFS_GC_SCORE_BUSY)
|
||||
#endif
|
||||
|
||||
// type sizes, depend of the size of the filesystem and the size of the pages
|
||||
|
||||
// must comprise NIFFS_OBJ_ID_BITS
|
||||
#ifndef NIFFS_TYPE_OBJ_ID_SIZE
|
||||
#define NIFFS_TYPE_OBJ_ID_SIZE u16_t
|
||||
#endif
|
||||
|
||||
// must comprise NIFFS_SPAN_IX_BITS
|
||||
#ifndef NIFFS_TYPE_SPAN_IX_SIZE
|
||||
#define NIFFS_TYPE_SPAN_IX_SIZE u16_t
|
||||
#endif
|
||||
|
||||
// must comprise (NIFFS_OBJ_ID_BITS + NIFFS_SPAN_IX_BITS)
|
||||
#ifndef NIFFS_TYPE_RAW_PAGE_ID_SIZE
|
||||
#define NIFFS_TYPE_RAW_PAGE_ID_SIZE u32_t
|
||||
#endif
|
||||
|
||||
// must uniquely address all pages
|
||||
#ifndef NIFFS_TYPE_PAGE_IX_SIZE
|
||||
#define NIFFS_TYPE_PAGE_IX_SIZE u32_t
|
||||
#endif
|
||||
|
||||
// magic bits, must be sized on alignment, NIFFS_WORD_ALIGN
|
||||
#ifndef NIFFS_TYPE_MAGIC_SIZE
|
||||
#define NIFFS_TYPE_MAGIC_SIZE u32_t
|
||||
#endif
|
||||
|
||||
// sector erase counter, must be sized on alignment, NIFFS_WORD_ALIGN
|
||||
#ifndef NIFFS_TYPE_ERASE_COUNT_SIZE
|
||||
#define NIFFS_TYPE_ERASE_COUNT_SIZE u32_t
|
||||
#endif
|
||||
|
||||
// page flag, 3 values, must be sized on alignment, NIFFS_WORD_ALIGN
|
||||
#ifndef NIFFS_TYPE_PAGE_FLAG_SIZE
|
||||
#define NIFFS_TYPE_PAGE_FLAG_SIZE u32_t
|
||||
#endif
|
||||
|
||||
typedef NIFFS_TYPE_OBJ_ID_SIZE niffs_obj_id;
|
||||
typedef NIFFS_TYPE_SPAN_IX_SIZE niffs_span_ix;
|
||||
typedef NIFFS_TYPE_RAW_PAGE_ID_SIZE niffs_page_id_raw;
|
||||
typedef NIFFS_TYPE_PAGE_IX_SIZE niffs_page_ix;
|
||||
typedef NIFFS_TYPE_MAGIC_SIZE niffs_magic;
|
||||
typedef NIFFS_TYPE_ERASE_COUNT_SIZE niffs_erase_cnt;
|
||||
typedef NIFFS_TYPE_PAGE_FLAG_SIZE niffs_flag;
|
||||
|
||||
#endif /* NIFFS_CONFIG_H_ */
|
282
inc/niffs/niffs_internal.h
Normal file
282
inc/niffs/niffs_internal.h
Normal file
@ -0,0 +1,282 @@
|
||||
/*
|
||||
* niffs_internal.h
|
||||
*
|
||||
* FLASH LAYOUT
|
||||
* SECTOR:
|
||||
* <sector header size> <page size> <page size>
|
||||
* | niffs_sector_hdr | niffs_page_hdr : data | niffs_page_hdr : data | ... | fill |
|
||||
* | magic : era_cnt | id : flag | .... | id : flag | .... | ...
|
||||
* | | \ obj_id | \ obj_id |
|
||||
* | | \ spix | \ spix |
|
||||
*
|
||||
* Page status:
|
||||
* FREE niffs_page_hdr.id 0xff..
|
||||
* DELE niffs_page_hdr.id 0x0
|
||||
* USED niffs_page_hdr.id != 0 && != 0xff..
|
||||
* CLEA niffs_page_hdr.flag 0xff..
|
||||
* WRIT niffs_page_hdr.flag 0x1
|
||||
* MOVI niffs_page_hdr.flag 0x0
|
||||
*
|
||||
* Free pages:
|
||||
* FREE & CLEA
|
||||
* Allocated pages:
|
||||
* USED
|
||||
* USED & CLEA : allocated but not yet written (semi bad)
|
||||
* USED & WRIT : allocated and written
|
||||
* USED & MOVI : allocated and being moved/updated
|
||||
* Bad pages:
|
||||
* FREE & WRIT : not allowed
|
||||
* FREE & MOVI : not allowed
|
||||
*
|
||||
* A page life cycle: FREE->CLEAN(->WRITN(->MOVIN))->DELE->FREE
|
||||
*
|
||||
* Object header:
|
||||
* niffs_page_hdr.id != 0 && != 0xff..
|
||||
* niffs_page_hdr.id.spix 0
|
||||
*
|
||||
* Invalid object_ids are 0 and 0xff..
|
||||
*
|
||||
* File creation:
|
||||
* write phdr.flag
|
||||
* write phdr.id
|
||||
* ----- page now allocated
|
||||
* write ohdr (len = -1)
|
||||
* ----- file now created, size 0
|
||||
*
|
||||
* File open:
|
||||
* * aborted append / updated length:
|
||||
* If obj header is MOVI:
|
||||
* try finding a WRIT obj header with id,
|
||||
* use this if found, delete MOVI. Else, copy MOVI as WRIT and
|
||||
* delete MOVI. For used obj header: check if there are more spix
|
||||
* pages than file len allows, delete these
|
||||
|
||||
* File append:
|
||||
* if spix == 0 & len == -1, use same page, update page after full/finished as WRIT
|
||||
* for following pages:
|
||||
* mark obj hdr as MOVI
|
||||
* if free space in last page
|
||||
* mark MOVI, fill copy, write WRIT, delete MOVI
|
||||
* create new pages with new spix as WRIT
|
||||
* store new obj hdr with correct len as WRIT
|
||||
* delete obj hdr MOVI
|
||||
*
|
||||
* File read:
|
||||
* * aborted rewrite / updated content:
|
||||
* if a MOVI page is encountered, niffs must check for pages
|
||||
* WRIT with same id/span index. If found, use this page instead
|
||||
* and delete MOVI. Else, copy MOVI page to free page as WRIT,
|
||||
* delete MOVI page, and use dest.
|
||||
*
|
||||
* File trunc:
|
||||
* trunc to zero/rm:
|
||||
* set obj hdr file len to 0
|
||||
* delete all pages with same id
|
||||
* if aborted, check will clean
|
||||
* delete obj hdr
|
||||
* trunc to size:
|
||||
* mark obj hdr MOVi
|
||||
* create new obj hdr with correct size as WRIT
|
||||
* if aborted, check will clean
|
||||
* rewrite last page if trunc to midst of page (MOVI -> WRIT -> delete)
|
||||
* delete all removed pages
|
||||
*
|
||||
* Check:
|
||||
* sector headers for valid magic
|
||||
*
|
||||
* if FREE & (WRIT | MOVI) bad page, delete
|
||||
* if MOVI and no equal page with same id, copy and delete original
|
||||
* if MOVI object header => modified during trunc or append, check length and all spix with same id
|
||||
* file length - remove all pages where spix is beyond file size
|
||||
*
|
||||
* remove orphans - check for WRIT && MOVI with ids and spix > 0 having no corresponding page with spix == 0, remove all
|
||||
* file length - if length == 0, remove all with same id, including obj hdr
|
||||
* if obj hdr flag is WRIT, but length is UNDEF, fail during append, remove all containing same id
|
||||
*
|
||||
* Created on: Feb 3, 2015
|
||||
* Author: petera
|
||||
*/
|
||||
|
||||
#include "niffs.h"
|
||||
#include "niffs_config.h"
|
||||
|
||||
#ifndef NIFFS_INTERNAL_H_
|
||||
#define NIFFS_INTERNAL_H_
|
||||
|
||||
#define _NIFFS_PAGE_FREE_ID ((niffs_page_id_raw)-1)
|
||||
#define _NIFFS_PAGE_DELE_ID ((niffs_page_id_raw)0)
|
||||
|
||||
#define _NIFFS_FLAG_CLEAN ((niffs_flag)-1)
|
||||
#define _NIFFS_FLAG_WRITTEN ((niffs_flag)1)
|
||||
#define _NIFFS_FLAG_MOVING ((niffs_flag)0)
|
||||
#define NIFFS_FLAG_MOVE_KEEP ((niffs_flag)0xaa)
|
||||
|
||||
#define _NIFFS_FTYPE_FILE (0)
|
||||
#define _NIFFS_FTYPE_LINFILE (1)
|
||||
|
||||
// change of magic since file type introduction
|
||||
#if NIFFS_LINEAR_AREA
|
||||
//If we are using a partially linear file system, we need to store the linear vs regular page allocations
|
||||
//somewhere so lets store it in the first 4 bytes of the sector magic!
|
||||
//LINEAR MAGIC SECTOR DEFINITION
|
||||
//BYTES 7-6 (0xe1)
|
||||
//BYTES 5-3 fs->page_size
|
||||
//BYTES 2-0 fs->linear sectors
|
||||
#define _NIFFS_SECT_MAGIC_BYTES 0xe1
|
||||
#define _NIFFS_SECT_MAGIC(_fs) (niffs_magic)((_NIFFS_SECT_MAGIC_BYTES << 24) | (((_fs)->page_size & 0xFFF) << 12) | ((_fs)->lin_sectors & 0xFFF))
|
||||
//Bytes 5-3 of magic number holds the page size
|
||||
#define _NIFFS_SECT_PAGE_SIZE(data) (u32_t)((data >> 12) & 0xFFF)
|
||||
//Lower 3 bytes of magic number holds the linear size
|
||||
#define _NIFFS_SECT_LINEAR_SIZE(data) (u32_t)(data & 0xFFF)
|
||||
#else
|
||||
#define _NIFFS_SECT_MAGIC(_fs) (niffs_magic)(0xfee1c001 ^ (_fs)->page_size)
|
||||
#endif
|
||||
|
||||
#ifndef _NIFFS_ALIGN
|
||||
#define _NIFFS_ALIGN __attribute__ (( aligned(NIFFS_WORD_ALIGN) ))
|
||||
#endif
|
||||
#ifndef _NIFFS_PACKED
|
||||
#define _NIFFS_PACKED __attribute__ (( packed ))
|
||||
#endif
|
||||
|
||||
// checks if page is free, i.e. not used at all
|
||||
#define _NIFFS_IS_FREE(_pg_hdr) (((_pg_hdr)->id.raw) == _NIFFS_PAGE_FREE_ID)
|
||||
// checks if page is deleted
|
||||
#define _NIFFS_IS_DELE(_pg_hdr) (((_pg_hdr)->id.raw) == _NIFFS_PAGE_DELE_ID)
|
||||
// checks if page is allocated, but has no data written to it
|
||||
#define _NIFFS_IS_CLEA(_pg_hdr) (((_pg_hdr)->flag) == _NIFFS_FLAG_CLEAN)
|
||||
// checks if page is written
|
||||
#define _NIFFS_IS_WRIT(_pg_hdr) (((_pg_hdr)->flag) == _NIFFS_FLAG_WRITTEN)
|
||||
// checks if page is moving
|
||||
#define _NIFFS_IS_MOVI(_pg_hdr) (((_pg_hdr)->flag) == _NIFFS_FLAG_MOVING)
|
||||
|
||||
#define _NIFFS_SECTOR_2_ADDR(_fs, _s) \
|
||||
((_fs)->phys_addr + (_fs)->sector_size * (_s))
|
||||
#define _NIFFS_ADDR_2_SECTOR(_fs, _addr) \
|
||||
(((u8_t *)(_addr) - (_fs)->phys_addr) / (_fs)->sector_size)
|
||||
|
||||
#define _NIFFS_PIX_2_SECTOR(_fs, _pix) \
|
||||
((_pix) / (_fs)->pages_per_sector)
|
||||
#define _NIFFS_PIX_IN_SECTOR(_fs, _pix) \
|
||||
((_pix) % (_fs)->pages_per_sector)
|
||||
#define _NIFFS_PIX_AT_SECTOR(_fs, _s) \
|
||||
((_s) * (_fs)->pages_per_sector)
|
||||
#define _NIFFS_PIX_2_ADDR(_fs, _pix) (\
|
||||
_NIFFS_SECTOR_2_ADDR(_fs, _NIFFS_PIX_2_SECTOR(_fs, _pix)) + \
|
||||
sizeof(niffs_sector_hdr) + \
|
||||
_NIFFS_PIX_IN_SECTOR(_fs, _pix) * (_fs)->page_size \
|
||||
)
|
||||
|
||||
#define _NIFFS_SPIX_2_PDATA_LEN(_fs, _spix) \
|
||||
((_fs)->page_size - sizeof(niffs_page_hdr) - ((_spix) == 0 ? sizeof(niffs_object_hdr) : 0))
|
||||
|
||||
#define _NIFFS_OFFS_2_SPIX(_fs, _offs) ( \
|
||||
(_offs) < _NIFFS_SPIX_2_PDATA_LEN(_fs, 0) ? 0 : \
|
||||
(1 + (((_offs) - _NIFFS_SPIX_2_PDATA_LEN(_fs, 0)) / _NIFFS_SPIX_2_PDATA_LEN(_fs, 1))) \
|
||||
)
|
||||
|
||||
#define _NIFFS_OFFS_2_PDATA_OFFS(_fs, _offs) ( \
|
||||
(_offs) < _NIFFS_SPIX_2_PDATA_LEN(_fs, 0) ? (_offs) : \
|
||||
(((_offs) - _NIFFS_SPIX_2_PDATA_LEN(_fs, 0)) % _NIFFS_SPIX_2_PDATA_LEN(_fs, 1)) \
|
||||
)
|
||||
|
||||
#define _NIFFS_RD(_fs, _dst, _src, _len) do {niffs_memcpy((_dst), (_src), (_len));}while(0)
|
||||
|
||||
#define _NIFFS_IS_ID_VALID(phdr) ((phdr)->id.obj_id != (niffs_obj_id)-1 && (phdr)-> id.obj_id != 0)
|
||||
#define _NIFFS_IS_FLAG_VALID(phdr) \
|
||||
((phdr)->flag == _NIFFS_FLAG_CLEAN || (phdr)->flag == _NIFFS_FLAG_WRITTEN || (phdr)->flag == _NIFFS_FLAG_MOVING)
|
||||
#define _NIFFS_IS_OBJ_HDR(phdr) (_NIFFS_IS_ID_VALID(phdr) && (phdr->id.spix) == 0)
|
||||
|
||||
#define NIFFS_EXCL_SECT_NONE (u32_t)-1
|
||||
#define NIFFS_UNDEF_LEN (u32_t)-1
|
||||
|
||||
#ifndef niffs_memcpy
|
||||
#define niffs_memcpy(_d, _s, _l) memcpy((_d), (_s), (_l))
|
||||
#endif
|
||||
#ifndef niffs_memset
|
||||
#define niffs_memset(_d, _v, _l) memset((_d), (_v), (_l))
|
||||
#endif
|
||||
#ifndef niffs_strncpy
|
||||
#define niffs_strncpy(_d, _s, _l) strncpy((_d), (_s), (_l))
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
_NIFFS_ALIGN niffs_erase_cnt era_cnt;
|
||||
_NIFFS_ALIGN niffs_magic abra; // page size xored with magic
|
||||
} _NIFFS_PACKED niffs_sector_hdr;
|
||||
|
||||
typedef struct {
|
||||
union {
|
||||
niffs_page_id_raw raw;
|
||||
struct {
|
||||
niffs_span_ix spix : NIFFS_SPAN_IX_BITS;
|
||||
niffs_obj_id obj_id : NIFFS_OBJ_ID_BITS;
|
||||
};
|
||||
};
|
||||
} _NIFFS_PACKED niffs_page_hdr_id;
|
||||
|
||||
// keep member order, used in offsetof in internals
|
||||
typedef struct {
|
||||
_NIFFS_ALIGN niffs_page_hdr_id id;
|
||||
_NIFFS_ALIGN niffs_flag flag;
|
||||
} _NIFFS_PACKED niffs_page_hdr;
|
||||
|
||||
// keep member order, used in offsetof in internals
|
||||
typedef struct {
|
||||
niffs_page_hdr phdr;
|
||||
_NIFFS_ALIGN u32_t len;
|
||||
_NIFFS_ALIGN u8_t name[NIFFS_NAME_LEN];
|
||||
_NIFFS_ALIGN niffs_file_type type;
|
||||
} _NIFFS_PACKED niffs_object_hdr;
|
||||
|
||||
typedef struct {
|
||||
niffs_object_hdr ohdr;
|
||||
_NIFFS_ALIGN u32_t start_sector; // absolute index from fs start
|
||||
_NIFFS_ALIGN u32_t resv_sectors;
|
||||
} _NIFFS_PACKED niffs_linear_file_hdr;
|
||||
|
||||
// super header containing all header types
|
||||
typedef union {
|
||||
niffs_page_hdr_id phdr;
|
||||
niffs_object_hdr ohdr;
|
||||
niffs_linear_file_hdr lfhdr;
|
||||
// .. add more if needed
|
||||
} niffs_super_hdr;
|
||||
|
||||
#define NIFFS_VIS_CONT 1
|
||||
#define NIFFS_VIS_END 2
|
||||
|
||||
typedef int (* niffs_visitor_f)(niffs *fs, niffs_page_ix pix, niffs_page_hdr *phdr, void *v_arg);
|
||||
|
||||
#ifdef NIFFS_TEST
|
||||
TESTATIC int niffs_find_free_id(niffs *fs, niffs_obj_id *id, const char *conflict_name);
|
||||
TESTATIC int niffs_find_free_page(niffs *fs, niffs_page_ix *pix, u32_t excl_sector);
|
||||
TESTATIC int niffs_find_page(niffs *fs, niffs_page_ix *pix, niffs_obj_id oid, niffs_span_ix spix, niffs_page_ix start_pix);
|
||||
TESTATIC int niffs_erase_sector(niffs *fs, u32_t sector_ix);
|
||||
TESTATIC int niffs_move_page(niffs *fs, niffs_page_ix src_pix, niffs_page_ix dst_pix, const u8_t *data, u32_t len, niffs_flag force_flag);
|
||||
TESTATIC int niffs_write_page(niffs *fs, niffs_page_ix pix, niffs_page_hdr *phdr, const u8_t *data, u32_t len);
|
||||
TESTATIC int niffs_write_phdr(niffs *fs, niffs_page_ix pix, niffs_page_hdr *phdr);
|
||||
TESTATIC int niffs_delete_page(niffs *fs, niffs_page_ix pix);
|
||||
#endif
|
||||
|
||||
int niffs_traverse(niffs *fs, niffs_page_ix pix_start, niffs_page_ix pix_end, niffs_visitor_f v, void *v_arg);
|
||||
int niffs_get_filedesc(niffs *fs, int fd_ix, niffs_file_desc **fd);
|
||||
int niffs_create(niffs *fs, const char *name, niffs_file_type type, void *meta);
|
||||
int niffs_open(niffs *fs, const char *name, niffs_fd_flags flags);
|
||||
int niffs_close(niffs *fs, int fd_ix);
|
||||
int niffs_read_ptr(niffs *fs, int fd_ix, u8_t **data, u32_t *avail);
|
||||
int niffs_seek(niffs *fs, int fd_ix, s32_t offset, u8_t whence);
|
||||
int niffs_append(niffs *fs, int fd_ix, const u8_t *src, u32_t len);
|
||||
int niffs_modify(niffs *fs, int fd_ix, u32_t offs, const u8_t *src, u32_t len);
|
||||
int niffs_truncate(niffs *fs, int fd_ix, u32_t new_len);
|
||||
int niffs_rename(niffs *fs, const char *old_name, const char *new_name);
|
||||
|
||||
int niffs_gc(niffs *fs, u32_t *freed_pages, u8_t allow_full_pages);
|
||||
|
||||
int niffs_chk(niffs *fs);
|
||||
|
||||
int niffs_linear_map(niffs *fs);
|
||||
int niffs_linear_find_space(niffs *fs, u32_t sectors, u32_t *start_sector);
|
||||
int niffs_linear_avail_size(niffs *fs, int fd_ix, u32_t *available_sectors);
|
||||
|
||||
#endif /* NIFFS_INTERNAL_H_ */
|
34
src/common.c
34
src/common.c
@ -79,7 +79,7 @@ static int term_in( int mode )
|
||||
static int term_translate( int data )
|
||||
{
|
||||
int c;
|
||||
|
||||
|
||||
if( isprint( data ) )
|
||||
return data;
|
||||
else if( data == 0x1B ) // escape sequence
|
||||
@ -100,7 +100,7 @@ static int term_translate( int data )
|
||||
case 0x43:
|
||||
return KC_RIGHT;
|
||||
case 0x44:
|
||||
return KC_LEFT;
|
||||
return KC_LEFT;
|
||||
}
|
||||
else if( c > 48 && c < 55 )
|
||||
{
|
||||
@ -116,7 +116,7 @@ static int term_translate( int data )
|
||||
case 53:
|
||||
return KC_PAGEUP;
|
||||
case 54:
|
||||
return KC_PAGEDOWN;
|
||||
return KC_PAGEDOWN;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -152,7 +152,7 @@ static int term_translate( int data )
|
||||
case 21:
|
||||
return KC_CTRL_U;
|
||||
case 11:
|
||||
return KC_CTRL_K;
|
||||
return KC_CTRL_K;
|
||||
}
|
||||
}
|
||||
return KC_UNKNOWN;
|
||||
@ -183,21 +183,21 @@ void cmn_platform_init(void)
|
||||
|
||||
#ifdef BUILD_SERMUX
|
||||
unsigned i;
|
||||
unsigned bufsizes[] = SERMUX_BUFFER_SIZES;
|
||||
unsigned bufsizes[] = SERMUX_BUFFER_SIZES;
|
||||
|
||||
// Setup the serial multiplexer
|
||||
platform_uart_setup( SERMUX_PHYS_ID, SERMUX_PHYS_SPEED, 8, PLATFORM_UART_PARITY_NONE, PLATFORM_UART_STOPBITS_1 );
|
||||
platform_uart_set_flow_control( SERMUX_PHYS_ID, SERMUX_FLOW_TYPE );
|
||||
cmn_uart_setup_sermux();
|
||||
|
||||
// Set buffers for all virtual UARTs
|
||||
// Set buffers for all virtual UARTs
|
||||
for( i = 0; i < sizeof( bufsizes ) / sizeof( unsigned ); i ++ )
|
||||
platform_uart_set_buffer( i + SERMUX_SERVICE_ID_FIRST, bufsizes[ i ] );
|
||||
#endif // #ifdef BUILD_SERMUX
|
||||
|
||||
#if defined( CON_UART_ID ) && ( CON_UART_ID < SERMUX_SERVICE_ID_FIRST ) && ( CON_UART_ID != CDC_UART_ID )
|
||||
// Setup console UART
|
||||
platform_uart_setup( CON_UART_ID, CON_UART_SPEED, 8, PLATFORM_UART_PARITY_NONE, PLATFORM_UART_STOPBITS_1 );
|
||||
platform_uart_setup( CON_UART_ID, CON_UART_SPEED, 8, PLATFORM_UART_PARITY_NONE, PLATFORM_UART_STOPBITS_1 );
|
||||
platform_uart_set_flow_control( CON_UART_ID, CON_FLOW_TYPE );
|
||||
platform_uart_set_buffer( CON_UART_ID, CON_BUF_SIZE );
|
||||
#endif // #if defined( CON_UART_ID ) && CON_UART_ID < SERMUX_SERVICE_ID_FIRST
|
||||
@ -206,16 +206,16 @@ void cmn_platform_init(void)
|
||||
platform_uart_set_buffer( CDC_UART_ID, CDC_BUF_SIZE );
|
||||
#endif
|
||||
|
||||
// Set the send/recv functions
|
||||
// Set the send/recv functions
|
||||
std_set_send_func( uart_send );
|
||||
std_set_get_func( uart_recv );
|
||||
|
||||
#ifdef BUILD_XMODEM
|
||||
#ifdef BUILD_XMODEM
|
||||
// Initialize XMODEM
|
||||
xmodem_init( xmodem_send, xmodem_recv );
|
||||
xmodem_init( xmodem_send, xmodem_recv );
|
||||
#endif
|
||||
|
||||
#ifdef BUILD_TERM
|
||||
#ifdef BUILD_TERM
|
||||
// Initialize terminal
|
||||
term_init( TERM_LINES, TERM_COLS, term_out, term_in, term_translate );
|
||||
#endif
|
||||
@ -239,7 +239,7 @@ int platform_pio_has_port( unsigned port )
|
||||
const char* platform_pio_get_prefix( unsigned port )
|
||||
{
|
||||
static char c[ 3 ];
|
||||
|
||||
|
||||
sprintf( c, "P%c", ( char )( port + PIO_PREFIX ) );
|
||||
return c;
|
||||
}
|
||||
@ -458,14 +458,14 @@ void cmn_int_handler( elua_int_id id, elua_int_resnum resnum )
|
||||
#endif // #ifdef BUILD_INT_HANDLERS
|
||||
|
||||
// ****************************************************************************
|
||||
// Internal flash support functions (currently used only by WOFS)
|
||||
// Internal flash support functions (currently used only by WOFS and NIFFS)
|
||||
|
||||
#if defined( BUILD_WOFS ) && !defined( ELUA_CPU_LINUX )
|
||||
#if (defined( BUILD_WOFS ) || defined( BUILD_NIFFS )) && !defined( ELUA_CPU_LINUX )
|
||||
|
||||
// This symbol must be exported by the linker command file and must reflect the
|
||||
// TOTAL size of flash used by the eLua image (not only the code and constants,
|
||||
// but also .data and whatever else ends up in the eLua image). WOFS will start
|
||||
// at the next usable (aligned to a flash sector boundary) address after
|
||||
// at the next usable (aligned to a flash sector boundary) address after
|
||||
// flash_used_size.
|
||||
extern char flash_used_size[];
|
||||
|
||||
@ -627,7 +627,7 @@ const char* cmn_str64( u64 x )
|
||||
}
|
||||
|
||||
// Read a timeout spec from the user and return it
|
||||
// The timeout spec has the format [timer_id, timeout]. Both arguments are optional:
|
||||
// The timeout spec has the format [timer_id, timeout]. Both arguments are optional:
|
||||
// If none is specified -> defaults to infinite timeout
|
||||
// If timer_id is specified, but timeout is not specified -> defaults to infinite timeout
|
||||
// If timeout is PLATFORM_TIMER_INF_TIMEOUT -> also infinite timeout (independent of timer_id)
|
||||
@ -637,7 +637,7 @@ void cmn_get_timeout_data( lua_State *L, int pidx, unsigned *pid, timer_data_typ
|
||||
{
|
||||
lua_Number tempn;
|
||||
|
||||
*ptimeout = PLATFORM_TIMER_INF_TIMEOUT;
|
||||
*ptimeout = PLATFORM_TIMER_INF_TIMEOUT;
|
||||
*pid = ( unsigned )luaL_optinteger( L, pidx, PLATFORM_TIMER_SYS_ID );
|
||||
if( lua_type( L, pidx + 1 ) == LUA_TNUMBER )
|
||||
{
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "mmcfs.h"
|
||||
#include "romfs.h"
|
||||
#include "semifs.h"
|
||||
#include "nffs.h"
|
||||
|
||||
// Define here your autorun/boot files,
|
||||
// in the order you want eLua to search for them
|
||||
@ -34,6 +35,10 @@ const char *boot_order[] = {
|
||||
"/wo/autorun.lua",
|
||||
"/wo/autorun.lc",
|
||||
#endif
|
||||
#if defined(BUILD_NIFFS)
|
||||
"/f/autorun.lua",
|
||||
"/f/autorun.lc",
|
||||
#endif
|
||||
#if defined(BUILD_ROMFS)
|
||||
"/rom/autorun.lua",
|
||||
"/rom/autorun.lc",
|
||||
@ -94,6 +99,9 @@ int main( void )
|
||||
// Register the remote filesystem
|
||||
remotefs_init();
|
||||
|
||||
// Register NIFFS
|
||||
nffs_init();
|
||||
|
||||
// Search for autorun files in the defined order and execute the 1st if found
|
||||
for( i = 0; i < sizeof( boot_order ) / sizeof( *boot_order ); i++ )
|
||||
{
|
||||
|
@ -58,6 +58,9 @@ LUALIB_API int ( luaopen_elua )( lua_State *L );
|
||||
#define AUXLIB_I2C "i2c"
|
||||
LUALIB_API int ( luaopen_i2c )( lua_State *L );
|
||||
|
||||
#define AUXLIB_FS "fs"
|
||||
LUALIB_API int ( luaopen_fs )( lua_State *L );
|
||||
|
||||
// Helper macros
|
||||
#define MOD_CHECK_ID( mod, id )\
|
||||
if( !platform_ ## mod ## _exists( id ) )\
|
||||
|
44
src/modules/fs.c
Normal file
44
src/modules/fs.c
Normal file
@ -0,0 +1,44 @@
|
||||
// Module for interfacing with various file systems
|
||||
// For now this is enabled only if NIFFS is enabled
|
||||
|
||||
#include "platform_conf.h"
|
||||
#if defined( BUILD_NIFFS )
|
||||
|
||||
//#include "lua.h"
|
||||
#include "lualib.h"
|
||||
#include "auxmods.h"
|
||||
#include "lrotable.h"
|
||||
#include "nffs.h"
|
||||
|
||||
// Lua: res = niffs_format( linear_size )
|
||||
static int fs_nffs_format( lua_State *L )
|
||||
{
|
||||
s32 linear_size = -1;
|
||||
|
||||
switch ( lua_gettop( L ) ) { /* check number of arguments */
|
||||
case 1: /* format filesystem with the given linear size */
|
||||
linear_size = luaL_checkinteger ( L, 1 );
|
||||
break;
|
||||
|
||||
default:
|
||||
return luaL_error( L, "wrong number of arguments" );
|
||||
}
|
||||
lua_pushinteger( L, nffs_format( linear_size ) );
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Module function map
|
||||
#define MIN_OPT_LEVEL 2
|
||||
#include "lrodefs.h"
|
||||
const LUA_REG_TYPE fs_map[] =
|
||||
{
|
||||
{ LSTRKEY( "nffs_format" ), LFUNCVAL( fs_nffs_format ) },
|
||||
{ LNILKEY, LNILVAL }
|
||||
};
|
||||
|
||||
LUALIB_API int luaopen_fs( lua_State* L )
|
||||
{
|
||||
LREGISTER( L, AUXLIB_FS, fs_map );
|
||||
}
|
||||
|
||||
#endif // #ifdef BUILD_NIFFS
|
435
src/niffs/niffs.c
Normal file
435
src/niffs/niffs.c
Normal file
@ -0,0 +1,435 @@
|
||||
// Filesystem implementation
|
||||
#include "romfs.h"
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include "romfiles.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "ioctl.h"
|
||||
#include <fcntl.h>
|
||||
#include "platform.h"
|
||||
#include "platform_conf.h"
|
||||
#include "niffs.h"
|
||||
#include "niffs_internal.h"
|
||||
|
||||
#if defined( BUILD_NIFFS )
|
||||
|
||||
//#define NFFS_DBG(...) printf(__VA_ARGS__)
|
||||
#ifndef NFFS_DBG
|
||||
#define NFFS_DBG(...)
|
||||
#endif
|
||||
|
||||
// FIXME: Needs to be adjusted to support non-uniform sector sizes
|
||||
#define LAST_SECTOR_NUM ( platform_flash_get_num_sectors() - 1 )
|
||||
#define LAST_SECTOR_END ( INTERNAL_FLASH_SIZE - INTERNAL_FLASH_START_ADDRESS )
|
||||
|
||||
niffs fs;
|
||||
|
||||
#define NIFFS_BUF_SIZE 128
|
||||
#define NIFFS_FILE_DESCS 4
|
||||
static u8_t buf[NIFFS_BUF_SIZE];
|
||||
static niffs_file_desc descs[NIFFS_FILE_DESCS];
|
||||
static u8_t * niffs_pbase;
|
||||
static u32_t niffs_max_size;
|
||||
static u32_t niffs_total_sectors;
|
||||
static u32_t niffs_paged_sectors;
|
||||
static u32_t niffs_lin_sectors;
|
||||
|
||||
static int nffs_open_r( struct _reent *r, const char *path, int flags, int mode, void *pdata )
|
||||
{
|
||||
u8 lflags = 0;
|
||||
int ret;
|
||||
|
||||
lflags = NIFFS_O_RDONLY;
|
||||
|
||||
//check for read/write flags and overwrite read only if so
|
||||
if(flags & O_RDWR) {
|
||||
lflags = NIFFS_O_RDWR;
|
||||
//printf("-S");
|
||||
}
|
||||
if(flags & O_WRONLY) {
|
||||
lflags = NIFFS_O_WRONLY;
|
||||
//printf("-W");
|
||||
}
|
||||
|
||||
//add other flags
|
||||
if(flags & O_CREAT) {
|
||||
lflags |= NIFFS_O_CREAT;
|
||||
//printf("-C");
|
||||
}
|
||||
if(flags & O_TRUNC) {
|
||||
lflags |= NIFFS_O_TRUNC;
|
||||
//printf("-T");
|
||||
}
|
||||
if(flags & O_APPEND) {
|
||||
lflags |= NIFFS_O_APPEND;
|
||||
//printf("-A");
|
||||
}
|
||||
if(flags & O_EXCL) {
|
||||
lflags |= NIFFS_O_EXCL;
|
||||
//printf("-E");
|
||||
}
|
||||
|
||||
// If file name starts with autorun or lin_, then put it on the linear filesystem
|
||||
if ((strncmp("lin_", path, 7) == 0) || (strncmp("autorun", path, 7) == 0)) {
|
||||
lflags |= NIFFS_O_LINEAR;
|
||||
//printf("-L\n");
|
||||
}
|
||||
ret = NIFFS_open(&fs, (char *)path, lflags, mode);
|
||||
NFFS_DBG("\nN_O:%s,%i,%i,%i,%i\n", path, ret, flags, lflags, mode);
|
||||
if(ret < 0)
|
||||
{
|
||||
r->_errno = ENOENT; //File does not exist
|
||||
return -1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int nffs_close_r( struct _reent *r, int fd, void *pdata )
|
||||
{
|
||||
return NIFFS_close(&fs, fd);
|
||||
}
|
||||
|
||||
static _ssize_t nffs_write_r( struct _reent *r, int fd, const void* ptr, size_t len, void *pdata )
|
||||
{
|
||||
return NIFFS_write(&fs, fd, (void *)ptr, len);
|
||||
}
|
||||
|
||||
static _ssize_t nffs_read_r( struct _reent *r, int fd, void* ptr, size_t len, void *pdata )
|
||||
{
|
||||
return NIFFS_read(&fs, fd, ptr, len);
|
||||
}
|
||||
|
||||
static off_t nffs_lseek_r( struct _reent *r, int fd, off_t off, int whence, void *pdata )
|
||||
{
|
||||
// Ensure the whence arg here matches NIFFS_SEEK_SET, NIFFS_SEEK_CUR, NIFFS_SEEK_END?
|
||||
// niffs adapts to the posix values so should work (Yes)
|
||||
//#define SEEK_SET 0 /* set file offset to offset */
|
||||
//#define SEEK_CUR 1 /* set file offset to current plus offset */
|
||||
//#define SEEK_END 2 /* set file offset to EOF plus offset */
|
||||
//#define NIFFS_SEEK_SET (0)
|
||||
//#define NIFFS_SEEK_CUR (1)
|
||||
//#define NIFFS_SEEK_END (2)
|
||||
|
||||
int res;
|
||||
|
||||
//Return value will be greater than 0 if file seek occurs, or 0 IE NIFFS_OK if successful but didn't move, and
|
||||
//less than zero if an error occured.
|
||||
res = NIFFS_lseek(&fs, fd, off, whence);
|
||||
if(res >= NIFFS_OK)
|
||||
{
|
||||
//printf("Nl r:%i fd:%i o:%li w:%i\n", res, fd, off, whence);
|
||||
return res;
|
||||
} else {
|
||||
//printf("Nl FAIL r:%i fd:%i o:%li w:%i\n", res, fd, off, whence);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// getaddr
|
||||
static const char* nffs_getaddr_r( struct _reent *r, int fd, void *pdata )
|
||||
{
|
||||
u8_t * ptrptr;
|
||||
u32_t len;
|
||||
NIFFS_read_ptr(&fs, fd, &ptrptr, &len);
|
||||
//printf("getaddr %p\n", (u32_t *)ptrptr);
|
||||
return (char*)ptrptr;
|
||||
}
|
||||
|
||||
// Directory operations
|
||||
//static u32 romfs_dir_data = 0;
|
||||
|
||||
static niffs_DIR niffs_d;
|
||||
// opendir
|
||||
static void* nffs_opendir_r( struct _reent *r, const char* dname, void *pdata )
|
||||
{
|
||||
return NIFFS_opendir(&fs, (char *)dname, &niffs_d);
|
||||
}
|
||||
// TODO peter no clue what I am doing here, but could perhaps work
|
||||
extern struct dm_dirent dm_shared_dirent;
|
||||
extern char dm_shared_fname[ DM_MAX_FNAME_LENGTH + 1 ];
|
||||
static struct dm_dirent *nffs_readdir_r( struct _reent *r, void *d, void *pdata )
|
||||
{
|
||||
struct dm_dirent *pent = &dm_shared_dirent;
|
||||
struct niffs_dirent niffs_ent;
|
||||
struct niffs_dirent *p_niffs_ent = &niffs_ent;
|
||||
p_niffs_ent = NIFFS_readdir(&niffs_d, p_niffs_ent);
|
||||
if (p_niffs_ent) {
|
||||
pent->fname = dm_shared_fname;
|
||||
strncpy((char *)pent->fname, (char *)p_niffs_ent->name, UMIN(NIFFS_NAME_LEN, DM_MAX_FNAME_LENGTH));
|
||||
pent->fsize = p_niffs_ent->size;
|
||||
pent->flags = 0; // TODO peter don't know what elua uses this for
|
||||
pent->ftime = 0;
|
||||
if (p_niffs_ent->type) {
|
||||
// TODO peter placeholder
|
||||
// 0x00 = paged file
|
||||
// 0x01 = linear file
|
||||
}
|
||||
}
|
||||
return p_niffs_ent == NULL ? NULL : pent;
|
||||
}
|
||||
/*
|
||||
NIFFS_readdir
|
||||
// readdir
|
||||
extern struct dm_dirent dm_shared_dirent;
|
||||
extern char dm_shared_fname[ DM_MAX_FNAME_LENGTH + 1 ];
|
||||
static struct dm_dirent* romfs_readdir_r( struct _reent *r, void *d, void *pdata )
|
||||
{
|
||||
u32 off = *( u32* )d;
|
||||
struct dm_dirent *pent = &dm_shared_dirent;
|
||||
unsigned j;
|
||||
FSDATA *pfsdata = ( FSDATA* )pdata;
|
||||
int is_deleted;
|
||||
|
||||
while( 1 )
|
||||
{
|
||||
// Check if we're at the end of the FS
|
||||
if( romfsh_read8( off, pfsdata ) == WOFS_END_MARKER_CHAR )
|
||||
return NULL;
|
||||
|
||||
// Read filename
|
||||
j = 0;
|
||||
while( ( dm_shared_fname[ j ++ ] = romfsh_read8( off ++, pfsdata ) ) != '\0' );
|
||||
pent->fname = dm_shared_fname;
|
||||
|
||||
// Move to next aligned offset after name
|
||||
off = ( off + ROMFS_ALIGN - 1 ) & ~( ROMFS_ALIGN - 1 );
|
||||
|
||||
// If WOFS, check if file is marked as deleted
|
||||
if( romfsh_is_wofs( pfsdata ) )
|
||||
{
|
||||
is_deleted = romfsh_read8( off, pfsdata ) == WOFS_FILE_DELETED;
|
||||
off += WOFS_DEL_FIELD_SIZE;
|
||||
}
|
||||
else
|
||||
is_deleted = 0;
|
||||
|
||||
// Get file size file and pack into fsize
|
||||
pent->fsize = romfsh_read8( off, pfsdata ) + ( romfsh_read8( off + 1, pfsdata ) << 8 );
|
||||
pent->fsize += ( romfsh_read8( off + 2, pfsdata ) << 16 ) + ( romfsh_read8( off + 3, pfsdata ) << 24 );
|
||||
|
||||
if( (( u64 )off + ( u64 )ROMFS_SIZE_LEN + ( u64 )pent->fsize) > ( u64 )pfsdata->max_size )
|
||||
{
|
||||
if( romfs_fs_is_flag_set( pfsdata, ROMFS_FS_FLAG_READY_WRITE ) &&
|
||||
!( romfs_fs_is_flag_set( pfsdata, ROMFS_FS_FLAG_WRITING ) && ( u64 )pent->fsize == 0xFFFFFFFF ) )
|
||||
{
|
||||
fprintf(stderr, "[ERROR] Read File too long, making filesystem readonly\n");
|
||||
romfs_fs_clear_flag( pfsdata, ROMFS_FS_FLAG_READY_WRITE );
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// fill in file time & flags
|
||||
pent->ftime = 0;
|
||||
pent->flags = 0;
|
||||
|
||||
// Jump offset ahead by length field & file size
|
||||
off += ROMFS_SIZE_LEN;
|
||||
off += pent->fsize;
|
||||
|
||||
|
||||
// If WOFS, also advance offset by deleted file field
|
||||
if( romfsh_is_wofs( pfsdata ) )
|
||||
off = ( off + ROMFS_ALIGN - 1 ) & ~( ROMFS_ALIGN - 1 );
|
||||
|
||||
//If file security is enabled, don't return a matching filename as valid
|
||||
#ifdef ROMFS_SECURE_FILENAMES_WITH_CHAR
|
||||
if( !is_deleted && ( romfs_security_lock == 0 || strstr( pent->fname, ROMFS_SECURE_FILENAMES_WITH_CHAR) == NULL ) )
|
||||
break;
|
||||
#else
|
||||
if( !is_deleted )
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
*( u32* )d = off;
|
||||
return pent;
|
||||
}*/
|
||||
|
||||
// closedir
|
||||
static int nffs_closedir_r( struct _reent *r, void *d, void *pdata )
|
||||
{
|
||||
*( u32* )d = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// unlink
|
||||
static int nffs_unlink_r( struct _reent *r, const char *path, void *pdata )
|
||||
{
|
||||
return NIFFS_remove(&fs, (char *)path);
|
||||
}
|
||||
|
||||
static const DM_DEVICE niffs_device =
|
||||
{
|
||||
nffs_open_r, // open
|
||||
nffs_close_r, // close
|
||||
nffs_write_r, // write
|
||||
nffs_read_r, // read
|
||||
nffs_lseek_r, // lseek
|
||||
nffs_opendir_r, // opendir
|
||||
nffs_readdir_r, // readdir TODO peter, made an attempt at this
|
||||
nffs_closedir_r, // closedir
|
||||
nffs_getaddr_r, // getaddr
|
||||
NULL, // mkdir
|
||||
nffs_unlink_r, // unlink
|
||||
NULL, // rmdir
|
||||
NULL // rename // TODO peter, this exists in niffs also if you want it
|
||||
};
|
||||
|
||||
static int platform_hal_erase_f(u8_t *addr, u32_t len) {
|
||||
// flash boundary checks
|
||||
if ((intptr_t)addr < (intptr_t)niffs_pbase ||
|
||||
(intptr_t)addr + len > (intptr_t)niffs_pbase + niffs_max_size) {
|
||||
NFFS_DBG("N_E: OOB %li,%li\n", (u32_t)addr, len);
|
||||
return -1; // TODO peter better err code?
|
||||
}
|
||||
/* if (addr < &_flash[0]) return ERR_NIFFS_TEST_BAD_ADDR;
|
||||
if (addr+len > &_flash[0] + EMUL_SECTORS * EMUL_SECTOR_SIZE) return ERR_NIFFS_TEST_BAD_ADDR;
|
||||
if ((addr - &_flash[0]) % EMUL_SECTOR_SIZE) return ERR_NIFFS_TEST_BAD_ADDR;
|
||||
if (len != EMUL_SECTOR_SIZE) return ERR_NIFFS_TEST_BAD_ADDR;*/
|
||||
platform_flash_erase_sector(((u32_t)addr)/INTERNAL_FLASH_SECTOR_SIZE); // == PLATFORM_OK;
|
||||
NFFS_DBG("N_E:%li,%li\n", (u32_t)addr, len);
|
||||
return NIFFS_OK;
|
||||
}
|
||||
|
||||
static int platform_hal_write_f(u8_t *addr, const u8_t *src, u32_t len) {
|
||||
if ((intptr_t)addr < (intptr_t)niffs_pbase ||
|
||||
(intptr_t)addr + len > (intptr_t)niffs_pbase + niffs_max_size) {
|
||||
NFFS_DBG("N_W: OOB %li,%li\n", (u32_t)addr, len);
|
||||
return -1; // TODO peter better err code?
|
||||
}
|
||||
//TODO: Write actual data to addresses here
|
||||
// toaddr += ( u32 )pfsdata->pbase;
|
||||
//platform_flash_write( const void *from, u32 toaddr, u32 size )
|
||||
platform_flash_write( src, (u32_t)addr, len );
|
||||
NFFS_DBG("N_W:%li,%li,%li\n", (u32_t)addr, (u32_t)src, len);
|
||||
return NIFFS_OK;
|
||||
}
|
||||
|
||||
int nffs_check_and_mount()
|
||||
{
|
||||
//Check filesystem, and format if it has not been formatted or corrupted...
|
||||
NIFFS_unmount(&fs);
|
||||
if(NIFFS_chk(&fs) == ERR_NIFFS_NOT_A_FILESYSTEM)
|
||||
{
|
||||
NFFS_DBG("chk NOT FS\n");
|
||||
NIFFS_format(&fs);
|
||||
} else
|
||||
NFFS_DBG("chk OK\n");
|
||||
|
||||
if(NIFFS_mount(&fs))
|
||||
{
|
||||
printf("FILE SYSTEM MOUNT FAIL\n");
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
NFFS_DBG("MNT OK\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
int nffs_create( s32_t linear_bytes )
|
||||
{
|
||||
niffs_pbase = ( u8* )platform_flash_get_first_free_block_address( NULL );
|
||||
niffs_max_size = INTERNAL_FLASH_SIZE - ( ( u32 )niffs_pbase - INTERNAL_FLASH_START_ADDRESS ) - (INTERNAL_FLASH_SECTOR_SIZE);
|
||||
niffs_total_sectors = niffs_max_size / INTERNAL_FLASH_SECTOR_SIZE;
|
||||
|
||||
if(linear_bytes == -1)
|
||||
{
|
||||
//Look to see if we have a valid magic byte and if so, get the linear page size
|
||||
//It is stored in the lower 2 bytes of the magic number (abra)
|
||||
niffs_sector_hdr *shdr = (niffs_sector_hdr *)niffs_pbase;
|
||||
NFFS_DBG("%08lX %08lX\n",
|
||||
shdr->abra,
|
||||
_NIFFS_SECT_LINEAR_SIZE(shdr->abra));
|
||||
|
||||
niffs_lin_sectors = 1;
|
||||
//Get linear sectors stored on flash...if it's set...if not, assume zero linear sectors
|
||||
//If not, format the file system with no linear page area. User will format it if needed
|
||||
if ((shdr->abra >> 24) == (_NIFFS_SECT_MAGIC_BYTES))
|
||||
niffs_lin_sectors = _NIFFS_SECT_LINEAR_SIZE(shdr->abra);
|
||||
} else {
|
||||
//We were told to create a linear space, calculate it here
|
||||
//Division drops the decimal, so we need to divide and add 1 sector
|
||||
niffs_lin_sectors = (linear_bytes / INTERNAL_FLASH_SECTOR_SIZE) + 1;
|
||||
//Make sure we leave at least 1 sector for paged sectors
|
||||
if(niffs_lin_sectors > (niffs_total_sectors - 1))
|
||||
niffs_lin_sectors = niffs_total_sectors - 1;
|
||||
}
|
||||
|
||||
niffs_paged_sectors = niffs_total_sectors - niffs_lin_sectors;
|
||||
printf("NIFFS: LIN %li PAGE %li\n", niffs_lin_sectors, niffs_paged_sectors);
|
||||
|
||||
NIFFS_init(&fs, niffs_pbase, niffs_paged_sectors, INTERNAL_FLASH_SECTOR_SIZE, NIFFS_BUF_SIZE,
|
||||
buf, sizeof(buf),
|
||||
descs, NIFFS_FILE_DESCS,
|
||||
platform_hal_erase_f, platform_hal_write_f, niffs_lin_sectors);
|
||||
|
||||
//If given a specific linear byte size, format flash
|
||||
if(linear_bytes != -1)
|
||||
NIFFS_format(&fs);
|
||||
|
||||
//Check filesystem, and format if it has not been formatted or corrupted...
|
||||
return nffs_check_and_mount();
|
||||
}
|
||||
|
||||
int nffs_init( void )
|
||||
{
|
||||
nffs_create(-1);
|
||||
|
||||
dm_register( "/f", &fs, &niffs_device );
|
||||
|
||||
return dm_register( NULL, NULL, NULL );
|
||||
}
|
||||
|
||||
int nffs_format(s32_t linear_bytes)
|
||||
{
|
||||
NIFFS_unmount(&fs);
|
||||
nffs_create(linear_bytes);
|
||||
NFFS_DBG("N_I:%li,%li,%li,%li\n", (u32_t)niffs_pbase, niffs_max_size, niffs_paged_sectors, niffs_lin_sectors);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int nffs_mount()
|
||||
{
|
||||
return NIFFS_mount(&fs);
|
||||
}
|
||||
|
||||
int nffs_unmount()
|
||||
{
|
||||
return NIFFS_unmount(&fs);
|
||||
}
|
||||
|
||||
int nffs_info(s32_t *total, s32_t *used, u8_t *overflow, s32_t *lin_total, s32_t *lin_used, s32_t *lin_free)
|
||||
{
|
||||
niffs_sector_hdr *shdr = (niffs_sector_hdr *)_NIFFS_SECTOR_2_ADDR(&fs, 0);
|
||||
printf("%08lX %08lX %08lX\n",
|
||||
shdr->abra,
|
||||
_NIFFS_SECT_MAGIC(&fs),
|
||||
_NIFFS_SECT_LINEAR_SIZE(shdr->abra));
|
||||
|
||||
nffs_check_and_mount();
|
||||
|
||||
niffs_info info;
|
||||
int res = NIFFS_info(&fs, &info);
|
||||
if (res == NIFFS_OK) {
|
||||
*total = info.total_bytes;
|
||||
*used = info.used_bytes;
|
||||
*overflow = info.overflow;
|
||||
*lin_total = info.lin_total_sectors * INTERNAL_FLASH_SECTOR_SIZE;
|
||||
*lin_used = info.lin_used_sectors * INTERNAL_FLASH_SECTOR_SIZE;
|
||||
*lin_free = info.lin_max_conseq_free * INTERNAL_FLASH_SECTOR_SIZE;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
#else // #if defined( BUILD_ROMFS ) || defined( BUILD_WOFS )
|
||||
|
||||
int nffs_init( void )
|
||||
{
|
||||
return dm_register( NULL, NULL, NULL );
|
||||
}
|
||||
|
||||
#endif // #if defined( BUILD_NIFFS )
|
||||
|
346
src/niffs/niffs_api.c
Normal file
346
src/niffs/niffs_api.c
Normal file
@ -0,0 +1,346 @@
|
||||
/*
|
||||
* niffs_api.c
|
||||
*
|
||||
* Created on: Feb 22, 2015
|
||||
* Author: petera
|
||||
*/
|
||||
|
||||
#include "niffs.h"
|
||||
#include "niffs_internal.h"
|
||||
|
||||
int NIFFS_info(niffs *fs, niffs_info *i) {
|
||||
if (!fs->mounted) return ERR_NIFFS_NOT_MOUNTED;
|
||||
if (i == 0) return ERR_NIFFS_NULL_PTR;
|
||||
|
||||
i->total_bytes = (fs->sectors-1) * fs->pages_per_sector * _NIFFS_SPIX_2_PDATA_LEN(fs, 1);
|
||||
i->used_bytes = ((fs->sectors) * fs->pages_per_sector - (fs->free_pages + fs->dele_pages)) * _NIFFS_SPIX_2_PDATA_LEN(fs, 1);
|
||||
i->overflow = fs->free_pages < fs->pages_per_sector;
|
||||
|
||||
#if NIFFS_LINEAR_AREA
|
||||
i->lin_total_sectors = fs->lin_sectors;
|
||||
i->lin_used_sectors = 0;
|
||||
int res = niffs_linear_map(fs);
|
||||
if (res) return res;
|
||||
u32_t lsix;
|
||||
u32_t max_conseq_free = 0;
|
||||
u32_t cur_conseq_free = 0;
|
||||
u8_t taken = 1;
|
||||
for (lsix = 0; lsix < fs->lin_sectors; lsix++) {
|
||||
if ((fs->buf[lsix/8] & (1<<(lsix&7)))) {
|
||||
i->lin_used_sectors++;
|
||||
cur_conseq_free = 0;
|
||||
taken = 1;
|
||||
} else {
|
||||
cur_conseq_free++;
|
||||
if (taken) taken = 0;
|
||||
max_conseq_free = NIFFS_MAX(cur_conseq_free, max_conseq_free);
|
||||
}
|
||||
}
|
||||
i->lin_max_conseq_free = max_conseq_free;
|
||||
#endif
|
||||
return NIFFS_OK;
|
||||
}
|
||||
|
||||
|
||||
int NIFFS_creat(niffs *fs, const char *name, niffs_mode mode) {
|
||||
(void)mode;
|
||||
if (!fs->mounted) return ERR_NIFFS_NOT_MOUNTED;
|
||||
int res;
|
||||
res = niffs_create(fs, name, _NIFFS_FTYPE_FILE, 0);
|
||||
return res;
|
||||
}
|
||||
|
||||
int NIFFS_open(niffs *fs, const char *name, u8_t flags, niffs_mode mode) {
|
||||
(void)mode;
|
||||
if (!fs->mounted) return ERR_NIFFS_NOT_MOUNTED;
|
||||
int res = NIFFS_OK;
|
||||
niffs_file_type type =
|
||||
flags & NIFFS_O_LINEAR ? _NIFFS_FTYPE_LINFILE : _NIFFS_FTYPE_FILE;
|
||||
#if !NIFFS_LINEAR_AREA
|
||||
if (type == _NIFFS_FTYPE_LINFILE) return ERR_NIFFS_BAD_CONF;
|
||||
#endif
|
||||
if (type) {
|
||||
flags |= NIFFS_O_APPEND; // force append for linear files
|
||||
}
|
||||
int fd_ix = niffs_open(fs, name, flags);
|
||||
if (fd_ix < 0) {
|
||||
// file not found
|
||||
if (fd_ix == ERR_NIFFS_FILE_NOT_FOUND && (flags & NIFFS_O_CREAT)) {
|
||||
res = niffs_create(fs, name, type, 0);
|
||||
if (res == NIFFS_OK) {
|
||||
fd_ix = niffs_open(fs, name, flags);
|
||||
} else {
|
||||
fd_ix = res;
|
||||
}
|
||||
}
|
||||
res = fd_ix;
|
||||
} else {
|
||||
// file found
|
||||
if ((flags & (NIFFS_O_CREAT | NIFFS_O_EXCL)) == (NIFFS_O_CREAT | NIFFS_O_EXCL)) {
|
||||
(void)niffs_close(fs, fd_ix);
|
||||
return ERR_NIFFS_FILE_EXISTS;
|
||||
}
|
||||
}
|
||||
|
||||
if (res != NIFFS_OK) return res;
|
||||
|
||||
if (flags & NIFFS_O_TRUNC) {
|
||||
niffs_file_desc *fd;
|
||||
res = niffs_get_filedesc(fs, fd_ix, &fd);
|
||||
if (res != NIFFS_OK) return res;
|
||||
niffs_object_hdr *ohdr = (niffs_object_hdr *)_NIFFS_PIX_2_ADDR(fs, fd->obj_pix);
|
||||
if (ohdr->len != NIFFS_UNDEF_LEN) {
|
||||
// only truncate if file len is > 0
|
||||
res = niffs_truncate(fs, fd_ix, 0);
|
||||
if (res != NIFFS_OK) {
|
||||
(void)niffs_close(fs, fd_ix);
|
||||
return res;
|
||||
}
|
||||
res = niffs_create(fs, name, type, 0);
|
||||
if (res != NIFFS_OK) return res;
|
||||
fd_ix = niffs_open(fs, name, flags);
|
||||
}
|
||||
}
|
||||
|
||||
return res < 0 ? res : fd_ix;
|
||||
}
|
||||
|
||||
#if NIFFS_LINEAR_AREA
|
||||
|
||||
int NIFFS_mknod_linear(niffs *fs, const char *name, u32_t resv_size) {
|
||||
if (!fs->mounted) return ERR_NIFFS_NOT_MOUNTED;
|
||||
u8_t flags = NIFFS_O_LINEAR | NIFFS_O_RDWR | NIFFS_O_APPEND;
|
||||
int res = NIFFS_OK;
|
||||
|
||||
// check free linear space, fetch starting sector
|
||||
u32_t lsix_start;
|
||||
u32_t resv_sects = (resv_size + fs->sector_size - 1) / fs->sector_size;
|
||||
res = niffs_linear_find_space(fs, resv_sects, &lsix_start);
|
||||
if (res < 0) return res;
|
||||
|
||||
int fd_ix = niffs_open(fs, name, flags);
|
||||
if (fd_ix >= 0) {
|
||||
// file exists
|
||||
(void)niffs_close(fs, fd_ix);
|
||||
return ERR_NIFFS_FILE_EXISTS;
|
||||
}
|
||||
if (fd_ix != ERR_NIFFS_FILE_NOT_FOUND) {
|
||||
// some other error
|
||||
return fd_ix;
|
||||
}
|
||||
// create linear file meta header
|
||||
niffs_linear_file_hdr lfhdr = {.start_sector = lsix_start, .resv_sectors = resv_sects};
|
||||
res = niffs_create(fs, name, _NIFFS_FTYPE_LINFILE, &lfhdr);
|
||||
if (res != NIFFS_OK) return res;
|
||||
fd_ix = niffs_open(fs, name, flags);
|
||||
if (fd_ix < 0) return fd_ix;
|
||||
return fd_ix;
|
||||
}
|
||||
|
||||
#endif // NIFFS_LINEAR_AREA
|
||||
|
||||
int NIFFS_read_ptr(niffs *fs, int fd, u8_t **ptr, u32_t *len) {
|
||||
if (!fs->mounted) return ERR_NIFFS_NOT_MOUNTED;
|
||||
return niffs_read_ptr(fs, fd, ptr, len);
|
||||
}
|
||||
|
||||
int NIFFS_read(niffs *fs, int fd_ix, u8_t *dst, u32_t len) {
|
||||
if (!fs->mounted) return ERR_NIFFS_NOT_MOUNTED;
|
||||
|
||||
int res = NIFFS_OK;
|
||||
s32_t read_len = 0;
|
||||
do {
|
||||
u8_t *rptr;
|
||||
u32_t rlen;
|
||||
res = niffs_read_ptr(fs, fd_ix, &rptr, &rlen);
|
||||
if (res >= 0 && rlen == 0) res = ERR_NIFFS_END_OF_FILE;
|
||||
if (res >= 0) {
|
||||
u32_t clen = NIFFS_MIN(len, rlen);
|
||||
niffs_memcpy(dst, rptr, clen);
|
||||
dst += clen;
|
||||
len -= clen;
|
||||
read_len += clen;
|
||||
res = niffs_seek(fs, fd_ix, clen, NIFFS_SEEK_CUR);
|
||||
}
|
||||
} while (len > 0 && res >= 0);
|
||||
|
||||
if (res == ERR_NIFFS_END_OF_FILE && read_len >= 0) {
|
||||
return read_len;
|
||||
}
|
||||
|
||||
return res == NIFFS_OK ? read_len : res;
|
||||
}
|
||||
|
||||
int NIFFS_lseek(niffs *fs, int fd_ix, s32_t offs, int whence) {
|
||||
if (!fs->mounted) return ERR_NIFFS_NOT_MOUNTED;
|
||||
int res = niffs_seek(fs, fd_ix, offs, whence);
|
||||
if (res == NIFFS_OK) {
|
||||
niffs_file_desc *fd;
|
||||
res = niffs_get_filedesc(fs, fd_ix, &fd);
|
||||
if (res != NIFFS_OK) return res;
|
||||
return (int)fd->offs;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
int NIFFS_remove(niffs *fs, const char *name) {
|
||||
if (!fs->mounted) return ERR_NIFFS_NOT_MOUNTED;
|
||||
int res;
|
||||
|
||||
int fd = NIFFS_open(fs, name, NIFFS_O_WRONLY, 0);
|
||||
if (fd < 0) return fd;
|
||||
res = niffs_truncate(fs, fd, 0);
|
||||
(void)niffs_close(fs, fd);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int NIFFS_fremove(niffs *fs, int fd) {
|
||||
if (!fs->mounted) return ERR_NIFFS_NOT_MOUNTED;
|
||||
return niffs_truncate(fs, fd, 0);
|
||||
}
|
||||
|
||||
int NIFFS_write(niffs *fs, int fd_ix, const u8_t *data, u32_t len) {
|
||||
if (!fs->mounted) return ERR_NIFFS_NOT_MOUNTED;
|
||||
int res;
|
||||
niffs_file_desc *fd;
|
||||
res = niffs_get_filedesc(fs, fd_ix, &fd);
|
||||
if (res != NIFFS_OK) return res;
|
||||
niffs_object_hdr *ohdr = (niffs_object_hdr *)_NIFFS_PIX_2_ADDR(fs, fd->obj_pix);
|
||||
|
||||
s32_t written = 0;
|
||||
if (fd->flags & NIFFS_O_APPEND) {
|
||||
// always append
|
||||
res = niffs_append(fs, fd_ix, data, len);
|
||||
written += len;
|
||||
} else {
|
||||
// check if modify and/or append
|
||||
u32_t mod_len = (ohdr->len == NIFFS_UNDEF_LEN ? 0 : ohdr->len) - fd->offs;
|
||||
mod_len = NIFFS_MIN(mod_len, len);
|
||||
if (mod_len > 0) {
|
||||
res = niffs_modify(fs, fd_ix, fd->offs, data, mod_len);
|
||||
if (res != NIFFS_OK) return res;
|
||||
len -= mod_len;
|
||||
data += mod_len;
|
||||
written += mod_len;
|
||||
}
|
||||
if (len > 0) {
|
||||
res = niffs_append(fs, fd_ix, data, len);
|
||||
written += len;
|
||||
}
|
||||
}
|
||||
|
||||
// if (res == NIFFS_OK) {
|
||||
// res = niffs_seek(fs, fd_ix, len, NIFFS_SEEK_CUR);
|
||||
// }
|
||||
|
||||
return res == 0 ? written : res;
|
||||
}
|
||||
|
||||
int NIFFS_fflush(niffs *fs, int fd) {
|
||||
if (!fs->mounted) return ERR_NIFFS_NOT_MOUNTED;
|
||||
(void)fd;
|
||||
return NIFFS_OK;
|
||||
}
|
||||
|
||||
int NIFFS_stat(niffs *fs, const char *name, niffs_stat *s) {
|
||||
if (!fs->mounted) return ERR_NIFFS_NOT_MOUNTED;
|
||||
int res;
|
||||
|
||||
int fd = NIFFS_open(fs, name, 0, 0);
|
||||
if (fd < 0) return fd;
|
||||
res = NIFFS_fstat(fs, fd, s);
|
||||
(void)niffs_close(fs, fd);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int NIFFS_fstat(niffs *fs, int fd_ix, niffs_stat *s) {
|
||||
if (!fs->mounted) return ERR_NIFFS_NOT_MOUNTED;
|
||||
int res;
|
||||
|
||||
niffs_file_desc *fd;
|
||||
res = niffs_get_filedesc(fs, fd_ix, &fd);
|
||||
if (res != NIFFS_OK) return res;
|
||||
|
||||
niffs_object_hdr *ohdr = (niffs_object_hdr *)_NIFFS_PIX_2_ADDR(fs, fd->obj_pix);
|
||||
|
||||
s->obj_id = ohdr->phdr.id.obj_id;
|
||||
s->size = ohdr->len == NIFFS_UNDEF_LEN ? 0 : ohdr->len;
|
||||
s->type = ohdr->type;
|
||||
niffs_strncpy((char *)s->name, (char *)ohdr->name, NIFFS_NAME_LEN);
|
||||
|
||||
return NIFFS_OK;
|
||||
}
|
||||
|
||||
int NIFFS_ftell(niffs *fs, int fd_ix) {
|
||||
if (!fs->mounted) return ERR_NIFFS_NOT_MOUNTED;
|
||||
int res;
|
||||
|
||||
niffs_file_desc *fd;
|
||||
res = niffs_get_filedesc(fs, fd_ix, &fd);
|
||||
if (res != NIFFS_OK) return res;
|
||||
|
||||
return (int)fd->offs;
|
||||
}
|
||||
|
||||
int NIFFS_close(niffs *fs, int fd) {
|
||||
if (!fs->mounted) return ERR_NIFFS_NOT_MOUNTED;
|
||||
return niffs_close(fs, fd);
|
||||
}
|
||||
|
||||
int NIFFS_rename(niffs *fs, const char *old_name, const char *new_name) {
|
||||
if (!fs->mounted) return ERR_NIFFS_NOT_MOUNTED;
|
||||
return niffs_rename(fs, old_name, new_name);
|
||||
}
|
||||
|
||||
niffs_DIR *NIFFS_opendir(niffs *fs, const char *name, niffs_DIR *d) {
|
||||
(void)name;
|
||||
if (!fs->mounted) return 0;
|
||||
d->fs = fs;
|
||||
d->pix = 0;
|
||||
return d;
|
||||
}
|
||||
|
||||
int NIFFS_closedir(niffs_DIR *d) {
|
||||
if (!d->fs->mounted) return ERR_NIFFS_NOT_MOUNTED;
|
||||
return NIFFS_OK;
|
||||
}
|
||||
|
||||
static int niffs_readdir_v(niffs *fs, niffs_page_ix pix, niffs_page_hdr *phdr, void *v_arg) {
|
||||
(void)fs;
|
||||
struct niffs_dirent *e = (struct niffs_dirent *)v_arg;
|
||||
if (_NIFFS_IS_FLAG_VALID(phdr) && !_NIFFS_IS_FREE(phdr) && !_NIFFS_IS_DELE(phdr)) {
|
||||
if (_NIFFS_IS_OBJ_HDR(phdr)) {
|
||||
// object header page
|
||||
niffs_object_hdr *ohdr = (niffs_object_hdr *)phdr;
|
||||
e->obj_id = ohdr->phdr.id.obj_id;
|
||||
e->pix = pix;
|
||||
e->size = ohdr->len == NIFFS_UNDEF_LEN ? 0 : ohdr->len;
|
||||
e->type = ohdr->type;
|
||||
niffs_strncpy((char *)e->name, (char *)ohdr->name, NIFFS_NAME_LEN);
|
||||
return NIFFS_OK;
|
||||
}
|
||||
}
|
||||
return NIFFS_VIS_CONT;
|
||||
}
|
||||
|
||||
struct niffs_dirent *NIFFS_readdir(niffs_DIR *d, struct niffs_dirent *e) {
|
||||
if (!d->fs->mounted) return 0;
|
||||
struct niffs_dirent *ret = 0;
|
||||
|
||||
int res = niffs_traverse(d->fs, d->pix, 0, niffs_readdir_v, e);
|
||||
if (res == NIFFS_OK) {
|
||||
d->pix = e->pix + 1;
|
||||
ret = e;
|
||||
} else if (res == NIFFS_VIS_END) {
|
||||
// end of stream
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int NIFFS_chk(niffs *fs) {
|
||||
if (fs->mounted) return ERR_NIFFS_MOUNTED;
|
||||
return niffs_chk(fs);
|
||||
}
|
2229
src/niffs/niffs_internal.c
Normal file
2229
src/niffs/niffs_internal.c
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user