From 33263fc5f9ac8e8cb2b22d06af3ce5ac1dd815e4 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Fri, 4 Feb 2000 07:40:19 +0000 Subject: Merge with Linux 2.3.32. --- fs/ncpfs/Config.in | 6 +- fs/ncpfs/dir.c | 288 ++++++++++++++++++++--------------------------- fs/ncpfs/file.c | 2 - fs/ncpfs/inode.c | 17 ++- fs/ncpfs/ioctl.c | 80 +++++++------ fs/ncpfs/mmap.c | 6 +- fs/ncpfs/ncplib_kernel.c | 222 ++++++++++++++++++++++++++++++++++++ fs/ncpfs/ncplib_kernel.h | 100 +++++----------- fs/ncpfs/symlink.c | 159 ++++++++------------------ 9 files changed, 480 insertions(+), 400 deletions(-) (limited to 'fs/ncpfs') diff --git a/fs/ncpfs/Config.in b/fs/ncpfs/Config.in index 5bbc29dc8..a9909cb49 100644 --- a/fs/ncpfs/Config.in +++ b/fs/ncpfs/Config.in @@ -6,10 +6,8 @@ bool ' Proprietary file locking' CONFIG_NCPFS_IOCTL_LOCKING bool ' Clear remove/delete inhibit when needed' CONFIG_NCPFS_STRONG bool ' Use NFS namespace if available' CONFIG_NCPFS_NFS_NS bool ' Use LONG (OS/2) namespace if available' CONFIG_NCPFS_OS2_NS -if [ "$CONFIG_NCPFS_OS2_NS" = "y" ]; then - bool ' Lowercase DOS filenames' CONFIG_NCPFS_SMALLDOS -fi +bool ' Lowercase DOS filenames' CONFIG_NCPFS_SMALLDOS bool ' Allow mounting of volume subdirectories' CONFIG_NCPFS_MOUNT_SUBDIR -# bool ' NDS interserver authentication support' CONFIG_NCPFS_NDS_DOMAINS +bool ' NDS authentication support' CONFIG_NCPFS_NDS_DOMAINS bool ' Use Native Language Support' CONFIG_NCPFS_NLS bool ' Enable symbolic links and execute flags' CONFIG_NCPFS_EXTRAS 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 */ }; @@ -111,12 +109,6 @@ 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. @@ -124,13 +116,17 @@ struct dentry_operations ncp_dentry_operations = 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; ilen ; 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; ilen; 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) { diff --git a/fs/ncpfs/file.c b/fs/ncpfs/file.c index 4a907a9b1..98fd9f23e 100644 --- a/fs/ncpfs/file.c +++ b/fs/ncpfs/file.c @@ -294,9 +294,7 @@ struct inode_operations ncp_file_inode_operations = NULL, /* get_block */ NULL, /* readpage */ NULL, /* writepage */ - NULL, /* flushpage */ NULL, /* truncate */ NULL, /* permission */ - NULL, /* smap */ NULL /* revalidate */ }; diff --git a/fs/ncpfs/inode.c b/fs/ncpfs/inode.c index ec2c1a4e4..26bd474d2 100644 --- a/fs/ncpfs/inode.c +++ b/fs/ncpfs/inode.c @@ -124,16 +124,15 @@ void ncp_update_inode2(struct inode* inode, struct ncp_entry_info *nwinfo) } inode->i_blocks = (inode->i_size + NCP_BLOCK_SIZE - 1) >> NCP_BLOCK_SHIFT; - inode->i_mtime = ncp_date_dos2unix(le16_to_cpu(nwinfo->i.modifyTime), - le16_to_cpu(nwinfo->i.modifyDate)); - inode->i_ctime = ncp_date_dos2unix(le16_to_cpu(nwinfo->i.creationTime), - le16_to_cpu(nwinfo->i.creationDate)); - inode->i_atime = ncp_date_dos2unix(0, - le16_to_cpu(nwinfo->i.lastAccessDate)); + inode->i_mtime = ncp_date_dos2unix(le16_to_cpu(nwi->modifyTime), + le16_to_cpu(nwi->modifyDate)); + inode->i_ctime = ncp_date_dos2unix(le16_to_cpu(nwi->creationTime), + le16_to_cpu(nwi->creationDate)); + inode->i_atime = ncp_date_dos2unix(0, le16_to_cpu(nwi->lastAccessDate)); - NCP_FINFO(inode)->DosDirNum = nwinfo->i.DosDirNum; - NCP_FINFO(inode)->dirEntNum = nwinfo->i.dirEntNum; - NCP_FINFO(inode)->volNumber = nwinfo->i.volNumber; + NCP_FINFO(inode)->DosDirNum = nwi->DosDirNum; + NCP_FINFO(inode)->dirEntNum = nwi->dirEntNum; + NCP_FINFO(inode)->volNumber = nwi->volNumber; } /* diff --git a/fs/ncpfs/ioctl.c b/fs/ncpfs/ioctl.c index 05def9d6c..36063db81 100644 --- a/fs/ncpfs/ioctl.c +++ b/fs/ncpfs/ioctl.c @@ -3,7 +3,7 @@ * * Copyright (C) 1995, 1996 by Volker Lendecke * 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 * */ @@ -364,8 +364,7 @@ int ncp_ioctl(struct inode *inode, struct file *filp, #ifdef CONFIG_NCPFS_NDS_DOMAINS case NCP_IOC_GETOBJECTNAME: - if ( (permission(inode, MAY_READ) != 0) - && (current->uid != server->m.mounted_uid)) { + if (current->uid != server->m.mounted_uid) { return -EACCES; } { @@ -396,8 +395,7 @@ int ncp_ioctl(struct inode *inode, struct file *filp, return 0; } case NCP_IOC_SETOBJECTNAME: - if ( (permission(inode, MAY_WRITE) != 0) - && (current->uid != server->m.mounted_uid)) { + if (current->uid != server->m.mounted_uid) { return -EACCES; } { @@ -441,8 +439,7 @@ int ncp_ioctl(struct inode *inode, struct file *filp, return 0; } case NCP_IOC_GETPRIVATEDATA: - if ( (permission(inode, MAY_READ) != 0) - && (current->uid != server->m.mounted_uid)) { + if (current->uid != server->m.mounted_uid) { return -EACCES; } { @@ -471,8 +468,7 @@ int ncp_ioctl(struct inode *inode, struct file *filp, return 0; } case NCP_IOC_SETPRIVATEDATA: - if ( (permission(inode, MAY_WRITE) != 0) - && (current->uid != server->m.mounted_uid)) { + if (current->uid != server->m.mounted_uid) { return -EACCES; } { @@ -531,7 +527,8 @@ int ncp_ioctl(struct inode *inode, struct file *filp, codepage = NULL; user.codepage[NCP_IOCSNAME_LEN] = 0; - if (!user.codepage[0]) + if (!user.codepage[0] || + !strcmp(user.codepage, "default")) codepage = load_nls_default(); else { codepage = load_nls(user.codepage); @@ -542,13 +539,21 @@ int ncp_ioctl(struct inode *inode, struct file *filp, iocharset = NULL; user.iocharset[NCP_IOCSNAME_LEN] = 0; - if (user.iocharset[0] == 0) + if (!user.iocharset[0] || + !strcmp(user.iocharset, "default")) { iocharset = load_nls_default(); - else { - iocharset = load_nls(user.iocharset); - if (!iocharset) { - unload_nls(codepage); - return -EBADRQC; + NCP_CLR_FLAG(server, NCP_FLAG_UTF8); + } else { + if (!strcmp(user.iocharset, "utf8")) { + iocharset = load_nls_default(); + NCP_SET_FLAG(server, NCP_FLAG_UTF8); + } else { + iocharset = load_nls(user.iocharset); + if (!iocharset) { + unload_nls(codepage); + return -EBADRQC; + } + NCP_CLR_FLAG(server, NCP_FLAG_UTF8); } } @@ -568,35 +573,28 @@ int ncp_ioctl(struct inode *inode, struct file *filp, case NCP_IOC_GETCHARSETS: /* not tested */ { struct ncp_nls_ioctl user; + int len; memset(&user, 0, sizeof(user)); - if (server->nls_vol) - if (server->nls_vol->charset) { - strncpy(user.codepage, - server->nls_vol->charset, - NCP_IOCSNAME_LEN); - user.codepage[NCP_IOCSNAME_LEN] = 0; - if (!strcmp(user.codepage, "default")) - /* unfortunately, we cannot set - 'default' charset... maybe - we should change load_nls()? - It is easy, do not initialize - 'tables' in fs/nls/nls_base.c - with NULL, but with - 'default_table'... */ - memset(user.codepage, 0, - sizeof(user.codepage)); - } + if (server->nls_vol && server->nls_vol->charset) { + len = strlen(server->nls_vol->charset); + if (len > NCP_IOCSNAME_LEN) + len = NCP_IOCSNAME_LEN; + strncpy(user.codepage, + server->nls_vol->charset, len); + user.codepage[len] = 0; + } - if (server->nls_io) - if (server->nls_io->charset) { + if (NCP_IS_FLAG(server, NCP_FLAG_UTF8)) + strcpy(user.iocharset, "utf8"); + else + if (server->nls_io && server->nls_io->charset) { + len = strlen(server->nls_io->charset); + if (len > NCP_IOCSNAME_LEN) + len = NCP_IOCSNAME_LEN; strncpy(user.iocharset, - server->nls_io->charset, - NCP_IOCSNAME_LEN); - user.iocharset[NCP_IOCSNAME_LEN] = 0; - if (!strcmp(user.iocharset, "default")) - memset(user.iocharset, 0, - sizeof(user.iocharset)); + server->nls_io->charset, len); + user.iocharset[len] = 0; } if (copy_to_user((struct ncp_nls_ioctl*)arg, &user, diff --git a/fs/ncpfs/mmap.c b/fs/ncpfs/mmap.c index 036e92e93..806c05d6e 100644 --- a/fs/ncpfs/mmap.c +++ b/fs/ncpfs/mmap.c @@ -43,10 +43,11 @@ static struct page* ncp_file_mmap_nopage(struct vm_area_struct *area, int bufsize; int pos; - page = alloc_page(GFP_KERNEL); + page = alloc_page(GFP_HIGHMEM); /* ncpfs has nothing against GFP_HIGHMEM + as long as recvmsg and memset works on it */ if (!page) return page; - pg_addr = page_address(page); + pg_addr = kmap(page); address &= PAGE_MASK; pos = address - area->vm_start + (area->vm_pgoff << PAGE_SHIFT); @@ -87,6 +88,7 @@ static struct page* ncp_file_mmap_nopage(struct vm_area_struct *area, if (already_read < PAGE_SIZE) memset((char*)(pg_addr + already_read), 0, PAGE_SIZE - already_read); + kunmap(page); return page; } diff --git a/fs/ncpfs/ncplib_kernel.c b/fs/ncpfs/ncplib_kernel.c index 5dbd0c55a..7220e4852 100644 --- a/fs/ncpfs/ncplib_kernel.c +++ b/fs/ncpfs/ncplib_kernel.c @@ -4,6 +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 1999 Wolfram Pienkoss for NLS * */ @@ -886,4 +887,225 @@ ncp_ClearPhysicalRecord(struct ncp_server *server, const char *file_id, } #endif /* CONFIG_NCPFS_IOCTL_LOCKING */ +#ifdef CONFIG_NCPFS_NLS +/* This are the NLS conversion routines with inspirations and code parts + * from the vfat file system and hints from Petr Vandrovec. + */ + +inline unsigned char +ncp__tolower(struct nls_table *t, unsigned char c) +{ + unsigned char nc = t->charset2lower[c]; + + return nc ? nc : c; +} + +inline unsigned char +ncp__toupper(struct nls_table *t, unsigned char c) +{ + unsigned char nc = t->charset2upper[c]; + + return nc ? nc : c; +} + +int +ncp__io2vol(struct ncp_server *server, unsigned char *vname, unsigned int *vlen, + const unsigned char *iname, unsigned int ilen, int cc) +{ + struct nls_table *in = server->nls_io; + struct nls_table *out = server->nls_vol; + struct nls_unicode uc; + unsigned char nc, *up; + int i, k, maxlen = *vlen - 1; + __u16 ec; + + *vlen = 0; + + for (i = 0; i < ilen;) { + if (*vlen == maxlen) + return -ENAMETOOLONG; + + if (NCP_IS_FLAG(server, NCP_FLAG_UTF8)) { + k = utf8_mbtowc(&ec, iname, ilen - i); + if (k == -1) + return -EINVAL; + uc.uni1 = ec & 0xFF; + uc.uni2 = ec >> 8; + iname += k; + i += k; + } else { + if (*iname == NCP_ESC) { + if (i > ilen - 5) + return -EINVAL; + + ec = 0; + for (k = 1; k < 5; k++) { + nc = iname[k]; + ec <<= 4; + if (nc >= '0' && nc <= '9') { + ec |= nc - '0'; + continue; + } + if (nc >= 'a' && nc <= 'f') { + ec |= nc - ('a' - 10); + continue; + } + if (nc >= 'A' && nc <= 'F') { + ec |= nc - ('A' - 10); + continue; + } + return -EINVAL; + } + uc.uni1 = ec & 0xFF; + uc.uni2 = ec >> 8; + iname += 5; + i += 5; + } else { + uc = in->charset2uni[*iname]; + iname++; + i++; + } + } + + up = out->page_uni2charset[uc.uni2]; + if (!up) + return -EINVAL; + + nc = up[uc.uni1]; + if (!nc) + return -EINVAL; + + *vname = cc ? ncp_toupper(out, nc) : nc; + vname++; + *vlen += 1; + } + + *vname = 0; + return 0; +} + +int +ncp__vol2io(struct ncp_server *server, unsigned char *iname, unsigned int *ilen, + const unsigned char *vname, unsigned int vlen, int cc) +{ + struct nls_table *in = server->nls_vol; + struct nls_table *out = server->nls_io; + struct nls_unicode uc; + unsigned char nc, *up; + int i, k, maxlen = *ilen - 1; + __u16 ec; + + *ilen = 0; + + for (i = 0; i < vlen; i++) { + if (*ilen == maxlen) + return -ENAMETOOLONG; + + uc = in->charset2uni[cc ? ncp_tolower(in, *vname) : *vname]; + + if (NCP_IS_FLAG(server, NCP_FLAG_UTF8)) { + k = utf8_wctomb(iname, (uc.uni2 << 8) + uc.uni1, + maxlen - *ilen); + if (k == -1) + return -ENAMETOOLONG; + iname += k; + *ilen += k; + } else { + up = out->page_uni2charset[uc.uni2]; + if (up) + nc = up[uc.uni1]; + else + nc = 0; + + if (nc) { + *iname = nc; + iname++; + *ilen += 1; + } else { + if (*ilen > maxlen - 5) + return -ENAMETOOLONG; + ec = (uc.uni2 << 8) + uc.uni1; + *iname = NCP_ESC; + for (k = 4; k > 0; k--) { + nc = ec & 0xF; + iname[k] = nc > 9 ? nc + ('a' - 10) + : nc + '0'; + ec >>= 4; + } + iname += 5; + *ilen += 5; + } + } + vname++; + } + + *iname = 0; + return 0; +} +#else + +int +ncp__io2vol(unsigned char *vname, unsigned int *vlen, + const unsigned char *iname, unsigned int ilen, int cc) +{ + int i; + + if (*vlen <= ilen) + return -ENAMETOOLONG; + + if (cc) + for (i = 0; i < ilen; i++) { + *vname = toupper(*iname); + vname++; + iname++; + } + else { + memmove(vname, iname, ilen); + vname += ilen; + } + + *vlen = ilen; + *vname = 0; + return 0; +} + +int +ncp__vol2io(unsigned char *iname, unsigned int *ilen, + const unsigned char *vname, unsigned int vlen, int cc) +{ + int i; + + if (*ilen <= vlen) + return -ENAMETOOLONG; + + if (cc) + for (i = 0; i < vlen; i++) { + *iname = tolower(*vname); + iname++; + vname++; + } + else { + memmove(iname, vname, vlen); + iname += vlen; + } + + *ilen = vlen; + *iname = 0; + return 0; +} + +#endif + +inline int +ncp_strnicmp(struct nls_table *t, const unsigned char *s1, + const unsigned char *s2, int n) +{ + int i; + + for (i=0; i -#endif +#else +#include +#endif /* CONFIG_NCPFS_NLS */ #include @@ -97,82 +99,40 @@ ncp_mount_subdir(struct ncp_server *, struct nw_info_struct *, #endif /* CONFIG_NCPFS_MOUNT_SUBDIR */ #ifdef CONFIG_NCPFS_NLS -/* This are the NLS conversion routines with inspirations and code parts - * from the vfat file system and hints from Petr Vandrovec. - */ -/* - * It should be replaced by charset specifc conversion. Gordon Chaffee - * has prepared some things, but I don't know, what he thinks about it. - * The conversion tables for the io charsets should be generatable by - * Unicode table, shouldn't it? I have written so generation code for it. - * The tables for the vendor specific codepages...? Hmm. The Samba sources - * contains also any hints. - */ +inline unsigned char ncp__tolower(struct nls_table *, unsigned char); +inline unsigned char ncp__toupper(struct nls_table *, unsigned char); +int ncp__io2vol(struct ncp_server *, unsigned char *, unsigned int *, + const unsigned char *, unsigned int, int); +int ncp__vol2io(struct ncp_server *, unsigned char *, unsigned int *, + const unsigned char *, unsigned int, int); -#define toupperif(c, u) ((((u) != 0) && ((c) >= 'a') && ((c) <= 'z')) \ - ? (c)-('a'-'A') : (c)) -#define tolowerif(c, u) ((((u) != 0) && ((c) >= 'A') && ((c) <= 'Z')) \ - ? (c)-('A'-'a') : (c)) - -static inline void -io2vol(struct ncp_server *server, char *name, int case_trans) -{ - unsigned char nc; - unsigned char *np; - unsigned char *up; - struct nls_unicode uc; - struct nls_table *nls_in; - struct nls_table *nls_out; - - nls_in = server->nls_io; - nls_out = server->nls_vol; - np = name; - - while (*np) - { - nc = 0; - uc = nls_in->charset2uni[toupperif(*np, case_trans)]; - up = nls_out->page_uni2charset[uc.uni2]; - if (up != NULL) nc = up[uc.uni1]; - if (nc != 0) *np = nc; - np++; - } -} - -static inline void -vol2io(struct ncp_server *server, char *name, int case_trans) -{ - unsigned char nc; - unsigned char *np; - unsigned char *up; - struct nls_unicode uc; - struct nls_table *nls_in; - struct nls_table *nls_out; - - nls_in = server->nls_vol; - nls_out = server->nls_io; - np = name; - - while (*np) - { - nc = 0; - uc = nls_in->charset2uni[*np]; - up = nls_out->page_uni2charset[uc.uni2]; - if (up != NULL) nc = up[uc.uni1]; - if (nc == 0) nc = *np; - *np = tolowerif(nc, case_trans); - np++; - } -} +#define NCP_ESC ':' +#define NCP_IO_TABLE(dentry) (NCP_SERVER((dentry)->d_inode)->nls_io) +#define ncp_tolower(t, c) ncp__tolower(t, c) +#define ncp_toupper(t, c) ncp__toupper(t, c) +#define ncp_io2vol(S,m,i,n,k,U) ncp__io2vol(S,m,i,n,k,U) +#define ncp_vol2io(S,m,i,n,k,U) ncp__vol2io(S,m,i,n,k,U) #else -#define io2vol(S,N,U) if (U) str_upper(N) -#define vol2io(S,N,U) if (U) str_lower(N) +int ncp__io2vol(unsigned char *, unsigned int *, + const unsigned char *, unsigned int, int); +int ncp__vol2io(unsigned char *, unsigned int *, + const unsigned char *, unsigned int, int); + +#define NCP_IO_TABLE(dentry) NULL +#define ncp_tolower(t, c) tolower(c) +#define ncp_toupper(t, c) toupper(c) +#define ncp_io2vol(S,m,i,n,k,U) ncp__io2vol(m,i,n,k,U) +#define ncp_vol2io(S,m,i,n,k,U) ncp__vol2io(m,i,n,k,U) #endif /* CONFIG_NCPFS_NLS */ +inline int +ncp_strnicmp(struct nls_table *, + const unsigned char *, const unsigned char *, int); + #define NCP_GET_AGE(dentry) (jiffies - (dentry)->d_time) #define NCP_MAX_AGE(server) ((server)->dentry_ttl) #define NCP_TEST_AGE(server,dentry) (NCP_GET_AGE(dentry) < NCP_MAX_AGE(server)) diff --git a/fs/ncpfs/symlink.c b/fs/ncpfs/symlink.c index 81151959a..5e5bf2fbd 100644 --- a/fs/ncpfs/symlink.c +++ b/fs/ncpfs/symlink.c @@ -38,139 +38,76 @@ #define NCP_SYMLINK_MAGIC0 le32_to_cpu(0x6c6d7973) /* "symlnk->" */ #define NCP_SYMLINK_MAGIC1 le32_to_cpu(0x3e2d6b6e) -static int ncp_readlink(struct dentry *, char *, int); -static struct dentry *ncp_follow_link(struct dentry *, struct dentry *, unsigned int); int ncp_create_new(struct inode *dir, struct dentry *dentry, int mode,int attributes); -/* - * symlinks can't do much... - */ -struct inode_operations ncp_symlink_inode_operations={ - NULL, /* no file-operations */ - NULL, /* create */ - NULL, /* lookup */ - NULL, /* link */ - NULL, /* unlink */ - NULL, /* symlink */ - NULL, /* mkdir */ - NULL, /* rmdir */ - NULL, /* mknod */ - NULL, /* rename */ - ncp_readlink, /* readlink */ - ncp_follow_link, /* follow_link */ - NULL, /* get_block */ - NULL, /* readpage */ - NULL, /* writepage */ - NULL, /* flushpage */ - NULL, /* truncate */ - NULL, /* permission */ - NULL, /* smap */ - NULL /* revalidate */ -}; - -/* ----- follow a symbolic link ------------------------------------------ */ +/* ----- read a symbolic link ------------------------------------------ */ -static struct dentry *ncp_follow_link(struct dentry *dentry, - struct dentry *base, - unsigned int follow) +static int ncp_symlink_readpage(struct dentry *dentry, struct page *page) { struct inode *inode=dentry->d_inode; - int error, length, cnt; + int error, length, len, cnt; char *link; + char *buf = (char*)kmap(page); -#ifdef DEBUG - PRINTK("ncp_follow_link(dentry=%p,base=%p,follow=%u)\n",dentry,base,follow); -#endif - - if(!S_ISLNK(inode->i_mode)) { - dput(base); - return ERR_PTR(-EINVAL); - } + error = -EIO; + if (ncp_make_open(inode,O_RDONLY)) + goto fail; - if(ncp_make_open(inode,O_RDONLY)) { - dput(base); - return ERR_PTR(-EIO); - } - - for (cnt = 0; (link=(char *)kmalloc(NCP_MAX_SYMLINK_SIZE+1, GFP_NFS))==NULL; cnt++) { - if (cnt > 10) { - dput(base); - return ERR_PTR(-EAGAIN); /* -ENOMEM? */ - } + error = -ENOMEM; + for (cnt = 0; (link=(char *)kmalloc(NCP_MAX_SYMLINK_SIZE, GFP_NFS))==NULL; cnt++) { + if (cnt > 10) + goto fail; schedule(); } error=ncp_read_kernel(NCP_SERVER(inode),NCP_FINFO(inode)->file_handle, 0,NCP_MAX_SYMLINK_SIZE,link,&length); - if (error!=0 || lengthd_inode; - char *link; - int length,error; - -#ifdef DEBUG - PRINTK("ncp_readlink(dentry=%p,buffer=%p,buflen=%d)\n",dentry,buffer,buflen); -#endif - - if(!S_ISLNK(inode->i_mode)) - return -EINVAL; - - if(ncp_make_open(inode,O_RDONLY)) - return -EIO; - - if((link=(char *)kmalloc(NCP_MAX_SYMLINK_SIZE+1,GFP_NFS))==NULL) - return -ENOMEM; - - error = ncp_read_kernel(NCP_SERVER(inode),NCP_FINFO(inode)->file_handle, - 0,NCP_MAX_SYMLINK_SIZE,link,&length); - - if (error!=0 || length < NCP_MIN_SYMLINK_SIZE || buflen < (length-8) || - ((__u32 *)link)[0]!=NCP_SYMLINK_MAGIC0 ||((__u32 *)link)[1]!=NCP_SYMLINK_MAGIC1) { - error = -EIO; - goto out; + if (lengthm.flags & NCP_MOUNT_SYMLINKS)) return -EPERM; /* EPERM is returned by VFS if symlink procedure does not exist */ - if ((length=strlen(symname))>NCP_MAX_SYMLINK_SIZE) + if ((length=strlen(symname))>NCP_MAX_SYMLINK_SIZE-8) return -EINVAL; if ((link=(char *)kmalloc(length+9,GFP_NFS))==NULL) @@ -194,12 +131,16 @@ int ncp_symlink(struct inode *dir, struct dentry *dentry, const char *symname) { ((__u32 *)link)[0]=NCP_SYMLINK_MAGIC0; ((__u32 *)link)[1]=NCP_SYMLINK_MAGIC1; - memcpy(link+8, symname, length+1); /* including last zero for io2vol */ /* map to/from server charset, do not touch upper/lower case as symlink can point out of ncp filesystem */ - io2vol(NCP_SERVER(inode), link+8, 0); - + length += 1; + err = ncp_io2vol(NCP_SERVER(inode),link+8,&length,symname,length-1,0); + if (err) { + kfree(link); + return err; + } + if(ncp_write_kernel(NCP_SERVER(inode), NCP_FINFO(inode)->file_handle, 0, length+8, link, &i) || i!=length+8) { kfree(link); -- cgit v1.2.3