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