]> andersk Git - moira.git/blob - afssync/ptutils.c
a8e2b3418940348cff81f1d738124df23f2092e5
[moira.git] / afssync / ptutils.c
1 /* $Header$ */
2 /* $Source$ */
3
4
5 /*
6  * P_R_P_Q_# (C) COPYRIGHT IBM CORPORATION 1988
7  * LICENSED MATERIALS - PROPERTY OF IBM
8  * REFER TO COPYRIGHT INSTRUCTIONS FORM NUMBER G120-2083
9  */
10
11 /*      
12              Sherri Nichols
13              Information Technology Center
14        November, 1988
15
16        Modified May, 1989 by Jeff Schiller to keep disk file in
17        network byte order
18
19 */
20
21 #include <stdio.h>
22 #include <strings.h>
23 #include <lock.h>
24 #define UBIK_INTERNALS
25 #include <ubik.h>
26 #include <rx/xdr.h>
27 #include "print.h"
28 #include "prserver.h"
29 #include "prerror.h"
30 #include <netinet/in.h>
31
32 extern struct prheader cheader;
33 extern struct ubik_dbase *dbase;
34 extern struct afsconf_dir *prdir;
35
36 long CreateEntry(at, aname, aid, idflag,flag,oid,creator)  
37 register struct ubik_trans *at;
38 char aname[PR_MAXNAMELEN];
39 long *aid;
40 long idflag;
41 long flag;
42 long oid;
43 long creator;
44 {
45     /* get and init a new entry */
46     register long code;
47     long newEntry;
48     long temp;
49     struct prentry tentry;
50     
51     bzero(&tentry, sizeof(tentry));
52     newEntry = AllocBlock(at);
53     if (!newEntry) return PRDBFAIL;
54     if (flag & PRGRP) {
55         tentry.flags |= PRGRP;
56         tentry.owner = oid;
57     }
58     else if (flag & PRFOREIGN) {
59         tentry.flags |= PRFOREIGN;
60         tentry.owner = oid;
61     }
62     else tentry.owner = SYSADMINID;
63     if (idflag) 
64         tentry.id = *aid;
65     else {
66         code= AllocID(at,flag,&tentry.id);
67         if (code != PRSUCCESS) return code;
68     }
69     if (flag & PRGRP) {
70         if (tentry.id < ntohl(cheader.maxGroup)) {
71             cheader.maxGroup = htonl(tentry.id);
72             code = pr_Write(at,0,16,(char *) &cheader.maxGroup,sizeof(cheader.maxGroup));
73             if (code) return PRDBFAIL;
74         }
75     }
76     else if (flag & PRFOREIGN) {
77         if (tentry.id > ntohl(cheader.maxForeign)) {
78             cheader.maxForeign = htonl(tentry.id);
79             code = pr_Write(at,0,24,(char *) &cheader.maxForeign,sizeof(cheader.maxForeign));
80             if (code) return PRDBFAIL;
81         }
82     }
83     else {
84         if (tentry.id > ntohl(cheader.maxID)) {
85             cheader.maxID = htonl(tentry.id);
86             code = pr_Write(at,0,20,(char *) &cheader.maxID,sizeof(cheader.maxID));
87             if (code) return PRDBFAIL;
88         }
89     }
90     tentry.creator = creator;
91     *aid = tentry.id;
92     strncpy(tentry.name, aname, PR_MAXNAMELEN);
93     code = pr_WriteEntry(at, 0, newEntry, &tentry);
94     if (code) return PRDBFAIL;
95     code = AddToIDHash(at,*aid,newEntry);
96     if (code != PRSUCCESS) return code;
97     code = AddToNameHash(at,aname,newEntry);
98     if (code != PRSUCCESS) return code;
99     if (tentry.flags & PRGRP) {
100         code = AddToOwnerChain(at,tentry.id,oid);
101         if (code) return code;
102     }
103     if (tentry.flags & PRGRP) {
104         temp = ntohl(cheader.groupcount) + 1;
105         cheader.groupcount = htonl(temp);
106         code = pr_Write(at,0,40,(char *)&cheader.groupcount,sizeof(cheader.groupcount));
107         if (code) return PRDBFAIL;
108     }
109     else if (tentry.flags & PRFOREIGN) {
110         temp = ntohl(cheader.foreigncount) + 1;
111         cheader.foreigncount = htonl(temp);
112         code = pr_Write(at,0,44,(char *)&cheader.foreigncount,sizeof(cheader.foreigncount));
113         if (code) return PRDBFAIL;
114     }
115     else if (tentry.flags & PRINST) {
116         temp = ntohl(cheader.instcount) + 1;
117         cheader.instcount = htonl(temp);
118         code = pr_Write(at,0,48,(char *)&cheader.instcount,sizeof(cheader.instcount));
119         if (code) return PRDBFAIL;
120     }
121     else {
122         temp = ntohl(cheader.usercount) + 1;
123         cheader.usercount = htonl(temp);
124         code = pr_Write(at,0,36,(char *)&cheader.usercount,sizeof(cheader.usercount));
125         if (code) return PRDBFAIL;
126     }
127     return PRSUCCESS;
128 }
129     
130
131
132 long RemoveFromEntry(at,aid,bid)
133 register struct ubik_trans *at;
134 register long aid;
135 register long bid;
136 {
137     /* remove aid from bid's entries list, freeing a continuation entry if appropriate */
138
139     register long code;
140     struct prentry tentry;
141     struct contentry centry;
142     struct contentry hentry;
143     long temp;
144     long first;
145     long i,j;
146     long nptr;
147     long hloc = 0;
148     
149     bzero(&hentry,sizeof(hentry));
150     temp = FindByID(at,bid);
151     code = pr_ReadEntry(at, 0, temp, &tentry);
152     if (code != 0) return code;
153     for (i=0;i<PRSIZE;i++) {
154         if (tentry.entries[i] == aid) {  
155             tentry.entries[i] = PRBADID;
156             tentry.count--;
157             code = pr_WriteEntry(at,0,temp,&tentry);
158             if (code != 0) return code;
159             return PRSUCCESS;
160         }
161         if (tentry.entries[i] == 0)   /* found end of list */
162             return PRNOENT;
163     }
164     if (tentry.next != NULL) {
165         nptr = tentry.next;
166         first = 1;
167         while (nptr != NULL) {
168             code = pr_ReadCoEntry(at,0,nptr,&centry);
169             if (code != 0) return code;
170             for (i=0;i<COSIZE;i++) {
171                 if (centry.entries[i] == aid) {
172                     centry.entries[i] = PRBADID;
173                     tentry.count--;
174                     code = pr_WriteEntry(at,0,temp,&tentry);
175                     if (code) return PRDBFAIL;
176                     for (j=0;j<COSIZE;j++)
177                         if (centry.entries[j] != PRBADID && centry.entries[j] != 0) break;
178                     if (j == COSIZE) {   /* can free this block */
179                         if (first) {
180                             tentry.next = centry.next;
181                             code = pr_WriteEntry(at,0,temp,&tentry);
182                             if (code != 0) return code;
183                         }
184                         else {
185                             hentry.next = centry.next;
186                             code = pr_WriteCoEntry(at,0,hloc,(char *) &hentry);
187                             if (code != 0) return code;
188                         }
189                         code = FreeBlock(at,nptr);
190                         return code;
191                     }
192                     else { /* can't free it yet */
193                         code = pr_WriteCoEntry(at,0,nptr,&centry);
194                         if (code != 0) return code;
195                         return PRSUCCESS;
196                     }
197                 }
198                 if (centry.entries[i] == 0) return PRNOENT;
199             }
200             hloc = nptr;
201             nptr = centry.next;
202             bcopy(&centry,&hentry,sizeof(centry));
203         }
204     }
205     else return PRNOENT;
206     return PRSUCCESS;
207 }
208
209 long DeleteEntry(at,aid,cid)
210 register struct ubik_trans *at;
211 long aid;
212 long cid;
213 {
214     /* delete the entry aid, removing it from all groups, putting groups owned by it on orphan chain, and freeing the space */
215     register long code;
216     long temp;
217     long temp1;
218     struct prentry tentry;
219     struct contentry centry;
220     struct prentry nentry;
221     register long  i;
222     long nptr;
223     long noAuth;
224
225     noAuth = afsconf_GetNoAuthFlag(prdir);
226     bzero(&tentry,sizeof(tentry));
227     temp = FindByID(at,aid);
228     if (!temp) return PRNOENT;
229     code = pr_ReadEntry(at,0,temp,&tentry);
230     if (code != 0) return PRDBFAIL;
231     if (tentry.owner != cid && !IsAMemberOf(at,cid,SYSADMINID) && !IsAMemberOf(at,cid,tentry.owner) && !noAuth) return PRPERM;
232     for (i=0;i<PRSIZE;i++) {
233         if (tentry.entries[i] == 0) break;
234         RemoveFromEntry(at,aid,tentry.entries[i]);
235     }
236     nptr = tentry.next;
237     while (nptr != NULL) {
238         code = pr_ReadCoEntry(at,0,nptr,&centry);
239         if (code != 0) return PRDBFAIL;
240         for (i=0;i<COSIZE;i++) {
241             if (centry.entries[i] == 0) break;
242             RemoveFromEntry(at,aid,centry.entries[i]);
243         }
244         nptr = centry.next;
245     }
246     if (tentry.flags & PRGRP) {
247         if (FindByID(at,tentry.owner)) {
248             code = RemoveFromOwnerChain(at,aid,tentry.owner);
249             if (code) return code;
250         }
251         else {
252             code = RemoveFromOrphan(at,aid);
253             if (code) return code;
254         }
255     }
256     if (tentry.owned) {
257         nptr = tentry.owned;
258         while (nptr != NULL) {
259             code = pr_ReadEntry(at,0,nptr,&nentry);
260             if (code != 0) return PRDBFAIL;
261             if (nentry.id != aid)  /* don't add this entry to orphan chain! */
262                 code = AddToOrphan(at,nentry.id);
263             nptr = nentry.nextOwned;
264         }
265     }
266     code = RemoveFromIDHash(at,tentry.id,&temp);
267     if (code != PRSUCCESS) return code;
268     code = RemoveFromNameHash(at,tentry.name,&temp);
269     if (code != PRSUCCESS) return code;
270    if (tentry.flags & PRGRP) {
271         temp1 = ntohl(cheader.groupcount) + 1;
272         cheader.groupcount = htonl(temp1);
273         code = pr_Write(at,0,40,(char *)&cheader.groupcount,sizeof(cheader.groupcount));
274         if (code) return PRDBFAIL;
275     }
276     else if (tentry.flags & PRFOREIGN) {
277         temp1 = ntohl(cheader.foreigncount) + 1;
278         cheader.foreigncount = htonl(temp1);
279         code = pr_Write(at,0,44,(char *)&cheader.foreigncount,sizeof(cheader.foreigncount));
280         if (code) return PRDBFAIL;
281     }
282     else if (tentry.flags & PRINST) {
283         temp1 = ntohl(cheader.instcount) + 1;
284         cheader.instcount = htonl(temp1);
285         code = pr_Write(at,0,48,(char *)&cheader.instcount,sizeof(cheader.instcount));
286         if (code) return PRDBFAIL;
287     }
288     else {
289         temp1 = ntohl(cheader.usercount) + 1;
290         cheader.usercount = htonl(temp1);
291         code = pr_Write(at,0,36,(char *)&cheader.usercount,sizeof(cheader.usercount));
292         if (code) return PRDBFAIL;
293     }
294     FreeBlock(at,temp);
295     return PRSUCCESS;
296 }
297
298
299
300
301 long AddToEntry(tt,entry,loc,aid)
302 struct ubik_trans *tt;
303 struct prentry entry;
304 long loc;
305 long aid;
306 {
307     /* add aid to entry's entries list, alloc'ing a continuation block if needed */
308     register long code;
309     long i;
310     struct contentry nentry;
311     struct contentry aentry;
312     long nptr;
313     long last = 0;
314     long first = 0;
315     long cloc;
316     long slot = -1;
317
318     bzero(&nentry,sizeof(nentry));
319     bzero(&aentry,sizeof(aentry));
320     for (i=0;i<PRSIZE;i++) {
321         if (entry.entries[i] == aid)
322             return PRIDEXIST;
323         if (entry.entries[i] == PRBADID) { /* remember this spot */
324             first = 1;
325             slot = i;
326         }
327         if (entry.entries[i] == 0) { /* end of the line */
328             if (slot == -1) {
329                 first = 1;
330                 slot = i;
331             }
332             break;
333         }
334     }
335     nptr = entry.next;
336     while (nptr != NULL) {
337         code = pr_ReadCoEntry(tt,0,nptr,&nentry);
338         if (code != 0) return code;
339         if (!(nentry.flags & PRCONT)) return PRDBFAIL;
340         for (i=0;i<COSIZE;i++) {
341             if (nentry.entries[i] == aid)
342                 return PRIDEXIST;
343             if (nentry.entries[i] == PRBADID) {
344                 if (slot == -1) {
345                     slot = i;
346                     cloc = nptr;
347                 }
348             }
349             if (nentry.entries[i] == 0) {
350                 if (slot == -1) {
351                     slot = i;
352                     cloc = nptr;
353                 }
354                 break;
355             }
356         }
357         last = nptr;
358         nptr = nentry.next;
359     }
360     if (slot != -1) {  /* we found a place */
361         entry.count++;
362         if (first) {  /* place is in first block */
363             entry.entries[slot] = aid;
364             code = pr_WriteEntry(tt,0,loc,&entry);
365             if (code != 0) return code;
366             return PRSUCCESS;
367         }
368         code = pr_WriteEntry(tt,0,loc,&entry);
369         code = pr_ReadCoEntry(tt,0,cloc,&aentry);
370         if (code != 0) return code;
371         aentry.entries[slot] = aid;
372         code = pr_WriteCoEntry(tt,0,cloc,&aentry);
373         if (code != 0) return code;
374         return PRSUCCESS;
375     }
376     /* have to allocate a continuation block if we got here */
377     nptr = AllocBlock(tt);
378     if (nentry.flags & PRCONT) {
379         /* then we should tack new block here */
380         nentry.next = nptr;
381         code = pr_WriteCoEntry(tt,0,last,&nentry);
382         if (code != 0) return code;
383     }
384     else {
385         entry.next = nptr;
386         code = pr_WriteEntry(tt,0,loc,&entry);
387         if (code != 0) return code;
388     }
389     aentry.flags |= PRCONT;
390     aentry.id = entry.id;
391     aentry.next = NULL;
392     aentry.entries[0] = aid;
393     code = pr_WriteCoEntry(tt,0,nptr,&aentry);
394     if (code != 0) return code;
395     /* don't forget to update count, here! */
396     entry.count++;
397     code = pr_WriteEntry(tt,0,loc,&entry);
398     return PRSUCCESS;
399         
400 }
401
402 long GetList(at,aid,alist,add)
403 struct ubik_trans *at;
404 long aid;
405 prlist *alist;
406 long add;
407 {
408     register long code;
409     long temp;
410     long i;
411     long count;
412     struct prentry tentry;
413     struct contentry centry;
414     long nptr;
415     long size;
416     extern long IDCmp();
417
418     temp = FindByID(at,aid);
419     if (!temp) return PRNOENT;
420     code = pr_ReadEntry(at,0,temp,&tentry);
421     if (code != 0) return code;
422     alist->prlist_val = (long *)malloc(100*sizeof(long));
423     size = 100;
424     alist->prlist_len = 0;
425     count = 0;
426     for (i=0;i<PRSIZE;i++) {
427         if (tentry.entries[i] == PRBADID) continue;
428         if (tentry.entries[i] == 0) break;
429         alist->prlist_val[count]= tentry.entries[i];
430         count++;
431         alist->prlist_len++;
432     }
433     nptr = tentry.next;
434     while (nptr != NULL) {
435         /* look through cont entries */
436         code = pr_ReadCoEntry(at,0,nptr,&centry);
437         if (code != 0) return code;
438         for (i=0;i<COSIZE;i++) {
439             if (centry.entries[i] == PRBADID) continue;
440             if (centry.entries[i] == 0) break;
441             if (alist->prlist_len >= size) {
442                 alist->prlist_val = (long *)realloc(alist->prlist_val,(size+100)*sizeof(long));
443                 size += 100;
444             }
445             alist->prlist_val[count] = centry.entries[i];
446             count++;
447             alist->prlist_len++;
448         }
449         nptr = centry.next;
450     }
451     if (add) { /* this is for a CPS, so tack on appropriate stuff */
452         if (aid != ANONYMOUSID && aid != ANYUSERID) {
453             if (alist->prlist_len >= size)
454                 alist->prlist_val = (long *)realloc(alist->prlist_val,(size + 3)*sizeof(long));
455             alist->prlist_val[count] = ANYUSERID;
456             count++;
457             alist->prlist_val[count] = AUTHUSERID;
458             count++;
459             alist->prlist_val[count] = aid;
460             count++;
461             alist->prlist_len += 3;
462         }
463         else {
464             if (alist->prlist_len >= size)
465                 alist->prlist_val = (long *)realloc(alist->prlist_val,(size + 2)*sizeof(long));
466             alist->prlist_val[count] = ANYUSERID;
467             count++;
468             alist->prlist_val[count] = aid;
469             count++;
470             alist->prlist_len += 2;
471         }
472     }
473     qsort(alist->prlist_val,alist->prlist_len,sizeof(long),IDCmp);
474     return PRSUCCESS;
475 }
476
477 long GetMax(at,uid,gid)
478 register struct ubik_trans *at;
479 long *uid;
480 long *gid;
481 {
482     *uid = ntohl(cheader.maxID);
483     *gid = ntohl(cheader.maxGroup);
484     return PRSUCCESS;
485 }
486
487 long SetMax(at,id,flag)
488 register struct ubik_trans *at;
489 long id;
490 long flag;
491 {
492     register long code;
493     if (flag & PRGRP) {
494         cheader.maxGroup = htonl(id);
495         code = pr_Write(at,0,16,(char *)&cheader.maxGroup,sizeof(cheader.maxGroup));
496         if (code != 0) return code;
497     }
498     else {
499         cheader.maxID = htonl(id);
500         code = pr_Write(at,0,20,(char *)&cheader.maxID,sizeof(cheader.maxID));
501         if (code != 0) return code;
502     }
503     return PRSUCCESS;
504 }
505
506 Initdb()
507 {
508     long code;
509     struct ubik_trans *tt;
510     long len;
511     long temp;
512     long flag = 0;
513     static long initd=0;
514     static struct ubik_version curver;
515     struct ubik_version newver;
516     struct ubik_hdr header;
517
518     /* init the database.  We'll try reading it, but if we're starting from scratch, we'll have to do a write transaction. */
519
520     code = ubik_BeginTrans(dbase,UBIK_READTRANS, &tt);
521     if (code) return code;
522     code = ubik_SetLock(tt,1,1,LOCKREAD);
523     if (code) {
524         ubik_AbortTrans(tt);
525         return code;
526     }
527     if (!initd) {
528         initd = 1;
529         bzero(&curver,sizeof(curver));
530     }
531     len = sizeof(cheader);
532     code = pr_Read(tt, 0, 0, (char *) &cheader, len);
533     if (code != 0) {
534         printf("prserver: couldn't read header -code is %d\n",code);
535         ubik_AbortTrans(tt);
536         return code;
537     }
538     if (ntohl(cheader.headerSize) == sizeof(cheader) && ntohl(cheader.eofPtr) != NULL && FindByID(tt,ANONYMOUSID) != 0){
539         /* database exists, so we don't have to build it */
540         code = ubik_EndTrans(tt);
541         if (code) return code;
542         return PRSUCCESS;
543     }
544     /* else we need to build a database */
545     code = ubik_EndTrans(tt);
546     if (code) return code;
547     fprintf(stderr, "Creating new database\n");
548     code = ubik_BeginTrans(dbase,UBIK_WRITETRANS, &tt);
549     if (code) return code;
550     code = ubik_SetLock(tt,1,1,LOCKWRITE);
551     if (code) {
552         ubik_AbortTrans(tt);
553         return code;
554     }
555     header.magic = htonl(UBIK_MAGIC);
556     header.pad1 = 0;
557     header.size = 0;
558     header.version.epoch = header.version.counter = htonl(1);
559     code = pr_Write(tt, 0, -(HDRSIZE), (char *)&header, sizeof(header));
560     if (code != 0) {
561         printf("prserver: couldn't write ubik header - code is %d.\n", code);
562         return code;
563     }
564     cheader.headerSize = htonl(sizeof(cheader));
565     code = pr_Write(tt,0,4,(char *)&cheader.headerSize,sizeof(cheader.headerSize));
566     if (code != 0) {
567         printf("prserver:  couldn't write header size - code is %d.\n",code);
568         ubik_AbortTrans(tt);
569         return code;
570     }
571     cheader.eofPtr = cheader.headerSize; /* already in network order! */
572     code = pr_Write(tt,0,12,(char *)&cheader.eofPtr,sizeof(cheader.eofPtr));
573     if (code != 0) {
574         printf("prserver:  couldn't write eof Ptr - code is %d.\n",code);
575         ubik_AbortTrans(tt);
576         return code;
577     }
578     temp = SYSADMINID;
579     if (FindByID(tt,SYSADMINID) == 0) {
580         /* init sysadmin */
581         flag |= PRGRP;
582         code = CreateEntry(tt,"system:administrators",&temp,1,flag,SYSADMINID,SYSADMINID);
583         if (code != PRSUCCESS) {
584             printf("prserver: couldn't create system:administrators.\n");
585             ubik_AbortTrans(tt);
586             return code;
587         }
588         flag = 0;
589     }
590     temp = ANYUSERID;
591     if ( FindByID(tt,temp) == 0) { /* init sysadmin */
592         flag |= PRGRP;
593         code = CreateEntry(tt,"system:anyuser",&temp,1,flag,SYSADMINID,SYSADMINID);
594         if (code != PRSUCCESS) {
595             printf("prserver:  couldn't create system:anyuser.\n");
596             ubik_AbortTrans(tt);
597             return code;
598         }
599         flag = 0;
600     }
601     temp = AUTHUSERID;
602     if (FindByID(tt,temp) == 0) { /* init sysadmin */
603         flag |= PRGRP;
604         code = CreateEntry(tt,"system:authuser",&temp,1,flag,SYSADMINID,SYSADMINID);
605         if (code != PRSUCCESS) {
606             printf("prserver:  couldn't create system:authuser.\n");
607             ubik_AbortTrans(tt);
608             return code;
609         }
610         flag = 0;
611     }
612     temp = ANONYMOUSID;
613     if (FindByID(tt,temp) == 0) { /* init sysadmin */
614         code = CreateEntry(tt,"anonymous",&temp,1,flag,SYSADMINID,SYSADMINID);
615         if (code != PRSUCCESS) {
616             printf("prserver:  couldn't create anonymous.\n");
617             ubik_AbortTrans(tt);
618             return code;
619         }
620         /* well, we don't really want the max id set to anonymousid, so we'll set it back to 0 */
621         cheader.maxID = 0; /* Zero is in correct byte order no matter what! */
622         code = pr_Write(tt,0,20,(char *)&cheader.maxID,sizeof(cheader.maxID));
623         if (code) {
624             printf("prserver: couldn't set max id - code is %d.\n");
625             ubik_AbortTrans(tt);
626             return code;
627         }
628     }
629     code = ubik_EndTrans(tt);
630     if (code) return code;
631     return PRSUCCESS;
632 }
633
634 long NameToID(at, aname, aid)
635 register struct ubik_trans *at;
636 char aname[PR_MAXNAMELEN];
637 long *aid;
638 {
639     register long code;
640     long temp;
641     struct prentry tentry;
642
643     temp = FindByName(at,aname);
644     if (!temp) return PRNOENT;
645     code = pr_ReadEntry(at, 0, temp, &tentry);
646     if (code != 0) return code;
647     *aid = tentry.id;
648     return PRSUCCESS;
649 }
650
651 long IDToName(at, aid, aname)
652 register struct ubik_trans *at;
653 long aid;
654 char aname[PR_MAXNAMELEN];
655 {
656     long temp;
657     struct prentry tentry;
658     register long code;
659
660     temp = FindByID(at,aid);
661     if (!temp) return PRNOENT;
662     code = pr_ReadEntry(at,0,temp,&tentry);
663     if (code != 0) return code;
664     strncpy(aname,tentry.name,PR_MAXNAMELEN);
665     return PRSUCCESS;
666 }
667
668 long ChangeEntry(at, aid,cid,name,oid,newid)
669 struct ubik_trans *at;
670 long aid;
671 long cid;
672 char *name;
673 long oid;
674 long newid;
675 {
676     register long code;
677     long pos;
678     struct prentry tentry;
679     long loc;
680     long noAuth;
681     char *check;
682     long tid;
683     char holder[PR_MAXNAMELEN];
684     char temp[PR_MAXNAMELEN];
685
686     noAuth = afsconf_GetNoAuthFlag(prdir);
687     bzero(holder,PR_MAXNAMELEN);
688     bzero(temp,PR_MAXNAMELEN);
689     loc = FindByID(at,aid);
690     if (!loc) return PRNOENT;
691     code = pr_ReadEntry(at,0,loc,&tentry);
692     if (code) return PRDBFAIL;
693     if (tentry.owner != cid && !IsAMemberOf(at,cid,SYSADMINID) && !IsAMemberOf(at,cid,tentry.owner) && !noAuth)
694         return PRPERM;
695     if (aid != newid && newid != 0) { /* then we're actually trying to change the id */
696         pos = FindByID(at,newid);
697         if (pos) return PRIDEXIST;  /* new id already in use! */
698         if ((aid < 0 && newid) > 0 || (aid > 0 && newid < 0)) return PRPERM;
699         /* if new id is not in use, rehash things */
700         code = RemoveFromIDHash(at,aid,&loc);
701         if (code != PRSUCCESS) return code;
702         tentry.id = newid;
703         code = pr_WriteEntry(at,0,loc,&tentry);
704         code = AddToIDHash(at,tentry.id,loc);
705         if (code) return code;
706     }
707     if (tentry.owner != oid && oid) {
708         if (tentry.flags & PRGRP) {
709             /* switch owner chains before we lose old owner */
710             if (FindByID(at,tentry.owner)) /* if it has an owner */
711                 code = RemoveFromOwnerChain(at,tentry.id,tentry.owner);
712             else  /* must be an orphan */
713                 code = RemoveFromOrphan(at,tentry.id);
714             if (code) return code;
715             code = AddToOwnerChain(at,tentry.id,oid);
716             if (code) return code;
717         }
718         tentry.owner = oid;
719         if ((tentry.flags & PRGRP) && (strlen(name) == 0)) {
720             /* if we change the owner of a group, it's name will change as well */
721             if (tentry.owner < 0) {
722                 code = IDToName(at,tentry.owner,temp);
723                 if (code) return code;
724                 check = index(temp,':');
725                 strncpy(holder,temp,check - temp);
726             }
727             else {
728                 code = IDToName(at,tentry.owner,holder);
729                 if (code) return code;
730             }
731             strncat(holder,":",PR_MAXNAMELEN);
732             /* now the rest of the name */
733             check = index(tentry.name,':');
734             strncat(holder,++check,PR_MAXNAMELEN);
735             if (strcmp(holder,tentry.name)) {
736                 /* then the name really did change */
737                 pos = FindByName(at,holder);
738                 if (pos) return PREXIST;
739                 code = RemoveFromNameHash(at,tentry.name,&loc);
740                 if (code != PRSUCCESS) return code;
741                 strncpy(tentry.name,holder,PR_MAXNAMELEN);
742                 code = AddToNameHash(at,tentry.name,loc);
743                 if (code != PRSUCCESS) return code;
744             }
745         }
746         code = pr_WriteEntry(at,0,loc,&tentry);
747         if (code) return PRDBFAIL;
748     }
749     if ((strcmp(tentry.name,name)) && (strlen(name)!= 0)) {
750         if (tentry.flags & PRGRP) {
751             if ((check = index(name,':')) == NULL) return PRBADNAM;
752             strncpy(temp,name,check-name);
753             code = NameToID(at,temp,&tid);
754             if (tid != tentry.owner) return PRPERM;
755         }
756         else
757             /* if it's not a group, shouldn't have a : in it */
758             if ((check = index(name,':')) != NULL) 
759                 return PRBADNAM;
760         pos = FindByName(at,name);
761         if (pos) return PREXIST;
762         code = RemoveFromNameHash(at,tentry.name,&loc);
763         if (code != PRSUCCESS) return code;
764         strncpy(tentry.name,name,PR_MAXNAMELEN);
765         code = pr_WriteEntry(at,0,loc,&tentry);
766         if (code) return PRDBFAIL;
767         code = AddToNameHash(at,tentry.name,loc);
768         if (code != PRSUCCESS) return code;
769     }
770     return PRSUCCESS;
771 }
This page took 0.08282 seconds and 3 git commands to generate.