1
0
mirror of git://git.gnupg.org/gnupg.git synced 2025-03-25 22:19:59 +01:00

See ChangeLog: Sat Dec 4 12:30:28 CET 1999 Werner Koch

This commit is contained in:
Werner Koch 1999-12-04 11:33:45 +00:00
parent deb9c3866f
commit 8eec0983f6
25 changed files with 258 additions and 83 deletions

@ -1,3 +1,10 @@
Sat Dec 4 12:30:28 CET 1999 Werner Koch <wk@gnupg.de>
* configure.in (dlopen): Use CHECK_FUNC for a test of dlopen in libc.
Suggested by Alexandre Oliva.
(-Wall): Moved the settting of gcc warning options near to the end
so that tests don't get confused. Suggested by Paul D. Smith.
Mon Nov 22 11:14:53 CET 1999 Werner Koch <wk@gnupg.de>
* BUGS: Replaced content with a link to the online list.

7
NEWS

@ -1,5 +1,3 @@
Noteworthy changes in version 1.0.x (1999-??-??)
-----------------------------------
* New command --verify-files. New option --fast-list-mode.
@ -24,6 +22,11 @@ Noteworthy changes in version 1.0.x (1999-??-??)
* Passing non-ascii user IDs on the commandline should now work in all
cases.
* New keys are now generated with an additional preference to Blowfish.
* Removed the GNU Privacy Handbook from the distribution as it will go
into a separate one.
Noteworthy changes in version 1.0.0 (1999-09-07)
-----------------------------------

20
README

@ -1,5 +1,3 @@
-----BEGIN PGP SIGNED MESSAGE-----
GnuPG - The GNU Privacy Guard
-------------------------------
Version 1.0
@ -135,10 +133,11 @@
Documentation
-------------
A draft version of the manual is included in the subdirectory doc/gph.
The supplied version is rendered in HTML and you may access it with any
browser (e.g.: lynx doc/gpg/index.html). The GnuPG webpages have a link
to the latest development version and you may want to read those instead.
The manual will be distributed separate under the name "gnupgdoc".
An online version of the latest manual draft is available at the
GnuPG web pages:
http://www.gnupg.org/gph/
A couple of HOWTO documents are available online; for a listing see:
@ -473,7 +472,7 @@
The primary WWW page is "http://www.gnupg.org"
The primary FTP site is "ftp://ftp.gnupg.org/pub/gcrypt/"
See http://www.gnupg.org/mirrors.html for a list of FTP mirrors
See http://www.gnupg.org/mirrors.html for a list of mirrors
and use them if possible. You may also find GnuPG mirrored on
some of the regular GNU mirrors.
@ -509,10 +508,3 @@
Commercial grade support for GnuPG is available; please see
the GNU service directory or search other resources.
-----BEGIN PGP SIGNATURE-----
iQB1AwUBOCv6bB0Z9MEMmFelAQGktwL/SyzPDeU2I38lFj3Xx7IhL9vUTEaEDuAH
FFjs0i4qpRlvYVfTtEQjkUMCUe6PCMXNXY+var1FOECpJwS93t4uf3VV83ESOMCu
VR5JjhowfU2l957aFOFyzBpNuMPBuwBR
=+Tbg
-----END PGP SIGNATURE-----

@ -1,3 +1,10 @@
Sat Dec 4 12:30:28 CET 1999 Werner Koch <wk@gnupg.de>
* primegen.c (generate_elg_prime): All primes are now generated with
the lowest random quality level. Becuase they are public anyway we
don't need stronger random and by this we do not drain the systems
entropy so much.
Thu Oct 28 16:08:20 CEST 1999 Werner Koch <wk@gnupg.de>
* random.c (fast_random_poll): Check whether RUSAGE_SELF is defined;

@ -117,8 +117,8 @@ generate_elg_prime( int mode, unsigned pbits, unsigned qbits,
log_debug("gen prime: pbits=%u qbits=%u fbits=%u/%u n=%d\n",
pbits, req_qbits, qbits, fbits, n );
prime = mpi_alloc( (pbits + BITS_PER_MPI_LIMB - 1) / BITS_PER_MPI_LIMB );
q = gen_prime( qbits, 0, 1 );
q_factor = mode==1? gen_prime( req_qbits, 0, 1 ) : NULL;
q = gen_prime( qbits, 0, 0 );
q_factor = mode==1? gen_prime( req_qbits, 0, 0 ) : NULL;
/* allocate an array to hold the factors + 2 for later usage */
factors = m_alloc_clear( (n+2) * sizeof *factors );
@ -145,7 +145,7 @@ generate_elg_prime( int mode, unsigned pbits, unsigned qbits,
perms = m_alloc_clear( m );
for(i=0; i < n; i++ ) {
perms[i] = 1;
pool[i] = gen_prime( fbits, 0, 1 );
pool[i] = gen_prime( fbits, 0, 0 );
factors[i] = pool[i];
}
}
@ -154,7 +154,7 @@ generate_elg_prime( int mode, unsigned pbits, unsigned qbits,
for(i=j=0; i < m && j < n ; i++ )
if( perms[i] ) {
if( !pool[i] )
pool[i] = gen_prime( fbits, 0, 1 );
pool[i] = gen_prime( fbits, 0, 0 );
factors[j++] = pool[i];
}
if( i == n ) {
@ -177,7 +177,7 @@ generate_elg_prime( int mode, unsigned pbits, unsigned qbits,
count1 = 0;
qbits++;
progress('>');
q = gen_prime( qbits, 0, 1 );
q = gen_prime( qbits, 0, 0 );
goto next_try;
}
}
@ -188,7 +188,7 @@ generate_elg_prime( int mode, unsigned pbits, unsigned qbits,
count2 = 0;
qbits--;
progress('<');
q = gen_prime( qbits, 0, 1 );
q = gen_prime( qbits, 0, 0 );
goto next_try;
}
}

@ -314,8 +314,8 @@ if test "$try_dynload" = yes ; then
DYNLINK_LDFLAGS="$CFLAGS_RDYNAMIC"
use_gnupg_extensions=yes
else
AC_CHECK_LIB(c,dlopen)
if test "$ac_cv_lib_c_dlopen" = "yes"; then
AC_CHECK_FUNCS(dlopen)
if test "$ac_cv_func_dlopen" = "yes"; then
AC_DEFINE(USE_DYNAMIC_LINKING)
AC_DEFINE(HAVE_DL_DLOPEN)
DYNLINK_LDFLAGS="$CFLAGS_RDYNAMIC"
@ -666,6 +666,10 @@ GNUPG_DO_LINK_FILES
GNUPG_CHECK_GNUMAKE
if test "$GCC" = yes; then
CFLAGS="$CFLAGS -Wall -Wcast-align -Wshadow -Wstrict-prototypes"
fi
AC_OUTPUT_COMMANDS([
cat >g10defs.tmp <<G10EOF
/* Generated automatically by configure */

@ -1,3 +1,7 @@
Sat Dec 4 12:30:28 CET 1999 Werner Koch <wk@gnupg.de>
* gpg.sgml: Add section about the user ID
Mon Nov 22 11:14:53 CET 1999 Werner Koch <wk@gnupg.de>
* gph: Removed the directory from the dist becuase it will

14
doc/FAQ

@ -346,10 +346,10 @@
material?
A: No. For example you can add or remove "Comment:" lines. They
have a purpose like the mail header lines. However a "Hash:"
line is needed for modern signatures, to tell the parser which
line is needed for OpenPGG signatures to tell the parser which
hash algorithm to use.
Q: Now can a get list of key IDs used to encrypt a message?
Q: How can a get list of key IDs used to encrypt a message?
A: gpg --batch --decrypt --status-fd 1 2>/dev/null \
| awk '/^\[GNUPG:\] ENC_TO / { print $3 }'
@ -357,9 +357,17 @@
Q: PGP 5.x, 6.x does not like my secret key.
A: PGP probaly bails out on some private comment packets used by GnuPG.
These packets are fully in compliance with OpenPGP; however PGP is not
really OPenPGP aware. A workaround is to eport the secret keys with
really OpenPGP aware. A workaround is to eport the secret keys with
this command:
gpg --export-secret-keys --no-comment -a your-key-id
Q: I can't decrypt my symmetrical only (-c) encrypted message with
a new version of GnuPG.
A: There used to be a bug in GnuPG < 1.0.1 which happens only if 3DES
was used for symmetric only encryption (this has never been the default).
The bug has been fixed but to enable you to decrypt old messages, you
should run gpg with the option "--emulate-3des-s2k-bug", decrypt the
message and encrypt it again without this option. The option will
be removed in 1.1, so better re/encrypt your message now.

@ -1248,6 +1248,101 @@ This is not for normal use. Use the source to see for what it might be useful.
</variablelist>
</refsect1>
<refsect1>
<title>How to specify a user ID</title>
<para>
There are different ways on how to specify a user ID to GnuPG;
here are some examples:
</para>
<variablelist>
<varlistentry>
<term></term>
<listitem><para>Used to locate the default home directory.</para></listitem>
</varlistentry>
<varlistentry>
<term>234567C4</term>
<term>0F34E556E</term>
<term>01347A56A</term>
<term>0xAB123456</term>
<listitem><para>
Here the key ID is given in the usual short form.
</para></listitem>
</varlistentry>
<varlistentry>
<term>234AABBCC34567C4</term>
<term>0F323456784E56EAB</term>
<term>01AB3FED1347A5612</term>
<term>0x234AABBCC34567C4</term>
<listitem><para>
Here the key ID is given in the long form as used by OpenPGP.
</para></listitem>
</varlistentry>
<varlistentry>
<term>1234343434343434C434343434343434</term>
<term>123434343434343C3434343434343734349A3434</term>
<term>0E12343434343434343434EAB3484343434343434</term>
<term>0xE12343434343434343434EAB3484343434343434</term>
<listitem><para>
The best way to specify a key ID is by using the fingerprint of
the key. This avoids any ambiguities in case that there are duplicated
kez IDs (which are really rare for the long key IDs).
</para></listitem>
</varlistentry>
<varlistentry>
<term>=Heinrich Heine &lt;heinrichh@uni-duesseldorf.de&gt;</term>
<listitem><para>
Using an exact to match string. The equal sign indicates this.
</para></listitem>
</varlistentry>
<varlistentry>
<term>&lt;heinrichh@uni-duesseldorf.de&gt;</term>
<listitem><para>
Using the email address part which must match exactly. The left angle bracket
indicates this email address mode.
</para></listitem>
</varlistentry>
<varlistentry>
<term>+Heinrich Heine duesseldorf</term>
<listitem><para>
All words must match exactly (not case sensitive) but can appear in
any order in the user ID. Words are any sequences of letters,
digits, the underscore and all characters with bit 7 set.
</para></listitem>
</varlistentry>
<varlistentry>
<term>#34</term>
<listitem><para>
Using the Local ID. This is a very low level method and should
only be used by applications which really need it. The hash character
indicates this method. An application should not assume that this is
only a number.
</para></listitem>
</varlistentry>
<varlistentry>
<term>Heine</term>
<term>*Heine</term>
<listitem><para>
By case insensitive substring matching. This is the default mode but
applications maz want to explicitely indicate this bz putting the asterisk
in front.
</para></listitem>
</varlistentry>
</variablelist>
</refsect1>
<refsect1>
<title>RETURN VALUE</title>
<para>

@ -1,3 +1,27 @@
Sat Dec 4 12:30:28 CET 1999 Werner Koch <wk@gnupg.de>
* pkclist.c (build_pk_list): Validate the trust using the namehash
if this one has been set by the key lookup.
* g10.c: Add --delete-secret-key to the help page.
* openfile.c (copy_options_file): Made static.
(try_make_homedir): New.
* ringedit.c (add_keyblock_resource): Use the try_make_hoemdir logic.
* tdbio.c (tdbio_set_dbname): Likewise.
* keygen.c (generate_user_id): Use m_alloc_clear() here. We should
better use an allocation function specific to the user_id packet.
* keygen.c (keygen_add_std_prefs): Changed symmetric preferences
to include Blowfish again. This is due to it's better speed compared
to CAST5.
* g10.c (strusage): Print the home directory.
* armor.c (armor_filter): Take action on the cancel control msg.
* filter.h (armor_filter_context_t): Add cancel flag.
Mon Nov 29 21:52:11 CET 1999 Werner Koch <wk@gnupg.de>
* g10.c: New option --fast-list-mode ..

@ -874,7 +874,7 @@ armor_filter( void *opaque, int control,
#endif
*ret_len = n;
}
else if( control == IOBUFCTRL_FLUSH ) {
else if( control == IOBUFCTRL_FLUSH && !afx->cancel ) {
if( !afx->status ) { /* write the header line */
if( afx->what >= DIM(head_strings) )
log_bug("afx->what=%d", afx->what);
@ -951,8 +951,13 @@ armor_filter( void *opaque, int control,
if( !is_initialized )
initialize();
}
else if( control == IOBUFCTRL_CANCEL ) {
afx->cancel = 1;
}
else if( control == IOBUFCTRL_FREE ) {
if( afx->status ) { /* pad, write cecksum, and bottom line */
if( afx->cancel )
;
else if( afx->status ) { /* pad, write cecksum, and bottom line */
crc = afx->crc;
idx = afx->idx;
idx2 = afx->idx2;

@ -59,6 +59,7 @@ typedef struct {
u32 crc;
int status; /* an internal state flag */
int cancel;
int any_data; /* any valid armored data seen */
int pending_lf; /* used together with faked */
} armor_filter_context_t;

@ -205,6 +205,8 @@ static ARGPARSE_OPTS opts[] = {
{ aListSecretKeys, "list-secret-keys", 256, N_("list secret keys")},
{ aKeygen, "gen-key", 256, N_("generate a new key pair")},
{ aDeleteKey, "delete-key",256, N_("remove key from the public keyring")},
{ aDeleteSecretKey, "delete-secret-key",256,
N_("remove key from the secret keyring")},
{ aSignKey, "sign-key" ,256, N_("sign a key")},
{ aLSignKey, "lsign-key" ,256, N_("sign a key locally")},
{ aEditKey, "edit-key" ,256, N_("sign or edit a key")},
@ -304,7 +306,6 @@ static ARGPARSE_OPTS opts[] = {
{ aListTrustPath, "list-trust-path",0, "@"},
{ oKOption, NULL, 0, "@"},
{ oPasswdFD, "passphrase-fd",1, "@" },
{ aDeleteSecretKey, "delete-secret-key",0, "@" },
{ oQuickRandom, "quick-random", 0, "@"},
{ oNoVerbose, "no-verbose", 0, "@"},
{ oTrustDBName, "trustdb-name", 2, "@" },
@ -391,26 +392,29 @@ strusage( int level )
"default operation depends on the input data\n");
break;
case 31: p = _("\nSupported algorithms:\n"); break;
case 32:
case 31: p = "\nHome: "; break;
case 32: p = opt.homedir; break;
case 33: p = _("\nSupported algorithms:\n"); break;
case 34:
if( !ciphers )
ciphers = build_list("Cipher: ", cipher_algo_to_string,
check_cipher_algo );
p = ciphers;
break;
case 33:
case 35:
if( !pubkeys )
pubkeys = build_list("Pubkey: ", pubkey_algo_to_string,
check_pubkey_algo );
p = pubkeys;
break;
case 34:
case 36:
if( !digests )
digests = build_list("Hash: ", digest_algo_to_string,
check_digest_algo );
p = digests;
break;
default: p = default_strusage(level);
}
return p;

@ -43,7 +43,7 @@ write_uid( KBNODE root, const char *s )
size_t n = strlen(s);
pkt->pkttype = PKT_USER_ID;
pkt->pkt.user_id = m_alloc( sizeof *pkt->pkt.user_id + n - 1 );
pkt->pkt.user_id = m_alloc_clear( sizeof *pkt->pkt.user_id + n - 1 );
pkt->pkt.user_id->len = n;
strcpy(pkt->pkt.user_id->name, s);
add_kbnode( root, new_kbnode( pkt ) );
@ -84,8 +84,9 @@ keygen_add_std_prefs( PKT_signature *sig, void *opaque )
keygen_add_key_expire( sig, opaque );
buf[0] = CIPHER_ALGO_TWOFISH;
buf[1] = CIPHER_ALGO_CAST5;
build_sig_subpkt( sig, SIGSUBPKT_PREF_SYM, buf, 2 );
buf[1] = CIPHER_ALGO_BLOWFISH;
buf[2] = CIPHER_ALGO_CAST5;
build_sig_subpkt( sig, SIGSUBPKT_PREF_SYM, buf, 3 );
buf[0] = DIGEST_ALGO_RMD160;
buf[1] = DIGEST_ALGO_SHA1;
@ -558,7 +559,7 @@ ask_expire_interval(void)
tty_printf(_("Key expires at %s\n"),
asctimestamp((ulong)(curtime + interval) ) );
if( (time_t)((ulong)(curtime+interval)) < 0 )
tty_printf(_("Your system can't display dates beyond 2036.\n"
tty_printf(_("Your system can't display dates beyond 2038.\n"
"However, it will be correctly handled up to 2106.\n"));
}
@ -827,7 +828,7 @@ generate_user_id()
if( !p )
return NULL;
n = strlen(p);
uid = m_alloc( sizeof *uid + n - 1 );
uid = m_alloc_clear( sizeof *uid + n - 1 );
uid->len = n;
strcpy(uid->name, p);
return uid;

@ -103,7 +103,7 @@ char *make_outfile_name( const char *iname );
char *ask_outfile_name( const char *name, size_t namelen );
int open_outfile( const char *iname, int mode, IOBUF *a );
IOBUF open_sigfile( const char *iname );
void copy_options_file( const char *destdir );
void try_make_homedir( const char *fname );
/*-- seskey.c --*/
void make_session_key( DEK *dek );

@ -24,6 +24,9 @@
#include <string.h>
#include <assert.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include "util.h"
#include "memory.h"
@ -45,6 +48,10 @@
#define CMP_FILENAME(a,b) strcmp( (a), (b) )
#endif
#ifdef MKDIR_TAKES_ONE_ARG
# undef mkdir
# define mkdir(a,b) mkdir(a)
#endif
/* FIXME: Implement opt.interactive. */
@ -251,7 +258,7 @@ open_sigfile( const char *iname )
/****************
* Copy the option file skeleton to the given directory.
*/
void
static void
copy_options_file( const char *destdir )
{
const char *datadir = GNUPG_DATADIR;
@ -294,3 +301,23 @@ copy_options_file( const char *destdir )
m_free(fname);
}
void
try_make_homedir( const char *fname )
{
if( opt.dry_run )
return;
if( strlen(fname) >= 7
&& !strcmp(fname+strlen(fname)-7, "/.gnupg" ) ) {
if( mkdir( fname, S_IRUSR|S_IWUSR|S_IXUSR ) )
log_fatal( _("%s: can't create directory: %s\n"),
fname, strerror(errno) );
else if( !opt.quiet )
log_info( _("%s: directory created\n"), fname );
copy_options_file( fname );
log_info(_("you have to start GnuPG again, "
"so it can read the new options file\n") );
g10_exit(1);
}
}

@ -775,7 +775,8 @@ build_pk_list( STRLIST remusr, PK_LIST *ret_pk_list, unsigned use )
else {
int trustlevel;
rc = check_trust( pk, &trustlevel, NULL, NULL, NULL );
rc = check_trust( pk, &trustlevel, pk->namehash,
NULL, NULL );
if( rc ) {
log_error("error checking pk of `%s': %s\n",
answer, g10_errstr(rc) );
@ -849,7 +850,7 @@ build_pk_list( STRLIST remusr, PK_LIST *ret_pk_list, unsigned use )
else if( !(rc=check_pubkey_algo2(pk->pubkey_algo, use )) ) {
int trustlevel;
rc = check_trust( pk, &trustlevel, NULL, NULL, NULL );
rc = check_trust( pk, &trustlevel, pk->namehash, NULL, NULL );
if( rc ) {
free_public_key( pk ); pk = NULL;
log_error(_("%s: error checking key: %s\n"),

@ -63,10 +63,6 @@
#include "i18n.h"
#ifdef MKDIR_TAKES_ONE_ARG
# undef mkdir
# define mkdir(a,b) mkdir(a)
#endif
struct resource_table_struct {
@ -291,24 +287,13 @@ add_keyblock_resource( const char *url, int force, int secret )
*last_slash_in_filename = 0;
if( access(filename, F_OK) ) {
if( strlen(filename) >= 7
&& !strcmp(filename+strlen(filename)-7, "/.gnupg") ) {
if( mkdir(filename, S_IRUSR|S_IWUSR|S_IXUSR) )
{
log_error( _("%s: can't create directory: %s\n"),
filename, strerror(errno));
rc = G10ERR_OPEN_FILE;
goto leave;
}
else if( !opt.quiet )
log_info( _("%s: directory created\n"), filename );
copy_options_file( filename );
}
else
{
rc = G10ERR_OPEN_FILE;
goto leave;
}
/* on the first time we try to create the default homedir and
* in this case the process will be terminated, so that on the
* next invocation it can read the options file in on startup
*/
try_make_homedir( filename );
rc = G10ERR_OPEN_FILE;
goto leave;
}
*last_slash_in_filename = '/';

@ -40,11 +40,6 @@
#include "tdbio.h"
#ifdef MKDIR_TAKES_ONE_ARG
# undef mkdir
# define mkdir(a,b) mkdir(a)
#endif
/****************
* Yes, this is a very simple implementation. We should really
* use a page aligned buffer and read complete pages.
@ -439,17 +434,8 @@ tdbio_set_dbname( const char *new_dbname, int create )
assert(p);
*p = 0;
if( access( fname, F_OK ) ) {
if( strlen(fname) >= 7
&& !strcmp(fname+strlen(fname)-7, "/.gnupg" ) ) {
if( mkdir( fname, S_IRUSR|S_IWUSR|S_IXUSR ) )
log_fatal( _("%s: can't create directory: %s\n"),
fname, strerror(errno) );
else if( !opt.quiet )
log_info( _("%s: directory created\n"), fname );
copy_options_file( fname );
}
else
log_fatal( _("%s: directory does not exist!\n"), fname );
try_make_homedir( fname );
log_fatal( _("%s: directory does not exist!\n"), fname );
}
*p = '/';

@ -2664,7 +2664,7 @@ enum_cert_paths_print( void **context, FILE *fp,
/*
* Return an allocated buffer with the preference values for
* the key with LID and the userid which is identified by the
* HAMEHASH or the firstone if namehash is NULL. ret_n receives
* HAMEHASH or the first one if namehash is NULL. ret_n receives
* the length of the allocated buffer. Structure of the buffer is
* a repeated sequences of 2 bytes; where the first byte describes the
* type of the preference and the second one the value. The constants

@ -1,3 +1,7 @@
Sat Dec 4 12:30:28 CET 1999 Werner Koch <wk@gnupg.de>
* iobuf.h (IOBUFCTRL_CANCEL): Nww.
Mon Oct 4 21:23:04 CEST 1999 Werner Koch <wk@gnupg.de>
* errors.h (G10ERR_NOT_PROCESSED): New.

@ -32,6 +32,7 @@
#define IOBUFCTRL_UNDERFLOW 3
#define IOBUFCTRL_FLUSH 4
#define IOBUFCTRL_DESC 5
#define IOBUFCTRL_CANCEL 6
#define IOBUFCTRL_USER 16
typedef struct iobuf_struct *IOBUF;

@ -49,4 +49,3 @@ g10/seskey.c
g10/delkey.c
g10/helptext.c
#---end--

@ -1,3 +1,8 @@
Sat Dec 4 12:30:28 CET 1999 Werner Koch <wk@gnupg.de>
* iobuf.c (iobuf_cancel): Broadcast the new Cancel mesaage to all
filters.
Mon Nov 22 11:14:53 CET 1999 Werner Koch <wk@gnupg.de>
* strgutil.c (strcasecmp): New.

@ -80,6 +80,8 @@ static int underflow(IOBUF a);
* IOBUFCTRL_FLUSH: called by iobuf_flush() to write out the collected stuff.
* *RET_LAN is the number of bytes in BUF.
*
* IOBUFCTRL_CANCEL: send to all filters on behalf of iobuf_cancel. The
* filter may take appropriate action on this message.
*/
static int
file_filter(void *opaque, int control, IOBUF chain, byte *buf, size_t *ret_len)
@ -497,12 +499,22 @@ int
iobuf_cancel( IOBUF a )
{
const char *s;
IOBUF a2;
if( a && a->use == 2 ) {
s = iobuf_get_real_fname(a);
if( s && *s )
remove(s); /* remove the file. Fixme: this will fail for MSDOZE*/
} /* because the file is still open */
/* send a cancel message to all filters */
for( a2 = a; a2 ; a2 = a2->chain ) {
size_t dummy;
if( a2->filter )
a2->filter( a2->filter_ov, IOBUFCTRL_CANCEL, a2->chain,
NULL, &dummy );
}
return iobuf_close(a);
}