vfat for 2.1.45

Michael Harnois (mharnois@sbt.net)
18 Jul 1997 15:29:05 -0500


As far as I can tell, this does everything but create new directory entries
-- when I try to create a new file or directory, it responds, e.g.:

cannot make directory `tmp': No such file or directory

Someone more knowledgeable than I will probably see the source of the
problem right away.

--- namei.c.orig Thu Jul 17 23:52:31 1997
+++ namei.c Fri Jul 18 14:44:22 1997
@@ -67,11 +67,12 @@
}


-static struct super_operations vfat_sops = {
+struct super_operations vfat_sops = {
vfat_read_inode,
- fat_notify_change,
fat_write_inode,
fat_put_inode,
+ fat_delete_inode,
+ fat_notify_change,
vfat_put_super,
NULL, /* added in 0.96c */
fat_statfs,
@@ -910,71 +911,59 @@
return -ENOENT;
}

-int vfat_lookup(struct inode *dir,const char *name,int len,
- struct inode **result)
+int vfat_lookup(struct inode *dir,struct dentry *dentry)
{
int res, ino;
- struct inode *next;
+ struct inode *next, *inode;
struct slot_info sinfo;

PRINTK (("vfat_lookup: name=%s, len=%d\n", name, len));
-
- *result = NULL;
- if (!dir) return -ENOENT;
- if (!S_ISDIR(dir->i_mode)) {
- iput(dir);
- return -ENOENT;
- }
+
PRINTK (("vfat_lookup 2\n"));
- if (len == 1 && name[0] == '.') {
- *result = dir;
- return 0;
+ if (dentry->d_name.len == 1 && dentry->d_name.name[0] == '.') {
+ inode = dir;
+ return 0;
}
- if (len == 2 && name[0] == '.' && name[1] == '.') {
+ if (dentry->d_name.len == 2 && dentry->d_name.name[0] == '.' && dentry->d_name.name[1] == '.') {
ino = fat_parent_ino(dir,0);
- iput(dir);
if (ino < 0) return ino;
- if (!(*result = iget(dir->i_sb,ino))) return -EACCES;
+ if (!(inode = iget(dir->i_sb,ino))) return -EACCES;
return 0;
}
PRINTK (("vfat_lookup 3\n"));
- if ((res = vfat_find(dir,name,len,1,0,0,&sinfo)) < 0) {
- iput(dir);
+ if ((res = vfat_find(dir,dentry->d_name.name,dentry->d_name.len,1,0,0,&sinfo)) < 0)
return res;
- }
- PRINTK (("vfat_lookup 4.5\n"));
- if (!(*result = iget(dir->i_sb,sinfo.ino))) {
- iput(dir);
+
+
+ PRINTK (("vfat_lookup 4.5\n"));
+ if (!(inode = iget(dir->i_sb,sinfo.ino)))
return -EACCES;
- }
+
PRINTK (("vfat_lookup 5\n"));
- if (!(*result)->i_sb ||
- ((*result)->i_sb->s_magic != MSDOS_SUPER_MAGIC)) {
+ if (!(inode)->i_sb ||
+ ((inode)->i_sb->s_magic != MSDOS_SUPER_MAGIC))
/* crossed a mount point into a non-msdos fs */
- iput(dir);
return 0;
- }
- if (MSDOS_I(*result)->i_busy) { /* mkdir in progress */
- iput(*result);
- iput(dir);
+
+ if (MSDOS_I(inode)->i_busy) { /* mkdir in progress */
+ iput(inode);
return -ENOENT;
}
PRINTK (("vfat_lookup 6\n"));
- while (MSDOS_I(*result)->i_old) {
- next = MSDOS_I(*result)->i_old;
- iput(*result);
- if (!(*result = iget(next->i_sb,next->i_ino))) {
+ while (MSDOS_I(inode)->i_old) {
+ next = MSDOS_I(inode)->i_old;
+ iput(inode);
+ if (!(inode = iget(next->i_sb,next->i_ino))) {
fat_fs_panic(dir->i_sb,"vfat_lookup: Can't happen");
- iput(dir);
return -ENOENT;
}
}
- iput(dir);
- return 0;
+ d_add(dentry, inode);
+ return 0;
}


-static int vfat_create_entry(struct inode *dir,const char *name,int len,
+static int vfat_create_entry(struct inode *dir,const char *name, int len,
int is_dir, struct inode **result)
{
struct super_block *sb = dir->i_sb;
@@ -1010,26 +999,24 @@
return -EIO;
(*result)->i_mtime = (*result)->i_atime = (*result)->i_ctime =
CURRENT_TIME;
- mark_inode_dirty(*result);
+ mark_inode_dirty( (*result ) );
(*result)->i_version = ++event;
dir->i_version = event;

return 0;
}

-int vfat_create(struct inode *dir,const char *name,int len,int mode,
- struct inode **result)
+int vfat_create(struct inode *dir, struct dentry * dentry, int mode)
{
int res;
-
+ struct inode *result;
if (!dir) return -ENOENT;

fat_lock_creation();
- res = vfat_create_entry(dir,name,len,0,result);
+ res = vfat_create_entry(dir,dentry->d_name.name,dentry->d_name.len,0,&result);
if (res < 0) PRINTK(("vfat_create: unable to get new entry\n"));
-
+ d_instantiate(dentry, result);
fat_unlock_creation();
- iput(dir);
return res;
}

@@ -1241,7 +1228,7 @@
}


-static int vfat_rmdirx(struct inode *dir,const char *name,int len)
+static int vfat_rmdirx(struct inode * dir, const char *name, int len)
{
struct super_block *sb = dir->i_sb;
int res;
@@ -1251,9 +1238,13 @@

bh = NULL;
res = -EPERM;
- if (name[0] == '.' && (len == 1 || (len == 2 && name[1] == '.')))
+ if (name[0] == '.' &&
+ (len == 1 ||
+ (len == 2 && name[1] == '.')))
goto rmdir_done;
- res = vfat_find(dir,name,len,1,0,0,&sinfo);
+ res = vfat_find(dir,
+ name,len,
+ 1,0,0,&sinfo);

if (res >= 0 && sinfo.total_slots > 0) {
res = vfat_remove_entry(dir,&sinfo,&bh,&de,1,0);
@@ -1271,12 +1262,11 @@
}

/***** Remove a directory */
-int vfat_rmdir(struct inode *dir,const char *name,int len)
+int vfat_rmdir(struct inode *dir,struct dentry *dentry)
{
int res;

- res = vfat_rmdirx(dir, name, len);
- iput(dir);
+ res = vfat_rmdirx(dir, dentry->d_name.name, dentry->d_name.len);
return res;
}

@@ -1311,15 +1301,14 @@
}


-int vfat_mkdir(struct inode *dir,const char *name,int len,int mode)
+int vfat_mkdir(struct inode * dir, struct dentry * dentry, int mode)
{
struct inode *inode;
int res;

fat_lock_creation();
- if ((res = vfat_create_entry(dir,name,len,1,&inode)) < 0) {
- fat_unlock_creation();
- iput(dir);
+ if ((res = vfat_create_entry(dir,dentry->d_name.name,dentry->d_name.len,1,&inode)) < 0) {
+ fat_unlock_creation();
return res;
}

@@ -1330,28 +1319,28 @@
res = vfat_create_dotdirs(inode, dir);
fat_unlock_creation();
MSDOS_I(inode)->i_busy = 0;
- iput(inode);
- iput(dir);
- if (res < 0) {
- if (vfat_rmdir(dir,name,len) < 0)
+ d_instantiate(dentry, inode);
+ return 0;
+ iput(inode);
+ if (res < 0) {
+ if (vfat_rmdir(dir,dentry) < 0)
fat_fs_panic(dir->i_sb,"rmdir in mkdir failed");
}
- return res;
+ return res;
}

/***** Unlink, as called for msdosfs */
-int vfat_unlink(struct inode *dir,const char *name,int len)
+int vfat_unlink(struct inode *dir,struct dentry *dentry)
{
int res;

- res = vfat_unlinkx (dir,name,len,1);
- iput(dir);
+ res = vfat_unlinkx (dir,dentry->d_name.name,dentry->d_name.len,1);
return res;
}


-int vfat_rename(struct inode *old_dir,const char *old_name,int old_len,
- struct inode *new_dir,const char *new_name,int new_len)
+int vfat_rename(struct inode * old_dir,struct dentry *old_dentry,
+ struct inode * new_dir,struct dentry *new_dentry)
{
struct super_block *sb = old_dir->i_sb;
struct buffer_head *old_bh,*new_bh,*dotdot_bh;
@@ -1364,13 +1353,13 @@
struct slot_info sinfo;

PRINTK(("vfat_rename 1\n"));
- if (old_dir == new_dir && old_len == new_len &&
- strncmp(old_name, new_name, old_len) == 0)
+ if (old_dir == new_dir && old_dentry->d_name.len == new_dentry->d_name.len &&
+ strncmp(old_dentry->d_name.name, new_dentry->d_name.name, old_dentry->d_name.len) == 0)
return 0;

old_bh = new_bh = NULL;
old_inode = new_inode = NULL;
- res = vfat_find(old_dir,old_name,old_len,1,0,0,&sinfo);
+ res = vfat_find(old_dir,old_dentry->d_name.name,old_dentry->d_name.len,1,0,0,&sinfo);
PRINTK(("vfat_rename 2\n"));
if (res < 0) goto rename_done;

@@ -1413,7 +1402,7 @@
iput(walk);
}

- res = vfat_find(new_dir,new_name,new_len,1,0,is_dir,&sinfo);
+ res = vfat_find(new_dir,new_dentry->d_name.name,new_dentry->d_name.len,1,0,is_dir,&sinfo);

PRINTK(("vfat_rename 4\n"));
if (res > -1) {
@@ -1432,12 +1421,12 @@
iput(new_inode);
if (new_is_dir) {
PRINTK(("vfat_rename 7\n"));
- res = vfat_rmdirx(new_dir,new_name,new_len);
+ res = vfat_rmdirx(new_dir,new_dentry->d_name.name,new_dentry->d_name.len);
PRINTK(("vfat_rename 8\n"));
if (res < 0) goto rename_done;
} else {
PRINTK(("vfat_rename 9\n"));
- res = vfat_unlinkx(new_dir,new_name,new_len,1);
+ res = vfat_unlinkx(new_dir,new_dentry->d_name.name,new_dentry->d_name.len,1);
PRINTK(("vfat_rename 10\n"));
if (res < 0) goto rename_done;
}
@@ -1445,7 +1434,7 @@

PRINTK(("vfat_rename 11\n"));
fat_lock_creation(); locked = 1;
- res = vfat_find(new_dir,new_name,new_len,1,1,is_dir,&sinfo);
+ res = vfat_find(new_dir,new_dentry->d_name.name,new_dentry->d_name.len,1,1,is_dir,&sinfo);

PRINTK(("vfat_rename 12\n"));
if (res < 0) goto rename_done;
@@ -1521,6 +1510,8 @@
dotdot_inode->i_nlink = new_dir->i_nlink;
iput(dotdot_inode);
fat_brelse(sb, dotdot_bh);
+ d_move(old_dentry, new_dentry->d_parent, &new_dentry->d_name);
+ d_delete(new_dentry);
}

if (res > 0) res = 0;
@@ -1534,9 +1525,7 @@
fat_brelse(sb, new_bh);
if (old_inode)
iput(old_inode);
- iput(old_dir);
- iput(new_dir);
- return res;
+ return res;
}


@@ -1554,7 +1543,8 @@
NULL, /* mknod */
vfat_rename, /* rename */
NULL, /* readlink */
- NULL, /* readpage */
+ NULL, /* follow_link */
+ NULL, /* readpage */
NULL, /* writepage */
fat_bmap, /* bmap */
NULL, /* truncate */

-- 
 Michael D. Harnois, Redeemer Lutheran Church, Washburn, IA
 mharnois@sbt.net  aa0bt@aa0bt.ampr.org
 "Few sinners are saved after the first 20 minutes of 
  a sermon."  --Mark Twain