reindent-20030715
[openafs.git] / src / tests / xf_files.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 /* xf_files.c - XFILE routines for accessing UNIX files */
30
31 #include <sys/types.h>
32 #include <sys/stat.h>
33 #include <fcntl.h>
34 #include <errno.h>
35
36 #include "xfiles.h"
37 #include "xf_errs.h"
38
39 #define O_MODE_MASK (O_RDONLY | O_WRONLY | O_RDWR)
40
41
42 /* do_read for stdio xfiles */
43 static afs_uint32
44 xf_FILE_do_read(XFILE * X, void *buf, afs_uint32 count)
45 {
46     FILE *F = X->refcon;
47
48     /* XXX: handle short and interrupted reads */
49     if (fread(buf, count, 1, F) != 1)
50         return ferror(F) ? errno : ERROR_XFILE_EOF;
51     return 0;
52 }
53
54
55 /* do_write for stdio xfiles */
56 static afs_uint32
57 xf_FILE_do_write(XFILE * X, void *buf, afs_uint32 count)
58 {
59     FILE *F = X->refcon;
60
61     /* XXX: handle interrupted writes */
62     if (fwrite(buf, count, 1, F) != 1)
63         return errno;
64     return 0;
65 }
66
67
68 /* do_tell for stdio xfiles */
69 static afs_uint32
70 xf_FILE_do_tell(XFILE * X, u_int64 * offset)
71 {
72     FILE *F = X->refcon;
73     off_t where;
74
75     where = ftell(F);
76     if (where == -1)
77         return errno;
78     set64(*offset, where);
79     return 0;
80 }
81
82
83 /* do_seek for stdio xfiles */
84 static afs_uint32
85 xf_FILE_do_seek(XFILE * X, u_int64 * offset)
86 {
87     FILE *F = X->refcon;
88     off_t where = get64(*offset);
89
90     if (fseek(F, where, SEEK_SET) == -1)
91         return errno;
92     return 0;
93 }
94
95
96 /* do_skip for stdio xfiles */
97 static afs_uint32
98 xf_FILE_do_skip(XFILE * X, afs_uint32 count)
99 {
100     FILE *F = X->refcon;
101
102     if (fseek(F, count, SEEK_CUR) == -1)
103         return errno;
104     return 0;
105 }
106
107
108 /* do_close for stdio xfiles */
109 static afs_uint32
110 xf_FILE_do_close(XFILE * X)
111 {
112     FILE *F = X->refcon;
113
114     X->refcon = 0;
115     if (fclose(F))
116         return errno;
117     return 0;
118 }
119
120
121 /* Prepare a stdio XFILE */
122 static void
123 prepare(XFILE * X, FILE * F, int xflag)
124 {
125     struct stat st;
126
127     memset(X, 0, sizeof(*X));
128     X->do_read = xf_FILE_do_read;
129     X->do_write = xf_FILE_do_write;
130     X->do_tell = xf_FILE_do_tell;
131     X->do_close = xf_FILE_do_close;
132     X->refcon = F;
133     if (xflag == O_RDWR)
134         X->is_writable = 1;
135
136     if (!fstat(fileno(F), &st)
137         && ((st.st_mode & S_IFMT) == S_IFREG
138             || (st.st_mode & S_IFMT) == S_IFBLK)) {
139         X->is_seekable = 1;
140         X->do_seek = xf_FILE_do_seek;
141         X->do_skip = xf_FILE_do_skip;
142     }
143 }
144
145
146 /* Open an XFILE by path */
147 afs_uint32
148 xfopen_path(XFILE * X, int flag, char *path, int mode)
149 {
150     FILE *F = 0;
151     int fd = -1, xflag;
152     afs_uint32 code;
153
154     xflag = flag & O_MODE_MASK;
155     if (xflag == O_WRONLY)
156         return ERROR_XFILE_WRONLY;
157
158     if ((fd = open(path, flag, mode)) < 0)
159         return errno;
160     if (!(F = fdopen(fd, (xflag == O_RDONLY) ? "r" : "r+"))) {
161         code = errno;
162         close(fd);
163         return code;
164     }
165
166     prepare(X, F, xflag);
167     return 0;
168 }
169
170
171 /* Open an XFILE by FILE * */
172 afs_uint32
173 xfopen_FILE(XFILE * X, int flag, FILE * F)
174 {
175     flag &= O_MODE_MASK;
176     if (flag == O_WRONLY)
177         return ERROR_XFILE_WRONLY;
178     prepare(X, F, flag);
179     return 0;
180 }
181
182
183 /* Open an XFILE by file descriptor */
184 afs_uint32
185 xfopen_fd(XFILE * X, int flag, int fd)
186 {
187     FILE *F;
188
189     flag &= O_MODE_MASK;
190     if (flag == O_WRONLY)
191         return ERROR_XFILE_WRONLY;
192     if (!(F = fdopen(fd, (flag == O_RDONLY) ? "r" : "r+")))
193         return errno;
194     prepare(X, F, flag);
195     return 0;
196 }
197
198
199 /* open-by-name support for filenames */
200 afs_uint32
201 xfon_path(XFILE * X, int flag, char *name)
202 {
203     return xfopen_path(X, flag, name, 0644);
204 }
205
206
207 /* open-by-name support for file descriptors */
208 afs_uint32
209 xfon_fd(XFILE * X, int flag, char *name)
210 {
211     int fd = atoi(name);
212     return xfopen_fd(X, flag, fd);
213 }
214
215
216 /* open-by-name support for standard I/O */
217 afs_uint32
218 xfon_stdio(XFILE * X, int flag)
219 {
220     flag &= O_MODE_MASK;
221     if (flag == O_WRONLY)
222         flag = O_RDWR;
223     return xfopen_FILE(X, flag, (flag == O_RDONLY) ? stdin : stdout);
224 }