reindent-20030715
[openafs.git] / src / tests / 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
34 #include "xfiles.h"
35 #include "xf_errs.h"
36
37 #define SKIP_SIZE 65536
38
39 extern afs_uint32 xfon_path(XFILE *, int, char *);
40 extern afs_uint32 xfon_fd(XFILE *, int, char *);
41 extern afs_uint32 xfon_voldump(XFILE *, int, char *);
42 extern afs_uint32 xfon_profile(XFILE *, int, char *);
43 extern afs_uint32 xfon_stdio(XFILE *, int);
44
45 struct xftype {
46     struct xftype *next;
47     char *name;
48       afs_uint32(*do_on) (XFILE *, int, char *);
49 };
50
51
52 static struct xftype *xftypes = 0;
53 static int did_register_defaults = 0;
54
55
56 afs_uint32
57 xfread(XFILE * X, void *buf, afs_uint32 count)
58 {
59     afs_uint32 code;
60     u_int64 tmp64;
61
62     code = (X->do_read) (X, buf, count);
63     if (code)
64         return code;
65
66     add64_32(tmp64, X->filepos, count);
67     cp64(X->filepos, tmp64);
68     if (X->passthru)
69         return xfwrite(X->passthru, buf, count);
70     return 0;
71 }
72
73
74 afs_uint32
75 xfwrite(XFILE * X, void *buf, afs_uint32 count)
76 {
77     afs_uint32 code;
78     u_int64 tmp64;
79
80     if (!X->is_writable)
81         return ERROR_XFILE_RDONLY;
82     code = (X->do_write) (X, buf, count);
83     if (code)
84         return code;
85
86     add64_32(tmp64, X->filepos, count);
87     cp64(X->filepos, tmp64);
88     return 0;
89 }
90
91
92 afs_uint32
93 xftell(XFILE * X, u_int64 * offset)
94 {
95     if (X->do_tell)
96         return (X->do_tell) (X, offset);
97     cp64(*offset, X->filepos);
98     return 0;
99 }
100
101
102 afs_uint32
103 xfseek(XFILE * X, u_int64 * offset)
104 {
105     afs_uint32 code;
106
107     if (!X->do_seek)
108         return ERROR_XFILE_NOSEEK;
109     code = (X->do_seek) (X, offset);
110     if (code)
111         return code;
112     cp64(X->filepos, *offset);
113     return 0;
114 }
115
116
117 afs_uint32
118 xfskip(XFILE * X, afs_uint32 count)
119 {
120     afs_uint32 code;
121     u_int64 tmp64;
122
123     /* Use the skip method, if there is one */
124     if (X->do_skip && !X->passthru) {
125         code = (X->do_skip) (X, count);
126         if (code)
127             return code;
128         add64_32(tmp64, X->filepos, count);
129         cp64(X->filepos, tmp64);
130         return 0;
131     }
132
133     /* Simulate using absolute seek, if available */
134     if (X->do_seek && !X->passthru) {
135         if (code = xftell(X, &tmp64))
136             return code;
137         add64_32(X->filepos, tmp64, count);
138         cp64(tmp64, X->filepos);
139         return xfseek(X, &tmp64);
140     }
141
142     /* Do it the hard/slow way - read all the data to be skipped.
143      * This is done if no other method is available, or if we are
144      * supposed to be copying all the data to another XFILE
145      */
146     {
147         char buf[SKIP_SIZE];
148         afs_uint32 n;
149
150         while (count) {
151             n = (count > SKIP_SIZE) ? SKIP_SIZE : count;
152             if (code = xfread(X, buf, n))
153                 return code;
154             count -= n;
155         }
156         return 0;
157     }
158 }
159
160
161 afs_uint32
162 xfpass(XFILE * X, XFILE * Y)
163 {
164     if (X->passthru)
165         return ERROR_XFILE_ISPASS;
166     if (!Y->is_writable)
167         return ERROR_XFILE_RDONLY;
168     X->passthru = Y;
169     return 0;
170 }
171
172
173 afs_uint32
174 xfunpass(XFILE * X)
175 {
176     if (!X->passthru)
177         return ERROR_XFILE_NOPASS;
178     X->passthru = 0;
179     return 0;
180 }
181
182
183 afs_uint32
184 xfclose(XFILE * X)
185 {
186     int code = 0;
187
188     if (X->do_close)
189         code = (X->do_close) (X);
190     memset(X, 0, sizeof(*X));
191     return 0;
192 }
193
194
195 afs_uint32
196 xfregister(char *name, afs_uint32(*do_on) (XFILE *, int, char *))
197 {
198     struct xftype *x;
199
200     if (!(x = (struct xftype *)malloc(sizeof(struct xftype))))
201         return ENOMEM;
202     memset(x, 0, sizeof(*x));
203     x->next = xftypes;
204     x->name = name;
205     x->do_on = do_on;
206     xftypes = x;
207 }
208
209
210 static void
211 register_default_types(void)
212 {
213     xfregister("FILE", xfon_path);
214     xfregister("FD", xfon_fd);
215     xfregister("AFSDUMP", xfon_voldump);
216     xfregister("PROFILE", xfon_profile);
217     did_register_defaults = 1;
218 }
219
220
221 afs_uint32
222 xfopen(XFILE * X, int flag, char *name)
223 {
224     struct xftype *x;
225     char *type, *sep;
226
227     if (!did_register_defaults)
228         register_default_types();
229     if (!strcmp(name, "-"))
230         return xfon_stdio(X, flag);
231
232     for (type = name; *name && *name != ':'; name++);
233     if (*name) {
234         sep = name;
235         *name++ = 0;
236     } else {
237         sep = 0;
238         name = type;
239         type = "FILE";
240     }
241
242     for (x = xftypes; x; x = x->next)
243         if (!strcmp(type, x->name))
244             break;
245     if (sep)
246         *sep = ':';
247     if (x)
248         return (x->do_on) (X, flag, name);
249     return ERROR_XFILE_TYPE;
250 }