Protect ubik cache accesses
[openafs.git] / src / ptserver / ptutils.c
index 53704a0..c4315c2 100644 (file)
@@ -23,8 +23,6 @@
 #include <afsconfig.h>
 #include <afs/param.h>
 
-RCSID
-    ("$Header$");
 
 #include <afs/stds.h>
 #include <sys/types.h>
@@ -34,13 +32,7 @@ RCSID
 #else
 #include <netinet/in.h>
 #endif
-#ifdef HAVE_STRING_H
 #include <string.h>
-#else
-#ifdef HAVE_STRINGS_H
-#include <strings.h>
-#endif
-#endif
 #include <lock.h>
 #include <ubik.h>
 #include <rx/xdr.h>
@@ -48,6 +40,7 @@ RCSID
 #include <afs/cellconfig.h>
 #include "ptserver.h"
 #include "pterror.h"
+#include "ptprototypes.h"
 #include <stdlib.h>
 
 /* Foreign cells are represented by the group system:authuser@cell*/
@@ -57,9 +50,11 @@ extern int restricted;
 extern struct ubik_dbase *dbase;
 extern struct afsconf_dir *prdir;
 extern int pr_noAuth;
-extern int IDCmp();
 
-extern afs_int32 AddToEntry();
+static int inRange(struct prentry *cellEntry, afs_int32 aid);
+static afs_int32 allocNextId(struct ubik_trans *, struct prentry *);
+static int AddAuthGroup(struct prentry *tentry, prlist *alist, afs_int32 *size);
+
 static char *whoami = "ptserver";
 
 int prp_user_default = PRP_USER_DEFAULT;
@@ -70,10 +65,8 @@ int prp_group_default = PRP_GROUP_DEFAULT;
 #include "map.h"
 
 afs_int32 depthsg = 5;         /* Maximum iterations used during IsAMemberOF */
-extern int IDCmp();
 afs_int32 GetListSG2(struct ubik_trans *at, afs_int32 gid, prlist * alist,
                     afs_int32 * sizeP, afs_int32 depth);
-afs_int32 allocNextId(struct ubik_trans *, struct prentry *);
 
 struct map *sg_flagged;
 struct map *sg_found;
@@ -91,10 +84,11 @@ struct map *sg_found;
  *  so we can always tell if we're writing a group record.
  */
 
-int (*pt_save_dbase_write) ();
+int (*pt_save_dbase_write)(struct ubik_dbase *, afs_int32, void *, afs_int32,
+                           afs_int32);
 
 int
-pt_mywrite(struct ubik_dbase *tdb, afs_int32 fno, char *bp, afs_int32 pos, afs_int32 count)
+pt_mywrite(struct ubik_dbase *tdb, afs_int32 fno, void *bp, afs_int32 pos, afs_int32 count)
 {
     afs_uint32 headersize = ntohl(cheader.headerSize);
 
@@ -170,7 +164,7 @@ pt_mywrite(struct ubik_dbase *tdb, afs_int32 fno, char *bp, afs_int32 pos, afs_i
  */
 
 void 
-pt_hook_write()
+pt_hook_write(void)
 {
     extern struct ubik_dbase *ubik_dbase;
     if (ubik_dbase->write != pt_mywrite) {
@@ -300,7 +294,7 @@ AccessOK(struct ubik_trans *ut, afs_int32 cid,              /* caller id */
        return 1;
     if (cid == SYSADMINID)
        return 1;               /* special case fileserver */
-    if (restricted && ((mem == PRP_ADD_MEM) || (mem == any == 0)))
+    if (restricted && ((mem == PRP_ADD_MEM) || (mem == PRP_REMOVE_MEM)) && (any == 0))
        return 0;
     if (tentry) {
        flags = tentry->flags;
@@ -848,7 +842,7 @@ RemoveFromSGEntry(register struct ubik_trans *at, register afs_int32 aid, regist
        }                       /* for all coentry slots */
        hloc = nptr;
        nptr = centry.next;
-       bcopy((char *)&centry, (char *)&hentry, sizeof(centry));
+       memcpy((char *)&centry, (char *)&hentry, sizeof(centry));
     }                          /* while there are coentries */
     return PRNOENT;
 }
@@ -922,7 +916,7 @@ DeleteEntry(struct ubik_trans *at, struct prentry *tentry, afs_int32 loc)
     }
 #endif /* SUPERGROUPS */
     nptr = tentry->next;
-    while (nptr != (afs_int32) NULL) {
+    while (nptr != 0) {
        code = pr_ReadCoEntry(at, 0, nptr, &centry);
        if (code != 0)
            return PRDBFAIL;
@@ -1043,7 +1037,7 @@ AddToEntry(struct ubik_trans *tt, struct prentry *entry, afs_int32 loc, afs_int3
     }
     last = 0;
     nptr = entry->next;
-    while (nptr != (afs_int32) NULL) {
+    while (nptr != 0) {
        code = pr_ReadCoEntry(tt, 0, nptr, &nentry);
        if (code != 0)
            return code;
@@ -1133,7 +1127,7 @@ AddToSGEntry(struct ubik_trans *tt, struct prentry *entry, afs_int32 loc, afs_in
     afs_int32 nptr;
     afs_int32 last;            /* addr of last cont. block */
     afs_int32 first = 0;
-    afs_int32 cloc;
+    afs_int32 cloc = 0;
     afs_int32 slot = -1;
 
     if (entry->id == aid)
@@ -1306,8 +1300,12 @@ GetList(struct ubik_trans *at, struct prentry *tentry, prlist *alist, afs_int32
                return code;
 #endif
        }
-       if (count++ > 50)
-           IOMGR_Poll(), count = 0;
+       if (count++ > 50) {
+#ifndef AFS_PTHREAD_ENV
+           IOMGR_Poll();
+#endif
+           count = 0;
+       }
     }
 
     if (add) {                 /* this is for a CPS, so tack on appropriate stuff */
@@ -1322,8 +1320,10 @@ GetList(struct ubik_trans *at, struct prentry *tentry, prlist *alist, afs_int32
                return code;
        }
     }
+#ifndef AFS_PTHREAD_ENV
     if (alist->prlist_len > 100)
        IOMGR_Poll();
+#endif
     qsort(alist->prlist_val, alist->prlist_len, sizeof(afs_int32), IDCmp);
     return PRSUCCESS;
 }
@@ -1360,7 +1360,7 @@ GetList2(struct ubik_trans *at, struct prentry *tentry, struct prentry *tentry2,
     }
 
     nptr = tentry->next;
-    while (nptr != (afs_uint32) NULL) {
+    while (nptr != 0) {
        /* look through cont entries */
        code = pr_ReadCoEntry(at, 0, nptr, &centry);
        if (code != 0)
@@ -1382,8 +1382,12 @@ GetList2(struct ubik_trans *at, struct prentry *tentry, struct prentry *tentry2,
 #endif
        }
        nptr = centry.next;
-       if (count++ > 50)
-           IOMGR_Poll(), count = 0;
+       if (count++ > 50) {
+#ifndef AFS_PTHREAD_ENV
+           IOMGR_Poll();
+#endif
+           count = 0;
+       }
     }
 
     for (i = 0; i < PRSIZE; i++) {
@@ -1398,7 +1402,7 @@ GetList2(struct ubik_trans *at, struct prentry *tentry, struct prentry *tentry2,
 
     if (!code) {
        nptr = tentry2->next;
-       while (nptr != (afs_uint32) NULL) {
+       while (nptr != 0) {
            /* look through cont entries */
            code = pr_ReadCoEntry(at, 0, nptr, &centry);
            if (code != 0)
@@ -1413,8 +1417,12 @@ GetList2(struct ubik_trans *at, struct prentry *tentry, struct prentry *tentry2,
                    break;
            }
            nptr = centry.next;
-           if (count++ > 50)
-               IOMGR_Poll(), count = 0;
+           if (count++ > 50) {
+#ifndef AFS_PTHREAD_ENV
+               IOMGR_Poll();
+#endif
+               count = 0;
+           }
        }
     }
     if (add) {                 /* this is for a CPS, so tack on appropriate stuff */
@@ -1429,8 +1437,10 @@ GetList2(struct ubik_trans *at, struct prentry *tentry, struct prentry *tentry2,
                return code;
        }
     }
+#ifndef AFS_PTHREAD_ENV
     if (alist->prlist_len > 100)
        IOMGR_Poll();
+#endif
     qsort(alist->prlist_val, alist->prlist_len, sizeof(afs_int32), IDCmp);
     return PRSUCCESS;
 }
@@ -1535,8 +1545,12 @@ GetListSG2(struct ubik_trans *at, afs_int32 gid, prlist *alist, afs_int32 *sizeP
                return code;
        }
        nptr = centry.next;
-       if (count++ > 50)
-           IOMGR_Poll(), count = 0;
+       if (count++ > 50) {
+#ifndef AFS_PTHREAD_ENV
+           IOMGR_Poll();
+#endif
+           count = 0;
+       }
     }
 #if DEBUG_SG_MAP
     fprintf(stderr, "] for gid %d, done [flag=%s]\n", gid,
@@ -1595,12 +1609,18 @@ GetSGList(struct ubik_trans *at, struct prentry *tentry, prlist *alist)
                return code;
        }
        nptr = centry.next;
-       if (count++ > 50)
-           IOMGR_Poll(), count = 0;
+       if (count++ > 50) {
+#ifndef AFS_PTHREAD_ENV
+           IOMGR_Poll();
+#endif
+           count = 0;
+       }
     }
 
+#ifndef AFS_PTHREAD_ENV
     if (alist->prlist_len > 100)
        IOMGR_Poll();
+#endif
     qsort((char *)alist->prlist_val, (int)alist->prlist_len,
          sizeof(afs_int32), IDCmp);
     return PRSUCCESS;
@@ -1629,11 +1649,17 @@ GetOwnedChain(struct ubik_trans *ut, afs_int32 *next, prlist *alist)
        }
        if (code)
            return code;
-       if (count++ > 50)
-           IOMGR_Poll(), count = 0;
+       if (count++ > 50) {
+#ifndef AFS_PTHREAD_ENV
+           IOMGR_Poll();
+#endif
+           count = 0;
+       }
     }
+#ifndef AFS_PTHREAD_ENV
     if (alist->prlist_len > 100)
        IOMGR_Poll();
+#endif
     qsort(alist->prlist_val, alist->prlist_len, sizeof(afs_int32), IDCmp);
     return PRSUCCESS;
 }
@@ -1668,14 +1694,11 @@ SetMax(struct ubik_trans *at, afs_int32 id, afs_int32 flag)
     return PRSUCCESS;
 }
 
-afs_int32
-read_DbHeader(struct ubik_trans *tt)
+static afs_int32
+UpdateCache(struct ubik_trans *tt, void *rock)
 {
     afs_int32 code;
 
-    if (!ubik_CacheUpdate(tt))
-       return 0;
-
     code = pr_Read(tt, 0, 0, (char *)&cheader, sizeof(cheader));
     if (code != 0) {
        afs_com_err(whoami, code, "Couldn't read header");
@@ -1683,16 +1706,58 @@ read_DbHeader(struct ubik_trans *tt)
     return code;
 }
 
+afs_int32
+read_DbHeader(struct ubik_trans *tt)
+{
+    return ubik_CheckCache(tt, UpdateCache, NULL);
+}
+
 int pr_noAuth;
-afs_int32 initd = 0;
 
-afs_int32
-Initdb()
+/**
+ * reads in db cache from ubik.
+ *
+ * @param[in] ut ubik transaction
+ * @param[out] rock  opaque pointer to an int*, which on success will be set
+ *                   to 1 if we need to build the database, or 0 if we do not
+ *
+ * @return operation status
+ *   @retval 0 success
+ */
+static afs_int32
+Initdb_check(struct ubik_trans *tt, void *rock)
 {
+    int *build_rock = rock;
     afs_int32 code;
-    struct ubik_trans *tt;
     afs_int32 len;
 
+    len = sizeof(cheader);
+    code = pr_Read(tt, 0, 0, (char *)&cheader, len);
+    if (code != 0) {
+       afs_com_err(whoami, code, "couldn't read header");
+       return code;
+    }
+    if ((ntohl(cheader.version) == PRDBVERSION)
+       && ntohl(cheader.headerSize) == sizeof(cheader)
+       && ntohl(cheader.eofPtr) != 0
+       && FindByID(tt, ANONYMOUSID) != 0) {
+       /* database exists, so we don't have to build it */
+       *build_rock = 0;
+       return 0;
+    }
+
+    /* else we need to build a database */
+    *build_rock = 1;
+    return 0;
+}
+
+afs_int32
+Initdb(void)
+{
+    struct ubik_trans *tt;
+    int build = 0;
+    afs_int32 code;
+
     /* init the database.  We'll try reading it, but if we're starting
      * from scratch, we'll have to do a write transaction. */
 
@@ -1706,52 +1771,40 @@ Initdb()
        ubik_AbortTrans(tt);
        return code;
     }
-    if (!initd) {
-       initd = 1;
-    } else if (!ubik_CacheUpdate(tt)) {
-       code = ubik_EndTrans(tt);
-       return code;
-    }
 
-    len = sizeof(cheader);
-    code = pr_Read(tt, 0, 0, (char *)&cheader, len);
-    if (code != 0) {
-       afs_com_err(whoami, code, "couldn't read header");
+    code = ubik_CheckCache(tt, Initdb_check, &build);
+    if (code) {
        ubik_AbortTrans(tt);
        return code;
     }
-    if ((ntohl(cheader.version) == PRDBVERSION)
-       && ntohl(cheader.headerSize) == sizeof(cheader)
-       && ntohl(cheader.eofPtr) != (afs_uint32) NULL
-       && FindByID(tt, ANONYMOUSID) != 0) {
-       /* database exists, so we don't have to build it */
-       code = ubik_EndTrans(tt);
-       if (code)
-           return code;
-       return PRSUCCESS;
-    }
-    /* else we need to build a database */
-    code = ubik_EndTrans(tt);
-    if (code)
-       return code;
 
-    /* Only rebuild database if the db was deleted (the header is zero) and we
-     * are running noAuth. */
-    {
+    if (build) {
+       /* 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++)
+       for (i = 0; i < sizeof(cheader); i++) {
            if (bp[i]) {
                code = PRDBBAD;
                afs_com_err(whoami, code,
                        "Can't rebuild database because it is not empty");
-               return code;
+               break;
            }
+       }
+       if (!pr_noAuth) {
+           code = PRDBBAD;
+           afs_com_err(whoami, code,
+                       "Can't rebuild database because not running NoAuth");
+       }
+    }
+
+    if (code) {
+       ubik_EndTrans(tt);
+    } else {
+       code = ubik_EndTrans(tt);
     }
-    if (!pr_noAuth) {
-       code = PRDBBAD;
-       afs_com_err(whoami, code,
-               "Can't rebuild database because not running NoAuth");
+    if (code || !build) {
+       /* either we encountered an error, or we don't need to build the db */
        return code;
     }
 
@@ -1770,9 +1823,15 @@ Initdb()
      * actually have been a good database out there.  Now that we have a
      * real write transaction, make sure things are still bad.
      */
+    code = pr_Read(tt, 0, 0, (char *)&cheader, sizeof(cheader));
+    if (code != 0) {
+       afs_com_err(whoami, code, "couldn't read header");
+       ubik_AbortTrans(tt);
+       return code;
+    }
     if ((ntohl(cheader.version) == PRDBVERSION)
        && ntohl(cheader.headerSize) == sizeof(cheader)
-       && ntohl(cheader.eofPtr) != (afs_uint32) NULL
+       && ntohl(cheader.eofPtr) != 0
        && FindByID(tt, ANONYMOUSID) != 0) {
        /* database exists, so we don't have to build it */
        code = ubik_EndTrans(tt);
@@ -1828,11 +1887,13 @@ afs_int32
 ChangeEntry(struct ubik_trans *at, afs_int32 aid, afs_int32 cid, char *name, afs_int32 oid, afs_int32 newid)
 {
     afs_int32 code;
-    afs_int32 i, nptr, pos;
+    afs_int32 i, pos;
 #if defined(SUPERGROUPS)
     afs_int32 nextpos;
-#endif
+#else
+    afs_int32 nptr;
     struct contentry centry;
+#endif
     struct prentry tentry, tent;
     afs_int32 loc;
     afs_int32 oldowner;
@@ -2019,7 +2080,7 @@ ChangeEntry(struct ubik_trans *at, afs_int32 aid, afs_int32 cid, char *name, afs
        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);
+       code = pr_WriteEntry(at, 0, loc, &tentry);
        if (code)
            return PRDBFAIL;
 
@@ -2086,7 +2147,7 @@ ChangeEntry(struct ubik_trans *at, afs_int32 aid, afs_int32 cid, char *name, afs
        if (code != PRSUCCESS)
            return code;
        strncpy(tentry.name, name, PR_MAXNAMELEN);
-       code = pr_WriteEntry(at, 0, loc, (char *)&tentry);
+       code = pr_WriteEntry(at, 0, loc, &tentry);
        if (code)
            return PRDBFAIL;
        code = AddToNameHash(at, tentry.name, loc);
@@ -2098,7 +2159,7 @@ ChangeEntry(struct ubik_trans *at, afs_int32 aid, afs_int32 cid, char *name, afs
 }
 
 
-afs_int32
+static afs_int32
 allocNextId(struct ubik_trans * at, struct prentry * cellEntry)
 {
     /* Id's for foreign cell entries are constructed as follows:
@@ -2129,7 +2190,7 @@ allocNextId(struct ubik_trans * at, struct prentry * cellEntry)
     return id;
 }
 
-int
+static int
 inRange(struct prentry *cellEntry, afs_int32 aid)
 {
     afs_uint32 id, cellid, groupid;
@@ -2160,7 +2221,7 @@ inRange(struct prentry *cellEntry, afs_int32 aid)
 
 }
 
-int
+static int
 AddAuthGroup(struct prentry *tentry, prlist *alist, afs_int32 *size)
 {
     if (!(strchr(tentry->name, '@')))