Ejemplo n.º 1
0
static void
test_Open_FileHandle(TestBatch *batch)
{
    Folder     *folder = (Folder*)RAMFolder_new(NULL);
    FileHandle *fh;

    Folder_MkDir(folder, &foo);

    fh = Folder_Open_FileHandle(folder, &boffo, FH_CREATE | FH_WRITE_ONLY);
    TEST_TRUE(batch, fh && FH_Is_A(fh, FILEHANDLE), "Open_FileHandle");
    DECREF(fh);

    fh = Folder_Open_FileHandle(folder, &foo_boffo, 
        FH_CREATE | FH_WRITE_ONLY);
    TEST_TRUE(batch, fh && FH_Is_A(fh, FILEHANDLE), 
        "Open_FileHandle for nested file");
    DECREF(fh);

    Err_set_error(NULL);
    fh = Folder_Open_FileHandle(folder, &foo, FH_CREATE | FH_WRITE_ONLY);
    TEST_TRUE(batch, fh == NULL,
        "Open_FileHandle on existing dir path fails");
    TEST_TRUE(batch, Err_get_error() != NULL,
        "Open_FileHandle on existing dir name sets Err_error");

    Err_set_error(NULL);
    fh = Folder_Open_FileHandle(folder, &foo_bar_baz_boffo, 
        FH_CREATE | FH_WRITE_ONLY);
    TEST_TRUE(batch, fh == NULL,
        "Open_FileHandle for entry within non-existent dir fails");
    TEST_TRUE(batch, Err_get_error() != NULL,
        "Open_FileHandle for entry within non-existent dir sets Err_error");

    DECREF(folder);
}
Ejemplo n.º 2
0
static void
test_Local_MkDir(TestBatchRunner *runner) {
    RAMFolder *folder = RAMFolder_new(NULL);
    bool result;

    result = RAMFolder_Local_MkDir(folder, foo);
    TEST_TRUE(runner, result, "Local_MkDir succeeds and returns true");

    Err_set_error(NULL);
    result = RAMFolder_Local_MkDir(folder, foo);
    TEST_FALSE(runner, result,
               "Local_MkDir returns false when a dir already exists");
    TEST_TRUE(runner, Err_get_error() != NULL,
              "Local_MkDir sets Err_error when a dir already exists");
    TEST_TRUE(runner, RAMFolder_Exists(folder, foo),
              "Existing dir untouched after failed Local_MkDir");

    FileHandle *fh = RAMFolder_Open_FileHandle(folder, boffo,
                                               FH_CREATE | FH_WRITE_ONLY);
    DECREF(fh);
    Err_set_error(NULL);
    result = RAMFolder_Local_MkDir(folder, foo);
    TEST_FALSE(runner, result,
               "Local_MkDir returns false when a file already exists");
    TEST_TRUE(runner, Err_get_error() != NULL,
              "Local_MkDir sets Err_error when a file already exists");
    TEST_TRUE(runner, RAMFolder_Exists(folder, boffo) &&
              !RAMFolder_Local_Is_Directory(folder, boffo),
              "Existing file untouched after failed Local_MkDir");

    DECREF(folder);
}
Ejemplo n.º 3
0
static void
test_Open_Dir(TestBatch *batch)
{
    Folder     *folder = (Folder*)RAMFolder_new(NULL);
    DirHandle  *dh;

    Folder_MkDir(folder, &foo);
    Folder_MkDir(folder, &foo_bar);

    dh = Folder_Open_Dir(folder, &foo);
    TEST_TRUE(batch, dh && DH_Is_A(dh, DIRHANDLE), "Open_Dir");
    DECREF(dh);
    dh = Folder_Open_Dir(folder, &foo_bar);
    TEST_TRUE(batch, dh && DH_Is_A(dh, DIRHANDLE), "Open_Dir nested dir");
    DECREF(dh);

    Err_set_error(NULL);
    dh = Folder_Open_Dir(folder, &bar);
    TEST_TRUE(batch, dh == NULL,
        "Open_Dir on non-existent entry fails");
    TEST_TRUE(batch, Err_get_error() != NULL,
        "Open_Dir on non-existent entry sets Err_error");

    Err_set_error(NULL);
    dh = Folder_Open_Dir(folder, &foo_foo);
    TEST_TRUE(batch, dh == NULL,
        "Open_Dir on non-existent nested entry fails");
    TEST_TRUE(batch, Err_get_error() != NULL,
        "Open_Dir on non-existent nested entry sets Err_error");

    DECREF(folder);
}
Ejemplo n.º 4
0
bool_t
FSFH_read(FSFileHandle *self, char *dest, int64_t offset, size_t len) {
    int64_t check_val;

    // Sanity check.
    if (offset < 0) {
        Err_set_error(Err_new(CB_newf("Can't read from an offset less than 0 (%i64)",
                                      offset)));
        return false;
    }

    // Read.
    check_val = pread64(self->fd, dest, len, offset);
    if (check_val != (int64_t)len) {
        if (check_val == -1) {
            Err_set_error(Err_new(CB_newf("Tried to read %u64 bytes, got %i64: %s",
                                          (uint64_t)len, check_val, strerror(errno))));
        }
        else {
            Err_set_error(Err_new(CB_newf("Tried to read %u64 bytes, got %i64",
                                          (uint64_t)len, check_val)));
        }
        return false;
    }

    return true;
}
Ejemplo n.º 5
0
static INLINE bool_t
SI_close_win_handles(FSFileHandle *self) {
    // Close both standard handle and mapping handle.
    if (self->win_maphandle) {
        if (!CloseHandle(self->win_maphandle)) {
            char *win_error = Err_win_error();
            Err_set_error(Err_new(CB_newf("Failed to close file mapping handle: %s",
                                          win_error)));
            FREEMEM(win_error);
            return false;
        }
        self->win_maphandle = NULL;
    }
    if (self->win_fhandle) {
        if (!CloseHandle(self->win_fhandle)) {
            char *win_error = Err_win_error();
            Err_set_error(Err_new(CB_newf("Failed to close file handle: %s",
                                          win_error)));
            FREEMEM(win_error);
            return false;
        }
        self->win_fhandle = NULL;
    }

    return true;
}
Ejemplo n.º 6
0
static void
test_Read_Write(TestBatchRunner *runner) {
    FSFileHandle *fh;
    const char *foo = "foo";
    const char *bar = "bar";
    char buffer[12];
    char *buf = buffer;
    String *test_filename = SSTR_WRAP_C("_fstest");

    S_remove(test_filename);
    fh = FSFH_open(test_filename,
                   FH_CREATE | FH_WRITE_ONLY | FH_EXCLUSIVE);

    TEST_TRUE(runner, FSFH_Length(fh) == INT64_C(0), "Length initially 0");
    TEST_TRUE(runner, FSFH_Write(fh, foo, 3), "Write returns success");
    TEST_TRUE(runner, FSFH_Length(fh) == INT64_C(3), "Length after Write");
    TEST_TRUE(runner, FSFH_Write(fh, bar, 3), "Write returns success");
    TEST_TRUE(runner, FSFH_Length(fh) == INT64_C(6), "Length after 2 Writes");

    Err_set_error(NULL);
    TEST_FALSE(runner, FSFH_Read(fh, buf, 0, 2),
               "Reading from a write-only handle returns false");
    TEST_TRUE(runner, Err_get_error() != NULL,
              "Reading from a write-only handle sets error");
    if (!FSFH_Close(fh)) { RETHROW(INCREF(Err_get_error())); }
    DECREF(fh);

    // Reopen for reading.
    Err_set_error(NULL);
    fh = FSFH_open(test_filename, FH_READ_ONLY);

    TEST_TRUE(runner, FSFH_Length(fh) == INT64_C(6), "Length on Read");
    TEST_TRUE(runner, FSFH_Read(fh, buf, 0, 6), "Read returns success");
    TEST_TRUE(runner, strncmp(buf, "foobar", 6) == 0, "Read/Write");
    TEST_TRUE(runner, FSFH_Read(fh, buf, 2, 3), "Read returns success");
    TEST_TRUE(runner, strncmp(buf, "oba", 3) == 0, "Read with offset");

    Err_set_error(NULL);
    TEST_FALSE(runner, FSFH_Read(fh, buf, -1, 4),
               "Read() with a negative offset returns false");
    TEST_TRUE(runner, Err_get_error() != NULL,
              "Read() with a negative offset sets error");

    Err_set_error(NULL);
    TEST_FALSE(runner, FSFH_Read(fh, buf, 6, 1),
               "Read() past EOF returns false");
    TEST_TRUE(runner, Err_get_error() != NULL,
              "Read() past EOF sets error");

    Err_set_error(NULL);
    TEST_FALSE(runner, FSFH_Write(fh, foo, 3),
               "Writing to a read-only handle returns false");
    TEST_TRUE(runner, Err_get_error() != NULL,
              "Writing to a read-only handle sets error");

    DECREF(fh);
    S_remove(test_filename);
}
Ejemplo n.º 7
0
static INLINE bool_t 
SI_init_read_only(FSFileHandle *self)
{
    LARGE_INTEGER large_int;
    char *filepath = (char*)CB_Get_Ptr8(self->path);
    SYSTEM_INFO sys_info;

    // Get system page size. 
    GetSystemInfo(&sys_info);
    self->page_size = sys_info.dwAllocationGranularity;

    // Open. 
    self->win_fhandle = CreateFile(
        filepath,
        GENERIC_READ,
        FILE_SHARE_READ,
        NULL,
        OPEN_EXISTING,
        FILE_ATTRIBUTE_READONLY | FILE_FLAG_OVERLAPPED,
        NULL
    );
    if (self->win_fhandle == INVALID_HANDLE_VALUE) {
        char *win_error = Err_win_error();
        Err_set_error(Err_new(CB_newf("CreateFile for %o failed: %s", 
            self->path, win_error)));
        FREEMEM(win_error);
        return false;
    }

    // Derive len. 
    GetFileSizeEx(self->win_fhandle, &large_int);
    self->len = large_int.QuadPart;
    if (self->len < 0) {
        Err_set_error(Err_new(CB_newf(
            "GetFileSizeEx for %o returned a negative length: '%i64'", 
            self->path, self->len)));
        return false;
    }

    // Init mapping handle. 
    self->buf = NULL;
    if (self->len) {
        self->win_maphandle = CreateFileMapping(self->win_fhandle, NULL,
            PAGE_READONLY, 0, 0, NULL);
        if (self->win_maphandle == NULL) {
            char *win_error = Err_win_error();
            Err_set_error(Err_new(CB_newf(
                "CreateFileMapping for %o failed: %s", 
                self->path, win_error)));
            FREEMEM(win_error);
            return false;
        }
    }
    
    return true;
}
Ejemplo n.º 8
0
static INLINE bool
SI_init_read_only(FSFileHandle *self, FSFileHandleIVARS *ivars) {
    char *filepath = (char*)CB_Get_Ptr8(ivars->path);
    SYSTEM_INFO sys_info;

    // Get system page size.
    GetSystemInfo(&sys_info);
    ivars->page_size = sys_info.dwAllocationGranularity;

    // Open.
    ivars->win_fhandle = CreateFile(
                            filepath,
                            GENERIC_READ,
                            FILE_SHARE_READ,
                            NULL,
                            OPEN_EXISTING,
                            FILE_ATTRIBUTE_READONLY | FILE_FLAG_OVERLAPPED,
                            NULL
                        );
    if (ivars->win_fhandle == INVALID_HANDLE_VALUE) {
        char *win_error = Err_win_error();
        Err_set_error(Err_new(CB_newf("CreateFile for %o failed: %s",
                                      ivars->path, win_error)));
        FREEMEM(win_error);
        return false;
    }

    // Derive len.
    DWORD file_size_hi;
    DWORD file_size_lo = GetFileSize(ivars->win_fhandle, &file_size_hi);
    if (file_size_lo == INVALID_FILE_SIZE && GetLastError() != NO_ERROR) {
        Err_set_error(Err_new(CB_newf("GetFileSize for %o failed",
                                      ivars->path)));
        return false;
    }
    ivars->len = ((uint64_t)file_size_hi << 32) | file_size_lo;

    // Init mapping handle.
    ivars->buf = NULL;
    if (ivars->len) {
        ivars->win_maphandle = CreateFileMapping(ivars->win_fhandle, NULL,
                                                 PAGE_READONLY, 0, 0, NULL);
        if (ivars->win_maphandle == NULL) {
            char *win_error = Err_win_error();
            Err_set_error(Err_new(CB_newf("CreateFileMapping for %o failed: %s",
                                          ivars->path, win_error)));
            FREEMEM(win_error);
            return false;
        }
    }

    return true;
}
Ejemplo n.º 9
0
static void
test_Window(TestBatchRunner *runner) {
    String *test_filename = SSTR_WRAP_C("_fstest");
    FSFileHandle *fh;
    FileWindow *window = FileWindow_new();
    uint32_t i;

    S_remove(test_filename);
    fh = FSFH_open(test_filename,
                   FH_CREATE | FH_WRITE_ONLY | FH_EXCLUSIVE);
    for (i = 0; i < 1024; i++) {
        FSFH_Write(fh, "foo ", 4);
    }
    if (!FSFH_Close(fh)) { RETHROW(INCREF(Err_get_error())); }

    // Reopen for reading.
    DECREF(fh);
    fh = FSFH_open(test_filename, FH_READ_ONLY);
    if (!fh) { RETHROW(INCREF(Err_get_error())); }

    Err_set_error(NULL);
    TEST_FALSE(runner, FSFH_Window(fh, window, -1, 4),
               "Window() with a negative offset returns false");
    TEST_TRUE(runner, Err_get_error() != NULL,
              "Window() with a negative offset sets error");

    Err_set_error(NULL);
    TEST_FALSE(runner, FSFH_Window(fh, window, 4000, 1000),
               "Window() past EOF returns false");
    TEST_TRUE(runner, Err_get_error() != NULL,
              "Window() past EOF sets error");

    TEST_TRUE(runner, FSFH_Window(fh, window, 1021, 2),
              "Window() returns true");
    const char *buf = FileWindow_Get_Buf(window);
    int64_t offset = FileWindow_Get_Offset(window);
    TEST_TRUE(runner,
              strncmp(buf - offset + 1021, "oo", 2) == 0,
              "Window()");

    TEST_TRUE(runner, FSFH_Release_Window(fh, window),
              "Release_Window() returns true");
    TEST_TRUE(runner, FileWindow_Get_Buf(window) == NULL,
              "Release_Window() resets buf");
    TEST_INT_EQ(runner, FileWindow_Get_Offset(window), 0,
                "Release_Window() resets offset");
    TEST_INT_EQ(runner, FileWindow_Get_Len(window), 0,
                "Release_Window() resets len");

    DECREF(window);
    DECREF(fh);
    S_remove(test_filename);
}
Ejemplo n.º 10
0
static void
test_Window(TestBatchRunner *runner) {
    String *test_filename = (String*)SSTR_WRAP_UTF8("_fstest", 7);
    FSFileHandle *fh;
    FileWindow *window = FileWindow_new();
    FileWindowIVARS *const window_ivars = FileWindow_IVARS(window);
    uint32_t i;

    remove(Str_Get_Ptr8(test_filename));
    fh = FSFH_open(test_filename,
                   FH_CREATE | FH_WRITE_ONLY | FH_EXCLUSIVE);
    for (i = 0; i < 1024; i++) {
        FSFH_Write(fh, "foo ", 4);
    }
    if (!FSFH_Close(fh)) { RETHROW(INCREF(Err_get_error())); }

    // Reopen for reading.
    DECREF(fh);
    fh = FSFH_open(test_filename, FH_READ_ONLY);
    if (!fh) { RETHROW(INCREF(Err_get_error())); }

    Err_set_error(NULL);
    TEST_FALSE(runner, FSFH_Window(fh, window, -1, 4),
               "Window() with a negative offset returns false");
    TEST_TRUE(runner, Err_get_error() != NULL,
              "Window() with a negative offset sets error");

    Err_set_error(NULL);
    TEST_FALSE(runner, FSFH_Window(fh, window, 4000, 1000),
               "Window() past EOF returns false");
    TEST_TRUE(runner, Err_get_error() != NULL,
              "Window() past EOF sets error");

    TEST_TRUE(runner, FSFH_Window(fh, window, 1021, 2),
              "Window() returns true");
    TEST_TRUE(runner,
              strncmp(window_ivars->buf - window_ivars->offset + 1021, "oo", 2) == 0,
              "Window()");

    TEST_TRUE(runner, FSFH_Release_Window(fh, window),
              "Release_Window() returns true");
    TEST_TRUE(runner, window_ivars->buf == NULL, "Release_Window() resets buf");
    TEST_TRUE(runner, window_ivars->offset == 0, "Release_Window() resets offset");
    TEST_TRUE(runner, window_ivars->len == 0, "Release_Window() resets len");

    DECREF(window);
    DECREF(fh);
    remove(Str_Get_Ptr8(test_filename));
}
Ejemplo n.º 11
0
bool_t
FSFH_read(FSFileHandle *self, char *dest, int64_t offset, size_t len)
{
    BOOL check_val;
    DWORD got;
    OVERLAPPED read_op_state;
    uint64_t offs = (uint64_t)offset;

    read_op_state.hEvent     = NULL;
    read_op_state.OffsetHigh = offs >> 32;
    read_op_state.Offset     = offs & 0xFFFFFFFF;
    
    // Sanity check. 
    if (offset < 0) {
        Err_set_error(Err_new(CB_newf(
            "Can't read from an offset less than 0 (%i64)", offset)));
        return false;
    }

    // ReadFile() takes a DWORD (unsigned 32-bit integer) as a length
    // argument, so throw a sensible error rather than wrap around. 
    if (len > U32_MAX) {
        Err_set_error(Err_new(CB_newf(
            "Can't read more than 4 GB (%u64)", (uint64_t)len))); 
        return false;
    }

    // Read. 
    check_val = ReadFile(self->win_fhandle, dest, len, &got, &read_op_state);
    if (!check_val && GetLastError() == ERROR_IO_PENDING) {
        // Read has been queued by the OS and will soon complete.  Wait for
        // it, since this is a blocking IO call from the point of the rest of
        // the library.
        check_val = GetOverlappedResult(self->win_fhandle, &read_op_state,
           &got, TRUE);
    }

    // Verify that the read has succeeded by now. 
    if (!check_val) {
        char *win_error = Err_win_error();
        Err_set_error(Err_new(CB_newf("Failed to read %u64 bytes: %s",
            (uint64_t)len, win_error)));
        FREEMEM(win_error);
        return false;
    }

    return true;
}
Ejemplo n.º 12
0
static void
test_spew_and_slurp(TestBatch *batch) {
    Obj *dump = S_make_dump();
    Folder *folder = (Folder*)RAMFolder_new(NULL);

    CharBuf *foo = (CharBuf*)ZCB_WRAP_STR("foo", 3);
    bool_t result = Json_spew_json(dump, folder, foo);
    TEST_TRUE(batch, result, "spew_json returns true on success");
    TEST_TRUE(batch, Folder_Exists(folder, foo),
              "spew_json wrote file");

    Obj *got = Json_slurp_json(folder, foo);
    TEST_TRUE(batch, got && Obj_Equals(dump, got),
              "Round trip through spew_json and slurp_json");
    DECREF(got);

    Err_set_error(NULL);
    result = Json_spew_json(dump, folder, foo);
    TEST_FALSE(batch, result, "Can't spew_json when file exists");
    TEST_TRUE(batch, Err_get_error() != NULL,
              "Failed spew_json sets Err_error");

    Err_set_error(NULL);
    CharBuf *bar = (CharBuf*)ZCB_WRAP_STR("bar", 3);
    got = Json_slurp_json(folder, bar);
    TEST_TRUE(batch, got == NULL,
              "slurp_json returns NULL when file doesn't exist");
    TEST_TRUE(batch, Err_get_error() != NULL,
              "Failed slurp_json sets Err_error");

    CharBuf *boffo = (CharBuf*)ZCB_WRAP_STR("boffo", 5);

    FileHandle *fh
        = Folder_Open_FileHandle(folder, boffo, FH_CREATE | FH_WRITE_ONLY);
    FH_Write(fh, "garbage", 7);
    DECREF(fh);

    Err_set_error(NULL);
    got = Json_slurp_json(folder, boffo);
    TEST_TRUE(batch, got == NULL,
              "slurp_json returns NULL when file doesn't contain valid JSON");
    TEST_TRUE(batch, Err_get_error() != NULL,
              "Failed slurp_json sets Err_error");
    DECREF(got);

    DECREF(dump);
    DECREF(folder);
}
Ejemplo n.º 13
0
void
ErrMsg_set_with_errno(const char *fmt, ...) {
    int cur_errno = errno;

    CharBuf *buf = CB_new(0);

    va_list args;
    va_start(args, fmt);
    CB_VCatF(buf, fmt, args);
    va_end(args);

    CB_Cat_Trusted_Utf8(buf, ": ", 2);

    const char *msg = ErrMsg_strerror(cur_errno);

    if (msg != NULL) {
        CB_Cat_Trusted_Utf8(buf, msg, strlen(msg));
    }
    else {
        CB_catf(buf, "Unknown error: %i32", (int32_t)cur_errno);
    }

    Err_set_error(Err_new(CB_Yield_String(buf)));
    DECREF(buf);
}
Ejemplo n.º 14
0
CharBuf*
Json_to_json(Obj *dump) {
    // Validate object type, only allowing hashes and arrays per JSON spec.
    if (!dump || !(Obj_Is_A(dump, HASH) || Obj_Is_A(dump, VARRAY))) {
        if (!tolerant) {
            CharBuf *class_name = dump ? Obj_Get_Class_Name(dump) : NULL;
            CharBuf *mess = MAKE_MESS("Illegal top-level object type: %o",
                                      class_name);
            Err_set_error(Err_new(mess));
            return NULL;
        }
    }

    // Encode.
    CharBuf *json = CB_new(31);
    if (!S_to_json(dump, json, 0)) {
        DECREF(json);
        ERR_ADD_FRAME(Err_get_error());
        json = NULL;
    }
    else {
        // Append newline.
        CB_Cat_Trusted_Str(json, "\n", 1);
    }

    return json;
}
Ejemplo n.º 15
0
InStream*
CFReader_local_open_in(CompoundFileReader *self, const CharBuf *name) {
    Hash *entry = (Hash*)Hash_Fetch(self->records, (Obj*)name);

    if (!entry) {
        InStream *instream = Folder_Local_Open_In(self->real_folder, name);
        if (!instream) {
            ERR_ADD_FRAME(Err_get_error());
        }
        return instream;
    }
    else {
        Obj *len    = Hash_Fetch_Str(entry, "length", 6);
        Obj *offset = Hash_Fetch_Str(entry, "offset", 6);
        if (!len || !offset) {
            Err_set_error(Err_new(CB_newf("Malformed entry for '%o' in '%o'",
                                          name, Folder_Get_Path(self->real_folder))));
            return NULL;
        }
        else if (CB_Get_Size(self->path)) {
            CharBuf *fullpath = CB_newf("%o/%o", self->path, name);
            InStream *instream = InStream_Reopen(self->instream, fullpath,
                                                 Obj_To_I64(offset), Obj_To_I64(len));
            DECREF(fullpath);
            return instream;
        }
        else {
            return InStream_Reopen(self->instream, name, Obj_To_I64(offset),
                                   Obj_To_I64(len));
        }
    }
}
Ejemplo n.º 16
0
static void
test_Close(TestBatchRunner *runner) {
    String *test_filename = SSTR_WRAP_C("_fstest");
    FSFileHandle *fh;

    S_remove(test_filename);
    fh = FSFH_open(test_filename,
                   FH_CREATE | FH_WRITE_ONLY | FH_EXCLUSIVE);
    TEST_TRUE(runner, FSFH_Close(fh), "Close returns true for write-only");
    DECREF(fh);

    // Simulate an OS error when closing the file descriptor.  This
    // approximates what would happen if, say, we run out of disk space.
    S_remove(test_filename);
    fh = FSFH_open(test_filename,
                   FH_CREATE | FH_WRITE_ONLY | FH_EXCLUSIVE);
#ifdef _MSC_VER
    SKIP(runner, 2, "LUCY-155");
#else
    int saved_fd = FSFH_Set_FD(fh, -1);
    Err_set_error(NULL);
    bool result = FSFH_Close(fh);
    TEST_FALSE(runner, result, "Failed Close() returns false");
    TEST_TRUE(runner, Err_get_error() != NULL,
              "Failed Close() sets global error");
    FSFH_Set_FD(fh, saved_fd);
#endif /* _MSC_VER */
    DECREF(fh);

    fh = FSFH_open(test_filename, FH_READ_ONLY);
    TEST_TRUE(runner, FSFH_Close(fh), "Close returns true for read-only");

    DECREF(fh);
    S_remove(test_filename);
}
Ejemplo n.º 17
0
static void
test_Local_Open_In(TestBatchRunner *runner) {
    Folder *real_folder = S_folder_with_contents();
    CompoundFileReader *cf_reader = CFReader_open(real_folder);
    InStream *instream;

    instream = CFReader_Local_Open_In(cf_reader, foo);
    TEST_TRUE(runner, instream != NULL,
              "Local_Open_In for virtual file");
    TEST_TRUE(runner,
              Str_Starts_With(InStream_Get_Filename(instream), CFReader_Get_Path(cf_reader)),
              "InStream's path includes directory");
    DECREF(instream);

    OutStream *outstream = CFReader_Open_Out(cf_reader, baz);
    OutStream_Write_Bytes(outstream, "baz", 3);
    OutStream_Close(outstream);
    DECREF(outstream);
    instream = CFReader_Local_Open_In(cf_reader, baz);
    TEST_TRUE(runner, instream != NULL,
              "Local_Open_In pass-through for real file");
    DECREF(instream);

    Err_set_error(NULL);
    instream = CFReader_Local_Open_In(cf_reader, stuff);
    TEST_TRUE(runner, instream == NULL,
              "Local_Open_In for non-existent file returns NULL");
    TEST_TRUE(runner, Err_get_error() != NULL,
              "Local_Open_In for non-existent file sets global error");

    DECREF(cf_reader);
    DECREF(real_folder);
}
Ejemplo n.º 18
0
static void
test_Local_Delete(TestBatchRunner *runner) {
    RAMFolder *folder = RAMFolder_new(NULL);
    FileHandle *fh;

    fh = RAMFolder_Open_FileHandle(folder, boffo, FH_CREATE | FH_WRITE_ONLY);
    DECREF(fh);
    TEST_TRUE(runner, RAMFolder_Local_Delete(folder, boffo),
              "Local_Delete on file succeeds");

    RAMFolder_Local_MkDir(folder, foo);
    fh = RAMFolder_Open_FileHandle(folder, foo_boffo,
                                   FH_CREATE | FH_WRITE_ONLY);
    DECREF(fh);

    Err_set_error(NULL);
    TEST_FALSE(runner, RAMFolder_Local_Delete(folder, foo),
               "Local_Delete on non-empty dir fails");

    RAMFolder_Delete(folder, foo_boffo);
    TEST_TRUE(runner, RAMFolder_Local_Delete(folder, foo),
              "Local_Delete on empty dir succeeds");

    DECREF(folder);
}
Ejemplo n.º 19
0
bool_t
FSFH_close(FSFileHandle *self) {
    // On 64-bit systems, cancel the whole-file mapping.
    if (IS_64_BIT && (self->flags & FH_READ_ONLY) && self->buf != NULL) {
        if (!SI_unmap(self, self->buf, self->len)) { return false; }
        self->buf = NULL;
    }

    // Close system-specific handles.
    if (self->fd) {
        if (close(self->fd)) {
            Err_set_error(Err_new(CB_newf("Failed to close file: %s",
                                          strerror(errno))));
            return false;
        }
        self->fd  = 0;
    }
    #if (defined(CHY_HAS_WINDOWS_H) && !defined(CHY_HAS_SYS_MMAN_H))
    if (self->win_fhandle) {
        if (!SI_close_win_handles(self)) { return false; }
    }
    #endif

    return true;
}
Ejemplo n.º 20
0
bool
FSDH_close(FSDirHandle *self) {
    FSDirHandleIVARS *const ivars = FSDH_IVARS(self);
    if (ivars->sys_dirhandle && ivars->sys_dirhandle != INVALID_HANDLE_VALUE) {
        HANDLE dirhandle = (HANDLE)ivars->sys_dirhandle;
        ivars->sys_dirhandle = NULL;
        if (dirhandle != INVALID_HANDLE_VALUE && !FindClose(dirhandle)) {
            if (!ivars->saved_error) {
                char *win_error = Err_win_error();
                ivars->saved_error
                    = Err_new(CB_newf("Error while closing directory: %s",
                                      win_error));
                FREEMEM(win_error);
            }
        }
    }
    if (ivars->sys_dir_entry) {
        FREEMEM(ivars->sys_dir_entry);
        ivars->sys_dir_entry = NULL;
    }

    // If we encountered an error condition previously, report it now.
    if (ivars->saved_error) {
        Err_set_error((Err*)CFISH_INCREF(ivars->saved_error));
        return false;
    }
    else {
        return true;
    }
}
Ejemplo n.º 21
0
static INLINE void*
SI_map(FSFileHandle *self, int64_t offset, int64_t len)
{
    void *buf = NULL;

    if (len) {
        // Read-only memory map. 
        uint64_t offs = (uint64_t)offset;
        DWORD file_offset_hi = offs >> 32;
        DWORD file_offset_lo = offs & 0xFFFFFFFF;
        size_t amount = (size_t)len;
        buf = MapViewOfFile(
            self->win_maphandle, 
            FILE_MAP_READ, 
            file_offset_hi,
            file_offset_lo,
            amount
        );
        if (buf == NULL) {
            char *win_error = Err_win_error();
            Err_set_error(Err_new(CB_newf(
                "MapViewOfFile for %o failed: %s", 
                self->path, win_error)));
            FREEMEM(win_error);
        }
    }

    return buf;
}
Ejemplo n.º 22
0
InStream*
CFReader_Local_Open_In_IMP(CompoundFileReader *self, String *name) {
    CompoundFileReaderIVARS *const ivars = CFReader_IVARS(self);
    Hash *entry = (Hash*)Hash_Fetch(ivars->records, name);

    if (!entry) {
        InStream *instream = Folder_Local_Open_In(ivars->real_folder, name);
        if (!instream) {
            ERR_ADD_FRAME(Err_get_error());
        }
        return instream;
    }
    else {
        Obj *len    = Hash_Fetch_Utf8(entry, "length", 6);
        Obj *offset = Hash_Fetch_Utf8(entry, "offset", 6);
        if (!len || !offset) {
            Err_set_error(Err_new(Str_newf("Malformed entry for '%o' in '%o'",
                                           name, Folder_Get_Path(ivars->real_folder))));
            return NULL;
        }
        else if (Str_Get_Size(ivars->path)) {
            String *fullpath = Str_newf("%o/%o", ivars->path, name);
            InStream *instream = InStream_Reopen(ivars->instream, fullpath,
                                                 Obj_To_I64(offset), Obj_To_I64(len));
            DECREF(fullpath);
            return instream;
        }
        else {
            return InStream_Reopen(ivars->instream, name, Obj_To_I64(offset),
                                   Obj_To_I64(len));
        }
    }
}
Ejemplo n.º 23
0
static void
test_MkDir_and_Is_Directory(TestBatch *batch)
{
    Folder *folder = (Folder*)RAMFolder_new(NULL);
    FileHandle *fh;

    TEST_FALSE(batch, Folder_Is_Directory(folder, &foo), 
        "Is_Directory() false for non-existent entry");

    TEST_TRUE(batch, Folder_MkDir(folder, &foo), 
        "MkDir returns true on success");
    TEST_TRUE(batch, Folder_Is_Directory(folder, &foo), 
        "Is_Directory() true for local folder");

    TEST_FALSE(batch, Folder_Is_Directory(folder, &foo_bar_baz), 
        "Is_Directory() false for non-existent deeply nested dir");
    Err_set_error(NULL);
    TEST_FALSE(batch, Folder_MkDir(folder, &foo_bar_baz), 
        "MkDir for deeply nested dir fails");
    TEST_TRUE(batch, Err_get_error() != NULL,
        "MkDir for deeply nested dir sets Err_error");

    TEST_TRUE(batch, Folder_MkDir(folder, &foo_bar), 
        "MkDir for nested dir");
    TEST_TRUE(batch, Folder_Is_Directory(folder, &foo_bar), 
        "Is_Directory() true for nested dir");

    Err_set_error(NULL);
    TEST_FALSE(batch, Folder_MkDir(folder, &foo_bar), 
        "Overwrite dir with MkDir fails");
    TEST_TRUE(batch, Err_get_error() != NULL,
        "Overwrite dir with MkDir sets Err_error");

    fh = Folder_Open_FileHandle(folder, &foo_boffo, 
        FH_CREATE | FH_WRITE_ONLY);
    DECREF(fh);
    Err_set_error(NULL);
    TEST_FALSE(batch, Folder_MkDir(folder, &foo_boffo), 
        "Overwrite file with MkDir fails");
    TEST_TRUE(batch, Err_get_error() != NULL,
        "Overwrite file with MkDir sets Err_error");
    TEST_FALSE(batch, Folder_Is_Directory(folder, &foo_boffo), 
        "Is_Directory() false for nested file");

    DECREF(folder);
}
Ejemplo n.º 24
0
static void
S_verify_bad_syntax(TestBatch *batch, const char *bad, const char *mess) {
    ZombieCharBuf *has_errors = ZCB_WRAP_STR(bad, strlen(bad));
    Err_set_error(NULL);
    Obj *not_json = Json_from_json((CharBuf*)has_errors);
    TEST_TRUE(batch, not_json == NULL, "from_json returns NULL: %s", mess);
    TEST_TRUE(batch, Err_get_error() != NULL, "from_json sets Err_error: %s",
              mess);
}
Ejemplo n.º 25
0
static void
S_verify_bad_syntax(TestBatchRunner *runner, const char *bad, const char *mess) {
    String *has_errors = SSTR_WRAP_C(bad);
    Err_set_error(NULL);
    Obj *not_json = Json_from_json(has_errors);
    TEST_TRUE(runner, not_json == NULL, "from_json returns NULL: %s", mess);
    TEST_TRUE(runner, Err_get_error() != NULL,
              "from_json sets global error: %s", mess);
}
Ejemplo n.º 26
0
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;
}
Ejemplo n.º 27
0
static void
test_Local_MkDir_and_Find_Folder(TestBatchRunner *runner) {
    Folder *real_folder = S_folder_with_contents();
    CompoundFileReader *cf_reader = CFReader_open(real_folder);

    TEST_FALSE(runner,
               CFReader_Local_Is_Directory(cf_reader, stuff),
               "Local_Is_Directory returns false for non-existent entry");

    TEST_TRUE(runner, CFReader_MkDir(cf_reader, stuff),
              "MkDir returns true");
    TEST_TRUE(runner,
              Folder_Find_Folder(real_folder, stuff) != NULL,
              "Local_MkDir pass-through");
    TEST_TRUE(runner,
              Folder_Find_Folder(real_folder, stuff)
              == CFReader_Find_Folder(cf_reader, stuff),
              "Local_Find_Folder pass-through");
    TEST_TRUE(runner,
              CFReader_Local_Is_Directory(cf_reader, stuff),
              "Local_Is_Directory pass through");

    Err_set_error(NULL);
    TEST_FALSE(runner, CFReader_MkDir(cf_reader, stuff),
               "MkDir returns false when dir already exists");
    TEST_TRUE(runner, Err_get_error() != NULL,
              "MkDir sets global error when dir already exists");

    Err_set_error(NULL);
    TEST_FALSE(runner, CFReader_MkDir(cf_reader, foo),
               "MkDir returns false when virtual file exists");
    TEST_TRUE(runner, Err_get_error() != NULL,
              "MkDir sets global error when virtual file exists");

    TEST_TRUE(runner,
              CFReader_Find_Folder(cf_reader, foo) == NULL,
              "Virtual file not reported as directory");
    TEST_FALSE(runner, CFReader_Local_Is_Directory(cf_reader, foo),
               "Local_Is_Directory returns false for virtual file");

    DECREF(real_folder);
    DECREF(cf_reader);
}
Ejemplo n.º 28
0
FSDirHandle*
FSDH_do_open(FSDirHandle *self, const CharBuf *dir) {
    size_t  dir_path_size = CB_Get_Size(dir);
    char   *dir_path_ptr  = (char*)CB_Get_Ptr8(dir);
    char    search_string[MAX_PATH + 1];
    char   *path_ptr = search_string;

    DH_init((DirHandle*)self, dir);
    FSDirHandleIVARS *const ivars = FSDH_IVARS(self);
    ivars->sys_dir_entry    = MALLOCATE(sizeof(WIN32_FIND_DATA));
    ivars->sys_dirhandle    = INVALID_HANDLE_VALUE;
    ivars->saved_error      = NULL;

    if (dir_path_size >= MAX_PATH - 2) {
        // Deal with Windows ceiling on file path lengths.
        Err_set_error(Err_new(CB_newf("Directory path is too long: %o",
                                      dir)));
        CFISH_DECREF(self);
        return NULL;
    }

    // Append trailing wildcard so Windows lists dir contents rather than just
    // the dir name itself.
    memcpy(path_ptr, dir_path_ptr, dir_path_size);
    memcpy(path_ptr + dir_path_size, "\\*\0", 3);

    ivars->sys_dirhandle
        = FindFirstFile(search_string, (WIN32_FIND_DATA*)ivars->sys_dir_entry);
    if (INVALID_HANDLE_VALUE == ivars->sys_dirhandle) {
        // Directory inaccessible or doesn't exist.
        Err_set_error(Err_new(CB_newf("Failed to open dir '%o'", dir)));
        CFISH_DECREF(self);
        return NULL;
    }
    else {
        // Compensate for the fact that FindFirstFile has already returned the
        // first entry but DirHandle's API requires that you call Next() to
        // start the iterator.
        ivars->delayed_iter = true;
    }

    return self;
}
Ejemplo n.º 29
0
static bool
S_hard_link(char *from8, char *to8) {
    if (-1 == link(from8, to8)) {
        Err_set_error(Err_new(Str_newf("hard link for new file '%s' from '%s' failed: %s",
                                       to8, from8, strerror(errno))));
        return false;
    }
    else {
        return true;
    }
}
Ejemplo n.º 30
0
static INLINE bool_t
SI_unmap(FSFileHandle *self, char *buf, int64_t len) {
    if (buf != NULL) {
        if (munmap(buf, len)) {
            Err_set_error(Err_new(CB_newf("Failed to munmap '%o': %s",
                                          self->path, strerror(errno))));
            return false;
        }
    }
    return true;
}