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