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