minitar/examples/pack.c
apio 482ac6d949
feat: Add write support
This uses a new struct (struct minitar_w).
This struct is initialized using the minitar_open_w function, and deleted using minitar_close_w.

The functions to write to an archive are minitar_write_file_entry() and minitar_write_special_entry().
The difference is that regular files have content, while the rest (special entries) do not.

This commit also adds a new example program (pack), which can create tar archives from files (no directory support though).

Archives created using pack and minitar can be read and extracted using GNU tar!!

Documentation is coming in another commit.
2023-02-04 19:02:08 +01:00

88 lines
1.9 KiB
C

/*
* Copyright (c) 2023, apio.
*
* SPDX-License-Identifier: BSD-2-Clause
*
* pack.c: Example utility which creates a tar archive (POSIX only).
*/
#define _XOPEN_SOURCE 700
#include <minitar.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
int main(int argc, char** argv)
{
if (argc < 3)
{
fprintf(stderr, "Usage: %s [output] files\n", argv[0]);
return 1;
}
struct minitar_w mp;
if (minitar_open_w(argv[1], &mp, MTAR_OVERWRITE) != 0)
{
perror(argv[1]);
return 1;
}
int exit_status = 0;
struct minitar_entry_metadata metadata;
int arg = 2;
while (arg < argc)
{
FILE* fp = fopen(argv[arg], "r");
if (!fp)
{
perror("fopen");
exit_status = 1;
break;
}
// Get the file length.
fseek(fp, 0, SEEK_END);
size_t length = ftell(fp);
fseek(fp, 0, SEEK_SET);
char* buf = malloc(length);
fread(buf, 1, length, fp);
if (ferror(fp))
{
perror("fread");
exit_status = 1;
break;
}
struct stat st;
int rc = fstat(fileno(fp), &st);
if (rc < 0)
{
perror("fstat");
exit_status = 1;
break;
}
struct minitar_entry_metadata metadata;
strncpy(metadata.path, argv[arg], sizeof(metadata.path));
metadata.uid = st.st_uid;
metadata.gid = st.st_gid;
metadata.mtime = st.st_mtim.tv_sec;
metadata.size = length;
metadata.type = MTAR_REGULAR;
metadata.mode = st.st_mode & ~S_IFMT;
rc = minitar_write_file_entry(&mp, &metadata, buf);
free(buf);
if (rc != 0)
{
perror("write entry failed");
exit_status = 1;
break;
}
arg++;
}
minitar_close_w(&mp);
return exit_status;
}