/****************************************************************************** * * Copyright (C) 2002 - 2014 Xilinx, Inc. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * Use of the Software is limited solely to applications: * (a) running on a Xilinx device, or * (b) that interact with a Xilinx device through a bus or interconnect. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. * * Except as contained in this notice, the name of the Xilinx shall not be used * in advertising or otherwise to promote the sale, use or other dealings in * this Software without prior written authorization from Xilinx. * ******************************************************************************/ #ifndef MFS_FILESYS_H #define MFS_FILESYS_H #ifdef __cplusplus extern "C" { #endif /* MFS_BLOCK_DATA_SIZE (= number of bytes of data in a file) * and MFS_MAX_LOCAL_ENT (= number of directory entries in * a directory block) are related. * see block_data union */ #define MFS_BLOCK_DATA_SIZE 512 #define MFS_MAX_LOCAL_ENT 16 /* block type definitions */ #define MFS_BLOCK_TYPE_DIR 2 #define MFS_BLOCK_TYPE_FILE 1 #define MFS_BLOCK_TYPE_EMPTY 0 /* MFS_MAX_FILENAME_LENGTH determines the size of mfs_dir_ent_block - see below */ #define MFS_MAX_FILENAME_LENGTH 23 /** * dir entry contains file name and index of first file block * mfs_dir_entry_blocks are contained in a mfs_dir_block * size of mfs_dir_ent_block determines size of mfs_dir_block - see below * Make the size a multiple of 4 bytes to ensure alignment at 4 byte boundaries */ struct mfs_dir_ent_block { char name[MFS_MAX_FILENAME_LENGTH]; char deleted; /* value ='y' for deleted files and dirs, 'n' otherwise */ unsigned int index; }; /** * a mfs_dir_block is contained within a mfs_file_block * each mfs_dir_block contains at least 1 entry (its parent dir) * each dir block can contain at most MFS_MAX_LOCAL_ENT physical entries * If num_entries > MFS_MAX_LOCAL_ENT, there must be some * continuation blocks indexed by the next_block entry of the mfs_file_block * The size of this block is determined by the size of the dir_ent array * The size should be less than or equal to the size of block_data in * struct mfs_file_block - see below * Make the size a multiple of 4 bytes to ensure alignment at 4 byte boundaries */ struct mfs_dir_block { short num_entries; short num_deleted; struct mfs_dir_ent_block dir_ent[MFS_MAX_LOCAL_ENT]; }; /** * mfs_file_block is the basic unit of the file system * each block has a type identifier to identify the block as * being part of a file a directory or empty * each block has pointers to the next and prev blocks if any, * in the file/dir/free-list */ struct mfs_file_block { unsigned int block_size; /* has meaning for data files only */ unsigned int block_type; /* 2 = dir, 1 = file, 0 = empty */ unsigned int next_block; /* points to (index of) next block if any */ unsigned int prev_block; /* points to (index of) previous block if any */ unsigned int index; /* index of this block */ union { unsigned char block_data[MFS_BLOCK_DATA_SIZE]; struct mfs_dir_block dir_data; }u; } ; #define MFS_MAX_OPEN_FILES 10 #define MFS_MODE_READ 0 #define MFS_MODE_WRITE 1 /* MFS_MODE_CREATE creates a new file and opens it with MFS_MODE_WRITE */ #define MFS_MODE_CREATE 3 #define MFS_MODE_FREE 8 struct mfs_open_file_struct { unsigned int first_block; /* first block of file */ unsigned int current_block; /* currently accessed block */ unsigned short offset; /* current offset within block */ unsigned short mode ; /* read or write */ } ; /* number of mfs_file_blocks that can fit in the memory reserved for the file system */ extern int mfs_max_file_blocks; /* pointer to block of memory allocated or reserved for the file system */ extern struct mfs_file_block* mfs_file_system; /* index of first free block; the next_block value in this one continues the doubly linked free block list; the prev_block value of the first free block is 0 and the next_block value of the last free block is 0 */ extern int mfs_free_block_list; /* the current directory is initialized to 0 for the top level directory, and is modified by change_dir() calls */ extern int mfs_current_dir; /* information about files/dirs that are currently open for reading/writing */ extern struct mfs_open_file_struct mfs_open_files[MFS_MAX_OPEN_FILES]; extern int mfs_num_open_files; /* the number of open_files */ /* codes for initializing memory for MFS; see below for more info */ #define MFSINIT_NEW 0 #define MFSINIT_IMAGE 1 #define MFSINIT_ROM_IMAGE 2 /** * initialize the file system; * this function must be called before any file system operations * use mfs_init_genimage instead of this function for initializing with * file images generated by mfsgen * @param numbytes is the number of bytes allocated or reserved for this file system * @param address is the starting address of the memory block * Note: address must be word aligned (4 byte boundary) * @param init_type is one of * MFSINIT_NEW for creating empty read/write filesystem * MFSINIT_IMAGE for creating read/write filesystem with predefined data * MFSINIT_ROM_IMAGE for creating read-only filesystem with predefined data */ void mfs_init_fs(int numbytes, char *address, int init_type) ; /** * initialize the file system with a file image generated by mfsgen; * this function must be called before any file system operations * use mfs_init_fs instead of this function for other initialization * @param numbytes is the number of bytes allocated or reserved for this file sy stem * @param address is the starting address of the memory block * Note: address must be word aligned (4 byte boundary) * @param init_type is one of * MFSINIT_IMAGE for creating read/write filesystem with predefined data * MFSINIT_ROM_IMAGE for creating read-only filesystem with predefined data */ void mfs_init_genimage(int numbytes, char *address, int init_type) ; /** * modify global mfs_current_dir to index of newdir if it exists * mfs_current_dir is not modified otherwise * @param newdir is the name of the new directory * @return 1 for success and 0 for failure */ int mfs_change_dir(const char *newdir) ; /** * delete a file * @param filename is the name of the file to be deleted * delete the data blocks corresponding to the file and then delete the * file entry from its directory * @return 1 on success, 0 on failure * delete will not work on a directory unless the directory is empty */ int mfs_delete_file (char *filename) ; /** * create a new empty directory inside the current directory * @param newdir is the name of the directory * @return index of new directory in file system if success, 0 if failure */ int mfs_create_dir(char *newdir); /** * delete the directory named newdir if it exists, and is empty * return 1 on success, 0 on failure * cannot delete . or .. */ int mfs_delete_dir (char *newdir) ; /** * rename from_file to to_file * works for dirs as well as files * cannot rename to something that already exists * @param from_file * @param to_file * @return 1 on success, 0 on failure */ int mfs_rename_file(char *from_file, char *to_file); /** * check if a file exists * @param filename is the name of the file * @return 0 if filename is not a file in the current directory * @return 1 if filename is a file in the current directory * @return 2 if filename is a directory in the current directory */ int mfs_exists_file(char *filename); /** * get the name of the current directory * @param dirname = pre_allocated buffer of at least MFS_MAX_FILENAME_SIZE+1 chars * The directory name is copied to this buffer * @return 1 if success, 0 if failure */ int mfs_get_current_dir_name(char *dirname); /** * get the number of used blocks and the number of free blocks in the file system through pointers * @param num_blocks_used * @param num_blocks_free * the return value is 1 (for success) and 0 for failure to obtain the numbers */ int mfs_get_usage(int *num_blocks_used, int *num_blocks_free); /** * open a directory for reading * each subsequent call to mfs_dir_read() returns one directory entry until * end of directory * @param dirname is the name of the directory to open * @return index of dir in array mfs_open_files or -1 */ int mfs_dir_open(const char *dirname); /** * close a directory - same as closing a file * @param fd is the descriptor of the directory to close * @return 1 on success, 0 otherwise */ int mfs_dir_close(int fd); /** * read values from the next valid directory entry * The last 3 parameters are output values * @param fd is the file descriptor for an open directory file * @param filename is a pointer to the filename within the MFS itself * @param filesize is the size in bytes for a regular file or * the number of entries in a directory * @param filetype is MFS_BLOCK_TYPE_FILE or MFS_BLOCK_TYPE_DIR * @return 1 for success and 0 for failure or end of dir */ int mfs_dir_read(int fd, char **filename, int *filesize, int *filetype); /** * open a file * @param filename is the name of the file to open * @param mode is MFS_MODE_READ or MFS_MODE_WRITE or MFS_MODE_CREATE * this function should be used for FILEs and not DIRs * no error checking (is this FILE and not DIR?) is done for MFS_MODE_READ * MFS_MODE_CREATE automatically creates a FILE and not a DIR * MFS_MODE_WRITE fails if the specified file is a DIR * @return index of file in array mfs_open_files or -1 */ int mfs_file_open(const char *filename, int mode) ; /** * read characters to a file * @param fd is a descriptor for the file from which the characters are read * @param buf is a pre allocated buffer that will contain the read characters * @param buflen is the number of characters from buf to be read * fd should be a valid index in mfs_open_files array * Works only if fd points to a file and not a dir * buf should be a pointer to a pre-allocated buffer of size buflen or more * buflen chars are read and placed in buf * if fewer than buflen chars are available then only that many chars are read * @return num bytes read or 0 for error=no bytes read */ int mfs_file_read(int fd, char *buf, int buflen) ; /** * write characters to a file * @param fd is a descriptor for the file to which the characters are written * @param buf is a buffer containing the characters to be written out * @param buflen is the number of characters from buf to be written out * fd should be a valid index in mfs_open_files array * buf should be a pointer to a pre-allocated buffer of size buflen or more * buflen chars are read from buf and written to 1 or more blocks of the file * @return 1 for success or 0 for error=unable to write to file */ int mfs_file_write (int fd, const char *buf, int buflen) ; /** * close an open file and * recover the file table entry in mfs_open_files corresponding to the fd * if the fd is not valid, return 0 * fd is not valid if the index in mfs_open_files is out of range, or * if the corresponding entry is not an open file * @param fd is the file descriptor for the file to be closed * @return 1 on success, 0 otherwise */ int mfs_file_close(int fd); /* constants used in the lseek function - see below */ #define MFS_SEEK_SET 0 #define MFS_SEEK_CUR 1 #define MFS_SEEK_END 2 /** * seek to a given offset within the file * @param fd should be a valid file descriptor for an open file * @param whence is one of MFS_SEEK_SET, MFS_SEEK_CUR or MFS_SEEK_END * @param offset is the offset from the beginning, end or current position as specified by the whence parameter * if MFS_SEEK_END is specified, the offset can be either 0 or negative * otherwise offset should be positive or 0 * it is an error to seek before beginning of file or after the end of file * @return -1 on failure, value of the offset from the beginning of the file, on success */ long mfs_file_lseek(int fd, long offset, int whence); /*** Additional Utility Functions ***/ /** * list contents of current directory * @return 1 on success and 0 on failure */ int mfs_ls() ; /** * recursive directory listing * list the contents of current directory * if any of the entries in the current directory is itself a directory, * immediately enter that directory and call mfs_ls_r() once again * @param recurse * If parameter recurse is non zero continue recursing * else stop recursing * recurse=0 lists just the current directory * recurse = -1 allows unlimited recursion * recurse = n stops recursing at a depth of n * @return 1 on success and 0 on failure */ int mfs_ls_r(int recurse) ; /** * print the file to stdout * @param filename - file to print * @return 1 on success, 0 on failure */ int mfs_cat(char *filename) ; /** * copy from stdin to named file * @param filename - file to print * @return 1 on success, 0 on failure */ int mfs_copy_stdin_to_file(char *filename) ; /** * copy from_file to to_file * to_file is created new * copy fails if to_file exists already * copy fails is from_file or to_file cannot be opened * @param from_file * @param to_file * @return 1 on success, 0 on failure */ int mfs_file_copy(char *from_file, char *to_file) ; #ifdef __cplusplus } #endif #endif // MFS_FILESYS_H