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