auth-cleanup-20070208
[openafs.git] / src / budb / db_lock.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  * 
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 #include <afsconfig.h>
11 #include <afs/param.h>
12
13 RCSID
14     ("$Header$");
15
16 #include <sys/types.h>
17 #ifdef AFS_NT40_ENV
18 #include <winsock2.h>
19 #else
20 #include <netinet/in.h>
21 #include <sys/time.h>
22 #endif
23 #include <afs/afsutil.h>
24 #include <ubik.h>
25 #include <afs/bubasics.h>
26 #include "budb_errs.h"
27 #include "database.h"
28 #include "error_macros.h"
29 #include "afs/audit.h"
30
31 #define DBH_POS(ptr)            ( (char *) (ptr) - (char *) &db.h )
32
33 afs_int32 FreeAllLocks(), FreeLock(), GetInstanceId(), GetLock();
34
35 afs_int32
36 SBUDB_FreeAllLocks(call, instanceId)
37      struct rx_call *call;
38      afs_uint32 instanceId;
39 {
40     afs_int32 code;
41
42     code = FreeAllLocks(call, instanceId);
43     osi_auditU(call, BUDB_FrALckEvent, code, AUD_END);
44     return code;
45 }
46
47 afs_int32
48 FreeAllLocks(call, instanceId)
49      struct rx_call *call;
50      afs_uint32 instanceId;
51 {
52     db_lockP startPtr, endPtr;
53     struct ubik_trans *ut;
54     afs_int32 code;
55
56     if (callPermitted(call) == 0)
57         return (BUDB_NOTPERMITTED);
58
59     code = InitRPC(&ut, LOCKWRITE, 1);
60     if (code)
61         return (code);
62
63     startPtr = &db.h.textLocks[0];
64     endPtr = &db.h.textLocks[TB_NUM - 1];
65     while (startPtr <= endPtr) {
66         if ((ntohl(startPtr->lockState) == 1)
67             && (ntohl(startPtr->instanceId) == instanceId)
68             ) {
69             /* release the lock */
70             startPtr->lockState = 0;    /* unlock it */
71             startPtr->lockTime = 0;
72             startPtr->expires = 0;
73             startPtr->instanceId = 0;
74             dbwrite(ut, DBH_POS(startPtr), (char *)startPtr,
75                     sizeof(db_lockT));
76         }
77         startPtr++;
78     }
79     code = ubik_EndTrans(ut);
80     return (code);
81 }
82
83 afs_int32
84 SBUDB_FreeLock(call, lockHandle)
85      struct rx_call *call;
86      afs_uint32 lockHandle;
87 {
88     afs_int32 code;
89
90     code = FreeLock(call, lockHandle);
91     osi_auditU(call, BUDB_FreLckEvent, code, AUD_END);
92     return code;
93 }
94
95 afs_int32
96 FreeLock(call, lockHandle)
97      struct rx_call *call;
98      afs_uint32 lockHandle;
99 {
100     db_lockP lockPtr = 0;
101     struct ubik_trans *ut;
102     afs_int32 code;
103
104     if (callPermitted(call) == 0)
105         return (BUDB_NOTPERMITTED);
106
107     code = InitRPC(&ut, LOCKWRITE, 1);
108     if (code)
109         return (code);
110
111     if (checkLockHandle(ut, lockHandle) == 0)
112         ABORT(BUDB_BADARGUMENT);
113
114     lockPtr = &db.h.textLocks[lockHandle - 1];
115
116     lockPtr->lockState = 0;     /* unlock it */
117     lockPtr->lockTime = 0;
118     lockPtr->expires = 0;
119     lockPtr->instanceId = 0;
120     dbwrite(ut, DBH_POS(lockPtr), (char *)lockPtr, sizeof(db_lockT));
121
122     code = ubik_EndTrans(ut);
123     return (code);
124
125   abort_exit:
126     ubik_AbortTrans(ut);
127     return (code);
128 }
129
130 afs_int32
131 SBUDB_GetInstanceId(call, instanceId)
132      struct rx_call *call;
133      afs_uint32 *instanceId;
134 {
135     afs_int32 code;
136
137     code = GetInstanceId(call, instanceId);
138     osi_auditU(call, BUDB_GetIIdEvent, code, AUD_END);
139     return code;
140 }
141
142 afs_int32
143 GetInstanceId(call, instanceId)
144      struct rx_call *call;
145      afs_uint32 *instanceId;
146 {
147     struct ubik_trans *ut;
148     afs_int32 code;
149     afs_int32 instanceValue;
150
151     LogDebug(4, "GetInstanceId:\n");
152
153     /* *** Allow anyone to get the instance id ***
154      * if ( callPermitted(call) == 0 )
155      *    return(BUDB_NOTPERMITTED);
156      */
157
158     code = InitRPC(&ut, LOCKWRITE, 1);
159     if (code)
160         return (code);
161
162     instanceValue = ntohl(db.h.lastInstanceId) + 1;
163
164     set_header_word(ut, lastInstanceId, htonl(instanceValue));
165
166     code = ubik_EndTrans(ut);
167     return (code);
168 }
169
170
171 afs_int32
172 SBUDB_GetLock(call, instanceId, lockName, expiration, lockHandle)
173      struct rx_call *call;
174      afs_uint32 instanceId;
175      afs_int32 lockName;
176      afs_int32 expiration;
177      afs_uint32 *lockHandle;
178 {
179     afs_int32 code;
180
181     code = GetLock(call, instanceId, lockName, expiration, lockHandle);
182     osi_auditU(call, BUDB_GetLckEvent, code, AUD_END);
183     return code;
184 }
185
186 afs_int32
187 GetLock(call, instanceId, lockName, expiration, lockHandle)
188      struct rx_call *call;
189      afs_uint32 instanceId;
190      afs_int32 lockName;
191      afs_int32 expiration;
192      afs_uint32 *lockHandle;
193 {
194     struct timeval tv;
195     db_lockP lockPtr;
196     struct ubik_trans *ut;
197
198     afs_int32 code;
199
200     if (callPermitted(call) == 0)
201         return (BUDB_NOTPERMITTED);
202
203     if ((lockName < 0) || (lockName >= TB_NUM))
204         return (BUDB_BADARGUMENT);
205
206     /* get the current time */
207     gettimeofday(&tv, 0);
208
209     code = InitRPC(&ut, LOCKWRITE, 1);
210     if (code)
211         return (code);
212
213     lockPtr = &db.h.textLocks[lockName];
214
215     if ((ntohl(lockPtr->lockState) != 0)        /* lock set */
216         &&(ntohl(lockPtr->expires) > tv.tv_sec) /* not expired */
217         ) {
218         if (ntohl(lockPtr->instanceId) == instanceId)
219             code = BUDB_SELFLOCKED;
220         else
221             code = BUDB_LOCKED;
222         goto abort_exit;
223     }
224
225     lockPtr->lockState = htonl(1);      /* lock it */
226     lockPtr->lockTime = htonl(tv.tv_sec);       /* when locked */
227     lockPtr->expires = htonl(tv.tv_sec + expiration);
228     lockPtr->instanceId = htonl(instanceId);
229     code = dbwrite(ut, DBH_POS(lockPtr), (char *)lockPtr, sizeof(db_lockT));
230     if (code)
231         ABORT(code);
232
233     *lockHandle = (afs_uint32) (lockName + 1);
234     code = ubik_EndTrans(ut);
235     return (code);
236
237   abort_exit:
238     ubik_AbortTrans(ut);
239     return (code);
240 }
241
242
243 /* checkLockHandle
244  * exit:
245  *      0 - if invalid handle
246  *      1 - if handle is valid
247  */
248
249 checkLockHandle(ut, lockHandle)
250      struct ubik_trans *ut;
251      afs_uint32 lockHandle;
252 {
253     return (((lockHandle > 0) && (lockHandle <= TB_NUM)) ? 1 : 0);
254 }