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_pos = 0;
354 while (1){
355 struct dirent dirent;
356 if (umsdos_readdir_kmem (dir,&filp,&dirent,1) <= 0){
357 printk ("UMSDOS: can't locate inode %ld in DOS directory???\n"
358 ,inode->i_ino);
359 }else if (dirent.d_ino == inode->i_ino){
360 ret = 0;
361 memcpy (entry->name,dirent.d_name,dirent.d_reclen);
362 entry->name[dirent.d_reclen] = '\0';
363 entry->name_len = dirent.d_reclen;
364 inode->u.umsdos_i.i_dir_owner = dir->i_ino;
365 inode->u.umsdos_i.i_emd_owner = 0;
366 umsdos_setup_dir_inode(inode);
367 break;
368 }
369 }
370 }else{
371
372 struct file filp;
373 filp.f_pos = UMSDOS_SPECIAL_DIRFPOS;
374 while (1){
375 struct dirent dirent;
376 off_t f_pos;
377 if (umsdos_readdir_x(dir,&filp,&dirent
378 ,0,1,entry,0,&f_pos) <= 0){
379 printk ("UMSDOS: can't locate inode %ld in EMD file???\n"
380 ,inode->i_ino);
381 break;
382 }else if (dirent.d_ino == inode->i_ino){
383 ret = 0;
384 umsdos_lookup_patch (dir,inode,entry,f_pos);
385 break;
386 }
387 }
388 }
389 }
390 return ret;
391 }
392
393
394
395
396 static int umsdos_locate_ancestor (
397 struct inode *dir,
398 struct inode **result,
399 struct umsdos_dirent *entry)
400 {
401 int ret;
402 umsdos_patch_inode (dir,NULL,0);
403 ret = umsdos_real_lookup (dir,"..",2,result);
404 PRINTK (("result %d %x ",ret,*result));
405 if (ret == 0){
406 struct inode *adir = *result;
407 ret = umsdos_inode2entry (adir,dir,entry);
408 }
409 PRINTK (("\n"));
410 return ret;
411 }
412
413
414
415
416
417
418 int umsdos_locate_path (
419 struct inode *inode,
420 char *path)
421 {
422 int ret = 0;
423 struct inode *dir = inode;
424 char *bpath = (char*)kmalloc(PATH_MAX,GFP_KERNEL);
425 if (bpath == NULL){
426 ret = -ENOMEM;
427 }else{
428 struct umsdos_dirent entry;
429 char *ptbpath = bpath+PATH_MAX-1;
430 *ptbpath = '\0';
431 PRINTK (("locate_path mode %x ",inode->i_mode));
432 if (!S_ISDIR(inode->i_mode)){
433 ret = umsdos_get_dirowner (inode,&dir);
434 PRINTK (("locate_path ret %d ",ret));
435 if (ret == 0){
436 ret = umsdos_inode2entry (dir,inode,&entry);
437 if (ret == 0){
438 ptbpath -= entry.name_len;
439 memcpy (ptbpath,entry.name,entry.name_len);
440 PRINTK (("ptbpath :%s: ",ptbpath));
441 }
442 }
443 }else{
444 dir->i_count++;
445 }
446 if (ret == 0){
447 while (dir != dir->i_sb->s_mounted){
448 struct inode *adir;
449 ret = umsdos_locate_ancestor (dir,&adir,&entry);
450 iput (dir);
451 dir = NULL;
452 PRINTK (("ancestor %d ",ret));
453 if (ret == 0){
454 *--ptbpath = '/';
455 ptbpath -= entry.name_len;
456 memcpy (ptbpath,entry.name,entry.name_len);
457 dir = adir;
458 PRINTK (("ptbpath :%s: ",ptbpath));
459 }else{
460 break;
461 }
462 }
463 }
464 strcpy (path,ptbpath);
465 kfree (bpath);
466 }
467 PRINTK (("\n"));
468 iput (dir);
469 return ret;
470 }
471
472
473
474
475 int umsdos_is_pseudodos (
476 struct inode *dir,
477 const char *name,
478 int len)
479 {
480
481
482
483
484
485
486
487 return dir == pseudo_root
488 && len == 3
489 && name[0] == 'D' && name[1] == 'O' && name[2] == 'S';
490 }
491
492
493
494
495 static int umsdos_lookup_x (
496 struct inode *dir,
497 const char *name,
498 int len,
499 struct inode **result,
500 int nopseudo)
501 {
502 int ret = -ENOENT;
503 *result = NULL;
504 umsdos_startlookup(dir);
505 if (len == 1 && name[0] == '.'){
506 *result = dir;
507 dir->i_count++;
508 ret = 0;
509 }else if (len == 2 && name[0] == '.' && name[1] == '.'){
510 if (pseudo_root != NULL && dir == pseudo_root->i_sb->s_mounted){
511
512
513
514
515
516 ret = 0;
517 *result = pseudo_root;
518 pseudo_root->i_count++;
519 }else{
520
521
522
523
524
525
526
527
528
529
530 ret = umsdos_real_lookup (dir,"..",2,result);
531 PRINTK (("ancestor ret %d dir %p *result %p ",ret,dir,*result));
532 if (ret == 0
533 && *result != dir->i_sb->s_mounted
534 && *result != pseudo_root){
535 struct inode *aadir;
536 struct umsdos_dirent entry;
537 ret = umsdos_locate_ancestor (*result,&aadir,&entry);
538 iput (aadir);
539 }
540 }
541 }else if (umsdos_is_pseudodos(dir,name,len)){
542
543
544
545
546 *result = dir->i_sb->s_mounted;
547 (*result)->i_count++;
548 ret = 0;
549 }else{
550 struct umsdos_info info;
551 ret = umsdos_parse (name,len,&info);
552 if (ret == 0) ret = umsdos_findentry (dir,&info,0);
553 PRINTK (("lookup %s pos %d ret %d len %d ",info.fake.fname,info.f_pos,ret
554 ,info.fake.len));
555 if (ret == 0){
556
557
558
559
560
561
562
563
564
565 struct inode *inode;
566 ret = umsdos_real_lookup (dir,info.fake.fname,info.fake.len,result);
567 inode = *result;
568 if (inode == NULL){
569 printk ("UMSDOS: Erase entry %s, out of sync with MsDOS\n"
570 ,info.fake.fname);
571 umsdos_delentry (dir,&info,S_ISDIR(info.entry.mode));
572 }else{
573 umsdos_lookup_patch (dir,inode,&info.entry,info.f_pos);
574 PRINTK (("lookup ino %d flags %d\n",inode->i_ino
575 ,info.entry.flags));
576 if (info.entry.flags & UMSDOS_HLINK){
577 ret = umsdos_hlink2inode (inode,result);
578 }
579 if (*result == pseudo_root && !nopseudo){
580
581
582
583
584
585
586
587
588
589 iput (pseudo_root);
590 *result = NULL;
591 ret = -ENOENT;
592 }
593 }
594 }
595 }
596 umsdos_endlookup(dir);
597 iput (dir);
598 return ret;
599 }
600
601
602
603
604 int UMSDOS_lookup (
605 struct inode *dir,
606 const char *name,
607 int len,
608 struct inode **result)
609 {
610 return umsdos_lookup_x(dir,name,len,result,0);
611 }
612
613
614
615
616 int umsdos_hlink2inode (struct inode *hlink, struct inode **result)
617 {
618 int ret = -EIO;
619 char *path = (char*)kmalloc(PATH_MAX,GFP_KERNEL);
620 *result = NULL;
621 if (path == NULL){
622 ret = -ENOMEM;
623 iput (hlink);
624 }else{
625 struct file filp;
626 filp.f_pos = 0;
627 PRINTK (("hlink2inode "));
628 if (umsdos_file_read_kmem (hlink,&filp,path,hlink->i_size)
629 ==hlink->i_size){
630 struct inode *dir;
631 char *pt = path;
632 dir = hlink->i_sb->s_mounted;
633 path[hlink->i_size] = '\0';
634 iput (hlink);
635 dir->i_count++;
636 while (1){
637 char *start = pt;
638 int len;
639 while (*pt != '\0' && *pt != '/') pt++;
640 len = (int)(pt - start);
641 if (*pt == '/') *pt++ = '\0';
642 if (dir->u.umsdos_i.i_emd_dir == 0){
643
644 ret = msdos_lookup(dir,start,len,result);
645 }else{
646 ret = umsdos_lookup_x(dir,start,len,result,1);
647 }
648 PRINTK (("h2n lookup :%s: -> %d ",start,ret));
649 if (ret == 0 && *pt != '\0'){
650 dir = *result;
651 }else{
652 break;
653 }
654 }
655 }else{
656 iput (hlink);
657 }
658 PRINTK (("hlink2inode ret = %d %p -> %p\n",ret,hlink,*result));
659 kfree (path);
660 }
661 return ret;
662 }
663
664 static struct file_operations umsdos_dir_operations = {
665 NULL,
666 UMSDOS_dir_read,
667 NULL,
668 UMSDOS_readdir,
669 NULL,
670 UMSDOS_ioctl_dir,
671 NULL,
672 NULL,
673 NULL,
674 NULL
675 };
676
677 struct inode_operations umsdos_dir_inode_operations = {
678 &umsdos_dir_operations,
679 UMSDOS_create,
680 UMSDOS_lookup,
681 UMSDOS_link,
682 UMSDOS_unlink,
683 UMSDOS_symlink,
684 UMSDOS_mkdir,
685 UMSDOS_rmdir,
686 UMSDOS_mknod,
687 UMSDOS_rename,
688 NULL,
689 NULL,
690 NULL,
691 NULL,
692 NULL
693 };
694
695
696
697
698
699
700
701
702
703