153bc5663c98dae9b0c55ab02ff4581f0583f9b4
[openafs.git] / src / auth / writeconfig.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  * 
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 #include <afsconfig.h>
11 #include <afs/param.h>
12
13 RCSID
14     ("$Header$");
15
16 #include <afs/pthread_glock.h>
17 #include <afs/afsutil.h>
18 #include <sys/types.h>
19 #ifdef AFS_NT40_ENV
20 #include <winsock2.h>
21 #include <fcntl.h>
22 #include <io.h>
23 #else
24 #include <sys/file.h>
25 #include <sys/socket.h>
26 #include <netinet/in.h>
27 #include <netdb.h>
28 #endif
29 #include <stdio.h>
30 #include <errno.h>
31 #include <string.h>
32 #ifdef HAVE_FCNTL_H
33 #include <fcntl.h>
34 #endif
35 #ifdef HAVE_UNISTD_H
36 #include <unistd.h>
37 #endif
38 #include "cellconfig.h"
39 #include "keys.h"
40
41 /* write ThisCell and CellServDB containing exactly one cell's info specified
42     by acellInfo parm.   Useful only on the server (which describes only one cell).
43 */
44
45 static int
46 VerifyEntries(aci)
47      register struct afsconf_cell *aci;
48 {
49     register int i;
50     register struct hostent *th;
51
52     for (i = 0; i < aci->numServers; i++) {
53         if (aci->hostAddr[i].sin_addr.s_addr == 0) {
54             /* no address spec'd */
55             if (*(aci->hostName[i]) != 0) {
56                 th = gethostbyname(aci->hostName[i]);
57                 if (!th) {
58                     printf("Host %s not found in host database...\n",
59                            aci->hostName[i]);
60                     return AFSCONF_FAILURE;
61                 }
62                 memcpy(&aci->hostAddr[i].sin_addr, th->h_addr,
63                        sizeof(afs_int32));
64             }
65             /* otherwise we're deleting this entry */
66         } else {
67             /* address spec'd, perhaps no name known */
68             if (aci->hostName[i][0] != 0)
69                 continue;       /* name known too */
70             /* figure out name, if possible */
71             th = gethostbyaddr((char *)(&aci->hostAddr[i].sin_addr), 4,
72                                AF_INET);
73             if (!th) {
74                 strcpy(aci->hostName[i], "UNKNOWNHOST");
75             } else {
76                 strcpy(aci->hostName[i], th->h_name);
77             }
78         }
79     }
80     return 0;
81 }
82
83 /* Changed the interface to accept the afsconf_dir datastructure.
84    This is a handle to the internal cache that is maintained by the bosserver.
85    */
86
87 int
88 afsconf_SetCellInfo(adir, apath, acellInfo)
89      struct afsconf_dir *adir;
90      char *apath;
91      struct afsconf_cell *acellInfo;
92 {
93     afs_int32 code;
94
95     code = afsconf_SetExtendedCellInfo(adir, apath, acellInfo, NULL);
96     return code;
97 }
98
99 int
100 afsconf_SetExtendedCellInfo(adir, apath, acellInfo, clones)
101      struct afsconf_dir *adir;
102      char *apath;
103      struct afsconf_cell *acellInfo;
104      char clones[];
105 {
106     register afs_int32 code;
107     register int fd;
108     char tbuffer[1024];
109     register FILE *tf;
110     register afs_int32 i;
111
112     LOCK_GLOBAL_MUTEX;
113     /* write ThisCell file */
114     strcompose(tbuffer, 1024, apath, "/", AFSDIR_THISCELL_FILE, NULL);
115
116     fd = open(tbuffer, O_RDWR | O_CREAT | O_TRUNC, 0666);
117     if (fd < 0) {
118         UNLOCK_GLOBAL_MUTEX;
119         return errno;
120     }
121     i = (int)strlen(acellInfo->name);
122     code = write(fd, acellInfo->name, i);
123     if (code != i) {
124         UNLOCK_GLOBAL_MUTEX;
125         return AFSCONF_FAILURE;
126     }
127     if (close(fd) < 0) {
128         UNLOCK_GLOBAL_MUTEX;
129         return errno;
130     }
131
132     /* make sure we have both name and address for each host, looking up other
133      * if need be */
134     code = VerifyEntries(acellInfo);
135     if (code) {
136         UNLOCK_GLOBAL_MUTEX;
137         return code;
138     }
139
140     /* write CellServDB */
141     strcompose(tbuffer, 1024, apath, "/", AFSDIR_CELLSERVDB_FILE, NULL);
142     tf = fopen(tbuffer, "w");
143     if (!tf) {
144         UNLOCK_GLOBAL_MUTEX;
145         return AFSCONF_NOTFOUND;
146     }
147     fprintf(tf, ">%s    #Cell name\n", acellInfo->name);
148     for (i = 0; i < acellInfo->numServers; i++) {
149         code = acellInfo->hostAddr[i].sin_addr.s_addr;  /* net order */
150         if (code == 0)
151             continue;           /* delete request */
152         code = ntohl(code);     /* convert to host order */
153         if (clones && clones[i])
154             fprintf(tf, "[%d.%d.%d.%d]  #%s\n", (code >> 24) & 0xff,
155                     (code >> 16) & 0xff, (code >> 8) & 0xff, code & 0xff,
156                     acellInfo->hostName[i]);
157         else
158             fprintf(tf, "%d.%d.%d.%d    #%s\n", (code >> 24) & 0xff,
159                     (code >> 16) & 0xff, (code >> 8) & 0xff, code & 0xff,
160                     acellInfo->hostName[i]);
161     }
162     if (ferror(tf)) {
163         fclose(tf);
164         UNLOCK_GLOBAL_MUTEX;
165         return AFSCONF_FAILURE;
166     }
167     code = fclose(tf);
168
169     /* Reset the timestamp in the cache, so that
170      * the CellServDB is read into the cache next time.
171      * Resolves the lost update problem due to an inconsistent cache
172      */
173     if (adir)
174         adir->timeRead = 0;
175
176     UNLOCK_GLOBAL_MUTEX;
177     if (code == EOF)
178         return AFSCONF_FAILURE;
179     return 0;
180 }