]> andersk Git - moira.git/commitdiff
from Richard
authormar <mar>
Fri, 21 Sep 1990 15:17:34 +0000 (15:17 +0000)
committermar <mar>
Fri, 21 Sep 1990 15:17:34 +0000 (15:17 +0000)
afssync/ptprocs.c [new file with mode: 0644]
afssync/ptutils.c
afssync/resync.qc
afssync/sync.qc
afssync/ubik.c
afssync/utils.c

diff --git a/afssync/ptprocs.c b/afssync/ptprocs.c
new file mode 100644 (file)
index 0000000..ab8a119
--- /dev/null
@@ -0,0 +1,1134 @@
+/* Copyright (C) 1989 Transarc Corporation - All rights reserved */
+
+/*
+ * P_R_P_Q_# (C) COPYRIGHT IBM CORPORATION 1988
+ * LICENSED MATERIALS - PROPERTY OF IBM
+ * REFER TO COPYRIGHT INSTRUCTIONS FORM NUMBER G120-2083
+ */
+
+#ifndef lint
+static char rcsid[] = "$Header$";
+#endif
+
+/*     
+       Sherri Nichols
+       Information Technology Center
+       November, 1988
+*/
+
+#include <afs/param.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <lock.h>
+#include <ubik.h>
+#include <rx/xdr.h>
+#include <rx/rx.h>
+#include <rx/rx_vab.h>
+#include <rx/rxkad.h>
+#include <afs/auth.h>
+#include <netinet/in.h>
+#include "ptserver.h"
+#include "pterror.h"
+#include <strings.h>
+
+#ifdef AFS_ATHENA_STDENV
+#include <krb.h>
+#endif
+
+extern struct ubik_dbase *dbase;
+extern long Initdb();
+extern int pr_noAuth;
+
+static int CreateOK (ut, cid, oid, flag, admin)
+  struct ubik_trans *ut;
+  long cid;                            /* id of caller */
+  long oid;                            /* id of owner */
+  long flag;                           /* indicates type of entry */
+  int  admin;                          /* sysadmin membership */
+{
+    if (flag & (PRGRP | PRFOREIGN)) {
+       /* Allow anonymous group creation only if owner specified and running
+         * noAuth. */
+       if (cid == ANONYMOUSID) {
+           if ((oid == 0) || !pr_noAuth) return 0;
+       }
+    }
+    else { /* creating a user */
+       if (!admin && !pr_noAuth) return 0;
+    }
+    return 1;                          /* OK! */
+}
+
+long WhoIsThis (acall, at, aid)
+  struct rx_call *acall;
+  struct ubik_trans *at;
+  long *aid;
+{
+    /* aid is set to the identity of the caller, if known, ANONYMOUSID otherwise */
+    /* returns -1 and sets aid to ANONYMOUSID on any failure */
+    register struct rx_connection *tconn;
+    struct rxvab_conn *tc;
+    register long code;
+    char tcell[MAXKTCREALMLEN];
+    long exp;
+    char name[MAXKTCNAMELEN];
+    char inst[MAXKTCNAMELEN];
+    int  ilen;
+    char vname[256];
+
+    *aid = ANONYMOUSID;
+    tconn = rx_ConnectionOf(acall);
+    code = rx_SecurityClassOf(tconn);
+    if (code == 0) return 0;
+    else if (code == 1) {              /* vab class */
+       tc = (struct rxvab_conn *) tconn->securityData;
+       if (!tc) goto done;
+       *aid = ntohl(tc->viceID);
+       code = 0;
+    }
+    else if (code == 2) {              /* kad class */
+       if (code = rxkad_GetServerInfo
+           (acall->conn, (long *) 0, &exp, name, inst, tcell, (long *) 0))
+           goto done;
+       if (exp < FT_ApproxTime()) goto done;
+       if (strlen (tcell)) {
+           extern char *pr_realmName;
+#ifdef AFS_ATHENA_STDENV
+           static char local_realm[REALM_SZ] = "";
+           if (!local_realm[0]) {
+               krb_get_lrealm (local_realm, 0);
+           }
+#endif
+           if (
+#ifdef AFS_ATHENA_STDENV
+               strcasecmp (local_realm, tcell) &&
+#endif
+               strcasecmp (pr_realmName, tcell))
+               goto done;
+
+       }
+       strncpy (vname, name, sizeof(vname));
+       if (ilen = strlen (inst)) {
+           if (strlen(vname) + 1 + ilen >= sizeof(vname)) goto done;
+           strcat (vname, ".");
+           strcat (vname, inst);
+       }
+       lcstring(vname, vname, sizeof(vname));
+       code = NameToID(at,vname,aid);
+    }
+  done:
+    if (code && !pr_noAuth) return -1;
+    return 0;
+}
+
+long PR_INewEntry(call,aname,aid,oid)
+  struct rx_call *call;
+  char aname[PR_MAXNAMELEN];
+  long aid;
+  long oid;
+{
+    /* used primarily for conversion - not intended to be used as usual means
+       of entering people into the database. */
+    struct ubik_trans *tt;
+    register long code;
+    long gflag = 0;
+    long cid;
+    int  admin;
+
+#define abort_with(code) return (ubik_AbortTrans(tt),code)
+
+    stolower(aname);
+    code = Initdb();
+    if (code != PRSUCCESS) return code;
+    code = ubik_BeginTrans(dbase,UBIK_WRITETRANS, &tt);
+    if (code) return code;
+    code = ubik_SetLock(tt, 1,1,LOCKWRITE);
+    if (code) abort_with (code);
+
+    code = WhoIsThis(call,tt,&cid);
+    if (code) abort_with (PRPERM);
+    admin = IsAMemberOf(tt,cid,SYSADMINID);
+
+    /* first verify the id is good */
+    if (aid == 0) abort_with (PRPERM);
+    if (aid < 0) {
+       gflag |= PRGRP;
+       /* only sysadmin can reuse a group id */
+       if (!admin && !pr_noAuth && (aid != ntohl(cheader.maxGroup)-1))
+           abort_with (PRPERM);
+    }
+    if (FindByID (tt, aid)) abort_with (PRIDEXIST);
+
+    /* check a few other things */
+    if (!CreateOK (tt, cid, oid, gflag, admin)) abort_with (PRPERM);
+
+    code = CreateEntry (tt,aname,&aid,1,gflag,oid,cid);
+    if (code != PRSUCCESS) {
+       ubik_AbortTrans(tt);
+       return code;
+    }
+    /* finally, commit transaction */
+    code = ubik_EndTrans(tt);
+    if (code) return code;
+    return PRSUCCESS;
+}
+
+
+long PR_NewEntry (call, aname, flag, oid, aid)
+  struct rx_call *call;
+  char aname[PR_MAXNAMELEN];
+  long flag;
+  long oid;
+  long *aid;
+{
+    register long code;
+    struct ubik_trans *tt;
+    long cid;
+    int  admin;
+
+    stolower(aname);
+    code = Initdb();
+    if (code) return code;
+    code = ubik_BeginTrans(dbase,UBIK_WRITETRANS,&tt);
+    if (code) return code;
+    code = ubik_SetLock(tt,1,1,LOCKWRITE);
+    if (code) {
+      abort:
+       ubik_AbortTrans(tt);
+       return code;
+    }
+    code = WhoIsThis(call,tt,&cid);
+    if (code) {
+      perm:
+       ubik_AbortTrans(tt);
+       return PRPERM;
+    }
+    admin = IsAMemberOf(tt,cid,SYSADMINID);
+
+    if (!CreateOK (tt, cid, oid, flag, admin)) goto perm;
+
+    code = CreateEntry (tt,aname,aid,0,flag,oid,cid);
+    if (code != PRSUCCESS) goto abort;
+
+    code = ubik_EndTrans(tt);
+    if (code) return code;
+    return PRSUCCESS;
+}
+
+
+
+PR_WhereIsIt(call,aid,apos)
+struct rx_call *call;
+long aid;
+long *apos;
+{
+    register long code;
+    struct ubik_trans *tt;
+    long temp;
+
+    code = Initdb();
+    if (code != PRSUCCESS) return code;
+    code = ubik_BeginTrans(dbase,UBIK_READTRANS,&tt);
+    if (code) return code;
+    code = ubik_SetLock(tt,1,1,LOCKREAD);
+    if (code) {
+       ubik_AbortTrans(tt);
+       return code;
+    }
+    temp = FindByID(tt,aid);
+    if (!temp) {
+       ubik_AbortTrans(tt);
+       return PRNOENT;
+    }
+    *apos = temp;
+    code = ubik_EndTrans(tt);
+    if (code) return code;
+    return PRSUCCESS;
+}
+
+
+PR_DumpEntry(call,apos, aentry)
+struct rx_call *call;
+long apos;
+struct prdebugentry *aentry;
+{
+    register long code;
+    struct ubik_trans *tt;
+
+    code = Initdb();
+    if (code != PRSUCCESS) return code;
+    code = ubik_BeginTrans(dbase,UBIK_READTRANS,&tt);
+    if (code) return code;
+    code = ubik_SetLock(tt,1,1,LOCKREAD);
+    if (code) {
+      abort:
+       ubik_AbortTrans(tt);
+       return code;
+    }
+    code = pr_ReadEntry(tt, 0, apos, aentry);
+    if (code) goto abort;
+
+    if (aentry->flags & PRCONT) {      /* wrong type, get coentry instead */
+       code = pr_ReadCoEntry(tt, 0, apos, aentry);
+       if (code) goto abort;
+    }
+    code = ubik_EndTrans(tt);
+    if (code) return code;
+    return PRSUCCESS;
+}
+
+PR_AddToGroup(call,aid,gid)
+struct rx_call *call;
+long aid;
+long gid;
+{
+    register long code;
+    struct ubik_trans *tt;
+    long tempu;
+    long tempg;
+    struct prentry tentry;
+    struct prentry uentry;
+    long cid;
+
+    code = Initdb();
+    if (code != PRSUCCESS) return code;
+    if (gid == ANYUSERID || gid == AUTHUSERID) return PRPERM;
+    if (aid == ANONYMOUSID) return PRPERM;
+    code = ubik_BeginTrans(dbase,UBIK_WRITETRANS,&tt);
+    if (code) return code;
+    code = ubik_SetLock(tt,1,1,LOCKWRITE);
+    if (code) {
+       ubik_AbortTrans(tt);
+       return code;
+    }
+    code = WhoIsThis(call, tt, &cid);
+    if (code) {
+       ubik_AbortTrans(tt);
+       return PRPERM;
+    }
+    tempu = FindByID(tt,aid);
+    if (!tempu) { 
+       ubik_AbortTrans(tt);
+       return PRNOENT;
+    }
+    bzero(&uentry,sizeof(uentry));
+    code = pr_ReadEntry(tt,0,tempu,&uentry);
+    if (code != 0)  {
+       ubik_AbortTrans(tt);
+       return code;
+    }
+    /* we don't allow groups as members of groups at present */
+    if (uentry.flags & PRGRP) {
+       ubik_AbortTrans(tt);
+       return PRNOTUSER;
+    }
+    tempg = FindByID(tt,gid);
+    if (!tempg) {
+       ubik_AbortTrans(tt);
+       return PRNOENT;
+    }
+    code = pr_ReadEntry(tt,0,tempg,&tentry);
+    if (code != 0) {
+       ubik_AbortTrans(tt);
+       return code;
+    }
+    /* make sure that this is a group */
+    if (!(tentry.flags & PRGRP)) {
+       ubik_AbortTrans(tt);
+       return PRNOTGROUP;
+    }
+    if (!AccessOK (tt, cid, &tentry, PRP_ADD_MEM, PRP_ADD_ANY)) {
+       ubik_AbortTrans(tt);
+       return PRPERM;
+    }
+    
+    code = AddToEntry (tt, &tentry, tempg, aid);
+    if (code != PRSUCCESS) {
+       ubik_AbortTrans(tt);
+       return code;
+    }
+    /* now, modify the user's entry as well */
+    code = AddToEntry (tt, &uentry, tempu, gid);
+    if (code != PRSUCCESS) {
+       ubik_AbortTrans(tt);
+       return code;
+    }
+    code = ubik_EndTrans(tt);
+    if (code) return code;
+    return PRSUCCESS;
+}
+
+long PR_NameToID (call, aname, aid)
+  struct rx_call *call;
+  namelist *aname;
+  idlist *aid;
+{
+    register long code;
+    struct ubik_trans *tt;
+    long i;
+    int size;
+    int count = 0;
+
+    /* must do this first for RPC stub to work */
+    size = aname->namelist_len;
+    if ((size <= 0) || (size > PR_MAXLIST)) size = 0;
+    aid->idlist_val = (long *)malloc(size*sizeof(long));
+    aid->idlist_len = 0;
+    if (aname->namelist_len == 0) return 0;
+    if (size == 0) return PRTOOMANY;   /* rxgen will probably handle this */
+
+    code = Initdb();
+    if (code != PRSUCCESS) return code;
+    code = ubik_BeginTrans(dbase,UBIK_READTRANS,&tt);
+    if (code) return code;
+    code = ubik_SetLock(tt,1,1,LOCKREAD);
+    if (code) {
+       ubik_AbortTrans(tt);
+       return code;
+    }
+    for (i=0;i<aname->namelist_len;i++) {
+       code = NameToID(tt,aname->namelist_val[i],&aid->idlist_val[i]);
+       if (code != PRSUCCESS) aid->idlist_val[i] = ANONYMOUSID;
+       if (count++ > 50) IOMGR_Poll(), count = 0;
+    }
+    aid->idlist_len = aname->namelist_len;
+
+    code = ubik_EndTrans(tt);
+    if (code) return code;
+    return PRSUCCESS;
+}
+
+long PR_IDToName (call, aid, aname)
+  struct rx_call *call;
+  idlist *aid;
+  namelist *aname;
+{
+    register long code;
+    struct ubik_trans *tt;
+    long i;
+    int size;
+    int count = 0;
+
+    /* leave this first for rpc stub */
+    size = aid->idlist_len;
+    if ((size <= 0) || (size > PR_MAXLIST)) size = 0;
+    aname->namelist_val = (prname *)malloc(size*PR_MAXNAMELEN);
+    aname->namelist_len = 0;
+    if (aid->idlist_len == 0) return 0;
+    if (size == 0) return PRTOOMANY;   /* rxgen will probably handle this */
+
+    code = Initdb();
+    if (code != PRSUCCESS) return code;
+    code = ubik_BeginTrans(dbase,UBIK_READTRANS,&tt);
+    if (code) return code;
+    code = ubik_SetLock(tt,1,1,LOCKREAD);
+    if (code) {
+       ubik_AbortTrans(tt);
+       return code;
+    }
+    for (i=0;i<aid->idlist_len;i++) {
+       /* interface won't allow more than PR_MAXLIST to be sent in */
+       code = IDToName(tt,aid->idlist_val[i],aname->namelist_val[i]);
+       if (code != PRSUCCESS)
+           sprintf(aname->namelist_val[i],"%d",aid->idlist_val[i]);
+       if (count++ > 50) IOMGR_Poll(), count = 0;
+    }
+    aname->namelist_len = aid->idlist_len;
+
+    code = ubik_EndTrans(tt);
+    if (code) return code;
+    return PRSUCCESS;
+}
+
+long PR_Delete (call, aid)
+  struct rx_call *call;
+  long aid;
+{
+    register long code;
+    struct ubik_trans *tt;
+    long cid;
+    struct prentry tentry;
+    long loc, nptr;
+    int count;
+
+    code = Initdb();
+    if (code) return code;
+    if (code != PRSUCCESS) return code;
+    if (aid == SYSADMINID || aid == ANYUSERID || aid == AUTHUSERID || aid == ANONYMOUSID) return PRPERM;
+    code = ubik_BeginTrans(dbase,UBIK_WRITETRANS,&tt);
+    if (code) return code;
+    code = ubik_SetLock(tt,1,1,LOCKWRITE);
+    if (code) {
+      abort:
+       ubik_AbortTrans(tt);
+       return code;
+    }
+    code = WhoIsThis(call,tt,&cid);
+    if (code) {
+       ubik_AbortTrans(tt);
+       return PRPERM;
+    }
+
+    /* Read in entry to be deleted */
+    loc = FindByID (tt, aid);
+    if (loc == 0) {code = PRNOENT; goto abort;}
+    code = pr_ReadEntry (tt, 0, loc, &tentry);
+    if (code) {code = PRDBFAIL; goto abort;}
+
+    /* Do some access checking */
+    if (tentry.owner != cid &&
+       !IsAMemberOf (tt, cid, SYSADMINID) &&
+       !IsAMemberOf (tt, cid, tentry.owner) && !pr_noAuth)
+       {code = PRPERM; goto abort;}
+
+    /* Delete each continuation block as a separate transaction so that no one
+     * transaction become to large to complete. */
+    nptr = tentry.next;
+    while (nptr != NULL) {
+       struct contentry centry;
+       int i;
+
+       code = pr_ReadCoEntry(tt, 0, nptr, &centry);
+       if (code != 0) {code = PRDBFAIL; goto abort;}
+       for (i=0;i<COSIZE;i++) {
+           if (centry.entries[i] == PRBADID) continue;
+           if (centry.entries[i] == 0) break;
+           code = RemoveFromEntry (tt, aid, centry.entries[i]);
+           if (code) goto abort;
+           tentry.count--;             /* maintain count */
+           if ((i&3) == 0) IOMGR_Poll();
+       }
+       tentry.next = centry.next;      /* thread out this block */
+       code = FreeBlock (tt, nptr);    /* free continuation block */
+       if (code) goto abort;
+       code = pr_WriteEntry (tt, 0, loc, &tentry); /* update main entry */
+       if (code) goto abort;
+
+       /* end this trans and start a new one */
+       code = ubik_EndTrans(tt);
+       if (code) return code;
+       IOMGR_Poll();                   /* just to keep the connection alive */
+       code = ubik_BeginTrans(dbase,UBIK_WRITETRANS,&tt);
+       if (code) return code;
+       code = ubik_SetLock(tt,1,1,LOCKWRITE);
+       if (code) goto abort;
+
+       /* re-read entry to get consistent uptodate info */
+       loc = FindByID (tt, aid);
+       if (loc == 0) {code = PRNOENT; goto abort;}
+       code = pr_ReadEntry (tt, 0, loc, &tentry);
+       if (code) {code = PRDBFAIL; goto abort;}
+
+       nptr = tentry.next;
+    }
+
+    /* Then move the owned chain, except possibly ourself to the orphan list.
+     * Because this list can be very long and so exceed the size of a ubik
+     * transaction, we start a new transaction every 50 entries. */
+    count = 0;
+    nptr = tentry.owned;
+    while (nptr != NULL) {
+       struct prentry nentry;
+
+       code = pr_ReadEntry (tt, 0, nptr, &nentry);
+       if (code) {code = PRDBFAIL; goto abort;}
+       nptr = tentry.owned = nentry.nextOwned; /* thread out */
+       
+       if (nentry.id != tentry.id) {   /* don't add us to orphan chain! */
+           code = AddToOrphan (tt, nentry.id);
+           if (code) goto abort;
+           count++;
+           if ((count & 3) == 0) IOMGR_Poll();
+       }
+       if (count < 50) continue;
+       code = pr_WriteEntry (tt, 0, loc, &tentry); /* update main entry */
+       if (code) goto abort;
+
+       /* end this trans and start a new one */
+       code = ubik_EndTrans(tt);
+       if (code) return code;
+       IOMGR_Poll();                   /* just to keep the connection alive */
+       code = ubik_BeginTrans(dbase,UBIK_WRITETRANS,&tt);
+       if (code) return code;
+       code = ubik_SetLock(tt,1,1,LOCKWRITE);
+       if (code) goto abort;
+
+       /* re-read entry to get consistent uptodate info */
+       loc = FindByID (tt, aid);
+       if (loc == 0) {code = PRNOENT; goto abort;}
+       code = pr_ReadEntry (tt, 0, loc, &tentry);
+       if (code) {code = PRDBFAIL; goto abort;}
+
+       nptr = tentry.owned;
+    }
+
+    /* now do what's left of the deletion stuff */
+    code = DeleteEntry (tt, &tentry, loc);
+    if (code != PRSUCCESS) {
+       ubik_AbortTrans(tt);
+       return code;
+    }
+    code = ubik_EndTrans(tt);
+    if (code) return code;
+    return PRSUCCESS;
+}
+
+PR_RemoveFromGroup(call,aid,gid)
+struct rx_call *call;
+long aid;
+long gid;
+{
+    register long code;
+    struct ubik_trans *tt;
+    long tempu;
+    long tempg;
+    struct prentry uentry;
+    struct prentry gentry;
+    long cid;
+
+    code = Initdb();
+    if (code != PRSUCCESS) return code;
+    code = ubik_BeginTrans(dbase,UBIK_WRITETRANS,&tt);
+    if (code) return code;
+    code = ubik_SetLock(tt,1,1,LOCKWRITE);
+    if (code) {
+       ubik_AbortTrans(tt);
+       return code;
+    }
+    code = WhoIsThis(call,tt,&cid);
+    if (code) {
+       ubik_AbortTrans(tt);
+       return PRPERM;
+    }
+    tempu = FindByID(tt,aid);
+    if (!tempu) { 
+       ubik_AbortTrans(tt);
+       return PRNOENT;
+    }
+    tempg = FindByID(tt,gid);
+    if (!tempg) {
+       ubik_AbortTrans(tt);
+       return PRNOENT;
+    }
+    bzero(&uentry,sizeof(uentry));
+    bzero(&gentry,sizeof(gentry));
+    code = pr_ReadEntry(tt,0,tempu,&uentry);
+    if (code != 0) {
+       ubik_AbortTrans(tt);
+       return code;
+    }
+    code = pr_ReadEntry(tt,0,tempg,&gentry);
+    if (code != 0) {
+       ubik_AbortTrans(tt);
+       return code;
+    }
+    if (!(gentry.flags & PRGRP)) {
+       ubik_AbortTrans(tt);
+       return PRNOTGROUP;
+    }
+    if (uentry.flags & PRGRP) {
+       ubik_AbortTrans(tt);
+       return PRNOTUSER;
+    }
+    if (!AccessOK (tt, cid, &gentry, PRP_REMOVE_MEM, 0)) {
+       ubik_AbortTrans(tt);
+       return PRPERM;
+    }
+    code = RemoveFromEntry(tt,aid,gid);
+    if (code != PRSUCCESS) {
+       ubik_AbortTrans(tt);
+       return code;
+    }
+    code = RemoveFromEntry(tt,gid,aid);
+    if (code != PRSUCCESS) {
+       ubik_AbortTrans(tt);
+       return code;
+    }
+    code = ubik_EndTrans(tt);
+    if (code) return code;
+    return PRSUCCESS;
+}
+
+long PR_GetCPS (call, aid, alist, over)
+  struct rx_call *call;
+  long aid;
+  prlist *alist;
+  long *over;
+{
+    register long code;
+    struct ubik_trans *tt;
+    long temp;
+    long cid;
+    struct prentry tentry;
+
+    alist->prlist_len = 0;
+    alist->prlist_val = (long *) 0;
+    code = Initdb();
+    if (code != PRSUCCESS) goto done;
+    code = ubik_BeginTrans(dbase,UBIK_READTRANS,&tt);
+    if (code) goto done;
+    code = ubik_SetLock(tt,1,1,LOCKREAD);
+    if (code) {
+      abort:
+       ubik_AbortTrans(tt);
+       goto done;
+    }
+
+
+    temp = FindByID(tt,aid);
+    if (!temp) {code = PRNOENT; goto abort;}
+    code = pr_ReadEntry (tt, 0, temp, &tentry);
+    if (code) goto abort;
+
+    if (0) {                           /* afs doesn't authenticate yet */
+       code = WhoIsThis (call, tt, &cid);
+       if (code || !AccessOK (tt, cid, &tentry, PRP_MEMBER_MEM, PRP_MEMBER_ANY)) {
+           code = PRPERM;
+           goto abort;
+       }
+    }
+       
+    code = GetList(tt, &tentry, alist, 1);
+    *over = 0;
+    if (code == PRTOOMANY) *over = 1;
+    else if (code != PRSUCCESS) {
+       ubik_AbortTrans(tt);
+       goto done;
+    }
+
+    code = ubik_EndTrans(tt);
+
+done:
+    /* return code, making sure that prlist_val points to malloc'd memory */
+    if (!alist->prlist_val)
+       alist->prlist_val = (long *) malloc(0); /* make xdr stub happy */
+    return code;
+}
+
+PR_ListMax(call,uid,gid)
+struct rx_call *call;
+long *uid;
+long *gid;
+{
+    register long code;
+    struct ubik_trans *tt;
+
+    code = Initdb();
+    if (code != PRSUCCESS) return code;
+    code = ubik_BeginTrans(dbase,UBIK_READTRANS,&tt);
+    if (code) return code;
+    code = ubik_SetLock(tt,1,1,LOCKREAD);
+    if (code) {
+       ubik_AbortTrans(tt);
+       return code;
+    }
+    code = GetMax(tt,uid,gid);
+    if (code != PRSUCCESS) {
+       ubik_AbortTrans(tt);
+       return code;
+    }
+    code = ubik_EndTrans(tt);
+    if (code) return code;
+    return PRSUCCESS;
+}
+
+PR_SetMax(call,aid,gflag)
+struct rx_call *call;
+long aid;
+long gflag;
+{
+    register long code;
+    struct ubik_trans *tt;
+    long cid;
+
+    code = Initdb();
+    if (code != PRSUCCESS) return code;
+    code = ubik_BeginTrans(dbase,UBIK_WRITETRANS,&tt);
+    if (code) return code;
+    code = ubik_SetLock(tt,1,1,LOCKWRITE);
+    if (code) {
+       ubik_AbortTrans(tt);
+       return code;
+    }
+    code = WhoIsThis(call,tt,&cid);
+    if (code) {
+       ubik_AbortTrans(tt);
+       return PRPERM;
+    }
+    if (!AccessOK (tt, cid, 0, 0, 0)) {
+       ubik_AbortTrans(tt);
+       return PRPERM;
+    }
+    if (((gflag & PRGRP) && (aid > 0)) ||
+       (!(gflag & PRGRP) && (aid < 0))) {
+       code = PRBADARG;
+       goto abort;
+    }
+
+    code = SetMax(tt,aid,gflag);
+    if (code != PRSUCCESS) {
+      abort:
+       ubik_AbortTrans(tt);
+       return code;
+    }
+    code = ubik_EndTrans(tt);
+    if (code) return code;
+    return PRSUCCESS;
+}
+
+PR_ListEntry(call,aid,aentry)
+struct rx_call *call;
+long aid;
+struct prcheckentry *aentry;
+{
+    register long code;
+    struct ubik_trans *tt;
+    long cid;
+    long temp;
+    struct prentry tentry;
+
+    code = Initdb();
+    if (code != PRSUCCESS) return code;
+    code = ubik_BeginTrans(dbase,UBIK_READTRANS,&tt);
+    if (code) return code;
+    code = ubik_SetLock(tt,1,1,LOCKREAD);
+    if (code) {
+       ubik_AbortTrans(tt);
+       return code;
+    }
+    code = WhoIsThis(call,tt,&cid);
+    if (code) {
+      perm:
+       ubik_AbortTrans(tt);
+       return PRPERM;
+    }
+    temp = FindByID(tt,aid);
+    if (!temp) { 
+       ubik_AbortTrans(tt);
+       return PRNOENT;
+    }
+    code = pr_ReadEntry(tt, 0, temp, &tentry);
+    if (code != 0) {
+       ubik_AbortTrans(tt);
+       return code;
+    } 
+    if (!AccessOK (tt, cid, &tentry, PRP_STATUS_MEM, PRP_STATUS_ANY)) goto perm;
+
+    aentry->flags = tentry.flags >> PRIVATE_SHIFT;
+    if (aentry->flags == 0)
+       if (tentry.flags & PRGRP)
+           aentry->flags = PRP_GROUP_DEFAULT >> PRIVATE_SHIFT;
+       else aentry->flags = PRP_USER_DEFAULT >> PRIVATE_SHIFT;
+    aentry->flags;
+    aentry->owner = tentry.owner;
+    aentry->id = tentry.id;
+    strncpy(aentry->name,tentry.name,PR_MAXNAMELEN);
+    aentry->creator = tentry.creator;
+    aentry->ngroups = tentry.ngroups;
+    aentry->nusers = tentry.nusers;
+    aentry->count = tentry.count;
+    bzero (aentry->reserved, sizeof(aentry->reserved));
+    code = ubik_EndTrans(tt);
+    if (code) return code;
+    return PRSUCCESS;
+}
+
+PR_ChangeEntry(call,aid,name,oid,newid)
+struct rx_call *call;
+long aid;
+char *name;
+long oid;
+long newid;
+{
+    register long code;
+    struct ubik_trans *tt;
+    long pos;
+    long cid;
+
+    stolower(name);
+    code = Initdb();
+    if (code) return code;
+    if (aid == ANYUSERID || aid == AUTHUSERID || aid == ANONYMOUSID || aid == SYSADMINID) return PRPERM;
+    if (code != PRSUCCESS) return code;
+    code = ubik_BeginTrans(dbase,UBIK_WRITETRANS,&tt);
+    if (code) return code;
+    code = ubik_SetLock(tt,1,1,LOCKWRITE);
+    if (code) {
+       ubik_AbortTrans(tt);
+       return code;
+    }
+    code = WhoIsThis(call,tt,&cid);
+    if (code) {
+       ubik_AbortTrans(tt);
+       return PRPERM;
+    }
+    pos = FindByID(tt,aid);
+    if (!pos) { 
+       ubik_AbortTrans(tt);
+       return PRNOENT;
+    }
+    /* protection check in changeentry */
+    code = ChangeEntry(tt,aid,cid,name,oid,newid);
+    if (code != PRSUCCESS) {
+       ubik_AbortTrans(tt);
+       return code;
+    }
+    code = ubik_EndTrans(tt);
+    return code;
+}
+
+PR_SetFieldsEntry(call, id, mask, flags, ngroups, nusers, spare1, spare2)
+  struct rx_call *call;
+  long id;
+  long mask;                           /* specify which fields to update */
+  long flags, ngroups, nusers;
+  long spare1, spare2;
+{
+    register long code;
+    struct ubik_trans *tt;
+    long pos;
+    long cid;
+    struct prentry tentry;
+    long tflags;
+
+    if (mask == 0) return 0;           /* no-op */
+    code = Initdb();
+    if (code) return code;
+    if (id == ANYUSERID || id == AUTHUSERID || id == ANONYMOUSID)
+       return PRPERM;
+    if (code != PRSUCCESS) return code;
+    code = ubik_BeginTrans(dbase,UBIK_WRITETRANS,&tt);
+    if (code) return code;
+    code = ubik_SetLock(tt,1,1,LOCKWRITE);
+    if (code) {
+      abort:
+       ubik_AbortTrans(tt);
+       return code;
+    }
+    code = WhoIsThis(call,tt,&cid);
+    if (code) {
+      perm:
+       ubik_AbortTrans(tt);
+       return PRPERM;
+    }
+    pos = FindByID(tt,id);
+    if (!pos) { 
+       ubik_AbortTrans(tt);
+       return PRNOENT;
+    }
+    code = pr_ReadEntry (tt, 0, pos, &tentry);
+    if (code) goto abort;
+    tflags = tentry.flags;
+
+    if (mask & (PR_SF_NGROUPS | PR_SF_NUSERS)) {
+       if (!AccessOK (tt, cid, 0, 0, 0)) goto perm;
+       if ((tflags & PRQUOTA) == 0) {  /* default if only setting one */
+           tentry.ngroups = tentry.nusers = 20;
+       }
+    } else {
+       if (!AccessOK (tt, cid, &tentry, 0, 0)) goto perm;
+    }
+
+    if (mask & 0xffff) {               /* if setting flag bits */
+       long flagsMask = mask & 0xffff;
+       tflags &= ~(flagsMask << PRIVATE_SHIFT);
+       tflags |= (flags & flagsMask) << PRIVATE_SHIFT;
+       tflags |= PRACCESS;
+    }
+
+    if (mask & PR_SF_NGROUPS) {                /* setting group limit */
+       if (ngroups < 0) {code = PRBADARG; goto abort;}
+       tentry.ngroups = ngroups;
+       tflags |= PRQUOTA;
+    }
+
+    if (mask & PR_SF_NUSERS) {         /* setting foreign user limit */
+       if (nusers < 0) {code = PRBADARG; goto abort;}
+       tentry.nusers = nusers;
+       tflags |= PRQUOTA;
+    }
+    tentry.flags = tflags;
+
+    code = pr_WriteEntry (tt, 0, pos, &tentry);
+    if (code) goto abort;
+
+    code = ubik_EndTrans(tt);
+    return code;
+}
+
+long PR_ListElements (call, aid, alist, over)
+  struct rx_call *call;
+  long aid;
+  prlist *alist;
+  long *over;
+{
+    register long code;
+    struct ubik_trans *tt;
+    long cid;
+    long temp;
+    struct prentry tentry;
+
+    alist->prlist_len = 0;
+    alist->prlist_val = (long *) 0;
+
+    code = Initdb();
+    if (code != PRSUCCESS) goto done;
+    code = ubik_BeginTrans(dbase,UBIK_READTRANS,&tt);
+    if (code) goto done;
+    code = ubik_SetLock(tt,1,1,LOCKREAD);
+    if (code) {
+      abort:
+       ubik_AbortTrans(tt);
+       goto done;
+    }
+    code = WhoIsThis(call,tt,&cid);
+    if (code) {
+      perm:
+       code = PRPERM;
+       ubik_AbortTrans(tt);
+       goto done;
+    }
+
+    temp = FindByID(tt,aid);
+    if (!temp) {code = PRNOENT; goto abort;}
+    code = pr_ReadEntry (tt, 0, temp, &tentry);
+    if (code) goto abort;
+    if (!AccessOK (tt, cid, &tentry, PRP_MEMBER_MEM, PRP_MEMBER_ANY))
+       goto perm;
+       
+    code = GetList (tt, &tentry, alist, 0);
+    *over = 0;
+    if (code == PRTOOMANY) *over = 1;
+    else if (code != PRSUCCESS) goto abort;
+
+    code = ubik_EndTrans(tt);
+
+done:
+    if (!alist->prlist_val)
+       alist->prlist_val = (long *) malloc(0); /* make calling stub happy */
+    return code;
+}
+
+/* List the entries owned by this id.  If the id is zero return the orphans
+ * list. */
+
+PR_ListOwned (call, aid, alist, over)
+  struct rx_call *call;
+  long aid;
+  prlist *alist;
+  long *over;
+{
+    register long code;
+    struct ubik_trans *tt;
+    long cid;
+    struct prentry tentry;
+    long head;
+
+    alist->prlist_len = 0;
+    alist->prlist_val = (long *) 0;
+
+    code = Initdb();
+    if (code != PRSUCCESS) goto done;
+    code = ubik_BeginTrans(dbase,UBIK_READTRANS,&tt);
+    if (code) goto done;
+    code = ubik_SetLock(tt,1,1,LOCKREAD);
+    if (code) {
+      abort:
+       ubik_AbortTrans(tt);
+       goto done;
+    }
+    code = WhoIsThis(call,tt,&cid);
+    if (code) {
+      perm:
+       code = PRPERM;
+       ubik_AbortTrans(tt);
+       goto done;
+    }
+
+    if (aid) {
+       long loc = FindByID (tt, aid);
+       if (loc == 0) { code =  PRNOENT; goto abort; }
+       code = pr_ReadEntry (tt, 0, loc, &tentry);
+       if (code) goto abort;
+;
+       if (!AccessOK (tt, cid, &tentry, -1, PRP_OWNED_ANY)) goto perm;
+       head = tentry.owned;
+    } else {
+       if (!AccessOK (tt, cid, 0, 0, 0)) goto perm;
+       head = ntohl(cheader.orphan);
+    }
+
+    code = GetOwnedChain (tt, head, alist);
+    *over = 0;
+    if (code == PRTOOMANY) *over = 1;
+    else if (code) goto abort;
+
+    code = ubik_EndTrans(tt);
+
+done:
+    if (!alist->prlist_val)
+       alist->prlist_val = (long *) malloc(0); /* make calling stub happy */
+    return code;
+}
+
+PR_IsAMemberOf(call,uid,gid,flag)
+struct rx_call *call;
+long uid;
+long gid;
+long *flag;
+{
+    register long code;
+    struct ubik_trans *tt;
+
+    code = Initdb();
+    if (code != PRSUCCESS) return code;
+    code = ubik_BeginTrans(dbase,UBIK_READTRANS,&tt);
+    if (code) return code;
+    code = ubik_SetLock(tt,1,1,LOCKREAD);
+    if (code) {
+      abort:
+       ubik_AbortTrans(tt);
+       return code;
+    }
+    {  long cid;
+       long uloc = FindByID (tt, uid);
+       long gloc = FindByID (tt, gid);
+       struct prentry uentry, gentry;
+
+       if (!uloc || !gloc) {
+           code = PRNOENT;
+           goto abort;
+       }
+       code = WhoIsThis(call, tt, &cid);
+       if (code) {
+         perm:
+           code = PRPERM;
+           goto abort;
+       }
+       code = pr_ReadEntry (tt, 0, uloc, &uentry);
+       if (code) goto abort;
+       code = pr_ReadEntry (tt, 0, gloc, &gentry);
+       if (code) goto abort;
+       if ((uentry.flags & PRGRP) || !(gentry.flags & PRGRP)) {
+           code = PRBADARG;
+           goto abort;
+       }
+       if (!AccessOK (tt, cid, &uentry, 0, PRP_MEMBER_ANY) &&
+           !AccessOK (tt, cid, &gentry, PRP_MEMBER_MEM, PRP_MEMBER_ANY)) goto perm;
+    }
+       
+    *flag = IsAMemberOf(tt,uid,gid);
+    code = ubik_EndTrans(tt);
+    return code;
+}
+
+
+static stolower(s)
+register char *s;
+{
+    register int tc;
+    while (tc = *s) {
+       if (isupper(tc)) *s = tolower(tc);
+       s++;
+    }
+}
index a8e2b3418940348cff81f1d738124df23f2092e5..ef6e3d6bcb706b33a830f7443dccb054a43aead4 100644 (file)
@@ -1,13 +1,14 @@
-/* $Header$ */
-/* $Source$ */
-
-
+/* Copyright (C) 1989 Transarc Corporation - All rights reserved */
 /*
  * P_R_P_Q_# (C) COPYRIGHT IBM CORPORATION 1988
  * LICENSED MATERIALS - PROPERTY OF IBM
  * REFER TO COPYRIGHT INSTRUCTIONS FORM NUMBER G120-2083
  */
 
+#ifndef lint
+static char rcsid[] = "$Header$";
+#endif
+
 /*     
              Sherri Nichols
              Information Technology Center
 
 */
 
+#include <afs/param.h>
+#include <sys/types.h>
 #include <stdio.h>
-#include <strings.h>
 #include <lock.h>
-#define UBIK_INTERNALS
+#include <netinet/in.h>
 #include <ubik.h>
 #include <rx/xdr.h>
-#include "print.h"
-#include "prserver.h"
-#include "prerror.h"
-#include <netinet/in.h>
+#include <afs/com_err.h>
+#include "ptserver.h"
+#include "pterror.h"
+#include <strings.h>
 
-extern struct prheader cheader;
 extern struct ubik_dbase *dbase;
 extern struct afsconf_dir *prdir;
+extern int pr_noAuth;
 
-long CreateEntry(at, aname, aid, idflag,flag,oid,creator)  
-register struct ubik_trans *at;
-char aname[PR_MAXNAMELEN];
-long *aid;
-long idflag;
-long flag;
-long oid;
-long creator;
+static char *whoami = "ptserver";
+
+/* CorrectUserName - Check to make sure a user name is OK.  It must not include
+ *   either a colon (or it would look like a group) or an atsign (or it would
+ *   look like a foreign user).  The length is checked as well to make sure
+ *   that the user name, an atsign, and the local cell name will fit in
+ *   PR_MAXNAMELEN.  This is so this user can fit in another cells database as
+ *   a foreign user with our cell name tacked on.  This is a predicate, so it
+ *   return one if name is OK and zero if name is bogus. */
+
+static int CorrectUserName (name)
+  char *name;
+{
+    extern int pr_realmNameLen;
+
+    if (index (name, ':') || index(name, '@') || index(name, '\n')) return 0;
+    if (strlen (name) >= PR_MAXNAMELEN - pr_realmNameLen - 1) return 0; 
+    return 1;
+}
+
+static long CorrectGroupName (ut, aname, cid, oid, cname)
+  struct ubik_trans *ut;
+  char aname[PR_MAXNAMELEN];           /* name for group */
+  long cid;                            /* caller id */
+  long oid;                            /* owner of group */
+  char cname[PR_MAXNAMELEN];           /* correct name for group */
+{
+    long  code;
+    int   admin;
+    char *prefix;                      /* ptr to group owner part */
+    char *suffix;                      /* ptr to group name part */
+    char  name[PR_MAXNAMELEN];         /* correct name for group */
+    struct prentry tentry;
+
+    if (strlen (aname) >= PR_MAXNAMELEN) return PRBADNAM;
+    admin = pr_noAuth || IsAMemberOf (ut, cid, SYSADMINID);
+
+    if (oid == 0) oid = cid;
+
+    /* Determine the correct prefix for the name. */
+    if (oid == SYSADMINID) prefix = "system";
+    else {
+       long loc = FindByID (ut, oid);
+       if (loc == 0) {
+           /* let admin create groups owned by non-existent ids (probably
+             * setting a group to own itself).  Check that they look like
+             * groups (with a colon) or otherwise are good user names. */
+           if (admin) {
+               strcpy (cname, aname);
+               goto done;
+           }
+           return PRNOENT;
+       }
+       code = pr_Read (ut, 0, loc, &tentry, sizeof(tentry));
+       if (code) return code;
+       if (ntohl(tentry.flags) & PRGRP) {
+           if ((tentry.count == 0) && !admin) return PRGROUPEMPTY;
+           /* terminate prefix at colon if there is one */
+           if (prefix = index(tentry.name, ':')) *prefix = 0;
+       }
+       prefix = tentry.name;
+    }
+    /* only sysadmin allow to use 'system:' prefix */
+    if ((strcmp (prefix, "system") == 0) && !admin) return PRPERM;
+
+    strcpy (name, aname);              /* in case aname & cname are same */
+    suffix = index(name, ':');
+    if (suffix == 0) {
+       /* sysadmin can make groups w/o ':', but they must still look like
+         * legal user names. */
+       if (!admin) return PRBADNAM;
+       strcpy (cname, name);
+    }
+    else {
+       if (strlen(prefix)+strlen(suffix) >= PR_MAXNAMELEN) return PRBADNAM;
+       strcpy (cname, prefix);
+       strcat (cname, suffix);
+    }
+  done:
+    /* check for legal name with either group rules or user rules */
+    if (suffix = index(cname, ':')) {
+       /* check for confusing characters */
+       if (index(cname, '@') ||        /* avoid confusion w/ foreign users */
+           index(cname, '\n') ||       /* restrict so recreate can work */
+           index(suffix+1, ':'))       /* avoid multiple colons */
+           return PRBADNAM;
+    } else {
+       if (!CorrectUserName (cname)) return PRBADNAM;
+    }
+    return 0;
+}
+
+int AccessOK (ut, cid, tentry, mem, any)
+  struct ubik_trans *ut;
+  long cid;                            /* caller id */
+  struct prentry *tentry;              /* object being accessed */
+  int mem;                             /* check membership in aid, if group */
+  int any;                             /* if set return true */
+{   long flags;
+    long oid;
+    long aid;
+
+    if (pr_noAuth) return 1;
+    if (tentry) {
+       flags = tentry->flags;
+       oid = tentry->owner;
+       aid = tentry->id;
+    } else {
+       flags = oid = aid = 0;
+    }
+    if (!(flags & PRACCESS))           /* provide default access */
+       if (flags & PRGRP)
+           flags |= PRP_GROUP_DEFAULT;
+       else
+           flags |= PRP_USER_DEFAULT;
+
+    if (flags & any) return 1;
+    if (oid) {
+       if ((cid == oid) ||
+           IsAMemberOf (ut, cid, oid)) return 1;
+    }
+    if (aid > 0) {                     /* checking on a user */
+       if (aid == cid) return 1;
+    } else if (aid < 0) {              /* checking on group */
+       if ((flags & mem) && IsAMemberOf (ut, cid, aid)) return 1;
+    }
+    if (IsAMemberOf (ut, cid, SYSADMINID)) return 1;
+    return 0;                          /* no access */
+}
+
+long CreateEntry (at, aname, aid, idflag, flag, oid, creator)  
+  register struct ubik_trans *at;
+  char aname[PR_MAXNAMELEN];
+  long *aid;
+  long idflag;
+  long flag;
+  long oid;
+  long creator;
 {
     /* get and init a new entry */
     register long code;
@@ -49,8 +181,25 @@ long creator;
     struct prentry tentry;
     
     bzero(&tentry, sizeof(tentry));
+
+    if ((oid == 0) || (oid == ANONYMOUSID)) oid = creator;
+
+    if (flag & PRGRP) {
+       code = CorrectGroupName (at, aname, creator, oid, tentry.name);
+       if (code) return code;
+       if (strcmp (aname, tentry.name) != 0)  return PRBADNAM;
+    } else {                           /* non-group must not have colon */
+       if (!CorrectUserName(aname)) return PRBADNAM;
+       strcpy (tentry.name, aname);
+    }
+
+    if (FindByName(at,aname)) return PREXIST;
+
     newEntry = AllocBlock(at);
     if (!newEntry) return PRDBFAIL;
+#ifdef PR_REMEMBER_TIMES
+    tentry.createTime = time(0);
+#endif
     if (flag & PRGRP) {
        tentry.flags |= PRGRP;
        tentry.owner = oid;
@@ -67,29 +216,64 @@ long creator;
        if (code != PRSUCCESS) return code;
     }
     if (flag & PRGRP) {
-       if (tentry.id < ntohl(cheader.maxGroup)) {
-           cheader.maxGroup = htonl(tentry.id);
-           code = pr_Write(at,0,16,(char *) &cheader.maxGroup,sizeof(cheader.maxGroup));
+       /* group ids are negative */
+       if (tentry.id < (long)ntohl(cheader.maxGroup)) {
+           code = set_header_word (at, maxGroup, htonl(tentry.id));
            if (code) return PRDBFAIL;
        }
     }
     else if (flag & PRFOREIGN) {
-       if (tentry.id > ntohl(cheader.maxForeign)) {
-           cheader.maxForeign = htonl(tentry.id);
-           code = pr_Write(at,0,24,(char *) &cheader.maxForeign,sizeof(cheader.maxForeign));
+       if (tentry.id > (long)ntohl(cheader.maxForeign)) {
+           code = set_header_word (at, maxForeign, htonl(tentry.id));
            if (code) return PRDBFAIL;
        }
     }
     else {
-       if (tentry.id > ntohl(cheader.maxID)) {
-           cheader.maxID = htonl(tentry.id);
-           code = pr_Write(at,0,20,(char *) &cheader.maxID,sizeof(cheader.maxID));
+       if (tentry.id > (long)ntohl(cheader.maxID)) {
+           code = set_header_word (at, maxID, htonl(tentry.id));
            if (code) return PRDBFAIL;
        }
     }
+    /* PRACCESS is off until set, defaults provided in AccessOK */
+    if (flag == 0) {                   /* only normal users get quota */
+       tentry.flags |= PRQUOTA;
+       tentry.ngroups = tentry.nusers = 20;
+    }
+
+    if (flag & (PRGRP | PRFOREIGN)) {
+       long loc = FindByID (at, creator);
+       struct prentry centry;
+       long *nP;                       /* ptr to entry to be decremented */
+       long  n;                        /* quota to check */
+
+       if (loc) { /* this should only fail during initialization */
+           code = pr_Read (at, 0, loc, &centry, sizeof(centry));
+           if (code) return code;
+
+           if (flag & PRGRP) nP = &centry.ngroups;
+           else if (flag & PRFOREIGN) nP = &centry.nusers;
+           else nP = 0;
+           
+           if (nP) {
+               if (!(ntohl(centry.flags) & PRQUOTA)) {
+                   /* quota uninitialized, so do it now */
+                   centry.flags = htonl (ntohl(centry.flags) | PRQUOTA);
+                   centry.ngroups = centry.nusers = htonl(20);
+               }
+               n = ntohl(*nP);
+               if (n <= 0) {
+                   if (!pr_noAuth &&
+                       !IsAMemberOf (at, creator, SYSADMINID))
+                       return PRNOMORE;
+               }
+               else *nP = htonl(n-1);
+           }
+           code = pr_Write (at, 0, loc, &centry, sizeof(centry));
+           if (code) return code;
+       } /* if (loc) */
+    } /* need to check creation quota */
     tentry.creator = creator;
     *aid = tentry.id;
-    strncpy(tentry.name, aname, PR_MAXNAMELEN);
     code = pr_WriteEntry(at, 0, newEntry, &tentry);
     if (code) return PRDBFAIL;
     code = AddToIDHash(at,*aid,newEntry);
@@ -101,55 +285,47 @@ long creator;
        if (code) return code;
     }
     if (tentry.flags & PRGRP) {
-        temp = ntohl(cheader.groupcount) + 1;
-       cheader.groupcount = htonl(temp);
-       code = pr_Write(at,0,40,(char *)&cheader.groupcount,sizeof(cheader.groupcount));
-       if (code) return PRDBFAIL;
+       if (inc_header_word (at, groupcount, 1)) return PRDBFAIL;
     }
     else if (tentry.flags & PRFOREIGN) {
-        temp = ntohl(cheader.foreigncount) + 1;
-       cheader.foreigncount = htonl(temp);
-       code = pr_Write(at,0,44,(char *)&cheader.foreigncount,sizeof(cheader.foreigncount));
-       if (code) return PRDBFAIL;
+       if (inc_header_word (at, foreigncount, 1)) return PRDBFAIL;
     }
     else if (tentry.flags & PRINST) {
-        temp = ntohl(cheader.instcount) + 1;
-       cheader.instcount = htonl(temp);
-       code = pr_Write(at,0,48,(char *)&cheader.instcount,sizeof(cheader.instcount));
-       if (code) return PRDBFAIL;
+       if (inc_header_word (at, instcount, 1)) return PRDBFAIL;
     }
     else {
-        temp = ntohl(cheader.usercount) + 1;
-       cheader.usercount = htonl(temp);
-       code = pr_Write(at,0,36,(char *)&cheader.usercount,sizeof(cheader.usercount));
-       if (code) return PRDBFAIL;
+       if (inc_header_word (at, usercount, 1)) return PRDBFAIL;
     }
     return PRSUCCESS;
 }
     
 
+/* RemoveFromEntry - remove aid from bid's entries list, freeing a continuation
+ * entry if appropriate */
 
-long RemoveFromEntry(at,aid,bid)
-register struct ubik_trans *at;
-register long aid;
-register long bid;
+long RemoveFromEntry (at, aid, bid)
+  register struct ubik_trans *at;
+  register long aid;
+  register long bid;
 {
-    /* remove aid from bid's entries list, freeing a continuation entry if appropriate */
-
     register long code;
     struct prentry tentry;
     struct contentry centry;
     struct contentry hentry;
     long temp;
-    long first;
     long i,j;
     long nptr;
-    long hloc = 0;
+    long hloc;
     
+    if (aid == bid) return PRINCONSISTENT;
     bzero(&hentry,sizeof(hentry));
     temp = FindByID(at,bid);
+    if (temp == 0) return PRNOENT;
     code = pr_ReadEntry(at, 0, temp, &tentry);
     if (code != 0) return code;
+#ifdef PR_REMEMBER_TIMES
+    tentry.removeTime = time(0);
+#endif
     for (i=0;i<PRSIZE;i++) {
        if (tentry.entries[i] == aid) {  
            tentry.entries[i] = PRBADID;
@@ -161,170 +337,171 @@ register long bid;
        if (tentry.entries[i] == 0)   /* found end of list */
            return PRNOENT;
     }
-    if (tentry.next != NULL) {
-       nptr = tentry.next;
-       first = 1;
-       while (nptr != NULL) {
-           code = pr_ReadCoEntry(at,0,nptr,&centry);
-           if (code != 0) return code;
-           for (i=0;i<COSIZE;i++) {
-               if (centry.entries[i] == aid) {
-                   centry.entries[i] = PRBADID;
-                   tentry.count--;
-                   code = pr_WriteEntry(at,0,temp,&tentry);
-                   if (code) return PRDBFAIL;
-                   for (j=0;j<COSIZE;j++)
-                       if (centry.entries[j] != PRBADID && centry.entries[j] != 0) break;
-                   if (j == COSIZE) {   /* can free this block */
-                       if (first) {
-                           tentry.next = centry.next;
-                           code = pr_WriteEntry(at,0,temp,&tentry);
-                           if (code != 0) return code;
-                       }
-                       else {
-                           hentry.next = centry.next;
-                           code = pr_WriteCoEntry(at,0,hloc,(char *) &hentry);
-                           if (code != 0) return code;
-                       }
-                       code = FreeBlock(at,nptr);
-                       return code;
+    hloc = 0;
+    nptr = tentry.next;
+    while (nptr != NULL) {
+       code = pr_ReadCoEntry(at,0,nptr,&centry);
+       if (code != 0) return code;
+       if ((centry.id != bid) || !(centry.flags & PRCONT)) return PRDBBAD;
+       for (i=0;i<COSIZE;i++) {
+           if (centry.entries[i] == aid) {
+               centry.entries[i] = PRBADID;
+               for (j=0;j<COSIZE;j++)
+                   if (centry.entries[j] != PRBADID &&
+                       centry.entries[j] != 0) break;
+               if (j == COSIZE) {   /* can free this block */
+                   if (hloc == 0) {
+                       tentry.next = centry.next;
                    }
-                   else { /* can't free it yet */
-                       code = pr_WriteCoEntry(at,0,nptr,&centry);
+                   else {
+                       hentry.next = centry.next;
+                       code = pr_WriteCoEntry (at, 0, hloc, &hentry);
                        if (code != 0) return code;
-                       return PRSUCCESS;
                    }
+                   code = FreeBlock (at, nptr);
+                   if (code) return code;
                }
-               if (centry.entries[i] == 0) return PRNOENT;
+               else { /* can't free it yet */
+                   code = pr_WriteCoEntry(at,0,nptr,&centry);
+                   if (code != 0) return code;
+               }
+               tentry.count--;
+               code = pr_WriteEntry(at,0,temp,&tentry);
+               if (code) return PRDBFAIL;
+               return 0;
            }
-           hloc = nptr;
-           nptr = centry.next;
-           bcopy(&centry,&hentry,sizeof(centry));
-       }
-    }
-    else return PRNOENT;
-    return PRSUCCESS;
+           if (centry.entries[i] == 0) return PRNOENT;
+       } /* for all coentry slots */
+       hloc = nptr;
+       nptr = centry.next;
+       bcopy(&centry,&hentry,sizeof(centry));
+    } /* while there are coentries */
+    return PRNOENT;
 }
 
-long DeleteEntry(at,aid,cid)
-register struct ubik_trans *at;
-long aid;
-long cid;
+/* DeleteEntry - delete the entry in tentry at loc, removing it from all
+ * groups, putting groups owned by it on orphan chain, and freeing the space */
+
+long DeleteEntry (at, tentry, loc)
+  register struct ubik_trans *at;
+  struct prentry *tentry;
+  long loc;
 {
-    /* delete the entry aid, removing it from all groups, putting groups owned by it on orphan chain, and freeing the space */
     register long code;
-    long temp;
     long temp1;
-    struct prentry tentry;
     struct contentry centry;
     struct prentry nentry;
     register long  i;
     long nptr;
-    long noAuth;
-
-    noAuth = afsconf_GetNoAuthFlag(prdir);
-    bzero(&tentry,sizeof(tentry));
-    temp = FindByID(at,aid);
-    if (!temp) return PRNOENT;
-    code = pr_ReadEntry(at,0,temp,&tentry);
-    if (code != 0) return PRDBFAIL;
-    if (tentry.owner != cid && !IsAMemberOf(at,cid,SYSADMINID) && !IsAMemberOf(at,cid,tentry.owner) && !noAuth) return PRPERM;
+
+    /* First remove the entire membership list */
     for (i=0;i<PRSIZE;i++) {
-       if (tentry.entries[i] == 0) break;
-       RemoveFromEntry(at,aid,tentry.entries[i]);
+       if (tentry->entries[i] == PRBADID) continue;
+       if (tentry->entries[i] == 0) break;
+       code = RemoveFromEntry (at, tentry->id, tentry->entries[i]);
+       if (code) return code;
     }
-    nptr = tentry.next;
+    nptr = tentry->next;
     while (nptr != NULL) {
        code = pr_ReadCoEntry(at,0,nptr,&centry);
        if (code != 0) return PRDBFAIL;
        for (i=0;i<COSIZE;i++) {
+           if (centry.entries[i] == PRBADID) continue;
            if (centry.entries[i] == 0) break;
-           RemoveFromEntry(at,aid,centry.entries[i]);
+           code = RemoveFromEntry (at, tentry->id, centry.entries[i]);
+           if (code) return code;
        }
+       code = FreeBlock (at, nptr);    /* free continuation block */
+       if (code) return code;
        nptr = centry.next;
     }
-    if (tentry.flags & PRGRP) {
-       if (FindByID(at,tentry.owner)) {
-           code = RemoveFromOwnerChain(at,aid,tentry.owner);
+
+    /* Remove us from other's owned chain.  Note that this will zero our owned
+     * field (on disk) so this step must follow the above step in case we are
+     * on our own owned list. */
+    if (tentry->flags & PRGRP) {
+       if (tentry->owner) {
+           code = RemoveFromOwnerChain (at, tentry->id, tentry->owner);
            if (code) return code;
        }
        else {
-           code = RemoveFromOrphan(at,aid);
+           code = RemoveFromOrphan (at, tentry->id);
            if (code) return code;
        }
     }
-    if (tentry.owned) {
-       nptr = tentry.owned;
-       while (nptr != NULL) {
-           code = pr_ReadEntry(at,0,nptr,&nentry);
-           if (code != 0) return PRDBFAIL;
-           if (nentry.id != aid)  /* don't add this entry to orphan chain! */
-               code = AddToOrphan(at,nentry.id);
-           nptr = nentry.nextOwned;
-       }
-    }
-    code = RemoveFromIDHash(at,tentry.id,&temp);
+
+    code = RemoveFromIDHash(at,tentry->id,&loc);
     if (code != PRSUCCESS) return code;
-    code = RemoveFromNameHash(at,tentry.name,&temp);
+    code = RemoveFromNameHash(at,tentry->name,&loc);
     if (code != PRSUCCESS) return code;
-   if (tentry.flags & PRGRP) {
-       temp1 = ntohl(cheader.groupcount) + 1;
-       cheader.groupcount = htonl(temp1);
-       code = pr_Write(at,0,40,(char *)&cheader.groupcount,sizeof(cheader.groupcount));
-       if (code) return PRDBFAIL;
+
+    if (tentry->flags & (PRGRP | PRFOREIGN)) {
+       long loc = FindByID (at, tentry->creator);
+       struct prentry centry;
+       if (loc) {
+           code = pr_Read (at, 0, loc, &centry, sizeof(centry));
+           if (code) return code;
+           if (ntohl(centry.flags) & PRQUOTA) {
+               if (tentry->flags & PRGRP) {
+                   centry.ngroups = htonl(ntohl(centry.ngroups) + 1);
+               } else if (tentry->flags & PRFOREIGN) {
+                   centry.nusers = htonl(ntohl(centry.nusers) + 1);
+               }
+           }
+           code = pr_Write (at, 0, loc, &centry, sizeof(centry));
+           if (code) return code;
+       }
     }
-    else if (tentry.flags & PRFOREIGN) {
-       temp1 = ntohl(cheader.foreigncount) + 1;
-       cheader.foreigncount = htonl(temp1);
-       code = pr_Write(at,0,44,(char *)&cheader.foreigncount,sizeof(cheader.foreigncount));
-       if (code) return PRDBFAIL;
+
+    if (tentry->flags & PRGRP) {
+       if (inc_header_word (at, groupcount, -1)) return PRDBFAIL;
     }
-    else if (tentry.flags & PRINST) {
-       temp1 = ntohl(cheader.instcount) + 1;
-       cheader.instcount = htonl(temp1);
-       code = pr_Write(at,0,48,(char *)&cheader.instcount,sizeof(cheader.instcount));
-       if (code) return PRDBFAIL;
+    else if (tentry->flags & PRFOREIGN) {
+       if (inc_header_word (at, foreigncount, -1)) return PRDBFAIL;
+    }
+    else if (tentry->flags & PRINST) {
+       if (inc_header_word (at, instcount, -1)) return PRDBFAIL;
     }
     else {
-       temp1 = ntohl(cheader.usercount) + 1;
-       cheader.usercount = htonl(temp1);
-       code = pr_Write(at,0,36,(char *)&cheader.usercount,sizeof(cheader.usercount));
-       if (code) return PRDBFAIL;
+       if (inc_header_word (at, usercount, -1)) return PRDBFAIL;
     }
-    FreeBlock(at,temp);
-    return PRSUCCESS;
+    code = FreeBlock(at, loc);
+    return code;
 }
 
+/* AddToEntry - add aid to entry's entries list, alloc'ing a continuation block
+ * if needed.
+ *
+ * Note the entry is written out by this routine. */
 
-
-
-long AddToEntry(tt,entry,loc,aid)
-struct ubik_trans *tt;
-struct prentry entry;
-long loc;
-long aid;
+long AddToEntry (tt, entry, loc, aid)
+  struct ubik_trans *tt;
+  struct prentry *entry;
+  long loc;
+  long aid;
 {
-    /* add aid to entry's entries list, alloc'ing a continuation block if needed */
     register long code;
     long i;
     struct contentry nentry;
     struct contentry aentry;
     long nptr;
-    long last = 0;
+    long last;                         /* addr of last cont. block */
     long first = 0;
     long cloc;
     long slot = -1;
 
-    bzero(&nentry,sizeof(nentry));
-    bzero(&aentry,sizeof(aentry));
+    if (entry->id == aid) return PRINCONSISTENT;
+#ifdef PR_REMEMBER_TIMES
+    entry->addTime = time(0);
+#endif
     for (i=0;i<PRSIZE;i++) {
-       if (entry.entries[i] == aid)
+       if (entry->entries[i] == aid)
            return PRIDEXIST;
-       if (entry.entries[i] == PRBADID) { /* remember this spot */
+       if (entry->entries[i] == PRBADID) { /* remember this spot */
            first = 1;
            slot = i;
        }
-       if (entry.entries[i] == 0) { /* end of the line */
+       else if (entry->entries[i] == 0) { /* end of the line */
            if (slot == -1) {
                first = 1;
                slot = i;
@@ -332,10 +509,12 @@ long aid;
            break;
        }
     }
-    nptr = entry.next;
+    last = 0;
+    nptr = entry->next;
     while (nptr != NULL) {
-       code = pr_ReadCoEntry(tt,0,nptr,&nentry);
+       code = pr_ReadCoEntry(tt,0,nptr,&nentry);
        if (code != 0) return code;
+       last = nptr;
        if (!(nentry.flags & PRCONT)) return PRDBFAIL;
        for (i=0;i<COSIZE;i++) {
            if (nentry.entries[i] == aid)
@@ -346,7 +525,7 @@ long aid;
                    cloc = nptr;
                }
            }
-           if (nentry.entries[i] == 0) {
+           else if (nentry.entries[i] == 0) {
                if (slot == -1) {
                    slot = i;
                    cloc = nptr;
@@ -354,18 +533,18 @@ long aid;
                break;
            }
        }
-       last = nptr;
        nptr = nentry.next;
     }
-    if (slot != -1) {  /* we found a place */
-       entry.count++;
+    if (slot != -1) {                  /* we found a place */
+       entry->count++;
        if (first) {  /* place is in first block */
-           entry.entries[slot] = aid;
-           code = pr_WriteEntry(tt,0,loc,&entry);
+           entry->entries[slot] = aid;
+           code = pr_WriteEntry (tt, 0, loc, entry);
            if (code != 0) return code;
            return PRSUCCESS;
        }
-       code = pr_WriteEntry(tt,0,loc,&entry);
+       code = pr_WriteEntry (tt, 0, loc, entry);
+       if (code) return code;
        code = pr_ReadCoEntry(tt,0,cloc,&aentry);
        if (code != 0) return code;
        aentry.entries[slot] = aid;
@@ -375,62 +554,73 @@ long aid;
     }
     /* have to allocate a continuation block if we got here */
     nptr = AllocBlock(tt);
-    if (nentry.flags & PRCONT) {
-       /* then we should tack new block here */
+    if (last) {
+       /* then we should tack new block after last block in cont. chain */
        nentry.next = nptr;
        code = pr_WriteCoEntry(tt,0,last,&nentry);
        if (code != 0) return code;
     }
     else {
-       entry.next = nptr;
-       code = pr_WriteEntry(tt,0,loc,&entry);
-       if (code != 0) return code;
+       entry->next = nptr;
     }
+    bzero(&aentry,sizeof(aentry));
     aentry.flags |= PRCONT;
-    aentry.id = entry.id;
+    aentry.id = entry->id;
     aentry.next = NULL;
     aentry.entries[0] = aid;
     code = pr_WriteCoEntry(tt,0,nptr,&aentry);
     if (code != 0) return code;
     /* don't forget to update count, here! */
-    entry.count++;
-    code = pr_WriteEntry(tt,0,loc,&entry);
-    return PRSUCCESS;
+    entry->count++;
+    code = pr_WriteEntry (tt, 0, loc, entry);
+    return code;
        
 }
 
-long GetList(at,aid,alist,add)
-struct ubik_trans *at;
-long aid;
-prlist *alist;
-long add;
+long AddToPRList (alist, sizeP, id)
+  prlist *alist;
+  int *sizeP;
+  long id;
+{
+    if (alist->prlist_len >= PR_MAXGROUPS) return PRTOOMANY;
+    if (alist->prlist_len >= *sizeP) {
+       *sizeP = *sizeP + 100;
+       if (*sizeP > PR_MAXGROUPS) *sizeP = PR_MAXGROUPS;
+       alist->prlist_val =
+           (long *) ((alist->prlist_val) ?
+                     realloc (alist->prlist_val, (*sizeP)*sizeof(long)) :
+                     malloc ((*sizeP)*sizeof(long)));
+    }
+    alist->prlist_val[alist->prlist_len++] = id;
+    return 0;
+}
+
+long GetList (at, tentry, alist, add)
+  struct ubik_trans *at;
+  struct prentry *tentry;
+  prlist *alist;
+  long add;
 {
     register long code;
-    long temp;
     long i;
-    long count;
-    struct prentry tentry;
     struct contentry centry;
     long nptr;
-    long size;
+    int size;
+    int count = 0;
     extern long IDCmp();
 
-    temp = FindByID(at,aid);
-    if (!temp) return PRNOENT;
-    code = pr_ReadEntry(at,0,temp,&tentry);
-    if (code != 0) return code;
-    alist->prlist_val = (long *)malloc(100*sizeof(long));
-    size = 100;
+    size = 0;
+    alist->prlist_val = 0;
     alist->prlist_len = 0;
-    count = 0;
+
     for (i=0;i<PRSIZE;i++) {
-       if (tentry.entries[i] == PRBADID) continue;
-       if (tentry.entries[i] == 0) break;
-       alist->prlist_val[count]= tentry.entries[i];
-       count++;
-       alist->prlist_len++;
+       if (tentry->entries[i] == PRBADID) continue;
+       if (tentry->entries[i] == 0) break;
+       code = AddToPRList (alist, &size, tentry->entries[i]);
+       if (code) return code;
     }
-    nptr = tentry.next;
+
+    nptr = tentry->next;
     while (nptr != NULL) {
        /* look through cont entries */
        code = pr_ReadCoEntry(at,0,nptr,&centry);
@@ -438,38 +628,51 @@ long add;
        for (i=0;i<COSIZE;i++) {
            if (centry.entries[i] == PRBADID) continue;
            if (centry.entries[i] == 0) break;
-           if (alist->prlist_len >= size) {
-               alist->prlist_val = (long *)realloc(alist->prlist_val,(size+100)*sizeof(long));
-               size += 100;
-           }
-           alist->prlist_val[count] = centry.entries[i];
-           count++;
-           alist->prlist_len++;
+           code = AddToPRList (alist, &size, centry.entries[i]);
+           if (code) return code;
        }
        nptr = centry.next;
+       if (count++ > 50) IOMGR_Poll(), count = 0;
     }
+
     if (add) { /* this is for a CPS, so tack on appropriate stuff */
-       if (aid != ANONYMOUSID && aid != ANYUSERID) {
-           if (alist->prlist_len >= size)
-               alist->prlist_val = (long *)realloc(alist->prlist_val,(size + 3)*sizeof(long));
-           alist->prlist_val[count] = ANYUSERID;
-           count++;
-           alist->prlist_val[count] = AUTHUSERID;
-           count++;
-           alist->prlist_val[count] = aid;
-           count++;
-           alist->prlist_len += 3;
+       if (tentry->id != ANONYMOUSID && tentry->id != ANYUSERID) {
+           if ((code = AddToPRList (alist, &size, ANYUSERID)) ||
+               (code = AddToPRList (alist, &size, AUTHUSERID)) ||
+               (code = AddToPRList (alist, &size, tentry->id))) return code;
        }
        else {
-           if (alist->prlist_len >= size)
-               alist->prlist_val = (long *)realloc(alist->prlist_val,(size + 2)*sizeof(long));
-           alist->prlist_val[count] = ANYUSERID;
-           count++;
-           alist->prlist_val[count] = aid;
-           count++;
-           alist->prlist_len += 2;
+           if ((code = AddToPRList (alist, &size, ANYUSERID)) ||
+               (code = AddToPRList (alist, &size, tentry->id))) return code;
        }
     }
+    if (alist->prlist_len > 100) IOMGR_Poll();
+    qsort(alist->prlist_val,alist->prlist_len,sizeof(long),IDCmp);
+    return PRSUCCESS;
+}
+
+long GetOwnedChain (ut, next, alist)
+  struct ubik_trans *ut;
+  long next;
+  prlist *alist;
+{   register long code;
+    struct prentry tentry;
+    int size;
+    int count = 0;
+
+    size = 0;
+    alist->prlist_val = 0;
+    alist->prlist_len = 0;
+
+    while (next) {
+       code = pr_Read (ut, 0, next, &tentry, sizeof(tentry));
+       if (code) return code;
+       code = AddToPRList (alist, &size, ntohl(tentry.id));
+       if (code) return code;
+       next = ntohl(tentry.nextOwned);
+       if (count++ > 50) IOMGR_Poll(), count = 0;
+    }
+    if (alist->prlist_len > 100) IOMGR_Poll();
     qsort(alist->prlist_val,alist->prlist_len,sizeof(long),IDCmp);
     return PRSUCCESS;
 }
@@ -503,20 +706,23 @@ long flag;
     return PRSUCCESS;
 }
 
-Initdb()
+int pr_noAuth;
+
+long Initdb()
 {
     long code;
     struct ubik_trans *tt;
     long len;
-    long temp;
-    long flag = 0;
     static long initd=0;
+#if 0
     static struct ubik_version curver;
     struct ubik_version newver;
-    struct ubik_hdr header;
+#endif
 
     /* init the database.  We'll try reading it, but if we're starting from scratch, we'll have to do a write transaction. */
 
+    pr_noAuth = afsconf_GetNoAuthFlag(prdir);
+
     code = ubik_BeginTrans(dbase,UBIK_READTRANS, &tt);
     if (code) return code;
     code = ubik_SetLock(tt,1,1,LOCKREAD);
@@ -526,16 +732,35 @@ Initdb()
     }
     if (!initd) {
        initd = 1;
+#if 0
        bzero(&curver,sizeof(curver));
+#endif
+    } else if (!ubik_CacheUpdate (tt)) {
+       code = ubik_EndTrans(tt);
+       return code;
+    }
+#if 0
+    code = ubik_GetVersion(tt,&newver);
+    if (vcmp(curver,newver) == 0) {
+       /* same version */
+       code = ubik_EndTrans(tt);
+       if (code) return code;
+       return PRSUCCESS;
     }
+    bcopy(&newver,&curver,sizeof(struct ubik_version));
+#endif
+
     len = sizeof(cheader);
     code = pr_Read(tt, 0, 0, (char *) &cheader, len);
     if (code != 0) {
-       printf("prserver: couldn't read header -code is %d\n",code);
+       com_err (whoami, code, "couldn't read header");
        ubik_AbortTrans(tt);
        return code;
     }
-    if (ntohl(cheader.headerSize) == sizeof(cheader) && ntohl(cheader.eofPtr) != NULL && FindByID(tt,ANONYMOUSID) != 0){
+    if ((ntohl(cheader.version) == PRDBVERSION) &&
+       ntohl(cheader.headerSize) == sizeof(cheader) &&
+       ntohl(cheader.eofPtr) != NULL &&
+       FindByID(tt,ANONYMOUSID) != 0){
        /* database exists, so we don't have to build it */
        code = ubik_EndTrans(tt);
        if (code) return code;
@@ -544,7 +769,26 @@ Initdb()
     /* else we need to build a database */
     code = ubik_EndTrans(tt);
     if (code) return code;
-    fprintf(stderr, "Creating new database\n");
+
+    /* Only rebuild database if the db was deleted (the header is zero) and we
+       are running noAuth. */
+    {   char *bp = (char *)&cheader;
+       int i;
+       for (i=0; i<sizeof(cheader); i++)
+           if (bp[i])  {
+               code = PRDBBAD;
+               com_err (whoami, code,
+                        "Can't rebuild database because it is not empty");
+               return code;
+           }
+    }
+    if (!pr_noAuth) {
+       code = PRDBBAD;
+       com_err (whoami, code,
+                "Can't rebuild database because not running NoAuth");
+       return code;
+    }
+
     code = ubik_BeginTrans(dbase,UBIK_WRITETRANS, &tt);
     if (code) return code;
     code = ubik_SetLock(tt,1,1,LOCKWRITE);
@@ -552,147 +796,83 @@ Initdb()
        ubik_AbortTrans(tt);
        return code;
     }
-    header.magic = htonl(UBIK_MAGIC);
-    header.pad1 = 0;
-    header.size = 0;
-    header.version.epoch = header.version.counter = htonl(1);
-    code = pr_Write(tt, 0, -(HDRSIZE), (char *)&header, sizeof(header));
-    if (code != 0) {
-       printf("prserver: couldn't write ubik header - code is %d.\n", code);
-       return code;
-    }
-    cheader.headerSize = htonl(sizeof(cheader));
-    code = pr_Write(tt,0,4,(char *)&cheader.headerSize,sizeof(cheader.headerSize));
-    if (code != 0) {
-       printf("prserver:  couldn't write header size - code is %d.\n",code);
+
+    /* Initialize the database header */
+
+    if ((code = set_header_word (tt, version, htonl(PRDBVERSION))) ||
+       (code = set_header_word (tt, headerSize, htonl(sizeof(cheader)))) ||
+       (code = set_header_word (tt, eofPtr, cheader.headerSize))) {
+       com_err (whoami, code, "couldn't write header words");
        ubik_AbortTrans(tt);
        return code;
     }
-    cheader.eofPtr = cheader.headerSize; /* already in network order! */
-    code = pr_Write(tt,0,12,(char *)&cheader.eofPtr,sizeof(cheader.eofPtr));
-    if (code != 0) {
-       printf("prserver:  couldn't write eof Ptr - code is %d.\n",code);
+
+#define InitialGroup(id,name) do {    \
+    long temp = (id);                \
+    long flag = (id) < 0 ? PRGRP : 0; \
+    code = CreateEntry               \
+       (tt, (name), &temp, /*idflag*/1, flag, SYSADMINID, SYSADMINID); \
+    if (code) {                              \
+       com_err (whoami, code, "couldn't create %s with id %di.",       \
+                (name), (id));       \
+       ubik_AbortTrans(tt);          \
+       return code;                  \
+    }                                \
+} while (0)
+
+    InitialGroup (SYSADMINID, "system:administrators");
+    InitialGroup (ANYUSERID, "system:anyuser");
+    InitialGroup (AUTHUSERID, "system:authuser");
+    InitialGroup (ANONYMOUSID, "anonymous");
+
+    /* Well, we don't really want the max id set to anonymousid, so we'll set
+     * it back to 0 */
+    code = set_header_word (tt, maxID, 0); /* correct in any byte order */
+    if (code) {
+       com_err (whoami, code, "couldn't reset max id");
        ubik_AbortTrans(tt);
        return code;
     }
-    temp = SYSADMINID;
-    if (FindByID(tt,SYSADMINID) == 0) {
-       /* init sysadmin */
-       flag |= PRGRP;
-       code = CreateEntry(tt,"system:administrators",&temp,1,flag,SYSADMINID,SYSADMINID);
-       if (code != PRSUCCESS) {
-           printf("prserver: couldn't create system:administrators.\n");
-           ubik_AbortTrans(tt);
-           return code;
-       }
-       flag = 0;
-    }
-    temp = ANYUSERID;
-    if ( FindByID(tt,temp) == 0) { /* init sysadmin */
-       flag |= PRGRP;
-       code = CreateEntry(tt,"system:anyuser",&temp,1,flag,SYSADMINID,SYSADMINID);
-       if (code != PRSUCCESS) {
-           printf("prserver:  couldn't create system:anyuser.\n");
-           ubik_AbortTrans(tt);
-           return code;
-       }
-       flag = 0;
-    }
-    temp = AUTHUSERID;
-    if (FindByID(tt,temp) == 0) { /* init sysadmin */
-       flag |= PRGRP;
-       code = CreateEntry(tt,"system:authuser",&temp,1,flag,SYSADMINID,SYSADMINID);
-       if (code != PRSUCCESS) {
-           printf("prserver:  couldn't create system:authuser.\n");
-           ubik_AbortTrans(tt);
-           return code;
-       }
-       flag = 0;
-    }
-    temp = ANONYMOUSID;
-    if (FindByID(tt,temp) == 0) { /* init sysadmin */
-       code = CreateEntry(tt,"anonymous",&temp,1,flag,SYSADMINID,SYSADMINID);
-       if (code != PRSUCCESS) {
-           printf("prserver:  couldn't create anonymous.\n");
-           ubik_AbortTrans(tt);
-           return code;
-       }
-       /* well, we don't really want the max id set to anonymousid, so we'll set it back to 0 */
-       cheader.maxID = 0; /* Zero is in correct byte order no matter what! */
-       code = pr_Write(tt,0,20,(char *)&cheader.maxID,sizeof(cheader.maxID));
-       if (code) {
-           printf("prserver: couldn't set max id - code is %d.\n");
-           ubik_AbortTrans(tt);
-           return code;
-       }
-    }
+
     code = ubik_EndTrans(tt);
     if (code) return code;
     return PRSUCCESS;
 }
 
-long NameToID(at, aname, aid)
-register struct ubik_trans *at;
-char aname[PR_MAXNAMELEN];
-long *aid;
-{
-    register long code;
-    long temp;
-    struct prentry tentry;
-
-    temp = FindByName(at,aname);
-    if (!temp) return PRNOENT;
-    code = pr_ReadEntry(at, 0, temp, &tentry);
-    if (code != 0) return code;
-    *aid = tentry.id;
-    return PRSUCCESS;
-}
-
-long IDToName(at, aid, aname)
-register struct ubik_trans *at;
-long aid;
-char aname[PR_MAXNAMELEN];
-{
-    long temp;
-    struct prentry tentry;
-    register long code;
-
-    temp = FindByID(at,aid);
-    if (!temp) return PRNOENT;
-    code = pr_ReadEntry(at,0,temp,&tentry);
-    if (code != 0) return code;
-    strncpy(aname,tentry.name,PR_MAXNAMELEN);
-    return PRSUCCESS;
-}
-
-long ChangeEntry(at, aid,cid,name,oid,newid)
-struct ubik_trans *at;
-long aid;
-long cid;
-char *name;
-long oid;
-long newid;
+long ChangeEntry (at, aid, cid, name, oid, newid)
+  struct ubik_trans *at;
+  long aid;
+  long cid;
+  char *name;
+  long oid;
+  long newid;
 {
     register long code;
     long pos;
     struct prentry tentry;
     long loc;
-    long noAuth;
-    char *check;
-    long tid;
+    long oldowner;
     char holder[PR_MAXNAMELEN];
     char temp[PR_MAXNAMELEN];
+    char oldname[PR_MAXNAMELEN];
 
-    noAuth = afsconf_GetNoAuthFlag(prdir);
     bzero(holder,PR_MAXNAMELEN);
     bzero(temp,PR_MAXNAMELEN);
     loc = FindByID(at,aid);
     if (!loc) return PRNOENT;
     code = pr_ReadEntry(at,0,loc,&tentry);
     if (code) return PRDBFAIL;
-    if (tentry.owner != cid && !IsAMemberOf(at,cid,SYSADMINID) && !IsAMemberOf(at,cid,tentry.owner) && !noAuth)
-       return PRPERM;
-    if (aid != newid && newid != 0) { /* then we're actually trying to change the id */
+    if (tentry.owner != cid &&
+       !IsAMemberOf(at,cid,SYSADMINID) &&
+       !IsAMemberOf(at,cid,tentry.owner) &&
+       !pr_noAuth) return PRPERM;
+#ifdef PR_REMEMBER_TIMES
+    tentry.changeTime = time(0);
+#endif
+
+    /* we're actually trying to change the id */
+    if (aid != newid && newid != 0) {
+       if (!IsAMemberOf(at,cid,SYSADMINID) && !pr_noAuth) return PRPERM;
        pos = FindByID(at,newid);
        if (pos) return PRIDEXIST;  /* new id already in use! */
        if ((aid < 0 && newid) > 0 || (aid > 0 && newid < 0)) return PRPERM;
@@ -701,71 +881,69 @@ long newid;
        if (code != PRSUCCESS) return code;
        tentry.id = newid;
        code = pr_WriteEntry(at,0,loc,&tentry);
+       if (code) return code;
        code = AddToIDHash(at,tentry.id,loc);
        if (code) return code;
+       /* get current data */
+       code = pr_ReadEntry(at,0,loc,&tentry);
+       if (code) return PRDBFAIL;
     }
+
+    /* Change the owner */
     if (tentry.owner != oid && oid) {
+       /* only groups can have their owner's changed */
+       if (!(tentry.flags & PRGRP)) return PRPERM;
+       oldowner = tentry.owner;
+       tentry.owner = oid;
+       /* The entry must be written through first so Remove and Add routines
+         * can operate on disk data */
+       code = pr_WriteEntry(at,0,loc,(char *)&tentry);
+       if (code) return PRDBFAIL;
        if (tentry.flags & PRGRP) {
-           /* switch owner chains before we lose old owner */
-           if (FindByID(at,tentry.owner)) /* if it has an owner */
-               code = RemoveFromOwnerChain(at,tentry.id,tentry.owner);
-           else  /* must be an orphan */
+           /* switch owner chains */
+           if (oldowner)               /* if it has an owner */
+               code = RemoveFromOwnerChain(at,tentry.id,oldowner);
+           else                        /* must be an orphan */
                code = RemoveFromOrphan(at,tentry.id);
            if (code) return code;
-           code = AddToOwnerChain(at,tentry.id,oid);
+           code = AddToOwnerChain(at,tentry.id,tentry.owner);
            if (code) return code;
        }
-       tentry.owner = oid;
-       if ((tentry.flags & PRGRP) && (strlen(name) == 0)) {
-           /* if we change the owner of a group, it's name will change as well */
-           if (tentry.owner < 0) {
-               code = IDToName(at,tentry.owner,temp);
-               if (code) return code;
-               check = index(temp,':');
-               strncpy(holder,temp,check - temp);
-           }
-           else {
-               code = IDToName(at,tentry.owner,holder);
-               if (code) return code;
-           }
-           strncat(holder,":",PR_MAXNAMELEN);
-           /* now the rest of the name */
-           check = index(tentry.name,':');
-           strncat(holder,++check,PR_MAXNAMELEN);
-           if (strcmp(holder,tentry.name)) {
-               /* then the name really did change */
-               pos = FindByName(at,holder);
-               if (pos) return PREXIST;
-               code = RemoveFromNameHash(at,tentry.name,&loc);
-               if (code != PRSUCCESS) return code;
-               strncpy(tentry.name,holder,PR_MAXNAMELEN);
-               code = AddToNameHash(at,tentry.name,loc);
-               if (code != PRSUCCESS) return code;
-           }
-       }
-       code = pr_WriteEntry(at,0,loc,&tentry);
+       /* fix up the name */
+       if ((tentry.flags & PRGRP) && (strlen(name) == 0)) name = tentry.name;
+       /* get current data */
+       code = pr_ReadEntry(at,0,loc,&tentry);
        if (code) return PRDBFAIL;
     }
-    if ((strcmp(tentry.name,name)) && (strlen(name)!= 0)) {
+
+    /* Change the name, if name is a ptr to tentry.name then this name change
+     * is due to a chown, otherwise caller has specified a new name */
+    if ((name == tentry.name) ||
+       (*name && (strcmp (tentry.name, name) != 0))) {
+       strncpy (oldname, tentry.name, PR_MAXNAMELEN);
        if (tentry.flags & PRGRP) {
-           if ((check = index(name,':')) == NULL) return PRBADNAM;
-           strncpy(temp,name,check-name);
-           code = NameToID(at,temp,&tid);
-           if (tid != tentry.owner) return PRPERM;
+           code = CorrectGroupName (at, name, cid, tentry.owner, tentry.name);
+           if (code) return code;
+
+           if (name == tentry.name) {  /* owner fixup */
+               if (strcmp (oldname, tentry.name) == 0) goto nameOK;
+           } else {                    /* new name, caller must be correct */
+               if (strcmp (name, tentry.name) != 0) return PRBADNAM;
+           }
        }
        else
-           /* if it's not a group, shouldn't have a : in it */
-           if ((check = index(name,':')) != NULL) 
-               return PRBADNAM;
+           if (!CorrectUserName(name)) return PRBADNAM;
+
        pos = FindByName(at,name);
        if (pos) return PREXIST;
-       code = RemoveFromNameHash(at,tentry.name,&loc);
+       code = RemoveFromNameHash (at, oldname, &loc);
        if (code != PRSUCCESS) return code;
-       strncpy(tentry.name,name,PR_MAXNAMELEN);
-       code = pr_WriteEntry(at,0,loc,&tentry);
+       strncpy (tentry.name, name, PR_MAXNAMELEN);
+       code = pr_WriteEntry(at,0,loc,(char *)&tentry);
        if (code) return PRDBFAIL;
        code = AddToNameHash(at,tentry.name,loc);
        if (code != PRSUCCESS) return code;
+nameOK:;
     }
     return PRSUCCESS;
 }
index c0ebfb6fe747904a01556a85f32ff41357cb9127..701d9b7bbc799d505828bf76a46a654dfdc116a4 100644 (file)
@@ -6,9 +6,9 @@
 #include <stdio.h>
 #include <sys/file.h>
 #include <rx/xdr.h>
-#include "print.h"
-#include "prserver.h"
-#include "prerror.h"
+#include <afs/ptint.h>
+#include <afs/ptserver.h>
+#include <afs/pterror.h>
 #include <moira.h>
 #include <moira_site.h>
 #include <ctype.h>
index 18a2d79490c43820931420a25f1ecbeaa3f8bd6a..ed6606d215a20a0a044c8801fc7e19f82e2dd3db 100644 (file)
@@ -10,9 +10,9 @@
 #include <stdio.h>
 #include <sys/file.h>
 #include <rx/xdr.h>
-#include "print.h"
-#include "prserver.h"
-#include "prerror.h"
+#include <afs/ptint.h>
+#include <afs/ptserver.h>
+#include <afs/pterror.h>
 #include <moira.h>
 #include <moira_site.h>
 #include <ctype.h>
index 07fa2d3f69a68ee205a61991be3678abc7459838..149a9bbe3308fbf0ea4c32bb8a718653cf90162f 100644 (file)
 
 struct ubik_dbase *dbase;
 
-long ubik_BeginTrans()
+int ubik_ServerInit()
+{
+    return(0);
+}
+
+int ubik_BeginTrans()
+{
+    return(0);
+}
+
+int ubik_BeginTransReadAny()
+{
+    return(0);
+}
+
+int ubik_AbortTrans()
+{
+    return(0);
+}
+
+int ubik_EndTrans()
+{
+    return(0);
+}
+
+int ubik_Tell()
+{
+    return(0);
+}
+
+int ubik_Truncate()
 {
     return(0);
 }
@@ -21,28 +51,37 @@ long ubik_SetLock()
     return(0);
 }
 
-long ubik_AbortTrans()
+int ubik_WaitVersion()
 {
     return(0);
 }
 
-long ubik_GetVersion(dummy, ver)
-int dummy;
-struct ubik_version *ver;
+int ubik_CacheUpdate()
 {
-    bzero(ver, sizeof(struct ubik_version));
     return(0);
 }
 
-long ubik_EndTrans()
+int panic(a, b, c, d)
+char *a, *b, *c, *d;
 {
+    printf(a, b, c, d);
+    abort();
+    printf("BACK FROM ABORT\n");    /* shouldn't come back from floating pt exception */
+    exit(1);    /* never know, though */
+}
+
+int ubik_GetVersion(dummy, ver)
+int dummy;
+struct ubik_version *ver;
+{
+    bzero(ver, sizeof(struct ubik_version));
     return(0);
 }
 
 
 extern int dbase_fd;
 
-long ubik_Seek(tt, afd, pos)
+int ubik_Seek(tt, afd, pos)
 struct ubik_trans *tt;
 long afd;
 long pos;
@@ -54,7 +93,7 @@ long pos;
     return(0);
 }
 
-long ubik_Write(tt, buf, len)
+int ubik_Write(tt, buf, len)
 struct ubik_trans *tt;
 char *buf;
 long len;
@@ -69,7 +108,7 @@ long len;
     return(0);
 }
 
-long ubik_Read(tt, buf, len)
+int ubik_Read(tt, buf, len)
 struct ubik_trans *tt;
 char *buf;
 long len;
@@ -87,7 +126,18 @@ long len;
 }
 
 
-char *prdir = "/dev/null";
+/* Global declarations from ubik.c */
+long ubik_quorum=0;
+struct ubik_dbase *ubik_dbase=0;
+struct ubik_stats ubik_stats;
+long ubik_host;
+long ubik_epochTime = 0;
+long urecovery_state = 0;
+
+struct rx_securityClass *ubik_sc[3];
+
+
+/* Other declarations */
 
 afsconf_GetNoAuthFlag()
 {
@@ -95,4 +145,7 @@ afsconf_GetNoAuthFlag()
 }
 
 
+char *prdir = "/dev/null";
 struct prheader cheader;
+int pr_realmNameLen;
+char *pr_realmName;
index c4d21a66bd3aefd56c7542f114c1bedb2a506507..4736ce3478e47ff6b423001db1da8c3d9a3ceece 100644 (file)
@@ -1,41 +1,33 @@
-/* $Header$ */
-/* $Source$ */
-
-
+/* Copyright (C) 1989 Transarc Corporation - All rights reserved */
 /*
  * P_R_P_Q_# (C) COPYRIGHT IBM CORPORATION 1988
  * LICENSED MATERIALS - PROPERTY OF IBM
  * REFER TO COPYRIGHT INSTRUCTIONS FORM NUMBER G120-2083
  */
 
+#ifndef lint
+static char rcsid[] = "$Header$";
+#endif
+
 /*     
        Sherri Nichols
        Information Technology Center
        November, 1988
 
+
        Modified May, 1989 by Jeff Schiller to keep disk file in
        network byte order
 
 */
 
-
 #include <sys/types.h>
 #include <lock.h>
 #include <ubik.h>
 #include <stdio.h>
 #include <netinet/in.h>
 #include <netdb.h>
-#include <rx/xdr.h>
-#include <rx/rx.h>
-#include <rx/rx_vab.h>
-#include "print.h"
-#include "prserver.h"
-#include "prerror.h"
-
-#define USERSMS        14487
-
-extern struct prheader cheader;
-extern struct ubik_dbase *dbase;
+#include "ptserver.h"
+#include "pterror.h"
 
 long IDHash(x)
 long x;
@@ -66,6 +58,10 @@ long len;
 {
     /* package up seek and write into one procedure for ease of use */
     long code;
+    if ((pos < sizeof(cheader)) && (buff != (char *)&cheader + pos)) {
+       fprintf (stderr, "ptserver: dbwrite: Illegal attempt to write a location 0\n");
+       return PRDBFAIL;
+    }
     code = ubik_Seek(tt,afd,pos);
     if (code) return code;
     code = ubik_Write(tt,buff,len);
@@ -96,7 +92,9 @@ struct prentry *tentry;
     long code;
     register long i;
     struct prentry nentry;
+
     if (ntohl(1) != 1) {       /* Need to swap bytes. */
+      bzero (&nentry, sizeof(nentry)); /* make sure reseved fields are zero */
       nentry.flags = htonl(tentry->flags);
       nentry.id = htonl(tentry->id);
       nentry.cellid = htonl(tentry->cellid);
@@ -115,20 +113,20 @@ struct prentry *tentry;
       nentry.sibling = htonl(tentry->sibling);
       nentry.child = htonl(tentry->child);
       strncpy(nentry.name, tentry->name, PR_MAXNAMELEN);
+#ifdef PR_REMEMBER_TIMES
+      nentry.createTime = htonl(tentry->createTime);
+      nentry.addTime = htonl(tentry->addTime);
+      nentry.removeTime = htonl(tentry->removeTime);
+      nentry.changeTime = htonl(tentry->changeTime);
+#endif
       for (i = 0; i < PRSIZE; i++)
        nentry.entries[i] = htonl(tentry->entries[i]);
-      code = ubik_Seek(tt, afd, pos);
-      if (code) return (code);
-      code = ubik_Write(tt, (char *) &nentry, sizeof(struct prentry));
-      return(code);
-    } else {
-      code = ubik_Seek(tt, afd, pos);
-      if (code) return (code);
-      code = ubik_Write(tt, (char *) tentry, sizeof(struct prentry));
-      return(code);
+      tentry = &nentry;
     }
+    code = pr_Write (tt, afd, pos, (char *)tentry, sizeof(struct prentry));
+    return(code);
 }
-
+  
 pr_ReadEntry(tt, afd, pos, tentry)
 struct ubik_trans *tt;
 long afd;
@@ -146,6 +144,7 @@ struct prentry *tentry;
     }
     code = ubik_Read(tt, (char *) &nentry, sizeof(struct prentry));
     if (code) return (code);
+    bzero (tentry, sizeof(*tentry));   /* make sure reseved fields are zero */
     tentry->flags = ntohl(nentry.flags);
     tentry->id = ntohl(nentry.id);
     tentry->cellid = ntohl(nentry.cellid);
@@ -164,35 +163,38 @@ struct prentry *tentry;
     tentry->sibling = ntohl(nentry.sibling);
     tentry->child = ntohl(nentry.child);
     strncpy(tentry->name, nentry.name, PR_MAXNAMELEN);
+#ifdef PR_REMEMBER_TIMES
+    tentry->createTime = ntohl(nentry.createTime);
+    tentry->addTime = ntohl(nentry.addTime);
+    tentry->removeTime = ntohl(nentry.removeTime);
+    tentry->changeTime = ntohl(nentry.changeTime);
+#endif
     for (i = 0; i < PRSIZE; i++)
       tentry->entries[i] = ntohl(nentry.entries[i]);
     return(code);
 }
 
 pr_WriteCoEntry(tt, afd, pos, tentry)
-struct ubik_trans *tt;
-long afd;
-long pos;
-struct contentry *tentry;
+  struct ubik_trans *tt;
+  long afd;
+  long pos;
+  struct contentry *tentry;
 {
     long code;
     register long i;
     struct contentry nentry;
-    if (ntohl(1) == 1) {       /* No need to swap */
-      code = ubik_Seek(tt, afd, pos);
-      if (code) return(code);
-      code = ubik_Write(tt, (char *) tentry, sizeof(struct contentry));
-      return(code);
+
+    if (ntohl(1) != 1) {       /* No need to swap */
+       bzero (&nentry, sizeof(nentry)); /* make reseved fields zero */
+       nentry.flags = htonl(tentry->flags);
+       nentry.id = htonl(tentry->id);
+       nentry.cellid = htonl(tentry->cellid);
+       nentry.next = htonl(tentry->next);
+       for (i = 0; i < COSIZE; i++)
+           nentry.entries[i] = htonl(tentry->entries[i]);
+       tentry = &nentry;
     }
-    nentry.flags = htonl(tentry->flags);
-    nentry.id = htonl(tentry->id);
-    nentry.cellid = htonl(tentry->cellid);
-    nentry.next = htonl(tentry->next);
-    for (i = 0; i < COSIZE; i++)
-      nentry.entries[i] = htonl(tentry->entries[i]);
-    code = ubik_Seek(tt, afd, pos);
-    if (code) return (code);
-    code = ubik_Write(tt, (char *) &nentry, sizeof(struct contentry));
+    code = pr_Write (tt, afd, pos, (char *)tentry, sizeof(struct contentry));
     return(code);
 }
 
@@ -213,6 +215,7 @@ struct contentry *tentry;
     }
     code = ubik_Read(tt, (char *) &nentry, sizeof(struct contentry));
     if (code) return (code);
+    bzero (tentry, sizeof(*tentry)); /* make reseved fields zero */
     tentry->flags = ntohl(nentry.flags);
     tentry->id = ntohl(nentry.id);
     tentry->cellid = ntohl(nentry.cellid);
@@ -222,10 +225,12 @@ struct contentry *tentry;
     return(code);
 }
 
+/* AllocBloc - allocate a free block of storage for entry, returning address of
+ * new entry */
+
 long AllocBlock(at)
-register struct ubik_trans *at;
+  register struct ubik_trans *at;
 {
-    /* allocate a free block of storage for entry, returning address of new entry  */
     register long code;
     long temp;
     struct prentry tentry;
@@ -279,6 +284,7 @@ long aid;
     struct prentry tentry;
     long entry;
 
+    if ((aid == PRBADID) || (aid == 0)) return 0;
     i = IDHash(aid);
     entry = ntohl(cheader.idHash[i]);
     if (entry == 0) return entry;
@@ -378,6 +384,40 @@ long *aid;
     }
 }
 
+long IDToName(at, aid, aname)
+  register struct ubik_trans *at;
+  long aid;
+  char aname[PR_MAXNAMELEN];
+{
+    long temp;
+    struct prentry tentry;
+    register long code;
+
+    temp = FindByID(at,aid);
+    if (temp == 0) return PRNOENT;
+    code = pr_Read (at, 0, temp, (char *)&tentry, sizeof(tentry));
+    if (code) return code;
+    strncpy (aname, tentry.name, PR_MAXNAMELEN);
+    return PRSUCCESS;
+}
+
+long NameToID(at, aname, aid)
+register struct ubik_trans *at;
+char aname[PR_MAXNAMELEN];
+long *aid;
+{
+    register long code;
+    long temp;
+    struct prentry tentry;
+
+    temp = FindByName(at,aname);
+    if (!temp) return PRNOENT;
+    code = pr_ReadEntry(at, 0, temp, &tentry);
+    if (code != 0) return code;
+    *aid = tentry.id;
+    return PRSUCCESS;
+}
+
 long IDCmp(a,b)
 long *a;
 long *b;
@@ -391,7 +431,7 @@ long *b;
 long RemoveFromIDHash(tt,aid,loc)
 struct ubik_trans *tt;
 long aid;
-long *loc;
+long *loc;                             /* ??? in case ID hashed twice ??? */
 {
     /* remove entry designated by aid from id hash table */
     register long code;
@@ -399,12 +439,13 @@ long *loc;
     struct prentry tentry;
     struct prentry bentry;
 
+    if ((aid == PRBADID) || (aid == 0)) return PRINCONSISTENT;
     i = IDHash(aid);
     current = ntohl(cheader.idHash[i]);
     bzero(&tentry,sizeof(tentry));
     bzero(&bentry,sizeof(bentry));
     trail = 0;
-    if (current == NULL) return PRNOENT;
+    if (current == NULL) return PRSUCCESS; /* already gone */
     code = pr_ReadEntry(tt,0,current,&tentry);
     if (code) return PRDBFAIL;
     while (aid != tentry.id) {
@@ -414,7 +455,7 @@ long *loc;
        code = pr_ReadEntry(tt,0,current,&tentry);
        if (code) return PRDBFAIL;
     }
-    if (current == NULL) return PRNOENT;  /* we didn't find him */
+    if (current == NULL) return PRSUCCESS;  /* we didn't find him, so he's already gone */
     if (trail == NULL) {
        /* it's the first entry! */
        cheader.idHash[i] = htonl(tentry.nextID);
@@ -434,13 +475,14 @@ long *loc;
 long AddToIDHash(tt, aid, loc)
 struct ubik_trans *tt;
 long aid;
-long loc;
+long loc;                              /* ??? */
 {
     /* add entry at loc designated by aid to id hash table */
     register long code;
     long i;
     struct prentry tentry;
 
+    if ((aid == PRBADID) || (aid == 0)) return PRINCONSISTENT;
     i = IDHash(aid);
     bzero(&tentry,sizeof(tentry));
     code = pr_ReadEntry(tt,0,loc,&tentry);
@@ -470,7 +512,7 @@ long *loc;
     bzero(&tentry,sizeof(tentry));
     bzero(&bentry,sizeof(bentry));
     trail = 0;
-    if (current == NULL) return PRNOENT;
+    if (current == NULL) return PRSUCCESS;  /* already gone */
     code = pr_ReadEntry(tt,0,current,&tentry);
     if (code) return PRDBFAIL;
     while (strcmp(aname,tentry.name)) {
@@ -480,7 +522,7 @@ long *loc;
        code = pr_ReadEntry(tt,0,current,&tentry);
        if (code) return PRDBFAIL;
     }
-    if (current == NULL) return PRNOENT;  /* we dnamen't find him */
+    if (current == NULL) return PRSUCCESS;  /* we didn't find him, already gone */
     if (trail == NULL) {
        /* it's the first entry! */
        cheader.nameHash[i] = htonl(tentry.nextName);
@@ -521,79 +563,97 @@ long loc;
 }
 
 long AddToOwnerChain(at,gid,oid)
-struct ubik_trans *at;
-long gid;
-long oid;
+  struct ubik_trans *at;
+  long gid;
+  long oid;
 {
     /* add entry designated by gid to owner chain of entry designated by oid */
     register long code;
     long loc;
-    long gloc;
     struct prentry tentry;
     struct prentry gentry;
+    long gloc;
 
     loc = FindByID(at,oid);
     if (!loc) return PRNOENT;
     code = pr_ReadEntry(at,0,loc,&tentry);
     if (code != 0) return PRDBFAIL;
-    gloc = FindByID(at,gid);
-    code = pr_ReadEntry(at,0,gloc,&gentry);
-    if (code != 0) return PRDBFAIL;
-    gentry.nextOwned = tentry.owned;
-    tentry.owned = gloc;
+    if (oid == gid) {                  /* added it to its own chain */
+       tentry.nextOwned = tentry.owned;
+       tentry.owned = loc;
+    } else {
+       gloc = FindByID(at,gid);
+       code = pr_ReadEntry(at,0,gloc,&gentry);
+       if (code != 0) return PRDBFAIL;
+       gentry.nextOwned = tentry.owned;
+       tentry.owned = gloc;
+       code = pr_WriteEntry(at,0,gloc,&gentry);
+       if (code != 0) return PRDBFAIL;
+    }
     code = pr_WriteEntry(at,0,loc,&tentry);
     if (code != 0) return PRDBFAIL;
-    code = pr_WriteEntry(at,0,gloc,&gentry);
-    if (code != 0) return PRDBFAIL;
     return PRSUCCESS;
 }
 
+/* RemoveFromOwnerChain - remove gid from owner chain for oid */
+
 long RemoveFromOwnerChain(at,gid,oid)
-struct ubik_trans *at;
-long gid;
-long oid;
+  struct ubik_trans *at;
+  long gid;
+  long oid;
 {
-    /* remove gid from owner chain for oid */
     register long code;
     long nptr;
-    struct prentry tentry;
-    struct prentry bentry;
-    long loc;
+    struct prentry thisEntry;
+    struct prentry thatEntry;
+    struct prentry *te;                        /* pointer to current (this) entry */
+    struct prentry *le;                        /* pointer to previous (last) entry */
+    long loc, lastLoc;
 
     loc = FindByID(at,oid);
     if (!loc) return PRNOENT;
-    code = pr_ReadEntry(at,0,loc,&tentry);
+    code = pr_ReadEntry (at, 0, loc, &thisEntry);
     if (code != 0) return PRDBFAIL;
-    if (!tentry.owned) return PRNOENT;
-    nptr = tentry.owned;
-    bcopy(&tentry,&bentry,sizeof(tentry));
+    le =  &thisEntry;
+    lastLoc = 0;
+    nptr = thisEntry.owned;
     while (nptr != NULL) {
-       code = pr_ReadEntry(at,0,nptr,&tentry);
-       if (code != 0) return PRDBFAIL;
-       if (tentry.id == gid) {
-           /* found it */
-           if (nptr == bentry.owned) /* modifying first of chain */
-               bentry.owned = tentry.nextOwned;
-           else bentry.nextOwned = tentry.nextOwned;
-           tentry.nextOwned = 0;
-           code = pr_WriteEntry(at,0,loc,&bentry);
+       if (nptr == lastLoc) te = le;
+       else {
+           if (&thisEntry == le) te = &thatEntry;
+           else te = &thisEntry;
+           code = pr_ReadEntry (at, 0, nptr, te);
            if (code != 0) return PRDBFAIL;
-           code = pr_WriteEntry(at,0,nptr,&tentry);
+       }
+       if (te->id == gid) {
+           /* found it */
+           if (lastLoc == 0) {         /* modifying first of chain */
+               le->owned = te->nextOwned;
+               lastLoc = loc;          /* so we write to correct location */
+           }
+           else le->nextOwned = te->nextOwned;
+           te->nextOwned = 0;
+           if (te != le) {
+               code = pr_WriteEntry (at, 0, nptr, te);
+               if (code != 0) return PRDBFAIL;
+           }
+           code = pr_WriteEntry (at, 0, lastLoc, le);
            if (code != 0) return PRDBFAIL;
            return PRSUCCESS;
        }
-       loc = nptr;
-       nptr = tentry.nextOwned;
-       bcopy(&tentry,&bentry,sizeof(tentry));
+       lastLoc = nptr;
+       le = te;
+       nptr = te->nextOwned;
     }
-    return PRNOENT;
+    return PRSUCCESS;                  /* already removed? */
 }
 
+/* AddToOrphan - add gid to orphan list, as it's owner has died */
+
 long AddToOrphan(at,gid)
-struct ubik_trans *at;
-long gid;
+  struct ubik_trans *at;
+  long gid;
 {
-    /* add gid to orphan list, as it's owner has died */
     register long code;
     long loc;
     struct prentry tentry;
@@ -603,10 +663,10 @@ long gid;
     code = pr_ReadEntry(at,0,loc,&tentry);
     if (code != 0) return PRDBFAIL;
     tentry.nextOwned = ntohl(cheader.orphan);
-    cheader.orphan = htonl(loc);
-    code = pr_WriteEntry(at,0,loc,&tentry);
+    code = set_header_word (at, orphan, htonl(loc));
     if (code != 0) return PRDBFAIL;
-    code = pr_Write(at,0,32,(char *)&cheader.orphan,sizeof(cheader.orphan));
+    tentry.owner = 0;                  /* so there's no confusion later */
+    code = pr_WriteEntry(at,0,loc,&tentry);
     if (code != 0) return PRDBFAIL;
     return PRSUCCESS;
 }
@@ -653,9 +713,9 @@ long gid;
        }
        loc = nptr;
        nptr = tentry.nextOwned;
-       bcopy(&tentry,&bentry,sizeof(tentry));
+       bcopy(&tentry,&bentry, sizeof(tentry));
     }
-    return PRNOENT;
+    return PRSUCCESS;
 }
 
 long IsOwnerOf(at,aid,gid)
@@ -693,15 +753,6 @@ long gid;
 }
     
 
-long WhoIsThis(acall, at, aid)
-struct rx_call *acall;
-struct ubik_trans *at;
-long *aid;
-{
-    *aid = USERSMS;
-    return 0;
-}
-
 long IsAMemberOf(at,aid,gid)
 struct ubik_trans *at;
 long aid;
@@ -714,6 +765,10 @@ long gid;
     long i;
     long loc;
 
+    /* special case anyuser and authuser */
+    if (gid == ANYUSERID) return 1;
+    if (gid == AUTHUSERID && aid != ANONYMOUSID) return 1;
+    if ((gid == 0) || (aid == 0)) return 0;
     loc = FindByID(at,gid);
     if (!loc) return 0;
     bzero(&tentry,sizeof(tentry));
@@ -721,8 +776,8 @@ long gid;
     if (code) return 0;
     if (!(tentry.flags & PRGRP)) return 0;
     for (i= 0;i<PRSIZE;i++) {
-       if (tentry.entries[i] == aid) return 1;
        if (tentry.entries[i] == 0) return 0;
+       if (tentry.entries[i] == aid) return 1;
     }
     if (tentry.next) {
        loc = tentry.next;
This page took 0.162813 seconds and 5 git commands to generate.