tools/gpgtar: Rework argument parsing.
[gnupg.git] / tools / gpgtar-create.c
1 /* gpgtar-create.c - Create a TAR archive
2  * Copyright (C) 2010 Free Software Foundation, Inc.
3  *
4  * This file is part of GnuPG.
5  *
6  * GnuPG is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * GnuPG is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, see <http://www.gnu.org/licenses/>.
18  */
19
20 #include <config.h>
21 #include <errno.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <sys/types.h>
26 #include <sys/stat.h>
27 #include <dirent.h>
28 #ifdef HAVE_W32_SYSTEM
29 # define WIN32_LEAN_AND_MEAN
30 # include <windows.h>
31 #else /*!HAVE_W32_SYSTEM*/
32 # include <unistd.h>
33 # include <pwd.h>
34 # include <grp.h>
35 #endif /*!HAVE_W32_SYSTEM*/
36 #include <assert.h>
37
38 #include "i18n.h"
39 #include "../common/call-gpg.h"
40 #include "../common/sysutils.h"
41 #include "gpgtar.h"
42
43 #ifndef HAVE_LSTAT
44 #define lstat(a,b) stat ((a), (b))
45 #endif
46
47
48 /* Object to control the file scanning.  */
49 struct scanctrl_s;
50 typedef struct scanctrl_s *scanctrl_t;
51 struct scanctrl_s
52 {
53   tar_header_t flist;
54   tar_header_t *flist_tail;
55   int nestlevel;
56 };
57
58
59
60
61 /* Given a fresh header object HDR with only the name field set, try
62    to gather all available info.  This is the W32 version.  */
63 #ifdef HAVE_W32_SYSTEM
64 static gpg_error_t
65 fillup_entry_w32 (tar_header_t hdr)
66 {
67   char *p;
68   wchar_t *wfname;
69   WIN32_FILE_ATTRIBUTE_DATA fad;
70   DWORD attr;
71
72   for (p=hdr->name; *p; p++)
73     if (*p == '/')
74       *p = '\\';
75   wfname = utf8_to_wchar (hdr->name);
76   for (p=hdr->name; *p; p++)
77     if (*p == '\\')
78       *p = '/';
79   if (!wfname)
80     {
81       log_error ("error utf8-ing '%s': %s\n", hdr->name, w32_strerror (-1));
82       return gpg_error_from_syserror ();
83     }
84   if (!GetFileAttributesExW (wfname, GetFileExInfoStandard, &fad))
85     {
86       log_error ("error stat-ing '%s': %s\n", hdr->name, w32_strerror (-1));
87       xfree (wfname);
88       return gpg_error_from_syserror ();
89     }
90   xfree (wfname);
91
92   attr = fad.dwFileAttributes;
93
94   if ((attr & FILE_ATTRIBUTE_NORMAL))
95     hdr->typeflag = TF_REGULAR;
96   else if ((attr & FILE_ATTRIBUTE_DIRECTORY))
97     hdr->typeflag = TF_DIRECTORY;
98   else if ((attr & FILE_ATTRIBUTE_DEVICE))
99     hdr->typeflag = TF_NOTSUP;
100   else if ((attr & (FILE_ATTRIBUTE_OFFLINE | FILE_ATTRIBUTE_TEMPORARY)))
101     hdr->typeflag = TF_NOTSUP;
102   else
103     hdr->typeflag = TF_REGULAR;
104
105   /* Map some attributes to  USTAR defined mode bits.  */
106   hdr->mode = 0640;      /* User may read and write, group only read.  */
107   if ((attr & FILE_ATTRIBUTE_DIRECTORY))
108     hdr->mode |= 0110;   /* Dirs are user and group executable.  */
109   if ((attr & FILE_ATTRIBUTE_READONLY))
110     hdr->mode &= ~0200;  /* Clear the user write bit.  */
111   if ((attr & FILE_ATTRIBUTE_HIDDEN))
112     hdr->mode &= ~0707;  /* Clear all user and other bits.  */
113   if ((attr & FILE_ATTRIBUTE_SYSTEM))
114     hdr->mode |= 0004;   /* Make it readable by other.  */
115
116   /* Only set the size for a regular file.  */
117   if (hdr->typeflag == TF_REGULAR)
118     hdr->size = (fad.nFileSizeHigh * (unsigned long long)(MAXDWORD+1)
119                  + fad.nFileSizeLow);
120
121   hdr->mtime = (((unsigned long long)fad.ftLastWriteTime.dwHighDateTime << 32)
122                 | fad.ftLastWriteTime.dwLowDateTime);
123   if (!hdr->mtime)
124     hdr->mtime = (((unsigned long long)fad.ftCreationTime.dwHighDateTime << 32)
125                   | fad.ftCreationTime.dwLowDateTime);
126   hdr->mtime -= 116444736000000000ULL; /* The filetime epoch is 1601-01-01.  */
127   hdr->mtime /= 10000000;  /* Convert from 0.1us to seconds. */
128
129   return 0;
130 }
131 #endif /*HAVE_W32_SYSTEM*/
132
133
134 /* Given a fresh header object HDR with only the name field set, try
135    to gather all available info.  This is the POSIX version.  */
136 #ifndef HAVE_W32_SYSTEM
137 static gpg_error_t
138 fillup_entry_posix (tar_header_t hdr)
139 {
140   gpg_error_t err;
141   struct stat sbuf;
142
143   if (lstat (hdr->name, &sbuf))
144     {
145       err = gpg_error_from_syserror ();
146       log_error ("error stat-ing '%s': %s\n", hdr->name, gpg_strerror (err));
147       return err;
148     }
149
150   if (S_ISREG (sbuf.st_mode))
151     hdr->typeflag = TF_REGULAR;
152   else if (S_ISDIR (sbuf.st_mode))
153     hdr->typeflag = TF_DIRECTORY;
154   else if (S_ISCHR (sbuf.st_mode))
155     hdr->typeflag = TF_CHARDEV;
156   else if (S_ISBLK (sbuf.st_mode))
157     hdr->typeflag = TF_BLOCKDEV;
158   else if (S_ISFIFO (sbuf.st_mode))
159     hdr->typeflag = TF_FIFO;
160   else if (S_ISLNK (sbuf.st_mode))
161     hdr->typeflag = TF_SYMLINK;
162   else
163     hdr->typeflag = TF_NOTSUP;
164
165   /* FIXME: Save DEV and INO? */
166
167   /* Set the USTAR defined mode bits using the system macros.  */
168   if (sbuf.st_mode & S_IRUSR)
169     hdr->mode |= 0400;
170   if (sbuf.st_mode & S_IWUSR)
171     hdr->mode |= 0200;
172   if (sbuf.st_mode & S_IXUSR)
173     hdr->mode |= 0100;
174   if (sbuf.st_mode & S_IRGRP)
175     hdr->mode |= 0040;
176   if (sbuf.st_mode & S_IWGRP)
177     hdr->mode |= 0020;
178   if (sbuf.st_mode & S_IXGRP)
179     hdr->mode |= 0010;
180   if (sbuf.st_mode & S_IROTH)
181     hdr->mode |= 0004;
182   if (sbuf.st_mode & S_IWOTH)
183     hdr->mode |= 0002;
184   if (sbuf.st_mode & S_IXOTH)
185     hdr->mode |= 0001;
186 #ifdef S_IXUID
187   if (sbuf.st_mode & S_IXUID)
188     hdr->mode |= 04000;
189 #endif
190 #ifdef S_IXGID
191   if (sbuf.st_mode & S_IXGID)
192     hdr->mode |= 02000;
193 #endif
194 #ifdef S_ISVTX
195   if (sbuf.st_mode & S_ISVTX)
196     hdr->mode |= 01000;
197 #endif
198
199   hdr->nlink = sbuf.st_nlink;
200
201   hdr->uid = sbuf.st_uid;
202   hdr->gid = sbuf.st_gid;
203
204   /* Only set the size for a regular file.  */
205   if (hdr->typeflag == TF_REGULAR)
206     hdr->size = sbuf.st_size;
207
208   hdr->mtime = sbuf.st_mtime;
209
210   return 0;
211 }
212 #endif /*!HAVE_W32_SYSTEM*/
213
214
215 /* Add a new entry.  The name of a director entry is ENTRYNAME; if
216    that is NULL, DNAME is the name of the directory itself.  Under
217    Windows ENTRYNAME shall have backslashes replaced by standard
218    slashes.  */
219 static gpg_error_t
220 add_entry (const char *dname, const char *entryname, scanctrl_t scanctrl)
221 {
222   gpg_error_t err;
223   tar_header_t hdr;
224   char *p;
225   size_t dnamelen = strlen (dname);
226
227   assert (dnamelen);
228
229   hdr = xtrycalloc (1, sizeof *hdr + dnamelen + 1
230                     + (entryname? strlen (entryname) : 0) + 1);
231   if (!hdr)
232     return gpg_error_from_syserror ();
233
234   p = stpcpy (hdr->name, dname);
235   if (entryname)
236     {
237       if (dname[dnamelen-1] != '/')
238         *p++ = '/';
239       strcpy (p, entryname);
240     }
241   else
242     {
243       if (hdr->name[dnamelen-1] == '/')
244         hdr->name[dnamelen-1] = 0;
245     }
246 #ifdef HAVE_DOSISH_SYSTEM
247   err = fillup_entry_w32 (hdr);
248 #else
249   err = fillup_entry_posix (hdr);
250 #endif
251   if (err)
252     xfree (hdr);
253   else
254     {
255       if (opt.verbose)
256         gpgtar_print_header (hdr, log_get_stream ());
257       *scanctrl->flist_tail = hdr;
258       scanctrl->flist_tail = &hdr->next;
259     }
260
261   return 0;
262 }
263
264
265 static gpg_error_t
266 scan_directory (const char *dname, scanctrl_t scanctrl)
267 {
268   gpg_error_t err = 0;
269
270 #ifdef HAVE_W32_SYSTEM
271   WIN32_FIND_DATAW fi;
272   HANDLE hd = INVALID_HANDLE_VALUE;
273   char *p;
274
275   if (!*dname)
276     return 0;  /* An empty directory name has no entries.  */
277
278   {
279     char *fname;
280     wchar_t *wfname;
281
282     fname = xtrymalloc (strlen (dname) + 2 + 2 + 1);
283     if (!fname)
284       {
285         err = gpg_error_from_syserror ();
286         goto leave;
287       }
288     if (!strcmp (dname, "/"))
289       strcpy (fname, "/*"); /* Trailing slash is not allowed.  */
290     else if (!strcmp (dname, "."))
291       strcpy (fname, "*");
292     else if (*dname && dname[strlen (dname)-1] == '/')
293       strcpy (stpcpy (fname, dname), "*");
294     else if (*dname && dname[strlen (dname)-1] != '*')
295       strcpy (stpcpy (fname, dname), "/*");
296     else
297       strcpy (fname, dname);
298
299     for (p=fname; *p; p++)
300       if (*p == '/')
301         *p = '\\';
302     wfname = utf8_to_wchar (fname);
303     xfree (fname);
304     if (!wfname)
305       {
306         err = gpg_error_from_syserror ();
307         log_error (_("error reading directory '%s': %s\n"),
308                    dname, gpg_strerror (err));
309         goto leave;
310       }
311     hd = FindFirstFileW (wfname, &fi);
312     if (hd == INVALID_HANDLE_VALUE)
313       {
314         err = gpg_error_from_syserror ();
315         log_error (_("error reading directory '%s': %s\n"),
316                    dname, w32_strerror (-1));
317         xfree (wfname);
318         goto leave;
319       }
320     xfree (wfname);
321   }
322
323   do
324     {
325       char *fname = wchar_to_utf8 (fi.cFileName);
326       if (!fname)
327         {
328           err = gpg_error_from_syserror ();
329           log_error ("error utf8-ing filename: %s\n", w32_strerror (-1));
330           break;
331         }
332       for (p=fname; *p; p++)
333         if (*p == '\\')
334           *p = '/';
335       if (!strcmp (fname, "." ) || !strcmp (fname, ".."))
336         err = 0; /* Skip self and parent dir entry.  */
337       else if (!strncmp (dname, "./", 2) && dname[2])
338         err = add_entry (dname+2, fname, scanctrl);
339       else
340         err = add_entry (dname, fname, scanctrl);
341       xfree (fname);
342     }
343   while (!err && FindNextFileW (hd, &fi));
344   if (err)
345     ;
346   else if (GetLastError () == ERROR_NO_MORE_FILES)
347     err = 0;
348   else
349     {
350       err = gpg_error_from_syserror ();
351       log_error (_("error reading directory '%s': %s\n"),
352                  dname, w32_strerror (-1));
353     }
354
355  leave:
356   if (hd != INVALID_HANDLE_VALUE)
357     FindClose (hd);
358
359 #else /*!HAVE_W32_SYSTEM*/
360   DIR *dir;
361   struct dirent *de;
362
363   if (!*dname)
364     return 0;  /* An empty directory name has no entries.  */
365
366   dir = opendir (dname);
367   if (!dir)
368     {
369       err = gpg_error_from_syserror ();
370       log_error (_("error reading directory '%s': %s\n"),
371                  dname, gpg_strerror (err));
372       return err;
373     }
374
375   while ((de = readdir (dir)))
376     {
377       if (!strcmp (de->d_name, "." ) || !strcmp (de->d_name, ".."))
378         continue; /* Skip self and parent dir entry.  */
379
380       err = add_entry (dname, de->d_name, scanctrl);
381       if (err)
382         goto leave;
383      }
384
385  leave:
386   closedir (dir);
387 #endif /*!HAVE_W32_SYSTEM*/
388   return err;
389 }
390
391
392 static gpg_error_t
393 scan_recursive (const char *dname, scanctrl_t scanctrl)
394 {
395   gpg_error_t err = 0;
396   tar_header_t hdr, *start_tail, *stop_tail;
397
398   if (scanctrl->nestlevel > 200)
399     {
400       log_error ("directories too deeply nested\n");
401       return gpg_error (GPG_ERR_RESOURCE_LIMIT);
402     }
403   scanctrl->nestlevel++;
404
405   assert (scanctrl->flist_tail);
406   start_tail = scanctrl->flist_tail;
407   scan_directory (dname, scanctrl);
408   stop_tail = scanctrl->flist_tail;
409   hdr = *start_tail;
410   for (; hdr && hdr != *stop_tail; hdr = hdr->next)
411     if (hdr->typeflag == TF_DIRECTORY)
412       {
413         if (opt.verbose > 1)
414           log_info ("scanning directory '%s'\n", hdr->name);
415         scan_recursive (hdr->name, scanctrl);
416       }
417
418   scanctrl->nestlevel--;
419   return err;
420 }
421
422
423 /* Returns true if PATTERN is acceptable.  */
424 static int
425 pattern_valid_p (const char *pattern)
426 {
427   if (!*pattern)
428     return 0;
429   if (*pattern == '.' && pattern[1] == '.')
430     return 0;
431   if (*pattern == '/' || *pattern == DIRSEP_C)
432     return 0; /* Absolute filenames are not supported.  */
433 #ifdef HAVE_DRIVE_LETTERS
434   if (((*pattern >= 'a' && *pattern <= 'z')
435        || (*pattern >= 'A' && *pattern <= 'Z'))
436       && pattern[1] == ':')
437     return 0; /* Drive letter are not allowed either.  */
438 #endif /*HAVE_DRIVE_LETTERS*/
439
440   return 1; /* Okay.  */
441 }
442
443
444 \f
445 static void
446 store_xoctal (char *buffer, size_t length, unsigned long long value)
447 {
448   char *p, *pend;
449   size_t n;
450   unsigned long long v;
451
452   assert (length > 1);
453
454   v = value;
455   n = length;
456   p = pend = buffer + length;
457   *--p = 0; /* Nul byte.  */
458   n--;
459   do
460     {
461       *--p = '0' + (v % 8);
462       v /= 8;
463       n--;
464     }
465   while (v && n);
466   if (!v)
467     {
468       /* Pad.  */
469       for ( ; n; n--)
470         *--p = '0';
471     }
472   else /* Does not fit into the field.  Store as binary number.  */
473     {
474       v = value;
475       n = length;
476       p = pend = buffer + length;
477       do
478         {
479           *--p = v;
480           v /= 256;
481           n--;
482         }
483       while (v && n);
484       if (!v)
485         {
486           /* Pad.  */
487           for ( ; n; n--)
488             *--p = 0;
489           if (*p & 0x80)
490             BUG ();
491           *p |= 0x80; /* Set binary flag.  */
492         }
493       else
494         BUG ();
495     }
496 }
497
498
499 static void
500 store_uname (char *buffer, size_t length, unsigned long uid)
501 {
502   static int initialized;
503   static unsigned long lastuid;
504   static char lastuname[32];
505
506   if (!initialized || uid != lastuid)
507     {
508 #ifdef HAVE_W32_SYSTEM
509       mem2str (lastuname, uid? "user":"root", sizeof lastuname);
510 #else
511       struct passwd *pw = getpwuid (uid);
512
513       lastuid = uid;
514       initialized = 1;
515       if (pw)
516         mem2str (lastuname, pw->pw_name, sizeof lastuname);
517       else
518         {
519           log_info ("failed to get name for uid %lu\n", uid);
520           *lastuname = 0;
521         }
522 #endif
523     }
524   mem2str (buffer, lastuname, length);
525 }
526
527
528 static void
529 store_gname (char *buffer, size_t length, unsigned long gid)
530 {
531   static int initialized;
532   static unsigned long lastgid;
533   static char lastgname[32];
534
535   if (!initialized || gid != lastgid)
536     {
537 #ifdef HAVE_W32_SYSTEM
538       mem2str (lastgname, gid? "users":"root", sizeof lastgname);
539 #else
540       struct group *gr = getgrgid (gid);
541
542       lastgid = gid;
543       initialized = 1;
544       if (gr)
545         mem2str (lastgname, gr->gr_name, sizeof lastgname);
546       else
547         {
548           log_info ("failed to get name for gid %lu\n", gid);
549           *lastgname = 0;
550         }
551 #endif
552     }
553   mem2str (buffer, lastgname, length);
554 }
555
556
557 static gpg_error_t
558 build_header (void *record, tar_header_t hdr)
559 {
560   gpg_error_t err;
561   struct ustar_raw_header *raw = record;
562   size_t namelen, n;
563   unsigned long chksum;
564   unsigned char *p;
565
566   memset (record, 0, RECORDSIZE);
567
568   /* Store name and prefix.  */
569   namelen = strlen (hdr->name);
570   if (namelen < sizeof raw->name)
571     memcpy (raw->name, hdr->name, namelen);
572   else
573     {
574       n = (namelen < sizeof raw->prefix)? namelen : sizeof raw->prefix;
575       for (n--; n ; n--)
576         if (hdr->name[n] == '/')
577           break;
578       if (namelen - n < sizeof raw->name)
579         {
580           /* Note that the N is < sizeof prefix and that the
581              delimiting slash is not stored.  */
582           memcpy (raw->prefix, hdr->name, n);
583           memcpy (raw->name, hdr->name+n+1, namelen - n);
584         }
585       else
586         {
587           err = gpg_error (GPG_ERR_TOO_LARGE);
588           log_error ("error storing file '%s': %s\n",
589                      hdr->name, gpg_strerror (err));
590           return err;
591         }
592     }
593
594   store_xoctal (raw->mode,  sizeof raw->mode,  hdr->mode);
595   store_xoctal (raw->uid,   sizeof raw->uid,   hdr->uid);
596   store_xoctal (raw->gid,   sizeof raw->gid,   hdr->gid);
597   store_xoctal (raw->size,  sizeof raw->size,  hdr->size);
598   store_xoctal (raw->mtime, sizeof raw->mtime, hdr->mtime);
599
600   switch (hdr->typeflag)
601     {
602     case TF_REGULAR:   raw->typeflag[0] = '0'; break;
603     case TF_HARDLINK:  raw->typeflag[0] = '1'; break;
604     case TF_SYMLINK:   raw->typeflag[0] = '2'; break;
605     case TF_CHARDEV:   raw->typeflag[0] = '3'; break;
606     case TF_BLOCKDEV:  raw->typeflag[0] = '4'; break;
607     case TF_DIRECTORY: raw->typeflag[0] = '5'; break;
608     case TF_FIFO:      raw->typeflag[0] = '6'; break;
609     default: return gpg_error (GPG_ERR_NOT_SUPPORTED);
610     }
611
612   memcpy (raw->magic, "ustar", 6);
613   raw->version[0] = '0';
614   raw->version[1] = '0';
615
616   store_uname (raw->uname, sizeof raw->uname, hdr->uid);
617   store_gname (raw->gname, sizeof raw->gname, hdr->gid);
618
619 #ifndef HAVE_W32_SYSTEM
620   if (hdr->typeflag == TF_SYMLINK)
621     {
622       int nread;
623
624       nread = readlink (hdr->name, raw->linkname, sizeof raw->linkname -1);
625       if (nread < 0)
626         {
627           err = gpg_error_from_syserror ();
628           log_error ("error reading symlink '%s': %s\n",
629                      hdr->name, gpg_strerror (err));
630           return err;
631         }
632       raw->linkname[nread] = 0;
633     }
634 #endif /*HAVE_W32_SYSTEM*/
635
636   /* Compute the checksum.  */
637   memset (raw->checksum, ' ', sizeof raw->checksum);
638   chksum = 0;
639   p = record;
640   for (n=0; n < RECORDSIZE; n++)
641     chksum += *p++;
642   store_xoctal (raw->checksum, sizeof raw->checksum - 1, chksum);
643   raw->checksum[7] = ' ';
644
645   return 0;
646 }
647
648
649 static gpg_error_t
650 write_file (estream_t stream, tar_header_t hdr)
651 {
652   gpg_error_t err;
653   char record[RECORDSIZE];
654   estream_t infp;
655   size_t nread, nbytes;
656   int any;
657
658   err = build_header (record, hdr);
659   if (err)
660     {
661       if (gpg_err_code (err) == GPG_ERR_NOT_SUPPORTED)
662         {
663           log_info ("skipping unsupported file '%s'\n", hdr->name);
664           err = 0;
665         }
666       return err;
667     }
668
669   if (hdr->typeflag == TF_REGULAR)
670     {
671       infp = es_fopen (hdr->name, "rb");
672       if (!infp)
673         {
674           err = gpg_error_from_syserror ();
675           log_error ("can't open '%s': %s - skipped\n",
676                      hdr->name, gpg_strerror (err));
677           return err;
678         }
679     }
680   else
681     infp = NULL;
682
683   err = write_record (stream, record);
684   if (err)
685     goto leave;
686
687   if (hdr->typeflag == TF_REGULAR)
688     {
689       hdr->nrecords = (hdr->size + RECORDSIZE-1)/RECORDSIZE;
690       any = 0;
691       while (hdr->nrecords--)
692         {
693           nbytes = hdr->nrecords? RECORDSIZE : (hdr->size % RECORDSIZE);
694           if (!nbytes)
695             nbytes = RECORDSIZE;
696           nread = es_fread (record, 1, nbytes, infp);
697           if (nread != nbytes)
698             {
699               err = gpg_error_from_syserror ();
700               log_error ("error reading file '%s': %s%s\n",
701                          hdr->name, gpg_strerror (err),
702                          any? " (file shrunk?)":"");
703               goto leave;
704             }
705           any = 1;
706           err = write_record (stream, record);
707           if (err)
708             goto leave;
709         }
710       nread = es_fread (record, 1, 1, infp);
711       if (nread)
712         log_info ("note: file '%s' has grown\n", hdr->name);
713     }
714
715  leave:
716   if (err)
717     es_fclose (infp);
718   else if ((err = es_fclose (infp)))
719     log_error ("error closing file '%s': %s\n", hdr->name, gpg_strerror (err));
720
721   return err;
722 }
723
724
725 static gpg_error_t
726 write_eof_mark (estream_t stream)
727 {
728   gpg_error_t err;
729   char record[RECORDSIZE];
730
731   memset (record, 0, sizeof record);
732   err = write_record (stream, record);
733   if (!err)
734     err = write_record (stream, record);
735   return err;
736 }
737
738
739 \f
740 /* Create a new tarball using the names in the array INPATTERN.  If
741    INPATTERN is NULL take the pattern as null terminated strings from
742    stdin.  */
743 gpg_error_t
744 gpgtar_create (char **inpattern, int encrypt)
745 {
746   gpg_error_t err = 0;
747   struct scanctrl_s scanctrl_buffer;
748   scanctrl_t scanctrl = &scanctrl_buffer;
749   tar_header_t hdr, *start_tail;
750   estream_t outstream = NULL;
751   estream_t cipher_stream = NULL;
752   int eof_seen = 0;
753
754   if (!inpattern)
755     es_set_binary (es_stdin);
756
757   memset (scanctrl, 0, sizeof *scanctrl);
758   scanctrl->flist_tail = &scanctrl->flist;
759
760   while (!eof_seen)
761     {
762       char *pat, *p;
763       int skip_this = 0;
764
765       if (inpattern)
766         {
767           const char *pattern = *inpattern;
768
769           if (!pattern)
770             break; /* End of array.  */
771           inpattern++;
772
773           if (!*pattern)
774             continue;
775
776           pat = xtrystrdup (pattern);
777         }
778       else /* Read null delimited pattern from stdin.  */
779         {
780           int c;
781           char namebuf[4096];
782           size_t n = 0;
783
784           for (;;)
785             {
786               if ((c = es_getc (es_stdin)) == EOF)
787                 {
788                   if (es_ferror (es_stdin))
789                     {
790                       err = gpg_error_from_syserror ();
791                       log_error ("error reading '%s': %s\n",
792                                  "[stdin]", strerror (errno));
793                       goto leave;
794                     }
795                   /* Note: The Nul is a delimiter and not a terminator.  */
796                   c = 0;
797                   eof_seen = 1;
798                 }
799               if (n >= sizeof namebuf - 1)
800                 {
801                   if (!skip_this)
802                     {
803                       skip_this = 1;
804                       log_error ("error reading '%s': %s\n",
805                                  "[stdin]", "filename too long");
806                     }
807                 }
808               else
809                 namebuf[n++] = c;
810               if (!c)
811                 {
812                   namebuf[n] = 0;
813                   break;
814                 }
815             }
816
817           if (skip_this || n < 2)
818             continue;
819
820           pat = xtrystrdup (namebuf);
821         }
822
823       if (!pat)
824         {
825           err = gpg_error_from_syserror ();
826           log_error ("memory allocation problem: %s\n", gpg_strerror (err));
827           goto leave;
828         }
829       for (p=pat; *p; p++)
830         if (*p == '\\')
831           *p = '/';
832
833       if (opt.verbose > 1)
834         log_info ("scanning '%s'\n", pat);
835
836       start_tail = scanctrl->flist_tail;
837       if (skip_this || !pattern_valid_p (pat))
838         log_error ("skipping invalid name '%s'\n", pat);
839       else if (!add_entry (pat, NULL, scanctrl)
840                && *start_tail && ((*start_tail)->typeflag & TF_DIRECTORY))
841         scan_recursive (pat, scanctrl);
842
843       xfree (pat);
844     }
845
846   if (opt.outfile)
847     {
848       if (!strcmp (opt.outfile, "-"))
849         outstream = es_stdout;
850       else
851         outstream = es_fopen (opt.outfile, "wb");
852       if (!outstream)
853         {
854           err = gpg_error_from_syserror ();
855           log_error (_("can't create '%s': %s\n"),
856                      opt.outfile, gpg_strerror (err));
857           goto leave;
858         }
859     }
860   else
861     {
862       outstream = es_stdout;
863     }
864
865   if (outstream == es_stdout)
866     es_set_binary (es_stdout);
867
868   if (encrypt)
869     {
870       cipher_stream = outstream;
871       outstream = es_fopenmem (0, "rwb");
872       if (! outstream)
873         {
874           err = gpg_error_from_syserror ();
875           goto leave;
876         }
877     }
878
879   for (hdr = scanctrl->flist; hdr; hdr = hdr->next)
880     {
881       err = write_file (outstream, hdr);
882       if (err)
883         goto leave;
884     }
885   err = write_eof_mark (outstream);
886   if (err)
887     goto leave;
888
889   if (encrypt)
890     {
891       err = es_fseek (outstream, 0, SEEK_SET);
892       if (err)
893         goto leave;
894
895       err = gpg_encrypt_stream (NULL,
896                                 opt.gpg_program,
897                                 outstream,
898                                 opt.recipients,
899                                 cipher_stream);
900       if (err)
901         goto leave;
902     }
903
904  leave:
905   if (!err)
906     {
907       gpg_error_t first_err;
908       if (outstream != es_stdout)
909         first_err = es_fclose (outstream);
910       else
911         first_err = es_fflush (outstream);
912       outstream = NULL;
913       if (cipher_stream != es_stdout)
914         err = es_fclose (cipher_stream);
915       else
916         err = es_fflush (cipher_stream);
917       cipher_stream = NULL;
918       if (! err)
919         err = first_err;
920     }
921   if (err)
922     {
923       log_error ("creating tarball '%s' failed: %s\n",
924                  es_fname_get (outstream), gpg_strerror (err));
925       if (outstream && outstream != es_stdout)
926         es_fclose (outstream);
927       if (cipher_stream && cipher_stream != es_stdout)
928         es_fclose (cipher_stream);
929       if (opt.outfile)
930         gnupg_remove (opt.outfile);
931     }
932   scanctrl->flist_tail = NULL;
933   while ( (hdr = scanctrl->flist) )
934     {
935       scanctrl->flist = hdr->next;
936       xfree (hdr);
937     }
938   return err;
939 }