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