summaryrefslogtreecommitdiffstats
path: root/fs/ncpfs/dir.c
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-02-04 07:40:19 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-02-04 07:40:19 +0000
commit33263fc5f9ac8e8cb2b22d06af3ce5ac1dd815e4 (patch)
tree2d1b86a40bef0958a68cf1a2eafbeb0667a70543 /fs/ncpfs/dir.c
parent216f5f51aa02f8b113aa620ebc14a9631a217a00 (diff)
Merge with Linux 2.3.32.
Diffstat (limited to 'fs/ncpfs/dir.c')
-rw-r--r--fs/ncpfs/dir.c288
1 files changed, 125 insertions, 163 deletions
diff --git a/fs/ncpfs/dir.c b/fs/ncpfs/dir.c
index 4ed7a9abe..31e414ebb 100644
--- a/fs/ncpfs/dir.c
+++ b/fs/ncpfs/dir.c
@@ -4,7 +4,7 @@
* Copyright (C) 1995, 1996 by Volker Lendecke
* Modified for big endian by J.F. Chadima and David S. Miller
* Modified 1997 Peter Waltenberg, Bill Hawes, David Woodhouse for 2.1 dcache
- * Modified 1998 Wolfram Pienkoss for NLS
+ * Modified 1998, 1999 Wolfram Pienkoss for NLS
* Modified 1999 Wolfram Pienkoss for directory caching
*
*/
@@ -81,10 +81,8 @@ struct inode_operations ncp_dir_inode_operations =
NULL, /* get_block */
NULL, /* readpage */
NULL, /* writepage */
- NULL, /* flushpage */
NULL, /* truncate */
NULL, /* permission */
- NULL, /* smap */
NULL, /* revalidate */
};
@@ -112,25 +110,23 @@ struct dentry_operations ncp_dentry_operations =
/*
- * XXX: It would be better to use the tolower from linux/ctype.h,
- * but _ctype is needed and it is not exported.
- */
-#define tolower(c) (((c) >= 'A' && (c) <= 'Z') ? (c)-('A'-'a') : (c))
-
-/*
* Note: leave the hash unchanged if the directory
* is case-sensitive.
*/
static int
ncp_hash_dentry(struct dentry *dentry, struct qstr *this)
{
+ struct nls_table *t;
unsigned long hash;
int i;
+ t = NCP_IO_TABLE(dentry);
+
if (!ncp_case_sensitive(dentry->d_inode)) {
hash = init_name_hash();
for (i=0; i<this->len ; i++)
- hash = partial_name_hash(tolower(this->name[i]),hash);
+ hash = partial_name_hash(ncp_tolower(t, this->name[i]),
+ hash);
this->hash = end_name_hash(hash);
}
return 0;
@@ -139,18 +135,13 @@ ncp_hash_dentry(struct dentry *dentry, struct qstr *this)
static int
ncp_compare_dentry(struct dentry *dentry, struct qstr *a, struct qstr *b)
{
- int i;
-
- if (a->len != b->len) return 1;
+ if (a->len != b->len)
+ return 1;
if (ncp_case_sensitive(dentry->d_inode))
- return strncmp(a->name, b->name, a->len);
-
- for (i=0; i<a->len; i++)
- if (tolower(a->name[i]) != tolower(b->name[i]))
- return 1;
+ return strncmp(a->name, b->name, a->len);
- return 0;
+ return ncp_strnicmp(NCP_IO_TABLE(dentry), a->name, b->name, a->len);
}
/*
@@ -303,10 +294,9 @@ ncp_lookup_validate(struct dentry * dentry, int flags)
{
struct ncp_server *server;
struct inode *dir = dentry->d_parent->d_inode;
- int res, val = 0;
- int len = dentry->d_name.len;
struct ncp_entry_info finfo;
- __u8 __name[dentry->d_name.len + 1];
+ int res, val = 0, len = dentry->d_name.len + 1;
+ __u8 __name[len];
if (!dentry->d_inode || !dir)
goto finished;
@@ -326,79 +316,42 @@ ncp_lookup_validate(struct dentry * dentry, int flags)
if (val)
goto finished;
- PPRINTK("ncp_lookup_validate: %s/%s not valid, age=%ld\n",
+ DDPRINTK("ncp_lookup_validate: %s/%s not valid, age=%ld, server lookup\n",
dentry->d_parent->d_name.name, dentry->d_name.name,
NCP_GET_AGE(dentry));
- memcpy(__name, dentry->d_name.name, len);
- __name[len] = '\0';
-
- PPRINTK("ncp_lookup_validate: %s, len %d\n", __name, len);
- PPRINTK("ncp_lookup_validate: server lookup for %s/%s\n",
- dentry->d_parent->d_name.name, __name);
-
if (ncp_is_server_root(dir)) {
- io2vol(server, __name, 1);
- res = ncp_lookup_volume(server, __name, &(finfo.i));
+ res = ncp_io2vol(server, __name, &len, dentry->d_name.name,
+ len-1, 1);
+ if (!res)
+ res = ncp_lookup_volume(server, __name, &(finfo.i));
} else {
- io2vol(server, __name, !ncp_preserve_case(dir));
- res = ncp_obtain_info(server, dir, __name, &(finfo.i));
+ res = ncp_io2vol(server, __name, &len, dentry->d_name.name,
+ len-1, !ncp_preserve_case(dir));
+ if (!res)
+ res = ncp_obtain_info(server, dir, __name, &(finfo.i));
}
- PPRINTK("ncp_lookup_validate: looked for %s/%s, res=%d\n",
+ DDPRINTK("ncp_lookup_validate: looked for %s/%s, res=%d\n",
dentry->d_parent->d_name.name, __name, res);
/*
* 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 (finfo.i.dirEntNum == NCP_FINFO(dentry->d_inode)->dirEntNum)
+ if (finfo.i.dirEntNum == NCP_FINFO(dentry->d_inode)->dirEntNum) {
+ ncp_new_dentry(dentry);
val=1;
- else
- PPRINTK("ncp_lookup_validate: found, but dirEntNum changed\n");
+ } else
+ DDPRINTK("ncp_lookup_validate: found, but dirEntNum changed\n");
- vol2io(server, finfo.i.entryName,
- !ncp_preserve_entry_case(dir, finfo.i.NSCreator));
ncp_update_inode2(dentry->d_inode, &finfo);
- if (val)
- ncp_new_dentry(dentry);
}
finished:
- PPRINTK("ncp_lookup_validate: result=%d\n", val);
+ DDPRINTK("ncp_lookup_validate: result=%d\n", val);
return val;
}
-static struct page *
-ncp_get_cache_page(struct inode *inode, unsigned long offset, int used)
-{
- struct address_space *i_data = &inode->i_data;
- struct page *new_page, *page, **hash;
-
- hash = page_hash(i_data, offset);
-
- page = __find_lock_page(i_data, offset, hash);
- if (used || page)
- return page;
-
- new_page = page_cache_alloc();
- if (!new_page)
- return NULL;
-
- for (;;) {
- page = new_page;
- if (!add_to_page_cache_unique(page, i_data, offset, hash))
- break;
- page_cache_release(page);
- page = __find_lock_page(i_data, offset, hash);
- if (page) {
- page_cache_free(new_page);
- break;
- }
- }
-
- return page;
-}
-
/* most parts from nfsd_d_validate() */
static int
ncp_d_validate(struct dentry *dentry)
@@ -458,11 +411,12 @@ ncp_dget_fpos(struct dentry *dentry, struct dentry *parent, unsigned long fpos)
goto out;
next = next->next;
}
- dent = NULL;
+ return NULL;
+
out:
- if (dent)
- if (dent->d_inode)
- return dget(dent);
+ if (dent->d_inode)
+ return dget(dent);
+
return NULL;
}
@@ -472,8 +426,7 @@ static time_t ncp_obtain_mtime(struct dentry *dentry)
struct ncp_server *server = NCP_SERVER(inode);
struct nw_info_struct i;
- if (!ncp_conn_valid(server) ||
- ncp_is_server_root(inode))
+ if (!ncp_conn_valid(server) || ncp_is_server_root(inode))
return 0;
if (ncp_obtain_info(server, inode, NULL, &i))
@@ -518,11 +471,11 @@ static int ncp_readdir(struct file *filp, void *dirent, filldir_t filldir)
filp->f_pos = 2;
}
- page = ncp_get_cache_page(inode, 0, 0);
+ page = grab_cache_page(&inode->i_data, 0);
if (!page)
goto read_really;
- ctl.cache = cache = (union ncp_dir_cache *) page_address(page);
+ ctl.cache = cache = (union ncp_dir_cache *) kmap(page);
ctl.head = cache->head;
if (!Page_Uptodate(page) || !ctl.head.eof)
@@ -547,13 +500,12 @@ static int ncp_readdir(struct file *filp, void *dirent, filldir_t filldir)
for (;;) {
if (ctl.ofs != 0) {
- ctl.page = ncp_get_cache_page(inode, ctl.ofs, 1);
+ ctl.page = find_lock_page(&inode->i_data, ctl.ofs);
if (!ctl.page)
goto invalid_cache;
+ ctl.cache = (union ncp_dir_cache *) kmap(ctl.page);
if (!Page_Uptodate(ctl.page))
goto invalid_cache;
- ctl.cache = (union ncp_dir_cache *)
- page_address(ctl.page);
}
while (ctl.idx < NCP_DIRCACHE_SIZE) {
struct dentry *dent;
@@ -575,6 +527,7 @@ static int ncp_readdir(struct file *filp, void *dirent, filldir_t filldir)
goto finished;
}
if (ctl.page) {
+ kunmap(ctl.page);
SetPageUptodate(ctl.page);
UnlockPage(ctl.page);
page_cache_release(ctl.page);
@@ -585,6 +538,7 @@ static int ncp_readdir(struct file *filp, void *dirent, filldir_t filldir)
}
invalid_cache:
if (ctl.page) {
+ kunmap(ctl.page);
UnlockPage(ctl.page);
page_cache_release(ctl.page);
ctl.page = NULL;
@@ -615,11 +569,13 @@ read_really:
finished:
if (page) {
cache->head = ctl.head;
+ kunmap(page);
SetPageUptodate(page);
UnlockPage(page);
page_cache_release(page);
}
if (ctl.page) {
+ kunmap(ctl.page);
SetPageUptodate(ctl.page);
UnlockPage(ctl.page);
page_cache_release(ctl.page);
@@ -634,17 +590,19 @@ ncp_fill_cache(struct file *filp, void *dirent, filldir_t filldir,
{
struct dentry *newdent, *dentry = filp->f_dentry;
struct inode *newino, *inode = dentry->d_inode;
- struct ncp_server *server = NCP_SERVER(inode);
struct ncp_cache_control ctl = *ctrl;
struct qstr qname;
- ino_t ino = 0;
int valid = 0;
+ ino_t ino = 0;
+ __u8 __name[256];
- vol2io(server, entry->i.entryName,
- !ncp_preserve_entry_case(inode, entry->i.NSCreator));
+ qname.len = 256;
+ if (ncp_vol2io(NCP_SERVER(inode), __name, &qname.len,
+ entry->i.entryName, entry->i.nameLen,
+ !ncp_preserve_entry_case(inode, entry->i.NSCreator)))
+ return 1; /* I'm not sure */
- qname.name = entry->i.entryName;
- qname.len = entry->i.nameLen;
+ qname.name = __name;
qname.hash = full_name_hash(qname.name, qname.len);
if (dentry->d_op && dentry->d_op->d_hash)
@@ -680,6 +638,7 @@ ncp_fill_cache(struct file *filp, void *dirent, filldir_t filldir,
if (ctl.idx >= NCP_DIRCACHE_SIZE) {
if (ctl.page) {
+ kunmap(ctl.page);
SetPageUptodate(ctl.page);
UnlockPage(ctl.page);
page_cache_release(ctl.page);
@@ -687,10 +646,9 @@ ncp_fill_cache(struct file *filp, void *dirent, filldir_t filldir,
ctl.cache = NULL;
ctl.idx -= NCP_DIRCACHE_SIZE;
ctl.ofs += 1;
- ctl.page = ncp_get_cache_page(inode, ctl.ofs, 0);
+ ctl.page = grab_cache_page(&inode->i_data, ctl.ofs);
if (ctl.page)
- ctl.cache = (union ncp_dir_cache *)
- page_address(ctl.page);
+ ctl.cache = (union ncp_dir_cache *) kmap(ctl.page);
}
if (ctl.cache) {
ctl.cache->dentry[ctl.idx] = newdent;
@@ -705,8 +663,8 @@ end_advance:
ino = find_inode_number(dentry, &qname);
if (!ino)
ino = iunique(inode->i_sb, 2);
- ctl.filled = filldir(dirent, entry->i.entryName,
- entry->i.nameLen, filp->f_pos, ino);
+ ctl.filled = filldir(dirent, qname.name, qname.len,
+ filp->f_pos, ino);
if (!ctl.filled)
filp->f_pos += 1;
}
@@ -751,8 +709,9 @@ ncp_read_volume_list(struct file *filp, void *dirent, filldir_t filldir,
}
}
-static void ncp_do_readdir(struct file *filp, void *dirent, filldir_t filldir,
- struct ncp_cache_control *ctl)
+static void
+ncp_do_readdir(struct file *filp, void *dirent, filldir_t filldir,
+ struct ncp_cache_control *ctl)
{
struct dentry *dentry = filp->f_dentry;
struct inode *dir = dentry->d_inode;
@@ -788,19 +747,21 @@ int ncp_conn_logged_in(struct super_block *sb)
{
struct ncp_server* server = NCP_SBP(sb);
struct nw_info_struct i;
- int result;
+ int result, len = strlen(server->m.mounted_vol) + 1;
+ __u8 __name[len];
if (ncp_single_volume(server)) {
struct dentry* dent;
result = -ENOENT;
- io2vol(server, server->m.mounted_vol, 1);
- if (ncp_lookup_volume(server, server->m.mounted_vol, &i)) {
+ if (ncp_io2vol(server, __name, &len, server->m.mounted_vol,
+ len-1, 1))
+ goto out;
+ if (ncp_lookup_volume(server, __name, &i)) {
PPRINTK("ncp_conn_logged_in: %s not found\n",
server->m.mounted_vol);
goto out;
}
- vol2io(server, i.entryName, 1);
dent = sb->s_root;
if (dent) {
struct inode* ino = dent->d_inode;
@@ -823,29 +784,29 @@ out:
static struct dentry *ncp_lookup(struct inode *dir, struct dentry *dentry)
{
- struct ncp_server *server;
+ struct ncp_server *server = NCP_SERVER(dir);
struct inode *inode = NULL;
- int error, res, len = dentry->d_name.len;
struct ncp_entry_info finfo;
- __u8 __name[dentry->d_name.len + 1];
-
- server = NCP_SERVER(dir);
+ int error, res, len = dentry->d_name.len + 1;
+ __u8 __name[len];
error = -EIO;
if (!ncp_conn_valid(server))
goto finished;
- memcpy(__name, dentry->d_name.name, len);
- __name[len] = '\0';
- PPRINTK("ncp_lookup: %s, len %d\n", __name, len);
PPRINTK("ncp_lookup: server lookup for %s/%s\n",
- dentry->d_parent->d_name.name, __name);
+ dentry->d_parent->d_name.name, dentry->d_name.name);
+
if (ncp_is_server_root(dir)) {
- io2vol(server, __name, 1);
- res = ncp_lookup_volume(server, __name, &(finfo.i));
+ res = ncp_io2vol(server, __name, &len, dentry->d_name.name,
+ len-1, 1);
+ if (!res)
+ res = ncp_lookup_volume(server, __name, &(finfo.i));
} else {
- io2vol(server, __name, !ncp_preserve_case(dir));
- res = ncp_obtain_info(server, dir, __name, &(finfo.i));
+ res = ncp_io2vol(server, __name, &len, dentry->d_name.name,
+ len-1, !ncp_preserve_case(dir));
+ if (!res)
+ res = ncp_obtain_info(server, dir, __name, &(finfo.i));
}
PPRINTK("ncp_lookup: looked for %s/%s, res=%d\n",
dentry->d_parent->d_name.name, __name, res);
@@ -855,9 +816,6 @@ static struct dentry *ncp_lookup(struct inode *dir, struct dentry *dentry)
if (res)
goto add_entry;
- vol2io(server, finfo.i.entryName,
- !ncp_preserve_entry_case(dir, finfo.i.NSCreator));
-
/*
* Create an inode for the entry.
*/
@@ -867,10 +825,10 @@ static struct dentry *ncp_lookup(struct inode *dir, struct dentry *dentry)
inode = ncp_iget(dir->i_sb, &finfo);
if (inode) {
+ ncp_new_dentry(dentry);
add_entry:
dentry->d_op = &ncp_dentry_operations;
d_add(dentry, inode);
- ncp_new_dentry(dentry);
error = 0;
}
@@ -907,10 +865,10 @@ out_close:
int ncp_create_new(struct inode *dir, struct dentry *dentry, int mode,
int attributes)
{
- int error, result;
- struct ncp_entry_info finfo;
struct ncp_server *server = NCP_SERVER(dir);
- __u8 _name[dentry->d_name.len + 1];
+ struct ncp_entry_info finfo;
+ int error, result, len = dentry->d_name.len + 1;
+ __u8 __name[len];
PPRINTK("ncp_create_new: creating %s/%s, mode=%x\n",
dentry->d_parent->d_name.name, dentry->d_name.name, mode);
@@ -919,16 +877,15 @@ int ncp_create_new(struct inode *dir, struct dentry *dentry, int mode,
goto out;
ncp_age_dentry(server, dentry);
-
- memcpy(_name, dentry->d_name.name, dentry->d_name.len);
- _name[dentry->d_name.len] = '\0';
-
- io2vol(server, _name, !ncp_preserve_case(dir));
+ error = ncp_io2vol(server, __name, &len, dentry->d_name.name,
+ len-1, !ncp_preserve_case(dir));
+ if (error)
+ goto out;
error = -EACCES;
- result = ncp_open_create_file_or_subdir(server, dir, _name,
- OC_MODE_CREATE | OC_MODE_OPEN | OC_MODE_REPLACE,
- attributes, AR_READ | AR_WRITE, &finfo);
+ result = ncp_open_create_file_or_subdir(server, dir, __name,
+ OC_MODE_CREATE | OC_MODE_OPEN | OC_MODE_REPLACE,
+ attributes, AR_READ | AR_WRITE, &finfo);
if (!result) {
finfo.access = O_RDWR;
error = ncp_instantiate(dir, dentry, &finfo);
@@ -949,10 +906,10 @@ static int ncp_create(struct inode *dir, struct dentry *dentry, int mode)
static int ncp_mkdir(struct inode *dir, struct dentry *dentry, int mode)
{
- int error;
struct ncp_entry_info finfo;
struct ncp_server *server = NCP_SERVER(dir);
- __u8 _name[dentry->d_name.len + 1];
+ int error, len = dentry->d_name.len + 1;
+ __u8 __name[len];
DPRINTK("ncp_mkdir: making %s/%s\n",
dentry->d_parent->d_name.name, dentry->d_name.name);
@@ -961,13 +918,13 @@ static int ncp_mkdir(struct inode *dir, struct dentry *dentry, int mode)
goto out;
ncp_age_dentry(server, dentry);
-
- memcpy(_name, dentry->d_name.name, dentry->d_name.len);
- _name[dentry->d_name.len] = '\0';
- io2vol(server, _name, !ncp_preserve_case(dir));
+ error = ncp_io2vol(server, __name, &len, dentry->d_name.name,
+ len-1, !ncp_preserve_case(dir));
+ if (error)
+ goto out;
error = -EACCES;
- if (ncp_open_create_file_or_subdir(server, dir, _name,
+ if (ncp_open_create_file_or_subdir(server, dir, __name,
OC_MODE_CREATE, aDIR, 0xffff,
&finfo) == 0)
{
@@ -979,9 +936,9 @@ out:
static int ncp_rmdir(struct inode *dir, struct dentry *dentry)
{
- int error, result;
struct ncp_server *server = NCP_SERVER(dir);
- __u8 _name[dentry->d_name.len + 1];
+ int error, result, len = dentry->d_name.len + 1;
+ __u8 __name[len];
DPRINTK("ncp_rmdir: removing %s/%s\n",
dentry->d_parent->d_name.name, dentry->d_name.name);
@@ -994,11 +951,12 @@ static int ncp_rmdir(struct inode *dir, struct dentry *dentry)
if (!list_empty(&dentry->d_hash))
goto out;
- memcpy(_name, dentry->d_name.name, dentry->d_name.len);
- _name[dentry->d_name.len] = '\0';
-
- io2vol(server, _name, !ncp_preserve_case(dir));
- result = ncp_del_file_or_subdir(server, dir, _name);
+ error = ncp_io2vol(server, __name, &len, dentry->d_name.name,
+ len-1, !ncp_preserve_case(dir));
+ if (error)
+ goto out;
+
+ result = ncp_del_file_or_subdir(server, dir, __name);
switch (result) {
case 0x00:
error = 0;
@@ -1091,38 +1049,42 @@ out:
static int ncp_rename(struct inode *old_dir, struct dentry *old_dentry,
struct inode *new_dir, struct dentry *new_dentry)
{
- int old_len = old_dentry->d_name.len;
- int new_len = new_dentry->d_name.len;
+ struct ncp_server *server = NCP_SERVER(old_dir);
int error;
- char _old_name[old_dentry->d_name.len + 1];
- char _new_name[new_dentry->d_name.len + 1];
+ int old_len = old_dentry->d_name.len + 1;
+ int new_len = new_dentry->d_name.len + 1;
+ __u8 __old_name[old_len], __new_name[new_len];
DPRINTK("ncp_rename: %s/%s to %s/%s\n",
old_dentry->d_parent->d_name.name, old_dentry->d_name.name,
new_dentry->d_parent->d_name.name, new_dentry->d_name.name);
error = -EIO;
- if (!ncp_conn_valid(NCP_SERVER(old_dir)))
+ if (!ncp_conn_valid(server))
goto out;
- ncp_age_dentry(NCP_SERVER(old_dir), old_dentry);
- ncp_age_dentry(NCP_SERVER(new_dir), new_dentry);
+ ncp_age_dentry(server, old_dentry);
+ ncp_age_dentry(server, new_dentry);
- memcpy(_old_name, old_dentry->d_name.name, old_len);
- _old_name[old_len] = '\0';
- io2vol(NCP_SERVER(old_dir), _old_name, !ncp_preserve_case(old_dir));
+ error = ncp_io2vol(server, __old_name, &old_len,
+ old_dentry->d_name.name, old_len-1,
+ !ncp_preserve_case(old_dir));
+ if (error)
+ goto out;
- memcpy(_new_name, new_dentry->d_name.name, new_len);
- _new_name[new_len] = '\0';
- io2vol(NCP_SERVER(new_dir), _new_name, !ncp_preserve_case(new_dir));
+ error = ncp_io2vol(server, __new_name, &new_len,
+ new_dentry->d_name.name, new_len-1,
+ !ncp_preserve_case(new_dir));
+ if (error)
+ goto out;
- error = ncp_ren_or_mov_file_or_subdir(NCP_SERVER(old_dir),
- old_dir, _old_name,
- new_dir, _new_name);
+ error = ncp_ren_or_mov_file_or_subdir(server, old_dir, __old_name,
+ new_dir, __new_name);
#ifdef CONFIG_NCPFS_STRONG
- if ((error == 0x90 || error == -EACCES) && 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);
+ if ((error == 0x90 || error == -EACCES) &&
+ server->m.flags & NCP_MOUNT_STRONG) { /* RO */
+ error = ncp_force_rename(old_dir, old_dentry, __old_name,
+ new_dir, new_dentry, __new_name);
}
#endif
switch (error) {