示例#1
0
static void
test_Local_Find_Folder(TestBatchRunner *runner) {
    RAMFolder *folder = RAMFolder_new(NULL);
    RAMFolder *local;
    FileHandle *fh;

    RAMFolder_MkDir(folder, foo);
    RAMFolder_MkDir(folder, foo_bar);
    fh = RAMFolder_Open_FileHandle(folder, boffo,
                                   FH_CREATE | FH_WRITE_ONLY);
    DECREF(fh);
    fh = RAMFolder_Open_FileHandle(folder, foo_boffo,
                                   FH_CREATE | FH_WRITE_ONLY);
    DECREF(fh);

    local = (RAMFolder*)RAMFolder_Local_Find_Folder(folder, nope);
    TEST_TRUE(runner, local == NULL, "Non-existent entry yields NULL");

    ZombieCharBuf *empty = ZCB_BLANK();
    local = (RAMFolder*)RAMFolder_Local_Find_Folder(folder, (CharBuf*)empty);
    TEST_TRUE(runner, local == NULL, "Empty string yields NULL");

    local = (RAMFolder*)RAMFolder_Local_Find_Folder(folder, foo_bar);
    TEST_TRUE(runner, local == NULL, "nested folder yields NULL");

    local = (RAMFolder*)RAMFolder_Local_Find_Folder(folder, foo_boffo);
    TEST_TRUE(runner, local == NULL, "nested file yields NULL");

    local = (RAMFolder*)RAMFolder_Local_Find_Folder(folder, boffo);
    TEST_TRUE(runner, local == NULL, "local file yields NULL");

    local = (RAMFolder*)RAMFolder_Local_Find_Folder(folder, bar);
    TEST_TRUE(runner, local == NULL, "name of nested folder yields NULL");

    local = (RAMFolder*)RAMFolder_Local_Find_Folder(folder, foo);
    TEST_TRUE(runner,
              local
              && RAMFolder_Is_A(local, RAMFOLDER)
              && CB_Equals_Str(RAMFolder_Get_Path(local), "foo", 3),
              "Find local directory");

    DECREF(folder);
}
示例#2
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;
}