1 rizwank 1.1 /*--------------------------------------------------------------------------
2 Trivial virtual file system for cabinet conformance test.
|
3 rizwank 1.2 (C) 2005 Dan Kegel and Rizwan Kassim
4 LGPL License
|
5 rizwank 1.1 --------------------------------------------------------------------------*/
6
7 #include "tvfs.h"
8 #include <string.h>
9
|
10 rizwank 1.9 #define MAXFILES 20
11 #define MAXHANDLES 20
|
12 rizwank 1.1 #define MAXFNAME 255
|
13 rizwank 1.9 #define MAXFLEN 65536*2
|
14 rizwank 1.1
|
15 rizwank 1.4 #include <fcntl.h>
|
16 rizwank 1.7 #include <stdlib.h>
|
17 rizwank 1.4 #include <stdio.h>
18 #include <malloc.h>
|
19 rizwank 1.8 #include <stdio.h>
20 #include <stdarg.h>
21
|
22 rizwank 1.4 #define SEEK_SET 0
23 #define SEEK_CUR 1
24 #define SEEK_END 2
|
25 rizwank 1.2
|
26 rizwank 1.8 #ifndef _O_BINARY
27 #define _O_BINARY 0
28 #endif
29
|
30 rizwank 1.12
31 #undef VERBOSE
32 #ifdef TVFS_DEBUG
33 #define VERBOSE
34 #endif
35
36 /*
37 Only debug output from tvfs.c IF TVFS_DEBUG is true, not just if VERBOSE is true
38 The TVFS debug traces are generally used for debugging TVFS, not cabinet_fdi
39 #define TVFS_MAIN
40 #define TVFS_DEBUG
41 */
42
|
43 rizwank 1.8 #ifndef STANDALONE
|
44 rizwank 1.11 #include "wine/test.h"
45 #define ok2 ok
|
46 rizwank 1.8 #else
|
47 rizwank 1.12 #include "standalone.h"
48 #undef START_TEST
|
49 rizwank 1.8 #endif
50
|
51 rizwank 1.1 struct tvfs_file {
|
52 rizwank 1.8 char fname[MAXFNAME];
53 int bytes_used;
54 char buf[MAXFLEN];
|
55 rizwank 1.1 };
56 static struct tvfs_file *files[MAXFILES];
57
58 struct tvfs_fcb {
|
59 rizwank 1.8 int pos;
60 int inode;
|
61 rizwank 1.1 };
62 static struct tvfs_fcb *handles[MAXHANDLES];
|
63 rizwank 1.8
|
64 rizwank 1.1 int nhandles = 0;
|
65 rizwank 1.8 int nfiles = 0;
|
66 rizwank 1.1
|
67 rizwank 1.2 /* tvfs_create does NOT correspond to _creat - it is an internal function
|
68 rizwank 1.10 use to put a file directly into our virtual file system. */
|
69 rizwank 1.2
|
70 rizwank 1.1 int tvfs_create(const char *fname, const char *buf, int len)
71 {
|
72 rizwank 1.8 int inode;
73 struct tvfs_file *f;
74
75 trace("tvfs_create called with %s, %d, %d\n", fname, buf, len);
76
77 if (nfiles >= MAXFILES)
78 return -1;
79 inode = nfiles++;
|
80 rizwank 1.4
|
81 rizwank 1.8 f = malloc(sizeof(struct tvfs_file));
82 strcpy(f->fname, fname);
83 f->bytes_used = len;
84
85 if (buf)
86 memcpy(f->buf, buf, len);
87
88 files[inode] = f;
89 return inode;
|
90 rizwank 1.1 }
91
92 int tvfs_open(const char *fname, int flags, int mode)
93 {
|
94 rizwank 1.4
|
95 rizwank 1.8 /* mode and flags are not handled */
96 int h;
97 int inode;
98 struct tvfs_fcb *handler;
99
100 trace("tvfs_open called with %s, %d, %d\n", fname, flags, mode);
101
102 /* Existing file? */
103 for (inode=0; inode<nfiles; inode++) {
104 if (!files[inode])
105 continue;
106 if (!strcmp(files[inode]->fname, fname))
107 break;
108 }
109
110 if (inode == nfiles) {
111 /* File did not exist */
112 if ((flags & O_CREAT) == 0) {
113 /* ENOENT */
114 trace("tvfs_open returning -1\n");
115 return -1;
116 rizwank 1.8 }
117
118 inode = tvfs_create(fname, 0, 0);
119 }
|
120 rizwank 1.9
|
121 rizwank 1.8 handler = malloc(sizeof(struct tvfs_fcb));
122 handler->inode = inode;
123 handler->pos=0;
|
124 rizwank 1.9 h = nhandles++;
|
125 rizwank 1.8 handles[h] = handler;
126
127 trace("tvfs_open returning with %d\n", h);
128
129 return h;
|
130 rizwank 1.1 }
|
131 rizwank 1.2
|
132 rizwank 1.1 unsigned int tvfs_read(int h, void *buf, unsigned int len)
133 {
|
134 rizwank 1.8 int inode = handles[h]->inode;
135 int pos = handles[h]->pos;
136 int size = files[inode]->bytes_used;
137
138 trace("tvfs_read called with %d, %d, %d\n", h, buf, len);
139
140 /* Edge Case 1 : Request beyond boundary of file */
141 if (pos + len > size) {
142 len = size-pos;
143 }
144
145 memcpy(buf, files[inode]->buf+pos, len);
146 handles[h]->pos += len;
|
147 rizwank 1.1
|
148 rizwank 1.8 return len;
|
149 rizwank 1.1 }
|
150 rizwank 1.2
|
151 rizwank 1.8 void tvfs_free()
152 {
153 int inode;
|
154 rizwank 1.9 int handle;
|
155 rizwank 1.4
|
156 rizwank 1.8 trace("tvfs_free\n");
157
158 nfiles=0;
159 nhandles=0;
|
160 rizwank 1.9
|
161 rizwank 1.4 for (inode=0; inode<nfiles; inode++) {
|
162 rizwank 1.8 if (!files[inode])
163 continue;
164 free(files[inode]);
165 }
|
166 rizwank 1.9
167 for (handle=0; handle<nhandles; handle++) {
168 if (!handles[handle])
169 continue;
170 free(handles[handle]);
171 }
172
|
173 rizwank 1.8 }
|
174 rizwank 1.2
|
175 rizwank 1.4 /* Compare given file with given contents, return 0 on equal, else nonzero */
|
176 rizwank 1.8 int tvfs_compare(const char *fname, const char *buf, int len)
177 {
178
179 int inode;
180
181 trace("tvfs_compare called with %s, %d, %d\n", fname, buf, len);
182
183 for (inode=0; inode<nfiles; inode++) {
184 if (!files[inode])
185 continue;
186 if (!strcmp(files[inode]->fname, fname))
187 break;
188 }
|
189 rizwank 1.9
|
190 rizwank 1.7 if (inode == nfiles) {
|
191 rizwank 1.8 /* File did not exist */
192 trace("tvfs_compare returning -1 (FAILURE)\n");
|
193 rizwank 1.7 return -1;
194 }
195
|
196 rizwank 1.8 return (memcmp(files[inode]->buf,buf,len));
|
197 rizwank 1.10 /* does not check for out of bound */
|
198 rizwank 1.4 }
|
199 rizwank 1.2
|
200 rizwank 1.8 long tvfs_lseek(int h, long whence, int whither )
201 {
|
202 rizwank 1.2
|
203 rizwank 1.8 int inode = handles[h]->inode;
204 int size = files[inode]->bytes_used;
205 trace("tvfs_lseek called with %d, %d, %d\n", h, whither, whence);
206
207 /* if (whence > size)
208 whence = size;*/
|
209 rizwank 1.10 /* Legit lseek does NOT do boundary checking */
|
210 rizwank 1.8
211 switch(whither) {
|
212 rizwank 1.12 case SEEK_SET: {
213 handles[h]->pos = whence;
214 break;
215 }
216 case SEEK_CUR: {
217 handles[h]->pos += whence;
218 break;
219 }
220 case SEEK_END: {
221 handles[h]->pos = size+whence;
222 break;
223 }
224 case 5: {
225 handles[h]->pos = size+whence;
226 break;
227 }
228 default:
229 {
230 trace("lseek was called with an invalid whither %d\n",whither);
231 return -1;
232 }
|
233 rizwank 1.8 }
234 return handles[h]->pos;
|
235 rizwank 1.4 }
236
|
237 rizwank 1.12 int tvfs_close(int h)
238 {
|
239 rizwank 1.8 int inode = handles[h]->inode;
240 trace("tvfs_close called with %d\n", h);
|
241 rizwank 1.12 if (!files[inode]) {
242 return -1;
|
243 rizwank 1.8 }
244 free(handles[h]);
245 /* Currently does NOT enabled open to reuse this handle */
246 return 0;
|
247 rizwank 1.12 }
|
248 rizwank 1.4
249 unsigned int tvfs_write(int h, void *buf, unsigned int len)
250 {
|
251 rizwank 1.8
252 int inode = handles[h]->inode;
253 int pos = handles[h]->pos;
254 trace("tvfs_write called with %d, %d, %d\n", h, buf, len);
255 memcpy(files[inode]->buf+pos, buf, len);
256 files[inode]->bytes_used += len;
|
257 rizwank 1.9 handles[h]->pos += len;
258
|
259 rizwank 1.8 return len;
260 /* return -1 to simulate diskfull or some other error */
|
261 rizwank 1.4 }
|
262 rizwank 1.8
263
|
264 rizwank 1.11 START_TEST(tvfs){
265 printf("dummy!");
266 }
|
267 rizwank 1.4
|
268 rizwank 1.2
269 #ifdef TVFS_MAIN
|
270 rizwank 1.4
|
271 rizwank 1.3 const static char name_test_txt[] = "test.txt";
272 const static char file_test_txt[] = "This is a test. Don't Panic!";
|
273 rizwank 1.4 const static int size_test_txt = sizeof(file_test_txt);
|
274 rizwank 1.2
|
275 rizwank 1.12 main()
276 {
|
277 rizwank 1.8 int result;
278 int active_handler;
|
279 rizwank 1.2
|
280 rizwank 1.8 char *filebuf;
281
282 char dummy_filename[] = "dummy.txt";
283 char bad_filename[] = "chicken.txt";
284
285 filebuf = malloc(MAXFLEN);
286
|
287 rizwank 1.10 trace("Testing TVFS implementation, creating %s\n",name_test_txt);
|
288 rizwank 1.8 result = tvfs_create( dummy_filename, file_test_txt, size_test_txt);
289 result = tvfs_create( name_test_txt, file_test_txt,size_test_txt);
|
290 rizwank 1.10 trace("Created virtual file with inode %d\n",result);
|
291 rizwank 1.8
|
292 rizwank 1.10 trace("Attempting to open non-existent file\n");
|
293 rizwank 1.8 result = tvfs_open(bad_filename, _O_BINARY, 0 );
|
294 rizwank 1.10 trace("Result code %d\n",result);
295 trace("Attempting to open existent file\n");
|
296 rizwank 1.8 result = tvfs_open(name_test_txt, _O_BINARY, 0 );
|
297 rizwank 1.10 trace("Result code %d\n",result);
|
298 rizwank 1.8
299 active_handler = result;
300
301 memset (filebuf,0,MAXFLEN);
302
|
303 rizwank 1.10 trace("Testing reading from file %s\n",name_test_txt);
|
304 rizwank 1.8 result = tvfs_read(active_handler, filebuf, 9);
|
305 rizwank 1.10 trace("Read _%s_\n", filebuf);
|
306 rizwank 1.8 if ( strcmp(filebuf,"This is a"))
|
307 rizwank 1.10 trace("File read check failed!\n");
|
308 rizwank 1.8
|
309 rizwank 1.10 trace("Testing sequential reading from file %s\n",name_test_txt);
|
310 rizwank 1.8 result = tvfs_read(active_handler, filebuf, 12);
|
311 rizwank 1.10 trace("Read _%s_\n", filebuf);
|
312 rizwank 1.8 if ( strcmp(filebuf," test. Don't"))
|
313 rizwank 1.10 trace("File read check failed!\n");
|
314 rizwank 1.8
|
315 rizwank 1.10 trace("Testing edge reading from file %s\n",name_test_txt);
|
316 rizwank 1.8 result = tvfs_read(active_handler, filebuf, 42);
|
317 rizwank 1.10 trace("Read %d bytes - _%s_\n", result, filebuf);
|
318 rizwank 1.8 if ( result != 8 )
|
319 rizwank 1.10 trace("File read check failed!\n");
|
320 rizwank 1.8
|
321 rizwank 1.10 trace("Testing direct file compare and lseek of %s\n", name_test_txt);
322 trace("Seeking to 0 (not needed) - ");
|
323 rizwank 1.8 tvfs_lseek( active_handler, SEEK_SET, 0);
|
324 rizwank 1.10 trace("Comparing file\n");
|
325 rizwank 1.8 result = tvfs_compare( name_test_txt , file_test_txt, size_test_txt);
326 if (result)
|
327 rizwank 1.10 trace ("File compare failed!\n");
|
328 rizwank 1.8
329
|
330 rizwank 1.10 trace("Closing %s\n",name_test_txt);
|
331 rizwank 1.8 tvfs_close(active_handler);
332 if (result)
|
333 rizwank 1.10 trace ("File close failed!\n");
|
334 rizwank 1.8
335 tvfs_free();
336 free(filebuf);
337
|
338 rizwank 1.2 }
339
340 #endif
|