719d3a2dcf3b0e82932796371be296567996bdea
[openafs.git] / src / tools / 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, u_int64 * 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, u_int64 * 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 }