void block_store_link(block_store_t *const bs, const char *const filename) { if (bs && filename) { if (! FLAG_CHECK(bs, FILE_LINKED)) { // Ok, I can make a giant complicated hunk of logic to: // Create if it doesn't exist // Increase size if smaller // Decrease size if larger // and It'll be a giant headache for various reasons (error checking, portability) // OR, I can just do it in two commands and call it a day. bs->fd = open(filename, O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP); if (bs->fd != -1) { if (utility_write_file(bs->fd, bs->data_blocks, BLOCK_COUNT * BLOCK_SIZE) == BLOCK_COUNT * BLOCK_SIZE) { // Kill the DBM and dirty flag, set link state bitmap_format(bs->dbm, 0x00); FLAG_CLEAR(bs, DIRTY); FLAG_SET(bs, FILE_LINKED); bs_errno = BS_OK; return; } bs_errno = BS_FILE_IO; return; } bs_errno = BS_FILE_ACCESS; return; } bs_errno = BS_LINK_EXISTS; return; } bs_errno = BS_PARAM; }
size_t block_store_export(const block_store_t *const bs, const char *const filename) { // Thankfully, this is less of a mess than import... // we're going to ignore dbm, we'll treat export like it's making a new copy of the drive if (filename && bs && bs->fbm && bs->data_blocks) { const int fd = open(filename, O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP); if (fd != -1) { if (utility_write_file(fd, bitmap_export(bs->fbm), FBM_SIZE * BLOCK_SIZE) == (FBM_SIZE * BLOCK_SIZE)) { if (utility_write_file(fd, bs->data_blocks, BLOCK_SIZE * (BLOCK_COUNT - FBM_SIZE)) == (BLOCK_SIZE * (BLOCK_COUNT - FBM_SIZE))) { block_store_errno = BS_OK; close(fd); return BLOCK_SIZE * BLOCK_COUNT; } } block_store_errno = BS_FILE_IO; close(fd); return 0; } block_store_errno = BS_FILE_ACCESS; return 0; } block_store_errno = BS_PARAM; return 0; }
// Block sync function to feed to bitmap_for_each // Jumps the fd to the needed location and writes to it // Admittedly, this function is not pretty. void block_sync(size_t block_id, void *bs_sync_ptr) { bs_sync_obj *bs_sync = (bs_sync_obj *)bs_sync_ptr; /* typedef struct { int disaster_errno; block_store_t *const bs; size_t byte_counter; bs_status status; } bs_sync_obj; */ if (bs_errno == BS_OK) { if (bs_sync && bs_sync->status == BS_OK) { if (bs_sync->bs) { if (FLAG_CHECK(bs_sync->bs, FILE_LINKED)) { // Ducks = in a row // jump to file position if (lseek(bs_sync->bs->fd, BLOCK_POSITION(block_id), SEEK_SET) == BLOCK_POSITION(block_id)) { // attempt to write size_t written = utility_write_file(bs_sync->bs->fd, bs_sync->bs->data_blocks + BLOCK_POSITION(block_id), BLOCK_SIZE); // Update written with WHATEVER happened bs_sync->byte_counter += written; if (written == BLOCK_SIZE) { // all is ok, we wrote everything, or so we were told return; } } bs_sync->status = BS_FILE_IO; // save whatever errno was generated by seek or write bs_sync->disaster_errno = errno; return; } bs_sync->status = BS_NO_LINK; // HOW DID THIS HAPPEN return; } bs_sync->status = BS_PARAM; } bs_errno = BS_PARAM; } return; }