1 /* 2 * linux/fs/umsdos/dir.c 3 * 4 * Written 1993 by Jacques Gelinas 5 * Inspired from linux/fs/msdos/... : Werner Almesberger 6 * 7 * Extended MS-DOS directory handling functions 8 */ 9
10 #ifdefMODULE 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 #definePRINTK(x)
27 #definePrintk(x) printkx 28
29 #defineUMSDOS_SPECIAL_DIRFPOS 3
30 externstructinode *pseudo_root;
31 /* 32 So grep * doesn't complain in the presence of directories. 33 */ 34 intUMSDOS_dir_read(structinode *inode,structfile *filp,char *buf,
/* */ 35 intcount)
36 { 37 return -EISDIR;
38 } 39
40 structUMSDOS_DIR_ONCE{ 41 void *dirbuf;
42 filldir_tfilldir;
43 intcount;
44 intstop;
45 };
46
47 /* 48 Record a single entry the first call. 49 Return -EINVAL the next one. 50 */ 51 staticintumsdos_dir_once(
/* */ 52 void * buf,
53 constchar * name,
54 intname_len,
55 off_toffset,
56 ino_tino)
57 { 58 intret = -EINVAL;
59 structUMSDOS_DIR_ONCE *d = (structUMSDOS_DIR_ONCE *)buf;
60 if (d->count == 0){ 61 #if 0
62 charzname[100];
63 memcpy (zname,name,name_len);
64 zname[name_len] = '\0';
65 Printk (("dir_once :%s: offset %Ld\n",zname,offset));
66 #endif 67 ret = d->filldir (d->dirbuf,name,name_len,offset,ino);
68 d->stop = ret < 0;
69 d->count = 1;
70 } 71 returnret;
72 } 73
74 /* 75 Read count directory entries from directory filp 76 Return a negative value from linux/errno.h. 77 Return > 0 if success (The amount of byte written by filldir). 78
79 This function is used by the normal readdir VFS entry point and by 80 some function who try to find out info on a file from a pure MSDOS 81 inode. See umsdos_locate_ancestor() below. 82 */ 83 staticintumsdos_readdir_x(
/* */ 84 structinode *dir, /* Point to a description of the super block */ 85 structfile *filp, /* Point to a directory which is read */ 86 void *dirbuf, /* Will hold count directory entry */ 87 /* but filled by the filldir function */ 88 intinternal_read, /* Called for internal purpose */ 89 structumsdos_dirent *u_entry, /* Optional umsdos entry */ 90 intfollow_hlink,
91 filldir_tfilldir)
92 { 93 intret = 0;
94
95 umsdos_startlookup(dir);
96 if (filp->f_pos == UMSDOS_SPECIAL_DIRFPOS 97 && dir == pseudo_root 98 && !internal_read){ 99 /* 100 We don't need to simulate this pseudo directory 101 when umsdos_readdir_x is called for internal operation 102 of umsdos. This is why dirent_in_fs is tested 103 */ 104 /* #Specification: pseudo root / directory /DOS 105 When umsdos operates in pseudo root mode (C:\linux is the 106 linux root), it simulate a directory /DOS which points to 107 the real root of the file system. 108 */ 109 if (filldir (dirbuf,"DOS",3,UMSDOS_SPECIAL_DIRFPOS 110 ,dir->i_sb->s_mounted->i_ino) == 0){ 111 filp->f_pos++;
112 } 113 }elseif (filp->f_pos < 2
114 || (dir != dir->i_sb->s_mounted && filp->f_pos == 32)){ 115 /* #Specification: readdir / . and .. 116 The msdos filesystem manage the . and .. entry properly 117 so the EMD file won't hold any info about it. 118
119 In readdir, we assume that for the root directory 120 the read position will be 0 for ".", 1 for "..". For 121 a non root directory, the read position will be 0 for "." 122 and 32 for "..". 123 */ 124 /* 125 This is a trick used by the msdos file system (fs/msdos/dir.c) 126 to manage . and .. for the root directory of a file system. 127 Since there is no such entry in the root, fs/msdos/dir.c 128 use the following: 129
130 if f_pos == 0, return ".". 131 if f_pos == 1, return "..". 132
133 So let msdos handle it 134
135 Since umsdos entries are much larger, we share the same f_pos. 136 if f_pos is 0 or 1 or 32, we are clearly looking at . and 137 .. 138
139 As soon as we get f_pos == 2 or f_pos == 64, then back to 140 0, but this time we are reading the EMD file. 141
142 Well, not so true. The problem, is that UMSDOS_REC_SIZE is 143 also 64, so as soon as we read the first record in the 144 EMD, we are back at offset 64. So we set the offset 145 to UMSDOS_SPECIAL_DIRFPOS(3) as soon as we have read the 146 .. entry from msdos. 147 148 Now (linux 1.3), umsdos_readdir can read more than one 149 entry even if we limit (umsdos_dir_once) to only one: 150 It skips over hidden file. So we switch to 151 UMSDOS_SPECIAL_DIRFPOS as soon as we have read successfully 152 the .. entry. 153 */ 154 intlast_f_pos = filp->f_pos;
155 structUMSDOS_DIR_ONCEbufk;
156 bufk.dirbuf = dirbuf;
157 bufk.filldir = filldir;
158 bufk.count = 0;
159 ret = msdos_readdir(dir,filp,&bufk,umsdos_dir_once);
160 if (last_f_pos > 0 && filp->f_pos > last_f_pos) filp->f_pos = UMSDOS_SPECIAL_DIRFPOS;
161 if (u_entry != NULL) u_entry->flags = 0;
162 }else{ 163 structinode *emd_dir = umsdos_emd_dir_lookup(dir,0);
164 if (emd_dir != NULL){ 165 off_tstart_fpos = filp->f_pos;
166 if (filp->f_pos <= UMSDOS_SPECIAL_DIRFPOS+1) filp->f_pos = 0;
167 PRINTK (("f_pos %lu i_size %ld\n",filp->f_pos,emd_dir->i_size));
168 ret = 0;
169 while (filp->f_pos < emd_dir->i_size){ 170 structumsdos_dirententry;
171 off_tcur_f_pos = filp->f_pos;
172 if (umsdos_emd_dir_readentry (emd_dir,filp,&entry)!=0){ 173 ret = -EIO;
174 break;
175 }elseif (entry.name_len != 0){ 176 /* #Specification: umsdos / readdir 177 umsdos_readdir() should fill a struct dirent with 178 an inode number. The cheap way to get it is to 179 do a lookup in the MSDOS directory for each 180 entry processed by the readdir() function. 181 This is not very efficient, but very simple. The 182 other way around is to maintain a copy of the inode 183 number in the EMD file. This is a problem because 184 this has to be maintained in sync using tricks. 185 Remember that MSDOS (the OS) does not update the 186 modification time (mtime) of a directory. There is 187 no easy way to tell that a directory was modified 188 during a DOS session and synchronise the EMD file. 189
190 Suggestion welcome. 191
192 So the easy way is used! 193 */ 194 structumsdos_infoinfo;
195 structinode *inode;
196 intlret;
197 umsdos_parse (entry.name,entry.name_len,&info);
198 info.f_pos = cur_f_pos;
199 umsdos_manglename (&info);
200 lret = umsdos_real_lookup (dir,info.fake.fname 201 ,info.fake.len,&inode);
202 PRINTK (("Cherche inode de %s lret %d flags %d\n"
203 ,info.fake.fname,lret,entry.flags));
204 if (lret == 0
205 && (entry.flags & UMSDOS_HLINK)
206 && follow_hlink){ 207 structinode *rinode;
208 lret = umsdos_hlink2inode (inode,&rinode);
209 inode = rinode;
210 } 211 if (lret == 0){ 212 /* #Specification: pseudo root / reading real root 213 The pseudo root (/linux) is logically 214 erased from the real root. This mean that 215 ls /DOS, won't show "linux". This avoids 216 infinite recursion /DOS/linux/DOS/linux while 217 walking the file system. 218 */ 219 if (inode != pseudo_root 220 && (internal_read 221 || !(entry.flags & UMSDOS_HIDDEN))){ 222 if (filldir (dirbuf 223 ,entry.name,entry.name_len 224 ,cur_f_pos, inode->i_ino) < 0){ 225 filp->f_pos = cur_f_pos;
226 } 227 PRINTK (("Trouve ino %ld ",inode->i_ino));
228 if (u_entry != NULL) *u_entry = entry;
229 iput (inode);
230 break;
231 } 232 iput (inode);
233 }else{ 234 /* #Specification: umsdos / readdir / not in MSDOS 235 During a readdir operation, if the file is not 236 in the MSDOS directory anymore, the entry is 237 removed from the EMD file silently. 238 */ 239 ret = umsdos_writeentry (dir,emd_dir,&info,1);
240 if (ret != 0){ 241 break;
242 } 243 } 244 } 245 } 246 /* 247 If the fillbuf has failed, f_pos is back to 0. 248 To avoid getting back into the . and .. state 249 (see comments at the beginning), we put back 250 the special offset. 251 */ 252 if (filp->f_pos == 0) filp->f_pos = start_fpos;
253 iput(emd_dir);
254 } 255 } 256 umsdos_endlookup(dir);
257 PRINTK (("read dir %p pos %Ld ret %d\n",dir,filp->f_pos,ret));
258 returnret;
259 } 260 /* 261 Read count directory entries from directory filp 262 Return a negative value from linux/errno.h. 263 Return > 0 if success (the amount of byte written to dirent) 264 */ 265 staticintUMSDOS_readdir(
/* */ 266 structinode *dir, /* Point to a description of the super block */ 267 structfile *filp, /* Point to a directory which is read */ 268 void *dirbuf, /* Will hold directory entries */ 269 filldir_tfilldir)
270 { 271 intret = 0;
272 intcount = 0;
273 structUMSDOS_DIR_ONCEbufk;
274 bufk.dirbuf = dirbuf;
275 bufk.filldir = filldir;
276 bufk.stop = 0;
277 PRINTK (("UMSDOS_readdir in\n"));
278 while (ret == 0 && bufk.stop == 0){ 279 structumsdos_dirententry;
280 bufk.count = 0;
281 ret = umsdos_readdir_x (dir,filp,&bufk,0,&entry,1,umsdos_dir_once);
282 if (bufk.count == 0) break;
283 count += bufk.count;
284 } 285 PRINTK (("UMSDOS_readdir out %d count %d pos %Ld\n",ret,count 286 ,filp->f_pos));
287 returncount == 0 ? -ENOENT : ret;
288 } 289 /* 290 Complete the inode content with info from the EMD file 291 */ 292 voidumsdos_lookup_patch (
/* */ 293 structinode *dir,
294 structinode *inode,
295 structumsdos_dirent *entry,
296 off_temd_pos)
297 { 298 /* 299 This function modify the state of a dir inode. It decides 300 if the dir is a umsdos dir or a dos dir. This is done 301 deeper in umsdos_patch_inode() called at the end of this function. 302
303 umsdos_patch_inode() may block because it is doing disk access. 304 At the same time, another process may get here to initialise 305 the same dir inode. There is 3 cases. 306
307 1-The inode is already initialised. We do nothing. 308 2-The inode is not initialised. We lock access and do it. 309 3-Like 2 but another process has lock the inode, so we try 310 to lock it and right after check if initialisation is still 311 needed. 312
313
314 Thanks to the mem option of the kernel command line, it was 315 possible to consistently reproduce this problem by limiting 316 my mem to 4 meg and running X. 317 */ 318 /* 319 Do this only if the inode is freshly read, because we will lose 320 the current (updated) content. 321 */ 322 /* 323 A lookup of a mount point directory yield the inode into 324 the other fs, so we don't care about initialising it. iget() 325 does this automatically. 326 */ 327 if (inode->i_sb == dir->i_sb && !umsdos_isinit(inode)){ 328 if (S_ISDIR(inode->i_mode)) umsdos_lockcreate(inode);
329 if (!umsdos_isinit(inode)){ 330 /* #Specification: umsdos / lookup / inode info 331 After successfully reading an inode from the MSDOS 332 filesystem, we use the EMD file to complete it. 333 We update the following field. 334
335 uid, gid, atime, ctime, mtime, mode. 336
337 We rely on MSDOS for mtime. If the file 338 was modified during an MSDOS session, at least 339 mtime will be meaningful. We do this only for regular 340 file. 341 342 We don't rely on MSDOS for mtime for directory because 343 the MSDOS directory date is creation time (strange 344 MSDOS behavior) which fit nowhere in the three UNIX 345 time stamp. 346 */ 347 if (S_ISREG(entry->mode)) entry->mtime = inode->i_mtime;
348 inode->i_mode = entry->mode;
349 inode->i_rdev = to_kdev_t(entry->rdev);
350 inode->i_atime = entry->atime;
351 inode->i_ctime = entry->ctime;
352 inode->i_mtime = entry->mtime;
353 inode->i_uid = entry->uid;
354 inode->i_gid = entry->gid;
355 /* #Specification: umsdos / conversion mode 356 The msdos fs can do some inline conversion 357 of the data of a file. It can translate 358 silently from MsDOS text file format to Unix 359 one (crlf -> lf) while reading, and the reverse 360 while writting. This is activated using the mount 361 option conv=.... 362
363 This is not useful for Linux file in promoted 364 directory. It can even be harmful. For this 365 reason, the binary (no conversion) mode is 366 always activated. 367 */ 368 /* #Specification: umsdos / conversion mode / todo 369 A flag could be added to file and directories 370 forcing an automatic conversion mode (as 371 done with the msdos fs). 372 373 This flag could be setup on a directory basis 374 (instead of file) and all file in it would 375 logically inherited. If the conversion mode 376 is active (conv=) then the i_binary flag would 377 be left untouched in those directories. 378 379 It was proposed that the sticky bit was used 380 to set this. The problem is that new file would 381 be written incorrectly. The other problem is that 382 the sticky bit has a meaning for directories. So 383 another bit should be used (there is some space 384 in the EMD file for it) and a special utilities 385 would be used to assign the flag to a directory). 386 I don't think it is useful to assign this flag 387 on a single file. 388 */ 389
390 MSDOS_I(inode)->i_binary = 1;
391 /* #Specification: umsdos / i_nlink 392 The nlink field of an inode is maintain by the MSDOS file system 393 for directory and by UMSDOS for other file. The logic is that 394 MSDOS is already figuring out what to do for directories and 395 does nothing for other files. For MSDOS, there are no hard link 396 so all file carry nlink==1. UMSDOS use some info in the 397 EMD file to plug the correct value. 398 */ 399 if (!S_ISDIR(entry->mode)){ 400 if (entry->nlink > 0){ 401 inode->i_nlink = entry->nlink;
402 }else{ 403 printk ("UMSDOS: lookup_patch entry->nlink < 1 ???\n");
404 } 405 } 406 umsdos_patch_inode(inode,dir,emd_pos);
407 } 408 if (S_ISDIR(inode->i_mode)) umsdos_unlockcreate(inode);
409 if (inode->u.umsdos_i.i_emd_owner==0) printk ("emd_owner still 0 ???\n");
410 } 411 } 412 structUMSDOS_DIRENT_K{ 413 off_tf_pos; /* will hold the offset of the entry in EMD */ 414 ino_tino;
415 };
416
417 /* 418 Just to record the offset of one entry. 419 */ 420 staticintumsdos_filldir_k(
/* */ 421 void * buf,
422 constchar * name,
423 intname_len,
424 off_toffset,
425 ino_tino)
426 { 427 structUMSDOS_DIRENT_K *d = (structUMSDOS_DIRENT_K *)buf;
428 d->f_pos = offset;
429 d->ino = ino;
430 return 0;
431 } 432
433 structUMSDOS_DIR_SEARCH{ 434 structumsdos_dirent *entry;
435 intfound;
436 ino_tsearch_ino;
437 };
438
439 staticintumsdos_dir_search (
/* */ 440 void * buf,
441 constchar * name,
442 intname_len,
443 off_toffset,
444 ino_tino)
445 { 446 intret = 0;
447 structUMSDOS_DIR_SEARCH *d = (structUMSDOS_DIR_SEARCH *)buf;
448 if (d->search_ino == ino){ 449 d->found = 1;
450 memcpy (d->entry->name,name,name_len);
451 d->entry->name[name_len] = '\0';
452 d->entry->name_len = name_len;
453 ret = 1; /* So msdos_readdir will terminate */ 454 } 455 returnret;
456 } 457
458
459 /* 460 Locate entry of an inode in a directory. 461 Return 0 or a negative error code. 462
463 Normally, this function must succeed. It means a strange corruption 464 in the file system if not. 465 */ 466 intumsdos_inode2entry (
/* */ 467 structinode *dir,
468 structinode *inode,
469 structumsdos_dirent *entry) /* Will hold the entry */ 470 { 471 intret = -ENOENT;
472 if (inode == pseudo_root){ 473 /* 474 Quick way to find the name. 475 Also umsdos_readdir_x won't show /linux anyway 476 */ 477 memcpy (entry->name,UMSDOS_PSDROOT_NAME,UMSDOS_PSDROOT_LEN+1);
478 entry->name_len = UMSDOS_PSDROOT_LEN;
479 ret = 0;
480 }else{ 481 structinode *emddir = umsdos_emd_dir_lookup(dir,0);
482 iput (emddir);
483 if (emddir == NULL){ 484 /* This is a DOS directory */ 485 structUMSDOS_DIR_SEARCHbufk;
486 structfilefilp;
487 filp.f_reada = 1;
488 filp.f_pos = 0;
489 bufk.entry = entry;
490 bufk.search_ino = inode->i_ino;
491 msdos_readdir (dir,&filp,&bufk,umsdos_dir_search);
492 if (bufk.found){ 493 ret = 0;
494 inode->u.umsdos_i.i_dir_owner = dir->i_ino;
495 inode->u.umsdos_i.i_emd_owner = 0;
496 umsdos_setup_dir_inode(inode);
497 } 498 }else{ 499 /* skip . and .. see umsdos_readdir_x() */ 500 structfilefilp;
501 filp.f_reada = 1;
502 filp.f_pos = UMSDOS_SPECIAL_DIRFPOS;
503 while (1){ 504 structUMSDOS_DIRENT_Kbufk;
505 if (umsdos_readdir_x(dir,&filp,&bufk 506 ,1,entry,0,umsdos_filldir_k) < 0){ 507 printk ("UMSDOS: can't locate inode %ld in EMD file???\n"
508 ,inode->i_ino);
509 break;
510 }elseif (bufk.ino == inode->i_ino){ 511 ret = 0;
512 umsdos_lookup_patch (dir,inode,entry,bufk.f_pos);
513 break;
514 } 515 } 516 } 517 } 518 returnret;
519 } 520 /* 521 Locate the parent of a directory and the info on that directory 522 Return 0 or a negative error code. 523 */ 524 staticintumsdos_locate_ancestor (
/* */ 525 structinode *dir,
526 structinode **result,
527 structumsdos_dirent *entry)
528 { 529 intret;
530 umsdos_patch_inode (dir,NULL,0);
531 ret = umsdos_real_lookup (dir,"..",2,result);
532 PRINTK (("result %d %p ",ret,*result));
533 if (ret == 0){ 534 structinode *adir = *result;
535 ret = umsdos_inode2entry (adir,dir,entry);
536 } 537 PRINTK (("\n"));
538 returnret;
539 } 540 /* 541 Build the path name of an inode (relative to the file system. 542 This function is need to set (pseudo) hard link. 543
544 It uses the same strategy as the standard getcwd(). 545 */ 546 intumsdos_locate_path (
/* */ 547 structinode *inode,
548 char *path)
549 { 550 intret = 0;
551 structinode *dir = inode;
552 char *bpath = (char*)kmalloc(PATH_MAX,GFP_KERNEL);
553 if (bpath == NULL){ 554 ret = -ENOMEM;
555 }else{ 556 structumsdos_dirententry;
557 char *ptbpath = bpath+PATH_MAX-1;
558 *ptbpath = '\0';
559 PRINTK (("locate_path mode %x ",inode->i_mode));
560 if (!S_ISDIR(inode->i_mode)){ 561 ret = umsdos_get_dirowner (inode,&dir);
562 PRINTK (("locate_path ret %d ",ret));
563 if (ret == 0){ 564 ret = umsdos_inode2entry (dir,inode,&entry);
565 if (ret == 0){ 566 ptbpath -= entry.name_len;
567 memcpy (ptbpath,entry.name,entry.name_len);
568 PRINTK (("ptbpath :%s: ",ptbpath));
569 } 570 } 571 }else{ 572 dir->i_count++;
573 } 574 if (ret == 0){ 575 while (dir != dir->i_sb->s_mounted){ 576 structinode *adir;
577 ret = umsdos_locate_ancestor (dir,&adir,&entry);
578 iput (dir);
579 dir = NULL;
580 PRINTK (("ancestor %d ",ret));
581 if (ret == 0){ 582 *--ptbpath = '/';
583 ptbpath -= entry.name_len;
584 memcpy (ptbpath,entry.name,entry.name_len);
585 dir = adir;
586 PRINTK (("ptbpath :%s: ",ptbpath));
587 }else{ 588 break;
589 } 590 } 591 } 592 strcpy (path,ptbpath);
593 kfree (bpath);
594 } 595 PRINTK (("\n"));
596 iput (dir);
597 returnret;
598 } 599
600 /* 601 Return != 0 if an entry is the pseudo DOS entry in the pseudo root. 602 */ 603 intumsdos_is_pseudodos (
/* */ 604 structinode *dir,
605 constchar *name,
606 intlen)
607 { 608 /* #Specification: pseudo root / DOS hard coded 609 The pseudo sub-directory DOS in the pseudo root is hard coded. 610 The name is DOS. This is done this way to help standardised 611 the umsdos layout. The idea is that from now on /DOS is 612 a reserved path and nobody will think of using such a path 613 for a package. 614 */ 615 returndir == pseudo_root 616 && len == 3
617 && name[0] == 'D' && name[1] == 'O' && name[2] == 'S';
618 } 619 /* 620 Check if a file exist in the current directory. 621 Return 0 if ok, negative error code if not (ex: -ENOENT). 622 */ 623 staticintumsdos_lookup_x (
/* */ 624 structinode *dir,
625 constchar *name,
626 intlen,
627 structinode **result, /* Will hold inode of the file, if successful */ 628 intnopseudo) /* Don't care about pseudo root mode */ 629 { 630 intret = -ENOENT;
631 *result = NULL;
632 umsdos_startlookup(dir);
633 if (len == 1 && name[0] == '.'){ 634 *result = dir;
635 dir->i_count++;
636 ret = 0;
637 }elseif (len == 2 && name[0] == '.' && name[1] == '.'){ 638 if (pseudo_root != NULL && dir == pseudo_root->i_sb->s_mounted){ 639 /* #Specification: pseudo root / .. in real root 640 Whenever a lookup is those in the real root for 641 the directory .., and pseudo root is active, the 642 pseudo root is returned. 643 */ 644 ret = 0;
645 *result = pseudo_root;
646 pseudo_root->i_count++;
647 }else{ 648 /* #Specification: locating .. / strategy 649 We use the msdos filesystem to locate the parent directory. 650 But it is more complicated than that. 651 652 We have to step back even further to 653 get the parent of the parent, so we can get the EMD 654 of the parent of the parent. Using the EMD file, we can 655 locate all the info on the parent, such a permissions 656 and owner. 657 */ 658 ret = umsdos_real_lookup (dir,"..",2,result);
659 PRINTK (("ancestor ret %d dir %p *result %p ",ret,dir,*result));
660 if (ret == 0
661 && *result != dir->i_sb->s_mounted 662 && *result != pseudo_root){ 663 structinode *aadir;
664 structumsdos_dirententry;
665 ret = umsdos_locate_ancestor (*result,&aadir,&entry);
666 iput (aadir);
667 } 668 } 669 }elseif (umsdos_is_pseudodos(dir,name,len)){ 670 /* #Specification: pseudo root / lookup(DOS) 671 A lookup of DOS in the pseudo root will always succeed 672 and return the inode of the real root. 673 */ 674 *result = dir->i_sb->s_mounted;
675 (*result)->i_count++;
676 ret = 0;
677 }else{ 678 structumsdos_infoinfo;
679 ret = umsdos_parse (name,len,&info);
680 if (ret == 0) ret = umsdos_findentry (dir,&info,0);
681 PRINTK (("lookup %s pos %lu ret %d len %d ",info.fake.fname,info.f_pos,ret 682 ,info.fake.len));
683 if (ret == 0){ 684 /* #Specification: umsdos / lookup 685 A lookup for a file is done in two step. First, we locate 686 the file in the EMD file. If not present, we return 687 an error code (-ENOENT). If it is there, we repeat the 688 operation on the msdos file system. If this fails, it means 689 that the file system is not in sync with the emd file. 690 We silently remove this entry from the emd file, 691 and return ENOENT. 692 */ 693 structinode *inode;
694 ret = umsdos_real_lookup (dir,info.fake.fname,info.fake.len,result);
695 inode = *result;
696 if (inode == NULL){ 697 printk ("UMSDOS: Erase entry %s, out of sync with MsDOS\n"
698 ,info.fake.fname);
699 umsdos_delentry (dir,&info,S_ISDIR(info.entry.mode));
700 }else{ 701 umsdos_lookup_patch (dir,inode,&info.entry,info.f_pos);
702 PRINTK (("lookup ino %ld flags %d\n",inode->i_ino 703 ,info.entry.flags));
704 if (info.entry.flags & UMSDOS_HLINK){ 705 ret = umsdos_hlink2inode (inode,result);
706 } 707 if (*result == pseudo_root && !nopseudo){ 708 /* #Specification: pseudo root / dir lookup 709 For the same reason as readdir, a lookup in /DOS for 710 the pseudo root directory (linux) will fail. 711 */ 712 /* 713 This has to be allowed for resolving hard link 714 which are recorded independently of the pseudo-root 715 mode. 716 */ 717 iput (pseudo_root);
718 *result = NULL;
719 ret = -ENOENT;
720 } 721 } 722 } 723 } 724 umsdos_endlookup(dir);
725 iput (dir);
726 returnret;
727 } 728 /* 729 Check if a file exist in the current directory. 730 Return 0 if ok, negative error code if not (ex: -ENOENT). 731 */ 732 intUMSDOS_lookup (
/* */ 733 structinode *dir,
734 constchar *name,
735 intlen,
736 structinode **result) /* Will hold inode of the file, if successful */ 737 { 738 returnumsdos_lookup_x(dir,name,len,result,0);
739 } 740 /* 741 Locate the inode pointed by a (pseudo) hard link 742 Return 0 if ok, a negative error code if not. 743 */ 744 intumsdos_hlink2inode (structinode *hlink, structinode **result)
/* */ 745 { 746 intret = -EIO;
747 char *path = (char*)kmalloc(PATH_MAX,GFP_KERNEL);
748 *result = NULL;
749 if (path == NULL){ 750 ret = -ENOMEM;
751 iput (hlink);
752 }else{ 753 structfilefilp;
754 filp.f_reada = 1;
755 filp.f_pos = 0;
756 PRINTK (("hlink2inode "));
757 if (umsdos_file_read_kmem (hlink,&filp,path,hlink->i_size)
758 ==hlink->i_size){ 759 structinode *dir;
760 char *pt = path;
761 dir = hlink->i_sb->s_mounted;
762 path[hlink->i_size] = '\0';
763 iput (hlink);
764 dir->i_count++;
765 while (1){ 766 char *start = pt;
767 intlen;
768 while (*pt != '\0' && *pt != '/') pt++;
769 len = (int)(pt - start);
770 if (*pt == '/') *pt++ = '\0';
771 if (dir->u.umsdos_i.i_emd_dir == 0){ 772 /* This is a DOS directory */ 773 ret = umsdos_rlookup_x(dir,start,len,result,1);
774 }else{ 775 ret = umsdos_lookup_x(dir,start,len,result,1);
776 } 777 PRINTK (("h2n lookup :%s: -> %d ",start,ret));
778 if (ret == 0 && *pt != '\0'){ 779 dir = *result;
780 }else{ 781 break;
782 } 783 } 784 }else{ 785 iput (hlink);
786 } 787 PRINTK (("hlink2inode ret = %d %p -> %p\n",ret,hlink,*result));
788 kfree (path);
789 } 790 returnret;
791 } 792
793 staticstructfile_operationsumsdos_dir_operations = { 794 NULL, /* lseek - default */ 795 UMSDOS_dir_read, /* read */ 796 NULL, /* write - bad */ 797 UMSDOS_readdir, /* readdir */ 798 NULL, /* select - default */ 799 UMSDOS_ioctl_dir, /* ioctl - default */ 800 NULL, /* mmap */ 801 NULL, /* no special open code */ 802 NULL, /* no special release code */ 803 NULL/* fsync */ 804 };
805
806 structinode_operationsumsdos_dir_inode_operations = { 807 &umsdos_dir_operations, /* default directory file-ops */ 808 UMSDOS_create, /* create */ 809 UMSDOS_lookup, /* lookup */ 810 UMSDOS_link, /* link */ 811 UMSDOS_unlink, /* unlink */ 812 UMSDOS_symlink, /* symlink */ 813 UMSDOS_mkdir, /* mkdir */ 814 UMSDOS_rmdir, /* rmdir */ 815 UMSDOS_mknod, /* mknod */ 816 UMSDOS_rename, /* rename */ 817 NULL, /* readlink */ 818 NULL, /* follow_link */ 819 NULL, /* bmap */ 820 NULL, /* truncate */ 821 NULL/* permission */ 822 };
823
824
825
826
827
828
829
830
831
832