[Midnightbsd-cvs] src: usr.bin/tar: Upgrade to bsdtar 2.2.5
ctriv at midnightbsd.org
ctriv at midnightbsd.org
Sat Sep 29 18:15:57 EDT 2007
Log Message:
-----------
Upgrade to bsdtar 2.2.5
Modified Files:
--------------
src/usr.bin/tar:
COPYING (r1.2 -> r1.3)
Makefile (r1.2 -> r1.3)
bsdtar.1 (r1.2 -> r1.3)
bsdtar.c (r1.2 -> r1.3)
bsdtar.h (r1.2 -> r1.3)
bsdtar_platform.h (r1.2 -> r1.3)
getdate.y (r1.2 -> r1.3)
matching.c (r1.2 -> r1.3)
read.c (r1.2 -> r1.3)
tree.c (r1.2 -> r1.3)
tree.h (r1.2 -> r1.3)
util.c (r1.2 -> r1.3)
write.c (r1.2 -> r1.3)
Added Files:
-----------
src/usr.bin/tar:
config_midnightbsd.h (r1.1)
-------------- next part --------------
Index: util.c
===================================================================
RCS file: /home/cvs/src/usr.bin/tar/util.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -Lusr.bin/tar/util.c -Lusr.bin/tar/util.c -u -r1.2 -r1.3
--- usr.bin/tar/util.c
+++ usr.bin/tar/util.c
@@ -24,17 +24,29 @@
*/
#include "bsdtar_platform.h"
+__FBSDID("$FreeBSD: src/usr.bin/tar/util.c,v 1.17 2007/04/18 04:36:11 kientzle Exp $");
__MBSDID("$MidnightBSD$");
-__FBSDID("$FreeBSD: src/usr.bin/tar/util.c,v 1.13.2.2 2007/01/27 06:48:39 kientzle Exp $");
+#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
+#endif
+#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h> /* Linux doesn't define mode_t, etc. in sys/stat.h. */
+#endif
#include <ctype.h>
+#ifdef HAVE_ERRNO_H
#include <errno.h>
+#endif
+#ifdef HAVE_STDARG_H
#include <stdarg.h>
+#endif
#include <stdio.h>
+#ifdef HAVE_STDLIB_H
#include <stdlib.h>
+#endif
+#ifdef HAVE_STRING_H
#include <string.h>
+#endif
#include "bsdtar.h"
@@ -383,6 +395,8 @@
/*
* Handle --strip-components and any future path-rewriting options.
* Returns non-zero if the pathname should not be extracted.
+ *
+ * TODO: Support pax-style regex path rewrites.
*/
int
edit_pathname(struct bsdtar *bsdtar, struct archive_entry *entry)
@@ -407,10 +421,6 @@
}
}
- /* Strip redundant "./" from start of filename. */
- if (name[0] == '.' && name[1] == '/' && name[2] != '\0')
- name += 2;
-
/* Strip redundant leading '/' characters. */
while (name[0] == '/' && name[1] == '/')
name++;
@@ -437,3 +447,42 @@
}
return (0);
}
+
+/*
+ * Like strcmp(), but try to be a little more aware of the fact that
+ * we're comparing two paths. Right now, it just handles leading
+ * "./" and trailing '/' specially, so that "a/b/" == "./a/b"
+ *
+ * TODO: Make this better, so that "./a//b/./c/" == "a/b/c"
+ * TODO: After this works, push it down into libarchive.
+ * TODO: Publish the path normalization routines in libarchive so
+ * that bsdtar can normalize paths and use fast strcmp() instead
+ * of this.
+ */
+
+int
+pathcmp(const char *a, const char *b)
+{
+ /* Skip leading './' */
+ if (a[0] == '.' && a[1] == '/' && a[2] != '\0')
+ a += 2;
+ if (b[0] == '.' && b[1] == '/' && b[2] != '\0')
+ b += 2;
+ /* Find the first difference, or return (0) if none. */
+ while (*a == *b) {
+ if (*a == '\0')
+ return (0);
+ a++;
+ b++;
+ }
+ /*
+ * If one ends in '/' and the other one doesn't,
+ * they're the same.
+ */
+ if (a[0] == '/' && a[1] == '\0' && b[0] == '\0')
+ return (0);
+ if (a[0] == '\0' && b[0] == '/' && b[1] == '\0')
+ return (0);
+ /* They're really different, return the correct sign. */
+ return (*(const unsigned char *)a - *(const unsigned char *)b);
+}
Index: getdate.y
===================================================================
RCS file: /home/cvs/src/usr.bin/tar/getdate.y,v
retrieving revision 1.2
retrieving revision 1.3
diff -Lusr.bin/tar/getdate.y -Lusr.bin/tar/getdate.y -u -r1.2 -r1.3
--- usr.bin/tar/getdate.y
+++ usr.bin/tar/getdate.y
@@ -8,6 +8,7 @@
* (eliminate some state variables and post-processing). Among other
* things, these changes eliminated two shift/reduce conflicts. (Went
* from 10 to 8.)
+ * All of Tim Kientzle's changes to this file are public domain.
*/
/*
@@ -25,8 +26,7 @@
#ifdef __FreeBSD__
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
-__FBSDID("$FreeBSD: src/usr.bin/tar/getdate.y,v 1.4.2.2 2006/11/10 16:09:13 kientzle Exp $");
+__FBSDID("$FreeBSD: src/usr.bin/tar/getdate.y,v 1.9 2007/07/20 01:27:50 kientzle Exp $");
#endif
#include <ctype.h>
@@ -611,7 +611,7 @@
char buff[64];
for ( ; ; ) {
- while (isspace(*yyInput))
+ while (isspace((unsigned char)*yyInput))
yyInput++;
/* Skip parenthesized comments. */
@@ -638,11 +638,11 @@
/* Force to lowercase and strip '.' characters. */
while (*src != '\0'
- && (isalnum(*src) || *src == '.')
+ && (isalnum((unsigned char)*src) || *src == '.')
&& i < sizeof(buff)-1) {
if (*src != '.') {
- if (isupper(*src))
- buff[i++] = tolower(*src);
+ if (isupper((unsigned char)*src))
+ buff[i++] = tolower((unsigned char)*src);
else
buff[i++] = *src;
}
@@ -676,8 +676,8 @@
* Because '-' and '+' have other special meanings, I
* don't deal with signed numbers here.
*/
- if (isdigit(c = *yyInput)) {
- for (yylval.Number = 0; isdigit(c = *yyInput++); )
+ if (isdigit((unsigned char)(c = *yyInput))) {
+ for (yylval.Number = 0; isdigit((unsigned char)(c = *yyInput++)); )
yylval.Number = 10 * yylval.Number + c - '0';
yyInput--;
return (tUNUMBER);
Index: COPYING
===================================================================
RCS file: /home/cvs/src/usr.bin/tar/COPYING,v
retrieving revision 1.2
retrieving revision 1.3
diff -Lusr.bin/tar/COPYING -Lusr.bin/tar/COPYING -u -r1.2 -r1.3
--- usr.bin/tar/COPYING
+++ usr.bin/tar/COPYING
@@ -24,4 +24,4 @@
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-$FreeBSD: src/usr.bin/tar/COPYING,v 1.1.8.1 2007/01/27 06:48:39 kientzle Exp $
+$FreeBSD: src/usr.bin/tar/COPYING,v 1.2 2007/01/09 08:12:17 kientzle Exp $
Index: matching.c
===================================================================
RCS file: /home/cvs/src/usr.bin/tar/matching.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -Lusr.bin/tar/matching.c -Lusr.bin/tar/matching.c -u -r1.2 -r1.3
--- usr.bin/tar/matching.c
+++ usr.bin/tar/matching.c
@@ -24,12 +24,18 @@
*/
#include "bsdtar_platform.h"
+__FBSDID("$FreeBSD: src/usr.bin/tar/matching.c,v 1.11 2007/03/11 10:36:42 kientzle Exp $");
__MBSDID("$MidnightBSD$");
-__FBSDID("$FreeBSD: src/usr.bin/tar/matching.c,v 1.9.2.1 2007/01/27 06:48:39 kientzle Exp $");
+#ifdef HAVE_ERRNO_H
#include <errno.h>
+#endif
+#ifdef HAVE_STDLIB_H
#include <stdlib.h>
+#endif
+#ifdef HAVE_STRING_H
#include <string.h>
+#endif
#include "bsdtar.h"
--- /dev/null
+++ usr.bin/tar/config_midnightbsd.h
@@ -0,0 +1,101 @@
+/*-
+ * Copyright (c) 2003-2007 Tim Kientzle
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD: src/usr.bin/tar/config_freebsd.h,v 1.1 2007/03/11 10:36:42 kientzle Exp $
+ # $MidnightBSD: src/usr.bin/tar/config_midnightbsd.h,v 1.1 2007/09/29 22:15:57 ctriv Exp $
+ */
+
+/* A default configuration for FreeBSD, used if there is no config.h. */
+
+#define PACKAGE_NAME "bsdtar"
+
+#define HAVE_ACL_GET_PERM 0
+#define HAVE_ACL_GET_PERM_NP 1
+#define HAVE_ACL_PERMSET_T 1
+#define HAVE_ACL_USER 1
+#undef HAVE_ATTR_XATTR_H
+#define HAVE_BZLIB_H 1
+#define HAVE_CHFLAGS 1
+#define HAVE_DIRENT_D_NAMLEN 1
+#define HAVE_DIRENT_H 1
+#define HAVE_D_MD_ORDER 1
+#define HAVE_ERRNO_H 1
+#undef HAVE_EXT2FS_EXT2_FS_H
+#define HAVE_FCHDIR 1
+#define HAVE_FCNTL_H 1
+#define HAVE_FNMATCH 1
+#define HAVE_FNMATCH_H 1
+#define HAVE_FNM_LEADING_DIR 1
+#define HAVE_FTRUNCATE 1
+#define HAVE_GETOPT_LONG 1
+#undef HAVE_GETXATTR
+#define HAVE_GRP_H 1
+#define HAVE_INTTYPES_H 1
+#define HAVE_LANGINFO_H 1
+#undef HAVE_LGETXATTR
+#undef HAVE_LIBACL
+#define HAVE_LIBARCHIVE 1
+#define HAVE_LIBBZ2 1
+#define HAVE_LIBZ 1
+#define HAVE_LIMITS_H 1
+#undef HAVE_LINUX_EXT2_FS_H
+#undef HAVE_LINUX_FS_H
+#undef HAVE_LISTXATTR
+#undef HAVE_LLISTXATTR
+#define HAVE_LOCALE_H 1
+#define HAVE_MALLOC 1
+#define HAVE_MEMMOVE 1
+#define HAVE_MEMORY_H 1
+#define HAVE_MEMSET 1
+#define HAVE_NL_LANGINFO 1
+#define HAVE_PATHS_H 1
+#define HAVE_PWD_H 1
+#define HAVE_SETLOCALE 1
+#define HAVE_STDARG_H 1
+#define HAVE_STDINT_H 1
+#define HAVE_STDLIB_H 1
+#define HAVE_STRCHR 1
+#define HAVE_STRDUP 1
+#define HAVE_STRERROR 1
+#define HAVE_STRFTIME 1
+#define HAVE_STRINGS_H 1
+#define HAVE_STRING_H 1
+#define HAVE_STRRCHR 1
+#undef HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC
+#define HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC 1
+#define HAVE_STRUCT_STAT_ST_RDEV 1
+#define HAVE_SYS_ACL_H 1
+#define HAVE_SYS_IOCTL_H 1
+#define HAVE_SYS_PARAM_H 1
+#define HAVE_SYS_STAT_H 1
+#define HAVE_TIME_H 1
+#define HAVE_SYS_TYPES_H 1
+#define HAVE_UINTMAX_T 1
+#define HAVE_UNISTD_H 1
+#define HAVE_UNSIGNED_LONG_LONG
+#define HAVE_VPRINTF 1
+#define HAVE_ZLIB_H 1
+#undef MAJOR_IN_MKDEV
+#define STDC_HEADERS 1
+
Index: tree.h
===================================================================
RCS file: /home/cvs/src/usr.bin/tar/tree.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -Lusr.bin/tar/tree.h -Lusr.bin/tar/tree.h -u -r1.2 -r1.3
--- usr.bin/tar/tree.h
+++ usr.bin/tar/tree.h
@@ -22,8 +22,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $MidnightBSD$
- * $FreeBSD: src/usr.bin/tar/tree.h,v 1.2.2.1 2007/01/27 06:48:39 kientzle Exp $
+ * $FreeBSD: src/usr.bin/tar/tree.h,v 1.3 2007/01/09 08:12:17 kientzle Exp $
*/
/*-
Index: bsdtar.h
===================================================================
RCS file: /home/cvs/src/usr.bin/tar/bsdtar.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -Lusr.bin/tar/bsdtar.h -Lusr.bin/tar/bsdtar.h -u -r1.2 -r1.3
--- usr.bin/tar/bsdtar.h
+++ usr.bin/tar/bsdtar.h
@@ -22,8 +22,8 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
+ * $FreeBSD: src/usr.bin/tar/bsdtar.h,v 1.28 2007/05/29 05:39:10 kientzle Exp $
* $MidnightBSD$
- * $FreeBSD: src/usr.bin/tar/bsdtar.h,v 1.23.2.3 2007/01/27 06:48:39 kientzle Exp $
*/
#include "bsdtar_platform.h"
@@ -56,6 +56,7 @@
char mode; /* Program mode: 'c', 't', 'r', 'u', 'x' */
char symlink_mode; /* H or L, per BSD conventions */
char create_compression; /* j, y, or z */
+ const char *compress_program;
char option_absolute_paths; /* -P */
char option_dont_traverse_mounts; /* --one-file-system */
char option_fast_read; /* --fast-read */
@@ -109,6 +110,7 @@
int excluded(struct bsdtar *, const char *pathname);
int include(struct bsdtar *, const char *pattern);
int include_from_file(struct bsdtar *, const char *pathname);
+int pathcmp(const char *a, const char *b);
int process_lines(struct bsdtar *bsdtar, const char *pathname,
int (*process)(struct bsdtar *, const char *));
void safe_fprintf(FILE *, const char *fmt, ...);
Index: write.c
===================================================================
RCS file: /home/cvs/src/usr.bin/tar/write.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -Lusr.bin/tar/write.c -Lusr.bin/tar/write.c -u -r1.2 -r1.3
--- usr.bin/tar/write.c
+++ usr.bin/tar/write.c
@@ -24,30 +24,60 @@
*/
#include "bsdtar_platform.h"
+__FBSDID("$FreeBSD: src/usr.bin/tar/write.c,v 1.63 2007/05/29 05:39:10 kientzle Exp $");
__MBSDID("$MidnightBSD$");
-__FBSDID("$FreeBSD: src/usr.bin/tar/write.c,v 1.41.2.5 2007/02/25 07:24:44 kientzle Exp $");
-#include <sys/stat.h>
+#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
-#ifdef HAVE_POSIX_ACL
+#endif
+#ifdef HAVE_SYS_ACL_H
#include <sys/acl.h>
#endif
+#ifdef HAVE_SYS_IOCTL_H
+#include <sys/ioctl.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
#ifdef HAVE_ATTR_XATTR_H
#include <attr/xattr.h>
#endif
+#ifdef HAVE_ERRNO_H
#include <errno.h>
+#endif
+#ifdef HAVE_EXT2FS_EXT2_FS_H
+#include <ext2fs/ext2_fs.h>
+#endif
+#ifdef HAVE_FCNTL_H
#include <fcntl.h>
+#endif
+#ifdef HAVE_FNMATCH_H
#include <fnmatch.h>
+#endif
+#ifdef HAVE_GRP_H
#include <grp.h>
+#endif
+#ifdef HAVE_LIMITS_H
#include <limits.h>
+#endif
+#ifdef HAVE_LINUX_FS_H
+#include <linux/fs.h> /* for Linux file flags */
+#endif
+#ifdef HAVE_LINUX_EXT2_FS_H
+#include <linux/ext2_fs.h> /* for Linux file flags */
+#endif
+#ifdef HAVE_PWD_H
#include <pwd.h>
+#endif
#include <stdio.h>
+#ifdef HAVE_STDLIB_H
#include <stdlib.h>
+#endif
+#ifdef HAVE_STRING_H
#include <string.h>
+#endif
+#ifdef HAVE_UNISTD_H
#include <unistd.h>
-#ifdef __linux
-#include <ext2fs/ext2_fs.h>
-#include <sys/ioctl.h>
#endif
#include "bsdtar.h"
@@ -100,11 +130,15 @@
static void add_dir_list(struct bsdtar *bsdtar, const char *path,
time_t mtime_sec, int mtime_nsec);
static int append_archive(struct bsdtar *, struct archive *,
- const char *fname);
+ struct archive *ina);
+static int append_archive_filename(struct bsdtar *,
+ struct archive *, const char *fname);
static void archive_names_from_file(struct bsdtar *bsdtar,
struct archive *a);
static int archive_names_from_file_helper(struct bsdtar *bsdtar,
const char *line);
+static int copy_file_data(struct bsdtar *bsdtar,
+ struct archive *a, struct archive *ina);
static void create_cleanup(struct bsdtar *);
static void free_buckets(struct bsdtar *, struct links_cache *);
static void free_cache(struct name_cache *cache);
@@ -126,7 +160,7 @@
static void write_archive(struct archive *, struct bsdtar *);
static void write_entry(struct bsdtar *, struct archive *,
const struct stat *, const char *pathname,
- unsigned pathlen, const char *accpath);
+ const char *accpath);
static int write_file_data(struct bsdtar *, struct archive *,
int fd);
static void write_hierarchy(struct bsdtar *, struct archive *,
@@ -170,23 +204,28 @@
} else
archive_write_set_bytes_per_block(a, DEFAULT_BYTES_PER_BLOCK);
- switch (bsdtar->create_compression) {
- case 0:
- break;
+ if (bsdtar->compress_program) {
+ archive_write_set_compression_program(a, bsdtar->compress_program);
+ } else {
+ switch (bsdtar->create_compression) {
+ case 0:
+ archive_write_set_compression_none(a);
+ break;
#ifdef HAVE_LIBBZ2
- case 'j': case 'y':
- archive_write_set_compression_bzip2(a);
- break;
+ case 'j': case 'y':
+ archive_write_set_compression_bzip2(a);
+ break;
#endif
#ifdef HAVE_LIBZ
- case 'z':
- archive_write_set_compression_gzip(a);
- break;
+ case 'z':
+ archive_write_set_compression_gzip(a);
+ break;
#endif
- default:
- bsdtar_errc(bsdtar, 1, 0,
- "Unrecognized compression option -%c",
- bsdtar->create_compression);
+ default:
+ bsdtar_errc(bsdtar, 1, 0,
+ "Unrecognized compression option -%c",
+ bsdtar->create_compression);
+ }
}
r = archive_write_open_file(a, bsdtar->filename);
@@ -421,10 +460,11 @@
}
set_chdir(bsdtar, arg);
} else {
- if (*arg != '/' || (arg[0] == '@' && arg[1] != '/'))
+ if (*arg != '/' && (arg[0] != '@' || arg[1] != '/'))
do_chdir(bsdtar); /* Handle a deferred -C */
if (*arg == '@') {
- if (append_archive(bsdtar, a, arg + 1) != 0)
+ if (append_archive_filename(bsdtar, a,
+ arg + 1) != 0)
break;
} else
write_hierarchy(bsdtar, a, arg);
@@ -484,12 +524,11 @@
* operation will complete and return non-zero.
*/
static int
-append_archive(struct bsdtar *bsdtar, struct archive *a, const char *filename)
+append_archive_filename(struct bsdtar *bsdtar, struct archive *a,
+ const char *filename)
{
struct archive *ina;
- struct archive_entry *in_entry;
- int bytes_read, bytes_written;
- char buff[8192];
+ int rc;
if (strcmp(filename, "-") == 0)
filename = NULL; /* Library uses NULL for stdio. */
@@ -502,6 +541,25 @@
bsdtar->return_value = 1;
return (0);
}
+
+ rc = append_archive(bsdtar, a, ina);
+
+ if (archive_errno(ina)) {
+ bsdtar_warnc(bsdtar, 0, "Error reading archive %s: %s",
+ filename, archive_error_string(ina));
+ bsdtar->return_value = 1;
+ }
+ archive_read_finish(ina);
+
+ return (rc);
+}
+
+static int
+append_archive(struct bsdtar *bsdtar, struct archive *a, struct archive *ina)
+{
+ struct archive_entry *in_entry;
+ int e;
+
while (0 == archive_read_next_header(ina, &in_entry)) {
if (!new_enough(bsdtar, archive_entry_pathname(in_entry),
archive_entry_stat(in_entry)))
@@ -514,40 +572,52 @@
if (bsdtar->verbose)
safe_fprintf(stderr, "a %s",
archive_entry_pathname(in_entry));
- /* XXX handle/report errors XXX */
- if (archive_write_header(a, in_entry)) {
- bsdtar_warnc(bsdtar, 0, "%s",
- archive_error_string(a));
- bsdtar->return_value = 1;
- return (-1);
- }
- bytes_read = archive_read_data(ina, buff, sizeof(buff));
- while (bytes_read > 0) {
- bytes_written =
- archive_write_data(a, buff, bytes_read);
- if (bytes_written < bytes_read) {
- bsdtar_warnc(bsdtar, archive_errno(a), "%s",
+
+ e = archive_write_header(a, in_entry);
+ if (e != ARCHIVE_OK) {
+ if (!bsdtar->verbose)
+ bsdtar_warnc(bsdtar, 0, "%s: %s",
+ archive_entry_pathname(in_entry),
archive_error_string(a));
- return (-1);
- }
- bytes_read =
- archive_read_data(ina, buff, sizeof(buff));
+ else
+ fprintf(stderr, ": %s", archive_error_string(a));
}
+ if (e == ARCHIVE_FATAL)
+ exit(1);
+
+ if (e >= ARCHIVE_WARN)
+ if (copy_file_data(bsdtar, a, ina))
+ exit(1);
+
if (bsdtar->verbose)
fprintf(stderr, "\n");
-
}
- if (archive_errno(ina)) {
- bsdtar_warnc(bsdtar, 0, "Error reading archive %s: %s",
- filename, archive_error_string(ina));
- bsdtar->return_value = 1;
- }
- archive_read_finish(ina);
/* Note: If we got here, we saw no write errors, so return success. */
return (0);
}
+/* Helper function to copy data between archives. */
+static int
+copy_file_data(struct bsdtar *bsdtar, struct archive *a, struct archive *ina)
+{
+ char buff[64*1024];
+ ssize_t bytes_read;
+ ssize_t bytes_written;
+
+ bytes_read = archive_read_data(ina, buff, sizeof(buff));
+ while (bytes_read > 0) {
+ bytes_written = archive_write_data(a, buff, bytes_read);
+ if (bytes_written < bytes_read) {
+ bsdtar_warnc(bsdtar, 0, "%s", archive_error_string(a));
+ return (-1);
+ }
+ bytes_read = archive_read_data(ina, buff, sizeof(buff));
+ }
+
+ return (0);
+}
+
/*
* Add the file or dir hierarchy named by 'path' to the archive
*/
@@ -584,8 +654,17 @@
lst = tree_current_lstat(tree);
if (lst == NULL) {
/* Couldn't lstat(); must not exist. */
- bsdtar_warnc(bsdtar, errno, "%s: Cannot stat", path);
- bsdtar->return_value = 1;
+ bsdtar_warnc(bsdtar, errno, "%s: Cannot stat", name);
+
+ /*
+ * Report an error via the exit code if the failed
+ * path is a prefix of what the user provided via
+ * the command line. (Testing for string equality
+ * here won't work due to trailing '/' characters.)
+ */
+ if (memcmp(name, path, strlen(name)) == 0)
+ bsdtar->return_value = 1;
+
continue;
}
if (S_ISLNK(lst->st_mode))
@@ -690,7 +769,6 @@
* pathname editing and newness testing.
*/
write_entry(bsdtar, a, lst, name,
- tree_current_pathlen(tree),
tree_current_access_path(tree));
}
tree_close(tree);
@@ -701,7 +779,7 @@
*/
static void
write_entry(struct bsdtar *bsdtar, struct archive *a, const struct stat *st,
- const char *pathname, unsigned pathlen, const char *accpath)
+ const char *pathname, const char *accpath)
{
struct archive_entry *entry;
int e;
@@ -712,8 +790,6 @@
#endif
static char linkbuffer[PATH_MAX+1];
- (void)pathlen; /* UNUSED */
-
fd = -1;
entry = archive_entry_new();
@@ -821,7 +897,7 @@
* to inform us that the archive body won't get stored. In
* that case, just skip the write.
*/
- if (fd >= 0 && archive_entry_size(entry) > 0)
+ if (e >= ARCHIVE_WARN && fd >= 0 && archive_entry_size(entry) > 0)
if (write_file_data(bsdtar, a, fd))
exit(1);
@@ -1396,7 +1472,7 @@
if (bsdtar->archive_dir != NULL &&
bsdtar->archive_dir->head != NULL) {
for (p = bsdtar->archive_dir->head; p != NULL; p = p->next) {
- if (strcmp(path, p->name)==0)
+ if (pathcmp(path, p->name)==0)
return (p->mtime_sec < st->st_mtime ||
(p->mtime_sec == st->st_mtime &&
p->mtime_nsec
@@ -1419,9 +1495,6 @@
{
struct archive_dir_entry *p;
- if (path[0] == '.' && path[1] == '/' && path[2] != '\0')
- path += 2;
-
/*
* Search entire list to see if this file has appeared before.
* If it has, override the timestamp data.
Index: bsdtar.1
===================================================================
RCS file: /home/cvs/src/usr.bin/tar/bsdtar.1,v
retrieving revision 1.2
retrieving revision 1.3
diff -Lusr.bin/tar/bsdtar.1 -Lusr.bin/tar/bsdtar.1 -u -r1.2 -r1.3
--- usr.bin/tar/bsdtar.1
+++ usr.bin/tar/bsdtar.1
@@ -22,8 +22,8 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
+.\" $FreeBSD: src/usr.bin/tar/bsdtar.1,v 1.35 2007/05/29 05:39:10 kientzle Exp $
.\" $MidnightBSD$
-.\" $FreeBSD: src/usr.bin/tar/bsdtar.1,v 1.29.2.3 2007/01/27 06:48:39 kientzle Exp $
.\"
.Dd April 13, 2004
.Dt BSDTAR 1
@@ -51,6 +51,9 @@
.Sh DESCRIPTION
.Nm
creates and manipulates streaming archive files.
+This implementation can extract from tar, pax, cpio, zip, jar, ar,
+and ISO 9660 cdrom images and can create tar, pax, cpio, ar,
+and shar archives.
.Pp
The first synopsis form shows a
.Dq bundled
@@ -358,6 +361,10 @@
overwrites existing files, which preserves existing hardlinks.
With this option, existing hardlinks will be broken, as will any
symlink that would affect the location of an extracted file.
+.It Fl -use-compress-program Ar program
+Pipe the input (in x or t mode) or the output (in c mode) through
+.Pa program
+instead of using the builtin compression support.
.It Fl v
Produce verbose output.
In create and extract modes,
@@ -461,6 +468,9 @@
the default tape drive:
.Dl Nm Fl x
.Pp
+To examine the contents of an ISO 9660 cdrom image:
+.Dl Nm Fl tf Pa image.iso
+.Pp
To move file hierarchies, invoke
.Nm
as
Index: bsdtar.c
===================================================================
RCS file: /home/cvs/src/usr.bin/tar/bsdtar.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -Lusr.bin/tar/bsdtar.c -Lusr.bin/tar/bsdtar.c -u -r1.2 -r1.3
--- usr.bin/tar/bsdtar.c
+++ usr.bin/tar/bsdtar.c
@@ -24,13 +24,21 @@
*/
#include "bsdtar_platform.h"
+__FBSDID("$FreeBSD: src/usr.bin/tar/bsdtar.c,v 1.77 2007/09/09 00:07:18 kientzle Exp $");
__MBSDID("$MidnightBSD$");
-__FBSDID("$FreeBSD: src/usr.bin/tar/bsdtar.c,v 1.63.2.5 2007/01/27 06:48:39 kientzle Exp $");
+#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
+#endif
+#ifdef HAVE_ERRNO_H
#include <errno.h>
+#endif
+#ifdef HAVE_FCNTL_H
#include <fcntl.h>
+#endif
#ifdef HAVE_GETOPT_LONG
#include <getopt.h>
#else
@@ -46,21 +54,35 @@
#ifdef HAVE_LANGINFO_H
#include <langinfo.h>
#endif
+#ifdef HAVE_LOCALE_H
#include <locale.h>
+#endif
#ifdef HAVE_PATHS_H
#include <paths.h>
#endif
#include <stdio.h>
+#ifdef HAVE_STDLIB_H
#include <stdlib.h>
+#endif
+#ifdef HAVE_STRING_H
#include <string.h>
+#endif
+#ifdef HAVE_TIME_H
#include <time.h>
+#endif
+#ifdef HAVE_UNISTD_H
#include <unistd.h>
+#endif
#if HAVE_ZLIB_H
#include <zlib.h>
#endif
#include "bsdtar.h"
+/*
+ * Per POSIX.1-1988, tar defaults to reading/writing archives to/from
+ * the default tape device for the system. Pick something reasonable here.
+ */
#ifdef __linux
#define _PATH_DEFTAPE "/dev/st0"
#endif
@@ -118,11 +140,14 @@
OPTION_NEWER_MTIME,
OPTION_NEWER_MTIME_THAN,
OPTION_NODUMP,
+ OPTION_NO_SAME_OWNER,
OPTION_NO_SAME_PERMISSIONS,
OPTION_NULL,
OPTION_ONE_FILE_SYSTEM,
+ OPTION_POSIX,
OPTION_STRIP_COMPONENTS,
OPTION_TOTALS,
+ OPTION_USE_COMPRESS_PROGRAM,
OPTION_VERSION
};
@@ -167,10 +192,11 @@
{ "nodump", no_argument, NULL, OPTION_NODUMP },
{ "norecurse", no_argument, NULL, 'n' },
{ "no-recursion", no_argument, NULL, 'n' },
- { "no-same-owner", no_argument, NULL, 'o' },
+ { "no-same-owner", no_argument, NULL, OPTION_NO_SAME_OWNER },
{ "no-same-permissions",no_argument, NULL, OPTION_NO_SAME_PERMISSIONS },
{ "null", no_argument, NULL, OPTION_NULL },
{ "one-file-system", no_argument, NULL, OPTION_ONE_FILE_SYSTEM },
+ { "posix", no_argument, NULL, OPTION_POSIX },
{ "preserve-permissions", no_argument, NULL, 'p' },
{ "read-full-blocks", no_argument, NULL, 'B' },
{ "same-permissions", no_argument, NULL, 'p' },
@@ -180,11 +206,18 @@
{ "unlink", no_argument, NULL, 'U' },
{ "unlink-first", no_argument, NULL, 'U' },
{ "update", no_argument, NULL, 'u' },
+ { "use-compress-program",
+ required_argument, NULL, OPTION_USE_COMPRESS_PROGRAM },
{ "verbose", no_argument, NULL, 'v' },
{ "version", no_argument, NULL, OPTION_VERSION },
{ NULL, 0, NULL, 0 }
};
+/* A basic set of security flags to request from libarchive. */
+#define SECURITY \
+ (ARCHIVE_EXTRACT_SECURE_SYMLINKS \
+ | ARCHIVE_EXTRACT_SECURE_NODOTDOT)
+
int
main(int argc, char **argv)
{
@@ -233,9 +266,19 @@
/* Default: preserve mod time on extract */
bsdtar->extract_flags = ARCHIVE_EXTRACT_TIME;
- /* Default for root user: preserve ownership on extract. */
- if (bsdtar->user_uid == 0)
+ /* Default: Perform basic security checks. */
+ bsdtar->extract_flags |= SECURITY;
+
+ /* Defaults for root user: */
+ if (bsdtar->user_uid == 0) {
+ /* --same-owner */
bsdtar->extract_flags |= ARCHIVE_EXTRACT_OWNER;
+ /* -p */
+ bsdtar->extract_flags |= ARCHIVE_EXTRACT_PERM;
+ bsdtar->extract_flags |= ARCHIVE_EXTRACT_ACL;
+ bsdtar->extract_flags |= ARCHIVE_EXTRACT_XATTR;
+ bsdtar->extract_flags |= ARCHIVE_EXTRACT_FFLAGS;
+ }
/* Rewrite traditional-style tar arguments, if used. */
argv = rewrite_argv(bsdtar, &argc, argv, tar_opts);
@@ -244,6 +287,12 @@
bsdtar->argc = argc;
/* Process all remaining arguments now. */
+ /*
+ * Comments following each option indicate where that option
+ * originated: SUSv2, POSIX, GNU tar, star, etc. If there's
+ * no such comment, then I don't know of anyone else who
+ * implements that option.
+ */
while ((opt = bsdtar_getopt(bsdtar, tar_opts, &option)) != -1) {
switch (opt) {
case 'B': /* GNU tar */
@@ -270,7 +319,7 @@
bsdtar_errc(bsdtar, 1, 0,
"Couldn't exclude %s\n", optarg);
break;
- case OPTION_FORMAT:
+ case OPTION_FORMAT: /* GNU tar, others */
bsdtar->create_format = optarg;
break;
case 'f': /* SUSv2 */
@@ -289,14 +338,29 @@
/* Hack: -h by itself is the "help" command. */
possible_help_request = 1;
break;
- case OPTION_HELP:
+ case OPTION_HELP: /* GNU tar, others */
long_help(bsdtar);
exit(0);
break;
case 'I': /* GNU tar */
+ /*
+ * TODO: Allow 'names' to come from an archive,
+ * not just a text file. Design a good UI for
+ * allowing names and mode/owner to be read
+ * from an archive, with contents coming from
+ * disk. This can be used to "refresh" an
+ * archive or to design archives with special
+ * permissions without having to create those
+ * permissions on disk.
+ */
bsdtar->names_from_file = optarg;
break;
case OPTION_INCLUDE:
+ /*
+ * Noone else has the @archive extension, so
+ * noone else needs this to filter entries
+ * when transforming archives.
+ */
if (include(bsdtar, optarg))
bsdtar_errc(bsdtar, 1, 0,
"Failed to add %s to inclusion list",
@@ -340,6 +404,13 @@
case 'n': /* GNU tar */
bsdtar->option_no_subdirs = 1;
break;
+ /*
+ * Selecting files by time:
+ * --newer-?time='date' Only files newer than 'date'
+ * --newer-?time-than='file' Only files newer than time
+ * on specified file (useful for incremental backups)
+ * TODO: Add corresponding "older" options to reverse these.
+ */
case OPTION_NEWER_CTIME: /* GNU tar */
bsdtar->newer_ctime_sec = get_date(optarg);
break;
@@ -371,13 +442,14 @@
case OPTION_NODUMP: /* star */
bsdtar->option_honor_nodump = 1;
break;
+ case OPTION_NO_SAME_OWNER: /* GNU tar */
+ bsdtar->extract_flags &= ~ARCHIVE_EXTRACT_OWNER;
+ break;
case OPTION_NO_SAME_PERMISSIONS: /* GNU tar */
- /*
- * This is always the default in FreeBSD's
- * version of GNU tar; it's also the default
- * behavior for bsdtar, so treat the
- * command-line option as a no-op.
- */
+ bsdtar->extract_flags &= ~ARCHIVE_EXTRACT_PERM;
+ bsdtar->extract_flags &= ~ARCHIVE_EXTRACT_ACL;
+ bsdtar->extract_flags &= ~ARCHIVE_EXTRACT_XATTR;
+ bsdtar->extract_flags &= ~ARCHIVE_EXTRACT_FFLAGS;
break;
case OPTION_NULL: /* GNU tar */
bsdtar->option_null++;
@@ -385,10 +457,10 @@
case 'O': /* GNU tar */
bsdtar->option_stdout = 1;
break;
- case 'o': /* SUSv2 and GNU conflict here */
+ case 'o': /* SUSv2 and GNU conflict here, but not fatally */
option_o = 1; /* Record it and resolve it later. */
break;
- case OPTION_ONE_FILE_SYSTEM: /* -l in GNU tar */
+ case OPTION_ONE_FILE_SYSTEM: /* GNU tar */
bsdtar->option_dont_traverse_mounts = 1;
break;
#if 0
@@ -403,6 +475,7 @@
break;
#endif
case 'P': /* GNU tar */
+ bsdtar->extract_flags &= ~SECURITY;
bsdtar->option_absolute_paths = 1;
break;
case 'p': /* GNU tar, star */
@@ -411,6 +484,9 @@
bsdtar->extract_flags |= ARCHIVE_EXTRACT_XATTR;
bsdtar->extract_flags |= ARCHIVE_EXTRACT_FFLAGS;
break;
+ case OPTION_POSIX: /* GNU tar */
+ bsdtar->create_format = "pax";
+ break;
case 'r': /* SUSv2 */
set_mode(bsdtar, opt);
break;
@@ -437,9 +513,17 @@
case 'v': /* SUSv2 */
bsdtar->verbose++;
break;
- case OPTION_VERSION:
+ case OPTION_VERSION: /* GNU convention */
version();
break;
+#if 0
+ /*
+ * The -W longopt feature is handled inside of
+ * bsdtar_getop(), so -W is not available here.
+ */
+ case 'W': /* Obscure, but useful GNU convention. */
+ break;
+#endif
case 'w': /* SUSv2 */
bsdtar->option_interactive = 1;
break;
@@ -483,6 +567,9 @@
usage(bsdtar);
#endif
break;
+ case OPTION_USE_COMPRESS_PROGRAM:
+ bsdtar->compress_program = optarg;
+ break;
default:
usage(bsdtar);
}
@@ -491,11 +578,14 @@
/*
* Sanity-check options.
*/
+
+ /* If no "real" mode was specified, treat -h as --help. */
if ((bsdtar->mode == '\0') && possible_help_request) {
long_help(bsdtar);
exit(0);
}
+ /* Otherwise, a mode is required. */
if (bsdtar->mode == '\0')
bsdtar_errc(bsdtar, 1, 0,
"Must specify one of -c, -r, -t, -u, -x");
@@ -579,6 +669,9 @@
}
cleanup_exclusions(bsdtar);
+ if (bsdtar->return_value != 0)
+ bsdtar_warnc(bsdtar, 0,
+ "Error exit delayed from previous errors.");
return (bsdtar->return_value);
}
@@ -824,6 +917,10 @@
"(matches both %s and %s)",
p, (*poption)->name, option->name);
+ if ((*poption)->has_arg == required_argument
+ && optarg == NULL)
+ bsdtar_errc(bsdtar, 1, 0,
+ "Option \"%s\" requires argument", p);
} else {
opt = '?';
/* TODO: Set up a fake 'struct option' for
Index: Makefile
===================================================================
RCS file: /home/cvs/src/usr.bin/tar/Makefile,v
retrieving revision 1.2
retrieving revision 1.3
diff -Lusr.bin/tar/Makefile -Lusr.bin/tar/Makefile -u -r1.2 -r1.3
--- usr.bin/tar/Makefile
+++ usr.bin/tar/Makefile
@@ -1,13 +1,14 @@
+# $FreeBSD: src/usr.bin/tar/Makefile,v 1.32 2007/07/20 01:24:49 kientzle Exp $
# $MidnightBSD$
-# $FreeBSD: src/usr.bin/tar/Makefile,v 1.24.2.1 2006/07/30 06:32:14 kientzle Exp $
PROG= bsdtar
-VERSION= 1.2.53
+VERSION= 2.2.5
SRCS= bsdtar.c getdate.y matching.c read.c tree.c util.c write.c
WARNS?= 5
DPADD= ${LIBARCHIVE} ${LIBBZ2} ${LIBZ}
LDADD= -larchive -lbz2 -lz
CFLAGS+= -DPACKAGE_VERSION=\"${VERSION}\"
+CFLAGS+= -DPLATFORM_CONFIG_H=\"config_midnightbsd.h\"
CFLAGS+= -I${.CURDIR}
SYMLINKS= bsdtar ${BINDIR}/tar
MLINKS= bsdtar.1 tar.1
Index: tree.c
===================================================================
RCS file: /home/cvs/src/usr.bin/tar/tree.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -Lusr.bin/tar/tree.c -Lusr.bin/tar/tree.c -u -r1.2 -r1.3
--- usr.bin/tar/tree.c
+++ usr.bin/tar/tree.c
@@ -43,16 +43,30 @@
* regular dir or via fchdir(2) for a symlink).
*/
#include "bsdtar_platform.h"
+__FBSDID("$FreeBSD: src/usr.bin/tar/tree.c,v 1.8 2007/03/11 10:36:42 kientzle Exp $");
__MBSDID("$MidnightBSD$");
-__FBSDID("$FreeBSD: src/usr.bin/tar/tree.c,v 1.2.2.2 2007/01/27 06:48:39 kientzle Exp $");
+#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
+#endif
+#ifdef HAVE_DIRENT_H
#include <dirent.h>
+#endif
+#ifdef HAVE_ERRNO_H
#include <errno.h>
+#endif
+#ifdef HAVE_FCNTL_H
#include <fcntl.h>
+#endif
+#ifdef HAVE_STDLIB_H
#include <stdlib.h>
+#endif
+#ifdef HAVE_STRING_H
#include <string.h>
+#endif
+#ifdef HAVE_UNISTD_H
#include <unistd.h>
+#endif
#include "tree.h"
@@ -394,46 +408,70 @@
}
/*
- * Test whether current entry is a dir or dir link.
+ * Test whether current entry is a dir or link to a dir.
*/
int
tree_current_is_dir(struct tree *t)
{
- /* If we've already pulled stat(), just use that. */
- if (t->flags & hasStat)
- return (S_ISDIR(tree_current_stat(t)->st_mode));
+ const struct stat *st;
- /* If we've already pulled lstat(), we may be able to use that. */
+ /*
+ * If we already have lstat() info, then try some
+ * cheap tests to determine if this is a dir.
+ */
if (t->flags & hasLstat) {
/* If lstat() says it's a dir, it must be a dir. */
if (S_ISDIR(tree_current_lstat(t)->st_mode))
return 1;
- /* If it's not a dir and not a link, we're done. */
+ /* Not a dir; might be a link to a dir. */
+ /* If it's not a link, then it's not a link to a dir. */
if (!S_ISLNK(tree_current_lstat(t)->st_mode))
return 0;
/*
- * If the above two tests fail, then it's a link, but
- * we don't know whether it's a link to a dir or a
- * non-dir.
+ * It's a link, but we don't know what it's a link to,
+ * so we'll have to use stat().
*/
}
- /* TODO: Use a more efficient mechanism when available. */
- return (S_ISDIR(tree_current_stat(t)->st_mode));
+ st = tree_current_stat(t);
+ /* If we can't stat it, it's not a dir. */
+ if (st == NULL)
+ return 0;
+ /* Use the definitive test. Hopefully this is cached. */
+ return (S_ISDIR(st->st_mode));
}
/*
- * Test whether current entry is a physical directory.
+ * Test whether current entry is a physical directory. Usually, we
+ * already have at least one of stat() or lstat() in memory, so we
+ * use tricks to try to avoid an extra trip to the disk.
*/
int
tree_current_is_physical_dir(struct tree *t)
{
- /* If we've already pulled lstat(), just use that. */
- if (t->flags & hasLstat)
- return (S_ISDIR(tree_current_lstat(t)->st_mode));
+ const struct stat *st;
+
+ /*
+ * If stat() says it isn't a dir, then it's not a dir.
+ * If stat() data is cached, this check is free, so do it first.
+ */
+ if ((t->flags & hasStat)
+ && (!S_ISDIR(tree_current_stat(t)->st_mode)))
+ return 0;
- /* TODO: Use a more efficient mechanism when available. */
- return (S_ISDIR(tree_current_lstat(t)->st_mode));
+ /*
+ * Either stat() said it was a dir (in which case, we have
+ * to determine whether it's really a link to a dir) or
+ * stat() info wasn't available. So we use lstat(), which
+ * hopefully is already cached.
+ */
+
+ st = tree_current_lstat(t);
+ /* If we can't stat it, it's not a dir. */
+ if (st == NULL)
+ return 0;
+ /* Use the definitive test. Hopefully this is cached. */
+ return (S_ISDIR(st->st_mode));
}
/*
@@ -442,12 +480,10 @@
int
tree_current_is_physical_link(struct tree *t)
{
- /* If we've already pulled lstat(), just use that. */
- if (t->flags & hasLstat)
- return (S_ISLNK(tree_current_lstat(t)->st_mode));
-
- /* TODO: Use a more efficient mechanism when available. */
- return (S_ISLNK(tree_current_lstat(t)->st_mode));
+ const struct stat *st = tree_current_lstat(t);
+ if (st == NULL)
+ return 0;
+ return (S_ISLNK(st->st_mode));
}
/*
Index: read.c
===================================================================
RCS file: /home/cvs/src/usr.bin/tar/read.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -Lusr.bin/tar/read.c -Lusr.bin/tar/read.c -u -r1.2 -r1.3
--- usr.bin/tar/read.c
+++ usr.bin/tar/read.c
@@ -24,33 +24,55 @@
*/
#include "bsdtar_platform.h"
+__FBSDID("$FreeBSD: src/usr.bin/tar/read.c,v 1.34 2007/07/20 01:24:49 kientzle Exp $");
__MBSDID("$MidnightBSD$");
-__FBSDID("$FreeBSD: src/usr.bin/tar/read.c,v 1.23.2.3 2007/01/27 06:48:39 kientzle Exp $");
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
#ifdef MAJOR_IN_MKDEV
#include <sys/mkdev.h>
+#elif defined(MAJOR_IN_SYSMACROS)
+#include <sys/sysmacros.h>
#endif
+#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
-#include <sys/types.h>
+#endif
+#ifdef HAVE_ERRNO_H
#include <errno.h>
+#endif
+#ifdef HAVE_GRP_H
#include <grp.h>
+#endif
+#ifdef HAVE_LIMITS_H
#include <limits.h>
+#endif
+#ifdef HAVE_PWD_H
#include <pwd.h>
+#endif
#include <stdio.h>
+#ifdef HAVE_STDLIB_H
#include <stdlib.h>
+#endif
+#ifdef HAVE_STRING_H
#include <string.h>
+#endif
+#ifdef HAVE_TIME_H
#include <time.h>
+#endif
+#ifdef HAVE_UNISTD_H
#include <unistd.h>
+#endif
#include "bsdtar.h"
-static void cleanup_security(struct bsdtar *);
static void list_item_verbose(struct bsdtar *, FILE *,
struct archive_entry *);
static void read_archive(struct bsdtar *bsdtar, char mode);
-static int security_problem(struct bsdtar *, struct archive_entry *);
void
tar_mode_t(struct bsdtar *bsdtar)
@@ -85,7 +107,10 @@
include_from_file(bsdtar, bsdtar->names_from_file);
a = archive_read_new();
- archive_read_support_compression_all(a);
+ if (bsdtar->compress_program != NULL)
+ archive_read_support_compression_program(a, bsdtar->compress_program);
+ else
+ archive_read_support_compression_all(a);
archive_read_support_format_all(a);
if (archive_read_open_file(a, bsdtar->filename,
bsdtar->bytes_per_block != 0 ? bsdtar->bytes_per_block :
@@ -103,19 +128,17 @@
r = archive_read_next_header(a, &entry);
if (r == ARCHIVE_EOF)
break;
- if (r == ARCHIVE_WARN)
+ if (r < ARCHIVE_OK)
bsdtar_warnc(bsdtar, 0, "%s", archive_error_string(a));
- if (r == ARCHIVE_FATAL) {
+ if (r <= ARCHIVE_WARN)
bsdtar->return_value = 1;
- bsdtar_warnc(bsdtar, 0, "%s", archive_error_string(a));
- break;
- }
if (r == ARCHIVE_RETRY) {
/* Retryable error: try again */
- bsdtar_warnc(bsdtar, 0, "%s", archive_error_string(a));
bsdtar_warnc(bsdtar, 0, "Retrying...");
continue;
}
+ if (r == ARCHIVE_FATAL)
+ break;
/*
* Exclude entries that are too old.
@@ -187,19 +210,11 @@
fprintf(out, "\n");
bsdtar_warnc(bsdtar, 0, "%s",
archive_error_string(a));
+ bsdtar->return_value = 1;
break;
}
fprintf(out, "\n");
} else {
- /*
- * Skip security problems before prompting.
- * Otherwise, the user may be confused that a
- * file they wanted to extract was
- * subsequently skipped.
- */
- if (security_problem(bsdtar, entry))
- continue;
-
if (bsdtar->option_interactive &&
!yes("extract '%s'", archive_entry_pathname(entry)))
continue;
@@ -213,11 +228,12 @@
archive_entry_pathname(entry));
fflush(stderr);
}
- if (bsdtar->option_stdout) {
- /* TODO: Catch/recover any errors here. */
- archive_read_data_into_fd(a, 1);
- } else if (archive_read_extract(a, entry,
- bsdtar->extract_flags)) {
+ if (bsdtar->option_stdout)
+ r = archive_read_data_into_fd(a, 1);
+ else
+ r = archive_read_extract(a, entry,
+ bsdtar->extract_flags);
+ if (r != ARCHIVE_OK) {
if (!bsdtar->verbose)
safe_fprintf(stderr, "%s",
archive_entry_pathname(entry));
@@ -225,14 +241,12 @@
archive_error_string(a));
if (!bsdtar->verbose)
fprintf(stderr, "\n");
- /*
- * TODO: Decide how to handle
- * extraction error... <sigh>
- */
bsdtar->return_value = 1;
}
if (bsdtar->verbose)
fprintf(stderr, "\n");
+ if (r == ARCHIVE_FATAL)
+ break;
}
}
@@ -241,7 +255,6 @@
archive_format_name(a), archive_compression_name(a));
archive_read_finish(a);
- cleanup_security(bsdtar);
}
@@ -285,7 +298,7 @@
/* Use uname if it's present, else uid. */
p = archive_entry_uname(entry);
if ((p == NULL) || (*p == '\0')) {
- sprintf(tmp, "%d ", st->st_uid);
+ sprintf(tmp, "%lu ", (unsigned long)st->st_uid);
p = tmp;
}
w = strlen(p);
@@ -299,7 +312,7 @@
fprintf(out, "%s", p);
w = strlen(p);
} else {
- sprintf(tmp, "%d", st->st_gid);
+ sprintf(tmp, "%lu", (unsigned long)st->st_gid);
w = strlen(tmp);
fprintf(out, "%s", tmp);
}
@@ -310,9 +323,9 @@
* If gs_width is too small, grow it.
*/
if (S_ISCHR(st->st_mode) || S_ISBLK(st->st_mode)) {
- sprintf(tmp, "%d,%u",
- major(st->st_rdev),
- (unsigned)minor(st->st_rdev)); /* ls(1) also casts here. */
+ sprintf(tmp, "%lu,%lu",
+ (unsigned long)major(st->st_rdev),
+ (unsigned long)minor(st->st_rdev)); /* ls(1) also casts here. */
} else {
/*
* Note the use of platform-dependent macros to format
@@ -343,128 +356,3 @@
else if (S_ISLNK(st->st_mode)) /* Symbolic link */
safe_fprintf(out, " -> %s", archive_entry_symlink(entry));
}
-
-/*
- * Structure for storing path of last successful security check.
- */
-struct security {
- char *path;
- size_t path_size;
-};
-
-/*
- * Check for a variety of security issues. Fix what we can here,
- * generate warnings as appropriate, return non-zero to prevent
- * this entry from being extracted.
- */
-static int
-security_problem(struct bsdtar *bsdtar, struct archive_entry *entry)
-{
- struct stat st;
- const char *name, *pn;
- char *p;
- int r;
-
- /* -P option forces us to just accept all pathnames as-is. */
- if (bsdtar->option_absolute_paths)
- return (0);
-
- name = archive_entry_pathname(entry);
-
- /* Reject any archive entry with '..' as a path element. */
- pn = name;
- while (pn != NULL && pn[0] != '\0') {
- if (pn[0] == '.' && pn[1] == '.' &&
- (pn[2] == '\0' || pn[2] == '/')) {
- bsdtar_warnc(bsdtar, 0,
- "Skipping pathname containing ..");
- bsdtar->return_value = 1;
- return (1);
- }
- pn = strchr(pn, '/');
- if (pn != NULL)
- pn++;
- }
-
- /*
- * Gaurd against symlink tricks. Reject any archive entry whose
- * destination would be altered by a symlink.
- */
- /* XXX TODO: Make this faster by comparing current path to
- * prefix of last successful check to avoid duplicate lstat()
- * calls. XXX */
- pn = name;
- if (bsdtar->security == NULL) {
- bsdtar->security = malloc(sizeof(*bsdtar->security));
- if (bsdtar->security == NULL)
- bsdtar_errc(bsdtar, 1, errno, "No Memory");
- bsdtar->security->path_size = MAXPATHLEN + 1;
- bsdtar->security->path = malloc(bsdtar->security->path_size);
- if (bsdtar->security->path == NULL)
- bsdtar_errc(bsdtar, 1, errno, "No Memory");
- }
- if (strlen(name) >= bsdtar->security->path_size) {
- free(bsdtar->security->path);
- while (strlen(name) >= bsdtar->security->path_size)
- bsdtar->security->path_size *= 2;
- bsdtar->security->path = malloc(bsdtar->security->path_size);
- if (bsdtar->security->path == NULL)
- bsdtar_errc(bsdtar, 1, errno, "No Memory");
- }
- p = bsdtar->security->path;
- while (pn != NULL && pn[0] != '\0') {
- *p++ = *pn++;
- while (*pn != '\0' && *pn != '/')
- *p++ = *pn++;
- p[0] = '\0';
- r = lstat(bsdtar->security->path, &st);
- if (r != 0) {
- if (errno == ENOENT)
- break;
- } else if (S_ISLNK(st.st_mode)) {
- if (pn[0] == '\0') {
- /*
- * Last element is symlink; remove it
- * so we can overwrite it with the
- * item being extracted.
- */
- if (!S_ISLNK(archive_entry_mode(entry))) {
- /*
- * Warn only if the symlink is being
- * replaced with a non-symlink.
- */
- bsdtar_warnc(bsdtar, 0,
- "Removing symlink %s",
- bsdtar->security->path);
- }
- if (unlink(bsdtar->security->path))
- bsdtar_errc(bsdtar, 1, errno,
- "Unlink failed");
- /* Symlink gone. No more problem! */
- return (0);
- } else if (bsdtar->option_unlink_first) {
- /* User asked us to remove problems. */
- if (unlink(bsdtar->security->path))
- bsdtar_errc(bsdtar, 1, errno,
- "Unlink failed");
- } else {
- bsdtar_warnc(bsdtar, 0,
- "Cannot extract %s through symlink %s",
- name, bsdtar->security->path);
- bsdtar->return_value = 1;
- return (1);
- }
- }
- }
-
- return (0);
-}
-
-static void
-cleanup_security(struct bsdtar *bsdtar)
-{
- if (bsdtar->security != NULL) {
- free(bsdtar->security->path);
- free(bsdtar->security);
- }
-}
Index: bsdtar_platform.h
===================================================================
RCS file: /home/cvs/src/usr.bin/tar/bsdtar_platform.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -Lusr.bin/tar/bsdtar_platform.h -Lusr.bin/tar/bsdtar_platform.h -u -r1.2 -r1.3
--- usr.bin/tar/bsdtar_platform.h
+++ usr.bin/tar/bsdtar_platform.h
@@ -22,8 +22,8 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
+ * $FreeBSD: src/usr.bin/tar/bsdtar_platform.h,v 1.24 2007/04/12 04:45:32 kientzle Exp $
* $MidnightBSD$
- * $FreeBSD: src/usr.bin/tar/bsdtar_platform.h,v 1.15.2.4 2007/03/11 19:46:56 kientzle Exp $
*/
/*
@@ -35,75 +35,15 @@
#ifndef BSDTAR_PLATFORM_H_INCLUDED
#define BSDTAR_PLATFORM_H_INCLUDED
-#if HAVE_CONFIG_H
+#if defined(PLATFORM_CONFIG_H)
+/* Use hand-built config.h in environments that need it. */
+#include PLATFORM_CONFIG_H
+#elif defined(HAVE_CONFIG_H)
+/* Most POSIX platforms use the 'configure' script to build config.h */
#include "../config.h"
#else
-
-#ifdef __FreeBSD__
-#include <sys/param.h> /* __FreeBSD_version */
-/* A default configuration for FreeBSD, used if there is no config.h. */
-#define PACKAGE_NAME "bsdtar"
-
-#if __FreeBSD__ > 4
-#define HAVE_ACL_GET_PERM 0
-#define HAVE_ACL_GET_PERM_NP 1
-#define HAVE_ACL_PERMSET_T 1
-#define HAVE_ACL_USER 1
-#endif
-#define HAVE_BZLIB_H 1
-#define HAVE_CHFLAGS 1
-#define HAVE_DIRENT_D_NAMLEN 1
-#define HAVE_DIRENT_H 1
-#define HAVE_D_MD_ORDER 1
-#define HAVE_FCHDIR 1
-#define HAVE_FCNTL_H 1
-#define HAVE_FNMATCH 1
-#define HAVE_FNM_LEADING_DIR 1
-#define HAVE_FTRUNCATE 1
-#define HAVE_GETOPT_LONG 1
-#define HAVE_INTTYPES_H 1
-#define HAVE_LANGINFO_H 1
-#define HAVE_LIBARCHIVE 1
-#define HAVE_LIBBZ2 1
-#define HAVE_LIBZ 1
-#define HAVE_LIMITS_H 1
-#define HAVE_LOCALE_H 1
-#define HAVE_MALLOC 1
-#define HAVE_MEMMOVE 1
-#define HAVE_MEMORY_H 1
-#define HAVE_MEMSET 1
-#if __FreeBSD_version >= 450002 /* nl_langinfo introduced */
-#define HAVE_NL_LANGINFO 1
-#endif
-#define HAVE_PATHS_H 1
-#define HAVE_SETLOCALE 1
-#define HAVE_STDINT_H 1
-#define HAVE_STDLIB_H 1
-#define HAVE_STRCHR 1
-#define HAVE_STRDUP 1
-#define HAVE_STRERROR 1
-#define HAVE_STRFTIME 1
-#define HAVE_STRINGS_H 1
-#define HAVE_STRING_H 1
-#define HAVE_STRRCHR 1
-#define HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC 1
-#define HAVE_STRUCT_STAT_ST_RDEV 1
-#define HAVE_SYS_ACL_H 1
-#define HAVE_SYS_IOCTL_H 1
-#define HAVE_SYS_PARAM_H 1
-#define HAVE_SYS_STAT_H 1
-#define HAVE_SYS_TYPES_H 1
-#define HAVE_UINTMAX_T 1
-#define HAVE_UNISTD_H 1
-#define HAVE_VPRINTF 1
-#define HAVE_ZLIB_H 1
-#define STDC_HEADERS 1
-
-#else /* !__FreeBSD__ */
/* Warn if bsdtar hasn't been (automatically or manually) configured. */
#error Oops: No config.h and no built-in configuration in bsdtar_platform.h.
-#endif /* !__FreeBSD__ */
-
#endif /* !HAVE_CONFIG_H */
/* No non-FreeBSD platform will have __FBSDID, so just define it here. */
@@ -139,10 +79,10 @@
#endif
#if HAVE_ACL_GET_PERM
-#define ACL_GET_PERM acl_get_perm
+#define ACL_GET_PERM acl_get_perm
#else
#if HAVE_ACL_GET_PERM_NP
-#define ACL_GET_PERM acl_get_perm_np
+#define ACL_GET_PERM acl_get_perm_np
#endif
#endif
More information about the Midnightbsd-cvs
mailing list