Esempio n. 1
0
void
Folder_consolidate(Folder *self, const CharBuf *path) {
    Folder *folder = Folder_Find_Folder(self, path);
    Folder *enclosing_folder = Folder_Enclosing_Folder(self, path);
    if (!folder) {
        THROW(ERR, "Can't consolidate %o", path);
    }
    else if (Folder_Is_A(folder, COMPOUNDFILEREADER)) {
        THROW(ERR, "Can't consolidate %o twice", path);
    }
    else {
        CompoundFileWriter *cf_writer = CFWriter_new(folder);
        CFWriter_Consolidate(cf_writer);
        DECREF(cf_writer);
        if (CB_Get_Size(path)) {
            ZombieCharBuf *name = IxFileNames_local_part(path, ZCB_BLANK());
            CompoundFileReader *cf_reader = CFReader_open(folder);
            if (!cf_reader) {
                RETHROW(INCREF(Err_get_error()));
            }
            Hash_Store(enclosing_folder->entries, (Obj*)name,
                       (Obj*)cf_reader);
        }
    }
}
Esempio n. 2
0
Folder*
RAMFolder_local_find_folder(RAMFolder *self, const CharBuf *path)
{
    Folder *local_folder = (Folder*)Hash_Fetch(self->entries, (Obj*)path);
    if (local_folder && Folder_Is_A(local_folder, FOLDER)) {
        return local_folder;
    }
    return NULL;
}
Esempio n. 3
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;
}
Esempio n. 4
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;
}
Esempio n. 5
0
static void
test_Enclosing_Folder_and_Find_Folder(TestBatch *batch)
{
    Folder *folder = (Folder*)RAMFolder_new(NULL);
    FileHandle *fh;

    Folder_MkDir(folder, &foo);
    Folder_MkDir(folder, &foo_bar);
    Folder_MkDir(folder, &foo_bar_baz);
    fh = Folder_Open_FileHandle(folder, &foo_bar_baz_boffo, 
        FH_CREATE | FH_WRITE_ONLY);

    {
        Folder *encloser = Folder_Enclosing_Folder(folder, (CharBuf*)&nope);
        Folder *found = Folder_Find_Folder(folder, (CharBuf*)&nope);
        TEST_TRUE(batch, encloser == folder, 
            "Enclosing_Folder() - non-existent entry yields parent");
        TEST_TRUE(batch, found == NULL,
            "Find_Folder() - non-existent entry yields NULL");
    }

    {
        Folder *encloser = Folder_Enclosing_Folder(folder, &foo_bar);
        Folder *found = Folder_Find_Folder(folder, &foo_bar);
        TEST_TRUE(batch, 
            encloser 
            && Folder_Is_A(encloser, FOLDER)
            && CB_Ends_With(Folder_Get_Path(encloser), &foo),
            "Enclosing_Folder() - find one directory down");
        TEST_TRUE(batch, 
            found 
            && Folder_Is_A(found, FOLDER)
            && CB_Ends_With(Folder_Get_Path(found), &bar),
            "Find_Folder() - 'foo/bar'");
    }

    {
        Folder *encloser = Folder_Enclosing_Folder(folder, &foo_bar_baz);
        Folder *found = Folder_Find_Folder(folder, &foo_bar_baz);
        TEST_TRUE(batch, 
            encloser 
            && Folder_Is_A(encloser, FOLDER)
            && CB_Ends_With(Folder_Get_Path(encloser), &bar), 
            "Find two directories down");
        TEST_TRUE(batch, 
            found 
            && Folder_Is_A(found, FOLDER)
            && CB_Ends_With(Folder_Get_Path(found), &baz),
            "Find_Folder() - 'foo/bar/baz'");
    }

    {
        Folder *encloser 
            = Folder_Enclosing_Folder(folder, &foo_bar_baz_boffo);
        Folder *found = Folder_Find_Folder(folder, &foo_bar_baz_boffo);
        TEST_TRUE(batch, 
            encloser 
            && Folder_Is_A(encloser, FOLDER)
            && CB_Ends_With(Folder_Get_Path(encloser), &baz), 
            "Recurse to find a directory containing a real file");
        TEST_TRUE(batch, found == NULL,
            "Find_Folder() - file instead of folder yields NULL");
    }

    DECREF(fh);
    DECREF(folder);
}