Files
azerothcore-wotlk/deps/acelite/ace/MQX_Filesystem.h
2020-11-11 09:09:02 -06:00

261 lines
6.9 KiB
C++

/**
* @file MQX_Filesystem.h
*
* @author Frederick Hornsey <hornseyf@objectcomputing.com>
*/
#ifndef MQX_FILESYSTEM_HEADER
#define MQX_FILESYSTEM_HEADER
#include "ace/config-all.h"
#ifdef ACE_MQX
#include <mqx.h>
#include <fio.h>
#if !defined (FOPEN_MAX)
# define FOPEN_MAX 20
#endif
#if !defined (ACE_MQX_DLIB_FULL)
# undef read
# undef write
#endif
struct stat;
typedef struct stat ACE_stat;
#define ACE_MQX_ABS_PATH_SIZE (IOCFG_FS_MAX_DEVLEN + FS_FILENAME_SIZE - 1)
/**
* Since MQX has an unusual filesystem API, this class is provided to try to
* normalize it by managing the current working directory on a global context
* instead of a device by device context provided by MQX. It also tries to make
* these functions act more like their UNIX counterparts to some extent.
*
* This class is also the interface between the DLib IO functions and MQX file
* IO. It does this by implementing the classic UNIX IO functions below.
*
* WARNING: This is already being done in the ACE_TMAIN macro, but
* complete_initialization() should be called before using DLib or ACE file IO
* functions, but after MQX has been initialized. Either way, standard streams
* will not work properly, or some other behavior depending on the what
* functions are called in what order.
*/
class MQX_Filesystem {
public:
/// Get the singleton instance of the class
inline static MQX_Filesystem &inst() {
return instance_;
}
/**
* Initialize the Standard Streams and the Current Filesystem
*
* This must be done after MQX has been initialized. See warning in class
* documenting comment.
*/
void complete_initialization ();
/**
* Attempt to reset the cwd state by asking MQX for the first valid filesystem
* and "cd-ing" into the root of it.
*/
bool reset_state ();
/**
* @name Unix-like File Functions
*
* Classic UNIX-like Operations Implemented for for DLib
*/
///@{
/**
* Open a file and return the file descriptor.
*
* Returns the file descriptor if successful, -1 otherwise.
*
* Known Limitations:
* - Mode is being converted from DLib Unix-like mode to MQX cstdlib mode.
* This is not perfected yet and is limited by the common denominator of
* what is supported by both systems.
*/
int open (const char *path, int mode);
int close (int fd);
size_t read (int fd, unsigned char *buffer, size_t size);
size_t write (int fd, const unsigned char *buffer, size_t size);
long lseek (int fd, long offset, int whence);
///@}
/**
* @name Unix-like Filesystem Functions
*/
///@{
/**
* Put the current directory path in buf of size.
*
* Returns NULL if an error occurred, otherwise buf.
*/
char *getcwd (char *buf, size_t size);
/**
* Create a directory at path.
*
* Returns -1 if an error occurred, otherwise 0.
*/
int mkdir (const char *path);
/**
* Change to the directory at path.
*
* Returns -1 if an error occurred, otherwise 0.
*/
int chdir (const char *path);
/**
* Remove the empty directory at path.
*
* Returns -1 if an error occurred, otherwise 0.
*/
int rmdir (const char *path);
/**
* Unlink the file at path.
*
* Returns -1 if an error occurred, otherwise 0.
*/
int unlink (const char *path);
/**
* Rename or move the file or rename the directory from newpath to oldpath.
*
* Returns -1 if an error occurred, otherwise 0.
*
* As standard rename does, this sets errno to EXDEV if you try to move a
* file across filesystems. It also overwrites regular files that occupy the
* new path.
*
* Known Limitations:
* - Can only rename directories, will refuse to move them. This is MFS's
* IO_IOCTL_RENAME_FILE refusing to do this. This could be implemented by
* the function, but would involve either manually copying the file tree
* or refusing to move nonempty directories.
*/
int rename (const char *oldpath, const char *newpath);
/**
* Get status of file given by path.
*
* Returns -1 if an error occurred, otherwise 0.
*
* Known Limitations:
* - st_mtime is currently not implemented and is set to 0.
* - st_mode is limited to
* - S_IFDIR: file is a directory
* - S_IFREG: file is a regular file
*/
int stat (const char * path, ACE_stat *statbuf);
/**
* Get status of file given by file descriptor.
*
* Returns -1 if an error occurred, otherwise 0.
*
* Known Limitations:
* - st_mtime is currently not implemented and returns 0
* - In MFS there seems to be no direct way to get st_msize from a MQX file
* alone. The only way to get a file size using the documented API seems
* to be IO_IOCTL_FIND_FIRST_FILE, which requires the path. For now this
* will be set to 0.
* - st_mode is limited to
* - S_IFDIR: file is a directory
* - S_IFREG: file is a regular file
* - S_IFCHR: file is a special character device file, (e.g. ACE_STDOUT)
*/
int fstat (int fd, ACE_stat *statbuf);
///@}
private:
/// The singleton instance of the class
static MQX_Filesystem instance_;
MQX_Filesystem();
/**
* @name Current Filesystem for resolving relative paths.
*/
///@{
MQX_FILE_PTR current_fs_;
char current_fs_name_[IOCFG_FS_MAX_DEVLEN];
unsigned current_fs_name_len_;
///@}
/**
* @name Manage open files using file descriptors.
*/
///@{
struct File {
/// DLib File Descriptor. Invalid if -1.
int fd;
/// MQX File
MQX_FILE_PTR mqx_file;
/// Mark this as special character device file (Standard Streams)
bool chardev_file;
};
File files_[FOPEN_MAX];
/**
* Last file descriptor created.
*/
int last_fd_;
/**
* Max VALUE for File Descriptors.
*
* NOTE: Max open file count is FOPEN_MAX, defined by DLib. This creates a
* limit on the number of unique file descriptor values.
*/
int max_fd_;
/**
* Get a File struct for the file descriptor.
*
* Returns NULL and sets EBADF if no such file exists
*/
File *get_file (int fd);
/**
* Get a File struct pointer to use for a new file.
*
* Returns NULL and sets ENFILE if exceeded max number of open files.
*/
File *get_new_file ();
///@}
/**
* Check to see if the current filesystem is valid, if not reset it.
*
* Returns true if reseting failed, otherwise false. Failure would probably
* mean no filesystems are mounted.
*/
bool check_state ();
/**
* Set the supplied pointer as the filesystem of the current working
* directory.
*/
void update_fs (MQX_FILE_PTR fs);
/**
* Resolve the filesystem of the supplied path and return it.
*
* This will be the filesystem of the current working directory if the path
* is relative. Sets the fs_name_len to the length of the device name in the
* path. This would be 0 if the path is relative.
*/
MQX_FILE_PTR resolve_fs (const char *path, int *fs_name_len);
};
#endif // ACE_MQX
#endif // MQX_FILESYSTEM_HEADER