Add new gnupg version and a patch with gpgtar.
[gpg4win.git] / patches / gnupg2-2.0.16 / 02-gpgtar.patch
1 #! /bin/sh
2 patch -p1 -f $* < $0
3 exit $?
4
5 2010-07-19  Werner Koch  <wk@g10code.com>
6
7         * Makefile.am (bin_PROGRAMS): Add gpgtar.
8         (gpgtar_SOURCES, gpgtar_CFLAGS, gpgtar_LDADD): New.
9
10         * gpgtar.c, gpgtar.h, gpgtar-create.c, gpgtar-extract.c
11         * gpgtar-list.c: New.  Take from GnuPG trunk and add missing
12          functions.
13
14 diff -urNp orig/gnupg-2.0.16/tools/Makefile.am gnupg-2.0.16/tools/Makefile.am
15 --- orig/gnupg-2.0.16/tools/Makefile.am 2009-09-21 18:53:44.000000000 +0200
16 +++ gnupg-2.0.16/tools/Makefile.am      2010-07-19 10:51:22.000000000 +0200
17 @@ -42,7 +42,7 @@ else
18    symcryptrun =
19  endif
20  
21 -bin_PROGRAMS = gpgconf gpg-connect-agent gpgkey2ssh ${symcryptrun}
22 +bin_PROGRAMS = gpgconf gpg-connect-agent gpgkey2ssh ${symcryptrun} gpgtar
23  if !HAVE_W32_SYSTEM
24  bin_PROGRAMS += watchgnupg gpgparsemail
25  endif
26 @@ -99,6 +99,15 @@ gpg_check_pattern_LDADD = $(common_libs)
27                            $(LIBINTL) $(LIBICONV) $(W32SOCKLIBS)
28  endif
29  
30 +gpgtar_SOURCES = \
31 +       gpgtar.c gpgtar.h \
32 +       gpgtar-create.c \
33 +       gpgtar-extract.c \
34 +       gpgtar-list.c \
35 +       no-libgcrypt.c
36 +gpgtar_CFLAGS = $(GPG_ERROR_CFLAGS)
37 +gpgtar_LDADD = $(common_libs) $(GPG_ERROR_LIBS) $(W32SOCKLIBS)
38 +
39  # Make sure that all libs are build before we use them.  This is
40  # important for things like make -j2.
41  $(PROGRAMS): $(common_libs) $(pwquery_libs) ../common/libgpgrl.a
42 diff -urNp orig/gnupg-2.0.16/tools/Makefile.in gnupg-2.0.16/tools/Makefile.in
43 --- orig/gnupg-2.0.16/tools/Makefile.in 2010-07-19 09:05:41.000000000 +0200
44 +++ gnupg-2.0.16/tools/Makefile.in      2010-07-19 10:53:02.000000000 +0200
45 @@ -87,7 +87,8 @@ DIST_COMMON = $(srcdir)/Makefile.am $(sr
46  @GNUPG_DIRMNGR_PGM_TRUE@am__append_5 = -DGNUPG_DEFAULT_DIRMNGR="\"@GNUPG_DIRMNGR_PGM@\""
47  @GNUPG_PROTECT_TOOL_PGM_TRUE@am__append_6 = -DGNUPG_DEFAULT_PROTECT_TOOL="\"@GNUPG_PROTECT_TOOL_PGM@\""
48  bin_PROGRAMS = gpgconf$(EXEEXT) gpg-connect-agent$(EXEEXT) \
49 -       gpgkey2ssh$(EXEEXT) $(am__EXEEXT_1) $(am__EXEEXT_2)
50 +       gpgkey2ssh$(EXEEXT) $(am__EXEEXT_1) gpgtar$(EXEEXT) \
51 +       $(am__EXEEXT_2)
52  @HAVE_W32_SYSTEM_FALSE@am__append_7 = watchgnupg gpgparsemail
53  @DISABLE_REGEX_FALSE@libexec_PROGRAMS = gpg-check-pattern$(EXEEXT)
54  noinst_PROGRAMS = clean-sat$(EXEEXT) mk-tdata$(EXEEXT) \
55 @@ -173,6 +174,14 @@ gpgsplit_OBJECTS = gpgsplit.$(OBJEXT)
56  gpgsplit_DEPENDENCIES = $(common_libs) $(am__DEPENDENCIES_1) \
57         $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
58         $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
59 +am_gpgtar_OBJECTS = gpgtar-gpgtar.$(OBJEXT) \
60 +       gpgtar-gpgtar-create.$(OBJEXT) gpgtar-gpgtar-extract.$(OBJEXT) \
61 +       gpgtar-gpgtar-list.$(OBJEXT) gpgtar-no-libgcrypt.$(OBJEXT)
62 +gpgtar_OBJECTS = $(am_gpgtar_OBJECTS)
63 +gpgtar_DEPENDENCIES = $(common_libs) $(am__DEPENDENCIES_1) \
64 +       $(am__DEPENDENCIES_1)
65 +gpgtar_LINK = $(CCLD) $(gpgtar_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
66 +       $(LDFLAGS) -o $@
67  make_dns_cert_SOURCES = make-dns-cert.c
68  make_dns_cert_OBJECTS = make-dns-cert.$(OBJEXT)
69  make_dns_cert_LDADD = $(LDADD)
70 @@ -201,13 +210,13 @@ LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(
71  SOURCES = clean-sat.c $(gpg_check_pattern_SOURCES) \
72         $(gpg_connect_agent_SOURCES) $(gpgconf_SOURCES) \
73         $(gpgkey2ssh_SOURCES) $(gpgparsemail_SOURCES) gpgsplit.c \
74 -       make-dns-cert.c mk-tdata.c $(symcryptrun_SOURCES) \
75 -       $(watchgnupg_SOURCES)
76 +       $(gpgtar_SOURCES) make-dns-cert.c mk-tdata.c \
77 +       $(symcryptrun_SOURCES) $(watchgnupg_SOURCES)
78  DIST_SOURCES = clean-sat.c $(am__gpg_check_pattern_SOURCES_DIST) \
79         $(gpg_connect_agent_SOURCES) $(gpgconf_SOURCES) \
80         $(gpgkey2ssh_SOURCES) $(gpgparsemail_SOURCES) gpgsplit.c \
81 -       make-dns-cert.c mk-tdata.c $(symcryptrun_SOURCES) \
82 -       $(watchgnupg_SOURCES)
83 +       $(gpgtar_SOURCES) make-dns-cert.c mk-tdata.c \
84 +       $(symcryptrun_SOURCES) $(watchgnupg_SOURCES)
85  ETAGS = etags
86  CTAGS = ctags
87  DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
88 @@ -466,6 +475,15 @@ gpgkey2ssh_LDADD = $(common_libs) \
89  @DISABLE_REGEX_FALSE@gpg_check_pattern_LDADD = $(common_libs) $(LIBGCRYPT_LIBS) $(GPG_ERROR_LIBS) \
90  @DISABLE_REGEX_FALSE@                          $(LIBINTL) $(LIBICONV) $(W32SOCKLIBS)
91  
92 +gpgtar_SOURCES = \
93 +       gpgtar.c gpgtar.h \
94 +       gpgtar-create.c \
95 +       gpgtar-extract.c \
96 +       gpgtar-list.c \
97 +       no-libgcrypt.c
98 +
99 +gpgtar_CFLAGS = $(GPG_ERROR_CFLAGS)
100 +gpgtar_LDADD = $(common_libs) $(GPG_ERROR_LIBS) $(W32SOCKLIBS)
101  all: all-am
102  
103  .SUFFIXES:
104 @@ -571,6 +589,9 @@ gpgparsemail$(EXEEXT): $(gpgparsemail_OB
105  gpgsplit$(EXEEXT): $(gpgsplit_OBJECTS) $(gpgsplit_DEPENDENCIES) 
106         @rm -f gpgsplit$(EXEEXT)
107         $(LINK) $(gpgsplit_OBJECTS) $(gpgsplit_LDADD) $(LIBS)
108 +gpgtar$(EXEEXT): $(gpgtar_OBJECTS) $(gpgtar_DEPENDENCIES) 
109 +       @rm -f gpgtar$(EXEEXT)
110 +       $(gpgtar_LINK) $(gpgtar_OBJECTS) $(gpgtar_LDADD) $(LIBS)
111  make-dns-cert$(EXEEXT): $(make_dns_cert_OBJECTS) $(make_dns_cert_DEPENDENCIES) 
112         @rm -f make-dns-cert$(EXEEXT)
113         $(LINK) $(make_dns_cert_OBJECTS) $(make_dns_cert_LDADD) $(LIBS)
114 @@ -636,6 +657,11 @@ distclean-compile:
115  @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gpgkey2ssh-gpgkey2ssh.Po@am__quote@
116  @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gpgparsemail.Po@am__quote@
117  @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gpgsplit.Po@am__quote@
118 +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gpgtar-gpgtar-create.Po@am__quote@
119 +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gpgtar-gpgtar-extract.Po@am__quote@
120 +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gpgtar-gpgtar-list.Po@am__quote@
121 +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gpgtar-gpgtar.Po@am__quote@
122 +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gpgtar-no-libgcrypt.Po@am__quote@
123  @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/make-dns-cert.Po@am__quote@
124  @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mk-tdata.Po@am__quote@
125  @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/no-libgcrypt.Po@am__quote@
126 @@ -685,6 +711,76 @@ gpgkey2ssh-gpgkey2ssh.obj: gpgkey2ssh.c
127  @AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
128  @am__fastdepCC_FALSE@  $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gpgkey2ssh_CFLAGS) $(CFLAGS) -c -o gpgkey2ssh-gpgkey2ssh.obj `if test -f 'gpgkey2ssh.c'; then $(CYGPATH_W) 'gpgkey2ssh.c'; else $(CYGPATH_W) '$(srcdir)/gpgkey2ssh.c'; fi`
129  
130 +gpgtar-gpgtar.o: gpgtar.c
131 +@am__fastdepCC_TRUE@   $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gpgtar_CFLAGS) $(CFLAGS) -MT gpgtar-gpgtar.o -MD -MP -MF $(DEPDIR)/gpgtar-gpgtar.Tpo -c -o gpgtar-gpgtar.o `test -f 'gpgtar.c' || echo '$(srcdir)/'`gpgtar.c
132 +@am__fastdepCC_TRUE@   mv -f $(DEPDIR)/gpgtar-gpgtar.Tpo $(DEPDIR)/gpgtar-gpgtar.Po
133 +@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='gpgtar.c' object='gpgtar-gpgtar.o' libtool=no @AMDEPBACKSLASH@
134 +@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
135 +@am__fastdepCC_FALSE@  $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gpgtar_CFLAGS) $(CFLAGS) -c -o gpgtar-gpgtar.o `test -f 'gpgtar.c' || echo '$(srcdir)/'`gpgtar.c
136 +
137 +gpgtar-gpgtar.obj: gpgtar.c
138 +@am__fastdepCC_TRUE@   $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gpgtar_CFLAGS) $(CFLAGS) -MT gpgtar-gpgtar.obj -MD -MP -MF $(DEPDIR)/gpgtar-gpgtar.Tpo -c -o gpgtar-gpgtar.obj `if test -f 'gpgtar.c'; then $(CYGPATH_W) 'gpgtar.c'; else $(CYGPATH_W) '$(srcdir)/gpgtar.c'; fi`
139 +@am__fastdepCC_TRUE@   mv -f $(DEPDIR)/gpgtar-gpgtar.Tpo $(DEPDIR)/gpgtar-gpgtar.Po
140 +@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='gpgtar.c' object='gpgtar-gpgtar.obj' libtool=no @AMDEPBACKSLASH@
141 +@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
142 +@am__fastdepCC_FALSE@  $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gpgtar_CFLAGS) $(CFLAGS) -c -o gpgtar-gpgtar.obj `if test -f 'gpgtar.c'; then $(CYGPATH_W) 'gpgtar.c'; else $(CYGPATH_W) '$(srcdir)/gpgtar.c'; fi`
143 +
144 +gpgtar-gpgtar-create.o: gpgtar-create.c
145 +@am__fastdepCC_TRUE@   $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gpgtar_CFLAGS) $(CFLAGS) -MT gpgtar-gpgtar-create.o -MD -MP -MF $(DEPDIR)/gpgtar-gpgtar-create.Tpo -c -o gpgtar-gpgtar-create.o `test -f 'gpgtar-create.c' || echo '$(srcdir)/'`gpgtar-create.c
146 +@am__fastdepCC_TRUE@   mv -f $(DEPDIR)/gpgtar-gpgtar-create.Tpo $(DEPDIR)/gpgtar-gpgtar-create.Po
147 +@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='gpgtar-create.c' object='gpgtar-gpgtar-create.o' libtool=no @AMDEPBACKSLASH@
148 +@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
149 +@am__fastdepCC_FALSE@  $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gpgtar_CFLAGS) $(CFLAGS) -c -o gpgtar-gpgtar-create.o `test -f 'gpgtar-create.c' || echo '$(srcdir)/'`gpgtar-create.c
150 +
151 +gpgtar-gpgtar-create.obj: gpgtar-create.c
152 +@am__fastdepCC_TRUE@   $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gpgtar_CFLAGS) $(CFLAGS) -MT gpgtar-gpgtar-create.obj -MD -MP -MF $(DEPDIR)/gpgtar-gpgtar-create.Tpo -c -o gpgtar-gpgtar-create.obj `if test -f 'gpgtar-create.c'; then $(CYGPATH_W) 'gpgtar-create.c'; else $(CYGPATH_W) '$(srcdir)/gpgtar-create.c'; fi`
153 +@am__fastdepCC_TRUE@   mv -f $(DEPDIR)/gpgtar-gpgtar-create.Tpo $(DEPDIR)/gpgtar-gpgtar-create.Po
154 +@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='gpgtar-create.c' object='gpgtar-gpgtar-create.obj' libtool=no @AMDEPBACKSLASH@
155 +@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
156 +@am__fastdepCC_FALSE@  $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gpgtar_CFLAGS) $(CFLAGS) -c -o gpgtar-gpgtar-create.obj `if test -f 'gpgtar-create.c'; then $(CYGPATH_W) 'gpgtar-create.c'; else $(CYGPATH_W) '$(srcdir)/gpgtar-create.c'; fi`
157 +
158 +gpgtar-gpgtar-extract.o: gpgtar-extract.c
159 +@am__fastdepCC_TRUE@   $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gpgtar_CFLAGS) $(CFLAGS) -MT gpgtar-gpgtar-extract.o -MD -MP -MF $(DEPDIR)/gpgtar-gpgtar-extract.Tpo -c -o gpgtar-gpgtar-extract.o `test -f 'gpgtar-extract.c' || echo '$(srcdir)/'`gpgtar-extract.c
160 +@am__fastdepCC_TRUE@   mv -f $(DEPDIR)/gpgtar-gpgtar-extract.Tpo $(DEPDIR)/gpgtar-gpgtar-extract.Po
161 +@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='gpgtar-extract.c' object='gpgtar-gpgtar-extract.o' libtool=no @AMDEPBACKSLASH@
162 +@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
163 +@am__fastdepCC_FALSE@  $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gpgtar_CFLAGS) $(CFLAGS) -c -o gpgtar-gpgtar-extract.o `test -f 'gpgtar-extract.c' || echo '$(srcdir)/'`gpgtar-extract.c
164 +
165 +gpgtar-gpgtar-extract.obj: gpgtar-extract.c
166 +@am__fastdepCC_TRUE@   $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gpgtar_CFLAGS) $(CFLAGS) -MT gpgtar-gpgtar-extract.obj -MD -MP -MF $(DEPDIR)/gpgtar-gpgtar-extract.Tpo -c -o gpgtar-gpgtar-extract.obj `if test -f 'gpgtar-extract.c'; then $(CYGPATH_W) 'gpgtar-extract.c'; else $(CYGPATH_W) '$(srcdir)/gpgtar-extract.c'; fi`
167 +@am__fastdepCC_TRUE@   mv -f $(DEPDIR)/gpgtar-gpgtar-extract.Tpo $(DEPDIR)/gpgtar-gpgtar-extract.Po
168 +@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='gpgtar-extract.c' object='gpgtar-gpgtar-extract.obj' libtool=no @AMDEPBACKSLASH@
169 +@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
170 +@am__fastdepCC_FALSE@  $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gpgtar_CFLAGS) $(CFLAGS) -c -o gpgtar-gpgtar-extract.obj `if test -f 'gpgtar-extract.c'; then $(CYGPATH_W) 'gpgtar-extract.c'; else $(CYGPATH_W) '$(srcdir)/gpgtar-extract.c'; fi`
171 +
172 +gpgtar-gpgtar-list.o: gpgtar-list.c
173 +@am__fastdepCC_TRUE@   $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gpgtar_CFLAGS) $(CFLAGS) -MT gpgtar-gpgtar-list.o -MD -MP -MF $(DEPDIR)/gpgtar-gpgtar-list.Tpo -c -o gpgtar-gpgtar-list.o `test -f 'gpgtar-list.c' || echo '$(srcdir)/'`gpgtar-list.c
174 +@am__fastdepCC_TRUE@   mv -f $(DEPDIR)/gpgtar-gpgtar-list.Tpo $(DEPDIR)/gpgtar-gpgtar-list.Po
175 +@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='gpgtar-list.c' object='gpgtar-gpgtar-list.o' libtool=no @AMDEPBACKSLASH@
176 +@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
177 +@am__fastdepCC_FALSE@  $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gpgtar_CFLAGS) $(CFLAGS) -c -o gpgtar-gpgtar-list.o `test -f 'gpgtar-list.c' || echo '$(srcdir)/'`gpgtar-list.c
178 +
179 +gpgtar-gpgtar-list.obj: gpgtar-list.c
180 +@am__fastdepCC_TRUE@   $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gpgtar_CFLAGS) $(CFLAGS) -MT gpgtar-gpgtar-list.obj -MD -MP -MF $(DEPDIR)/gpgtar-gpgtar-list.Tpo -c -o gpgtar-gpgtar-list.obj `if test -f 'gpgtar-list.c'; then $(CYGPATH_W) 'gpgtar-list.c'; else $(CYGPATH_W) '$(srcdir)/gpgtar-list.c'; fi`
181 +@am__fastdepCC_TRUE@   mv -f $(DEPDIR)/gpgtar-gpgtar-list.Tpo $(DEPDIR)/gpgtar-gpgtar-list.Po
182 +@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='gpgtar-list.c' object='gpgtar-gpgtar-list.obj' libtool=no @AMDEPBACKSLASH@
183 +@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
184 +@am__fastdepCC_FALSE@  $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gpgtar_CFLAGS) $(CFLAGS) -c -o gpgtar-gpgtar-list.obj `if test -f 'gpgtar-list.c'; then $(CYGPATH_W) 'gpgtar-list.c'; else $(CYGPATH_W) '$(srcdir)/gpgtar-list.c'; fi`
185 +
186 +gpgtar-no-libgcrypt.o: no-libgcrypt.c
187 +@am__fastdepCC_TRUE@   $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gpgtar_CFLAGS) $(CFLAGS) -MT gpgtar-no-libgcrypt.o -MD -MP -MF $(DEPDIR)/gpgtar-no-libgcrypt.Tpo -c -o gpgtar-no-libgcrypt.o `test -f 'no-libgcrypt.c' || echo '$(srcdir)/'`no-libgcrypt.c
188 +@am__fastdepCC_TRUE@   mv -f $(DEPDIR)/gpgtar-no-libgcrypt.Tpo $(DEPDIR)/gpgtar-no-libgcrypt.Po
189 +@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='no-libgcrypt.c' object='gpgtar-no-libgcrypt.o' libtool=no @AMDEPBACKSLASH@
190 +@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
191 +@am__fastdepCC_FALSE@  $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gpgtar_CFLAGS) $(CFLAGS) -c -o gpgtar-no-libgcrypt.o `test -f 'no-libgcrypt.c' || echo '$(srcdir)/'`no-libgcrypt.c
192 +
193 +gpgtar-no-libgcrypt.obj: no-libgcrypt.c
194 +@am__fastdepCC_TRUE@   $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gpgtar_CFLAGS) $(CFLAGS) -MT gpgtar-no-libgcrypt.obj -MD -MP -MF $(DEPDIR)/gpgtar-no-libgcrypt.Tpo -c -o gpgtar-no-libgcrypt.obj `if test -f 'no-libgcrypt.c'; then $(CYGPATH_W) 'no-libgcrypt.c'; else $(CYGPATH_W) '$(srcdir)/no-libgcrypt.c'; fi`
195 +@am__fastdepCC_TRUE@   mv -f $(DEPDIR)/gpgtar-no-libgcrypt.Tpo $(DEPDIR)/gpgtar-no-libgcrypt.Po
196 +@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='no-libgcrypt.c' object='gpgtar-no-libgcrypt.obj' libtool=no @AMDEPBACKSLASH@
197 +@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
198 +@am__fastdepCC_FALSE@  $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gpgtar_CFLAGS) $(CFLAGS) -c -o gpgtar-no-libgcrypt.obj `if test -f 'no-libgcrypt.c'; then $(CYGPATH_W) 'no-libgcrypt.c'; else $(CYGPATH_W) '$(srcdir)/no-libgcrypt.c'; fi`
199 +
200  ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
201         list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
202         unique=`for i in $$list; do \
203 diff -urNp orig/gnupg-2.0.16/tools/gpgtar-create.c gnupg-2.0.16/tools/gpgtar-create.c
204 --- orig/gnupg-2.0.16/tools/gpgtar-create.c     1970-01-01 01:00:00.000000000 +0100
205 +++ gnupg-2.0.16/tools/gpgtar-create.c  2010-07-19 11:10:34.000000000 +0200
206 @@ -0,0 +1,831 @@
207 +/* gpgtar-create.c - Create a TAR archive
208 + * Copyright (C) 2010 Free Software Foundation, Inc.
209 + *
210 + * This file is part of GnuPG.
211 + *
212 + * GnuPG is free software; you can redistribute it and/or modify
213 + * it under the terms of the GNU General Public License as published by
214 + * the Free Software Foundation; either version 3 of the License, or
215 + * (at your option) any later version.
216 + *
217 + * GnuPG is distributed in the hope that it will be useful,
218 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
219 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
220 + * GNU General Public License for more details.
221 + *
222 + * You should have received a copy of the GNU General Public License
223 + * along with this program; if not, see <http://www.gnu.org/licenses/>.
224 + */
225 +
226 +#include <config.h>
227 +#include <errno.h>
228 +#include <stdio.h>
229 +#include <stdlib.h>
230 +#include <string.h>
231 +#include <sys/types.h>
232 +#include <sys/stat.h>
233 +#include <dirent.h>
234 +#ifdef HAVE_W32_SYSTEM
235 +# define WIN32_LEAN_AND_MEAN
236 +# include <windows.h>
237 +#else /*!HAVE_W32_SYSTEM*/
238 +# include <unistd.h>
239 +# include <pwd.h>
240 +# include <grp.h>
241 +#endif /*!HAVE_W32_SYSTEM*/
242 +#include <assert.h>
243 +
244 +#include "i18n.h"
245 +#include "../common/sysutils.h"
246 +#include "gpgtar.h"
247 +
248 +#ifndef HAVE_LSTAT
249 +#define lstat(a,b) stat ((a), (b))
250 +#endif
251 +
252 +
253 +/* Object to control the file scanning.  */
254 +struct scanctrl_s;
255 +typedef struct scanctrl_s *scanctrl_t;
256 +struct scanctrl_s
257 +{
258 +  tar_header_t flist;
259 +  tar_header_t *flist_tail;
260 +  int nestlevel;
261 +};
262 +
263 +
264 +
265 +
266 +/* Given a fresh header object HDR with only the name field set, try
267 +   to gather all available info.  This is the W32 version.  */
268 +#ifdef HAVE_W32_SYSTEM
269 +static gpg_error_t
270 +fillup_entry_w32 (tar_header_t hdr)
271 +{
272 +  char *p;
273 +  wchar_t *wfname;
274 +  WIN32_FILE_ATTRIBUTE_DATA fad;
275 +  DWORD attr;
276 +
277 +  for (p=hdr->name; *p; p++)
278 +    if (*p == '/')
279 +      *p = '\\';
280 +  wfname = utf8_to_wchar (hdr->name);
281 +  for (p=hdr->name; *p; p++)
282 +    if (*p == '\\')
283 +      *p = '/';
284 +  if (!wfname)
285 +    {
286 +      log_error ("error utf8-ing `%s': %s\n", hdr->name, w32_strerror (-1));
287 +      return gpg_error_from_syserror ();
288 +    }
289 +  if (!GetFileAttributesExW (wfname, GetFileExInfoStandard, &fad))
290 +    {
291 +      log_error ("error stat-ing `%s': %s\n", hdr->name, w32_strerror (-1));
292 +      xfree (wfname);
293 +      return gpg_error_from_syserror ();
294 +    }
295 +  xfree (wfname);
296 +
297 +  attr = fad.dwFileAttributes;
298 +
299 +  if ((attr & FILE_ATTRIBUTE_NORMAL))
300 +    hdr->typeflag = TF_REGULAR;
301 +  else if ((attr & FILE_ATTRIBUTE_DIRECTORY))
302 +    hdr->typeflag = TF_DIRECTORY;
303 +  else if ((attr & FILE_ATTRIBUTE_DEVICE))
304 +    hdr->typeflag = TF_NOTSUP;
305 +  else if ((attr & (FILE_ATTRIBUTE_OFFLINE | FILE_ATTRIBUTE_TEMPORARY)))
306 +    hdr->typeflag = TF_NOTSUP;
307 +  else
308 +    hdr->typeflag = TF_REGULAR;
309 +
310 +  /* Map some attributes to  USTAR defined mode bits.  */
311 +  hdr->mode = 0640;      /* User may read and write, group only read.  */
312 +  if ((attr & FILE_ATTRIBUTE_DIRECTORY))
313 +    hdr->mode |= 0110;   /* Dirs are user and group executable.  */
314 +  if ((attr & FILE_ATTRIBUTE_READONLY))
315 +    hdr->mode &= ~0200;  /* Clear the user write bit.  */
316 +  if ((attr & FILE_ATTRIBUTE_HIDDEN))
317 +    hdr->mode &= ~0707;  /* Clear all user and other bits.  */ 
318 +  if ((attr & FILE_ATTRIBUTE_SYSTEM))
319 +    hdr->mode |= 0004;   /* Make it readable by other.  */ 
320 +
321 +  /* Only set the size for a regular file.  */
322 +  if (hdr->typeflag == TF_REGULAR)
323 +    hdr->size = (fad.nFileSizeHigh * (unsigned long long)(MAXDWORD+1)
324 +                 + fad.nFileSizeLow);
325 +
326 +  hdr->mtime = (((unsigned long long)fad.ftLastWriteTime.dwHighDateTime << 32)
327 +                | fad.ftLastWriteTime.dwLowDateTime);
328 +  if (!hdr->mtime)
329 +    hdr->mtime = (((unsigned long long)fad.ftCreationTime.dwHighDateTime << 32)
330 +                  | fad.ftCreationTime.dwLowDateTime);
331 +  hdr->mtime -= 116444736000000000ULL; /* The filetime epoch is 1601-01-01.  */
332 +  hdr->mtime /= 10000000;  /* Convert from 0.1us to seconds. */
333 +
334 +  return 0;
335 +}
336 +#endif /*HAVE_W32_SYSTEM*/
337 +
338 +
339 +/* Given a fresh header obje`<ct HDR with only the name field set, try
340 +   to gather all available info.  This is the POSIX version.  */
341 +#ifndef HAVE_W32_SYSTEM
342 +static gpg_error_t
343 +fillup_entry_posix (tar_header_t hdr)
344 +{
345 +  gpg_error_t err;
346 +  struct stat sbuf;
347 +
348 +  if (lstat (hdr->name, &sbuf))
349 +    {
350 +      err = gpg_error_from_syserror ();
351 +      log_error ("error stat-ing `%s': %s\n", hdr->name, gpg_strerror (err));
352 +      return err;
353 +    }
354 +  
355 +  if (S_ISREG (sbuf.st_mode))
356 +    hdr->typeflag = TF_REGULAR;
357 +  else if (S_ISDIR (sbuf.st_mode))
358 +    hdr->typeflag = TF_DIRECTORY;
359 +  else if (S_ISCHR (sbuf.st_mode))
360 +    hdr->typeflag = TF_CHARDEV;
361 +  else if (S_ISBLK (sbuf.st_mode))
362 +    hdr->typeflag = TF_BLOCKDEV;
363 +  else if (S_ISFIFO (sbuf.st_mode))
364 +    hdr->typeflag = TF_FIFO;
365 +  else if (S_ISLNK (sbuf.st_mode))
366 +    hdr->typeflag = TF_SYMLINK;
367 +  else 
368 +    hdr->typeflag = TF_NOTSUP;
369 +
370 +  /* FIXME: Save DEV and INO? */
371 +
372 +  /* Set the USTAR defined mode bits using the system macros.  */
373 +  if (sbuf.st_mode & S_IRUSR)
374 +    hdr->mode |= 0400;
375 +  if (sbuf.st_mode & S_IWUSR)
376 +    hdr->mode |= 0200;
377 +  if (sbuf.st_mode & S_IXUSR)
378 +    hdr->mode |= 0100;
379 +  if (sbuf.st_mode & S_IRGRP)
380 +    hdr->mode |= 0040;
381 +  if (sbuf.st_mode & S_IWGRP)
382 +    hdr->mode |= 0020;
383 +  if (sbuf.st_mode & S_IXGRP)
384 +    hdr->mode |= 0010;
385 +  if (sbuf.st_mode & S_IROTH)
386 +    hdr->mode |= 0004;
387 +  if (sbuf.st_mode & S_IWOTH)
388 +    hdr->mode |= 0002;
389 +  if (sbuf.st_mode & S_IXOTH)
390 +    hdr->mode |= 0001;
391 +#ifdef S_IXUID
392 +  if (sbuf.st_mode & S_IXUID)
393 +    hdr->mode |= 04000;
394 +#endif
395 +#ifdef S_IXGID
396 +  if (sbuf.st_mode & S_IXGID)
397 +    hdr->mode |= 02000;
398 +#endif
399 +#ifdef S_ISVTX
400 +  if (sbuf.st_mode & S_ISVTX)
401 +    hdr->mode |= 01000;
402 +#endif
403 +
404 +  hdr->nlink = sbuf.st_nlink;
405 +
406 +  hdr->uid = sbuf.st_uid;
407 +  hdr->gid = sbuf.st_gid;
408 +
409 +  /* Only set the size for a regular file.  */
410 +  if (hdr->typeflag == TF_REGULAR)
411 +    hdr->size = sbuf.st_size;
412 +
413 +  hdr->mtime = sbuf.st_mtime;
414 +  
415 +  return 0;
416 +}
417 +#endif /*!HAVE_W32_SYSTEM*/
418 +
419 +
420 +/* Add a new entry.  The name of a director entry is ENTRYNAME; if
421 +   that is NULL, DNAME is the name of the directory itself.  Under
422 +   Windows ENTRYNAME shall have backslashes replaced by standard
423 +   slashes.  */
424 +static gpg_error_t
425 +add_entry (const char *dname, const char *entryname, scanctrl_t scanctrl)
426 +{
427 +  gpg_error_t err;
428 +  tar_header_t hdr;
429 +  char *p;
430 +  size_t dnamelen = strlen (dname);
431 +
432 +  assert (dnamelen);
433 +
434 +  hdr = xtrycalloc (1, sizeof *hdr + dnamelen + 1
435 +                    + (entryname? strlen (entryname) : 0) + 1);
436 +  if (!hdr)
437 +    return gpg_error_from_syserror ();
438 +
439 +  p = stpcpy (hdr->name, dname);
440 +  if (entryname)
441 +    {
442 +      if (dname[dnamelen-1] != '/')
443 +        *p++ = '/';
444 +      strcpy (p, entryname);
445 +    }
446 +  else
447 +    {
448 +      if (hdr->name[dnamelen-1] == '/')
449 +        hdr->name[dnamelen-1] = 0;
450 +    }
451 +#ifdef HAVE_DOSISH_SYSTEM
452 +  err = fillup_entry_w32 (hdr);
453 +#else
454 +  err = fillup_entry_posix (hdr);
455 +#endif
456 +  if (err)
457 +    xfree (hdr);
458 +  else
459 +    {
460 +      if (opt.verbose)
461 +        gpgtar_print_header (hdr, log_get_stream ());
462 +      *scanctrl->flist_tail = hdr;
463 +      scanctrl->flist_tail = &hdr->next;
464 +    }
465 +
466 +  return 0;
467 +}
468 +
469 +
470 +static gpg_error_t
471 +scan_directory (const char *dname, scanctrl_t scanctrl)
472 +{
473 +  gpg_error_t err = 0;
474 +
475 +#ifdef HAVE_W32_SYSTEM
476 +  WIN32_FIND_DATAW fi;
477 +  HANDLE hd = INVALID_HANDLE_VALUE;
478 +  char *p;
479 +
480 +  if (!*dname)
481 +    return 0;  /* An empty directory name has no entries.  */
482 +
483 +  {
484 +    char *fname;
485 +    wchar_t *wfname;
486 +
487 +    fname = xtrymalloc (strlen (dname) + 2 + 2 + 1);
488 +    if (!fname)
489 +      {
490 +        err = gpg_error_from_syserror ();
491 +        goto leave;
492 +      }
493 +    if (!strcmp (dname, "/"))
494 +      strcpy (fname, "/*"); /* Trailing slash is not allowed.  */
495 +    else if (!strcmp (dname, "."))
496 +      strcpy (fname, "*");
497 +    else if (*dname && dname[strlen (dname)-1] == '/')
498 +      strcpy (stpcpy (fname, dname), "*");
499 +    else if (*dname && dname[strlen (dname)-1] != '*')
500 +      strcpy (stpcpy (fname, dname), "/*");
501 +    else
502 +      strcpy (fname, dname);
503 +
504 +    for (p=fname; *p; p++)
505 +      if (*p == '/')
506 +        *p = '\\';
507 +    wfname = utf8_to_wchar (fname);
508 +    xfree (fname);
509 +    if (!wfname)
510 +      {
511 +        err = gpg_error_from_syserror ();
512 +        log_error (_("error reading directory `%s': %s\n"),
513 +                   dname, gpg_strerror (err));
514 +        goto leave;
515 +      }
516 +    hd = FindFirstFileW (wfname, &fi);
517 +    if (hd == INVALID_HANDLE_VALUE)
518 +      {
519 +        err = gpg_error_from_syserror ();
520 +        log_error (_("error reading directory `%s': %s\n"),
521 +                   dname, w32_strerror (-1));
522 +        xfree (wfname);
523 +        goto leave;
524 +      }
525 +    xfree (wfname);
526 +  }
527 +
528 +  do 
529 +    {
530 +      char *fname = wchar_to_utf8 (fi.cFileName);
531 +      if (!fname)
532 +        {
533 +          err = gpg_error_from_syserror ();
534 +          log_error ("error utf8-ing filename: %s\n", w32_strerror (-1));
535 +          break;
536 +        }
537 +      for (p=fname; *p; p++)
538 +        if (*p == '\\')
539 +          *p = '/';
540 +      if (!strcmp (fname, "." ) || !strcmp (fname, ".."))
541 +        err = 0; /* Skip self and parent dir entry.  */
542 +      else if (!strncmp (dname, "./", 2) && dname[2])
543 +        err = add_entry (dname+2, fname, scanctrl);
544 +      else
545 +        err = add_entry (dname, fname, scanctrl);
546 +      xfree (fname);
547 +    }
548 +  while (!err && FindNextFileW (hd, &fi));
549 +  if (err)
550 +    ;
551 +  else if (GetLastError () == ERROR_NO_MORE_FILES)
552 +    err = 0;
553 +  else
554 +    {
555 +      err = gpg_error_from_syserror (); 
556 +      log_error (_("error reading directory `%s': %s\n"),
557 +                 dname, w32_strerror (-1));
558 +    }
559 +  
560 + leave:
561 +  if (hd != INVALID_HANDLE_VALUE)
562 +    FindClose (hd);
563 +
564 +#else /*!HAVE_W32_SYSTEM*/
565 +  DIR *dir;
566 +  struct dirent *de;
567 +
568 +  if (!*dname)
569 +    return 0;  /* An empty directory name has no entries.  */
570 +
571 +  dir = opendir (dname);
572 +  if (!dir)
573 +    {
574 +      err = gpg_error_from_syserror ();
575 +      log_error (_("error reading directory `%s': %s\n"),
576 +                 dname, gpg_strerror (err));
577 +      return err;
578 +    }
579 +  
580 +  while ((de = readdir (dir)))
581 +    {
582 +      if (!strcmp (de->d_name, "." ) || !strcmp (de->d_name, ".."))
583 +        continue; /* Skip self and parent dir entry.  */
584 +      
585 +      err = add_entry (dname, de->d_name, scanctrl);
586 +      if (err)
587 +        goto leave;
588 +     }
589 +
590 + leave:
591 +  closedir (dir);
592 +#endif /*!HAVE_W32_SYSTEM*/
593 +  return err;
594 +}
595 +
596 +
597 +static gpg_error_t
598 +scan_recursive (const char *dname, scanctrl_t scanctrl)
599 +{
600 +  gpg_error_t err = 0;
601 +  tar_header_t hdr, *start_tail, *stop_tail;
602 +
603 +  if (scanctrl->nestlevel > 200)
604 +    {
605 +      log_error ("directories too deeply nested\n");
606 +      return gpg_error (GPG_ERR_RESOURCE_LIMIT);
607 +    }
608 +  scanctrl->nestlevel++;
609 +
610 +  assert (scanctrl->flist_tail);
611 +  start_tail = scanctrl->flist_tail;
612 +  scan_directory (dname, scanctrl);
613 +  stop_tail = scanctrl->flist_tail;
614 +  hdr = *start_tail;
615 +  for (; hdr && hdr != *stop_tail; hdr = hdr->next)
616 +    if (hdr->typeflag == TF_DIRECTORY)
617 +      {
618 +        if (opt.verbose > 1)
619 +          log_info ("scanning directory `%s'\n", hdr->name);
620 +        scan_recursive (hdr->name, scanctrl);
621 +      }
622 +  
623 +  scanctrl->nestlevel--;
624 +  return err;
625 +}
626 +
627 +
628 +/* Returns true if PATTERN is acceptable.  */
629 +static int
630 +pattern_valid_p (const char *pattern)
631 +{
632 +  if (!*pattern)
633 +    return 0;
634 +  if (*pattern == '.' && pattern[1] == '.')
635 +    return 0;
636 +  if (*pattern == '/' || *pattern == DIRSEP_C)
637 +    return 0; /* Absolute filenames are not supported.  */
638 +#ifdef HAVE_DRIVE_LETTERS
639 +  if (((*pattern >= 'a' && *pattern <= 'z')
640 +       || (*pattern >= 'A' && *pattern <= 'Z'))
641 +      && pattern[1] == ':')
642 +    return 0; /* Drive letter are not allowed either.  */
643 +#endif /*HAVE_DRIVE_LETTERS*/ 
644 +
645 +  return 1; /* Okay.  */
646 +}
647 +
648 +
649 +\f
650 +static void
651 +store_xoctal (char *buffer, size_t length, unsigned long long value)
652 +{
653 +  char *p, *pend;
654 +  size_t n;
655 +  unsigned long long v;
656 +
657 +  assert (length > 1);
658 +
659 +  v = value;
660 +  n = length;
661 +  p = pend = buffer + length;
662 +  *--p = 0; /* Nul byte.  */
663 +  n--;
664 +  do
665 +    {
666 +      *--p = '0' + (v % 8);
667 +      v /= 8;
668 +      n--;
669 +    }
670 +  while (v && n);
671 +  if (!v)
672 +    {
673 +      /* Pad.  */
674 +      for ( ; n; n--)
675 +        *--p = '0';
676 +    }
677 +  else /* Does not fit into the field.  Store as binary number.  */
678 +    {
679 +      v = value;
680 +      n = length;
681 +      p = pend = buffer + length;
682 +      do
683 +        {
684 +          *--p = v;
685 +          v /= 256;
686 +          n--;
687 +        }
688 +      while (v && n);
689 +      if (!v)
690 +        {
691 +          /* Pad.  */
692 +          for ( ; n; n--)
693 +            *--p = 0;
694 +          if (*p & 0x80)
695 +            BUG ();
696 +          *p |= 0x80; /* Set binary flag.  */
697 +        }
698 +      else
699 +        BUG ();
700 +    }
701 +}
702 +
703 +
704 +static void
705 +store_uname (char *buffer, size_t length, unsigned long uid)
706 +{
707 +  static int initialized;
708 +  static unsigned long lastuid;
709 +  static char lastuname[32];
710 +
711 +  if (!initialized || uid != lastuid)
712 +    {
713 +#ifdef HAVE_W32_SYSTEM
714 +      mem2str (lastuname, uid? "user":"root", sizeof lastuname); 
715 +#else
716 +      struct passwd *pw = getpwuid (uid);
717 +
718 +      lastuid = uid;
719 +      initialized = 1;
720 +      if (pw)
721 +        mem2str (lastuname, pw->pw_name, sizeof lastuname); 
722 +      else
723 +        {
724 +          log_info ("failed to get name for uid %lu\n", uid);
725 +          *lastuname = 0;
726 +        }
727 +#endif
728 +    }
729 +  mem2str (buffer, lastuname, length);
730 +}
731 +
732 +
733 +static void
734 +store_gname (char *buffer, size_t length, unsigned long gid)
735 +{
736 +  static int initialized;
737 +  static unsigned long lastgid;
738 +  static char lastgname[32];
739 +
740 +  if (!initialized || gid != lastgid)
741 +    {
742 +#ifdef HAVE_W32_SYSTEM
743 +      mem2str (lastgname, gid? "users":"root", sizeof lastgname); 
744 +#else
745 +      struct group *gr = getgrgid (gid);
746 +
747 +      lastgid = gid;
748 +      initialized = 1;
749 +      if (gr)
750 +        mem2str (lastgname, gr->gr_name, sizeof lastgname); 
751 +      else
752 +        {
753 +          log_info ("failed to get name for gid %lu\n", gid);
754 +          *lastgname = 0;
755 +        }
756 +#endif
757 +    }
758 +  mem2str (buffer, lastgname, length);
759 +}
760 +
761 +
762 +static gpg_error_t
763 +build_header (void *record, tar_header_t hdr)
764 +{
765 +  gpg_error_t err;
766 +  struct ustar_raw_header *raw = record;
767 +  size_t namelen, n;
768 +  unsigned long chksum;
769 +  unsigned char *p;
770 +
771 +  memset (record, 0, RECORDSIZE);
772 +
773 +  /* Store name and prefix.  */
774 +  namelen = strlen (hdr->name);
775 +  if (namelen < sizeof raw->name)
776 +    memcpy (raw->name, hdr->name, namelen);
777 +  else 
778 +    {
779 +      n = (namelen < sizeof raw->prefix)? namelen : sizeof raw->prefix;
780 +      for (n--; n ; n--)
781 +        if (hdr->name[n] == '/')
782 +          break;
783 +      if (namelen - n < sizeof raw->name)
784 +        {
785 +          /* Note that the N is < sizeof prefix and that the
786 +             delimiting slash is not stored.  */
787 +          memcpy (raw->prefix, hdr->name, n);
788 +          memcpy (raw->name, hdr->name+n+1, namelen - n);
789 +        }
790 +      else
791 +        {
792 +          err = gpg_error (GPG_ERR_TOO_LARGE);
793 +          log_error ("error storing file `%s': %s\n", 
794 +                     hdr->name, gpg_strerror (err));
795 +          return err;
796 +        }
797 +    }
798 +  
799 +  store_xoctal (raw->mode,  sizeof raw->mode,  hdr->mode);
800 +  store_xoctal (raw->uid,   sizeof raw->uid,   hdr->uid);
801 +  store_xoctal (raw->gid,   sizeof raw->gid,   hdr->gid);
802 +  store_xoctal (raw->size,  sizeof raw->size,  hdr->size);
803 +  store_xoctal (raw->mtime, sizeof raw->mtime, hdr->mtime);
804 +
805 +  switch (hdr->typeflag)
806 +    {
807 +    case TF_REGULAR:   raw->typeflag[0] = '0'; break;
808 +    case TF_HARDLINK:  raw->typeflag[0] = '1'; break;
809 +    case TF_SYMLINK:   raw->typeflag[0] = '2'; break;
810 +    case TF_CHARDEV:   raw->typeflag[0] = '3'; break;
811 +    case TF_BLOCKDEV:  raw->typeflag[0] = '4'; break;
812 +    case TF_DIRECTORY: raw->typeflag[0] = '5'; break;
813 +    case TF_FIFO:      raw->typeflag[0] = '6'; break;
814 +    default: return gpg_error (GPG_ERR_NOT_SUPPORTED);
815 +    }
816 +
817 +  memcpy (raw->magic, "ustar", 6);
818 +  raw->version[0] = '0';
819 +  raw->version[1] = '0';
820 +
821 +  store_uname (raw->uname, sizeof raw->uname, hdr->uid);
822 +  store_gname (raw->gname, sizeof raw->gname, hdr->gid);
823 +
824 +#ifndef HAVE_W32_SYSTEM
825 +  if (hdr->typeflag == TF_SYMLINK)
826 +    {
827 +      int nread;
828 +
829 +      nread = readlink (hdr->name, raw->linkname, sizeof raw->linkname -1);
830 +      if (nread < 0)
831 +        {
832 +          err = gpg_error_from_syserror ();
833 +          log_error ("error reading symlink `%s': %s\n", 
834 +                     hdr->name, gpg_strerror (err));
835 +          return err;
836 +        }
837 +      raw->linkname[nread] = 0;
838 +    }
839 +#endif /*HAVE_W32_SYSTEM*/
840 +
841 +  /* Compute the checksum.  */
842 +  memset (raw->checksum, ' ', sizeof raw->checksum);
843 +  chksum = 0;
844 +  p = record;
845 +  for (n=0; n < RECORDSIZE; n++)
846 +    chksum += *p++;
847 +  store_xoctal (raw->checksum, sizeof raw->checksum - 1, chksum);
848 +  raw->checksum[7] = ' ';
849 +
850 +  return 0;
851 +}
852 +
853 +
854 +static gpg_error_t
855 +write_file (estream_t stream, tar_header_t hdr)
856 +{
857 +  gpg_error_t err;
858 +  char record[RECORDSIZE];
859 +  estream_t infp;
860 +  size_t nread, nbytes;
861 +  int any;
862 +
863 +  err = build_header (record, hdr);
864 +  if (err)
865 +    {
866 +      if (gpg_err_code (err) == GPG_ERR_NOT_SUPPORTED)
867 +        {
868 +          log_info ("skipping unsupported file `%s'\n", hdr->name);
869 +          err = 0;
870 +        }
871 +      return err;
872 +    }
873 +
874 +  if (hdr->typeflag == TF_REGULAR)
875 +    {
876 +      infp = es_fopen (hdr->name, "rb");
877 +      if (!infp)
878 +        {
879 +          err = gpg_error_from_syserror ();
880 +          log_error ("can't open `%s': %s - skipped\n",
881 +                     hdr->name, gpg_strerror (err));
882 +          return err;
883 +        }
884 +    }
885 +  else
886 +    infp = NULL;
887 +
888 +  err = write_record (stream, record);
889 +  if (err)
890 +    goto leave;
891 +
892 +  if (hdr->typeflag == TF_REGULAR)
893 +    {
894 +      hdr->nrecords = (hdr->size + RECORDSIZE-1)/RECORDSIZE;
895 +      any = 0;
896 +      while (hdr->nrecords--)
897 +        {
898 +          nbytes = hdr->nrecords? RECORDSIZE : (hdr->size % RECORDSIZE);
899 +          if (!nbytes)
900 +            nbytes = RECORDSIZE;
901 +          nread = es_fread (record, 1, nbytes, infp);
902 +          if (nread != nbytes)
903 +            {
904 +              err = gpg_error_from_syserror ();
905 +              log_error ("error reading file `%s': %s%s\n",
906 +                         hdr->name, gpg_strerror (err),
907 +                         any? " (file shrunk?)":"");
908 +              goto leave;
909 +            }
910 +          any = 1;
911 +          err = write_record (stream, record);
912 +          if (err)
913 +            goto leave;
914 +        }
915 +      nread = es_fread (record, 1, 1, infp);
916 +      if (nread)
917 +        log_info ("note: file `%s' has grown\n", hdr->name);
918 +    }
919 +
920 + leave:
921 +  if (err)
922 +    es_fclose (infp);
923 +  else if ((err = es_fclose (infp)))
924 +    log_error ("error closing file `%s': %s\n", hdr->name, gpg_strerror (err));
925 +      
926 +  return err;
927 +}
928 +
929 +
930 +static gpg_error_t
931 +write_eof_mark (estream_t stream)
932 +{
933 +  gpg_error_t err;
934 +  char record[RECORDSIZE];
935 +
936 +  memset (record, 0, sizeof record);
937 +  err = write_record (stream, record);
938 +  if (!err)
939 +    err = write_record (stream, record);
940 +  return err;
941 +}
942 +
943 +
944 +\f
945 +void
946 +gpgtar_create (char **inpattern)
947 +{
948 +  gpg_error_t err = 0;
949 +  const char *pattern;
950 +  struct scanctrl_s scanctrl_buffer;
951 +  scanctrl_t scanctrl = &scanctrl_buffer;
952 +  tar_header_t hdr, *start_tail;
953 +  estream_t outstream = NULL;
954 +
955 +  memset (scanctrl, 0, sizeof *scanctrl);
956 +  scanctrl->flist_tail = &scanctrl->flist;
957 +
958 +  for (; (pattern = *inpattern); inpattern++)
959 +    {
960 +      char *pat, *p;
961 +
962 +      if (!*pattern)
963 +        continue;
964 +
965 +      pat = xtrystrdup (pattern);
966 +      if (!pat)
967 +        {
968 +          err = gpg_error_from_syserror ();
969 +          log_error ("memory allocation problem: %s\n", gpg_strerror (err));
970 +          goto leave;
971 +        }
972 +      for (p=pat; *p; p++)
973 +        if (*p == '\\')
974 +          *p = '/';
975 +
976 +      if (opt.verbose > 1)
977 +        log_info ("scanning `%s'\n", pat);
978 +
979 +      start_tail = scanctrl->flist_tail;
980 +      if (!pattern_valid_p (pat))
981 +        log_error ("skipping invalid name `%s'\n", pat);
982 +      else if (!add_entry (pat, NULL, scanctrl)
983 +               && *start_tail && ((*start_tail)->typeflag & TF_DIRECTORY))
984 +        scan_recursive (pat, scanctrl);
985 +
986 +      xfree (pat);
987 +    }
988 +
989 +  if (opt.outfile)
990 +    {
991 +      outstream = es_fopen (opt.outfile, "wb");
992 +      if (!outstream)
993 +        {
994 +          err = gpg_error_from_syserror ();
995 +          log_error (_("can't create `%s': %s\n"),
996 +                     opt.outfile, gpg_strerror (err));
997 +          goto leave;
998 +        }
999 +    }
1000 +  else
1001 +    {
1002 +      outstream = es_stdout;
1003 +    }
1004 +
1005 +  for (hdr = scanctrl->flist; hdr; hdr = hdr->next)
1006 +    {
1007 +      err = write_file (outstream, hdr);
1008 +      if (err)
1009 +        goto leave;
1010 +    }
1011 +  err = write_eof_mark (outstream);
1012 +
1013 + leave:
1014 +  if (!err)
1015 +    {
1016 +      if (outstream != es_stdout)
1017 +        err = es_fclose (outstream);
1018 +      else
1019 +        err = es_fflush (outstream);
1020 +      outstream = NULL;
1021 +    }
1022 +  if (err)
1023 +    {
1024 +      log_error ("creating tarball `%s' failed: %s\n",
1025 +                 es_fname_get (outstream), gpg_strerror (err));
1026 +      if (outstream && outstream != es_stdout)
1027 +        es_fclose (outstream);
1028 +      if (opt.outfile)
1029 +        remove (opt.outfile);
1030 +    }
1031 +  scanctrl->flist_tail = NULL;
1032 +  while ( (hdr = scanctrl->flist) )
1033 +    {
1034 +      scanctrl->flist = hdr->next;
1035 +      xfree (hdr);
1036 +    }
1037 +}
1038 diff -urNp orig/gnupg-2.0.16/tools/gpgtar-extract.c gnupg-2.0.16/tools/gpgtar-extract.c
1039 --- orig/gnupg-2.0.16/tools/gpgtar-extract.c    1970-01-01 01:00:00.000000000 +0100
1040 +++ gnupg-2.0.16/tools/gpgtar-extract.c 2010-07-19 11:10:27.000000000 +0200
1041 @@ -0,0 +1,334 @@
1042 +/* gpgtar-extract.c - Extract from a TAR archive
1043 + * Copyright (C) 2010 Free Software Foundation, Inc.
1044 + *
1045 + * This file is part of GnuPG.
1046 + *
1047 + * GnuPG is free software; you can redistribute it and/or modify
1048 + * it under the terms of the GNU General Public License as published by
1049 + * the Free Software Foundation; either version 3 of the License, or
1050 + * (at your option) any later version.
1051 + *
1052 + * GnuPG is distributed in the hope that it will be useful,
1053 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1054 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1055 + * GNU General Public License for more details.
1056 + *
1057 + * You should have received a copy of the GNU General Public License
1058 + * along with this program; if not, see <http://www.gnu.org/licenses/>.
1059 + */
1060 +
1061 +#include <config.h>
1062 +#include <errno.h>
1063 +#include <stdio.h>
1064 +#include <stdlib.h>
1065 +#include <string.h>
1066 +#include <sys/types.h>
1067 +#include <sys/stat.h>
1068 +#include <unistd.h>
1069 +#include <assert.h>
1070 +
1071 +#include "i18n.h"
1072 +#include "../common/sysutils.h"
1073 +#include "gpgtar.h"
1074 +
1075 +#ifndef GPG_ERR_LIMIT_REACHED
1076 +#define GPG_ERR_LIMIT_REACHED 183
1077 +#endif
1078 +
1079 +
1080 +static gpg_error_t
1081 +extract_regular (estream_t stream, const char *dirname,
1082 +                 tar_header_t hdr)
1083 +{
1084 +  gpg_error_t err;
1085 +  char record[RECORDSIZE];
1086 +  size_t n, nbytes, nwritten;
1087 +  char *fname;
1088 +  estream_t outfp = NULL;
1089 +
1090 +  fname = strconcat (dirname, "/", hdr->name, NULL);
1091 +  if (!fname)
1092 +    {
1093 +      err = gpg_error_from_syserror ();
1094 +      log_error ("error creating filename: %s\n", gpg_strerror (err));
1095 +      goto leave;
1096 +    }
1097 +  else
1098 +    err = 0;
1099 +  
1100 +  outfp = es_fopen (fname, "wb");
1101 +  if (!outfp)
1102 +    {
1103 +      err = gpg_error_from_syserror ();
1104 +      log_error ("error creating `%s': %s\n", fname, gpg_strerror (err));
1105 +      goto leave;
1106 +    }
1107 +
1108 +  for (n=0; n < hdr->nrecords;)
1109 +    {
1110 +      err = read_record (stream, record);
1111 +      if (err)
1112 +        goto leave;
1113 +      n++;
1114 +      nbytes = (n < hdr->nrecords)? RECORDSIZE : (hdr->size % RECORDSIZE);
1115 +      nwritten = es_fwrite (record, 1, nbytes, outfp);
1116 +      if (nwritten != nbytes)
1117 +        {
1118 +          err = gpg_error_from_syserror ();
1119 +          log_error ("error writing `%s': %s\n", fname, gpg_strerror (err));
1120 +          goto leave;
1121 +        }
1122 +    }
1123 +  /* Fixme: Set permissions etc.  */
1124 +
1125 + leave:
1126 +  if (!err && opt.verbose)
1127 +    log_info ("extracted `%s/'\n", fname);
1128 +  es_fclose (outfp);
1129 +  if (err && fname && outfp)
1130 +    {
1131 +      if (remove (fname))
1132 +        log_error ("error removing incomplete file `%s': %s\n",
1133 +                   fname, gpg_strerror (gpg_error_from_syserror ()));
1134 +    }
1135 +  xfree (fname);
1136 +  return err;
1137 +}
1138 +
1139 +
1140 +static gpg_error_t
1141 +extract_directory (const char *dirname, tar_header_t hdr)
1142 +{
1143 +  gpg_error_t err;
1144 +  char *fname;
1145 +  size_t prefixlen;
1146 +  
1147 +  prefixlen = strlen (dirname) + 1;
1148 +  fname = strconcat (dirname, "/", hdr->name, NULL);
1149 +  if (!fname)
1150 +    {
1151 +      err = gpg_error_from_syserror ();
1152 +      log_error ("error creating filename: %s\n", gpg_strerror (err));
1153 +      goto leave;
1154 +    }
1155 +  else
1156 +    err = 0;
1157 +
1158 +  if (fname[strlen (fname)-1] == '/')
1159 +    fname[strlen (fname)-1] = 0;
1160 +
1161 + /* Note that we don't need to care about EEXIST because we always
1162 +     extract into a new hierarchy.  */
1163 +  if (gnupg_mkdir (fname, "-rwx------"))
1164 +    {
1165 +      err = gpg_error_from_syserror ();
1166 +      if (gpg_err_code (err) == GPG_ERR_ENOENT)
1167 +        {
1168 +          /* Try to create the directory with parents but keep the
1169 +             original error code in case of a failure.  */
1170 +          char *p;
1171 +          int rc = 0;
1172 +          
1173 +          for (p = fname+prefixlen; (p = strchr (p, '/')); p++)
1174 +            {
1175 +              *p = 0;
1176 +              rc = gnupg_mkdir (fname, "-rwx------");
1177 +              *p = '/';
1178 +              if (rc)
1179 +                break;
1180 +            }
1181 +          if (!rc && !gnupg_mkdir (fname, "-rwx------"))
1182 +            err = 0;
1183 +        }
1184 +      if (err)
1185 +        log_error ("error creating directory `%s': %s\n",
1186 +                   fname, gpg_strerror (err));
1187 +    }
1188 +
1189 + leave:
1190 +  if (!err && opt.verbose)
1191 +    log_info ("created   `%s/'\n", fname);
1192 +  xfree (fname);
1193 +  return err;
1194 +}
1195 +
1196 +
1197 +static gpg_error_t
1198 +extract (estream_t stream, const char *dirname, tar_header_t hdr)
1199 +{
1200 +  gpg_error_t err;
1201 +  size_t n;
1202 +
1203 +  n = strlen (hdr->name);
1204 +#ifdef HAVE_DOSISH_SYSTEM
1205 +  if (strchr (hdr->name, '\\'))
1206 +    {
1207 +      log_error ("filename `%s' contains a backslash - "
1208 +                 "can't extract on this system\n", hdr->name);
1209 +      return gpg_error (GPG_ERR_INV_NAME);
1210 +    }
1211 +#endif /*HAVE_DOSISH_SYSTEM*/
1212 +
1213 +  if (!n
1214 +      || strstr (hdr->name, "//") 
1215 +      || strstr (hdr->name, "/../") 
1216 +      || !strncmp (hdr->name, "../", 3)
1217 +      || (n >= 3 && !strcmp (hdr->name+n-3, "/.." )))
1218 +    {
1219 +      log_error ("filename `%s' as suspicious parts - not extracting\n",
1220 +                 hdr->name);
1221 +      return gpg_error (GPG_ERR_INV_NAME);
1222 +    }
1223 +
1224 +  if (hdr->typeflag == TF_REGULAR || hdr->typeflag == TF_UNKNOWN)
1225 +    err = extract_regular (stream, dirname, hdr);
1226 +  else if (hdr->typeflag == TF_DIRECTORY)
1227 +    err = extract_directory (dirname, hdr);
1228 +  else
1229 +    {
1230 +      char record[RECORDSIZE];
1231 +
1232 +      log_info ("unsupported file type %d for `%s' - skipped\n",
1233 +                (int)hdr->typeflag, hdr->name);
1234 +      for (err = 0, n=0; !err && n < hdr->nrecords; n++)
1235 +        err = read_record (stream, record);
1236 +    }
1237 +  return err;
1238 +}
1239 +
1240 +
1241 +/* Create a new directory to be used for extracting the tarball.
1242 +   Returns the name of the directory which must be freed by the
1243 +   caller.  In case of an error a diagnostic is printed and NULL
1244 +   returned.  */
1245 +static char *
1246 +create_directory (const char *dirprefix)
1247 +{
1248 +  gpg_error_t err = 0;
1249 +  char *prefix_buffer = NULL;
1250 +  char *dirname = NULL;
1251 +  size_t n;
1252 +  int idx;
1253 +
1254 +  /* Remove common suffixes.  */
1255 +  n = strlen (dirprefix);
1256 +  if (n > 4 && (!compare_filenames    (dirprefix + n - 4, EXTSEP_S "gpg")
1257 +                || !compare_filenames (dirprefix + n - 4, EXTSEP_S "pgp")
1258 +                || !compare_filenames (dirprefix + n - 4, EXTSEP_S "asc")
1259 +                || !compare_filenames (dirprefix + n - 4, EXTSEP_S "pem")
1260 +                || !compare_filenames (dirprefix + n - 4, EXTSEP_S "p7e")))
1261 +    {
1262 +      prefix_buffer = xtrystrdup (dirprefix);
1263 +      if (!prefix_buffer)
1264 +        {
1265 +          err = gpg_error_from_syserror ();
1266 +          goto leave;
1267 +        }
1268 +      prefix_buffer[n-4] = 0;
1269 +      dirprefix = prefix_buffer;
1270 +    }
1271 +
1272 +
1273 +
1274 +  for (idx=1; idx < 5000; idx++)
1275 +    {
1276 +      xfree (dirname);
1277 +      dirname = xtryasprintf ("%s_%d_", dirprefix, idx);
1278 +      if (!dirname)
1279 +        {
1280 +          err = gpg_error_from_syserror ();
1281 +          goto leave;
1282 +        }
1283 +      if (!gnupg_mkdir (dirname, "-rwx------"))
1284 +        goto leave; /* Ready.  */
1285 +      if (errno != EEXIST && errno != ENOTDIR)
1286 +        {
1287 +          err = gpg_error_from_syserror ();
1288 +          goto leave;
1289 +        }
1290 +    }
1291 +  err = gpg_error (GPG_ERR_LIMIT_REACHED);
1292 +
1293 + leave:
1294 +  if (err)
1295 +    {
1296 +      log_error ("error creating an extract directory: %s\n",
1297 +                 gpg_strerror (err));
1298 +      xfree (dirname);
1299 +      dirname = NULL;
1300 +    }
1301 +  xfree (prefix_buffer);
1302 +  return dirname;
1303 +}
1304 +
1305 +
1306 +\f
1307 +void
1308 +gpgtar_extract (const char *filename)
1309 +{
1310 +  gpg_error_t err;
1311 +  estream_t stream;
1312 +  tar_header_t header = NULL;
1313 +  const char *dirprefix = NULL;
1314 +  char *dirname = NULL;
1315 +
1316 +  if (filename)
1317 +    {
1318 +      stream = es_fopen (filename, "rb");
1319 +      if (!stream)
1320 +        {
1321 +          err = gpg_error_from_syserror ();
1322 +          log_error ("error opening `%s': %s\n", filename, gpg_strerror (err));
1323 +          return;
1324 +        }
1325 +    }
1326 +  else
1327 +    stream = es_stdin;  /* FIXME:  How can we enforce binary mode?  */
1328 +
1329 +
1330 +  if (filename)
1331 +    {
1332 +      dirprefix = strrchr (filename, '/');
1333 +      if (dirprefix)
1334 +        dirprefix++;
1335 +    }
1336 +  else if (opt.filename)
1337 +    {
1338 +      dirprefix = strrchr (opt.filename, '/');
1339 +      if (dirprefix)
1340 +        dirprefix++;
1341 +    }
1342 +
1343 +  if (!dirprefix || !*dirprefix)
1344 +    dirprefix = "GPGARCH";
1345 +
1346 +  dirname = create_directory (dirprefix);
1347 +  if (!dirname)
1348 +    {
1349 +      err = gpg_error (GPG_ERR_GENERAL);
1350 +      goto leave;
1351 +    }
1352 +
1353 +  if (opt.verbose)
1354 +    log_info ("extracting to `%s/'\n", dirname);
1355 +
1356 +  for (;;)
1357 +    {
1358 +      header = gpgtar_read_header (stream);
1359 +      if (!header)
1360 +        goto leave;
1361 +     
1362 +      if (extract (stream, dirname, header))
1363 +        goto leave;
1364 +      xfree (header);
1365 +      header = NULL;
1366 +    }
1367 +
1368 +
1369 + leave:
1370 +  xfree (header);
1371 +  xfree (dirname);
1372 +  if (stream != es_stdin)
1373 +    es_fclose (stream);
1374 +  return;
1375 +}
1376 diff -urNp orig/gnupg-2.0.16/tools/gpgtar-list.c gnupg-2.0.16/tools/gpgtar-list.c
1377 --- orig/gnupg-2.0.16/tools/gpgtar-list.c       1970-01-01 01:00:00.000000000 +0100
1378 +++ gnupg-2.0.16/tools/gpgtar-list.c    2010-07-19 10:52:02.000000000 +0200
1379 @@ -0,0 +1,323 @@
1380 +/* gpgtar-list.c - List a TAR archive
1381 + * Copyright (C) 2010 Free Software Foundation, Inc.
1382 + *
1383 + * This file is part of GnuPG.
1384 + *
1385 + * GnuPG is free software; you can redistribute it and/or modify
1386 + * it under the terms of the GNU General Public License as published by
1387 + * the Free Software Foundation; either version 3 of the License, or
1388 + * (at your option) any later version.
1389 + *
1390 + * GnuPG is distributed in the hope that it will be useful,
1391 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1392 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1393 + * GNU General Public License for more details.
1394 + *
1395 + * You should have received a copy of the GNU General Public License
1396 + * along with this program; if not, see <http://www.gnu.org/licenses/>.
1397 + */
1398 +
1399 +#include <config.h>
1400 +#include <errno.h>
1401 +#include <stdio.h>
1402 +#include <stdlib.h>
1403 +#include <string.h>
1404 +#include <assert.h>
1405 +
1406 +#include "i18n.h"
1407 +#include "gpgtar.h"
1408 +
1409 +
1410 +\f
1411 +static unsigned long long
1412 +parse_xoctal (const void *data, size_t length, const char *filename)
1413 +{
1414 +  const unsigned char *p = data;
1415 +  unsigned long long value;
1416 +
1417 +  if (!length)
1418 +    value = 0;
1419 +  else if ( (*p & 0x80))
1420 +    {
1421 +      /* Binary format.  */
1422 +      value = (*p++ & 0x7f);
1423 +      while (--length)
1424 +        {
1425 +          value <<= 8;
1426 +          value |= *p++;
1427 +        }
1428 +    }
1429 +  else
1430 +    {
1431 +      /* Octal format  */
1432 +      value = 0;
1433 +      /* Skip leading spaces and zeroes.  */
1434 +      for (; length && (*p == ' ' || *p == '0'); length--, p++)
1435 +        ;
1436 +      for (; length && *p; length--, p++)
1437 +        {
1438 +          if (*p >= '0' && *p <= '7')
1439 +            {
1440 +              value <<= 3;
1441 +              value += (*p - '0');
1442 +            }
1443 +          else
1444 +            {
1445 +              log_error ("%s: invalid octal number encountered - assuming 0\n", 
1446 +                         filename);
1447 +              value = 0;
1448 +              break;
1449 +            }
1450 +        }
1451 +    }
1452 +  return value;
1453 +}
1454 +
1455 +
1456 +static tar_header_t
1457 +parse_header (const void *record, const char *filename)
1458 +{
1459 +  const struct ustar_raw_header *raw = record;
1460 +  size_t n, namelen, prefixlen;
1461 +  tar_header_t header;
1462 +  int use_prefix;
1463 +
1464 +  use_prefix = (!memcmp (raw->magic, "ustar", 5) 
1465 +                && (raw->magic[5] == ' ' || !raw->magic[5]));
1466 +
1467 +
1468 +  for (namelen=0; namelen < sizeof raw->name && raw->name[namelen]; namelen++)
1469 +    ;
1470 +  if (namelen == sizeof raw->name)
1471 +    log_info ("%s: warning: name not terminated by a nul byte\n", filename);
1472 +  for (n=namelen+1; n < sizeof raw->name; n++)
1473 +    if (raw->name[n])
1474 +      {
1475 +        log_info ("%s: warning: garbage after name\n", filename);
1476 +        break;
1477 +      }
1478 +
1479 +
1480 +  if (use_prefix && raw->prefix[0])
1481 +    {
1482 +      for (prefixlen=0; (prefixlen < sizeof raw->prefix
1483 +                         && raw->prefix[prefixlen]); prefixlen++)
1484 +        ;
1485 +      if (prefixlen == sizeof raw->prefix)
1486 +        log_info ("%s: warning: prefix not terminated by a nul byte\n",
1487 +                  filename);
1488 +      for (n=prefixlen+1; n < sizeof raw->prefix; n++)
1489 +        if (raw->prefix[n])
1490 +          {
1491 +            log_info ("%s: warning: garbage after prefix\n", filename);
1492 +            break;
1493 +          }
1494 +    }
1495 +  else
1496 +    prefixlen = 0;
1497 +
1498 +  header = xtrycalloc (1, sizeof *header + prefixlen + 1 + namelen);
1499 +  if (!header)
1500 +    {
1501 +      log_error ("%s: error allocating header: %s\n",
1502 +                 filename, gpg_strerror (gpg_error_from_syserror ()));
1503 +      return NULL;
1504 +    }
1505 +  if (prefixlen)
1506 +    {
1507 +      n = prefixlen;
1508 +      memcpy (header->name, raw->prefix, n);
1509 +      if (raw->prefix[n-1] != '/')
1510 +        header->name[n++] = '/';
1511 +    }
1512 +  else
1513 +    n = 0;
1514 +  memcpy (header->name+n, raw->name, namelen);
1515 +  header->name[n+namelen] = 0;
1516 +  
1517 +  header->mode  = parse_xoctal (raw->mode, sizeof raw->mode, filename);
1518 +  header->uid   = parse_xoctal (raw->uid, sizeof raw->uid, filename);
1519 +  header->gid   = parse_xoctal (raw->gid, sizeof raw->gid, filename);
1520 +  header->size  = parse_xoctal (raw->size, sizeof raw->size, filename);
1521 +  header->mtime = parse_xoctal (raw->mtime, sizeof raw->mtime, filename);
1522 +  /* checksum = */
1523 +  switch (raw->typeflag[0])
1524 +    {
1525 +    case '0': header->typeflag = TF_REGULAR; break;
1526 +    case '1': header->typeflag = TF_HARDLINK; break;
1527 +    case '2': header->typeflag = TF_SYMLINK; break;
1528 +    case '3': header->typeflag = TF_CHARDEV; break;
1529 +    case '4': header->typeflag = TF_BLOCKDEV; break;
1530 +    case '5': header->typeflag = TF_DIRECTORY; break;
1531 +    case '6': header->typeflag = TF_FIFO; break;
1532 +    case '7': header->typeflag = TF_RESERVED; break;
1533 +    default:  header->typeflag = TF_UNKNOWN; break;
1534 +    }
1535 +
1536 +
1537 +  /* Compute the number of data records following this header.  */
1538 +  if (header->typeflag == TF_REGULAR || header->typeflag == TF_UNKNOWN)
1539 +    header->nrecords = (header->size + RECORDSIZE-1)/RECORDSIZE;
1540 +  else
1541 +    header->nrecords = 0;
1542 +  
1543 +
1544 +  return header;
1545 +}
1546 +
1547 +
1548 +\f
1549 +/* Read the next block, assming it is a tar header.  Returns a header
1550 +   object on success or NULL one error.  In case of an error an error
1551 +   message has been printed.  */
1552 +static tar_header_t
1553 +read_header (estream_t stream)
1554 +{
1555 +  gpg_error_t err;
1556 +  char record[RECORDSIZE];
1557 +  int i;
1558 +
1559 +  err = read_record (stream, record);
1560 +  if (err)
1561 +    return NULL;
1562 +
1563 +  for (i=0; i < RECORDSIZE && !record[i]; i++)
1564 +    ;
1565 +  if (i == RECORDSIZE)
1566 +    {
1567 +      /* All zero header - check whether it is the first part of an
1568 +         end of archive mark.  */
1569 +      err = read_record (stream, record);
1570 +      if (err)
1571 +        return NULL;
1572 +      
1573 +      for (i=0; i < RECORDSIZE && !record[i]; i++)
1574 +        ;
1575 +      if (i != RECORDSIZE)
1576 +        log_info ("%s: warning: skipping empty header\n",
1577 +                  es_fname_get (stream));
1578 +      else
1579 +        {
1580 +          /* End of archive - FIXME: we might want to check for garbage.  */
1581 +          return NULL;
1582 +        }
1583 +    }
1584 +
1585 +  return parse_header (record, es_fname_get (stream));
1586 +}
1587 +
1588 +
1589 +/* Skip the data records according to HEADER.  Prints an error message
1590 +   on error and return -1. */
1591 +static int
1592 +skip_data (estream_t stream, tar_header_t header)
1593 +{
1594 +  char record[RECORDSIZE];
1595 +  unsigned long long n;
1596 +
1597 +  for (n=0; n < header->nrecords; n++)
1598 +    {
1599 +      if (read_record (stream, record))
1600 +        return -1;
1601 +    }
1602 +
1603 +  return 0;
1604 +}
1605 +
1606 +
1607 +\f
1608 +static void
1609 +print_header (tar_header_t header, estream_t out)
1610 +{
1611 +  unsigned long mask;
1612 +  char modestr[10+1];
1613 +  int i;
1614 +
1615 +  *modestr = '?';
1616 +  switch (header->typeflag)
1617 +    {
1618 +    case TF_REGULAR:  *modestr = '-'; break;
1619 +    case TF_HARDLINK: *modestr = 'h'; break;
1620 +    case TF_SYMLINK:  *modestr = 'l'; break;
1621 +    case TF_CHARDEV:  *modestr = 'c'; break;
1622 +    case TF_BLOCKDEV: *modestr = 'b'; break;
1623 +    case TF_DIRECTORY:*modestr = 'd'; break;
1624 +    case TF_FIFO:     *modestr = 'f'; break;
1625 +    case TF_RESERVED: *modestr = '='; break;
1626 +    case TF_UNKNOWN:  break;
1627 +    case TF_NOTSUP:   break;
1628 +    }
1629 +  for (mask = 0400, i = 0; i < 9; i++, mask >>= 1)
1630 +    modestr[1+i] = (header->mode & mask)? "rwxrwxrwx"[i]:'-';
1631 +  if ((header->typeflag & 04000))
1632 +    modestr[3] = modestr[3] == 'x'? 's':'S';
1633 +  if ((header->typeflag & 02000))
1634 +    modestr[6] = modestr[6] == 'x'? 's':'S';
1635 +  if ((header->typeflag & 01000))
1636 +    modestr[9] = modestr[9] == 'x'? 't':'T';
1637 +  modestr[10] = 0;
1638 +
1639 +  es_fprintf (out, "%s %lu %lu/%lu %12llu %s %s\n",
1640 +              modestr, header->nlink, header->uid, header->gid, header->size,
1641 +              isotimestamp (header->mtime), header->name);
1642 +}
1643 +
1644 +
1645 +\f
1646 +/* List the tarball FILENAME or, if FILENAME is NULL, the tarball read
1647 +   from stdin.  */
1648 +void
1649 +gpgtar_list (const char *filename)
1650 +{
1651 +  gpg_error_t err;
1652 +  estream_t stream;
1653 +  tar_header_t header;
1654 +
1655 +  if (filename)
1656 +    {
1657 +      stream = es_fopen (filename, "rb");
1658 +      if (!stream)
1659 +        {
1660 +          err = gpg_error_from_syserror ();
1661 +          log_error ("error opening `%s': %s\n", filename, gpg_strerror (err));
1662 +          return;
1663 +        }
1664 +    }
1665 +  else
1666 +    stream = es_stdin;  /* FIXME:  How can we enforce binary mode?  */
1667 +
1668 +  for (;;)
1669 +    {
1670 +      header = read_header (stream);
1671 +      if (!header)
1672 +        goto leave;
1673 +      
1674 +      print_header (header, es_stdout);
1675 +      
1676 +      if (skip_data (stream, header))
1677 +        goto leave;
1678 +      xfree (header);
1679 +      header = NULL;
1680 +    }
1681 +
1682 +
1683 + leave:
1684 +  xfree (header);
1685 +  if (filename)
1686 +    es_fclose (stream);
1687 +  return;
1688 +}
1689 +
1690 +tar_header_t
1691 +gpgtar_read_header (estream_t stream)
1692 +{
1693 +  /*FIXME: Change to return an error code.  */
1694 +  return read_header (stream);
1695 +}
1696 +
1697 +void
1698 +gpgtar_print_header (tar_header_t header, estream_t out)
1699 +{
1700 +  if (header && out)
1701 +    print_header (header, out);
1702 +}
1703 diff -urNp orig/gnupg-2.0.16/tools/gpgtar.c gnupg-2.0.16/tools/gpgtar.c
1704 --- orig/gnupg-2.0.16/tools/gpgtar.c    1970-01-01 01:00:00.000000000 +0100
1705 +++ gnupg-2.0.16/tools/gpgtar.c 2010-07-19 11:17:08.000000000 +0200
1706 @@ -0,0 +1,509 @@
1707 +/* gpgtar.c - A simple TAR implementation mainly useful for Windows.
1708 + * Copyright (C) 2010 Free Software Foundation, Inc.
1709 + *
1710 + * This file is part of GnuPG.
1711 + *
1712 + * GnuPG is free software; you can redistribute it and/or modify
1713 + * it under the terms of the GNU General Public License as published by
1714 + * the Free Software Foundation; either version 3 of the License, or
1715 + * (at your option) any later version.
1716 + *
1717 + * GnuPG is distributed in the hope that it will be useful,
1718 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1719 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1720 + * GNU General Public License for more details.
1721 + *
1722 + * You should have received a copy of the GNU General Public License
1723 + * along with this program; if not, see <http://www.gnu.org/licenses/>.
1724 + */
1725 +
1726 +/* GnuPG comes with a shell script gpg-zip which creates archive files
1727 +   in the same format as PGP Zip, which is actually a USTAR format.
1728 +   That is fine and works nicely on all Unices but for Windows we
1729 +   don't have a compatible shell and the supply of tar programs is
1730 +   limited.  Given that we need just a few tar option and it is an
1731 +   open question how many Unix concepts are to be mapped to Windows,
1732 +   we might as well write our own little tar customized for use with
1733 +   gpg.  So here we go.  */
1734 +
1735 +#include <config.h>
1736 +#include <errno.h>
1737 +#include <stdio.h>
1738 +#include <stdlib.h>
1739 +#include <string.h>
1740 +#include <assert.h>
1741 +
1742 +#include "util.h"
1743 +#include "i18n.h"
1744 +#include "sysutils.h"
1745 +#include "../common/openpgpdefs.h"
1746 +
1747 +#include "gpgtar.h"
1748 +
1749 +
1750 +/* Constants to identify the commands and options. */
1751 +enum cmd_and_opt_values
1752 +  {
1753 +    aNull = 0,
1754 +    aEncrypt    = 'e',
1755 +    aDecrypt    = 'd',
1756 +    aSign       = 's',
1757 +
1758 +    oSymmetric  = 'c',
1759 +    oRecipient = 'r',
1760 +    oUser       = 'u',
1761 +    oOutput    = 'o',
1762 +    oQuiet      = 'q',
1763 +    oVerbose   = 'v',
1764 +    oNoVerbose = 500,
1765 +
1766 +    aSignEncrypt,
1767 +    oSkipCrypto,
1768 +    oSetFilename,
1769 +    aList
1770 +  };
1771 +
1772 +
1773 +/* The list of commands and options. */
1774 +static ARGPARSE_OPTS opts[] = {
1775 +  ARGPARSE_group (300, N_("@Commands:\n ")),
1776 +    
1777 +  ARGPARSE_c (aEncrypt,   "encrypt", N_("create an archive")),
1778 +  ARGPARSE_c (aDecrypt,   "decrypt", N_("extract an archive")),
1779 +  ARGPARSE_c (aSign,      "sign",    N_("create a signed archive")),
1780 +  ARGPARSE_c (aList,      "list-archive", N_("list an archive")),
1781 +
1782 +  ARGPARSE_group (301, N_("@\nOptions:\n ")),
1783 +
1784 +  ARGPARSE_s_n (oSymmetric, "symmetric", N_("use symmetric encryption")),
1785 +  ARGPARSE_s_s (oRecipient, "recipient", N_("|USER-ID|encrypt for USER-ID")),
1786 +  ARGPARSE_s_s (oUser, "local-user",
1787 +                N_("|USER-ID|use USER-ID to sign or decrypt")),
1788 +  ARGPARSE_s_s (oOutput, "output", N_("|FILE|write output to FILE")),
1789 +  ARGPARSE_s_n (oVerbose, "verbose", N_("verbose")),
1790 +  ARGPARSE_s_n (oQuiet,        "quiet",  N_("be somewhat more quiet")),
1791 +  ARGPARSE_s_n (oSkipCrypto, "skip-crypto", N_("skip the crypto processing")),
1792 +  ARGPARSE_s_s (oSetFilename, "set-filename", "@"),
1793 +
1794 +  ARGPARSE_end ()
1795 +};
1796 +
1797 +
1798 +\f
1799 +static void tar_and_encrypt (char **inpattern);
1800 +static void decrypt_and_untar (const char *fname);
1801 +static void decrypt_and_list (const char *fname);
1802 +
1803 +
1804 +
1805 +\f
1806 +/* Print usage information and and provide strings for help. */
1807 +static const char *
1808 +my_strusage( int level )
1809 +{
1810 +  const char *p;
1811 +
1812 +  switch (level)
1813 +    {
1814 +    case 11: p = "gpgtar (GnuPG)";
1815 +      break;
1816 +    case 13: p = VERSION; break;
1817 +    case 17: p = PRINTABLE_OS_NAME; break;
1818 +    case 19: p = _("Please report bugs to <@EMAIL@>.\n"); break;
1819 +
1820 +    case 1:
1821 +    case 40:
1822 +      p = _("Usage: gpgtar [options] [files] [directories] (-h for help)");
1823 +      break;
1824 +    case 41:
1825 +      p = _("Syntax: gpgtar [options] [files] [directories]\n"
1826 +            "Encrypt or sign files into an archive\n");
1827 +      break;
1828 +
1829 +    default: p = NULL; break;
1830 +    }
1831 +  return p;
1832 +}
1833 +
1834 +
1835 +static void
1836 +set_cmd (enum cmd_and_opt_values *ret_cmd, enum cmd_and_opt_values new_cmd)
1837 +{
1838 +  enum cmd_and_opt_values cmd = *ret_cmd;
1839 +
1840 +  if (!cmd || cmd == new_cmd)
1841 +    cmd = new_cmd;
1842 +  else if (cmd == aSign && new_cmd == aEncrypt)
1843 +    cmd = aSignEncrypt;
1844 +  else if (cmd == aEncrypt && new_cmd == aSign)
1845 +    cmd = aSignEncrypt;
1846 +  else 
1847 +    {
1848 +      log_error (_("conflicting commands\n"));
1849 +      exit (2);
1850 +    }
1851 +
1852 +  *ret_cmd = cmd;
1853 +}
1854 +
1855 +
1856 +\f
1857 +/* gpgtar main. */
1858 +int
1859 +main (int argc, char **argv)
1860 +{
1861 +  ARGPARSE_ARGS pargs;
1862 +  const char *fname;
1863 +  int no_more_options = 0;
1864 +  enum cmd_and_opt_values cmd = 0;
1865 +  int skip_crypto = 0;
1866 +
1867 +  assert (sizeof (struct ustar_raw_header) == 512);
1868 +
1869 +  gnupg_reopen_std ("gpgtar");
1870 +  set_strusage (my_strusage);
1871 +  log_set_prefix ("gpgtar", 1);
1872 +
1873 +  /* Make sure that our subsystems are ready.  */
1874 +  i18n_init();
1875 +  init_common_subsystems ();
1876 +
1877 +  /* Parse the command line. */
1878 +  pargs.argc  = &argc;
1879 +  pargs.argv  = &argv;
1880 +  pargs.flags = ARGPARSE_FLAG_KEEP;
1881 +  while (!no_more_options && optfile_parse (NULL, NULL, NULL, &pargs, opts))
1882 +    {
1883 +      switch (pargs.r_opt)
1884 +        {
1885 +        case oOutput:    opt.outfile = pargs.r.ret_str; break;
1886 +        case oSetFilename: opt.filename = pargs.r.ret_str; break;
1887 +       case oQuiet:     opt.quiet = 1; break;
1888 +        case oVerbose:   opt.verbose++; break;
1889 +        case oNoVerbose: opt.verbose = 0; break;
1890 +          
1891 +       case aList:
1892 +        case aDecrypt:
1893 +        case aEncrypt:
1894 +        case aSign:
1895 +          set_cmd (&cmd, pargs.r_opt);
1896 +         break;
1897 +
1898 +        case oSymmetric:
1899 +          set_cmd (&cmd, aEncrypt);
1900 +          opt.symmetric = 1;
1901 +          break;
1902 +
1903 +        case oSkipCrypto:
1904 +          skip_crypto = 1;
1905 +          break;
1906 +
1907 +        default: pargs.err = 2; break;
1908 +       }
1909 +    }
1910 +  
1911 +  if (log_get_errorcount (0))
1912 +    exit (2);
1913 +
1914 +  switch (cmd)
1915 +    {
1916 +    case aList:
1917 +      if (argc > 1)
1918 +        usage (1);
1919 +      fname = argc ? *argv : NULL;
1920 +      if (opt.filename)
1921 +        log_info ("note: ignoring option --set-filename\n");
1922 +      if (skip_crypto)
1923 +        gpgtar_list (fname);
1924 +      else
1925 +        decrypt_and_list (fname);
1926 +      break;
1927 +
1928 +    case aEncrypt:
1929 +      if (!argc)
1930 +        usage (1);
1931 +      if (opt.filename)
1932 +        log_info ("note: ignoring option --set-filename\n");
1933 +      if (skip_crypto)
1934 +        gpgtar_create (argv);
1935 +      else
1936 +        tar_and_encrypt (argv);
1937 +      break;
1938 +
1939 +    case aDecrypt:
1940 +      if (argc != 1)
1941 +        usage (1);
1942 +      if (opt.outfile)
1943 +        log_info ("note: ignoring option --output\n");
1944 +      fname = argc ? *argv : NULL;
1945 +      if (skip_crypto)
1946 +        gpgtar_extract (fname);
1947 +      else
1948 +        decrypt_and_untar (fname);
1949 +      break;
1950 +
1951 +    default:
1952 +      log_error (_("invalid command (there is no implicit command)\n"));
1953 +      break;
1954 +    }
1955 +
1956 +  return log_get_errorcount (0)? 1:0;
1957 +}
1958 +
1959 +
1960 +/* Read the next record from STREAM.  RECORD is a buffer provided by
1961 +   the caller and must be at leadt of size RECORDSIZE.  The function
1962 +   return 0 on success and and error code on failure; a diagnostic
1963 +   printed as well.  Note that there is no need for an EOF indicator
1964 +   because a tarball has an explicit EOF record. */
1965 +gpg_error_t
1966 +read_record (estream_t stream, void *record)
1967 +{
1968 +  gpg_error_t err;
1969 +  size_t nread;
1970 +
1971 +  nread = es_fread (record, 1, RECORDSIZE, stream);
1972 +  if (nread != RECORDSIZE)
1973 +    {
1974 +      err = gpg_error_from_syserror ();
1975 +      if (es_ferror (stream))
1976 +        log_error ("error reading `%s': %s\n",
1977 +                   es_fname_get (stream), gpg_strerror (err));
1978 +      else
1979 +        log_error ("error reading `%s': premature EOF "
1980 +                   "(size of last record: %zu)\n",
1981 +                   es_fname_get (stream), nread);
1982 +    }
1983 +  else
1984 +    err = 0;
1985 +
1986 +  return err;
1987 +}
1988 +
1989 +
1990 +/* Write the RECORD of size RECORDSIZE to STREAM.  FILENAME is the
1991 +   name of the file used for diagnostics.  */
1992 +gpg_error_t
1993 +write_record (estream_t stream, const void *record)
1994 +{
1995 +  gpg_error_t err;
1996 +  size_t nwritten;
1997 +
1998 +  nwritten = es_fwrite (record, 1, RECORDSIZE, stream);
1999 +  if (nwritten != RECORDSIZE)
2000 +    {
2001 +      err = gpg_error_from_syserror ();
2002 +      log_error ("error writing `%s': %s\n",
2003 +                 es_fname_get (stream), gpg_strerror (err));
2004 +    }
2005 +  else
2006 +    err = 0;
2007 +  
2008 +  return err;
2009 +}
2010 +
2011 +
2012 +/* Return true if FP is an unarmored OpenPGP message.  Note that this
2013 +   fucntion reads a few bytes from FP but pushes them back.  */
2014 +#if 0
2015 +static int
2016 +openpgp_message_p (estream_t fp)
2017 +{
2018 +  int ctb;
2019 +
2020 +  ctb = es_getc (fp);
2021 +  if (ctb != EOF)
2022 +    {
2023 +      if (es_ungetc (ctb, fp))
2024 +        log_fatal ("error ungetting first byte: %s\n", 
2025 +                   gpg_strerror (gpg_error_from_syserror ()));
2026 +      
2027 +      if ((ctb & 0x80))
2028 +        {
2029 +          switch ((ctb & 0x40) ? (ctb & 0x3f) : ((ctb>>2)&0xf))
2030 +            {
2031 +            case PKT_MARKER:
2032 +            case PKT_SYMKEY_ENC:
2033 +            case PKT_ONEPASS_SIG:
2034 +            case PKT_PUBKEY_ENC:
2035 +            case PKT_SIGNATURE:
2036 +            case PKT_COMMENT:
2037 +            case PKT_OLD_COMMENT:
2038 +            case PKT_PLAINTEXT:
2039 +            case PKT_COMPRESSED:
2040 +            case PKT_ENCRYPTED:
2041 +              return 1; /* Yes, this seems to be an OpenPGP message.  */
2042 +            default:
2043 +              break;
2044 +            }
2045 +        }
2046 +    }
2047 +  return 0;
2048 +}
2049 +#endif
2050 +
2051 +
2052 +
2053 +\f
2054 +static void
2055 +tar_and_encrypt (char **inpattern)
2056 +{
2057 +  (void)inpattern;
2058 +  log_error ("tar_and_encrypt has not yet been implemented\n");
2059 +}
2060 +
2061 +
2062 +\f
2063 +static void
2064 +decrypt_and_untar (const char *fname)
2065 +{
2066 +  (void)fname;
2067 +  log_error ("decrypt_and_untar has not yet been implemented\n");
2068 +}
2069 +
2070 +
2071 +\f
2072 +static void
2073 +decrypt_and_list (const char *fname)
2074 +{
2075 +  (void)fname;
2076 +  log_error ("decrypt_and_list has not yet been implemented\n");
2077 +}
2078 +
2079 +
2080 +
2081 +
2082 +/* A wrapper around mkdir which takes a string for the mode argument.
2083 +   This makes it easier to handle the mode argument which is not
2084 +   defined on all systems.  The format of the modestring is
2085 +
2086 +      "-rwxrwxrwx"
2087 +      
2088 +   '-' is a don't care or not set.  'r', 'w', 'x' are read allowed,
2089 +   write allowed, execution allowed with the first group for the user,
2090 +   the second for the group and the third for all others.  If the
2091 +   string is shorter than above the missing mode characters are meant
2092 +   to be not set.  */
2093 +int
2094 +gnupg_mkdir (const char *name, const char *modestr)
2095 +{
2096 +#ifdef HAVE_W32CE_SYSTEM
2097 +  wchar_t *wname;
2098 +  (void)modestr;
2099 +  
2100 +  wname = utf8_to_wchar (name);
2101 +  if (!wname)
2102 +    return -1;
2103 +  if (!CreateDirectoryW (wname, NULL))
2104 +    {
2105 +      xfree (wname);
2106 +      return -1;  /* ERRNO is automagically provided by gpg-error.h.  */
2107 +    }
2108 +  xfree (wname);
2109 +  return 0;
2110 +#elif MKDIR_TAKES_ONE_ARG
2111 +  (void)modestr;
2112 +  /* Note: In the case of W32 we better use CreateDirectory and try to
2113 +     set appropriate permissions.  However using mkdir is easier
2114 +     because this sets ERRNO.  */
2115 +  return mkdir (name);
2116 +#else
2117 +  mode_t mode = 0;
2118 +
2119 +  if (modestr && *modestr)
2120 +    {
2121 +      modestr++;
2122 +      if (*modestr && *modestr++ == 'r')
2123 +        mode |= S_IRUSR;
2124 +      if (*modestr && *modestr++ == 'w')
2125 +        mode |= S_IWUSR;
2126 +      if (*modestr && *modestr++ == 'x')
2127 +        mode |= S_IXUSR;
2128 +      if (*modestr && *modestr++ == 'r')
2129 +        mode |= S_IRGRP;
2130 +      if (*modestr && *modestr++ == 'w')
2131 +        mode |= S_IWGRP;
2132 +      if (*modestr && *modestr++ == 'x')
2133 +        mode |= S_IXGRP;
2134 +      if (*modestr && *modestr++ == 'r')
2135 +        mode |= S_IROTH;
2136 +      if (*modestr && *modestr++ == 'w')
2137 +        mode |= S_IWOTH;
2138 +      if (*modestr && *modestr++ == 'x')
2139 +        mode |= S_IXOTH;
2140 +    }
2141 +  return mkdir (name, mode);
2142 +#endif
2143 +}
2144 +
2145 +#ifdef HAVE_W32_SYSTEM
2146 +/* Return a malloced string encoded in UTF-8 from the wide char input
2147 +   string STRING.  Caller must free this value.  Returns NULL and sets
2148 +   ERRNO on failure.  Calling this function with STRING set to NULL is
2149 +   not defined.  */
2150 +char *
2151 +wchar_to_utf8 (const wchar_t *string)
2152 +{
2153 +  int n;
2154 +  char *result;
2155 +
2156 +  n = WideCharToMultiByte (CP_UTF8, 0, string, -1, NULL, 0, NULL, NULL);
2157 +  if (n < 0)
2158 +    {
2159 +      errno = EINVAL;
2160 +      return NULL;
2161 +    }
2162 +
2163 +  result = xtrymalloc (n+1);
2164 +  if (!result)
2165 +    return NULL;
2166 +
2167 +  n = WideCharToMultiByte (CP_UTF8, 0, string, -1, result, n, NULL, NULL);
2168 +  if (n < 0)
2169 +    {
2170 +      xfree (result);
2171 +      errno = EINVAL;
2172 +      result = NULL;
2173 +    }
2174 +  return result;
2175 +}
2176 +
2177 +
2178 +/* Return a malloced wide char string from an UTF-8 encoded input
2179 +   string STRING.  Caller must free this value.  Returns NULL and sets
2180 +   ERRNO on failure.  Calling this function with STRING set to NULL is
2181 +   not defined.  */
2182 +wchar_t *
2183 +utf8_to_wchar (const char *string)
2184 +{
2185 +  int n;
2186 +  size_t nbytes;
2187 +  wchar_t *result;
2188 +
2189 +  n = MultiByteToWideChar (CP_UTF8, 0, string, -1, NULL, 0);
2190 +  if (n < 0)
2191 +    {
2192 +      errno = EINVAL;
2193 +      return NULL;
2194 +    }
2195 +
2196 +  nbytes = (size_t)(n+1) * sizeof(*result);
2197 +  if (nbytes / sizeof(*result) != (n+1)) 
2198 +    {
2199 +      errno = ENOMEM;
2200 +      return NULL;
2201 +    }
2202 +  result = xtrymalloc (nbytes);
2203 +  if (!result)
2204 +    return NULL;
2205 +
2206 +  n = MultiByteToWideChar (CP_UTF8, 0, string, -1, result, n);
2207 +  if (n < 0)
2208 +    {
2209 +      free (result);
2210 +      errno = EINVAL;
2211 +      result = NULL;
2212 +    }
2213 +  return result;
2214 +}
2215 +#endif /*HAVE_W32_SYSTEM*/
2216 diff -urNp orig/gnupg-2.0.16/tools/gpgtar.h gnupg-2.0.16/tools/gpgtar.h
2217 --- orig/gnupg-2.0.16/tools/gpgtar.h    1970-01-01 01:00:00.000000000 +0100
2218 +++ gnupg-2.0.16/tools/gpgtar.h 2010-07-19 11:15:30.000000000 +0200
2219 @@ -0,0 +1,132 @@
2220 +/* gpgtar.h - Global definitions for gpgtar
2221 + * Copyright (C) 2010 Free Software Foundation, Inc.
2222 + *
2223 + * This file is part of GnuPG.
2224 + *
2225 + * GnuPG is free software; you can redistribute it and/or modify
2226 + * it under the terms of the GNU General Public License as published by
2227 + * the Free Software Foundation; either version 3 of the License, or
2228 + * (at your option) any later version.
2229 + *
2230 + * GnuPG is distributed in the hope that it will be useful,
2231 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
2232 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
2233 + * GNU General Public License for more details.
2234 + *
2235 + * You should have received a copy of the GNU General Public License
2236 + * along with this program; if not, see <http://www.gnu.org/licenses/>.
2237 + */
2238 +
2239 +#ifndef GPGTAR_H
2240 +#define GPGTAR_H
2241 +
2242 +#include "../common/util.h"
2243 +#include "../common/estream.h"
2244 +
2245 +/* We keep all global options in the structure OPT.  */
2246 +struct
2247 +{
2248 +  int verbose;
2249 +  int quiet;
2250 +  const char *outfile;
2251 +  int symmetric;
2252 +  const char *filename;
2253 +} opt;
2254 +
2255 +
2256 +/* The size of a tar record.  All IO is done in chunks of this size.
2257 +   Note that we don't care about blocking because this version of tar
2258 +   is not expected to be used directly on a tape drive in fact it is
2259 +   used in a pipeline with GPG and thus any blocking would be
2260 +   useless.  */
2261 +#define RECORDSIZE 512 
2262 +
2263 +
2264 +/* Description of the USTAR header format.  */
2265 +struct ustar_raw_header
2266 +{
2267 +  char name[100];
2268 +  char mode[8];
2269 +  char uid[8];
2270 +  char gid[8];
2271 +  char size[12];
2272 +  char mtime[12];
2273 +  char checksum[8];
2274 +  char typeflag[1];
2275 +  char linkname[100];
2276 +  char magic[6];
2277 +  char version[2];
2278 +  char uname[32];
2279 +  char gname[32];   
2280 +  char devmajor[8]; 
2281 +  char devminor[8];
2282 +  char prefix[155]; 
2283 +  char pad[12];
2284 +};
2285 +
2286 +
2287 +/* Filetypes as defined by USTAR.  */
2288 +typedef enum 
2289 +  {
2290 +    TF_REGULAR,
2291 +    TF_HARDLINK,
2292 +    TF_SYMLINK,
2293 +    TF_CHARDEV,
2294 +    TF_BLOCKDEV,
2295 +    TF_DIRECTORY,
2296 +    TF_FIFO,
2297 +    TF_RESERVED,
2298 +    TF_UNKNOWN,    /* Needs to be treated as regular file.  */
2299 +    TF_NOTSUP      /* Not supported (used with --create).  */
2300 +  } typeflag_t;
2301 +
2302 +
2303 +/* The internal represenation of a TAR header.  */
2304 +struct tar_header_s;
2305 +typedef struct tar_header_s *tar_header_t;
2306 +struct tar_header_s
2307 +{
2308 +  tar_header_t next;        /* Used to build a linked list iof entries.  */
2309 +
2310 +  unsigned long mode;       /* The file mode.  */
2311 +  unsigned long nlink;      /* Number of hard links.  */
2312 +  unsigned long uid;        /* The user id of the file.  */
2313 +  unsigned long gid;        /* The group id of the file.  */
2314 +  unsigned long long size;  /* The size of the file.  */
2315 +  unsigned long long mtime; /* Modification time since Epoch.  Note
2316 +                               that we don't use time_t here but a
2317 +                               type which is more likely to be larger
2318 +                               that 32 bit and thus allows to track
2319 +                               times beyond 2106.  */
2320 +  typeflag_t typeflag;      /* The type of the file.  */
2321 +  
2322 +
2323 +  unsigned long long nrecords; /* Number of data records.  */
2324 +
2325 +  char name[1];             /* Filename (dynamically extended).  */
2326 +};
2327 +
2328 +
2329 +/*-- gpgtar.c --*/
2330 +gpg_error_t read_record (estream_t stream, void *record);
2331 +gpg_error_t write_record (estream_t stream, const void *record);
2332 +
2333 +int gnupg_mkdir (const char *name, const char *modestr);
2334 +#ifdef HAVE_W32_SYSTEM
2335 +char *wchar_to_utf8 (const wchar_t *string);
2336 +wchar_t *utf8_to_wchar (const char *string);
2337 +#endif
2338 +
2339 +/*-- gpgtar-create.c --*/
2340 +void gpgtar_create (char **inpattern);
2341 +
2342 +/*-- gpgtar-extract.c --*/
2343 +void gpgtar_extract (const char *filename);
2344 +
2345 +/*-- gpgtar-list.c --*/
2346 +void gpgtar_list (const char *filename);
2347 +tar_header_t gpgtar_read_header (estream_t stream);
2348 +void gpgtar_print_header (tar_header_t header, estream_t out);
2349 +
2350 +
2351 +#endif /*GPGTAR_H*/