1 // Copyright 2018 The Fuchsia Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #pragma once
6 
7 #ifdef __cplusplus
8 extern "C" {
9 #endif
10 
11 #include <stdio_tfs.h>
12 #include <posix.h>
13 #include <fsdriver.h>
14 
15 /***********************************************************************/
16 /* Configuration                                                       */
17 /***********************************************************************/
18 #ifndef FS_MEM_PROFILE
19 #define FS_MEM_PROFILE FALSE  // TRUE to enable FS heap profiling
20 #endif
21 #define INC_FAT_MBR INC_FAT
22 
23 /***********************************************************************/
24 /* Symbol Definitions                                                  */
25 /***********************************************************************/
26 // FS API input parameter checking
27 #define FS_PARM_CHECK (OS_PARM_CHECK || CIFS_INCLUDED)
28 
29 // FSEARCH codes
30 #define FIRST_DIR   0
31 #define CURR_DIR    1
32 #define PARENT_DIR  2
33 #define ACTUAL_DIR  3
34 #define DIR_FILE    4
35 
36 // The different types of FileTable entries
37 #define FEMPTY 0
38 #define FDIREN 1
39 #define FCOMMN 2
40 #define FFILEN 3
41 
42 // The different types of sectors
43 #define FOTHR 0
44 #define FHEAD 1
45 #define FTAIL 2
46 
47 // Number of entries per file table
48 #define FNUM_ENT 20
49 
50 // Flag values for writing/skipping control information
51 #define FFLUSH_DO 1
52 #define FFLUSH_DONT 0
53 
54 // Flag values for adjusting file pointers in file control blocks
55 #define ADJUST_FCBs TRUE
56 #define DONT_ADJUST_FCBs FALSE
57 
58 // Flag values for acquiring exclusive access to volumes
59 #define FS_GRAB_SEM TRUE
60 #define FS_NO_SEM FALSE
61 
62 // Flag values for FS sync
63 #define FORCED_SYNC TRUE
64 #define UNFORCED_SYNC FALSE
65 
66 // Flag values for the file/directory structure
67 #define F_WRITE            (1u << 0)
68 #define F_READ             (1u << 1)
69 #define F_EXECUTE          (1u << 2)
70 #define F_APPEND           (1u << 3)
71 #define F_NONBLOCK         (1u << 4)
72 #define F_ASYNC            (1u << 5)
73 
74 #define FCB_DIR            (1u << 6)
75 #define FCB_FILE           (1u << 7)
76 #define FCB_TTY            (1u << 8)
77 #define FCB_MOD            (1u << 9)
78 #define FCB_NO_UPDATE      (1u << 10)
79 #define FCB_CLOSE          (1u << 11)
80 #define FCB_ESC_HIT        (1u << 12)
81 #define FCB_NO_OVERWRITE   (1u << 13)
82 #define FSEARCH_NO_SEM     (1u << 14)
83 
84 // Flag values for FSearchFSUID()
85 #define FILE_NAME 1
86 #define PATH_NAME 2
87 
88 // Return values for TFFS recycle function
89 #define RECYCLE_FAILED      -1
90 #define RECYCLE_NOT_NEEDED  1
91 #define RECYCLE_OK          0
92 
93 #define REMOVED_LINK 0xFFFFFFFF // Value assigned to next and
94                                 // prev for removed link
95 #define OFF_REMOVED_LINK 0xFFFE
96 
97 #define ROOT_DIR_INDEX FOPEN_MAX // index in Files[] for root
98 
99 // Maximum allowed number of FFS_VOLS + FAT_VOLS with NAND_FTLS or fixed
100 // This value is used to issue volume ID numbers for the FSUID when a
101 // serial number is not provided
102 #define MAX_FIXED_VOLS 32
103 
104 /*
105 ** Number of bits the file ID, volume ID take in the 32 bit FSUID
106 */
107 #define FID_LEN 20
108 #define VID_LEN 8
109 
110 #define FID_MASK 0xFFFFFu // MUST be 2^FID_LEN - 1
111 #define VID_MASK 0xFFu    // MUST be 2^VID_LEN - 1
112 #define FSUID_MASK ((VID_MASK << FID_LEN) | FID_MASK)
113 
114 // Default block read limits to avoid read-disturb errors
115 #define MLC_NAND_RC_LIMIT 100000
116 #define SLC_NAND_RC_LIMIT 1000000
117 #define NOR_RC_LIMIT 1000000
118 
119 // Symbols for excluding/including SLC/MLC-specific code
120 #define INC_NDM_SLC (INC_FTL_NDM_SLC || INC_FFS_NDM_SLC)
121 #define INC_NDM_MLC (INC_FFS_NDM_MLC || INC_FTL_NDM_MLC)
122 
123 /***********************************************************************/
124 /* Macro Definitions                                                   */
125 /***********************************************************************/
126 // Bitmap accessors
127 #define BITMAP_ON(start, i) (*((ui8*)(start) + (i) / 8) |= (ui8)(1 << ((i) % 8)))
128 #define BITMAP_OFF(start, i) (*((ui8*)(start) + (i) / 8) &= (ui8) ~(1 << ((i) % 8)))
129 #define IS_BITMAP_ON(start, i) (*((ui8*)(start) + (i) / 8) & (1 << ((i) % 8)))
130 
131 // Create an FSUID val(ui32) based on volume number and file number
132 #define FSUID(vid, fid) (ui32)((((vid)&VID_MASK) << FID_LEN) | ((fid)&FID_MASK))
133 
134 // Accessor macros for volume ID, file ID from an FSUID
135 #define GET_VID(fsuid) (((fsuid) & (VID_MASK << FID_LEN)) >> FID_LEN)
136 #define GET_FID(fsuid) ((fsuid)&FID_MASK)
137 
138 // Determine if an FCB pointer/fid is valid
139 #define IS_VALID_FCB(fcbp) ((fcbp) && (fcbp) >= &Files[0] && (fcbp) < &Files[FOPEN_MAX])
140 #define IS_VALID_FID(fid) ((fid) >= 0 && (fid) < FOPEN_MAX)
141 
142 // Determine if a file system volume is on the mounted list
143 #define IS_MOUNTED(vol) ((vol)->sys.prev || (MountedList.head == &((vol)->sys)))
144 
145 /***********************************************************************/
146 /* Type Definitions                                                    */
147 /***********************************************************************/
148 typedef struct file_sys FileSys;
149 struct file_sys {
150     FileSys* next;
151     FileSys* prev;
152     ui32 flags; // holds various volume bit flags
153 #define FSYS_FATAL_ERR (1 << 0)
154 #define FSYS_READ_ONLY (1 << 1)
155 #define FSYS_VOL_BUSY (1 << 2)
156     void* (*ioctl)(FILE_TFS* stream, int code, ...);
157     void* volume;
158 #if FILE_AIO_INC
159     int aio_buf_size; // max number of buffered AIO transfers
160     int aio_num_bufs; // number of sectors in each AIO transfer
161 #endif
162     char name[(FILENAME_MAX + 3) & ~3]; // avoid extra padding
163 };
164 
165 typedef struct head_entry {
166     FileSys* head;
167     FileSys* tail;
168 } HeadEntry;
169 
170 #if FILE_OFFSETS
171 // An indivual value in the offsets values array
172 typedef struct {
173     ui32 sect_num; // volume sector for offset
174     ui32 sect_off; // sector offset within file for offset
175 } FOff;
176 
177 // FCB offsets type
178 typedef struct {
179     FOff values[FILE_OFFSETS]; // recorded file offsets
180     ui32 f_sects;              // recorded file size in sectors
181 } FOffs;
182 #endif // FILE_OFFSETS
183 
184 // FILE implementation for stdio.h, DIR implementation for posix.h
185 struct file {
186     SEM sem; // internal locking semaphore
187     void (*acquire)(FILE_TFS* fcb, uint access_mode);
188     void (*release)(FILE_TFS* fcb, uint access_mode);
189     void* handle; // self handle to be passed to ioctl
190     void* volume; // file system file/dir belongs to
191     void* pos;    // directory position; used for readdir
192     void* (*ioctl)(FILE_TFS* fcb, int code, ...);
193     int (*read_TFS)(FILE_TFS* fcb, ui8* buf, ui32 len);
194     int (*write_TFS)(FILE_TFS* fcb, const ui8* buf, ui32 len);
195 #if FILE_AIO_INC
196     void* aio_ext; // asynchronous I/O control block
197 #endif
198 #if FILE_OFFSETS
199     FOffs* offsets; // file offsets
200 #endif
201     int hold_char;
202     int errcode;
203     struct dirent_TFS dent; // used by readdir()
204     fpos_t_TFS curr_ptr;    // current position in file
205     fpos_t_TFS old_ptr;     // previous position in file
206     ui32 flags;             // file/dir specific flags
207     ui32 parent;            // parent directory
208 };
209 
210 // Ioctl() Commands
211 typedef enum {
212     // Begin list of APIs that cause state change. Must be grouped together
213     // numerically because XFS uses range comparisons to test for these.
214     CHMOD = 1,
215     CHOWN,
216     CLOSE_UNLINK,
217     FCLOSE,
218     FFLUSH,
219     FSEEK,
220     FSEEK64,
221     FSTAT_SET,
222     FTRUNCATE,
223     FTRUNCATE64,
224     LINK,
225     MKDIR,
226     OPEN,
227     REMOVE,
228     RENAME,
229     RMDIR,
230     SHRED,
231     SORTDIR,
232     STAT_SET,
233     TRUNCATE,
234     TRUNCATE64,
235     UNLINK_ALL,
236     UTIME,
237     VFS_CREATE,
238     VFS_LINK,
239     VFS_MKDIR,
240     VFS_RENAME,
241     VFS_TRUNCATE,
242     VFS_FTRUNCATE64,
243     VFS_UNLINK,
244     // End list of APIs that cause change of media state
245     ACCESS,
246     ATTRIB,
247     CHDIR,
248     CLOSEDIR,
249     CTIME,
250     DISABLE_SYNC,
251     DUP,
252     ENABLE_SYNC,
253     FEOF,
254     FREOPEN,
255     FSEARCH,
256     FSETPOS,
257     FRSTAT,
258     FSTAT,
259     FTELL,
260     GETCWD,
261     GET_FL,
262     GET_FSUID,
263     GET_FSUID_FID,
264     GET_NAME,
265     GET_QUOTA,
266     GET_QUOTAM,
267     ISOPEN,
268     MMAP,
269     NXT_SECT_CHAIN,
270     OPENDIR,
271     PARAM_DELETE,
272     PARAM_READ,
273     PARAM_SIZE,
274     PARAM_WRITE,
275     READDIR,
276     READDIR_OPEN,
277     READDIR_STAT,
278     REWINDDIR,
279     RSTAT,
280     SECT_FIRST,
281     SECT_NEXT,
282     SETVBUF,
283     SET_FL,
284     STAT,
285     TMPFILE,
286     TMPNAM,
287     UNMOUNT,
288     VCLEAN,
289     VMEMGB,
290     VSTAT,
291     VSYNC,
292     VFS_OPEN
293 } IOCTLS;
294 
295 typedef struct f_f_e FFSEnt;
296 typedef struct r_f_e RFSEnt;
297 typedef struct flash_entries FFSEnts;
298 typedef struct ram_entries RFSEnts;
299 
300 typedef struct {
301     ui16 sector;
302     ui16 offset;
303 } OffLoc;
304 
305 // Represents structure of common info between dir and file in RAM
306 typedef struct {
307     uid_t user_id;  // used ID
308     gid_t group_id; // group ID
309     mode_t mode;    // file/dir create mode
310     ui16 padding;
311     time_t mod_time;      // last modified time for entry
312     time_t ac_time;       // last access time for entry
313     ui32 size;            // size of file (0 for dirs)
314     ui32 fileno;          // file/dir number
315     ui32 attrib;          // attribute() field
316     FFSEnt* addr;         // entry location in RAM
317     OffLoc one_past_last; // pointer to one past the EOF
318     ui16 frst_sect;       // first sector for files (0 for dirs)
319     ui16 last_sect;       // last sector for files (0 for dirs)
320     ui8 link_cnt;         // number of links from file/dir
321     ui8 open_cnt;         // number of file/dir open FCBs
322     ui8 open_mode;        // file/dir open mode
323     ui8 opl_offset_hi;    // one past last offset overflow byte
324 } FCOM_T;
325 
326 // RFS variation of common entry
327 typedef struct {
328     uid_t user_id;  // user ID
329     gid_t group_id; // group ID
330     mode_t mode;    // file/dir create mode
331     ui16 padding;
332     time_t mod_time;    // last modified time for entry
333     time_t ac_time;     // last access time for entry
334     ui32 size;          // size of file (0 for dirs)
335     ui32 fileno;        // file/dir number
336     RFSEnt* addr;       // entry location in RAM
337     ui32 one_past_last; // offset within last sector
338     void* first;        // first sector(file)/entry(directory)
339     void* last;         // last sector(file)
340     ui8 link_cnt;       // number of links from file/dir
341     ui8 open_cnt;       // number of file/dir open FCBs
342     ui8 open_mode;      // file/dir open mode
343     ui8 temp;           // indicates temporary file
344 } RCOM_T;
345 
346 // Represents structure of a link to a file as used in RAM
347 typedef struct {
348     char* name;         // link name
349     FFSEnt* next;       // next entry in parent directory
350     FFSEnt* prev;       // prev entry in parent directory
351     FCOM_T* comm;       // pointer to actual file info
352     FFSEnt* parent_dir; // pointer to parent directory
353     uint open_cnt;      // number of file entry opens
354 } FFIL_T;
355 
356 // Represents structure of a link to a dir as used in RAM
357 typedef struct {
358     char* name;         // directory name
359     FFSEnt* next;       // next entry in parent directory
360     FFSEnt* prev;       // prev entry in parent directory
361     FCOM_T* comm;       // pointer to actual dir info
362     FFSEnt* parent_dir; // pointer to parent directory
363     uint open_cnt;      // number of directory entry opens
364     FFSEnt* first;      // head of contents list for dir
365 #if QUOTA_ENABLED
366     ui32 max_q;      // max quota
367     ui32 min_q;      // min quota
368     ui32 used;       // used space
369     ui32 free;       // free space
370     ui32 free_below; // free space below
371     ui32 res_below;  // reserved below
372 #endif
373 } FDIR_T;
374 
375 // RFS variation of file entry
376 typedef struct {
377     char* name;         // file/directory name
378     RFSEnt* next;       // next entry in parent directory
379     RFSEnt* prev;       // prev entry in parent directory
380     RCOM_T* comm;       // pointer to common entry
381     RFSEnt* parent_dir; // pointer to parent directory
382     uint open_cnt;      // number of file entry opens
383 } RFIL_T;
384 
385 typedef RFIL_T RDIR_T;
386 
387 // Represents the type for an entry in RAM (dir, file or link)
388 union f_file_entry {
389     FDIR_T dir;
390     FCOM_T comm;
391     FFIL_T file;
392 };
393 
394 // Represents the type for an entry for RFS (dif, file or link)
395 union r_file_entry {
396     RDIR_T dir;
397     RCOM_T comm;
398     RFIL_T file;
399 };
400 
401 // An entry in RAM consists of its type and value as a union
402 struct f_f_e {
403     union f_file_entry entry;
404     ui8 type;
405     FFSEnts* tbl;
406 };
407 
408 // An entry in RFS consists of its type and value as a union
409 struct r_f_e {
410     union r_file_entry entry;
411     ui8 type;
412 };
413 
414 // Holds a table full of entries, pointers to next and prev, num free
415 struct flash_entries {
416     FFSEnt tbl[FNUM_ENT];
417     FFSEnts* next_tbl;
418     FFSEnts* prev_tbl;
419     ui32 free;
420     ui32 num;
421 };
422 
423 struct ram_entries {
424     RFSEnt tbl[FNUM_ENT];
425     RFSEnts* next_tbl;
426     RFSEnts* prev_tbl;
427     ui32 free;
428 };
429 
430 // Structure to cast all volume structures to, to retrieve ioctl_func
431 typedef struct {
432     CircLink link; /*lint !e601, !e10*/
433     FileSys sys;
434 } FsVolume;
435 
436 #if FS_CRYPT
437 // FS Crypt Type
438 typedef struct fscrypt FSCrypt;
439 struct fscrypt {
440     // Public API
441     void (*delete)(FSCrypt** fs_crypt);
442     int (*decr)(const FSCrypt* fs_crypt, ui8* data, ui32 vpn, int n);
443     int (*rd_decr)(const FSCrypt* fs_crypt, ui8* data, ui32 vpn, int n);
444     int (*encr)(const FSCrypt* fs_crypt, ui8* data, ui32 vpn, int n);
445     int (*encr_wr)(const FSCrypt* fs_crypt, const ui8* data, ui32 vpn, int n);
446     ui32 (*ram_use)(const FSCrypt* fs_crypt);
447 
448     ui32 page_sz; // FS read/write page size
449     ui32 buf_pgs; // encryption buffer size in pages
450     ui8* buf;     // encryption buffer
451     void* crypt;  // encryption/decryption engine
452     void* fs_vol; // parameter passed to FS driver functions
453 
454     // FS driver read/write
455     int (*fs_wr)(const void* buf, ui32 frst, int n, void* fs_vol);
456     int (*fs_rd)(void* buf, ui32 frst, int n, void* fs_vol);
457 };
458 #endif // FS_CRYPT
459 
460 /***********************************************************************/
461 /* Variable Declarations                                               */
462 /***********************************************************************/
463 extern int CurrFixedVols;
464 extern FILE_TFS Files[FOPEN_MAX + 1];
465 extern HeadEntry MountedList;
466 extern FileSys TtySys;
467 extern int FsMaxOpen; // maximum # of concurrently open files
468 extern void* FSIterCurrVol;
469 
470 // FS Volumes Lists
471 extern CircLink FatVols;
472 extern CircLink FfsVols;
473 extern CircLink XfsVols;
474 extern CircLink RfsVols;
475 extern CircLink ZfsVols;
476 
477 /***********************************************************************/
478 /* Function Prototypes                                                 */
479 /***********************************************************************/
480 // File/directory path lookup related functions
481 int FsInvalName(const char* name, int ignore_last);
482 int FsIsLast(const char* name, ui32* lenp, ui32* incp);
483 const char* FsSkipSeparators(const char* path);
484 void* FSearch(void* hndl, const char** path, int dir_lookup, uint flags);
485 char* FSearchFSUID(ui32 fsuid, char* buf, size_t size, int lookup);
486 FileSys* FsResolvePath(const char* path);
487 
488 // General system/root level functions
489 int IsFreeFCB(const FILE_TFS* file);
490 void FsInitFCB(FILE_TFS* file, ui32 type);
491 void FsCopyFCB(FILE_TFS* dst, const FILE_TFS* src);
492 int DirFileWrite(FILE_TFS* stream, const ui8* buf, ui32 len);
493 int DirFileRead(FILE_TFS* stream, ui8* buf, ui32 len);
494 void* RootIoctl(DIR_TFS* dir, int code, ...);
495 int FsError(int err_code);
496 int FsIoError(FileSys* file_sys);
497 int FsSetErrno(int flags);
498 
499 // Auxiliary functions
500 void QuickSort(RFSEnt** head, RFSEnt** tail, DirEntry* e1, DirEntry* e2,
501                int (*cmp)(const DirEntry*, const DirEntry*));
502 int FNameEqu(const char* s1, const char* s2);
503 int FNameEquN(const char* s1, const char* s2, size_t n);
504 void DNameCpy(char* dst, const char* src);
505 int DNameEqu(const char* s1, const char* s2);
506 int DNameEquCase(const char* s1, const char* s2);
507 size_t DNameLen(const char* s);
508 void FsAddMount(FileSys* volume);
509 void FsDelMount(FileSys* volume);
510 void* FtlNdmAddFatFTL(FtlNdmVol* ftl_dvr, FatVol* fat_dvr);
511 void* FtlNdmAddXfsFTL(FtlNdmVol* ftl_dvr, XfsVol* xfs_dvr);
512 void FtlnFreeFTL(void* ftl);
513 int FsConvOpenMode(const char* mode);
514 int FsCheckPerm(mode_t mode, uid_t uid, gid_t gid, uint permissions);
515 void FsSetFl(FILE_TFS* fcb, int oflag);
516 void* FsGetFl(const FILE_TFS* fcb);
517 int FsFormatResetWc(const char* name);
518 int FatGetSectSize(const FatVol* fat_vol);
519 ui32 UDiv64(ui64 dividend, ui32 divisor);
520 void FsMemPrn(void);
521 ui32 FsMemPeakRst(void);
522 
523 #if FS_CRYPT
524 // FS Crypt Initialization
525 FSCrypt* FsCryptNew(FSCryptDrvr* fs_crypt);
526 int FsCryptSetBufSz(FSCrypt* fs_crypt, ui32 buf_pgs);
527 #endif
528 
529 // FCB recorded file offsets interface
530 fpos_t_TFS FOffGet(const FILE_TFS* fcbp, ui32 sect_off, ui32 frst_sect);
531 void FOffSet(FILE_TFS* fcbp, const fpos_t_TFS* new_pos, ui32 f_sects);
532 void FOffUpdate(const FILE_TFS* fcbp, ui32 old_sect, ui32 new_sect);
533 void FOffDel(FILE_TFS* fcbp);
534 
535 // Asynchronous I/O
536 void aioInit(void);
537 int aioOpen(FILE_TFS* file, int sect_size);
538 void aioSetIdle(FILE_TFS* file, uint code);
539 void aioVolInit(FileSys* vol);
540 
541 // File System Memory Allocation Wrapper Functions
542 void* FsCalloc(size_t nmemb, size_t size);
543 void* FsMalloc(size_t size);
544 void* FsAalloc(size_t size);
545 void FsFreeClear(void* ptr_ptr);
546 void FsAfreeClear(void* ptr_ptr);
547 void FsFree(void* ptr);
548 
549 #ifdef __cplusplus
550 }
551 #endif
552