patch-2.1.89 linux/fs/ncpfs/dir.c
Next file: linux/fs/ncpfs/inode.c
Previous file: linux/fs/ncpfs/Config.in
Back to the patch index
Back to the overall index
- Lines: 247
- Date:
Fri Mar 6 10:03:04 1998
- Orig file:
v2.1.88/linux/fs/ncpfs/dir.c
- Orig date:
Sun Jan 4 00:53:42 1998
diff -u --recursive --new-file v2.1.88/linux/fs/ncpfs/dir.c linux/fs/ncpfs/dir.c
@@ -7,6 +7,8 @@
*
*/
+#include <linux/config.h>
+
#include <linux/sched.h>
#include <linux/errno.h>
#include <linux/stat.h>
@@ -247,6 +249,98 @@
* This is the callback when the dcache has a lookup hit.
*/
+
+#ifdef CONFIG_NCPFS_STRONG
+/* try to delete a readonly file (NW R bit set) */
+
+static int
+ncp_force_unlink(struct inode *dir, struct dentry* dentry)
+{
+ int res=0x9c,res2;
+ struct iattr ia;
+
+ /* remove the Read-Only flag on the NW server */
+
+ memset(&ia,0,sizeof(struct iattr));
+ ia.ia_mode = dentry->d_inode->i_mode;
+ ia.ia_mode |= NCP_SERVER(dir)->m.file_mode & 0222; /* set write bits */
+ ia.ia_valid = ATTR_MODE;
+
+ res2=ncp_notify_change(dentry, &ia);
+ if (res2)
+ {
+ goto leave_me;
+ }
+
+ /* now try again the delete operation */
+
+ res = ncp_del_file_or_subdir2(NCP_SERVER(dir), dentry);
+
+ if (res) /* delete failed, set R bit again */
+ {
+ memset(&ia,0,sizeof(struct iattr));
+ ia.ia_mode = dentry->d_inode->i_mode;
+ ia.ia_mode &= ~(NCP_SERVER(dir)->m.file_mode & 0222); /* clear write bits */
+ ia.ia_valid = ATTR_MODE;
+
+ res2=ncp_notify_change(dentry, &ia);
+ if (res2)
+ {
+ goto leave_me;
+ }
+ }
+leave_me:
+ return(res);
+}
+#endif /* CONFIG_NCPFS_STRONG */
+
+#ifdef CONFIG_NCPFS_STRONG
+static int
+ncp_force_rename(struct inode *old_dir, struct dentry* old_dentry, char *_old_name,
+ struct inode *new_dir, struct dentry* new_dentry, char *_new_name)
+{
+ int res=0x90,res2;
+ struct iattr ia;
+
+ /* remove the Read-Only flag on the NW server */
+
+ memset(&ia,0,sizeof(struct iattr));
+ ia.ia_mode = old_dentry->d_inode->i_mode;
+ ia.ia_mode |= NCP_SERVER(old_dir)->m.file_mode & 0222; /* set write bits */
+ ia.ia_valid = ATTR_MODE;
+
+ res2=ncp_notify_change(old_dentry, &ia);
+ if (res2)
+ {
+ goto leave_me;
+ }
+
+ /* now try again the rename operation */
+ res = ncp_ren_or_mov_file_or_subdir(NCP_SERVER(old_dir),
+ old_dir, _old_name,
+ new_dir, _new_name);
+
+ memset(&ia,0,sizeof(struct iattr));
+ ia.ia_mode = old_dentry->d_inode->i_mode;
+ ia.ia_mode &= ~(NCP_SERVER(old_dentry->d_inode)->m.file_mode & 0222); /* clear write bits */
+ ia.ia_valid = ATTR_MODE;
+
+ /* FIXME: uses only inode info, no dentry info... so it is safe to call */
+ /* it now with old dentry. If we use name (in future), we have to move */
+ /* it after dentry_move in caller */
+ res2=ncp_notify_change(old_dentry, &ia);
+ if (res2)
+ {
+ printk(KERN_INFO "ncpfs: ncp_notify_change (2) failed: %08x\n",res2);
+ goto leave_me;
+ }
+
+ leave_me:
+ return(res);
+}
+#endif /* CONFIG_NCPFS_STRONG */
+
+
static int
ncp_lookup_validate(struct dentry * dentry)
{
@@ -314,13 +408,15 @@
* If we didn't find it, or if it has a different dirEntNum to
* what we remember, it's not valid any more.
*/
- if (!res)
+ if (!res) {
if (finfo.nw_info.i.dirEntNum == NCP_FINFO(dentry->d_inode)->dirEntNum)
val=1;
#ifdef NCPFS_PARANOIA
else
printk(KERN_DEBUG "ncp_lookup_validate: found, but dirEntNum changed\n");
#endif
+ ncp_update_inode2(dentry->d_inode, &finfo.nw_info);
+ }
if (!val) ncp_invalid_dir_cache(dir);
finished:
@@ -617,6 +713,8 @@
int result;
if (ncp_single_volume(server)) {
+ struct dentry* dent;
+
result = -ENOENT;
str_upper(server->m.mounted_vol);
if (ncp_lookup_volume(server, server->m.mounted_vol,
@@ -627,6 +725,19 @@
goto out;
}
str_lower(server->root.finfo.i.entryName);
+ dent = server->root_dentry;
+ if (dent) {
+ struct inode* ino = dent->d_inode;
+ if (ino) {
+ NCP_FINFO(ino)->volNumber = server->root.finfo.i.volNumber;
+ NCP_FINFO(ino)->dirEntNum = server->root.finfo.i.dirEntNum;
+ NCP_FINFO(ino)->DosDirNum = server->root.finfo.i.DosDirNum;
+ } else {
+ DPRINTK(KERN_DEBUG "ncpfs: sb->root_dentry->d_inode == NULL!\n");
+ }
+ } else {
+ DPRINTK(KERN_DEBUG "ncpfs: sb->root_dentry == NULL!\n");
+ }
}
result = 0;
@@ -814,6 +925,7 @@
finfo.nw_info.access = O_RDWR;
error = ncp_instantiate(dir, dentry, &finfo);
} else {
+ if (result == 0x87) error = -ENAMETOOLONG;
DPRINTK(KERN_DEBUG "ncp_create: %s/%s failed\n",
dentry->d_parent->d_name.name, dentry->d_name.name);
}
@@ -904,8 +1016,7 @@
static int ncp_unlink(struct inode *dir, struct dentry *dentry)
{
struct inode *inode = dentry->d_inode;
- int error, result;
- __u8 _name[dentry->d_name.len + 1];
+ int error;
DPRINTK(KERN_DEBUG "ncp_unlink: unlinking %s/%s\n",
dentry->d_parent->d_name.name, dentry->d_name.name);
@@ -929,21 +1040,23 @@
ncp_make_closed(inode);
}
- strncpy(_name, dentry->d_name.name, dentry->d_name.len);
- _name[dentry->d_name.len] = '\0';
- if (!ncp_preserve_case(dir))
- {
- str_upper(_name);
+ error = ncp_del_file_or_subdir2(NCP_SERVER(dir), dentry);
+#ifdef CONFIG_NCPFS_STRONG
+ if (error == 0x9C && NCP_SERVER(dir)->m.flags & NCP_MOUNT_STRONG) { /* R/O */
+ error = ncp_force_unlink(dir, dentry);
}
- error = -EACCES;
- result = ncp_del_file_or_subdir(NCP_SERVER(dir), dir, _name);
- if (!result) {
+#endif
+ if (!error) {
DPRINTK(KERN_DEBUG "ncp: removed %s/%s\n",
dentry->d_parent->d_name.name, dentry->d_name.name);
ncp_invalid_dir_cache(dir);
d_delete(dentry);
- error = 0;
+ } else if (error == 0xFF) {
+ error = -ENOENT;
+ } else {
+ error = -EACCES;
}
+
out:
return error;
}
@@ -953,7 +1066,7 @@
{
int old_len = old_dentry->d_name.len;
int new_len = new_dentry->d_name.len;
- int error, result;
+ int error;
char _old_name[old_dentry->d_name.len + 1];
char _new_name[new_dentry->d_name.len + 1];
@@ -986,18 +1099,28 @@
str_upper(_new_name);
}
- error = -EACCES;
- result = ncp_ren_or_mov_file_or_subdir(NCP_SERVER(old_dir),
+ error = ncp_ren_or_mov_file_or_subdir(NCP_SERVER(old_dir),
old_dir, _old_name,
new_dir, _new_name);
- if (result == 0)
+#ifdef CONFIG_NCPFS_STRONG
+ if (error == 0x90 && NCP_SERVER(old_dir)->m.flags & NCP_MOUNT_STRONG) { /* RO */
+ error = ncp_force_rename(old_dir, old_dentry, _old_name, new_dir, new_dentry, _new_name);
+ }
+#endif
+ if (error == 0)
{
DPRINTK(KERN_DEBUG "ncp renamed %s -> %s.\n",
old_dentry->d_name.name,new_dentry->d_name.name);
ncp_invalid_dir_cache(old_dir);
ncp_invalid_dir_cache(new_dir);
d_move(old_dentry,new_dentry);
- error = 0;
+ } else {
+ if (error == 0x9E)
+ error = -ENAMETOOLONG;
+ else if (error == 0xFF)
+ error = -ENOENT;
+ else
+ error = -EACCES;
}
out:
return error;
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov