Beispiel #1
0
bool_t
Folder_delete_tree(Folder *self, const CharBuf *path) {
    Folder *enclosing_folder = Folder_Enclosing_Folder(self, path);

    // Don't allow Folder to delete itself.
    if (!path || !CB_Get_Size(path)) {
        return false;
    }

    if (enclosing_folder) {
        ZombieCharBuf *local = IxFileNames_local_part(path, ZCB_BLANK());
        if (Folder_Local_Is_Directory(enclosing_folder, (CharBuf*)local)) {
            Folder *inner_folder
                = Folder_Local_Find_Folder(enclosing_folder, (CharBuf*)local);
            DirHandle *dh = Folder_Local_Open_Dir(inner_folder);
            if (dh) {
                VArray *files = VA_new(20);
                VArray *dirs  = VA_new(20);
                CharBuf *entry = DH_Get_Entry(dh);
                while (DH_Next(dh)) {
                    VA_Push(files, (Obj*)CB_Clone(entry));
                    if (DH_Entry_Is_Dir(dh) && !DH_Entry_Is_Symlink(dh)) {
                        VA_Push(dirs, (Obj*)CB_Clone(entry));
                    }
                }
                for (uint32_t i = 0, max = VA_Get_Size(dirs); i < max; i++) {
                    CharBuf *name = (CharBuf*)VA_Fetch(files, i);
                    bool_t success = Folder_Delete_Tree(inner_folder, name);
                    if (!success && Folder_Local_Exists(inner_folder, name)) {
                        break;
                    }
                }
                for (uint32_t i = 0, max = VA_Get_Size(files); i < max; i++) {
                    CharBuf *name = (CharBuf*)VA_Fetch(files, i);
                    bool_t success = Folder_Local_Delete(inner_folder, name);
                    if (!success && Folder_Local_Exists(inner_folder, name)) {
                        break;
                    }
                }
                DECREF(dirs);
                DECREF(files);
                DECREF(dh);
            }
        }
        return Folder_Local_Delete(enclosing_folder, (CharBuf*)local);
    }
    else {
        // Return failure if the entry wasn't there in the first place.
        return false;
    }
}
Beispiel #2
0
bool
CFReader_Local_Exists_IMP(CompoundFileReader *self, String *name) {
    CompoundFileReaderIVARS *const ivars = CFReader_IVARS(self);
    if (Hash_Fetch(ivars->records, name))              { return true; }
    if (Folder_Local_Exists(ivars->real_folder, name)) { return true; }
    return false;
}
Beispiel #3
0
bool
Folder_exists(Folder *self, const CharBuf *path) {
    Folder *enclosing_folder = Folder_Enclosing_Folder(self, path);
    bool retval = false;
    if (enclosing_folder) {
        ZombieCharBuf *name = IxFileNames_local_part(path, ZCB_BLANK());
        if (Folder_Local_Exists(enclosing_folder, (CharBuf*)name)) {
            retval = true;
        }
    }
    return retval;
}
Beispiel #4
0
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;
}
Beispiel #5
0
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;
}
Beispiel #6
0
bool_t
CFReader_local_exists(CompoundFileReader *self, const CharBuf *name) {
    if (Hash_Fetch(self->records, (Obj*)name))        { return true; }
    if (Folder_Local_Exists(self->real_folder, name)) { return true; }
    return false;
}