diff options
Diffstat (limited to 'util')
-rw-r--r-- | util/ChangeLog | 22 | ||||
-rw-r--r-- | util/Makefile.am | 18 | ||||
-rw-r--r-- | util/argparse.c | 5 | ||||
-rw-r--r-- | util/iobuf.c | 132 |
4 files changed, 168 insertions, 9 deletions
diff --git a/util/ChangeLog b/util/ChangeLog index c693e3857..25034cfda 100644 --- a/util/ChangeLog +++ b/util/ChangeLog @@ -1,3 +1,13 @@ +2001-03-08 Werner Koch <[email protected]> + + * argparse.c (default_strusage): Changed year of printed copyright + to 2001. + + * iobuf.c (fd_cache_invalidate, fd_cache_close, fd_cache_open): New. + (direct_open): Invalidate the fd_cache for read access. + (file_filter): Cache the close here. + (iobuf_open): Use new my_fopen_ro macro to try the cache first. + 2001-03-07 Werner Koch <[email protected]> * iobuf.c: Made the old stdio file handling cpp conditional @@ -606,3 +616,15 @@ Fri Feb 13 15:14:13 1998 Werner Koch ([email protected]) * argparse.c (show_help): New '\v' kludge. + + Copyright 1998, 1999, 2000, 2001 Free Software Foundation, Inc. + + This file is free software; as a special exception the author gives + unlimited permission to copy and/or distribute it, with or without + modifications, as long as this notice is preserved. + + This file is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY, to the extent permitted by law; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + diff --git a/util/Makefile.am b/util/Makefile.am index 5870fb6a9..407595989 100644 --- a/util/Makefile.am +++ b/util/Makefile.am @@ -1,3 +1,21 @@ +# Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. +# +# This file is part of GnuPG. +# +# GnuPG is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# GnuPG is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + ## Process this file with automake to produce Makefile.in INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)/intl diff --git a/util/argparse.c b/util/argparse.c index 1fdc8d1bd..35144560a 100644 --- a/util/argparse.c +++ b/util/argparse.c @@ -1,5 +1,6 @@ /* [argparse.c wk 17.06.97] Argument Parser for option handling - * Copyright (C) 1998,1999 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. + * * This file is part of GnuPG. * * GnuPG is free software; you can redistribute it and/or modify @@ -898,7 +899,7 @@ default_strusage( int level ) switch( level ) { case 11: p = "foo"; break; case 13: p = "0.0"; break; - case 14: p = "Copyright (C) 2000 Free Software Foundation, Inc."; break; + case 14: p = "Copyright (C) 2001 Free Software Foundation, Inc."; break; case 15: p = "This program comes with ABSOLUTELY NO WARRANTY.\n" "This is free software, and you are welcome to redistribute it\n" diff --git a/util/iobuf.c b/util/iobuf.c index 5e46db272..ce4f93645 100644 --- a/util/iobuf.c +++ b/util/iobuf.c @@ -45,7 +45,8 @@ #ifdef FILE_FILTER_USES_STDIO #define my_fileno(a) fileno ((a)) - #define my_fopen(a,b) fopen ((a),(b)) + #define my_fopen_ro(a,b) fopen ((a),(b)) + #define my_fopen(a,b) fopen ((a),(b)) typedef FILE *FILEP_OR_FD; #define INVALID_FP NULL #define FILEP_OR_FD_FOR_STDIN (stdin) @@ -57,6 +58,7 @@ } file_filter_ctx_t ; #else #define my_fileno(a) (a) + #define my_fopen_ro(a,b) fd_cache_open ((a),(b)) #define my_fopen(a,b) direct_open ((a),(b)) #ifdef HAVE_DOSISH_SYSTEM typedef HANDLE FILEP_OR_FD; @@ -76,6 +78,14 @@ int print_only_name; /* flags indicating that fname is not a real file*/ char fname[1]; /* name of the file */ } file_filter_ctx_t ; + + struct close_cache_s { + struct close_cache_s *next; + FILEP_OR_FD fp; + char fname[1]; + }; + typedef struct close_cache_s *CLOSE_CACHE; + static CLOSE_CACHE close_cache; #endif @@ -101,6 +111,33 @@ static int special_names_enabled; static int underflow(IOBUF a); #ifndef FILE_FILTER_USES_STDIO + +/* + * Invalidate (i.e. close) a cached iobuf + */ +static void +fd_cache_invalidate (const char *fname) +{ + CLOSE_CACHE cc; + + assert (fname); + if( DBG_IOBUF ) + log_debug ("fd_cache_invalidate (%s)\n", fname); + + for (cc=close_cache; cc; cc = cc->next ) { + if ( cc->fp != INVALID_FP && !strcmp (cc->fname, fname) ) { + #ifdef HAVE_DOSISH_SYSTEM + CloseHandle (cc->fp); + #else + close(cc->fp); + #endif + cc->fp = INVALID_FP; + } + } +} + + + static FILEP_OR_FD direct_open (const char *fname, const char *mode) { @@ -115,11 +152,13 @@ direct_open (const char *fname, const char *mode) * something new for MS applications ;-) */ if ( strchr (mode, '+') ) { + fd_cache_invalidate (fname); da = GENERIC_READ|GENERIC_WRITE; cd = OPEN_EXISTING; sm = FILE_SHARE_READ | FILE_SHARE_WRITE; } else if ( strchr (mode, 'w') ) { + fd_cache_invalidate (fname); da = GENERIC_WRITE; cd = CREATE_ALWAYS; sm = FILE_SHARE_WRITE; @@ -137,15 +176,94 @@ direct_open (const char *fname, const char *mode) int cflag = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH; /* Note, that we do not handle all mode combinations */ - if ( strchr (mode, '+') ) + if ( strchr (mode, '+') ) { + fd_cache_invalidate (fname); oflag = O_RDWR; - else if ( strchr (mode, 'w') ) + } + else if ( strchr (mode, 'w') ) { + fd_cache_invalidate (fname); oflag = O_WRONLY | O_CREAT | O_TRUNC; - else + } + else { oflag = O_RDONLY; + } return open (fname, oflag, cflag ); #endif } + + +/* + * Instead of closing an FD we keep it open and cache it for later reuse + * Note that this caching strategy only works if the process does not chdir. + */ +static void +fd_cache_close (const char *fname, FILEP_OR_FD fp) +{ + CLOSE_CACHE cc; + + assert (fp); + if ( !fname || !*fname ) { +#ifdef HAVE_DOSISH_SYSTEM + CloseHandle (fp); +#else + close(fp); +#endif + if( DBG_IOBUF ) + log_debug ("fd_cache_close (%s) immediately\n", fname); + return; + } + /* try to reuse a slot */ + for (cc=close_cache; cc; cc = cc->next ) { + if ( cc->fp == INVALID_FP && !strcmp (cc->fname, fname) ) { + cc->fp = fp; + } + } + /* add a new one */ + if( DBG_IOBUF ) + log_debug ("fd_cache_close (%s) new\n", fname); + cc = m_alloc_clear (sizeof *cc + strlen (fname)); + strcpy (cc->fname, fname); + cc->fp = fp; + cc->next = close_cache; + close_cache = cc; +} + +/* + * Do an direct_open on FNAME but first try to reuse one from the fd_cache + */ +static FILEP_OR_FD +fd_cache_open (const char *fname, const char *mode) +{ + CLOSE_CACHE cc; + + assert (fname); + for (cc=close_cache; cc; cc = cc->next ) { + if ( cc->fp != INVALID_FP && !strcmp (cc->fname, fname) ) { + FILEP_OR_FD fp = cc->fp; + cc->fp = INVALID_FP; + if( DBG_IOBUF ) + log_debug ("fd_cache_open (%s) hit\n", fname); + #ifdef HAVE_DOSISH_SYSTEM + if (SetFilePointer (fp, 0, NULL, FILE_BEGIN) == 0xffffffff ) { + log_error ("rewind file failed on handle %p: ec=%d\n", + fp, (int)GetLastError () ); + fp = INVALID_FP; + } + #else + if ( lseek (fp, 0, SEEK_SET) == (off_t)-1 ) { + log_error("can't rewind fd %d: %s\n", fp, strerror(errno) ); + fp = INVALID_FP; + } + #endif + return fp; + } + } + if( DBG_IOBUF ) + log_debug ("fd_cache_open (%s) miss\n", fname); + return direct_open (fname, mode); +} + + #endif /*FILE_FILTER_USES_STDIO*/ @@ -334,13 +452,13 @@ file_filter(void *opaque, int control, IOBUF chain, byte *buf, size_t *ret_len) if ( f != FILEP_OR_FD_FOR_STDIN && f != FILEP_OR_FD_FOR_STDOUT ) { if( DBG_IOBUF ) log_debug("%s: close handle %p\n", a->fname, f ); - CloseHandle (f); + fd_cache_close (a->fname, f); } #else if ( (int)f != 0 && (int)f != 1 ) { if( DBG_IOBUF ) log_debug("%s: close fd %d\n", a->fname, f ); - close(f); + fd_cache_close (a->fname, f); } f = INVALID_FP; #endif @@ -825,7 +943,7 @@ iobuf_open( const char *fname ) } else if ( (fd = check_special_filename ( fname )) != -1 ) return iobuf_fdopen ( iobuf_translate_file_handle (fd,0), "rb" ); - else if( (fp = my_fopen(fname, "rb")) == INVALID_FP ) + else if( (fp = my_fopen_ro(fname, "rb")) == INVALID_FP ) return NULL; a = iobuf_alloc(1, 8192 ); fcx = m_alloc( sizeof *fcx + strlen(fname) ); |