static direntry_t *direntry_from_listing (CALLER_DECL listing_t *li) { /* TODO: stop being lazy and have listing_init */ direntry_t *de = realloc(li, sizeof(direntry_t)); bzero(de + sizeof(listing_t), sizeof(direntry_t) - sizeof(listing_t)); de->inode = inode_next(); inode_map_add(de); direntry_trace( "[direntry %p inode %lu] new (" CALLER_FORMAT ") ref %u\n", de, de->inode, CALLER_PASS 1 ); return de; }
/* * Read a container with the provided key * Read all files and place them into the provided list * Returns: * >0 Number of read files * -1 File error during reading * -2 Wrong password in input */ int memfile_readfiles(char * filename, char * password, memfile * root) { char * buf ; char * cur ; int fd ; int i ; struct stat fileinfo ; uint8_t nonce[NONCE_SZ]; uint8_t key[KEY_SZ]; uint64_t u1, u2, u3 ; size_t header_sz ; size_t payload_sz ; char fname[MAXNAMESZ]; header_sz = MAGIC_SZ + 2 + NONCE_SZ + CANARI_SZ ; /* Find out file size in bytes */ if (stat(filename, &fileinfo)!=0) { logger("no such file: %s", filename); return 1 ; } if (fileinfo.st_size < header_sz) { logger("not a container: ", filename); return -1 ; } /* Map input file */ if ((fd=open(filename, O_RDONLY))==-1) { logger("cannot open: %s", filename); return -1 ; } buf = (char*)mmap(0, fileinfo.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); close(fd); if (buf==(char*)-1) { logger("cannot map: %s", filename); return -1; } cur = buf ; payload_sz = fileinfo.st_size - header_sz ; /* * A container header is composed of: * A magic number of MAGIC_SZ bytes * A version number on 2 bytes: major.minor * A nonce of size NONCE_SZ bytes * A canari of size CANARI_SZ bytes */ /* Check magic number */ for (i=0 ; i<MAGIC_SZ ; i++) { if (cur[i]!=mefs_magic[i]) { logger("not a container: ", filename); munmap(buf, fileinfo.st_size); return -1 ; } } cur += MAGIC_SZ ; /* Read version number */ if (cur[0]!=mefs_version[0] || cur[1]!=mefs_version[1]) { logger("unsupported version for: ", filename); munmap(buf, fileinfo.st_size); return -1 ; } cur+=2 ; /* Copy nonce for later use */ memcpy(nonce, cur, NONCE_SZ); cur += NONCE_SZ ; /* Derive key from password */ derive_key(password, strlen(password), nonce, NONCE_SZ, key, KEY_SZ, 20000); /* Decrypt everything starting from CANARI, using nonce and key */ stream_cipher(cur, fileinfo.st_size-(MAGIC_SZ+2+NONCE_SZ), 0, key, nonce); /* Test canari has expected pattern: 0xaaaa...aa */ for (i=0 ; i<CANARI_SZ ; i++) { if ((unsigned char)cur[i]!=0xaa) { logger("wrong password for container: %s", filename); munmap(buf, fileinfo.st_size); return -2 ; } } cur+=CANARI_SZ ; /* Read files one by one */ /* * filename is a zero-padded string of size MAXNAMESZ * filesize on a 64 big-endian unsigned int * ctime on a 64-big-endian unsigned int * mtime on a 64-big-endian unsigned int */ i=0 ; while (1) { memcpy(fname, cur, MAXNAMESZ); cur+=MAXNAMESZ; memcpy(&u1, cur, sizeof(uint64_t)); cur+=sizeof(uint64_t); memcpy(&u2, cur, sizeof(uint64_t)); cur+=sizeof(uint64_t); memcpy(&u3, cur, sizeof(uint64_t)); cur+=sizeof(uint64_t); root[i].name = strdup(fname); root[i].sta.st_ino = inode_next(); root[i].sta.st_size = u1 ; root[i].sta.st_ctime = u2 ; root[i].sta.st_mtime = u3 ; root[i].data = malloc(u1); memcpy(root[i].data, cur, u1); cur+=u1 ; if ((cur-buf) >= fileinfo.st_size) break ; i++ ; } munmap(buf, fileinfo.st_size); return 0 ; }