| /* |
| ** Copyright 1998-2003 University of Illinois Board of Trustees |
| ** Copyright 1998-2003 Mark D. Roth |
| ** All rights reserved. |
| ** |
| ** libtar.c - demo driver program for libtar |
| ** |
| ** Mark D. Roth <roth@uiuc.edu> |
| ** Campus Information Technologies and Educational Services |
| ** University of Illinois at Urbana-Champaign |
| */ |
| #include <libtar/config.h> |
| #include <libtar/libtar.h> |
| |
| #include <stdio.h> |
| #include <fcntl.h> |
| #include <errno.h> |
| #if defined(_WIN32) && !defined(__CYGWIN__) |
| #include <libtar/compat.h> |
| #include <io.h> |
| #else |
| # ifdef HAVE_SYS_PARAM_H |
| # include <sys/param.h> |
| # endif |
| #endif |
| |
| #ifdef STDC_HEADERS |
| # include <string.h> |
| #endif |
| |
| #ifdef HAVE_UNISTD_H |
| # include <unistd.h> |
| # include <stdlib.h> |
| #endif |
| |
| #ifdef DEBUG |
| # include <signal.h> |
| #endif |
| |
| #include CMTAR_ZLIB_HEADER |
| |
| #include <libtar/compat.h> |
| |
| |
| char *progname; |
| int verbose = 0; |
| int use_gnu = 0; |
| |
| #ifdef DEBUG |
| void |
| segv_handler(int sig) |
| { |
| puts("OOPS! Caught SIGSEGV, bailing out..."); |
| fflush(stdout); |
| fflush(stderr); |
| } |
| #endif |
| |
| |
| #ifdef HAVE_LIBZ |
| |
| int use_zlib = 0; |
| |
| struct gzStruct |
| { |
| gzFile* GZFile; |
| }; |
| struct gzStruct GZStruct; |
| #if defined ( _MSC_VER) || defined(__WATCOMC__) |
| #include <io.h> |
| //Yogi: hack. this should work on windows where there is no O_ACCMODE defined |
| #ifndef O_ACCMODE |
| # define O_ACCMODE 0x0003 |
| #endif |
| #endif |
| |
| static int libtar_gzopen(void* call_data, const char *pathname, |
| int oflags, mode_t mode) |
| { |
| char *gzoflags; |
| int fd; |
| struct gzStruct* gzf = (struct gzStruct*)call_data; |
| |
| switch (oflags & O_ACCMODE) |
| { |
| case O_WRONLY: |
| gzoflags = "wb"; |
| break; |
| case O_RDONLY: |
| gzoflags = "rb"; |
| break; |
| default: |
| case O_RDWR: |
| errno = EINVAL; |
| return -1; |
| } |
| |
| fd = open(pathname, oflags, mode); |
| if (fd == -1) |
| { |
| return -1; |
| } |
| |
| #if defined(__BEOS__) && !defined(__ZETA__) /* no fchmod on BeOS...do pathname instead. */ |
| if ((oflags & O_CREAT) && chmod(pathname, mode & 07777)) |
| { |
| return -1; |
| } |
| #elif !defined(_WIN32) || defined(__CYGWIN__) |
| if ((oflags & O_CREAT) && fchmod(fd, mode & 07777)) |
| { |
| return -1; |
| } |
| #endif |
| |
| gzf->GZFile = gzdopen(fd, gzoflags); |
| if (!gzf->GZFile) |
| { |
| errno = ENOMEM; |
| return -1; |
| } |
| |
| return fd; |
| } |
| |
| static int libtar_gzclose(void* call_data) |
| { |
| struct gzStruct* gzf = (struct gzStruct*)call_data; |
| return gzclose(gzf->GZFile); |
| } |
| |
| static ssize_t libtar_gzread(void* call_data, void* buf, size_t count) |
| { |
| struct gzStruct* gzf = (struct gzStruct*)call_data; |
| return gzread(gzf->GZFile, buf, (unsigned int)count); |
| } |
| |
| static ssize_t libtar_gzwrite(void* call_data, const void* buf, size_t count) |
| { |
| struct gzStruct* gzf = (struct gzStruct*)call_data; |
| return gzwrite(gzf->GZFile, (void*)buf, (unsigned int)count); |
| } |
| |
| tartype_t gztype = { |
| libtar_gzopen, |
| libtar_gzclose, |
| libtar_gzread, |
| libtar_gzwrite, |
| &GZStruct |
| }; |
| |
| #endif /* HAVE_LIBZ */ |
| |
| |
| static int |
| create(char *tarfile, char *rootdir, libtar_list_t *l) |
| { |
| TAR *t; |
| char *pathname; |
| char buf[TAR_MAXPATHLEN]; |
| libtar_listptr_t lp; |
| |
| if (tar_open(&t, tarfile, |
| #ifdef HAVE_LIBZ |
| (use_zlib ? &gztype : NULL), |
| #else |
| NULL, |
| #endif |
| O_WRONLY | O_CREAT, 0644, |
| (verbose ? TAR_VERBOSE : 0) |
| | (use_gnu ? TAR_GNU : 0)) == -1) |
| { |
| fprintf(stderr, "tar_open(): %s\n", strerror(errno)); |
| return -1; |
| } |
| |
| libtar_listptr_reset(&lp); |
| while (libtar_list_next(l, &lp) != 0) |
| { |
| pathname = (char *)libtar_listptr_data(&lp); |
| if (pathname[0] != '/' && rootdir != NULL) |
| snprintf(buf, sizeof(buf), "%s/%s", rootdir, pathname); |
| else |
| strlcpy(buf, pathname, sizeof(buf)); |
| if (tar_append_tree(t, buf, pathname) != 0) |
| { |
| fprintf(stderr, |
| "tar_append_tree(\"%s\", \"%s\"): %s\n", buf, |
| pathname, strerror(errno)); |
| tar_close(t); |
| return -1; |
| } |
| } |
| |
| if (tar_append_eof(t) != 0) |
| { |
| fprintf(stderr, "tar_append_eof(): %s\n", strerror(errno)); |
| tar_close(t); |
| return -1; |
| } |
| |
| if (tar_close(t) != 0) |
| { |
| fprintf(stderr, "tar_close(): %s\n", strerror(errno)); |
| return -1; |
| } |
| |
| return 0; |
| } |
| |
| |
| static int |
| list(char *tarfile) |
| { |
| TAR *t; |
| int i; |
| |
| if (tar_open(&t, tarfile, |
| #ifdef HAVE_LIBZ |
| (use_zlib ? &gztype : NULL), |
| #else |
| NULL, |
| #endif |
| O_RDONLY, 0, |
| (verbose ? TAR_VERBOSE : 0) |
| | (use_gnu ? TAR_GNU : 0)) == -1) |
| { |
| fprintf(stderr, "tar_open(): %s\n", strerror(errno)); |
| return -1; |
| } |
| |
| while ((i = th_read(t)) == 0) |
| { |
| th_print_long_ls(t); |
| #ifdef DEBUG |
| th_print(t); |
| #endif |
| if (TH_ISREG(t) && tar_skip_regfile(t) != 0) |
| { |
| fprintf(stderr, "tar_skip_regfile(): %s\n", |
| strerror(errno)); |
| return -1; |
| } |
| } |
| |
| #ifdef DEBUG |
| printf("th_read() returned %d\n", i); |
| printf("EOF mark encountered after %ld bytes\n", |
| # ifdef HAVE_LIBZ |
| (use_zlib |
| ? gzseek((gzFile) t->fd, 0, SEEK_CUR) |
| : |
| # endif |
| lseek(t->fd, 0, SEEK_CUR) |
| # ifdef HAVE_LIBZ |
| ) |
| # endif |
| ); |
| #endif |
| |
| if (tar_close(t) != 0) |
| { |
| fprintf(stderr, "tar_close(): %s\n", strerror(errno)); |
| return -1; |
| } |
| (void)i; |
| |
| return 0; |
| } |
| |
| |
| static int |
| extract(char *tarfile, char *rootdir) |
| { |
| TAR *t; |
| |
| #ifdef DEBUG |
| puts("opening tarfile..."); |
| #endif |
| if (tar_open(&t, tarfile, |
| #ifdef HAVE_LIBZ |
| (use_zlib ? &gztype : NULL), |
| #else |
| NULL, |
| #endif |
| O_RDONLY, 0, |
| (verbose ? TAR_VERBOSE : 0) |
| | (use_gnu ? TAR_GNU : 0)) == -1) |
| { |
| fprintf(stderr, "tar_open(): %s\n", strerror(errno)); |
| return -1; |
| } |
| |
| #ifdef DEBUG |
| puts("extracting tarfile..."); |
| #endif |
| if (tar_extract_all(t, rootdir) != 0) |
| { |
| fprintf(stderr, "tar_extract_all(): %s\n", strerror(errno)); |
| return -1; |
| } |
| |
| #ifdef DEBUG |
| puts("closing tarfile..."); |
| #endif |
| if (tar_close(t) != 0) |
| { |
| fprintf(stderr, "tar_close(): %s\n", strerror(errno)); |
| return -1; |
| } |
| |
| return 0; |
| } |
| |
| #if !defined(_WIN32) || defined(__CYGWIN__) |
| static void |
| usage() |
| { |
| printf("Usage: %s [-C rootdir] [-g] [-z] -x|-t filename.tar\n", |
| progname); |
| printf(" %s [-C rootdir] [-g] [-z] -c filename.tar ...\n", |
| progname); |
| exit(-1); |
| } |
| #endif |
| |
| #define MODE_LIST 1 |
| #define MODE_CREATE 2 |
| #define MODE_EXTRACT 3 |
| |
| int |
| main(int argc, char *argv[]) |
| { |
| char* tarfile; |
| char *rootdir = NULL; |
| int c; |
| int mode; |
| libtar_list_t *l; |
| #if defined(_WIN32) && !defined(__CYGWIN__) |
| int optind; |
| #endif |
| progname = basename(argv[0]); |
| |
| #if !defined(_WIN32) || defined(__CYGWIN__) |
| mode = 0; |
| while ((c = getopt(argc, argv, "cC:gtvVxz")) != -1) |
| switch (c) |
| { |
| case 'V': |
| printf("libtar %s by Mark D. Roth <roth@uiuc.edu>\n", |
| libtar_version); |
| break; |
| case 'C': |
| rootdir = strdup(optarg); |
| break; |
| case 'v': |
| verbose = 1; |
| break; |
| case 'g': |
| use_gnu = 1; |
| break; |
| case 'c': |
| if (mode) |
| usage(); |
| mode = MODE_CREATE; |
| break; |
| case 'x': |
| if (mode) |
| usage(); |
| mode = MODE_EXTRACT; |
| break; |
| case 't': |
| if (mode) |
| usage(); |
| mode = MODE_LIST; |
| break; |
| #ifdef HAVE_LIBZ |
| case 'z': |
| use_zlib = 1; |
| break; |
| #endif /* HAVE_LIBZ */ |
| default: |
| usage(); |
| } |
| if (!mode || ((argc - optind) < (mode == MODE_CREATE ? 2 : 1))) |
| { |
| #ifdef DEBUG |
| printf("argc - optind == %d\tmode == %d\n", argc - optind, |
| mode); |
| #endif |
| usage(); |
| } |
| |
| #else |
| mode = MODE_EXTRACT; |
| use_zlib=1; |
| optind = 1; |
| #endif |
| |
| #ifdef DEBUG |
| signal(SIGSEGV, segv_handler); |
| #endif |
| |
| switch (mode) |
| { |
| case MODE_EXTRACT: |
| return extract(argv[optind], rootdir); |
| case MODE_CREATE: |
| tarfile = argv[optind]; |
| l = libtar_list_new(LIST_QUEUE, NULL); |
| for (c = optind + 1; c < argc; c++) |
| libtar_list_add(l, argv[c]); |
| return create(tarfile, rootdir, l); |
| case MODE_LIST: |
| return list(argv[optind]); |
| default: |
| break; |
| } |
| |
| /* NOTREACHED */ |
| return -2; |
| } |
| |
| |