Line data Source code
1 : #include "burp.h"
2 : #include "alloc.h"
3 : #include "lock.h"
4 : #include "log.h"
5 :
6 13 : struct lock *lock_alloc(void)
7 : {
8 370 : return (struct lock *)calloc_w(1, sizeof(struct lock), __func__);
9 : }
10 :
11 371 : int lock_init(struct lock *lock, const char *path)
12 : {
13 371 : free_w(&lock->path);
14 371 : if(!(lock->path=strdup_w(path, __func__)))
15 : return -1;
16 371 : return 0;
17 : }
18 :
19 357 : struct lock *lock_alloc_and_init(const char *path)
20 : {
21 : struct lock *lock;
22 357 : if(!(lock=lock_alloc()) || lock_init(lock, path))
23 0 : lock_free(&lock);
24 357 : return lock;
25 : }
26 :
27 : static void lock_free_content(struct lock *lock)
28 : {
29 370 : free_w(&lock->path);
30 : }
31 :
32 371 : void lock_free(struct lock **lock)
33 : {
34 742 : if(!lock || !*lock) return;
35 370 : lock_free_content(*lock);
36 370 : free_v((void **)lock);
37 : }
38 :
39 66 : 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 66 : char text[64]="";
47 :
48 132 : 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 66 : if(lockf(lock->fd, F_TLOCK, 0))
55 : {
56 4 : 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 62 : snprintf(text, sizeof(text), "%d\n%s\n", (int)getpid(), progname());
63 62 : 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 62 : lock->status=GET_LOCK_GOT;
69 62 : return;
70 : error:
71 0 : lock->status=GET_LOCK_ERROR;
72 0 : return;
73 : notgot:
74 4 : lock->status=GET_LOCK_NOT_GOT;
75 4 : return;
76 : #endif
77 : }
78 :
79 : // Return 0 for lock got, 1 for lock not got, -1 for error.
80 46 : 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 46 : char *cp=NULL;
88 46 : char *copy=NULL;
89 :
90 : // Try to make sure the lock directory exists.
91 46 : if(!(copy=strdup_w(lock->path, __func__)))
92 : {
93 0 : lock->status=GET_LOCK_ERROR;
94 0 : return;
95 : }
96 92 : if((cp=strrchr(copy, '/')))
97 : {
98 46 : *cp='\0';
99 46 : if(*copy) mkdir(copy, 0777);
100 : }
101 46 : free_w(©);
102 :
103 46 : lock_get_quick(lock);
104 :
105 : // Try to make sure the pid gets onto the disk.
106 46 : if(lock->status==GET_LOCK_GOT) fsync(lock->fd);
107 : return;
108 : #endif
109 : }
110 :
111 10 : 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 10 : int r=0;
118 : int fdlock;
119 :
120 10 : if((fdlock=open(path, O_WRONLY, 0666))<0)
121 : return 0; // file does not exist - could have got the lock
122 7 : errno=0;
123 7 : if((r=lockf(fdlock, F_TLOCK, 0)) && (errno==EAGAIN || errno==EACCES))
124 : {
125 : // could not have got the lock
126 3 : close(fdlock);
127 3 : return -1;
128 : }
129 4 : close(fdlock);
130 : // could have got the lock
131 4 : return 0;
132 : #endif
133 : }
134 :
135 63 : int lock_release(struct lock *lock)
136 : {
137 63 : int ret=0;
138 63 : if(!lock || lock->status!=GET_LOCK_GOT) return 0;
139 60 : if(lock->path) unlink(lock->path);
140 60 : if(lock->fd>=0)
141 : {
142 60 : if((ret=close(lock->fd)))
143 : logp("Could not close %s: %s\n",
144 0 : lock->path, strerror(errno));
145 60 : lock->fd=-1;
146 : }
147 60 : lock->status=GET_LOCK_NOT_GOT;
148 60 : 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 7 : 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 : }
|