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