Snapshot release 0.4.2
[gnupg.git] / util / dotlock.c
1 /* dotlock.c - dotfile locking
2  *      Copyright (C) 1998 Free Software Foundation, Inc.
3  *
4  * This file is part of GNUPG.
5  *
6  * GNUPG is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * GNUPG is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19  */
20
21 #include <config.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <errno.h>
25 #include <ctype.h>
26 #include "types.h"
27 #include "util.h"
28 #include "memory.h"
29
30
31
32
33 #if 0
34 /****************
35  * Create a lockfile with the given name. A TIMEOUT of 0
36  * returns immediately, -1 waits forever (hopefully not), other
37  * values are timeouts in milliseconds.
38  * Returns: a char pointer used as handle for release lock
39  *          or NULL in case of an error.
40  *
41  * Notes: This function creates a lock file in the same directory
42  *        as file_to_lock with the name "file_to_lock.lock"
43  *        A temporary file ".#lk.<pid>.<hostname> is used.
44  *        This function does nothing for Windoze.
45  */
46 const char *
47 make_dotlock( const char *file_to_lock, long timeout )
48 {
49     int rc=-1, fd=-1, pid;
50     char pidstr[16];
51     char *tname = NULL;
52     char *p;
53
54     log_debug("dotlock_make: lock='%s'\n", lockfile );
55     sprintf( pidstr, "%10d\n", getpid() );
56     /* add the hostname to the second line (FQDN or IP addr?) */
57
58     /* create a temporary file */
59     tname = CreateTmpFile2( p, ".#lk" );
60     free(p);
61     if( !tname )
62         log_fatal( "could not create temporary lock file '%s'\n");
63     log_debug( "dotlock_make: tmpname='%s'\n", tname );
64     chmod( tname, 0644 ); /* just in case an umask is set */
65     if( !(fd = open( tname, O_WRONLY )) )
66         log_fatal( "could not open temporary lock file '%s'\n", tname);
67     if( write(fd, pidstr, 11 ) != 11 )
68         log_fatal( "error writing to temporary lock file '%s'\n", tname);
69     if( close(fd) ) {
70         log_fatal( "error closing '%s'\n", tname);
71
72   retry:
73     if( !link(tname, lockfile) )
74         rc = 0; /* okay */
75     else if( errno != EEXIST )
76         log_error( "lock not made: link() failed: %s\n", strerror(errno) );
77     else { /* lock file already there */
78         if( (pid = read_lockfile(lockfile)) == -1 ) {
79             if( errno == ENOENT ) {
80                 log_debug( "lockfile disappeared\n");
81                 goto retry;
82             }
83             log_debug("cannot read lockfile\n");
84         }
85         else if( pid == getpid() ) {
86             log_info( "Oops: lock already hold by us\n");
87             rc = 0;  /* okay */
88         }
89         else if( kill(pid, 0) && errno == ESRCH ) {
90             log_info( "removing stale lockfile (created by %d)", (int)pid );
91             remove( lockfile );
92             goto retry;
93         }
94         log_debug( "lock not made: lock file exists\n" );
95     }
96
97     if( tname ) {
98         remove(tname);
99         free(tname);
100     }
101     if( !rc )
102         log_debug( "lock made\n");
103     return rc;
104 }
105
106 /****************
107  * Create a lockfile for a existing file
108  * Returns: a char pointer used as handle for release lock
109  *          or NULL in case of an error.
110  *
111  * Notes: This function creates a lock file in the same directory
112  *        as file_to_lock with the name "lock.<inode-no>"
113  *
114  * int
115  * make_inodelock( const char *file_to_lock )
116  *
117  */
118
119
120
121
122 /****************
123  * release a lock
124  * Returns: 0 := success
125  */
126 int
127 release_dotlock( const char *lockfile )
128 {
129     int pid = rad_lockfile( lockfile );
130     if( pid == -1 ) {
131         log_error( "release_dotlock: lockfile error");
132         return -1;
133     }
134     if( pid != getpid() ) {
135         log_error( "release_dotlock: not our lock (pid=%d)", pid);
136         return -1;
137     }
138     if( remove( lockfile ) ) {
139         log_error( "release_dotlock: error removing lockfile '%s'",
140                                                             lockfile);
141         return -1;
142     }
143     log_debug( "release_dotlock: released lockfile '%s'", lockfile);
144     return 0;
145 }
146
147
148 /****************
149  * Read the lock file and return the pid, returns -1 on error.
150  */
151 static int
152 read_lockfile( const char *name )
153 {
154     int fd, pid;
155     char pidstr[16];
156
157     if( (fd = open(name, O_RDONLY)) == -1 ) {
158         int e = errno;
159         log_debug("error opening lockfile '%s'", name );
160         errno = e;
161         return -1;
162     }
163     if( read(fd, pidstr, 10 ) != 10 ) {
164         log_debug("error reading lockfile '%s'", name );
165         close(fd);
166         errno = 0;
167         return -1;
168     }
169     close(fd);
170     pid = atoi(pidstr);
171     if( !pid || pid == -1 ) {
172         log_error("invalid pid %d in lockfile '%s'", pid, name );
173         errno = 0;
174         return -1;
175     }
176     return pid;
177 }
178 #endif