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