diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2000-02-04 07:40:19 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2000-02-04 07:40:19 +0000 |
commit | 33263fc5f9ac8e8cb2b22d06af3ce5ac1dd815e4 (patch) | |
tree | 2d1b86a40bef0958a68cf1a2eafbeb0667a70543 /fs/ncpfs/dir.c | |
parent | 216f5f51aa02f8b113aa620ebc14a9631a217a00 (diff) |
Merge with Linux 2.3.32.
Diffstat (limited to 'fs/ncpfs/dir.c')
-rw-r--r-- | fs/ncpfs/dir.c | 288 |
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) { |