Distributed File System written in C
at main 346 lines 7.3 kB view raw
1#include "lib.h" 2#include "log.h" 3#include <stdlib.h> 4#include <string.h> 5#include <sys/stat.h> 6 7ImplList(Buffer) 8 9Buffer ListBuffer_serialize(ListBuffer list) { 10 Buffer out = {0}; 11 for (ListBuffer lptr = list; lptr != NULL; lptr = lptr->rest) { 12 Buffer buf = lptr->head; 13 out = concat(out, Buffer_serialize(buf)); 14 } 15 return out; 16} 17 18ListBuffer ListBuffer_deserialize(Buffer buf) { 19 ListBuffer out = NULL; 20 for (size_t len = 0; len < buf.len;) { 21 Buffer mbuf = Buffer_deserialize((Buffer) { 22 .buf = buf.len + (Byte*)len, 23 .len = 0, 24 }); 25 len += mbuf.len + sizeof(size_t); 26 out = ListBuffer_cons(mbuf, out); 27 } 28 29 return out; 30} 31 32bool mkdir_p(SafeStr fpath, mode_t mode) { 33 char* tmp = calloc(fpath.len + 1, sizeof(char)); 34 size_t len = 0; 35 for (size_t i = 0; i < fpath.len; ++i) { 36 char c = fpath.str[i]; 37 if (c == '/') { 38 if (len != 0) { 39 if (mkdir(tmp, mode) != 0) { 40 if (errno != EEXIST) 41 try(-1); 42 } 43 } 44 } 45 tmp[len++] = c; 46 } 47 // INFO: This needs to get done one more time in case there isn't a '/' at 48 // the end of the fpath 49 if (mkdir(tmp, mode) != 0) { 50 if (errno != EEXIST) 51 try(-1); 52 } 53 return true; 54} 55 56void Buffer_deinit(Buffer kod) { 57 free(kod.buf); 58} 59 60void Buffer_write(Buffer buf, FILE* f) { 61 exists(f); 62 fwrite(buf.buf, sizeof(Byte), buf.len, f); 63} 64 65Buffer Buffer_read(FILE* f) { 66 exists(f); 67 fseek(f, 0, SEEK_END); 68 size_t len = (size_t)ftell(f); 69 fseek(f, 0, SEEK_SET); 70 Buffer buf = { 71 .buf = calloc(len, sizeof(Byte)), 72 .len = len, 73 }; 74 exists(buf.buf); 75 76 size_t count = fread(buf.buf, sizeof(Byte), len, f); 77 78 if (count != len) { 79 log(FATAL, "Error reading file\n"); 80 exit(EXIT_FAILURE); 81 } 82 83 return buf; 84} 85 86Byte* copy(Byte* src, size_t nbytes) { 87 exists(src); 88 Byte* out = (Byte*)malloc(nbytes * sizeof(Byte)); 89 exists(out); 90 memcpy(out, src, nbytes); 91 return out; 92} 93 94/// Allocates new memory from src and returns a buffer to that memory. The user 95/// must free that memory. 96Buffer bufcpy(Buffer src) { 97 Byte* buf = (Byte*)malloc(src.len * sizeof(Byte)); 98 exists(buf); 99 memcpy(buf, src.buf, src.len); 100 return (Buffer){ 101 .buf = buf, 102 .len = src.len, 103 }; 104} 105 106/// Checks whether the buffer contains a valid string and that the size provided 107/// matches the size of that string. 108Buffer validate_str(Buffer str, size_t max_len) { 109 size_t calculated_len = safe_strlen((const char*)str.buf, max_len); 110 if (str.len != calculated_len) { 111 log(ERROR, "%s:%d String's length (%zu) is not equal to given length (%zu).", __FILE__, __LINE__, calculated_len, str.len); 112 113 printf("\nBuffer contains: "); 114 for (size_t i = 0; i < max_len; ++i) printf("[%d] ", str.buf[i]); 115 printf("\n"); 116 117 exit(1); 118 } 119 if (str.len > max_len) { 120 log(ERROR, "%s:%d String's length (%zu) is larger than the buffer that contains it (%zu)\n", str.len, calculated_len); 121 122 printf("\nBuffer contains: "); 123 for (size_t i = 0; i < max_len; ++i) printf("[%d] ", str.buf[i]); 124 printf("\n"); 125 126 exit(1); 127 } 128 return str; 129} 130 131// uses memchr to calculate strlen. 132size_t safe_strlen(Str str, size_t max_len) { 133 char* last = memchr(str, '\0', max_len); 134 return last != NULL ? (size_t)last - (size_t)str : max_len; 135} 136 137// Esta funcion convierte un string a un buffer. 138Buffer atob(const char* str) { 139 return (Buffer){ 140 .buf = (Byte*)str, 141 .len = strlen(str), 142 }; 143} 144 145Buffer SafeStr_serialize(SafeStr str) { 146 return concat(size_t_serialize(str.len), to_buffer(str.str, str.len)); 147} 148 149SafeStr SafeStr_deserialize(Buffer buf) { 150 size_t len = size_t_deserialize((Buffer) { 151 .buf = buf.buf, 152 .len = sizeof(size_t) 153 }); 154 Str str = calloc(len + 1, sizeof(char)); 155 156 memcpy((void*)str, (void*)(buf.buf + sizeof(size_t)), len); 157 158 return (SafeStr){ 159 .str = str, 160 .len = len, 161 }; 162} 163 164Buffer size_t_serialize(size_t a) { 165 Buffer out = { 166 .len = sizeof(size_t), 167 .buf = (Byte*)calloc(1, sizeof(size_t)), 168 }; 169 170 memcpy(out.buf, &a, sizeof(size_t)); 171 172 return out; 173} 174 175size_t size_t_deserialize(Buffer buf) { 176 size_t out = 0; 177 178 if (buf.len != sizeof(size_t)) { 179 log(FATAL, "size_t has incorrect size\n"); 180 exit(EXIT_FAILURE); 181 } 182 183 memcpy(&out, buf.buf, sizeof(size_t)); 184 185 return out; 186} 187 188Buffer concat(Buffer l, Buffer r) { 189 // INFO: Notice that whenever either is null, the other is returned. 190 if (l.buf == NULL) { 191 return r; 192 } else if (r.buf == NULL) { 193 return l; 194 } 195 Buffer out = { 196 .len = l.len + r.len, 197 .buf = (Byte*)calloc(l.len + r.len, sizeof(Byte)), 198 }; 199 exists(out.buf); 200 201 memcpy(out.buf, l.buf, l.len); 202 memcpy(out.buf + l.len, r.buf, r.len); 203 free(l.buf); 204 free(r.buf); 205 206 return out; 207} 208 209bool Str_eq(Str l, Str r) { 210 return strcmp(l, r) == 0; 211} 212 213Buffer Buffer_serialize(Buffer buf) { 214 Buffer size = size_t_serialize(buf.len); 215 exists(size.buf); 216 return concat(size, buf); 217} 218 219Buffer Buffer_deserialize(Buffer buf) { 220 size_t size = size_t_deserialize((Buffer){ .buf = buf.buf, .len = sizeof(size_t) }); 221 222 if (buf.len < size + sizeof(size_t)) { 223 log(FATAL, "Error deserializing buffer. Incorrect size. Got: %zu. Expected greater than: %zu\n", buf.len, size + sizeof(size_t)); 224 exit(EXIT_FAILURE); 225 } 226 227 Buffer out = { 228 .buf = (Byte*)calloc(size, sizeof(Byte)), 229 .len = size, 230 }; 231 exists(out.buf); 232 233 memcpy(out.buf, buf.buf + sizeof(size_t), size); 234 return out; 235} 236 237Buffer to_buffer(const void* thing, size_t nbytes) { 238 Buffer out = { 239 .buf = (Byte*)calloc(1, nbytes), 240 .len = nbytes, 241 }; 242 exists(out.buf); 243 244 memcpy(out.buf, thing, nbytes); 245 return out; 246} 247 248 249Buffer uint8_t_serialize(uint8_t n) { 250 return to_buffer(&n, sizeof(uint8_t)); 251} 252 253uint8_t uint8_t_deserialize(Buffer buf) { 254 exists(buf.buf); 255 256 if (buf.len != sizeof(uint8_t)) { 257 log(FATAL, "Could not deserialize uint8_t. Buffer length incorrect: %zu\n", buf.len); 258 exit(EXIT_FAILURE); 259 } 260 261 uint8_t x; 262 memcpy(&x, buf.buf, sizeof x); 263 return x; 264} 265 266 267Buffer uint16_t_serialize(uint16_t n) { 268 return to_buffer(&n, sizeof(uint16_t)); 269} 270 271uint16_t uint16_t_deserialize(Buffer buf) { 272 exists(buf.buf); 273 274 if (buf.len != sizeof(uint16_t)) { 275 log(FATAL, "Could not deserialize uint16_t. Buffer length incorrect: %zu\n", buf.len); 276 exit(EXIT_FAILURE); 277 } 278 279 uint16_t x; 280 memcpy(&x, buf.buf, sizeof x); 281 return x; 282} 283 284Buffer uint32_t_serialize(uint32_t n) { 285 return to_buffer(&n, sizeof(uint32_t)); 286} 287 288uint32_t uint32_t_deserialize(Buffer buf) { 289 exists(buf.buf); 290 291 if (buf.len != sizeof(uint32_t)) { 292 log(FATAL, "Could not deserialize uint32_t. Buffer length incorrect: %zu\n", buf.len); 293 exit(EXIT_FAILURE); 294 } 295 296 uint32_t x; 297 memcpy(&x, buf.buf, sizeof x); 298 return x; 299} 300 301SafeStr atoss(Str str) { 302 return (SafeStr) { 303 .str = str, 304 .len = strlen(str), 305 }; 306} 307 308size_t min(size_t l, size_t r) { 309 return l < r ? l : r; 310} 311 312 313LazyBuffer open(Str fpath) { 314 FILE* f = fopen(fpath, "r"); 315 exists(f); 316 fseek(f, 0, SEEK_END); 317 size_t size = (size_t)ftell(f); 318 fseek(f, 0, SEEK_SET); 319 return (LazyBuffer){ 320 .fptr = f, 321 .buf = {0}, 322 .len = 0, 323 .position = 0, 324 .size = size, 325 }; 326} 327 328LazyBuffer next_chunk(LazyBuffer b) { 329 exists(b.fptr); 330 331 size_t read_len = min(b.size - b.position, CHUNK_SIZE); 332 if (read_len == 0) { 333 b.len = 0; 334 return b; 335 } 336 size_t count = fread(b.buf, sizeof(Byte), read_len, b.fptr); 337 338 if (count != read_len) { 339 log(FATAL, "Error reading file. Expected to read %zu bytes, got %zu\n", read_len, count); 340 exit(EXIT_FAILURE); 341 } 342 343 b.position += read_len; 344 b.len = read_len; 345 return b; 346}