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