edouard@3940: edouard@3940: #include edouard@3940: #include edouard@3940: edouard@3940: #include "blob.hpp" edouard@3940: #include edouard@3940: edouard@3940: Blob::Blob(uint8_t *seedData, size_t seedLength) edouard@3940: { edouard@3940: // Create a temporary file to store blob data edouard@3940: // not using tmpfile() because we need to know the filename edouard@3940: // for later renaming and avoid deletion on close edouard@3940: edouard@3940: // Assume that a tmp directory exists in the current directory edouard@3940: uint8_t template_name[] = "tmp/blobXXXXXX"; edouard@3940: int fd = mkstemp((char *)template_name); edouard@3940: if (fd == -1) { edouard@3940: throw errno; edouard@3940: } edouard@3940: edouard@3940: // Open file for stdlib I/O edouard@3940: m_file = fdopen(fd, "w+"); edouard@3940: if (m_file == NULL) { edouard@3940: throw errno; edouard@3940: } edouard@3940: edouard@3940: // Save a copy of the filename edouard@3940: m_filename = (char *)template_name; edouard@3940: edouard@3940: // Seed the MD5 hash with the seed data edouard@3940: md5.update(seedData, seedLength); edouard@3940: } edouard@3940: edouard@3940: Blob::~Blob() { edouard@3940: if (m_file != NULL) { edouard@3940: std::fclose(m_file); edouard@3940: std::remove(m_filename.c_str()); edouard@3940: } edouard@3940: } edouard@3940: edouard@3940: MD5::digest_t Blob::digest() { edouard@3940: return md5.digest(); edouard@3940: } edouard@3940: edouard@3940: uint32_t Blob::appendChunk(uint8_t *data, size_t length) { edouard@3940: // Write data to file edouard@3940: if (std::fwrite(data, 1, length, m_file) != length) { edouard@3940: return errno; edouard@3940: } edouard@3940: edouard@3940: // Update MD5 hash edouard@3940: md5.update(data, length); edouard@3940: edouard@3940: return 0; edouard@3940: } edouard@3940: edouard@3940: uint32_t Blob::asFile(std::filesystem::path &filename) edouard@3940: { edouard@3940: // Flush file edouard@3940: if (std::fflush(m_file) != 0) { edouard@3940: return errno; edouard@3940: } edouard@3940: edouard@3940: // Sync file to disk edouard@3940: if (fsync(fileno(m_file)) != 0) { edouard@3940: return errno; edouard@3940: } edouard@3940: edouard@3940: // Close file edouard@3940: if (std::fclose(m_file) != 0) { edouard@3940: return errno; edouard@3940: } edouard@3940: edouard@3940: m_file = NULL; edouard@3940: edouard@3940: // Rename temp file to final file edouard@3940: if (std::rename(m_filename.c_str(), filename.c_str()) != 0) { edouard@3940: return errno; edouard@3940: } edouard@3940: edouard@3940: return 0; edouard@3940: }