comparison lib/fsplib/lock.c @ 662:be9663e0be00

2005-1-16 Brian Masney <masneyb@gftp.org> * lib/fsplib/COPYING lib/fsplib/Makefile.am lib/fsplib/fsplib.c lib/fsplib/fsplib.h lib/fsplib/lock.c lib/fsplib/lock.h - added FSPLIB This library is written by Radim Kolar <hsn@netmag.cz> and was included with his permission
author masneyb
date Sun, 16 Jan 2005 16:12:13 +0000
parents
children 4029ab7f13e4
comparison
equal deleted inserted replaced
661:2e718fba351e 662:be9663e0be00
1 #include <string.h>
2 #include <stdio.h>
3 #include "lock.h"
4
5 /* ************ Locking functions ***************** */
6 #ifndef FSP_NOLOCKING
7
8 static char code_str[] =
9 "0123456789:_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
10
11 static void make_key_string( FSP_LOCK *lock,
12 unsigned long server_addr,
13 unsigned long server_port)
14 {
15 unsigned long v1, v2;
16 char *p;
17
18 strcpy(lock->key_string,FSP_KEY_PREFIX);
19 for(p = lock->key_string; *p; p++);
20 v1 = server_addr;
21 v2 = server_port;
22
23 *p++ = code_str[v1 & 0x3f]; v1 >>= 6;
24 *p++ = code_str[v1 & 0x3f]; v1 >>= 6;
25 *p++ = code_str[v1 & 0x3f]; v1 >>= 6;
26 v1 = v1 | (v2 << (32-3*6));
27 *p++ = code_str[v1 & 0x3f]; v1 >>= 6;
28 *p++ = code_str[v1 & 0x3f]; v1 >>= 6;
29 *p++ = code_str[v1 & 0x3f]; v1 >>= 6;
30 *p++ = code_str[v1 & 0x3f]; v1 >>= 6;
31 *p++ = code_str[v1 & 0x3f]; v1 >>= 6;
32 *p = 0;
33 }
34 #endif
35
36 /********************************************************************/
37 /******* For those systems that has SysV shared memory + semop ******/
38 /********************************************************************/
39 #ifdef FSP_USE_SHAREMEM_AND_SEMOP
40
41 #include <sys/types.h>
42 #include <sys/ipc.h>
43 #include <sys/shm.h>
44 #include <sys/sem.h>
45 #include <fcntl.h>
46 #include <sys/stat.h>
47 #include <unistd.h>
48
49 #ifdef _SEM_SEMUN_UNDEFINED
50 union semun
51 {
52 int val;
53 struct semid_ds *buf;
54 unsigned short int *array;
55 struct seminfo *__buf;
56 };
57 #endif
58
59 unsigned short client_get_key (FSP_LOCK *lock)
60 {
61 struct sembuf sem;
62 sem.sem_num = 0;
63 sem.sem_op = -1;
64 sem.sem_flg = SEM_UNDO;
65
66 if(semop(lock->lock_sem,&sem,1) == -1 )
67 {
68 perror("semop lock");
69 }
70 return(*lock->share_key);
71 }
72
73 void client_set_key (FSP_LOCK *lock,unsigned short key)
74 {
75 struct sembuf sem;
76
77 sem.sem_num = 0;
78 sem.sem_op = 1;
79 sem.sem_flg = SEM_UNDO;
80
81 *lock->share_key = key;
82 if(semop(lock->lock_sem,&sem,1) == -1) {
83 perror("semop unlock");
84 }
85 }
86
87 int client_init_key (FSP_LOCK *lock,
88 unsigned long server_addr,
89 unsigned short server_port)
90 {
91 mode_t omask;
92 key_t lock_key;
93 int fd;
94 union semun sun;
95 struct sembuf sem;
96
97 make_key_string(lock,server_addr,server_port);
98
99 omask = umask(0);
100 fd = open(lock->key_string,O_RDWR|O_CREAT,0666);
101 umask(omask);
102 close(fd);
103
104 if((lock_key = ftok(lock->key_string,238)) == -1) {
105 perror("ftok");
106 return -1;
107 }
108
109 if((lock->lock_shm = shmget(lock_key,2*sizeof(unsigned int),IPC_CREAT|0666)) == -1) {
110 perror("shmget");
111 return -1;
112 }
113
114 if(!(lock->share_key = (unsigned int *) shmat(lock->lock_shm,NULL,0))) {
115 perror("shmat");
116 return -1;
117 }
118
119 if((lock->lock_sem = semget(lock_key,0,0)) == -1) {
120 /* create a new semaphore and init it */
121 if((lock->lock_sem = semget(lock_key,2,IPC_CREAT|0666)) == -1) {
122 perror("semget");
123 return -1;
124 }
125 /* we need to init this semaphore */
126 sun.val=1;
127 if(semctl(lock->lock_sem,0,SETVAL,sun) == -1)
128 {
129 perror("semctl setval");
130 return -1;
131 }
132 }
133
134 /* increase in use counter */
135 sem.sem_num = 1;
136 sem.sem_op = 1;
137 sem.sem_flg = SEM_UNDO;
138
139 if(semop(lock->lock_sem,&sem,1) == -1) {
140 perror("semop incuse");
141 }
142
143 return 0;
144 }
145
146 void client_destroy_key(FSP_LOCK *lock)
147 {
148 int rc;
149 struct sembuf sem;
150
151 if (shmdt(lock->share_key) < 0)
152 {
153 perror("shmdt");
154 return;
155 }
156 /* check if we are only one process holding lock */
157 rc = semctl(lock->lock_sem,1,GETVAL);
158 if (rc == 1)
159 {
160 /* safe to destroy */
161 if (
162 (semctl(lock->lock_sem,0,IPC_RMID) < 0) ||
163 (shmctl(lock->lock_shm,IPC_RMID,NULL) < 0) ||
164 (unlink(lock->key_string) < 0) )
165 rc=0;/* ignore cleanup errors */
166 }
167 else
168 if(rc > 1)
169 {
170 /* we need to decrease sem. */
171 sem.sem_num = 1;
172 sem.sem_op = -1;
173 sem.sem_flg = SEM_UNDO;
174
175 if(semop(lock->lock_sem,&sem,1) == -1) {
176 perror("semop decuse");
177 }
178 }
179 }
180 #endif
181
182
183 /********************************************************************/
184 /******* For those who do not want to use locking *******************/
185 /********************************************************************/
186 #ifdef FSP_NOLOCKING
187
188 unsigned short client_get_key (FSP_LOCK *lock)
189 {
190 return lock->share_key;
191 }
192
193 void client_set_key (FSP_LOCK *lock,unsigned short key)
194 {
195 lock->share_key=key;
196 }
197
198 int client_init_key (FSP_LOCK *lock,
199 unsigned long server_addr,
200 unsigned short server_port)
201 {
202 return 0;
203 }
204
205 void client_destroy_key(FSP_LOCK *lock)
206 {
207 return;
208 }
209 #endif
210
211 /********************************************************************/
212 /******* For those systems that has lockf function call *************/
213 /********************************************************************/
214 #ifdef FSP_USE_LOCKF
215
216 #include <sys/stat.h>
217 #include <fcntl.h>
218 #include <unistd.h>
219
220 unsigned short client_get_key (FSP_LOCK *lock)
221 {
222 unsigned int okey;
223
224 if (lockf(lock->lock_fd, F_LOCK, sizeof(okey)) < 0)
225 {
226 perror("lockf");
227 }
228
229 if (read(lock->lock_fd, &okey, sizeof(okey)) < 0)
230 {
231 perror("readlk");
232 }
233
234 if (lseek(lock->lock_fd, 0L, 0) < 0)
235 {
236 perror("seek");
237 }
238
239 return(okey);
240 }
241
242 void client_set_key (FSP_LOCK *lock,unsigned short nkey)
243 {
244 unsigned int key;
245
246 key=nkey;
247
248 if (write(lock->lock_fd, &key, sizeof(key)) < 0)
249 {
250 perror("write");
251 }
252 if (lseek(lock->lock_fd, 0L, 0) < 0)
253 {
254 perror("seek");
255 }
256 if (lockf(lock->lock_fd, F_ULOCK, sizeof(key)) < 0)
257 {
258 perror("unlockf");
259 }
260 }
261
262 int client_init_key (FSP_LOCK *lock,
263 unsigned long server_addr,
264 unsigned short server_port)
265 {
266 mode_t omask;
267
268 make_key_string(lock,server_addr, server_port);
269
270 omask = umask(0);
271 lock->lock_fd = open(lock->key_string, O_RDWR | O_CREAT, 0666);
272 (void)umask(omask);
273
274 if(lock->lock_fd < 0)
275 return -1;
276 else
277 return 0;
278 }
279
280 void
281 client_destroy_key(FSP_LOCK *lock)
282 {
283 (void)close(lock->lock_fd);
284 }
285 #endif