2 * linux/fs/umsdos/dir.c
4 * Written 1993 by Jacques Gelinas
5 * Inspired from linux/fs/msdos/... : Werner Almesberger
7 * Extended MS-DOS directory handling functions
10 #include <linux/sched.h>
11 #include <linux/string.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>
20 #include <asm/uaccess.h>
23 #define Printk(x) printk x
25 #define UMSDOS_SPECIAL_DIRFPOS 3
26 extern struct inode
*pseudo_root
;
30 * I've retained this to facilitate the lookup of some of the hard-wired files/directories UMSDOS
31 * uses. It's easier to do once than hack all the other instances. Probably safer as well
34 /* FIXME: it returns inode with i_count of 0. this should be redesigned to return dentry instead,
35 and correct dentry (with correct d_parent) */
37 int compat_umsdos_real_lookup (struct inode
*dir
, const char *name
, int len
, struct inode
**inode
)
40 struct dentry
*dentry
;
43 Printk ((KERN_DEBUG
"compat_umsdos_real_lookup !!CNTx!!: start\n"));
45 dentry
= creat_dentry (name
, len
, NULL
, NULL
);
46 rv
= umsdos_real_lookup (dir
, dentry
);
47 iput (dir
); /* should be here, because umsdos_real_lookup does inc_count(dir) */
50 Printk ((KERN_WARNING
"compat_umsdos_real_lookup failed with %d\n", rv
));
55 Printk ((KERN_ERR
"inode should be set here. Arrgh! segfaulting...\n"));
58 ino
= dentry
->d_inode
->i_ino
;
59 *inode
= dentry
->d_inode
;
61 dput (dentry
); /* we are done with it: FIXME: does this work /mn/ ? */
63 check_dentry (dentry
);
66 Printk ((KERN_DEBUG
"compat_umsdos_real_lookup !!CNTx!!: end\n"));
72 int compat_msdos_create (struct inode
*dir
, const char *name
, int len
, int mode
, struct inode
**inode
)
75 struct dentry
*dentry
;
78 dentry
= creat_dentry (name
, len
, NULL
, NULL
);
79 check_dentry (dentry
);
80 rv
= msdos_create (dir
, dentry
, mode
);
81 check_dentry (dentry
);
83 *inode
= dentry
->d_inode
;
91 * So grep * doesn't complain in the presence of directories.
94 int UMSDOS_dir_read (struct file
*filp
, char *buff
, size_t size
, loff_t
*count
)
100 struct UMSDOS_DIR_ONCE
{
108 * Record a single entry the first call.
109 * Return -EINVAL the next one.
110 * NOTE: filldir DOES NOT use a dentry
113 static int umsdos_dir_once ( void *buf
,
120 struct UMSDOS_DIR_ONCE
*d
= (struct UMSDOS_DIR_ONCE
*) buf
;
123 PRINTK ((KERN_DEBUG
"dir_once :%.*s: offset %Ld\n", dentry
->d_len
, dentry
->d_name
, offset
));
124 ret
= d
->filldir (d
->dirbuf
, name
, len
, offset
, ino
);
133 * Read count directory entries from directory filp
134 * Return a negative value from linux/errno.h.
135 * Return > 0 if success (The amount of byte written by filldir).
137 * This function is used by the normal readdir VFS entry point and by
138 * some function who try to find out info on a file from a pure MSDOS
139 * inode. See umsdos_locate_ancestor() below.
142 static int umsdos_readdir_x (
143 struct inode
*dir
, /* Point to a description of the super block */
144 struct file
*filp
, /* Point to a directory which is read */
145 void *dirbuf
, /* Will hold count directory entry */
146 /* but filled by the filldir function */
147 int internal_read
, /* Called for internal purpose */
148 struct umsdos_dirent
*u_entry
, /* Optional umsdos entry */
154 umsdos_startlookup (dir
);
155 if (filp
->f_pos
== UMSDOS_SPECIAL_DIRFPOS
157 && dir
== pseudo_root
160 Printk (("umsdos_readdir_x: what UMSDOS_SPECIAL_DIRFPOS /mn/?\n"));
162 * We don't need to simulate this pseudo directory
163 * when umsdos_readdir_x is called for internal operation
164 * of umsdos. This is why dirent_in_fs is tested
166 /* #Specification: pseudo root / directory /DOS
167 * When umsdos operates in pseudo root mode (C:\linux is the
168 * linux root), it simulate a directory /DOS which points to
169 * the real root of the file system.
171 if (filldir (dirbuf
, "DOS", 3, UMSDOS_SPECIAL_DIRFPOS
, UMSDOS_ROOT_INO
) == 0) {
174 } else if (filp
->f_pos
< 2 || (dir
->i_ino
!= UMSDOS_ROOT_INO
&& filp
->f_pos
== 32)) {
176 /* FIXME: that was in 2.0.x: else if (filp->f_pos < 2 || (dir != dir->i_sb->s_mounted && filp->f_pos == 32))
177 * I'm probably screwing up pseudo-root and stuff with this. It needs proper fix.
181 /* #Specification: readdir / . and ..
182 * The msdos filesystem manage the . and .. entry properly
183 * so the EMD file won't hold any info about it.
185 * In readdir, we assume that for the root directory
186 * the read position will be 0 for ".", 1 for "..". For
187 * a non root directory, the read position will be 0 for "."
191 * This is a trick used by the msdos file system (fs/msdos/dir.c)
192 * to manage . and .. for the root directory of a file system.
193 * Since there is no such entry in the root, fs/msdos/dir.c
196 * if f_pos == 0, return ".".
197 * if f_pos == 1, return "..".
199 * So let msdos handle it
201 * Since umsdos entries are much larger, we share the same f_pos.
202 * if f_pos is 0 or 1 or 32, we are clearly looking at . and
205 * As soon as we get f_pos == 2 or f_pos == 64, then back to
206 * 0, but this time we are reading the EMD file.
208 * Well, not so true. The problem, is that UMSDOS_REC_SIZE is
209 * also 64, so as soon as we read the first record in the
210 * EMD, we are back at offset 64. So we set the offset
211 * to UMSDOS_SPECIAL_DIRFPOS(3) as soon as we have read the
212 * .. entry from msdos.
214 * Now (linux 1.3), umsdos_readdir can read more than one
215 * entry even if we limit (umsdos_dir_once) to only one:
216 * It skips over hidden file. So we switch to
217 * UMSDOS_SPECIAL_DIRFPOS as soon as we have read successfully
220 int last_f_pos
= filp
->f_pos
;
221 struct UMSDOS_DIR_ONCE bufk
;
223 Printk (("umsdos_readdir_x: . or .. /mn/?\n"));
225 bufk
.dirbuf
= dirbuf
;
226 bufk
.filldir
= filldir
;
229 ret
= fat_readdir (filp
, &bufk
, umsdos_dir_once
);
230 if (last_f_pos
> 0 && filp
->f_pos
> last_f_pos
)
231 filp
->f_pos
= UMSDOS_SPECIAL_DIRFPOS
;
235 struct inode
*emd_dir
;
237 Printk (("umsdos_readdir_x: normal file /mn/?\n"));
238 emd_dir
= umsdos_emd_dir_lookup (dir
, 0);
239 if (emd_dir
!= NULL
) {
240 off_t start_fpos
= filp
->f_pos
;
242 Printk (("umsdos_readdir_x: emd_dir->i_ino=%ld\n", emd_dir
->i_ino
));
243 if (filp
->f_pos
<= UMSDOS_SPECIAL_DIRFPOS
+ 1)
245 Printk (("f_pos %Ld i_size %ld\n", filp
->f_pos
, emd_dir
->i_size
));
247 while (filp
->f_pos
< emd_dir
->i_size
) {
248 struct umsdos_dirent entry
;
249 off_t cur_f_pos
= filp
->f_pos
;
251 if (umsdos_emd_dir_readentry (emd_dir
, filp
, &entry
) != 0) {
254 } else if (entry
.name_len
!= 0) {
255 /* #Specification: umsdos / readdir
256 * umsdos_readdir() should fill a struct dirent with
257 * an inode number. The cheap way to get it is to
258 * do a lookup in the MSDOS directory for each
259 * entry processed by the readdir() function.
260 * This is not very efficient, but very simple. The
261 * other way around is to maintain a copy of the inode
262 * number in the EMD file. This is a problem because
263 * this has to be maintained in sync using tricks.
264 * Remember that MSDOS (the OS) does not update the
265 * modification time (mtime) of a directory. There is
266 * no easy way to tell that a directory was modified
267 * during a DOS session and synchronise the EMD file.
269 * Suggestion welcome.
271 * So the easy way is used!
273 struct umsdos_info info
;
278 umsdos_parse (entry
.name
, entry
.name_len
, &info
);
279 info
.f_pos
= cur_f_pos
;
280 umsdos_manglename (&info
);
281 lret
= compat_umsdos_real_lookup (dir
, info
.fake
.fname
, info
.fake
.len
, &inode
);
282 Printk (("Cherche inode de %s lret %d flags %d\n", info
.fake
.fname
, lret
, entry
.flags
));
284 && (entry
.flags
& UMSDOS_HLINK
)
286 struct inode
*rinode
;
288 Printk ((KERN_DEBUG
"umsdos_hlink2inode now\n"));
289 lret
= umsdos_hlink2inode (inode
, &rinode
);
293 /* #Specification: pseudo root / reading real root
294 * The pseudo root (/linux) is logically
295 * erased from the real root. This mean that
296 * ls /DOS, won't show "linux". This avoids
297 * infinite recursion /DOS/linux/DOS/linux while
298 * walking the file system.
300 if (inode
!= pseudo_root
302 || !(entry
.flags
& UMSDOS_HIDDEN
))) {
303 Printk ((KERN_DEBUG
"filldir now\n"));
304 if (filldir (dirbuf
, entry
.name
, entry
.name_len
, cur_f_pos
, inode
->i_ino
) < 0) {
305 filp
->f_pos
= cur_f_pos
;
307 Printk (("Trouve ino %ld ", inode
->i_ino
));
310 iput (inode
); /* FIXME? */
313 Printk ((KERN_DEBUG
" dir.c:Putting inode %lu with i_count=%d\n", inode
->i_ino
, inode
->i_count
));
314 iput (inode
); /* FIXME? */
316 /* #Specification: umsdos / readdir / not in MSDOS
317 * During a readdir operation, if the file is not
318 * in the MSDOS directory anymore, the entry is
319 * removed from the EMD file silently.
321 Printk (("'Silently' removing EMD for file\n"));
322 ret
= umsdos_writeentry (dir
, emd_dir
, &info
, 1);
330 * If the fillbuf has failed, f_pos is back to 0.
331 * To avoid getting back into the . and .. state
332 * (see comments at the beginning), we put back
333 * the special offset.
335 if (filp
->f_pos
== 0)
336 filp
->f_pos
= start_fpos
;
337 Printk ((KERN_DEBUG
" dir.c:Putting emd_dir %lu with i_count=%d\n", emd_dir
->i_ino
, emd_dir
->i_count
));
338 iput (emd_dir
); /* FIXME? */
341 umsdos_endlookup (dir
);
343 Printk (("read dir %p pos %Ld ret %d\n", dir
, filp
->f_pos
, ret
));
349 * Read count directory entries from directory filp
350 * Return a negative value from linux/errno.h.
351 * Return 0 or positive if successful
354 static int UMSDOS_readdir (
355 struct file
*filp
, /* Point to a directory which is read */
356 void *dirbuf
, /* Will hold directory entries */
359 struct inode
*dir
= filp
->f_dentry
->d_inode
;
362 struct UMSDOS_DIR_ONCE bufk
;
364 bufk
.dirbuf
= dirbuf
;
365 bufk
.filldir
= filldir
;
368 Printk (("UMSDOS_readdir in\n"));
369 while (ret
== 0 && bufk
.stop
== 0) {
370 struct umsdos_dirent entry
;
373 Printk (("UMSDOS_readdir: calling _x (%p,%p,%p,%d,%p,%d,%p)\n", dir
, filp
, &bufk
, 0, &entry
, 1, umsdos_dir_once
));
374 ret
= umsdos_readdir_x (dir
, filp
, &bufk
, 0, &entry
, 1, umsdos_dir_once
);
379 Printk (("UMSDOS_readdir out %d count %d pos %Ld\n", ret
, count
, filp
->f_pos
));
380 return count
? : ret
;
385 * Complete the inode content with info from the EMD file
388 void umsdos_lookup_patch (
391 struct umsdos_dirent
*entry
,
395 * This function modify the state of a dir inode. It decides
396 * if the dir is a umsdos dir or a dos dir. This is done
397 * deeper in umsdos_patch_inode() called at the end of this function.
399 * umsdos_patch_inode() may block because it is doing disk access.
400 * At the same time, another process may get here to initialise
401 * the same dir inode. There is 3 cases.
403 * 1-The inode is already initialised. We do nothing.
404 * 2-The inode is not initialised. We lock access and do it.
405 * 3-Like 2 but another process has lock the inode, so we try
406 * to lock it and right after check if initialisation is still
410 * Thanks to the mem option of the kernel command line, it was
411 * possible to consistently reproduce this problem by limiting
412 * my mem to 4 meg and running X.
415 * Do this only if the inode is freshly read, because we will lose
416 * the current (updated) content.
419 * A lookup of a mount point directory yield the inode into
420 * the other fs, so we don't care about initialising it. iget()
421 * does this automatically.
424 if (inode
->i_sb
== dir
->i_sb
&& !umsdos_isinit (inode
)) {
425 if (S_ISDIR (inode
->i_mode
))
426 umsdos_lockcreate (inode
);
427 if (!umsdos_isinit (inode
)) {
428 /* #Specification: umsdos / lookup / inode info
429 * After successfully reading an inode from the MSDOS
430 * filesystem, we use the EMD file to complete it.
431 * We update the following field.
433 * uid, gid, atime, ctime, mtime, mode.
435 * We rely on MSDOS for mtime. If the file
436 * was modified during an MSDOS session, at least
437 * mtime will be meaningful. We do this only for regular
440 * We don't rely on MSDOS for mtime for directory because
441 * the MSDOS directory date is creation time (strange
442 * MSDOS behavior) which fit nowhere in the three UNIX
445 if (S_ISREG (entry
->mode
))
446 entry
->mtime
= inode
->i_mtime
;
447 inode
->i_mode
= entry
->mode
;
448 inode
->i_rdev
= to_kdev_t (entry
->rdev
);
449 inode
->i_atime
= entry
->atime
;
450 inode
->i_ctime
= entry
->ctime
;
451 inode
->i_mtime
= entry
->mtime
;
452 inode
->i_uid
= entry
->uid
;
453 inode
->i_gid
= entry
->gid
;
454 /* #Specification: umsdos / conversion mode
455 * The msdos fs can do some inline conversion
456 * of the data of a file. It can translate
457 * silently from MsDOS text file format to Unix
458 * one (crlf -> lf) while reading, and the reverse
459 * while writing. This is activated using the mount
462 * This is not useful for Linux file in promoted
463 * directory. It can even be harmful. For this
464 * reason, the binary (no conversion) mode is
467 /* #Specification: umsdos / conversion mode / todo
468 * A flag could be added to file and directories
469 * forcing an automatic conversion mode (as
470 * done with the msdos fs).
472 * This flag could be setup on a directory basis
473 * (instead of file) and all file in it would
474 * logically inherited. If the conversion mode
475 * is active (conv=) then the i_binary flag would
476 * be left untouched in those directories.
478 * It was proposed that the sticky bit was used
479 * to set this. The problem is that new file would
480 * be written incorrectly. The other problem is that
481 * the sticky bit has a meaning for directories. So
482 * another bit should be used (there is some space
483 * in the EMD file for it) and a special utilities
484 * would be used to assign the flag to a directory).
485 * I don't think it is useful to assign this flag
489 MSDOS_I (inode
)->i_binary
= 1;
490 /* #Specification: umsdos / i_nlink
491 * The nlink field of an inode is maintain by the MSDOS file system
492 * for directory and by UMSDOS for other file. The logic is that
493 * MSDOS is already figuring out what to do for directories and
494 * does nothing for other files. For MSDOS, there are no hard link
495 * so all file carry nlink==1. UMSDOS use some info in the
496 * EMD file to plug the correct value.
498 if (!S_ISDIR (entry
->mode
)) {
499 if (entry
->nlink
> 0) {
500 inode
->i_nlink
= entry
->nlink
;
502 printk (KERN_ERR
"UMSDOS: lookup_patch entry->nlink < 1 ???\n");
505 umsdos_patch_inode (inode
, dir
, emd_pos
);
507 if (S_ISDIR (inode
->i_mode
))
508 umsdos_unlockcreate (inode
);
509 if (inode
->u
.umsdos_i
.i_emd_owner
== 0)
510 printk (KERN_WARNING
"emd_owner still 0 ???\n");
516 struct UMSDOS_DIRENT_K
{
517 off_t f_pos
; /* will hold the offset of the entry in EMD */
523 * Just to record the offset of one entry.
526 static int umsdos_filldir_k (
533 struct UMSDOS_DIRENT_K
*d
= (struct UMSDOS_DIRENT_K
*) buf
;
540 struct UMSDOS_DIR_SEARCH
{
541 struct umsdos_dirent
*entry
;
546 static int umsdos_dir_search (
554 struct UMSDOS_DIR_SEARCH
*d
= (struct UMSDOS_DIR_SEARCH
*) buf
;
556 if (d
->search_ino
== ino
) {
558 memcpy (d
->entry
->name
, name
, len
);
559 d
->entry
->name
[len
] = '\0';
560 d
->entry
->name_len
= len
;
561 ret
= 1; /* So fat_readdir will terminate */
569 * Locate entry of an inode in a directory.
570 * Return 0 or a negative error code.
572 * Normally, this function must succeed. It means a strange corruption
573 * in the file system if not.
576 int umsdos_inode2entry (
579 struct umsdos_dirent
*entry
)
580 { /* Will hold the entry */
583 if (pseudo_root
&& inode
== pseudo_root
) {
585 * Quick way to find the name.
586 * Also umsdos_readdir_x won't show /linux anyway
588 memcpy (entry
->name
, UMSDOS_PSDROOT_NAME
, UMSDOS_PSDROOT_LEN
+ 1);
589 entry
->name_len
= UMSDOS_PSDROOT_LEN
;
592 struct inode
*emddir
= umsdos_emd_dir_lookup (dir
, 0);
594 iput (emddir
); /* FIXME? */
595 if (emddir
== NULL
) {
596 /* This is a DOS directory */
597 struct UMSDOS_DIR_SEARCH bufk
;
601 i2e
= creat_dentry ("i2e.nul", 7, dir
, NULL
);
603 fill_new_filp (&filp
, i2e
);
605 Printk ((KERN_ERR
"umsdos_inode2entry emddir==NULL: WARNING: Known filp problem. segfaulting :) fixed ?/mn/\n"));
609 bufk
.search_ino
= inode
->i_ino
;
610 fat_readdir (&filp
, &bufk
, umsdos_dir_search
);
613 inode
->u
.umsdos_i
.i_dir_owner
= dir
->i_ino
;
614 inode
->u
.umsdos_i
.i_emd_owner
= 0;
615 umsdos_setup_dir_inode (inode
);
618 /* skip . and .. see umsdos_readdir_x() */
622 i2e
= creat_dentry ("i2e.nn", 6, dir
, NULL
);
623 fill_new_filp (&filp
, i2e
);
626 filp
.f_pos
= UMSDOS_SPECIAL_DIRFPOS
;
627 Printk ((KERN_ERR
"umsdos_inode2entry skip...: WARNING: Known filp problem. segfaulting :) fixed ?/mn/\n"));
629 struct UMSDOS_DIRENT_K bufk
;
631 if (umsdos_readdir_x (dir
, &filp
, &bufk
632 ,1, entry
, 0, umsdos_filldir_k
) < 0) {
633 printk ("UMSDOS: can't locate inode %ld in EMD file???\n"
636 } else if (bufk
.ino
== inode
->i_ino
) {
638 umsdos_lookup_patch (dir
, inode
, entry
, bufk
.f_pos
);
649 * Locate the parent of a directory and the info on that directory
650 * Return 0 or a negative error code.
653 static int umsdos_locate_ancestor (
655 struct inode
**result
,
656 struct umsdos_dirent
*entry
)
660 umsdos_patch_inode (dir
, NULL
, 0);
662 ret
= compat_umsdos_real_lookup (dir
, "..", 2, result
);
663 Printk (("result %d %p ", ret
, *result
));
665 struct inode
*adir
= *result
;
667 ret
= umsdos_inode2entry (adir
, dir
, entry
);
675 * Build the path name of an inode (relative to the file system.
676 * This function is need to set (pseudo) hard link.
678 * It uses the same strategy as the standard getcwd().
681 int umsdos_locate_path (
686 struct inode
*dir
= inode
;
687 struct inode
*root_inode
;
688 char *bpath
= (char *) kmalloc (PATH_MAX
, GFP_KERNEL
);
690 root_inode
= iget (inode
->i_sb
, UMSDOS_ROOT_INO
);
694 struct umsdos_dirent entry
;
695 char *ptbpath
= bpath
+ PATH_MAX
- 1;
698 Printk (("locate_path mode %x ", inode
->i_mode
));
699 if (!S_ISDIR (inode
->i_mode
)) {
700 ret
= umsdos_get_dirowner (inode
, &dir
);
701 Printk (("locate_path ret %d ", ret
));
703 ret
= umsdos_inode2entry (dir
, inode
, &entry
);
705 ptbpath
-= entry
.name_len
;
706 memcpy (ptbpath
, entry
.name
, entry
.name_len
);
707 Printk (("ptbpath :%.*s: ", entry
.name_len
, ptbpath
));
714 while (dir
!= root_inode
) {
717 ret
= umsdos_locate_ancestor (dir
, &adir
, &entry
);
718 /* iput (dir); FIXME */
720 Printk (("ancestor %d ", ret
));
723 ptbpath
-= entry
.name_len
;
724 memcpy (ptbpath
, entry
.name
, entry
.name_len
);
726 Printk (("ptbpath :%.*s: ", entry
.name_len
, ptbpath
));
732 strcpy (path
, ptbpath
);
736 iput (dir
); /* FIXME?? */
742 * Return != 0 if an entry is the pseudo DOS entry in the pseudo root.
745 int umsdos_is_pseudodos (
747 struct dentry
*dentry
)
749 /* #Specification: pseudo root / DOS hard coded
750 * The pseudo sub-directory DOS in the pseudo root is hard coded.
751 * The name is DOS. This is done this way to help standardised
752 * the umsdos layout. The idea is that from now on /DOS is
753 * a reserved path and nobody will think of using such a path
757 && dir
== pseudo_root
758 && dentry
->d_name
.len
== 3
759 && dentry
->d_name
.name
[0] == 'D'
760 && dentry
->d_name
.name
[1] == 'O'
761 && dentry
->d_name
.name
[2] == 'S';
766 * Check if a file exist in the current directory.
767 * Return 0 if ok, negative error code if not (ex: -ENOENT).
770 int umsdos_lookup_x (
772 struct dentry
*dentry
,
774 { /* Don't care about pseudo root mode */
776 struct inode
*root_inode
;
777 int len
= dentry
->d_name
.len
;
778 const char *name
= dentry
->d_name
.name
;
780 PRINTK ((KERN_DEBUG
"umsdos_lookup_x: /mn/ name=%.*s, dir=%lu (i_count=%d), d_parent=%p\n", (int) dentry
->d_name
.len
, dentry
->d_name
.name
, dir
->i_ino
, dir
->i_count
, dentry
->d_parent
)); /* FIXME /mn/ debug only */
781 if (dentry
->d_parent
)
782 PRINTK ((KERN_DEBUG
" d_parent is %.*s\n", (int) dentry
->d_parent
->d_name
.len
, dentry
->d_parent
->d_name
.name
)); /* FIXME : delme /mn/ */
784 root_inode
= iget (dir
->i_sb
, UMSDOS_ROOT_INO
);
785 Printk ((KERN_ERR
"umsdos_lookup_x (CNT!): entering root_count=%d, dir %lu _count=%d\n", root_inode
->i_count
, dir
->i_ino
, dir
->i_count
)); /* FIXME: DEBUG, DELME */
787 d_instantiate (dentry
, NULL
);
788 umsdos_startlookup (dir
);
789 if (len
== 1 && name
[0] == '.') {
793 } else if (len
== 2 && name
[0] == '.' && name
[1] == '.') {
794 if (pseudo_root
&& dir
== pseudo_root
) {
795 /* #Specification: pseudo root / .. in real root
796 * Whenever a lookup is those in the real root for
797 * the directory .., and pseudo root is active, the
798 * pseudo root is returned.
801 d_add (dentry
, pseudo_root
);
802 inc_count (pseudo_root
);
804 /* #Specification: locating .. / strategy
805 * We use the msdos filesystem to locate the parent directory.
806 * But it is more complicated than that.
808 * We have to step back even further to
809 * get the parent of the parent, so we can get the EMD
810 * of the parent of the parent. Using the EMD file, we can
811 * locate all the info on the parent, such a permissions
815 ret
= compat_umsdos_real_lookup (dir
, "..", 2, &dentry
->d_inode
);
816 Printk (("ancestor ret %d dir %p *result %p ", ret
, dir
, dentry
->d_inode
));
818 && dentry
->d_inode
!= root_inode
819 && dentry
->d_inode
!= pseudo_root
) {
821 struct umsdos_dirent entry
;
823 ret
= umsdos_locate_ancestor (dentry
->d_inode
, &aadir
, &entry
);
824 iput (aadir
); /* FIXME */
827 } else if (umsdos_is_pseudodos (dir
, dentry
)) {
828 /* #Specification: pseudo root / lookup(DOS)
829 * A lookup of DOS in the pseudo root will always succeed
830 * and return the inode of the real root.
832 d_add (dentry
, root_inode
);
833 inc_count (dentry
->d_inode
);
836 struct umsdos_info info
;
838 ret
= umsdos_parse (dentry
->d_name
.name
, dentry
->d_name
.len
, &info
);
840 ret
= umsdos_findentry (dir
, &info
, 0);
841 Printk (("lookup %.*s pos %lu ret %d len %d ", info
.fake
.len
, info
.fake
.fname
, info
.f_pos
, ret
844 /* #Specification: umsdos / lookup
845 * A lookup for a file is done in two step. First, we locate
846 * the file in the EMD file. If not present, we return
847 * an error code (-ENOENT). If it is there, we repeat the
848 * operation on the msdos file system. If this fails, it means
849 * that the file system is not in sync with the emd file.
850 * We silently remove this entry from the emd file,
855 ret
= compat_umsdos_real_lookup (dir
, info
.fake
.fname
, info
.fake
.len
, &inode
);
857 Printk ((KERN_DEBUG
"umsdos_lookup_x: compat_umsdos_real_lookup for %.*s returned %d with inode=%p\n", info
.fake
.len
, info
.fake
.fname
, ret
, inode
));
860 printk (KERN_WARNING
"UMSDOS: Erase entry %.*s, out of sync with MsDOS\n"
861 ,info
.fake
.len
, info
.fake
.fname
);
862 umsdos_delentry (dir
, &info
, S_ISDIR (info
.entry
.mode
));
864 Printk ((KERN_DEBUG
"umsdos_lookup_x /mn/ debug: ino=%li\n", inode
->i_ino
));
866 /* we've found it. now put inode in dentry */
867 d_add (dentry
, inode
);
869 umsdos_lookup_patch (dir
, inode
, &info
.entry
, info
.f_pos
);
870 Printk (("lookup ino %ld flags %d\n", inode
->i_ino
, info
.entry
.flags
));
871 if (info
.entry
.flags
& UMSDOS_HLINK
) {
872 Printk ((KERN_DEBUG
"umsdos_lookup_x: here goes HLINK\n"));
873 ret
= umsdos_hlink2inode (inode
, &dentry
->d_inode
);
875 if (pseudo_root
&& dentry
->d_inode
== pseudo_root
&& !nopseudo
) {
876 /* #Specification: pseudo root / dir lookup
877 * For the same reason as readdir, a lookup in /DOS for
878 * the pseudo root directory (linux) will fail.
881 * This has to be allowed for resolving hard link
882 * which are recorded independently of the pseudo-root
885 Printk ((KERN_ERR
"umsdos_lookup_x: warning: untested /mn/ Pseudo_root thingy\n"));
886 iput (pseudo_root
); /* FIXME?? */
887 d_instantiate (dentry
, NULL
); /* FIXME: should be dput(dentry) ? */
893 umsdos_endlookup (dir
);
894 PRINTK ((KERN_DEBUG
"umsdos_lookup_x: returning %d : name=%.*s (i_count=%d), dir=%lu (i_count=%d)\n", ret
, (int) dentry
->d_name
.len
, dentry
->d_name
.name
, dentry
->d_inode
->i_count
, dir
->i_ino
, dir
->i_count
));
895 Printk ((KERN_ERR
"umsdos_lookup_x (CNT!): exiting root_count=%d, dir %lu _count=%d\n", root_inode
->i_count
, dir
->i_ino
, dir
->i_count
)); /* FIXME: DEBUG, DELME */
901 * Check if a file exist in the current directory.
902 * Return 0 if ok, negative error code if not (ex: -ENOENT).
909 struct dentry
*dentry
)
913 check_dentry (dentry
);
914 ret
= umsdos_lookup_x (dir
, dentry
, 0);
915 check_dentry (dentry
);
918 if (ret
== -ENOENT
) {
919 Printk ((KERN_DEBUG
"UMSDOS_lookup: converting -ENOENT to negative dentry !\n"));
920 d_add (dentry
, NULL
); /* create negative dentry if not found */
931 * Locate the inode pointed by a (pseudo) hard link
932 * Return 0 if ok, a negative error code if not.
935 int umsdos_hlink2inode (struct inode
*hlink
, struct inode
**result
)
937 struct inode
*root_inode
;
939 struct dentry
*dentry_src
, *dentry_dst
;
942 #if 0 /* FIXME: DELME */
943 Printk (("FIXME: just test. hlink2inode returning -ENOENT\n /mn/\n"));
944 return -ENOENT
; /* /mn/ FIXME just for test */
947 path
= (char *) kmalloc (PATH_MAX
, GFP_KERNEL
);
949 root_inode
= iget (hlink
->i_sb
, UMSDOS_ROOT_INO
);
953 iput (hlink
); /* FIXME? */
958 dentry_src
= creat_dentry ("hlink-mn", 8, hlink
, NULL
);
960 fill_new_filp (&filp
, dentry_src
);
961 filp
.f_flags
= O_RDONLY
;
963 Printk (("hlink2inode "));
964 if (umsdos_file_read_kmem (hlink
, &filp
, path
, hlink
->i_size
, &offs
) == hlink
->i_size
) {
969 path
[hlink
->i_size
] = '\0';
970 iput (hlink
); /* FIXME? */
976 while (*pt
!= '\0' && *pt
!= '/')
978 len
= (int) (pt
- start
);
981 /* FIXME. /mn/ fixed ? */
983 dentry_dst
= creat_dentry (start
, len
, NULL
, NULL
);
985 if (dir
->u
.umsdos_i
.i_emd_dir
== 0) {
986 /* This is a DOS directory */
988 Printk (("hlink2inode /mn/: doing umsdos_rlookup_x on %.*s\n", (int) dentry_dst
->d_name
.len
, dentry_dst
->d_name
.name
));
989 ret
= umsdos_rlookup_x (dir
, dentry_dst
, 1);
991 Printk (("hlink2inode /mn/: doing umsdos_lookup_x on %.*s\n", (int) dentry_dst
->d_name
.len
, dentry_dst
->d_name
.name
));
992 ret
= umsdos_lookup_x (dir
, dentry_dst
, 1);
994 Printk ((" returned %d\n", ret
));
995 *result
= dentry_dst
->d_inode
; /* /mn/ ok ? */
997 Printk (("h2n lookup :%s: -> %d ", start
, ret
));
998 if (ret
== 0 && *pt
!= '\0') {
1005 Printk (("umsdos_hlink2inode: all those iput's() frighten me /mn/. Whatabout dput() ? FIXME!\n"));
1006 iput (hlink
); /* FIXME? */
1008 Printk (("hlink2inode ret = %d %p -> %p\n", ret
, hlink
, *result
));
1015 static struct file_operations umsdos_dir_operations
=
1017 NULL
, /* lseek - default */
1018 UMSDOS_dir_read
, /* read */
1019 NULL
, /* write - bad */
1020 UMSDOS_readdir
, /* readdir */
1021 NULL
, /* poll - default */
1022 UMSDOS_ioctl_dir
, /* ioctl - default */
1024 NULL
, /* no special open code */
1026 NULL
, /* no special release code */
1027 NULL
/* fsync *//* in original NULL. changed to file_fsync. FIXME? /mn/ */
1030 struct inode_operations umsdos_dir_inode_operations
=
1032 &umsdos_dir_operations
, /* default directory file-ops */
1033 UMSDOS_create
, /* create */
1034 UMSDOS_lookup
, /* lookup */
1035 UMSDOS_link
, /* link */
1036 UMSDOS_unlink
, /* unlink */
1037 UMSDOS_symlink
, /* symlink */
1038 UMSDOS_mkdir
, /* mkdir */
1039 UMSDOS_rmdir
, /* rmdir */
1040 UMSDOS_mknod
, /* mknod */
1041 UMSDOS_rename
, /* rename */
1042 NULL
, /* readlink */
1043 NULL
, /* followlink */
1044 generic_readpage
, /* readpage *//* in original NULL. changed to generic_readpage. FIXME? /mn/ */
1045 NULL
, /* writepage */
1046 fat_bmap
, /* bmap *//* in original NULL. changed to fat_bmap. FIXME? /mn/ */
1047 NULL
, /* truncate */
1048 NULL
, /* permission */
1050 NULL
, /* updatepage */
1051 NULL
, /* revalidate */