This source file includes following definitions.
- UMSDOS_dir_read
- umsdos_dir_once
- umsdos_readdir_x
- UMSDOS_readdir
- umsdos_lookup_patch
- umsdos_filldir_k
- umsdos_dir_search
- umsdos_inode2entry
- umsdos_locate_ancestor
- umsdos_locate_path
- umsdos_is_pseudodos
- umsdos_lookup_x
- UMSDOS_lookup
- umsdos_hlink2inode
1
2
3
4
5
6
7
8
9
10 #ifdef MODULE
11 #include <linux/module.h>
12 #endif
13
14 #include <asm/segment.h>
15
16 #include <linux/sched.h>
17 #include <linux/string.h>
18 #include <linux/fs.h>
19 #include <linux/msdos_fs.h>
20 #include <linux/errno.h>
21 #include <linux/stat.h>
22 #include <linux/limits.h>
23 #include <linux/umsdos_fs.h>
24 #include <linux/malloc.h>
25
26 #define PRINTK(x)
27 #define Printk(x) printk x
28
29 #define UMSDOS_SPECIAL_DIRFPOS 3
30 extern struct inode *pseudo_root;
31
32
33
34 int UMSDOS_dir_read(struct inode *inode,struct file *filp,char *buf,
35 int count)
36 {
37 return -EISDIR;
38 }
39
40 struct UMSDOS_DIR_ONCE {
41 void *dirbuf;
42 filldir_t filldir;
43 int count;
44 int stop;
45 };
46
47
48
49
50
51 static int umsdos_dir_once(
52 void * buf,
53 char * name,
54 int name_len,
55 off_t offset,
56 ino_t ino)
57 {
58 int ret = -EINVAL;
59 struct UMSDOS_DIR_ONCE *d = (struct UMSDOS_DIR_ONCE *)buf;
60 if (d->count == 0){
61 char zname[100];
62 memcpy (zname,name,name_len);
63 zname[name_len] = '\0';
64 PRINTK (("dir_once :%s: offset %ld\n",zname,offset));
65 ret = d->filldir (d->dirbuf,name,name_len,offset,ino);
66 d->stop = ret < 0;
67 d->count = 1;
68 }
69 return ret;
70 }
71
72
73
74
75
76
77
78
79
80
81 static int umsdos_readdir_x(
82 struct inode *dir,
83 struct file *filp,
84 void *dirbuf,
85
86 int internal_read,
87 struct umsdos_dirent *u_entry,
88 int follow_hlink,
89 filldir_t filldir)
90 {
91 int ret = 0;
92
93 umsdos_startlookup(dir);
94 if (filp->f_pos == UMSDOS_SPECIAL_DIRFPOS
95 && dir == pseudo_root
96 && !internal_read){
97
98
99
100
101
102
103
104
105
106
107 if (filldir (dirbuf,"DOS",3,UMSDOS_SPECIAL_DIRFPOS
108 ,dir->i_sb->s_mounted->i_ino) == 0){
109 filp->f_pos++;
110 }
111 }else if (filp->f_pos < 2
112 || (dir != dir->i_sb->s_mounted && filp->f_pos == 32)){
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152 int last_f_pos = filp->f_pos;
153 struct UMSDOS_DIR_ONCE bufk;
154 bufk.dirbuf = dirbuf;
155 bufk.filldir = filldir;
156 bufk.count = 0;
157 ret = msdos_readdir(dir,filp,&bufk,umsdos_dir_once);
158 if (last_f_pos > 0 && filp->f_pos > last_f_pos) filp->f_pos = UMSDOS_SPECIAL_DIRFPOS;
159 if (u_entry != NULL) u_entry->flags = 0;
160 }else{
161 struct inode *emd_dir = umsdos_emd_dir_lookup(dir,0);
162 if (emd_dir != NULL){
163 if (filp->f_pos <= UMSDOS_SPECIAL_DIRFPOS+1) filp->f_pos = 0;
164 PRINTK (("f_pos %lu i_size %ld\n",filp->f_pos,emd_dir->i_size));
165 ret = 0;
166 while (filp->f_pos < emd_dir->i_size){
167 struct umsdos_dirent entry;
168 off_t cur_f_pos = filp->f_pos;
169 if (umsdos_emd_dir_readentry (emd_dir,filp,&entry)!=0){
170 ret = -EIO;
171 break;
172 }else if (entry.name_len != 0){
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191 struct umsdos_info info;
192 struct inode *inode;
193 int lret;
194 umsdos_parse (entry.name,entry.name_len,&info);
195 info.f_pos = cur_f_pos;
196 umsdos_manglename (&info);
197 lret = umsdos_real_lookup (dir,info.fake.fname
198 ,info.fake.len,&inode);
199 PRINTK (("Cherche inode de %s lret %d flags %d\n"
200 ,info.fake.fname,lret,entry.flags));
201 if (lret == 0
202 && (entry.flags & UMSDOS_HLINK)
203 && follow_hlink){
204 struct inode *rinode;
205 lret = umsdos_hlink2inode (inode,&rinode);
206 inode = rinode;
207 }
208 if (lret == 0){
209
210
211
212
213
214
215
216 if (inode != pseudo_root
217 && (internal_read
218 || !(entry.flags & UMSDOS_HIDDEN))){
219 if (filldir (dirbuf
220 ,entry.name,entry.name_len
221 ,cur_f_pos, inode->i_ino) < 0){
222 filp->f_pos = cur_f_pos;
223 }
224 PRINTK (("Trouve ino %ld ",inode->i_ino));
225 if (u_entry != NULL) *u_entry = entry;
226 iput (inode);
227 break;
228 }
229 iput (inode);
230 }else{
231
232
233
234
235
236 ret = umsdos_writeentry (dir,emd_dir,&info,1);
237 if (ret != 0){
238 break;
239 }
240 }
241 }
242 }
243
244
245
246
247
248
249 if (filp->f_pos == 0) filp->f_pos = UMSDOS_SPECIAL_DIRFPOS;
250 iput(emd_dir);
251 }
252 }
253 umsdos_endlookup(dir);
254 PRINTK (("read dir %p pos %lu ret %d\n",dir,filp->f_pos,ret));
255 return ret;
256 }
257
258
259
260
261
262 static int UMSDOS_readdir(
263 struct inode *dir,
264 struct file *filp,
265 void *dirbuf,
266 filldir_t filldir)
267 {
268 int ret = 0;
269 int count = 0;
270 struct UMSDOS_DIR_ONCE bufk;
271 bufk.dirbuf = dirbuf;
272 bufk.filldir = filldir;
273 bufk.stop = 0;
274 PRINTK (("UMSDOS_readdir in\n"));
275 while (ret == 0 && bufk.stop == 0){
276 struct umsdos_dirent entry;
277 bufk.count = 0;
278 ret = umsdos_readdir_x (dir,filp,&bufk,0,&entry,1,umsdos_dir_once);
279 if (bufk.count == 0) break;
280 count += bufk.count;
281 }
282 PRINTK (("UMSDOS_readdir out %d count %d pos %lu\n",ret,count
283 ,filp->f_pos));
284 return count == 0 ? -ENOENT : ret;
285 }
286
287
288
289 void umsdos_lookup_patch (
290 struct inode *dir,
291 struct inode *inode,
292 struct umsdos_dirent *entry,
293 off_t emd_pos)
294 {
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324 if (inode->i_sb == dir->i_sb && !umsdos_isinit(inode)){
325 if (S_ISDIR(inode->i_mode)) umsdos_lockcreate(inode);
326 if (!umsdos_isinit(inode)){
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344 if (S_ISREG(entry->mode)) entry->mtime = inode->i_mtime;
345 inode->i_mode = entry->mode;
346 inode->i_rdev = entry->rdev;
347 inode->i_atime = entry->atime;
348 inode->i_ctime = entry->ctime;
349 inode->i_mtime = entry->mtime;
350 inode->i_uid = entry->uid;
351 inode->i_gid = entry->gid;
352
353
354
355
356
357
358
359
360 if (!S_ISDIR(entry->mode)){
361 if (entry->nlink > 0){
362 inode->i_nlink = entry->nlink;
363 }else{
364 printk ("UMSDOS: lookup_patch entry->nlink < 1 ???\n");
365 }
366 }
367 umsdos_patch_inode(inode,dir,emd_pos);
368 }
369 if (S_ISDIR(inode->i_mode)) umsdos_unlockcreate(inode);
370 if (inode->u.umsdos_i.i_emd_owner==0) printk ("emd_owner still 0 ???\n");
371 }
372 }
373 struct UMSDOS_DIRENT_K{
374 off_t f_pos;
375 ino_t ino;
376 };
377
378
379
380
381 static int umsdos_filldir_k(
382 void * buf,
383 char * name,
384 int name_len,
385 off_t offset,
386 ino_t ino)
387 {
388 struct UMSDOS_DIRENT_K *d = (struct UMSDOS_DIRENT_K *)buf;
389 d->f_pos = offset;
390 d->ino = ino;
391 return 0;
392 }
393
394 struct UMSDOS_DIR_SEARCH{
395 struct umsdos_dirent *entry;
396 int found;
397 ino_t search_ino;
398 };
399
400 static int umsdos_dir_search (
401 void * buf,
402 char * name,
403 int name_len,
404 off_t offset,
405 ino_t ino)
406 {
407 int ret = 0;
408 struct UMSDOS_DIR_SEARCH *d = (struct UMSDOS_DIR_SEARCH *)buf;
409 if (d->search_ino == ino){
410 d->found = 1;
411 memcpy (d->entry->name,name,name_len);
412 d->entry->name[name_len] = '\0';
413 d->entry->name_len = name_len;
414 ret = 1;
415 }
416 return ret;
417 }
418
419
420
421
422
423
424
425
426
427 int umsdos_inode2entry (
428 struct inode *dir,
429 struct inode *inode,
430 struct umsdos_dirent *entry)
431 {
432 int ret = -ENOENT;
433 if (inode == pseudo_root){
434
435
436
437
438 memcpy (entry->name,UMSDOS_PSDROOT_NAME,UMSDOS_PSDROOT_LEN+1);
439 entry->name_len = UMSDOS_PSDROOT_LEN;
440 ret = 0;
441 }else{
442 struct inode *emddir = umsdos_emd_dir_lookup(dir,0);
443 iput (emddir);
444 if (emddir == NULL){
445
446 struct UMSDOS_DIR_SEARCH bufk;
447 struct file filp;
448 filp.f_reada = 1;
449 filp.f_pos = 0;
450 bufk.entry = entry;
451 bufk.search_ino = inode->i_ino;
452 msdos_readdir (dir,&filp,&bufk,umsdos_dir_search);
453 if (bufk.found){
454 ret = 0;
455 inode->u.umsdos_i.i_dir_owner = dir->i_ino;
456 inode->u.umsdos_i.i_emd_owner = 0;
457 umsdos_setup_dir_inode(inode);
458 }
459 }else{
460
461 struct file filp;
462 filp.f_reada = 1;
463 filp.f_pos = UMSDOS_SPECIAL_DIRFPOS;
464 while (1){
465 struct UMSDOS_DIRENT_K bufk;
466 if (umsdos_readdir_x(dir,&filp,&bufk
467 ,1,entry,0,umsdos_filldir_k) < 0){
468 printk ("UMSDOS: can't locate inode %ld in EMD file???\n"
469 ,inode->i_ino);
470 break;
471 }else if (bufk.ino == inode->i_ino){
472 ret = 0;
473 umsdos_lookup_patch (dir,inode,entry,bufk.f_pos);
474 break;
475 }
476 }
477 }
478 }
479 return ret;
480 }
481
482
483
484
485 static int umsdos_locate_ancestor (
486 struct inode *dir,
487 struct inode **result,
488 struct umsdos_dirent *entry)
489 {
490 int ret;
491 umsdos_patch_inode (dir,NULL,0);
492 ret = umsdos_real_lookup (dir,"..",2,result);
493 PRINTK (("result %d %p ",ret,*result));
494 if (ret == 0){
495 struct inode *adir = *result;
496 ret = umsdos_inode2entry (adir,dir,entry);
497 }
498 PRINTK (("\n"));
499 return ret;
500 }
501
502
503
504
505
506
507 int umsdos_locate_path (
508 struct inode *inode,
509 char *path)
510 {
511 int ret = 0;
512 struct inode *dir = inode;
513 char *bpath = (char*)kmalloc(PATH_MAX,GFP_KERNEL);
514 if (bpath == NULL){
515 ret = -ENOMEM;
516 }else{
517 struct umsdos_dirent entry;
518 char *ptbpath = bpath+PATH_MAX-1;
519 *ptbpath = '\0';
520 PRINTK (("locate_path mode %x ",inode->i_mode));
521 if (!S_ISDIR(inode->i_mode)){
522 ret = umsdos_get_dirowner (inode,&dir);
523 PRINTK (("locate_path ret %d ",ret));
524 if (ret == 0){
525 ret = umsdos_inode2entry (dir,inode,&entry);
526 if (ret == 0){
527 ptbpath -= entry.name_len;
528 memcpy (ptbpath,entry.name,entry.name_len);
529 PRINTK (("ptbpath :%s: ",ptbpath));
530 }
531 }
532 }else{
533 dir->i_count++;
534 }
535 if (ret == 0){
536 while (dir != dir->i_sb->s_mounted){
537 struct inode *adir;
538 ret = umsdos_locate_ancestor (dir,&adir,&entry);
539 iput (dir);
540 dir = NULL;
541 PRINTK (("ancestor %d ",ret));
542 if (ret == 0){
543 *--ptbpath = '/';
544 ptbpath -= entry.name_len;
545 memcpy (ptbpath,entry.name,entry.name_len);
546 dir = adir;
547 PRINTK (("ptbpath :%s: ",ptbpath));
548 }else{
549 break;
550 }
551 }
552 }
553 strcpy (path,ptbpath);
554 kfree (bpath);
555 }
556 PRINTK (("\n"));
557 iput (dir);
558 return ret;
559 }
560
561
562
563
564 int umsdos_is_pseudodos (
565 struct inode *dir,
566 const char *name,
567 int len)
568 {
569
570
571
572
573
574
575
576 return dir == pseudo_root
577 && len == 3
578 && name[0] == 'D' && name[1] == 'O' && name[2] == 'S';
579 }
580
581
582
583
584 static int umsdos_lookup_x (
585 struct inode *dir,
586 const char *name,
587 int len,
588 struct inode **result,
589 int nopseudo)
590 {
591 int ret = -ENOENT;
592 *result = NULL;
593 umsdos_startlookup(dir);
594 if (len == 1 && name[0] == '.'){
595 *result = dir;
596 dir->i_count++;
597 ret = 0;
598 }else if (len == 2 && name[0] == '.' && name[1] == '.'){
599 if (pseudo_root != NULL && dir == pseudo_root->i_sb->s_mounted){
600
601
602
603
604
605 ret = 0;
606 *result = pseudo_root;
607 pseudo_root->i_count++;
608 }else{
609
610
611
612
613
614
615
616
617
618
619 ret = umsdos_real_lookup (dir,"..",2,result);
620 PRINTK (("ancestor ret %d dir %p *result %p ",ret,dir,*result));
621 if (ret == 0
622 && *result != dir->i_sb->s_mounted
623 && *result != pseudo_root){
624 struct inode *aadir;
625 struct umsdos_dirent entry;
626 ret = umsdos_locate_ancestor (*result,&aadir,&entry);
627 iput (aadir);
628 }
629 }
630 }else if (umsdos_is_pseudodos(dir,name,len)){
631
632
633
634
635 *result = dir->i_sb->s_mounted;
636 (*result)->i_count++;
637 ret = 0;
638 }else{
639 struct umsdos_info info;
640 ret = umsdos_parse (name,len,&info);
641 if (ret == 0) ret = umsdos_findentry (dir,&info,0);
642 PRINTK (("lookup %s pos %lu ret %d len %d ",info.fake.fname,info.f_pos,ret
643 ,info.fake.len));
644 if (ret == 0){
645
646
647
648
649
650
651
652
653
654 struct inode *inode;
655 ret = umsdos_real_lookup (dir,info.fake.fname,info.fake.len,result);
656 inode = *result;
657 if (inode == NULL){
658 printk ("UMSDOS: Erase entry %s, out of sync with MsDOS\n"
659 ,info.fake.fname);
660 umsdos_delentry (dir,&info,S_ISDIR(info.entry.mode));
661 }else{
662 umsdos_lookup_patch (dir,inode,&info.entry,info.f_pos);
663 PRINTK (("lookup ino %ld flags %d\n",inode->i_ino
664 ,info.entry.flags));
665 if (info.entry.flags & UMSDOS_HLINK){
666 ret = umsdos_hlink2inode (inode,result);
667 }
668 if (*result == pseudo_root && !nopseudo){
669
670
671
672
673
674
675
676
677
678 iput (pseudo_root);
679 *result = NULL;
680 ret = -ENOENT;
681 }
682 }
683 }
684 }
685 umsdos_endlookup(dir);
686 iput (dir);
687 return ret;
688 }
689
690
691
692
693 int UMSDOS_lookup (
694 struct inode *dir,
695 const char *name,
696 int len,
697 struct inode **result)
698 {
699 return umsdos_lookup_x(dir,name,len,result,0);
700 }
701
702
703
704
705 int umsdos_hlink2inode (struct inode *hlink, struct inode **result)
706 {
707 int ret = -EIO;
708 char *path = (char*)kmalloc(PATH_MAX,GFP_KERNEL);
709 *result = NULL;
710 if (path == NULL){
711 ret = -ENOMEM;
712 iput (hlink);
713 }else{
714 struct file filp;
715 filp.f_reada = 1;
716 filp.f_pos = 0;
717 PRINTK (("hlink2inode "));
718 if (umsdos_file_read_kmem (hlink,&filp,path,hlink->i_size)
719 ==hlink->i_size){
720 struct inode *dir;
721 char *pt = path;
722 dir = hlink->i_sb->s_mounted;
723 path[hlink->i_size] = '\0';
724 iput (hlink);
725 dir->i_count++;
726 while (1){
727 char *start = pt;
728 int len;
729 while (*pt != '\0' && *pt != '/') pt++;
730 len = (int)(pt - start);
731 if (*pt == '/') *pt++ = '\0';
732 if (dir->u.umsdos_i.i_emd_dir == 0){
733
734 ret = umsdos_rlookup_x(dir,start,len,result,1);
735 }else{
736 ret = umsdos_lookup_x(dir,start,len,result,1);
737 }
738 PRINTK (("h2n lookup :%s: -> %d ",start,ret));
739 if (ret == 0 && *pt != '\0'){
740 dir = *result;
741 }else{
742 break;
743 }
744 }
745 }else{
746 iput (hlink);
747 }
748 PRINTK (("hlink2inode ret = %d %p -> %p\n",ret,hlink,*result));
749 kfree (path);
750 }
751 return ret;
752 }
753
754 static struct file_operations umsdos_dir_operations = {
755 NULL,
756 UMSDOS_dir_read,
757 NULL,
758 UMSDOS_readdir,
759 NULL,
760 UMSDOS_ioctl_dir,
761 NULL,
762 NULL,
763 NULL,
764 NULL
765 };
766
767 struct inode_operations umsdos_dir_inode_operations = {
768 &umsdos_dir_operations,
769 UMSDOS_create,
770 UMSDOS_lookup,
771 UMSDOS_link,
772 UMSDOS_unlink,
773 UMSDOS_symlink,
774 UMSDOS_mkdir,
775 UMSDOS_rmdir,
776 UMSDOS_mknod,
777 UMSDOS_rename,
778 NULL,
779 NULL,
780 NULL,
781 NULL,
782 NULL
783 };
784
785
786
787
788
789
790
791
792
793