diff options
author | Werner Koch <[email protected]> | 1999-02-10 16:22:40 +0000 |
---|---|---|
committer | Werner Koch <[email protected]> | 1999-02-10 16:22:40 +0000 |
commit | 9a4f506a18ed04f5dbd69d74ec0c35ade79e357a (patch) | |
tree | 07178f77cb23862b045b0edf8a2bc5ce188432cd /util | |
parent | See ChangeLog: Sun Jan 24 18:16:26 CET 1999 Werner Koch (diff) | |
download | gnupg-9a4f506a18ed04f5dbd69d74ec0c35ade79e357a.tar.gz gnupg-9a4f506a18ed04f5dbd69d74ec0c35ade79e357a.zip |
See ChangeLog: Wed Feb 10 17:15:39 CET 1999 Werner Koch
Diffstat (limited to 'util')
-rw-r--r-- | util/ChangeLog | 7 | ||||
-rw-r--r-- | util/dotlock.c | 261 | ||||
-rw-r--r-- | util/fileutil.c | 36 | ||||
-rw-r--r-- | util/iobuf.c | 8 | ||||
-rw-r--r-- | util/secmem.c | 10 | ||||
-rw-r--r-- | util/ttyio.c | 2 |
6 files changed, 218 insertions, 106 deletions
diff --git a/util/ChangeLog b/util/ChangeLog index 0c1597a51..a0a534603 100644 --- a/util/ChangeLog +++ b/util/ChangeLog @@ -1,3 +1,10 @@ +Wed Feb 10 17:15:39 CET 1999 Werner Koch <[email protected]> + + * dotlock.c (remove_lockfiles): Add cleanup function. + (make_dotlock): Add deadlock check. + + * secmem.c (secmem_malloc): Changed error message. + Wed Jan 20 21:40:21 CET 1999 Werner Koch <[email protected]> * http.c (http_wait_response): Moved the shutdown behind the dup diff --git a/util/dotlock.c b/util/dotlock.c index 71e6178b3..656454ee3 100644 --- a/util/dotlock.c +++ b/util/dotlock.c @@ -35,37 +35,56 @@ #include "util.h" #include "memory.h" +struct dotlock_handle { + struct dotlock_handle *next; + char *tname; /* name of lockfile template */ + char *lockname; /* name of the real lockfile */ + int locked; /* lock status */ +}; + + +static DOTLOCK all_lockfiles; static int read_lockfile( const char *name ); +static void remove_lockfiles(void); /**************** - * Create a lockfile with the given name. A TIMEOUT of 0 - * returns immediately, -1 waits forever (hopefully not), other - * values are timeouts in milliseconds. - * Returns: a char pointer used as handle for release lock - * or NULL in case of an error. + * Create a lockfile with the given name and return an object of + * type DOTLOCK which may be used later to actually do the lock. + * A cleanup routine gets installed to cleanup left over locks + * or other files used together with the lockmechanism. + * Althoug the function is called dotlock, this does not necessarily + * mean that real lockfiles are used - the function may decide to + * use fcntl locking. Calling the function with NULL only install + * the atexit handler and maybe used to assure that the cleanup + * is called after all other atexit handlers. * * Notes: This function creates a lock file in the same directory * as file_to_lock with the name "file_to_lock.lock" * A temporary file ".#lk.<hostname>.pid[.threadid] is used. * This function does nothing for Windoze. */ -const char * -make_dotlock( const char *file_to_lock, long timeout ) +DOTLOCK +create_dotlock( const char *file_to_lock ) { - int fd=-1, pid; + static int initialized; + DOTLOCK h; + int fd = -1; char pidstr[16]; - const char *handle = NULL; - char *lockname = NULL; - char *tname = NULL; - int have_tfile = 0; struct utsname uts; const char *nodename; const char *dirpart; int dirpartlen; - const char *maybe_dead=""; - int backoff=0; + if( !initialized ) { + atexit( remove_lockfiles ); + initialized = 1; + } + if( !file_to_lock ) + return NULL; + + h = m_alloc_clear( sizeof *h ); +#ifndef HAVE_DOSISH_SYSTEM sprintf( pidstr, "%10d\n", getpid() ); /* fixme: add the hostname to the second line (FQDN or IP addr?) */ @@ -84,131 +103,180 @@ make_dotlock( const char *file_to_lock, long timeout ) dirpart = file_to_lock; } - #ifdef _THREAD_SAFE - tname = m_alloc( dirpartlen + 6 + strlen(nodename) + 11+ 20 ); - sprintf( tname, "%.*s/.#lk.%s.%d.%p", - dirpartlen, dirpart, nodename, getpid(), &pid ); - #else - tname = m_alloc( dirpartlen + 6 + strlen(nodename) + 11 ); - sprintf( tname, "%.*s/.#lk.%s.%d", - dirpartlen, dirpart, nodename, getpid() ); + #ifdef _REENTRANT + /* fixme: aquire mutex on all_lockfiles */ #endif + h->next = all_lockfiles; + all_lockfiles = h; + + h->tname = m_alloc( dirpartlen + 6+30+ strlen(nodename) + 11 ); + sprintf( h->tname, "%.*s/.#lk%p.%s.%d", + dirpartlen, dirpart, h, nodename, (int)getpid() ); + do { errno = 0; - fd = open( tname, O_WRONLY|O_CREAT|O_EXCL, + fd = open( h->tname, O_WRONLY|O_CREAT|O_EXCL, S_IRUSR|S_IRGRP|S_IROTH|S_IWUSR ); } while( fd == -1 && errno == EINTR ); if( fd == -1 ) { log_error( "failed to create temporary file `%s': %s\n", - tname, strerror(errno)); - goto leave; + h->tname, strerror(errno)); + m_free(h->tname); + m_free(h); + return NULL; } - have_tfile = 1; if( write(fd, pidstr, 11 ) != 11 ) { - log_fatal( "error writing to `%s': %s\n", tname, strerror(errno) ); - goto leave; + all_lockfiles = h->next; + #ifdef _REENTRANT + /* release mutex */ + #endif + log_fatal( "error writing to `%s': %s\n", h->tname, strerror(errno) ); + close(fd); + unlink(h->tname); + m_free(h->tname); + m_free(h); + return NULL; } if( close(fd) ) { - log_error( "error closing `%s': %s\n", tname, strerror(errno)); - goto leave; + all_lockfiles = h->next; + #ifdef _REENTRANT + /* release mutex */ + #endif + log_error( "error closing `%s': %s\n", h->tname, strerror(errno)); + unlink(h->tname); + m_free(h->tname); + m_free(h); + return NULL; } - fd = -1; - lockname = m_alloc( strlen(file_to_lock) + 6 ); - strcpy(stpcpy(lockname, file_to_lock), ".lock"); + #ifdef _REENTRANT + /* release mutex */ + #endif +#endif /* !HAVE_DOSISH_SYSTEM */ + h->lockname = m_alloc( strlen(file_to_lock) + 6 ); + strcpy(stpcpy(h->lockname, file_to_lock), ".lock"); + return h; +} + +static int +maybe_deadlock( DOTLOCK h ) +{ + DOTLOCK r; - retry: - if( !link(tname, lockname) ) {/* fixme: better use stat to check the link count */ - handle = lockname; - lockname = NULL; + for( r=all_lockfiles; r; r = r->next ) { + if( r != h && r->locked ) + return 1; } - else if( errno == EEXIST ) { - if( (pid = read_lockfile(lockname)) == -1 ) { - if( errno == ENOENT ) { - log_info( "lockfile disappeared\n"); - goto retry; + return 0; +} + +/**************** + * Do a lock on H. A TIMEOUT of 0 returns immediately, + * -1 waits forever (hopefully not), other + * values are timeouts in milliseconds. + * Returns: 0 on success + */ +int +make_dotlock( DOTLOCK h, long timeout ) +{ +#ifdef HAVE_DOSISH_SYSTEM + return 0; +#else + int pid; + const char *maybe_dead=""; + int backoff=0; + + if( h->locked ) { + log_debug("oops, `%s' is already locked\n", h->lockname ); + return 0; + } + + for(;;) { + if( !link(h->tname, h->lockname) ) { + /* fixme: better use stat to check the link count */ + h->locked = 1; + return 0; /* okay */ + } + if( errno != EEXIST ) { + log_error( "lock not made: link() failed: %s\n", strerror(errno) ); + return -1; + } + if( (pid = read_lockfile(h->lockname)) == -1 ) { + if( errno != ENOENT ) { + log_info("cannot read lockfile\n"); + return -1; } - log_info("cannot read lockfile\n"); + log_info( "lockfile disappeared\n"); + continue; } else if( pid == getpid() ) { log_info( "Oops: lock already hold by us\n"); - handle = lockname; - lockname = NULL; + h->locked = 1; + return 0; /* okay */ } else if( kill(pid, 0) && errno == ESRCH ) { maybe_dead = " - probably dead"; #if 0 /* we should not do this without checking the permissions */ /* and the hostname */ log_info( "removing stale lockfile (created by %d)", pid ); - remove( lockname ); - goto retry; #endif } if( timeout == -1 ) { struct timeval tv; - log_info( "waiting for lock (hold by %d%s) ...\n", pid, maybe_dead ); + log_info( "waiting for lock (hold by %d%s) %s...\n", + pid, maybe_dead, maybe_deadlock(h)? "(deadlock?) ":""); + + /* can't use sleep, cause signals may be blocked */ tv.tv_sec = 1 + backoff; tv.tv_usec = 0; select(0, NULL, NULL, NULL, &tv); if( backoff < 10 ) backoff++ ; - goto retry; } - /* fixme: implement timeouts */ + else + return -1; } - else - log_error( "lock not made: link() failed: %s\n", strerror(errno) ); - - leave: - if( fd != -1 ) - close(fd); - if( have_tfile ) - remove(tname); - m_free(tname); - m_free(lockname); - return handle; + /*not reached */ +#endif /* !HAVE_DOSISH_SYSTEM */ } -/**************** - * Create a lockfile for a existing file - * Returns: a char pointer used as handle for release lock - * or NULL in case of an error. - * - * Notes: This function creates a lock file in the same directory - * as file_to_lock with the name "lock.<inode-no>" - * - * int - * make_inodelock( const char *file_to_lock ) - * - */ - - - /**************** * release a lock * Returns: 0 := success */ int -release_dotlock( const char *lockfile ) +release_dotlock( DOTLOCK h ) { - int pid = read_lockfile( lockfile ); +#ifdef HAVE_DOSISH_SYSTEM + return 0; +#else + int pid; + + if( !h->locked ) { + log_debug("oops, `%s' is not locked\n", h->lockname ); + return 0; + } + + pid = read_lockfile( h->lockname ); if( pid == -1 ) { - log_error( "release_dotlock: lockfile error"); + log_error( "release_dotlock: lockfile error\n"); return -1; } if( pid != getpid() ) { - log_error( "release_dotlock: not our lock (pid=%d)", pid); + log_error( "release_dotlock: not our lock (pid=%d)\n", pid); return -1; } - if( remove( lockfile ) ) { + if( unlink( h->lockname ) ) { log_error( "release_dotlock: error removing lockfile `%s'", - lockfile); + h->lockname); return -1; } - m_free( (char*)lockfile ); + /* fixme: check that the link count is now 1 */ + h->locked = 0; return 0; +#endif /* !HAVE_DOSISH_SYSTEM */ } @@ -218,6 +286,9 @@ release_dotlock( const char *lockfile ) static int read_lockfile( const char *name ) { + #ifdef HAVE_DOSISH_SYSTEM + return 0; + #else int fd, pid; char pidstr[16]; @@ -241,5 +312,29 @@ read_lockfile( const char *name ) return -1; } return pid; + #endif +} + + +static void +remove_lockfiles() +{ + #ifndef HAVE_DOSISH_SYSTEM + DOTLOCK h, h2; + + h = all_lockfiles; + all_lockfiles = NULL; + + while( h ) { + h2 = h->next; + if( h->locked ) + unlink( h->lockname ); + unlink(h->tname); + m_free(h->tname); + m_free(h->lockname); + m_free(h); + h = h2; + } + #endif } diff --git a/util/fileutil.c b/util/fileutil.c index adf5c7a5d..7910631c2 100644 --- a/util/fileutil.c +++ b/util/fileutil.c @@ -38,16 +38,16 @@ char * make_basename(const char *filepath) { char *p; - + if ( !(p=strrchr(filepath, '/')) ) - #ifdef __MINGW32__ - if ( !(p=strrchr(filepath, '\\')) ) - if ( !(p=strrchr(filepath, ':')) ) + #ifdef HAVE_DRIVE_LETTERS + if ( !(p=strrchr(filepath, '\\')) ) + if ( !(p=strrchr(filepath, ':')) ) #endif - { - return m_strdup(filepath); - } - + { + return m_strdup(filepath); + } + return m_strdup(p+1); } @@ -65,21 +65,21 @@ make_dirname(const char *filepath) char *dirname; int dirname_length; char *p; - + if ( !(p=strrchr(filepath, '/')) ) - #ifdef __MINGW32__ - if ( !(p=strrchr(filepath, '\\')) ) - if ( !(p=strrchr(filepath, ':')) ) + #ifdef HAVE_DRIVE_LETTERS + if ( !(p=strrchr(filepath, '\\')) ) + if ( !(p=strrchr(filepath, ':')) ) #endif - { - return m_strdup("."); - } - + { + return m_strdup("."); + } + dirname_length = p-filepath; dirname = m_alloc(dirname_length+1); strncpy(dirname, filepath, dirname_length); dirname[dirname_length] = 0; - + return dirname; } @@ -126,7 +126,7 @@ compare_filenames( const char *a, const char *b ) /* ? check whether this is an absolute filename and * resolve symlinks? */ - #ifdef __MINGW32__ + #ifdef HAVE_DRIVE_LETTERS return stricmp(a,b); #else return strcmp(a,b); diff --git a/util/iobuf.c b/util/iobuf.c index 9fba1fc0b..037d2cdc3 100644 --- a/util/iobuf.c +++ b/util/iobuf.c @@ -126,8 +126,11 @@ file_filter(void *opaque, int control, IOBUF chain, byte *buf, size_t *ret_len) *(char**)buf = "file_filter"; } else if( control == IOBUFCTRL_FREE ) { - if( fp != stdin && fp != stdout ) + if( fp != stdin && fp != stdout ) { + if( DBG_IOBUF ) + log_debug("%s: close fd %d\n", a->fname, fileno(fp) ); fclose(fp); + } fp = NULL; m_free(a); /* we can free our context now */ } @@ -545,7 +548,8 @@ iobuf_open( const char *fname ) file_filter( fcx, IOBUFCTRL_DESC, NULL, (byte*)&a->desc, &len ); file_filter( fcx, IOBUFCTRL_INIT, NULL, NULL, &len ); if( DBG_IOBUF ) - log_debug("iobuf-%d.%d: open `%s'\n", a->no, a->subno, fname ); + log_debug("iobuf-%d.%d: open `%s' fd=%d\n", + a->no, a->subno, fname, fileno(fcx->fp) ); return a; } diff --git a/util/secmem.c b/util/secmem.c index e9bc05abd..0aa4e9f61 100644 --- a/util/secmem.c +++ b/util/secmem.c @@ -217,7 +217,7 @@ void secmem_init( size_t n ) { if( !n ) { - #ifndef __MINGW32__ + #ifndef HAVE_DOSISH_SYSTEM uid_t uid; disable_secmem=1; @@ -245,8 +245,12 @@ secmem_malloc( size_t size ) MEMBLOCK *mb, *mb2; int compressed=0; - if( !pool_okay ) - log_bug("secmem not initialized\n"); + if( !pool_okay ) { + log_info( + _("operation is not possible without initialized secure memory\n")); + log_info(_("(you may have used the wrong program for this task)\n")); + exit(2); + } if( show_warning && !suspend_warning ) { show_warning = 0; print_warn(); diff --git a/util/ttyio.c b/util/ttyio.c index cfc8f4dac..e457949a0 100644 --- a/util/ttyio.c +++ b/util/ttyio.c @@ -105,6 +105,8 @@ init_ttyfp() SetConsoleMode(con.in, DEF_INPMODE ); SetConsoleMode(con.out, DEF_OUTMODE ); + #elif defined(__EMX__) + ttyfp = stdout; /* Fixme: replace by the real functions: see wklib */ #else ttyfp = fopen("/dev/tty", "r+"); if( !ttyfp ) |