summaryrefslogtreecommitdiffstats
path: root/libtar/append.c
diff options
context:
space:
mode:
Diffstat (limited to 'libtar/append.c')
-rw-r--r--libtar/append.c116
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;
+}
+