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