Commit | Line | Data |
---|---|---|
805e021f CE |
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 | } |