death to trailing whitespace
[openafs.git] / src / bucoord / tape_hosts.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
14 #include <afs/stds.h>
15 #include <sys/types.h>
16 #ifdef AFS_NT40_ENV
17 #include <winsock2.h>
18 #else
19 #include <sys/socket.h>
20 #include <netinet/in.h>
21 #include <netdb.h>
22 #endif
23 #include <afs/budb_client.h>
24 #include <afs/cmd.h>
25 #include <afs/com_err.h>
26 #include <afs/bubasics.h>
27 #include "bc.h"
28 #include "error_macros.h"
29 #include <errno.h>
30 #include "bucoord_internal.h"
31 #include "bucoord_prototypes.h"
32
33 /* code to manage tape hosts
34  * specific to the ubik database implementation
35  */
36
37 extern struct bc_config *bc_globalConfig;
38 extern struct udbHandleS udbHandle;
39 extern char *whoami;
40
41 /* ------------------------------------
42  * command level routines
43  * ------------------------------------
44  */
45
46
47 /* bc_AddHostCmd
48  *      Add a host to the tape hosts
49  */
50
51 int
52 bc_AddHostCmd(struct cmd_syndesc *as, void *arock)
53 {
54     struct cmd_item *ti;
55     udbClientTextP ctPtr;
56     afs_int32 port = 0;
57     afs_int32 code = 0;
58
59     ctPtr = &bc_globalConfig->configText[TB_TAPEHOSTS];
60     code = bc_LockText(ctPtr);
61     if (code)
62         ERROR(code);
63
64     code = bc_UpdateHosts();
65     if (code) {
66         afs_com_err(whoami, code, "; Can't retrieve tape hosts");
67         return (code);
68     }
69
70     /* add tape hosts first */
71     ti = as->parms[0].items;
72     if (ti) {
73         if (as->parms[1].items) {
74             port = getPortOffset(as->parms[1].items->data);
75             if (port < 0)
76                 ERROR(BC_BADARG);
77         }
78         printf("Adding host %s offset %u to tape list...", ti->data, port);
79         fflush(stdout);
80         code = bc_AddTapeHost(bc_globalConfig, ti->data, port);
81         if (code) {
82             printf("failed\n");
83             fflush(stdout);
84             if (code == EEXIST)
85                 afs_com_err(whoami, 0, "Port offset already in tape database");
86             ERROR(code);
87         }
88
89         code = bc_SaveHosts();
90         if (code) {
91             afs_com_err(whoami, code, "Cannot save tape hosts");
92             afs_com_err(whoami, 0,
93                     "Changes are temporary - for this session only");
94             ERROR(code);
95         }
96     }
97
98     /* done */
99     printf("done\n");
100
101   error_exit:
102     if (ctPtr->lockHandle != 0)
103         bc_UnlockText(ctPtr);
104     return (code);
105 }
106
107 int
108 bc_DeleteHostCmd(struct cmd_syndesc *as, void *arock)
109 {
110     struct cmd_item *ti;
111     afs_int32 port = 0;
112     udbClientTextP ctPtr;
113     afs_int32 code = 0;
114
115     ctPtr = &bc_globalConfig->configText[TB_TAPEHOSTS];
116     code = bc_LockText(ctPtr);
117     if (code)
118         ERROR(code);
119
120     code = bc_UpdateHosts();
121     if (code) {
122         afs_com_err(whoami, code, "; Can't retrieve tape hosts");
123         return (code);
124     }
125
126     /* delete tape hosts first */
127     ti = as->parms[0].items;
128     if (ti) {
129         if (as->parms[1].items) {
130             port = bc_SafeATOI(as->parms[1].items->data);
131             if (port < 0)
132                 return (BC_BADARG);
133         }
134
135         printf("Deleting host %s offset %u to tape list...", ti->data, port);
136         fflush(stdout);
137         code = bc_DeleteTapeHost(bc_globalConfig, ti->data, port);
138         if (code) {
139             if (code == ENOENT)
140                 printf("failed: no such host entry\n");
141             else
142                 printf("failed with code %d\n", code);
143             ERROR(code);
144         }
145
146         code = bc_SaveHosts();
147         if (code) {
148             afs_com_err(whoami, code, "Cannot save tape hosts");
149             afs_com_err(whoami, 0,
150                     "Changes are temporary - for this session only");
151             ERROR(code);
152         }
153     }
154
155     /* done */
156     printf("done\n");
157     fflush(stdout);
158
159   error_exit:
160     if (ctPtr->lockHandle != 0)
161         bc_UnlockText(ctPtr);
162     return (code);
163 }
164
165
166 /* bc_ListHostsCmd
167  *      list all tape hosts (from internally built tables)
168  * parameters:
169  *      ignored
170  */
171
172 int
173 bc_ListHostsCmd(struct cmd_syndesc *as, void *arock)
174 {
175     afs_int32 code;
176     struct bc_hostEntry *tentry;
177
178     code = bc_UpdateHosts();
179     if (code) {
180         afs_com_err(whoami, code, "; Can't retrieve tape hosts");
181         return (code);
182     }
183
184     printf("Tape hosts:\n");
185     for (tentry = bc_globalConfig->tapeHosts; tentry; tentry = tentry->next) {
186         printf("    Host %s, port offset %u\n", tentry->name,
187                tentry->portOffset);
188     }
189     fflush(stdout);
190     return 0;
191 }
192
193
194
195 /* ------------------------------------
196  * support routines
197  * ------------------------------------
198  */
199
200 int
201 bc_ClearHosts(void)
202 {
203     struct bc_hostEntry *tentry, *temp;
204
205     tentry = bc_globalConfig->tapeHosts;
206     while (tentry != 0) {
207         temp = tentry->next;
208         free(tentry->name);
209         free(tentry);
210         tentry = temp;
211     }
212
213     bc_globalConfig->tapeHosts = (struct bc_hostEntry *)0;
214     return (0);
215 }
216
217 /* bc_ParseHosts
218  *      Open up the volume set configuration file as specified in our argument,
219  *      then parse the file to set up our internal representation.
220  * exit:
221  *      0 on successful processing,
222  *      -1 otherwise.
223  */
224
225 int
226 bc_ParseHosts(void)
227 {
228     char tbuffer[256];
229     char hostName[256];
230     afs_int32 port = 0;
231     struct bc_hostEntry *tfirst, *tlast, *the;
232     char *tp;
233     struct hostent *th;
234
235     udbClientTextP ctPtr;
236     FILE *stream;
237
238     /* initialize locally used variables */
239     ctPtr = &bc_globalConfig->configText[TB_TAPEHOSTS];
240     stream = ctPtr->textStream;
241
242     if (ctPtr->textSize == 0)   /* nothing defined yet */
243         return (0);
244
245     if (stream == NULL)
246         return (BC_INTERNALERROR);
247
248     rewind(stream);
249
250     /* now read the lines and build the structure list */
251     tfirst = tlast = (struct bc_hostEntry *)0;
252
253     while (1) {
254         tp = fgets(tbuffer, sizeof(tbuffer), stream);
255         if (!tp)
256             break;              /* end of file */
257
258         sscanf(tbuffer, "%s %u", hostName, &port);
259         th = gethostbyname(hostName);
260         if (th == 0) {
261             afs_com_err(whoami, 0,
262                     "can't get host info for %s from nameserver or /etc/hosts.",
263                     hostName);
264         }
265         the = (struct bc_hostEntry *)malloc(sizeof(struct bc_hostEntry));
266         if (the == (struct bc_hostEntry *)0)
267             return (BC_NOMEM);
268         memset(the, 0, sizeof(struct bc_hostEntry));
269         if (tlast) {
270             tlast->next = the;
271             tlast = the;
272         } else {
273             tfirst = tlast = the;
274         }
275         the->next = (struct bc_hostEntry *)0;
276         the->name = (char *)malloc(strlen(hostName) + 1);
277         strcpy(the->name, hostName);
278         the->portOffset = port;
279         if (th) {
280             memcpy(&the->addr.sin_addr.s_addr, th->h_addr, 4);
281 #ifdef STRUCT_SOCKADDR_HAS_SA_LEN
282             the->addr.sin_len = sizeof(struct sockaddr_in);
283 #endif
284             the->addr.sin_family = AF_INET;
285             the->addr.sin_port = 0;
286         }
287     }
288
289     bc_globalConfig->tapeHosts = tfirst;
290     return (0);
291 }
292
293 /* bc_SaveHosts
294  *      really two parts
295  *      1) save the current host information to disk
296  *      2) transmit to ubik server
297  */
298
299 int
300 bc_SaveHosts(void)
301 {
302     afs_int32 code = 0;
303
304     udbClientTextP ctPtr;
305     FILE *stream;
306     struct bc_hostEntry *hePtr;
307
308     extern struct bc_config *bc_globalConfig;
309
310     ctPtr = &bc_globalConfig->configText[TB_TAPEHOSTS];
311     stream = ctPtr->textStream;
312
313     /* must be locked */
314     if (ctPtr->lockHandle == 0)
315         return (BC_INTERNALERROR);
316
317     /* truncate the file */
318     code = ftruncate(fileno(stream), 0);
319     if (code)
320         ERROR(errno);
321
322     rewind(stream);
323
324     hePtr = bc_globalConfig->tapeHosts;
325
326     while (hePtr != 0) {
327         fprintf(stream, "%s %u\n", hePtr->name, hePtr->portOffset);
328         hePtr = hePtr->next;
329     }
330
331     if (ferror(stream))
332         return (BC_INTERNALERROR);
333
334     /* send to server */
335     code = bcdb_SaveTextFile(ctPtr);
336     if (code)
337         ERROR(code);
338
339     /* do this on bcdb_SaveTextFile */
340     /* increment local version number */
341     ctPtr->textVersion++;
342
343     /* update locally stored file size */
344     ctPtr->textSize = filesize(ctPtr->textStream);
345
346   error_exit:
347     return (code);
348 }
349
350 afs_int32
351 bc_UpdateHosts(void)
352 {
353     struct udbHandleS *uhptr = &udbHandle;
354     udbClientTextP ctPtr;
355     afs_int32 code;
356     int lock = 0;
357
358     /* lock schedules and check validity */
359     ctPtr = &bc_globalConfig->configText[TB_TAPEHOSTS];
360
361     code = bc_CheckTextVersion(ctPtr);
362     if (code != BC_VERSIONMISMATCH) {
363         ERROR(code);            /* Version matches or some other error */
364     }
365
366     /* Must update the hosts */
367     /* If we are not already locked, then lock it now */
368     if (ctPtr->lockHandle == 0) {
369         code = bc_LockText(ctPtr);
370         if (code)
371             ERROR(code);
372         lock = 1;
373     }
374
375     if (ctPtr->textVersion != -1) {
376         afs_com_err(whoami, 0, "obsolete tapehosts - updating");
377         bc_ClearHosts();
378     }
379
380     /* open a temp file to store the config text received from buserver *
381      * The open file stream is stored in ctPtr->textStream */
382     code =
383         bc_openTextFile(ctPtr,
384                         &bc_globalConfig->tmpTextFileNames[TB_TAPEHOSTS][0]);
385     if (code)
386         ERROR(code);
387     /* now get a fresh set of information from the database */
388     code = bcdb_GetTextFile(ctPtr);
389     if (code)
390         ERROR(code);
391
392     /* fetch the version number */
393     code =
394         ubik_BUDB_GetTextVersion(uhptr->uh_client, 0, ctPtr->textType,
395                   &ctPtr->textVersion);
396     if (code)
397         ERROR(code);
398
399     /* parse the file */
400     code = bc_ParseHosts();
401     if (code)
402         ERROR(code);
403
404   error_exit:
405     if (lock && ctPtr->lockHandle)
406         bc_UnlockText(ctPtr);
407     return (code);
408 }