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