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