I'm trying to use libzip in a program that needs to archive several data chunks in different files. At the moment I have a code similar to the following snippet, edited from in-memory.c example in libzip examples.
The zip file is correctly saved with the files inside, but each file contains garbage. Any help is appreciated.
bool push_files(zip_t* za) {
for (int i = 0; i < 10; i++) {
// Generate data
std::stringstream ss;
ss << "Test file #" << i;
std::string a = ss.str();
zip_source_t* source = zip_source_buffer(za, a.c_str(), a.size(), 0);
if (source == NULL) {
std::cerr << "error creating source: " << zip_strerror(za) << std::endl;
return false;
}
// Add buffer with filename
std::stringstream fname;
fname << "TEST-" << i;
a = fname.str();
if (zip_file_add(za, a.c_str(), source, ZIP_FL_ENC_UTF_8) < 0) {
std::cerr << "error adding source: " << zip_strerror(za) << std::endl;
return false;
}
}
return true;
}
int main() {
zip_source_t* src;
zip_error_t error;
zip_t* za;
zip_error_init(&error);
if ((src = zip_source_buffer_create(NULL, 0, 1, &error)) == NULL) {
std::cerr << "can't create source: " << zip_error_strerror(&error) << std::endl;
zip_error_fini(&error);
return 1;
}
if ((za = zip_open_from_source(src, ZIP_TRUNCATE, &error)) == NULL) {
std::cerr << "can't open zip from source: " << zip_error_strerror(&error) << std::endl;
zip_source_free(src);
zip_error_fini(&error);
return 1;
}
zip_error_fini(&error);
zip_source_keep(src);
if (!push_files(za))
return -1;
if (zip_close(za) < 0) {
std::cerr << "can't close zip archive" << zip_strerror(za) << std::endl;
return 1;
}
// ... omissis, save archive to file as in in-memory.c
}
zip_source_bufferdoes not copy the data out of the buffer - it just creates azip_source_twhich points to the same buffer. So you must keep the buffer alive until you're done adding the file.Your code does not keep the buffer alive. The buffer you use is
a.c_str()which is the data buffer of the stringa. Fair enough, so far. But then before adding the file, you reassign the variablea = fname.str();which (probably) frees that buffer and allocates a new one.Solution: use a separate variable for the filename. Don't overwrite
auntil the file has been added.