Home | History | Annotate | Line # | Download | only in tar
      1      1.1     joerg /*-
      2  1.1.1.5  christos  * SPDX-License-Identifier: BSD-2-Clause
      3  1.1.1.5  christos  *
      4      1.1     joerg  * Copyright (c) 2003-2007 Tim Kientzle
      5      1.1     joerg  * All rights reserved.
      6      1.1     joerg  */
      7      1.1     joerg 
      8      1.1     joerg #include "bsdtar_platform.h"
      9      1.1     joerg 
     10      1.1     joerg #ifdef HAVE_SYS_STAT_H
     11      1.1     joerg #include <sys/stat.h>
     12      1.1     joerg #endif
     13      1.1     joerg #ifdef HAVE_SYS_TYPES_H
     14      1.1     joerg #include <sys/types.h>  /* Linux doesn't define mode_t, etc. in sys/stat.h. */
     15      1.1     joerg #endif
     16      1.1     joerg #include <ctype.h>
     17      1.1     joerg #ifdef HAVE_ERRNO_H
     18      1.1     joerg #include <errno.h>
     19      1.1     joerg #endif
     20  1.1.1.2     joerg #ifdef HAVE_IO_H
     21  1.1.1.2     joerg #include <io.h>
     22  1.1.1.2     joerg #endif
     23      1.1     joerg #ifdef HAVE_STDARG_H
     24      1.1     joerg #include <stdarg.h>
     25      1.1     joerg #endif
     26  1.1.1.2     joerg #ifdef HAVE_STDINT_H
     27  1.1.1.2     joerg #include <stdint.h>
     28  1.1.1.2     joerg #endif
     29      1.1     joerg #include <stdio.h>
     30      1.1     joerg #ifdef HAVE_STDLIB_H
     31      1.1     joerg #include <stdlib.h>
     32      1.1     joerg #endif
     33      1.1     joerg #ifdef HAVE_STRING_H
     34      1.1     joerg #include <string.h>
     35      1.1     joerg #endif
     36  1.1.1.2     joerg #ifdef HAVE_WCTYPE_H
     37  1.1.1.2     joerg #include <wctype.h>
     38  1.1.1.2     joerg #else
     39  1.1.1.2     joerg /* If we don't have wctype, we need to hack up some version of iswprint(). */
     40  1.1.1.3     joerg #define	iswprint isprint
     41  1.1.1.2     joerg #endif
     42      1.1     joerg 
     43      1.1     joerg #include "bsdtar.h"
     44  1.1.1.6  christos #include "lafe_err.h"
     45  1.1.1.3     joerg #include "passphrase.h"
     46  1.1.1.2     joerg 
     47  1.1.1.4  christos static size_t	bsdtar_expand_char(char *, size_t, size_t, char);
     48  1.1.1.2     joerg static const char *strip_components(const char *path, int elements);
     49  1.1.1.2     joerg 
     50  1.1.1.2     joerg #if defined(_WIN32) && !defined(__CYGWIN__)
     51  1.1.1.3     joerg #define	read _read
     52  1.1.1.2     joerg #endif
     53      1.1     joerg 
     54  1.1.1.2     joerg /* TODO:  Hack up a version of mbtowc for platforms with no wide
     55  1.1.1.2     joerg  * character support at all.  I think the following might suffice,
     56  1.1.1.2     joerg  * but it needs careful testing.
     57  1.1.1.2     joerg  * #if !HAVE_MBTOWC
     58  1.1.1.3     joerg  * #define	mbtowc(wcp, p, n) ((*wcp = *p), 1)
     59  1.1.1.2     joerg  * #endif
     60  1.1.1.2     joerg  */
     61      1.1     joerg 
     62      1.1     joerg /*
     63      1.1     joerg  * Print a string, taking care with any non-printable characters.
     64  1.1.1.2     joerg  *
     65  1.1.1.2     joerg  * Note that we use a stack-allocated buffer to receive the formatted
     66  1.1.1.2     joerg  * string if we can.  This is partly performance (avoiding a call to
     67  1.1.1.2     joerg  * malloc()), partly out of expedience (we have to call vsnprintf()
     68  1.1.1.2     joerg  * before malloc() anyway to find out how big a buffer we need; we may
     69  1.1.1.2     joerg  * as well point that first call at a small local buffer in case it
     70  1.1.1.6  christos  * works).
     71      1.1     joerg  */
     72      1.1     joerg 
     73      1.1     joerg void
     74  1.1.1.6  christos safe_fprintf(FILE * restrict f, const char * restrict fmt, ...)
     75      1.1     joerg {
     76  1.1.1.2     joerg 	char fmtbuff_stack[256]; /* Place to format the printf() string. */
     77  1.1.1.2     joerg 	char outbuff[256]; /* Buffer for outgoing characters. */
     78  1.1.1.2     joerg 	char *fmtbuff_heap; /* If fmtbuff_stack is too small, we use malloc */
     79  1.1.1.2     joerg 	char *fmtbuff;  /* Pointer to fmtbuff_stack or fmtbuff_heap. */
     80  1.1.1.6  christos 	size_t fmtbuff_length;
     81  1.1.1.2     joerg 	int length, n;
     82      1.1     joerg 	va_list ap;
     83  1.1.1.2     joerg 	const char *p;
     84  1.1.1.6  christos 	size_t i;
     85  1.1.1.2     joerg 	wchar_t wc;
     86  1.1.1.2     joerg 	char try_wc;
     87      1.1     joerg 
     88      1.1     joerg 	/* Use a stack-allocated buffer if we can, for speed and safety. */
     89  1.1.1.6  christos 	memset(fmtbuff_stack, '\0', sizeof(fmtbuff_stack));
     90  1.1.1.2     joerg 	fmtbuff_heap = NULL;
     91  1.1.1.2     joerg 	fmtbuff_length = sizeof(fmtbuff_stack);
     92  1.1.1.2     joerg 	fmtbuff = fmtbuff_stack;
     93      1.1     joerg 
     94  1.1.1.2     joerg 	/* Try formatting into the stack buffer. */
     95      1.1     joerg 	va_start(ap, fmt);
     96  1.1.1.2     joerg 	length = vsnprintf(fmtbuff, fmtbuff_length, fmt, ap);
     97      1.1     joerg 	va_end(ap);
     98  1.1.1.2     joerg 
     99  1.1.1.6  christos 	/* If vsnprintf will always fail, stop early. */
    100  1.1.1.6  christos 	if (length < 0 && errno == EOVERFLOW)
    101  1.1.1.6  christos 		return;
    102  1.1.1.6  christos 
    103  1.1.1.2     joerg 	/* If the result was too large, allocate a buffer on the heap. */
    104  1.1.1.6  christos 	while (length < 0 || (size_t)length >= fmtbuff_length) {
    105  1.1.1.6  christos 		if (length >= 0 && (size_t)length >= fmtbuff_length)
    106  1.1.1.6  christos 			fmtbuff_length = (size_t)length + 1;
    107  1.1.1.3     joerg 		else if (fmtbuff_length < 8192)
    108  1.1.1.3     joerg 			fmtbuff_length *= 2;
    109  1.1.1.3     joerg 		else if (fmtbuff_length < 1000000)
    110  1.1.1.3     joerg 			fmtbuff_length += fmtbuff_length / 4;
    111  1.1.1.3     joerg 		else {
    112  1.1.1.6  christos 			fmtbuff[fmtbuff_length - 1] = '\0';
    113  1.1.1.6  christos 			length = (int)strlen(fmtbuff);
    114  1.1.1.3     joerg 			break;
    115  1.1.1.3     joerg 		}
    116  1.1.1.3     joerg 		free(fmtbuff_heap);
    117  1.1.1.2     joerg 		fmtbuff_heap = malloc(fmtbuff_length);
    118  1.1.1.2     joerg 
    119  1.1.1.2     joerg 		/* Reformat the result into the heap buffer if we can. */
    120  1.1.1.2     joerg 		if (fmtbuff_heap != NULL) {
    121  1.1.1.2     joerg 			fmtbuff = fmtbuff_heap;
    122      1.1     joerg 			va_start(ap, fmt);
    123  1.1.1.2     joerg 			length = vsnprintf(fmtbuff, fmtbuff_length, fmt, ap);
    124      1.1     joerg 			va_end(ap);
    125  1.1.1.2     joerg 		} else {
    126  1.1.1.2     joerg 			/* Leave fmtbuff pointing to the truncated
    127  1.1.1.2     joerg 			 * string in fmtbuff_stack. */
    128  1.1.1.6  christos 			fmtbuff_stack[sizeof(fmtbuff_stack) - 1] = '\0';
    129  1.1.1.3     joerg 			fmtbuff = fmtbuff_stack;
    130  1.1.1.6  christos 			length = (int)strlen(fmtbuff);
    131  1.1.1.3     joerg 			break;
    132      1.1     joerg 		}
    133      1.1     joerg 	}
    134      1.1     joerg 
    135  1.1.1.2     joerg 	/* Note: mbrtowc() has a cleaner API, but mbtowc() seems a bit
    136  1.1.1.2     joerg 	 * more portable, so we use that here instead. */
    137  1.1.1.3     joerg 	if (mbtowc(NULL, NULL, 1) == -1) { /* Reset the shift state. */
    138  1.1.1.3     joerg 		/* mbtowc() should never fail in practice, but
    139  1.1.1.3     joerg 		 * handle the theoretical error anyway. */
    140  1.1.1.3     joerg 		free(fmtbuff_heap);
    141  1.1.1.3     joerg 		return;
    142  1.1.1.3     joerg 	}
    143  1.1.1.2     joerg 
    144      1.1     joerg 	/* Write data, expanding unprintable characters. */
    145  1.1.1.2     joerg 	p = fmtbuff;
    146      1.1     joerg 	i = 0;
    147  1.1.1.2     joerg 	try_wc = 1;
    148      1.1     joerg 	while (*p != '\0') {
    149      1.1     joerg 
    150  1.1.1.2     joerg 		/* Convert to wide char, test if the wide
    151  1.1.1.2     joerg 		 * char is printable in the current locale. */
    152  1.1.1.2     joerg 		if (try_wc && (n = mbtowc(&wc, p, length)) != -1) {
    153  1.1.1.2     joerg 			length -= n;
    154  1.1.1.2     joerg 			if (iswprint(wc) && wc != L'\\') {
    155  1.1.1.2     joerg 				/* Printable, copy the bytes through. */
    156  1.1.1.2     joerg 				while (n-- > 0)
    157  1.1.1.2     joerg 					outbuff[i++] = *p++;
    158  1.1.1.2     joerg 			} else {
    159  1.1.1.2     joerg 				/* Not printable, format the bytes. */
    160  1.1.1.2     joerg 				while (n-- > 0)
    161  1.1.1.6  christos 					i += bsdtar_expand_char(
    162  1.1.1.4  christos 					    outbuff, sizeof(outbuff), i, *p++);
    163      1.1     joerg 			}
    164  1.1.1.2     joerg 		} else {
    165  1.1.1.2     joerg 			/* After any conversion failure, don't bother
    166  1.1.1.2     joerg 			 * trying to convert the rest. */
    167  1.1.1.6  christos 			i += bsdtar_expand_char(outbuff, sizeof(outbuff), i, *p++);
    168  1.1.1.2     joerg 			try_wc = 0;
    169      1.1     joerg 		}
    170      1.1     joerg 
    171  1.1.1.2     joerg 		/* If our output buffer is full, dump it and keep going. */
    172  1.1.1.3     joerg 		if (i > (sizeof(outbuff) - 128)) {
    173  1.1.1.2     joerg 			outbuff[i] = '\0';
    174  1.1.1.2     joerg 			fprintf(f, "%s", outbuff);
    175      1.1     joerg 			i = 0;
    176      1.1     joerg 		}
    177      1.1     joerg 	}
    178  1.1.1.2     joerg 	outbuff[i] = '\0';
    179  1.1.1.2     joerg 	fprintf(f, "%s", outbuff);
    180      1.1     joerg 
    181  1.1.1.2     joerg 	/* If we allocated a heap-based formatting buffer, free it now. */
    182  1.1.1.3     joerg 	free(fmtbuff_heap);
    183      1.1     joerg }
    184      1.1     joerg 
    185  1.1.1.2     joerg /*
    186  1.1.1.2     joerg  * Render an arbitrary sequence of bytes into printable ASCII characters.
    187  1.1.1.2     joerg  */
    188  1.1.1.2     joerg static size_t
    189  1.1.1.4  christos bsdtar_expand_char(char *buff, size_t buffsize, size_t offset, char c)
    190      1.1     joerg {
    191  1.1.1.2     joerg 	size_t i = offset;
    192      1.1     joerg 
    193  1.1.1.2     joerg 	if (isprint((unsigned char)c) && c != '\\')
    194  1.1.1.2     joerg 		buff[i++] = c;
    195  1.1.1.2     joerg 	else {
    196  1.1.1.2     joerg 		buff[i++] = '\\';
    197  1.1.1.2     joerg 		switch (c) {
    198  1.1.1.2     joerg 		case '\a': buff[i++] = 'a'; break;
    199  1.1.1.2     joerg 		case '\b': buff[i++] = 'b'; break;
    200  1.1.1.2     joerg 		case '\f': buff[i++] = 'f'; break;
    201  1.1.1.2     joerg 		case '\n': buff[i++] = 'n'; break;
    202  1.1.1.2     joerg #if '\r' != '\n'
    203  1.1.1.2     joerg 		/* On some platforms, \n and \r are the same. */
    204  1.1.1.2     joerg 		case '\r': buff[i++] = 'r'; break;
    205  1.1.1.2     joerg #endif
    206  1.1.1.2     joerg 		case '\t': buff[i++] = 't'; break;
    207  1.1.1.2     joerg 		case '\v': buff[i++] = 'v'; break;
    208  1.1.1.2     joerg 		case '\\': buff[i++] = '\\'; break;
    209  1.1.1.2     joerg 		default:
    210  1.1.1.6  christos 			snprintf(buff + i, buffsize - i, "%03o",
    211  1.1.1.6  christos 			    0xFF & (unsigned int)c);
    212  1.1.1.2     joerg 			i += 3;
    213  1.1.1.2     joerg 		}
    214  1.1.1.2     joerg 	}
    215      1.1     joerg 
    216  1.1.1.2     joerg 	return (i - offset);
    217      1.1     joerg }
    218      1.1     joerg 
    219      1.1     joerg int
    220      1.1     joerg yes(const char *fmt, ...)
    221      1.1     joerg {
    222      1.1     joerg 	char buff[32];
    223      1.1     joerg 	char *p;
    224      1.1     joerg 	ssize_t l;
    225  1.1.1.5  christos 	int read_fd = 2; /* stderr */
    226      1.1     joerg 
    227      1.1     joerg 	va_list ap;
    228      1.1     joerg 	va_start(ap, fmt);
    229      1.1     joerg 	vfprintf(stderr, fmt, ap);
    230      1.1     joerg 	va_end(ap);
    231      1.1     joerg 	fprintf(stderr, " (y/N)? ");
    232      1.1     joerg 	fflush(stderr);
    233      1.1     joerg 
    234  1.1.1.5  christos #if defined(_WIN32) && !defined(__CYGWIN__)
    235  1.1.1.5  christos 	/* To be resilient when stdin is a pipe, bsdtar prefers to read from
    236  1.1.1.5  christos 	 * stderr.  On Windows, stderr cannot be read. The nearest "piping
    237  1.1.1.5  christos 	 * resilient" equivalent is reopening the console input handle.
    238  1.1.1.5  christos 	 */
    239  1.1.1.5  christos 	read_fd = _open("CONIN$", O_RDONLY);
    240  1.1.1.5  christos 	if (read_fd < 0) {
    241  1.1.1.5  christos 	  fprintf(stderr, "Keyboard read failed\n");
    242  1.1.1.5  christos 	  exit(1);
    243  1.1.1.5  christos 	}
    244  1.1.1.5  christos #endif
    245  1.1.1.5  christos 
    246  1.1.1.5  christos 	l = read(read_fd, buff, sizeof(buff) - 1);
    247  1.1.1.5  christos 
    248  1.1.1.5  christos #if defined(_WIN32) && !defined(__CYGWIN__)
    249  1.1.1.5  christos 	_close(read_fd);
    250  1.1.1.5  christos #endif
    251  1.1.1.5  christos 
    252  1.1.1.3     joerg 	if (l < 0) {
    253  1.1.1.3     joerg 	  fprintf(stderr, "Keyboard read failed\n");
    254  1.1.1.3     joerg 	  exit(1);
    255  1.1.1.3     joerg 	}
    256  1.1.1.3     joerg 	if (l == 0)
    257      1.1     joerg 		return (0);
    258      1.1     joerg 	buff[l] = 0;
    259      1.1     joerg 
    260      1.1     joerg 	for (p = buff; *p != '\0'; p++) {
    261  1.1.1.2     joerg 		if (isspace((unsigned char)*p))
    262      1.1     joerg 			continue;
    263      1.1     joerg 		switch(*p) {
    264      1.1     joerg 		case 'y': case 'Y':
    265      1.1     joerg 			return (1);
    266      1.1     joerg 		case 'n': case 'N':
    267      1.1     joerg 			return (0);
    268      1.1     joerg 		default:
    269      1.1     joerg 			return (0);
    270      1.1     joerg 		}
    271      1.1     joerg 	}
    272      1.1     joerg 
    273      1.1     joerg 	return (0);
    274      1.1     joerg }
    275      1.1     joerg 
    276      1.1     joerg /*-
    277      1.1     joerg  * The logic here for -C <dir> attempts to avoid
    278      1.1     joerg  * chdir() as long as possible.  For example:
    279      1.1     joerg  * "-C /foo -C /bar file"          needs chdir("/bar") but not chdir("/foo")
    280      1.1     joerg  * "-C /foo -C bar file"           needs chdir("/foo/bar")
    281      1.1     joerg  * "-C /foo -C bar /file1"         does not need chdir()
    282      1.1     joerg  * "-C /foo -C bar /file1 file2"   needs chdir("/foo/bar") before file2
    283      1.1     joerg  *
    284      1.1     joerg  * The only correct way to handle this is to record a "pending" chdir
    285      1.1     joerg  * request and combine multiple requests intelligently until we
    286      1.1     joerg  * need to process a non-absolute file.  set_chdir() adds the new dir
    287      1.1     joerg  * to the pending list; do_chdir() actually executes any pending chdir.
    288      1.1     joerg  *
    289      1.1     joerg  * This way, programs that build tar command lines don't have to worry
    290      1.1     joerg  * about -C with non-existent directories; such requests will only
    291      1.1     joerg  * fail if the directory must be accessed.
    292  1.1.1.2     joerg  *
    293      1.1     joerg  */
    294      1.1     joerg void
    295      1.1     joerg set_chdir(struct bsdtar *bsdtar, const char *newdir)
    296      1.1     joerg {
    297  1.1.1.3     joerg #if defined(_WIN32) && !defined(__CYGWIN__)
    298  1.1.1.3     joerg 	if (newdir[0] == '/' || newdir[0] == '\\' ||
    299  1.1.1.3     joerg 	    /* Detect this type, for example, "C:\" or "C:/" */
    300  1.1.1.3     joerg 	    (((newdir[0] >= 'a' && newdir[0] <= 'z') ||
    301  1.1.1.3     joerg 	      (newdir[0] >= 'A' && newdir[0] <= 'Z')) &&
    302  1.1.1.3     joerg 	    newdir[1] == ':' && (newdir[2] == '/' || newdir[2] == '\\'))) {
    303  1.1.1.3     joerg #else
    304      1.1     joerg 	if (newdir[0] == '/') {
    305  1.1.1.3     joerg #endif
    306      1.1     joerg 		/* The -C /foo -C /bar case; dump first one. */
    307      1.1     joerg 		free(bsdtar->pending_chdir);
    308      1.1     joerg 		bsdtar->pending_chdir = NULL;
    309      1.1     joerg 	}
    310      1.1     joerg 	if (bsdtar->pending_chdir == NULL)
    311      1.1     joerg 		/* Easy case: no previously-saved dir. */
    312      1.1     joerg 		bsdtar->pending_chdir = strdup(newdir);
    313      1.1     joerg 	else {
    314      1.1     joerg 		/* The -C /foo -C bar case; concatenate */
    315      1.1     joerg 		char *old_pending = bsdtar->pending_chdir;
    316      1.1     joerg 		size_t old_len = strlen(old_pending);
    317  1.1.1.6  christos 		size_t newdir_len = strlen(newdir);
    318  1.1.1.6  christos 		size_t new_len = old_len + newdir_len + 2;
    319  1.1.1.6  christos 		if (old_len > SIZE_MAX - newdir_len - 2)
    320  1.1.1.6  christos 		    lafe_errc(1, errno, "Path too long");
    321  1.1.1.4  christos 		bsdtar->pending_chdir = malloc(new_len);
    322      1.1     joerg 		if (old_pending[old_len - 1] == '/')
    323      1.1     joerg 			old_pending[old_len - 1] = '\0';
    324      1.1     joerg 		if (bsdtar->pending_chdir != NULL)
    325  1.1.1.4  christos 			snprintf(bsdtar->pending_chdir, new_len, "%s/%s",
    326      1.1     joerg 			    old_pending, newdir);
    327      1.1     joerg 		free(old_pending);
    328      1.1     joerg 	}
    329      1.1     joerg 	if (bsdtar->pending_chdir == NULL)
    330  1.1.1.2     joerg 		lafe_errc(1, errno, "No memory");
    331      1.1     joerg }
    332      1.1     joerg 
    333      1.1     joerg void
    334      1.1     joerg do_chdir(struct bsdtar *bsdtar)
    335      1.1     joerg {
    336      1.1     joerg 	if (bsdtar->pending_chdir == NULL)
    337      1.1     joerg 		return;
    338      1.1     joerg 
    339      1.1     joerg 	if (chdir(bsdtar->pending_chdir) != 0) {
    340  1.1.1.6  christos 		lafe_errc(1, 0, "could not chdir to '%s'",
    341      1.1     joerg 		    bsdtar->pending_chdir);
    342      1.1     joerg 	}
    343      1.1     joerg 	free(bsdtar->pending_chdir);
    344      1.1     joerg 	bsdtar->pending_chdir = NULL;
    345      1.1     joerg }
    346      1.1     joerg 
    347  1.1.1.2     joerg static const char *
    348  1.1.1.2     joerg strip_components(const char *p, int elements)
    349  1.1.1.2     joerg {
    350  1.1.1.2     joerg 	/* Skip as many elements as necessary. */
    351  1.1.1.2     joerg 	while (elements > 0) {
    352  1.1.1.2     joerg 		switch (*p++) {
    353  1.1.1.2     joerg 		case '/':
    354  1.1.1.2     joerg #if defined(_WIN32) && !defined(__CYGWIN__)
    355  1.1.1.2     joerg 		case '\\': /* Support \ path sep on Windows ONLY. */
    356  1.1.1.2     joerg #endif
    357  1.1.1.2     joerg 			elements--;
    358  1.1.1.2     joerg 			break;
    359  1.1.1.2     joerg 		case '\0':
    360  1.1.1.2     joerg 			/* Path is too short, skip it. */
    361  1.1.1.2     joerg 			return (NULL);
    362  1.1.1.2     joerg 		}
    363  1.1.1.2     joerg 	}
    364  1.1.1.2     joerg 
    365  1.1.1.2     joerg 	/* Skip any / characters.  This handles short paths that have
    366  1.1.1.2     joerg 	 * additional / termination.  This also handles the case where
    367  1.1.1.2     joerg 	 * the logic above stops in the middle of a duplicate //
    368  1.1.1.2     joerg 	 * sequence (which would otherwise get converted to an
    369  1.1.1.2     joerg 	 * absolute path). */
    370  1.1.1.2     joerg 	for (;;) {
    371  1.1.1.2     joerg 		switch (*p) {
    372  1.1.1.2     joerg 		case '/':
    373  1.1.1.2     joerg #if defined(_WIN32) && !defined(__CYGWIN__)
    374  1.1.1.2     joerg 		case '\\': /* Support \ path sep on Windows ONLY. */
    375  1.1.1.2     joerg #endif
    376  1.1.1.2     joerg 			++p;
    377  1.1.1.2     joerg 			break;
    378  1.1.1.2     joerg 		case '\0':
    379  1.1.1.2     joerg 			return (NULL);
    380  1.1.1.2     joerg 		default:
    381  1.1.1.2     joerg 			return (p);
    382  1.1.1.2     joerg 		}
    383  1.1.1.2     joerg 	}
    384  1.1.1.2     joerg }
    385  1.1.1.2     joerg 
    386  1.1.1.3     joerg static void
    387  1.1.1.3     joerg warn_strip_leading_char(struct bsdtar *bsdtar, const char *c)
    388  1.1.1.3     joerg {
    389  1.1.1.3     joerg 	if (!bsdtar->warned_lead_slash) {
    390  1.1.1.3     joerg 		lafe_warnc(0,
    391  1.1.1.3     joerg 			   "Removing leading '%c' from member names",
    392  1.1.1.3     joerg 			   c[0]);
    393  1.1.1.3     joerg 		bsdtar->warned_lead_slash = 1;
    394  1.1.1.3     joerg 	}
    395  1.1.1.3     joerg }
    396  1.1.1.3     joerg 
    397  1.1.1.3     joerg static void
    398  1.1.1.3     joerg warn_strip_drive_letter(struct bsdtar *bsdtar)
    399  1.1.1.3     joerg {
    400  1.1.1.3     joerg 	if (!bsdtar->warned_lead_slash) {
    401  1.1.1.3     joerg 		lafe_warnc(0,
    402  1.1.1.3     joerg 			   "Removing leading drive letter from "
    403  1.1.1.3     joerg 			   "member names");
    404  1.1.1.3     joerg 		bsdtar->warned_lead_slash = 1;
    405  1.1.1.3     joerg 	}
    406  1.1.1.3     joerg }
    407  1.1.1.3     joerg 
    408  1.1.1.3     joerg /*
    409  1.1.1.3     joerg  * Convert absolute path to non-absolute path by skipping leading
    410  1.1.1.3     joerg  * absolute path prefixes.
    411  1.1.1.3     joerg  */
    412  1.1.1.3     joerg static const char*
    413  1.1.1.3     joerg strip_absolute_path(struct bsdtar *bsdtar, const char *p)
    414  1.1.1.3     joerg {
    415  1.1.1.3     joerg 	const char *rp;
    416  1.1.1.3     joerg 
    417  1.1.1.3     joerg 	/* Remove leading "//./" or "//?/" or "//?/UNC/"
    418  1.1.1.3     joerg 	 * (absolute path prefixes used by Windows API) */
    419  1.1.1.3     joerg 	if ((p[0] == '/' || p[0] == '\\') &&
    420  1.1.1.3     joerg 	    (p[1] == '/' || p[1] == '\\') &&
    421  1.1.1.3     joerg 	    (p[2] == '.' || p[2] == '?') &&
    422  1.1.1.3     joerg 	    (p[3] == '/' || p[3] == '\\'))
    423  1.1.1.3     joerg 	{
    424  1.1.1.3     joerg 		if (p[2] == '?' &&
    425  1.1.1.3     joerg 		    (p[4] == 'U' || p[4] == 'u') &&
    426  1.1.1.3     joerg 		    (p[5] == 'N' || p[5] == 'n') &&
    427  1.1.1.3     joerg 		    (p[6] == 'C' || p[6] == 'c') &&
    428  1.1.1.3     joerg 		    (p[7] == '/' || p[7] == '\\'))
    429  1.1.1.3     joerg 			p += 8;
    430  1.1.1.3     joerg 		else
    431  1.1.1.3     joerg 			p += 4;
    432  1.1.1.3     joerg 		warn_strip_drive_letter(bsdtar);
    433  1.1.1.3     joerg 	}
    434  1.1.1.3     joerg 
    435  1.1.1.3     joerg 	/* Remove multiple leading slashes and Windows drive letters. */
    436  1.1.1.3     joerg 	do {
    437  1.1.1.3     joerg 		rp = p;
    438  1.1.1.3     joerg 		if (((p[0] >= 'a' && p[0] <= 'z') ||
    439  1.1.1.3     joerg 		     (p[0] >= 'A' && p[0] <= 'Z')) &&
    440  1.1.1.3     joerg 		    p[1] == ':') {
    441  1.1.1.3     joerg 			p += 2;
    442  1.1.1.3     joerg 			warn_strip_drive_letter(bsdtar);
    443  1.1.1.3     joerg 		}
    444  1.1.1.3     joerg 
    445  1.1.1.3     joerg 		/* Remove leading "/../", "/./", "//", etc. */
    446  1.1.1.3     joerg 		while (p[0] == '/' || p[0] == '\\') {
    447  1.1.1.3     joerg 			if (p[1] == '.' &&
    448  1.1.1.3     joerg 			    p[2] == '.' &&
    449  1.1.1.3     joerg 			    (p[3] == '/' || p[3] == '\\')) {
    450  1.1.1.3     joerg 				p += 3; /* Remove "/..", leave "/" for next pass. */
    451  1.1.1.3     joerg 			} else if (p[1] == '.' &&
    452  1.1.1.3     joerg 				   (p[2] == '/' || p[2] == '\\')) {
    453  1.1.1.3     joerg 				p += 2; /* Remove "/.", leave "/" for next pass. */
    454  1.1.1.3     joerg 			} else
    455  1.1.1.3     joerg 				p += 1; /* Remove "/". */
    456  1.1.1.3     joerg 			warn_strip_leading_char(bsdtar, rp);
    457  1.1.1.3     joerg 		}
    458  1.1.1.3     joerg 	} while (rp != p);
    459  1.1.1.3     joerg 
    460  1.1.1.3     joerg 	return (p);
    461  1.1.1.3     joerg }
    462  1.1.1.3     joerg 
    463      1.1     joerg /*
    464      1.1     joerg  * Handle --strip-components and any future path-rewriting options.
    465      1.1     joerg  * Returns non-zero if the pathname should not be extracted.
    466      1.1     joerg  *
    467  1.1.1.3     joerg  * Note: The rewrites are applied uniformly to pathnames and hardlink
    468  1.1.1.3     joerg  * names but not to symlink bodies.  This is deliberate: Symlink
    469  1.1.1.3     joerg  * bodies are not necessarily filenames.  Even when they are, they
    470  1.1.1.3     joerg  * need to be interpreted relative to the directory containing them,
    471  1.1.1.3     joerg  * so simple rewrites like this are rarely appropriate.
    472  1.1.1.3     joerg  *
    473      1.1     joerg  * TODO: Support pax-style regex path rewrites.
    474      1.1     joerg  */
    475      1.1     joerg int
    476      1.1     joerg edit_pathname(struct bsdtar *bsdtar, struct archive_entry *entry)
    477      1.1     joerg {
    478      1.1     joerg 	const char *name = archive_entry_pathname(entry);
    479  1.1.1.3     joerg 	const char *original_name = name;
    480  1.1.1.3     joerg 	const char *hardlinkname = archive_entry_hardlink(entry);
    481  1.1.1.3     joerg 	const char *original_hardlinkname = hardlinkname;
    482  1.1.1.4  christos #if defined(HAVE_REGEX_H) || defined(HAVE_PCREPOSIX_H) || defined(HAVE_PCRE2POSIX_H)
    483      1.1     joerg 	char *subst_name;
    484      1.1     joerg 	int r;
    485      1.1     joerg 
    486  1.1.1.3     joerg 	/* Apply user-specified substitution to pathname. */
    487  1.1.1.3     joerg 	r = apply_substitution(bsdtar, name, &subst_name, 0, 0);
    488      1.1     joerg 	if (r == -1) {
    489  1.1.1.2     joerg 		lafe_warnc(0, "Invalid substitution, skipping entry");
    490      1.1     joerg 		return 1;
    491      1.1     joerg 	}
    492      1.1     joerg 	if (r == 1) {
    493      1.1     joerg 		archive_entry_copy_pathname(entry, subst_name);
    494      1.1     joerg 		if (*subst_name == '\0') {
    495      1.1     joerg 			free(subst_name);
    496      1.1     joerg 			return -1;
    497      1.1     joerg 		} else
    498      1.1     joerg 			free(subst_name);
    499      1.1     joerg 		name = archive_entry_pathname(entry);
    500  1.1.1.3     joerg 		original_name = name;
    501      1.1     joerg 	}
    502      1.1     joerg 
    503  1.1.1.3     joerg 	/* Apply user-specified substitution to hardlink target. */
    504  1.1.1.3     joerg 	if (hardlinkname != NULL) {
    505  1.1.1.3     joerg 		r = apply_substitution(bsdtar, hardlinkname, &subst_name, 0, 1);
    506      1.1     joerg 		if (r == -1) {
    507  1.1.1.2     joerg 			lafe_warnc(0, "Invalid substitution, skipping entry");
    508      1.1     joerg 			return 1;
    509      1.1     joerg 		}
    510      1.1     joerg 		if (r == 1) {
    511      1.1     joerg 			archive_entry_copy_hardlink(entry, subst_name);
    512      1.1     joerg 			free(subst_name);
    513      1.1     joerg 		}
    514  1.1.1.3     joerg 		hardlinkname = archive_entry_hardlink(entry);
    515  1.1.1.3     joerg 		original_hardlinkname = hardlinkname;
    516      1.1     joerg 	}
    517  1.1.1.3     joerg 
    518  1.1.1.3     joerg 	/* Apply user-specified substitution to symlink body. */
    519      1.1     joerg 	if (archive_entry_symlink(entry) != NULL) {
    520  1.1.1.3     joerg 		r = apply_substitution(bsdtar, archive_entry_symlink(entry), &subst_name, 1, 0);
    521      1.1     joerg 		if (r == -1) {
    522  1.1.1.2     joerg 			lafe_warnc(0, "Invalid substitution, skipping entry");
    523      1.1     joerg 			return 1;
    524      1.1     joerg 		}
    525      1.1     joerg 		if (r == 1) {
    526      1.1     joerg 			archive_entry_copy_symlink(entry, subst_name);
    527      1.1     joerg 			free(subst_name);
    528      1.1     joerg 		}
    529      1.1     joerg 	}
    530      1.1     joerg #endif
    531      1.1     joerg 
    532      1.1     joerg 	/* Strip leading dir names as per --strip-components option. */
    533  1.1.1.2     joerg 	if (bsdtar->strip_components > 0) {
    534  1.1.1.2     joerg 		name = strip_components(name, bsdtar->strip_components);
    535  1.1.1.2     joerg 		if (name == NULL)
    536  1.1.1.2     joerg 			return (1);
    537      1.1     joerg 
    538  1.1.1.3     joerg 		if (hardlinkname != NULL) {
    539  1.1.1.3     joerg 			hardlinkname = strip_components(hardlinkname,
    540  1.1.1.2     joerg 			    bsdtar->strip_components);
    541  1.1.1.3     joerg 			if (hardlinkname == NULL)
    542      1.1     joerg 				return (1);
    543      1.1     joerg 		}
    544      1.1     joerg 	}
    545      1.1     joerg 
    546  1.1.1.3     joerg 	if ((bsdtar->flags & OPTFLAG_ABSOLUTE_PATHS) == 0) {
    547  1.1.1.3     joerg 		/* By default, don't write or restore absolute pathnames. */
    548  1.1.1.3     joerg 		name = strip_absolute_path(bsdtar, name);
    549  1.1.1.3     joerg 		if (*name == '\0')
    550  1.1.1.3     joerg 			name = ".";
    551  1.1.1.2     joerg 
    552  1.1.1.3     joerg 		if (hardlinkname != NULL) {
    553  1.1.1.3     joerg 			hardlinkname = strip_absolute_path(bsdtar, hardlinkname);
    554  1.1.1.3     joerg 			if (*hardlinkname == '\0')
    555  1.1.1.3     joerg 				return (1);
    556      1.1     joerg 		}
    557  1.1.1.2     joerg 	} else {
    558  1.1.1.2     joerg 		/* Strip redundant leading '/' characters. */
    559  1.1.1.2     joerg 		while (name[0] == '/' && name[1] == '/')
    560  1.1.1.2     joerg 			name++;
    561      1.1     joerg 	}
    562      1.1     joerg 
    563  1.1.1.3     joerg 	/* Replace name in archive_entry. */
    564  1.1.1.3     joerg 	if (name != original_name) {
    565  1.1.1.3     joerg 		archive_entry_copy_pathname(entry, name);
    566  1.1.1.3     joerg 	}
    567  1.1.1.3     joerg 	if (hardlinkname != original_hardlinkname) {
    568  1.1.1.3     joerg 		archive_entry_copy_hardlink(entry, hardlinkname);
    569      1.1     joerg 	}
    570      1.1     joerg 	return (0);
    571      1.1     joerg }
    572      1.1     joerg 
    573      1.1     joerg /*
    574  1.1.1.6  christos  * Apply --mtime and --clamp-mtime options.
    575  1.1.1.6  christos  */
    576  1.1.1.6  christos void
    577  1.1.1.6  christos edit_mtime(struct bsdtar *bsdtar, struct archive_entry *entry)
    578  1.1.1.6  christos {
    579  1.1.1.6  christos 	if (!bsdtar->has_mtime)
    580  1.1.1.6  christos 		return;
    581  1.1.1.6  christos 
    582  1.1.1.6  christos 	__LA_TIME_T entry_mtime = archive_entry_mtime(entry);
    583  1.1.1.6  christos 	if (!bsdtar->clamp_mtime || entry_mtime > bsdtar->mtime)
    584  1.1.1.6  christos 		archive_entry_set_mtime(entry, bsdtar->mtime, 0);
    585  1.1.1.6  christos }
    586  1.1.1.6  christos 
    587  1.1.1.6  christos /*
    588  1.1.1.2     joerg  * It would be nice to just use printf() for formatting large numbers,
    589  1.1.1.2     joerg  * but the compatibility problems are quite a headache.  Hence the
    590  1.1.1.2     joerg  * following simple utility function.
    591  1.1.1.2     joerg  */
    592  1.1.1.2     joerg const char *
    593  1.1.1.2     joerg tar_i64toa(int64_t n0)
    594  1.1.1.2     joerg {
    595  1.1.1.2     joerg 	static char buff[24];
    596  1.1.1.3     joerg 	uint64_t n = n0 < 0 ? -n0 : n0;
    597  1.1.1.2     joerg 	char *p = buff + sizeof(buff);
    598  1.1.1.2     joerg 
    599  1.1.1.2     joerg 	*--p = '\0';
    600  1.1.1.2     joerg 	do {
    601  1.1.1.2     joerg 		*--p = '0' + (int)(n % 10);
    602  1.1.1.3     joerg 	} while (n /= 10);
    603  1.1.1.2     joerg 	if (n0 < 0)
    604  1.1.1.2     joerg 		*--p = '-';
    605  1.1.1.2     joerg 	return p;
    606  1.1.1.2     joerg }
    607  1.1.1.2     joerg 
    608  1.1.1.2     joerg /*
    609      1.1     joerg  * Like strcmp(), but try to be a little more aware of the fact that
    610      1.1     joerg  * we're comparing two paths.  Right now, it just handles leading
    611      1.1     joerg  * "./" and trailing '/' specially, so that "a/b/" == "./a/b"
    612      1.1     joerg  *
    613      1.1     joerg  * TODO: Make this better, so that "./a//b/./c/" == "a/b/c"
    614      1.1     joerg  * TODO: After this works, push it down into libarchive.
    615      1.1     joerg  * TODO: Publish the path normalization routines in libarchive so
    616      1.1     joerg  * that bsdtar can normalize paths and use fast strcmp() instead
    617      1.1     joerg  * of this.
    618  1.1.1.2     joerg  *
    619  1.1.1.2     joerg  * Note: This is currently only used within write.c, so should
    620  1.1.1.2     joerg  * not handle \ path separators.
    621      1.1     joerg  */
    622      1.1     joerg 
    623      1.1     joerg int
    624      1.1     joerg pathcmp(const char *a, const char *b)
    625      1.1     joerg {
    626      1.1     joerg 	/* Skip leading './' */
    627      1.1     joerg 	if (a[0] == '.' && a[1] == '/' && a[2] != '\0')
    628      1.1     joerg 		a += 2;
    629      1.1     joerg 	if (b[0] == '.' && b[1] == '/' && b[2] != '\0')
    630      1.1     joerg 		b += 2;
    631      1.1     joerg 	/* Find the first difference, or return (0) if none. */
    632      1.1     joerg 	while (*a == *b) {
    633      1.1     joerg 		if (*a == '\0')
    634      1.1     joerg 			return (0);
    635      1.1     joerg 		a++;
    636      1.1     joerg 		b++;
    637      1.1     joerg 	}
    638      1.1     joerg 	/*
    639      1.1     joerg 	 * If one ends in '/' and the other one doesn't,
    640      1.1     joerg 	 * they're the same.
    641      1.1     joerg 	 */
    642      1.1     joerg 	if (a[0] == '/' && a[1] == '\0' && b[0] == '\0')
    643      1.1     joerg 		return (0);
    644      1.1     joerg 	if (a[0] == '\0' && b[0] == '/' && b[1] == '\0')
    645      1.1     joerg 		return (0);
    646      1.1     joerg 	/* They're really different, return the correct sign. */
    647      1.1     joerg 	return (*(const unsigned char *)a - *(const unsigned char *)b);
    648      1.1     joerg }
    649  1.1.1.3     joerg 
    650  1.1.1.3     joerg #define PPBUFF_SIZE 1024
    651  1.1.1.3     joerg const char *
    652  1.1.1.3     joerg passphrase_callback(struct archive *a, void *_client_data)
    653  1.1.1.3     joerg {
    654  1.1.1.3     joerg 	struct bsdtar *bsdtar = (struct bsdtar *)_client_data;
    655  1.1.1.3     joerg 	(void)a; /* UNUSED */
    656  1.1.1.3     joerg 
    657  1.1.1.3     joerg 	if (bsdtar->ppbuff == NULL) {
    658  1.1.1.3     joerg 		bsdtar->ppbuff = malloc(PPBUFF_SIZE);
    659  1.1.1.3     joerg 		if (bsdtar->ppbuff == NULL)
    660  1.1.1.3     joerg 			lafe_errc(1, errno, "Out of memory");
    661  1.1.1.3     joerg 	}
    662  1.1.1.3     joerg 	return lafe_readpassphrase("Enter passphrase:",
    663  1.1.1.3     joerg 		bsdtar->ppbuff, PPBUFF_SIZE);
    664  1.1.1.3     joerg }
    665  1.1.1.3     joerg 
    666  1.1.1.3     joerg void
    667  1.1.1.3     joerg passphrase_free(char *ppbuff)
    668  1.1.1.3     joerg {
    669  1.1.1.3     joerg 	if (ppbuff != NULL) {
    670  1.1.1.3     joerg 		memset(ppbuff, 0, PPBUFF_SIZE);
    671  1.1.1.3     joerg 		free(ppbuff);
    672  1.1.1.3     joerg 	}
    673  1.1.1.3     joerg }
    674  1.1.1.3     joerg 
    675  1.1.1.3     joerg /*
    676  1.1.1.3     joerg  * Display information about the current file.
    677  1.1.1.3     joerg  *
    678  1.1.1.3     joerg  * The format here roughly duplicates the output of 'ls -l'.
    679  1.1.1.3     joerg  * This is based on SUSv2, where 'tar tv' is documented as
    680  1.1.1.3     joerg  * listing additional information in an "unspecified format,"
    681  1.1.1.3     joerg  * and 'pax -l' is documented as using the same format as 'ls -l'.
    682  1.1.1.3     joerg  */
    683  1.1.1.3     joerg void
    684  1.1.1.3     joerg list_item_verbose(struct bsdtar *bsdtar, FILE *out, struct archive_entry *entry)
    685  1.1.1.3     joerg {
    686  1.1.1.3     joerg 	char			 tmp[100];
    687  1.1.1.3     joerg 	size_t			 w;
    688  1.1.1.6  christos 	size_t			 sw;
    689  1.1.1.3     joerg 	const char		*p;
    690  1.1.1.3     joerg 	const char		*fmt;
    691  1.1.1.3     joerg 	time_t			 tim;
    692  1.1.1.3     joerg 	static time_t		 now;
    693  1.1.1.4  christos 	struct tm		*ltime;
    694  1.1.1.4  christos #if defined(HAVE_LOCALTIME_R) || defined(HAVE_LOCALTIME_S)
    695  1.1.1.4  christos 	struct tm		tmbuf;
    696  1.1.1.4  christos #endif
    697  1.1.1.3     joerg 
    698  1.1.1.3     joerg 	/*
    699  1.1.1.3     joerg 	 * We avoid collecting the entire list in memory at once by
    700  1.1.1.3     joerg 	 * listing things as we see them.  However, that also means we can't
    701  1.1.1.3     joerg 	 * just pre-compute the field widths.  Instead, we start with guesses
    702  1.1.1.3     joerg 	 * and just widen them as necessary.  These numbers are completely
    703  1.1.1.3     joerg 	 * arbitrary.
    704  1.1.1.3     joerg 	 */
    705  1.1.1.3     joerg 	if (!bsdtar->u_width) {
    706  1.1.1.3     joerg 		bsdtar->u_width = 6;
    707  1.1.1.3     joerg 		bsdtar->gs_width = 13;
    708  1.1.1.3     joerg 	}
    709  1.1.1.3     joerg 	if (!now)
    710  1.1.1.3     joerg 		time(&now);
    711  1.1.1.6  christos 	fprintf(out, "%s %u ",
    712  1.1.1.3     joerg 	    archive_entry_strmode(entry),
    713  1.1.1.3     joerg 	    archive_entry_nlink(entry));
    714  1.1.1.3     joerg 
    715  1.1.1.3     joerg 	/* Use uname if it's present, else uid. */
    716  1.1.1.3     joerg 	p = archive_entry_uname(entry);
    717  1.1.1.3     joerg 	if ((p == NULL) || (*p == '\0')) {
    718  1.1.1.4  christos 		snprintf(tmp, sizeof(tmp), "%lu ",
    719  1.1.1.3     joerg 		    (unsigned long)archive_entry_uid(entry));
    720  1.1.1.3     joerg 		p = tmp;
    721  1.1.1.3     joerg 	}
    722  1.1.1.3     joerg 	w = strlen(p);
    723  1.1.1.3     joerg 	if (w > bsdtar->u_width)
    724  1.1.1.3     joerg 		bsdtar->u_width = w;
    725  1.1.1.3     joerg 	fprintf(out, "%-*s ", (int)bsdtar->u_width, p);
    726  1.1.1.3     joerg 
    727  1.1.1.3     joerg 	/* Use gname if it's present, else gid. */
    728  1.1.1.3     joerg 	p = archive_entry_gname(entry);
    729  1.1.1.3     joerg 	if (p != NULL && p[0] != '\0') {
    730  1.1.1.3     joerg 		fprintf(out, "%s", p);
    731  1.1.1.3     joerg 		w = strlen(p);
    732  1.1.1.3     joerg 	} else {
    733  1.1.1.4  christos 		snprintf(tmp, sizeof(tmp), "%lu",
    734  1.1.1.3     joerg 		    (unsigned long)archive_entry_gid(entry));
    735  1.1.1.3     joerg 		w = strlen(tmp);
    736  1.1.1.3     joerg 		fprintf(out, "%s", tmp);
    737  1.1.1.3     joerg 	}
    738  1.1.1.3     joerg 
    739  1.1.1.3     joerg 	/*
    740  1.1.1.3     joerg 	 * Print device number or file size, right-aligned so as to make
    741  1.1.1.3     joerg 	 * total width of group and devnum/filesize fields be gs_width.
    742  1.1.1.3     joerg 	 * If gs_width is too small, grow it.
    743  1.1.1.3     joerg 	 */
    744  1.1.1.3     joerg 	if (archive_entry_filetype(entry) == AE_IFCHR
    745  1.1.1.3     joerg 	    || archive_entry_filetype(entry) == AE_IFBLK) {
    746  1.1.1.4  christos 		snprintf(tmp, sizeof(tmp), "%lu,%lu",
    747  1.1.1.3     joerg 		    (unsigned long)archive_entry_rdevmajor(entry),
    748  1.1.1.3     joerg 		    (unsigned long)archive_entry_rdevminor(entry));
    749  1.1.1.3     joerg 	} else {
    750  1.1.1.3     joerg 		strcpy(tmp, tar_i64toa(archive_entry_size(entry)));
    751  1.1.1.3     joerg 	}
    752  1.1.1.3     joerg 	if (w + strlen(tmp) >= bsdtar->gs_width)
    753  1.1.1.3     joerg 		bsdtar->gs_width = w+strlen(tmp)+1;
    754  1.1.1.3     joerg 	fprintf(out, "%*s", (int)(bsdtar->gs_width - w), tmp);
    755  1.1.1.3     joerg 
    756  1.1.1.3     joerg 	/* Format the time using 'ls -l' conventions. */
    757  1.1.1.3     joerg 	tim = archive_entry_mtime(entry);
    758  1.1.1.3     joerg #define	HALF_YEAR (time_t)365 * 86400 / 2
    759  1.1.1.3     joerg #if defined(_WIN32) && !defined(__CYGWIN__)
    760  1.1.1.3     joerg #define	DAY_FMT  "%d"  /* Windows' strftime function does not support %e format. */
    761  1.1.1.3     joerg #else
    762  1.1.1.3     joerg #define	DAY_FMT  "%e"  /* Day number without leading zeros */
    763  1.1.1.3     joerg #endif
    764  1.1.1.3     joerg 	if (tim < now - HALF_YEAR || tim > now + HALF_YEAR)
    765  1.1.1.3     joerg 		fmt = bsdtar->day_first ? DAY_FMT " %b  %Y" : "%b " DAY_FMT "  %Y";
    766  1.1.1.3     joerg 	else
    767  1.1.1.3     joerg 		fmt = bsdtar->day_first ? DAY_FMT " %b %H:%M" : "%b " DAY_FMT " %H:%M";
    768  1.1.1.4  christos #if defined(HAVE_LOCALTIME_S)
    769  1.1.1.4  christos 	ltime = localtime_s(&tmbuf, &tim) ? NULL : &tmbuf;
    770  1.1.1.4  christos #elif defined(HAVE_LOCALTIME_R)
    771  1.1.1.4  christos 	ltime = localtime_r(&tim, &tmbuf);
    772  1.1.1.4  christos #else
    773  1.1.1.4  christos 	ltime = localtime(&tim);
    774  1.1.1.4  christos #endif
    775  1.1.1.6  christos 	if (ltime)
    776  1.1.1.6  christos 		sw = strftime(tmp, sizeof(tmp), fmt, ltime);
    777  1.1.1.6  christos 	if (!ltime || !sw)
    778  1.1.1.6  christos 		sprintf(tmp, "-- -- ----");
    779  1.1.1.3     joerg 	fprintf(out, " %s ", tmp);
    780  1.1.1.3     joerg 	safe_fprintf(out, "%s", archive_entry_pathname(entry));
    781  1.1.1.3     joerg 
    782  1.1.1.3     joerg 	/* Extra information for links. */
    783  1.1.1.3     joerg 	if (archive_entry_hardlink(entry)) /* Hard link */
    784  1.1.1.3     joerg 		safe_fprintf(out, " link to %s",
    785  1.1.1.3     joerg 		    archive_entry_hardlink(entry));
    786  1.1.1.3     joerg 	else if (archive_entry_symlink(entry)) /* Symbolic link */
    787  1.1.1.3     joerg 		safe_fprintf(out, " -> %s", archive_entry_symlink(entry));
    788  1.1.1.3     joerg }
    789