File: | dviced/./../libacl/aclprocs.c |
Location: | line 313, column 5 |
Description: | Value stored to 'j' is never read |
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 | /* |
11 | Information Technology Center |
12 | Carnegie-Mellon University |
13 | */ |
14 | |
15 | |
16 | #include <afsconfig.h> |
17 | #include <afs/param.h> |
18 | |
19 | #include <roken.h> |
20 | |
21 | #include <rx/xdr.h> |
22 | #include <rx/rx.h> |
23 | #include <afs/ptclient.h> |
24 | #include <afs/ptuser.h> |
25 | |
26 | #include "acl.h" |
27 | |
28 | #ifdef AFS_PTHREAD_ENV1 |
29 | #include <assert.h> |
30 | #include <pthread.h> |
31 | pthread_mutex_t acl_list_mutex; |
32 | #endif /* AFS_PTHREAD_ENV */ |
33 | |
34 | struct freeListEntry { |
35 | struct freeListEntry *next; |
36 | int size; |
37 | char body[1]; |
38 | }; |
39 | |
40 | struct freeListEntry *freeList; |
41 | |
42 | static int AddToList(struct freeListEntry **, struct freeListEntry *); |
43 | static int GetFromList(struct freeListEntry **, struct freeListEntry **, |
44 | afs_int32); |
45 | |
46 | /*todo: for sorting acls - make sure they work with new groups lists 10/5*/ |
47 | static int |
48 | CmpPlus(const void *arg1, const void *arg2) |
49 | { |
50 | const struct acl_accessEntry *a = (struct acl_accessEntry *) arg1; |
51 | const struct acl_accessEntry *b = (struct acl_accessEntry *) arg2; |
52 | if (a->id < b->id) |
53 | return (-1); |
54 | if (a->id == b->id) |
55 | return (0); |
56 | return (1); |
57 | } |
58 | |
59 | static int |
60 | CmpMinus(const void *arg1, const void *arg2) |
61 | { |
62 | const struct acl_accessEntry *a = (struct acl_accessEntry *) arg1; |
63 | const struct acl_accessEntry *b = (struct acl_accessEntry *) arg2; |
64 | |
65 | if (a->id > b->id) |
66 | return (-1); |
67 | if (a->id == b->id) |
68 | return (0); |
69 | return (1); |
70 | } |
71 | |
72 | static int |
73 | CmpInt(int x, int y) |
74 | { |
75 | if (x < y) |
76 | return (-1); |
77 | if (x == y) |
78 | return (0); |
79 | return (1); |
80 | } |
81 | |
82 | |
83 | int |
84 | acl_NewACL(int nEntries, struct acl_accessList **acl) |
85 | { |
86 | /* Creates an access list capable of holding at least nEntries entries. |
87 | * Returns 0 on success; aborts if we run out of memory. */ |
88 | |
89 | int t; |
90 | struct freeListEntry *e; |
91 | |
92 | t = sizeof(struct acl_accessList) + (nEntries - |
93 | 1) * sizeof(struct acl_accessEntry); |
94 | if (GetFromList(&freeList, &e, t) < 0) { |
95 | e = (struct freeListEntry *)malloc(t + sizeof(int) + |
96 | sizeof(struct freeListEntry *)); |
97 | if (e == NULL((void *)0)) { |
98 | perror("acl_NewACL: malloc() failed"); |
99 | abort(); |
100 | } |
101 | e->size = t; |
102 | *acl = (struct acl_accessList *)(e->body); |
103 | } else |
104 | *acl = (struct acl_accessList *)(e->body); |
105 | |
106 | (*acl)->size = t; /* May be less than actual size of storage */ |
107 | (*acl)->version = ACL_ACLVERSION1; |
108 | (*acl)->total = nEntries; |
109 | (*acl)->positive = (*acl)->negative = 0; |
110 | return (0); |
111 | } |
112 | |
113 | |
114 | int |
115 | acl_FreeACL(struct acl_accessList **acl) |
116 | { |
117 | /* Releases the access list defined by acl. Returns 0 always. */ |
118 | struct freeListEntry *x; |
119 | |
120 | x = (struct freeListEntry *) |
121 | ((char *)*acl - sizeof(struct freeListEntry *) - sizeof(int)); |
122 | *acl = NULL((void *)0); |
123 | return (AddToList(&freeList, x)); |
124 | } |
125 | |
126 | int |
127 | acl_NewExternalACL(int nEntries, char **r) |
128 | { |
129 | /* Puts an external acl big enough to hold nEntries in r. Returns 0 on success, aborts if insufficient memory. */ |
130 | |
131 | int t; |
132 | struct freeListEntry *e; |
133 | |
134 | t = 20 + (nEntries) * (PR_MAXNAMELEN64 + 20); |
135 | /* Conservative estimate: enough space in each entry for longest |
136 | * name plus decimal 2**32 (for largest rights mask) plus some formatting */ |
137 | |
138 | if (GetFromList(&freeList, &e, t)) { |
139 | e = (struct freeListEntry *)malloc(t + sizeof(int) + |
140 | sizeof(struct freeListEntry *)); |
141 | if (e == NULL((void *)0)) { |
142 | perror("acl_NewExternalACL(): malloc() failed"); |
143 | abort(); |
144 | } |
145 | e->size = t; |
146 | } |
147 | |
148 | *r = e->body; |
149 | sprintf(*r, "0\n0\n"); |
150 | return (0); |
151 | } |
152 | |
153 | int |
154 | acl_FreeExternalACL(char **r) |
155 | { |
156 | /* Releases the external access list defined by r. Returns 0 always. */ |
157 | |
158 | struct freeListEntry *x; |
159 | |
160 | x = (struct freeListEntry *) |
161 | ((char *)*r - sizeof(struct freeListEntry *) - sizeof(int)); |
162 | *r = NULL((void *)0); |
163 | return (AddToList(&freeList, x)); |
164 | } |
165 | |
166 | int |
167 | acl_Externalize_pr(int (*func)(idlist *ids, namelist *names), struct acl_accessList *acl, char **elist) |
168 | { |
169 | /* Converts the access list defined by acl into the external access list |
170 | * in elist. Non-translatable id's are converted to their ASCII string |
171 | * representations. Returns 0 on success, -1 if number of entries |
172 | * exceeds ACL_MAXENTRIES, or a failure code from the protection server |
173 | * if the problem occured there. */ |
174 | |
175 | int i; |
176 | int j; |
177 | int code; |
178 | char *nextc; |
179 | idlist lids; |
180 | namelist lnames; |
181 | |
182 | if (acl->total > ACL_MAXENTRIES20) |
183 | return (-1); |
184 | acl_NewExternalACL(acl->total, elist); |
185 | nextc = *elist; |
186 | lids.idlist_val = |
187 | (afs_int32 *) malloc(ACL_MAXENTRIES20 * sizeof(afs_int32)); |
188 | memset(lids.idlist_val, 0, ACL_MAXENTRIES20 * sizeof(afs_int32)); |
189 | lids.idlist_len = acl->total; |
190 | lnames.namelist_len = 0; |
191 | lnames.namelist_val = (prname *) 0; |
192 | sprintf(nextc, "%d\n%d\n", acl->positive, acl->negative); |
193 | nextc += strlen(nextc); |
194 | for (i = 0; i < acl->positive; i++) |
195 | lids.idlist_val[i] = acl->entries[i].id; |
196 | j = i; |
197 | for (i = acl->total - 1; i >= acl->total - acl->negative; i--, j++) |
198 | lids.idlist_val[j] = acl->entries[i].id; |
199 | code = (*func)(&lids, &lnames); |
200 | if (code != 0) { |
201 | if (lids.idlist_val) |
202 | free(lids.idlist_val); |
203 | if (lnames.namelist_val) |
204 | free(lnames.namelist_val); |
205 | return code; |
206 | } |
207 | for (i = 0; i < acl->positive; i++) { |
208 | sprintf(nextc, "%s", lnames.namelist_val[i]); |
209 | nextc += strlen(nextc); |
210 | sprintf(nextc, "\t%d\n", acl->entries[i].rights); |
211 | nextc += strlen(nextc); |
212 | } |
213 | j = i; |
214 | for (i = acl->total - 1; i >= acl->total - acl->negative; i--, j++) { |
215 | sprintf(nextc, "%s", lnames.namelist_val[j]); |
216 | nextc += strlen(nextc); |
217 | sprintf(nextc, "\t%d\n", acl->entries[i].rights); |
218 | nextc += strlen(nextc); |
219 | } |
220 | if (lids.idlist_val) |
221 | free(lids.idlist_val); |
222 | if (lnames.namelist_val) |
223 | free(lnames.namelist_val); |
224 | return (0); |
225 | } |
226 | |
227 | int |
228 | acl_Externalize(struct acl_accessList *acl, char **elist) |
229 | { |
230 | return acl_Externalize_pr(pr_IdToName, acl, elist); |
231 | } |
232 | |
233 | int |
234 | acl_Internalize_pr(int (*func)(namelist *names, idlist *ids), char *elist, struct acl_accessList **acl) |
235 | { |
236 | /* Converts the external access list elist into the access list acl. |
237 | * Returns 0 on success, -1 if ANY name is not translatable, or if |
238 | * the number of entries exceeds al_maxExtEntries. */ |
239 | int i; |
240 | int j; |
241 | char *nextc; |
242 | afs_int32 code; |
243 | int p, n; |
244 | namelist lnames; |
245 | idlist lids; |
246 | |
247 | if (sscanf(elist, "%d\n%d\n", &p, &n) != 2) |
248 | return -1; |
249 | if (p + n > ACL_MAXENTRIES20) |
250 | return (-1); |
251 | acl_NewACL(p + n, acl); |
252 | (*acl)->total = p + n; |
253 | (*acl)->positive = p; |
254 | (*acl)->negative = n; |
255 | if ((*acl)->total == 0) { |
256 | /* Empty acl entry; simply return success */ |
257 | return 0; |
258 | } |
259 | lnames.namelist_len = (*acl)->total; |
260 | lnames.namelist_val = |
261 | (prname *) malloc(lnames.namelist_len * PR_MAXNAMELEN64); |
262 | if (lnames.namelist_val == 0) { |
263 | return -1; |
264 | } |
265 | nextc = elist; |
266 | while (*nextc && *nextc != '\n') |
267 | nextc++; |
268 | nextc++; |
269 | while (*nextc && *nextc != '\n') |
270 | nextc++; |
271 | nextc++; /* now at the beginning of the entry list */ |
272 | for (i = 0; i < (*acl)->positive; i++) { |
273 | int k; |
274 | if (sscanf(nextc, "%s\t%d\n", lnames.namelist_val[i], &k) != 2) { |
275 | free(lnames.namelist_val); |
276 | return (-1); |
277 | } |
278 | (*acl)->entries[i].rights = k; |
279 | nextc = strchr(nextc, '\n'); |
280 | nextc++; /* 1 + index can cast ptr to integer */ |
281 | } |
282 | j = i; |
283 | for (i = (*acl)->total - 1; i >= (*acl)->total - (*acl)->negative; |
284 | i--, j++) { |
285 | if (sscanf |
286 | (nextc, "%s\t%d\n", lnames.namelist_val[j], |
287 | &((*acl)->entries[j].rights)) != 2) { |
288 | free(lnames.namelist_val); |
289 | return (-1); |
290 | } |
291 | nextc = strchr(nextc, '\n'); |
292 | nextc++; |
293 | } |
294 | lids.idlist_len = 0; |
295 | lids.idlist_val = 0; |
296 | |
297 | code = (*func)(&lnames, &lids); |
298 | if (code) { |
299 | free(lnames.namelist_val); |
300 | if (lids.idlist_val) |
301 | free(lids.idlist_val); |
302 | return -1; |
303 | } |
304 | for (i = 0; i < (*acl)->positive; i++) { |
305 | if (lids.idlist_val[i] == ANONYMOUSID32766) { |
306 | free(lnames.namelist_val); |
307 | if (lids.idlist_val) |
308 | free(lids.idlist_val); |
309 | return -1; |
310 | } |
311 | (*acl)->entries[i].id = lids.idlist_val[i]; |
312 | } |
313 | j = i; |
Value stored to 'j' is never read | |
314 | for (i = (*acl)->total - 1; i >= (*acl)->total - (*acl)->negative; i--) { |
315 | if (lids.idlist_val[i] == ANONYMOUSID32766) { |
316 | free(lnames.namelist_val); |
317 | if (lids.idlist_val) |
318 | free(lids.idlist_val); |
319 | return -1; |
320 | } |
321 | (*acl)->entries[i].id = lids.idlist_val[i]; |
322 | } |
323 | /* sort for easier lookup */ |
324 | qsort(&((*acl)->entries[0]), (*acl)->positive, |
325 | sizeof(struct acl_accessEntry), CmpPlus); |
326 | qsort(&((*acl)->entries[(*acl)->total - (*acl)->negative]), |
327 | (*acl)->negative, sizeof(struct acl_accessEntry), CmpMinus); |
328 | free(lnames.namelist_val); |
329 | if (lids.idlist_val) |
330 | free(lids.idlist_val); |
331 | return (0); |
332 | } |
333 | |
334 | int |
335 | acl_Internalize(char *elist, struct acl_accessList **acl) |
336 | { |
337 | return acl_Internalize_pr(pr_NameToId, elist, acl); |
338 | } |
339 | |
340 | int |
341 | acl_CheckRights(struct acl_accessList *acl, prlist *groups, int *rights) |
342 | { |
343 | /* Returns the rights given by acl to groups */ |
344 | |
345 | int temprights; /* positive rights accumulated so far */ |
346 | int negrights; /* negative rights accumulated so far */ |
347 | int a; /* index into next entry in acl */ |
348 | int c; /* index into next entry in CPS */ |
349 | |
350 | /* more sanity checks */ |
351 | if (acl->total > ACL_MAXENTRIES20) |
352 | return 1; |
353 | if (acl->total < 0) |
354 | return 1; |
355 | if (acl->size > 192) |
356 | return 1; /* 192 is the room in a 256 byte vnode reserved for the ACL */ |
357 | |
358 | if (acl->total <= 0 || groups->prlist_len <= 0) { |
359 | *rights = 0; |
360 | return (0); |
361 | } |
362 | if (groups->prlist_val[groups->prlist_len - 1] == SYSADMINID-204) { |
363 | *rights = -1; |
364 | return 0; |
365 | } |
366 | |
367 | /* Each iteration eats up exactly one entry from either acl or groups. |
368 | * Duplicate Entries in access list ==> accumulated rights are obtained. |
369 | * Duplicate Entries in groups ==> irrelevant */ |
370 | temprights = 0; |
371 | c = a = 0; |
372 | while ((a < acl->positive) && (c < groups->prlist_len)) |
373 | switch (CmpInt(acl->entries[a].id, groups->prlist_val[c])) { |
374 | case -1: |
375 | a += 1; |
376 | break; |
377 | |
378 | case 0: |
379 | temprights |= acl->entries[a].rights; |
380 | a += 1; |
381 | break; |
382 | |
383 | case 1: |
384 | c += 1; |
385 | break; |
386 | |
387 | default: |
388 | printf("CmpInt() returned bogus value. Aborting ...\n"); |
389 | abort(); |
390 | } |
391 | negrights = 0; |
392 | c = 0; |
393 | a = acl->total - 1; |
394 | while ((c < groups->prlist_len) && (a > acl->total - acl->negative - 1)) |
395 | switch (CmpInt(acl->entries[a].id, groups->prlist_val[c])) { |
396 | case -1: |
397 | a -= 1; |
398 | break; |
399 | case 0: |
400 | negrights |= acl->entries[a].rights; |
401 | a -= 1; |
402 | break; |
403 | case 1: |
404 | c += 1; |
405 | break; |
406 | } |
407 | *rights = temprights & (~negrights); |
408 | return (0); |
409 | } |
410 | |
411 | int |
412 | acl_Initialize(char *version) |
413 | { |
414 | /* I'm sure we need to do some initialization, I'm just not quite sure what yet! */ |
415 | if (strcmp(version, ACL_VERSION"Version 1") != 0) { |
416 | fprintf(stderr__stderrp, "Wrong version of acl package!\n"); |
417 | fprintf(stderr__stderrp, "This is version %s, file server passed in %s.\n", |
418 | ACL_VERSION"Version 1", version); |
419 | } |
420 | #ifdef AFS_PTHREAD_ENV1 |
421 | assert(pthread_mutex_init(&acl_list_mutex, NULL) == 0)((pthread_mutex_init(&acl_list_mutex, ((void *)0)) == 0) ? (void)0 : __assert(__func__, "./../libacl/aclprocs.c", 421, "pthread_mutex_init(&acl_list_mutex, NULL) == 0" )); |
422 | #endif /* AFS_PTHREAD_ENV */ |
423 | return 0; |
424 | } |
425 | |
426 | int |
427 | acl_IsAMember(afs_int32 aid, prlist *cps) |
428 | { |
429 | afs_int32 i; |
430 | |
431 | for (i = 0; i < cps->prlist_len; i++) |
432 | if (cps->prlist_val[i] == aid) |
433 | return 1; |
434 | return 0; |
435 | } |
436 | |
437 | |
438 | static int |
439 | AddToList(struct freeListEntry **pflist, struct freeListEntry *elem) |
440 | { |
441 | /* Adds elem to the freelist flist; returns 0 */ |
442 | #ifdef AFS_PTHREAD_ENV1 |
443 | assert(pthread_mutex_lock(&acl_list_mutex) == 0)((pthread_mutex_lock(&acl_list_mutex) == 0) ? (void)0 : __assert (__func__, "./../libacl/aclprocs.c", 443, "pthread_mutex_lock(&acl_list_mutex) == 0" )); |
444 | #endif /* AFS_PTHREAD_ENV */ |
445 | elem->next = *pflist; |
446 | *pflist = elem; |
447 | #ifdef AFS_PTHREAD_ENV1 |
448 | assert(pthread_mutex_unlock(&acl_list_mutex) == 0)((pthread_mutex_unlock(&acl_list_mutex) == 0) ? (void)0 : __assert(__func__, "./../libacl/aclprocs.c", 448, "pthread_mutex_unlock(&acl_list_mutex) == 0" )); |
449 | #endif /* AFS_PTHREAD_ENV */ |
450 | return 0; |
451 | } |
452 | |
453 | static int |
454 | GetFromList(struct freeListEntry **pflist, struct freeListEntry **elem, |
455 | afs_int32 minsize) |
456 | { |
457 | /* Looks for an element whose body is at least minsize bytes in the |
458 | * freelist flist. If found, unlinks it, puts its address in elem, |
459 | * and returns 0, else returns -1. A trivial first-fit algorithm is |
460 | * used. */ |
461 | |
462 | struct freeListEntry *y, *z; |
463 | |
464 | #ifdef AFS_PTHREAD_ENV1 |
465 | assert(pthread_mutex_lock(&acl_list_mutex) == 0)((pthread_mutex_lock(&acl_list_mutex) == 0) ? (void)0 : __assert (__func__, "./../libacl/aclprocs.c", 465, "pthread_mutex_lock(&acl_list_mutex) == 0" )); |
466 | #endif /* AFS_PTHREAD_ENV */ |
467 | if (*pflist == NULL((void *)0)) { |
468 | #ifdef AFS_PTHREAD_ENV1 |
469 | assert(pthread_mutex_unlock(&acl_list_mutex) == 0)((pthread_mutex_unlock(&acl_list_mutex) == 0) ? (void)0 : __assert(__func__, "./../libacl/aclprocs.c", 469, "pthread_mutex_unlock(&acl_list_mutex) == 0" )); |
470 | #endif /* AFS_PTHREAD_ENV */ |
471 | return -1; |
472 | } |
473 | for (y = *pflist, z = NULL((void *)0); y != NULL((void *)0); z = y, y = y->next) { |
474 | if (y->size >= minsize) { |
475 | *elem = y; |
476 | if (z == NULL((void *)0)) { /* pulling off the head */ |
477 | *pflist = y->next; |
478 | #ifdef AFS_PTHREAD_ENV1 |
479 | assert(pthread_mutex_unlock(&acl_list_mutex) == 0)((pthread_mutex_unlock(&acl_list_mutex) == 0) ? (void)0 : __assert(__func__, "./../libacl/aclprocs.c", 479, "pthread_mutex_unlock(&acl_list_mutex) == 0" )); |
480 | #endif /* AFS_PTHREAD_ENV */ |
481 | return 0; |
482 | } |
483 | z->next = y->next; |
484 | #ifdef AFS_PTHREAD_ENV1 |
485 | assert(pthread_mutex_unlock(&acl_list_mutex) == 0)((pthread_mutex_unlock(&acl_list_mutex) == 0) ? (void)0 : __assert(__func__, "./../libacl/aclprocs.c", 485, "pthread_mutex_unlock(&acl_list_mutex) == 0" )); |
486 | #endif /* AFS_PTHREAD_ENV */ |
487 | return 0; |
488 | } |
489 | } |
490 | #ifdef AFS_PTHREAD_ENV1 |
491 | assert(pthread_mutex_unlock(&acl_list_mutex) == 0)((pthread_mutex_unlock(&acl_list_mutex) == 0) ? (void)0 : __assert(__func__, "./../libacl/aclprocs.c", 491, "pthread_mutex_unlock(&acl_list_mutex) == 0" )); |
492 | #endif /* AFS_PTHREAD_ENV */ |
493 | return -1; |
494 | } |