Standardize License information
[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 <afs/param.h>
11 #include <afs/stds.h>
12 #include <sys/types.h>
13 #include <stdio.h>
14 #ifdef AFS_NT40_ENV
15 #include <winsock2.h>
16 #else
17 #include <sys/socket.h>
18 #include <netinet/in.h>
19 #include <netdb.h>
20 #endif
21 #include <afs/budb_client.h>
22 #include <afs/cmd.h>
23 #include <afs/com_err.h>
24 #include <afs/bubasics.h>
25 #include "bc.h"
26 #include "error_macros.h"
27 #include <errno.h>
28
29 /* code to manage tape hosts
30  * specific to the ubik database implementation
31  */
32
33 afs_int32 bc_UpdateHosts();
34 extern struct bc_config *bc_globalConfig;
35 extern struct udbHandleS udbHandle;
36 extern char *whoami;
37
38 /* ------------------------------------
39  * command level routines
40  * ------------------------------------
41  */
42
43
44 /* bc_AddHostCmd
45  *      Add a host to the tape hosts
46  */
47
48 afs_int32 bc_AddHostCmd(as, arock)
49      struct cmd_syndesc *as;
50      char *arock;
51 {
52     struct cmd_item *ti;
53     udbClientTextP ctPtr;
54     afs_int32 port = 0;
55     register afs_int32 code = 0;
56
57     ctPtr = &bc_globalConfig->configText[TB_TAPEHOSTS];
58     code = bc_LockText(ctPtr);
59     if ( code )
60         ERROR(code);
61
62     code = bc_UpdateHosts();
63     if (code) {
64        com_err(whoami, code, "; Can't retrieve tape hosts");
65        return(code);
66     }
67
68     /* add tape hosts first */
69     ti = as->parms[0].items;
70     if (ti) {
71         if (as->parms[1].items) {
72            port = getPortOffset(as->parms[1].items->data);
73            if (port < 0) ERROR(BC_BADARG);
74         }
75         printf("Adding host %s offset %u to tape list...", ti->data,port);
76         fflush(stdout);
77         code = bc_AddTapeHost(bc_globalConfig, ti->data, port);
78         if (code)
79         {
80             printf("failed\n"); fflush(stdout);
81             if (code == EEXIST) 
82                 com_err(whoami,0,"Port offset already in tape database");
83             ERROR(code);
84         }
85
86         code = bc_SaveHosts();
87         if ( code )
88         {
89             com_err(whoami, code, "Cannot save tape hosts");
90             com_err(whoami, 0,"Changes are temporary - for this session only");
91             ERROR(code);
92         }
93     }
94
95     /* done */
96     printf("done\n");
97
98 error_exit:
99     if ( ctPtr->lockHandle != 0 )
100         bc_UnlockText(ctPtr);
101     return(code);
102 }
103     
104 afs_int32 bc_DeleteHostCmd(as, arock)
105      struct cmd_syndesc *as;
106      char *arock; 
107 {
108     struct cmd_item *ti;
109     afs_int32 port = 0;
110     udbClientTextP ctPtr;
111     register afs_int32 code = 0;
112
113     ctPtr = &bc_globalConfig->configText[TB_TAPEHOSTS];
114     code = bc_LockText(ctPtr);
115     if ( code )
116         ERROR(code);
117
118     code = bc_UpdateHosts();
119     if (code) {
120        com_err(whoami, code, "; Can't retrieve tape hosts");
121        return(code);
122     }
123
124     /* delete tape hosts first */
125     ti = as->parms[0].items;
126     if (ti) {
127         if (as->parms[1].items) {
128            port = bc_SafeATOI(as->parms[1].items->data);
129            if (port < 0) return(BC_BADARG);
130         }
131
132         printf("Deleting host %s offset %u to tape list...", ti->data,port);
133         fflush(stdout);
134         code = bc_DeleteTapeHost(bc_globalConfig, ti->data,port);
135         if (code)
136         {
137             if (code == ENOENT)
138                 printf("failed: no such host entry\n");
139             else
140                 printf("failed with code %d\n", code);
141             ERROR(code);
142         }
143
144         code = bc_SaveHosts();
145         if ( code )
146         {
147             com_err(whoami, code, "Cannot save tape hosts");
148             com_err(whoami, 0,"Changes are temporary - for this session only");
149             ERROR(code);
150         }
151     }
152
153     /* done */
154     printf("done\n");
155     fflush(stdout);
156
157 error_exit:
158     if ( ctPtr->lockHandle != 0 )
159         bc_UnlockText(ctPtr);
160     return(code);
161 }
162
163
164 /* bc_ListHostsCmd
165  *      list all tape hosts (from internally built tables)
166  * parameters:
167  *      ignored
168  */
169
170 afs_int32 bc_ListHostsCmd(as, arock)
171      struct cmd_syndesc *as;
172      char *arock; 
173 {
174     afs_int32 code;
175     register struct bc_hostEntry *tentry;
176
177     code = bc_UpdateHosts();
178     if (code) {
179        com_err(whoami, code, "; Can't retrieve tape hosts");
180        return(code);
181     }
182
183     printf("Tape hosts:\n");
184     for ( tentry = bc_globalConfig->tapeHosts; tentry; tentry = tentry->next )
185     {
186         printf("    Host %s, port offset %u\n", 
187                tentry->name,tentry->portOffset);
188     }
189     fflush(stdout);
190     return 0;
191 }
192
193
194
195 /* ------------------------------------
196  * support routines
197  * ------------------------------------
198  */
199
200 bc_ClearHosts()
201 {
202     register struct bc_hostEntry *tentry, *temp;
203
204     tentry = bc_globalConfig->tapeHosts;
205     while ( tentry != 0 )
206     {
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 bc_ParseHosts()
226 {
227     char tbuffer[256];
228     char hostName[256];
229     afs_int32 port = 0;
230     struct bc_hostEntry *tfirst, *tlast, *the;
231     char *tp;
232     struct hostent *th;
233
234     udbClientTextP ctPtr;
235     FILE *stream;
236
237     /* initialize locally used variables */
238     ctPtr = &bc_globalConfig->configText[TB_TAPEHOSTS];
239     stream = ctPtr->textStream;
240
241     if ( ctPtr->textSize == 0 )                 /* nothing defined yet */
242         return(0);
243
244     if ( stream == NULL )
245         return(BC_INTERNALERROR);
246
247     rewind(stream);
248
249     /* now read the lines and build the structure list */
250     tfirst = tlast = (struct bc_hostEntry *) 0;
251
252     while(1) 
253     {
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         {
262             com_err(whoami,0,"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         bzero(the, sizeof(struct bc_hostEntry));
269         if (tlast) 
270         {
271             tlast->next = the;
272             tlast = the;
273         }
274         else 
275         {
276             tfirst = tlast = the;
277         }
278         the->next = (struct bc_hostEntry *) 0;
279         the->name = (char *) malloc(strlen(hostName)+1);
280         strcpy(the->name, hostName);
281         the->portOffset = port;
282         if (th) {
283             bcopy(th->h_addr, &the->addr.sin_addr.s_addr, 4);
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 bc_SaveHosts()
300 {
301     register afs_int32 code = 0;
302
303     udbClientTextP ctPtr;
304     register FILE *stream;
305     struct bc_hostEntry *hePtr;
306
307     extern struct bc_config *bc_globalConfig;
308
309     ctPtr = &bc_globalConfig->configText[TB_TAPEHOSTS];
310     stream = ctPtr->textStream;
311
312     /* must be locked */
313     if ( ctPtr->lockHandle == 0 )
314         return(BC_INTERNALERROR);
315
316     /* truncate the file */
317     code = ftruncate(fileno(stream), 0);
318     if ( code )
319         ERROR(errno);
320
321     rewind(stream);
322
323     hePtr = bc_globalConfig->tapeHosts;
324
325     while ( hePtr != 0 )
326     {
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 bc_UpdateHosts()
351 {
352     struct udbHandleS *uhptr = &udbHandle;
353     udbClientTextP ctPtr;
354     afs_int32 code;
355     int lock=0;
356
357     /* lock schedules and check validity */
358     ctPtr = &bc_globalConfig->configText[TB_TAPEHOSTS];
359
360     code = bc_CheckTextVersion(ctPtr);
361     if ( code != BC_VERSIONMISMATCH )
362     {
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     {
377         com_err(whoami,0,"obsolete tapehosts - updating");
378         bc_ClearHosts();
379     }
380
381     /* open a temp file to store the config text received from buserver *
382      * The open file stream is stored in ctPtr->textStream */
383     code = bc_openTextFile(ctPtr, &bc_globalConfig->tmpTextFileNames[TB_TAPEHOSTS][0]);
384     if ( code )
385       ERROR(code);
386     /* now get a fresh set of information from the database */
387     code = bcdb_GetTextFile(ctPtr);
388     if ( code )
389         ERROR(code);
390
391      /* fetch the version number */
392     code = ubik_Call(BUDB_GetTextVersion,  uhptr->uh_client, 0,
393                      ctPtr->textType, &ctPtr->textVersion);
394     if ( code )
395         ERROR(code);
396
397     /* parse the file */
398     code = bc_ParseHosts();
399     if ( code )
400         ERROR(code);
401
402 error_exit:
403     if ( lock && ctPtr->lockHandle )
404         bc_UnlockText(ctPtr);
405     return(code);
406 }