ticket-2618-patches-20031207
[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 #ifdef HAVE_STRING_H
32 #include <string.h>
33 #else
34 #ifdef HAVE_STRINGS_H
35 #include <strings.h>
36 #endif
37 #endif
38 #ifdef HAVE_FCNTL_H
39 #include <fcntl.h>
40 #endif
41 #ifdef HAVE_UNISTD_H
42 #include <unistd.h>
43 #endif
44 #include "cellconfig.h"
45 #include "keys.h"
46
47 /* write ThisCell and CellServDB containing exactly one cell's info specified
48     by acellInfo parm.   Useful only on the server (which describes only one cell).
49 */
50
51 static int
52 VerifyEntries(aci)
53      register struct afsconf_cell *aci;
54 {
55     register int i;
56     register struct hostent *th;
57
58     for (i = 0; i < aci->numServers; i++) {
59         if (aci->hostAddr[i].sin_addr.s_addr == 0) {
60             /* no address spec'd */
61             if (*(aci->hostName[i]) != 0) {
62                 th = gethostbyname(aci->hostName[i]);
63                 if (!th) {
64                     printf("Host %s not found in host database...\n",
65                            aci->hostName[i]);
66                     return AFSCONF_FAILURE;
67                 }
68                 memcpy(&aci->hostAddr[i].sin_addr, th->h_addr,
69                        sizeof(afs_int32));
70             }
71             /* otherwise we're deleting this entry */
72         } else {
73             /* address spec'd, perhaps no name known */
74             if (aci->hostName[i][0] != 0)
75                 continue;       /* name known too */
76             /* figure out name, if possible */
77             th = gethostbyaddr((char *)(&aci->hostAddr[i].sin_addr), 4,
78                                AF_INET);
79             if (!th) {
80                 strcpy(aci->hostName[i], "UNKNOWNHOST");
81             } else {
82                 strcpy(aci->hostName[i], th->h_name);
83             }
84         }
85     }
86     return 0;
87 }
88
89 /* Changed the interface to accept the afsconf_dir datastructure.
90    This is a handle to the internal cache that is maintained by the bosserver.
91    */
92
93 int
94 afsconf_SetCellInfo(adir, apath, acellInfo)
95      struct afsconf_dir *adir;
96      char *apath;
97      struct afsconf_cell *acellInfo;
98 {
99     afs_int32 code;
100
101     code = afsconf_SetExtendedCellInfo(adir, apath, acellInfo, NULL);
102     return code;
103 }
104
105 int
106 afsconf_SetExtendedCellInfo(adir, apath, acellInfo, clones)
107      struct afsconf_dir *adir;
108      char *apath;
109      struct afsconf_cell *acellInfo;
110      char clones[];
111 {
112     register afs_int32 code;
113     register int fd;
114     char tbuffer[1024];
115     register FILE *tf;
116     register afs_int32 i;
117
118     LOCK_GLOBAL_MUTEX
119         /* write ThisCell file */
120         strcompose(tbuffer, 1024, apath, "/", AFSDIR_THISCELL_FILE, NULL);
121
122     fd = open(tbuffer, O_RDWR | O_CREAT | O_TRUNC, 0666);
123     if (fd < 0) {
124         UNLOCK_GLOBAL_MUTEX return errno;
125     }
126     i = strlen(acellInfo->name);
127     code = write(fd, acellInfo->name, i);
128     if (code != i) {
129         UNLOCK_GLOBAL_MUTEX return AFSCONF_FAILURE;
130     }
131     if (close(fd) < 0) {
132         UNLOCK_GLOBAL_MUTEX return errno;
133     }
134
135     /* make sure we have both name and address for each host, looking up other
136      * if need be */
137     code = VerifyEntries(acellInfo);
138     if (code) {
139         UNLOCK_GLOBAL_MUTEX return code;
140     }
141
142     /* write CellServDB */
143     strcompose(tbuffer, 1024, apath, "/", AFSDIR_CELLSERVDB_FILE, NULL);
144     tf = fopen(tbuffer, "w");
145     if (!tf) {
146         UNLOCK_GLOBAL_MUTEX return AFSCONF_NOTFOUND;
147     }
148     fprintf(tf, ">%s    #Cell name\n", acellInfo->name);
149     for (i = 0; i < acellInfo->numServers; i++) {
150         code = acellInfo->hostAddr[i].sin_addr.s_addr;  /* net order */
151         if (code == 0)
152             continue;           /* delete request */
153         code = ntohl(code);     /* convert to host order */
154         if (clones && clones[i])
155             fprintf(tf, "[%d.%d.%d.%d]  #%s\n", (code >> 24) & 0xff,
156                     (code >> 16) & 0xff, (code >> 8) & 0xff, code & 0xff,
157                     acellInfo->hostName[i]);
158         else
159             fprintf(tf, "%d.%d.%d.%d    #%s\n", (code >> 24) & 0xff,
160                     (code >> 16) & 0xff, (code >> 8) & 0xff, code & 0xff,
161                     acellInfo->hostName[i]);
162     }
163     if (ferror(tf)) {
164         fclose(tf);
165         UNLOCK_GLOBAL_MUTEX 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 if (code == EOF)
177         return AFSCONF_FAILURE;
178     return 0;
179 }