2005-12-28 18:18:37 +03:00
|
|
|
/*
|
|
|
|
** Copyright 1998-2003 University of Illinois Board of Trustees
|
|
|
|
** Copyright 1998-2003 Mark D. Roth
|
|
|
|
** All rights reserved.
|
|
|
|
**
|
|
|
|
** libtar.h - header file for libtar library
|
|
|
|
**
|
|
|
|
** Mark D. Roth <roth@uiuc.edu>
|
|
|
|
** Campus Information Technologies and Educational Services
|
|
|
|
** University of Illinois at Urbana-Champaign
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef LIBTAR_H
|
|
|
|
#define LIBTAR_H
|
|
|
|
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <libtar/tar.h>
|
|
|
|
|
|
|
|
#include <libtar/libtar_listhash.h>
|
|
|
|
#include <libtar/compat.h>
|
|
|
|
#ifdef __cplusplus
|
2005-12-30 22:51:15 +03:00
|
|
|
extern "C" {
|
2005-12-28 18:18:37 +03:00
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
/* useful constants */
|
|
|
|
#define T_BLOCKSIZE 512
|
|
|
|
#define T_NAMELEN 100
|
|
|
|
#define T_PREFIXLEN 155
|
|
|
|
#define T_MAXPATHLEN (T_NAMELEN + T_PREFIXLEN)
|
|
|
|
|
|
|
|
/* GNU extensions for typeflag */
|
|
|
|
#define GNU_LONGNAME_TYPE 'L'
|
|
|
|
#define GNU_LONGLINK_TYPE 'K'
|
|
|
|
|
|
|
|
/* our version of the tar header structure */
|
|
|
|
struct tar_header
|
|
|
|
{
|
|
|
|
char name[100];
|
|
|
|
char mode[8];
|
|
|
|
char uid[8];
|
|
|
|
char gid[8];
|
|
|
|
char size[12];
|
|
|
|
char mtime[12];
|
|
|
|
char chksum[8];
|
|
|
|
char typeflag;
|
|
|
|
char linkname[100];
|
|
|
|
char magic[6];
|
|
|
|
char version[2];
|
|
|
|
char uname[32];
|
|
|
|
char gname[32];
|
|
|
|
char devmajor[8];
|
|
|
|
char devminor[8];
|
|
|
|
char prefix[155];
|
|
|
|
char padding[12];
|
|
|
|
char *gnu_longname;
|
|
|
|
char *gnu_longlink;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/***** handle.c ************************************************************/
|
|
|
|
|
2005-12-30 22:22:46 +03:00
|
|
|
typedef int (*openfunc_t)(void* call_data, const char *, int, mode_t);
|
2005-12-30 22:51:15 +03:00
|
|
|
typedef int (*closefunc_t)(void* call_data);
|
|
|
|
typedef ssize_t (*readfunc_t)(void* call_data, void *, size_t);
|
|
|
|
typedef ssize_t (*writefunc_t)(void* call_data, const void *, size_t);
|
2005-12-28 18:18:37 +03:00
|
|
|
|
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
openfunc_t openfunc;
|
|
|
|
closefunc_t closefunc;
|
|
|
|
readfunc_t readfunc;
|
|
|
|
writefunc_t writefunc;
|
2005-12-30 22:22:46 +03:00
|
|
|
void* call_data;
|
2005-12-28 18:18:37 +03:00
|
|
|
}
|
|
|
|
tartype_t;
|
|
|
|
|
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
tartype_t *type;
|
|
|
|
char *pathname;
|
|
|
|
int oflags;
|
|
|
|
int options;
|
|
|
|
struct tar_header th_buf;
|
|
|
|
libtar_hash_t *h;
|
|
|
|
}
|
|
|
|
TAR;
|
|
|
|
|
|
|
|
/* constant values for the TAR options field */
|
|
|
|
#define TAR_GNU 1 /* use GNU extensions */
|
|
|
|
#define TAR_VERBOSE 2 /* output file info to stdout */
|
|
|
|
#define TAR_NOOVERWRITE 4 /* don't overwrite existing files */
|
|
|
|
#define TAR_IGNORE_EOT 8 /* ignore double zero blocks as EOF */
|
|
|
|
#define TAR_CHECK_MAGIC 16 /* check magic in file header */
|
|
|
|
#define TAR_CHECK_VERSION 32 /* check version in file header */
|
|
|
|
#define TAR_IGNORE_CRC 64 /* ignore CRC in file header */
|
|
|
|
|
|
|
|
/* this is obsolete - it's here for backwards-compatibility only */
|
|
|
|
#define TAR_IGNORE_MAGIC 0
|
|
|
|
|
|
|
|
extern const char libtar_version[];
|
|
|
|
|
|
|
|
/* open a new tarfile handle */
|
|
|
|
int tar_open(TAR **t, char *pathname, tartype_t *type,
|
|
|
|
int oflags, int mode, int options);
|
|
|
|
|
|
|
|
/* make a tarfile handle out of a previously-opened descriptor */
|
|
|
|
int tar_fdopen(TAR **t, int fd, char *pathname, tartype_t *type,
|
|
|
|
int oflags, int mode, int options);
|
|
|
|
|
|
|
|
/* close tarfile handle */
|
|
|
|
int tar_close(TAR *t);
|
|
|
|
|
|
|
|
|
|
|
|
/***** append.c ************************************************************/
|
|
|
|
|
|
|
|
/* forward declaration to appease the compiler */
|
|
|
|
struct tar_dev;
|
|
|
|
|
|
|
|
/* cleanup function */
|
|
|
|
void tar_dev_free(struct tar_dev *tdp);
|
|
|
|
|
|
|
|
/* Appends a file to the tar archive.
|
|
|
|
* Arguments:
|
|
|
|
* t = TAR handle to append to
|
|
|
|
* realname = path of file to append
|
|
|
|
* savename = name to save the file under in the archive
|
|
|
|
*/
|
|
|
|
int tar_append_file(TAR *t, char *realname, char *savename);
|
|
|
|
|
|
|
|
/* write EOF indicator */
|
|
|
|
int tar_append_eof(TAR *t);
|
|
|
|
|
|
|
|
/* add file contents to a tarchive */
|
|
|
|
int tar_append_regfile(TAR *t, char *realname);
|
|
|
|
|
|
|
|
|
|
|
|
/***** block.c *************************************************************/
|
|
|
|
|
|
|
|
/* macros for reading/writing tarchive blocks */
|
|
|
|
#define tar_block_read(t, buf) \
|
2005-12-30 22:51:15 +03:00
|
|
|
(*((t)->type->readfunc))((t)->type->call_data, (char *)(buf), T_BLOCKSIZE)
|
2005-12-28 18:18:37 +03:00
|
|
|
#define tar_block_write(t, buf) \
|
2005-12-30 22:51:15 +03:00
|
|
|
(*((t)->type->writefunc))((t)->type->call_data, (char *)(buf), T_BLOCKSIZE)
|
2005-12-28 18:18:37 +03:00
|
|
|
|
|
|
|
/* read/write a header block */
|
|
|
|
int th_read(TAR *t);
|
|
|
|
int th_write(TAR *t);
|
|
|
|
|
|
|
|
|
|
|
|
/***** decode.c ************************************************************/
|
|
|
|
|
|
|
|
/* determine file type */
|
|
|
|
#define TH_ISREG(t) ((t)->th_buf.typeflag == REGTYPE \
|
|
|
|
|| (t)->th_buf.typeflag == AREGTYPE \
|
|
|
|
|| (t)->th_buf.typeflag == CONTTYPE \
|
|
|
|
|| (S_ISREG((mode_t)oct_to_int((t)->th_buf.mode)) \
|
|
|
|
&& (t)->th_buf.typeflag != LNKTYPE))
|
|
|
|
#define TH_ISLNK(t) ((t)->th_buf.typeflag == LNKTYPE)
|
|
|
|
#define TH_ISSYM(t) ((t)->th_buf.typeflag == SYMTYPE \
|
|
|
|
|| S_ISLNK((mode_t)oct_to_int((t)->th_buf.mode)))
|
|
|
|
#define TH_ISCHR(t) ((t)->th_buf.typeflag == CHRTYPE \
|
|
|
|
|| S_ISCHR((mode_t)oct_to_int((t)->th_buf.mode)))
|
|
|
|
#define TH_ISBLK(t) ((t)->th_buf.typeflag == BLKTYPE \
|
|
|
|
|| S_ISBLK((mode_t)oct_to_int((t)->th_buf.mode)))
|
|
|
|
#define TH_ISDIR(t) ((t)->th_buf.typeflag == DIRTYPE \
|
|
|
|
|| S_ISDIR((mode_t)oct_to_int((t)->th_buf.mode)) \
|
|
|
|
|| ((t)->th_buf.typeflag == AREGTYPE \
|
|
|
|
&& ((t)->th_buf.name[strlen((t)->th_buf.name) - 1] == '/')))
|
|
|
|
#define TH_ISFIFO(t) ((t)->th_buf.typeflag == FIFOTYPE \
|
|
|
|
|| S_ISFIFO((mode_t)oct_to_int((t)->th_buf.mode)))
|
|
|
|
#define TH_ISLONGNAME(t) ((t)->th_buf.typeflag == GNU_LONGNAME_TYPE)
|
|
|
|
#define TH_ISLONGLINK(t) ((t)->th_buf.typeflag == GNU_LONGLINK_TYPE)
|
|
|
|
|
|
|
|
/* decode tar header info */
|
|
|
|
#define th_get_crc(t) oct_to_int((t)->th_buf.chksum)
|
|
|
|
#define th_get_size(t) oct_to_int((t)->th_buf.size)
|
|
|
|
#define th_get_mtime(t) oct_to_int((t)->th_buf.mtime)
|
|
|
|
#define th_get_devmajor(t) oct_to_int((t)->th_buf.devmajor)
|
|
|
|
#define th_get_devminor(t) oct_to_int((t)->th_buf.devminor)
|
|
|
|
#define th_get_linkname(t) ((t)->th_buf.gnu_longlink \
|
|
|
|
? (t)->th_buf.gnu_longlink \
|
|
|
|
: (t)->th_buf.linkname)
|
|
|
|
char *th_get_pathname(TAR *t);
|
|
|
|
mode_t th_get_mode(TAR *t);
|
|
|
|
uid_t th_get_uid(TAR *t);
|
|
|
|
gid_t th_get_gid(TAR *t);
|
|
|
|
|
|
|
|
|
|
|
|
/***** encode.c ************************************************************/
|
|
|
|
|
|
|
|
/* encode file info in th_header */
|
|
|
|
void th_set_type(TAR *t, mode_t mode);
|
|
|
|
void th_set_path(TAR *t, char *pathname);
|
|
|
|
void th_set_link(TAR *t, char *linkname);
|
|
|
|
void th_set_device(TAR *t, dev_t device);
|
|
|
|
void th_set_user(TAR *t, uid_t uid);
|
|
|
|
void th_set_group(TAR *t, gid_t gid);
|
|
|
|
void th_set_mode(TAR *t, mode_t fmode);
|
|
|
|
#define th_set_mtime(t, fmtime) \
|
|
|
|
int_to_oct_nonull((fmtime), (t)->th_buf.mtime, 12)
|
|
|
|
#define th_set_size(t, fsize) \
|
|
|
|
int_to_oct_nonull((fsize), (t)->th_buf.size, 12)
|
|
|
|
|
|
|
|
/* encode everything at once (except the pathname and linkname) */
|
|
|
|
void th_set_from_stat(TAR *t, struct stat *s);
|
|
|
|
|
|
|
|
/* encode magic, version, and crc - must be done after everything else is set */
|
|
|
|
void th_finish(TAR *t);
|
|
|
|
|
|
|
|
|
|
|
|
/***** extract.c ***********************************************************/
|
|
|
|
|
|
|
|
/* sequentially extract next file from t */
|
|
|
|
int tar_extract_file(TAR *t, char *realname);
|
|
|
|
|
|
|
|
/* extract different file types */
|
|
|
|
int tar_extract_dir(TAR *t, char *realname);
|
|
|
|
int tar_extract_hardlink(TAR *t, char *realname);
|
|
|
|
int tar_extract_symlink(TAR *t, char *realname);
|
|
|
|
int tar_extract_chardev(TAR *t, char *realname);
|
|
|
|
int tar_extract_blockdev(TAR *t, char *realname);
|
|
|
|
int tar_extract_fifo(TAR *t, char *realname);
|
|
|
|
|
|
|
|
/* for regfiles, we need to extract the content blocks as well */
|
|
|
|
int tar_extract_regfile(TAR *t, char *realname);
|
|
|
|
int tar_skip_regfile(TAR *t);
|
|
|
|
|
|
|
|
|
|
|
|
/***** output.c ************************************************************/
|
|
|
|
|
|
|
|
/* print the tar header */
|
|
|
|
void th_print(TAR *t);
|
|
|
|
|
|
|
|
/* print "ls -l"-like output for the file described by th */
|
|
|
|
void th_print_long_ls(TAR *t);
|
|
|
|
|
|
|
|
|
|
|
|
/***** util.c *************************************************************/
|
|
|
|
|
|
|
|
/* hashing function for pathnames */
|
|
|
|
int path_hashfunc(char *key, int numbuckets);
|
|
|
|
|
|
|
|
/* matching function for dev_t's */
|
|
|
|
int dev_match(dev_t *dev1, dev_t *dev2);
|
|
|
|
|
|
|
|
/* matching function for ino_t's */
|
|
|
|
int ino_match(ino_t *ino1, ino_t *ino2);
|
|
|
|
|
|
|
|
/* hashing function for dev_t's */
|
|
|
|
int dev_hash(dev_t *dev);
|
|
|
|
|
|
|
|
/* hashing function for ino_t's */
|
|
|
|
int ino_hash(ino_t *inode);
|
|
|
|
|
|
|
|
/* create any necessary dirs */
|
|
|
|
int mkdirhier(char *path);
|
|
|
|
|
|
|
|
/* calculate header checksum */
|
|
|
|
int th_crc_calc(TAR *t);
|
|
|
|
#define th_crc_ok(t) (th_get_crc(t) == th_crc_calc(t))
|
|
|
|
|
|
|
|
/* string-octal to integer conversion */
|
|
|
|
int oct_to_int(char *oct);
|
|
|
|
|
|
|
|
/* integer to NULL-terminated string-octal conversion */
|
|
|
|
#define int_to_oct(num, oct, octlen) \
|
|
|
|
snprintf((oct), (octlen), "%*lo ", (octlen) - 2, (unsigned long)(num))
|
|
|
|
|
|
|
|
/* integer to string-octal conversion, no NULL */
|
|
|
|
void int_to_oct_nonull(int num, char *oct, size_t octlen);
|
|
|
|
|
|
|
|
|
|
|
|
/***** wrapper.c **********************************************************/
|
|
|
|
|
|
|
|
/* extract groups of files */
|
|
|
|
int tar_extract_glob(TAR *t, char *globname, char *prefix);
|
|
|
|
int tar_extract_all(TAR *t, char *prefix);
|
|
|
|
|
|
|
|
/* add a whole tree of files */
|
|
|
|
int tar_append_tree(TAR *t, char *realdir, char *savedir);
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef __cplusplus
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#endif /* ! LIBTAR_H */
|
|
|
|
|