libroken: Build on windows
[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 #include <roken.h>
14
15 #include <afs/pthread_glock.h>
16 #include <afs/afsutil.h>
17 #include <sys/types.h>
18 #ifdef AFS_NT40_ENV
19 #include <winsock2.h>
20 #include <fcntl.h>
21 #include <io.h>
22 #else
23 #include <sys/file.h>
24 #include <sys/socket.h>
25 #include <netinet/in.h>
26 #include <netdb.h>
27 #endif
28 #include <stdio.h>
29 #include <errno.h>
30 #include <string.h>
31 #ifdef HAVE_FCNTL_H
32 #include <fcntl.h>
33 #endif
34 #ifdef HAVE_UNISTD_H
35 #include <unistd.h>
36 #endif
37 #include <rx/rxkad.h>
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(struct afsconf_cell *aci)
47 {
48     int i;
49     struct hostent *th;
50
51     for (i = 0; i < aci->numServers; i++) {
52         if (aci->hostAddr[i].sin_addr.s_addr == 0) {
53             /* no address spec'd */
54             if (*(aci->hostName[i]) != 0) {
55                 th = gethostbyname(aci->hostName[i]);
56                 if (!th) {
57                     printf("Host %s not found in host database...\n",
58                            aci->hostName[i]);
59                     return AFSCONF_FAILURE;
60                 }
61                 memcpy(&aci->hostAddr[i].sin_addr, th->h_addr,
62                        sizeof(afs_int32));
63             }
64             /* otherwise we're deleting this entry */
65         } else {
66             /* address spec'd, perhaps no name known */
67             if (aci->hostName[i][0] != 0)
68                 continue;       /* name known too */
69             /* figure out name, if possible */
70             th = gethostbyaddr((char *)(&aci->hostAddr[i].sin_addr), 4,
71                                AF_INET);
72             if (!th) {
73                 strcpy(aci->hostName[i], "UNKNOWNHOST");
74             } else {
75                 strcpy(aci->hostName[i], th->h_name);
76             }
77         }
78     }
79     return 0;
80 }
81
82 /* Changed the interface to accept the afsconf_dir datastructure.
83    This is a handle to the internal cache that is maintained by the bosserver.
84    */
85
86 int
87 afsconf_SetCellInfo(struct afsconf_dir *adir, const char *apath,
88                     struct afsconf_cell *acellInfo)
89 {
90     afs_int32 code;
91
92     code = afsconf_SetExtendedCellInfo(adir, apath, acellInfo, NULL);
93     return code;
94 }
95
96 int
97 afsconf_SetExtendedCellInfo(struct afsconf_dir *adir,
98                             const char *apath,
99                             struct afsconf_cell *acellInfo, char clones[])
100 {
101     afs_int32 code;
102     int fd;
103     char tbuffer[1024];
104     FILE *tf;
105     afs_int32 i;
106
107     LOCK_GLOBAL_MUTEX;
108     /* write ThisCell file */
109     strcompose(tbuffer, 1024, apath, "/", AFSDIR_THISCELL_FILE, NULL);
110
111     fd = open(tbuffer, O_RDWR | O_CREAT | O_TRUNC, 0666);
112     if (fd < 0) {
113         UNLOCK_GLOBAL_MUTEX;
114         return errno;
115     }
116     i = (int)strlen(acellInfo->name);
117     code = write(fd, acellInfo->name, i);
118     if (code != i) {
119         UNLOCK_GLOBAL_MUTEX;
120         return AFSCONF_FAILURE;
121     }
122     if (close(fd) < 0) {
123         UNLOCK_GLOBAL_MUTEX;
124         return errno;
125     }
126
127     /* make sure we have both name and address for each host, looking up other
128      * if need be */
129     code = VerifyEntries(acellInfo);
130     if (code) {
131         UNLOCK_GLOBAL_MUTEX;
132         return code;
133     }
134
135     /* write CellServDB */
136     strcompose(tbuffer, 1024, apath, "/", AFSDIR_CELLSERVDB_FILE, NULL);
137     tf = fopen(tbuffer, "w");
138     if (!tf) {
139         UNLOCK_GLOBAL_MUTEX;
140         return AFSCONF_NOTFOUND;
141     }
142     fprintf(tf, ">%s    #Cell name\n", acellInfo->name);
143     for (i = 0; i < acellInfo->numServers; i++) {
144         code = acellInfo->hostAddr[i].sin_addr.s_addr;  /* net order */
145         if (code == 0)
146             continue;           /* delete request */
147         code = ntohl(code);     /* convert to host order */
148         if (clones && clones[i])
149             fprintf(tf, "[%d.%d.%d.%d]  #%s\n", (code >> 24) & 0xff,
150                     (code >> 16) & 0xff, (code >> 8) & 0xff, code & 0xff,
151                     acellInfo->hostName[i]);
152         else
153             fprintf(tf, "%d.%d.%d.%d    #%s\n", (code >> 24) & 0xff,
154                     (code >> 16) & 0xff, (code >> 8) & 0xff, code & 0xff,
155                     acellInfo->hostName[i]);
156     }
157     if (ferror(tf)) {
158         fclose(tf);
159         UNLOCK_GLOBAL_MUTEX;
160         return AFSCONF_FAILURE;
161     }
162     code = fclose(tf);
163
164     /* Reset the timestamp in the cache, so that
165      * the CellServDB is read into the cache next time.
166      * Resolves the lost update problem due to an inconsistent cache
167      */
168     if (adir)
169         adir->timeRead = 0;
170
171     UNLOCK_GLOBAL_MUTEX;
172     if (code == EOF)
173         return AFSCONF_FAILURE;
174     return 0;
175 }