tools: move useful tools from test dir to tools dir
[openafs.git] / src / tools / xfiles.c
1 /*
2  * CMUCS AFStools
3  * dumpscan - routines for scanning and manipulating AFS volume dumps
4  *
5  * Copyright (c) 1998 Carnegie Mellon University
6  * All Rights Reserved.
7  *
8  * Permission to use, copy, modify and distribute this software and its
9  * documentation is hereby granted, provided that both the copyright
10  * notice and this permission notice appear in all copies of the
11  * software, derivative works or modified versions, and any portions
12  * thereof, and that both notices appear in supporting documentation.
13  *
14  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
15  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
16  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
17  *
18  * Carnegie Mellon requests users of this software to return to
19  *
20  *  Software Distribution Coordinator  or  Software_Distribution@CS.CMU.EDU
21  *  School of Computer Science
22  *  Carnegie Mellon University
23  *  Pittsburgh PA 15213-3890
24  *
25  * any improvements or extensions that they make and grant Carnegie Mellon
26  * the rights to redistribute these changes.
27  */
28
29 /* xfiles.c - General support routines for xfiles */
30 #include <sys/types.h>
31 #include <string.h>
32 #include <errno.h>
33 #include <stdlib.h>
34
35 #include "xfiles.h"
36 #include "xf_errs.h"
37
38 #define SKIP_SIZE 65536
39
40 extern afs_uint32 xfon_path(XFILE *, int, char *);
41 extern afs_uint32 xfon_fd(XFILE *, int, char *);
42 extern afs_uint32 xfon_voldump(XFILE *, int, char *);
43 extern afs_uint32 xfon_profile(XFILE *, int, char *);
44 extern afs_uint32 xfon_stdio(XFILE *, int);
45
46 struct xftype {
47     struct xftype *next;
48     char *name;
49       afs_uint32(*do_on) (XFILE *, int, char *);
50 };
51
52
53 static struct xftype *xftypes = 0;
54 static int did_register_defaults = 0;
55
56
57 afs_uint32
58 xfread(XFILE * X, void *buf, afs_uint32 count)
59 {
60     afs_uint32 code;
61     u_int64 tmp64;
62
63     code = (X->do_read) (X, buf, count);
64     if (code)
65         return code;
66
67     add64_32(tmp64, X->filepos, count);
68     cp64(X->filepos, tmp64);
69     if (X->passthru)
70         return xfwrite(X->passthru, buf, count);
71     return 0;
72 }
73
74
75 afs_uint32
76 xfwrite(XFILE * X, void *buf, afs_uint32 count)
77 {
78     afs_uint32 code;
79     u_int64 tmp64;
80
81     if (!X->is_writable)
82         return ERROR_XFILE_RDONLY;
83     code = (X->do_write) (X, buf, count);
84     if (code)
85         return code;
86
87     add64_32(tmp64, X->filepos, count);
88     cp64(X->filepos, tmp64);
89     return 0;
90 }
91
92
93 afs_uint32
94 xftell(XFILE * X, u_int64 * offset)
95 {
96     if (X->do_tell)
97         return (X->do_tell) (X, offset);
98     cp64(*offset, X->filepos);
99     return 0;
100 }
101
102
103 afs_uint32
104 xfseek(XFILE * X, u_int64 * offset)
105 {
106     afs_uint32 code;
107
108     if (!X->do_seek)
109         return ERROR_XFILE_NOSEEK;
110     code = (X->do_seek) (X, offset);
111     if (code)
112         return code;
113     cp64(X->filepos, *offset);
114     return 0;
115 }
116
117
118 afs_uint32
119 xfskip(XFILE * X, afs_uint32 count)
120 {
121     afs_uint32 code;
122     u_int64 tmp64;
123
124     /* Use the skip method, if there is one */
125     if (X->do_skip && !X->passthru) {
126         code = (X->do_skip) (X, count);
127         if (code)
128             return code;
129         add64_32(tmp64, X->filepos, count);
130         cp64(X->filepos, tmp64);
131         return 0;
132     }
133
134     /* Simulate using absolute seek, if available */
135     if (X->do_seek && !X->passthru) {
136         if ((code = xftell(X, &tmp64)))
137             return code;
138         add64_32(X->filepos, tmp64, count);
139         cp64(tmp64, X->filepos);
140         return xfseek(X, &tmp64);
141     }
142
143     /* Do it the hard/slow way - read all the data to be skipped.
144      * This is done if no other method is available, or if we are
145      * supposed to be copying all the data to another XFILE
146      */
147     {
148         char buf[SKIP_SIZE];
149         afs_uint32 n;
150
151         while (count) {
152             n = (count > SKIP_SIZE) ? SKIP_SIZE : count;
153             if ((code = xfread(X, buf, n)))
154                 return code;
155             count -= n;
156         }
157         return 0;
158     }
159 }
160
161
162 afs_uint32
163 xfpass(XFILE * X, XFILE * Y)
164 {
165     if (X->passthru)
166         return ERROR_XFILE_ISPASS;
167     if (!Y->is_writable)
168         return ERROR_XFILE_RDONLY;
169     X->passthru = Y;
170     return 0;
171 }
172
173
174 afs_uint32
175 xfunpass(XFILE * X)
176 {
177     if (!X->passthru)
178         return ERROR_XFILE_NOPASS;
179     X->passthru = 0;
180     return 0;
181 }
182
183
184 afs_uint32
185 xfclose(XFILE * X)
186 {
187     int code = 0;
188
189     if (X->do_close)
190         code = (X->do_close) (X);
191     memset(X, 0, sizeof(*X));
192     return 0;
193 }
194
195
196 afs_uint32
197 xfregister(char *name, afs_uint32(*do_on) (XFILE *, int, char *))
198 {
199     struct xftype *x;
200
201     if (!(x = (struct xftype *)malloc(sizeof(struct xftype))))
202         return ENOMEM;
203     memset(x, 0, sizeof(*x));
204     x->next = xftypes;
205     x->name = name;
206     x->do_on = do_on;
207     xftypes = x;
208     return 0;
209 }
210
211
212 static void
213 register_default_types(void)
214 {
215     xfregister("FILE", xfon_path);
216     xfregister("FD", xfon_fd);
217     xfregister("AFSDUMP", xfon_voldump);
218     xfregister("PROFILE", xfon_profile);
219     did_register_defaults = 1;
220 }
221
222
223 afs_uint32
224 xfopen(XFILE * X, int flag, char *name)
225 {
226     struct xftype *x;
227     char *type, *sep;
228
229     if (!did_register_defaults)
230         register_default_types();
231     if (!strcmp(name, "-"))
232         return xfon_stdio(X, flag);
233
234     for (type = name; *name && *name != ':'; name++);
235     if (*name) {
236         sep = name;
237         *name++ = 0;
238     } else {
239         sep = 0;
240         name = type;
241         type = "FILE";
242     }
243
244     for (x = xftypes; x; x = x->next)
245         if (!strcmp(type, x->name))
246             break;
247     if (sep)
248         *sep = ':';
249     if (x)
250         return (x->do_on) (X, flag, name);
251     return ERROR_XFILE_TYPE;
252 }