patch-2.1.120 linux/fs/umsdos/dir.c
Next file: linux/fs/umsdos/emd.c
Previous file: linux/fs/umsdos/check.c
Back to the patch index
Back to the overall index
- Lines: 962
- Date:
Wed Sep 2 16:12:37 1998
- Orig file:
v2.1.119/linux/fs/umsdos/dir.c
- Orig date:
Wed Aug 26 11:37:43 1998
diff -u --recursive --new-file v2.1.119/linux/fs/umsdos/dir.c linux/fs/umsdos/dir.c
@@ -19,9 +19,6 @@
#include <asm/uaccess.h>
-#define PRINTK(x)
-#define Printk(x) printk x
-
#define UMSDOS_SPECIAL_DIRFPOS 3
extern struct inode *pseudo_root;
@@ -30,55 +27,56 @@
* I've retained this to facilitate the lookup of some of the hard-wired files/directories UMSDOS
* uses. It's easier to do once than hack all the other instances. Probably safer as well
*/
+
+/*
+ * d_dir is directory to search for file, name&len define the file.
+ * compat_umsdos_real_lookup returns dentry pointing to wanted file,
+ * or NULL if not found. Calling code is respondible to call fin_dentry (result)
+ */
-/* FIXME: it returns inode with i_count of 0. this should be redesigned to return dentry instead,
- and correct dentry (with correct d_parent) */
-
-int compat_umsdos_real_lookup (struct inode *dir, const char *name, int len, struct inode **inode)
+struct dentry *compat_umsdos_real_lookup (struct dentry *d_dir, const char *name, int len)
{
int rv;
struct dentry *dentry;
- unsigned long ino;
- Printk ((KERN_DEBUG "compat_umsdos_real_lookup !!CNTx!!: start\n"));
- check_inode (dir);
- dentry = creat_dentry (name, len, NULL, NULL);
- rv = umsdos_real_lookup (dir, dentry);
- iput (dir); /* should be here, because umsdos_real_lookup does inc_count(dir) */
+ PRINTK ((KERN_DEBUG "compat_umsdos_real_lookup !!CNTx!!: start\n"));
+
+ check_dentry_path (d_dir, "compat_umsdos_real_lookup B4 dir");
+ dentry = creat_dentry (name, len, NULL, d_dir);
+
+/* check_dentry_path (dentry, "compat_umsdos_real_lookup B4");*/
+
+ rv = umsdos_real_lookup (d_dir->d_inode, dentry);
+ check_dentry_path (dentry, "compat_umsdos_real_lookup END");
if (rv) {
- Printk ((KERN_WARNING "compat_umsdos_real_lookup failed with %d\n", rv));
- return rv;
+ printk (KERN_WARNING "compat_umsdos_real_lookup failed with %d\n", rv);
+ return NULL;
}
- if (!inode) {
- Printk ((KERN_ERR "inode should be set here. Arrgh! segfaulting...\n"));
- }
-
- ino = dentry->d_inode->i_ino;
- *inode = dentry->d_inode;
- dput (dentry); /* we are done with it: FIXME: does this work /mn/ ? */
-
- check_dentry (dentry);
- check_inode (dir);
+ PRINTK ((KERN_DEBUG "compat_umsdos_real_lookup !!CNTx!!: end\n"));
- Printk ((KERN_DEBUG "compat_umsdos_real_lookup !!CNTx!!: end\n"));
+ if (dentry->d_inode) return dentry; /* all OK */
- return rv;
+ /* otherwise, we have a negative dentry. return NULL */
+ Printk ((KERN_DEBUG "compat_umsdos_real_lookup: negative dentry - file not found\n"));
+ fin_dentry (dentry);
+ return NULL;
}
int compat_msdos_create (struct inode *dir, const char *name, int len, int mode, struct inode **inode)
{
int rv;
- struct dentry *dentry;
+ struct dentry *dentry, *d_dir;
check_inode (dir);
- dentry = creat_dentry (name, len, NULL, NULL);
- check_dentry (dentry);
+ d_dir = geti_dentry (dir);
+ dentry = creat_dentry (name, len, NULL, d_dir);
+ check_dentry_path (dentry, "compat_msdos_create START");
rv = msdos_create (dir, dentry, mode);
- check_dentry (dentry);
+ check_dentry_path (dentry, "compat_msdos_create END");
if (inode != NULL)
*inode = dentry->d_inode;
@@ -91,7 +89,7 @@
* So grep * doesn't complain in the presence of directories.
*/
-int UMSDOS_dir_read (struct file *filp, char *buff, size_t size, loff_t *count)
+int dummy_dir_read (struct file *filp, char *buff, size_t size, loff_t *count)
{
return -EISDIR;
}
@@ -120,7 +118,7 @@
struct UMSDOS_DIR_ONCE *d = (struct UMSDOS_DIR_ONCE *) buf;
if (d->count == 0) {
- PRINTK ((KERN_DEBUG "dir_once :%.*s: offset %Ld\n", dentry->d_len, dentry->d_name, offset));
+ PRINTK ((KERN_DEBUG "dir_once :%.*s: offset %Ld\n", len, name, offset));
ret = d->filldir (d->dirbuf, name, len, offset, ino);
d->stop = ret < 0;
d->count = 1;
@@ -139,8 +137,7 @@
* inode. See umsdos_locate_ancestor() below.
*/
-static int umsdos_readdir_x (
- struct inode *dir, /* Point to a description of the super block */
+static int umsdos_readdir_x ( struct inode *dir, /* Point to a description of the super block */
struct file *filp, /* Point to a directory which is read */
void *dirbuf, /* Will hold count directory entry */
/* but filled by the filldir function */
@@ -150,6 +147,7 @@
filldir_t filldir)
{
int ret = 0;
+ struct dentry *old_dent;
umsdos_startlookup (dir);
if (filp->f_pos == UMSDOS_SPECIAL_DIRFPOS
@@ -179,7 +177,7 @@
/* #Specification: readdir / . and ..
- * The msdos filesystem manage the . and .. entry properly
+ * The msdos filesystem manages the . and .. entry properly
* so the EMD file won't hold any info about it.
*
* In readdir, we assume that for the root directory
@@ -232,23 +230,22 @@
if (u_entry != NULL)
u_entry->flags = 0;
} else {
- struct inode *emd_dir;
-
Printk (("umsdos_readdir_x: normal file /mn/?\n"));
- emd_dir = umsdos_emd_dir_lookup (dir, 0);
- if (emd_dir != NULL) {
+ old_dent = filp->f_dentry; /* save dentry of directory */
+
+ if (fix_emd_filp (filp) == 0) {
off_t start_fpos = filp->f_pos;
- Printk (("umsdos_readdir_x: emd_dir->i_ino=%ld\n", emd_dir->i_ino));
+ Printk (("umsdos_readdir_x: emd_dir->i_ino=%ld\n", filp->f_dentry->d_inode->i_ino));
if (filp->f_pos <= UMSDOS_SPECIAL_DIRFPOS + 1)
filp->f_pos = 0;
- Printk (("f_pos %Ld i_size %ld\n", filp->f_pos, emd_dir->i_size));
+ Printk (("f_pos %Ld i_size %ld\n", filp->f_pos, filp->f_dentry->d_inode->i_size));
ret = 0;
- while (filp->f_pos < emd_dir->i_size) {
+ while (filp->f_pos < filp->f_dentry->d_inode->i_size) {
struct umsdos_dirent entry;
off_t cur_f_pos = filp->f_pos;
- if (umsdos_emd_dir_readentry (emd_dir, filp, &entry) != 0) {
+ if (umsdos_emd_dir_readentry (filp, &entry) != 0) {
ret = -EIO;
break;
} else if (entry.name_len != 0) {
@@ -271,55 +268,50 @@
* So the easy way is used!
*/
struct umsdos_info info;
- struct inode *inode;
-
- int lret;
+ struct dentry *d_dir, *dret;
umsdos_parse (entry.name, entry.name_len, &info);
info.f_pos = cur_f_pos;
umsdos_manglename (&info);
- lret = compat_umsdos_real_lookup (dir, info.fake.fname, info.fake.len, &inode);
- Printk (("Cherche inode de %s lret %d flags %d\n", info.fake.fname, lret, entry.flags));
- if (lret == 0
- && (entry.flags & UMSDOS_HLINK)
- && follow_hlink) {
- struct inode *rinode;
-
- Printk ((KERN_DEBUG "umsdos_hlink2inode now\n"));
- lret = umsdos_hlink2inode (inode, &rinode);
- inode = rinode;
+ d_dir = geti_dentry (dir);
+ dret = compat_umsdos_real_lookup (d_dir, info.fake.fname, info.fake.len);
+
+ Printk (("Looking for inode of %s dret %p flags %d\n", info.fake.fname, dret, entry.flags));
+ if (dret && !IS_ERR(dret)
+ && (entry.flags & UMSDOS_HLINK)
+ && follow_hlink) {
+ dret = umsdos_solve_hlink (dret);
}
- if (lret == 0) {
- /* #Specification: pseudo root / reading real root
+
+ if (dret && !IS_ERR(dret)) {
+ /* #Specification: pseudo root / reading real root
* The pseudo root (/linux) is logically
- * erased from the real root. This mean that
+ * erased from the real root. This means that
* ls /DOS, won't show "linux". This avoids
- * infinite recursion /DOS/linux/DOS/linux while
+ * infinite recursion (/DOS/linux/DOS/linux/...) while
* walking the file system.
*/
- if (inode != pseudo_root
- && (internal_read
- || !(entry.flags & UMSDOS_HIDDEN))) {
+ if (dret->d_inode != pseudo_root
+ && (internal_read || !(entry.flags & UMSDOS_HIDDEN))) {
Printk ((KERN_DEBUG "filldir now\n"));
- if (filldir (dirbuf, entry.name, entry.name_len, cur_f_pos, inode->i_ino) < 0) {
+ if (filldir (dirbuf, entry.name, entry.name_len, cur_f_pos, dret->d_inode->i_ino) < 0) {
filp->f_pos = cur_f_pos;
}
- Printk (("Trouve ino %ld ", inode->i_ino));
+ Printk (("Found ino %ld ", dret->d_inode->i_ino));
if (u_entry != NULL)
*u_entry = entry;
- iput (inode); /* FIXME? */
+ fin_dentry (dret);
break;
}
- Printk ((KERN_DEBUG " dir.c:Putting inode %lu with i_count=%d\n", inode->i_ino, inode->i_count));
- iput (inode); /* FIXME? */
+ fin_dentry (dret);
} else {
- /* #Specification: umsdos / readdir / not in MSDOS
+ /* #Specification: umsdos / readdir / not in MSDOS
* During a readdir operation, if the file is not
- * in the MSDOS directory anymore, the entry is
+ * in the MS-DOS directory any more, the entry is
* removed from the EMD file silently.
*/
Printk (("'Silently' removing EMD for file\n"));
- ret = umsdos_writeentry (dir, emd_dir, &info, 1);
+ ret = umsdos_writeentry (dir, filp->f_dentry->d_inode, &info, 1);
if (ret != 0) {
break;
}
@@ -334,25 +326,26 @@
*/
if (filp->f_pos == 0)
filp->f_pos = start_fpos;
- Printk ((KERN_DEBUG " dir.c:Putting emd_dir %lu with i_count=%d\n", emd_dir->i_ino, emd_dir->i_count));
- iput (emd_dir); /* FIXME? */
+ Printk ((KERN_DEBUG "dir.c: putting emd_dir %lu with i_count=%d\n", filp->f_dentry->d_inode->i_ino, filp->f_dentry->d_inode->i_count));
+
+ fin_dentry (filp->f_dentry);
+ filp->f_dentry = old_dent; /* restore dentry of directory */
}
}
umsdos_endlookup (dir);
- Printk (("read dir %p pos %Ld ret %d\n", dir, filp->f_pos, ret));
+ Printk ((KERN_DEBUG "read dir %p pos %Ld ret %d\n", dir, filp->f_pos, ret));
return ret;
}
/*
- * Read count directory entries from directory filp
+ * Read count directory entries from directory filp.
* Return a negative value from linux/errno.h.
- * Return 0 or positive if successful
+ * Return 0 or positive if successful.
*/
-static int UMSDOS_readdir (
- struct file *filp, /* Point to a directory which is read */
+static int UMSDOS_readdir ( struct file *filp, /* Point to a directory which is read. */
void *dirbuf, /* Will hold directory entries */
filldir_t filldir)
{
@@ -370,46 +363,46 @@
struct umsdos_dirent entry;
bufk.count = 0;
- Printk (("UMSDOS_readdir: calling _x (%p,%p,%p,%d,%p,%d,%p)\n", dir, filp, &bufk, 0, &entry, 1, umsdos_dir_once));
+ PRINTK (("UMSDOS_readdir: calling _x (%p,%p,%p,%d,%p,%d,%p)\n", dir, filp, &bufk, 0, &entry, 1, umsdos_dir_once));
ret = umsdos_readdir_x (dir, filp, &bufk, 0, &entry, 1, umsdos_dir_once);
if (bufk.count == 0)
break;
count += bufk.count;
}
+ /* FIXME: do we first need to deallocate old dentry ? look/check. see also all other instances of fix_emd_filp */
Printk (("UMSDOS_readdir out %d count %d pos %Ld\n", ret, count, filp->f_pos));
return count ? : ret;
}
/*
- * Complete the inode content with info from the EMD file
+ * Complete the inode content with info from the EMD file.
*/
-void umsdos_lookup_patch (
- struct inode *dir,
+void umsdos_lookup_patch ( struct inode *dir,
struct inode *inode,
struct umsdos_dirent *entry,
off_t emd_pos)
{
/*
- * This function modify the state of a dir inode. It decides
- * if the dir is a umsdos dir or a dos dir. This is done
+ * This function modifies the state of a dir inode. It decides
+ * whether the dir is a UMSDOS or DOS directory. This is done
* deeper in umsdos_patch_inode() called at the end of this function.
*
- * umsdos_patch_inode() may block because it is doing disk access.
+ * Because it is does disk access, umsdos_patch_inode() may block.
* At the same time, another process may get here to initialise
- * the same dir inode. There is 3 cases.
+ * the same directory inode. There are three cases.
*
- * 1-The inode is already initialised. We do nothing.
- * 2-The inode is not initialised. We lock access and do it.
- * 3-Like 2 but another process has lock the inode, so we try
- * to lock it and right after check if initialisation is still
- * needed.
+ * 1) The inode is already initialised. We do nothing.
+ * 2) The inode is not initialised. We lock access and do it.
+ * 3) Like 2 but another process has locked the inode, so we try
+ * to lock it and check right afterward check whether
+ * initialisation is still needed.
*
*
- * Thanks to the mem option of the kernel command line, it was
+ * Thanks to the "mem" option of the kernel command line, it was
* possible to consistently reproduce this problem by limiting
- * my mem to 4 meg and running X.
+ * my memory to 4 MB and running X.
*/
/*
* Do this only if the inode is freshly read, because we will lose
@@ -437,10 +430,10 @@
* mtime will be meaningful. We do this only for regular
* file.
*
- * We don't rely on MSDOS for mtime for directory because
- * the MSDOS directory date is creation time (strange
- * MSDOS behavior) which fit nowhere in the three UNIX
- * time stamp.
+ * We don't rely on MS-DOS for mtime for directories
+ * because the MS-DOS date on a directory is its
+ * creation time (strange MSDOS behavior) which
+ * corresponds to none of the three Unix time stamps.
*/
if (S_ISREG (entry->mode))
entry->mtime = inode->i_mtime;
@@ -452,35 +445,35 @@
inode->i_uid = entry->uid;
inode->i_gid = entry->gid;
/* #Specification: umsdos / conversion mode
- * The msdos fs can do some inline conversion
- * of the data of a file. It can translate
- * silently from MsDOS text file format to Unix
- * one (crlf -> lf) while reading, and the reverse
+ * The msdos filesystem can do some inline conversion
+ * of the data of a file. It can translate silently
+ * from the MS-DOS text file format to the Unix one
+ * (CRLF -> LF) while reading, and the reverse
* while writing. This is activated using the mount
* option conv=....
*
- * This is not useful for Linux file in promoted
- * directory. It can even be harmful. For this
+ * This is not useful for Linux files in a promoted
+ * directory. It can even be harmful. For this
* reason, the binary (no conversion) mode is
* always activated.
*/
/* #Specification: umsdos / conversion mode / todo
* A flag could be added to file and directories
* forcing an automatic conversion mode (as
- * done with the msdos fs).
+ * done with the msdos filesystem).
*
* This flag could be setup on a directory basis
- * (instead of file) and all file in it would
- * logically inherited. If the conversion mode
+ * (instead of file) and all files in it would
+ * logically inherit it. If the conversion mode
* is active (conv=) then the i_binary flag would
* be left untouched in those directories.
*
- * It was proposed that the sticky bit was used
- * to set this. The problem is that new file would
- * be written incorrectly. The other problem is that
+ * It was proposed that the sticky bit be used to set
+ * this. A problem with that is that new files would
+ * be written incorrectly. The other problem is that
* the sticky bit has a meaning for directories. So
* another bit should be used (there is some space
- * in the EMD file for it) and a special utilities
+ * in the EMD file for it) and a special utility
* would be used to assign the flag to a directory).
* I don't think it is useful to assign this flag
* on a single file.
@@ -488,18 +481,18 @@
MSDOS_I (inode)->i_binary = 1;
/* #Specification: umsdos / i_nlink
- * The nlink field of an inode is maintain by the MSDOS file system
- * for directory and by UMSDOS for other file. The logic is that
+ * The nlink field of an inode is maintained by the MSDOS file system
+ * for directory and by UMSDOS for other files. The logic is that
* MSDOS is already figuring out what to do for directories and
- * does nothing for other files. For MSDOS, there are no hard link
- * so all file carry nlink==1. UMSDOS use some info in the
+ * does nothing for other files. For MSDOS, there are no hard links
+ * so all file carry nlink==1. UMSDOS use some info in the
* EMD file to plug the correct value.
*/
if (!S_ISDIR (entry->mode)) {
if (entry->nlink > 0) {
inode->i_nlink = entry->nlink;
} else {
- printk (KERN_ERR "UMSDOS: lookup_patch entry->nlink < 1 ???\n");
+ printk (KERN_ERR "UMSDOS: lookup_patch entry->nlink < 1 ???\n");
}
}
umsdos_patch_inode (inode, dir, emd_pos);
@@ -507,7 +500,7 @@
if (S_ISDIR (inode->i_mode))
umsdos_unlockcreate (inode);
if (inode->u.umsdos_i.i_emd_owner == 0)
- printk (KERN_WARNING "emd_owner still 0 ???\n");
+ printk (KERN_WARNING "UMSDOS: emd_owner still 0?\n");
}
}
@@ -523,8 +516,7 @@
* Just to record the offset of one entry.
*/
-static int umsdos_filldir_k (
- void *buf,
+static int umsdos_filldir_k ( void *buf,
const char *name,
int len,
off_t offset,
@@ -543,8 +535,7 @@
ino_t search_ino;
};
-static int umsdos_dir_search (
- void *buf,
+static int umsdos_dir_search ( void *buf,
const char *name,
int len,
off_t offset,
@@ -569,15 +560,14 @@
* Locate entry of an inode in a directory.
* Return 0 or a negative error code.
*
- * Normally, this function must succeed. It means a strange corruption
+ * Normally, this function must succeed. It means a strange corruption
* in the file system if not.
*/
-int umsdos_inode2entry (
- struct inode *dir,
+int umsdos_inode2entry ( struct inode *dir,
struct inode *inode,
- struct umsdos_dirent *entry)
-{ /* Will hold the entry */
+ struct umsdos_dirent *entry) /* Will hold the entry */
+{
int ret = -ENOENT;
if (pseudo_root && inode == pseudo_root) {
@@ -591,14 +581,14 @@
} else {
struct inode *emddir = umsdos_emd_dir_lookup (dir, 0);
- iput (emddir); /* FIXME? */
+ /* iput (emddir); / * FIXME? */
if (emddir == NULL) {
- /* This is a DOS directory */
+ /* This is a DOS directory. */
struct UMSDOS_DIR_SEARCH bufk;
struct file filp;
struct dentry *i2e;
- i2e = creat_dentry ("i2e.nul", 7, dir, NULL);
+ i2e = creat_dentry ("@i2e.nul@", 9, dir, NULL);
fill_new_filp (&filp, i2e);
@@ -619,7 +609,7 @@
struct file filp;
struct dentry *i2e;
- i2e = creat_dentry ("i2e.nn", 6, dir, NULL);
+ i2e = creat_dentry ("@i2e.nn@", 8, dir, NULL);
fill_new_filp (&filp, i2e);
filp.f_reada = 1;
@@ -627,14 +617,15 @@
Printk ((KERN_ERR "umsdos_inode2entry skip...: WARNING: Known filp problem. segfaulting :) fixed ?/mn/\n"));
while (1) {
struct UMSDOS_DIRENT_K bufk;
+ struct dentry *old_dent;
- if (umsdos_readdir_x (dir, &filp, &bufk
- ,1, entry, 0, umsdos_filldir_k) < 0) {
- printk ("UMSDOS: can't locate inode %ld in EMD file???\n"
- ,inode->i_ino);
+ old_dent = filp.f_dentry;
+ if (umsdos_readdir_x (dir, &filp, &bufk, 1, entry, 0, umsdos_filldir_k) < 0) {
+ printk ("UMSDOS: can't locate inode %ld in EMD file???\n", inode->i_ino);
break;
} else if (bufk.ino == inode->i_ino) {
ret = 0;
+ filp.f_dentry = old_dent;
umsdos_lookup_patch (dir, inode, entry, bufk.f_pos);
break;
}
@@ -650,21 +641,24 @@
* Return 0 or a negative error code.
*/
-static int umsdos_locate_ancestor (
- struct inode *dir,
+static int umsdos_locate_ancestor ( struct inode *dir,
struct inode **result,
struct umsdos_dirent *entry)
{
- int ret;
+ int ret=-99;
+ struct dentry *dret, *d_dir = creat_dentry ("@d_dir2@", 7, dir, NULL);
umsdos_patch_inode (dir, NULL, 0);
/* FIXME */
- ret = compat_umsdos_real_lookup (dir, "..", 2, result);
- Printk (("result %d %p ", ret, *result));
- if (ret == 0) {
- struct inode *adir = *result;
+ dret = compat_umsdos_real_lookup (d_dir, "..", 2);
+ Printk (("result %p %p ", dret, *result));
+ if (dret) {
+ struct inode *adir;
+ *result = dret->d_inode;
+ adir = *result;
ret = umsdos_inode2entry (adir, dir, entry);
+ fin_dentry (dret);
}
Printk (("\n"));
return ret;
@@ -678,8 +672,7 @@
* It uses the same strategy as the standard getcwd().
*/
-int umsdos_locate_path (
- struct inode *inode,
+int umsdos_locate_path ( struct inode *inode,
char *path)
{
int ret = 0;
@@ -733,7 +726,7 @@
kfree (bpath);
}
Printk (("\n"));
- iput (dir); /* FIXME?? */
+ /* iput (dir); / * FIXME?? */
return ret;
}
@@ -742,8 +735,7 @@
* Return != 0 if an entry is the pseudo DOS entry in the pseudo root.
*/
-int umsdos_is_pseudodos (
- struct inode *dir,
+int umsdos_is_pseudodos ( struct inode *dir,
struct dentry *dentry)
{
/* #Specification: pseudo root / DOS hard coded
@@ -763,28 +755,33 @@
/*
- * Check if a file exist in the current directory.
- * Return 0 if ok, negative error code if not (ex: -ENOENT).
+ * Check if a file exists in the current directory.
+ * Return 0 if OK, negative error code if not (ex: -ENOENT).
+ *
+ * fills dentry->d_inode with found inode, and increments its count.
+ * if not found, return -ENOENT.
*/
-int umsdos_lookup_x (
- struct inode *dir,
+int umsdos_lookup_x ( struct inode *dir,
struct dentry *dentry,
- int nopseudo)
-{ /* Don't care about pseudo root mode */
+ int nopseudo) /* Don't care about pseudo root mode */
+{
int ret = -ENOENT;
struct inode *root_inode;
int len = dentry->d_name.len;
const char *name = dentry->d_name.name;
+
- 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 */
+#if UMS_DEBUG
+ 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 */
if (dentry->d_parent)
- PRINTK ((KERN_DEBUG " d_parent is %.*s\n", (int) dentry->d_parent->d_name.len, dentry->d_parent->d_name.name)); /* FIXME : delme /mn/ */
+ Printk ((KERN_DEBUG " d_parent is %.*s\n", (int) dentry->d_parent->d_name.len, dentry->d_parent->d_name.name)); /* FIXME : delme /mn/ */
+#endif
root_inode = iget (dir->i_sb, UMSDOS_ROOT_INO);
- 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 */
+ Printk ((KERN_ERR "umsdos_lookup_x (CNT!): entering root_count+1=%d, dir %lu _count=%d\n", root_inode->i_count, dir->i_ino, dir->i_count)); /* FIXME: DEBUG, DELME */
- d_instantiate (dentry, NULL);
+ dentry->d_inode = NULL;
umsdos_startlookup (dir);
if (len == 1 && name[0] == '.') {
d_add (dentry, dir);
@@ -802,26 +799,32 @@
inc_count (pseudo_root);
} else {
/* #Specification: locating .. / strategy
- * We use the msdos filesystem to locate the parent directory.
- * But it is more complicated than that.
+ * We use the msdos filesystem to locate the parent directory,
+ * but it is more complicated than that:
*
- * We have to step back even further to
+ * we have to step back even further to
* get the parent of the parent, so we can get the EMD
- * of the parent of the parent. Using the EMD file, we can
- * locate all the info on the parent, such a permissions
- * and owner.
+ * of the parent of the parent. Using the EMD file, we
+ * can locate all the info on the parent, such as
+ * permissions and ownership.
*/
+ struct dentry *dret, *d_dir = creat_dentry ("@d_dir3@", 5, dir, NULL);
+
- ret = compat_umsdos_real_lookup (dir, "..", 2, &dentry->d_inode);
- Printk (("ancestor ret %d dir %p *result %p ", ret, dir, dentry->d_inode));
- if (ret == 0
+ dret = compat_umsdos_real_lookup (d_dir, "..", 2);
+ Printk (("ancestor ret %p dir %p *result %p ", dret, dir, dentry->d_inode));
+ if (dret
&& dentry->d_inode != root_inode
&& dentry->d_inode != pseudo_root) {
struct inode *aadir;
struct umsdos_dirent entry;
+
+ Printk ((KERN_ERR "WARNING: umsdos_lookup_x: this won't work!\n"));
+
+ dentry->d_inode = dret->d_inode; /* FIXME! this should be rewritten ! it won't work this way! */
ret = umsdos_locate_ancestor (dentry->d_inode, &aadir, &entry);
- iput (aadir); /* FIXME */
+ fin_dentry (dret);
}
}
} else if (umsdos_is_pseudodos (dir, dentry)) {
@@ -830,7 +833,7 @@
* and return the inode of the real root.
*/
d_add (dentry, root_inode);
- inc_count (dentry->d_inode);
+ inc_count (dentry->d_inode); /* FIXME?! */
ret = 0;
} else {
struct umsdos_info info;
@@ -838,59 +841,61 @@
ret = umsdos_parse (dentry->d_name.name, dentry->d_name.len, &info);
if (ret == 0)
ret = umsdos_findentry (dir, &info, 0);
- Printk (("lookup %.*s pos %lu ret %d len %d ", info.fake.len, info.fake.fname, info.f_pos, ret
- ,info.fake.len));
+ Printk (("lookup %.*s pos %lu ret %d len %d ", info.fake.len, info.fake.fname, info.f_pos, ret, info.fake.len));
if (ret == 0) {
/* #Specification: umsdos / lookup
- * A lookup for a file is done in two step. First, we locate
- * the file in the EMD file. If not present, we return
- * an error code (-ENOENT). If it is there, we repeat the
- * operation on the msdos file system. If this fails, it means
- * that the file system is not in sync with the emd file.
- * We silently remove this entry from the emd file,
- * and return ENOENT.
+ * A lookup for a file is done in two steps. First, we
+ * locate the file in the EMD file. If not present, we
+ * return an error code (-ENOENT). If it is there, we
+ * repeat the operation on the msdos file system. If
+ * this fails, it means that the file system is not in
+ * sync with the EMD file. We silently remove this
+ * entry from the EMD file, and return ENOENT.
*/
- struct inode *inode;
-
- ret = compat_umsdos_real_lookup (dir, info.fake.fname, info.fake.len, &inode);
+ struct dentry *dret, *dir_dentry;
+
+ dir_dentry = geti_dentry (dir);
+ dret = compat_umsdos_real_lookup (dir_dentry, info.fake.fname, info.fake.len);
+
- 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));
+ PRINTK ((KERN_DEBUG "umsdos_lookup_x: compat_umsdos_real_lookup for %.*s returned %p\n", info.fake.len, info.fake.fname, dret));
- if (inode == NULL) {
- printk (KERN_WARNING "UMSDOS: Erase entry %.*s, out of sync with MsDOS\n"
- ,info.fake.len, info.fake.fname);
+ if (dret == NULL) {
+ printk (KERN_WARNING "UMSDOS: Erase entry %.*s, out of sync with MS-DOS\n", info.fake.len, info.fake.fname);
umsdos_delentry (dir, &info, S_ISDIR (info.entry.mode));
} else {
- Printk ((KERN_DEBUG "umsdos_lookup_x /mn/ debug: ino=%li\n", inode->i_ino));
+ Printk ((KERN_DEBUG "umsdos_lookup_x /mn/ debug: ino=%li\n", dret->d_inode->i_ino));
- /* we've found it. now put inode in dentry */
- d_add (dentry, inode);
-
- umsdos_lookup_patch (dir, inode, &info.entry, info.f_pos);
- Printk (("lookup ino %ld flags %d\n", inode->i_ino, info.entry.flags));
+ umsdos_lookup_patch (dir, dret->d_inode, &info.entry, info.f_pos);
+ Printk (("lookup ino %ld flags %d\n", dret->d_inode->i_ino, info.entry.flags));
if (info.entry.flags & UMSDOS_HLINK) {
- Printk ((KERN_DEBUG "umsdos_lookup_x: here goes HLINK\n"));
- ret = umsdos_hlink2inode (inode, &dentry->d_inode);
+ dret = umsdos_solve_hlink (dret);
}
- if (pseudo_root && dentry->d_inode == pseudo_root && !nopseudo) {
+ if (pseudo_root && dret->d_inode == pseudo_root && !nopseudo) {
/* #Specification: pseudo root / dir lookup
* For the same reason as readdir, a lookup in /DOS for
* the pseudo root directory (linux) will fail.
*/
/*
- * This has to be allowed for resolving hard link
+ * This has to be allowed for resolving hard links
* which are recorded independently of the pseudo-root
* mode.
*/
Printk ((KERN_ERR "umsdos_lookup_x: warning: untested /mn/ Pseudo_root thingy\n"));
- iput (pseudo_root); /* FIXME?? */
- d_instantiate (dentry, NULL); /* FIXME: should be dput(dentry) ? */
+ /* iput (pseudo_root); / * FIXME?? */
+ d_instantiate (dentry, NULL); /* negative lookup */
ret = -ENOENT;
+ } else {
+ /* We've found it OK. Now put inode in dentry. */
+ inc_count (dret->d_inode); /* lookup should return incremented i_count */
+ d_add (dentry, dret->d_inode);
}
+ fin_dentry (dret);
}
}
}
umsdos_endlookup (dir);
+ iput (root_inode); /* pair to iget() above.WHY is it not needed ?! */
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));
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 */
return ret;
@@ -898,90 +903,82 @@
/*
- * Check if a file exist in the current directory.
- * Return 0 if ok, negative error code if not (ex: -ENOENT).
- *
+ * Check whether a file exists in the current directory.
+ * Return 0 if OK, negative error code if not (ex: -ENOENT).
*
+ * called by VFS. should fill dentry->d_inode (via d_add), and
+ * set (increment) dentry->d_inode->i_count.
+ *
*/
-int UMSDOS_lookup (
- struct inode *dir,
+int UMSDOS_lookup ( struct inode *dir,
struct dentry *dentry)
{
int ret;
- check_dentry (dentry);
ret = umsdos_lookup_x (dir, dentry, 0);
- check_dentry (dentry);
-#if 1
if (ret == -ENOENT) {
Printk ((KERN_DEBUG "UMSDOS_lookup: converting -ENOENT to negative dentry !\n"));
- d_add (dentry, NULL); /* create negative dentry if not found */
+ d_add (dentry, NULL); /* Create negative dentry if not found. */
ret = 0;
}
-#endif
return ret;
}
-
/*
- * Locate the inode pointed by a (pseudo) hard link
- * Return 0 if ok, a negative error code if not.
+ * gets dentry which points to pseudo-hardlink
+ *
+ * it should try to find file it points to
+ * if file is found, it should dput() original dentry and return new one (with d_count = i_count = 1)
+ * Otherwise, it should return with error, with dput()ed original dentry.
+ *
*/
-int umsdos_hlink2inode (struct inode *hlink, struct inode **result)
-{
- struct inode *root_inode;
+struct dentry *umsdos_solve_hlink (struct dentry *hlink)
+{
+ struct dentry *base = hlink->d_sb->s_root; /* root is our root for resolving pseudo-hardlink */
+ struct dentry *final = NULL;
+ struct inode *result;
int ret = -EIO;
- struct dentry *dentry_src, *dentry_dst;
+ struct dentry *dentry_dst, *d_dir;
char *path;
-#if 0 /* FIXME: DELME */
- Printk (("FIXME: just test. hlink2inode returning -ENOENT\n /mn/\n"));
- return -ENOENT; /* /mn/ FIXME just for test */
-#endif
+ check_dentry_path (hlink, "HLINK BEGIN hlink");
path = (char *) kmalloc (PATH_MAX, GFP_KERNEL);
- root_inode = iget (hlink->i_sb, UMSDOS_ROOT_INO);
- *result = NULL;
+ result = NULL;
+
if (path == NULL) {
- ret = -ENOMEM;
- iput (hlink); /* FIXME? */
+ final = ERR_PTR (-ENOMEM);
} else {
struct file filp;
- loff_t offs = 0;
-
- dentry_src = creat_dentry ("hlink-mn", 8, hlink, NULL);
-
- fill_new_filp (&filp, dentry_src);
+ fill_new_filp (&filp, hlink);
filp.f_flags = O_RDONLY;
+ filp.f_pos = 0;
Printk (("hlink2inode "));
- if (umsdos_file_read_kmem (hlink, &filp, path, hlink->i_size, &offs) == hlink->i_size) {
+ if (umsdos_file_read_kmem (&filp, path, hlink->d_inode->i_size) == hlink->d_inode->i_size) {
struct inode *dir;
char *pt = path;
- dir = root_inode;
- path[hlink->i_size] = '\0';
- iput (hlink); /* FIXME? */
- inc_count (dir);
+ dir = base->d_inode; /* start at root inode */
+ path[hlink->d_inode->i_size] = '\0';
+ inc_count (dir); /* since we're going to iput() it in the loop below... */
+
while (1) {
char *start = pt;
int len;
- while (*pt != '\0' && *pt != '/')
- pt++;
+ while (*pt != '\0' && *pt != '/') pt++;
len = (int) (pt - start);
- if (*pt == '/')
- *pt++ = '\0';
- /* FIXME. /mn/ fixed ? */
-
- dentry_dst = creat_dentry (start, len, NULL, NULL);
+ if (*pt == '/') *pt++ = '\0';
+ d_dir = geti_dentry (dir);
+ dentry_dst = creat_dentry (start, len, NULL, d_dir);
if (dir->u.umsdos_i.i_emd_dir == 0) {
/* This is a DOS directory */
@@ -991,31 +988,48 @@
Printk (("hlink2inode /mn/: doing umsdos_lookup_x on %.*s\n", (int) dentry_dst->d_name.len, dentry_dst->d_name.name));
ret = umsdos_lookup_x (dir, dentry_dst, 1);
}
+
+ iput (dir); /* dir no longer needed */
Printk ((" returned %d\n", ret));
- *result = dentry_dst->d_inode; /* /mn/ ok ? */
+ result = dentry_dst->d_inode;
+ inc_count (result); /* we need inode to survive. We'll iput it in next loop */
+
+ fin_dentry (dentry_dst); /* no longer needed - this is pair to creat_dentry */
Printk (("h2n lookup :%s: -> %d ", start, ret));
- if (ret == 0 && *pt != '\0') {
- dir = *result;
- } else {
+
+ if (ret != 0) {
+ iput (result); /* we have no longer any use for it... */
+ final = ERR_PTR (ret); /* path componenet not found ! */
break;
+ } else {
+ if (*pt != '\0') {
+ dir = result;
+ } else { /* we're finished! */
+ final = creat_dentry (hlink->d_name.name, hlink->d_name.len, result, hlink->d_parent);
+ break;
+ }
}
- }
+ } /* end while */
} else {
- Printk (("umsdos_hlink2inode: all those iput's() frighten me /mn/. Whatabout dput() ? FIXME!\n"));
- iput (hlink); /* FIXME? */
+ Printk (("umsdos_solve_hlink: failed reading pseudolink!\n"));
}
- Printk (("hlink2inode ret = %d %p -> %p\n", ret, hlink, *result));
+
+ Printk (("hlink2inode ret = %d %p -> %p\n", ret, hlink, result));
kfree (path);
}
- return ret;
-}
+
+ fin_dentry (hlink); /* original hlink no longer needed */
+ check_dentry_path (hlink, "HLINK FIN hlink");
+ check_dentry_path (final, "HLINK RET final");
+ return final;
+}
static struct file_operations umsdos_dir_operations =
{
NULL, /* lseek - default */
- UMSDOS_dir_read, /* read */
+ dummy_dir_read, /* read */
NULL, /* write - bad */
UMSDOS_readdir, /* readdir */
NULL, /* poll - default */
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov