auth: Avoid cellconfig.c stdio renaming
[openafs.git] / src / auth / cellconfig.c
index b2fe227..d41d4d2 100644 (file)
@@ -195,12 +195,39 @@ afsconf_fgets(char *s, int n, afsconf_FILE *iop)
        }
     }
 }
-#define fopen afsconf_fopen
-#define fclose afsconf_fclose
-#define fgets afsconf_fgets
-#else
-#define afsconf_FILE FILE
-#endif /* AFS_SUN5_ENV && ! __sparcv9 */
+
+#else /* AFS_SUN5_ENV && !__sparcv9 */
+
+/*
+ * On all other platforms, we use the native stdio functions. We still go
+ * through our afsconf_f* wrappers here, to still do compile-time checks to
+ * make sure we don't mix afsconf_fopen with real stdio calls.
+ */
+struct afsconf_iobuffer;
+
+typedef struct afsconf_iobuffer afsconf_FILE;
+
+static afsconf_FILE *
+afsconf_fopen(const char *fname, const char *fmode)
+{
+    return (afsconf_FILE*)fopen(fname, fmode);
+}
+
+static int
+afsconf_fclose(afsconf_FILE *iop)
+{
+    FILE *fh = (FILE *)iop;
+    return fclose(fh);
+}
+
+static char *
+afsconf_fgets(char *s, int n, afsconf_FILE *iop)
+{
+    FILE *fh = (FILE *)iop;
+    return fgets(s, n, fh);
+}
+
+#endif /* AFS_SUN5_ENV && !__sparcv9 */
 
 /* return port number in network byte order in the low 16 bits of a long; return -1 if not found */
 afs_int32
@@ -315,32 +342,32 @@ _afsconf_IsClientConfigDirectory(const char *path)
 
 #ifdef AFS_NT40_ENV
 static void
-_afsconf_CellServDBPath(struct afsconf_dir *adir, char **path)
+_afsconf_CellServDBPath(const char *dirname, char **path)
 {
     char *p;
 
     /* NT client CellServDB has different file name than NT server or Unix */
-    if (_afsconf_IsClientConfigDirectory(adir->name)) {
+    if (_afsconf_IsClientConfigDirectory(dirname)) {
        if (!afssw_GetClientCellServDBDir(&p)) {
            if (asprintf(path, "%s/%s", p, AFSDIR_CELLSERVDB_FILE_NTCLIENT) < 0)
                *path = NULL;
            free(p);
        } else {
-           if (asprintf(path, "%s/%s", adir->name,
+           if (asprintf(path, "%s/%s", dirname,
                         AFSDIR_CELLSERVDB_FILE_NTCLIENT) < 0)
                *path = NULL;
        }
     } else {
-       if (asprintf(path, "%s/%s", adir->name, AFSDIR_CELLSERVDB_FILE) < 0)
+       if (asprintf(path, "%s/%s", dirname, AFSDIR_CELLSERVDB_FILE) < 0)
            *path = NULL;
     }
     return;
 }
 #else
 static void
-_afsconf_CellServDBPath(struct afsconf_dir *adir, char **path)
+_afsconf_CellServDBPath(const char *dirname, char **path)
 {
-    if (asprintf(path, "%s/%s", adir->name, AFSDIR_CELLSERVDB_FILE) < 0)
+    if (asprintf(path, "%s/%s", dirname, AFSDIR_CELLSERVDB_FILE) < 0)
        *path = NULL;
 }
 #endif /* AFS_NT40_ENV */
@@ -446,12 +473,12 @@ ReadFirstLine(const char *pathname, char **aline)
     afsconf_FILE *fp;
     size_t len = 0;
 
-    fp = fopen(pathname, "r");
+    fp = afsconf_fopen(pathname, "r");
     if (!fp)
        return ENOENT;
-    if (fgets(buffer, sizeof(buffer), fp) != NULL)
+    if (afsconf_fgets(buffer, sizeof(buffer), fp) != NULL)
        len = strlen(buffer);
-    fclose(fp);
+    afsconf_fclose(fp);
     if (len == 0)
        return EIO;
     /* Trim the trailing newline, if one. */
@@ -578,12 +605,12 @@ GetCellUnix(struct afsconf_dir *adir)
 
     strcompose(tbuffer, 256, adir->name, "/", AFSDIR_THISCELL_FILE,
        (char *)NULL);
-    fp = fopen(tbuffer, "r");
+    fp = afsconf_fopen(tbuffer, "r");
     if (fp == 0) {
        return -1;
     }
-    rc = fgets(tbuffer, 256, fp);
-    fclose(fp);
+    rc = afsconf_fgets(tbuffer, 256, fp);
+    afsconf_fclose(fp);
     if (rc == NULL)
         return -1;
 
@@ -732,7 +759,7 @@ LoadConfig(struct afsconf_dir *adir)
     /* now parse the individual lines */
     curEntry = 0;
 
-    _afsconf_CellServDBPath(adir, &adir->cellservDB);
+    _afsconf_CellServDBPath(adir->name, &adir->cellservDB);
 
 #ifdef AFS_NT40_ENV
     if (_afsconf_IsClientConfigDirectory(adir->name))
@@ -745,7 +772,7 @@ LoadConfig(struct afsconf_dir *adir)
        adir->timeRead = 0;
     }
 
-    tf = fopen(adir->cellservDB, "r");
+    tf = afsconf_fopen(adir->cellservDB, "r");
     if (!tf) {
        return -1;
     }
@@ -763,7 +790,7 @@ LoadConfig(struct afsconf_dir *adir)
      */
 
     while (1) {
-       tp = fgets(tbuffer, sizeof(tbuffer), tf);
+       tp = afsconf_fgets(tbuffer, sizeof(tbuffer), tf);
        if (!tp)
            break;
        TrimLine(tbuffer, sizeof tbuffer);      /* remove white space */
@@ -783,7 +810,7 @@ LoadConfig(struct afsconf_dir *adir)
                ParseCellLine(tbuffer, curEntry->cellInfo.name, linkedcell);
            if (code) {
                UnloadConfig(adir);
-               fclose(tf);
+               afsconf_fclose(tf);
                free(curEntry);
                return -1;
            }
@@ -793,7 +820,7 @@ LoadConfig(struct afsconf_dir *adir)
            /* new host in the current cell */
            if (!curEntry) {
                UnloadConfig(adir);
-               fclose(tf);
+               afsconf_fclose(tf);
                return -1;
            }
            i = curEntry->cellInfo.numServers;
@@ -814,7 +841,7 @@ LoadConfig(struct afsconf_dir *adir)
                                tbuffer, adir->cellservDB);
                    }
                    free(curEntry);
-                   fclose(tf);
+                   afsconf_fclose(tf);
                    UnloadConfig(adir);
                    return -1;
                }
@@ -826,7 +853,7 @@ LoadConfig(struct afsconf_dir *adir)
            }
        }
     }
-    fclose(tf);                        /* close the file now */
+    afsconf_fclose(tf);                        /* close the file now */
 
     /* end the last partially-completed cell */
     if (curEntry) {
@@ -850,11 +877,11 @@ LoadConfig(struct afsconf_dir *adir)
     strcompose(tbuffer, 256, adir->name, "/", AFSDIR_CELLALIAS_FILE,
        (char *)NULL);
 
-    tf = fopen(tbuffer, "r");
+    tf = afsconf_fopen(tbuffer, "r");
     while (tf) {
        char *aliasPtr;
 
-       tp = fgets(tbuffer, sizeof(tbuffer), tf);
+       tp = afsconf_fgets(tbuffer, sizeof(tbuffer), tf);
        if (!tp)
            break;
        TrimLine(tbuffer, sizeof tbuffer);      /* remove white space */
@@ -889,7 +916,7 @@ LoadConfig(struct afsconf_dir *adir)
     }
 
     if (tf != NULL)
-       fclose(tf);
+       afsconf_fclose(tf);
 
     /* now read the fs keys, if possible */
     code = _afsconf_LoadKeys(adir);
@@ -1684,3 +1711,200 @@ afsconf_Reopen(struct afsconf_dir *adir)
     code = LoadConfig(adir);
     return code;
 }
+
+static int
+VerifyEntries(struct afsconf_cell *aci)
+{
+    int i;
+    struct hostent *th;
+
+    for (i = 0; i < aci->numServers; i++) {
+       if (aci->hostAddr[i].sin_addr.s_addr == 0) {
+           /* no address spec'd */
+           if (*(aci->hostName[i]) != 0) {
+               int code;
+               struct addrinfo hints;
+               struct addrinfo *result;
+               struct addrinfo *rp;
+
+               memset(&hints, 0, sizeof(struct addrinfo));
+               hints.ai_family = AF_INET;
+               hints.ai_socktype = SOCK_DGRAM;
+
+               code = getaddrinfo(aci->hostName[i], NULL, &hints, &result);
+               if (code) {
+                   printf("Host %s not found in host database...\n",
+                          aci->hostName[i]);
+                   return AFSCONF_FAILURE;
+               }
+               for (rp = result; rp != NULL; rp = rp->ai_next) {
+                   struct sockaddr_in *sa = (struct sockaddr_in *)rp->ai_addr;
+                   if (!rx_IsLoopbackAddr(ntohl(sa->sin_addr.s_addr))) {
+                       aci->hostAddr[i].sin_addr.s_addr = sa->sin_addr.s_addr;
+                       break;
+                   }
+               }
+               freeaddrinfo(result);
+               if (aci->hostAddr[i].sin_addr.s_addr == 0) {
+                   printf("No non-loopback addresses found for host %s\n",
+                          aci->hostName[i]);
+                   return AFSCONF_FAILURE;
+               }
+           }
+           /* otherwise we're deleting this entry */
+       } else {
+           /* address spec'd, perhaps no name known */
+           if (aci->hostName[i][0] != 0)
+               continue;       /* name known too */
+           /* figure out name, if possible */
+           th = gethostbyaddr((char *)(&aci->hostAddr[i].sin_addr), 4,
+                              AF_INET);
+           if (!th) {
+               strcpy(aci->hostName[i], "UNKNOWNHOST");
+           } else {
+               if (strlcpy(aci->hostName[i],
+                           th->h_name,
+                           sizeof(aci->hostName[i]))
+                       >= sizeof(aci->hostName[i])) {
+                  strcpy(aci->hostName[i], "UNKNOWNHOST");
+               }
+           }
+       }
+    }
+    return 0;
+}
+
+/**
+ * Set cell information (deprecated)
+ *
+ * Write ThisCell and CellServDB containing exactly one cell's info specified
+ * by acellInfo param.  Useful only on the server (which describes only one
+ * cell).
+ *
+ * @param adir       cell configuation data; may be NULL
+ * @param apath      cell configuration path
+ * @param acellInfo  cell information
+ *
+ * @note This interface was changed at some point to optionally accept the
+ *       afsconf_dir data structure.  This is a handle to the internal cache
+ *       that is maintained by the bosserver.
+ *
+ * @return 0 on success
+ */
+int
+afsconf_SetCellInfo(struct afsconf_dir *adir, const char *apath,
+                   struct afsconf_cell *acellInfo)
+{
+    afs_int32 code;
+
+    code = afsconf_SetExtendedCellInfo(adir, apath, acellInfo, NULL);
+    return code;
+}
+
+/**
+ * Set cell information
+ *
+ * Write ThisCell and CellServDB containing exactly one cell's info specified
+ * by acellInfo param.  Useful only on the server (which describes only one
+ * cell).
+ *
+ * @param adir       cell configuation data; may be NULL
+ * @param apath      cell configuration path
+ * @param acellInfo  cell information
+ * @param clones     array of booleans to indicate which hosts are clones
+ *
+ * @return 0 on success
+ */
+int
+afsconf_SetExtendedCellInfo(struct afsconf_dir *adir,
+                           const char *apath,
+                           struct afsconf_cell *acellInfo, char clones[])
+{
+    afs_int32 code;
+    int fd;
+    char tbuffer[1024];
+    FILE *tf;
+    afs_int32 i;
+
+    opr_Assert(apath);
+    opr_Assert(acellInfo);
+
+    LOCK_GLOBAL_MUTEX;
+    /* write ThisCell file */
+    strcompose(tbuffer, 1024, apath, "/", AFSDIR_THISCELL_FILE, (char *)NULL);
+
+    fd = open(tbuffer, O_RDWR | O_CREAT | O_TRUNC, 0666);
+    if (fd < 0) {
+       UNLOCK_GLOBAL_MUTEX;
+       return errno;
+    }
+    i = (int)strlen(acellInfo->name);
+    code = write(fd, acellInfo->name, i);
+    if (code != i) {
+       close(fd);
+       UNLOCK_GLOBAL_MUTEX;
+       return AFSCONF_FAILURE;
+    }
+    if (close(fd) < 0) {
+       UNLOCK_GLOBAL_MUTEX;
+       return errno;
+    }
+
+    /* make sure we have both name and address for each host, looking up other
+     * if need be */
+    code = VerifyEntries(acellInfo);
+    if (code) {
+       UNLOCK_GLOBAL_MUTEX;
+       return code;
+    }
+
+    /* write CellServDB */
+    if (adir) {
+       tf = fopen(adir->cellservDB, "w");
+    } else {
+       char *cellservDB = NULL;
+       _afsconf_CellServDBPath(apath, &cellservDB);
+       if (cellservDB)
+           tf = fopen(cellservDB, "w");
+       else
+           tf = NULL;
+       free(cellservDB);
+    }
+    if (!tf) {
+       UNLOCK_GLOBAL_MUTEX;
+       return AFSCONF_NOTFOUND;
+    }
+    fprintf(tf, ">%s   #Cell name\n", acellInfo->name);
+    for (i = 0; i < acellInfo->numServers; i++) {
+       code = acellInfo->hostAddr[i].sin_addr.s_addr;  /* net order */
+       if (code == 0)
+           continue;           /* delete request */
+       code = ntohl(code);     /* convert to host order */
+       if (clones && clones[i])
+           fprintf(tf, "[%d.%d.%d.%d]  #%s\n", (code >> 24) & 0xff,
+                   (code >> 16) & 0xff, (code >> 8) & 0xff, code & 0xff,
+                   acellInfo->hostName[i]);
+       else
+           fprintf(tf, "%d.%d.%d.%d    #%s\n", (code >> 24) & 0xff,
+                   (code >> 16) & 0xff, (code >> 8) & 0xff, code & 0xff,
+                   acellInfo->hostName[i]);
+    }
+    if (ferror(tf)) {
+       fclose(tf);
+       UNLOCK_GLOBAL_MUTEX;
+       return AFSCONF_FAILURE;
+    }
+    code = fclose(tf);
+
+    /* Reset the timestamp in the cache, so that
+     * the CellServDB is read into the cache next time.
+     * Resolves the lost update problem due to an inconsistent cache
+     */
+    if (adir)
+       adir->timeRead = 0;
+
+    UNLOCK_GLOBAL_MUTEX;
+    if (code == EOF)
+       return AFSCONF_FAILURE;
+    return 0;
+}