summaryrefslogtreecommitdiffstats
path: root/fs/umsdos
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1998-08-25 09:12:35 +0000
committerRalf Baechle <ralf@linux-mips.org>1998-08-25 09:12:35 +0000
commitc7fc24dc4420057f103afe8fc64524ebc25c5d37 (patch)
tree3682407a599b8f9f03fc096298134cafba1c9b2f /fs/umsdos
parent1d793fade8b063fde3cf275bf1a5c2d381292cd9 (diff)
o Merge with Linux 2.1.116.
o New Newport console code. o New G364 console code.
Diffstat (limited to 'fs/umsdos')
-rw-r--r--fs/umsdos/README-WIP.txt31
-rw-r--r--fs/umsdos/check.c31
-rw-r--r--fs/umsdos/dir.c1734
-rw-r--r--fs/umsdos/emd.c964
-rw-r--r--fs/umsdos/file.c136
-rw-r--r--fs/umsdos/inode.c1247
-rw-r--r--fs/umsdos/ioctl.c628
-rw-r--r--fs/umsdos/mangle.c899
-rw-r--r--fs/umsdos/namei.c2156
-rw-r--r--fs/umsdos/rdir.c488
-rw-r--r--fs/umsdos/symlink.c143
11 files changed, 4412 insertions, 4045 deletions
diff --git a/fs/umsdos/README-WIP.txt b/fs/umsdos/README-WIP.txt
index 1357fdd69..05d3001c5 100644
--- a/fs/umsdos/README-WIP.txt
+++ b/fs/umsdos/README-WIP.txt
@@ -8,7 +8,7 @@ UMSDOS FILESYSTEM, AND MAYBE EVEN OTHER FILESYSTEMS IN USE.
YOU'VE BEEN WARNED.
--------- WARNING --------- WARNING --------- WARNING -----------
-Current status (980220) - UMSDOS dentry-WIP-Beta 0.82-3:
+Current status (980428) - UMSDOS dentry-WIP-Beta 0.82-4:
(1) pure MSDOS (no --linux-.--- EMD file):
@@ -32,14 +32,13 @@ Notes: possible very minor problems with dentry/inode/... kernel structures (ver
- long file names - works
- read file - works
- switching MSDOS/UMSDOS - works?
-- switching UMSDOS/MSDOS - UNTESTED
-- pseudo root things - COMMENTED OUT mostly currently. To be fixed when
- dentries stuff is straightened out.
+- switching UMSDOS/MSDOS - works?
+- pseudo root things - COMPLETELY UNTESTED
- resolve symlink - seems to work fully now!
- dereference symlink - seems to work fully now!
- hard links - seems to work now
- special files (block/char device, fifos, sockets...) - seems to work ok.
-- other ioctls - MOSTLY UNTESTED
+- other ioctls - some UNTESTED
- dangling symlink - UNTESTED !
- create symlink - seems to work both on short & long names now !
@@ -47,16 +46,16 @@ Notes: possible very minor problems with dentry/inode/... kernel structures (ver
- create file - seems to work both on short & long names now !
- create special file - seems to work both on short & long names now !
- write to file - seems to work both on short & long names now !
-- rename file (same dir) - WARNING: NOT FIXED YET!
-- rename file (dif. dir) - WARNING: NOT FIXED YET!
-- rename dir (same dir) - WARNING: NOT FIXED YET!
-- rename dir (dif. dir) - WARNING: NOT FIXED YET!
+- rename file (same dir) - seems to work, but with i_count PROBLEMS
+- rename file (dif. dir) - seems to work, but with i_count PROBLEMS
+- rename dir (same dir) - seems to work, but with i_count PROBLEMS
+- rename dir (dif. dir) - seems to work, but with i_count PROBLEMS
- delete file - seems to work fully now!
- notify_change (chown,perms) - seems to work!
- delete hardlink - WARNING: NOT FIXED YET!
- mkdir - seems to work both on short & long names now !
-- rmdir - WARNING: NOT FIXED YET!
-- umssyncing - seems to work, but NEEDS EXTENSIVE TESTING
+- rmdir - may work, but readdir blocks linux afterwards. to be FIXED!
+- umssyncing - seems to work, but NEEDS MORE TESTING
- CVF-FAT stuff (compressed DOS filesystem) - there is some support from
Frank Gockel <gockel@sent13.uni-duisburg.de> to use it even under
@@ -130,6 +129,8 @@ some of my notes for myself /mn/:
- what about .dotfiles ? working ? multiple dots ? etc....
- fix stuff like dir->i_count++ to atomic_inc(&dir->i_count) and simular?
+- chase down all "FIXME", "DELME", "CNT", check_dentry, check_inode, kill_dentry
+ and fix it properly.
- umsdos_create_any - calling msdos_create will create dentry for shor name. Hmmmm..?
- kill_dentry - put it where is needed. Also dput() at needed places.
@@ -144,6 +145,14 @@ something ?
- SECURITY WARNING: short dentries should be invalidated, or they could be
accessed instead of proper long names.
+- I've put many check_dentry() calls to trace down problems. those should be
+ removed in final version.
+
+- iput()s with "FIXME?" comment are uncomented and probably ok. Those with
+ "FIXME??" should be tested but prolly work. Commented iput()s with
+ any "FIXME" comments should probably be uncommented and tested. At some
+ places we may need dput() instead of iput(), but that should be checked.
+
- as for iput() : (my only pointer so far. anyone else ?)
>development I only know about iput. All functions that get an inode as
diff --git a/fs/umsdos/check.c b/fs/umsdos/check.c
index 67846925a..717a0df39 100644
--- a/fs/umsdos/check.c
+++ b/fs/umsdos/check.c
@@ -17,11 +17,11 @@
#include <asm/system.h>
-static int check_one_table(struct pde * page_dir)
+static int check_one_table (struct pde *page_dir)
{
- if (pgd_none(*page_dir))
+ if (pgd_none (*page_dir))
return 0;
- if (pgd_bad(*page_dir))
+ if (pgd_bad (*page_dir))
return 1;
return 0;
}
@@ -29,23 +29,28 @@ static int check_one_table(struct pde * page_dir)
/*
* This function checks all page tables of "current"
*/
-void check_page_tables(void)
+void check_page_tables (void)
{
- struct pgd * pg_dir;
+ struct pgd *pg_dir;
static int err = 0;
- int stack_level = (long)(&pg_dir)-current->kernel_stack_page;
- if (stack_level < 1500) printk ("** %d ** ",stack_level);
- pg_dir = PAGE_DIR_OFFSET(current, 0);
+ int stack_level = (long) (&pg_dir) - current->kernel_stack_page;
+
+ if (stack_level < 1500)
+ printk ("** %d ** ", stack_level);
+ pg_dir = PAGE_DIR_OFFSET (current, 0);
if (err == 0) {
int i;
- for (i = 0 ; i < PTRS_PER_PAGE ; i++,page_dir++){
- int notok = check_one_table(page_dir);
- if (notok){
+
+ for (i = 0; i < PTRS_PER_PAGE; i++, page_dir++) {
+ int notok = check_one_table (page_dir);
+
+ if (notok) {
err++;
- printk ("|%d:%08lx| ",i, page_dir->pgd);
+ printk ("|%d:%08lx| ", i, page_dir->pgd);
}
}
- if (err) printk ("\nErreur MM %d\n",err);
+ if (err)
+ printk ("\nErreur MM %d\n", err);
}
}
diff --git a/fs/umsdos/dir.c b/fs/umsdos/dir.c
index 288c77d45..3f49d0c2e 100644
--- a/fs/umsdos/dir.c
+++ b/fs/umsdos/dir.c
@@ -2,7 +2,7 @@
* linux/fs/umsdos/dir.c
*
* Written 1993 by Jacques Gelinas
- * Inspired from linux/fs/msdos/... : Werner Almesberger
+ * Inspired from linux/fs/msdos/... : Werner Almesberger
*
* Extended MS-DOS directory handling functions
*/
@@ -27,48 +27,76 @@ extern struct inode *pseudo_root;
/* P.T.Waltenberg
- 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
-*/
+ * 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
+ */
+
+/* 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)
+int compat_umsdos_real_lookup (struct inode *dir, const char *name, int len, struct inode **inode)
{
- int rv;
- struct dentry *dentry;
+ int rv;
+ struct dentry *dentry;
+ unsigned long ino;
- dentry = creat_dentry (name, len, NULL, NULL);
- rv = umsdos_real_lookup(dir,dentry);
- if (inode) *inode = dentry->d_inode;
- kill_dentry (dentry);
-
- return rv;
-}
+ 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) */
+ if (rv) {
+ Printk ((KERN_WARNING "compat_umsdos_real_lookup failed with %d\n", rv));
+ return rv;
+ }
-int compat_msdos_create(struct inode *dir,const char *name,int len, int mode, struct inode **inode)
+ 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"));
+
+ return rv;
+}
+
+
+int compat_msdos_create (struct inode *dir, const char *name, int len, int mode, struct inode **inode)
{
- int rv;
- struct dentry *dentry;
+ int rv;
+ struct dentry *dentry;
+
+ check_inode (dir);
+ dentry = creat_dentry (name, len, NULL, NULL);
+ check_dentry (dentry);
+ rv = msdos_create (dir, dentry, mode);
+ check_dentry (dentry);
+ if (inode != NULL)
+ *inode = dentry->d_inode;
- dentry = creat_dentry (name, len, NULL, NULL);
- rv = msdos_create(dir,dentry,mode);
- if(inode != NULL) *inode = dentry->d_inode;
-
- return rv;
-}
+ check_inode (dir);
+ return rv;
+}
/*
- 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)
+ * 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)
{
return -EISDIR;
}
+
struct UMSDOS_DIR_ONCE {
void *dirbuf;
filldir_t filldir;
@@ -77,873 +105,929 @@ struct UMSDOS_DIR_ONCE {
};
/*
- Record a single entry the first call.
- Return -EINVAL the next one.
- NOTE: filldir DOES NOT use a dentry
-*/
-static int umsdos_dir_once(
- void * buf,
- const char *name,
- int len,
- off_t offset,
- ino_t ino)
+ * Record a single entry the first call.
+ * Return -EINVAL the next one.
+ * NOTE: filldir DOES NOT use a dentry
+ */
+
+static int umsdos_dir_once ( void *buf,
+ const char *name,
+ int len,
+ off_t offset,
+ ino_t ino)
{
- int ret = -EINVAL;
- 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));
- ret = d->filldir (d->dirbuf,name,len,offset,ino);
- d->stop = ret < 0;
- d->count = 1;
- }
- return ret;
+ int ret = -EINVAL;
+ 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));
+ ret = d->filldir (d->dirbuf, name, len, offset, ino);
+ d->stop = ret < 0;
+ d->count = 1;
+ }
+ return ret;
}
+
/*
- Read count directory entries from directory filp
- Return a negative value from linux/errno.h.
- Return > 0 if success (The amount of byte written by filldir).
-
- This function is used by the normal readdir VFS entry point and by
- some function who try to find out info on a file from a pure MSDOS
- inode. See umsdos_locate_ancestor() below.
-*/
-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 */
- int internal_read, /* Called for internal purpose */
- struct umsdos_dirent *u_entry, /* Optional umsdos entry */
- int follow_hlink,
- filldir_t filldir)
+ * Read count directory entries from directory filp
+ * Return a negative value from linux/errno.h.
+ * Return > 0 if success (The amount of byte written by filldir).
+ *
+ * This function is used by the normal readdir VFS entry point and by
+ * some function who try to find out info on a file from a pure MSDOS
+ * inode. See umsdos_locate_ancestor() below.
+ */
+
+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 */
+ int internal_read, /* Called for internal purpose */
+ struct umsdos_dirent *u_entry, /* Optional umsdos entry */
+ int follow_hlink,
+ filldir_t filldir)
{
- int ret = 0;
- struct inode *root_inode;
-
- root_inode = iget(dir->i_sb,UMSDOS_ROOT_INO);
- umsdos_startlookup(dir);
- if (filp->f_pos == UMSDOS_SPECIAL_DIRFPOS
- && pseudo_root
- && dir == pseudo_root
- && !internal_read){
-
- Printk (("umsdos_readdir_x: what UMSDOS_SPECIAL_DIRFPOS /mn/?\n"));
- /*
- We don't need to simulate this pseudo directory
- when umsdos_readdir_x is called for internal operation
- of umsdos. This is why dirent_in_fs is tested
- */
- /* #Specification: pseudo root / directory /DOS
- When umsdos operates in pseudo root mode (C:\linux is the
- linux root), it simulate a directory /DOS which points to
- the real root of the file system.
- */
- if (filldir (dirbuf,"DOS",3,UMSDOS_SPECIAL_DIRFPOS
- ,UMSDOS_ROOT_INO) == 0){
- filp->f_pos++;
- }
- }else if (filp->f_pos < 2
- || (dir != root_inode && filp->f_pos == 32)){
- /* #Specification: readdir / . and ..
- The msdos filesystem manage the . and .. entry properly
- so the EMD file won't hold any info about it.
-
- In readdir, we assume that for the root directory
- the read position will be 0 for ".", 1 for "..". For
- a non root directory, the read position will be 0 for "."
- and 32 for "..".
- */
- /*
- This is a trick used by the msdos file system (fs/msdos/dir.c)
- to manage . and .. for the root directory of a file system.
- Since there is no such entry in the root, fs/msdos/dir.c
- use the following:
-
- if f_pos == 0, return ".".
- if f_pos == 1, return "..".
-
- So let msdos handle it
-
- Since umsdos entries are much larger, we share the same f_pos.
- if f_pos is 0 or 1 or 32, we are clearly looking at . and
- ..
-
- As soon as we get f_pos == 2 or f_pos == 64, then back to
- 0, but this time we are reading the EMD file.
-
- Well, not so true. The problem, is that UMSDOS_REC_SIZE is
- also 64, so as soon as we read the first record in the
- EMD, we are back at offset 64. So we set the offset
- to UMSDOS_SPECIAL_DIRFPOS(3) as soon as we have read the
- .. entry from msdos.
-
- Now (linux 1.3), umsdos_readdir can read more than one
- entry even if we limit (umsdos_dir_once) to only one:
- It skips over hidden file. So we switch to
- UMSDOS_SPECIAL_DIRFPOS as soon as we have read successfully
- the .. entry.
- */
- int last_f_pos = filp->f_pos;
- struct UMSDOS_DIR_ONCE bufk;
-
- Printk (("umsdos_readdir_x: . or .. /mn/?\n"));
-
- bufk.dirbuf = dirbuf;
- bufk.filldir = filldir;
- bufk.count = 0;
-
- ret = fat_readdir(filp,&bufk,umsdos_dir_once);
- if (last_f_pos > 0 && filp->f_pos > last_f_pos) filp->f_pos = UMSDOS_SPECIAL_DIRFPOS;
- 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){
- off_t start_fpos = filp->f_pos;
- Printk (("umsdos_readdir_x: emd_dir->i_ino=%ld\n",emd_dir->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));
- ret = 0;
- while (filp->f_pos < emd_dir->i_size){
- struct umsdos_dirent entry;
- off_t cur_f_pos = filp->f_pos;
- if (umsdos_emd_dir_readentry (emd_dir,filp,&entry)!=0){
- ret = -EIO;
- break;
- }else if (entry.name_len != 0){
- /* #Specification: umsdos / readdir
- umsdos_readdir() should fill a struct dirent with
- an inode number. The cheap way to get it is to
- do a lookup in the MSDOS directory for each
- entry processed by the readdir() function.
- This is not very efficient, but very simple. The
- other way around is to maintain a copy of the inode
- number in the EMD file. This is a problem because
- this has to be maintained in sync using tricks.
- Remember that MSDOS (the OS) does not update the
- modification time (mtime) of a directory. There is
- no easy way to tell that a directory was modified
- during a DOS session and synchronise the EMD file.
-
- Suggestion welcome.
-
- So the easy way is used!
- */
- struct umsdos_info info;
- struct inode *inode;
-
- int lret;
- umsdos_parse (entry.name,entry.name_len,&info);
- info.f_pos = cur_f_pos;
- umsdos_manglename (&info);
- /* FIXME, fake a dentry --> /mn/ fixed ? */
- 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;
- lret = umsdos_hlink2inode (inode,&rinode);
- inode = rinode;
- }
- if (lret == 0){
- /* #Specification: pseudo root / reading real root
- The pseudo root (/linux) is logically
- erased from the real root. This mean that
- ls /DOS, won't show "linux". This avoids
- infinite recursion /DOS/linux/DOS/linux while
- walking the file system.
- */
- if (inode != pseudo_root
- && (internal_read
- || !(entry.flags & UMSDOS_HIDDEN))){
- if (filldir (dirbuf,
- entry.name,
- entry.name_len,
- cur_f_pos,
- inode->i_ino) < 0){
- filp->f_pos = cur_f_pos;
- }
- Printk (("Trouve ino %ld ",inode->i_ino));
- if (u_entry != NULL) *u_entry = entry;
- /* iput (inode); FIXME */
- break;
- }
- /* iput (inode); FIXME */
- }else{
- /* #Specification: umsdos / readdir / not in MSDOS
- During a readdir operation, if the file is not
- in the MSDOS directory anymore, the entry is
- removed from the EMD file silently.
- */
- Printk (("'Silently' removing EMD for file\n"));
- ret = umsdos_writeentry (dir,emd_dir,&info,1);
- if (ret != 0){
- break;
- }
- }
+ int ret = 0;
+
+ umsdos_startlookup (dir);
+ if (filp->f_pos == UMSDOS_SPECIAL_DIRFPOS
+ && pseudo_root
+ && dir == pseudo_root
+ && !internal_read) {
+
+ Printk (("umsdos_readdir_x: what UMSDOS_SPECIAL_DIRFPOS /mn/?\n"));
+ /*
+ * We don't need to simulate this pseudo directory
+ * when umsdos_readdir_x is called for internal operation
+ * of umsdos. This is why dirent_in_fs is tested
+ */
+ /* #Specification: pseudo root / directory /DOS
+ * When umsdos operates in pseudo root mode (C:\linux is the
+ * linux root), it simulate a directory /DOS which points to
+ * the real root of the file system.
+ */
+ if (filldir (dirbuf, "DOS", 3, UMSDOS_SPECIAL_DIRFPOS, UMSDOS_ROOT_INO) == 0) {
+ filp->f_pos++;
+ }
+ } else if (filp->f_pos < 2 || (dir->i_ino != UMSDOS_ROOT_INO && filp->f_pos == 32)) {
+
+ /* FIXME: that was in 2.0.x: else if (filp->f_pos < 2 || (dir != dir->i_sb->s_mounted && filp->f_pos == 32))
+ * I'm probably screwing up pseudo-root and stuff with this. It needs proper fix.
+ */
+
+
+ /* #Specification: readdir / . and ..
+ * The msdos filesystem manage the . and .. entry properly
+ * so the EMD file won't hold any info about it.
+ *
+ * In readdir, we assume that for the root directory
+ * the read position will be 0 for ".", 1 for "..". For
+ * a non root directory, the read position will be 0 for "."
+ * and 32 for "..".
+ */
+ /*
+ * This is a trick used by the msdos file system (fs/msdos/dir.c)
+ * to manage . and .. for the root directory of a file system.
+ * Since there is no such entry in the root, fs/msdos/dir.c
+ * use the following:
+ *
+ * if f_pos == 0, return ".".
+ * if f_pos == 1, return "..".
+ *
+ * So let msdos handle it
+ *
+ * Since umsdos entries are much larger, we share the same f_pos.
+ * if f_pos is 0 or 1 or 32, we are clearly looking at . and
+ * ..
+ *
+ * As soon as we get f_pos == 2 or f_pos == 64, then back to
+ * 0, but this time we are reading the EMD file.
+ *
+ * Well, not so true. The problem, is that UMSDOS_REC_SIZE is
+ * also 64, so as soon as we read the first record in the
+ * EMD, we are back at offset 64. So we set the offset
+ * to UMSDOS_SPECIAL_DIRFPOS(3) as soon as we have read the
+ * .. entry from msdos.
+ *
+ * Now (linux 1.3), umsdos_readdir can read more than one
+ * entry even if we limit (umsdos_dir_once) to only one:
+ * It skips over hidden file. So we switch to
+ * UMSDOS_SPECIAL_DIRFPOS as soon as we have read successfully
+ * the .. entry.
+ */
+ int last_f_pos = filp->f_pos;
+ struct UMSDOS_DIR_ONCE bufk;
+
+ Printk (("umsdos_readdir_x: . or .. /mn/?\n"));
+
+ bufk.dirbuf = dirbuf;
+ bufk.filldir = filldir;
+ bufk.count = 0;
+
+ ret = fat_readdir (filp, &bufk, umsdos_dir_once);
+ if (last_f_pos > 0 && filp->f_pos > last_f_pos)
+ filp->f_pos = UMSDOS_SPECIAL_DIRFPOS;
+ 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) {
+ off_t start_fpos = filp->f_pos;
+
+ Printk (("umsdos_readdir_x: emd_dir->i_ino=%ld\n", emd_dir->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));
+ ret = 0;
+ while (filp->f_pos < emd_dir->i_size) {
+ struct umsdos_dirent entry;
+ off_t cur_f_pos = filp->f_pos;
+
+ if (umsdos_emd_dir_readentry (emd_dir, filp, &entry) != 0) {
+ ret = -EIO;
+ break;
+ } else if (entry.name_len != 0) {
+ /* #Specification: umsdos / readdir
+ * umsdos_readdir() should fill a struct dirent with
+ * an inode number. The cheap way to get it is to
+ * do a lookup in the MSDOS directory for each
+ * entry processed by the readdir() function.
+ * This is not very efficient, but very simple. The
+ * other way around is to maintain a copy of the inode
+ * number in the EMD file. This is a problem because
+ * this has to be maintained in sync using tricks.
+ * Remember that MSDOS (the OS) does not update the
+ * modification time (mtime) of a directory. There is
+ * no easy way to tell that a directory was modified
+ * during a DOS session and synchronise the EMD file.
+ *
+ * Suggestion welcome.
+ *
+ * So the easy way is used!
+ */
+ struct umsdos_info info;
+ struct inode *inode;
+
+ int lret;
+
+ 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;
+ }
+ if (lret == 0) {
+ /* #Specification: pseudo root / reading real root
+ * The pseudo root (/linux) is logically
+ * erased from the real root. This mean that
+ * ls /DOS, won't show "linux". This avoids
+ * infinite recursion /DOS/linux/DOS/linux while
+ * walking the file system.
+ */
+ if (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) {
+ filp->f_pos = cur_f_pos;
+ }
+ Printk (("Trouve ino %ld ", inode->i_ino));
+ if (u_entry != NULL)
+ *u_entry = entry;
+ iput (inode); /* FIXME? */
+ break;
+ }
+ Printk ((KERN_DEBUG " dir.c:Putting inode %lu with i_count=%d\n", inode->i_ino, inode->i_count));
+ iput (inode); /* FIXME? */
+ } else {
+ /* #Specification: umsdos / readdir / not in MSDOS
+ * During a readdir operation, if the file is not
+ * in the MSDOS directory anymore, the entry is
+ * removed from the EMD file silently.
+ */
+ Printk (("'Silently' removing EMD for file\n"));
+ ret = umsdos_writeentry (dir, emd_dir, &info, 1);
+ if (ret != 0) {
+ break;
+ }
+ }
+ }
+ }
+ /*
+ * If the fillbuf has failed, f_pos is back to 0.
+ * To avoid getting back into the . and .. state
+ * (see comments at the beginning), we put back
+ * the special offset.
+ */
+ 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? */
+ }
}
- }
- /*
- If the fillbuf has failed, f_pos is back to 0.
- To avoid getting back into the . and .. state
- (see comments at the beginning), we put back
- the special offset.
- */
- if (filp->f_pos == 0) filp->f_pos = start_fpos;
- /* iput(emd_dir); FIXME */
- }
- }
- umsdos_endlookup(dir);
- Printk (("read dir %p pos %Ld ret %d\n",dir,filp->f_pos,ret));
- return ret;
+ umsdos_endlookup (dir);
+
+ Printk (("read dir %p pos %Ld ret %d\n", dir, filp->f_pos, ret));
+ return ret;
}
/*
- Read count directory entries from directory filp
- Return a negative value from linux/errno.h.
- Return 0 or positive if successful
-*/
-static int UMSDOS_readdir(
- struct file *filp, /* Point to a directory which is read */
- void *dirbuf, /* Will hold directory entries */
- filldir_t filldir)
+ * Read count directory entries from directory filp
+ * Return a negative value from linux/errno.h.
+ * Return 0 or positive if successful
+ */
+
+static int UMSDOS_readdir (
+ struct file *filp, /* Point to a directory which is read */
+ void *dirbuf, /* Will hold directory entries */
+ filldir_t filldir)
{
- struct inode *dir = filp->f_dentry->d_inode;
- int ret = 0;
- int count = 0;
- struct UMSDOS_DIR_ONCE bufk;
- bufk.dirbuf = dirbuf;
- bufk.filldir = filldir;
- bufk.stop = 0;
-
- Printk (("UMSDOS_readdir in\n"));
- while (ret == 0 && bufk.stop == 0){
- 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));
- ret = umsdos_readdir_x (dir,filp,&bufk,0,&entry,1,umsdos_dir_once);
- if (bufk.count == 0) break;
- count += bufk.count;
- }
- Printk (("UMSDOS_readdir out %d count %d pos %Ld\n",ret,count
- ,filp->f_pos));
- return count?:ret;
+ struct inode *dir = filp->f_dentry->d_inode;
+ int ret = 0;
+ int count = 0;
+ struct UMSDOS_DIR_ONCE bufk;
+
+ bufk.dirbuf = dirbuf;
+ bufk.filldir = filldir;
+ bufk.stop = 0;
+
+ Printk (("UMSDOS_readdir in\n"));
+ while (ret == 0 && bufk.stop == 0) {
+ 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));
+ ret = umsdos_readdir_x (dir, filp, &bufk, 0, &entry, 1, umsdos_dir_once);
+ if (bufk.count == 0)
+ break;
+ count += bufk.count;
+ }
+ 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,
- struct inode *inode,
- struct umsdos_dirent *entry,
- off_t emd_pos)
+ 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
- deeper in umsdos_patch_inode() called at the end of this function.
-
- umsdos_patch_inode() may block because it is doing disk access.
- At the same time, another process may get here to initialise
- the same dir inode. There is 3 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.
-
-
- 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.
- */
- /*
- Do this only if the inode is freshly read, because we will lose
- the current (updated) content.
- */
- /*
- A lookup of a mount point directory yield the inode into
- the other fs, so we don't care about initialising it. iget()
- does this automatically.
- */
- if (inode->i_sb == dir->i_sb && !umsdos_isinit(inode)){
- if (S_ISDIR(inode->i_mode)) umsdos_lockcreate(inode);
- if (!umsdos_isinit(inode)){
- /* #Specification: umsdos / lookup / inode info
- After successfully reading an inode from the MSDOS
- filesystem, we use the EMD file to complete it.
- We update the following field.
-
- uid, gid, atime, ctime, mtime, mode.
-
- We rely on MSDOS for mtime. If the file
- was modified during an MSDOS session, at least
- 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.
- */
- if (S_ISREG(entry->mode)) entry->mtime = inode->i_mtime;
- inode->i_mode = entry->mode;
- inode->i_rdev = to_kdev_t(entry->rdev);
- inode->i_atime = entry->atime;
- inode->i_ctime = entry->ctime;
- inode->i_mtime = entry->mtime;
- 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
- 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
- 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).
-
- This flag could be setup on a directory basis
- (instead of file) and all file in it would
- logically inherited. 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
- 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
- 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.
- */
-
- 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
- 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
- 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");
+ /*
+ * 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
+ * deeper in umsdos_patch_inode() called at the end of this function.
+ *
+ * umsdos_patch_inode() may block because it is doing disk access.
+ * At the same time, another process may get here to initialise
+ * the same dir inode. There is 3 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.
+ *
+ *
+ * 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.
+ */
+ /*
+ * Do this only if the inode is freshly read, because we will lose
+ * the current (updated) content.
+ */
+ /*
+ * A lookup of a mount point directory yield the inode into
+ * the other fs, so we don't care about initialising it. iget()
+ * does this automatically.
+ */
+
+ if (inode->i_sb == dir->i_sb && !umsdos_isinit (inode)) {
+ if (S_ISDIR (inode->i_mode))
+ umsdos_lockcreate (inode);
+ if (!umsdos_isinit (inode)) {
+ /* #Specification: umsdos / lookup / inode info
+ * After successfully reading an inode from the MSDOS
+ * filesystem, we use the EMD file to complete it.
+ * We update the following field.
+ *
+ * uid, gid, atime, ctime, mtime, mode.
+ *
+ * We rely on MSDOS for mtime. If the file
+ * was modified during an MSDOS session, at least
+ * 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.
+ */
+ if (S_ISREG (entry->mode))
+ entry->mtime = inode->i_mtime;
+ inode->i_mode = entry->mode;
+ inode->i_rdev = to_kdev_t (entry->rdev);
+ inode->i_atime = entry->atime;
+ inode->i_ctime = entry->ctime;
+ inode->i_mtime = entry->mtime;
+ 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
+ * 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
+ * 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).
+ *
+ * This flag could be setup on a directory basis
+ * (instead of file) and all file in it would
+ * logically inherited. 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
+ * 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
+ * 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.
+ */
+
+ 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
+ * 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
+ * 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");
+ }
+ }
+ umsdos_patch_inode (inode, dir, emd_pos);
+ }
+ 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");
}
- }
- umsdos_patch_inode(inode,dir,emd_pos);
- }
- 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");
- }
}
-struct UMSDOS_DIRENT_K{
- off_t f_pos; /* will hold the offset of the entry in EMD */
- ino_t ino;
+
+
+struct UMSDOS_DIRENT_K {
+ off_t f_pos; /* will hold the offset of the entry in EMD */
+ ino_t ino;
};
+
/*
- Just to record the offset of one entry.
-*/
-static int umsdos_filldir_k(
- void * buf,
- const char *name,
- int len,
- off_t offset,
- ino_t ino)
+ * Just to record the offset of one entry.
+ */
+
+static int umsdos_filldir_k (
+ void *buf,
+ const char *name,
+ int len,
+ off_t offset,
+ ino_t ino)
{
- struct UMSDOS_DIRENT_K *d = (struct UMSDOS_DIRENT_K *)buf;
- d->f_pos = offset;
- d->ino = ino;
- return 0;
+ struct UMSDOS_DIRENT_K *d = (struct UMSDOS_DIRENT_K *) buf;
+
+ d->f_pos = offset;
+ d->ino = ino;
+ return 0;
}
-struct UMSDOS_DIR_SEARCH{
- struct umsdos_dirent *entry;
- int found;
- ino_t search_ino;
+struct UMSDOS_DIR_SEARCH {
+ struct umsdos_dirent *entry;
+ int found;
+ ino_t search_ino;
};
static int umsdos_dir_search (
- void * buf,
- const char *name,
- int len,
- off_t offset,
- ino_t ino)
+ void *buf,
+ const char *name,
+ int len,
+ off_t offset,
+ ino_t ino)
{
- int ret = 0;
- struct UMSDOS_DIR_SEARCH *d = (struct UMSDOS_DIR_SEARCH *)buf;
- if (d->search_ino == ino){
- d->found = 1;
- memcpy (d->entry->name,name,len);
- d->entry->name[len] = '\0';
- d->entry->name_len = len;
- ret = 1; /* So fat_readdir will terminate */
- }
- return ret;
+ int ret = 0;
+ struct UMSDOS_DIR_SEARCH *d = (struct UMSDOS_DIR_SEARCH *) buf;
+
+ if (d->search_ino == ino) {
+ d->found = 1;
+ memcpy (d->entry->name, name, len);
+ d->entry->name[len] = '\0';
+ d->entry->name_len = len;
+ ret = 1; /* So fat_readdir will terminate */
+ }
+ return ret;
}
+
/*
- 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
- in the file system if not.
-*/
+ * 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
+ * in the file system if not.
+ */
+
int umsdos_inode2entry (
- struct inode *dir,
- struct inode *inode,
- struct umsdos_dirent *entry) /* Will hold the entry */
-{
- int ret = -ENOENT;
- if (pseudo_root && inode == pseudo_root){
- /*
- Quick way to find the name.
- Also umsdos_readdir_x won't show /linux anyway
- */
- memcpy (entry->name,UMSDOS_PSDROOT_NAME,UMSDOS_PSDROOT_LEN+1);
- entry->name_len = UMSDOS_PSDROOT_LEN;
- ret = 0;
- }else{
- struct inode *emddir = umsdos_emd_dir_lookup(dir,0);
- /* iput (emddir); FIXME */
- if (emddir == NULL){
- /* This is a DOS directory */
- struct UMSDOS_DIR_SEARCH bufk;
- struct file filp;
-
- fill_new_filp (&filp, NULL);
-
- Printk ((KERN_ERR "umsdos_inode2entry emddir==NULL: WARNING: Known filp problem. segfaulting :) /mn/\n"));
- filp.f_reada = 1;
- filp.f_pos = 0;
- bufk.entry = entry;
- bufk.search_ino = inode->i_ino;
- fat_readdir (&filp,&bufk,umsdos_dir_search);
- if (bufk.found){
- ret = 0;
- inode->u.umsdos_i.i_dir_owner = dir->i_ino;
- inode->u.umsdos_i.i_emd_owner = 0;
- umsdos_setup_dir_inode(inode);
- }
- }else{
- /* skip . and .. see umsdos_readdir_x() */
- struct file filp;
- fill_new_filp (&filp, NULL);
-
- filp.f_reada = 1;
- filp.f_pos = UMSDOS_SPECIAL_DIRFPOS;
- Printk ((KERN_ERR "umsdos_inode2entry skip./..: WARNING: Known filp problem. segfaulting :) /mn/\n"));
- while (1){
- struct UMSDOS_DIRENT_K bufk;
- 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;
- umsdos_lookup_patch (dir,inode,entry,bufk.f_pos);
- break;
+ struct inode *dir,
+ struct inode *inode,
+ struct umsdos_dirent *entry)
+{ /* Will hold the entry */
+ int ret = -ENOENT;
+
+ if (pseudo_root && inode == pseudo_root) {
+ /*
+ * Quick way to find the name.
+ * Also umsdos_readdir_x won't show /linux anyway
+ */
+ memcpy (entry->name, UMSDOS_PSDROOT_NAME, UMSDOS_PSDROOT_LEN + 1);
+ entry->name_len = UMSDOS_PSDROOT_LEN;
+ ret = 0;
+ } else {
+ struct inode *emddir = umsdos_emd_dir_lookup (dir, 0);
+
+ iput (emddir); /* FIXME? */
+ if (emddir == NULL) {
+ /* This is a DOS directory */
+ struct UMSDOS_DIR_SEARCH bufk;
+ struct file filp;
+ struct dentry *i2e;
+
+ i2e = creat_dentry ("i2e.nul", 7, dir, NULL);
+
+ fill_new_filp (&filp, i2e);
+
+ Printk ((KERN_ERR "umsdos_inode2entry emddir==NULL: WARNING: Known filp problem. segfaulting :) fixed ?/mn/\n"));
+ filp.f_reada = 1;
+ filp.f_pos = 0;
+ bufk.entry = entry;
+ bufk.search_ino = inode->i_ino;
+ fat_readdir (&filp, &bufk, umsdos_dir_search);
+ if (bufk.found) {
+ ret = 0;
+ inode->u.umsdos_i.i_dir_owner = dir->i_ino;
+ inode->u.umsdos_i.i_emd_owner = 0;
+ umsdos_setup_dir_inode (inode);
+ }
+ } else {
+ /* skip . and .. see umsdos_readdir_x() */
+ struct file filp;
+ struct dentry *i2e;
+
+ i2e = creat_dentry ("i2e.nn", 6, dir, NULL);
+ fill_new_filp (&filp, i2e);
+
+ filp.f_reada = 1;
+ filp.f_pos = UMSDOS_SPECIAL_DIRFPOS;
+ Printk ((KERN_ERR "umsdos_inode2entry skip...: WARNING: Known filp problem. segfaulting :) fixed ?/mn/\n"));
+ while (1) {
+ struct UMSDOS_DIRENT_K bufk;
+
+ 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;
+ umsdos_lookup_patch (dir, inode, entry, bufk.f_pos);
+ break;
+ }
+ }
+ }
}
- }
- }
- }
- return ret;
+ return ret;
}
/*
- Locate the parent of a directory and the info on that directory
- Return 0 or a negative error code.
-*/
+ * Locate the parent of a directory and the info on that directory
+ * Return 0 or a negative error code.
+ */
+
static int umsdos_locate_ancestor (
- struct inode *dir,
- struct inode **result,
- struct umsdos_dirent *entry)
+ struct inode *dir,
+ struct inode **result,
+ struct umsdos_dirent *entry)
{
- int ret;
-
- 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;
- ret = umsdos_inode2entry (adir,dir,entry);
- }
- Printk (("\n"));
- return ret;
+ int ret;
+
+ 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;
+
+ ret = umsdos_inode2entry (adir, dir, entry);
+ }
+ Printk (("\n"));
+ return ret;
}
+
+
/*
- Build the path name of an inode (relative to the file system.
- This function is need to set (pseudo) hard link.
-
- It uses the same strategy as the standard getcwd().
-*/
+ * Build the path name of an inode (relative to the file system.
+ * This function is need to set (pseudo) hard link.
+ *
+ * It uses the same strategy as the standard getcwd().
+ */
+
int umsdos_locate_path (
- struct inode *inode,
- char *path)
+ struct inode *inode,
+ char *path)
{
- int ret = 0;
- struct inode *dir = inode;
- struct inode *root_inode;
- char *bpath = (char*)kmalloc(PATH_MAX,GFP_KERNEL);
- root_inode = iget(inode->i_sb,UMSDOS_ROOT_INO);
- if (bpath == NULL){
- ret = -ENOMEM;
- }else{
- struct umsdos_dirent entry;
- char *ptbpath = bpath+PATH_MAX-1;
- *ptbpath = '\0';
- Printk (("locate_path mode %x ",inode->i_mode));
- if (!S_ISDIR(inode->i_mode)){
- ret = umsdos_get_dirowner (inode,&dir);
- Printk (("locate_path ret %d ",ret));
- if (ret == 0){
- ret = umsdos_inode2entry (dir,inode,&entry);
- if (ret == 0){
- ptbpath -= entry.name_len;
- memcpy (ptbpath,entry.name,entry.name_len);
- Printk (("ptbpath :%.*s: ",entry.name_len,ptbpath));
- }
- }
- }else{
- dir->i_count++;
- }
- if (ret == 0){
- while (dir != root_inode){
- struct inode *adir;
- ret = umsdos_locate_ancestor (dir,&adir,&entry);
- /* iput (dir); FIXME */
- dir = NULL;
- Printk (("ancestor %d ",ret));
- if (ret == 0){
- *--ptbpath = '/';
- ptbpath -= entry.name_len;
- memcpy (ptbpath,entry.name,entry.name_len);
- dir = adir;
- Printk (("ptbpath :%.*s: ",entry.name_len,ptbpath));
- }else{
- break;
+ int ret = 0;
+ struct inode *dir = inode;
+ struct inode *root_inode;
+ char *bpath = (char *) kmalloc (PATH_MAX, GFP_KERNEL);
+
+ root_inode = iget (inode->i_sb, UMSDOS_ROOT_INO);
+ if (bpath == NULL) {
+ ret = -ENOMEM;
+ } else {
+ struct umsdos_dirent entry;
+ char *ptbpath = bpath + PATH_MAX - 1;
+
+ *ptbpath = '\0';
+ Printk (("locate_path mode %x ", inode->i_mode));
+ if (!S_ISDIR (inode->i_mode)) {
+ ret = umsdos_get_dirowner (inode, &dir);
+ Printk (("locate_path ret %d ", ret));
+ if (ret == 0) {
+ ret = umsdos_inode2entry (dir, inode, &entry);
+ if (ret == 0) {
+ ptbpath -= entry.name_len;
+ memcpy (ptbpath, entry.name, entry.name_len);
+ Printk (("ptbpath :%.*s: ", entry.name_len, ptbpath));
+ }
+ }
+ } else {
+ inc_count (dir);
+ }
+ if (ret == 0) {
+ while (dir != root_inode) {
+ struct inode *adir;
+
+ ret = umsdos_locate_ancestor (dir, &adir, &entry);
+ /* iput (dir); FIXME */
+ dir = NULL;
+ Printk (("ancestor %d ", ret));
+ if (ret == 0) {
+ *--ptbpath = '/';
+ ptbpath -= entry.name_len;
+ memcpy (ptbpath, entry.name, entry.name_len);
+ dir = adir;
+ Printk (("ptbpath :%.*s: ", entry.name_len, ptbpath));
+ } else {
+ break;
+ }
+ }
+ }
+ strcpy (path, ptbpath);
+ kfree (bpath);
}
- }
- }
- strcpy (path,ptbpath);
- kfree (bpath);
- }
- Printk (("\n"));
- /* iput (dir); FIXME */
- return ret;
+ Printk (("\n"));
+ iput (dir); /* FIXME?? */
+ return ret;
}
+
/*
- Return != 0 if an entry is the pseudo DOS entry in the pseudo root.
-*/
+ * Return != 0 if an entry is the pseudo DOS entry in the pseudo root.
+ */
+
int umsdos_is_pseudodos (
- struct inode *dir,
- struct dentry *dentry)
+ struct inode *dir,
+ struct dentry *dentry)
{
- /* #Specification: pseudo root / DOS hard coded
- The pseudo sub-directory DOS in the pseudo root is hard coded.
- The name is DOS. This is done this way to help standardised
- the umsdos layout. The idea is that from now on /DOS is
- a reserved path and nobody will think of using such a path
- for a package.
- */
- return pseudo_root
- && dir == pseudo_root
- && dentry->d_name.len == 3
- && dentry->d_name.name[0] == 'D'
- && dentry->d_name.name[1] == 'O'
- && dentry->d_name.name[2] == 'S';
+ /* #Specification: pseudo root / DOS hard coded
+ * The pseudo sub-directory DOS in the pseudo root is hard coded.
+ * The name is DOS. This is done this way to help standardised
+ * the umsdos layout. The idea is that from now on /DOS is
+ * a reserved path and nobody will think of using such a path
+ * for a package.
+ */
+ return pseudo_root
+ && dir == pseudo_root
+ && dentry->d_name.len == 3
+ && dentry->d_name.name[0] == 'D'
+ && dentry->d_name.name[1] == 'O'
+ && dentry->d_name.name[2] == 'S';
}
+
/*
- Check if a file exist in the current directory.
- Return 0 if ok, negative error code if not (ex: -ENOENT).
-*/
+ * Check if a file exist in the current directory.
+ * Return 0 if ok, negative error code if not (ex: -ENOENT).
+ */
+
int umsdos_lookup_x (
struct inode *dir,
struct dentry *dentry,
- int nopseudo)/* Don't care about pseudo root mode */
-{
- int ret = -ENOENT;
- struct inode *root_inode;
- struct inode *pseudo_root_inode=NULL;
- int len = dentry->d_name.len;
- const char *name = dentry->d_name.name;
-
- Printk ((KERN_DEBUG "umsdos_lookup_x: /mn/ name=%.*s, dir=%lu, d_parent=%p\n", (int) dentry->d_name.len, dentry->d_name.name, dir->i_ino, 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/ */
-
- root_inode = iget(dir->i_sb,UMSDOS_ROOT_INO);
- /* pseudo_root_inode = iget( ... ) ? */
- dentry->d_inode = NULL;
- umsdos_startlookup(dir);
- if (len == 1 && name[0] == '.'){
- d_add (dentry, dir);
- dir->i_count++;
- ret = 0;
- }else if (len == 2 && name[0] == '.' && name[1] == '.'){
- if (pseudo_root && dir == pseudo_root_inode){
- /* #Specification: pseudo root / .. in real root
- Whenever a lookup is those in the real root for
- the directory .., and pseudo root is active, the
- pseudo root is returned.
- */
- ret = 0;
- d_add (dentry, pseudo_root);
- pseudo_root->i_count++;
- }else{
- /* #Specification: locating .. / strategy
- 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
- 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.
- */
-
- 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
- && dentry->d_inode != root_inode
- && dentry->d_inode != pseudo_root){
- struct inode *aadir;
- struct umsdos_dirent entry;
- ret = umsdos_locate_ancestor (dentry->d_inode,&aadir,&entry);
- /* iput (aadir); FIXME */
- }
- }
- }else if (umsdos_is_pseudodos(dir,dentry)){
- /* #Specification: pseudo root / lookup(DOS)
- A lookup of DOS in the pseudo root will always succeed
- and return the inode of the real root.
- */
- d_add (dentry, root_inode);
- (dentry->d_inode)->i_count++;
- ret = 0;
- }else{
- struct umsdos_info info;
- 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));
- 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.
- */
- struct inode *inode;
-
- ret = compat_umsdos_real_lookup (dir,info.fake.fname,info.fake.len,&inode);
-
- 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));
-
- if (inode == NULL){
- printk (KERN_WARNING "UMSDOS: Erase entry %.*s, out of sync with MsDOS\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));
-
- /* we've found it. now get inode and put it in dentry. Is this ok /mn/ ? */
- d_add (dentry, iget(dir->i_sb, inode->i_ino));
-
- umsdos_lookup_patch (dir,inode,&info.entry,info.f_pos);
- Printk (("lookup ino %ld flags %d\n",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);
- }
- if (pseudo_root && dentry->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
- 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 */
- dentry->d_inode = NULL;
- ret = -ENOENT;
+ 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 (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/ */
+
+ 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 */
+
+ d_instantiate (dentry, NULL);
+ umsdos_startlookup (dir);
+ if (len == 1 && name[0] == '.') {
+ d_add (dentry, dir);
+ inc_count (dir);
+ ret = 0;
+ } else if (len == 2 && name[0] == '.' && name[1] == '.') {
+ if (pseudo_root && dir == pseudo_root) {
+ /* #Specification: pseudo root / .. in real root
+ * Whenever a lookup is those in the real root for
+ * the directory .., and pseudo root is active, the
+ * pseudo root is returned.
+ */
+ ret = 0;
+ d_add (dentry, pseudo_root);
+ 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 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.
+ */
+
+ 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
+ && dentry->d_inode != root_inode
+ && dentry->d_inode != pseudo_root) {
+ struct inode *aadir;
+ struct umsdos_dirent entry;
+
+ ret = umsdos_locate_ancestor (dentry->d_inode, &aadir, &entry);
+ iput (aadir); /* FIXME */
+ }
+ }
+ } else if (umsdos_is_pseudodos (dir, dentry)) {
+ /* #Specification: pseudo root / lookup(DOS)
+ * A lookup of DOS in the pseudo root will always succeed
+ * and return the inode of the real root.
+ */
+ d_add (dentry, root_inode);
+ inc_count (dentry->d_inode);
+ ret = 0;
+ } else {
+ struct umsdos_info info;
+
+ 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));
+ 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.
+ */
+ struct inode *inode;
+
+ ret = compat_umsdos_real_lookup (dir, info.fake.fname, info.fake.len, &inode);
+
+ 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));
+
+ if (inode == NULL) {
+ printk (KERN_WARNING "UMSDOS: Erase entry %.*s, out of sync with MsDOS\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));
+
+ /* 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));
+ if (info.entry.flags & UMSDOS_HLINK) {
+ Printk ((KERN_DEBUG "umsdos_lookup_x: here goes HLINK\n"));
+ ret = umsdos_hlink2inode (inode, &dentry->d_inode);
+ }
+ if (pseudo_root && dentry->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
+ * 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) ? */
+ ret = -ENOENT;
+ }
+ }
+ }
}
- }
- }
- }
- umsdos_endlookup(dir);
- /* iput (dir); FIXME */
- Printk ((KERN_DEBUG "umsdos_lookup_x: returning %d\n", ret));
- return ret;
+ umsdos_endlookup (dir);
+ 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;
}
/*
- Check if a file exist in the current directory.
- Return 0 if ok, negative error code if not (ex: -ENOENT).
-
-
-*/
+ * Check if a file exist in the current directory.
+ * Return 0 if ok, negative error code if not (ex: -ENOENT).
+ *
+ *
+ */
+
int UMSDOS_lookup (
- struct inode *dir,
- struct dentry *dentry)
+ struct inode *dir,
+ struct dentry *dentry)
{
- int ret;
- ret = umsdos_lookup_x(dir,dentry,0);
-
+ int ret;
+
+ check_dentry (dentry);
+ ret = umsdos_lookup_x (dir, dentry, 0);
+ check_dentry (dentry);
+
#if 1
- if (ret == -ENOENT) {
- Printk ((KERN_INFO "UMSDOS_lookup: converting -ENOENT to negative dentry !\n"));
- d_add (dentry, NULL); /* create negative dentry if not found */
- ret = 0;
- }
+ if (ret == -ENOENT) {
+ Printk ((KERN_DEBUG "UMSDOS_lookup: converting -ENOENT to negative dentry !\n"));
+ d_add (dentry, NULL); /* create negative dentry if not found */
+ ret = 0;
+ }
#endif
-
- return ret;
+
+ return ret;
}
/*
- Locate the inode pointed by a (pseudo) hard link
- Return 0 if ok, a negative error code if not.
-*/
+ * Locate the inode pointed by a (pseudo) hard link
+ * Return 0 if ok, a negative error code if not.
+ */
+
int umsdos_hlink2inode (struct inode *hlink, struct inode **result)
{
- struct inode *root_inode;
- int ret = -EIO;
- struct dentry *dentry_src, *dentry_dst;
- char *path;
-
-#if 0 /* FIXME: DELME */
- Printk (("FIXME: just test. hlink2inode returning -ENOENT\n /mn/\n"));
- return -ENOENT; /* /mn/ FIXME just for test */
+ struct inode *root_inode;
+ int ret = -EIO;
+ struct dentry *dentry_src, *dentry_dst;
+ char *path;
+
+#if 0 /* FIXME: DELME */
+ Printk (("FIXME: just test. hlink2inode returning -ENOENT\n /mn/\n"));
+ return -ENOENT; /* /mn/ FIXME just for test */
#endif
-
- path = (char*)kmalloc(PATH_MAX,GFP_KERNEL);
-
- root_inode = iget(hlink->i_sb,UMSDOS_ROOT_INO);
- *result = NULL;
- if (path == NULL){
- ret = -ENOMEM;
- /* iput (hlink); FIXME */
- }else{
- struct file filp;
- loff_t offs = 0;
-
- fill_new_filp (&filp, NULL);
-
-
- dentry_src = creat_dentry ("hlink-mn", 8, hlink, NULL);
-
- memset (&filp, 0, sizeof (filp));
-
- filp.f_pos = 0;
- filp.f_reada = 1;
- filp.f_flags = O_RDONLY;
- filp.f_dentry = dentry_src;
- filp.f_op = &umsdos_file_operations; /* /mn/ - we have to fill it with dummy values so we won't segfault */
-
- Printk (("hlink2inode "));
- if (umsdos_file_read_kmem (hlink, &filp, path, hlink->i_size, &offs) == hlink->i_size)
- {
- struct inode *dir;
- char *pt = path;
- dir = root_inode;
- path[hlink->i_size] = '\0';
-/* iput (hlink); / * FIXME! /mn/ */
- dir->i_count++;
- while (1)
- {
- char *start = pt;
- int len;
- 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 (dir->u.umsdos_i.i_emd_dir == 0){
- /* This is a DOS directory */
-
- Printk (("hlink2inode /mn/: doing umsdos_rlookup_x on %.*s\n", (int) dentry_dst->d_name.len, dentry_dst->d_name.name));
- ret = umsdos_rlookup_x(dir,dentry_dst,1);
- }else{
- 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);
- }
- Printk ((" returned %d\n", ret));
- *result = dentry_dst->d_inode; /* /mn/ ok ? */
-
- Printk (("h2n lookup :%s: -> %d ",start,ret));
- if (ret == 0 && *pt != '\0'){
- dir = *result;
- }else{
- break;
- }
- }
- }else{
- Printk (("umsdos_hlink2inode: all those iput's() frighten me /mn/. Whatabout dput() ? FIXME!\n"));
- /* iput (hlink); / * FIXME */
- }
- Printk (("hlink2inode ret = %d %p -> %p\n", ret, hlink, *result));
- kfree (path);
- }
- return ret;
+
+ path = (char *) kmalloc (PATH_MAX, GFP_KERNEL);
+
+ root_inode = iget (hlink->i_sb, UMSDOS_ROOT_INO);
+ *result = NULL;
+ if (path == NULL) {
+ ret = -ENOMEM;
+ iput (hlink); /* FIXME? */
+ } else {
+ struct file filp;
+ loff_t offs = 0;
+
+ dentry_src = creat_dentry ("hlink-mn", 8, hlink, NULL);
+
+ fill_new_filp (&filp, dentry_src);
+ filp.f_flags = O_RDONLY;
+
+ Printk (("hlink2inode "));
+ if (umsdos_file_read_kmem (hlink, &filp, path, hlink->i_size, &offs) == hlink->i_size) {
+ struct inode *dir;
+ char *pt = path;
+
+ dir = root_inode;
+ path[hlink->i_size] = '\0';
+ iput (hlink); /* FIXME? */
+ inc_count (dir);
+ while (1) {
+ char *start = pt;
+ int len;
+
+ 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 (dir->u.umsdos_i.i_emd_dir == 0) {
+ /* This is a DOS directory */
+
+ Printk (("hlink2inode /mn/: doing umsdos_rlookup_x on %.*s\n", (int) dentry_dst->d_name.len, dentry_dst->d_name.name));
+ ret = umsdos_rlookup_x (dir, dentry_dst, 1);
+ } else {
+ 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);
+ }
+ Printk ((" returned %d\n", ret));
+ *result = dentry_dst->d_inode; /* /mn/ ok ? */
+
+ Printk (("h2n lookup :%s: -> %d ", start, ret));
+ if (ret == 0 && *pt != '\0') {
+ dir = *result;
+ } else {
+ break;
+ }
+ }
+ } else {
+ Printk (("umsdos_hlink2inode: all those iput's() frighten me /mn/. Whatabout dput() ? FIXME!\n"));
+ iput (hlink); /* FIXME? */
+ }
+ Printk (("hlink2inode ret = %d %p -> %p\n", ret, hlink, *result));
+ kfree (path);
+ }
+ return ret;
}
-static struct file_operations umsdos_dir_operations = {
- NULL, /* lseek - default */
- UMSDOS_dir_read, /* read */
- NULL, /* write - bad */
- UMSDOS_readdir, /* readdir */
- NULL, /* poll - default */
- UMSDOS_ioctl_dir, /* ioctl - default */
- NULL, /* mmap */
- NULL, /* no special open code */
- NULL, /* no special release code */
- NULL /* fsync */ /* in original NULL. changed to file_fsync. FIXME? /mn/ */
+static struct file_operations umsdos_dir_operations =
+{
+ NULL, /* lseek - default */
+ UMSDOS_dir_read, /* read */
+ NULL, /* write - bad */
+ UMSDOS_readdir, /* readdir */
+ NULL, /* poll - default */
+ UMSDOS_ioctl_dir, /* ioctl - default */
+ NULL, /* mmap */
+ NULL, /* no special open code */
+ NULL, /* no special release code */
+ NULL /* fsync *//* in original NULL. changed to file_fsync. FIXME? /mn/ */
};
-struct inode_operations umsdos_dir_inode_operations = {
+struct inode_operations umsdos_dir_inode_operations =
+{
&umsdos_dir_operations, /* default directory file-ops */
UMSDOS_create, /* create */
UMSDOS_lookup, /* lookup */
@@ -955,22 +1039,14 @@ struct inode_operations umsdos_dir_inode_operations = {
UMSDOS_mknod, /* mknod */
UMSDOS_rename, /* rename */
NULL, /* readlink */
- NULL, /* followlink */
- generic_readpage, /* readpage */ /* in original NULL. changed to generic_readpage. FIXME? /mn/ */
+ NULL, /* followlink */
+ generic_readpage, /* readpage *//* in original NULL. changed to generic_readpage. FIXME? /mn/ */
NULL, /* writepage */
- fat_bmap, /* bmap */ /* in original NULL. changed to fat_bmap. FIXME? /mn/ */
+ fat_bmap, /* bmap *//* in original NULL. changed to fat_bmap. FIXME? /mn/ */
NULL, /* truncate */
NULL, /* permission */
NULL, /* smap */
NULL, /* updatepage */
NULL, /* revalidate */
-
-};
-
-
-
-
-
-
-
+};
diff --git a/fs/umsdos/emd.c b/fs/umsdos/emd.c
index 6cb630b1c..bf52a4d96 100644
--- a/fs/umsdos/emd.c
+++ b/fs/umsdos/emd.c
@@ -24,200 +24,118 @@
#define Printk(x) printk x
/*
- * makes empty filp
- *
+ * Read a file into kernel space memory
+ * returns how many bytes read (from fat_file_read)
*/
-
-void fill_new_filp (struct file *filp, struct dentry *dentry)
-{
- Printk (("/mn/ fill_new_filp: filling empty filp at %p\n", filp));
- if (dentry)
- Printk ((" dentry=%.*s\n", (int) dentry->d_name.len, dentry->d_name.name));
- else
- Printk ((" dentry is NULL ! you must fill it later...\n"));
-
- memset (filp, 0, sizeof (struct file));
-
- filp->f_pos = 0;
- filp->f_reada = 1;
- filp->f_flags = O_RDWR;
- filp->f_dentry = dentry;
- filp->f_op = &umsdos_file_operations; /* /mn/ - we have to fill it with SOMETHING */
-}
-
-/*
- * makes dentry. for name name with length len. /mn/
- * if inode is not NULL, puts it also.
- *
- */
-
-struct dentry *creat_dentry (const char *name, const int len, struct inode *inode, struct dentry *parent)
+ssize_t umsdos_file_read_kmem ( struct inode *emd_dir,
+ struct file *filp,
+ char *buf,
+ size_t count,
+ loff_t *offs)
{
-/* FIXME /mn/: parent is not passed many times... if it is not, dentry should be destroyed before someone else gets to use it */
-
- struct dentry *ret;
- struct qstr qname;
-
- if (inode)
- Printk ((KERN_DEBUG "/mn/ creat_dentry: creating dentry with inode=%lu for %.*s\n", inode->i_ino, len, name));
- else
- Printk ((KERN_DEBUG "/mn/ creat_dentry: creating empty dentry for %.*s\n", len, name));
-
- qname.name = name;
- qname.len = len;
- qname.hash = 0;
-
- ret = d_alloc (parent,&qname); /* create new dentry */
- ret->d_inode = NULL;
-
- if (inode) d_add (ret, inode);
-
- return ret;
-}
-
+ int ret;
-/*
- * removes temporary dentry created by creat_dentry
- *
- */
-
-void kill_dentry (struct dentry *dentry)
-{
- if (dentry) {
- Printk (("/mn/ kill_dentry: kill_dentry %.*s :", (int) dentry->d_name.len, dentry->d_name.name));
- if (dentry->d_inode)
- Printk (("inode=%lu\n", dentry->d_inode->i_ino));
- else
- Printk (("inode is NULL\n"));
-
- /* FIXME: is this ok ?! /mn/ */
- /* d_invalidate (dentry); */
- /*dput (dentry);*/
- } else {
- Printk (("/mn/ kill_dentry: dentry is NULL ?!\n"));
- }
-
-
- Printk ((KERN_DEBUG "/mn/ kill_dentry: exiting...\n"));
- return;
-}
+ struct dentry *old_dentry;
+ mm_segment_t old_fs = get_fs ();
+ set_fs (KERNEL_DS);
+ old_dentry = filp->f_dentry; /* save it */
+ filp->f_dentry = creat_dentry (UMSDOS_EMD_FILE, UMSDOS_EMD_NAMELEN, emd_dir, NULL);
+ *offs = filp->f_pos;
+
+ PRINTK ((KERN_DEBUG "umsdos_file_read_kmem /mn/: Checkin: filp=%p, buf=%p, size=%d, offs=%p\n", filp, buf, count, offs));
+ PRINTK ((KERN_DEBUG " using emd=%ld\n", emd_dir->i_ino));
+ PRINTK ((KERN_DEBUG " inode=%lu, i_size=%lu\n", filp->f_dentry->d_inode->i_ino, filp->f_dentry->d_inode->i_size));
+ PRINTK ((KERN_DEBUG " ofs=%ld\n", (unsigned long) *offs));
+ PRINTK ((KERN_DEBUG " f_pos=%Lu\n", filp->f_pos));
+ PRINTK ((KERN_DEBUG " name=%.*s\n", (int) filp->f_dentry->d_name.len, filp->f_dentry->d_name.name));
+ PRINTK ((KERN_DEBUG " i_binary(sb)=%d\n", MSDOS_I (filp->f_dentry->d_inode)->i_binary));
+ PRINTK ((KERN_DEBUG " f_count=%d, f_flags=%d\n", filp->f_count, filp->f_flags));
+ PRINTK ((KERN_DEBUG " f_owner=%d\n", filp->f_owner.uid));
+ PRINTK ((KERN_DEBUG " f_version=%ld\n", filp->f_version));
+ PRINTK ((KERN_DEBUG " f_reada=%ld, f_ramax=%ld, f_raend=%ld, f_ralen=%ld, f_rawin=%ld\n", filp->f_reada, filp->f_ramax, filp->f_raend, filp->f_ralen, filp->f_rawin));
+
+ MSDOS_I (filp->f_dentry->d_inode)->i_binary = 2;
+ ret = fat_file_read (filp, buf, count, offs);
+ PRINTK ((KERN_DEBUG "fat_file_read returned with %d!\n", ret));
+
+ filp->f_pos = *offs; /* we needed *filp only for this? grrrr... /mn/ */
+ /* FIXME: I have no idea what f_pos is used for. It seems to be used this way before offs was introduced.
+ * this probably needs fixing /mn/ */
+
+ d_drop (filp->f_dentry); /* FIXME: hmmmm... we should not dispose of it in this way ? */
+ filp->f_dentry = old_dentry; /* restore orig. dentry (it is dentry of file we need info about. Dunno why it gets passed to us
+ * since we have no use for it, expect to store totally unrelated data of offset of EMD_FILE
+ * end not directory in it. But what the hell now... fat_file_read requires it also, but prolly expects
+ * it to be file* of EMD not file we want to read EMD entry about... ugh. complicated to explain :) /mn/ */
+
+ /* FIXME: we probably need to destroy original filp->f_dentry first ? Do we ? And how ? this way we leave all sorts of dentries, inodes etc. lying around */
+ /* Also FIXME: all the same problems in umsdos_file_write_kmem */
+
+ PRINTK ((KERN_DEBUG " (ret) using emd=%lu\n", emd_dir->i_ino));
+ PRINTK ((KERN_DEBUG " (ret) inode=%lu, i_size=%lu\n", filp->f_dentry->d_inode->i_ino, filp->f_dentry->d_inode->i_size));
+ PRINTK ((KERN_DEBUG " (ret) ofs=%Lu\n", *offs));
+ PRINTK ((KERN_DEBUG " (ret) f_pos=%Lu\n", filp->f_pos));
+ PRINTK ((KERN_DEBUG " (ret) name=%.*s\n", (int) filp->f_dentry->d_name.len, filp->f_dentry->d_name.name));
+ PRINTK ((KERN_DEBUG " (ret) i_binary(sb)=%d\n", MSDOS_I (filp->f_dentry->d_inode)->i_binary));
+ PRINTK ((KERN_DEBUG " (ret) f_count=%d, f_flags=%d\n", filp->f_count, filp->f_flags));
+ PRINTK ((KERN_DEBUG " (ret) f_owner=%d\n", filp->f_owner.uid));
+ PRINTK ((KERN_DEBUG " (ret) f_version=%ld\n", filp->f_version));
+ PRINTK ((KERN_DEBUG " (ret) f_reada=%ld, f_ramax=%ld, f_raend=%ld, f_ralen=%ld, f_rawin=%ld\n", filp->f_reada, filp->f_ramax, filp->f_raend, filp->f_ralen, filp->f_rawin));
-/*
- * Read a file into kernel space memory
- * returns how many bytes read (from fat_file_read)
- */
+#if 0
+ {
+ struct umsdos_dirent *mydirent = buf;
-ssize_t umsdos_file_read_kmem (struct inode *emd_dir,
- struct file *filp,
- char *buf,
- size_t count,
- loff_t *offs
- )
-{
- int ret;
-
- struct dentry *old_dentry;
- mm_segment_t old_fs = get_fs();
-
- set_fs (KERNEL_DS);
-
- old_dentry=filp->f_dentry; /* save it */
- filp->f_dentry = creat_dentry (UMSDOS_EMD_FILE, UMSDOS_EMD_NAMELEN, emd_dir, NULL);
- *offs = filp->f_pos;
-
- PRINTK ((KERN_DEBUG "umsdos_file_read_kmem /mn/: Checkin: filp=%p, buf=%p, size=%d, offs=%p\n", filp, buf, count, offs));
- PRINTK ((KERN_DEBUG " using emd=%ld\n", emd_dir->i_ino));
- PRINTK ((KERN_DEBUG " inode=%lu, i_size=%lu\n", filp->f_dentry->d_inode->i_ino, filp->f_dentry->d_inode->i_size));
- PRINTK ((KERN_DEBUG " ofs=%ld\n",(unsigned long) *offs));
- PRINTK ((KERN_DEBUG " f_pos=%Lu\n", filp->f_pos));
- PRINTK ((KERN_DEBUG " name=%.*s\n", (int) filp->f_dentry->d_name.len, filp->f_dentry->d_name.name));
- PRINTK ((KERN_DEBUG " i_binary(sb)=%d\n", MSDOS_I(filp->f_dentry->d_inode)->i_binary ));
- PRINTK ((KERN_DEBUG " f_count=%d, f_flags=%d\n", filp->f_count, filp->f_flags));
- PRINTK ((KERN_DEBUG " f_owner=%d\n", filp->f_owner.uid));
- PRINTK ((KERN_DEBUG " f_version=%ld\n", filp->f_version));
- PRINTK ((KERN_DEBUG " f_reada=%ld, f_ramax=%ld, f_raend=%ld, f_ralen=%ld, f_rawin=%ld\n", filp->f_reada, filp->f_ramax, filp->f_raend, filp->f_ralen, filp->f_rawin));
-
- MSDOS_I(filp->f_dentry->d_inode)->i_binary=2;
- ret = fat_file_read(filp,buf,count,offs);
- PRINTK ((KERN_DEBUG "fat_file_read returned with %d!\n", ret));
-
- filp->f_pos = *offs; /* we needed *filp only for this? grrrr... /mn/ */
- /* FIXME: I have no idea what f_pos is used for. It seems to be used this way before offs was introduced.
- this probably needs fixing /mn/ */
-
- filp->f_dentry=old_dentry; /* restore orig. dentry (it is dentry of file we need info about. Dunno why it gets passed to us
- since we have no use for it, expect to store totally unrelated data of offset of EMD_FILE
- end not directory in it. But what the hell now... fat_file_read requires it also, but prolly expects
- it to be file* of EMD not file we want to read EMD entry about... ugh. complicated to explain :) /mn/ */
-
- /* FIXME: we probably need to destroy originl filp->f_dentry first ? Do we ? And how ? this way we leave all sorts of dentries, inodes etc. lying around */
- /* Also FIXME: all the same problems in umsdos_file_write_kmem */
-
- PRINTK ((KERN_DEBUG " (ret) using emd=%lu\n", emd_dir->i_ino));
- PRINTK ((KERN_DEBUG " (ret) inode=%lu, i_size=%lu\n", filp->f_dentry->d_inode->i_ino, filp->f_dentry->d_inode->i_size));
- PRINTK ((KERN_DEBUG " (ret) ofs=%Lu\n", *offs));
- PRINTK ((KERN_DEBUG " (ret) f_pos=%Lu\n", filp->f_pos));
- PRINTK ((KERN_DEBUG " (ret) name=%.*s\n", (int) filp->f_dentry->d_name.len, filp->f_dentry->d_name.name));
- PRINTK ((KERN_DEBUG " (ret) i_binary(sb)=%d\n", MSDOS_I(filp->f_dentry->d_inode)->i_binary ));
- PRINTK ((KERN_DEBUG " (ret) f_count=%d, f_flags=%d\n", filp->f_count, filp->f_flags));
- PRINTK ((KERN_DEBUG " (ret) f_owner=%d\n", filp->f_owner.uid));
- PRINTK ((KERN_DEBUG " (ret) f_version=%ld\n", filp->f_version));
- PRINTK ((KERN_DEBUG " (ret) f_reada=%ld, f_ramax=%ld, f_raend=%ld, f_ralen=%ld, f_rawin=%ld\n", filp->f_reada, filp->f_ramax, filp->f_raend, filp->f_ralen, filp->f_rawin));
+ PRINTK ((KERN_DEBUG " (DDD) uid=%d\n", mydirent->uid));
+ PRINTK ((KERN_DEBUG " (DDD) gid=%d\n", mydirent->gid));
+ PRINTK ((KERN_DEBUG " (DDD) name=>%.20s<\n", mydirent->name));
+ }
+#endif
-#if 0
- {
- struct umsdos_dirent *mydirent=buf;
-
- PRINTK ((KERN_DEBUG " (DDD) uid=%d\n",mydirent->uid));
- PRINTK ((KERN_DEBUG " (DDD) gid=%d\n",mydirent->gid));
- PRINTK ((KERN_DEBUG " (DDD) name=>%.20s<\n",mydirent->name));
- }
-#endif
-
- set_fs (old_fs);
- return ret;
+ set_fs (old_fs);
+ return ret;
}
/*
- * Write to file from kernel space.
- * Does the real job, assumes all structures are initialized !
+ * Write to file from kernel space.
+ * Does the real job, assumes all structures are initialized !
*/
-
-ssize_t umsdos_file_write_kmem_real (struct file *filp,
- const char *buf,
- size_t count,
- loff_t *offs)
+
+ssize_t umsdos_file_write_kmem_real (struct file * filp,
+ const char *buf,
+ size_t count,
+ loff_t * offs)
{
ssize_t ret;
- mm_segment_t old_fs = get_fs();
-
+ mm_segment_t old_fs = get_fs ();
+
set_fs (KERNEL_DS);
- Printk ((KERN_DEBUG "umsdos_file_write_kmem /mn/: Checkin: filp=%p, buf=%p, size=%d, offs=%p\n", filp, buf, count, offs));
- Printk ((KERN_DEBUG " struct dentry=%p\n", filp->f_dentry));
- Printk ((KERN_DEBUG " struct inode=%p\n", filp->f_dentry->d_inode));
- Printk ((KERN_DEBUG " inode=%lu, i_size=%lu\n", filp->f_dentry->d_inode->i_ino, filp->f_dentry->d_inode->i_size));
- Printk ((KERN_DEBUG " ofs=%ld\n",(unsigned long) *offs));
- Printk ((KERN_DEBUG " f_pos=%Lu\n", filp->f_pos));
- Printk ((KERN_DEBUG " name=%.*s\n", (int) filp->f_dentry->d_name.len, filp->f_dentry->d_name.name));
- Printk ((KERN_DEBUG " i_binary(sb)=%d\n", MSDOS_I(filp->f_dentry->d_inode)->i_binary ));
- Printk ((KERN_DEBUG " f_count=%d, f_flags=%d\n", filp->f_count, filp->f_flags));
- Printk ((KERN_DEBUG " f_owner=%d\n", filp->f_owner.uid));
- Printk ((KERN_DEBUG " f_version=%ld\n", filp->f_version));
- Printk ((KERN_DEBUG " f_reada=%ld, f_ramax=%ld, f_raend=%ld, f_ralen=%ld, f_rawin=%ld\n", filp->f_reada, filp->f_ramax, filp->f_raend, filp->f_ralen, filp->f_rawin));
+ PRINTK ((KERN_DEBUG "umsdos_file_write_kmem /mn/: Checkin: filp=%p, buf=%p, size=%d, offs=%p\n", filp, buf, count, offs));
+ PRINTK ((KERN_DEBUG " struct dentry=%p\n", filp->f_dentry));
+ PRINTK ((KERN_DEBUG " struct inode=%p\n", filp->f_dentry->d_inode));
+ PRINTK ((KERN_DEBUG " inode=%lu, i_size=%lu\n", filp->f_dentry->d_inode->i_ino, filp->f_dentry->d_inode->i_size));
+ PRINTK ((KERN_DEBUG " ofs=%ld\n", (unsigned long) *offs));
+ PRINTK ((KERN_DEBUG " f_pos=%Lu\n", filp->f_pos));
+ PRINTK ((KERN_DEBUG " name=%.*s\n", (int) filp->f_dentry->d_name.len, filp->f_dentry->d_name.name));
+ PRINTK ((KERN_DEBUG " i_binary(sb)=%d\n", MSDOS_I (filp->f_dentry->d_inode)->i_binary));
+ PRINTK ((KERN_DEBUG " f_count=%d, f_flags=%d\n", filp->f_count, filp->f_flags));
+ PRINTK ((KERN_DEBUG " f_owner=%d\n", filp->f_owner.uid));
+ PRINTK ((KERN_DEBUG " f_version=%ld\n", filp->f_version));
+ PRINTK ((KERN_DEBUG " f_reada=%ld, f_ramax=%ld, f_raend=%ld, f_ralen=%ld, f_rawin=%ld\n", filp->f_reada, filp->f_ramax, filp->f_raend, filp->f_ralen, filp->f_rawin));
/* note: i_binary=2 is for CVF-FAT. We put it here, instead of
- umsdos_file_write_kmem, since it is also wise not to compress symlinks
- (in unlikely event that they are > 512 bytes and can be compressed
- FIXME: should we set it when reading symlink too ? */
+ * umsdos_file_write_kmem, since it is also wise not to compress symlinks
+ * (in unlikely event that they are > 512 bytes and can be compressed
+ * FIXME: should we set it when reading symlink too ? */
+
+ MSDOS_I (filp->f_dentry->d_inode)->i_binary = 2;
- MSDOS_I(filp->f_dentry->d_inode)->i_binary=2;
-
ret = fat_file_write (filp, buf, count, offs);
PRINTK ((KERN_DEBUG "fat_file_write returned with %ld!\n", ret));
@@ -227,32 +145,32 @@ ssize_t umsdos_file_write_kmem_real (struct file *filp,
/*
- * Write to a file from kernel space
+ * Write to a file from kernel space
*/
-
-ssize_t umsdos_file_write_kmem (struct inode *emd_dir,
- struct file *filp,
+
+ssize_t umsdos_file_write_kmem (struct inode * emd_dir,
+ struct file * filp,
const char *buf,
- size_t count,
- loff_t *offs
- )
+ size_t count,
+ loff_t * offs)
{
int ret;
struct dentry *old_dentry;
-
+
Printk ((KERN_DEBUG " STARTED WRITE_KMEM /mn/\n"));
- Printk ((KERN_DEBUG " using emd=%ld\n", emd_dir->i_ino));
+ Printk ((KERN_DEBUG " using emd=%ld\n", emd_dir->i_ino));
- old_dentry=filp->f_dentry; /* save it */
+ old_dentry = filp->f_dentry; /* save it */
filp->f_dentry = creat_dentry (UMSDOS_EMD_FILE, UMSDOS_EMD_NAMELEN, emd_dir, NULL);
*offs = filp->f_pos; /* FIXME, in read_kmem also: offs is not used so why pass it ?!!! /mn/ */
- ret=umsdos_file_write_kmem_real (filp, buf, count, offs);
+ ret = umsdos_file_write_kmem_real (filp, buf, count, offs);
+ d_drop (filp->f_dentry);
filp->f_pos = *offs;
- filp->f_dentry=old_dentry;
+ filp->f_dentry = old_dentry;
return ret;
}
@@ -261,26 +179,27 @@ ssize_t umsdos_file_write_kmem (struct inode *emd_dir,
/*
- Write a block of bytes into one EMD file.
- The block of data is NOT in user space.
-
- Return 0 if ok, a negative error code if not.
-*/
-ssize_t umsdos_emd_dir_write (struct inode *emd_dir,
- struct file *filp,
- char *buf, /* buffer in kernel memory, not in user space */
- size_t count,
- loff_t *offs
- )
+ * Write a block of bytes into one EMD file.
+ * The block of data is NOT in user space.
+ *
+ * Return 0 if ok, a negative error code if not.
+ */
+
+ssize_t umsdos_emd_dir_write ( struct inode * emd_dir,
+ struct file * filp,
+ char *buf, /* buffer in kernel memory, not in user space */
+ size_t count,
+ loff_t * offs)
{
int written;
- loff_t myofs=0;
-
+ loff_t myofs = 0;
+
#ifdef __BIG_ENDIAN
- struct umsdos_dirent *d = (struct umsdos_dirent *)buf;
+ struct umsdos_dirent *d = (struct umsdos_dirent *) buf;
+
#endif
filp->f_flags = 0;
-#ifdef __BIG_ENDIAN
+#ifdef __BIG_ENDIAN
d->nlink = cpu_to_le16 (d->nlink);
d->uid = cpu_to_le16 (d->uid);
d->gid = cpu_to_le16 (d->gid);
@@ -289,15 +208,17 @@ ssize_t umsdos_emd_dir_write (struct inode *emd_dir,
d->ctime = cpu_to_le32 (d->ctime);
d->rdev = cpu_to_le16 (d->rdev);
d->mode = cpu_to_le16 (d->mode);
-#endif
-
- if (offs) myofs=*offs; /* if offs is not NULL, read it */
+#endif
+
+ if (offs)
+ myofs = *offs; /* if offs is not NULL, read it */
Printk (("umsdos_emd_dir_write /mn/: calling write_kmem with %p, %p, %p, %d, %Ld\n", emd_dir, filp, buf, count, myofs));
written = umsdos_file_write_kmem (emd_dir, filp, buf, count, &myofs);
Printk (("umsdos_emd_dir_write /mn/: write_kmem returned\n"));
- if (offs) *offs=myofs; /* if offs is not NULL, store myofs there */
-
-#ifdef __BIG_ENDIAN
+ if (offs)
+ *offs = myofs; /* if offs is not NULL, store myofs there */
+
+#ifdef __BIG_ENDIAN
d->nlink = le16_to_cpu (d->nlink);
d->uid = le16_to_cpu (d->uid);
d->gid = le16_to_cpu (d->gid);
@@ -306,12 +227,12 @@ ssize_t umsdos_emd_dir_write (struct inode *emd_dir,
d->ctime = le32_to_cpu (d->ctime);
d->rdev = le16_to_cpu (d->rdev);
d->mode = le16_to_cpu (d->mode);
-#endif
-
-#ifdef 1
- if (written != count) Printk ((KERN_ERR "umsdos_emd_dir_write: ERROR: written (%d) != count (%d)\n", written, count));
#endif
+#if 1
+ if (written != count)
+ Printk ((KERN_ERR "umsdos_emd_dir_write: ERROR: written (%d) != count (%d)\n", written, count));
+#endif
return written != count ? -EIO : 0;
}
@@ -319,36 +240,36 @@ ssize_t umsdos_emd_dir_write (struct inode *emd_dir,
/*
- * Read a block of bytes from one EMD file.
- * The block of data is NOT in user space.
- * Return 0 if ok, -EIO if any error.
+ * Read a block of bytes from one EMD file.
+ * The block of data is NOT in user space.
+ * Return 0 if ok, -EIO if any error.
*/
-
-ssize_t umsdos_emd_dir_read (struct inode *emd_dir,
- struct file *filp,
- char *buf, /* buffer in kernel memory, not in user space */
- size_t count,
- loff_t *offs
- )
+
+ssize_t umsdos_emd_dir_read (struct inode * emd_dir,
+ struct file * filp,
+ char *buf, /* buffer in kernel memory, not in user space */
+ size_t count,
+ loff_t * offs)
{
- loff_t myofs=0;
+ loff_t myofs = 0;
long int ret = 0;
int sizeread;
-
-
+
+
#ifdef __BIG_ENDIAN
- struct umsdos_dirent *d = (struct umsdos_dirent *)buf;
+ struct umsdos_dirent *d = (struct umsdos_dirent *) buf;
+
#endif
- if (offs) myofs=*offs; /* if offs is not NULL, read it */
+ if (offs)
+ myofs = *offs; /* if offs is not NULL, read it */
filp->f_flags = 0;
sizeread = umsdos_file_read_kmem (emd_dir, filp, buf, count, &myofs);
- if (sizeread != count){
- printk ("UMSDOS: problem with EMD file. Can't read pos = %Ld (%d != %d)\n"
- ,filp->f_pos,sizeread,count);
+ if (sizeread != count) {
+ printk ("UMSDOS: problem with EMD file. Can't read pos = %Ld (%d != %d)\n", filp->f_pos, sizeread, count);
ret = -EIO;
}
-#ifdef __BIG_ENDIAN
+#ifdef __BIG_ENDIAN
d->nlink = le16_to_cpu (d->nlink);
d->uid = le16_to_cpu (d->uid);
d->gid = le16_to_cpu (d->gid);
@@ -357,8 +278,9 @@ ssize_t umsdos_emd_dir_read (struct inode *emd_dir,
d->ctime = le32_to_cpu (d->ctime);
d->rdev = le16_to_cpu (d->rdev);
d->mode = le16_to_cpu (d->mode);
-#endif
- if (offs) *offs=myofs; /* if offs is not NULL, store myofs there */
+#endif
+ if (offs)
+ *offs = myofs; /* if offs is not NULL, store myofs there */
return ret;
}
@@ -367,92 +289,95 @@ ssize_t umsdos_emd_dir_read (struct inode *emd_dir,
/*
- Locate the EMD file in a directory .
+ * Locate the EMD file in a directory .
+ *
+ * Return NULL if error. If ok, dir->u.umsdos_i.emd_inode
+ */
- Return NULL if error. If ok, dir->u.umsdos_i.emd_inode
-*/
struct inode *umsdos_emd_dir_lookup (struct inode *dir, int creat)
{
- struct inode *ret = NULL;
- int res;
- PRINTK ((KERN_DEBUG "Entering umsdos_emd_dir_lookup\n"));
- if (dir->u.umsdos_i.i_emd_dir != 0){
- ret = iget (dir->i_sb,dir->u.umsdos_i.i_emd_dir);
- Printk (("umsdos_emd_dir_lookup: deja trouve %ld %p\n"
- ,dir->u.umsdos_i.i_emd_dir,ret));
- } else {
- PRINTK ((KERN_DEBUG "umsdos /mn/: Looking for %.*s -", UMSDOS_EMD_NAMELEN, UMSDOS_EMD_FILE));
- res = compat_umsdos_real_lookup (dir, UMSDOS_EMD_FILE, UMSDOS_EMD_NAMELEN, &ret);
- PRINTK ((KERN_DEBUG "-returned %d\n", res));
- Printk ((KERN_INFO "emd_dir_lookup "));
- if (ret != NULL){
- Printk (("Found --linux "));
- dir->u.umsdos_i.i_emd_dir = ret->i_ino;
- } else if (creat) {
- int code;
- Printk ((" * ERROR * /mn/: creat not yet implemented!!!!" ));
- Printk ((KERN_DEBUG "avant create "));
- dir->i_count++;
-
- code = compat_msdos_create (dir,UMSDOS_EMD_FILE,UMSDOS_EMD_NAMELEN
- ,S_IFREG|0777,&ret);
- Printk ((KERN_WARNING "Creat EMD code %d ret %p ", code, ret));
- if (ret != NULL){
- dir->u.umsdos_i.i_emd_dir = ret->i_ino;
- }else{
- printk (KERN_WARNING "UMSDOS: Can't create EMD file\n");
- }
- }
-
- if (ret != NULL){
- /* Disable UMSDOS_notify_change() for EMD file */
- ret->u.umsdos_i.i_emd_owner = 0xffffffff;
+ struct inode *ret = NULL;
+ int res;
+
+ Printk ((KERN_DEBUG "Entering umsdos_emd_dir_lookup\n"));
+ if (dir->u.umsdos_i.i_emd_dir != 0) {
+ ret = iget (dir->i_sb, dir->u.umsdos_i.i_emd_dir);
+ Printk (("umsdos_emd_dir_lookup: deja trouve %ld %p\n"
+ ,dir->u.umsdos_i.i_emd_dir, ret));
+ } else {
+ PRINTK ((KERN_DEBUG "umsdos /mn/: Looking for %.*s -", UMSDOS_EMD_NAMELEN, UMSDOS_EMD_FILE));
+ res = compat_umsdos_real_lookup (dir, UMSDOS_EMD_FILE, UMSDOS_EMD_NAMELEN, &ret);
+ PRINTK ((KERN_DEBUG "-returned %d\n", res));
+ Printk ((KERN_INFO "emd_dir_lookup "));
+ if (ret != NULL) {
+ Printk (("Found --linux "));
+ dir->u.umsdos_i.i_emd_dir = ret->i_ino;
+ } else if (creat) {
+ int code;
+
+ Printk ((" * ERROR * /mn/: creat not yet implemented? not fixed? "));
+ Printk (("avant create "));
+ inc_count (dir);
+
+ check_inode (ret);
+ code = compat_msdos_create (dir, UMSDOS_EMD_FILE, UMSDOS_EMD_NAMELEN, S_IFREG | 0777, &ret);
+ check_inode (ret);
+ Printk (("Creat EMD code %d ret %p ", code, ret));
+ if (ret != NULL) {
+ Printk ((" ino=%lu", ret->i_ino));
+ dir->u.umsdos_i.i_emd_dir = ret->i_ino;
+ } else {
+ printk (KERN_WARNING "UMSDOS: Can't create EMD file\n");
+ }
+ }
+ if (ret != NULL) {
+ /* Disable UMSDOS_notify_change() for EMD file */
+ ret->u.umsdos_i.i_emd_owner = 0xffffffff;
+ }
+
}
- }
-
-#if 0
- PRINTK ((KERN_DEBUG "umsdos_emd_dir_lookup returning %p /mn/\n", ret));
- if (ret != NULL) PRINTK ((KERN_DEBUG " debug : returning ino=%lu\n", ret->i_ino));
-#endif
- return ret;
+#if 1
+ Printk ((KERN_DEBUG "umsdos_emd_dir_lookup returning %p /mn/\n", ret));
+ if (ret != NULL)
+ Printk ((KERN_DEBUG " returning ino=%lu\n", ret->i_ino));
+#endif
+ return ret;
}
-/*
- creates an EMD file
- Return NULL if error. If ok, dir->u.umsdos_i.emd_inode
-*/
-struct inode *umsdos_emd_dir_create(struct inode *dir, struct dentry *dentry,int mode)
+/*
+ * creates an EMD file
+ *
+ * Return NULL if error. If ok, dir->u.umsdos_i.emd_inode
+ */
+
+struct inode *umsdos_emd_dir_create (struct inode *dir, struct dentry *dentry, int mode)
{
struct inode *ret = NULL;
- if (dir->u.umsdos_i.i_emd_dir != 0){
- ret = iget (dir->i_sb,dir->u.umsdos_i.i_emd_dir);
+
+ if (dir->u.umsdos_i.i_emd_dir != 0) {
+ ret = iget (dir->i_sb, dir->u.umsdos_i.i_emd_dir);
Printk (("deja trouve %lu %p", dir->u.umsdos_i.i_emd_dir, ret));
- }else{
-
- int code;
- Printk (("avant create "));
- dir->i_count++;
- /*
- code = msdos_create (dir,UMSDOS_EMD_FILE,UMSDOS_EMD_NAMELEN
- ,S_IFREG|0777,&ret);
-
- FIXME, I think I need a new dentry here
- */
- code = compat_msdos_create (dir,UMSDOS_EMD_FILE,UMSDOS_EMD_NAMELEN, S_IFREG|0777, &ret);
- Printk (("Creat EMD code %d ret %p ", code, ret));
- if (ret != NULL){
- dir->u.umsdos_i.i_emd_dir = ret->i_ino;
- }else{
- printk ("UMSDOS: Can't create EMD file\n");
- }
+ } else {
+
+ int code;
+
+ Printk (("avant create "));
+ inc_count (dir);
+ code = compat_msdos_create (dir, UMSDOS_EMD_FILE, UMSDOS_EMD_NAMELEN, S_IFREG | 0777, &ret);
+ Printk (("Creat EMD code %d ret %p ", code, ret));
+ if (ret != NULL) {
+ dir->u.umsdos_i.i_emd_dir = ret->i_ino;
+ } else {
+ printk ("UMSDOS: Can't create EMD file\n");
+ }
}
- if (ret != NULL){
- /* Disable UMSDOS_notify_change() for EMD file */
- ret->u.umsdos_i.i_emd_owner = 0xffffffff;
+ if (ret != NULL) {
+ /* Disable UMSDOS_notify_change() for EMD file */
+ ret->u.umsdos_i.i_emd_owner = 0xffffffff;
}
return ret;
}
@@ -460,28 +385,29 @@ struct inode *umsdos_emd_dir_create(struct inode *dir, struct dentry *dentry,int
/*
- Read an entry from the EMD file.
- Support variable length record.
- Return -EIO if error, 0 if ok.
-*/
+ * Read an entry from the EMD file.
+ * Support variable length record.
+ * Return -EIO if error, 0 if ok.
+ */
+
int umsdos_emd_dir_readentry (
- struct inode *emd_dir,
- struct file *filp,
- struct umsdos_dirent *entry)
+ struct inode *emd_dir,
+ struct file *filp,
+ struct umsdos_dirent *entry)
{
int ret;
+
Printk ((KERN_DEBUG "umsdos_emd_dir_readentry /mn/: entering.\n"));
Printk (("umsdos_emd_dir_readentry /mn/: trying to lookup %.*s (ino=%lu) using EMD %lu\n", (int) filp->f_dentry->d_name.len, filp->f_dentry->d_name.name, filp->f_dentry->d_inode->i_ino, emd_dir->i_ino));
-
- ret = umsdos_emd_dir_read(emd_dir, filp, (char*)entry, UMSDOS_REC_SIZE, NULL);
- if (ret == 0){ /* note /mn/: is this wrong? ret is allways 0 or -EIO. but who knows. It used to work this way... */
+
+ ret = umsdos_emd_dir_read (emd_dir, filp, (char *) entry, UMSDOS_REC_SIZE, NULL);
+ if (ret == 0) { /* note /mn/: is this wrong? ret is always 0 or -EIO. but who knows. It used to work this way... */
/* Variable size record. Maybe, we have to read some more */
int recsize = umsdos_evalrecsize (entry->name_len);
- Printk ((KERN_DEBUG "umsdos_emd_dir_readentry /mn/: FIXME if %d > %d?\n",recsize, UMSDOS_REC_SIZE));
- if (recsize > UMSDOS_REC_SIZE){
- ret = umsdos_emd_dir_read(emd_dir, filp
- ,((char*)entry)+UMSDOS_REC_SIZE,recsize - UMSDOS_REC_SIZE,NULL);
-
+
+ Printk ((KERN_DEBUG "umsdos_emd_dir_readentry /mn/: FIXME if %d > %d?\n", recsize, UMSDOS_REC_SIZE));
+ if (recsize > UMSDOS_REC_SIZE) {
+ ret = umsdos_emd_dir_read (emd_dir, filp, ((char *) entry) + UMSDOS_REC_SIZE, recsize - UMSDOS_REC_SIZE, NULL);
}
}
Printk (("umsdos_emd_dir_readentry /mn/: returning %d.\n", ret));
@@ -492,61 +418,62 @@ int umsdos_emd_dir_readentry (
/*
- Write an entry in the EMD file.
- Return 0 if ok, -EIO if some error.
-*/
+ * Write an entry in the EMD file.
+ * Return 0 if ok, -EIO if some error.
+ */
+
int umsdos_writeentry (
- struct inode *dir,
- struct inode *emd_dir,
- struct umsdos_info *info,
- int free_entry) /* This entry is deleted, so Write all 0's */
-{
+ struct inode *dir,
+ struct inode *emd_dir,
+ struct umsdos_info *info,
+ int free_entry)
+
+{ /* This entry is deleted, so Write all 0's */
int ret = 0;
struct dentry *emd_dentry;
struct file filp;
struct umsdos_dirent *entry = &info->entry;
struct umsdos_dirent entry0;
- fill_new_filp (&filp, NULL);
+ fill_new_filp (&filp, NULL);
Printk (("umsdos_writeentry /mn/: entering...\n"));
- emd_dentry=creat_dentry ("wremd_mn", 8, emd_dir, NULL);
-
- if (free_entry){
+ emd_dentry = creat_dentry ("wremd_mn", 8, emd_dir, NULL);
+
+ if (free_entry) {
/* #Specification: EMD file / empty entries
- Unused entry in the EMD file are identify
- by the name_len field equal to 0. However to
- help future extension (or bug correction :-( ),
- empty entries are filled with 0.
- */
- memset (&entry0,0,sizeof(entry0));
+ * Unused entry in the EMD file are identify
+ * by the name_len field equal to 0. However to
+ * help future extension (or bug correction :-( ),
+ * empty entries are filled with 0.
+ */
+ memset (&entry0, 0, sizeof (entry0));
entry = &entry0;
- }else if (entry->name_len > 0){
- memset (entry->name+entry->name_len,'\0'
- ,sizeof(entry->name)-entry->name_len);
+ } else if (entry->name_len > 0) {
+ memset (entry->name + entry->name_len, '\0', sizeof (entry->name) - entry->name_len);
/* #Specification: EMD file / spare bytes
- 10 bytes are unused in each record of the EMD. They
- are set to 0 all the time. So it will be possible
- to do new stuff and rely on the state of those
- bytes in old EMD file around.
- */
- memset (entry->spare,0,sizeof(entry->spare));
+ * 10 bytes are unused in each record of the EMD. They
+ * are set to 0 all the time. So it will be possible
+ * to do new stuff and rely on the state of those
+ * bytes in old EMD file around.
+ */
+ memset (entry->spare, 0, sizeof (entry->spare));
}
-
Printk (("umsdos_writeentry /mn/: if passed...\n"));
- if (!info) printk (KERN_ERR "umsdosfs: /mn/ info is empty ! ooops...\n");
+ if (!info)
+ printk (KERN_ERR "umsdosfs: /mn/ info is empty ! ooops...\n");
filp.f_pos = info->f_pos;
filp.f_reada = 0;
filp.f_flags = O_RDWR;
filp.f_dentry = emd_dentry;
- filp.f_op = &umsdos_file_operations; /* /mn/ - we have to fill it with dummy values so we won't segfault */
-
- ret = umsdos_emd_dir_write (emd_dir, &filp, (char*)entry, info->recsize, NULL);
+ filp.f_op = &umsdos_file_operations; /* /mn/ - we have to fill it with dummy values so we won't segfault */
+
+ ret = umsdos_emd_dir_write (emd_dir, &filp, (char *) entry, info->recsize, NULL);
Printk (("emd_dir_write returned with %d!\n", ret));
- if (ret != 0){
+ if (ret != 0) {
printk ("UMSDOS: problem with EMD file. Can't write\n");
- }else{
+ } else {
dir->i_ctime = dir->i_mtime = CURRENT_TIME;
/* dir->i_dirt = 1; FIXME iput/dput ??? */
}
@@ -558,10 +485,10 @@ int umsdos_writeentry (
#define CHUNK_SIZE (8*UMSDOS_REC_SIZE)
-struct find_buffer{
+struct find_buffer {
char buffer[CHUNK_SIZE];
- int pos; /* read offset in buffer */
- int size; /* Current size of buffer */
+ int pos; /* read offset in buffer */
+ int size; /* Current size of buffer */
struct file filp;
};
@@ -570,34 +497,36 @@ struct find_buffer{
/*
- Fill the read buffer and take care of the byte remaining inside.
- Unread bytes are simply move to the beginning.
+ * Fill the read buffer and take care of the byte remaining inside.
+ * Unread bytes are simply move to the beginning.
+ *
+ * Return -ENOENT if EOF, 0 if ok, a negative error code if any problem.
+ */
- Return -ENOENT if EOF, 0 if ok, a negative error code if any problem.
-*/
static int umsdos_fillbuf (
- struct inode *inode,
- struct find_buffer *buf)
+ struct inode *inode,
+ struct find_buffer *buf)
{
int ret = -ENOENT;
int mustmove = buf->size - buf->pos;
int mustread;
int remain;
-
+
PRINTK ((KERN_DEBUG "Entering umsdos_fillbuf, for inode %lu, buf=%p\n", inode->i_ino, buf));
-
- if (mustmove > 0){
- memcpy (buf->buffer,buf->buffer+buf->pos,mustmove);
+
+ if (mustmove > 0) {
+ memcpy (buf->buffer, buf->buffer + buf->pos, mustmove);
}
buf->pos = 0;
mustread = CHUNK_SIZE - mustmove;
remain = inode->i_size - buf->filp.f_pos;
- if (remain < mustread) mustread = remain;
- if (mustread > 0){
- ret = umsdos_emd_dir_read (inode, &buf->filp,buf->buffer+mustmove
- ,mustread,NULL);
- if (ret == 0) buf->size = mustmove + mustread;
- }else if (mustmove){
+ if (remain < mustread)
+ mustread = remain;
+ if (mustread > 0) {
+ ret = umsdos_emd_dir_read (inode, &buf->filp, buf->buffer + mustmove, mustread, NULL);
+ if (ret == 0)
+ buf->size = mustmove + mustread;
+ } else if (mustmove) {
buf->size = mustmove;
ret = 0;
}
@@ -607,61 +536,61 @@ static int umsdos_fillbuf (
/*
- General search, locate a name in the EMD file or an empty slot to
- store it. if info->entry.name_len == 0, search the first empty
- slot (of the proper size).
-
- Caller must do iput on *pt_emd_dir.
-
- Return 0 if found, -ENOENT if not found, another error code if
- other problem.
-
- So this routine is used to either find an existing entry or to
- create a new one, while making sure it is a new one. After you
- get -ENOENT, you make sure the entry is stuffed correctly and
- call umsdos_writeentry().
-
- To delete an entry, you find it, zero out the entry (memset)
- and call umsdos_writeentry().
+ * General search, locate a name in the EMD file or an empty slot to
+ * store it. if info->entry.name_len == 0, search the first empty
+ * slot (of the proper size).
+ *
+ * Caller must do iput on *pt_emd_dir.
+ *
+ * Return 0 if found, -ENOENT if not found, another error code if
+ * other problem.
+ *
+ * So this routine is used to either find an existing entry or to
+ * create a new one, while making sure it is a new one. After you
+ * get -ENOENT, you make sure the entry is stuffed correctly and
+ * call umsdos_writeentry().
+ *
+ * To delete an entry, you find it, zero out the entry (memset)
+ * and call umsdos_writeentry().
+ *
+ * All this to say that umsdos_writeentry must be call after this
+ * function since it rely on the f_pos field of info.
+ */
- All this to say that umsdos_writeentry must be call after this
- function since it rely on the f_pos field of info.
-*/
static int umsdos_find (
- struct inode *dir,
- struct umsdos_info *info, /* Hold name and name_len */
- /* Will hold the entry found */
- struct inode **pt_emd_dir) /* Will hold the emd_dir inode */
- /* or NULL if not found */
+ struct inode *dir,
+ struct umsdos_info *info, /* Hold name and name_len */
+ /* Will hold the entry found */
+ struct inode **pt_emd_dir) /* Will hold the emd_dir inode or NULL if not found */
+
{
/* #Specification: EMD file structure
- The EMD file uses a fairly simple layout. It is made of records
- (UMSDOS_REC_SIZE == 64). When a name can't be written is a single
- record, multiple contiguous record are allocated.
- */
+ * The EMD file uses a fairly simple layout. It is made of records
+ * (UMSDOS_REC_SIZE == 64). When a name can't be written is a single
+ * record, multiple contiguous record are allocated.
+ */
int ret = -ENOENT;
struct inode *emd_dir;
struct umsdos_dirent *entry = &info->entry;
-
+
Printk (("umsdos_find: locating %.*s in dir %lu\n", entry->name_len, entry->name, dir->i_ino));
-
+
emd_dir = umsdos_emd_dir_lookup (dir, 1);
- if (emd_dir != NULL){
+ if (emd_dir != NULL) {
int recsize = info->recsize;
struct {
off_t posok; /* Position available to store the entry */
- int found; /* A valid empty position has been found */
- off_t one; /* One empty position -> maybe <- large enough */
+ int found; /* A valid empty position has been found */
+ off_t one; /* One empty position -> maybe <- large enough */
int onesize; /* size of empty region starting at one */
- }empty;
+ } empty;
+
/* Read several entries at a time to speed up the search */
struct find_buffer buf;
struct dentry *dentry;
- memset (&buf.filp, 0, sizeof (buf.filp));
-
dentry = creat_dentry ("umsfind-mn", 10, emd_dir, NULL);
-
+
fill_new_filp (&buf.filp, dentry);
buf.pos = 0;
@@ -670,218 +599,225 @@ static int umsdos_find (
empty.found = 0;
empty.posok = emd_dir->i_size;
empty.onesize = 0;
- while (1){
- struct umsdos_dirent *rentry = (struct umsdos_dirent*)
- (buf.buffer + buf.pos);
+ while (1) {
+ struct umsdos_dirent *rentry = (struct umsdos_dirent *)
+ (buf.buffer + buf.pos);
int file_pos = buf.filp.f_pos - buf.size + buf.pos;
- if (buf.pos == buf.size){
- ret = umsdos_fillbuf (emd_dir,&buf);
- if (ret < 0){
+
+ if (buf.pos == buf.size) {
+ ret = umsdos_fillbuf (emd_dir, &buf);
+ if (ret < 0) {
/* Not found, so note where it can be added */
info->f_pos = empty.posok;
break;
}
- }else if (rentry->name_len == 0){
+ } else if (rentry->name_len == 0) {
/* We are looking for an empty section at least */
/* recsize large */
- if (entry->name_len == 0){
+ if (entry->name_len == 0) {
info->f_pos = file_pos;
ret = 0;
break;
- }else if (!empty.found){
- if (empty.onesize == 0){
+ } else if (!empty.found) {
+ if (empty.onesize == 0) {
/* This is the first empty record of a section */
empty.one = file_pos;
}
/* grow the empty section */
empty.onesize += UMSDOS_REC_SIZE;
- if (empty.onesize == recsize){
+ if (empty.onesize == recsize) {
/* here is a large enough section */
empty.posok = empty.one;
empty.found = 1;
}
}
buf.pos += UMSDOS_REC_SIZE;
- }else{
- int entry_size = umsdos_evalrecsize(rentry->name_len);
- if (buf.pos+entry_size > buf.size){
- ret = umsdos_fillbuf (emd_dir,&buf);
- if (ret < 0){
+ } else {
+ int entry_size = umsdos_evalrecsize (rentry->name_len);
+
+ if (buf.pos + entry_size > buf.size) {
+ ret = umsdos_fillbuf (emd_dir, &buf);
+ if (ret < 0) {
/* Not found, so note where it can be added */
info->f_pos = empty.posok;
break;
}
- }else{
+ } else {
empty.onesize = 0; /* Reset the free slot search */
if (entry->name_len == rentry->name_len
- && memcmp(entry->name,rentry->name,rentry->name_len)
- ==0){
+ && memcmp (entry->name, rentry->name, rentry->name_len)
+ == 0) {
info->f_pos = file_pos;
*entry = *rentry;
ret = 0;
break;
- }else{
+ } else {
buf.pos += entry_size;
}
}
- }
+ }
}
- umsdos_manglename(info);
+ umsdos_manglename (info);
}
*pt_emd_dir = emd_dir;
-
+
Printk (("umsdos_find: returning %d\n", ret));
return ret;
}
+
/*
- Add a new entry in the emd file
- Return 0 if ok or a negative error code.
- Return -EEXIST if the entry already exist.
+ * Add a new entry in the emd file
+ * Return 0 if ok or a negative error code.
+ * Return -EEXIST if the entry already exist.
+ *
+ * Complete the information missing in info.
+ */
- Complete the information missing in info.
-*/
int umsdos_newentry (
- struct inode *dir,
- struct umsdos_info *info)
+ struct inode *dir,
+ struct umsdos_info *info)
{
struct inode *emd_dir;
- int ret = umsdos_find (dir,info,&emd_dir);
- if (ret == 0){
+ int ret = umsdos_find (dir, info, &emd_dir);
+
+ if (ret == 0) {
ret = -EEXIST;
- }else if (ret == -ENOENT){
- ret = umsdos_writeentry(dir,emd_dir,info,0);
- Printk (("umsdos_newentry EMD ret = %d\n",ret));
+ } else if (ret == -ENOENT) {
+ ret = umsdos_writeentry (dir, emd_dir, info, 0);
+ Printk (("umsdos_writeentry EMD ret = %d\n", ret));
}
- /* iput (emd_dir); FIXME */
+ iput (emd_dir); /* FIXME? */
return ret;
}
+
/*
- Create a new hidden link.
- Return 0 if ok, an error code if not.
-*/
+ * Create a new hidden link.
+ * Return 0 if ok, an error code if not.
+ */
+
int umsdos_newhidden (
- struct inode *dir,
- struct umsdos_info *info)
+ struct inode *dir,
+ struct umsdos_info *info)
{
struct inode *emd_dir;
int ret;
- umsdos_parse ("..LINK",6,info);
+
+ umsdos_parse ("..LINK", 6, info);
info->entry.name_len = 0;
- ret = umsdos_find (dir,info,&emd_dir);
- /* iput (emd_dir); FIXME */
- if (ret == -ENOENT || ret == 0){
+ ret = umsdos_find (dir, info, &emd_dir);
+ iput (emd_dir); /* FIXME? */
+ if (ret == -ENOENT || ret == 0) {
/* #Specification: hard link / hidden name
- When a hard link is created, the original file is renamed
- to a hidden name. The name is "..LINKNNN" where NNN is a
- number define from the entry offset in the EMD file.
- */
- info->entry.name_len = sprintf (info->entry.name,"..LINK%ld"
- ,info->f_pos);
+ * When a hard link is created, the original file is renamed
+ * to a hidden name. The name is "..LINKNNN" where NNN is a
+ * number define from the entry offset in the EMD file.
+ */
+ info->entry.name_len = sprintf (info->entry.name, "..LINK%ld"
+ ,info->f_pos);
ret = 0;
}
return ret;
}
/*
- Remove an entry from the emd file
- Return 0 if ok, a negative error code otherwise.
+ * Remove an entry from the emd file
+ * Return 0 if ok, a negative error code otherwise.
+ *
+ * Complete the information missing in info.
+ */
- Complete the information missing in info.
-*/
int umsdos_delentry (
- struct inode *dir,
- struct umsdos_info *info,
- int isdir)
+ struct inode *dir,
+ struct umsdos_info *info,
+ int isdir)
{
struct inode *emd_dir;
- int ret = umsdos_find (dir,info,&emd_dir);
- if (ret == 0){
- if (info->entry.name_len != 0){
- if ((isdir != 0) != (S_ISDIR(info->entry.mode) != 0)){
- if (S_ISDIR(info->entry.mode)){
+ int ret = umsdos_find (dir, info, &emd_dir);
+
+ if (ret == 0) {
+ if (info->entry.name_len != 0) {
+ if ((isdir != 0) != (S_ISDIR (info->entry.mode) != 0)) {
+ if (S_ISDIR (info->entry.mode)) {
ret = -EISDIR;
- }else{
+ } else {
ret = -ENOTDIR;
}
- }else{
- ret = umsdos_writeentry(dir,emd_dir,info,1);
+ } else {
+ ret = umsdos_writeentry (dir, emd_dir, info, 1);
}
}
}
- /* iput(emd_dir); FIXME */
+ iput(emd_dir); /* FIXME? */
return ret;
}
/*
- Verify is a EMD directory is empty.
- Return 0 if not empty
- 1 if empty
- 2 if empty, no EMD file.
-*/
+ * Verify is a EMD directory is empty.
+ * Return 0 if not empty
+ * 1 if empty
+ * 2 if empty, no EMD file.
+ */
+
int umsdos_isempty (struct inode *dir)
{
struct dentry *dentry;
-
+
int ret = 2;
- struct inode *emd_dir = umsdos_emd_dir_lookup(dir,0);
+ struct inode *emd_dir = umsdos_emd_dir_lookup (dir, 0);
+
/* If the EMD file does not exist, it is certainly empty :-) */
- if (emd_dir != NULL){
+ if (emd_dir != NULL) {
struct file filp;
- fill_new_filp (&filp, NULL);
-
- /* Find an empty slot */
- memset (&filp, 0, sizeof (filp));
dentry = creat_dentry ("isempty-mn", 10, dir, NULL);
-
- filp.f_pos = 0;
- filp.f_reada = 1;
+ fill_new_filp (&filp, dentry);
filp.f_flags = O_RDONLY;
- filp.f_dentry = dentry;
- filp.f_op = &umsdos_file_operations; /* /mn/ - we have to fill it with dummy values so we won't segfault */
-
+
ret = 1;
- while (filp.f_pos < emd_dir->i_size){
+ while (filp.f_pos < emd_dir->i_size) {
struct umsdos_dirent entry;
- if (umsdos_emd_dir_readentry(emd_dir,&filp,&entry)!=0){
+
+ if (umsdos_emd_dir_readentry (emd_dir, &filp, &entry) != 0) {
ret = 0;
break;
- }else if (entry.name_len != 0){
+ } else if (entry.name_len != 0) {
ret = 0;
break;
- }
+ }
}
- /* iput (emd_dir); FIXME */
+ iput (emd_dir); /* FIXME? */
}
return ret;
}
/*
- Locate an entry in a EMD directory.
- Return 0 if ok, errcod if not, generally -ENOENT.
-*/
+ * Locate an entry in a EMD directory.
+ * Return 0 if ok, errcod if not, generally -ENOENT.
+ */
+
int umsdos_findentry (
- struct inode *dir,
- struct umsdos_info *info,
- int expect) /* 0: anything */
- /* 1: file */
- /* 2: directory */
-{
+ struct inode *dir,
+ struct umsdos_info *info,
+ int expect)
+{ /* 0: anything */
+ /* 1: file */
+ /* 2: directory */
struct inode *emd_dir;
- int ret = umsdos_find (dir,info,&emd_dir);
- if (ret == 0){
- if (expect != 0){
- if (S_ISDIR(info->entry.mode)){
- if (expect != 2) ret = -EISDIR;
- }else if (expect == 2){
+ int ret = umsdos_find (dir, info, &emd_dir);
+
+ if (ret == 0) {
+ if (expect != 0) {
+ if (S_ISDIR (info->entry.mode)) {
+ if (expect != 2)
+ ret = -EISDIR;
+ } else if (expect == 2) {
ret = -ENOTDIR;
}
}
}
- /* iput (emd_dir); FIXME */
+ iput (emd_dir); /* FIXME? */
Printk (("umsdos_findentry: returning %d\n", ret));
return ret;
}
-
diff --git a/fs/umsdos/file.c b/fs/umsdos/file.c
index b7f58a2b9..a9267e122 100644
--- a/fs/umsdos/file.c
+++ b/fs/umsdos/file.c
@@ -2,7 +2,7 @@
* linux/fs/umsdos/file.c
*
* Written 1993 by Jacques Gelinas
- * inspired from linux/fs/msdos/file.c Werner Almesberger
+ * inspired from linux/fs/msdos/file.c Werner Almesberger
*
* Extended MS-DOS regular file handling primitives
*/
@@ -24,71 +24,74 @@
/*
- Read a file into user space memory
-*/
-static ssize_t UMSDOS_file_read(
- struct file *filp,
- char *buf,
- size_t count,
- loff_t *ppos
- )
+ * Read a file into user space memory
+ */
+static ssize_t UMSDOS_file_read (
+ struct file *filp,
+ char *buf,
+ size_t count,
+ loff_t * ppos
+)
{
- struct dentry * dentry = filp->f_dentry;
+ struct dentry *dentry = filp->f_dentry;
struct inode *inode = dentry->d_inode;
-
+
/* We have to set the access time because msdos don't care */
/* FIXME */
- int ret = fat_file_read(filp,buf,count,ppos);
- if (!IS_RDONLY(inode)){
+ int ret = fat_file_read (filp, buf, count, ppos);
+
+ if (!IS_RDONLY (inode)) {
inode->i_atime = CURRENT_TIME;
/* FIXME
- inode->i_dirt = 1;
- */
+ * inode->i_dirt = 1;
+ */
}
return ret;
}
/*
- Write a file from user space memory
-*/
-static ssize_t UMSDOS_file_write(
- struct file *filp,
- const char *buf,
- size_t count,
- loff_t *ppos)
+ * Write a file from user space memory
+ */
+static ssize_t UMSDOS_file_write (
+ struct file *filp,
+ const char *buf,
+ size_t count,
+ loff_t * ppos)
{
- return fat_file_write(filp,buf,count,ppos);
+ return fat_file_write (filp, buf, count, ppos);
}
/*
- Truncate a file to 0 length.
-*/
-static void UMSDOS_truncate(struct inode *inode)
+ * Truncate a file to 0 length.
+ */
+static void UMSDOS_truncate (struct inode *inode)
{
Printk (("UMSDOS_truncate\n"));
fat_truncate (inode);
inode->i_ctime = inode->i_mtime = CURRENT_TIME;
-
- /*FIXME inode->i_dirt = 1; */
+
+ /*FIXME inode->i_dirt = 1; */
}
/* Function for normal file system (512 bytes hardware sector size) */
-struct file_operations umsdos_file_operations = {
- NULL, /* lseek - default */
+struct file_operations umsdos_file_operations =
+{
+ NULL, /* lseek - default */
UMSDOS_file_read, /* read */
UMSDOS_file_write, /* write */
- NULL, /* readdir - bad */
- NULL, /* poll - default */
- NULL, /* ioctl - default */
- generic_file_mmap, /* mmap */
- NULL, /* no special open is needed */
- NULL, /* release */
- file_fsync /* fsync */
+ NULL, /* readdir - bad */
+ NULL, /* poll - default */
+ NULL, /* ioctl - default */
+ generic_file_mmap, /* mmap */
+ NULL, /* no special open is needed */
+ NULL, /* release */
+ file_fsync /* fsync */
};
-struct inode_operations umsdos_file_inode_operations = {
+struct inode_operations umsdos_file_inode_operations =
+{
&umsdos_file_operations, /* default file operations */
NULL, /* create */
NULL, /* lookup */
@@ -110,20 +113,22 @@ struct inode_operations umsdos_file_inode_operations = {
};
/* For other with larger and unaligned file system */
-struct file_operations umsdos_file_operations_no_bmap = {
- NULL, /* lseek - default */
- UMSDOS_file_read, /* read */
- UMSDOS_file_write, /* write */
- NULL, /* readdir - bad */
- NULL, /* poll - default */
- NULL, /* ioctl - default */
- fat_mmap, /* mmap */
- NULL, /* no special open is needed */
- NULL, /* release */
- file_fsync /* fsync */
+struct file_operations umsdos_file_operations_no_bmap =
+{
+ NULL, /* lseek - default */
+ UMSDOS_file_read, /* read */
+ UMSDOS_file_write, /* write */
+ NULL, /* readdir - bad */
+ NULL, /* poll - default */
+ NULL, /* ioctl - default */
+ fat_mmap, /* mmap */
+ NULL, /* no special open is needed */
+ NULL, /* release */
+ file_fsync /* fsync */
};
-struct inode_operations umsdos_file_inode_operations_no_bmap = {
+struct inode_operations umsdos_file_inode_operations_no_bmap =
+{
&umsdos_file_operations_no_bmap, /* default file operations */
NULL, /* create */
NULL, /* lookup */
@@ -135,7 +140,7 @@ struct inode_operations umsdos_file_inode_operations_no_bmap = {
NULL, /* mknod */
NULL, /* rename */
NULL, /* readlink */
- NULL, /* follow link */
+ NULL, /* follow link */
NULL, /* readpage */
NULL, /* writepage */
NULL, /* bmap */
@@ -145,20 +150,22 @@ struct inode_operations umsdos_file_inode_operations_no_bmap = {
};
/* For other with larger and unaligned file system with readpage */
-struct file_operations umsdos_file_operations_readpage = {
- NULL, /* lseek - default */
- UMSDOS_file_read, /* read */
- UMSDOS_file_write, /* write */
- NULL, /* readdir - bad */
- NULL, /* poll - default */
- NULL, /* ioctl - default */
- generic_file_mmap, /* mmap */
- NULL, /* no special open is needed */
- NULL, /* release */
- file_fsync /* fsync */
+struct file_operations umsdos_file_operations_readpage =
+{
+ NULL, /* lseek - default */
+ UMSDOS_file_read, /* read */
+ UMSDOS_file_write, /* write */
+ NULL, /* readdir - bad */
+ NULL, /* poll - default */
+ NULL, /* ioctl - default */
+ generic_file_mmap, /* mmap */
+ NULL, /* no special open is needed */
+ NULL, /* release */
+ file_fsync /* fsync */
};
-struct inode_operations umsdos_file_inode_operations_readpage = {
+struct inode_operations umsdos_file_inode_operations_readpage =
+{
&umsdos_file_operations_readpage, /* default file operations */
NULL, /* create */
NULL, /* lookup */
@@ -170,7 +177,7 @@ struct inode_operations umsdos_file_inode_operations_readpage = {
NULL, /* mknod */
NULL, /* rename */
NULL, /* readlink */
- NULL, /* follow link */
+ NULL, /* follow link */
fat_readpage, /* readpage */
NULL, /* writepage */
NULL, /* bmap */
@@ -178,4 +185,3 @@ struct inode_operations umsdos_file_inode_operations_readpage = {
NULL, /* permission */
NULL, /* smap */
};
-
diff --git a/fs/umsdos/inode.c b/fs/umsdos/inode.c
index 0238a5bd1..4bf2a65ce 100644
--- a/fs/umsdos/inode.c
+++ b/fs/umsdos/inode.c
@@ -1,8 +1,8 @@
/*
* linux/fs/umsdos/inode.c
*
- * Written 1993 by Jacques Gelinas
- * Inspired from linux/fs/msdos/... by Werner Almesberger
+ * Written 1993 by Jacques Gelinas
+ * Inspired from linux/fs/msdos/... by Werner Almesberger
*
*/
@@ -18,122 +18,348 @@
#include <linux/string.h>
#include <linux/stat.h>
#include <linux/umsdos_fs.h>
+#include <linux/list.h>
-struct inode *pseudo_root=NULL; /* Useful to simulate the pseudo DOS */
- /* directory. See UMSDOS_readdir_x() */
+extern struct inode_operations umsdos_rdir_inode_operations;
+
+
+struct inode *pseudo_root = NULL; /* Useful to simulate the pseudo DOS */
+
+ /* directory. See UMSDOS_readdir_x() */
/* #Specification: convention / PRINTK Printk and printk
- Here is the convention for the use of printk inside fs/umsdos
-
- printk carry important message (error or status).
- Printk is for debugging (it is a macro defined at the beginning of
- most source.
- PRINTK is a nulled Printk macro.
-
- This convention makes the source easier to read, and Printk easier
- to shut off.
-*/
+ * Here is the convention for the use of printk inside fs/umsdos
+ *
+ * printk carry important message (error or status).
+ * Printk is for debugging (it is a macro defined at the beginning of
+ * most source.
+ * PRINTK is a nulled Printk macro.
+ *
+ * This convention makes the source easier to read, and Printk easier
+ * to shut off.
+ */
#define PRINTK(x)
#define Printk(x) printk x
-void UMSDOS_put_inode(struct inode *inode)
+
+
+
+/*
+ * makes return inode->i_dentry
+ *
+ */
+
+inline struct dentry *geti_dentry (struct inode *inode)
{
- PRINTK ((KERN_DEBUG "put inode %p (%lu) owner %lu pos %lu dir %lu\n", inode, inode->i_ino
- ,inode->u.umsdos_i.i_emd_owner, inode->u.umsdos_i.pos
- ,inode->u.umsdos_i.i_emd_dir));
- if (inode && pseudo_root && inode == pseudo_root){
- printk (KERN_ERR "Umsdos: Oops releasing pseudo_root. Notify jacques@solucorp.qc.ca\n");
- }
-
-#if 1
- fat_put_inode(inode);
-#else
- Printk ((KERN_WARNING "UMSDOS_put_inode: skipping ! FIXME /mn/\n"));
-#endif
+ struct dentry *ret;
+ if (!inode) {
+ printk (KERN_ERR "geti_dentry: inode is NULL!\n");
+ return NULL;
+ }
+ ret = list_entry (inode->i_dentry.next, struct dentry, d_alias); /* FIXME: does this really work ? :) */
+ Printk ((KERN_DEBUG "geti_dentry : inode %lu: i_dentry is %p\n", inode->i_ino, ret));
+ return ret;
}
+/*
+ * makes inode->i_count++
+ *
+ */
-void UMSDOS_put_super(struct super_block *sb)
+inline void inc_count (struct inode *inode)
{
- Printk ((KERN_DEBUG "UMSDOS_put_super: entering\n"));
- msdos_put_super(sb);
- MOD_DEC_USE_COUNT;
+ inode->i_count++;
+ Printk ((KERN_DEBUG "inc_count: inode %lu incremented count to %d\n", inode->i_ino, inode->i_count));
}
+/*
+ * makes empty filp
+ *
+ */
+
+void fill_new_filp (struct file *filp, struct dentry *dentry)
+{
+ Printk (("/mn/ fill_new_filp: filling empty filp at %p\n", filp));
+ if (dentry)
+ Printk ((" dentry=%.*s\n", (int) dentry->d_name.len, dentry->d_name.name));
+ else
+ Printk ((" dentry is NULL ! you must fill it later...\n"));
+
+ memset (filp, 0, sizeof (struct file));
+
+ filp->f_pos = 0;
+ filp->f_reada = 1;
+ filp->f_flags = O_RDWR;
+ filp->f_dentry = dentry;
+ filp->f_op = &umsdos_file_operations; /* /mn/ - we have to fill it with SOMETHING */
+}
/*
- Call msdos_lookup, but set back the original msdos function table.
- Return 0 if ok, or a negative error code if not.
-*/
-int umsdos_real_lookup (
- struct inode *dir,
- struct dentry *dentry
- ) /* Will hold inode of the file, if successful */
+ * check a superblock
+ */
+
+void check_sb (struct super_block *sb, const char c)
+{
+ if (sb) {
+ Printk ((" (has %c_sb=%d, %d)", c, MAJOR (sb->s_dev), MINOR (sb->s_dev)));
+ } else {
+ Printk ((" (%c_sb is NULL)", c));
+ }
+}
+
+/*
+ * check an inode
+ */
+
+void check_inode (struct inode *inode)
+{
+ if (inode) {
+ Printk ((KERN_DEBUG "* inode is %lu (i_count=%d)", inode->i_ino, inode->i_count));
+ check_sb (inode->i_sb, 'i');
+
+ if (inode->i_dentry.next) { /* FIXME: does this work ? */
+ Printk ((" (has i_dentry)"));
+ } else {
+ Printk ((" (NO i_dentry)"));
+ }
+
+ if (inode->i_op == NULL) {
+ Printk ((" (i_op is NULL)\n"));
+ } else if (inode->i_op == &umsdos_dir_inode_operations) {
+ Printk ((" (i_op is umsdos_dir_inode_operations)\n"));
+ } else if (inode->i_op == &umsdos_file_inode_operations) {
+ Printk ((" (i_op is umsdos_file_inode_operations)\n"));
+ } else if (inode->i_op == &umsdos_file_inode_operations_no_bmap) {
+ Printk ((" (i_op is umsdos_file_inode_operations_no_bmap)\n"));
+ } else if (inode->i_op == &umsdos_file_inode_operations_readpage) {
+ Printk ((" (i_op is umsdos_file_inode_operations_readpage)\n"));
+ } else if (inode->i_op == &umsdos_rdir_inode_operations) {
+ Printk ((" (i_op is umsdos_rdir_inode_operations)\n"));
+ } else if (inode->i_op == &umsdos_symlink_inode_operations) {
+ Printk ((" (i_op is umsdos_symlink_inode_operations)\n"));
+ } else {
+ Printk ((" (i_op is UNKNOWN: %p)\n", inode->i_op));
+ }
+ } else {
+ Printk ((KERN_DEBUG "* inode is NULL\n"));
+ }
+}
+
+
+/*
+ * internal part of check_dentry. does the real job.
+ *
+ */
+
+void check_dent_int (struct dentry *dentry, int parent)
+{
+ if (parent) {
+ Printk ((KERN_DEBUG "* parent dentry: %.*s\n", (int) dentry->d_name.len, dentry->d_name.name));
+ } else {
+ Printk ((KERN_DEBUG "\n*** checking dentry: %.*s\n", (int) dentry->d_name.len, dentry->d_name.name));
+ }
+ check_inode (dentry->d_inode);
+ Printk ((KERN_DEBUG "* d_count=%d", dentry->d_count));
+ check_sb (dentry->d_sb, 'd');
+ if (dentry->d_op == NULL) {
+ Printk ((" (d_op is NULL)\n"));
+ } else {
+ Printk ((" (d_op is UNKNOWN: %p)\n", dentry->d_op));
+ }
+}
+
+/*
+ * checks dentry and prints info
+ *
+ */
+
+void check_dentry (struct dentry *dentry)
{
- int ret;
-
- PRINTK ((KERN_DEBUG "umsdos_real_lookup /mn/: looking for %s /",dentry->d_name.name));
- dir->i_count++; /* /mn/ what is this and why ? locking? */
- ret = msdos_lookup (dir,dentry);
- PRINTK (("/ returned %d\n", ret));
-
- return ret;
+ if (!dentry) {
+ Printk ((KERN_DEBUG "\n*** checking dentry... it is NULL !\n"));
+ return;
+ }
+ check_dent_int (dentry, 0);
+
+ if (dentry->d_parent) {
+ check_dent_int (dentry->d_parent, 1);
+ } else {
+ Printk ((KERN_DEBUG "* has no parent.\n"));
+ }
+
+ Printk ((KERN_DEBUG "*** end checking dentry\n"));
}
+
/*
- Complete the setup of an directory inode.
- First, it completes the function pointers, then
- it locates the EMD file. If the EMD is there, then plug the
- umsdos function table. If not, use the msdos one.
-*/
+ * makes dentry. for name name with length len. /mn/
+ * if inode is not NULL, puts it also.
+ *
+ */
+
+struct dentry *creat_dentry (const char *name, const int len, struct inode *inode, struct dentry *parent)
+{
+/* FIXME /mn/: parent is not passed many times... if it is not, dentry should be destroyed before someone else gets to use it */
+
+ struct dentry *ret;
+ struct qstr qname;
+
+ if (inode)
+ Printk ((KERN_DEBUG "/mn/ creat_dentry: creating dentry with inode=%lu for %.*s\n", inode->i_ino, len, name));
+ else
+ Printk ((KERN_DEBUG "/mn/ creat_dentry: creating empty dentry for %.*s\n", len, name));
+
+ qname.name = name;
+ qname.len = len;
+ qname.hash = 0;
+
+ ret = d_alloc (parent, &qname); /* create new dentry */
+ ret->d_inode = NULL;
+
+ if (!parent) {
+ ret->d_parent = ret;
+ Printk ((KERN_WARNING "creat_dentry: WARNING: NO parent! faking! beware !\n"));
+ }
+
+
+ if (inode) {
+ ret->d_sb = inode->i_sb; /* try to fill it in if avalaible. If avalaible in parent->d_sb, d_alloc will add it automatically */
+ d_add (ret, inode);
+ }
+
+ return ret;
+}
+
+
+/*
+ * removes temporary dentry created by creat_dentry
+ *
+ */
+
+void kill_dentry (struct dentry *dentry)
+{
+ if (dentry) {
+ Printk (("/mn/ kill_dentry: kill_dentry %.*s :", (int) dentry->d_name.len, dentry->d_name.name));
+ if (dentry->d_inode)
+ Printk (("inode=%lu (i_count=%d)\n", dentry->d_inode->i_ino, dentry->d_inode->i_count));
+ else
+ Printk (("inode is NULL\n"));
+
+ /* FIXME: is this ok ?! /mn/ */
+ /* d_drop (dentry); */
+ /* d_invalidate (dentry); */
+ /*dput (dentry); */
+ /*d_delete (dentry) */
+ } else {
+ Printk (("/mn/ kill_dentry: dentry is NULL ?!\n"));
+ }
+
+
+ Printk ((KERN_DEBUG "/mn/ kill_dentry: exiting...\n"));
+ return;
+}
+
+
+
+
+
+
+void UMSDOS_put_inode (struct inode *inode)
+{
+ PRINTK ((KERN_DEBUG "put inode %p (%lu) owner %lu pos %lu dir %lu count=%d\n", inode, inode->i_ino
+ ,inode->u.umsdos_i.i_emd_owner, inode->u.umsdos_i.pos
+ ,inode->u.umsdos_i.i_emd_dir, inode->i_count));
+
+ if (inode && pseudo_root && inode == pseudo_root) {
+ printk (KERN_ERR "Umsdos: Oops releasing pseudo_root. Notify jacques@solucorp.qc.ca\n");
+ }
+
+ fat_put_inode (inode);
+}
+
+
+void UMSDOS_put_super (struct super_block *sb)
+{
+ Printk ((KERN_DEBUG "UMSDOS_put_super: entering\n"));
+ msdos_put_super (sb);
+ MOD_DEC_USE_COUNT;
+}
+
+
+
+/*
+ * Call msdos_lookup, but set back the original msdos function table.
+ * Return 0 if ok, or a negative error code if not.
+ */
+int umsdos_real_lookup (
+ struct inode *dir,
+ struct dentry *dentry
+)
+{ /* Will hold inode of the file, if successful */
+ int ret;
+
+ PRINTK ((KERN_DEBUG "umsdos_real_lookup: looking for %s /", dentry->d_name.name));
+ inc_count (dir); /* should be here ? Causes all kind of missing iput()'s all around, but panics w/o it /mn/ */
+ ret = msdos_lookup (dir, dentry);
+ PRINTK (("/ returned %d\n", ret));
+
+ return ret;
+}
+
+/*
+ * Complete the setup of an directory inode.
+ * First, it completes the function pointers, then
+ * it locates the EMD file. If the EMD is there, then plug the
+ * umsdos function table. If not, use the msdos one.
+ */
void umsdos_setup_dir_inode (struct inode *inode)
{
- inode->u.umsdos_i.i_emd_dir = 0;
- {
- struct inode *emd_dir = NULL;
- extern struct inode_operations umsdos_rdir_inode_operations;
-
- emd_dir = umsdos_emd_dir_lookup (inode,0);
- Printk ((KERN_DEBUG "umsdos_setup_dir_inode: umsdos_emd_dir_lookup for inode=%p returned %p\n",inode,emd_dir));
-
- if (emd_dir == NULL) {
- Printk ((KERN_DEBUG "umsdos_setup_dir_inode /mn/: Setting up dir_inode_ops --> eg. NOT using EMD.\n"));
- inode->i_op = &umsdos_rdir_inode_operations;
- } else {
- Printk ((KERN_DEBUG "umsdos_setup_dir_inode /mn/: Setting up rdir_inode_ops --> eg. using EMD.\n"));
- inode->i_op = &umsdos_dir_inode_operations;
- }
-
-/* iput (emd_dir); FIXME /mn/ ! */
- }
+ inode->u.umsdos_i.i_emd_dir = 0;
+ {
+ struct inode *emd_dir;
+
+ emd_dir = umsdos_emd_dir_lookup (inode, 0);
+ Printk ((KERN_DEBUG "umsdos_setup_dir_inode: umsdos_emd_dir_lookup for inode=%p returned %p\n", inode, emd_dir));
+
+ if (emd_dir == NULL) {
+ Printk ((KERN_DEBUG "umsdos_setup_dir_inode /mn/: Setting up rdir_inode_ops --> eg. NOT using EMD.\n"));
+ inode->i_op = &umsdos_rdir_inode_operations;
+ } else {
+ Printk ((KERN_DEBUG "umsdos_setup_dir_inode /mn/: Setting up dir_inode_ops --> eg. using EMD.\n"));
+ inode->i_op = &umsdos_dir_inode_operations;
+ }
+
+ iput (emd_dir); /* FIXME? OK? */
+ }
}
/*
- Add some info into an inode so it can find its owner quickly
-*/
-void umsdos_set_dirinfo(
- struct inode *inode,
- struct inode *dir,
- off_t f_pos)
+ * Add some info into an inode so it can find its owner quickly
+ */
+void umsdos_set_dirinfo (
+ struct inode *inode,
+ struct inode *dir,
+ off_t f_pos)
{
- struct inode *emd_owner;
- /* FIXME, I don't have a clue on this one - /mn/ hmmm ? ok ? */
-/* Printk ((KERN_WARNING "umsdos_set_dirinfo: /mn/ FIXME: no clue. inode=%lu dir=%lu\n", inode->i_ino, dir->i_ino));*/
- emd_owner = umsdos_emd_dir_lookup(dir,1);
- Printk (("umsdos_set_dirinfo: emd_owner is %lu for dir %lu\n", emd_owner->i_ino, dir->i_ino));
- inode->u.umsdos_i.i_dir_owner = dir->i_ino;
- inode->u.umsdos_i.i_emd_owner = emd_owner->i_ino;
- /* iput (emd_owner); FIXME */
- inode->u.umsdos_i.pos = f_pos;
+ struct inode *emd_owner;
+
+ /* FIXME, I don't have a clue on this one - /mn/ hmmm ? ok ? */
+/* Printk ((KERN_WARNING "umsdos_set_dirinfo: /mn/ FIXME: no clue. inode=%lu dir=%lu\n", inode->i_ino, dir->i_ino)); */
+ emd_owner = umsdos_emd_dir_lookup (dir, 1);
+ Printk (("umsdos_set_dirinfo: emd_owner is %lu for dir %lu\n", emd_owner->i_ino, dir->i_ino));
+ inode->u.umsdos_i.i_dir_owner = dir->i_ino;
+ inode->u.umsdos_i.i_emd_owner = emd_owner->i_ino;
+ iput (emd_owner); /* FIXME? */
+ inode->u.umsdos_i.pos = f_pos;
}
/*
- Tells if an Umsdos inode has been "patched" once.
- Return != 0 if so.
-*/
+ * Tells if an Umsdos inode has been "patched" once.
+ * Return != 0 if so.
+ */
int umsdos_isinit (struct inode *inode)
{
#if 1
@@ -141,125 +367,129 @@ int umsdos_isinit (struct inode *inode)
#elif 0
return inode->i_atime != 0;
#else
- return atomic_read(&inode->i_count) > 1;
+ return atomic_read (&inode->i_count) > 1;
#endif
}
/*
- Connect the proper tables in the inode and add some info.
-*/
+ * Connect the proper tables in the inode and add some info.
+ */
void umsdos_patch_inode (
- struct inode *inode,
- struct inode *dir, /* May be NULL */
- off_t f_pos)
+ struct inode *inode,
+ struct inode *dir, /* May be NULL */
+ off_t f_pos)
{
- /*
- This function is called very early to setup the inode, somewhat
- too early (called by UMSDOS_read_inode). At this point, we can't
- do to much, such as lookup up EMD files and so on. This causes
- confusion in the kernel. This is why some initialisation
- will be done when dir != NULL only.
-
- UMSDOS do run piggy back on top of msdos fs. It looks like something
- is missing in the VFS to accommodate stacked fs. Still unclear what
- (quite honestly).
-
- Well, maybe one! A new entry "may_unmount" which would allow
- the stacked fs to allocate some inode permanently and release
- them at the end. Doing that now introduce a problem. unmount
- always fail because some inodes are in use.
- */
-
- Printk ((KERN_DEBUG "Entering umsdos_patch_inode for inode=%lu\n", inode->i_ino));
-
- if (!umsdos_isinit(inode)){
- inode->u.umsdos_i.i_emd_dir = 0;
- if (S_ISREG(inode->i_mode)){
- if (MSDOS_SB(inode->i_sb)->cvf_format){
- if (MSDOS_SB(inode->i_sb)->cvf_format->flags&CVF_USE_READPAGE){
- Printk ((KERN_DEBUG "umsdos_patch_inode /mn/: seting i_op = umsdos_file_inode_operations_readpage\n"));
- inode->i_op = &umsdos_file_inode_operations_readpage;
- }else{
- Printk ((KERN_DEBUG "umsdos_patch_inode /mn/: seting i_op = umsdos_file_inode_operations_no_bmap\n"));
- inode->i_op = &umsdos_file_inode_operations_no_bmap;
- }
- }else{
- if (inode->i_op->bmap != NULL){
- Printk ((KERN_DEBUG "umsdos_patch_inode /mn/: seting i_op = umsdos_file_inode_operations\n"));
- inode->i_op = &umsdos_file_inode_operations;
- }else{
- Printk ((KERN_DEBUG "umsdos_patch_inode /mn/: seting i_op = umsdos_file_inode_operations_no_bmap\n"));
- inode->i_op = &umsdos_file_inode_operations_no_bmap;
- }
- }
- }else if (S_ISDIR(inode->i_mode)){
- if (dir != NULL){
- umsdos_setup_dir_inode(inode);
- }
- }else if (S_ISLNK(inode->i_mode)){
- Printk ((KERN_DEBUG "umsdos_patch_inode /mn/: seting i_op = umsdos_symlink_inode_operations\n"));
- inode->i_op = &umsdos_symlink_inode_operations;
- }else if (S_ISCHR(inode->i_mode)){
- Printk ((KERN_DEBUG "umsdos_patch_inode /mn/: seting i_op = chrdev_inode_operations\n"));
- inode->i_op = &chrdev_inode_operations;
- }else if (S_ISBLK(inode->i_mode)){
- Printk ((KERN_DEBUG "umsdos_patch_inode /mn/: seting i_op = blkdev_inode_operations\n"));
- inode->i_op = &blkdev_inode_operations;
- }else if (S_ISFIFO(inode->i_mode)){
- Printk ((KERN_DEBUG "umsdos_patch_inode /mn/: uhm, init_fifo\n"));
- init_fifo(inode);
- }
- if (dir != NULL){
- /* #Specification: inode / umsdos info
- The first time an inode is seen (inode->i_count == 1),
- the inode number of the EMD file which control this inode
- is tagged to this inode. It allows operation such
- as notify_change to be handled.
- */
- /*
- This is done last because it also control the
- status of umsdos_isinit()
- */
- PRINTK ((KERN_DEBUG "umsdos_patch_inode /mn/: here we go: calling umsdos_set_dirinfo (%p,%p,%lu)\n", inode, dir, f_pos));
- umsdos_set_dirinfo (inode,dir,f_pos);
- }
- }else if (dir != NULL){
- /*
- Test to see if the info is maintained.
- This should be removed when the file system will be proven.
- */
- /* FIXME, again, not a clue */
- struct inode *emd_owner;
- Printk ((KERN_WARNING "umsdos_patch_inode: /mn/ Warning: untested emd_owner thingy...\n"));
- emd_owner = umsdos_emd_dir_lookup(dir,1);
- /* iput (emd_owner); FIXME */
- if (emd_owner->i_ino != inode->u.umsdos_i.i_emd_owner){
- printk ("UMSDOS: *** EMD_OWNER ??? *** ino = %ld %ld <> %ld "
- ,inode->i_ino,emd_owner->i_ino,inode->u.umsdos_i.i_emd_owner);
- }
- }
+ /*
+ * This function is called very early to setup the inode, somewhat
+ * too early (called by UMSDOS_read_inode). At this point, we can't
+ * do to much, such as lookup up EMD files and so on. This causes
+ * confusion in the kernel. This is why some initialisation
+ * will be done when dir != NULL only.
+ *
+ * UMSDOS do run piggy back on top of msdos fs. It looks like something
+ * is missing in the VFS to accommodate stacked fs. Still unclear what
+ * (quite honestly).
+ *
+ * Well, maybe one! A new entry "may_unmount" which would allow
+ * the stacked fs to allocate some inode permanently and release
+ * them at the end. Doing that now introduce a problem. unmount
+ * always fail because some inodes are in use.
+ */
+
+ Printk ((KERN_DEBUG "Entering umsdos_patch_inode for inode=%lu\n", inode->i_ino));
+
+ if (!umsdos_isinit (inode)) {
+ inode->u.umsdos_i.i_emd_dir = 0;
+ if (S_ISREG (inode->i_mode)) {
+ if (MSDOS_SB (inode->i_sb)->cvf_format) {
+ if (MSDOS_SB (inode->i_sb)->cvf_format->flags & CVF_USE_READPAGE) {
+ Printk ((KERN_DEBUG "umsdos_patch_inode /mn/: seting i_op = umsdos_file_inode_operations_readpage\n"));
+ inode->i_op = &umsdos_file_inode_operations_readpage;
+ } else {
+ Printk ((KERN_DEBUG "umsdos_patch_inode /mn/: seting i_op = umsdos_file_inode_operations_no_bmap\n"));
+ inode->i_op = &umsdos_file_inode_operations_no_bmap;
+ }
+ } else {
+ if (inode->i_op->bmap != NULL) {
+ Printk ((KERN_DEBUG "umsdos_patch_inode /mn/: seting i_op = umsdos_file_inode_operations\n"));
+ inode->i_op = &umsdos_file_inode_operations;
+ } else {
+ Printk ((KERN_DEBUG "umsdos_patch_inode /mn/: seting i_op = umsdos_file_inode_operations_no_bmap\n"));
+ inode->i_op = &umsdos_file_inode_operations_no_bmap;
+ }
+ }
+ } else if (S_ISDIR (inode->i_mode)) {
+ if (dir != NULL) {
+ umsdos_setup_dir_inode (inode);
+ }
+ } else if (S_ISLNK (inode->i_mode)) {
+ Printk ((KERN_DEBUG "umsdos_patch_inode /mn/: seting i_op = umsdos_symlink_inode_operations\n"));
+ inode->i_op = &umsdos_symlink_inode_operations;
+ } else if (S_ISCHR (inode->i_mode)) {
+ Printk ((KERN_DEBUG "umsdos_patch_inode /mn/: seting i_op = chrdev_inode_operations\n"));
+ inode->i_op = &chrdev_inode_operations;
+ } else if (S_ISBLK (inode->i_mode)) {
+ Printk ((KERN_DEBUG "umsdos_patch_inode /mn/: seting i_op = blkdev_inode_operations\n"));
+ inode->i_op = &blkdev_inode_operations;
+ } else if (S_ISFIFO (inode->i_mode)) {
+ Printk ((KERN_DEBUG "umsdos_patch_inode /mn/: uhm, init_fifo\n"));
+ init_fifo (inode);
+ }
+ if (dir != NULL) {
+ /* #Specification: inode / umsdos info
+ * The first time an inode is seen (inode->i_count == 1),
+ * the inode number of the EMD file which control this inode
+ * is tagged to this inode. It allows operation such
+ * as notify_change to be handled.
+ */
+ /*
+ * This is done last because it also control the
+ * status of umsdos_isinit()
+ */
+ Printk ((KERN_DEBUG "umsdos_patch_inode /mn/: here we go: calling umsdos_set_dirinfo (%p,%p,%lu)\n", inode, dir, f_pos));
+ umsdos_set_dirinfo (inode, dir, f_pos);
+ }
+ } else if (dir != NULL) {
+ /*
+ * Test to see if the info is maintained.
+ * This should be removed when the file system will be proven.
+ */
+ /* FIXME, again, not a clue */
+ struct inode *emd_owner;
+
+ Printk ((KERN_WARNING "umsdos_patch_inode: /mn/ Warning: untested emd_owner thingy...\n"));
+ emd_owner = umsdos_emd_dir_lookup (dir, 1);
+ iput (emd_owner); /* FIXME? */
+ if (emd_owner->i_ino != inode->u.umsdos_i.i_emd_owner) {
+ printk ("UMSDOS: *** EMD_OWNER ??? *** ino = %ld %ld <> %ld "
+ ,inode->i_ino, emd_owner->i_ino, inode->u.umsdos_i.i_emd_owner);
+ }
+ }
}
/*
- Get the inode of the directory which owns this inode.
- Return 0 if ok, -EIO if error.
-*/
-int umsdos_get_dirowner(
- struct inode *inode,
- struct inode **result) /* Hold NULL if any error */
- /* else, the inode of the directory */
-{
+ * Get the inode of the directory which owns this inode.
+ * Return 0 if ok, -EIO if error.
+ */
+int umsdos_get_dirowner (
+ struct inode *inode,
+ struct inode **result)
+{ /* Hold NULL if any error */
+ /* else, the inode of the directory */
int ret = -EIO;
unsigned long ino = inode->u.umsdos_i.i_dir_owner;
+
*result = NULL;
- if (ino == 0){
+ if (ino == 0) {
printk ("UMSDOS: umsdos_get_dirowner ino == 0\n");
- }else{
- struct inode *dir = *result = iget(inode->i_sb,ino);
- if (dir != NULL){
- umsdos_patch_inode (dir,NULL,0);
+ } else {
+ struct inode *dir = *result = iget (inode->i_sb, ino);
+
+ if (dir != NULL) {
+ umsdos_patch_inode (dir, NULL, 0);
+ /* iput (dir); / * FIXME: /mn/ added this. Is it ok ? */
ret = 0;
}
}
@@ -269,366 +499,369 @@ int umsdos_get_dirowner(
/*
- Load an inode from disk.
-*/
-void UMSDOS_read_inode(struct inode *inode)
+ * Load an inode from disk.
+ */
+void UMSDOS_read_inode (struct inode *inode)
{
- PRINTK ((KERN_DEBUG "UMSDOS_read_inode %p ino = %lu ",inode,inode->i_ino));
- msdos_read_inode(inode);
- PRINTK (("ino after msdos_read_inode= %lu\n",inode->i_ino));
- if (S_ISDIR(inode->i_mode)
- && (inode->u.umsdos_i.u.dir_info.creating != 0
- || inode->u.umsdos_i.u.dir_info.looking != 0
- || waitqueue_active(&inode->u.umsdos_i.u.dir_info.p))){
- PRINTK (("read inode %d %d %p\n"
- ,inode->u.umsdos_i.u.dir_info.creating
- ,inode->u.umsdos_i.u.dir_info.looking
- ,inode->u.umsdos_i.u.dir_info.p));
+ Printk ((KERN_DEBUG "UMSDOS_read_inode %p ino = %lu ", inode, inode->i_ino));
+ msdos_read_inode (inode);
+ Printk (("ino after msdos_read_inode= %lu i_count=%d\n", inode->i_ino, inode->i_count));
+ if (S_ISDIR (inode->i_mode)
+ && (inode->u.umsdos_i.u.dir_info.creating != 0
+ || inode->u.umsdos_i.u.dir_info.looking != 0
+ || waitqueue_active (&inode->u.umsdos_i.u.dir_info.p))) {
+ Printk (("read inode %d %d %p\n"
+ ,inode->u.umsdos_i.u.dir_info.creating
+ ,inode->u.umsdos_i.u.dir_info.looking
+ ,inode->u.umsdos_i.u.dir_info.p));
}
/* #Specification: Inode / post initialisation
- To completely initialise an inode, we need access to the owner
- directory, so we can locate more info in the EMD file. This is
- not available the first time the inode is access, we use
- a value in the inode to tell if it has been finally initialised.
-
- At first, we have tried testing i_count but it was causing
- problem. It is possible that two or more process use the
- newly accessed inode. While the first one block during
- the initialisation (probably while reading the EMD file), the
- others believe all is well because i_count > 1. They go banana
- with a broken inode. See umsdos_lookup_patch and umsdos_patch_inode.
- */
- umsdos_patch_inode(inode,NULL,0);
+ * To completely initialise an inode, we need access to the owner
+ * directory, so we can locate more info in the EMD file. This is
+ * not available the first time the inode is access, we use
+ * a value in the inode to tell if it has been finally initialised.
+ *
+ * At first, we have tried testing i_count but it was causing
+ * problem. It is possible that two or more process use the
+ * newly accessed inode. While the first one block during
+ * the initialisation (probably while reading the EMD file), the
+ * others believe all is well because i_count > 1. They go banana
+ * with a broken inode. See umsdos_lookup_patch and umsdos_patch_inode.
+ */
+ umsdos_patch_inode (inode, NULL, 0);
+}
+
+
+int internal_notify_change (struct inode *inode, struct iattr *attr)
+{
+ int ret = 0;
+ struct inode *root;
+
+ PRINTK ((KERN_DEBUG "UMSDOS_notify_change: entering\n"));
+
+ if ((ret = inode_change_ok (inode, attr)) != 0)
+ return ret;
+
+ if (inode->i_nlink > 0) {
+ /* #Specification: notify_change / i_nlink > 0
+ * notify change is only done for inode with nlink > 0. An inode
+ * with nlink == 0 is no longer associated with any entry in
+ * the EMD file, so there is nothing to update.
+ */
+ unsigned long i_emd_owner = inode->u.umsdos_i.i_emd_owner;
+
+ root = iget (inode->i_sb, UMSDOS_ROOT_INO);
+ if (inode == root) {
+ /* #Specification: root inode / attributes
+ * I don't know yet how this should work. Normally
+ * the attributes (permissions bits, owner, times) of
+ * a directory are stored in the EMD file of its parent.
+ *
+ * One thing we could do is store the attributes of the root
+ * inode in its own EMD file. A simple entry named "." could
+ * be used for this special case. It would be read once
+ * when the file system is mounted and update in
+ * UMSDOS_notify_change() (right here).
+ *
+ * I am not sure of the behavior of the root inode for
+ * a real UNIX file system. For now, this is a nop.
+ */
+ } else if (i_emd_owner != 0xffffffff && i_emd_owner != 0) {
+ /* This inode is not a EMD file nor an inode used internally
+ * by MSDOS, so we can update its status.
+ * See emd.c
+ */
+ struct inode *emd_owner;
+
+ emd_owner = iget (inode->i_sb, i_emd_owner);
+ Printk (("notify change %p ", inode));
+ if (emd_owner == NULL) {
+ printk ("UMSDOS: emd_owner = NULL ???");
+ ret = -EPERM;
+ } else {
+ struct file filp;
+ struct umsdos_dirent entry;
+ struct dentry *emd_dentry;
+ loff_t offs;
+
+ emd_dentry = creat_dentry ("notify_emd", 10, emd_owner, NULL);
+ fill_new_filp (&filp, emd_dentry);
+
+ filp.f_pos = inode->u.umsdos_i.pos;
+ filp.f_reada = 0;
+ offs = filp.f_pos; /* FIXME: /mn/ is this ok ? */
+ Printk (("pos = %Lu ", filp.f_pos));
+ /* Read only the start of the entry since we don't touch */
+ /* the name */
+ ret = umsdos_emd_dir_read (emd_owner, &filp, (char *) &entry, UMSDOS_REC_SIZE, &offs);
+ if (ret == 0) {
+ if (attr->ia_valid & ATTR_UID)
+ entry.uid = attr->ia_uid;
+ if (attr->ia_valid & ATTR_GID)
+ entry.gid = attr->ia_gid;
+ if (attr->ia_valid & ATTR_MODE)
+ entry.mode = attr->ia_mode;
+ if (attr->ia_valid & ATTR_ATIME)
+ entry.atime = attr->ia_atime;
+ if (attr->ia_valid & ATTR_MTIME)
+ entry.mtime = attr->ia_mtime;
+ if (attr->ia_valid & ATTR_CTIME)
+ entry.ctime = attr->ia_ctime;
+
+ entry.nlink = inode->i_nlink;
+ filp.f_pos = inode->u.umsdos_i.pos;
+ offs = filp.f_pos; /* FIXME: /mn/ is this ok ? */
+ ret = umsdos_emd_dir_write (emd_owner, &filp, (char *) &entry, UMSDOS_REC_SIZE, &offs);
+
+ Printk (("notify pos %lu ret %d nlink %d "
+ ,inode->u.umsdos_i.pos
+ ,ret, entry.nlink));
+ /* #Specification: notify_change / msdos fs
+ * notify_change operation are done only on the
+ * EMD file. The msdos fs is not even called.
+ */
+ }
+ iput (emd_owner); /* FIXME? /mn/ */
+ }
+ Printk (("\n"));
+ }
+ iput (root); /* FIXME - /mn/ this is hopefully ok */
+ }
+ if (ret == 0)
+ inode_setattr (inode, attr);
+
+ return ret;
}
+int UMSDOS_notify_change (struct dentry *dentry, struct iattr *attr)
+{
+ return internal_notify_change (dentry->d_inode, attr);
+}
+
/*
- Update the disk with the inode content
-*/
-void UMSDOS_write_inode(struct inode *inode)
+ * Update the disk with the inode content
+ */
+void UMSDOS_write_inode (struct inode *inode)
{
struct iattr newattrs;
- PRINTK (("UMSDOS_write_inode emd %d (FIXME: missing notify_change)\n",inode->u.umsdos_i.i_emd_owner));
- fat_write_inode(inode);
+ PRINTK (("UMSDOS_write_inode emd %d (FIXME: missing notify_change)\n", inode->u.umsdos_i.i_emd_owner));
+ fat_write_inode (inode);
newattrs.ia_mtime = inode->i_mtime;
newattrs.ia_atime = inode->i_atime;
newattrs.ia_ctime = inode->i_ctime;
newattrs.ia_valid = ATTR_MTIME | ATTR_ATIME | ATTR_CTIME;
/*
- UMSDOS_notify_change is convenient to call here
- to update the EMD entry associated with this inode.
- But it has the side effect to re"dirt" the inode.
- */
- /* FIXME, notify_change now takes a dentry, not an
- inode so, the emd update needs to be done here
- UMSDOS_notify_change (inode, &newattrs);
- */
-
- /* FIXME inode->i_dirt = 0; */
+ * UMSDOS_notify_change is convenient to call here
+ * to update the EMD entry associated with this inode.
+ * But it has the side effect to re"dirt" the inode.
+ */
+
+/*
+ * internal_notify_change (inode, &newattrs);
+ * inode->i_state &= ~I_DIRTY; / * FIXME: this doesn't work... we need to remove ourselfs from list on dirty inodes /mn/ */
}
-int internal_notify_change(struct inode *inode, struct iattr *attr)
-{
- int ret = 0;
-
- PRINTK ((KERN_DEBUG "UMSDOS_notify_change: entering\n"));
-
- if ((ret = inode_change_ok(inode, attr)) != 0)
- return ret;
-
- if (inode->i_nlink > 0){
- /* #Specification: notify_change / i_nlink > 0
- notify change is only done for inode with nlink > 0. An inode
- with nlink == 0 is no longer associated with any entry in
- the EMD file, so there is nothing to update.
- */
- unsigned long i_emd_owner = inode->u.umsdos_i.i_emd_owner;
- if (inode == iget(inode->i_sb,UMSDOS_ROOT_INO)){
- /* #Specification: root inode / attributes
- I don't know yet how this should work. Normally
- the attributes (permissions bits, owner, times) of
- a directory are stored in the EMD file of its parent.
-
- One thing we could do is store the attributes of the root
- inode in its own EMD file. A simple entry named "." could
- be used for this special case. It would be read once
- when the file system is mounted and update in
- UMSDOS_notify_change() (right here).
-
- I am not sure of the behavior of the root inode for
- a real UNIX file system. For now, this is a nop.
- */
- }else if (i_emd_owner != 0xffffffff && i_emd_owner != 0){
- /* This inode is not a EMD file nor an inode used internally
- by MSDOS, so we can update its status.
- See emd.c
- */
- struct inode *emd_owner = iget (inode->i_sb,i_emd_owner);
- Printk (("notify change %p ",inode));
- if (emd_owner == NULL){
- printk ("UMSDOS: emd_owner = NULL ???");
- ret = -EPERM;
- }else{
- struct file filp;
- struct umsdos_dirent entry;
- struct dentry *emd_dentry;
- loff_t offs;
-
- emd_dentry = creat_dentry ("notify_emd", 10, emd_owner, NULL);
- fill_new_filp (&filp, emd_dentry);
-
- filp.f_pos = inode->u.umsdos_i.pos;
- filp.f_reada = 0;
- offs = filp.f_pos; /* FIXME: /mn/ is this ok ? */
- Printk (("pos = %Lu ", filp.f_pos));
- /* Read only the start of the entry since we don't touch */
- /* the name */
- ret = umsdos_emd_dir_read (emd_owner, &filp, (char*)&entry, UMSDOS_REC_SIZE, &offs);
- if (ret == 0){
- if (attr->ia_valid & ATTR_UID)
- entry.uid = attr->ia_uid;
- if (attr->ia_valid & ATTR_GID)
- entry.gid = attr->ia_gid;
- if (attr->ia_valid & ATTR_MODE)
- entry.mode = attr->ia_mode;
- if (attr->ia_valid & ATTR_ATIME)
- entry.atime = attr->ia_atime;
- if (attr->ia_valid & ATTR_MTIME)
- entry.mtime = attr->ia_mtime;
- if (attr->ia_valid & ATTR_CTIME)
- entry.ctime = attr->ia_ctime;
-
- entry.nlink = inode->i_nlink;
- filp.f_pos = inode->u.umsdos_i.pos;
- offs = filp.f_pos; /* FIXME: /mn/ is this ok ? */
- ret = umsdos_emd_dir_write (emd_owner, &filp, (char*)&entry, UMSDOS_REC_SIZE, &offs);
-
- Printk (("notify pos %lu ret %d nlink %d "
- ,inode->u.umsdos_i.pos
- ,ret, entry.nlink));
- /* #Specification: notify_change / msdos fs
- notify_change operation are done only on the
- EMD file. The msdos fs is not even called.
- */
- }
- /* iput (emd_owner); FIXME */
- }
- Printk (("\n"));
- }
- }
- if (ret == 0)
- inode_setattr(inode, attr);
- return ret;
-}
-
-
-int UMSDOS_notify_change(struct dentry *dentry, struct iattr *attr)
-{
- return internal_notify_change (dentry->d_inode, attr);
-}
-
/* #Specification: function name / convention
- A simple convention for function name has been used in
- the UMSDOS file system. First all function use the prefix
- umsdos_ to avoid name clash with other part of the kernel.
-
- And standard VFS entry point use the prefix UMSDOS (upper case)
- so it's easier to tell them apart.
- N.B. (FIXME) PTW, the order and contents of this struct changed
-*/
-
-static struct super_operations umsdos_sops = {
- UMSDOS_read_inode, /* read_inode */
- UMSDOS_write_inode, /* write_inode */
- UMSDOS_put_inode, /* put_inode */
- NULL, /* delete_inode */
- UMSDOS_notify_change, /* notify_change */
- UMSDOS_put_super, /* put_super */
- NULL, /* write_super */
- fat_statfs, /* statfs */
- NULL /* remount_fs*/
+ * A simple convention for function name has been used in
+ * the UMSDOS file system. First all function use the prefix
+ * umsdos_ to avoid name clash with other part of the kernel.
+ *
+ * And standard VFS entry point use the prefix UMSDOS (upper case)
+ * so it's easier to tell them apart.
+ * N.B. (FIXME) PTW, the order and contents of this struct changed
+ */
+
+static struct super_operations umsdos_sops =
+{
+ UMSDOS_read_inode, /* read_inode */
+ UMSDOS_write_inode, /* write_inode */
+ UMSDOS_put_inode, /* put_inode */
+ fat_delete_inode, /* delete_inode */
+ UMSDOS_notify_change, /* notify_change */
+ UMSDOS_put_super, /* put_super */
+ NULL, /* write_super */
+ fat_statfs, /* statfs */
+ NULL /* remount_fs */
};
/*
- Read the super block of an Extended MS-DOS FS.
-*/
-struct super_block *UMSDOS_read_super(
- struct super_block *sb,
- void *data,
- int silent)
+ * Read the super block of an Extended MS-DOS FS.
+ */
+struct super_block *UMSDOS_read_super (
+ struct super_block *sb,
+ void *data,
+ int silent)
{
- /* #Specification: mount / options
- Umsdos run on top of msdos. Currently, it supports no
- mount option, but happily pass all option received to
- the msdos driver. I am not sure if all msdos mount option
- make sense with Umsdos. Here are at least those who
- are useful.
- uid=
- gid=
-
- These options affect the operation of umsdos in directories
- which do not have an EMD file. They behave like normal
- msdos directory, with all limitation of msdos.
- */
- struct super_block *res;
- struct inode *pseudo=NULL;
- Printk ((KERN_DEBUG "UMSDOS /mn/: starting UMSDOS_read_super\n"));
- MOD_INC_USE_COUNT;
- PRINTK ((KERN_DEBUG "UMSDOS /mn/: sb = %p\n",sb));
- res = msdos_read_super(sb,data,silent);
- PRINTK ((KERN_DEBUG "UMSDOS /mn/: res = %p\n",res));
- printk (KERN_INFO "UMSDOS dentry-WIP-Beta 0.82-3 (compatibility level %d.%d, fast msdos)\n", UMSDOS_VERSION, UMSDOS_RELEASE);
-
- if (res == NULL) { MOD_DEC_USE_COUNT; return NULL; }
-
- MSDOS_SB(res)->options.dotsOK = 0; /* disable hidden==dotfile */
- res->s_op = &umsdos_sops;
- Printk ((KERN_DEBUG "umsdos /mn/: here goes the iget ROOT_INO\n"));
-
- pseudo = iget(res,UMSDOS_ROOT_INO);
- Printk ((KERN_DEBUG "umsdos_read_super %p\n",pseudo));
-
- umsdos_setup_dir_inode (pseudo);
-
-#if 0 /* disabled /mn/ test FIXME */
-
- /* if (s == super_blocks){ FIXME, super_blocks no longer exported */
- if(pseudo) {
- /* #Specification: pseudo root / mount
- When a umsdos fs is mounted, a special handling is done
- if it is the root partition. We check for the presence
- of the file /linux/etc/init or /linux/etc/rc or
- /linux/sbin/init. If one is there, we do a chroot("/linux").
-
- We check both because (see init/main.c) the kernel
- try to exec init at different place and if it fails
- it tries /bin/sh /etc/rc. To be consistent with
- init/main.c, many more test would have to be done
- to locate init. Any complain ?
-
- The chroot is done manually in init/main.c but the
- info (the inode) is located at mount time and store
- in a global variable (pseudo_root) which is used at
- different place in the umsdos driver. There is no
- need to store this variable elsewhere because it
- will always be one, not one per mount.
-
- This feature allows the installation
- of a linux system within a DOS system in a subdirectory.
-
- A user may install its linux stuff in c:\linux
- avoiding any clash with existing DOS file and subdirectory.
- When linux boots, it hides this fact, showing a normal
- root directory with /etc /bin /tmp ...
-
- The word "linux" is hardcoded in /usr/include/linux/umsdos_fs.h
- in the macro UMSDOS_PSDROOT_NAME.
- */
- struct dentry *root, *etc, *etc_rc, *init, *sbin;
-
- root = creat_dentry (UMSDOS_PSDROOT_NAME, strlen(UMSDOS_PSDROOT_NAME), NULL, NULL);
- sbin = creat_dentry ("sbin", 4, NULL, NULL);
-
- Printk ((KERN_DEBUG "Mounting root\n"));
- if (umsdos_real_lookup (pseudo,root)==0
- && (root->d_inode != NULL)
- && S_ISDIR(root->d_inode->i_mode)){
-
- int pseudo_ok = 0;
- Printk ((KERN_DEBUG "/%s is there\n",UMSDOS_PSDROOT_NAME));
- etc = creat_dentry ("etc", 3, NULL, NULL);
-
-
- /* if (umsdos_real_lookup (pseudo,"etc",3,etc)==0 */
- if(umsdos_real_lookup(pseudo, etc) == 0
- && S_ISDIR(etc->d_inode->i_mode)){
-
- Printk ((KERN_DEBUG "/%s/etc is there\n",UMSDOS_PSDROOT_NAME));
-
- init = creat_dentry ("init", 4, NULL, NULL);
- etc_rc = creat_dentry ("rc", 2, NULL, NULL);
-
- /* if ((umsdos_real_lookup (etc,"init",4,init)==0*/
- if((umsdos_real_lookup(pseudo, init) == 0
- && S_ISREG(init->d_inode->i_mode))
- /* || (umsdos_real_lookup (etc,"rc",2,&rc)==0*/
- || (umsdos_real_lookup(pseudo, etc_rc) == 0
- && S_ISREG(etc_rc->d_inode->i_mode))){
- pseudo_ok = 1;
- }
- /* FIXME !!!!!! */
- /* iput(init); */
- /* iput(rc); */
- }
- if (!pseudo_ok
- /* && umsdos_real_lookup (pseudo, "sbin", 4, sbin)==0*/
- && umsdos_real_lookup(pseudo, sbin) == 0
- && S_ISDIR(sbin->d_inode->i_mode)){
-
- Printk ((KERN_DEBUG "/%s/sbin is there\n",UMSDOS_PSDROOT_NAME));
- /* if (umsdos_real_lookup (sbin,"init",4,init)==0 */
- if(umsdos_real_lookup(pseudo, init) == 0
- && S_ISREG(init->d_inode->i_mode)){
- pseudo_ok = 1;
- }
- /* FIXME !!!
- iput (init); */
+ /* #Specification: mount / options
+ * Umsdos run on top of msdos. Currently, it supports no
+ * mount option, but happily pass all option received to
+ * the msdos driver. I am not sure if all msdos mount option
+ * make sense with Umsdos. Here are at least those who
+ * are useful.
+ * uid=
+ * gid=
+ *
+ * These options affect the operation of umsdos in directories
+ * which do not have an EMD file. They behave like normal
+ * msdos directory, with all limitation of msdos.
+ */
+ struct super_block *res;
+ struct inode *pseudo = NULL;
+
+ Printk ((KERN_DEBUG "UMSDOS /mn/: starting UMSDOS_read_super\n"));
+ MOD_INC_USE_COUNT;
+ PRINTK ((KERN_DEBUG "UMSDOS /mn/: sb = %p\n", sb));
+ res = msdos_read_super (sb, data, silent);
+ PRINTK ((KERN_DEBUG "UMSDOS /mn/: res = %p\n", res));
+ printk (KERN_INFO "UMSDOS dentry-WIP-Beta 0.82-4 (compatibility level %d.%d, fast msdos)\n", UMSDOS_VERSION, UMSDOS_RELEASE);
+
+ if (res == NULL) {
+ MOD_DEC_USE_COUNT;
+ return NULL;
}
- if (pseudo_ok){
- umsdos_setup_dir_inode (pseudo);
- Printk ((KERN_INFO "Activating pseudo root /%s\n",UMSDOS_PSDROOT_NAME));
- pseudo_root = pseudo;
- pseudo->i_count++;
- pseudo = NULL;
+ MSDOS_SB (res)->options.dotsOK = 0; /* disable hidden==dotfile */
+ res->s_op = &umsdos_sops;
+ Printk ((KERN_DEBUG "umsdos /mn/: here goes the iget ROOT_INO\n"));
+
+ pseudo = iget (res, UMSDOS_ROOT_INO);
+ Printk ((KERN_DEBUG "umsdos_read_super %p\n", pseudo));
+
+ umsdos_setup_dir_inode (pseudo);
+ Printk ((KERN_DEBUG "umsdos_setup_dir_inode passed. pseudo i_count=%d\n", pseudo->i_count));
+
+ /* if (s == super_blocks){ FIXME, super_blocks no longer exported */
+ if (pseudo) {
+ /* #Specification: pseudo root / mount
+ * When a umsdos fs is mounted, a special handling is done
+ * if it is the root partition. We check for the presence
+ * of the file /linux/etc/init or /linux/etc/rc or
+ * /linux/sbin/init. If one is there, we do a chroot("/linux").
+ *
+ * We check both because (see init/main.c) the kernel
+ * try to exec init at different place and if it fails
+ * it tries /bin/sh /etc/rc. To be consistent with
+ * init/main.c, many more test would have to be done
+ * to locate init. Any complain ?
+ *
+ * The chroot is done manually in init/main.c but the
+ * info (the inode) is located at mount time and store
+ * in a global variable (pseudo_root) which is used at
+ * different place in the umsdos driver. There is no
+ * need to store this variable elsewhere because it
+ * will always be one, not one per mount.
+ *
+ * This feature allows the installation
+ * of a linux system within a DOS system in a subdirectory.
+ *
+ * A user may install its linux stuff in c:\linux
+ * avoiding any clash with existing DOS file and subdirectory.
+ * When linux boots, it hides this fact, showing a normal
+ * root directory with /etc /bin /tmp ...
+ *
+ * The word "linux" is hardcoded in /usr/include/linux/umsdos_fs.h
+ * in the macro UMSDOS_PSDROOT_NAME.
+ */
+ struct dentry *root, *etc, *etc_rc, *sbin, *init = NULL;
+
+ root = creat_dentry (UMSDOS_PSDROOT_NAME, strlen (UMSDOS_PSDROOT_NAME), NULL, NULL);
+ sbin = creat_dentry ("sbin", 4, NULL, NULL);
+
+ Printk ((KERN_DEBUG "Mounting root\n"));
+ if (umsdos_real_lookup (pseudo, root) == 0
+ && (root->d_inode != NULL)
+ && S_ISDIR (root->d_inode->i_mode)) {
+
+ int pseudo_ok = 0;
+
+ Printk ((KERN_DEBUG "/%s is there\n", UMSDOS_PSDROOT_NAME));
+ etc = creat_dentry ("etc", 3, NULL, root);
+
+
+ if (umsdos_real_lookup (pseudo, etc) == 0
+ && S_ISDIR (etc->d_inode->i_mode)) {
+
+ Printk ((KERN_DEBUG "/%s/etc is there\n", UMSDOS_PSDROOT_NAME));
+
+ init = creat_dentry ("init", 4, NULL, etc);
+ etc_rc = creat_dentry ("rc", 2, NULL, etc);
+
+ /* if ((umsdos_real_lookup (etc,"init",4,init)==0 */
+ if ((umsdos_real_lookup (pseudo, init) == 0
+ && S_ISREG (init->d_inode->i_mode))
+ /* || (umsdos_real_lookup (etc,"rc",2,&rc)==0 */
+ || (umsdos_real_lookup (pseudo, etc_rc) == 0
+ && S_ISREG (etc_rc->d_inode->i_mode))) {
+ pseudo_ok = 1;
+ }
+ /* FIXME !!!!!! */
+ /* iput(init); */
+ /* iput(rc); */
+ }
+ if (!pseudo_ok
+ /* && umsdos_real_lookup (pseudo, "sbin", 4, sbin)==0 */
+ && umsdos_real_lookup (pseudo, sbin) == 0
+ && S_ISDIR (sbin->d_inode->i_mode)) {
+
+ Printk ((KERN_DEBUG "/%s/sbin is there\n", UMSDOS_PSDROOT_NAME));
+ /* if (umsdos_real_lookup (sbin,"init",4,init)==0 */
+ if (umsdos_real_lookup (pseudo, init) == 0
+ && S_ISREG (init->d_inode->i_mode)) {
+ pseudo_ok = 1;
+ }
+ /* FIXME !!!
+ * iput (init); */
+ }
+ if (pseudo_ok) {
+ umsdos_setup_dir_inode (pseudo);
+ Printk ((KERN_INFO "Activating pseudo root /%s\n", UMSDOS_PSDROOT_NAME));
+ pseudo_root = pseudo;
+ inc_count (pseudo);
+ pseudo = NULL;
+ }
+ /* FIXME
+ *
+ * iput (sbin);
+ * iput (etc);
+ */
+ }
+ iput (pseudo);
}
- /* FIXME
-
- iput (sbin);
- iput (etc);
- */
- }
-
- Printk ((KERN_WARNING "umsdos_read_super /mn/: Pseudo should be iput-ed here...\n"));
-
- /* iput (pseudo); / * FIXME */
- }
-
-#endif /* disabled */
-
- PRINTK ((KERN_DEBUG "umsdos_read_super /mn/: returning %p\n",res));
- return res;
+ Printk ((KERN_DEBUG "umsdos_read_super /mn/: (pseudo=%lu, i_count=%d) returning %p\n", pseudo->i_ino, pseudo->i_count, res));
+ return res;
}
-static struct file_system_type umsdos_fs_type = {
- "umsdos",
- FS_REQUIRES_DEV,
- UMSDOS_read_super,
- NULL
+static struct file_system_type umsdos_fs_type =
+{
+ "umsdos",
+ FS_REQUIRES_DEV,
+ UMSDOS_read_super,
+ NULL
};
-__initfunc(int init_umsdos_fs(void))
+__initfunc (int init_umsdos_fs (void))
{
- return register_filesystem(&umsdos_fs_type);
+ return register_filesystem (&umsdos_fs_type);
}
#ifdef MODULE
EXPORT_NO_SYMBOLS;
-int init_module(void)
+int init_module (void)
{
- return init_umsdos_fs();
+ return init_umsdos_fs ();
}
-void cleanup_module(void)
+void cleanup_module (void)
{
- unregister_filesystem(&umsdos_fs_type);
+ unregister_filesystem (&umsdos_fs_type);
}
#endif
diff --git a/fs/umsdos/ioctl.c b/fs/umsdos/ioctl.c
index b3f11ee32..a379ba368 100644
--- a/fs/umsdos/ioctl.c
+++ b/fs/umsdos/ioctl.c
@@ -24,326 +24,336 @@ struct UMSDOS_DIR_ONCE {
};
/*
- Record a single entry the first call.
- Return -EINVAL the next one.
-*/
-static int umsdos_ioctl_fill(
- void * buf,
- const char * name,
- int name_len,
- off_t offset,
- ino_t ino)
+ * Record a single entry the first call.
+ * Return -EINVAL the next one.
+ */
+static int umsdos_ioctl_fill (
+ void *buf,
+ const char *name,
+ int name_len,
+ off_t offset,
+ ino_t ino)
{
- int ret = -EINVAL;
- struct UMSDOS_DIR_ONCE *d = (struct UMSDOS_DIR_ONCE *)buf;
- if (d->count == 0){
- copy_to_user (d->ent->d_name,name,name_len);
- put_user ('\0',d->ent->d_name+name_len);
- put_user (name_len,&d->ent->d_reclen);
- put_user (ino,&d->ent->d_ino);
- put_user (offset,&d->ent->d_off);
- d->count = 1;
- ret = 0;
- }
- return ret;
+ int ret = -EINVAL;
+ struct UMSDOS_DIR_ONCE *d = (struct UMSDOS_DIR_ONCE *) buf;
+
+ if (d->count == 0) {
+ copy_to_user (d->ent->d_name, name, name_len);
+ put_user ('\0', d->ent->d_name + name_len);
+ put_user (name_len, &d->ent->d_reclen);
+ put_user (ino, &d->ent->d_ino);
+ put_user (offset, &d->ent->d_off);
+ d->count = 1;
+ ret = 0;
+ }
+ return ret;
}
/*
- Perform special function on a directory
-*/
+ * Perform special function on a directory
+ */
int UMSDOS_ioctl_dir (
- struct inode *dir,
- struct file *filp,
- unsigned int cmd,
- unsigned long data)
+ struct inode *dir,
+ struct file *filp,
+ unsigned int cmd,
+ unsigned long data)
{
- int ret = -EPERM;
- int err;
+ int ret = -EPERM;
+ int err;
- /* forward non-umsdos ioctls - this hopefully doesn't cause conflicts */
- if(cmd!=UMSDOS_GETVERSION
- &&cmd!=UMSDOS_READDIR_DOS
- &&cmd!=UMSDOS_READDIR_EMD
- &&cmd!=UMSDOS_INIT_EMD
- &&cmd!=UMSDOS_CREAT_EMD
- &&cmd!=UMSDOS_RENAME_DOS
- &&cmd!=UMSDOS_UNLINK_EMD
- &&cmd!=UMSDOS_UNLINK_DOS
- &&cmd!=UMSDOS_RMDIR_DOS
- &&cmd!=UMSDOS_STAT_DOS
- &&cmd!=UMSDOS_DOS_SETUP)
- return fat_dir_ioctl(dir,filp,cmd,data);
+ /* forward non-umsdos ioctls - this hopefully doesn't cause conflicts */
+ if (cmd != UMSDOS_GETVERSION
+ && cmd != UMSDOS_READDIR_DOS
+ && cmd != UMSDOS_READDIR_EMD
+ && cmd != UMSDOS_INIT_EMD
+ && cmd != UMSDOS_CREAT_EMD
+ && cmd != UMSDOS_RENAME_DOS
+ && cmd != UMSDOS_UNLINK_EMD
+ && cmd != UMSDOS_UNLINK_DOS
+ && cmd != UMSDOS_RMDIR_DOS
+ && cmd != UMSDOS_STAT_DOS
+ && cmd != UMSDOS_DOS_SETUP)
+ return fat_dir_ioctl (dir, filp, cmd, data);
- /* #Specification: ioctl / acces
- Only root (effective id) is allowed to do IOCTL on directory
- in UMSDOS. EPERM is returned for other user.
- */
- /*
- Well, not all cases require write access, but it simplifies
- the code, and let's face it, there is only one client (umssync)
- for all this.
- */
- if ((err = verify_area(VERIFY_WRITE,(void*)data,sizeof(struct umsdos_ioctl))) < 0) {
- ret = err;
- }else if (current->euid == 0
- || cmd == UMSDOS_GETVERSION){
- struct umsdos_ioctl *idata = (struct umsdos_ioctl *)data;
- ret = -EINVAL;
- /* #Specification: ioctl / prototypes
- The official prototype for the umsdos ioctl on directory
- is:
-
- int ioctl (
- int fd, // File handle of the directory
- int cmd, // command
- struct umsdos_ioctl *data)
-
- The struct and the commands are defined in linux/umsdos_fs.h.
-
- umsdos_progs/umsdosio.c provide an interface in C++ to all
- these ioctl. umsdos_progs/udosctl is a small utility showing
- all this.
-
- These ioctl generally allow one to work on the EMD or the
- DOS directory independently. These are essential to implement
- the synchronise.
- */
- Printk (("ioctl %d ",cmd));
- if (cmd == UMSDOS_GETVERSION){
- /* #Specification: ioctl / UMSDOS_GETVERSION
- The field version and release of the structure
- umsdos_ioctl are filled with the version and release
- number of the fs code in the kernel. This will allow
- some form of checking. Users won't be able to run
- incompatible utility such as the synchroniser (umssync).
- umsdos_progs/umsdosio.c enforce this checking.
-
- Return always 0.
- */
- put_user(UMSDOS_VERSION,&idata->version);
- put_user(UMSDOS_RELEASE,&idata->release);
- ret = 0;
- }else if (cmd == UMSDOS_READDIR_DOS){
- /* #Specification: ioctl / UMSDOS_READDIR_DOS
- One entry is read from the DOS directory at the current
- file position. The entry is put as is in the dos_dirent
- field of struct umsdos_ioctl.
-
- Return > 0 if success.
- */
- struct UMSDOS_DIR_ONCE bufk;
- bufk.count = 0;
- bufk.ent = &idata->dos_dirent;
-
- fat_readdir(filp,&bufk,umsdos_ioctl_fill);
-
- ret = bufk.count == 1 ? 1 : 0;
- }else if (cmd == UMSDOS_READDIR_EMD){
- /* #Specification: ioctl / UMSDOS_READDIR_EMD
- One entry is read from the EMD at the current
- file position. The entry is put as is in the umsdos_dirent
- field of struct umsdos_ioctl. The corresponding mangled
- DOS entry name is put in the dos_dirent field.
-
- All entries are read including hidden links. Blank
- entries are skipped.
-
- Return > 0 if success.
- */
- struct inode *emd_dir = umsdos_emd_dir_lookup (dir,0);
- if (emd_dir != NULL){
- while (1){
- if (filp->f_pos >= emd_dir->i_size){
- ret = 0;
- break;
- }else{
- struct umsdos_dirent entry;
- off_t f_pos = filp->f_pos;
- ret = umsdos_emd_dir_readentry (emd_dir,filp,&entry);
- if (ret < 0){
- break;
- }else if (entry.name_len > 0){
- struct umsdos_info info;
- ret = entry.name_len;
- umsdos_parse (entry.name,entry.name_len,&info);
- info.f_pos = f_pos;
- umsdos_manglename(&info);
- copy_to_user(&idata->umsdos_dirent,&entry
- ,sizeof(entry));
- copy_to_user(&idata->dos_dirent.d_name
- ,info.fake.fname,info.fake.len+1);
- break;
- }
- }
- }
- /* iput (emd_dir); FIXME */
- }else{
- /* The absence of the EMD is simply seen as an EOF */
- ret = 0;
- }
- }else if (cmd == UMSDOS_INIT_EMD){
- /* #Specification: ioctl / UMSDOS_INIT_EMD
- The UMSDOS_INIT_EMD command make sure the EMD
- exist for a directory. If it does not, it is
- created. Also, it makes sure the directory functions
- table (struct inode_operations) is set to the UMSDOS
- semantic. This mean that umssync may be applied to
- an "opened" msdos directory, and it will change behavior
- on the fly.
-
- Return 0 if success.
- */
- extern struct inode_operations umsdos_rdir_inode_operations;
- struct inode *emd_dir = umsdos_emd_dir_lookup (dir,1);
- ret = emd_dir != NULL;
- /* iput (emd_dir); FIXME */
-
- dir->i_op = ret
- ? &umsdos_dir_inode_operations
- : &umsdos_rdir_inode_operations;
- }else{
- struct umsdos_ioctl data;
- copy_from_user (&data,idata,sizeof(data));
- if (cmd == UMSDOS_CREAT_EMD){
- /* #Specification: ioctl / UMSDOS_CREAT_EMD
- The umsdos_dirent field of the struct umsdos_ioctl is used
- as is to create a new entry in the EMD of the directory.
- The DOS directory is not modified.
- No validation is done (yet).
-
- Return 0 if success.
- */
- struct umsdos_info info;
- /* This makes sure info.entry and info in general is correctly */
- /* initialised */
- memcpy (&info.entry,&data.umsdos_dirent
- ,sizeof(data.umsdos_dirent));
- umsdos_parse (data.umsdos_dirent.name
- ,data.umsdos_dirent.name_len,&info);
- ret = umsdos_newentry (dir,&info);
- }else if (cmd == UMSDOS_RENAME_DOS){
- struct dentry *old_dentry,*new_dentry; /* FIXME */
- /* #Specification: ioctl / UMSDOS_RENAME_DOS
- A file or directory is rename in a DOS directory
- (not moved across directory). The source name
- is in the dos_dirent.name field and the destination
- is in umsdos_dirent.name field.
-
- This ioctl allows umssync to rename a mangle file
- name before syncing it back in the EMD.
- */
- dir->i_count+=2;
- /*
- ret = msdos_rename (dir
- ,data.dos_dirent.d_name,data.dos_dirent.d_reclen
- ,dir
- ,data.umsdos_dirent.name,data.umsdos_dirent.name_len);
- */
- old_dentry = creat_dentry (data.dos_dirent.d_name, data.dos_dirent.d_reclen, NULL, NULL); /* FIXME: prolly should fill inode part */
- new_dentry = creat_dentry (data.umsdos_dirent.name, data.umsdos_dirent.name_len, NULL, NULL);
- ret = msdos_rename(dir,old_dentry,dir,new_dentry);
- }else if (cmd == UMSDOS_UNLINK_EMD){
- /* #Specification: ioctl / UMSDOS_UNLINK_EMD
- The umsdos_dirent field of the struct umsdos_ioctl is used
- as is to remove an entry from the EMD of the directory.
- No validation is done (yet). The mode field is used
- to validate S_ISDIR or S_ISREG.
-
- Return 0 if success.
- */
- struct umsdos_info info;
- /* This makes sure info.entry and info in general is correctly */
- /* initialised */
- memcpy (&info.entry,&data.umsdos_dirent
- ,sizeof(data.umsdos_dirent));
- umsdos_parse (data.umsdos_dirent.name
- ,data.umsdos_dirent.name_len,&info);
- ret = umsdos_delentry (dir,&info
- ,S_ISDIR(data.umsdos_dirent.mode));
- }else if (cmd == UMSDOS_UNLINK_DOS){
- struct dentry *dentry; /* FIXME */
- /* #Specification: ioctl / UMSDOS_UNLINK_DOS
- The dos_dirent field of the struct umsdos_ioctl is used to
- execute a msdos_unlink operation. The d_name and d_reclen
- fields are used.
-
- Return 0 if success.
- */
- dir->i_count++;
+ /* #Specification: ioctl / acces
+ * Only root (effective id) is allowed to do IOCTL on directory
+ * in UMSDOS. EPERM is returned for other user.
+ */
/*
- ret = msdos_unlink (dir,data.dos_dirent.d_name,data.dos_dirent.d_reclen);
- */
- ret = msdos_unlink(dir,dentry);
- }else if (cmd == UMSDOS_RMDIR_DOS){
- struct dentry *dentry; /* FIXME */
- /* #Specification: ioctl / UMSDOS_RMDIR_DOS
- The dos_dirent field of the struct umsdos_ioctl is used to
- execute a msdos_unlink operation. The d_name and d_reclen
- fields are used.
-
- Return 0 if success.
- */
- dir->i_count++;
- /*
- ret = msdos_rmdir (dir,data.dos_dirent.d_name
- ,data.dos_dirent.d_reclen);
- */
- ret = msdos_rmdir(dir,dentry);
- }else if (cmd == UMSDOS_STAT_DOS){
- /* #Specification: ioctl / UMSDOS_STAT_DOS
- The dos_dirent field of the struct umsdos_ioctl is
- used to execute a stat operation in the DOS directory.
- The d_name and d_reclen fields are used.
-
- The following field of umsdos_ioctl.stat are filled.
-
- st_ino,st_mode,st_size,st_atime,st_mtime,st_ctime,
- Return 0 if success.
- */
- struct inode *inode;
+ * Well, not all cases require write access, but it simplifies
+ * the code, and let's face it, there is only one client (umssync)
+ * for all this.
+ */
+ if ((err = verify_area (VERIFY_WRITE, (void *) data, sizeof (struct umsdos_ioctl))) < 0) {
+ ret = err;
+ } else if (current->euid == 0
+ || cmd == UMSDOS_GETVERSION) {
+ struct umsdos_ioctl *idata = (struct umsdos_ioctl *) data;
- ret = compat_umsdos_real_lookup (dir, data.dos_dirent.d_name, data.dos_dirent.d_reclen, &inode);
- if (ret == 0){
- data.stat.st_ino = inode->i_ino;
- data.stat.st_mode = inode->i_mode;
- data.stat.st_size = inode->i_size;
- data.stat.st_atime = inode->i_atime;
- data.stat.st_ctime = inode->i_ctime;
- data.stat.st_mtime = inode->i_mtime;
- copy_to_user (&idata->stat,&data.stat,sizeof(data.stat));
- /* iput (inode); FIXME */
- }
- }else if (cmd == UMSDOS_DOS_SETUP){
- /* #Specification: ioctl / UMSDOS_DOS_SETUP
- The UMSDOS_DOS_SETUP ioctl allow changing the
- default permission of the MsDOS file system driver
- on the fly. The MsDOS driver apply global permission
- to every file and directory. Normally these permissions
- are controlled by a mount option. This is not
- available for root partition, so a special utility
- (umssetup) is provided to do this, normally in
- /etc/rc.local.
-
- Be aware that this apply ONLY to MsDOS directory
- (those without EMD --linux-.---). Umsdos directory
- have independent (standard) permission for each
- and every file.
-
- The field umsdos_dirent provide the information needed.
- umsdos_dirent.uid and gid sets the owner and group.
- umsdos_dirent.mode set the permissions flags.
- */
- dir->i_sb->u.msdos_sb.options.fs_uid = data.umsdos_dirent.uid;
- dir->i_sb->u.msdos_sb.options.fs_gid = data.umsdos_dirent.gid;
- dir->i_sb->u.msdos_sb.options.fs_umask = data.umsdos_dirent.mode;
- ret = 0;
- }
- }
- }
- Printk (("ioctl return %d\n",ret));
- return ret;
-}
+ ret = -EINVAL;
+ /* #Specification: ioctl / prototypes
+ * The official prototype for the umsdos ioctl on directory
+ * is:
+ *
+ * int ioctl (
+ * int fd, // File handle of the directory
+ * int cmd, // command
+ * struct umsdos_ioctl *data)
+ *
+ * The struct and the commands are defined in linux/umsdos_fs.h.
+ *
+ * umsdos_progs/umsdosio.c provide an interface in C++ to all
+ * these ioctl. umsdos_progs/udosctl is a small utility showing
+ * all this.
+ *
+ * These ioctl generally allow one to work on the EMD or the
+ * DOS directory independently. These are essential to implement
+ * the synchronise.
+ */
+ Printk (("ioctl %d ", cmd));
+ if (cmd == UMSDOS_GETVERSION) {
+ /* #Specification: ioctl / UMSDOS_GETVERSION
+ * The field version and release of the structure
+ * umsdos_ioctl are filled with the version and release
+ * number of the fs code in the kernel. This will allow
+ * some form of checking. Users won't be able to run
+ * incompatible utility such as the synchroniser (umssync).
+ * umsdos_progs/umsdosio.c enforce this checking.
+ *
+ * Return always 0.
+ */
+ put_user (UMSDOS_VERSION, &idata->version);
+ put_user (UMSDOS_RELEASE, &idata->release);
+ ret = 0;
+ } else if (cmd == UMSDOS_READDIR_DOS) {
+ /* #Specification: ioctl / UMSDOS_READDIR_DOS
+ * One entry is read from the DOS directory at the current
+ * file position. The entry is put as is in the dos_dirent
+ * field of struct umsdos_ioctl.
+ *
+ * Return > 0 if success.
+ */
+ struct UMSDOS_DIR_ONCE bufk;
+
+ bufk.count = 0;
+ bufk.ent = &idata->dos_dirent;
+ fat_readdir (filp, &bufk, umsdos_ioctl_fill);
+ ret = bufk.count == 1 ? 1 : 0;
+ } else if (cmd == UMSDOS_READDIR_EMD) {
+ /* #Specification: ioctl / UMSDOS_READDIR_EMD
+ * One entry is read from the EMD at the current
+ * file position. The entry is put as is in the umsdos_dirent
+ * field of struct umsdos_ioctl. The corresponding mangled
+ * DOS entry name is put in the dos_dirent field.
+ *
+ * All entries are read including hidden links. Blank
+ * entries are skipped.
+ *
+ * Return > 0 if success.
+ */
+ struct inode *emd_dir = umsdos_emd_dir_lookup (dir, 0);
+ if (emd_dir != NULL) {
+ while (1) {
+ if (filp->f_pos >= emd_dir->i_size) {
+ ret = 0;
+ break;
+ } else {
+ struct umsdos_dirent entry;
+ off_t f_pos = filp->f_pos;
+
+ ret = umsdos_emd_dir_readentry (emd_dir, filp, &entry);
+ if (ret < 0) {
+ break;
+ } else if (entry.name_len > 0) {
+ struct umsdos_info info;
+
+ ret = entry.name_len;
+ umsdos_parse (entry.name, entry.name_len, &info);
+ info.f_pos = f_pos;
+ umsdos_manglename (&info);
+ copy_to_user (&idata->umsdos_dirent, &entry
+ ,sizeof (entry));
+ copy_to_user (&idata->dos_dirent.d_name
+ ,info.fake.fname, info.fake.len + 1);
+ break;
+ }
+ }
+ }
+ iput (emd_dir); /* FIXME? */
+ } else {
+ /* The absence of the EMD is simply seen as an EOF */
+ ret = 0;
+ }
+ } else if (cmd == UMSDOS_INIT_EMD) {
+ /* #Specification: ioctl / UMSDOS_INIT_EMD
+ * The UMSDOS_INIT_EMD command make sure the EMD
+ * exist for a directory. If it does not, it is
+ * created. Also, it makes sure the directory functions
+ * table (struct inode_operations) is set to the UMSDOS
+ * semantic. This mean that umssync may be applied to
+ * an "opened" msdos directory, and it will change behavior
+ * on the fly.
+ *
+ * Return 0 if success.
+ */
+ extern struct inode_operations umsdos_rdir_inode_operations;
+ struct inode *emd_dir = umsdos_emd_dir_lookup (dir, 1);
+
+ ret = emd_dir != NULL;
+ iput (emd_dir); /* FIXME?? */
+
+ dir->i_op = ret
+ ? &umsdos_dir_inode_operations
+ : &umsdos_rdir_inode_operations;
+ } else {
+ struct umsdos_ioctl data;
+
+ copy_from_user (&data, idata, sizeof (data));
+ if (cmd == UMSDOS_CREAT_EMD) {
+ /* #Specification: ioctl / UMSDOS_CREAT_EMD
+ * The umsdos_dirent field of the struct umsdos_ioctl is used
+ * as is to create a new entry in the EMD of the directory.
+ * The DOS directory is not modified.
+ * No validation is done (yet).
+ *
+ * Return 0 if success.
+ */
+ struct umsdos_info info;
+
+ /* This makes sure info.entry and info in general is correctly */
+ /* initialised */
+ memcpy (&info.entry, &data.umsdos_dirent
+ ,sizeof (data.umsdos_dirent));
+ umsdos_parse (data.umsdos_dirent.name
+ ,data.umsdos_dirent.name_len, &info);
+ ret = umsdos_newentry (dir, &info);
+ } else if (cmd == UMSDOS_RENAME_DOS) {
+ struct dentry *old_dentry, *new_dentry; /* FIXME */
+
+ /* #Specification: ioctl / UMSDOS_RENAME_DOS
+ * A file or directory is rename in a DOS directory
+ * (not moved across directory). The source name
+ * is in the dos_dirent.name field and the destination
+ * is in umsdos_dirent.name field.
+ *
+ * This ioctl allows umssync to rename a mangle file
+ * name before syncing it back in the EMD.
+ */
+ inc_count (dir);
+ inc_count (dir);
+ /*
+ * ret = msdos_rename (dir
+ * ,data.dos_dirent.d_name,data.dos_dirent.d_reclen
+ * ,dir
+ * ,data.umsdos_dirent.name,data.umsdos_dirent.name_len);
+ */
+ old_dentry = creat_dentry (data.dos_dirent.d_name, data.dos_dirent.d_reclen, NULL, geti_dentry (dir)); /* FIXME: prolly should fill inode part */
+ new_dentry = creat_dentry (data.umsdos_dirent.name, data.umsdos_dirent.name_len, NULL, geti_dentry (dir));
+ ret = msdos_rename (dir, old_dentry, dir, new_dentry);
+ } else if (cmd == UMSDOS_UNLINK_EMD) {
+ /* #Specification: ioctl / UMSDOS_UNLINK_EMD
+ * The umsdos_dirent field of the struct umsdos_ioctl is used
+ * as is to remove an entry from the EMD of the directory.
+ * No validation is done (yet). The mode field is used
+ * to validate S_ISDIR or S_ISREG.
+ *
+ * Return 0 if success.
+ */
+ struct umsdos_info info;
+
+ /* This makes sure info.entry and info in general is correctly */
+ /* initialised */
+ memcpy (&info.entry, &data.umsdos_dirent
+ ,sizeof (data.umsdos_dirent));
+ umsdos_parse (data.umsdos_dirent.name
+ ,data.umsdos_dirent.name_len, &info);
+ ret = umsdos_delentry (dir, &info
+ ,S_ISDIR (data.umsdos_dirent.mode));
+ } else if (cmd == UMSDOS_UNLINK_DOS) {
+ struct dentry *dentry, *dp;
+
+ /* #Specification: ioctl / UMSDOS_UNLINK_DOS
+ * The dos_dirent field of the struct umsdos_ioctl is used to
+ * execute a msdos_unlink operation. The d_name and d_reclen
+ * fields are used.
+ *
+ * Return 0 if success.
+ */
+ inc_count (dir);
+ dp = creat_dentry (data.dos_dirent.d_name, data.dos_dirent.d_reclen, dir, NULL);
+ dentry = creat_dentry ("ioctl_unlink", 12, NULL, dp);
+ ret = msdos_unlink (dir, dentry);
+
+ } else if (cmd == UMSDOS_RMDIR_DOS) {
+ struct dentry *dentry, *dp;
+
+ /* #Specification: ioctl / UMSDOS_RMDIR_DOS
+ * The dos_dirent field of the struct umsdos_ioctl is used to
+ * execute a msdos_unlink operation. The d_name and d_reclen
+ * fields are used.
+ *
+ * Return 0 if success.
+ */
+ inc_count (dir);
+ dp = creat_dentry (data.dos_dirent.d_name, data.dos_dirent.d_reclen, dir, NULL);
+ dentry = creat_dentry ("ioctl_unlink", 12, NULL, dp);
+ ret = msdos_rmdir (dir, dentry);
+
+ } else if (cmd == UMSDOS_STAT_DOS) {
+ /* #Specification: ioctl / UMSDOS_STAT_DOS
+ * The dos_dirent field of the struct umsdos_ioctl is
+ * used to execute a stat operation in the DOS directory.
+ * The d_name and d_reclen fields are used.
+ *
+ * The following field of umsdos_ioctl.stat are filled.
+ *
+ * st_ino,st_mode,st_size,st_atime,st_mtime,st_ctime,
+ * Return 0 if success.
+ */
+ struct inode *inode;
+
+ ret = compat_umsdos_real_lookup (dir, data.dos_dirent.d_name, data.dos_dirent.d_reclen, &inode);
+ if (ret == 0) {
+ data.stat.st_ino = inode->i_ino;
+ data.stat.st_mode = inode->i_mode;
+ data.stat.st_size = inode->i_size;
+ data.stat.st_atime = inode->i_atime;
+ data.stat.st_ctime = inode->i_ctime;
+ data.stat.st_mtime = inode->i_mtime;
+ copy_to_user (&idata->stat, &data.stat, sizeof (data.stat));
+ /* iput (inode); FIXME */
+ }
+ } else if (cmd == UMSDOS_DOS_SETUP) {
+ /* #Specification: ioctl / UMSDOS_DOS_SETUP
+ * The UMSDOS_DOS_SETUP ioctl allow changing the
+ * default permission of the MsDOS file system driver
+ * on the fly. The MsDOS driver apply global permission
+ * to every file and directory. Normally these permissions
+ * are controlled by a mount option. This is not
+ * available for root partition, so a special utility
+ * (umssetup) is provided to do this, normally in
+ * /etc/rc.local.
+ *
+ * Be aware that this apply ONLY to MsDOS directory
+ * (those without EMD --linux-.---). Umsdos directory
+ * have independent (standard) permission for each
+ * and every file.
+ *
+ * The field umsdos_dirent provide the information needed.
+ * umsdos_dirent.uid and gid sets the owner and group.
+ * umsdos_dirent.mode set the permissions flags.
+ */
+ dir->i_sb->u.msdos_sb.options.fs_uid = data.umsdos_dirent.uid;
+ dir->i_sb->u.msdos_sb.options.fs_gid = data.umsdos_dirent.gid;
+ dir->i_sb->u.msdos_sb.options.fs_umask = data.umsdos_dirent.mode;
+ ret = 0;
+ }
+ }
+ }
+ Printk (("ioctl return %d\n", ret));
+ return ret;
+}
diff --git a/fs/umsdos/mangle.c b/fs/umsdos/mangle.c
index e94ff12d5..ecd62f4c3 100644
--- a/fs/umsdos/mangle.c
+++ b/fs/umsdos/mangle.c
@@ -1,7 +1,7 @@
/*
* linux/fs/umsdos/mangle.c
*
- * Written 1993 by Jacques Gelinas
+ * Written 1993 by Jacques Gelinas
*
* Control the mangling of file name to fit msdos name space.
* Many optimisation by GLU == dglaude@is1.vub.ac.be (GLAUDE DAVID)
@@ -13,474 +13,507 @@
#include <linux/umsdos_fs.h>
/*
- Complete the mangling of the MSDOS fake name
- based on the position of the entry in the EMD file.
-
- Simply complete the job of umsdos_parse; fill the extension.
-
- Beware that info->f_pos must be set.
-*/
+ * Complete the mangling of the MSDOS fake name
+ * based on the position of the entry in the EMD file.
+ *
+ * Simply complete the job of umsdos_parse; fill the extension.
+ *
+ * Beware that info->f_pos must be set.
+ */
void umsdos_manglename (struct umsdos_info *info)
{
- if (info->msdos_reject){
- /* #Specification: file name / non MSDOS conforming / mangling
- Each non MSDOS conforming file has a special extension
- build from the entry position in the EMD file.
-
- This number is then transform in a base 32 number, where
- each digit is expressed like hexadecimal number, using
- digit and letter, except it uses 22 letters from 'a' to 'v'.
- The number 32 comes from 2**5. It is faster to split a binary
- number using a base which is a power of two. And I was 32
- when I started this project. Pick your answer :-) .
-
- If the result is '0', it is replace with '_', simply
- to make it odd.
-
- This is true for the first two character of the extension.
- The last one is taken from a list of odd character, which
- are:
-
- { } ( ) ! ` ^ & @
-
- With this scheme, we can produce 9216 ( 9* 32 * 32)
- different extensions which should not clash with any useful
- extension already popular or meaningful. Since most directory
- have much less than 32 * 32 files in it, the first character
- of the extension of any mangle name will be {.
-
- Here are the reason to do this (this kind of mangling).
-
- -The mangling is deterministic. Just by the extension, we
- are able to locate the entry in the EMD file.
-
- -By keeping to beginning of the file name almost unchanged,
- we are helping the MSDOS user.
-
- -The mangling produces names not too ugly, so an msdos user
- may live with it (remember it, type it, etc...).
-
- -The mangling produces names ugly enough so no one will
- ever think of using such a name in real life. This is not
- fool proof. I don't think there is a total solution to this.
- */
- union {
- int entry_num;
- struct {
- unsigned num1:5,num2:5,num3:5;
- }num;
- } u;
- char *pt = info->fake.fname + info->fake.len;
- /* lookup for encoding the last character of the extension */
- /* It contain valid character after the ugly one to make sure */
- /* even if someone overflow the 32 * 32 * 9 limit, it still do */
- /* something */
+ if (info->msdos_reject) {
+ /* #Specification: file name / non MSDOS conforming / mangling
+ * Each non MSDOS conforming file has a special extension
+ * build from the entry position in the EMD file.
+ *
+ * This number is then transform in a base 32 number, where
+ * each digit is expressed like hexadecimal number, using
+ * digit and letter, except it uses 22 letters from 'a' to 'v'.
+ * The number 32 comes from 2**5. It is faster to split a binary
+ * number using a base which is a power of two. And I was 32
+ * when I started this project. Pick your answer :-) .
+ *
+ * If the result is '0', it is replace with '_', simply
+ * to make it odd.
+ *
+ * This is true for the first two character of the extension.
+ * The last one is taken from a list of odd character, which
+ * are:
+ *
+ * { } ( ) ! ` ^ & @
+ *
+ * With this scheme, we can produce 9216 ( 9* 32 * 32)
+ * different extensions which should not clash with any useful
+ * extension already popular or meaningful. Since most directory
+ * have much less than 32 * 32 files in it, the first character
+ * of the extension of any mangle name will be {.
+ *
+ * Here are the reason to do this (this kind of mangling).
+ *
+ * -The mangling is deterministic. Just by the extension, we
+ * are able to locate the entry in the EMD file.
+ *
+ * -By keeping to beginning of the file name almost unchanged,
+ * we are helping the MSDOS user.
+ *
+ * -The mangling produces names not too ugly, so an msdos user
+ * may live with it (remember it, type it, etc...).
+ *
+ * -The mangling produces names ugly enough so no one will
+ * ever think of using such a name in real life. This is not
+ * fool proof. I don't think there is a total solution to this.
+ */
+ union {
+ int entry_num;
+ struct {
+ unsigned num1:5, num2:5, num3:5;
+ } num;
+ } u;
+ char *pt = info->fake.fname + info->fake.len;
+
+ /* lookup for encoding the last character of the extension */
+ /* It contain valid character after the ugly one to make sure */
+ /* even if someone overflow the 32 * 32 * 9 limit, it still do */
+ /* something */
#define SPECIAL_MANGLING '{','}','(',')','!','`','^','&','@'
- static char lookup3[]={
- SPECIAL_MANGLING,
- /* This is the start of lookup12 */
- '_','1','2','3','4','5','6','7','8','9',
- 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o',
- 'p','q','r','s','t','u','v'
- };
+ static char lookup3[] =
+ {
+ SPECIAL_MANGLING,
+ /* This is the start of lookup12 */
+ '_', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
+ 'p', 'q', 'r', 's', 't', 'u', 'v'
+ };
+
#define lookup12 (lookup3+9)
- u.entry_num = info->f_pos / UMSDOS_REC_SIZE;
- if (u.entry_num > (9* 32 * 32)){
- printk ("UMSDOS: More than 9216 file in a directory.\n"
- "This may break the mangling strategy.\n"
- "Not a killer problem. See doc.\n");
- }
- *pt++ = '.';
- *pt++ = lookup3 [u.num.num3];
- *pt++ = lookup12[u.num.num2];
- *pt++ = lookup12[u.num.num1];
- *pt = '\0'; /* help doing printk */
- info->fake.len += 4;
- info->msdos_reject = 0; /* Avoid mangling twice */
- }
+ u.entry_num = info->f_pos / UMSDOS_REC_SIZE;
+ if (u.entry_num > (9 * 32 * 32)) {
+ printk ("UMSDOS: More than 9216 file in a directory.\n"
+ "This may break the mangling strategy.\n"
+ "Not a killer problem. See doc.\n");
+ }
+ *pt++ = '.';
+ *pt++ = lookup3[u.num.num3];
+ *pt++ = lookup12[u.num.num2];
+ *pt++ = lookup12[u.num.num1];
+ *pt = '\0'; /* help doing printk */
+ info->fake.len += 4;
+ info->msdos_reject = 0; /* Avoid mangling twice */
+ }
}
/*
- Evaluate the record size needed to store of name of len character.
- The value returned is a multiple of UMSDOS_REC_SIZE.
-*/
+ * Evaluate the record size needed to store of name of len character.
+ * The value returned is a multiple of UMSDOS_REC_SIZE.
+ */
int umsdos_evalrecsize (int len)
{
- struct umsdos_dirent dirent;
- int nbrec = 1+((len-1+(dirent.name-(char*)&dirent))
- / UMSDOS_REC_SIZE);
- return nbrec * UMSDOS_REC_SIZE;
- /*
- GLU This should be inlined or something to speed it up to the max.
- GLU nbrec is absolutely not needed to return the value.
- */
+ struct umsdos_dirent dirent;
+ int nbrec = 1 + ((len - 1 + (dirent.name - (char *) &dirent))
+ / UMSDOS_REC_SIZE);
+
+ return nbrec * UMSDOS_REC_SIZE;
+ /*
+ * GLU This should be inlined or something to speed it up to the max.
+ * GLU nbrec is absolutely not needed to return the value.
+ */
}
#ifdef TEST
int umsdos_evalrecsize_old (int len)
{
- struct umsdos_dirent dirent;
- int size = len + (dirent.name-(char*)&dirent);
- int nbrec = size / UMSDOS_REC_SIZE;
- int extra = size % UMSDOS_REC_SIZE;
- if (extra > 0) nbrec++;
- return nbrec * UMSDOS_REC_SIZE;
+ struct umsdos_dirent dirent;
+ int size = len + (dirent.name - (char *) &dirent);
+ int nbrec = size / UMSDOS_REC_SIZE;
+ int extra = size % UMSDOS_REC_SIZE;
+
+ if (extra > 0)
+ nbrec++;
+ return nbrec * UMSDOS_REC_SIZE;
}
#endif
/*
- Fill the struct info with the full and msdos name of a file
- Return 0 if all is ok, a negative error code otherwise.
-*/
+ * Fill the struct info with the full and msdos name of a file
+ * Return 0 if all is ok, a negative error code otherwise.
+ */
int umsdos_parse (
- const char *fname,
- int len,
- struct umsdos_info *info)
+ const char *fname,
+ int len,
+ struct umsdos_info *info)
{
- int ret = -ENAMETOOLONG;
- /* #Specification: file name / too long
- If a file name exceed UMSDOS maxima, the file name is silently
- truncated. This makes it conformant with the other file system
- of Linux (minix and ext2 at least).
- */
- if (len > UMSDOS_MAXNAME) len = UMSDOS_MAXNAME;
- {
- const char *firstpt=NULL; /* First place we saw a . in fname */
- /* #Specification: file name / non MSDOS conforming / base length 0
- file name beginning with a period '.' are invalid for MsDOS.
- It needs absolutely a base name. So the file name is mangled
- */
- int ivldchar = fname[0] == '.';/* At least one invalid character */
- int msdos_len = len;
- int base_len;
- /*
- cardinal_per_size tells if there exist at least one
- DOS pseudo devices on length n. See the test below.
- */
- static const char cardinal_per_size[9]={
- 0, 0, 0, 1, 1, 0, 1, 0, 1
- };
- /*
- lkp translate all character to acceptable character (for DOS).
- When lkp[n] == n, it means also it is an acceptable one.
- So it serve both as a flag and as a translator.
- */
- static char lkp[256];
- static char is_init=0;
- if (!is_init){
- /*
- Initialisation of the array is easier and less error prone
- like this.
- */
- int i;
- static const char *spc = "\"*+,/:;<=>?[\\]|~";
- is_init = 1;
- for (i=0; i<=32; i++) lkp[i] = '#';
- for (i=33; i<'A'; i++) lkp[i] = (char)i;
- for (i='A'; i<='Z'; i++) lkp[i] = (char)(i+('a'-'A'));
- for (i='Z'+1; i<127; i++) lkp[i] = (char)i;
- for (i=128; i<256; i++) lkp[i] = '#';
-
- lkp['.'] = '_';
- while (*spc != '\0') lkp[(unsigned char)(*spc++)] = '#';
- }
- /* GLU
- file name which are longer than 8+'.'+3 are invalid for MsDOS.
- So the file name is to be mangled no more test needed.
- This Speed Up for long and very long name.
- The position of the last point is no more necessary anyway.
- */
- if (len<=(8+1+3)){
- const char *pt = fname;
- const char *endpt = fname + len;
- while (pt < endpt){
- if (*pt == '.'){
- if (firstpt != NULL){
- /* 2 . in a file name. Reject */
- ivldchar = 1;
- break;
- }else{
- int extlen = (int)(endpt - pt);
- firstpt = pt;
- if (firstpt - fname > 8){
- /* base name longer than 8: reject */
- ivldchar = 1;
- break;
- }else if (extlen > 4){
- /* Extension longer than 4 (including .): reject */
- ivldchar = 1;
- break;
- }else if (extlen == 1){
- /* #Specification: file name / non MSDOS conforming / last char == .
- If the last character of a file name is
- a period, mangling is applied. MsDOS do
- not support those file name.
- */
- ivldchar = 1;
- break;
- }else if (extlen == 4){
- /* #Specification: file name / non MSDOS conforming / mangling clash
- To avoid clash with the umsdos mangling, any file
- with a special character as the first character
- of the extension will be mangled. This solve the
- following problem:
-
- #
- touch FILE
- # FILE is invalid for DOS, so mangling is applied
- # file.{_1 is created in the DOS directory
- touch file.{_1
- # To UMSDOS file point to a single DOS entry.
- # So file.{_1 has to be mangled.
- #
- */
- static char special[]={
- SPECIAL_MANGLING,'\0'
- };
- if (strchr(special,firstpt[1])!= NULL){
- ivldchar = 1;
- break;
- }
- }
- }
- }else if (lkp[(unsigned char)(*pt)] != *pt){
- ivldchar = 1;
- break;
- }
- pt++;
- }
- }else{
- ivldchar = 1;
- }
- if (ivldchar
- || (firstpt == NULL && len > 8)
- || (len == UMSDOS_EMD_NAMELEN
- && memcmp(fname,UMSDOS_EMD_FILE,UMSDOS_EMD_NAMELEN)==0)){
- /* #Specification: file name / --linux-.---
- The name of the EMD file --linux-.--- is map to a mangled
- name. So UMSDOS does not restrict its use.
- */
- /* #Specification: file name / non MSDOS conforming / mangling
- Non MSDOS conforming file name must use some alias to fit
- in the MSDOS name space.
-
- The strategy is simple. The name is simply truncated to
- 8 char. points are replace with underscore and a
- number is given as an extension. This number correspond
- to the entry number in the EMD file. The EMD file
- only need to carry the real name.
-
- Upper case is also convert to lower case.
- Control character are converted to #.
- Space are converted to #.
- The following character are also converted to #.
- #
- " * + , / : ; < = > ? [ \ ] | ~
- #
-
- Sometime, the problem is not in MsDOS itself but in
- command.com.
- */
- int i;
- char *pt = info->fake.fname;
- base_len = msdos_len = (msdos_len>8) ? 8 : msdos_len;
- /*
- There is no '.' any more so we know for a fact that
- the base length is the length.
- */
- memcpy (info->fake.fname,fname,msdos_len);
- for (i=0; i<msdos_len; i++, pt++) *pt = lkp[(unsigned char)(*pt)];
- *pt = '\0'; /* GLU C'est sur on a un 0 a la fin */
- info->msdos_reject = 1;
- /*
- The numeric extension is added only when we know
- the position in the EMD file, in umsdos_newentry(),
- umsdos_delentry(), and umsdos_findentry().
- See umsdos_manglename().
- */
- }else{
- /* Conforming MSDOS file name */
- strncpy (info->fake.fname,fname,len);
- info->msdos_reject = 0;
- base_len = firstpt != NULL ? (int)(firstpt - fname) : len;
- }
- if (cardinal_per_size[base_len]){
- /* #Specification: file name / MSDOS devices / mangling
- To avoid unreachable file from MsDOS, any MsDOS conforming
- file with a basename equal to one of the MsDOS pseudo
- devices will be mangled.
-
- If a file such as "prn" was created, it would be unreachable
- under MsDOS because prn is assumed to be the printer, even
- if the file does have an extension.
-
- Since the extension is unimportant to MsDOS, we must patch
- the basename also. We simply insert a minus '-'. To avoid
- conflict with valid file with a minus in front (such as
- "-prn"), we add an mangled extension like any other
- mangled file name.
-
- Here is the list of DOS pseudo devices:
-
- #
- "prn","con","aux","nul",
- "lpt1","lpt2","lpt3","lpt4",
- "com1","com2","com3","com4",
- "clock$"
- #
-
- and some standard ones for common DOS programs
-
- "emmxxxx0","xmsxxxx0","setverxx"
-
- (Thanks to Chris Hall <CAH17@PHOENIX.CAMBRIDGE.AC.UK>
- for pointing these to me).
-
- Is there one missing ?
- */
- /* This table must be ordered by length */
- static const char *tbdev[]={
- "prn","con","aux","nul",
- "lpt1","lpt2","lpt3","lpt4",
- "com1","com2","com3","com4",
- "clock$",
- "emmxxxx0","xmsxxxx0","setverxx"
- };
- /* Tell where to find in tbdev[], the first name of */
- /* a certain length */
- static const char start_ind_dev[9]={
- 0, 0, 0, 4, 12, 12, 13, 13, 16
- };
- char basen[9];
- int i;
- for (i=start_ind_dev[base_len-1]; i<start_ind_dev[base_len]; i++){
- if (memcmp(info->fake.fname,tbdev[i],base_len)==0){
- memcpy (basen,info->fake.fname,base_len);
- basen[base_len] = '\0'; /* GLU C'est sur on a un 0 a la fin */
- /*
- GLU On ne fait cela que si necessaire, on essaye d'etre le
- GLU simple dans le cas general (le plus frequent).
- */
- info->fake.fname[0] = '-';
- strcpy (info->fake.fname+1,basen); /* GLU C'est sur on a un 0 a la fin */
- msdos_len = (base_len==8) ? 8 : base_len + 1;
- info->msdos_reject = 1;
- break;
+ int ret = -ENAMETOOLONG;
+
+ /* #Specification: file name / too long
+ * If a file name exceed UMSDOS maxima, the file name is silently
+ * truncated. This makes it conformant with the other file system
+ * of Linux (minix and ext2 at least).
+ */
+ if (len > UMSDOS_MAXNAME)
+ len = UMSDOS_MAXNAME;
+ {
+ const char *firstpt = NULL; /* First place we saw a . in fname */
+
+ /* #Specification: file name / non MSDOS conforming / base length 0
+ * file name beginning with a period '.' are invalid for MsDOS.
+ * It needs absolutely a base name. So the file name is mangled
+ */
+ int ivldchar = fname[0] == '.'; /* At least one invalid character */
+ int msdos_len = len;
+ int base_len;
+
+ /*
+ * cardinal_per_size tells if there exist at least one
+ * DOS pseudo devices on length n. See the test below.
+ */
+ static const char cardinal_per_size[9] =
+ {
+ 0, 0, 0, 1, 1, 0, 1, 0, 1
+ };
+
+ /*
+ * lkp translate all character to acceptable character (for DOS).
+ * When lkp[n] == n, it means also it is an acceptable one.
+ * So it serve both as a flag and as a translator.
+ */
+ static char lkp[256];
+ static char is_init = 0;
+
+ if (!is_init) {
+ /*
+ * Initialisation of the array is easier and less error prone
+ * like this.
+ */
+ int i;
+ static const char *spc = "\"*+,/:;<=>?[\\]|~";
+
+ is_init = 1;
+ for (i = 0; i <= 32; i++)
+ lkp[i] = '#';
+ for (i = 33; i < 'A'; i++)
+ lkp[i] = (char) i;
+ for (i = 'A'; i <= 'Z'; i++)
+ lkp[i] = (char) (i + ('a' - 'A'));
+ for (i = 'Z' + 1; i < 127; i++)
+ lkp[i] = (char) i;
+ for (i = 128; i < 256; i++)
+ lkp[i] = '#';
+
+ lkp['.'] = '_';
+ while (*spc != '\0')
+ lkp[(unsigned char) (*spc++)] = '#';
+ }
+ /* GLU
+ * file name which are longer than 8+'.'+3 are invalid for MsDOS.
+ * So the file name is to be mangled no more test needed.
+ * This Speed Up for long and very long name.
+ * The position of the last point is no more necessary anyway.
+ */
+ if (len <= (8 + 1 + 3)) {
+ const char *pt = fname;
+ const char *endpt = fname + len;
+
+ while (pt < endpt) {
+ if (*pt == '.') {
+ if (firstpt != NULL) {
+ /* 2 . in a file name. Reject */
+ ivldchar = 1;
+ break;
+ } else {
+ int extlen = (int) (endpt - pt);
+
+ firstpt = pt;
+ if (firstpt - fname > 8) {
+ /* base name longer than 8: reject */
+ ivldchar = 1;
+ break;
+ } else if (extlen > 4) {
+ /* Extension longer than 4 (including .): reject */
+ ivldchar = 1;
+ break;
+ } else if (extlen == 1) {
+ /* #Specification: file name / non MSDOS conforming / last char == .
+ * If the last character of a file name is
+ * a period, mangling is applied. MsDOS do
+ * not support those file name.
+ */
+ ivldchar = 1;
+ break;
+ } else if (extlen == 4) {
+ /* #Specification: file name / non MSDOS conforming / mangling clash
+ * To avoid clash with the umsdos mangling, any file
+ * with a special character as the first character
+ * of the extension will be mangled. This solve the
+ * following problem:
+ *
+ * #
+ * touch FILE
+ * # FILE is invalid for DOS, so mangling is applied
+ * # file.{_1 is created in the DOS directory
+ * touch file.{_1
+ * # To UMSDOS file point to a single DOS entry.
+ * # So file.{_1 has to be mangled.
+ * #
+ */
+ static char special[] =
+ {
+ SPECIAL_MANGLING, '\0'
+ };
+
+ if (strchr (special, firstpt[1]) != NULL) {
+ ivldchar = 1;
+ break;
+ }
+ }
+ }
+ } else if (lkp[(unsigned char) (*pt)] != *pt) {
+ ivldchar = 1;
+ break;
+ }
+ pt++;
+ }
+ } else {
+ ivldchar = 1;
+ }
+ if (ivldchar
+ || (firstpt == NULL && len > 8)
+ || (len == UMSDOS_EMD_NAMELEN
+ && memcmp (fname, UMSDOS_EMD_FILE, UMSDOS_EMD_NAMELEN) == 0)) {
+ /* #Specification: file name / --linux-.---
+ * The name of the EMD file --linux-.--- is map to a mangled
+ * name. So UMSDOS does not restrict its use.
+ */
+ /* #Specification: file name / non MSDOS conforming / mangling
+ * Non MSDOS conforming file name must use some alias to fit
+ * in the MSDOS name space.
+ *
+ * The strategy is simple. The name is simply truncated to
+ * 8 char. points are replace with underscore and a
+ * number is given as an extension. This number correspond
+ * to the entry number in the EMD file. The EMD file
+ * only need to carry the real name.
+ *
+ * Upper case is also convert to lower case.
+ * Control character are converted to #.
+ * Space are converted to #.
+ * The following character are also converted to #.
+ * #
+ * " * + , / : ; < = > ? [ \ ] | ~
+ * #
+ *
+ * Sometime, the problem is not in MsDOS itself but in
+ * command.com.
+ */
+ int i;
+ char *pt = info->fake.fname;
+
+ base_len = msdos_len = (msdos_len > 8) ? 8 : msdos_len;
+ /*
+ * There is no '.' any more so we know for a fact that
+ * the base length is the length.
+ */
+ memcpy (info->fake.fname, fname, msdos_len);
+ for (i = 0; i < msdos_len; i++, pt++)
+ *pt = lkp[(unsigned char) (*pt)];
+ *pt = '\0'; /* GLU C'est sur on a un 0 a la fin */
+ info->msdos_reject = 1;
+ /*
+ * The numeric extension is added only when we know
+ * the position in the EMD file, in umsdos_newentry(),
+ * umsdos_delentry(), and umsdos_findentry().
+ * See umsdos_manglename().
+ */
+ } else {
+ /* Conforming MSDOS file name */
+ strncpy (info->fake.fname, fname, len);
+ info->msdos_reject = 0;
+ base_len = firstpt != NULL ? (int) (firstpt - fname) : len;
+ }
+ if (cardinal_per_size[base_len]) {
+ /* #Specification: file name / MSDOS devices / mangling
+ * To avoid unreachable file from MsDOS, any MsDOS conforming
+ * file with a basename equal to one of the MsDOS pseudo
+ * devices will be mangled.
+ *
+ * If a file such as "prn" was created, it would be unreachable
+ * under MsDOS because prn is assumed to be the printer, even
+ * if the file does have an extension.
+ *
+ * Since the extension is unimportant to MsDOS, we must patch
+ * the basename also. We simply insert a minus '-'. To avoid
+ * conflict with valid file with a minus in front (such as
+ * "-prn"), we add an mangled extension like any other
+ * mangled file name.
+ *
+ * Here is the list of DOS pseudo devices:
+ *
+ * #
+ * "prn","con","aux","nul",
+ * "lpt1","lpt2","lpt3","lpt4",
+ * "com1","com2","com3","com4",
+ * "clock$"
+ * #
+ *
+ * and some standard ones for common DOS programs
+ *
+ * "emmxxxx0","xmsxxxx0","setverxx"
+ *
+ * (Thanks to Chris Hall <CAH17@PHOENIX.CAMBRIDGE.AC.UK>
+ * for pointing these to me).
+ *
+ * Is there one missing ?
+ */
+ /* This table must be ordered by length */
+ static const char *tbdev[] =
+ {
+ "prn", "con", "aux", "nul",
+ "lpt1", "lpt2", "lpt3", "lpt4",
+ "com1", "com2", "com3", "com4",
+ "clock$",
+ "emmxxxx0", "xmsxxxx0", "setverxx"
+ };
+
+ /* Tell where to find in tbdev[], the first name of */
+ /* a certain length */
+ static const char start_ind_dev[9] =
+ {
+ 0, 0, 0, 4, 12, 12, 13, 13, 16
+ };
+ char basen[9];
+ int i;
+
+ for (i = start_ind_dev[base_len - 1]; i < start_ind_dev[base_len]; i++) {
+ if (memcmp (info->fake.fname, tbdev[i], base_len) == 0) {
+ memcpy (basen, info->fake.fname, base_len);
+ basen[base_len] = '\0'; /* GLU C'est sur on a un 0 a la fin */
+ /*
+ * GLU On ne fait cela que si necessaire, on essaye d'etre le
+ * GLU simple dans le cas general (le plus frequent).
+ */
+ info->fake.fname[0] = '-';
+ strcpy (info->fake.fname + 1, basen); /* GLU C'est sur on a un 0 a la fin */
+ msdos_len = (base_len == 8) ? 8 : base_len + 1;
+ info->msdos_reject = 1;
+ break;
+ }
+ }
+ }
+ info->fake.fname[msdos_len] = '\0'; /* Help doing printk */
+ /* GLU Ce zero devrais deja y etre ! (invariant ?) */
+ info->fake.len = msdos_len;
+ /* Pourquoi ne pas utiliser info->fake.len partout ??? plus long ? */
+ memcpy (info->entry.name, fname, len);
+ info->entry.name_len = len;
+ ret = 0;
}
- }
- }
- info->fake.fname[msdos_len] = '\0'; /* Help doing printk */
- /* GLU Ce zero devrais deja y etre ! (invariant ?) */
- info->fake.len = msdos_len;
- /* Pourquoi ne pas utiliser info->fake.len partout ??? plus long ?*/
- memcpy (info->entry.name,fname,len);
- info->entry.name_len = len;
- ret = 0;
- }
- /*
- Evaluate how many record are needed to store this entry.
- */
- info->recsize = umsdos_evalrecsize (len);
- return ret;
+ /*
+ * Evaluate how many record are needed to store this entry.
+ */
+ info->recsize = umsdos_evalrecsize (len);
+ return ret;
}
#ifdef TEST
-struct MANG_TEST{
- char *fname; /* Name to validate */
- int msdos_reject; /* Expected msdos_reject flag */
- char *msname; /* Expected msdos name */
+struct MANG_TEST {
+ char *fname; /* Name to validate */
+ int msdos_reject; /* Expected msdos_reject flag */
+ char *msname; /* Expected msdos name */
};
-struct MANG_TEST tb[]={
- "hello", 0, "hello",
- "hello.1", 0, "hello.1",
- "hello.1_", 0, "hello.1_",
- "prm", 0, "prm",
-
+struct MANG_TEST tb[] =
+{
+ "hello", 0, "hello",
+ "hello.1", 0, "hello.1",
+ "hello.1_", 0, "hello.1_",
+ "prm", 0, "prm",
+
#ifdef PROPOSITION
- "HELLO", 1, "hello",
- "Hello.1", 1, "hello.1",
- "Hello.c", 1, "hello.c",
+ "HELLO", 1, "hello",
+ "Hello.1", 1, "hello.1",
+ "Hello.c", 1, "hello.c",
#elseif
/*
- Je trouve les trois exemples ci-dessous tres "malheureux".
- Je propose de mettre en minuscule dans un passe preliminaire,
- et de tester apres si il y a d'autres caracters "mechants".
- Bon, je ne l'ai pas fait, parceque ce n'est pas si facilement
- modifiable que ca. Mais c'est pour le principe.
- Evidemment cela augmente les chances de "Collision",
- par exemple: entre "HELLO" et "Hello", mais ces problemes
- peuvent etre traiter ailleur avec les autres collisions.
-*/
- "HELLO", 1, "hello",
- "Hello.1", 1, "hello_1",
- "Hello.c", 1, "hello_c",
+ * Je trouve les trois exemples ci-dessous tres "malheureux".
+ * Je propose de mettre en minuscule dans un passe preliminaire,
+ * et de tester apres si il y a d'autres caracters "mechants".
+ * Bon, je ne l'ai pas fait, parceque ce n'est pas si facilement
+ * modifiable que ca. Mais c'est pour le principe.
+ * Evidemment cela augmente les chances de "Collision",
+ * par exemple: entre "HELLO" et "Hello", mais ces problemes
+ * peuvent etre traiter ailleur avec les autres collisions.
+ */
+ "HELLO", 1, "hello",
+ "Hello.1", 1, "hello_1",
+ "Hello.c", 1, "hello_c",
#endif
-
- "hello.{_1", 1, "hello_{_",
- "hello\t", 1, "hello#",
- "hello.1.1", 1, "hello_1_",
- "hel,lo", 1, "hel#lo",
- "Salut.Tu.vas.bien?", 1, "salut_tu",
- ".profile", 1, "_profile",
- ".xv", 1, "_xv",
- "toto.", 1, "toto_",
- "clock$.x", 1, "-clock$",
- "emmxxxx0", 1, "-emmxxxx",
- "emmxxxx0.abcd", 1, "-emmxxxx",
- "aux", 1, "-aux",
- "prn", 1, "-prn",
- "prn.abc", 1, "-prn",
- "PRN", 1, "-prn",
+
+ "hello.{_1", 1, "hello_{_",
+ "hello\t", 1, "hello#",
+ "hello.1.1", 1, "hello_1_",
+ "hel,lo", 1, "hel#lo",
+ "Salut.Tu.vas.bien?", 1, "salut_tu",
+ ".profile", 1, "_profile",
+ ".xv", 1, "_xv",
+ "toto.", 1, "toto_",
+ "clock$.x", 1, "-clock$",
+ "emmxxxx0", 1, "-emmxxxx",
+ "emmxxxx0.abcd", 1, "-emmxxxx",
+ "aux", 1, "-aux",
+ "prn", 1, "-prn",
+ "prn.abc", 1, "-prn",
+ "PRN", 1, "-prn",
/*
- GLU ATTENTION : Le resultat de ceux-ci sont differents avec ma version
- GLU du mangle par rapport au mangle originale.
- GLU CAUSE: La maniere de calculer la variable baselen.
- GLU Pour toi c'est toujours 3
- GLU Pour moi c'est respectivement 7, 8 et 8
- */
- "PRN.abc", 1, "prn_abc",
- "Prn.abcd", 1, "prn_abcd",
- "prn.abcd", 1, "prn_abcd",
- "Prn.abcdefghij", 1, "prn_abcd"
+ * GLU ATTENTION : Le resultat de ceux-ci sont differents avec ma version
+ * GLU du mangle par rapport au mangle originale.
+ * GLU CAUSE: La maniere de calculer la variable baselen.
+ * GLU Pour toi c'est toujours 3
+ * GLU Pour moi c'est respectivement 7, 8 et 8
+ */
+ "PRN.abc", 1, "prn_abc",
+ "Prn.abcd", 1, "prn_abcd",
+ "prn.abcd", 1, "prn_abcd",
+ "Prn.abcdefghij", 1, "prn_abcd"
};
int main (int argc, char *argv[])
{
- int i,rold,rnew;
- printf ("Testing the umsdos_parse.\n");
- for (i=0; i<sizeof(tb)/sizeof(tb[0]); i++){
- struct MANG_TEST *pttb = tb+i;
- struct umsdos_info info;
- int ok = umsdos_parse (pttb->fname,strlen(pttb->fname),&info);
- if (strcmp(info.fake.fname,pttb->msname)!=0){
- printf ("**** %s -> ",pttb->fname);
- printf ("%s <> %s\n",info.fake.fname,pttb->msname);
- }else if (info.msdos_reject != pttb->msdos_reject){
- printf ("**** %s -> %s ",pttb->fname,pttb->msname);
- printf ("%d <> %d\n",info.msdos_reject,pttb->msdos_reject);
- }else{
- printf (" %s -> %s %d\n",pttb->fname,pttb->msname
- ,pttb->msdos_reject);
- }
- }
- printf ("Testing the new umsdos_evalrecsize.");
- for (i=0; i<UMSDOS_MAXNAME ; i++){
- rnew=umsdos_evalrecsize (i);
- rold=umsdos_evalrecsize_old (i);
- if (!(i%UMSDOS_REC_SIZE)){
- printf ("\n%d:\t",i);
- }
- if (rnew!=rold){
- printf ("**** %d newres: %d != %d \n", i, rnew, rold);
- }else{
- printf(".");
- }
- }
- printf ("\nEnd of Testing.\n");
-
- return 0;
+ int i, rold, rnew;
+
+ printf ("Testing the umsdos_parse.\n");
+ for (i = 0; i < sizeof (tb) / sizeof (tb[0]); i++) {
+ struct MANG_TEST *pttb = tb + i;
+ struct umsdos_info info;
+ int ok = umsdos_parse (pttb->fname, strlen (pttb->fname), &info);
+
+ if (strcmp (info.fake.fname, pttb->msname) != 0) {
+ printf ("**** %s -> ", pttb->fname);
+ printf ("%s <> %s\n", info.fake.fname, pttb->msname);
+ } else if (info.msdos_reject != pttb->msdos_reject) {
+ printf ("**** %s -> %s ", pttb->fname, pttb->msname);
+ printf ("%d <> %d\n", info.msdos_reject, pttb->msdos_reject);
+ } else {
+ printf (" %s -> %s %d\n", pttb->fname, pttb->msname
+ ,pttb->msdos_reject);
+ }
+ }
+ printf ("Testing the new umsdos_evalrecsize.");
+ for (i = 0; i < UMSDOS_MAXNAME; i++) {
+ rnew = umsdos_evalrecsize (i);
+ rold = umsdos_evalrecsize_old (i);
+ if (!(i % UMSDOS_REC_SIZE)) {
+ printf ("\n%d:\t", i);
+ }
+ if (rnew != rold) {
+ printf ("**** %d newres: %d != %d \n", i, rnew, rold);
+ } else {
+ printf (".");
+ }
+ }
+ printf ("\nEnd of Testing.\n");
+
+ return 0;
}
#endif
diff --git a/fs/umsdos/namei.c b/fs/umsdos/namei.c
index 7b549fd96..387ed4fe3 100644
--- a/fs/umsdos/namei.c
+++ b/fs/umsdos/namei.c
@@ -1,8 +1,8 @@
/*
* linux/fs/umsdos/namei.c
*
- * Written 1993 by Jacques Gelinas
- * Inspired from linux/fs/msdos/... by Werner Almesberger
+ * Written 1993 by Jacques Gelinas
+ * Inspired from linux/fs/msdos/... by Werner Almesberger
*
* Maintain and access the --linux alternate directory file.
*/
@@ -23,291 +23,306 @@
#if 1
/*
- Wait for creation exclusivity.
- Return 0 if the dir was already available.
- Return 1 if a wait was necessary.
- When 1 is return, it means a wait was done. It does not
- mean the directory is available.
-*/
-static int umsdos_waitcreate(struct inode *dir)
+ * Wait for creation exclusivity.
+ * Return 0 if the dir was already available.
+ * Return 1 if a wait was necessary.
+ * When 1 is return, it means a wait was done. It does not
+ * mean the directory is available.
+ */
+static int umsdos_waitcreate (struct inode *dir)
{
- int ret = 0;
- if (dir->u.umsdos_i.u.dir_info.creating
- && dir->u.umsdos_i.u.dir_info.pid != current->pid){
- sleep_on(&dir->u.umsdos_i.u.dir_info.p);
- ret = 1;
- }
- return ret;
+ int ret = 0;
+
+ if (dir->u.umsdos_i.u.dir_info.creating
+ && dir->u.umsdos_i.u.dir_info.pid != current->pid) {
+ sleep_on (&dir->u.umsdos_i.u.dir_info.p);
+ ret = 1;
+ }
+ return ret;
}
/*
- Wait for any lookup process to finish
-*/
+ * Wait for any lookup process to finish
+ */
static void umsdos_waitlookup (struct inode *dir)
{
- while (dir->u.umsdos_i.u.dir_info.looking){
- sleep_on(&dir->u.umsdos_i.u.dir_info.p);
- }
+ while (dir->u.umsdos_i.u.dir_info.looking) {
+ sleep_on (&dir->u.umsdos_i.u.dir_info.p);
+ }
}
/*
- Lock all other process out of this directory.
-*/
+ * Lock all other process out of this directory.
+ */
void umsdos_lockcreate (struct inode *dir)
{
- /* #Specification: file creation / not atomic
- File creation is a two step process. First we create (allocate)
- an entry in the EMD file and then (using the entry offset) we
- build a unique name for MSDOS. We create this name in the msdos
- space.
-
- We have to use semaphore (sleep_on/wake_up) to prevent lookup
- into a directory when we create a file or directory and to
- prevent creation while a lookup is going on. Since many lookup
- may happen at the same time, the semaphore is a counter.
-
- Only one creation is allowed at the same time. This protection
- may not be necessary. The problem arise mainly when a lookup
- or a readdir is done while a file is partially created. The
- lookup process see that as a "normal" problem and silently
- erase the file from the EMD file. Normal because a file
- may be erased during a MSDOS session, but not removed from
- the EMD file.
-
- The locking is done on a directory per directory basis. Each
- directory inode has its wait_queue.
-
- For some operation like hard link, things even get worse. Many
- creation must occur at once (atomic). To simplify the design
- a process is allowed to recursively lock the directory for
- creation. The pid of the locking process is kept along with
- a counter so a second level of locking is granted or not.
- */
- /*
- Wait for any creation process to finish except
- if we (the process) own the lock
- */
- while (umsdos_waitcreate(dir)!=0);
- dir->u.umsdos_i.u.dir_info.creating++;
- dir->u.umsdos_i.u.dir_info.pid = current->pid;
- umsdos_waitlookup (dir);
+ /* #Specification: file creation / not atomic
+ * File creation is a two step process. First we create (allocate)
+ * an entry in the EMD file and then (using the entry offset) we
+ * build a unique name for MSDOS. We create this name in the msdos
+ * space.
+ *
+ * We have to use semaphore (sleep_on/wake_up) to prevent lookup
+ * into a directory when we create a file or directory and to
+ * prevent creation while a lookup is going on. Since many lookup
+ * may happen at the same time, the semaphore is a counter.
+ *
+ * Only one creation is allowed at the same time. This protection
+ * may not be necessary. The problem arise mainly when a lookup
+ * or a readdir is done while a file is partially created. The
+ * lookup process see that as a "normal" problem and silently
+ * erase the file from the EMD file. Normal because a file
+ * may be erased during a MSDOS session, but not removed from
+ * the EMD file.
+ *
+ * The locking is done on a directory per directory basis. Each
+ * directory inode has its wait_queue.
+ *
+ * For some operation like hard link, things even get worse. Many
+ * creation must occur at once (atomic). To simplify the design
+ * a process is allowed to recursively lock the directory for
+ * creation. The pid of the locking process is kept along with
+ * a counter so a second level of locking is granted or not.
+ */
+ /*
+ * Wait for any creation process to finish except
+ * if we (the process) own the lock
+ */
+ while (umsdos_waitcreate (dir) != 0);
+ dir->u.umsdos_i.u.dir_info.creating++;
+ dir->u.umsdos_i.u.dir_info.pid = current->pid;
+ umsdos_waitlookup (dir);
}
/*
- Lock all other process out of those two directories.
-*/
+ * Lock all other process out of those two directories.
+ */
static void umsdos_lockcreate2 (struct inode *dir1, struct inode *dir2)
{
- /*
- We must check that both directory are available before
- locking anyone of them. This is to avoid some deadlock.
- Thanks to dglaude@is1.vub.ac.be (GLAUDE DAVID) for pointing
- this to me.
- */
- while (1){
- if (umsdos_waitcreate(dir1)==0
- && umsdos_waitcreate(dir2)==0){
- /* We own both now */
- dir1->u.umsdos_i.u.dir_info.creating++;
- dir1->u.umsdos_i.u.dir_info.pid = current->pid;
- dir2->u.umsdos_i.u.dir_info.creating++;
- dir2->u.umsdos_i.u.dir_info.pid = current->pid;
- break;
- }
- }
- umsdos_waitlookup(dir1);
- umsdos_waitlookup(dir2);
+ /*
+ * We must check that both directory are available before
+ * locking anyone of them. This is to avoid some deadlock.
+ * Thanks to dglaude@is1.vub.ac.be (GLAUDE DAVID) for pointing
+ * this to me.
+ */
+ while (1) {
+ if (umsdos_waitcreate (dir1) == 0
+ && umsdos_waitcreate (dir2) == 0) {
+ /* We own both now */
+ dir1->u.umsdos_i.u.dir_info.creating++;
+ dir1->u.umsdos_i.u.dir_info.pid = current->pid;
+ dir2->u.umsdos_i.u.dir_info.creating++;
+ dir2->u.umsdos_i.u.dir_info.pid = current->pid;
+ break;
+ }
+ }
+ umsdos_waitlookup (dir1);
+ umsdos_waitlookup (dir2);
}
/*
- Wait until creation is finish in this directory.
-*/
+ * Wait until creation is finish in this directory.
+ */
void umsdos_startlookup (struct inode *dir)
{
- while (umsdos_waitcreate (dir) != 0);
- dir->u.umsdos_i.u.dir_info.looking++;
+ while (umsdos_waitcreate (dir) != 0);
+ dir->u.umsdos_i.u.dir_info.looking++;
}
/*
- Unlock the directory.
-*/
+ * Unlock the directory.
+ */
void umsdos_unlockcreate (struct inode *dir)
{
- dir->u.umsdos_i.u.dir_info.creating--;
- if (dir->u.umsdos_i.u.dir_info.creating < 0){
- printk ("UMSDOS: dir->u.umsdos_i.u.dir_info.creating < 0: %d"
- ,dir->u.umsdos_i.u.dir_info.creating);
- }
- wake_up (&dir->u.umsdos_i.u.dir_info.p);
+ dir->u.umsdos_i.u.dir_info.creating--;
+ if (dir->u.umsdos_i.u.dir_info.creating < 0) {
+ printk ("UMSDOS: dir->u.umsdos_i.u.dir_info.creating < 0: %d"
+ ,dir->u.umsdos_i.u.dir_info.creating);
+ }
+ wake_up (&dir->u.umsdos_i.u.dir_info.p);
}
/*
- Tell directory lookup is over.
-*/
+ * Tell directory lookup is over.
+ */
void umsdos_endlookup (struct inode *dir)
{
- dir->u.umsdos_i.u.dir_info.looking--;
- if (dir->u.umsdos_i.u.dir_info.looking < 0){
- printk ("UMSDOS: dir->u.umsdos_i.u.dir_info.looking < 0: %d"
- ,dir->u.umsdos_i.u.dir_info.looking);
- }
- wake_up (&dir->u.umsdos_i.u.dir_info.p);
+ dir->u.umsdos_i.u.dir_info.looking--;
+ if (dir->u.umsdos_i.u.dir_info.looking < 0) {
+ printk ("UMSDOS: dir->u.umsdos_i.u.dir_info.looking < 0: %d"
+ ,dir->u.umsdos_i.u.dir_info.looking);
+ }
+ wake_up (&dir->u.umsdos_i.u.dir_info.p);
}
#else
-static void umsdos_lockcreate (struct inode *dir){}
-static void umsdos_lockcreate2 (struct inode *dir1, struct inode *dir2){}
-void umsdos_startlookup (struct inode *dir){}
-static void umsdos_unlockcreate (struct inode *dir){}
-void umsdos_endlookup (struct inode *dir){}
+static void umsdos_lockcreate (struct inode *dir)
+{
+}
+static void umsdos_lockcreate2 (struct inode *dir1, struct inode *dir2)
+{
+}
+void umsdos_startlookup (struct inode *dir)
+{
+}
+static void umsdos_unlockcreate (struct inode *dir)
+{
+}
+void umsdos_endlookup (struct inode *dir)
+{
+}
+
#endif
-static int umsdos_nevercreat(
- struct inode *dir,
- struct dentry *dentry,
- int errcod) /* Length of the name */
-{
- const char *name = dentry->d_name.name;
- int len = dentry->d_name.len;
- int ret = 0;
- if (umsdos_is_pseudodos(dir,dentry)){
- /* #Specification: pseudo root / any file creation /DOS
- The pseudo sub-directory /DOS can't be created!
- EEXIST is returned.
-
- The pseudo sub-directory /DOS can't be removed!
- EPERM is returned.
- */
- ret = -EPERM;
- ret = errcod;
- }else if (name[0] == '.'
- && (len == 1 || (len == 2 && name[1] == '.'))){
- /* #Specification: create / . and ..
- If one try to creates . or .., it always fail and return
- EEXIST.
-
- If one try to delete . or .., it always fail and return
- EPERM.
-
- This should be test at the VFS layer level to avoid
- duplicating this in all file systems. Any comments ?
- */
- ret = errcod;
- }
- return ret;
+static int umsdos_nevercreat (
+ struct inode *dir,
+ struct dentry *dentry,
+ int errcod)
+{ /* Length of the name */
+ const char *name = dentry->d_name.name;
+ int len = dentry->d_name.len;
+ int ret = 0;
+
+ if (umsdos_is_pseudodos (dir, dentry)) {
+ /* #Specification: pseudo root / any file creation /DOS
+ * The pseudo sub-directory /DOS can't be created!
+ * EEXIST is returned.
+ *
+ * The pseudo sub-directory /DOS can't be removed!
+ * EPERM is returned.
+ */
+ ret = -EPERM;
+ ret = errcod;
+ } else if (name[0] == '.'
+ && (len == 1 || (len == 2 && name[1] == '.'))) {
+ /* #Specification: create / . and ..
+ * If one try to creates . or .., it always fail and return
+ * EEXIST.
+ *
+ * If one try to delete . or .., it always fail and return
+ * EPERM.
+ *
+ * This should be test at the VFS layer level to avoid
+ * duplicating this in all file systems. Any comments ?
+ */
+ ret = errcod;
+ }
+ return ret;
}
-
+
/*
- Add a new file (ordinary or special) into the alternate directory.
- The file is added to the real MSDOS directory. If successful, it
- is then added to the EDM file.
-
- Return the status of the operation. 0 mean success.
-*/
+ * Add a new file (ordinary or special) into the alternate directory.
+ * The file is added to the real MSDOS directory. If successful, it
+ * is then added to the EDM file.
+ *
+ * Return the status of the operation. 0 mean success.
+ */
static int umsdos_create_any (
- struct inode *dir,
- struct dentry *dentry, /* name/length etc*/
- int mode, /* Permission bit + file type ??? */
- int rdev, /* major, minor or 0 for ordinary file */
- /* and symlinks */
- char flags
- ) /* Will hold the inode of the newly created */
- /* file */
-{
-
- int ret;
- struct dentry *fake;
-
- Printk (("umsdos_create_any /mn/: create %.*s in dir=%lu - nevercreat=/", (int) dentry->d_name.len, dentry->d_name.name, dir->i_ino));
- ret = umsdos_nevercreat(dir,dentry,-EEXIST);
- Printk (("%d/\n", ret));
- if (ret == 0){
- struct umsdos_info info;
- ret = umsdos_parse(dentry->d_name.name,dentry->d_name.len,&info);
-
- if (ret == 0){
- info.entry.mode = mode;
- info.entry.rdev = rdev;
- info.entry.flags = flags;
- info.entry.uid = current->fsuid;
- info.entry.gid = (dir->i_mode & S_ISGID)
- ? dir->i_gid : current->fsgid;
- info.entry.ctime = info.entry.atime = info.entry.mtime
- = CURRENT_TIME;
- info.entry.nlink = 1;
- umsdos_lockcreate(dir);
- ret = umsdos_newentry (dir,&info);
- if (ret == 0){
- dir->i_count++;
- fake = creat_dentry (info.fake.fname, info.fake.len, NULL, dentry->d_parent); /* create short name dentry */
- ret = msdos_create (dir, fake, S_IFREG|0777);
- if (ret == 0){
- struct inode *inode = fake->d_inode;
- umsdos_lookup_patch (dir,inode,&info.entry,info.f_pos);
- Printk (("inode %p[%lu], count=%d ",inode, inode->i_ino, inode->i_count));
- Printk (("Creation OK: [dir %lu] %.*s pid=%d pos %ld\n", dir->i_ino,
- info.fake.len, info.fake.fname, current->pid, info.f_pos));
-
- d_instantiate(dentry, inode); /* long name also gets inode info */
- }else{
- /* #Specification: create / file exist in DOS
- Here is a situation. Trying to create a file with
- UMSDOS. The file is unknown to UMSDOS but already
- exist in the DOS directory.
-
- Here is what we are NOT doing:
-
- We could silently assume that everything is fine
- and allows the creation to succeed.
-
- It is possible not all files in the partition
- are mean to be visible from linux. By trying to create
- those file in some directory, one user may get access
- to those file without proper permissions. Looks like
- a security hole to me. Off course sharing a file system
- with DOS is some kind of security hole :-)
-
- So ?
-
- We return EEXIST in this case.
- The same is true for directory creation.
- */
- if (ret == -EEXIST){
- printk ("UMSDOS: out of sync, Creation error [%ld], "
- "deleting %.*s %d %d pos %ld\n",dir->i_ino
- ,info.fake.len,info.fake.fname,-ret,current->pid,info.f_pos);
- }
- umsdos_delentry (dir,&info,0);
+ struct inode *dir,
+ struct dentry *dentry, /* name/length etc */
+ int mode, /* Permission bit + file type ??? */
+ int rdev, /* major, minor or 0 for ordinary file and symlinks */
+ char flags
+)
+{ /* Will hold the inode of the newly created file */
+
+ int ret;
+ struct dentry *fake;
+
+ Printk (("umsdos_create_any /mn/: create %.*s in dir=%lu - nevercreat=/", (int) dentry->d_name.len, dentry->d_name.name, dir->i_ino));
+ check_dentry (dentry);
+ ret = umsdos_nevercreat (dir, dentry, -EEXIST);
+ Printk (("%d/\n", ret));
+ if (ret == 0) {
+ struct umsdos_info info;
+
+ ret = umsdos_parse (dentry->d_name.name, dentry->d_name.len, &info);
+
+ if (ret == 0) {
+ info.entry.mode = mode;
+ info.entry.rdev = rdev;
+ info.entry.flags = flags;
+ info.entry.uid = current->fsuid;
+ info.entry.gid = (dir->i_mode & S_ISGID)
+ ? dir->i_gid : current->fsgid;
+ info.entry.ctime = info.entry.atime = info.entry.mtime
+ = CURRENT_TIME;
+ info.entry.nlink = 1;
+ umsdos_lockcreate (dir);
+ ret = umsdos_newentry (dir, &info);
+ if (ret == 0) {
+ inc_count (dir);
+ fake = creat_dentry (info.fake.fname, info.fake.len, NULL, dentry->d_parent); /* create short name dentry */
+ ret = msdos_create (dir, fake, S_IFREG | 0777);
+ if (ret == 0) {
+ struct inode *inode = fake->d_inode;
+
+ umsdos_lookup_patch (dir, inode, &info.entry, info.f_pos);
+ Printk (("inode %p[%lu], count=%d ", inode, inode->i_ino, inode->i_count));
+ Printk (("Creation OK: [dir %lu] %.*s pid=%d pos %ld\n", dir->i_ino,
+ info.fake.len, info.fake.fname, current->pid, info.f_pos));
+
+ d_instantiate (dentry, inode); /* long name also gets inode info */
+ dput (fake); /* FIXME: is this ok ? we try to kill short name dentry that we don't need */
+ } else {
+ /* #Specification: create / file exist in DOS
+ * Here is a situation. Trying to create a file with
+ * UMSDOS. The file is unknown to UMSDOS but already
+ * exist in the DOS directory.
+ *
+ * Here is what we are NOT doing:
+ *
+ * We could silently assume that everything is fine
+ * and allows the creation to succeed.
+ *
+ * It is possible not all files in the partition
+ * are mean to be visible from linux. By trying to create
+ * those file in some directory, one user may get access
+ * to those file without proper permissions. Looks like
+ * a security hole to me. Off course sharing a file system
+ * with DOS is some kind of security hole :-)
+ *
+ * So ?
+ *
+ * We return EEXIST in this case.
+ * The same is true for directory creation.
+ */
+ if (ret == -EEXIST) {
+ printk ("UMSDOS: out of sync, Creation error [%ld], "
+ "deleting %.*s %d %d pos %ld\n", dir->i_ino
+ ,info.fake.len, info.fake.fname, -ret, current->pid, info.f_pos);
+ }
+ umsdos_delentry (dir, &info, 0);
+ }
+ Printk (("umsdos_create %.*s ret = %d pos %ld\n",
+ info.fake.len, info.fake.fname, ret, info.f_pos));
+ }
+ umsdos_unlockcreate (dir);
+ }
}
- Printk (("umsdos_create %.*s ret = %d pos %ld\n",
- info.fake.len, info.fake.fname, ret, info.f_pos));
- }
- umsdos_unlockcreate(dir);
- }
- }
- /* d_add(dentry,dir); /mn/ FIXME: msdos_create already did this for short name ! */
- return ret;
+ /* d_add(dentry,dir); /mn/ FIXME: msdos_create already did this for short name ! */
+ return ret;
}
/*
- Initialise the new_entry from the old for a rename operation.
- (Only useful for umsdos_rename_f() below).
-*/
-static void umsdos_ren_init(
- struct umsdos_info *new_info,
- struct umsdos_info *old_info,
- int flags) /* 0 == copy flags from old_name */
- /* != 0, this is the value of flags */
-{
- new_info->entry.mode = old_info->entry.mode;
- new_info->entry.rdev = old_info->entry.rdev;
- new_info->entry.uid = old_info->entry.uid;
- new_info->entry.gid = old_info->entry.gid;
- new_info->entry.ctime = old_info->entry.ctime;
- new_info->entry.atime = old_info->entry.atime;
- new_info->entry.mtime = old_info->entry.mtime;
- new_info->entry.flags = flags ? flags : old_info->entry.flags;
- new_info->entry.nlink = old_info->entry.nlink;
+ * Initialise the new_entry from the old for a rename operation.
+ * (Only useful for umsdos_rename_f() below).
+ */
+static void umsdos_ren_init (
+ struct umsdos_info *new_info,
+ struct umsdos_info *old_info,
+ int flags)
+{ /* 0 == copy flags from old_name */
+ /* != 0, this is the value of flags */
+ new_info->entry.mode = old_info->entry.mode;
+ new_info->entry.rdev = old_info->entry.rdev;
+ new_info->entry.uid = old_info->entry.uid;
+ new_info->entry.gid = old_info->entry.gid;
+ new_info->entry.ctime = old_info->entry.ctime;
+ new_info->entry.atime = old_info->entry.atime;
+ new_info->entry.mtime = old_info->entry.mtime;
+ new_info->entry.flags = flags ? flags : old_info->entry.flags;
+ new_info->entry.nlink = old_info->entry.nlink;
}
#define chkstk() \
@@ -319,870 +334,909 @@ if (STACK_MAGIC != *(unsigned long *)current->kernel_stack_page){\
}
#undef chkstk
-#define chkstk() do { } while (0)
-
+#define chkstk() do { } while (0);
+
/*
- Rename a file (move) in the file system.
-*/
-static int umsdos_rename_f(
- struct inode * old_dir,
- struct dentry *old_dentry,
- struct inode * new_dir,
- struct dentry *new_dentry,
- int flags) /* 0 == copy flags from old_name */
- /* != 0, this is the value of flags */
-{
- int ret = -EPERM;
- struct umsdos_info old_info;
- int old_ret = umsdos_parse (old_dentry->d_name.name,
- old_dentry->d_name.len,&old_info);
- struct umsdos_info new_info;
- int new_ret = umsdos_parse (new_dentry->d_name.name,
- new_dentry->d_name.len,&new_info);
- chkstk();
- Printk (("umsdos_rename %d %d ",old_ret,new_ret));
- if (old_ret == 0 && new_ret == 0){
- umsdos_lockcreate2(old_dir,new_dir);
- chkstk();
- Printk (("old findentry "));
- ret = umsdos_findentry(old_dir,&old_info,0);
- chkstk();
- Printk (("ret %d ",ret));
- if (ret == 0){
- /* check sticky bit on old_dir */
- if ( !(old_dir->i_mode & S_ISVTX) || capable(CAP_FOWNER) ||
- current->fsuid == old_info.entry.uid ||
- current->fsuid == old_dir->i_uid ) {
- /* Does new_name already exist? */
- PRINTK(("new findentry "));
- ret = umsdos_findentry(new_dir,&new_info,0);
- if (ret != 0 || /* if destination file exists, are we allowed to replace it ? */
- !(new_dir->i_mode & S_ISVTX) || capable(CAP_FOWNER) ||
- current->fsuid == new_info.entry.uid ||
- current->fsuid == new_dir->i_uid ) {
- PRINTK (("new newentry "));
- umsdos_ren_init(&new_info,&old_info,flags);
- ret = umsdos_newentry (new_dir,&new_info);
- chkstk();
- PRINTK (("ret %d %d ",ret,new_info.fake.len));
- if (ret == 0){
- struct dentry *old, *new;
- old = creat_dentry (old_info.fake.fname, old_info.fake.len, NULL, NULL);
- new = creat_dentry (new_info.fake.fname, new_info.fake.len, NULL, NULL);
-
- PRINTK (("msdos_rename "));
- old_dir->i_count++;
- new_dir->i_count++; /* Both inode are needed later */
- ret = msdos_rename (old_dir,
- old,
- new_dir,
- new);
- chkstk();
- PRINTK (("after m_rename ret %d ",ret));
- if (ret != 0){
- umsdos_delentry (new_dir,&new_info
- ,S_ISDIR(new_info.entry.mode));
- chkstk();
- }else{
- ret = umsdos_delentry (old_dir,&old_info
- ,S_ISDIR(old_info.entry.mode));
- chkstk();
- if (ret == 0){
- /*
- This umsdos_lookup_x does not look very useful.
- It makes sure that the inode of the file will
- be correctly setup (umsdos_patch_inode()) in
- case it is already in use.
-
- Not very efficient ...
- */
- struct inode *inode;
- new_dir->i_count++;
- PRINTK ((KERN_DEBUG "rename lookup len %d %d -- ",new_len,new_info.entry.flags));
- ret = umsdos_lookup_x (new_dir, new_dentry, 0);
- inode = new_dentry->d_inode;
- chkstk();
- if (ret != 0){
- printk ("UMSDOS: partial rename for file %.*s\n"
- ,new_info.entry.name_len,new_info.entry.name);
- }else{
- /*
- Update f_pos so notify_change will succeed
- if the file was already in use.
- */
- umsdos_set_dirinfo (inode,new_dir,new_info.f_pos);
- chkstk();
- /* iput (inode); FIXME */
+ * Rename a file (move) in the file system.
+ */
+
+static int umsdos_rename_f (
+ struct inode *old_dir,
+ struct dentry *old_dentry,
+ struct inode *new_dir,
+ struct dentry *new_dentry,
+ int flags)
+{ /* 0 == copy flags from old_name */
+ /* != 0, this is the value of flags */
+ int ret = -EPERM;
+ struct umsdos_info old_info;
+ int old_ret = umsdos_parse (old_dentry->d_name.name,
+ old_dentry->d_name.len, &old_info);
+ struct umsdos_info new_info;
+ int new_ret = umsdos_parse (new_dentry->d_name.name,
+ new_dentry->d_name.len, &new_info);
+
+ check_dentry (old_dentry);
+ check_dentry (new_dentry);
+
+ chkstk ();
+ Printk (("umsdos_rename %d %d ", old_ret, new_ret));
+ if (old_ret == 0 && new_ret == 0) {
+ umsdos_lockcreate2 (old_dir, new_dir);
+ chkstk ();
+ Printk (("old findentry "));
+ ret = umsdos_findentry (old_dir, &old_info, 0);
+ chkstk ();
+ Printk (("ret %d ", ret));
+ if (ret == 0) {
+ /* check sticky bit on old_dir */
+ if (!(old_dir->i_mode & S_ISVTX) || capable (CAP_FOWNER) ||
+ current->fsuid == old_info.entry.uid ||
+ current->fsuid == old_dir->i_uid) {
+ /* Does new_name already exist? */
+ Printk (("new findentry "));
+ ret = umsdos_findentry (new_dir, &new_info, 0);
+ if (ret != 0 || /* if destination file exists, are we allowed to replace it ? */
+ !(new_dir->i_mode & S_ISVTX) || capable (CAP_FOWNER) ||
+ current->fsuid == new_info.entry.uid ||
+ current->fsuid == new_dir->i_uid) {
+ Printk (("new newentry "));
+ umsdos_ren_init (&new_info, &old_info, flags);
+ ret = umsdos_newentry (new_dir, &new_info);
+ chkstk ();
+ Printk (("ret %d %d ", ret, new_info.fake.len));
+ if (ret == 0) {
+ struct dentry *old, *new;
+ struct inode *oldid = NULL;
+
+ ret = compat_umsdos_real_lookup (old_dir, old_info.fake.fname, old_info.fake.len, &oldid);
+ old = creat_dentry (old_info.fake.fname, old_info.fake.len, oldid, old_dentry->d_parent);
+
+ new = creat_dentry (new_info.fake.fname, new_info.fake.len, NULL, new_dentry->d_parent);
+
+ Printk (("msdos_rename "));
+ inc_count (old_dir);
+ inc_count (new_dir); /* Both inode are needed later */
+
+ check_dentry (old); check_dentry (new); /* FIXME: debug only */
+ ret = msdos_rename (old_dir, old, new_dir, new);
+ chkstk ();
+ Printk (("after m_rename ret %d ", ret));
+ kill_dentry (old);
+ kill_dentry (new);
+
+ if (ret != 0) {
+ umsdos_delentry (new_dir, &new_info, S_ISDIR (new_info.entry.mode));
+ chkstk ();
+ } else {
+ ret = umsdos_delentry (old_dir, &old_info, S_ISDIR (old_info.entry.mode));
+ chkstk ();
+ if (ret == 0) {
+ /*
+ * This umsdos_lookup_x does not look very useful.
+ * It makes sure that the inode of the file will
+ * be correctly setup (umsdos_patch_inode()) in
+ * case it is already in use.
+ *
+ * Not very efficient ...
+ */
+ struct inode *inode;
+
+ inc_count (new_dir);
+ PRINTK ((KERN_DEBUG "rename lookup len %d %d -- ", new_len, new_info.entry.flags));
+ ret = umsdos_lookup_x (new_dir, new_dentry, 0);
+ inode = new_dentry->d_inode;
+ chkstk ();
+ if (ret != 0) {
+ printk ("UMSDOS: partial rename for file %.*s\n"
+ ,new_info.entry.name_len, new_info.entry.name);
+ } else {
+ /*
+ * Update f_pos so notify_change will succeed
+ * if the file was already in use.
+ */
+ umsdos_set_dirinfo (inode, new_dir, new_info.f_pos);
+ d_move (old_dentry, new_dentry);
+ chkstk ();
+ /* iput (inode); FIXME */
+ }
+ }
+ }
+ }
+ } else {
+ /* sticky bit set on new_dir */
+ Printk (("sticky set on new "));
+ ret = -EPERM;
+ }
+ } else {
+ /* sticky bit set on old_dir */
+ Printk (("sticky set on old "));
+ ret = -EPERM;
+ }
}
- }
- }
- }
- }else{
- /* sticky bit set on new_dir */
- Printk(("sticky set on new "));
- ret = -EPERM;
+ Printk ((KERN_DEBUG "umsdos_rename_f: unlocking dirs...\n"));
+ umsdos_unlockcreate (old_dir);
+ umsdos_unlockcreate (new_dir);
}
- }else{
- /* sticky bit set on old_dir */
- Printk(("sticky set on old "));
- ret = -EPERM;
- }
- }
- umsdos_unlockcreate(old_dir);
- umsdos_unlockcreate(new_dir);
- }
- d_move(old_dentry,new_dentry);
- Printk (("\n"));
- return ret;
+ check_dentry (old_dentry);
+ check_dentry (new_dentry);
+
+ Printk ((" _ret=%d\n", ret));
+ return ret;
}
/*
- Setup un Symbolic link or a (pseudo) hard link
- Return a negative error code or 0 if ok.
-*/
-static int umsdos_symlink_x(
- struct inode * dir,
- struct dentry *dentry,
- const char * symname, /* name will point to this path */
- int mode,
- char flags)
+ * Setup un Symbolic link or a (pseudo) hard link
+ * Return a negative error code or 0 if ok.
+ */
+static int umsdos_symlink_x (
+ struct inode *dir,
+ struct dentry *dentry,
+ const char *symname, /* name will point to this path */
+ int mode,
+ char flags)
{
- /* #Specification: symbolic links / strategy
- A symbolic link is simply a file which hold a path. It is
- implemented as a normal MSDOS file (not very space efficient :-()
-
- I see 2 different way to do it. One is to place the link data
- in unused entry of the EMD file. The other is to have a separate
- file dedicated to hold all symbolic links data.
-
- Let's go for simplicity...
- */
-
-
- int ret;
- dir->i_count++;/* We keep the inode in case we need it */
- /* later */
- ret = umsdos_create_any (dir,dentry,mode,0,flags);
- Printk (("umsdos_symlink ret %d ",ret));
- if (ret == 0){
- int len = strlen(symname);
- struct file filp;
- loff_t myofs=0;
- fill_new_filp (&filp, dentry);
-
- /* Make the inode acceptable to MSDOS FIXME */
- Printk ((KERN_WARNING "umsdos_symlink_x: /mn/ Is this ok?\n"));
- Printk ((KERN_WARNING " symname=%s ; dentry name=%.*s (ino=%lu)\n", symname, (int) dentry->d_name.len, dentry->d_name.name, dentry->d_inode->i_ino));
- ret = umsdos_file_write_kmem_real (&filp, symname, len, &myofs);
- /* dput(dentry); ?? where did this come from FIXME */
- if (ret >= 0){
- if (ret != len){
- ret = -EIO;
- printk ("UMSDOS: "
- "Can't write symbolic link data\n");
- }else{
- ret = 0;
- }
- }
- if (ret != 0){
- UMSDOS_unlink (dir,dentry);
- dir = NULL;
- }
- }
- /* d_instantiate(dentry,dir); //already done in umsdos_create_any */
- Printk (("\n"));
- return ret;
+ /* #Specification: symbolic links / strategy
+ * A symbolic link is simply a file which hold a path. It is
+ * implemented as a normal MSDOS file (not very space efficient :-()
+ *
+ * I see 2 different way to do it. One is to place the link data
+ * in unused entry of the EMD file. The other is to have a separate
+ * file dedicated to hold all symbolic links data.
+ *
+ * Let's go for simplicity...
+ */
+
+
+ int ret;
+
+ inc_count (dir); /* We keep the inode in case we need it */
+ /* later */
+ ret = umsdos_create_any (dir, dentry, mode, 0, flags);
+ Printk (("umsdos_symlink ret %d ", ret));
+ if (ret == 0) {
+ int len = strlen (symname);
+ struct file filp;
+ loff_t myofs = 0;
+
+ fill_new_filp (&filp, dentry);
+
+ /* Make the inode acceptable to MSDOS FIXME */
+ Printk ((KERN_WARNING "umsdos_symlink_x: /mn/ Is this ok?\n"));
+ Printk ((KERN_WARNING " symname=%s ; dentry name=%.*s (ino=%lu)\n", symname, (int) dentry->d_name.len, dentry->d_name.name, dentry->d_inode->i_ino));
+ ret = umsdos_file_write_kmem_real (&filp, symname, len, &myofs);
+ /* dput(dentry); ?? where did this come from FIXME */
+
+ if (ret >= 0) {
+ if (ret != len) {
+ ret = -EIO;
+ printk ("UMSDOS: "
+ "Can't write symbolic link data\n");
+ } else {
+ ret = 0;
+ }
+ }
+ if (ret != 0) {
+ UMSDOS_unlink (dir, dentry);
+ dir = NULL;
+ }
+ }
+ /* d_instantiate(dentry,dir); //already done in umsdos_create_any. */
+ Printk (("\n"));
+ return ret;
}
/*
- Setup un Symbolic link.
- Return a negative error code or 0 if ok.
-*/
-int UMSDOS_symlink(
- struct inode * dir,
- struct dentry *dentry,
- const char * symname
- )
+ * Setup un Symbolic link.
+ * Return a negative error code or 0 if ok.
+ */
+int UMSDOS_symlink (
+ struct inode *dir,
+ struct dentry *dentry,
+ const char *symname
+)
{
- return umsdos_symlink_x (dir,dentry,symname,S_IFLNK|0777,0);
+ return umsdos_symlink_x (dir, dentry, symname, S_IFLNK | 0777, 0);
}
/*
- Add a link to an inode in a directory
-*/
+ * Add a link to an inode in a directory
+ */
int UMSDOS_link (
- struct dentry * olddentry,
- struct inode * dir,
- struct dentry *dentry)
+ struct dentry *olddentry,
+ struct inode *dir,
+ struct dentry *dentry)
{
- struct inode *oldinode = olddentry->d_inode;
- /* #Specification: hard link / strategy
- Well ... hard link are difficult to implement on top of an
- MsDOS fat file system. Unlike UNIX file systems, there are no
- inode. A directory entry hold the functionality of the inode
- and the entry.
-
- We will used the same strategy as a normal Unix file system
- (with inode) except we will do it symbolically (using paths).
-
- Because anything can happen during a DOS session (defragment,
- directory sorting, etc...), we can't rely on MsDOS pseudo
- inode number to record the link. For this reason, the link
- will be done using hidden symbolic links. The following
- scenario illustrate how it work.
-
- Given a file /foo/file
-
- #
- ln /foo/file /tmp/file2
-
- become internally
-
- mv /foo/file /foo/-LINK1
- ln -s /foo/-LINK1 /foo/file
- ln -s /foo/-LINK1 /tmp/file2
- #
-
- Using this strategy, we can operate on /foo/file or /foo/file2.
- We can remove one and keep the other, like a normal Unix hard link.
- We can rename /foo/file or /tmp/file2 independently.
-
- The entry -LINK1 will be hidden. It will hold a link count.
- When all link are erased, the hidden file is erased too.
- */
- /* #Specification: weakness / hard link
- The strategy for hard link introduces a side effect that
- may or may not be acceptable. Here is the sequence
-
- #
- mkdir subdir1
- touch subdir1/file
- mkdir subdir2
- ln subdir1/file subdir2/file
- rm subdir1/file
- rmdir subdir1
- rmdir: subdir1: Directory not empty
- #
-
- This happen because there is an invisible file (--link) in
- subdir1 which is referenced by subdir2/file.
-
- Any idea ?
- */
- /* #Specification: weakness / hard link / rename directory
- Another weakness of hard link come from the fact that
- it is based on hidden symbolic links. Here is an example.
-
- #
- mkdir /subdir1
- touch /subdir1/file
- mkdir /subdir2
- ln /subdir1/file subdir2/file
- mv /subdir1 subdir3
- ls -l /subdir2/file
- #
-
- Since /subdir2/file is a hidden symbolic link
- to /subdir1/..hlinkNNN, accessing it will fail since
- /subdir1 does not exist anymore (has been renamed).
- */
- int ret = 0;
- if (S_ISDIR(oldinode->i_mode)){
- /* #Specification: hard link / directory
- A hard link can't be made on a directory. EPERM is returned
- in this case.
- */
- ret = -EPERM;
- }else if ((ret = umsdos_nevercreat(dir,dentry,-EPERM))==0){
- struct inode *olddir;
- ret = umsdos_get_dirowner(oldinode,&olddir);
- Printk (("umsdos_link dir_owner = %lu -> %p [%d] ",
- oldinode->u.umsdos_i.i_dir_owner, olddir, olddir->i_count));
- if (ret == 0){
- struct umsdos_dirent entry;
- umsdos_lockcreate2(dir,olddir);
- ret = umsdos_inode2entry (olddir,oldinode,&entry);
- if (ret == 0){
- Printk (("umsdos_link :%.*s: ino %lu flags %d "
- ,entry.name_len, entry.name
- ,oldinode->i_ino, entry.flags));
- if (!(entry.flags & UMSDOS_HIDDEN)){
- /* #Specification: hard link / first hard link
- The first time a hard link is done on a file, this
- file must be renamed and hidden. Then an internal
- symbolic link must be done on the hidden file.
-
- The second link is done after on this hidden file.
-
- It is expected that the Linux MSDOS file system
- keeps the same pseudo inode when a rename operation
- is done on a file in the same directory.
- */
- struct umsdos_info info;
- ret = umsdos_newhidden (olddir,&info);
- if (ret == 0){
- Printk (("olddir[%d] ",olddir->i_count));
- ret = umsdos_rename_f(
- olddentry->d_inode,
- olddentry,
- dir,
- dentry,
- UMSDOS_HIDDEN);
- if (ret == 0){
- char *path = (char*)kmalloc(PATH_MAX,GFP_KERNEL);
- if (path == NULL){
- ret = -ENOMEM;
- }else{
- struct dentry *temp;
- temp = creat_dentry (entry.name, entry.name_len, NULL, NULL);
- Printk (("olddir[%d] ",olddir->i_count));
- ret = umsdos_locate_path (oldinode,path);
- Printk (("olddir[%d] ",olddir->i_count));
- if (ret == 0){
- olddir->i_count++;
- ret = umsdos_symlink_x (olddir
- ,temp
- ,path
- ,S_IFREG|0777,UMSDOS_HLINK);
- if (ret == 0){
- dir->i_count++;
- ret = umsdos_symlink_x (dir,dentry,
- path,
- S_IFREG|0777,UMSDOS_HLINK);
- }
+ struct inode *oldinode = olddentry->d_inode;
+
+ /* #Specification: hard link / strategy
+ * Well ... hard link are difficult to implement on top of an
+ * MsDOS fat file system. Unlike UNIX file systems, there are no
+ * inode. A directory entry hold the functionality of the inode
+ * and the entry.
+ *
+ * We will used the same strategy as a normal Unix file system
+ * (with inode) except we will do it symbolically (using paths).
+ *
+ * Because anything can happen during a DOS session (defragment,
+ * directory sorting, etc...), we can't rely on MsDOS pseudo
+ * inode number to record the link. For this reason, the link
+ * will be done using hidden symbolic links. The following
+ * scenario illustrate how it work.
+ *
+ * Given a file /foo/file
+ *
+ * #
+ * ln /foo/file /tmp/file2
+ *
+ * become internally
+ *
+ * mv /foo/file /foo/-LINK1
+ * ln -s /foo/-LINK1 /foo/file
+ * ln -s /foo/-LINK1 /tmp/file2
+ * #
+ *
+ * Using this strategy, we can operate on /foo/file or /foo/file2.
+ * We can remove one and keep the other, like a normal Unix hard link.
+ * We can rename /foo/file or /tmp/file2 independently.
+ *
+ * The entry -LINK1 will be hidden. It will hold a link count.
+ * When all link are erased, the hidden file is erased too.
+ */
+ /* #Specification: weakness / hard link
+ * The strategy for hard link introduces a side effect that
+ * may or may not be acceptable. Here is the sequence
+ *
+ * #
+ * mkdir subdir1
+ * touch subdir1/file
+ * mkdir subdir2
+ * ln subdir1/file subdir2/file
+ * rm subdir1/file
+ * rmdir subdir1
+ * rmdir: subdir1: Directory not empty
+ * #
+ *
+ * This happen because there is an invisible file (--link) in
+ * subdir1 which is referenced by subdir2/file.
+ *
+ * Any idea ?
+ */
+ /* #Specification: weakness / hard link / rename directory
+ * Another weakness of hard link come from the fact that
+ * it is based on hidden symbolic links. Here is an example.
+ *
+ * #
+ * mkdir /subdir1
+ * touch /subdir1/file
+ * mkdir /subdir2
+ * ln /subdir1/file subdir2/file
+ * mv /subdir1 subdir3
+ * ls -l /subdir2/file
+ * #
+ *
+ * Since /subdir2/file is a hidden symbolic link
+ * to /subdir1/..hlinkNNN, accessing it will fail since
+ * /subdir1 does not exist anymore (has been renamed).
+ */
+ int ret = 0;
+
+ if (S_ISDIR (oldinode->i_mode)) {
+ /* #Specification: hard link / directory
+ * A hard link can't be made on a directory. EPERM is returned
+ * in this case.
+ */
+ ret = -EPERM;
+ } else if ((ret = umsdos_nevercreat (dir, dentry, -EPERM)) == 0) {
+ struct inode *olddir;
+
+ ret = umsdos_get_dirowner (oldinode, &olddir);
+ Printk (("umsdos_link dir_owner = %lu -> %p [%d] ",
+ oldinode->u.umsdos_i.i_dir_owner, olddir, olddir->i_count));
+ if (ret == 0) {
+ struct umsdos_dirent entry;
+
+ umsdos_lockcreate2 (dir, olddir);
+ ret = umsdos_inode2entry (olddir, oldinode, &entry);
+ if (ret == 0) {
+ Printk (("umsdos_link :%.*s: ino %lu flags %d "
+ ,entry.name_len, entry.name
+ ,oldinode->i_ino, entry.flags));
+ if (!(entry.flags & UMSDOS_HIDDEN)) {
+ /* #Specification: hard link / first hard link
+ * The first time a hard link is done on a file, this
+ * file must be renamed and hidden. Then an internal
+ * symbolic link must be done on the hidden file.
+ *
+ * The second link is done after on this hidden file.
+ *
+ * It is expected that the Linux MSDOS file system
+ * keeps the same pseudo inode when a rename operation
+ * is done on a file in the same directory.
+ */
+ struct umsdos_info info;
+
+ ret = umsdos_newhidden (olddir, &info);
+ if (ret == 0) {
+ Printk (("olddir[%d] ", olddir->i_count));
+ ret = umsdos_rename_f (olddentry->d_inode, olddentry, dir, dentry, UMSDOS_HIDDEN);
+ if (ret == 0) {
+ char *path = (char *) kmalloc (PATH_MAX, GFP_KERNEL);
+
+ if (path == NULL) {
+ ret = -ENOMEM;
+ } else {
+ struct dentry *temp;
+
+ temp = creat_dentry (entry.name, entry.name_len, NULL, NULL);
+ Printk (("olddir[%d] ", olddir->i_count));
+ ret = umsdos_locate_path (oldinode, path);
+ Printk (("olddir[%d] ", olddir->i_count));
+ if (ret == 0) {
+ inc_count (olddir);
+ ret = umsdos_symlink_x (olddir, temp, path, S_IFREG | 0777, UMSDOS_HLINK);
+ if (ret == 0) {
+ inc_count (dir);
+ ret = umsdos_symlink_x (dir, dentry, path, S_IFREG | 0777, UMSDOS_HLINK);
+ }
+ }
+ kfree (path);
+ }
+ }
+ }
+ } else {
+ char *path = (char *) kmalloc (PATH_MAX, GFP_KERNEL);
+
+ if (path == NULL) {
+ ret = -ENOMEM;
+ } else {
+ ret = umsdos_locate_path (oldinode, path);
+ if (ret == 0) {
+ inc_count (dir);
+ ret = umsdos_symlink_x (dir, dentry, path, S_IFREG | 0777, UMSDOS_HLINK);
+ }
+ kfree (path);
+ }
+ }
+ }
+ umsdos_unlockcreate (olddir);
+ umsdos_unlockcreate (dir);
}
- kfree (path);
- }
- }
- }
- }else{
- char *path = (char*)kmalloc(PATH_MAX,GFP_KERNEL);
- if (path == NULL){
- ret = -ENOMEM;
- }else{
- ret = umsdos_locate_path (oldinode,path);
- if (ret == 0){
- dir->i_count++;
- ret = umsdos_symlink_x (dir,dentry,path
- ,S_IFREG|0777,UMSDOS_HLINK);
- }
- kfree (path);
- }
+ /* iput (olddir); FIXME */
}
- }
- umsdos_unlockcreate(olddir);
- umsdos_unlockcreate(dir);
- }
- /* iput (olddir); FIXME */
- }
- if (ret == 0){
- struct iattr newattrs;
- oldinode->i_nlink++;
- newattrs.ia_valid = 0;
- ret = UMSDOS_notify_change(olddentry, &newattrs);
- }
+ if (ret == 0) {
+ struct iattr newattrs;
+ oldinode->i_nlink++;
+ newattrs.ia_valid = 0;
+ ret = UMSDOS_notify_change (olddentry, &newattrs);
+ }
/* dput (olddentry);
- dput (dentry); FIXME.... */
-
- Printk (("umsdos_link %d\n",ret));
- return ret;
+ * dput (dentry); FIXME.... */
+
+ Printk (("umsdos_link %d\n", ret));
+ return ret;
}
/*
- Add a new file into the alternate directory.
- The file is added to the real MSDOS directory. If successful, it
- is then added to the EDM file.
-
- Return the status of the operation. 0 mean success.
-*/
+ * Add a new file into the alternate directory.
+ * The file is added to the real MSDOS directory. If successful, it
+ * is then added to the EDM file.
+ *
+ * Return the status of the operation. 0 mean success.
+ */
int UMSDOS_create (
- struct inode *dir,
- struct dentry *dentry,
- int mode /* Permission bit + file type ??? */
- ) /* Will hold the inode of the newly created */
- /* file */
-{
- return umsdos_create_any (dir,dentry,mode,0,0);
+ struct inode *dir,
+ struct dentry *dentry,
+ int mode /* Permission bit + file type ??? */
+)
+{ /* Will hold the inode of the newly created file */
+ Printk ((KERN_ERR "UMSDOS_create: entering\n"));
+ check_dentry (dentry);
+ return umsdos_create_any (dir, dentry, mode, 0, 0);
}
/*
- Add a sub-directory in a directory
-*/
-int UMSDOS_mkdir(
- struct inode * dir,
- struct dentry *dentry,
- int mode)
+ * Add a sub-directory in a directory
+ */
+int UMSDOS_mkdir (
+ struct inode *dir,
+ struct dentry *dentry,
+ int mode)
{
- int ret = umsdos_nevercreat(dir,dentry,-EEXIST);
- if (ret == 0){
- struct umsdos_info info;
- ret = umsdos_parse (dentry->d_name.name,dentry->d_name.len,&info);
- Printk (("umsdos_mkdir %d\n",ret));
- if (ret == 0){
- info.entry.mode = mode | S_IFDIR;
- info.entry.rdev = 0;
- info.entry.uid = current->fsuid;
- info.entry.gid = (dir->i_mode & S_ISGID)
- ? dir->i_gid : current->fsgid;
- info.entry.ctime = info.entry.atime = info.entry.mtime
- = CURRENT_TIME;
- info.entry.flags = 0;
- umsdos_lockcreate(dir);
- info.entry.nlink = 1;
- ret = umsdos_newentry (dir,&info);
- Printk (("newentry %d ",ret));
- if (ret == 0){
- struct dentry *temp, *tdir;
- tdir = creat_dentry ("mkd-dir", 7, dir, NULL);
- temp = creat_dentry (info.fake.fname, info.fake.len, NULL, tdir);
- dir->i_count++;
- ret = msdos_mkdir (dir, temp, mode);
-
- if (ret != 0){
- umsdos_delentry (dir,&info,1);
- /* #Specification: mkdir / Directory already exist in DOS
- We do the same thing as for file creation.
- For all user it is an error.
- */
- }else{
- /* #Specification: mkdir / umsdos directory / create EMD
- When we created a new sub-directory in a UMSDOS
- directory (one with full UMSDOS semantic), we
- create immediately an EMD file in the new
- sub-directory so it inherit UMSDOS semantic.
- */
- struct inode *subdir;
- ret = compat_umsdos_real_lookup (dir,info.fake.fname,
- info.fake.len,&subdir);
- if (ret == 0){
- struct dentry *tdentry, *tdsub;
- tdsub = creat_dentry ("mkd-emd", 7, subdir, NULL);
- tdentry = creat_dentry (UMSDOS_EMD_FILE, UMSDOS_EMD_NAMELEN, NULL, tdsub);
- ret = msdos_create (subdir, tdentry, S_IFREG|0777);
- kill_dentry (tdentry); /* we don't want empty EMD file to be visible ! too bad kill_dentry does nothing at the moment :-) FIXME */
- kill_dentry (tdsub);
- umsdos_setup_dir_inode (subdir); /* this should setup dir so it is promoted to EMD, and EMD file is not visible inside it */
- subdir = NULL;
- d_instantiate(dentry, temp->d_inode);
- /* iput (result); FIXME */
- }
- if (ret < 0){
- printk ("UMSDOS: Can't create empty --linux-.---\n");
- }
-
-
- /* iput (subdir); FIXME */
+ int ret = umsdos_nevercreat (dir, dentry, -EEXIST);
+
+ if (ret == 0) {
+ struct umsdos_info info;
+
+ ret = umsdos_parse (dentry->d_name.name, dentry->d_name.len, &info);
+ Printk (("umsdos_mkdir %d\n", ret));
+ if (ret == 0) {
+ info.entry.mode = mode | S_IFDIR;
+ info.entry.rdev = 0;
+ info.entry.uid = current->fsuid;
+ info.entry.gid = (dir->i_mode & S_ISGID)
+ ? dir->i_gid : current->fsgid;
+ info.entry.ctime = info.entry.atime = info.entry.mtime
+ = CURRENT_TIME;
+ info.entry.flags = 0;
+ umsdos_lockcreate (dir);
+ info.entry.nlink = 1;
+ ret = umsdos_newentry (dir, &info);
+ Printk (("newentry %d ", ret));
+ if (ret == 0) {
+ struct dentry *temp, *tdir;
+
+ tdir = creat_dentry ("mkd-dir", 7, dir, NULL);
+ temp = creat_dentry (info.fake.fname, info.fake.len, NULL, tdir);
+ inc_count (dir);
+ ret = msdos_mkdir (dir, temp, mode);
+
+ if (ret != 0) {
+ umsdos_delentry (dir, &info, 1);
+ /* #Specification: mkdir / Directory already exist in DOS
+ * We do the same thing as for file creation.
+ * For all user it is an error.
+ */
+ } else {
+ /* #Specification: mkdir / umsdos directory / create EMD
+ * When we created a new sub-directory in a UMSDOS
+ * directory (one with full UMSDOS semantic), we
+ * create immediately an EMD file in the new
+ * sub-directory so it inherit UMSDOS semantic.
+ */
+ struct inode *subdir;
+
+ ret = compat_umsdos_real_lookup (dir, info.fake.fname,
+ info.fake.len, &subdir);
+ if (ret == 0) {
+ struct dentry *tdentry,
+ *tdsub;
+
+ tdsub = creat_dentry ("mkd-emd", 7, subdir, NULL);
+ tdentry = creat_dentry (UMSDOS_EMD_FILE, UMSDOS_EMD_NAMELEN, NULL, tdsub);
+ ret = msdos_create (subdir, tdentry, S_IFREG | 0777);
+ kill_dentry (tdentry); /* we don't want empty EMD file to be visible ! too bad kill_dentry does nothing at the moment :-) FIXME */
+ kill_dentry (tdsub);
+ umsdos_setup_dir_inode (subdir); /* this should setup dir so it is promoted to EMD, and EMD file is not visible inside it */
+ subdir = NULL;
+ d_instantiate (dentry, temp->d_inode);
+ /* iput (result); FIXME */
+ }
+ if (ret < 0) {
+ printk ("UMSDOS: Can't create empty --linux-.---\n");
+ }
+ /* iput (subdir); FIXME */
+ }
+ }
+ umsdos_unlockcreate (dir);
+ }
}
- }
- umsdos_unlockcreate(dir);
- }
- }
- Printk (("umsdos_mkdir %d\n",ret));
- /* dput (dentry); / * FIXME /mn/ */
- return ret;
+ Printk (("umsdos_mkdir %d\n", ret));
+ /* dput (dentry); / * FIXME /mn/ */
+ return ret;
}
/*
- Add a new device special file into a directory.
-*/
-int UMSDOS_mknod(
- struct inode * dir,
- struct dentry *dentry,
- int mode,
- int rdev)
+ * Add a new device special file into a directory.
+ */
+int UMSDOS_mknod (
+ struct inode *dir,
+ struct dentry *dentry,
+ int mode,
+ int rdev)
{
- /* #Specification: Special files / strategy
- Device special file, pipes, etc ... are created like normal
- file in the msdos file system. Of course they remain empty.
-
- One strategy was to create those files only in the EMD file
- since they were not important for MSDOS. The problem with
- that, is that there were not getting inode number allocated.
- The MSDOS filesystems is playing a nice game to fake inode
- number, so why not use it.
-
- The absence of inode number compatible with those allocated
- for ordinary files was causing major trouble with hard link
- in particular and other parts of the kernel I guess.
- */
-
- int ret = umsdos_create_any (dir,dentry,mode,rdev,0);
- /* dput(dentry); / * /mn/ FIXME! */
- return ret;
+ /* #Specification: Special files / strategy
+ * Device special file, pipes, etc ... are created like normal
+ * file in the msdos file system. Of course they remain empty.
+ *
+ * One strategy was to create those files only in the EMD file
+ * since they were not important for MSDOS. The problem with
+ * that, is that there were not getting inode number allocated.
+ * The MSDOS filesystems is playing a nice game to fake inode
+ * number, so why not use it.
+ *
+ * The absence of inode number compatible with those allocated
+ * for ordinary files was causing major trouble with hard link
+ * in particular and other parts of the kernel I guess.
+ */
+
+ int ret;
+
+ check_dentry (dentry);
+ ret = umsdos_create_any (dir, dentry, mode, rdev, 0);
+ check_dentry (dentry);
+
+ /* dput(dentry); / * /mn/ FIXME! */
+ return ret;
}
/*
- Remove a sub-directory.
-*/
-int UMSDOS_rmdir(
- struct inode * dir,
- struct dentry *dentry)
+ * Remove a sub-directory.
+ */
+int UMSDOS_rmdir (
+ struct inode *dir,
+ struct dentry *dentry)
{
- /* #Specification: style / iput strategy
- In the UMSDOS project, I am trying to apply a single
- programming style regarding inode management. Many
- entry point are receiving an inode to act on, and must
- do an iput() as soon as they are finished with
- the inode.
-
- For simple case, there is no problem. When you introduce
- error checking, you end up with many iput placed around the
- code.
-
- The coding style I use all around is one where I am trying
- to provide independent flow logic (I don't know how to
- name this). With this style, code is easier to understand
- but you rapidly get iput() all around. Here is an exemple
- of what I am trying to avoid.
-
- #
- if (a){
- ...
- if(b){
- ...
- }
- ...
- if (c){
- // Complex state. Was b true ?
- ...
- }
- ...
- }
- // Weird state
- if (d){
- // ...
- }
- // Was iput finally done ?
- return status;
- #
-
- Here is the style I am using. Still sometime I do the
- first when things are very simple (or very complicated :-( )
-
- #
- if (a){
- if (b){
- ...
- }else if (c){
- // A single state gets here
- }
- }else if (d){
- ...
- }
- return status;
- #
-
- Again, while this help clarifying the code, I often get a lot
- of iput(), unlike the first style, where I can place few
- "strategic" iput(). "strategic" also mean, more difficult
- to place.
-
- So here is the style I will be using from now on in this project.
- There is always an iput() at the end of a function (which has
- to do an iput()). One iput by inode. There is also one iput()
- at the places where a successful operation is achieved. This
- iput() is often done by a sub-function (often from the msdos
- file system). So I get one too many iput() ? At the place
- where an iput() is done, the inode is simply nulled, disabling
- the last one.
-
- #
- if (a){
- if (b){
- ...
- }else if (c){
- msdos_rmdir(dir,...);
- dir = NULL;
- }
- }else if (d){
- ...
- }
- iput (dir);
- return status;
- #
-
- Note that the umsdos_lockcreate() and umsdos_unlockcreate() function
- pair goes against this practice of "forgetting" the inode as soon
- as possible.
- */
-
- int ret;
-
- ret = umsdos_nevercreat(dir,dentry,-EPERM);
- if (ret == 0){
- volatile struct inode *sdir;
- dir->i_count++;
- ret = umsdos_lookup_x (dir, dentry, 0);
- sdir = dentry->d_inode;
- Printk (("rmdir lookup %d ",ret));
- if (ret == 0){
- int empty;
- umsdos_lockcreate(dir);
- if (sdir->i_count > 1){
- Printk ((" /mn/ rmdir: FIXME EBUSY: hmmm, i_count is %d > 1\n", sdir->i_count));
- ret = -EBUSY;
- }else if ((empty = umsdos_isempty (sdir)) != 0){
- struct dentry *tdentry, *tedir;
- tedir = creat_dentry ("emd-rmd", 7, dir, NULL);
- tdentry = creat_dentry (UMSDOS_EMD_FILE, UMSDOS_EMD_NAMELEN, NULL, tedir);
- umsdos_real_lookup (dir, tdentry); /* fill inode part */
- Printk (("isempty %d i_count %d ",empty,sdir->i_count));
+ /* #Specification: style / iput strategy
+ * In the UMSDOS project, I am trying to apply a single
+ * programming style regarding inode management. Many
+ * entry point are receiving an inode to act on, and must
+ * do an iput() as soon as they are finished with
+ * the inode.
+ *
+ * For simple case, there is no problem. When you introduce
+ * error checking, you end up with many iput placed around the
+ * code.
+ *
+ * The coding style I use all around is one where I am trying
+ * to provide independent flow logic (I don't know how to
+ * name this). With this style, code is easier to understand
+ * but you rapidly get iput() all around. Here is an exemple
+ * of what I am trying to avoid.
+ *
+ * #
+ * if (a){
+ * ...
+ * if(b){
+ * ...
+ * }
+ * ...
+ * if (c){
+ * // Complex state. Was b true ?
+ * ...
+ * }
+ * ...
+ * }
+ * // Weird state
+ * if (d){
+ * // ...
+ * }
+ * // Was iput finally done ?
+ * return status;
+ * #
+ *
+ * Here is the style I am using. Still sometime I do the
+ * first when things are very simple (or very complicated :-( )
+ *
+ * #
+ * if (a){
+ * if (b){
+ * ...
+ * }else if (c){
+ * // A single state gets here
+ * }
+ * }else if (d){
+ * ...
+ * }
+ * return status;
+ * #
+ *
+ * Again, while this help clarifying the code, I often get a lot
+ * of iput(), unlike the first style, where I can place few
+ * "strategic" iput(). "strategic" also mean, more difficult
+ * to place.
+ *
+ * So here is the style I will be using from now on in this project.
+ * There is always an iput() at the end of a function (which has
+ * to do an iput()). One iput by inode. There is also one iput()
+ * at the places where a successful operation is achieved. This
+ * iput() is often done by a sub-function (often from the msdos
+ * file system). So I get one too many iput() ? At the place
+ * where an iput() is done, the inode is simply nulled, disabling
+ * the last one.
+ *
+ * #
+ * if (a){
+ * if (b){
+ * ...
+ * }else if (c){
+ * msdos_rmdir(dir,...);
+ * dir = NULL;
+ * }
+ * }else if (d){
+ * ...
+ * }
+ * iput (dir);
+ * return status;
+ * #
+ *
+ * Note that the umsdos_lockcreate() and umsdos_unlockcreate() function
+ * pair goes against this practice of "forgetting" the inode as soon
+ * as possible.
+ */
+
+ int ret;
+
+ ret = umsdos_nevercreat (dir, dentry, -EPERM);
+ if (ret == 0) {
+ volatile struct inode *sdir;
+
+ inc_count (dir);
+ ret = umsdos_lookup_x (dir, dentry, 0);
+ sdir = dentry->d_inode;
+ Printk (("rmdir lookup %d ", ret));
+ if (ret == 0) {
+ int empty;
+
+ umsdos_lockcreate (dir);
+
+ Printk ((" /mn/ rmdir: FIXME EBUSY TEST: hmmm, i_count is %d > 1 -- FAKING!\n", sdir->i_count));
+ sdir->i_count = 1; /* /mn/ FIXME! DELME! FOR TEST ONLY ! */
+
+ if (sdir->i_count > 1) {
+ Printk ((" /mn/ rmdir: FIXME EBUSY: hmmm, i_count is %d > 1 -- FAKING!\n", sdir->i_count));
+ ret = -EBUSY;
+ } else if ((empty = umsdos_isempty (sdir)) != 0) {
+ struct dentry *tdentry, *tedir;
+
+ tedir = creat_dentry ("emd-rmd", 7, dir, NULL);
+ tdentry = creat_dentry (UMSDOS_EMD_FILE, UMSDOS_EMD_NAMELEN, NULL, tedir);
+ umsdos_real_lookup (dir, tdentry); /* fill inode part */
+ Printk (("isempty %d i_count %d ", empty, sdir->i_count));
/* check sticky bit */
- if ( !(dir->i_mode & S_ISVTX) || capable(CAP_FOWNER) ||
- current->fsuid == sdir->i_uid ||
- current->fsuid == dir->i_uid ) {
- if (empty == 1){
- /* We have to remove the EMD file */
- ret = msdos_unlink (sdir, tdentry);
- Printk (("UMSDOS_rmdir: unlinking empty EMD ret=%d", ret));
- sdir = NULL;
- }
- /* sdir must be free before msdos_rmdir() */
- /* iput (sdir); FIXME */
- sdir = NULL;
- Printk (("isempty ret %d nlink %d ",ret,dir->i_nlink));
- if (ret == 0){
- struct umsdos_info info;
- struct dentry *temp, *tdir;
- dir->i_count++;
- umsdos_parse (dentry->d_name.name,dentry->d_name.len,&info);
- /* The findentry is there only to complete */
- /* the mangling */
- umsdos_findentry (dir,&info,2);
-
- tdir = creat_dentry ("dir-rmd", 7, dir, NULL);
- temp = creat_dentry (info.fake.fname, info.fake.len, NULL, tdir);
- umsdos_real_lookup (dir, temp); /* fill inode part */
-
- Printk ((KERN_ERR " rmdir start dir=%lu, dir->sb=%p\n", dir->i_ino, dir->i_sb)); /* FIXME: /mn/ debug only */
- Printk ((KERN_ERR " dentry=%.*s d_count=%d ino=%lu\n", (int) temp->d_name.len, temp->d_name.name, temp->d_count, temp->d_inode->i_ino));
- Printk ((KERN_ERR " d_parent=%.*s d_count=%d ino=%lu\n", (int) temp->d_parent->d_name.len, temp->d_parent->d_name.name, temp->d_parent->d_count, temp->d_parent->d_inode->i_ino));
-
- ret = msdos_rmdir (dir, temp);
-
- Printk ((KERN_ERR " rmdir passed %d\n", ret)); /* FIXME: /mn/ debug only */
- Printk ((KERN_ERR " rmdir end dir=%lu, dir->sb=%p\n", dir->i_ino, dir->i_sb));
- Printk ((KERN_ERR " dentry=%.*s d_count=%d ino=%p\n", (int) temp->d_name.len, temp->d_name.name, temp->d_count, temp->d_inode));
- Printk ((KERN_ERR " d_parent=%.*s d_count=%d ino=%lu\n", (int) temp->d_parent->d_name.len, temp->d_parent->d_name.name, temp->d_parent->d_count, temp->d_parent->d_inode->i_ino));
-
- kill_dentry (tdir);
- kill_dentry (temp);
-
- if (ret == 0){
- ret = umsdos_delentry (dir,&info,1);
- d_delete (dentry);
- }
- }
- }else{
- /* sticky bit set and we don't have permission */
- Printk(("sticky set "));
- ret = -EPERM;
+ if (!(dir->i_mode & S_ISVTX) || capable (CAP_FOWNER) ||
+ current->fsuid == sdir->i_uid ||
+ current->fsuid == dir->i_uid) {
+ if (empty == 1) {
+ /* We have to remove the EMD file */
+ ret = msdos_unlink (sdir, tdentry);
+ Printk (("UMSDOS_rmdir: unlinking empty EMD ret=%d", ret));
+ sdir = NULL;
+ }
+ /* sdir must be free before msdos_rmdir() */
+ /* iput (sdir); FIXME */
+ sdir = NULL;
+ Printk (("isempty ret %d nlink %d ", ret, dir->i_nlink));
+ if (ret == 0) {
+ struct umsdos_info info;
+ struct dentry *temp, *tdir;
+
+ inc_count (dir);
+ umsdos_parse (dentry->d_name.name, dentry->d_name.len, &info);
+ /* The findentry is there only to complete */
+ /* the mangling */
+ umsdos_findentry (dir, &info, 2);
+
+ tdir = creat_dentry ("dir-rmd", 7, dir, NULL);
+ temp = creat_dentry (info.fake.fname, info.fake.len, NULL, tdir);
+ umsdos_real_lookup (dir, temp); /* fill inode part */
+
+ Printk ((KERN_ERR " rmdir start dir=%lu, dir->sb=%p\n", dir->i_ino, dir->i_sb)); /* FIXME: /mn/ debug only */
+ Printk ((KERN_ERR " dentry=%.*s d_count=%d ino=%lu\n", (int) temp->d_name.len, temp->d_name.name, temp->d_count, temp->d_inode->i_ino));
+ Printk ((KERN_ERR " d_parent=%.*s d_count=%d ino=%lu\n", (int) temp->d_parent->d_name.len, temp->d_parent->d_name.name, temp->d_parent->d_count, temp->d_parent->d_inode->i_ino));
+
+ ret = msdos_rmdir (dir, temp);
+
+ Printk ((KERN_ERR " rmdir passed %d\n", ret)); /* FIXME: /mn/ debug only */
+ Printk ((KERN_ERR " rmdir end dir=%lu, dir->sb=%p\n", dir->i_ino, dir->i_sb));
+ Printk ((KERN_ERR " dentry=%.*s d_count=%d ino=%p\n", (int) temp->d_name.len, temp->d_name.name, temp->d_count, temp->d_inode));
+ Printk ((KERN_ERR " d_parent=%.*s d_count=%d ino=%lu\n", (int) temp->d_parent->d_name.len, temp->d_parent->d_name.name, temp->d_parent->d_count, temp->d_parent->d_inode->i_ino));
+
+ kill_dentry (tdir);
+ kill_dentry (temp);
+
+ if (ret == 0) {
+ ret = umsdos_delentry (dir, &info, 1);
+ d_delete (dentry);
+ }
+ }
+ } else {
+ /* sticky bit set and we don't have permission */
+ Printk (("sticky set "));
+ ret = -EPERM;
+ }
+ } else {
+ /*
+ * The subdirectory is not empty, so leave it there
+ */
+ ret = -ENOTEMPTY;
+ }
+ /* iput(sdir); FIXME */
+ umsdos_unlockcreate (dir);
+ }
}
- }else{
- /*
- The subdirectory is not empty, so leave it there
- */
- ret = -ENOTEMPTY;
- }
- /* iput(sdir); FIXME */
- umsdos_unlockcreate(dir);
- }
- }
- /* dput(dentry); FIXME /mn/ */
- Printk (("umsdos_rmdir %d\n",ret));
- return ret;
+ /* dput(dentry); FIXME /mn/ */
+ Printk (("umsdos_rmdir %d\n", ret));
+ return ret;
}
/*
- Remove a file from the directory.
-*/
+ * Remove a file from the directory.
+ */
int UMSDOS_unlink (
- struct inode * dir,
- struct dentry *dentry)
+ struct inode *dir,
+ struct dentry *dentry)
{
- int ret;
- Printk ((" *** UMSDOS_unlink entering /mn/ *** \n"));
-
- ret = umsdos_nevercreat(dir,dentry,-EPERM);
-
- Printk (("UMSDOS_unlink /mn/: nevercreat=%d\n", ret));
-
- if (ret == 0){
- struct umsdos_info info;
- ret = umsdos_parse (dentry->d_name.name,dentry->d_name.len,&info);
- if (ret == 0){
- umsdos_lockcreate(dir);
- ret = umsdos_findentry(dir,&info,1);
- Printk (("UMSDOS_unlink: findentry returned %d\n", ret));
- if (ret == 0){
- Printk (("UMSDOS_unlink %.*s ",info.fake.len,info.fake.fname));
+ int ret;
+
+ Printk ((" *** UMSDOS_unlink entering /mn/ *** \n"));
+
+ ret = umsdos_nevercreat (dir, dentry, -EPERM);
+
+ Printk (("UMSDOS_unlink /mn/: nevercreat=%d\n", ret));
+
+ if (ret == 0) {
+ struct umsdos_info info;
+
+ ret = umsdos_parse (dentry->d_name.name, dentry->d_name.len, &info);
+ if (ret == 0) {
+ umsdos_lockcreate (dir);
+ ret = umsdos_findentry (dir, &info, 1);
+ Printk (("UMSDOS_unlink: findentry returned %d\n", ret));
+ if (ret == 0) {
+ Printk (("UMSDOS_unlink %.*s ", info.fake.len, info.fake.fname));
/* check sticky bit */
- if ( !(dir->i_mode & S_ISVTX) || capable(CAP_FOWNER) ||
- current->fsuid == info.entry.uid ||
- current->fsuid == dir->i_uid ) {
- if (info.entry.flags & UMSDOS_HLINK){
- /* #Specification: hard link / deleting a link
- When we deletes a file, and this file is a link
- we must subtract 1 to the nlink field of the
- hidden link.
-
- If the count goes to 0, we delete this hidden
- link too.
- */
- /*
- First, get the inode of the hidden link
- using the standard lookup function.
- */
- struct inode *inode;
- dir->i_count++;
- ret = umsdos_lookup_x (dir, dentry, 0);
- inode = dentry->d_inode;
- if (ret == 0){
- Printk (("unlink nlink = %d ",inode->i_nlink));
- inode->i_nlink--;
- if (inode->i_nlink == 0){
- struct inode *hdir = iget(inode->i_sb
- ,inode->u.umsdos_i.i_dir_owner);
- struct umsdos_dirent entry;
- ret = umsdos_inode2entry (hdir,inode,&entry);
- if (ret == 0){
- ret = UMSDOS_unlink (hdir,dentry);
- }else{
- /* iput (hdir); FIXME */
+ if (!(dir->i_mode & S_ISVTX) || capable (CAP_FOWNER) ||
+ current->fsuid == info.entry.uid ||
+ current->fsuid == dir->i_uid) {
+ if (info.entry.flags & UMSDOS_HLINK) {
+ /* #Specification: hard link / deleting a link
+ * When we deletes a file, and this file is a link
+ * we must subtract 1 to the nlink field of the
+ * hidden link.
+ *
+ * If the count goes to 0, we delete this hidden
+ * link too.
+ */
+ /*
+ * First, get the inode of the hidden link
+ * using the standard lookup function.
+ */
+ struct inode *inode;
+
+ inc_count (dir);
+ ret = umsdos_lookup_x (dir, dentry, 0);
+ inode = dentry->d_inode;
+ if (ret == 0) {
+ Printk (("unlink nlink = %d ", inode->i_nlink));
+ inode->i_nlink--;
+ if (inode->i_nlink == 0) {
+ struct inode *hdir = iget (inode->i_sb
+ ,inode->u.umsdos_i.i_dir_owner);
+ struct umsdos_dirent entry;
+
+ ret = umsdos_inode2entry (hdir, inode, &entry);
+ if (ret == 0) {
+ ret = UMSDOS_unlink (hdir, dentry);
+ } else {
+ /* iput (hdir); FIXME */
+ }
+ } else {
+ struct iattr newattrs;
+
+ newattrs.ia_valid = 0;
+ ret = UMSDOS_notify_change (dentry, &newattrs);
+ }
+ /* iput (inode); FIXME */
+ }
+ }
+ if (ret == 0) {
+ ret = umsdos_delentry (dir, &info, 0);
+ if (ret == 0) {
+ struct dentry *temp,
+ *tdir;
+
+ Printk (("Avant msdos_unlink %.*s ", info.fake.len, info.fake.fname));
+ inc_count (dir); /* FIXME /mn/ is this needed anymore now that msdos_unlink locks dir using d_parent ? */
+ tdir = creat_dentry ("dir-del", 7, dir, NULL); /* FIXME /mn/: do we need iget(dir->i_ino) or would dir itself suffice ? */
+ temp = creat_dentry (info.fake.fname, info.fake.len, NULL, tdir);
+ umsdos_real_lookup (dir, temp); /* fill inode part */
+
+ ret = msdos_unlink_umsdos (dir, temp);
+ Printk (("msdos_unlink %.*s %o ret %d ", info.fake.len, info.fake.fname
+ ,info.entry.mode, ret));
+
+ d_delete (dentry);
+
+ kill_dentry (tdir);
+ kill_dentry (temp);
+ }
+ }
+ } else {
+ /* sticky bit set and we've not got permission */
+ Printk (("sticky set "));
+ ret = -EPERM;
+ }
+ }
+ umsdos_unlockcreate (dir);
}
- }else{
- struct iattr newattrs;
- newattrs.ia_valid = 0;
- ret = UMSDOS_notify_change (dentry, &newattrs);
- }
- /* iput (inode); FIXME */
- }
- }
- if (ret == 0){
- ret = umsdos_delentry (dir,&info,0);
- if (ret == 0){
- struct dentry *temp, *tdir;
- Printk (("Avant msdos_unlink %.*s ",info.fake.len,info.fake.fname));
- dir->i_count++; /* FIXME /mn/ is this needed anymore now that msdos_unlink locks dir using d_parent ? */
- tdir = creat_dentry ("dir-del", 7, dir, NULL); /* FIXME /mn/: do we need iget(dir->i_ino) or would dir itself suffice ? */
- temp = creat_dentry (info.fake.fname, info.fake.len, NULL, tdir);
- umsdos_real_lookup (dir, temp); /* fill inode part */
-
- ret = msdos_unlink_umsdos (dir, temp);
- Printk (("msdos_unlink %.*s %o ret %d ",info.fake.len,info.fake.fname
- ,info.entry.mode,ret));
-
- d_delete (dentry);
-
- kill_dentry (tdir);
- kill_dentry (temp);
- }
- }
- }else{
- /* sticky bit set and we've not got permission */
- Printk(("sticky set "));
- ret = -EPERM;
}
- }
- umsdos_unlockcreate(dir);
- }
- }
- /* dput(dentry); FIXME: shouldn't this be done in msdos_unlink ? */
- Printk (("umsdos_unlink %d\n",ret));
- return ret;
+ /* dput(dentry); FIXME: shouldn't this be done in msdos_unlink ? */
+ Printk (("umsdos_unlink %d\n", ret));
+ return ret;
}
/*
- Rename a file (move) in the file system.
-*/
-int UMSDOS_rename(
- struct inode * old_dir,
- struct dentry * old_dentry,
- struct inode * new_dir,
- struct dentry * new_dentry)
+ * Rename a file (move) in the file system.
+ */
+int UMSDOS_rename (
+ struct inode *old_dir,
+ struct dentry *old_dentry,
+ struct inode *new_dir,
+ struct dentry *new_dentry)
{
- /* #Specification: weakness / rename
- There is a case where UMSDOS rename has a different behavior
- than normal UNIX file system. Renaming an open file across
- directory boundary does not work. Renaming an open file within
- a directory does work however.
-
- The problem (not sure) is in the linux VFS msdos driver.
- I believe this is not a bug but a design feature, because
- an inode number represent some sort of directory address
- in the MSDOS directory structure. So moving the file into
- another directory does not preserve the inode number.
- */
- int ret = umsdos_nevercreat(new_dir,new_dentry,-EEXIST);
- if (ret == 0){
- /* umsdos_rename_f eat the inode and we may need those later */
- old_dir->i_count++;
- new_dir->i_count++;
- ret = umsdos_rename_f (old_dir,old_dentry,new_dir,new_dentry,0);
- if (ret == -EEXIST){
- /* #Specification: rename / new name exist
- If the destination name already exist, it will
- silently be removed. EXT2 does it this way
- and this is the spec of SUNOS. So does UMSDOS.
-
- If the destination is an empty directory it will
- also be removed.
- */
- /* #Specification: rename / new name exist / possible flaw
- The code to handle the deletion of the target (file
- and directory) use to be in umsdos_rename_f, surrounded
- by proper directory locking. This was insuring that only
- one process could achieve a rename (modification) operation
- in the source and destination directory. This was also
- insuring the operation was "atomic".
-
- This has been changed because this was creating a kernel
- stack overflow (stack is only 4k in the kernel). To avoid
- the code doing the deletion of the target (if exist) has
- been moved to a upper layer. umsdos_rename_f is tried
- once and if it fails with EEXIST, the target is removed
- and umsdos_rename_f is done again.
-
- This makes the code cleaner and (not sure) solve a
- deadlock problem one tester was experiencing.
-
- The point is to mention that possibly, the semantic of
- "rename" may be wrong. Anyone dare to check that :-)
- Be aware that IF it is wrong, to produce the problem you
- will need two process trying to rename a file to the
- same target at the same time. Again, I am not sure it
- is a problem at all.
- */
- /* This is not super efficient but should work */
- new_dir->i_count++;
- ret = UMSDOS_unlink (new_dir,new_dentry);
- chkstk();
- Printk (("rename unlink ret %d -- ",ret));
- if (ret == -EISDIR){
- new_dir->i_count++;
- ret = UMSDOS_rmdir (new_dir,new_dentry);
- chkstk();
- Printk (("rename rmdir ret %d -- ",ret));
- }
- if (ret == 0){
- ret = umsdos_rename_f(old_dir,old_dentry,
- new_dir,new_dentry,0);
- new_dir = old_dir = NULL;
- }
- }
- }
- /*
- dput (new_dentry);
- dput (old_dentry); FIXME /mn/ */
- return ret;
-}
+ /* #Specification: weakness / rename
+ * There is a case where UMSDOS rename has a different behavior
+ * than normal UNIX file system. Renaming an open file across
+ * directory boundary does not work. Renaming an open file within
+ * a directory does work however.
+ *
+ * The problem (not sure) is in the linux VFS msdos driver.
+ * I believe this is not a bug but a design feature, because
+ * an inode number represent some sort of directory address
+ * in the MSDOS directory structure. So moving the file into
+ * another directory does not preserve the inode number.
+ */
+ int ret = umsdos_nevercreat (new_dir, new_dentry, -EEXIST);
+ if (ret == 0) {
+ /* umsdos_rename_f eat the inode and we may need those later */
+ inc_count (old_dir);
+ inc_count (new_dir);
+ ret = umsdos_rename_f (old_dir, old_dentry, new_dir, new_dentry, 0);
+ if (ret == -EEXIST) {
+ /* #Specification: rename / new name exist
+ * If the destination name already exist, it will
+ * silently be removed. EXT2 does it this way
+ * and this is the spec of SUNOS. So does UMSDOS.
+ *
+ * If the destination is an empty directory it will
+ * also be removed.
+ */
+ /* #Specification: rename / new name exist / possible flaw
+ * The code to handle the deletion of the target (file
+ * and directory) use to be in umsdos_rename_f, surrounded
+ * by proper directory locking. This was insuring that only
+ * one process could achieve a rename (modification) operation
+ * in the source and destination directory. This was also
+ * insuring the operation was "atomic".
+ *
+ * This has been changed because this was creating a kernel
+ * stack overflow (stack is only 4k in the kernel). To avoid
+ * the code doing the deletion of the target (if exist) has
+ * been moved to a upper layer. umsdos_rename_f is tried
+ * once and if it fails with EEXIST, the target is removed
+ * and umsdos_rename_f is done again.
+ *
+ * This makes the code cleaner and (not sure) solve a
+ * deadlock problem one tester was experiencing.
+ *
+ * The point is to mention that possibly, the semantic of
+ * "rename" may be wrong. Anyone dare to check that :-)
+ * Be aware that IF it is wrong, to produce the problem you
+ * will need two process trying to rename a file to the
+ * same target at the same time. Again, I am not sure it
+ * is a problem at all.
+ */
+ /* This is not super efficient but should work */
+ inc_count (new_dir);
+ ret = UMSDOS_unlink (new_dir, new_dentry);
+ chkstk ();
+ Printk (("rename unlink ret %d -- ", ret));
+ if (ret == -EISDIR) {
+ inc_count (new_dir);
+ ret = UMSDOS_rmdir (new_dir, new_dentry);
+ chkstk ();
+ Printk (("rename rmdir ret %d -- ", ret));
+ }
+ if (ret == 0) {
+ ret = umsdos_rename_f (old_dir, old_dentry,
+ new_dir, new_dentry, 0);
+ new_dir = old_dir = NULL;
+ }
+ }
+ }
+ /*
+ * dput (new_dentry);
+ * dput (old_dentry); FIXME /mn/ */
+ return ret;
+}
diff --git a/fs/umsdos/rdir.c b/fs/umsdos/rdir.c
index 612002c3b..f0252254a 100644
--- a/fs/umsdos/rdir.c
+++ b/fs/umsdos/rdir.c
@@ -30,276 +30,284 @@ struct RDIR_FILLDIR {
int real_root;
};
-static int rdir_filldir(
- void * buf,
- const char *name,
- int name_len,
- off_t offset,
- ino_t ino)
+static int rdir_filldir (
+ void *buf,
+ const char *name,
+ int name_len,
+ off_t offset,
+ ino_t ino)
{
- int ret = 0;
- struct RDIR_FILLDIR *d = (struct RDIR_FILLDIR*) buf;
- PRINTK ((KERN_DEBUG "rdir_filldir /mn/: entering\n"));
- if (d->real_root){
- PRINTK ((KERN_DEBUG "rdir_filldir /mn/: real root!\n"));
- /* real root of a pseudo_rooted partition */
- if (name_len != UMSDOS_PSDROOT_LEN
- || memcmp(name,UMSDOS_PSDROOT_NAME,UMSDOS_PSDROOT_LEN)!=0){
- /* So it is not the /linux directory */
- if (name_len == 2
- && name[0] == '.'
- && name[1] == '.'){
+ int ret = 0;
+ struct RDIR_FILLDIR *d = (struct RDIR_FILLDIR *) buf;
+
+ PRINTK ((KERN_DEBUG "rdir_filldir /mn/: entering\n"));
+ if (d->real_root) {
+ PRINTK ((KERN_DEBUG "rdir_filldir /mn/: real root!\n"));
+ /* real root of a pseudo_rooted partition */
+ if (name_len != UMSDOS_PSDROOT_LEN
+ || memcmp (name, UMSDOS_PSDROOT_NAME, UMSDOS_PSDROOT_LEN) != 0) {
+ /* So it is not the /linux directory */
+ if (name_len == 2
+ && name[0] == '.'
+ && name[1] == '.') {
/* Make sure the .. entry points back to the pseudo_root */
- ino = pseudo_root->i_ino;
- }
- ret = d->filldir (d->dirbuf,name,name_len,offset,ino);
- }
- }else{
- /* Any DOS directory */
- PRINTK ((KERN_DEBUG "rdir_filldir /mn/: calling d->filldir (%p) for %.*s (%lu)\n", d->filldir, name_len, name, ino));
- ret = d->filldir (d->dirbuf, name, name_len, offset, ino);
- }
- return ret;
+ ino = pseudo_root->i_ino;
+ }
+ ret = d->filldir (d->dirbuf, name, name_len, offset, ino);
+ }
+ } else {
+ /* Any DOS directory */
+ PRINTK ((KERN_DEBUG "rdir_filldir /mn/: calling d->filldir (%p) for %.*s (%lu)\n", d->filldir, name_len, name, ino));
+ ret = d->filldir (d->dirbuf, name, name_len, offset, ino);
+ }
+ return ret;
}
static int UMSDOS_rreaddir (
- struct file *filp,
- void *dirbuf,
- filldir_t filldir)
+ struct file *filp,
+ void *dirbuf,
+ filldir_t filldir)
{
- struct RDIR_FILLDIR bufk;
- struct inode *dir = filp->f_dentry->d_inode;
-
- PRINTK ((KERN_DEBUG "UMSDOS_rreaddir /mn/: entering %p %p\n", filldir, dirbuf));
+ struct RDIR_FILLDIR bufk;
+ struct inode *dir = filp->f_dentry->d_inode;
+
+ PRINTK ((KERN_DEBUG "UMSDOS_rreaddir /mn/: entering %p %p\n", filldir, dirbuf));
-
- bufk.filldir = filldir;
- bufk.dirbuf = dirbuf;
- bufk.real_root = pseudo_root
- && dir == iget(dir->i_sb,UMSDOS_ROOT_INO)
- && dir == iget(pseudo_root->i_sb,UMSDOS_ROOT_INO);
- PRINTK ((KERN_DEBUG "UMSDOS_rreaddir /mn/: calling fat_readdir with filldir=%p and exiting\n",filldir));
- return fat_readdir(filp, &bufk, rdir_filldir);
+
+ bufk.filldir = filldir;
+ bufk.dirbuf = dirbuf;
+ bufk.real_root = pseudo_root
+ && dir == iget (dir->i_sb, UMSDOS_ROOT_INO)
+ && dir == iget (pseudo_root->i_sb, UMSDOS_ROOT_INO);
+ PRINTK ((KERN_DEBUG "UMSDOS_rreaddir /mn/: calling fat_readdir with filldir=%p and exiting\n", filldir));
+ return fat_readdir (filp, &bufk, rdir_filldir);
}
/*
- Lookup into a non promoted directory.
- If the result is a directory, make sure we find out if it is
- a promoted one or not (calling umsdos_setup_dir_inode(inode)).
-*/
-int umsdos_rlookup_x(
- struct inode *dir,
- struct dentry *dentry,
- int nopseudo) /* Don't care about pseudo root mode */
- /* so locating "linux" will work */
-{
- int len = dentry->d_name.len;
- const char *name = dentry->d_name.name;
- struct inode *inode;
- int ret;
- if (pseudo_root
- && len == 2
- && name[0] == '.'
- && name[1] == '.'
- && dir == iget(dir->i_sb,UMSDOS_ROOT_INO)
- && dir == iget(pseudo_root->i_sb,UMSDOS_ROOT_INO) ){
- /* *result = pseudo_root;*/
- Printk ((KERN_WARNING "umsdos_rlookup_x: we are at pseudo-root thingy?\n"));
- pseudo_root->i_count++;
- ret = 0;
- /* #Specification: pseudo root / DOS/..
- In the real root directory (c:\), the directory ..
- is the pseudo root (c:\linux).
- */
- }else{
- ret = umsdos_real_lookup (dir, dentry); inode=dentry->d_inode;
+ * Lookup into a non promoted directory.
+ * If the result is a directory, make sure we find out if it is
+ * a promoted one or not (calling umsdos_setup_dir_inode(inode)).
+ */
+int umsdos_rlookup_x (
+ struct inode *dir,
+ struct dentry *dentry,
+ int nopseudo)
+{ /* Don't care about pseudo root mode */
+ /* so locating "linux" will work */
+ int len = dentry->d_name.len;
+ const char *name = dentry->d_name.name;
+ struct inode *inode;
+ int ret;
+
+ if (pseudo_root
+ && len == 2
+ && name[0] == '.'
+ && name[1] == '.'
+ && dir == iget (dir->i_sb, UMSDOS_ROOT_INO)
+ && dir == iget (pseudo_root->i_sb, UMSDOS_ROOT_INO)) {
+ /* *result = pseudo_root; */
+ Printk ((KERN_WARNING "umsdos_rlookup_x: we are at pseudo-root thingy?\n"));
+ inc_count (pseudo_root);
+ ret = 0;
+ /* #Specification: pseudo root / DOS/..
+ * In the real root directory (c:\), the directory ..
+ * is the pseudo root (c:\linux).
+ */
+ } else {
+ ret = umsdos_real_lookup (dir, dentry);
+ inode = dentry->d_inode;
#if 0
- Printk ((KERN_DEBUG "umsdos_rlookup_x: umsdos_real_lookup for %.*s in %lu returned %d\n", len, name, dir->i_ino, ret));
- Printk ((KERN_DEBUG "umsdos_rlookup_x: umsdos_real_lookup: inode is %p resolving to ", inode));
- if (inode) { /* /mn/ FIXME: DEL_ME */
- Printk ((KERN_DEBUG "i_ino=%lu\n", inode->i_ino));
- } else {
- Printk ((KERN_DEBUG "NONE!\n"));
- }
+ Printk ((KERN_DEBUG "umsdos_rlookup_x: umsdos_real_lookup for %.*s in %lu returned %d\n", len, name, dir->i_ino, ret));
+ Printk ((KERN_DEBUG "umsdos_rlookup_x: umsdos_real_lookup: inode is %p resolving to ", inode));
+ if (inode) { /* /mn/ FIXME: DEL_ME */
+ Printk ((KERN_DEBUG "i_ino=%lu\n", inode->i_ino));
+ } else {
+ Printk ((KERN_DEBUG "NONE!\n"));
+ }
#endif
-
- if ((ret == 0) && inode){
-
- if (pseudo_root && inode == pseudo_root && !nopseudo){
- /* #Specification: pseudo root / DOS/linux
- Even in the real root directory (c:\), the directory
- /linux won't show
- */
- Printk ((KERN_WARNING "umsdos_rlookup_x: do the pseudo-thingy...\n"));
- ret = -ENOENT;
- /* iput (pseudo_root); FIXME */
-
- }else if (S_ISDIR(inode->i_mode)){
- /* We must place the proper function table */
- /* depending if this is a MsDOS directory or an UMSDOS directory */
- Printk ((KERN_DEBUG "umsdos_rlookup_x: setting up setup_dir_inode %lu...\n", inode->i_ino));
- umsdos_setup_dir_inode (inode);
- }
- }
- }
- /* iput (dir); FIXME */
- PRINTK ((KERN_DEBUG "umsdos_rlookup_x: returning %d\n", ret));
- return ret;
+
+ if ((ret == 0) && inode) {
+
+ if (pseudo_root && inode == pseudo_root && !nopseudo) {
+ /* #Specification: pseudo root / DOS/linux
+ * Even in the real root directory (c:\), the directory
+ * /linux won't show
+ */
+ Printk ((KERN_WARNING "umsdos_rlookup_x: do the pseudo-thingy...\n"));
+ ret = -ENOENT;
+ iput (pseudo_root); /* FIXME? */
+
+ } else if (S_ISDIR (inode->i_mode)) {
+ /* We must place the proper function table */
+ /* depending if this is a MsDOS directory or an UMSDOS directory */
+ Printk ((KERN_DEBUG "umsdos_rlookup_x: setting up setup_dir_inode %lu...\n", inode->i_ino));
+ umsdos_setup_dir_inode (inode);
+ }
+ }
+ }
+ iput (dir); /* FIXME? */
+ PRINTK ((KERN_DEBUG "umsdos_rlookup_x: returning %d\n", ret));
+ return ret;
}
-int UMSDOS_rlookup(
- struct inode *dir,
- struct dentry *dentry
- )
+int UMSDOS_rlookup (
+ struct inode *dir,
+ struct dentry *dentry
+)
{
- PRINTK ((KERN_DEBUG "UMSDOS_rlookup /mn/: executing umsdos_rlookup_x for ino=%lu in %.*s\n", dir->i_ino, (int) dentry->d_name.len, dentry->d_name.name));
- return umsdos_rlookup_x(dir,dentry,0);
+ PRINTK ((KERN_DEBUG "UMSDOS_rlookup /mn/: executing umsdos_rlookup_x for ino=%lu in %.*s\n", dir->i_ino, (int) dentry->d_name.len, dentry->d_name.name));
+ return umsdos_rlookup_x (dir, dentry, 0);
}
static int UMSDOS_rrmdir (
- struct inode *dir,
- struct dentry *dentry)
+ struct inode *dir,
+ struct dentry *dentry)
{
- /* #Specification: dual mode / rmdir in a DOS directory
- In a DOS (not EMD in it) directory, we use a reverse strategy
- compared with an Umsdos directory. We assume that a subdirectory
- of a DOS directory is also a DOS directory. This is not always
- true (umssync may be used anywhere), but make sense.
-
- So we call msdos_rmdir() directly. If it failed with a -ENOTEMPTY
- then we check if it is a Umsdos directory. We check if it is
- really empty (only . .. and --linux-.--- in it). If it is true
- we remove the EMD and do a msdos_rmdir() again.
+ /* #Specification: dual mode / rmdir in a DOS directory
+ * In a DOS (not EMD in it) directory, we use a reverse strategy
+ * compared with an Umsdos directory. We assume that a subdirectory
+ * of a DOS directory is also a DOS directory. This is not always
+ * true (umssync may be used anywhere), but make sense.
+ *
+ * So we call msdos_rmdir() directly. If it failed with a -ENOTEMPTY
+ * then we check if it is a Umsdos directory. We check if it is
+ * really empty (only . .. and --linux-.--- in it). If it is true
+ * we remove the EMD and do a msdos_rmdir() again.
+ *
+ * In a Umsdos directory, we assume all subdirectory are also
+ * Umsdos directory, so we check the EMD file first.
+ */
+ int ret;
- In a Umsdos directory, we assume all subdirectory are also
- Umsdos directory, so we check the EMD file first.
- */
- int ret;
- if (umsdos_is_pseudodos(dir,dentry)){
- /* #Specification: pseudo root / rmdir /DOS
- The pseudo sub-directory /DOS can't be removed!
- This is done even if the pseudo root is not a Umsdos
- directory anymore (very unlikely), but an accident (under
- MsDOS) is always possible.
-
- EPERM is returned.
- */
- ret = -EPERM;
- }else{
- umsdos_lockcreate (dir);
- dir->i_count++;
- ret = msdos_rmdir (dir,dentry);
- if (ret == -ENOTEMPTY){
- struct inode *sdir;
- dir->i_count++;
-
- ret = UMSDOS_rlookup (dir,dentry);
- sdir = dentry->d_inode;
- PRINTK (("rrmdir lookup %d ",ret));
- if (ret == 0){
- int empty;
- if ((empty = umsdos_isempty (sdir)) != 0){
- PRINTK (("isempty %d i_count %d ",empty,
- atomic_read(&sdir->i_count)));
- if (empty == 2){
- /*
- Not a Umsdos directory, so the previous msdos_rmdir
- was not lying :-)
- */
- ret = -ENOTEMPTY;
- }else if (empty == 1){
- /* We have to removed the EMD file */
- struct dentry *temp;
- temp = creat_dentry (UMSDOS_EMD_FILE, UMSDOS_EMD_NAMELEN, NULL, NULL); /* FIXME: prolly should fill inode part ? */
- ret = msdos_unlink(sdir, temp);
- sdir = NULL;
- if (ret == 0){
- dir->i_count++;
- ret = msdos_rmdir (dir,dentry);
- }
- }
- }else{
- ret = -ENOTEMPTY;
- }
- /* iput (sdir); FIXME */
- }
- }
- umsdos_unlockcreate (dir);
- }
- /* iput (dir); FIXME */
- return ret;
-}
-
-/* #Specification: dual mode / introduction
- One goal of UMSDOS is to allow a practical and simple coexistence
- between MsDOS and Linux in a single partition. Using the EMD file
- in each directory, UMSDOS add Unix semantics and capabilities to
- normal DOS file system. To help and simplify coexistence, here is
- the logic related to the EMD file.
-
- If it is missing, then the directory is managed by the MsDOS driver.
- The names are limited to DOS limits (8.3). No links, no device special
- and pipe and so on.
+ if (umsdos_is_pseudodos (dir, dentry)) {
+ /* #Specification: pseudo root / rmdir /DOS
+ * The pseudo sub-directory /DOS can't be removed!
+ * This is done even if the pseudo root is not a Umsdos
+ * directory anymore (very unlikely), but an accident (under
+ * MsDOS) is always possible.
+ *
+ * EPERM is returned.
+ */
+ ret = -EPERM;
+ } else {
+ umsdos_lockcreate (dir);
+ inc_count (dir);
+ ret = msdos_rmdir (dir, dentry);
+ if (ret == -ENOTEMPTY) {
+ struct inode *sdir;
- If it is there, it is the directory. If it is there but empty, then
- the directory looks empty. The utility umssync allows synchronisation
- of the real DOS directory and the EMD.
+ inc_count (dir);
- Whenever umssync is applied to a directory without EMD, one is
- created on the fly. The directory is promoted to full unix semantic.
- Of course, the ls command will show exactly the same content as before
- the umssync session.
+ ret = UMSDOS_rlookup (dir, dentry);
+ sdir = dentry->d_inode;
+ PRINTK (("rrmdir lookup %d ", ret));
+ if (ret == 0) {
+ int empty;
- It is believed that the user/admin will promote directories to unix
- semantic as needed.
+ if ((empty = umsdos_isempty (sdir)) != 0) {
+ PRINTK (("isempty %d i_count %d ", empty,
+ atomic_read (&sdir->i_count)));
+ if (empty == 2) {
+ /*
+ * Not a Umsdos directory, so the previous msdos_rmdir
+ * was not lying :-)
+ */
+ ret = -ENOTEMPTY;
+ } else if (empty == 1) {
+ /* We have to removed the EMD file */
+ struct dentry *temp;
- The strategy to implement this is to use two function table (struct
- inode_operations). One for true UMSDOS directory and one for directory
- with missing EMD.
+ Printk ((KERN_WARNING "UMSDOS_rmdir: hmmm... whatabout inode ? FIXME\n"));
+ temp = creat_dentry (UMSDOS_EMD_FILE, UMSDOS_EMD_NAMELEN, NULL, NULL); /* FIXME: prolly should fill inode part ? */
+ ret = msdos_unlink (sdir, temp);
+ sdir = NULL;
+ if (ret == 0) {
+ inc_count (dir);
+ ret = msdos_rmdir (dir, dentry);
+ }
+ }
+ } else {
+ ret = -ENOTEMPTY;
+ }
+ /* iput (sdir); FIXME */
+ }
+ }
+ umsdos_unlockcreate (dir);
+ }
+ /* iput (dir); FIXME */
+ return ret;
+}
- Functions related to the DOS semantic (but aware of UMSDOS) generally
- have a "r" prefix (r for real) such as UMSDOS_rlookup, to differentiate
- from the one with full UMSDOS semantic.
-*/
-static struct file_operations umsdos_rdir_operations = {
- NULL, /* lseek - default */
- UMSDOS_dir_read, /* read */
- NULL, /* write - bad */
- UMSDOS_rreaddir, /* readdir */
- NULL, /* poll - default */
- UMSDOS_ioctl_dir, /* ioctl - default */
- NULL, /* mmap */
- NULL, /* no special open code */
- NULL, /* no special release code */
- NULL /* fsync */
+/* #Specification: dual mode / introduction
+ * One goal of UMSDOS is to allow a practical and simple coexistence
+ * between MsDOS and Linux in a single partition. Using the EMD file
+ * in each directory, UMSDOS add Unix semantics and capabilities to
+ * normal DOS file system. To help and simplify coexistence, here is
+ * the logic related to the EMD file.
+ *
+ * If it is missing, then the directory is managed by the MsDOS driver.
+ * The names are limited to DOS limits (8.3). No links, no device special
+ * and pipe and so on.
+ *
+ * If it is there, it is the directory. If it is there but empty, then
+ * the directory looks empty. The utility umssync allows synchronisation
+ * of the real DOS directory and the EMD.
+ *
+ * Whenever umssync is applied to a directory without EMD, one is
+ * created on the fly. The directory is promoted to full unix semantic.
+ * Of course, the ls command will show exactly the same content as before
+ * the umssync session.
+ *
+ * It is believed that the user/admin will promote directories to unix
+ * semantic as needed.
+ *
+ * The strategy to implement this is to use two function table (struct
+ * inode_operations). One for true UMSDOS directory and one for directory
+ * with missing EMD.
+ *
+ * Functions related to the DOS semantic (but aware of UMSDOS) generally
+ * have a "r" prefix (r for real) such as UMSDOS_rlookup, to differentiate
+ * from the one with full UMSDOS semantic.
+ */
+static struct file_operations umsdos_rdir_operations =
+{
+ NULL, /* lseek - default */
+ UMSDOS_dir_read, /* read */
+ NULL, /* write - bad */
+ UMSDOS_rreaddir, /* readdir */
+ NULL, /* poll - default */
+ UMSDOS_ioctl_dir, /* ioctl - default */
+ NULL, /* mmap */
+ NULL, /* no special open code */
+ NULL, /* no special release code */
+ NULL /* fsync */
};
-struct inode_operations umsdos_rdir_inode_operations = {
- &umsdos_rdir_operations, /* default directory file-ops */
- msdos_create, /* create */
- UMSDOS_rlookup, /* lookup */
- NULL, /* link */
- msdos_unlink, /* unlink */
- NULL, /* symlink */
- msdos_mkdir, /* mkdir */
- UMSDOS_rrmdir, /* rmdir */
- NULL, /* mknod */
- msdos_rename, /* rename */
- NULL, /* readlink */
- NULL, /* followlink */
- NULL, /* readpage */
- NULL, /* writepage */
- NULL, /* bmap */
- NULL, /* truncate */
- NULL, /* permission */
- NULL, /* smap */
- NULL, /* updatepage */
- NULL, /* revalidate */
+struct inode_operations umsdos_rdir_inode_operations =
+{
+ &umsdos_rdir_operations, /* default directory file-ops */
+ msdos_create, /* create */
+ UMSDOS_rlookup, /* lookup */
+ NULL, /* link */
+ msdos_unlink, /* unlink */
+ NULL, /* symlink */
+ msdos_mkdir, /* mkdir */
+ UMSDOS_rrmdir, /* rmdir */
+ NULL, /* mknod */
+ msdos_rename, /* rename */
+ NULL, /* readlink */
+ NULL, /* followlink */
+ NULL, /* readpage */
+ NULL, /* writepage */
+ NULL, /* bmap */
+ NULL, /* truncate */
+ NULL, /* permission */
+ NULL, /* smap */
+ NULL, /* updatepage */
+ NULL, /* revalidate */
};
-
-
diff --git a/fs/umsdos/symlink.c b/fs/umsdos/symlink.c
index 3ed550742..32510a46b 100644
--- a/fs/umsdos/symlink.c
+++ b/fs/umsdos/symlink.c
@@ -2,7 +2,7 @@
* linux/fs/umsdos/file.c
*
* Written 1992 by Jacques Gelinas
- * inspired from linux/fs/msdos/file.c Werner Almesberger
+ * inspired from linux/fs/msdos/file.c Werner Almesberger
*
* Extended MS-DOS regular file handling primitives
*/
@@ -26,59 +26,57 @@ static struct file_operations umsdos_symlink_operations;
/*
- Read the data associate with the symlink.
- Return length read in buffer or a negative error code.
-
-*/
+ * Read the data associate with the symlink.
+ * Return length read in buffer or a negative error code.
+ *
+ */
static int umsdos_readlink_x (
- struct dentry *dentry,
- char *buffer,
- int bufsiz)
+ struct dentry *dentry,
+ char *buffer,
+ int bufsiz)
{
int ret;
loff_t loffs = 0;
struct file filp;
- fill_new_filp (&filp, NULL);
-
ret = dentry->d_inode->i_size;
-
- memset (&filp, 0, sizeof (filp));
-
- filp.f_pos = 0;
+
+ check_dentry (dentry);
+ fill_new_filp (&filp, dentry);
+
filp.f_reada = 0;
filp.f_flags = O_RDONLY;
- filp.f_dentry = dentry;
- filp.f_op = &umsdos_symlink_operations; /* /mn/ - we have to fill it with dummy values so we won't segfault */
+ filp.f_op = &umsdos_symlink_operations; /* /mn/ - we have to fill it with dummy values so we won't segfault */
- if (ret > bufsiz) ret = bufsiz;
+ if (ret > bufsiz)
+ ret = bufsiz;
- PRINTK ((KERN_DEBUG "umsdos_readlink_x /mn/: Checkin: filp=%p, buffer=%p, size=%d, offs=%Lu\n", &filp, buffer, ret, loffs));
- PRINTK ((KERN_DEBUG " f_op=%p\n", filp.f_op));
- PRINTK ((KERN_DEBUG " inode=%lu, i_size=%lu\n", filp.f_dentry->d_inode->i_ino, filp.f_dentry->d_inode->i_size));
- PRINTK ((KERN_DEBUG " f_pos=%Lu\n", filp.f_pos));
- PRINTK ((KERN_DEBUG " name=%.*s\n", (int) filp.f_dentry->d_name.len, filp.f_dentry->d_name.name));
- PRINTK ((KERN_DEBUG " i_binary(sb)=%d\n", MSDOS_I(filp.f_dentry->d_inode)->i_binary ));
- PRINTK ((KERN_DEBUG " f_count=%d, f_flags=%d\n", filp.f_count, filp.f_flags));
- PRINTK ((KERN_DEBUG " f_owner=%d\n", filp.f_owner.uid));
- PRINTK ((KERN_DEBUG " f_version=%ld\n", filp.f_version));
- PRINTK ((KERN_DEBUG " f_reada=%ld, f_ramax=%ld, f_raend=%ld, f_ralen=%ld, f_rawin=%ld\n", filp.f_reada, filp.f_ramax, filp.f_raend, filp.f_ralen, filp.f_rawin));
+ PRINTK ((KERN_DEBUG "umsdos_readlink_x /mn/: Checkin: filp=%p, buffer=%p, size=%d, offs=%Lu\n", &filp, buffer, ret, loffs));
+ PRINTK ((KERN_DEBUG " f_op=%p\n", filp.f_op));
+ PRINTK ((KERN_DEBUG " inode=%lu, i_size=%lu\n", filp.f_dentry->d_inode->i_ino, filp.f_dentry->d_inode->i_size));
+ PRINTK ((KERN_DEBUG " f_pos=%Lu\n", filp.f_pos));
+ PRINTK ((KERN_DEBUG " name=%.*s\n", (int) filp.f_dentry->d_name.len, filp.f_dentry->d_name.name));
+ PRINTK ((KERN_DEBUG " i_binary(sb)=%d\n", MSDOS_I (filp.f_dentry->d_inode)->i_binary));
+ PRINTK ((KERN_DEBUG " f_count=%d, f_flags=%d\n", filp.f_count, filp.f_flags));
+ PRINTK ((KERN_DEBUG " f_owner=%d\n", filp.f_owner.uid));
+ PRINTK ((KERN_DEBUG " f_version=%ld\n", filp.f_version));
+ PRINTK ((KERN_DEBUG " f_reada=%ld, f_ramax=%ld, f_raend=%ld, f_ralen=%ld, f_rawin=%ld\n", filp.f_reada, filp.f_ramax, filp.f_raend, filp.f_ralen, filp.f_rawin));
- PRINTK ((KERN_DEBUG"umsdos_readlink_x: FIXME /mn/: running fat_file_read (%p, %p, %d, %Lu)\n", &filp, buffer, ret, loffs));
- if (fat_file_read (&filp, buffer, (size_t) ret, &loffs) != ret){
+ PRINTK ((KERN_DEBUG "umsdos_readlink_x: FIXME /mn/: running fat_file_read (%p, %p, %d, %Lu)\n", &filp, buffer, ret, loffs));
+ if (fat_file_read (&filp, buffer, (size_t) ret, &loffs) != ret) {
ret = -EIO;
}
-#if 0 /* DEBUG */
- {
- struct umsdos_dirent *mydirent=buffer;
+#if 0 /* DEBUG */
+ {
+ struct umsdos_dirent *mydirent = buffer;
- PRINTK ((KERN_DEBUG " (DDD) uid=%d\n",mydirent->uid));
- PRINTK ((KERN_DEBUG " (DDD) gid=%d\n",mydirent->gid));
- PRINTK ((KERN_DEBUG " (DDD) name=>%.20s<\n",mydirent->name));
- }
-#endif
+ PRINTK ((KERN_DEBUG " (DDD) uid=%d\n", mydirent->uid));
+ PRINTK ((KERN_DEBUG " (DDD) gid=%d\n", mydirent->gid));
+ PRINTK ((KERN_DEBUG " (DDD) name=>%.20s<\n", mydirent->name));
+ }
+#endif
PRINTK ((KERN_DEBUG "umsdos_readlink_x: FIXME /mn/: fat_file_read returned offs=%Lu ret=%d\n", loffs, ret));
return ret;
@@ -86,7 +84,7 @@ static int umsdos_readlink_x (
-static int UMSDOS_readlink(struct dentry *dentry, char *buffer, int buflen)
+static int UMSDOS_readlink (struct dentry *dentry, char *buffer, int buflen)
{
int ret;
@@ -96,67 +94,69 @@ static int UMSDOS_readlink(struct dentry *dentry, char *buffer, int buflen)
/* dput(dentry); / * FIXME /mn/ */
Printk ((KERN_WARNING "UMSDOS_readlink /mn/: FIXME! skipped dput(dentry). returning %d\n", ret));
return ret;
-
+
}
/* this one mostly stolen from romfs :) */
-static struct dentry *UMSDOS_followlink(struct dentry *dentry, struct dentry *base)
+static struct dentry *UMSDOS_followlink (struct dentry *dentry, struct dentry *base)
{
struct inode *inode = dentry->d_inode;
- char *symname=NULL;
+ char *symname = NULL;
int len, cnt;
- mm_segment_t old_fs = get_fs();
+ mm_segment_t old_fs = get_fs ();
+
Printk ((KERN_DEBUG "UMSDOS_followlink /mn/: (%.*s/%.*s)\n", (int) dentry->d_parent->d_name.len, dentry->d_parent->d_name.name, (int) dentry->d_name.len, dentry->d_name.name));
len = inode->i_size;
- if (!(symname = kmalloc(len+1, GFP_KERNEL))) {
- dentry = ERR_PTR(-EAGAIN); /* correct? */
+ if (!(symname = kmalloc (len + 1, GFP_KERNEL))) {
+ dentry = ERR_PTR (-EAGAIN); /* correct? */
goto outnobuf;
}
-
set_fs (KERNEL_DS); /* we read into kernel space this time */
PRINTK ((KERN_DEBUG "UMSDOS_followlink /mn/: Here goes umsdos_readlink_x %p, %p, %d\n", dentry, symname, len));
cnt = umsdos_readlink_x (dentry, symname, len);
PRINTK ((KERN_DEBUG "UMSDOS_followlink /mn/: back from umsdos_readlink_x %p, %p, %d!\n", dentry, symname, len));
set_fs (old_fs);
Printk ((KERN_DEBUG "UMSDOS_followlink /mn/: link name is %.*s with len %d\n", cnt, symname, cnt));
-
+
if (len != cnt) {
- dentry = ERR_PTR(-EIO);
+ dentry = ERR_PTR (-EIO);
goto out;
} else
symname[len] = 0;
- dentry = lookup_dentry(symname, base, 1);
- kfree(symname);
+ dentry = lookup_dentry (symname, base, 1);
+ kfree (symname);
if (0) {
-out:
- kfree(symname);
-outnobuf:
- dput(base);
+ out:
+ kfree (symname);
+ outnobuf:
+ dput (base);
}
return dentry;
}
-static struct file_operations umsdos_symlink_operations = {
- NULL, /* lseek - default */
- NULL, /* read */
- NULL, /* write */
- NULL, /* readdir - bad */
- NULL, /* poll - default */
- NULL, /* ioctl - default */
- NULL, /* mmap */
- NULL, /* no special open is needed */
- NULL, /* release */
- NULL /* fsync */
+static struct file_operations umsdos_symlink_operations =
+{
+ NULL, /* lseek - default */
+ NULL, /* read */
+ NULL, /* write */
+ NULL, /* readdir - bad */
+ NULL, /* poll - default */
+ NULL, /* ioctl - default */
+ NULL, /* mmap */
+ NULL, /* no special open is needed */
+ NULL, /* release */
+ NULL /* fsync */
};
-struct inode_operations umsdos_symlink_inode_operations = {
- NULL, /* default file operations */
+struct inode_operations umsdos_symlink_inode_operations =
+{
+ NULL, /* default file operations */
NULL, /* create */
NULL, /* lookup */
NULL, /* link */
@@ -167,17 +167,14 @@ struct inode_operations umsdos_symlink_inode_operations = {
NULL, /* mknod */
NULL, /* rename */
UMSDOS_readlink, /* readlink */
- UMSDOS_followlink, /* followlink */ /* /mn/ is this REALLY needed ? I recall seeing it working w/o it... */
- generic_readpage, /* readpage */ /* in original NULL. changed to generic_readpage. FIXME? /mn/ */
+ UMSDOS_followlink, /* followlink *//* /mn/ is this REALLY needed ? I recall seeing it working w/o it... */
+ generic_readpage, /* readpage *//* in original NULL. changed to generic_readpage. FIXME? /mn/ */
NULL, /* writepage */
- fat_bmap, /* bmap */ /* in original NULL. changed to fat_bmap. FIXME? /mn/ */
+ fat_bmap, /* bmap *//* in original NULL. changed to fat_bmap. FIXME? /mn/ */
NULL, /* truncate */
NULL, /* permission */
NULL, /* smap */
NULL, /* updatepage */
NULL /* revalidate */
-
-};
-
-
+};