1 #include <stdio.h> 2 #include <string.h> 3 #include <sys/types.h> 4 #include <sys/stat.h> 5 6 #include <algorithm> 7 8 #include "block_file_accessor.h" 9 10 11 12 BlockFileAccessor::BlockFileAccessor(const char *path, fileid_t fileid) 13 : Accessor(fileid) 14 { 15 /* Obtain the size of the file. */ 16 17 struct stat buf; 18 19 if (stat(path, &buf)) 20 { 21 _size = 0; 22 return; 23 } 24 25 /* Allocate memory. */ 26 27 _size = buf.st_size; 28 _data = (char *) malloc(_size); 29 30 if (_data == NULL) 31 return; 32 33 /* Load the file into memory and initialise the size. */ 34 35 FILE *fp = fopen(path, "r"); 36 37 if (fp == NULL) 38 { 39 free(_data); 40 return; 41 } 42 43 _size = fread(_data, sizeof(char), _size, fp); 44 45 fclose(fp); 46 } 47 48 /* Update the size of the file. */ 49 50 void BlockFileAccessor::set_size(offset_t size) 51 { 52 void *new_data = realloc(_data, size); 53 54 if (new_data != NULL) 55 { 56 _data = (char *) new_data; 57 58 if (size > _size) 59 memset(_data + _size, 0, size - _size); 60 61 Accessor::set_size(size); 62 } 63 } 64 65 /* Data transfer methods. */ 66 67 void BlockFileAccessor::fill(Flexpage *flexpage) 68 { 69 offset_t filepos = flexpage->base_offset; 70 offset_t addr = flexpage->base_addr; 71 offset_t populated_size; 72 73 /* Filling completely beyond the end of file should produce an empty 74 flexpage. This could potentially be a shared read-only flexpage that 75 would be replaced by an independent writable flexpage if ever written. */ 76 77 if (filepos > _size) 78 { 79 memset((void *) addr, 0, flexpage->size); 80 return; 81 } 82 83 /* Otherwise, fill the populated portion of a flexpage. */ 84 85 populated_size = std::min(flexpage->size, _size - filepos); 86 87 /* Tag the region with file state. */ 88 89 flexpage->region->fill(fileid, filepos); 90 91 /* Fill the region with file content. */ 92 93 memcpy((void *) addr, _data + filepos, populated_size); 94 95 /* Pad the flexpage with zero. */ 96 97 if (populated_size < flexpage->size) 98 memset((void *) (addr + populated_size), 0, flexpage->size - populated_size); 99 } 100 101 void BlockFileAccessor::flush(Flexpage *flexpage) 102 { 103 offset_t addr = flexpage->base_addr; 104 offset_t filepos = flexpage->base_offset; 105 offset_t populated_size; 106 107 /* Flushing completely beyond the end of file should discard the 108 flexpage. */ 109 110 if (filepos > _size) 111 return; 112 113 /* Otherwise, only the populated portion of a flexpage should be flushed. */ 114 115 populated_size = std::min(flexpage->size, _size - filepos); 116 117 /* Remove the file state tag from the region. */ 118 119 flexpage->region->flush(); 120 121 /* Copy the populated region to the block memory. */ 122 123 memcpy((void *) (_data + filepos), (const void *) addr, populated_size); 124 } 125 126 // vim: tabstop=4 expandtab shiftwidth=4