?revision_form?Rev ?revision_input??revision_submit??revision_endform?
Blame |
Last modification |
View Log
| RSS feed
/*
** 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 <config.h>
#include <libtar.h>
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/param.h>
#ifdef STDC_HEADERS
# include <stdlib.h>
# include <string.h>
#endif
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#ifdef DEBUG
# include <signal.h>
#endif
#ifdef HAVE_LIBZ
# include <zlib.h>
#endif
#include <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;
int
gzopen_frontend
(char *pathname
, int oflags
, int mode
)
{
char *gzoflags
;
gzFile gzf
;
int fd
;
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 ((oflags
& O_CREAT
) && fchmod
(fd
, mode
))
return -1;
gzf
= gzdopen
(fd
, gzoflags
);
if (!gzf
)
{
errno
= ENOMEM
;
return -1;
}
/* This is a bad thing to do on big-endian lp64 systems, where the
size and placement of integers is different than pointers.
However, to fix the problem 4 wrapper functions would be needed and
an extra bit of data associating GZF with the wrapper functions. */
return (int)gzf
;
}
tartype_t gztype
= { (openfunc_t
) gzopen_frontend
, (closefunc_t
) gzclose
,
(readfunc_t
) gzread
, (writefunc_t
) gzwrite
};
#endif /* HAVE_LIBZ */
int
create
(char *tarfile
, char *rootdir
, libtar_list_t
*l
)
{
TAR
*t
;
char *pathname
;
char buf
[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;
}
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;
}
return 0;
}
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;
}
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);
}
#define MODE_LIST 1
#define MODE_CREATE 2
#define MODE_EXTRACT 3
int
main
(int argc
, char *argv
[])
{
char *tarfile
= NULL
;
char *rootdir
= NULL
;
int c
;
int mode
= 0;
libtar_list_t
*l
;
progname
= basename
(argv
[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
();
}
#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;
}