Line data Source code
1 : #include "burp.h"
2 : #include "alloc.h"
3 : #include "lock.h"
4 : #include "log.h"
5 :
6 17 : struct lock *lock_alloc(void)
7 : {
8 447 : return (struct lock *)calloc_w(1, sizeof(struct lock), __func__);
9 : }
10 :
11 448 : int lock_init(struct lock *lock, const char *path)
12 : {
13 448 : free_w(&lock->path);
14 448 : if(!(lock->path=strdup_w(path, __func__)))
15 : return -1;
16 448 : return 0;
17 : }
18 :
19 430 : struct lock *lock_alloc_and_init(const char *path)
20 : {
21 : struct lock *lock;
22 430 : if(!(lock=lock_alloc()) || lock_init(lock, path))
23 0 : lock_free(&lock);
24 430 : return lock;
25 : }
26 :
27 : static void lock_free_content(struct lock *lock)
28 : {
29 446 : free_w(&lock->path);
30 : }
31 :
32 455 : void lock_free(struct lock **lock)
33 : {
34 910 : if(!lock || !*lock) return;
35 446 : lock_free_content(*lock);
36 446 : free_v((void **)lock);
37 : }
38 :
39 102 : void lock_get_quick(struct lock *lock)
40 : {
41 : #if defined(HAVE_WIN32) || !defined(HAVE_LOCKF)
42 : // Would somebody please tell me how to get a lock on Windows?!
43 : lock->status=GET_LOCK_GOT;
44 : return;
45 : #else
46 204 : if((lock->fd=open(lock->path, O_WRONLY|O_CREAT, 0666))<0)
47 : {
48 0 : logp("Could not open lock file %s: %s\n",
49 0 : lock->path, strerror(errno));
50 0 : goto error;
51 : }
52 102 : if(lockf(lock->fd, F_TLOCK, 0))
53 : {
54 2 : if(errno==EACCES || errno==EAGAIN)
55 : goto notgot;
56 0 : logp("Could not get lock %s: %s\n",
57 : lock->path, strerror(errno));
58 0 : goto error; // Some other error.
59 : }
60 100 : if(lock_write_pid_and_prog(lock))
61 : goto error;
62 :
63 100 : lock->status=GET_LOCK_GOT;
64 100 : return;
65 : error:
66 0 : lock->status=GET_LOCK_ERROR;
67 0 : return;
68 : notgot:
69 2 : lock->status=GET_LOCK_NOT_GOT;
70 2 : return;
71 : #endif
72 : }
73 :
74 100 : int lock_write_pid_and_prog(struct lock *lock)
75 : {
76 100 : char text[64]="";
77 100 : if(ftruncate(lock->fd, 0))
78 : {
79 0 : logp("Could not ftruncate lock %s: %s\n",
80 0 : lock->path, strerror(errno));
81 0 : return -1;
82 : }
83 100 : if(lseek(lock->fd, 0, SEEK_SET)<0)
84 : {
85 0 : logp("Could not seek to start of lock %s: %s\n",
86 0 : lock->path, strerror(errno));
87 0 : return -1;
88 : }
89 100 : snprintf(text, sizeof(text), "%d\n%s\n", (int)getpid(), progname());
90 100 : if(write(lock->fd, text, strlen(text))!=(ssize_t)strlen(text))
91 : {
92 0 : logp("Could not write pid/progname to %s: %s\n",
93 0 : lock->path, strerror(errno));
94 0 : return -1;
95 : }
96 : return 0;
97 : }
98 :
99 : // Return 0 for lock got, 1 for lock not got, -1 for error.
100 81 : void lock_get(struct lock *lock)
101 : {
102 : #if defined(HAVE_WIN32) || !defined(HAVE_LOCKF)
103 : // Would somebody please tell me how to get a lock on Windows?!
104 : lock->status=GET_LOCK_GOT;
105 : return;
106 : #else
107 81 : char *cp=NULL;
108 81 : char *copy=NULL;
109 :
110 : // Try to make sure the lock directory exists.
111 81 : if(!(copy=strdup_w(lock->path, __func__)))
112 : {
113 0 : lock->status=GET_LOCK_ERROR;
114 0 : return;
115 : }
116 81 : if((cp=strrchr(copy, '/')))
117 : {
118 81 : *cp='\0';
119 81 : if(*copy) mkdir(copy, 0777);
120 : }
121 81 : free_w(©);
122 :
123 81 : lock_get_quick(lock);
124 :
125 : // Try to make sure the pid gets onto the disk.
126 81 : if(lock->status==GET_LOCK_GOT) fsync(lock->fd);
127 : return;
128 : #endif
129 : }
130 :
131 11 : int lock_test(const char *path)
132 : {
133 : #if defined(HAVE_WIN32) || !defined(HAVE_LOCKF)
134 : // Would somebody please tell me how to test a lock on Windows?!
135 : return 0;
136 : #else
137 11 : int r=0;
138 : int fdlock;
139 :
140 11 : if((fdlock=open(path, O_WRONLY, 0666))<0)
141 : return 0; // file does not exist - could have got the lock
142 2 : errno=0;
143 2 : if((r=lockf(fdlock, F_TLOCK, 0)) && (errno==EAGAIN || errno==EACCES))
144 : {
145 : // could not have got the lock
146 1 : close(fdlock);
147 1 : return -1;
148 : }
149 1 : close(fdlock);
150 : // could have got the lock
151 1 : return 0;
152 : #endif
153 : }
154 :
155 118 : int lock_release(struct lock *lock)
156 : {
157 118 : int ret=0;
158 118 : if(!lock || lock->status!=GET_LOCK_GOT) return 0;
159 99 : if(lock->path) unlink(lock->path);
160 99 : if(lock->fd>=0)
161 : {
162 99 : if((ret=close(lock->fd)))
163 0 : logp("Could not close %s: %s\n",
164 0 : lock->path, strerror(errno));
165 99 : lock->fd=-1;
166 : }
167 99 : lock->status=GET_LOCK_NOT_GOT;
168 99 : return ret;
169 : }
170 :
171 3 : void lock_add_to_list(struct lock **locklist, struct lock *lock)
172 : {
173 3 : if(*locklist) lock->next=*locklist;
174 3 : *locklist=lock;
175 3 : }
176 :
177 4 : void locks_release_and_free(struct lock **locklist)
178 : {
179 : struct lock *l;
180 : struct lock *head;
181 7 : if(!locklist) return;
182 1 : head=*locklist;
183 5 : while(head)
184 : {
185 3 : l=head;
186 3 : head=head->next;
187 3 : lock_release(l);
188 3 : lock_free(&l);
189 : }
190 1 : *locklist=NULL;
191 : }
|