Forgot to commit this:
[gnupg.git] / util / dotlock.c
index 18841ec..fac8254 100644 (file)
@@ -1,5 +1,5 @@
 /* dotlock.c - dotfile locking
- *     Copyright (C) 1998 Free Software Foundation, Inc.
+ *     Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
  *
  * This file is part of GnuPG.
  *
@@ -25,7 +25,7 @@
 #include <ctype.h>
 #include <errno.h>
 #include <unistd.h>
-#ifndef  HAVE_DOSISH_SYSTEM
+#if !defined (HAVE_DOSISH_SYSTEM)
 #include <sys/utsname.h>
 #endif
 #include <sys/types.h>
@@ -42,13 +42,20 @@ struct dotlock_handle {
     char *tname;    /* name of lockfile template */
     char *lockname; /* name of the real lockfile */
     int locked;     /* lock status */
+    int disable;    /* locking */
 };
 
 
-static DOTLOCK all_lockfiles;
+static volatile DOTLOCK all_lockfiles;
+static int never_lock;
 
 static int read_lockfile( const char *name );
-static void remove_lockfiles(void);
+
+void
+disable_dotlock(void)
+{
+    never_lock = 1;
+}
 
 /****************
  * Create a lockfile with the given name and return an object of
@@ -73,8 +80,8 @@ create_dotlock( const char *file_to_lock )
     DOTLOCK h;
     int  fd = -1;
     char pidstr[16];
-  #ifndef  HAVE_DOSISH_SYSTEM
-    struct utsname uts;
+  #if !defined (HAVE_DOSISH_SYSTEM)
+    struct utsname utsbuf;
   #endif
     const char *nodename;
     const char *dirpart;
@@ -88,18 +95,38 @@ create_dotlock( const char *file_to_lock )
        return NULL;
 
     h = m_alloc_clear( sizeof *h );
-#ifndef HAVE_DOSISH_SYSTEM
+    if( never_lock ) {
+       h->disable = 1;
+      #ifdef _REENTRANT
+       /* fixme: aquire mutex on all_lockfiles */
+      #endif
+       h->next = all_lockfiles;
+       all_lockfiles = h;
+       return h;
+    }
+
+
+#if !defined (HAVE_DOSISH_SYSTEM)
     sprintf( pidstr, "%10d\n", (int)getpid() );
     /* fixme: add the hostname to the second line (FQDN or IP addr?) */
 
     /* create a temporary file */
-    if( uname( &uts ) )
+    if( uname( &utsbuf ) )
        nodename = "unknown";
     else
-       nodename = uts.nodename;
+       nodename = utsbuf.nodename;
+
+#ifdef __riscos__
+    {
+        char *iter = (char *) nodename;
+        for (; iter[0]; iter++)
+            if (iter[0] == '.')
+                iter[0] = '/';
+    }
+#endif /* __riscos__ */
 
-    if( !(dirpart = strrchr( file_to_lock, '/' )) ) {
-       dirpart = ".";
+    if( !(dirpart = strrchr( file_to_lock, DIRSEP_C )) ) {
+       dirpart = EXTSEP_S;
        dirpartlen = 1;
     }
     else {
@@ -114,8 +141,13 @@ create_dotlock( const char *file_to_lock )
     all_lockfiles = h;
 
     h->tname = m_alloc( dirpartlen + 6+30+ strlen(nodename) + 11 );
+#ifndef __riscos__
     sprintf( h->tname, "%.*s/.#lk%p.%s.%d",
             dirpartlen, dirpart, h, nodename, (int)getpid() );
+#else /* __riscos__ */
+    sprintf( h->tname, "%.*s.lk%p/%s/%d",
+            dirpartlen, dirpart, h, nodename, (int)getpid() );
+#endif /* __riscos__ */
 
     do {
        errno = 0;
@@ -123,6 +155,7 @@ create_dotlock( const char *file_to_lock )
                          S_IRUSR|S_IRGRP|S_IROTH|S_IWUSR );
     } while( fd == -1 && errno == EINTR );
     if( fd == -1 ) {
+       all_lockfiles = h->next;
        log_error( "failed to create temporary file `%s': %s\n",
                                            h->tname, strerror(errno));
        m_free(h->tname);
@@ -156,9 +189,9 @@ create_dotlock( const char *file_to_lock )
   #ifdef _REENTRANT
     /* release mutex */
   #endif
-#endif /* !HAVE_DOSISH_SYSTEM */
+#endif
     h->lockname = m_alloc( strlen(file_to_lock) + 6 );
-    strcpy(stpcpy(h->lockname, file_to_lock), ".lock");
+    strcpy(stpcpy(h->lockname, file_to_lock), EXTSEP_S "lock");
     return h;
 }
 
@@ -183,19 +216,26 @@ maybe_deadlock( DOTLOCK h )
 int
 make_dotlock( DOTLOCK h, long timeout )
 {
-#ifdef HAVE_DOSISH_SYSTEM
+#if defined (HAVE_DOSISH_SYSTEM)
     return 0;
 #else
     int  pid;
     const char *maybe_dead="";
     int backoff=0;
 
+    if( h->disable ) {
+       return 0;
+    }
+
     if( h->locked ) {
+#ifndef __riscos__
        log_debug("oops, `%s' is already locked\n", h->lockname );
+#endif /* !__riscos__ */
        return 0;
     }
 
     for(;;) {
+#ifndef __riscos__
        if( !link(h->tname, h->lockname) ) {
            /* fixme: better use stat to check the link count */
            h->locked = 1;
@@ -205,6 +245,16 @@ make_dotlock( DOTLOCK h, long timeout )
            log_error( "lock not made: link() failed: %s\n", strerror(errno) );
            return -1;
        }
+#else /* __riscos__ */
+        if( !renamefile(h->tname, h->lockname) ) {
+            h->locked = 1;
+            return 0; /* okay */
+        }
+        if( errno != EEXIST ) {
+           log_error( "lock not made: rename() failed: %s\n", strerror(errno) );
+           return -1;
+        }
+#endif /* __riscos__ */
        if( (pid = read_lockfile(h->lockname)) == -1 ) {
            if( errno != ENOENT ) {
                log_info("cannot read lockfile\n");
@@ -214,20 +264,27 @@ make_dotlock( DOTLOCK h, long timeout )
            continue;
        }
        else if( pid == getpid() ) {
-           log_info( "Oops: lock already hold by us\n");
+           log_info( "Oops: lock already held by us\n");
            h->locked = 1;
            return 0; /* okay */
        }
        else if( kill(pid, 0) && errno == ESRCH ) {
+#ifndef __riscos__
            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 );
         #endif
+#else /* __riscos__ */
+            /* we are *pretty* sure that the other task is dead and therefore
+               we remove the other lock file */
+            maybe_dead = " - probably dead - removing lock";
+            unlink(h->lockname);
+#endif /* __riscos__ */
        }
        if( timeout == -1 ) {
            struct timeval tv;
-           log_info( "waiting for lock (hold by %d%s) %s...\n",
+           log_info( "waiting for lock (held by %d%s) %s...\n",
                      pid, maybe_dead, maybe_deadlock(h)? "(deadlock?) ":"");
 
 
@@ -242,7 +299,7 @@ make_dotlock( DOTLOCK h, long timeout )
            return -1;
     }
     /*not reached */
-#endif /* !HAVE_DOSISH_SYSTEM */
+#endif
 }
 
 
@@ -253,11 +310,15 @@ make_dotlock( DOTLOCK h, long timeout )
 int
 release_dotlock( DOTLOCK h )
 {
-#ifdef HAVE_DOSISH_SYSTEM
+#if defined (HAVE_DOSISH_SYSTEM)
     return 0;
 #else
     int pid;
 
+    if( h->disable ) {
+       return 0;
+    }
+
     if( !h->locked ) {
        log_debug("oops, `%s' is not locked\n", h->lockname );
        return 0;
@@ -272,15 +333,23 @@ release_dotlock( DOTLOCK h )
        log_error( "release_dotlock: not our lock (pid=%d)\n", pid);
        return -1;
     }
+#ifndef __riscos__
     if( unlink( h->lockname ) ) {
        log_error( "release_dotlock: error removing lockfile `%s'",
                                                        h->lockname);
        return -1;
     }
+#else /* __riscos__ */
+    if( renamefile(h->lockname, h->tname) ) {
+       log_error( "release_dotlock: error renaming lockfile `%s' to `%s'",
+                                                       h->lockname, h->tname);
+       return -1;
+    }
+#endif /* __riscos__ */
     /* fixme: check that the link count is now 1 */
     h->locked = 0;
     return 0;
-#endif /* !HAVE_DOSISH_SYSTEM */
+#endif
 }
 
 
@@ -290,7 +359,7 @@ release_dotlock( DOTLOCK h )
 static int
 read_lockfile( const char *name )
 {
-  #ifdef HAVE_DOSISH_SYSTEM
+  #if defined (HAVE_DOSISH_SYSTEM)
     return 0;
   #else
     int fd, pid;
@@ -311,7 +380,11 @@ read_lockfile( const char *name )
     pidstr[10] = 0;  /* terminate pid string */
     close(fd);
     pid = atoi(pidstr);
+#ifndef __riscos__
     if( !pid || pid == -1 ) {
+#else /* __riscos__ */
+    if( (!pid && riscos_getpid()) || pid == -1 ) {
+#endif /* __riscos__ */
        log_error("invalid pid %d in lockfile `%s'", pid, name );
        errno = 0;
        return -1;
@@ -321,10 +394,10 @@ read_lockfile( const char *name )
 }
 
 
-static void
+void
 remove_lockfiles()
 {
-  #ifndef HAVE_DOSISH_SYSTEM
+  #if !defined (HAVE_DOSISH_SYSTEM)
     DOTLOCK h, h2;
 
     h = all_lockfiles;
@@ -332,11 +405,13 @@ remove_lockfiles()
 
     while( h ) {
        h2 = h->next;
-       if( h->locked )
-           unlink( h->lockname );
-       unlink(h->tname);
-       m_free(h->tname);
-       m_free(h->lockname);
+       if( !h->disable ) {
+           if( h->locked )
+               unlink( h->lockname );
+           unlink(h->tname);
+           m_free(h->tname);
+           m_free(h->lockname);
+       }
        m_free(h);
        h = h2;
     }