void append_data_to_file(int inum, u8 *data, size_t size) { printf("append data file at num %i\n", inum); inode *in = inode_at_num(inum); printf("inode: num: %i, size: %i, blocks: %i, end addr: %i\n", in->num, in->size, in->blocks, in->end_block); block *cur_blk = block_from_num(in->end_block); printf("block addr: %i\n", in->end_block); int pos = in->size % BLOCK_SIZE; int blocks = (pos + size) / BLOCK_SIZE; int numbytes = BLOCK_SIZE - pos; write_data_to_block(cur_blk, data, size, pos); in->size += numbytes; //printf("%i:",pos); for (int i = 0; i < blocks; i++) { alloc_blocks(in, 1); cur_blk = block_from_num(in->end_block); int pos = in->size % BLOCK_SIZE; int numbytes = BLOCK_SIZE - pos; write_data_to_block(cur_blk, data, numbytes, pos); in->size += numbytes; } write_block_to_disk(cur_blk); in->size += size; write_inode_to_disk(in); free(in); free(cur_blk); }
/* * Write a Record to the block * * Returns: false on failure (none or partially written) * true on success (all bytes written) * * and remainder returned in packet. * * We require enough room for the header, and we deal with * two special cases. 1. Only part of the record may have * been transferred the last time (when remainder is * non-zero), and 2. The remaining bytes to write may not * all fit into the block. */ bool write_record_to_block(DCR *dcr, DEV_RECORD *rec) { ssize_t n; bool retval = false; char buf1[100], buf2[100]; DEV_BLOCK *block = dcr->block; /* * After this point the record is in nrec not rec e.g. its either converted * or is just a pointer to the same as the rec pointer being passed in. */ while (1) { ASSERT(block->binbuf == (uint32_t)(block->bufp - block->buf)); ASSERT(block->buf_len >= block->binbuf); Dmsg9(890, "%s() state=%d (%s) FI=%s SessId=%d Strm=%s len=%d " "block_navail=%d remainder=%d\n", __func__, rec->state, record_state_to_ascii(rec->state), FI_to_ascii(buf1, rec->FileIndex), rec->VolSessionId, stream_to_ascii(buf2, rec->Stream, rec->FileIndex), rec->data_len, block_write_navail(block), rec->remainder); switch (rec->state) { case st_none: /* * Figure out what to do */ rec->state = st_header; rec->remainder = rec->data_len; /* length of data remaining to write */ continue; /* goto st_header */ case st_header: /* * Write header */ n = write_header_to_block(block, rec, rec->Stream); if (n < 0) { /* * the header did not fit into the block, so flush the current * block and come back to st_header and try again on the next block. */ goto bail_out; } if (block_write_navail(block) == 0) { /* * The header fit, but no bytes of data will fit, * so flush this block and start the next block with a * continuation header. */ rec->state = st_header_cont; goto bail_out; } /* * The header fit, and at least one byte of data will fit, * so move to the st_data state and start filling the block * with data bytes */ rec->state = st_data; continue; case st_header_cont: /* * Write continuation header */ n = write_header_to_block(block, rec, -rec->Stream); if (n < 0) { /* * The continuation header wouldn't fit, which is impossible * unless something is broken */ Emsg0(M_ABORT, 0, _("couldn't write continuation header\n")); } /* * After successfully writing a continuation header, we always start writing * data, even if none will fit into this block. */ rec->state = st_data; if (block_write_navail(block) == 0) { /* * The header fit, but no bytes of data will fit, * so flush the block and start the next block with * data bytes */ goto bail_out; /* Partial transfer */ } continue; case st_data: /* * Write normal data * * Part of it may have already been transferred, and we * may not have enough room to transfer the whole this time. */ if (rec->remainder > 0) { n = write_data_to_block(block, rec); if (n < 0) { /* * error appending data to block should be impossible * unless something is broken */ Emsg0(M_ABORT, 0, _("data write error\n")); } rec->remainder -= n; if (rec->remainder > 0) { /* * Could not fit all of the data bytes into this block, so * flush the current block, and start the next block with a * continuation header */ rec->state = st_header_cont; goto bail_out; } } rec->remainder = 0; /* did whole transfer */ rec->state = st_none; retval = true; goto bail_out; default: Emsg1(M_ABORT, 0, _("Something went wrong. Unknown state %d.\n"), rec->state); rec->state = st_none; retval = true; goto bail_out; } } bail_out: return retval; }
/* * Write a Record to the block * * Returns: false on failure (none or partially written) * true on success (all bytes written) * * and remainder returned in packet. * * We require enough room for the header, and we deal with * two special cases. 1. Only part of the record may have * been transferred the last time (when remainder is * non-zero), and 2. The remaining bytes to write may not * all fit into the block. */ bool write_record_to_block(DCR *dcr, DEV_RECORD *rec) { bool retval = false; char buf1[100], buf2[100]; DEV_BLOCK *block = dcr->block; /* * After this point the record is in nrec not rec e.g. its either converted * or is just a pointer to the same as the rec pointer being passed in. */ while (1) { ASSERT(block->binbuf == (uint32_t)(block->bufp - block->buf)); ASSERT(block->buf_len >= block->binbuf); Dmsg6(890, "write_record_to_block() FI=%s SessId=%d Strm=%s len=%d\n" "rem=%d remainder=%d\n", FI_to_ascii(buf1, rec->FileIndex), rec->VolSessionId, stream_to_ascii(buf2, rec->Stream, rec->FileIndex), rec->data_len, rec->remlen, rec->remainder); switch (rec->state) { case st_none: /* * Figure out what to do */ rec->state = st_header; continue; /* go to next state */ case st_header: /* * Write header * * If rec->remainder is non-zero, we have been called a * second (or subsequent) time to finish writing a record * that did not previously fit into the block. */ if (!write_header_to_block(block, rec)) { goto bail_out; /* write block then come back here */ } rec->state = st_data; /* after header, now write data */ continue; /* * Write continuation header */ case st_header_cont: write_continue_header_to_block(block, rec); rec->state = st_data; if (rec->remlen == 0) { goto bail_out; /* Partial transfer */ } continue; /* * Write normal data */ case st_data: /* * Write data * * Part of it may have already been transferred, and we * may not have enough room to transfer the whole this time. */ if (rec->remainder > 0) { if (!write_data_to_block(block, rec)) { rec->state = st_header_cont; goto bail_out; } } rec->remainder = 0; /* did whole transfer */ rec->state = st_none; retval = true; goto bail_out; default: Dmsg0(000, "Something went wrong. Default state.\n"); rec->state = st_none; retval = true; goto bail_out; } } bail_out: return retval; }