diff options
Diffstat (limited to 'libtar/append.c')
-rw-r--r-- | libtar/append.c | 116 |
1 files changed, 95 insertions, 21 deletions
diff --git a/libtar/append.c b/libtar/append.c index 1831990be..4be679ccd 100644 --- a/libtar/append.c +++ b/libtar/append.c @@ -13,8 +13,11 @@ #include <internal.h> #include <stdio.h> +#include <stdlib.h> +#include <string.h> #include <errno.h> #include <fcntl.h> +#include <time.h> #include <sys/param.h> #include <sys/types.h> @@ -28,7 +31,7 @@ #endif #ifdef HAVE_SELINUX -#include "selinux/selinux.h" +# include "selinux/selinux.h" #endif struct tar_dev @@ -57,7 +60,7 @@ tar_dev_free(tar_dev_t *tdp) /* appends a file to the tar archive */ int -tar_append_file(TAR *t, char *realname, char *savename) +tar_append_file(TAR *t, const char *realname, const char *savename) { struct stat s; int i; @@ -82,38 +85,46 @@ tar_append_file(TAR *t, char *realname, char *savename) /* set header block */ #ifdef DEBUG - puts(" tar_append_file(): setting header block..."); + puts("tar_append_file(): setting header block..."); #endif memset(&(t->th_buf), 0, sizeof(struct tar_header)); th_set_from_stat(t, &s); /* set the header path */ #ifdef DEBUG - puts(" tar_append_file(): setting header path..."); + puts("tar_append_file(): setting header path..."); #endif th_set_path(t, (savename ? savename : realname)); #ifdef HAVE_SELINUX /* get selinux context */ - if(t->options & TAR_STORE_SELINUX) { - if(t->th_buf.selinux_context != NULL) { + if (t->options & TAR_STORE_SELINUX) + { + if (t->th_buf.selinux_context != NULL) + { free(t->th_buf.selinux_context); t->th_buf.selinux_context = NULL; } security_context_t selinux_context = NULL; - if (lgetfilecon(realname, &selinux_context) >= 0) { + if (lgetfilecon(realname, &selinux_context) >= 0) + { t->th_buf.selinux_context = strdup(selinux_context); - printf("setting selinux context: %s\n", selinux_context); + printf(" ==> set selinux context: %s\n", selinux_context); freecon(selinux_context); } else + { +#ifdef DEBUG perror("Failed to get selinux context"); +#endif + } } #endif + /* check if it's a hardlink */ #ifdef DEBUG - puts(" tar_append_file(): checking inode cache for hardlink..."); + puts("tar_append_file(): checking inode cache for hardlink..."); #endif libtar_hashptr_reset(&hp); if (libtar_hash_getkey(t->h, &hp, &(s.st_dev), @@ -171,7 +182,7 @@ tar_append_file(TAR *t, char *realname, char *savename) i = MAXPATHLEN - 1; path[i] = '\0'; #ifdef DEBUG - printf(" tar_append_file(): encoding symlink \"%s\" -> " + printf("tar_append_file(): encoding symlink \"%s\" -> " "\"%s\"...\n", realname, path); #endif th_set_link(t, path); @@ -179,10 +190,10 @@ tar_append_file(TAR *t, char *realname, char *savename) /* print file info */ if (t->options & TAR_VERBOSE) - th_print_long_ls(t); + printf("%s\n", th_get_pathname(t)); #ifdef DEBUG - puts(" tar_append_file(): writing header"); + puts("tar_append_file(): writing header"); #endif /* write header */ if (th_write(t) != 0) @@ -193,7 +204,7 @@ tar_append_file(TAR *t, char *realname, char *savename) return -1; } #ifdef DEBUG - puts(" tar_append_file(): back from th_write()"); + puts("tar_append_file(): back from th_write()"); #endif /* if it's a regular file, write the contents as well */ @@ -229,14 +240,19 @@ tar_append_eof(TAR *t) /* add file contents to a tarchive */ int -tar_append_regfile(TAR *t, char *realname) +tar_append_regfile(TAR *t, const char *realname) { char block[T_BLOCKSIZE]; int filefd; - int j; - size_t size, i; + int64_t i, size; + ssize_t j; + int rv = -1; +#if defined(O_BINARY) + filefd = open(realname, O_RDONLY|O_BINARY); +#else filefd = open(realname, O_RDONLY); +#endif if (filefd == -1) { #ifdef DEBUG @@ -253,25 +269,83 @@ tar_append_regfile(TAR *t, char *realname) { if (j != -1) errno = EINVAL; - return -1; + goto fail; } if (tar_block_write(t, &block) == -1) - return -1; + goto fail; } if (i > 0) { j = read(filefd, &block, i); if (j == -1) - return -1; + goto fail; memset(&(block[i]), 0, T_BLOCKSIZE - i); if (tar_block_write(t, &block) == -1) - return -1; + goto fail; } + /* success! */ + rv = 0; +fail: close(filefd); - return 0; + return rv; } +/* add file contents to a tarchive */ +int +tar_append_file_contents(TAR *t, const char *savename, mode_t mode, + uid_t uid, gid_t gid, void *buf, size_t len) +{ + struct stat st; + + memset(&st, 0, sizeof(st)); + st.st_mode = S_IFREG | mode; + st.st_uid = uid; + st.st_gid = gid; + st.st_mtime = time(NULL); + st.st_size = len; + + th_set_from_stat(t, &st); + th_set_path(t, savename); + + /* write header */ + if (th_write(t) != 0) + { +#ifdef DEBUG + fprintf(stderr, "tar_append_file_contents(): could not write header, t->fd = %d\n", t->fd); +#endif + return -1; + } + + return tar_append_buffer(t, buf, len); +} + +int +tar_append_buffer(TAR *t, void *buf, size_t len) +{ + char block[T_BLOCKSIZE]; + int filefd; + int i, j; + size_t size = len; + + for (i = size; i > T_BLOCKSIZE; i -= T_BLOCKSIZE) + { + if (tar_block_write(t, buf) == -1) + return -1; + buf = (char *)buf + T_BLOCKSIZE; + } + + if (i > 0) + { + memcpy(block, buf, i); + memset(&(block[i]), 0, T_BLOCKSIZE - i); + if (tar_block_write(t, &block) == -1) + return -1; + } + + return 0; +} + |