patch-1.3.71 linux/fs/ncpfs/dir.c
Next file: linux/fs/ncpfs/file.c
Previous file: linux/fs/exec.c
Back to the patch index
Back to the overall index
- Lines: 479
- Date:
Sat Mar 2 13:15:35 1996
- Orig file:
v1.3.70/linux/fs/ncpfs/dir.c
- Orig date:
Fri Feb 23 13:54:37 1996
diff -u --recursive --new-file v1.3.70/linux/fs/ncpfs/dir.c linux/fs/ncpfs/dir.c
@@ -1,7 +1,7 @@
/*
* dir.c
*
- * Copyright (C) 1995 by Volker Lendecke
+ * Copyright (C) 1995, 1996 by Volker Lendecke
*
*/
@@ -41,7 +41,7 @@
ncp_iget(struct inode *dir, struct nw_file_info *finfo);
static struct ncp_inode_info *
-ncp_find_inode(struct inode *dir, const char *name);
+ncp_find_dir_inode(struct inode *dir, const char *name);
static int
ncp_lookup(struct inode *dir, const char *__name,
@@ -123,6 +123,60 @@
};
+/* Here we encapsulate the inode number handling that depends upon the
+ * mount mode: When we mount a complete server, the memory address of
+ * the npc_inode_info is used as an inode. When only a single volume
+ * is mounted, then the DosDirNum is used as the inode number. As this
+ * is unique for the complete volume, this should enable the NFS
+ * exportability of a ncpfs-mounted volume.
+ */
+
+static inline int
+ncp_single_volume(struct ncp_server *server)
+{
+ return (server->m.mounted_vol[0] != '\0');
+}
+
+inline ino_t
+ncp_info_ino(struct ncp_server *server, struct ncp_inode_info *info)
+{
+ return ncp_single_volume(server)
+ ? info->finfo.i.DosDirNum : (ino_t)info;
+}
+
+static inline int
+ncp_is_server_root(struct inode *inode)
+{
+ struct ncp_server *s = NCP_SERVER(inode);
+
+ return ( (!ncp_single_volume(s))
+ && (inode->i_ino == ncp_info_ino(s, &(s->root))));
+}
+
+struct ncp_inode_info *
+ncp_find_inode(struct inode *inode)
+{
+ struct ncp_server *server = NCP_SERVER(inode);
+ struct ncp_inode_info *root = &(server->root);
+ struct ncp_inode_info *this = root;
+
+ ino_t ino = inode->i_ino;
+
+ do
+ {
+ if (ino == ncp_info_ino(server, this))
+ {
+ return this;
+ }
+ this = this->next;
+ }
+ while (this != root);
+
+ return NULL;
+}
+
+
+
static int
ncp_dir_read(struct inode *inode, struct file *filp, char *buf, int count)
{
@@ -133,6 +187,7 @@
all inodes that are in memory. That's why it's enough to index the
directory cache by the inode number. */
+static kdev_t c_dev = 0;
static unsigned long c_ino = 0;
static int c_size;
static int c_seen_eof;
@@ -147,7 +202,7 @@
int index = 0;
struct ncp_dirent *entry = NULL;
struct ncp_server *server = NCP_SERVER(inode);
- struct ncp_inode_info *dir = (struct ncp_inode_info *)(inode->i_ino);
+ struct ncp_inode_info *dir = NCP_INOP(inode);
DDPRINTK("ncp_readdir: filp->f_pos = %d\n", (int)filp->f_pos);
DDPRINTK("ncp_readdir: inode->i_ino = %ld, c_ino = %ld\n",
@@ -159,7 +214,7 @@
return -EBADF;
}
- if (!ncp_conn_valid(NCP_SERVER(inode)))
+ if (!ncp_conn_valid(server))
{
return -EIO;
}
@@ -177,8 +232,9 @@
if (filp->f_pos == 0)
{
- ncp_invalid_dir_cache(inode->i_ino);
- if (filldir(dirent,".",1, filp->f_pos, (int)dir) < 0)
+ ncp_invalid_dir_cache(inode);
+ if (filldir(dirent,".",1, filp->f_pos,
+ ncp_info_ino(server, dir)) < 0)
{
return 0;
}
@@ -187,14 +243,15 @@
if (filp->f_pos == 1)
{
- if (filldir(dirent,"..",2, filp->f_pos, (int)(dir->dir)) < 0)
+ if (filldir(dirent,"..",2, filp->f_pos,
+ ncp_info_ino(server, dir->dir)) < 0)
{
return 0;
}
filp->f_pos += 1;
}
- if (inode->i_ino == c_ino)
+ if ((inode->i_dev == c_dev) && (inode->i_ino == c_ino))
{
for (i = 0; i < c_size; i++)
{
@@ -216,7 +273,7 @@
{
DDPRINTK("ncp_readdir: Not found in cache.\n");
- if (inode->i_ino == (int)&(server->root))
+ if (ncp_is_server_root(inode))
{
result = ncp_read_volume_list(server, filp->f_pos,
NCP_READDIR_CACHE_SIZE);
@@ -233,6 +290,7 @@
if (result < 0)
{
+ c_dev = 0;
c_ino = 0;
return result;
}
@@ -240,6 +298,7 @@
if (result > 0)
{
c_seen_eof = (result < NCP_READDIR_CACHE_SIZE);
+ c_dev = inode->i_dev;
c_ino = inode->i_ino;
c_size = result;
entry = c_entry;
@@ -264,29 +323,41 @@
/* We found it. For getwd(), we have to return the
correct inode in d_ino if the inode is currently in
use. Otherwise the inode number does not
- matter. (You can argue a lot about this..) */
+ matter. (You can argue a lot about this..) */
- struct ncp_inode_info *ino_info;
- ino_info = ncp_find_inode(inode, entry->i.entryName);
+ ino_t ino;
- /* Some programs seem to be confused about a zero
- inode number, so we set it to one. Thanks to
- Gordon Chaffee for this one. */
- if (ino_info == NULL)
+ if (ncp_single_volume(server))
{
- ino_info = (struct ncp_inode_info *) 1;
- }
+ ino = (ino_t)(entry->i.DosDirNum);
+ }
+ else
+ {
+ struct ncp_inode_info *ino_info;
+ ino_info = ncp_find_dir_inode(inode,
+ entry->i.entryName);
+
+ /* Some programs seem to be confused about a
+ * zero inode number, so we set it to one.
+ * Thanks to Gordon Chaffee for this one. */
+ if (ino_info == NULL)
+ {
+ ino_info = (struct ncp_inode_info *) 1;
+ }
+ ino = (ino_t)(ino_info);
+ }
DDPRINTK("ncp_readdir: entry->path= %s\n", entry->i.entryName);
DDPRINTK("ncp_readdir: entry->f_pos = %ld\n", entry->f_pos);
if (filldir(dirent, entry->i.entryName, entry->i.nameLen,
- entry->f_pos, (ino_t)ino_info) < 0)
+ entry->f_pos, ino) < 0)
{
break;
}
- if ( (inode->i_ino != c_ino)
+ if ( (inode->i_dev != c_dev)
+ || (inode->i_ino != c_ino)
|| (entry->f_pos != filp->f_pos))
{
/* Someone has destroyed the cache while we slept
@@ -341,9 +412,9 @@
DPRINTK("ncp_read_volumes: found vol: %s\n",
info.volume_name);
- if (ncp_do_lookup(server, NULL,
- info.volume_name,
- &(entry->i)) != 0)
+ if (ncp_lookup_volume(server,
+ info.volume_name,
+ &(entry->i)) != 0)
{
printk("ncpfs: could not lookup vol "
"%s\n", info.volume_name);
@@ -426,15 +497,17 @@
void
ncp_init_dir_cache(void)
{
+ c_dev = 0;
c_ino = 0;
c_entry = NULL;
}
void
-ncp_invalid_dir_cache(unsigned long ino)
+ncp_invalid_dir_cache(struct inode *ino)
{
- if (ino == c_ino)
+ if ((ino->i_dev == c_dev) && (ino->i_ino == c_ino))
{
+ c_dev = 0;
c_ino = 0;
c_seen_eof = 0;
}
@@ -505,7 +578,8 @@
root->next->prev = new_inode_info;
root->next = new_inode_info;
- if (!(inode = iget(dir->i_sb, (int)new_inode_info)))
+ if (!(inode = iget(dir->i_sb, ncp_info_ino(NCP_SERVER(dir),
+ new_inode_info))))
{
printk("ncp_iget: iget failed!");
return NULL;
@@ -556,12 +630,13 @@
root->finfo.opened = 0;
i->attributes = aDIR;
i->dataStreamSize = 1024;
+ i->DosDirNum = 0;
i->volNumber = NCP_NUMBER_OF_VOLUMES+1; /* illegal volnum */
ncp_date_unix2dos(0, &(i->creationTime), &(i->creationDate));
ncp_date_unix2dos(0, &(i->modifyTime), &(i->modifyDate));
ncp_date_unix2dos(0, &dummy, &(i->lastAccessDate));
i->nameLen = 0;
- i->entryName[0] = '\0';
+ i->entryName[0] = '\0';
root->state = NCP_INODE_LOOKED_UP;
root->nused = 1;
@@ -570,6 +645,25 @@
return;
}
+int
+ncp_conn_logged_in(struct ncp_server *server)
+{
+ if (server->m.mounted_vol[0] == '\0')
+ {
+ return 0;
+ }
+
+ str_upper(server->m.mounted_vol);
+ if (ncp_lookup_volume(server, server->m.mounted_vol,
+ &(server->root.finfo.i)) != 0)
+ {
+ return -ENOENT;
+ }
+ str_lower(server->root.finfo.i.entryName);
+
+ return 0;
+}
+
void
ncp_free_all_inodes(struct ncp_server *server)
{
@@ -600,7 +694,7 @@
complete linear search through the inodes belonging to this
filesystem. This has to be fixed. */
static struct ncp_inode_info *
-ncp_find_inode(struct inode *dir, const char *name)
+ncp_find_dir_inode(struct inode *dir, const char *name)
{
struct ncp_server *server = NCP_SERVER(dir);
struct nw_info_struct *dir_info = NCP_ISTRUCT(dir);
@@ -645,15 +739,16 @@
iput(dir);
return -ENOENT;
}
- if (!ncp_conn_valid(NCP_SERVER(dir)))
+
+ server = NCP_SERVER(dir);
+
+ if (!ncp_conn_valid(server))
{
iput(dir);
return -EIO;
}
- DDPRINTK("ncp_lookup: %s, len %d\n", __name, len);
-
- server = NCP_SERVER(dir);
+ DPRINTK("ncp_lookup: %s, len %d\n", __name, len);
/* Fast cheat for . */
if (len == 0 || (len == 1 && __name[0] == '.'))
@@ -672,7 +767,7 @@
parent->state = NCP_INODE_LOOKED_UP;
}
- *result = iget(dir->i_sb, (int)parent);
+ *result = iget(dir->i_sb, ncp_info_ino(server, parent));
iput(dir);
if (*result == 0)
{
@@ -686,7 +781,7 @@
memcpy(name, __name, len);
name[len] = 0;
- result_info = ncp_find_inode(dir, name);
+ result_info = ncp_find_dir_inode(dir, name);
if (result_info != 0)
{
@@ -698,7 +793,7 @@
/* Here we convert the inode_info address into an
inode number */
- *result = iget(dir->i_sb, (int)result_info);
+ *result = iget(dir->i_sb, ncp_info_ino(server, result_info));
iput(dir);
if (*result == NULL)
@@ -713,8 +808,8 @@
server. */
found_in_cache = 0;
-
- if (dir->i_ino == c_ino)
+
+ if ((dir->i_dev == c_dev) && (dir->i_ino == c_ino))
{
int first = c_last_returned_index;
int i;
@@ -723,7 +818,7 @@
do
{
DDPRINTK("ncp_lookup: trying index: %d, name: %s\n",
- i, c_entry[i].i.entryName);
+ i, c_entry[i].i.entryName);
if (strcmp(c_entry[i].i.entryName, name) == 0)
{
@@ -739,15 +834,24 @@
if (found_in_cache == 0)
{
+ int res;
str_upper(name);
DDPRINTK("ncp_lookup: do_lookup on %s/%s\n",
NCP_ISTRUCT(dir)->entryName, name);
- if (ncp_do_lookup(server,
- dir->i_ino == (int)&(NCP_SERVER(dir)->root)
- ? NULL : NCP_ISTRUCT(dir),
- name, &(finfo.i)) != 0)
+ if (ncp_is_server_root(dir))
+ {
+ res = ncp_lookup_volume(server, name, &(finfo.i));
+ }
+ else
+ {
+ res = ncp_obtain_info(server,
+ NCP_ISTRUCT(dir)->volNumber,
+ NCP_ISTRUCT(dir)->DosDirNum,
+ name, &(finfo.i));
+ }
+ if (res != 0)
{
iput(dir);
return -ENOENT;
@@ -803,7 +907,7 @@
return -EACCES;
}
- ncp_invalid_dir_cache(dir->i_ino);
+ ncp_invalid_dir_cache(dir);
str_lower(finfo.i.entryName);
finfo.access = O_RDWR;
@@ -860,7 +964,7 @@
else
{
error = 0;
- ncp_invalid_dir_cache(dir->i_ino);
+ ncp_invalid_dir_cache(dir);
}
iput(dir);
@@ -884,7 +988,7 @@
iput(dir);
return -EIO;
}
- if (ncp_find_inode(dir, name) != NULL)
+ if (ncp_find_dir_inode(dir, name) != NULL)
{
iput(dir);
error = -EBUSY;
@@ -900,7 +1004,7 @@
NCP_ISTRUCT(dir),
_name)) == 0)
{
- ncp_invalid_dir_cache(dir->i_ino);
+ ncp_invalid_dir_cache(dir);
}
else
{
@@ -928,7 +1032,7 @@
iput(dir);
return -EIO;
}
- if (ncp_find_inode(dir, name) != NULL)
+ if (ncp_find_dir_inode(dir, name) != NULL)
{
iput(dir);
error = -EBUSY;
@@ -943,7 +1047,7 @@
NCP_ISTRUCT(dir),
_name)) == 0)
{
- ncp_invalid_dir_cache(dir->i_ino);
+ ncp_invalid_dir_cache(dir);
}
else
{
@@ -982,8 +1086,8 @@
goto finished;
}
- if ( (ncp_find_inode(old_dir, old_name) != NULL)
- || (ncp_find_inode(new_dir, new_name) != NULL))
+ if ( (ncp_find_dir_inode(old_dir, old_name) != NULL)
+ || (ncp_find_dir_inode(new_dir, new_name) != NULL))
{
res = -EBUSY;
goto finished;
@@ -1003,8 +1107,8 @@
if (res == 0)
{
- ncp_invalid_dir_cache(old_dir->i_ino);
- ncp_invalid_dir_cache(new_dir->i_ino);
+ ncp_invalid_dir_cache(old_dir);
+ ncp_invalid_dir_cache(new_dir);
}
else
{
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov
with Sam's (original) version of this