I have a .zip file to unzip which contain multiple sub-folders. I am using zlib.h library function to unzip the .zip file.
#include<stdio.h>
#include<zlib.h>
#define MAX_MOI_PATH 200
#define READ_BLOCK_SIZE 1024*16
BOOL DCompressFile(char *SourceFILENAME, char *DestinationFILENAME)
{
char buffer[READ_BLOCK_SIZE];
unsigned long dwBytesRead;
unsigned long numberOfBytesWritten;
Bool status = false;
char cFilename[MAX_MOI_PATH];
int pathIndex=0;
char FileMode[4] = "w";
gzFile * FileFd = (gzFile *)gzopen (SourceFILENAME, "rb");
if (FileFd)
{
FILE* handle = fopen(DestinationFILENAME, "wb");
if(handle != NULL)
{
status = true;
while (status)
{
dwBytesRead = gzread(FileFd, buffer, READ_BLOCK_SIZE-1);
buffer[dwBytesRead] = '\0';
if (dwBytesRead)
{
status = fwrite(buffer, 1 , sizeof(buffer) , handle );
if(!status)
status = false;
else if (dwBytesRead < READ_BLOCK_SIZE)
{
break;
status = false;
}
}
}
fclose(handle);
}
gzclose (FileFd);
}
return status;
}
int main()
{
DCompressFile("/home/vivek/zlib_test/1.zip","/home/vivek/zlib_test/1");
return 0;
}
problem with this source code is, it is creating again a zip file "1.zip" with same content, not decompressing the .zip file to folder.
please help what going wrong with this?
gzip is not zip. zip is not gzip. Completely different things. You need to find a library or class that handles zip files. zlib doesn't do this by itself.
I complete this task using libarchive
static int
copy_data(struct archive *ar, struct archive *aw)
{
int r;
const void *buff;
size_t size;
#if ARCHIVE_VERSION_NUMBER >= 3000000
int64_t offset;
#else
off_t offset;
#endif
for (;;) {
r = archive_read_data_block(ar, &buff, &size, &offset);
if (r == ARCHIVE_EOF)
return (ARCHIVE_OK);
if (r != ARCHIVE_OK)
return (r);
r = archive_write_data_block(aw, buff, size, offset);
if (r != ARCHIVE_OK) {
return (r);
}
}
}
static int
extract(const char *filename)
{
struct archive *a;
struct archive *ext;
struct archive_entry *entry;
int flags;
int r;
//Select which attributes we want to restore.
flags = ARCHIVE_EXTRACT_TIME;
flags |= ARCHIVE_EXTRACT_PERM;
flags |= ARCHIVE_EXTRACT_ACL;
flags |= ARCHIVE_EXTRACT_FFLAGS;
a = archive_read_new();
archive_read_support_filter_all(a);
archive_read_support_format_all(a);
ext = archive_write_disk_new();
archive_write_disk_set_options(ext, flags);
archive_write_disk_set_standard_lookup(ext);
if ((r = archive_read_open_filename(a, filename, 16384)))
{
printf("File name %s\n",filename);
return 1;
}
for (;;) {
r = archive_read_next_header(a, &entry);
printf("%s \n",archive_entry_pathname(entry));
if (r == ARCHIVE_EOF)
break;
if (r < ARCHIVE_OK)
{
fprintf(stderr, "%s\n", archive_error_string(a));
printf("Error1 : %s\n",archive_error_string(a));
if (r < ARCHIVE_WARN)
return 1;
}
r = archive_write_header(ext, entry);
if (r < ARCHIVE_OK){
fprintf(stderr, "%s\n", archive_error_string(ext));
printf("Error2 : %s\n",archive_error_string(ext));
}
else if (archive_entry_size(entry) > 0) {
r = copy_data(a, ext);
if (r < ARCHIVE_OK){
fprintf(stderr, "%s\n", archive_error_string(ext));
printf("Error3 : %s\n",archive_error_string(ext));
}
if (r < ARCHIVE_WARN)
return 1;
}
r = archive_write_finish_entry(ext);
if (r < ARCHIVE_OK){
fprintf(stderr, "%s\n", archive_error_string(ext));
printf("Error4 : %s\n",archive_error_string(ext));
}
if (r < ARCHIVE_WARN)
return 1;
}
archive_read_close(a);
archive_read_free(a);
archive_write_close(ext);
archive_write_free(ext);
return 0;
}
int main()
{
extract("/home/sanjay/zlib_test/FileDownload.zip");
return 0;
}
Related
I'm using ffmpeg to write an h264 stream to a mp4 file.
Everything is working, but now I need to embed to this file the actual timestamp in milliseconds of each frame.
Is it possible?
This is my code:
void mp4_file_create(mp4_par * par, t_image * img_in)
{
AVCodec * codec = NULL;
AVCodecContext * cc_in;
AVFormatContext * av_fmt_ctx_out;
AVStream * av_stream;
AVPacket av_pkt;
AVFormatContext * ifmt_ctx;
unsigned long long last_frame_ts_utc;
unsigned long long last_frame_ts_absolute;
unsigned long long last_pts;
t_mp4_dict_metadata metadata;
char file_name[1024];
char TSstrdate[128];
av_register_all();
cc_in = NULL;
av_stream = NULL;
if (avformat_alloc_output_context2(&mp4h->av_fmt_ctx_out, NULL, NULL, file_name) < 0) {
trace_error("avformat_alloc_output_context2 failed");
goto FnExit;
}
/* find the H264 RAW encoder */
codec = avcodec_find_encoder(AV_CODEC_ID_H264);
if (!codec) {
int ret;
AVStream *in_stream = NULL;
if (av_fmt_ctx_in == NULL)
{
trace_error("av_fmt_ctx_in is NULL");
goto FnExit;
}
in_stream = av_fmt_ctx_in->streams[0];
in_stream->codec->width = par.width;
in_stream->codec->height = par.height;
in_stream->codec->coded_width = par.width;
in_stream->codec->coded_height = par.height;
in_stream->codec->bit_rate = 1024;
in_stream->codec->flags = CODEC_FLAG_GLOBAL_HEADER;
in_stream->codec->time_base.num = 1;
in_stream->codec->time_base.den = par.frame_rate;
in_stream->codec->gop_size = par.gop;
in_stream->codec->pix_fmt = AV_PIX_FMT_YUV420P;
av_stream = avformat_new_stream(mp4h->av_fmt_ctx_out, in_stream->codec->codec);
if (!av_stream) {
trace_error("Failed allocating output stream");
goto FnExit;
}
ret = avcodec_copy_context(av_stream->codec, in_stream->codec);
if (ret != 0) {
goto FnExit;
}
}
else {
int ret;
av_stream = avformat_new_stream(mp4h->av_fmt_ctx_out, NULL);
if (!av_stream) {
goto FnExit;
}
cc_in = avcodec_alloc_context3(codec);
if (cc_in == NULL) {
goto FnExit;
}
cc_in->width = par.width;
cc_in->height = par.height;
cc_in->bit_rate = 1024;
cc_in->flags = CODEC_FLAG_GLOBAL_HEADER;
cc_in->time_base.num = 1;
cc_in->time_base.den = par.frame_rate;
cc_in->gop_size = par.gop;
cc_in->pix_fmt = AV_PIX_FMT_YUVJ420P;
cc_in->extradata = (unsigned char*)av_mallocz(sizeof(sample_spspps));
cc_in->extradata_size = sizeof(sample_spspps);
memcpy(cc_in->extradata, sample_spspps, cc_in->extradata_size);
ret = avcodec_copy_context(av_stream->codec, cc_in);
if (ret != 0) {
goto FnExit;
}
}
av_stream->codec->codec_tag = 0;
if (av_fmt_ctx_out->oformat->flags & AVFMT_GLOBALHEADER)
av_stream->codec->flags |= CODEC_FLAG_GLOBAL_HEADER;
if (!(av_fmt_ctx_out->flags & AVFMT_NOFILE)) {
int ret = avio_open(&av_fmt_ctx_out->pb, file_name, AVIO_FLAG_READ_WRITE);
if (ret < 0) {
trace_error("Could not open output file '%s'", file_name);
goto FnExit;
}
}
av_fmt_ctx_out->streams[0]->time_base.num = 1;
av_fmt_ctx_out->streams[0]->time_base.den = par.frame_rate;
av_fmt_ctx_out->streams[0]->codec->time_base.num = 1;
av_fmt_ctx_out->streams[0]->codec->time_base.den = par.frame_rate;
AVRational fps;
fps.num = 1;
fps.den = par.frame_rate;
av_stream_set_r_frame_rate(av_fmt_ctx_out->streams[0], fps);
mp4h->av_fmt_ctx_out->streams[0]->first_dts = AV_TIME_BASE;
av_dict_set(&pMetaData, "title", par.guid_video_function, 0);
av_dict_set(&pMetaData, "artist", "Test Artist", 0);
av_dict_set(&pMetaData, "date", TSstrdate, 0);
av_fmt_ctx_out->metadata = pMetaData;
if (avformat_write_header(av_fmt_ctx_out, NULL) < 0) {
goto FnExit;
}
//............. Now for each frame_rate........
av_init_packet(&av_pkt);
if (first_frame)
{
av_pkt.pts = 0;
av_pkt.dts = 0;
}
else
{
av_pkt.pts = last_pts + (long long int)((img->timestamp_absolute - last_frame_ts_absolute) * (unsigned long long)av_stream->time_base.den / 1000000ULL);
av_pkt.dts = last_pts + (long long int)((img->timestamp_absolute - last_frame_ts_absolute) * (unsigned long long)av_stream->time_base.den / 1000000ULL);
}
mp4h->av_pkt.duration = 0;
mp4h->av_pkt.pos = -1;
last_frame_ts_utc = img->timestamp_utc.t;
last_frame_ts_absolute = img->timestamp_absolute.t;
last_pts = av_pkt.pts;
if (img->type == keyframe)
{
av_pkt.flags |= AV_PKT_FLAG_KEY;
}
av_pkt.data = img->ptr;
av_pkt.size = img->size;
av_pkt.stream_index = av_stream->index;
ret = av_interleaved_write_frame(av_fmt_ctx_out, &av_pkt);
if (ret != 0) {
char strE[256];
av_strerror(ret, strE, sizeof(strE));
trace_error("av_write_frame returns %d - %s", ret, strE);
return;
}
//........then I will close the file
FnExit:
if (av_fmt_ctx_out && av_fmt_ctx_out->pb != NULL) {
if (av_write_trailer(mp4h->av_fmt_ctx_out) != 0) {
trace_error("av_write_trailer Error!");
}
}
if (ifmt_ctx)
avformat_close_input(&ifmt_ctx);
avio_closep(&av_fmt_ctx_out->pb);
avcodec_close(av_stream->codec);
avformat_free_context(av_fmt_ctx_out);
}
How can I modify it in order to embed the actual timestamp of each frame?
I tried to add the actual timestamp to the first frame pts instead of setting it to zero, but it didn't work.
I can't get the message verified after signing it.
I'm writing a project to simulate signing and verifying data from files with OpenSSL.
the signing process seems to work great, but on the verification process RSA_Verify always return 0. which is not verified.
I can't get it. what am I missing here?
#include <string>
#include <fstream>
#include <openssl/rsa.h>
#include <openssl/pem.h>
#include <openssl/applink.c>
#include <openssl/err.h>
#define PRIKEY_FILENAME "private"
#define PUBKEY_FILENAME "public"
using namespace std;
typedef struct _INFO
{
unsigned char *sig;
unsigned int nLen;
}INFO, *pINFO;
bool ReadFileContent(string fileName, char** out, size_t &nLen)
{
if (NULL == out)
return false;
ifstream file(fileName, ios::in | ios::binary | ios::ate);
if (file.is_open())
{
nLen = (int)file.tellg();
*out = new char[nLen];
file.seekg(0, ios::beg);
file.read(*out, nLen);
file.close();
}
else
{
cout << "Unable to open file \"" << fileName << " \"\n";
return false;
}
return true;
}
bool WriteFileContent(const char* data, int nLen, string fileName)
{
if (NULL == data)
return false;
ofstream file(fileName, ios::out | ios::binary | ios::ate);
if (file.is_open())
{
file.write(data, nLen);
file.close();
}
else
{
cout << "Unable to open file \"" << fileName << " \"\n";
return false;
}
return true;
}
bool GenerateKeyPairs()
{
int ret = 0;
RSA *r = NULL;
BIGNUM *bne = NULL;
BIO *bp_public = NULL, *bp_private = NULL;
int bits = 2048;
unsigned long e = RSA_F4;
// 1. generate rsa key
bne = BN_new();
ret = BN_set_word(bne, e);
if (ret != 1)
{
goto free_all;
}
r = RSA_new();
ret = RSA_generate_key_ex(r, bits, bne, NULL);
if (ret != 1)
{
goto free_all;
}
// 2. save public key
bp_public = BIO_new_file(PUBKEY_FILENAME, "w+");
ret = PEM_write_bio_RSAPublicKey(bp_public, r);
if (ret != 1)
{
goto free_all;
}
// 3. save private key
bp_private = BIO_new_file(PRIKEY_FILENAME, "w+");
ret = PEM_write_bio_RSAPrivateKey(bp_private, r, NULL, NULL, 0, NULL, NULL);
// 4. free
free_all:
BIO_free_all(bp_public);
BIO_free_all(bp_private);
RSA_free(r);
BN_free(bne);
return (ret == 1);
}
bool DoSign(string priKeyFile, pINFO pInfo, string fileName)
{
int ret;
unsigned char* data = NULL;
unsigned char* encodedData = NULL;
size_t nFileSize = 0;
unsigned int nEncodedDataLen = 0;
RSA* priKey = NULL;
FILE* fp = NULL;
if (!ReadFileContent(fileName, (char**)&data, nFileSize))
{
return false;
}
if (data == NULL || nFileSize <= 0)
return false;
//SHA512(data, nFileSize, pInfo->sig);
fp = fopen(PRIKEY_FILENAME, "r");
priKey = PEM_read_RSAPrivateKey(fp, &priKey, NULL, NULL);
pInfo->sig = (unsigned char*)malloc(RSA_size(priKey));
/* Sign */
ret = RSA_sign(NID_sha512, data, nFileSize, pInfo->sig, &pInfo->nLen, priKey);
WriteFileContent((char*)pInfo->sig, pInfo->nLen, fileName + ".sign");
return true;
}
bool DoVerify(string pubKeyFile, pINFO pInfo, string fileName)
{
int ret = 0;
unsigned char* data = NULL;
unsigned char* encodedData = NULL;
size_t nFileSize = 0;
FILE* fp = NULL;
RSA* pubkey = NULL;
unsigned int nEncodedDataLen = 0;
if (!ReadFileContent(fileName, (char**)&data, nFileSize))
{
return false;
}
if (data == NULL || nFileSize <= 0)
return false;
fp = fopen(PUBKEY_FILENAME, "r");
pubkey = PEM_read_RSAPublicKey(fp, NULL, NULL, NULL);
ret = RSA_verify(NID_sha512, data, nFileSize, pInfo->sig, pInfo->nLen, pubkey);
char buf[512];
ERR_error_string(ERR_get_error(), buf);
//Error here says bad signature
return true;
}
int main()
{
INFO info = { 0 };
GenerateKeyPairs();
DoSign(PRIKEY_FILENAME, &info, "Hello.txt");
DoVerify(PUBKEY_FILENAME, &info, "Hello.txt.sign");
return 0;
}
It should return 1 in RSA_Sign.
DoVerify(PUBKEY_FILENAME, &info, "Hello.txt.sign");
This should be:
DoVerify(PUBKEY_FILENAME, &info, "Hello.txt");
The signature itself is being passed through the &info parameter. The last parameter is supposed to be the actual thing signed, not the signature.
I use FFMPEG to record video from a RTSP stream. What my code does is get current day time, create a folder with this format year/month/day/hour/minute and save the video to that folder.
When a new minute arrive, I create the new folder base on the new minute and run the record again to the new folder.
Basically It works, but the next video start time is continue the end of previous video. For example:
video1: 00:00 -> 00:55
video2: 00:56 -> ...
I hope I can set for all videos start from 00:00. Can I do that?
Here my code
ffmpeg.h
class CtFfmpeg {
public:
CtFfmpeg();
~CtFfmpeg();
void init();
int getInput();
int getOutputName(const char *filename);
int release();
int ret;
AVFormatContext *ifmt_ctx, *ofmt_ctx;
AVStream *in_stream, *out_stream;
AVPacket pkt;
const char *in_filename;
char *out_filename;
private:
int setOutput(const char *outfilename);
AVOutputFormat *ofmt;
};
ffmpeg.cpp
#include "ctffmpeg.h"
CtFfmpeg::CtFfmpeg() {
in_filename = new char [1024];
out_filename = new char [1024];
}
CtFfmpeg::~CtFfmpeg() {
delete [] in_filename;
delete [] out_filename;
}
void CtFfmpeg::init() {
avcodec_register_all();
av_register_all();
avformat_network_init();
pkt = { 0 };
av_init_packet(&pkt);
ofmt = NULL;
ifmt_ctx = NULL;
ofmt_ctx = NULL;
return;
}
int CtFfmpeg::release() {
av_write_trailer(ofmt_ctx);
avcodec_close(out_stream->codec);
// avcodec_close(in_stream->codec);
// avformat_close_input(&ifmt_ctx);
/* close output */
if (!(ofmt->flags & AVFMT_NOFILE))
avio_close(ofmt_ctx->pb);
avformat_free_context(ofmt_ctx);
av_free_packet(&pkt);
if (ret < 0 && ret != AVERROR_EOF) {
fprintf(stderr, "Error occurred\n");
return 1;
}
}
int CtFfmpeg::getInput() {
if ((ret = avformat_open_input(&ifmt_ctx, in_filename, 0, 0)) < 0) {
fprintf(stderr, "Could not open input file '%s'", in_filename);
release();
}
if ((ret = avformat_find_stream_info(ifmt_ctx, 0)) < 0) {
fprintf(stderr, "Failed to retrieve input stream information");
release();
}
av_dump_format(ifmt_ctx, 0, in_filename, 0);
}
int CtFfmpeg::setOutput(const char *outfilename) {
avformat_alloc_output_context2(&ofmt_ctx, NULL, NULL, outfilename);
if (!ofmt_ctx) {
fprintf(stderr, "Could not create output context\n");
ret = AVERROR_UNKNOWN;
release();
}
ofmt = ofmt_ctx->oformat;
for (int i = 0; i < ifmt_ctx->nb_streams; i++) {
in_stream = ifmt_ctx->streams[i];
out_stream = avformat_new_stream(ofmt_ctx, in_stream->codec->codec);
if (!out_stream) {
fprintf(stderr, "Failed allocating output stream\n");
ret = AVERROR_UNKNOWN;
release();
}
ret = avcodec_copy_context(out_stream->codec, in_stream->codec);
if (ret < 0) {
fprintf(stderr, "Failed to copy context from input to output stream codec context\n");
release();
}
out_stream->codec->codec_tag = 0;
if (ofmt_ctx->oformat->flags & AVFMT_GLOBALHEADER)
out_stream->codec->flags |= CODEC_FLAG_GLOBAL_HEADER;
} // for
av_dump_format(ofmt_ctx, 0, outfilename, 1);
if (!(ofmt->flags & AVFMT_NOFILE)) {
ret = avio_open(&ofmt_ctx->pb, outfilename, AVIO_FLAG_WRITE);
if (ret < 0) {
fprintf(stderr, "Could not open output file '%s'", outfilename);
release();
}
}
ret = avformat_write_header(ofmt_ctx, NULL);
if (ret < 0) {
fprintf(stderr, "Error occurred when opening output file\n");
release();
}
}
int CtFfmpeg::getOutputName(const char *filename){
sprintf(out_filename,filename);
setOutput(out_filename);
}
main.cpp
#include "ctfolder.h"
#include "ctffmpeg.h"
CtFfmpeg * ff;
int main(int argc, char** argv) {
if (argc < 2) {
printf("usage: %s <RTSP link> \n", argv[0]);
return 1;
}
ff = new CtFfmpeg();
ff->in_filename = argv[1]; //RTSP input link
ff->init();
ff->getInput();
string filename;
videoRecorder obj;
int start, now;
start = obj.get_current_min();
if(obj.create_folder(0755))
cout << "Cannot create folder, maybe it already exists" << endl;
else
cout << "Create folder succesfully" << endl;
int skip = 0;
while(1){
filename = obj.update_filename();
ff->getOutputName(filename.c_str());
while((now = obj.get_current_min()) == start) {
ff->ret = av_read_frame(ff->ifmt_ctx, &(ff->pkt));
skip++;
if(skip==1)
continue;
if(skip>2)
skip=2;
if (ff->ret < 0)
continue;
ff->pkt.pts = av_rescale_q_rnd(ff->pkt.pts, ff->in_stream->time_base, ff->out_stream->time_base, (AVRounding)(AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX));
ff->pkt.dts = av_rescale_q_rnd(ff->pkt.dts, ff->in_stream->time_base, ff->out_stream->time_base, (AVRounding)(AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX));
ff->pkt.duration = av_rescale_q(ff->pkt.duration, ff->in_stream->time_base, ff->out_stream->time_base);
ff->pkt.pos = -1;
ff->ret = av_interleaved_write_frame(ff->ofmt_ctx, &(ff->pkt));
if (ff->ret < 0) {
fprintf(stderr, "Error muxing packet\n");
continue;
}
av_free_packet(&(ff->pkt));
}
ff->release();
cout << "New minute!" << endl;
if(obj.create_folder(0755))
cout << "Cannot create folder, something's wrong" << endl;
else
cout << "Create folder succesfully" << endl;
start = now;
}
return 0;
}
You need to shift your recording packet's pts to 0.
while(<some condition>)
{
//...
int64_t pts_offset = AV_NOPTS_VALUE ;
while((now = obj.get_current_min()) == start)
{
//...
ff.pkt.pts = ...
//...
if( pts_offset == AV_NOPTS_VALUE )
{
pts_offset = ff.pkt.pts ;
}
ff.pkt.pts -= pts_offset ;
// ...
}
}
I tried to build your code and add Alexander Chernin suggestion to it but I face to muxer error!
When you decrease recording packet's pts, it's value go lower than recording packet's dts. In avcodec.h, above declaration of pts I found this comment:
pts MUST be larger or equal to dts as presentation cannot happen before decompression.
I solved this error by decreasing recording packet's dts.
ff->pkt.pts = av_rescale_q_rnd(ff->pkt.pts, ff->in_stream->ff->out_stream->(AVRounding) (AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX));
if (pts_offset == AV_NOPTS_VALUE) {
pts_offset = ff->pkt.pts;
}
ff->pkt.pts -= pts_offset;
ff->pkt.dts -= pts_offset;
ff->pkt.dts = av_rescale_q_rnd(ff->pkt.dts, ff->in_stream->time_base,ff->out_stream->time_base,(AVRounding) (AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX));
ff->pkt.duration = av_rescale_q(ff->pkt.duration,ff->in_stream->time_base,ff->out_stream->time_base);
ff->pkt.pos = -1;
like title, here is my code:
int decompress_one_file(char *infilename, char *outfilename)
{
gzFile infile = gzopen(infilename, "rb");
FILE *outfile = fopen(outfilename, "wb");
if (!infile || !outfile) return -1;
char buffer[128] = {NULL};
int num_read = 0;
num_read = gzread(infile, buffer, sizeof(buffer)); // crash here
while (num_read > 0) {
fwrite(buffer, 1, num_read, outfile);
}
gzclose(infile);
fclose(outfile);
return 0;
}
when my console-app run to gzread(), its crash, I don't know what type of error is this?. zlib version: 1.2.11
update compress function:
int compress_one_file(char *infilename, char *outfilename)
{
FILE *infile = fopen(infilename, "rb");
gzFile outfile = gzopen(outfilename, "wb");
if (!infile || !outfile) return -1;
char inbuffer[128] = {NULL};
int num_read = 0;
unsigned long total_read = 0, total_wrote = 0;
while ((num_read = fread(inbuffer, 1, sizeof(inbuffer), infile)) > 0) {
total_read += num_read;
gzwrite(outfile, inbuffer, num_read);
}
fclose(infile);
gzclose(outfile);
return 0;
}
Error that shows up:
Anyone got an idea about this error?
I checked and it works fine at my workstation. May be here is a issue with gzipped file?
Could you show a file that give a crash?
But in any case you have a infinity loop of fwrite:
int num_read = 0;
while ((num_read = gzread(infile, buffer, sizeof(buffer))) > 0) {
while (num_read > 0) {
num_read -= fwrite(buffer, 1, num_read, outfile);
}
}
I'm trying to zip/unzip folders using libarchive. But, I couldn't know how to use it?
Include these:
#include <archive.h>
#include <archive_entry.h>
And compile with:
gcc -Wall -o test test.c -lz -lbz2 -larchive
So all together it should look something like this
#include <sys/types.h>
#include <sys/stat.h>
#include <archive.h>
#include <archive_entry.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
static int
copy_data(struct archive *ar, struct archive *aw)
{
int r;
const void *buff;
size_t size;
off_t offset;
for (;;) {
r = archive_read_data_block(ar, &buff, &size, &offset);
if (r == ARCHIVE_EOF)
return (ARCHIVE_OK);
if (r < ARCHIVE_OK)
return (r);
r = archive_write_data_block(aw, buff, size, offset);
if (r < ARCHIVE_OK) {
fprintf(stderr, "%s\n", archive_error_string(aw));
return (r);
}
}
}
static int
extract(const char *filename)
{
struct archive *a;
struct archive *ext;
struct archive_entry *entry;
int flags;
int r;
/* Select which attributes we want to restore. */
flags = ARCHIVE_EXTRACT_TIME;
flags |= ARCHIVE_EXTRACT_PERM;
flags |= ARCHIVE_EXTRACT_ACL;
flags |= ARCHIVE_EXTRACT_FFLAGS;
a = archive_read_new();
archive_read_support_format_all(a);
ext = archive_write_disk_new();
archive_write_disk_set_options(ext, flags);
archive_write_disk_set_standard_lookup(ext);
if ((r = archive_read_open_filename(a, filename, 10240)))
return 1;
for (;;) {
r = archive_read_next_header(a, &entry);
if (r == ARCHIVE_EOF)
break;
if (r < ARCHIVE_OK)
fprintf(stderr, "%s\n", archive_error_string(a));
if (r < ARCHIVE_WARN)
return 1;
r = archive_write_header(ext, entry);
if (r < ARCHIVE_OK)
fprintf(stderr, "%s\n", archive_error_string(ext));
else if (archive_entry_size(entry) > 0) {
r = copy_data(a, ext);
if (r < ARCHIVE_OK)
fprintf(stderr, "%s\n", archive_error_string(ext));
if (r < ARCHIVE_WARN)
return 1;
}
r = archive_write_finish_entry(ext);
if (r < ARCHIVE_OK)
fprintf(stderr, "%s\n", archive_error_string(ext));
if (r < ARCHIVE_WARN)
return 1;
}
archive_read_close(a);
archive_read_free(a);
archive_write_close(ext);
archive_write_free(ext);
return 0;
}
int main ( int argc, const char **argv )
{
return extract (argv[1]);;
}
Perhaps this link will help? Examples from LibArchive Wiki
For example, here is the code they give to write files to an archive:
void
write_archive(const char *outname, const char **filename)
{
struct archive *a;
struct archive_entry *entry;
struct stat st;
char buff[8192];
int len;
int fd;
a = archive_write_new();
archive_write_add_filter_gzip(a);
archive_write_set_format_pax_restricted(a); // Note 1
archive_write_open_filename(a, outname, 10240);
while (*filename) {
stat(*filename, &st);
entry = archive_entry_new(); // Note 2
archive_entry_set_pathname(entry, *filename);
archive_entry_set_size(entry, st.st_size); // Note 3
archive_entry_set_filetype(entry, AE_IFREG);
archive_entry_set_perm(entry, 0644);
archive_write_header(a, entry);
fd = open(*filename, O_RDONLY);
len = read(fd, buff, sizeof(buff));
while ( len > 0 ) {
archive_write_data(a, buff, len);
len = read(fd, buff, sizeof(buff));
}
close(fd);
archive_entry_free(entry);
filename++;
}
archive_write_close(a); // Note 4
archive_write_free(a); // Note 5
}
int main(int argc, const char **argv)
{
const char *outname;
argv++;
outname = argv++;
write_archive(outname, argv);
return 0;
}