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