PinkTurtle
PinkTurtle

Reputation: 7041

How to write archive to disk that was created in memory?

I have a zip archive encrypted on disk. I read the file into a buffer, decrypt it (using some custom algorythm), and make a zip out of it in memory.

Now I can modify the archive but how do I write back the changes to disk ? Am I missing something ? The archive is created with zip_source_buffer_create(...) and when calling zip_close(...) the changes are made to memory.

mcve:

#include <zip.h>
#include <fstream>
#include <filesystem>
#include <vector>
#include <string>

int main(int argc, char** argv) {

    std::string zip_file = "test.zip";
    size_t file_sz = std::filesystem::file_size("test.zip");
    std::vector<char> buf(file_sz);
    std::ifstream ifs{ zip_file, std::ios::binary };
    ifs.read(buf.data(), file_sz);

    /*
        buffer is decrypted here
    */

    zip_error_t ze;
    zip_error_init(&ze);
    zip_source_t* zip_source = zip_source_buffer_create(buf.data(), buf.size(), 1, &ze);
    zip_t* zip = zip_open_from_source(zip_source, NULL, &ze);

    zip_source_t* file_source = zip_source_buffer(zip, "hello", 6, 0);
    zip_file_add(zip, "hello.txt", file_source, ZIP_FL_ENC_GUESS);
    zip_source_free(file_source);

    zip_error_fini(&ze);
    zip_close(zip); //modifications are written to memory but how do I retrieve the data?

    /*
        zip data should be acquired here, encrypted, and written to disk
    */

    return 0;
}

Upvotes: 0

Views: 851

Answers (2)

Remy Lebeau
Remy Lebeau

Reputation: 595837

zip_close() writes the new data to the original zip_source_t that the zip was opened from, which in your case is your zip_source variable that wraps a vector buffer.

When zip_close() commits to your zip_source, the input buffer that zip_source is pointing at (the vector buffer) will get replaced with a new data buffer allocated by libzip. So, you should be able to call zip_source_keep(zip_source) to ensure zip_close() doesn't free zip_source from memory, then you can use zip_source_open(zip_source) and zip_source_read(zip_source) to read from zip_source's new data buffer as needed, and then you can call zip_source_close(zip_source) and zip_source_free(zip_source) when done.

Do whatever you want with the data you read from zip_source, and then save it to a disk file of your choosing.

There is an example of this process provided in libzip's repo:

https://github.com/nih-at/libzip/blob/master/examples/in-memory.c

Upvotes: 2

PinkTurtle
PinkTurtle

Reputation: 7041

I have found the solution there, in the libzip distro. File examples/in-memory.c. There is quite a few lines of code involved so I won't post it here.

It involves zip_source_keep to keep the source alive after closing the archive in memory, zip_stat to know the read buffer size and zip_source_open / zip_source_read to read the source' contents.

Upvotes: 0

Related Questions