Correct some redundant if() clauses
[openafs.git] / src / libadmin / client / afs_clientAdmin.c
index f256586..aa49358 100644 (file)
@@ -9,36 +9,23 @@
 
 #include <afsconfig.h>
 #include <afs/param.h>
+#include <afs/stds.h>
 
-RCSID
-    ("$Header$");
+#include <roken.h>
 
-#include <afs/stds.h>
-#include "afs_clientAdmin.h"
-#include "../adminutil/afs_AdminInternal.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <afs/cellconfig.h>
 #ifdef AFS_NT40_ENV
 #include <afs/afssyscalls.h>
-#include <winsock2.h>
 #include <afs/fs_utils.h>
+#define close(x) closesocket(x)
 #else
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <netdb.h>
 #include <afs/venus.h>
-#include <errno.h>
-#include <strings.h>
-#include <unistd.h>
 #endif
-#include <string.h>
-#include <afs/kautils.h>
 #include <rx/rx.h>
+#include <rx/rxstat.h>
 #include <rx/rx_null.h>
 #include <rx/rxkad.h>
+
+#include <afs/kautils.h>
 #include <afs/dirpath.h>
 #include <afs/afs_AdminErrors.h>
 #include <afs/afs_vosAdmin.h>
@@ -46,6 +33,10 @@ RCSID
 #include <afs/ptserver.h>
 #include <afs/vlserver.h>
 #include <afs/pthread_glock.h>
+#include <afs/sys_prototypes.h>
+
+#include "afs_clientAdmin.h"
+#include "../adminutil/afs_AdminInternal.h"
 
 /*
  * AFS client administration functions.
@@ -59,6 +50,8 @@ RCSID
 
 static const unsigned long ADMIN_TICKET_LIFETIME = 24 * 3600;
 
+static const unsigned long SERVER_TTL = 10 * 60;
+
 /*
  * We need a way to track whether or not the client library has been 
  * initialized.  We count on the fact that the other library initialization
@@ -193,7 +186,8 @@ afsclient_TokenGetExisting(const char *cellName, void **tokenHandle,
         * The token has been retrieved successfully, initialize
         * the rest of the token handle structure
         */
-       strcpy(t_handle->cell, cellName);
+       strncpy(t_handle->cell, cellName, MAXCELLCHARS);
+        t_handle->cell[MAXCELLCHARS - 1] = '\0';
        t_handle->afs_token_set = 1;
        t_handle->from_kernel = 1;
        t_handle->kas_token_set = 0;
@@ -211,7 +205,7 @@ afsclient_TokenGetExisting(const char *cellName, void **tokenHandle,
                                          t_handle->afs_token.ticketLen,
                                          t_handle->afs_token.ticket);
        if ((t_handle->afs_sc[t_handle->sc_index] == NULL)
-           || (t_handle->afs_sc[t_handle->sc_index] == NULL)) {
+           || (t_handle->afs_encrypt_sc[t_handle->sc_index] == NULL)) {
            tst = ADMCLIENTTOKENHANDLENOSECURITY;
            goto fail_afsclient_TokenGetExisting;
        } else {
@@ -568,7 +562,8 @@ afsclient_TokenGetNew(const char *cellName, const char *principal,
 
        if ((GetAFSToken(cellName, principal, password, t_handle, &tst))
            && (GetKASToken(cellName, principal, password, t_handle, &tst))) {
-           strcpy(t_handle->cell, cellName);
+           strncpy(t_handle->cell, cellName, MAXCELLCHARS);
+            t_handle->cell[MAXCELLCHARS - 1] = '\0';
            t_handle->from_kernel = 0;
            t_handle->afs_token_set = 1;
            t_handle->kas_token_set = 1;
@@ -754,12 +749,6 @@ typedef struct afs_server {
     int *valid;
 } afs_server_t, *afs_server_p;
 
-static afs_server_t servers[NUM_SERVER_TYPES]
-= { {AFSCONF_KAUTHSERVICE, KA_MAINTENANCE_SERVICE, 0, 0, 0},
-{AFSCONF_PROTSERVICE, PRSRV, 0, 0, 0},
-{AFSCONF_VLDBSERVICE, USER_SERVICE_ID, 0, 0, 0}
-};
-
 /*
  * afsclient_CellOpen - Open a particular cell for work as a particular
  * user.
@@ -803,6 +792,12 @@ afsclient_CellOpen(const char *cellName, const void *tokenHandle,
     int scIndex;
     char copyCell[MAXCELLCHARS];
 
+    afs_server_t servers[NUM_SERVER_TYPES]
+      = { {AFSCONF_KAUTHSERVICE, KA_MAINTENANCE_SERVICE, 0, 0, 0},
+         {AFSCONF_PROTSERVICE, PRSRV, 0, 0, 0},
+         {AFSCONF_VLDBSERVICE, USER_SERVICE_ID, 0, 0, 0}
+      };
+    
     if (client_init == 0) {
        tst = ADMCLIENTNOINIT;
        goto fail_afsclient_CellOpen;
@@ -868,7 +863,8 @@ afsclient_CellOpen(const char *cellName, const void *tokenHandle,
      * information for each server in the cell
      */
 
-    strcpy(c_handle->working_cell, cellName);
+    strncpy(c_handle->working_cell, cellName, MAXCELLCHARS);
+    c_handle->working_cell[MAXCELLCHARS - 1] = '\0';
     if (!(tdir = afsconf_Open(AFSDIR_CLIENT_ETC_DIRPATH))) {
        tst = ADMCLIENTBADCLIENTCONFIG;
        goto fail_afsclient_CellOpen;
@@ -878,7 +874,8 @@ afsclient_CellOpen(const char *cellName, const void *tokenHandle,
      * We must copy the cellName here because afsconf_GetCellInfo
      * actually writes over the cell name it is passed.
      */
-    strncpy(copyCell, cellName, MAXCELLCHARS - 1);
+    strncpy(copyCell, cellName, MAXCELLCHARS);
+    copyCell[MAXCELLCHARS - 1] ='\0';
     for (i = 0; (i < NUM_SERVER_TYPES); i++) {
        if (i == KAS) {
            tst =
@@ -942,6 +939,8 @@ afsclient_CellOpen(const char *cellName, const void *tokenHandle,
        c_handle->begin_magic = BEGIN_MAGIC;
        c_handle->is_valid = 1;
        c_handle->is_null = 0;
+       c_handle->server_list = NULL;
+       c_handle->server_ttl = 0;
        c_handle->end_magic = END_MAGIC;
        *cellHandleP = (void *)c_handle;
     }
@@ -1016,9 +1015,11 @@ afsclient_NullCellOpen(void **cellHandleP, afs_status_p st)
     c_handle->kas_valid = 0;
     c_handle->pts_valid = 0;
     c_handle->vos_valid = 0;
-    c_handle->kas = 0;
-    c_handle->pts = 0;
-    c_handle->vos = 0;
+    c_handle->kas = NULL;
+    c_handle->pts = NULL;
+    c_handle->vos = NULL;
+    c_handle->server_list = NULL;
+    c_handle->server_ttl = 0;
     *cellHandleP = (void *)c_handle;
     rc = 1;
 
@@ -1067,6 +1068,8 @@ afsclient_CellClose(const void *cellHandle, afs_status_p st)
        goto fail_afsclient_CellClose;
     }
 
+    if (c_handle->server_list)
+       free(c_handle->server_list);
     if (c_handle->kas_valid)
        ubik_ClientDestroy(c_handle->kas);
     if (c_handle->pts_valid)
@@ -1224,7 +1227,7 @@ client_ExtractDriveLetter(char *path)
 static int
 Parent(char *directory, char *parentDirectory)
 {
-    register char *tp;
+    char *tp;
     int rc = 0;
 
     strcpy(parentDirectory, directory);
@@ -1354,7 +1357,8 @@ afsclient_MountPointCreate(const void *cellHandle, const char *directory,
      */
 
     if (volCheck == CHECK_VOLUME) {
-       if (!vos_VLDBGet(cellHandle, 0, 0, volumeName, &vldbEntry, &tst)) {
+       if (!vos_VLDBGet(cellHandle, 0, 0, (char *)volumeName, &vldbEntry,
+                        &tst)) {
            goto fail_afsclient_MountPointCreate;
        }
     }
@@ -1486,7 +1490,7 @@ afsclient_ACLEntryAdd(const char *directory, const char *user,
     idata.out_size = 2048;
     idata.in_size = 0;
     idata.in = idata.out = old_acl_string;
-    tst = pioctl(directory, VIOCGETAL, &idata, 1);
+    tst = pioctl((char *)directory, VIOCGETAL, &idata, 1);
 
     if (tst != 0) {
        goto fail_afsclient_ACLEntryAdd;
@@ -1528,7 +1532,7 @@ afsclient_ACLEntryAdd(const char *directory, const char *user,
      */
 
     is_dfs =
-       sscanf(old_acl_string, "%d dfs:%d %s", &cur_acl.nplus, &cur_acl.dfs,
+       sscanf(old_acl_string, "%d dfs:%d %1024s", &cur_acl.nplus, &cur_acl.dfs,
               cur_acl.cell);
     ptr = strchr(old_acl_string, '\n');
     ptr++;
@@ -1553,7 +1557,7 @@ afsclient_ACLEntryAdd(const char *directory, const char *user,
      */
 
     for (i = 0; i < (cur_acl.nplus + cur_acl.nminus); i++) {
-       sscanf(ptr, "%s%d\n", cur_user, &cur_user_acl);
+       sscanf(ptr, "%63s%d\n", cur_user, &cur_user_acl);
        /*
         * Skip the entry for the user we are replacing/adding
         */
@@ -1575,7 +1579,7 @@ afsclient_ACLEntryAdd(const char *directory, const char *user,
     idata.out_size = 0;
     idata.in_size = strlen(new_acl_string) + 1;
     idata.in = idata.out = new_acl_string;
-    tst = pioctl(directory, VIOCSETAL, &idata, 1);
+    tst = pioctl((char *) directory, VIOCSETAL, &idata, 1);
 
     if (tst != 0) {
        goto fail_afsclient_ACLEntryAdd;
@@ -1818,10 +1822,10 @@ afsclient_AFSServerGetBegin(const void *cellHandle, void **iterationIdP,
     int rc = 0;
     afs_status_t tst = 0;
     afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
-    afs_admin_iterator_p iter =
-       (afs_admin_iterator_p) malloc(sizeof(afs_admin_iterator_t));
-    server_get_p serv = (server_get_p) calloc(1, sizeof(server_get_t));
-    const char *cellName;
+    afs_admin_iterator_p iter = malloc(sizeof(afs_admin_iterator_t));
+    server_get_p serv = calloc(1, sizeof(server_get_t));
+    server_get_p serv_cache = NULL;
+    const char *cellName = NULL;
     void *database_iter;
     util_databaseServerEntry_t database_entry;
     void *fileserver_iter;
@@ -1843,57 +1847,77 @@ afsclient_AFSServerGetBegin(const void *cellHandle, void **iterationIdP,
        goto fail_afsclient_AFSServerGetBegin;
     }
 
-    /*
-     * Retrieve the list of database servers for this cell.
-     */
-
-    if (!afsclient_CellNameGet(cellHandle, &cellName, &tst)) {
-       goto fail_afsclient_AFSServerGetBegin;
+  restart:
+    LOCK_GLOBAL_MUTEX;
+    if (c_handle->server_list != NULL && c_handle->server_ttl < time(NULL)) {
+       serv_cache = c_handle->server_list;
+       c_handle->server_list = NULL;
     }
+    UNLOCK_GLOBAL_MUTEX;
 
-    if (!util_DatabaseServerGetBegin(cellName, &database_iter, &tst)) {
-       goto fail_afsclient_AFSServerGetBegin;
-    }
+    if (c_handle->server_list == NULL) {
+       if (serv_cache == NULL) {
+           serv_cache = (server_get_p) calloc(1, sizeof(server_get_t));
 
-    while (util_DatabaseServerGetNext(database_iter, &database_entry, &tst)) {
-       serv->server[serv->total].serverAddress[0] =
-           database_entry.serverAddress;
-       serv->server[serv->total].serverType = DATABASE_SERVER;
-       serv->total++;
-    }
+           if (serv_cache == NULL) {
+               tst = ADMNOMEM;
+               goto fail_afsclient_AFSServerGetBegin;
+           }
+       }
 
-    if (tst != ADMITERATORDONE) {
-       util_DatabaseServerGetDone(database_iter, 0);
-       goto fail_afsclient_AFSServerGetBegin;
-    }
+       /*
+        * Retrieve the list of database servers for this cell.
+        */
 
-    if (!util_DatabaseServerGetDone(database_iter, &tst)) {
-       goto fail_afsclient_AFSServerGetBegin;
-    }
+       if (!afsclient_CellNameGet(c_handle, &cellName, &tst)) {
+           goto fail_afsclient_AFSServerGetBegin;
+       }
 
-    /*
-     * Retrieve the list of file servers for this cell.
-     */
+       if (!util_DatabaseServerGetBegin(cellName, &database_iter, &tst)) {
+           goto fail_afsclient_AFSServerGetBegin;
+       }
 
-    if (!vos_FileServerGetBegin(cellHandle, 0, &fileserver_iter, &tst)) {
-       goto fail_afsclient_AFSServerGetBegin;
-    }
+       while (util_DatabaseServerGetNext(database_iter, &database_entry, &tst)) {
+           serv->server[serv->total].serverAddress[0] =
+               database_entry.serverAddress;
+           serv->server[serv->total].serverType = DATABASE_SERVER;
+           serv->total++;
+       }
+
+       if (tst != ADMITERATORDONE) {
+           util_DatabaseServerGetDone(database_iter, 0);
+           goto fail_afsclient_AFSServerGetBegin;
+       }
+
+       if (!util_DatabaseServerGetDone(database_iter, &tst)) {
+           goto fail_afsclient_AFSServerGetBegin;
+       }
 
-    while (vos_FileServerGetNext(fileserver_iter, &fileserver_entry, &tst)) {
        /*
-        * See if any of the addresses returned in this fileserver_entry
-        * structure already exist in the list of servers we're building.
-        * If not, create a new record for this server.
+        * Retrieve the list of file servers for this cell.
         */
-       is_dup = 0;
-       for (iserv = 0; iserv < serv->total; iserv++) {
-           for (ientryaddr = 0; ientryaddr < fileserver_entry.count;
-                ientryaddr++) {
-               for (iservaddr = 0; iservaddr < AFS_MAX_SERVER_ADDRESS;
-                    iservaddr++) {
-                   if (serv->server[iserv].serverAddress[iservaddr] ==
-                       fileserver_entry.serverAddress[ientryaddr]) {
-                       is_dup = 1;
+
+       if (!vos_FileServerGetBegin(c_handle, 0, &fileserver_iter, &tst)) {
+           goto fail_afsclient_AFSServerGetBegin;
+       }
+
+       while (vos_FileServerGetNext(fileserver_iter, &fileserver_entry, &tst)) {
+           /*
+            * See if any of the addresses returned in this fileserver_entry
+            * structure already exist in the list of servers we're building.
+            * If not, create a new record for this server.
+            */
+           is_dup = 0;
+           for (iserv = 0; iserv < serv->total; iserv++) {
+               for (ientryaddr = 0; ientryaddr < fileserver_entry.count; ientryaddr++) {
+                   for (iservaddr = 0; iservaddr < AFS_MAX_SERVER_ADDRESS; iservaddr++) {
+                       if (serv->server[iserv].serverAddress[iservaddr] ==
+                            fileserver_entry.serverAddress[ientryaddr]) {
+                           is_dup = 1;
+                           break;
+                       }
+                   }
+                   if (is_dup) {
                        break;
                    }
                }
@@ -1901,71 +1925,80 @@ afsclient_AFSServerGetBegin(const void *cellHandle, void **iterationIdP,
                    break;
                }
            }
+
            if (is_dup) {
-               break;
+               serv->server[iserv].serverType |= FILE_SERVER;
+           } else {
+               iserv = serv->total++;
+               serv->server[iserv].serverType = FILE_SERVER;
            }
-       }
 
-       if (is_dup) {
-           serv->server[iserv].serverType |= FILE_SERVER;
-       } else {
-           iserv = serv->total++;
-           serv->server[iserv].serverType = FILE_SERVER;
-       }
+           /*
+            * Add the addresses from the vldb list to the serv->server[iserv]
+            * record.  Remember that VLDB's list-of-addrs is not guaranteed
+            * to be unique in a particular entry, or to return only one entry
+            * per machine--so when we add addresses, always check for
+            * duplicate entries.
+            */
 
-       /*
-        * Add the addresses from the vldb list to the serv->server[iserv]
-        * record.  Remember that VLDB's list-of-addrs is not guaranteed
-        * to be unique in a particular entry, or to return only one entry
-        * per machine--so when we add addresses, always check for
-        * duplicate entries.
-        */
-
-       for (ientryaddr = 0; ientryaddr < fileserver_entry.count;
-            ientryaddr++) {
-           for (iservaddr = 0; iservaddr < AFS_MAX_SERVER_ADDRESS;
-                iservaddr++) {
-               if (serv->server[iserv].serverAddress[iservaddr] ==
-                   fileserver_entry.serverAddress[ientryaddr]) {
-                   break;
-               }
-           }
-           if (iservaddr == AFS_MAX_SERVER_ADDRESS) {
-               for (iservaddr = 0; iservaddr < AFS_MAX_SERVER_ADDRESS;
-                    iservaddr++) {
-                   if (!serv->server[iserv].serverAddress[iservaddr]) {
-                       serv->server[iserv].serverAddress[iservaddr] =
-                           fileserver_entry.serverAddress[ientryaddr];
+           for (ientryaddr = 0; ientryaddr < fileserver_entry.count; ientryaddr++) {
+               for (iservaddr = 0; iservaddr < AFS_MAX_SERVER_ADDRESS; iservaddr++) {
+                   if (serv->server[iserv].serverAddress[iservaddr] ==
+                        fileserver_entry.serverAddress[ientryaddr]) {
                        break;
                    }
                }
+               if (iservaddr == AFS_MAX_SERVER_ADDRESS) {
+                   for (iservaddr = 0; iservaddr < AFS_MAX_SERVER_ADDRESS;
+                         iservaddr++) {
+                       if (!serv->server[iserv].serverAddress[iservaddr]) {
+                           serv->server[iserv].serverAddress[iservaddr] =
+                               fileserver_entry.serverAddress[ientryaddr];
+                           break;
+                       }
+                   }
+               }
            }
        }
-    }
 
-    if (tst != ADMITERATORDONE) {
-       vos_FileServerGetDone(fileserver_iter, 0);
-       goto fail_afsclient_AFSServerGetBegin;
-    }
+       if (tst != ADMITERATORDONE) {
+           vos_FileServerGetDone(fileserver_iter, 0);
+           goto fail_afsclient_AFSServerGetBegin;
+       }
 
-    if (!vos_FileServerGetDone(fileserver_iter, &tst)) {
-       goto fail_afsclient_AFSServerGetBegin;
-    }
+       if (!vos_FileServerGetDone(fileserver_iter, &tst)) {
+           goto fail_afsclient_AFSServerGetBegin;
+       }
 
-    /*
-     * Iterate over the list and fill in the hostname of each of the servers
-     */
+       /*
+        * Iterate over the list and fill in the hostname of each of the servers
+        */
 
-    LOCK_GLOBAL_MUTEX;
-    for (iserv = 0; iserv < serv->total; iserv++) {
-       int addr = htonl(serv->server[iserv].serverAddress[0]);
-       host = gethostbyaddr((const char *)&addr, sizeof(int), AF_INET);
-       if (host != NULL) {
-           strncpy(serv->server[iserv].serverName, host->h_name,
-                   AFS_MAX_SERVER_NAME_LEN);
+       for (iserv = 0; iserv < serv->total; iserv++) {
+           int addr = htonl(serv->server[iserv].serverAddress[0]);
+           LOCK_GLOBAL_MUTEX;
+           host = gethostbyaddr((const char *)&addr, sizeof(int), AF_INET);
+           if (host != NULL) {
+               strncpy(serv->server[iserv].serverName, host->h_name,
+                        AFS_MAX_SERVER_NAME_LEN);
+               serv->server[iserv].serverName[AFS_MAX_SERVER_NAME_LEN - 1] = '\0';
+           }
+           UNLOCK_GLOBAL_MUTEX;
        }
+    
+       memcpy(serv_cache, serv, sizeof(server_get_t));
+    } else {
+       int race = 0;
+       LOCK_GLOBAL_MUTEX;
+       if (c_handle->server_list == NULL)
+           race = 1;
+       else
+           memcpy(serv, c_handle->server_list, sizeof(server_get_t));
+       UNLOCK_GLOBAL_MUTEX;
+       if (race)
+           goto restart;
     }
-    UNLOCK_GLOBAL_MUTEX;
+
     if (IteratorInit
            (iter, (void *)serv, GetServerRPC, GetServerFromCache, NULL, NULL,
             &tst)) {
@@ -1976,17 +2009,28 @@ afsclient_AFSServerGetBegin(const void *cellHandle, void **iterationIdP,
   fail_afsclient_AFSServerGetBegin:
 
     if (rc == 0) {
-       if (iter != NULL) {
+       if (iter != NULL)
            free(iter);
-       }
-       if (serv != NULL) {
+       if (serv != NULL)
            free(serv);
+       if (serv_cache != NULL)
+           free(serv_cache);
+    } else {
+       if (serv_cache) {
+           LOCK_GLOBAL_MUTEX;
+           /* in case there was a race and we constructed the list twice */
+           if (c_handle->server_list)
+               free(c_handle->server_list);
+
+           c_handle->server_list = serv_cache;
+           c_handle->server_ttl = time(NULL) + SERVER_TTL;
+           UNLOCK_GLOBAL_MUTEX;
        }
     }
 
-    if (st != NULL) {
+    if (st != NULL)
        *st = tst;
-    }
+
     return rc;
 }
 
@@ -2609,7 +2653,7 @@ afsclient_RXDebugOpen(const char *serverName, afs_stat_source_t type,
        goto fail_afsclient_RXDebugOpen;
     }
 
-    handle = (rxdebugHandle_p) malloc(sizeof(rxdebugHandle_t));
+    handle = malloc(sizeof(rxdebugHandle_t));
     if (!handle) {
        close(sock);
        tst = ADMNOMEM;
@@ -2694,7 +2738,7 @@ afsclient_RXDebugOpenPort(const char *serverName, int serverPort,
        goto fail_afsclient_RXDebugOpenPort;
     }
 
-    handle = (rxdebugHandle_p) malloc(sizeof(rxdebugHandle_t));
+    handle = malloc(sizeof(rxdebugHandle_t));
     if (!handle) {
        close(sock);
        tst = ADMNOMEM;