#include #include #include #include #include #include #include #include #include "ramdisk.h" #define NAMELENMAX 0x80 #define MAXPATHLEN 0x100 class RAMDISK_PARTITION; class RAMDISK_LINK_ENTRY; class RAMDISK_DIR_ENTRY; class RAMDISK_FILE_ENTRY; class RAMDISK_BASE_ENTRY { public: RAMDISK_BASE_ENTRY(const char *Name, RAMDISK_DIR_ENTRY *Parent); virtual ~RAMDISK_BASE_ENTRY(); void Rename(const char *Name); RAMDISK_LINK_ENTRY *IsLink(); RAMDISK_DIR_ENTRY *IsDir(); RAMDISK_FILE_ENTRY *IsFile(); RAMDISK_PARTITION *GetPartition(); char *name; RAMDISK_DIR_ENTRY *parent; RAMDISK_BASE_ENTRY *next; }; class RAMDISK_LINK_ENTRY : public RAMDISK_BASE_ENTRY { public: RAMDISK_LINK_ENTRY(const char* Name, RAMDISK_DIR_ENTRY *Parent, RAMDISK_BASE_ENTRY *Link); RAMDISK_BASE_ENTRY *link; }; class RAMDISK_DIR_ENTRY : public RAMDISK_BASE_ENTRY { public: RAMDISK_DIR_ENTRY(const char* Name, RAMDISK_DIR_ENTRY *Parent); ~RAMDISK_DIR_ENTRY(); RAMDISK_BASE_ENTRY *FindEntry(const char* Path); RAMDISK_FILE_ENTRY *CreateFile(const char *Filename); RAMDISK_DIR_ENTRY *CreateDir(const char *Filename); void RemoveEntry(RAMDISK_BASE_ENTRY *Entry); RAMDISK_BASE_ENTRY *first; RAMDISK_BASE_ENTRY *last; }; typedef struct { RAMDISK_DIR_ENTRY *dir; RAMDISK_BASE_ENTRY *current_entry; } DIR_STRUCT; class RAMDISK_PARTITION : public RAMDISK_DIR_ENTRY { public: RAMDISK_PARTITION(const char *Mountpoint, bool AutoMount); RAMDISK_BASE_ENTRY *FindEntry(const char* Path); RAMDISK_DIR_ENTRY *FindPath(const char* Path, const char **Basename=NULL); RAMDISK_DIR_ENTRY *cwd; bool automount; }; class FILE_DATA { public: FILE_DATA(size_t Len); ~FILE_DATA(); u8 *data; size_t len; FILE_DATA *next; }; typedef struct { RAMDISK_FILE_ENTRY *file; bool isLink; u32 current_pos; bool read; bool write; } FILE_STRUCT; class RAMDISK_FILE_ENTRY : public RAMDISK_BASE_ENTRY { public: RAMDISK_FILE_ENTRY(const char* Name, RAMDISK_DIR_ENTRY *Parent); ~RAMDISK_FILE_ENTRY(); bool Truncate(size_t newLen); bool AddCluster(size_t size); size_t Read(struct _reent *r, FILE_STRUCT *fileStruct, char *ptr, size_t len); size_t Write(struct _reent *r, FILE_STRUCT *fileStruct, const char *ptr, size_t len); size_t file_len; size_t cluster_len; FILE_DATA *first_cluster; FILE_DATA *last_cluster; }; RAMDISK_LINK_ENTRY::RAMDISK_LINK_ENTRY(const char* Name, RAMDISK_DIR_ENTRY *Parent, RAMDISK_BASE_ENTRY *Link) : RAMDISK_BASE_ENTRY(Name, Parent), link(Link) { } RAMDISK_BASE_ENTRY::RAMDISK_BASE_ENTRY(const char *Name, RAMDISK_DIR_ENTRY *Parent) : name(strdup(Name)), parent(Parent), next(NULL) {} RAMDISK_BASE_ENTRY::~RAMDISK_BASE_ENTRY() { free(name); if(parent) parent->RemoveEntry(this); } void RAMDISK_BASE_ENTRY::Rename(const char *Name) { free(name); name = strdup(Name); } inline RAMDISK_LINK_ENTRY *RAMDISK_BASE_ENTRY::IsLink() { return dynamic_cast(this); } inline RAMDISK_DIR_ENTRY *RAMDISK_BASE_ENTRY::IsDir() { RAMDISK_LINK_ENTRY *lentry = dynamic_cast(this); return dynamic_cast(lentry ? lentry->link : this); } inline RAMDISK_FILE_ENTRY *RAMDISK_BASE_ENTRY::IsFile() { RAMDISK_LINK_ENTRY *lentry = dynamic_cast(this); return dynamic_cast(lentry ? lentry->link : this); } RAMDISK_PARTITION *RAMDISK_BASE_ENTRY::GetPartition() { for(RAMDISK_BASE_ENTRY *entry = this; entry; entry = entry->parent) if(entry->parent == NULL) return dynamic_cast(entry); return NULL; } RAMDISK_DIR_ENTRY::RAMDISK_DIR_ENTRY(const char* Name, RAMDISK_DIR_ENTRY *Parent) : RAMDISK_BASE_ENTRY(Name, Parent) { RAMDISK_BASE_ENTRY* entry = new RAMDISK_LINK_ENTRY(".", this, this); first = entry; last = entry; if(parent) { entry = new RAMDISK_LINK_ENTRY("..", this, parent); first->next = entry; last = entry; } } RAMDISK_DIR_ENTRY::~RAMDISK_DIR_ENTRY() { while(first) { first->parent = NULL; // ~RAMDISK_BASE_ENTRY() no calls RemoveEntry() RAMDISK_BASE_ENTRY* next = first->next; delete first; first = next; } } RAMDISK_BASE_ENTRY *RAMDISK_DIR_ENTRY::FindEntry(const char* Path) { const char* dirpath = Path; const char* cptr; while( dirpath[0] == '/') dirpath++; // move past leading '/' if(dirpath[0] == '\0') // this path is found return this; cptr = strchr(dirpath,'/'); // find next '/' if(cptr == NULL) cptr = strchr(dirpath,'\0'); // cptr at end for(RAMDISK_BASE_ENTRY *curr = first; curr; curr=curr->next) { if( strncmp(curr->name, dirpath, cptr-dirpath) == 0) { if(RAMDISK_DIR_ENTRY *dir = curr->IsDir()) return dir->FindEntry(cptr); else return curr; } } return NULL; } RAMDISK_FILE_ENTRY *RAMDISK_DIR_ENTRY::CreateFile(const char *Filename) { try { RAMDISK_FILE_ENTRY* file = new RAMDISK_FILE_ENTRY(Filename, this); if(!first) first = file; last->next = file; last = file; return file; } catch(...) { return NULL; } } RAMDISK_DIR_ENTRY *RAMDISK_DIR_ENTRY::CreateDir(const char *Filename) { try { RAMDISK_DIR_ENTRY* dir = new RAMDISK_DIR_ENTRY(Filename, this); if(!first) first = dir; last->next = dir; last = dir; return dir; } catch(...) { return NULL; } } void RAMDISK_DIR_ENTRY::RemoveEntry(RAMDISK_BASE_ENTRY *Entry) { RAMDISK_BASE_ENTRY **p_last = NULL; for(RAMDISK_BASE_ENTRY **curr = &first; *curr; curr=&((*curr)->next) ) { if( *curr == Entry ) { *curr = Entry->next; if(Entry->next == NULL) // entry is last last = *p_last; break; } p_last = curr; } } RAMDISK_PARTITION::RAMDISK_PARTITION(const char *Mountpoint, bool AutoMount) : RAMDISK_DIR_ENTRY(Mountpoint, NULL), cwd(this), automount(AutoMount) { } RAMDISK_BASE_ENTRY * RAMDISK_PARTITION::FindEntry(const char* path) { char *cptr; if ( (cptr=strchr(path,':')) ) path=cptr+1; //move path past any device names if ( strchr(path, ':') != NULL ) { // r->_errno = EINVAL; return NULL; } if(*path=='/') // if first character is '/' use absolute root path return RAMDISK_DIR_ENTRY::FindEntry(path); else // else use current working dir return cwd->FindEntry(path); } RAMDISK_DIR_ENTRY * RAMDISK_PARTITION::FindPath(const char* path, const char **basename) { int pathLen = strlen(path); char dirfilename[pathLen+1]; // to hold a full path const char *cptr = path+pathLen; // find the end... const char *filename = NULL; // to hold filename while(cptr-->path) //search till start { if((*cptr=='/') || (*cptr==':')) // split at either / or : (whichever comes first form the end!) { cptr++; strlcpy(dirfilename, path, 1+cptr-path); //copy string up till and including / or : filename = cptr; //filename = now remainder of string break; } } if(!filename) { filename = path; //filename = complete path dirfilename[0] = 0; //make directory path "" } RAMDISK_BASE_ENTRY *entry = FindEntry(dirfilename); if(entry) { if(basename) *basename = filename; return entry->IsDir(); } return NULL; } FILE_DATA::FILE_DATA(size_t Len) : next(NULL) { data = new u8[Len]; len = Len; memset(data, 0, len); } FILE_DATA::~FILE_DATA() { delete [] data; delete next; } RAMDISK_FILE_ENTRY::RAMDISK_FILE_ENTRY(const char* Name, RAMDISK_DIR_ENTRY *Parent) : RAMDISK_BASE_ENTRY(Name, Parent), file_len(0), cluster_len(0), first_cluster(NULL), last_cluster(NULL) {} RAMDISK_FILE_ENTRY::~RAMDISK_FILE_ENTRY() { Truncate(0); } #define CLUSTER_SIZE 4*1024 bool RAMDISK_FILE_ENTRY::Truncate(size_t newSize) { if (newSize > cluster_len) { // Expanding the file over cluster_len return AddCluster(newSize - cluster_len); } else if (newSize < file_len) { // Shrinking the file FILE_DATA *prev_cluster = NULL; size_t len = 0; for(FILE_DATA **p_cluster = &first_cluster; *p_cluster; p_cluster = &(*p_cluster)->next) { if(len >= newSize) { last_cluster = prev_cluster; delete *p_cluster; (*p_cluster) = NULL; break; } len += (*p_cluster)->len; prev_cluster = *p_cluster; } } file_len = newSize; return true; } bool RAMDISK_FILE_ENTRY::AddCluster(size_t len) { if(len < CLUSTER_SIZE) len = CLUSTER_SIZE; try { *(last_cluster ? &last_cluster->next : &first_cluster) = last_cluster = new FILE_DATA(len); cluster_len += len; return true; } catch(...) { return false; } } size_t RAMDISK_FILE_ENTRY::Read(struct _reent *r, FILE_STRUCT *fileStruct, char *ptr, size_t len) { if (!fileStruct->read) { r->_errno = EBADF; return 0; } // Short circuit cases where len is 0 (or less) if (len <= 0) return 0; // Don't try to read if the read pointer is past the end of file if (fileStruct->current_pos >= file_len) { r->_errno = EOVERFLOW; return 0; } // Don't read past end of file if (len + fileStruct->current_pos > file_len) { r->_errno = EOVERFLOW; len = fileStruct->current_pos - file_len; } off_t pos = fileStruct->current_pos; size_t readed = 0; size_t max_len = file_len; for(FILE_DATA *cluster = first_cluster; cluster; cluster = cluster->next) { if(pos > cluster->len) { pos -= cluster->len; max_len -= cluster->len; } else { size_t read = max_len; if(read > cluster->len) read = cluster->len; read -= pos; if(read > len) read = len; memcpy(ptr, &(cluster->data[pos]), read); readed += read; ptr += read; len -= read; if(len == 0) break; pos -= cluster->len; max_len -= cluster->len; } } fileStruct->current_pos += readed; return readed; } size_t RAMDISK_FILE_ENTRY::Write(struct _reent *r, FILE_STRUCT *fileStruct, const char *ptr, size_t len) { if (!fileStruct->write) { r->_errno = EBADF; return 0; } // Short circuit cases where len is 0 (or less) if (len <= 0) return 0; off_t pos = fileStruct->current_pos; if(cluster_len < (pos+len) && !AddCluster((pos+len) - cluster_len)) { // Couldn't get a cluster, so abort r->_errno = ENOSPC; return 0; } if(file_len < (pos+len)) file_len = (pos+len); size_t written = 0; size_t max_len = cluster_len; for(FILE_DATA *cluster = first_cluster; cluster; cluster = cluster->next) { if(pos > cluster->len) { pos -= cluster->len; max_len -= cluster->len; } else { size_t write = cluster->len - pos; if(write > len) write = len; memcpy(&(cluster->data[pos]), ptr, write); written += write; ptr += write; len -= write; if(len == 0) break; pos -= cluster->len; max_len -= cluster->len; } } fileStruct->current_pos += written; return written; } static int ramdiskFS_open_r(struct _reent *r, void *fileStruct, const char *path, int flags, int mode); static int ramdiskFS_close_r(struct _reent *r, int fd); static int ramdiskFS_write_r(struct _reent *r, int fd, const char *ptr, size_t len); static int ramdiskFS_read_r(struct _reent *r, int fd, char *ptr, size_t len); static off_t ramdiskFS_seek_r(struct _reent *r, int fd, off_t pos, int dir); static int ramdiskFS_fstat_r(struct _reent *r, int fd, struct stat *st); static int ramdiskFS_stat_r(struct _reent *r, const char *file, struct stat *st); static int ramdiskFS_unlink_r(struct _reent *r, const char *name); static int ramdiskFS_chdir_r(struct _reent *r, const char *name); static int ramdiskFS_mkdir_r(struct _reent *r, const char *path, int mode); static DIR_ITER* ramdiskFS_diropen_r(struct _reent *r, DIR_ITER *dirState, const char *path); static int ramdiskFS_dirreset_r(struct _reent *r, DIR_ITER *dirState); static int ramdiskFS_dirnext_r(struct _reent *r, DIR_ITER *dirState, char *filename, struct stat *st); static int ramdiskFS_dirclose_r(struct _reent *r, DIR_ITER *dirState); static int ramdiskFS_ftruncate_r(struct _reent *r, int fd, off_t len); static devoptab_t ramdiskFS_devoptab={ "ramdisk", sizeof(FILE_STRUCT), // int structSize; &ramdiskFS_open_r, // int (*open_r)(struct _reent *r, void *fileStruct, const char *path,int // flags,int mode); &ramdiskFS_close_r, // int (*close_r)(struct _reent *r, int fd); &ramdiskFS_write_r, // int (*write_r)(struct _reent *r, int fd, const char *ptr, int len); &ramdiskFS_read_r, // int (*read_r)(struct _reent *r, int fd, char *ptr, int len); &ramdiskFS_seek_r, // off_t (*seek_r)(struct _reent *r, off_t fd, int pos, int dir); &ramdiskFS_fstat_r, // int (*fstat_r)(struct _reent *r, int fd, struct stat *st); &ramdiskFS_stat_r, // int (*stat_r)(struct _reent *r, const char *file, struct stat *st); NULL, // int (*link_r)(struct _reent *r, const char *existing, const char *newLink); &ramdiskFS_unlink_r, // int (*unlink_r)(struct _reent *r, const char *name); &ramdiskFS_chdir_r, // int (*chdir_r)(struct _reent *r, const char *name); NULL, // int (*rename_r) (struct _reent *r, const char *oldName, const char *newName); ramdiskFS_mkdir_r, // int (*mkdir_r) (struct _reent *r, const char *path, int mode); sizeof(DIR_STRUCT), // int dirStateSize; &ramdiskFS_diropen_r, // DIR_ITER* (*diropen_r)(struct _reent *r, DIR_ITER *dirState, const char *path); &ramdiskFS_dirreset_r, // int (*dirreset_r)(struct _reent *r, DIR_ITER *dirState); &ramdiskFS_dirnext_r, // int (*dirnext_r)(struct _reent *r, DIR_ITER *dirState, char *filename, // struct stat *filestat); &ramdiskFS_dirclose_r, // int (*dirclose_r)(struct _reent *r, DIR_ITER *dirState); NULL, // statvfs_r &ramdiskFS_ftruncate_r, // int (*ftruncate_r)(struct _reent *r, int fd, off_t len); NULL, // fsync_r, NULL // Device data }; //--------------------------------------------------------------------------------- static inline RAMDISK_PARTITION* ramdiskFS_getPartitionFromPath(const char* path) { //--------------------------------------------------------------------------------- const devoptab_t *devops = GetDeviceOpTab(path); if (!devops) return NULL; return *((RAMDISK_PARTITION**)devops->deviceData); } //--------------------------------------------------------------------------------- // File functions //--------------------------------------------------------------------------------- static int ramdiskFS_open_r(struct _reent *r, void *file_Struct, const char *path, int flags, int mode) { //--------------------------------------------------------------------------------- FILE_STRUCT *fileStruct = (FILE_STRUCT*)file_Struct; RAMDISK_PARTITION *partition = ramdiskFS_getPartitionFromPath(path); if ( partition == NULL ) { r->_errno = ENODEV; return -1; } if ((flags & 0x03) == O_RDONLY) { // Open the file for read-only access fileStruct->read = true; fileStruct->write = false; } else if ((flags & 0x03) == O_WRONLY) { // Open file for write only access fileStruct->read = false; fileStruct->write = true; } else if ((flags & 0x03) == O_RDWR) { // Open file for read/write access fileStruct->read = true; fileStruct->write = true; } else { r->_errno = EACCES; return -1; } RAMDISK_BASE_ENTRY *entry = partition->FindEntry(path); // The file shouldn't exist if we are trying to create it if (entry && (flags & O_CREAT) && (flags & O_EXCL)) { r->_errno = EEXIST; return -1; } // It should not be a directory if we're openning a file, if (entry && entry->IsDir()) { r->_errno = EISDIR; return -1; } fileStruct->isLink = entry ? entry->IsLink() : false; fileStruct->file = entry ? entry->IsFile() : NULL; if(!fileStruct->file) // entry not exists { if (flags & O_CREAT) { const char *filename; RAMDISK_DIR_ENTRY *dir = partition->FindPath(path, &filename); if(!dir) { r->_errno = ENOTDIR; return -1; } fileStruct->file = dir->CreateFile(filename); } else { // file doesn't exist, and we aren't creating it r->_errno = ENOENT; return -1; } } if(fileStruct->file) { fileStruct->current_pos = 0; // Truncate the file if requested if ((flags & O_TRUNC) && fileStruct->write) fileStruct->file->Truncate(0); if (flags & O_APPEND) fileStruct->current_pos = fileStruct->file->file_len; return 0; } r->_errno = ENOENT; return(-1); } //--------------------------------------------------------------------------------- static int ramdiskFS_close_r(struct _reent *r, int fd) { //--------------------------------------------------------------------------------- return(0); } //--------------------------------------------------------------------------------- static int ramdiskFS_read_r(struct _reent *r, int fd, char *ptr, size_t len) { //--------------------------------------------------------------------------------- FILE_STRUCT *fileStruct = (FILE_STRUCT*)fd; return fileStruct->file->Read(r, fileStruct, ptr, len); } //--------------------------------------------------------------------------------- static int ramdiskFS_write_r(struct _reent *r, int fd, const char *ptr, size_t len) { //--------------------------------------------------------------------------------- FILE_STRUCT *fileStruct = (FILE_STRUCT*)fd; return fileStruct->file->Write(r, fileStruct, ptr, len); } //--------------------------------------------------------------------------------- static off_t ramdiskFS_seek_r(struct _reent *r, int fd, off_t pos, int dir) { //--------------------------------------------------------------------------------- //need check for eof here... FILE_STRUCT *fileStruct = (FILE_STRUCT*)fd; switch(dir) { case SEEK_SET: break; case SEEK_CUR: pos += fileStruct->current_pos; break; case SEEK_END: pos += fileStruct->file->file_len; // set start to end of file break; default: r->_errno = EINVAL; return -1; } return fileStruct->current_pos = pos; } //--------------------------------------------------------------------------------- static int ramdiskFS_fstat_r(struct _reent *r, int fd, struct stat *st) { //--------------------------------------------------------------------------------- FILE_STRUCT *fileStruct = (FILE_STRUCT*)fd; st->st_mode = fileStruct->isLink ? S_IFLNK : S_IFREG; st->st_size = fileStruct->file->file_len; return(0); } //--------------------------------------------------------------------------------- static int ramdiskFS_stat_r(struct _reent *r, const char *file, struct stat *st) { //--------------------------------------------------------------------------------- FILE_STRUCT fileStruct; DIR_STRUCT dirStruct; DIR_ITER dirState; dirState.dirStruct=&dirStruct; //create a temp dirstruct int ret; if( ramdiskFS_open_r(r, &fileStruct, file, 0, 0) ==0 ) { ret = ramdiskFS_fstat_r(r, (int)&fileStruct, st); ramdiskFS_close_r(r, (int)&fileStruct); return(ret); } else if( (ramdiskFS_diropen_r(r, &dirState, file)!=NULL) ) { st->st_mode = S_IFDIR; ramdiskFS_dirclose_r(r, &dirState); return(0); } r->_errno = ENOENT; return(-1); } //--------------------------------------------------------------------------------- static int ramdiskFS_unlink_r(struct _reent *r, const char *name) { //--------------------------------------------------------------------------------- RAMDISK_PARTITION *partition = ramdiskFS_getPartitionFromPath(name); if ( partition == NULL ) { r->_errno = ENODEV; return -1; } RAMDISK_BASE_ENTRY *entry = partition->FindEntry(name); if(!entry) { r->_errno = ENOENT; return -1; } if (entry->IsLink()) { if(entry->name[0] == '.' && (entry->name[1] == '\0' || (entry->name[1] == '.' && entry->name[2] == '\0'))) { r->_errno = EPERM; return -1; } delete entry; return 0; } if (RAMDISK_DIR_ENTRY *dir = entry->IsDir()) { for(RAMDISK_BASE_ENTRY *entry = dir->first; entry; entry = entry->next) { if(!(entry->name[0] == '.' && (entry->name[1] == '\0' || (entry->name[1] == '.' && entry->name[2] == '\0')))) { r->_errno = EPERM; return -1; } } } delete entry; return 0; } //--------------------------------------------------------------------------------- static int ramdiskFS_chdir_r(struct _reent *r, const char *name) { //--------------------------------------------------------------------------------- DIR_STRUCT dirStruct; DIR_ITER dirState; dirState.dirStruct=&dirStruct; if( (name == NULL) ) { r->_errno = ENODEV; return -1; } if( (ramdiskFS_diropen_r(r, &dirState, name) == NULL) ) return -1; RAMDISK_PARTITION *partition = dirStruct.dir->GetPartition(); if ( partition == NULL ) { r->_errno = ENODEV; return -1; } partition->cwd = dirStruct.dir; ramdiskFS_dirclose_r(r, &dirState); return 0; } //--------------------------------------------------------------------------------- static int ramdiskFS_mkdir_r(struct _reent *r, const char *path, int mode) { //--------------------------------------------------------------------------------- RAMDISK_PARTITION *partition = ramdiskFS_getPartitionFromPath(path); if ( partition == NULL ) { r->_errno = ENODEV; return -1; } RAMDISK_BASE_ENTRY *entry = partition->FindEntry(path); if (entry) { r->_errno = EEXIST; return -1; } const char *filename; RAMDISK_DIR_ENTRY *dir = partition->FindPath(path, &filename); if(!dir) { r->_errno = ENOTDIR; return -1; } dir->CreateDir(filename); return 0; } //--------------------------------------------------------------------------------- // Directory functions //--------------------------------------------------------------------------------- static DIR_ITER* ramdiskFS_diropen_r(struct _reent *r, DIR_ITER *dirState, const char *path) { //--------------------------------------------------------------------------------- DIR_STRUCT *dirStruct = (DIR_STRUCT*)dirState->dirStruct; char *cptr; RAMDISK_PARTITION *partition = ramdiskFS_getPartitionFromPath(path); if ( partition == NULL ) { r->_errno = ENODEV; return NULL; } if ( (cptr=strchr(path,':')) ) path=cptr+1; //move path past any device names if ( strchr(path, ':') != NULL ) { r->_errno = EINVAL; return NULL; } if(*path=='/') //if first character is '/' use absolute root path dirStruct->dir = partition; //first root dir else dirStruct->dir = partition->cwd; //else use current working dir RAMDISK_BASE_ENTRY *entry = dirStruct->dir->FindEntry(path); if(entry==NULL) { r->_errno = ENOENT; return NULL; } dirStruct->dir = entry->IsDir(); if(dirStruct->dir==NULL) { r->_errno = ENOTDIR; return NULL; } dirStruct->current_entry = dirStruct->dir->first; return dirState; } /*Consts containing relative system path strings*/ //reset dir to start of entry selected by dirStruct->cur_dir_id //--------------------------------------------------------------------------------- static int ramdiskFS_dirreset_r(struct _reent *r, DIR_ITER *dirState) { //--------------------------------------------------------------------------------- DIR_STRUCT *dirStruct = (DIR_STRUCT*)dirState->dirStruct; dirStruct->current_entry = dirStruct->dir->first; return(0); } //--------------------------------------------------------------------------------- static int ramdiskFS_dirnext_r(struct _reent *r, DIR_ITER *dirState, char *filename, struct stat *st) { //--------------------------------------------------------------------------------- DIR_STRUCT *dirStruct = (DIR_STRUCT*)dirState->dirStruct; // RAMDISK_BASE_ENTRY **dirStruct = (RAMDISK_BASE_ENTRY**)dirState->dirStruct; if(dirStruct->current_entry) { strcpy(filename, dirStruct->current_entry->name); if(dirStruct->current_entry->IsDir()) { if(st) st->st_mode=S_IFDIR; } else { if(st) st->st_mode=0; } dirStruct->current_entry = dirStruct->current_entry->next; return(0); } r->_errno = ENOENT; return(-1); } //--------------------------------------------------------------------------------- static int ramdiskFS_dirclose_r(struct _reent *r, DIR_ITER *dirState) { //--------------------------------------------------------------------------------- return(0); } //--------------------------------------------------------------------------------- static int ramdiskFS_ftruncate_r(struct _reent *r, int fd, off_t len) { //--------------------------------------------------------------------------------- FILE_STRUCT *fileStruct = (FILE_STRUCT*)fd; if (len < 0) { // Trying to truncate to a negative size r->_errno = EINVAL; return -1; } /* if ((sizeof(len) > 4) && len > (off_t)FILE_MAX_SIZE) { // Trying to extend the file beyond what supports r->_errno = EFBIG; return -1; } */ if (!fileStruct->write) { // Read-only file r->_errno = EINVAL; return -1; } if(fileStruct->file->Truncate(len)) return 0; r->_errno = ENOSPC; return -1; } //--------------------------------------------------------------------------------- void ramdiskFS_Unmount(const char* mountpoint) { //--------------------------------------------------------------------------------- RAMDISK_PARTITION *partition; devoptab_t *devops = (devoptab_t*)GetDeviceOpTab(mountpoint); if (!devops) return; // Perform a quick check to make sure we're dealing with a ramdiskFS_ controlled device if (devops->open_r != ramdiskFS_devoptab.open_r) return; if (RemoveDevice (mountpoint) == -1) return; partition = *((RAMDISK_PARTITION **)devops->deviceData); if(partition->automount) delete partition; free (devops); } extern "C" void ramdiskUnmount(const char *mountpoint) { ramdiskFS_Unmount(mountpoint); } //--------------------------------------------------------------------------------- int ramdiskFS_Mount(const char *mountpoint, void *handle) { //--------------------------------------------------------------------------------- devoptab_t* devops; char* nameCopy; RAMDISK_PARTITION** partition; char Mountpoint[100]; char *cptr; strlcpy(Mountpoint, mountpoint, sizeof(Mountpoint)); int len = strlen(Mountpoint); cptr = strchr(Mountpoint, ':'); if(cptr) { len = cptr-Mountpoint; *++cptr = 0; } else strlcat(Mountpoint, ":", sizeof(Mountpoint)); ramdiskFS_Unmount(Mountpoint); if(handle) ramdiskFS_Unmount(((RAMDISK_PARTITION*)handle)->name); devops = (devoptab_t*)malloc(sizeof(devoptab_t) + sizeof(RAMDISK_PARTITION*) + len + 1); if (!devops) return false; partition = (RAMDISK_PARTITION**)(devops+1); // Use the space allocated at the end of the devoptab struct // for storing the partition nameCopy = (char*)( partition+1); // Use the space allocated at the end of the partition struct // for storing the name memcpy (devops, &ramdiskFS_devoptab, sizeof(ramdiskFS_devoptab)); // Add an entry for this device to the devoptab table strlcpy (nameCopy, Mountpoint, len + 1); devops->name = nameCopy; if(handle) { *partition = (RAMDISK_PARTITION*)handle; (*partition)->Rename(Mountpoint); } else *partition = new RAMDISK_PARTITION(Mountpoint, true); devops->deviceData = partition; if(AddDevice(devops)<0) { free(devops); return false; } return true; } extern "C" int ramdiskMount(const char *mountpoint, void *handle) { return ramdiskFS_Mount(mountpoint, handle); } //--------------------------------------------------------------------------------- extern "C" void* ramdiskCreate() { //--------------------------------------------------------------------------------- return new RAMDISK_PARTITION("", false); } //--------------------------------------------------------------------------------- extern "C" void ramdiskDelete(void* Handle) { //--------------------------------------------------------------------------------- RAMDISK_PARTITION *partition = (RAMDISK_PARTITION*)Handle; if(partition->automount==false) ramdiskFS_Unmount(partition->name); delete partition; }