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 #ifdef DEBUG
81 printf("tvfs_open called with %s, %d, %d\n", fname, flags, mode);
82 #endif
83
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 return -1;
95 }
96 inode = tvfs_create(fname, 0, 0);
97 }
|
98 rizwank 1.2 handler = malloc(sizeof(struct tvfs_fcb));
99 handler->inode = inode;
100 handler->pos=0;
101 h = nfiles++;
102 handles[h] = handler;
103 return h;
|
104 rizwank 1.1 }
|
105 rizwank 1.2
|
106 rizwank 1.1 unsigned int tvfs_read(int h, void *buf, unsigned int len)
107 {
|
108 rizwank 1.2 int inode = handles[h]->inode;
109 int pos = handles[h]->pos;
110 int size = files[inode]->bytes_used;
|
111 rizwank 1.1
|
112 rizwank 1.4 #ifdef DEBUG
113 printf("tvfs_read called with %d, %d, %d\n", h, buf, len);
114 #endif
115
|
116 rizwank 1.1 /* FIXME: handle edge cases */
|
117 rizwank 1.2 /* Edge Case 1 : Request beyond boundary of file */
118 if (pos + len > size) {
119 len = size-pos;
120 }
121
122 memcpy(buf, files[inode]->buf+pos, len);
123 handles[h]->pos += len;
|
124 rizwank 1.1
125 return len;
126 }
|
127 rizwank 1.2
128 void tvfs_free(){
|
129 rizwank 1.4
|
130 rizwank 1.2 int inode;
|
131 rizwank 1.4
132 #ifdef DEBUG
133 printf("tvfs_free\n");
134 #endif
135
136 for (inode=0; inode<nfiles; inode++) {
|
137 rizwank 1.2 if (!files[inode])
138 continue;
139 free(files[inode]);
140 }
141 }
142
|
143 rizwank 1.4 /* Compare given file with given contents, return 0 on equal, else nonzero */
144 int tvfs_compare(const char *fname, const char *buf, int len){
145 #ifdef DEBUG
146 printf("tvfs_compare called with %s, %d, %d\n", fname, buf, len);
147 #endif
148
149 return (memcmp(fname,buf,len));
150 /* doesnt check for out of bound */
151 }
|
152 rizwank 1.2
|
153 rizwank 1.4 long tvfs_lseek(int h, long whither, int whence){
|
154 rizwank 1.2
|
155 rizwank 1.4 int inode = handles[h]->inode;
156 int size = files[inode]->bytes_used;
157 #ifdef DEBUG
158 printf("tvfs_lseek called with %d, %d, %d\n", h, whither, whence);
159 #endif
160 /* if (whence > size)
161 whence = size;*/
162 /* Legit lseek does NOT do boundry checking */
163
164 switch(whither) {
165 case SEEK_SET: {
166 handles[h]->pos = whence;
167 break;
168 }
169 case SEEK_CUR: {
170 handles[h]->pos += whence;
171 break;
172 }
173 case SEEK_END: {
174 handles[h]->pos = size+whence;
175 break;
176 rizwank 1.4 }
177 case 5: {
178 handles[h]->pos = size+whence;
179 break;
180 }
181 case 44: {
182 handles[h]->pos = size+whence;
183 break;
184 }
185 default:
186 {
187 printf("lseek was called with an invalid whither %d\n",whither);
188 return -1;
189 }
190 }
191 return handles[h]->pos;
192 }
193
194 int tvfs_close(int h){
195 int inode = handles[h]->inode;
196 #ifdef DEBUG
197 rizwank 1.4 printf("tvfs_close called with %d\n", h);
198 #endif
199 if (!files[inode]){
200 return -1;
201 }
202 free(handles[h]);
203 /* Currently does NOT enabled open to reuse this handle */
204 return 0;
205 }
206
207 unsigned int tvfs_write(int h, void *buf, unsigned int len)
208 {
209 printf("tvfs_write called with %d, %d, %d\n", h, buf, len);
210 return len;
211 /* return -1 to simulate diskfull or some other error */
212 }
213
214
215
216
|
217 rizwank 1.2
218 #ifdef TVFS_MAIN
|
219 rizwank 1.4
|
220 rizwank 1.3 const static char name_test_txt[] = "test.txt";
221 const static char file_test_txt[] = "This is a test. Don't Panic!";
|
222 rizwank 1.4 const static int size_test_txt = sizeof(file_test_txt);
|
223 rizwank 1.2
224 main(){
225 int result;
226 int active_handler;
227
228 char *filebuf;
229
230 char dummy_filename[] = "dummy.txt";
231 char bad_filename[] = "chicken.txt";
232
233 filebuf = malloc(MAXFLEN);
234
|
235 rizwank 1.3 printf("Testing TVFS implementation, creating %s\n",name_test_txt);
|
236 rizwank 1.4 result = tvfs_create( dummy_filename, file_test_txt, size_test_txt);
237 result = tvfs_create( name_test_txt, file_test_txt,size_test_txt);
|
238 rizwank 1.2 printf("Created virtual file with inode %d\n",result);
239
240 /* This test failes because strcmp returns 0 incorrectly! */
241 printf("Attempting to open non-existant file\n");
242 result = tvfs_open(bad_filename, _O_BINARY, 0 );
243 printf("Result code %d\n",result);
244 printf("Attempting to open existant file\n");
|
245 rizwank 1.3 result = tvfs_open(name_test_txt, _O_BINARY, 0 );
|
246 rizwank 1.2 printf("Result code %d\n",result);
247
248 active_handler = result;
249
250 memset (filebuf,0,MAXFLEN);
251
|
252 rizwank 1.3 printf("Testing reading from file %s\n",name_test_txt);
|
253 rizwank 1.2 result = tvfs_read(active_handler, filebuf, 9);
254 printf("Read _%s_\n", filebuf);
|
255 rizwank 1.4 if ( strcmp(filebuf,"This is a"))
256 printf("File read check failed!\n");
|
257 rizwank 1.2
|
258 rizwank 1.3 printf("Testing sequential reading from file %s\n",name_test_txt);
|
259 rizwank 1.2 result = tvfs_read(active_handler, filebuf, 12);
260 printf("Read _%s_\n", filebuf);
|
261 rizwank 1.4 if ( strcmp(filebuf," test. Don't"))
|
262 rizwank 1.2 printf("File read check failed!\n");
|
263 rizwank 1.4
|
264 rizwank 1.3 printf("Testing edge reading from file %s\n",name_test_txt);
|
265 rizwank 1.4 result = tvfs_read(active_handler, filebuf, 42);
|
266 rizwank 1.2 printf("Read %d bytes - _%s_\n", result, filebuf);
|
267 rizwank 1.4 if ( result != 8 )
|
268 rizwank 1.2 printf("File read check failed!\n");
269
|
270 rizwank 1.4 printf("Testing direct file compare and lseek of %s\n", name_test_txt);
271 printf("Seeking to 0 - ");
272 tvfs_lseek( active_handler, SEEK_SET, 0);
273 printf("Reading and comparing file\n");
274 result = tvfs_read(active_handler, filebuf, size_test_txt);
275 result = tvfs_compare( filebuf , file_test_txt, size_test_txt);
276 if (result)
277 printf ("File compare failed!\n");
278
|
279 rizwank 1.2
|
280 rizwank 1.4 printf("Closing %s\n",name_test_txt);
281 tvfs_close(active_handler);
282 if (result)
283 printf ("File close failed!\n");
284
|
285 rizwank 1.2 tvfs_free();
286 free(filebuf);
287
288 }
289
290 #endif
|