blob: 131a2a477b74a5d5973e6ecb280e9de382dbb8b0 [file] [log] [blame]
// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#include <stdio_tfs.h>
#include <posix.h>
#include <fsdriver.h>
/***********************************************************************/
/* Configuration */
/***********************************************************************/
#ifndef FS_MEM_PROFILE
#define FS_MEM_PROFILE FALSE // TRUE to enable FS heap profiling
#endif
#define INC_FAT_MBR INC_FAT
/***********************************************************************/
/* Symbol Definitions */
/***********************************************************************/
// FS API input parameter checking
#define FS_PARM_CHECK (OS_PARM_CHECK || CIFS_INCLUDED)
// FSEARCH codes
#define FIRST_DIR 0
#define CURR_DIR 1
#define PARENT_DIR 2
#define ACTUAL_DIR 3
#define DIR_FILE 4
// The different types of FileTable entries
#define FEMPTY 0
#define FDIREN 1
#define FCOMMN 2
#define FFILEN 3
// The different types of sectors
#define FOTHR 0
#define FHEAD 1
#define FTAIL 2
// Number of entries per file table
#define FNUM_ENT 20
// Flag values for writing/skipping control information
#define FFLUSH_DO 1
#define FFLUSH_DONT 0
// Flag values for adjusting file pointers in file control blocks
#define ADJUST_FCBs TRUE
#define DONT_ADJUST_FCBs FALSE
// Flag values for acquiring exclusive access to volumes
#define FS_GRAB_SEM TRUE
#define FS_NO_SEM FALSE
// Flag values for FS sync
#define FORCED_SYNC TRUE
#define UNFORCED_SYNC FALSE
// Flag values for the file/directory structure
#define F_WRITE (1u << 0)
#define F_READ (1u << 1)
#define F_EXECUTE (1u << 2)
#define F_APPEND (1u << 3)
#define F_NONBLOCK (1u << 4)
#define F_ASYNC (1u << 5)
#define FCB_DIR (1u << 6)
#define FCB_FILE (1u << 7)
#define FCB_TTY (1u << 8)
#define FCB_MOD (1u << 9)
#define FCB_NO_UPDATE (1u << 10)
#define FCB_CLOSE (1u << 11)
#define FCB_ESC_HIT (1u << 12)
#define FCB_NO_OVERWRITE (1u << 13)
#define FSEARCH_NO_SEM (1u << 14)
// Flag values for FSearchFSUID()
#define FILE_NAME 1
#define PATH_NAME 2
// Return values for TFFS recycle function
#define RECYCLE_FAILED -1
#define RECYCLE_NOT_NEEDED 1
#define RECYCLE_OK 0
#define REMOVED_LINK 0xFFFFFFFF // Value assigned to next and
// prev for removed link
#define OFF_REMOVED_LINK 0xFFFE
#define ROOT_DIR_INDEX FOPEN_MAX // index in Files[] for root
// Maximum allowed number of FFS_VOLS + FAT_VOLS with NAND_FTLS or fixed
// This value is used to issue volume ID numbers for the FSUID when a
// serial number is not provided
#define MAX_FIXED_VOLS 32
/*
** Number of bits the file ID, volume ID take in the 32 bit FSUID
*/
#define FID_LEN 20
#define VID_LEN 8
#define FID_MASK 0xFFFFFu // MUST be 2^FID_LEN - 1
#define VID_MASK 0xFFu // MUST be 2^VID_LEN - 1
#define FSUID_MASK ((VID_MASK << FID_LEN) | FID_MASK)
// Default block read limits to avoid read-disturb errors
#define MLC_NAND_RC_LIMIT 100000
#define SLC_NAND_RC_LIMIT 1000000
#define NOR_RC_LIMIT 1000000
// Symbols for excluding/including SLC/MLC-specific code
#define INC_NDM_SLC (INC_FTL_NDM_SLC || INC_FFS_NDM_SLC)
#define INC_NDM_MLC (INC_FFS_NDM_MLC || INC_FTL_NDM_MLC)
/***********************************************************************/
/* Macro Definitions */
/***********************************************************************/
// Bitmap accessors
#define BITMAP_ON(start, i) (*((ui8*)(start) + (i) / 8) |= (ui8)(1 << ((i) % 8)))
#define BITMAP_OFF(start, i) (*((ui8*)(start) + (i) / 8) &= (ui8) ~(1 << ((i) % 8)))
#define IS_BITMAP_ON(start, i) (*((ui8*)(start) + (i) / 8) & (1 << ((i) % 8)))
// Create an FSUID val(ui32) based on volume number and file number
#define FSUID(vid, fid) (ui32)((((vid)&VID_MASK) << FID_LEN) | ((fid)&FID_MASK))
// Accessor macros for volume ID, file ID from an FSUID
#define GET_VID(fsuid) (((fsuid) & (VID_MASK << FID_LEN)) >> FID_LEN)
#define GET_FID(fsuid) ((fsuid)&FID_MASK)
// Determine if an FCB pointer/fid is valid
#define IS_VALID_FCB(fcbp) ((fcbp) && (fcbp) >= &Files[0] && (fcbp) < &Files[FOPEN_MAX])
#define IS_VALID_FID(fid) ((fid) >= 0 && (fid) < FOPEN_MAX)
// Determine if a file system volume is on the mounted list
#define IS_MOUNTED(vol) ((vol)->sys.prev || (MountedList.head == &((vol)->sys)))
/***********************************************************************/
/* Type Definitions */
/***********************************************************************/
typedef struct file_sys FileSys;
struct file_sys {
FileSys* next;
FileSys* prev;
ui32 flags; // holds various volume bit flags
#define FSYS_FATAL_ERR (1 << 0)
#define FSYS_READ_ONLY (1 << 1)
#define FSYS_VOL_BUSY (1 << 2)
void* (*ioctl)(FILE_TFS* stream, int code, ...);
void* volume;
#if FILE_AIO_INC
int aio_buf_size; // max number of buffered AIO transfers
int aio_num_bufs; // number of sectors in each AIO transfer
#endif
char name[(FILENAME_MAX + 3) & ~3]; // avoid extra padding
};
typedef struct head_entry {
FileSys* head;
FileSys* tail;
} HeadEntry;
#if FILE_OFFSETS
// An indivual value in the offsets values array
typedef struct {
ui32 sect_num; // volume sector for offset
ui32 sect_off; // sector offset within file for offset
} FOff;
// FCB offsets type
typedef struct {
FOff values[FILE_OFFSETS]; // recorded file offsets
ui32 f_sects; // recorded file size in sectors
} FOffs;
#endif // FILE_OFFSETS
// FILE implementation for stdio.h, DIR implementation for posix.h
struct file {
SEM sem; // internal locking semaphore
void (*acquire)(FILE_TFS* fcb, uint access_mode);
void (*release)(FILE_TFS* fcb, uint access_mode);
void* handle; // self handle to be passed to ioctl
void* volume; // file system file/dir belongs to
void* pos; // directory position; used for readdir
void* (*ioctl)(FILE_TFS* fcb, int code, ...);
int (*read_TFS)(FILE_TFS* fcb, ui8* buf, ui32 len);
int (*write_TFS)(FILE_TFS* fcb, const ui8* buf, ui32 len);
#if FILE_AIO_INC
void* aio_ext; // asynchronous I/O control block
#endif
#if FILE_OFFSETS
FOffs* offsets; // file offsets
#endif
int hold_char;
int errcode;
struct dirent_TFS dent; // used by readdir()
fpos_t_TFS curr_ptr; // current position in file
fpos_t_TFS old_ptr; // previous position in file
ui32 flags; // file/dir specific flags
ui32 parent; // parent directory
};
// Ioctl() Commands
typedef enum {
// Begin list of APIs that cause state change. Must be grouped together
// numerically because XFS uses range comparisons to test for these.
CHMOD = 1,
CHOWN,
CLOSE_UNLINK,
FCLOSE,
FFLUSH,
FSEEK,
FSEEK64,
FSTAT_SET,
FTRUNCATE,
FTRUNCATE64,
LINK,
MKDIR,
OPEN,
REMOVE,
RENAME,
RMDIR,
SHRED,
SORTDIR,
STAT_SET,
TRUNCATE,
TRUNCATE64,
UNLINK_ALL,
UTIME,
VFS_CREATE,
VFS_LINK,
VFS_MKDIR,
VFS_RENAME,
VFS_TRUNCATE,
VFS_FTRUNCATE64,
VFS_UNLINK,
// End list of APIs that cause change of media state
ACCESS,
ATTRIB,
CHDIR,
CLOSEDIR,
CTIME,
DISABLE_SYNC,
DUP,
ENABLE_SYNC,
FEOF,
FREOPEN,
FSEARCH,
FSETPOS,
FRSTAT,
FSTAT,
FTELL,
GETCWD,
GET_FL,
GET_FSUID,
GET_FSUID_FID,
GET_NAME,
GET_QUOTA,
GET_QUOTAM,
ISOPEN,
MMAP,
NXT_SECT_CHAIN,
OPENDIR,
PARAM_DELETE,
PARAM_READ,
PARAM_SIZE,
PARAM_WRITE,
READDIR,
READDIR_OPEN,
READDIR_STAT,
REWINDDIR,
RSTAT,
SECT_FIRST,
SECT_NEXT,
SETVBUF,
SET_FL,
STAT,
TMPFILE,
TMPNAM,
UNMOUNT,
VCLEAN,
VMEMGB,
VSTAT,
VSYNC,
VFS_OPEN
} IOCTLS;
typedef struct f_f_e FFSEnt;
typedef struct r_f_e RFSEnt;
typedef struct flash_entries FFSEnts;
typedef struct ram_entries RFSEnts;
typedef struct {
ui16 sector;
ui16 offset;
} OffLoc;
// Represents structure of common info between dir and file in RAM
typedef struct {
uid_t user_id; // used ID
gid_t group_id; // group ID
mode_t mode; // file/dir create mode
ui16 padding;
time_t mod_time; // last modified time for entry
time_t ac_time; // last access time for entry
ui32 size; // size of file (0 for dirs)
ui32 fileno; // file/dir number
ui32 attrib; // attribute() field
FFSEnt* addr; // entry location in RAM
OffLoc one_past_last; // pointer to one past the EOF
ui16 frst_sect; // first sector for files (0 for dirs)
ui16 last_sect; // last sector for files (0 for dirs)
ui8 link_cnt; // number of links from file/dir
ui8 open_cnt; // number of file/dir open FCBs
ui8 open_mode; // file/dir open mode
ui8 opl_offset_hi; // one past last offset overflow byte
} FCOM_T;
// RFS variation of common entry
typedef struct {
uid_t user_id; // user ID
gid_t group_id; // group ID
mode_t mode; // file/dir create mode
ui16 padding;
time_t mod_time; // last modified time for entry
time_t ac_time; // last access time for entry
ui32 size; // size of file (0 for dirs)
ui32 fileno; // file/dir number
RFSEnt* addr; // entry location in RAM
ui32 one_past_last; // offset within last sector
void* first; // first sector(file)/entry(directory)
void* last; // last sector(file)
ui8 link_cnt; // number of links from file/dir
ui8 open_cnt; // number of file/dir open FCBs
ui8 open_mode; // file/dir open mode
ui8 temp; // indicates temporary file
} RCOM_T;
// Represents structure of a link to a file as used in RAM
typedef struct {
char* name; // link name
FFSEnt* next; // next entry in parent directory
FFSEnt* prev; // prev entry in parent directory
FCOM_T* comm; // pointer to actual file info
FFSEnt* parent_dir; // pointer to parent directory
uint open_cnt; // number of file entry opens
} FFIL_T;
// Represents structure of a link to a dir as used in RAM
typedef struct {
char* name; // directory name
FFSEnt* next; // next entry in parent directory
FFSEnt* prev; // prev entry in parent directory
FCOM_T* comm; // pointer to actual dir info
FFSEnt* parent_dir; // pointer to parent directory
uint open_cnt; // number of directory entry opens
FFSEnt* first; // head of contents list for dir
#if QUOTA_ENABLED
ui32 max_q; // max quota
ui32 min_q; // min quota
ui32 used; // used space
ui32 free; // free space
ui32 free_below; // free space below
ui32 res_below; // reserved below
#endif
} FDIR_T;
// RFS variation of file entry
typedef struct {
char* name; // file/directory name
RFSEnt* next; // next entry in parent directory
RFSEnt* prev; // prev entry in parent directory
RCOM_T* comm; // pointer to common entry
RFSEnt* parent_dir; // pointer to parent directory
uint open_cnt; // number of file entry opens
} RFIL_T;
typedef RFIL_T RDIR_T;
// Represents the type for an entry in RAM (dir, file or link)
union f_file_entry {
FDIR_T dir;
FCOM_T comm;
FFIL_T file;
};
// Represents the type for an entry for RFS (dif, file or link)
union r_file_entry {
RDIR_T dir;
RCOM_T comm;
RFIL_T file;
};
// An entry in RAM consists of its type and value as a union
struct f_f_e {
union f_file_entry entry;
ui8 type;
FFSEnts* tbl;
};
// An entry in RFS consists of its type and value as a union
struct r_f_e {
union r_file_entry entry;
ui8 type;
};
// Holds a table full of entries, pointers to next and prev, num free
struct flash_entries {
FFSEnt tbl[FNUM_ENT];
FFSEnts* next_tbl;
FFSEnts* prev_tbl;
ui32 free;
ui32 num;
};
struct ram_entries {
RFSEnt tbl[FNUM_ENT];
RFSEnts* next_tbl;
RFSEnts* prev_tbl;
ui32 free;
};
// Structure to cast all volume structures to, to retrieve ioctl_func
typedef struct {
CircLink link; /*lint !e601, !e10*/
FileSys sys;
} FsVolume;
#if FS_CRYPT
// FS Crypt Type
typedef struct fscrypt FSCrypt;
struct fscrypt {
// Public API
void (*delete)(FSCrypt** fs_crypt);
int (*decr)(const FSCrypt* fs_crypt, ui8* data, ui32 vpn, int n);
int (*rd_decr)(const FSCrypt* fs_crypt, ui8* data, ui32 vpn, int n);
int (*encr)(const FSCrypt* fs_crypt, ui8* data, ui32 vpn, int n);
int (*encr_wr)(const FSCrypt* fs_crypt, const ui8* data, ui32 vpn, int n);
ui32 (*ram_use)(const FSCrypt* fs_crypt);
ui32 page_sz; // FS read/write page size
ui32 buf_pgs; // encryption buffer size in pages
ui8* buf; // encryption buffer
void* crypt; // encryption/decryption engine
void* fs_vol; // parameter passed to FS driver functions
// FS driver read/write
int (*fs_wr)(const void* buf, ui32 frst, int n, void* fs_vol);
int (*fs_rd)(void* buf, ui32 frst, int n, void* fs_vol);
};
#endif // FS_CRYPT
/***********************************************************************/
/* Variable Declarations */
/***********************************************************************/
extern int CurrFixedVols;
extern FILE_TFS Files[FOPEN_MAX + 1];
extern HeadEntry MountedList;
extern FileSys TtySys;
extern int FsMaxOpen; // maximum # of concurrently open files
extern void* FSIterCurrVol;
// FS Volumes Lists
extern CircLink FatVols;
extern CircLink FfsVols;
extern CircLink XfsVols;
extern CircLink RfsVols;
extern CircLink ZfsVols;
/***********************************************************************/
/* Function Prototypes */
/***********************************************************************/
// File/directory path lookup related functions
int FsInvalName(const char* name, int ignore_last);
int FsIsLast(const char* name, ui32* lenp, ui32* incp);
const char* FsSkipSeparators(const char* path);
void* FSearch(void* hndl, const char** path, int dir_lookup, uint flags);
char* FSearchFSUID(ui32 fsuid, char* buf, size_t size, int lookup);
FileSys* FsResolvePath(const char* path);
// General system/root level functions
int IsFreeFCB(const FILE_TFS* file);
void FsInitFCB(FILE_TFS* file, ui32 type);
void FsCopyFCB(FILE_TFS* dst, const FILE_TFS* src);
int DirFileWrite(FILE_TFS* stream, const ui8* buf, ui32 len);
int DirFileRead(FILE_TFS* stream, ui8* buf, ui32 len);
void* RootIoctl(DIR_TFS* dir, int code, ...);
int FsError(int err_code);
int FsIoError(FileSys* file_sys);
int FsSetErrno(int flags);
// Auxiliary functions
void QuickSort(RFSEnt** head, RFSEnt** tail, DirEntry* e1, DirEntry* e2,
int (*cmp)(const DirEntry*, const DirEntry*));
int FNameEqu(const char* s1, const char* s2);
int FNameEquN(const char* s1, const char* s2, size_t n);
void DNameCpy(char* dst, const char* src);
int DNameEqu(const char* s1, const char* s2);
int DNameEquCase(const char* s1, const char* s2);
size_t DNameLen(const char* s);
void FsAddMount(FileSys* volume);
void FsDelMount(FileSys* volume);
void* FtlNdmAddFatFTL(FtlNdmVol* ftl_dvr, FatVol* fat_dvr);
void* FtlNdmAddXfsFTL(FtlNdmVol* ftl_dvr, XfsVol* xfs_dvr);
void FtlnFreeFTL(void* ftl);
int FsConvOpenMode(const char* mode);
int FsCheckPerm(mode_t mode, uid_t uid, gid_t gid, uint permissions);
void FsSetFl(FILE_TFS* fcb, int oflag);
void* FsGetFl(const FILE_TFS* fcb);
int FsFormatResetWc(const char* name);
int FatGetSectSize(const FatVol* fat_vol);
ui32 UDiv64(ui64 dividend, ui32 divisor);
void FsMemPrn(void);
ui32 FsMemPeakRst(void);
#if FS_CRYPT
// FS Crypt Initialization
FSCrypt* FsCryptNew(FSCryptDrvr* fs_crypt);
int FsCryptSetBufSz(FSCrypt* fs_crypt, ui32 buf_pgs);
#endif
// FCB recorded file offsets interface
fpos_t_TFS FOffGet(const FILE_TFS* fcbp, ui32 sect_off, ui32 frst_sect);
void FOffSet(FILE_TFS* fcbp, const fpos_t_TFS* new_pos, ui32 f_sects);
void FOffUpdate(const FILE_TFS* fcbp, ui32 old_sect, ui32 new_sect);
void FOffDel(FILE_TFS* fcbp);
// Asynchronous I/O
void aioInit(void);
int aioOpen(FILE_TFS* file, int sect_size);
void aioSetIdle(FILE_TFS* file, uint code);
void aioVolInit(FileSys* vol);
// File System Memory Allocation Wrapper Functions
void* FsCalloc(size_t nmemb, size_t size);
void* FsMalloc(size_t size);
void* FsAalloc(size_t size);
void FsFreeClear(void* ptr_ptr);
void FsAfreeClear(void* ptr_ptr);
void FsFree(void* ptr);
#ifdef __cplusplus
}
#endif