Rework bucoord prototypes for external dlq use
[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     
32 /* code to manage tape hosts
33  * specific to the ubik database implementation
34  */
35
36 extern struct bc_config *bc_globalConfig;
37 extern struct udbHandleS udbHandle;
38 extern char *whoami;
39
40 /* ------------------------------------
41  * command level routines
42  * ------------------------------------
43  */
44
45
46 /* bc_AddHostCmd
47  *      Add a host to the tape hosts
48  */
49
50 int
51 bc_AddHostCmd(struct cmd_syndesc *as, void *arock)
52 {
53     struct cmd_item *ti;
54     udbClientTextP ctPtr;
55     afs_int32 port = 0;
56     register afs_int32 code = 0;
57
58     ctPtr = &bc_globalConfig->configText[TB_TAPEHOSTS];
59     code = bc_LockText(ctPtr);
60     if (code)
61         ERROR(code);
62
63     code = bc_UpdateHosts();
64     if (code) {
65         afs_com_err(whoami, code, "; Can't retrieve tape hosts");
66         return (code);
67     }
68
69     /* add tape hosts first */
70     ti = as->parms[0].items;
71     if (ti) {
72         if (as->parms[1].items) {
73             port = getPortOffset(as->parms[1].items->data);
74             if (port < 0)
75                 ERROR(BC_BADARG);
76         }
77         printf("Adding host %s offset %u to tape list...", ti->data, port);
78         fflush(stdout);
79         code = bc_AddTapeHost(bc_globalConfig, ti->data, port);
80         if (code) {
81             printf("failed\n");
82             fflush(stdout);
83             if (code == EEXIST)
84                 afs_com_err(whoami, 0, "Port offset already in tape database");
85             ERROR(code);
86         }
87
88         code = bc_SaveHosts();
89         if (code) {
90             afs_com_err(whoami, code, "Cannot save tape hosts");
91             afs_com_err(whoami, 0,
92                     "Changes are temporary - for this session only");
93             ERROR(code);
94         }
95     }
96
97     /* done */
98     printf("done\n");
99
100   error_exit:
101     if (ctPtr->lockHandle != 0)
102         bc_UnlockText(ctPtr);
103     return (code);
104 }
105
106 int
107 bc_DeleteHostCmd(struct cmd_syndesc *as, void *arock)
108 {
109     struct cmd_item *ti;
110     afs_int32 port = 0;
111     udbClientTextP ctPtr;
112     register afs_int32 code = 0;
113
114     ctPtr = &bc_globalConfig->configText[TB_TAPEHOSTS];
115     code = bc_LockText(ctPtr);
116     if (code)
117         ERROR(code);
118
119     code = bc_UpdateHosts();
120     if (code) {
121         afs_com_err(whoami, code, "; Can't retrieve tape hosts");
122         return (code);
123     }
124
125     /* delete tape hosts first */
126     ti = as->parms[0].items;
127     if (ti) {
128         if (as->parms[1].items) {
129             port = bc_SafeATOI(as->parms[1].items->data);
130             if (port < 0)
131                 return (BC_BADARG);
132         }
133
134         printf("Deleting host %s offset %u to tape list...", ti->data, port);
135         fflush(stdout);
136         code = bc_DeleteTapeHost(bc_globalConfig, ti->data, port);
137         if (code) {
138             if (code == ENOENT)
139                 printf("failed: no such host entry\n");
140             else
141                 printf("failed with code %d\n", code);
142             ERROR(code);
143         }
144
145         code = bc_SaveHosts();
146         if (code) {
147             afs_com_err(whoami, code, "Cannot save tape hosts");
148             afs_com_err(whoami, 0,
149                     "Changes are temporary - for this session only");
150             ERROR(code);
151         }
152     }
153
154     /* done */
155     printf("done\n");
156     fflush(stdout);
157
158   error_exit:
159     if (ctPtr->lockHandle != 0)
160         bc_UnlockText(ctPtr);
161     return (code);
162 }
163
164
165 /* bc_ListHostsCmd
166  *      list all tape hosts (from internally built tables)
167  * parameters:
168  *      ignored
169  */
170
171 int
172 bc_ListHostsCmd(struct cmd_syndesc *as, void *arock)
173 {
174     afs_int32 code;
175     register struct bc_hostEntry *tentry;
176
177     code = bc_UpdateHosts();
178     if (code) {
179         afs_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         printf("    Host %s, port offset %u\n", tentry->name,
186                tentry->portOffset);
187     }
188     fflush(stdout);
189     return 0;
190 }
191
192
193
194 /* ------------------------------------
195  * support routines
196  * ------------------------------------
197  */
198
199 int
200 bc_ClearHosts(void)
201 {
202     register struct bc_hostEntry *tentry, *temp;
203
204     tentry = bc_globalConfig->tapeHosts;
205     while (tentry != 0) {
206         temp = tentry->next;
207         free(tentry->name);
208         free(tentry);
209         tentry = temp;
210     }
211
212     bc_globalConfig->tapeHosts = (struct bc_hostEntry *)0;
213     return (0);
214 }
215
216 /* bc_ParseHosts
217  *      Open up the volume set configuration file as specified in our argument,
218  *      then parse the file to set up our internal representation.
219  * exit:
220  *      0 on successful processing,
221  *      -1 otherwise.
222  */
223
224 int
225 bc_ParseHosts(void)
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         tp = fgets(tbuffer, sizeof(tbuffer), stream);
254         if (!tp)
255             break;              /* end of file */
256
257         sscanf(tbuffer, "%s %u", hostName, &port);
258         th = gethostbyname(hostName);
259         if (th == 0) {
260             afs_com_err(whoami, 0,
261                     "can't get host info for %s from nameserver or /etc/hosts.",
262                     hostName);
263         }
264         the = (struct bc_hostEntry *)malloc(sizeof(struct bc_hostEntry));
265         if (the == (struct bc_hostEntry *)0)
266             return (BC_NOMEM);
267         memset(the, 0, sizeof(struct bc_hostEntry));
268         if (tlast) {
269             tlast->next = the;
270             tlast = the;
271         } else {
272             tfirst = tlast = the;
273         }
274         the->next = (struct bc_hostEntry *)0;
275         the->name = (char *)malloc(strlen(hostName) + 1);
276         strcpy(the->name, hostName);
277         the->portOffset = port;
278         if (th) {
279             memcpy(&the->addr.sin_addr.s_addr, th->h_addr, 4);
280 #ifdef STRUCT_SOCKADDR_HAS_SA_LEN
281             the->addr.sin_len = sizeof(struct sockaddr_in);
282 #endif
283             the->addr.sin_family = AF_INET;
284             the->addr.sin_port = 0;
285         }
286     }
287
288     bc_globalConfig->tapeHosts = tfirst;
289     return (0);
290 }
291
292 /* bc_SaveHosts
293  *      really two parts
294  *      1) save the current host information to disk
295  *      2) transmit to ubik server
296  */
297
298 int
299 bc_SaveHosts(void)
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         fprintf(stream, "%s %u\n", hePtr->name, hePtr->portOffset);
327         hePtr = hePtr->next;
328     }
329
330     if (ferror(stream))
331         return (BC_INTERNALERROR);
332
333     /* send to server */
334     code = bcdb_SaveTextFile(ctPtr);
335     if (code)
336         ERROR(code);
337
338     /* do this on bcdb_SaveTextFile */
339     /* increment local version number */
340     ctPtr->textVersion++;
341
342     /* update locally stored file size */
343     ctPtr->textSize = filesize(ctPtr->textStream);
344
345   error_exit:
346     return (code);
347 }
348
349 afs_int32
350 bc_UpdateHosts(void)
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         ERROR(code);            /* Version matches or some other error */
363     }
364
365     /* Must update the hosts */
366     /* If we are not already locked, then lock it now */
367     if (ctPtr->lockHandle == 0) {
368         code = bc_LockText(ctPtr);
369         if (code)
370             ERROR(code);
371         lock = 1;
372     }
373
374     if (ctPtr->textVersion != -1) {
375         afs_com_err(whoami, 0, "obsolete tapehosts - updating");
376         bc_ClearHosts();
377     }
378
379     /* open a temp file to store the config text received from buserver *
380      * The open file stream is stored in ctPtr->textStream */
381     code =
382         bc_openTextFile(ctPtr,
383                         &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 =
393         ubik_BUDB_GetTextVersion(uhptr->uh_client, 0, ctPtr->textType,
394                   &ctPtr->textVersion);
395     if (code)
396         ERROR(code);
397
398     /* parse the file */
399     code = bc_ParseHosts();
400     if (code)
401         ERROR(code);
402
403   error_exit:
404     if (lock && ctPtr->lockHandle)
405         bc_UnlockText(ctPtr);
406     return (code);
407 }