diff --git a/doc/DETAILS b/doc/DETAILS index 10307bae0..4c1e9b67c 100644 --- a/doc/DETAILS +++ b/doc/DETAILS @@ -1183,6 +1183,17 @@ pkd:0:1024:B665B1435F4C2 .... FF26ABB: send to the client instead of this status line. Such an inquiry may be used to sync with Pinentry +*** GPGTAR_EXTRACT + This status line is emitted after gpgtar has extracted files. + + - tot :: Total number of files extracted and stored + - skp :: Total number of files skipped during extraction + - bad :: Number of files skipped due to a bad file name + - sus :: Number of files skipped due to a suspicious file name + - sym :: Number of symlinks not restored + - hrd :: Number of hard links not restored + - oth :: Number of files not extracted due to other reasons. + ** Obsolete status codes *** SIGEXPIRED Removed on 2011-02-04. This is deprecated in favor of KEYEXPIRED. diff --git a/tools/gpgtar-extract.c b/tools/gpgtar-extract.c index e690dde7a..936d03e3e 100644 --- a/tools/gpgtar-extract.c +++ b/tools/gpgtar-extract.c @@ -37,7 +37,7 @@ #include "gpgtar.h" static gpg_error_t -check_suspicious_name (const char *name) +check_suspicious_name (const char *name, tarinfo_t info) { size_t n; @@ -47,6 +47,7 @@ check_suspicious_name (const char *name) { log_error ("filename '%s' contains a backslash - " "can't extract on this system\n", name); + info->skipped_badname++; return gpg_error (GPG_ERR_INV_NAME); } #endif /*HAVE_DOSISH_SYSTEM*/ @@ -59,6 +60,7 @@ check_suspicious_name (const char *name) { log_error ("filename '%s' has suspicious parts - not extracting\n", name); + info->skipped_suspicious++; return gpg_error (GPG_ERR_INV_NAME); } @@ -83,7 +85,7 @@ extract_regular (estream_t stream, const char *dirname, if (sl->flags == 1) fname = sl->d; - err = check_suspicious_name (fname); + err = check_suspicious_name (fname, info); if (err) goto leave; @@ -131,8 +133,12 @@ extract_regular (estream_t stream, const char *dirname, /* Fixme: Set permissions etc. */ leave: - if (!err && opt.verbose) - log_info ("extracted '%s'\n", fname); + if (!err) + { + if (opt.verbose) + log_info ("extracted '%s'\n", fname); + info->nextracted++; + } es_fclose (outfp); if (err && fname && outfp) { @@ -146,7 +152,8 @@ extract_regular (estream_t stream, const char *dirname, static gpg_error_t -extract_directory (const char *dirname, tar_header_t hdr, strlist_t exthdr) +extract_directory (const char *dirname, tarinfo_t info, + tar_header_t hdr, strlist_t exthdr) { gpg_error_t err; const char *name; @@ -158,7 +165,7 @@ extract_directory (const char *dirname, tar_header_t hdr, strlist_t exthdr) if (sl->flags == 1) name = sl->d; - err = check_suspicious_name (name); + err = check_suspicious_name (name, info); if (err) goto leave; @@ -230,13 +237,19 @@ extract (estream_t stream, const char *dirname, tarinfo_t info, if (hdr->typeflag == TF_REGULAR || hdr->typeflag == TF_UNKNOWN) err = extract_regular (stream, dirname, info, hdr, exthdr); else if (hdr->typeflag == TF_DIRECTORY) - err = extract_directory (dirname, hdr, exthdr); + err = extract_directory (dirname, info, hdr, exthdr); else { char record[RECORDSIZE]; log_info ("unsupported file type %d for '%s' - skipped\n", (int)hdr->typeflag, hdr->name); + if (hdr->typeflag == TF_SYMLINK) + info->skipped_symlinks++; + else if (hdr->typeflag == TF_HARDLINK) + info->skipped_hardlinks++; + else + info->skipped_other++; for (err = 0, n=0; !err && n < hdr->nrecords; n++) { err = read_record (stream, record); @@ -328,7 +341,7 @@ gpgtar_extract (const char *filename, int decrypt) tarinfo_t tarinfo = &tarinfo_buffer; pid_t pid = (pid_t)(-1); char *logfilename = NULL; - + unsigned long long notextracted; memset (&tarinfo_buffer, 0, sizeof tarinfo_buffer); @@ -478,8 +491,37 @@ gpgtar_extract (const char *filename, int decrypt) } } - leave: + notextracted = tarinfo->skipped_badname; + notextracted += tarinfo->skipped_suspicious; + notextracted += tarinfo->skipped_symlinks; + notextracted += tarinfo->skipped_hardlinks; + notextracted += tarinfo->skipped_other; + if (opt.status_stream) + es_fprintf (opt.status_stream, "[GNUPG:] GPGTAR_EXTRACT" + " %llu %llu %lu %lu %lu %lu %lu\n", + tarinfo->nextracted, + notextracted, + tarinfo->skipped_badname, + tarinfo->skipped_suspicious, + tarinfo->skipped_symlinks, + tarinfo->skipped_hardlinks, + tarinfo->skipped_other); + if (notextracted && !opt.quiet) + { + log_info ("Number of files not extracted: %llu\n", notextracted); + if (tarinfo->skipped_badname) + log_info (" invalid name: %lu\n", tarinfo->skipped_badname); + if (tarinfo->skipped_suspicious) + log_info (" suspicious name: %lu\n", tarinfo->skipped_suspicious); + if (tarinfo->skipped_symlinks) + log_info (" symlink: %lu\n", tarinfo->skipped_symlinks); + if (tarinfo->skipped_hardlinks) + log_info (" hardlink: %lu\n", tarinfo->skipped_hardlinks); + if (tarinfo->skipped_other) + log_info (" other reason: %lu\n", tarinfo->skipped_other); + } + free_strlist (extheader); xfree (header); xfree (dirname); diff --git a/tools/gpgtar.h b/tools/gpgtar.h index 303db0045..9177fcfcb 100644 --- a/tools/gpgtar.h +++ b/tools/gpgtar.h @@ -54,8 +54,14 @@ struct /* An info structure to avoid global variables. */ struct tarinfo_s { - unsigned long long nblocks; /* Count of processed blocks. */ + unsigned long long nblocks; /* Count of processed blocks. */ unsigned long long headerblock; /* Number of current header block. */ + unsigned long long nextracted; /* Number of extracted files. */ + unsigned long skipped_badname; + unsigned long skipped_suspicious; + unsigned long skipped_symlinks; + unsigned long skipped_hardlinks; + unsigned long skipped_other; }; typedef struct tarinfo_s *tarinfo_t;