This source file includes following definitions.
- umsdos_readdir_kmem
- umsdos_file_read_kmem
- umsdos_file_write_kmem
- umsdos_emd_dir_write
- umsdos_emd_dir_read
- umsdos_emd_dir_lookup
- umsdos_emd_dir_readentry
- umsdos_writeentry
- umsdos_fillbuf
- umsdos_find
- umsdos_newentry
- umsdos_newhidden
- umsdos_delentry
- umsdos_isempty
- umsdos_findentry
1
2
3
4
5
6
7
8 #include <linux/types.h>
9 #include <linux/fcntl.h>
10 #include <linux/kernel.h>
11 #include <asm/segment.h>
12 #include <linux/sched.h>
13 #include <linux/errno.h>
14 #include <linux/string.h>
15 #include <linux/msdos_fs.h>
16 #include <linux/umsdos_fs.h>
17
18 #define PRINTK(x)
19 #define Printk(x) printk x
20
21 int umsdos_readdir_kmem(
22 struct inode *inode,
23 struct file *filp,
24 struct dirent *dirent,
25 int count)
26 {
27 int ret;
28 set_fs (KERNEL_DS);
29 ret = msdos_readdir(inode,filp,dirent,count);
30 set_fs (USER_DS);
31 return ret;
32 }
33
34
35
36 int umsdos_file_read_kmem(
37 struct inode *inode,
38 struct file *filp,
39 char *buf,
40 int count)
41 {
42 int ret;
43 set_fs (KERNEL_DS);
44 ret = msdos_file_read(inode,filp,buf,count);
45 set_fs (USER_DS);
46 return ret;
47 }
48
49
50
51 int umsdos_file_write_kmem(
52 struct inode *inode,
53 struct file *filp,
54 char *buf,
55 int count)
56 {
57 int ret;
58 set_fs (KERNEL_DS);
59 ret = msdos_file_write(inode,filp,buf,count);
60 set_fs (USER_DS);
61 return ret;
62 }
63
64
65
66
67
68
69
70
71 int umsdos_emd_dir_write (
72 struct inode *emd_dir,
73 struct file *filp,
74 char *buf,
75 int count)
76 {
77 int written;
78 filp->f_flags = 0;
79 written = umsdos_file_write_kmem (emd_dir,filp,buf,count);
80 return written != count ? -EIO : 0;
81 }
82
83
84
85
86
87 int umsdos_emd_dir_read (
88 struct inode *emd_dir,
89 struct file *filp,
90 char *buf,
91 int count)
92 {
93 int ret = 0;
94 int sizeread;
95 filp->f_flags = 0;
96 sizeread = umsdos_file_read_kmem (emd_dir,filp,buf,count);
97 if (sizeread != count){
98 printk ("UMSDOS: problem with EMD file. Can't read\n");
99 ret = -EIO;
100 }
101 return ret;
102
103 }
104
105
106
107
108
109 struct inode *umsdos_emd_dir_lookup(struct inode *dir, int creat)
110 {
111 struct inode *ret = NULL;
112 if (dir->u.umsdos_i.i_emd_dir != 0){
113 ret = iget (dir->i_sb,dir->u.umsdos_i.i_emd_dir);
114 PRINTK (("deja trouve %d %x [%d] "
115 ,dir->u.umsdos_i.i_emd_dir,ret,ret->i_count));
116 }else{
117 umsdos_real_lookup (dir,UMSDOS_EMD_FILE,UMSDOS_EMD_NAMELEN,&ret);
118 PRINTK (("emd_dir_lookup "));
119 if (ret != NULL){
120 PRINTK (("Find --linux "));
121 dir->u.umsdos_i.i_emd_dir = ret->i_ino;
122 }else if (creat){
123 int code;
124 PRINTK (("avant create "));
125 dir->i_count++;
126 code = msdos_create (dir,UMSDOS_EMD_FILE,UMSDOS_EMD_NAMELEN
127 ,S_IFREG|0777,&ret);
128 PRINTK (("Creat EMD code %d ret %x ",code,ret));
129 if (ret != NULL){
130 dir->u.umsdos_i.i_emd_dir = ret->i_ino;
131 }else{
132 printk ("UMSDOS: Can't create EMD file\n");
133 }
134 }
135 }
136 if (ret != NULL){
137
138 ret->u.umsdos_i.i_emd_owner = 0xffffffff;
139 }
140 return ret;
141 }
142
143
144
145
146
147
148 int umsdos_emd_dir_readentry (
149 struct inode *emd_dir,
150 struct file *filp,
151 struct umsdos_dirent *entry)
152 {
153 int ret = umsdos_emd_dir_read(emd_dir,filp,(char*)entry,UMSDOS_REC_SIZE);
154 if (ret == 0){
155
156 int recsize = umsdos_evalrecsize (entry->name_len);
157 if (recsize > UMSDOS_REC_SIZE){
158 ret = umsdos_emd_dir_read(emd_dir,filp
159 ,((char*)entry)+UMSDOS_REC_SIZE,recsize - UMSDOS_REC_SIZE);
160
161 }
162 }
163 return ret;
164 }
165
166
167
168
169 int umsdos_writeentry (
170 struct inode *dir,
171 struct inode *emd_dir,
172 struct umsdos_info *info,
173 int free_entry)
174 {
175 int ret = 0;
176 struct file filp;
177 struct umsdos_dirent *entry = &info->entry;
178 struct umsdos_dirent entry0;
179 if (free_entry){
180
181
182
183
184
185
186 memset (&entry0,0,sizeof(entry0));
187 entry = &entry0;
188 }else if (entry->name_len > 0){
189 memset (entry->name+entry->name_len,'\0'
190 ,sizeof(entry->name)-entry->name_len);
191
192
193
194
195
196
197 memset (entry->spare,0,sizeof(entry->spare));
198 }
199 filp.f_pos = info->f_pos;
200 ret = umsdos_emd_dir_write(emd_dir,&filp,(char*)entry,info->recsize);
201 if (ret != 0){
202 printk ("UMSDOS: problem with EMD file. Can't write\n");
203 }else{
204 dir->i_ctime = dir->i_mtime = CURRENT_TIME;
205 dir->i_dirt = 1;
206 }
207 return ret;
208 }
209
210 #define CHUNK_SIZE (16*UMSDOS_REC_SIZE)
211 struct find_buffer{
212 char buffer[CHUNK_SIZE];
213 int pos;
214 int size;
215 struct file filp;
216 };
217
218
219
220
221
222
223
224 static int umsdos_fillbuf (
225 struct inode *inode,
226 struct find_buffer *buf)
227 {
228 int ret = -ENOENT;
229 int mustmove = buf->size - buf->pos;
230 int mustread;
231 int remain;
232 if (mustmove > 0){
233 memcpy (buf->buffer,buf->buffer+buf->pos,mustmove);
234 }
235 buf->pos = 0;
236 mustread = CHUNK_SIZE - mustmove;
237 remain = inode->i_size - buf->filp.f_pos;
238 if (remain < mustread) mustread = remain;
239 if (mustread > 0){
240 ret = umsdos_emd_dir_read (inode,&buf->filp,buf->buffer+mustmove
241 ,mustread);
242 if (ret == 0) buf->size = mustmove + mustread;
243 }else if (mustmove){
244 buf->size = mustmove;
245 ret = 0;
246 }
247 return ret;
248 }
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271 static int umsdos_find (
272 struct inode *dir,
273 struct umsdos_info *info,
274
275 struct inode **pt_emd_dir)
276
277 {
278
279
280
281
282
283 int ret = -ENOENT;
284 struct inode *emd_dir = umsdos_emd_dir_lookup(dir,1);
285 if (emd_dir != NULL){
286 struct umsdos_dirent *entry = &info->entry;
287 int recsize = info->recsize;
288 struct {
289 off_t posok;
290 int found;
291 off_t one;
292 int onesize;
293 }empty;
294
295 struct find_buffer buf;
296 buf.pos = 0;
297 buf.size = 0;
298 buf.filp.f_pos = 0;
299 empty.found = 0;
300 empty.posok = emd_dir->i_size;
301 empty.onesize = 0;
302 while (1){
303 struct umsdos_dirent *rentry = (struct umsdos_dirent*)
304 (buf.buffer + buf.pos);
305 int file_pos = buf.filp.f_pos - buf.size + buf.pos;
306 if (buf.pos == buf.size){
307 ret = umsdos_fillbuf (emd_dir,&buf);
308 if (ret < 0){
309
310 info->f_pos = empty.posok;
311 break;
312 }
313 }else if (rentry->name_len == 0){
314
315
316 if (entry->name_len == 0){
317 info->f_pos = file_pos;
318 ret = 0;
319 break;
320 }else if (!empty.found){
321 if (empty.onesize == 0){
322
323 empty.one = file_pos;
324 }
325
326 empty.onesize += UMSDOS_REC_SIZE;
327 if (empty.onesize == recsize){
328
329 empty.posok = empty.one;
330 empty.found = 1;
331 }
332 }
333 buf.pos += UMSDOS_REC_SIZE;
334 }else{
335 int entry_size = umsdos_evalrecsize(rentry->name_len);
336 if (buf.pos+entry_size > buf.size){
337 ret = umsdos_fillbuf (emd_dir,&buf);
338 if (ret < 0){
339
340 info->f_pos = empty.posok;
341 break;
342 }
343 }else{
344 empty.onesize = 0;
345 if (entry->name_len == rentry->name_len
346 && memcmp(entry->name,rentry->name,rentry->name_len)
347 ==0){
348 info->f_pos = file_pos;
349 *entry = *rentry;
350 ret = 0;
351 break;
352 }else{
353 buf.pos += entry_size;
354 }
355 }
356 }
357 }
358 umsdos_manglename(info);
359 }
360 *pt_emd_dir = emd_dir;
361 return ret;
362 }
363
364
365
366
367
368
369
370 int umsdos_newentry (
371 struct inode *dir,
372 struct umsdos_info *info)
373 {
374 struct inode *emd_dir;
375 int ret = umsdos_find (dir,info,&emd_dir);
376 if (ret == 0){
377 ret = -EEXIST;
378 }else if (ret == -ENOENT){
379 ret = umsdos_writeentry(dir,emd_dir,info,0);
380 PRINTK (("umsdos_newentry EDM ret = %d\n",ret));
381 }
382 iput (emd_dir);
383 return ret;
384 }
385
386
387
388
389 int umsdos_newhidden (
390 struct inode *dir,
391 struct umsdos_info *info)
392 {
393 struct inode *emd_dir;
394 int ret;
395 umsdos_parse ("..LINK",6,info);
396 info->entry.name_len = 0;
397 ret = umsdos_find (dir,info,&emd_dir);
398 iput (emd_dir);
399 if (ret == -ENOENT || ret == 0){
400
401
402
403
404
405 info->entry.name_len = sprintf (info->entry.name,"..LINK%ld"
406 ,info->f_pos);
407 ret = 0;
408 }
409 return ret;
410 }
411
412
413
414
415
416
417 int umsdos_delentry (
418 struct inode *dir,
419 struct umsdos_info *info,
420 int isdir)
421 {
422 struct inode *emd_dir;
423 int ret = umsdos_find (dir,info,&emd_dir);
424 if (ret == 0){
425 if (info->entry.name_len != 0){
426 if ((isdir != 0) != (S_ISDIR(info->entry.mode) != 0)){
427 if (S_ISDIR(info->entry.mode)){
428 ret = -EISDIR;
429 }else{
430 ret = -ENOTDIR;
431 }
432 }else{
433 ret = umsdos_writeentry(dir,emd_dir,info,1);
434 }
435 }
436 }
437 iput(emd_dir);
438 return ret;
439 }
440
441
442
443
444
445
446
447
448 int umsdos_isempty (struct inode *dir)
449 {
450 int ret = 2;
451 struct inode *emd_dir = umsdos_emd_dir_lookup(dir,0);
452
453 if (emd_dir != NULL){
454 struct file filp;
455
456 filp.f_pos = 0;
457 filp.f_flags = O_RDONLY;
458 ret = 1;
459 while (filp.f_pos < emd_dir->i_size){
460 struct umsdos_dirent entry;
461 if (umsdos_emd_dir_readentry(emd_dir,&filp,&entry)!=0){
462 ret = 0;
463 break;
464 }else if (entry.name_len != 0){
465 ret = 0;
466 break;
467 }
468 }
469 iput (emd_dir);
470 }
471 return ret;
472 }
473
474
475
476
477
478 int umsdos_findentry (
479 struct inode *dir,
480 struct umsdos_info *info,
481 int expect)
482
483
484 {
485 struct inode *emd_dir;
486 int ret = umsdos_find (dir,info,&emd_dir);
487 if (ret == 0){
488 if (expect != 0){
489 if (S_ISDIR(info->entry.mode)){
490 if (expect != 2) ret = -EISDIR;
491 }else if (expect == 2){
492 ret = -ENOTDIR;
493 }
494 }
495 }
496 iput (emd_dir);
497 return ret;
498 }
499