| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279 |
- /*
- ** Copyright 1998-2003 University of Illinois Board of Trustees
- ** Copyright 1998-2003 Mark D. Roth
- ** All rights reserved.
- **
- ** append.c - libtar code to append files to a tar archive
- **
- ** Mark D. Roth <[email protected]>
- ** Campus Information Technologies and Educational Services
- ** University of Illinois at Urbana-Champaign
- */
- #include <libtarint/internal.h>
- #include <stdio.h>
- #include <errno.h>
- #include <fcntl.h>
- #if defined(_WIN32) && !defined(__CYGWIN__)
- # include <libtar/compat.h>
- #else
- # include <sys/param.h>
- #endif
- #include <libtar/compat.h>
- #include <sys/types.h>
- #ifdef STDC_HEADERS
- # include <stdlib.h>
- # include <string.h>
- #endif
- #ifdef HAVE_UNISTD_H
- # include <unistd.h>
- #endif
- #ifdef _MSC_VER
- #include <io.h>
- #endif
- struct tar_dev
- {
- dev_t td_dev;
- libtar_hash_t *td_h;
- };
- typedef struct tar_dev tar_dev_t;
- struct tar_ino
- {
- ino_t ti_ino;
- char ti_name[TAR_MAXPATHLEN];
- };
- typedef struct tar_ino tar_ino_t;
- /* free memory associated with a tar_dev_t */
- void
- tar_dev_free(tar_dev_t *tdp)
- {
- libtar_hash_free(tdp->td_h, free);
- free(tdp);
- }
- /* appends a file to the tar archive */
- int
- tar_append_file(TAR *t, char *realname, char *savename)
- {
- struct stat s;
- libtar_hashptr_t hp;
- tar_dev_t *td = NULL;
- tar_ino_t *ti = NULL;
- #if !defined(_WIN32) || defined(__CYGWIN__)
- int i;
- char path[TAR_MAXPATHLEN];
- #endif
- #ifdef DEBUG
- printf("==> tar_append_file(TAR=0x%lx (\"%s\"), realname=\"%s\", "
- "savename=\"%s\")\n", t, t->pathname, realname,
- (savename ? savename : "[NULL]"));
- #endif
- #ifdef WIN32
- if (stat(realname, &s) != 0)
- #else
- if (lstat(realname, &s) != 0)
- #endif
- {
- #ifdef DEBUG
- perror("lstat()");
- #endif
- return -1;
- }
- /* set header block */
- #ifdef DEBUG
- 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...");
- #endif
- th_set_path(t, (savename ? savename : realname));
- /* check if it's a hardlink */
- #ifdef DEBUG
- puts(" tar_append_file(): checking inode cache for hardlink...");
- #endif
- libtar_hashptr_reset(&hp);
- if (libtar_hash_getkey(t->h, &hp, &(s.st_dev),
- (libtar_matchfunc_t)dev_match) != 0)
- td = (tar_dev_t *)libtar_hashptr_data(&hp);
- else
- {
- #ifdef DEBUG
- printf("+++ adding hash for device (0x%lx, 0x%lx)...\n",
- major(s.st_dev), minor(s.st_dev));
- #endif
- td = (tar_dev_t *)calloc(1, sizeof(tar_dev_t));
- td->td_dev = s.st_dev;
- td->td_h = libtar_hash_new(256, (libtar_hashfunc_t)ino_hash);
- if (td->td_h == NULL)
- return -1;
- if (libtar_hash_add(t->h, td) == -1)
- return -1;
- }
- libtar_hashptr_reset(&hp);
- if (libtar_hash_getkey(td->td_h, &hp, &(s.st_ino),
- (libtar_matchfunc_t)ino_match) != 0)
- {
- ti = (tar_ino_t *)libtar_hashptr_data(&hp);
- #ifdef DEBUG
- printf(" tar_append_file(): encoding hard link \"%s\" "
- "to \"%s\"...\n", realname, ti->ti_name);
- #endif
- t->th_buf.typeflag = LNKTYPE;
- th_set_link(t, ti->ti_name);
- }
- else
- {
- #ifdef DEBUG
- printf("+++ adding entry: device (0x%lx,0x%lx), inode %ld "
- "(\"%s\")...\n", major(s.st_dev), minor(s.st_dev),
- s.st_ino, realname);
- #endif
- ti = (tar_ino_t *)calloc(1, sizeof(tar_ino_t));
- if (ti == NULL)
- return -1;
- ti->ti_ino = s.st_ino;
- snprintf(ti->ti_name, sizeof(ti->ti_name), "%s",
- savename ? savename : realname);
- libtar_hash_add(td->td_h, ti);
- }
- #if !defined(_WIN32) || defined(__CYGWIN__)
- /* check if it's a symlink */
- if (TH_ISSYM(t))
- {
- #ifdef WIN32
- i = -1;
- #else
- i = readlink(realname, path, sizeof(path));
- #endif
- if (i == -1)
- return -1;
- if (i >= TAR_MAXPATHLEN)
- i = TAR_MAXPATHLEN - 1;
- path[i] = '\0';
- #ifdef DEBUG
- printf(" tar_append_file(): encoding symlink \"%s\" -> "
- "\"%s\"...\n", realname, path);
- #endif
- th_set_link(t, path);
- }
- #endif
- /* print file info */
- if (t->options & TAR_VERBOSE)
- th_print_long_ls(t);
- #ifdef DEBUG
- puts(" tar_append_file(): writing header");
- #endif
- /* write header */
- if (th_write(t) != 0)
- {
- #ifdef DEBUG
- printf("t->fd = %d\n", t->fd);
- #endif
- return -1;
- }
- #ifdef DEBUG
- puts(" tar_append_file(): back from th_write()");
- #endif
- /* if it's a regular file, write the contents as well */
- if (TH_ISREG(t) && tar_append_regfile(t, realname) != 0)
- return -1;
- return 0;
- }
- /* write EOF indicator */
- int
- tar_append_eof(TAR *t)
- {
- int i, j;
- char block[T_BLOCKSIZE];
- memset(&block, 0, T_BLOCKSIZE);
- for (j = 0; j < 2; j++)
- {
- i = tar_block_write(t, &block);
- if (i != T_BLOCKSIZE)
- {
- if (i != -1)
- errno = EINVAL;
- return -1;
- }
- }
- return 0;
- }
- /* add file contents to a tarchive */
- int
- tar_append_regfile(TAR *t, char *realname)
- {
- char block[T_BLOCKSIZE];
- int filefd;
- int i, j;
- size_t size;
- #ifdef _WIN32
- filefd = open(realname, O_RDONLY | O_BINARY);
- #else
- filefd = open(realname, O_RDONLY);
- #endif
- if (filefd == -1)
- {
- #ifdef DEBUG
- perror("open()");
- #endif
- return -1;
- }
- size = th_get_size(t);
- for (i = size; i > T_BLOCKSIZE; i -= T_BLOCKSIZE)
- {
- j = read(filefd, &block, T_BLOCKSIZE);
- if (j != T_BLOCKSIZE)
- {
- if (j != -1)
- errno = EINVAL;
- return -1;
- }
- if (tar_block_write(t, &block) == -1)
- return -1;
- }
- if (i > 0)
- {
- j = read(filefd, &block, i);
- if (j == -1)
- return -1;
- memset(&(block[i]), 0, T_BLOCKSIZE - i);
- if (tar_block_write(t, &block) == -1)
- return -1;
- }
- close(filefd);
- return 0;
- }
|