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