bool FSFolder_Local_MkDir_IMP(FSFolder *self, String *name) { String *dir = S_fullpath(self, name); bool result = S_create_dir(dir); if (!result) { ERR_ADD_FRAME(Err_get_error()); } DECREF(dir); return result; }
FileHandle* FSFolder_Local_Open_FileHandle_IMP(FSFolder *self, String *name, uint32_t flags) { String *fullpath = S_fullpath(self, name); FSFileHandle *fh = FSFH_open(fullpath, flags); if (!fh) { ERR_ADD_FRAME(Err_get_error()); } DECREF(fullpath); return (FileHandle*)fh; }
Folder* FSFolder_Local_Find_Folder_IMP(FSFolder *self, String *name) { FSFolderIVARS *const ivars = FSFolder_IVARS(self); Folder *subfolder = NULL; if (!name || !Str_Get_Size(name)) { // No entity can be identified by NULL or empty string. return NULL; } else if (!S_is_local_entry(name)) { return NULL; } else if (Str_Starts_With_Utf8(name, ".", 1)) { // Don't allow access outside of the main dir. return NULL; } else if (NULL != (subfolder = (Folder*)Hash_Fetch(ivars->entries, (Obj*)name))) { if (Folder_Is_A(subfolder, FOLDER)) { return subfolder; } else { return NULL; } } String *fullpath = S_fullpath(self, name); if (S_dir_ok(fullpath)) { subfolder = (Folder*)FSFolder_new(fullpath); if (!subfolder) { DECREF(fullpath); THROW(ERR, "Failed to open FSFolder at '%o'", fullpath); } // Try to open a CompoundFileReader. On failure, just use the // existing folder. String *cfmeta_file = (String*)SSTR_WRAP_UTF8("cfmeta.json", 11); if (Folder_Local_Exists(subfolder, cfmeta_file)) { CompoundFileReader *cf_reader = CFReader_open(subfolder); if (cf_reader) { DECREF(subfolder); subfolder = (Folder*)cf_reader; } } Hash_Store(ivars->entries, (Obj*)name, (Obj*)subfolder); } DECREF(fullpath); return subfolder; }
bool_t RAMFolder_local_mkdir(RAMFolder *self, const CharBuf *name) { if (Hash_Fetch(self->entries, (Obj*)name)) { Err_set_error(Err_new(CB_newf( "Can't MkDir, '%o' already exists", name))); return false; } else { CharBuf *fullpath = S_fullpath(self, name); Hash_Store(self->entries, (Obj*)name, (Obj*)RAMFolder_new(fullpath)); DECREF(fullpath); return true; } }
bool FSFolder_Local_Is_Directory_IMP(FSFolder *self, String *name) { FSFolderIVARS *const ivars = FSFolder_IVARS(self); // Check for a cached object, then fall back to a system call. Obj *elem = Hash_Fetch(ivars->entries, (Obj*)name); if (elem && Obj_Is_A(elem, FOLDER)) { return true; } else { String *fullpath = S_fullpath(self, name); bool result = S_dir_ok(fullpath); DECREF(fullpath); return result; } }
FileHandle* RAMFolder_local_open_filehandle(RAMFolder *self, const CharBuf *name, uint32_t flags) { RAMFileHandle *fh; CharBuf *fullpath = S_fullpath(self, name); RAMFile *file = (RAMFile*)Hash_Fetch(self->entries, (Obj*)name); bool_t can_create = (flags & (FH_WRITE_ONLY | FH_CREATE)) == (FH_WRITE_ONLY | FH_CREATE) ? true : false; // Make sure the filepath isn't a directory, and that it either exists // or we have permission to create it. if (file) { if (!RAMFile_Is_A(file, RAMFILE)) { Err_set_error(Err_new(CB_newf("Not a file: '%o'", fullpath))); DECREF(fullpath); return NULL; } } else if (!can_create) { Err_set_error(Err_new(CB_newf("File not found: '%o'", fullpath))); DECREF(fullpath); return NULL; } // Open the file and store it if it was just created. fh = RAMFH_open(fullpath, flags, file); if (fh) { if (!file) { file = RAMFH_Get_File(fh); Hash_Store(self->entries, (Obj*)name, INCREF(file)); } } else { Err *error = Err_get_error(); ERR_ADD_FRAME(error); } DECREF(fullpath); return (FileHandle*)fh; }
static bool_t S_rename_or_hard_link(RAMFolder *self, const CharBuf* from, const CharBuf *to, Folder *from_folder, Folder *to_folder, ZombieCharBuf *from_name, ZombieCharBuf *to_name, int op) { Obj *elem = NULL; RAMFolder *inner_from_folder = NULL; RAMFolder *inner_to_folder = NULL; UNUSED_VAR(self); // Make sure the source and destination folders exist. if (!from_folder) { Err_set_error(Err_new(CB_newf("File not found: '%o'", from))); return false; } if (!to_folder) { Err_set_error(Err_new(CB_newf( "Invalid file path (can't find dir): '%o'", to))); return false; } // Extract RAMFolders from compound reader wrappers, if necessary. if (Folder_Is_A(from_folder, COMPOUNDFILEREADER)) { inner_from_folder = (RAMFolder*)CFReader_Get_Real_Folder( (CompoundFileReader*)from_folder); } else { inner_from_folder = (RAMFolder*)from_folder; } if (Folder_Is_A(to_folder, COMPOUNDFILEREADER)) { inner_to_folder = (RAMFolder*)CFReader_Get_Real_Folder( (CompoundFileReader*)to_folder); } else { inner_to_folder = (RAMFolder*)to_folder; } if (!RAMFolder_Is_A(inner_from_folder, RAMFOLDER)) { Err_set_error(Err_new(CB_newf("Not a RAMFolder, but a '%o'", Obj_Get_Class_Name((Obj*)inner_from_folder)))); return false; } if (!RAMFolder_Is_A(inner_to_folder, RAMFOLDER)) { Err_set_error(Err_new(CB_newf("Not a RAMFolder, but a '%o'", Obj_Get_Class_Name((Obj*)inner_to_folder)))); return false; } // Find the original element. elem = Hash_Fetch(inner_from_folder->entries, (Obj*)from_name); if (!elem) { if ( Folder_Is_A(from_folder, COMPOUNDFILEREADER) && Folder_Local_Exists(from_folder, (CharBuf*)from_name) ) { Err_set_error(Err_new(CB_newf("Source file '%o' is virtual", from))); } else { Err_set_error(Err_new(CB_newf("File not found: '%o'", from))); } return false; } // Execute the rename/hard-link. if (op == OP_RENAME) { Obj *existing = Hash_Fetch(inner_to_folder->entries, (Obj*)to_name); if (existing) { bool_t conflict = false; // Return success fast if file is copied on top of itself. if ( inner_from_folder == inner_to_folder && ZCB_Equals(from_name, (Obj*)to_name) ) { return true; } // Don't allow clobbering of different entry type. if (Obj_Is_A(elem, RAMFILE)) { if (!Obj_Is_A(existing, RAMFILE)) { conflict = true; } } else if (Obj_Is_A(elem, FOLDER)) { if (!Obj_Is_A(existing, FOLDER)) { conflict = true; } } if (conflict) { Err_set_error(Err_new(CB_newf("Can't clobber a %o with a %o", Obj_Get_Class_Name(existing), Obj_Get_Class_Name(elem)))); return false; } } // Perform the store first, then the delete. Inform Folder objects // about the relocation. Hash_Store(inner_to_folder->entries, (Obj*)to_name, INCREF(elem)); DECREF(Hash_Delete(inner_from_folder->entries, (Obj*)from_name)); if (Obj_Is_A(elem, FOLDER)) { CharBuf *newpath = S_fullpath(inner_to_folder, (CharBuf*)to_name); Folder_Set_Path((Folder*)elem, newpath); DECREF(newpath); } } else if (op == OP_HARD_LINK) { if (!Obj_Is_A(elem, RAMFILE)) { Err_set_error(Err_new(CB_newf("'%o' isn't a file, it's a %o", from, Obj_Get_Class_Name(elem)))); return false; } else { Obj *existing = Hash_Fetch(inner_to_folder->entries, (Obj*)to_name); if (existing) { Err_set_error(Err_new(CB_newf("'%o' already exists", to))); return false; } else { Hash_Store(inner_to_folder->entries, (Obj*)to_name, INCREF(elem)); } } } else { THROW(ERR, "Unexpected op: %i32", (int32_t)op); } return true; }