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