Last active
August 18, 2022 11:47
-
-
Save cat-in-136/5509961 to your computer and use it in GitHub Desktop.
Study for reading/writing a tar file using libtar
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdlib.h> | |
#include <stdio.h> | |
#include <fcntl.h> | |
#include <libtar.h> | |
int main(int argc, char *argv[]) { | |
TAR *tar = NULL; | |
int ret = 0; | |
int exitcode = 0; | |
if (argc != 2) { | |
fprintf(stderr, "Usage: %s tarfile.tar\n", argv[0]); | |
return 1; | |
} | |
ret = tar_open(&tar, argv[1], NULL, O_RDONLY, 0, 0); | |
if (ret != 0) { | |
fprintf(stderr, "Fail to open file: %s\n", argv[1]); | |
return 1; | |
} | |
while (th_read(tar) == 0) { | |
char *filename = th_get_pathname(tar); | |
printf("%s\n", filename); | |
free(filename); | |
if (TH_ISREG(tar) && (tar_skip_regfile(tar) != 0)) { | |
fprintf(stderr, "tar_skip_regfile()\n"); | |
exitcode = 2; | |
break; | |
} | |
} | |
ret = tar_close(tar); | |
tar = NULL; | |
return exitcode; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdlib.h> | |
#include <stdio.h> | |
#include <string.h> | |
#include <fcntl.h> | |
#include <libtar.h> | |
int main(int argc, char *argv[]) { | |
TAR *tar = NULL; | |
int ret = 0; | |
int th_found = 0; | |
int exitcode = 0; | |
if (argc != 3) { | |
fprintf(stderr, "Usage: %s tarfile.tar entry\n", argv[0]); | |
return 1; | |
} | |
ret = tar_open(&tar, argv[1], NULL, O_RDONLY, 0, 0); | |
if (ret != 0) { | |
fprintf(stderr, "Fail to open file: %s\n", argv[1]); | |
return 1; | |
} | |
while (th_read(tar) == 0) { | |
char *filename = th_get_pathname(tar); | |
if (strcmp(filename, argv[2]) == 0) { | |
th_found = 1; | |
free(filename); | |
break; | |
} | |
free(filename); | |
if (TH_ISREG(tar) && (tar_skip_regfile(tar) != 0)) { | |
fprintf(stderr, "tar_skip_regfile()\n"); | |
exitcode = 2; | |
break; | |
} | |
} | |
if (th_found == 1) { | |
char buf[T_BLOCKSIZE]; | |
const off_t size = th_get_size(tar); | |
int i; | |
for (i = size; i > 0; i -= T_BLOCKSIZE) { | |
int n_buf = tar_block_read(tar, buf); | |
if (n_buf == EOF) { | |
break; | |
} | |
fwrite(buf, sizeof(char), (n_buf > T_BLOCKSIZE)? T_BLOCKSIZE : n_buf, stdout); | |
} | |
} else if (exitcode == 0) { | |
fprintf(stderr, "entry \"%s\" could not found.\n", argv[2]); | |
exitcode = 1; | |
} | |
ret = tar_close(tar); | |
tar = NULL; | |
return 0; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdlib.h> | |
#include <stdio.h> | |
#include <string.h> | |
#include <fcntl.h> | |
#include <libtar.h> | |
int main(int argc, char *argv[]) { | |
TAR *tar = NULL; | |
int ret = 0; | |
int th_found = 0; | |
int exitcode = 0; | |
char tmp_filepath[] = P_tmpdir "/tartest-tmpfile-XXXXXX"; | |
int tmp_fd = -1; | |
if (argc != 3) { | |
fprintf(stderr, "Usage: %s tarfile.tar entry\n", argv[0]); | |
fprintf(stderr, " (entry body is captured from STDIN.)\n"); | |
return 1; | |
} | |
ret = tar_open(&tar, argv[1], NULL, O_RDONLY, 0, 0); | |
if (ret != 0) { | |
fprintf(stderr, "Fail to open file: %s\n", argv[1]); | |
return 1; | |
} | |
while (th_read(tar) == 0) { | |
char *filename = th_get_pathname(tar); | |
if (strcmp(filename, argv[2]) == 0) { | |
th_found = 1; | |
free(filename); | |
break; | |
} | |
free(filename); | |
if (TH_ISREG(tar) && (tar_skip_regfile(tar) != 0)) { | |
fprintf(stderr, "tar_skip_regfile()\n"); | |
exitcode = 2; | |
break; | |
} | |
} | |
tmp_fd = mkstemp(tmp_filepath); | |
if (tmp_fd == -1) { | |
fprintf(stderr, "Failed to build temp file.\n"); | |
exitcode = 2; | |
} | |
if (exitcode == 0) { | |
if (th_found == 1) { | |
if (tar_extract_regfile(tar, tmp_filepath) != 0) { | |
char *filename = th_get_pathname(tar); | |
fprintf(stderr, "Failed to extract \"%s\" to \"%s\"\n", filename, tmp_filepath); | |
free(filename); | |
exitcode = 2; | |
} | |
} | |
} | |
ret = tar_close(tar); | |
if (ret != 0) { | |
perror("Failed to close tar file."); | |
exitcode = 2; | |
} | |
tar = NULL; | |
if (exitcode == 0) { | |
char buf[BUFSIZ]; | |
ssize_t n_buf = 0; | |
FILE *tmpfile = NULL; | |
tmpfile = fdopen(tmp_fd, "w"); | |
if (tmpfile != NULL) { | |
while ((n_buf = fread(buf, sizeof(char), BUFSIZ, stdin)) != 0) { | |
fwrite(buf, sizeof(char), (n_buf > BUFSIZ)? BUFSIZ : n_buf, tmpfile); | |
} | |
fclose(tmpfile); | |
tmpfile = NULL; | |
} else { | |
perror("Failed to open temp file."); | |
exitcode = 2; | |
} | |
} | |
if (exitcode == 0) { | |
// Note: libtar is NOT able to replace a given file from an archive. | |
// So, we use GNU tar(1) command! | |
const char TAR_PROG_NAME[] = "gtar"; // GNU tar. (may be tar). | |
char cmdl[BUFSIZ]; | |
// TODO multiple file is appended when the file is already exists in the tar file. | |
sprintf(cmdl, "%s -uf '%s' --xform='s|%s|%s|' -- '%s' > /dev/null 2> /dev/null", | |
TAR_PROG_NAME, | |
argv[1], // tar file | |
tmp_filepath+1, // --xform | |
argv[2], // --xform (replacement) | |
tmp_filepath); | |
// printf("%s\n", cmdl); | |
// TODO do not use system() and use fork() and execve(). (Secure Coding - ENV04-C) | |
system(cmdl); | |
} | |
if (tmp_fd != -1) { | |
if (remove(tmp_filepath) == -1) { | |
fprintf(stderr, "Failed to remove a temp file \"%s\".\n", tmp_filepath); | |
exitcode = 2; | |
} | |
tmp_fd = -1; | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment