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