Commit 59ece965 authored by Linus Torvalds's avatar Linus Torvalds

Merge bk://vana.vc.cvut.cz/ncpfs

into home.transmeta.com:/home/torvalds/v2.5/linux
parents 6eebabfa 41783de4
...@@ -5,7 +5,13 @@ ...@@ -5,7 +5,13 @@
obj-$(CONFIG_NCP_FS) += ncpfs.o obj-$(CONFIG_NCP_FS) += ncpfs.o
ncpfs-objs := dir.o file.o inode.o ioctl.o mmap.o ncplib_kernel.o sock.o \ ncpfs-objs := dir.o file.o inode.o ioctl.o mmap.o ncplib_kernel.o sock.o \
symlink.o ncpsign_kernel.o ncpsign_kernel.o
ifeq ($(CONFIG_NCPFS_EXTRAS),y)
ncpfs-objs += symlink.o
endif
ifeq ($(CONFIG_NCPFS_NFS_NS),y)
ncpfs-objs += symlink.o
endif
# If you want debugging output, please uncomment the following line # If you want debugging output, please uncomment the following line
# EXTRA_CFLAGS += -DDEBUG_NCP=1 # EXTRA_CFLAGS += -DDEBUG_NCP=1
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
* Modified 1997 Peter Waltenberg, Bill Hawes, David Woodhouse for 2.1 dcache * Modified 1997 Peter Waltenberg, Bill Hawes, David Woodhouse for 2.1 dcache
* Modified 1998, 1999 Wolfram Pienkoss for NLS * Modified 1998, 1999 Wolfram Pienkoss for NLS
* Modified 1999 Wolfram Pienkoss for directory caching * Modified 1999 Wolfram Pienkoss for directory caching
* Modified 2000 Ben Harris, University of Cambridge for NFS NS meta-info
* *
*/ */
...@@ -40,8 +41,12 @@ static int ncp_mkdir(struct inode *, struct dentry *, int); ...@@ -40,8 +41,12 @@ static int ncp_mkdir(struct inode *, struct dentry *, int);
static int ncp_rmdir(struct inode *, struct dentry *); static int ncp_rmdir(struct inode *, struct dentry *);
static int ncp_rename(struct inode *, struct dentry *, static int ncp_rename(struct inode *, struct dentry *,
struct inode *, struct dentry *); struct inode *, struct dentry *);
#ifdef CONFIG_NCPFS_EXTRAS static int ncp_mknod(struct inode * dir, struct dentry *dentry,
int mode, int rdev);
#if defined(CONFIG_NCPFS_EXTRAS) || defined(CONFIG_NCPFS_NFS_NS)
extern int ncp_symlink(struct inode *, struct dentry *, const char *); extern int ncp_symlink(struct inode *, struct dentry *, const char *);
#else
#define ncp_symlink NULL
#endif #endif
struct file_operations ncp_dir_operations = struct file_operations ncp_dir_operations =
...@@ -56,11 +61,10 @@ struct inode_operations ncp_dir_inode_operations = ...@@ -56,11 +61,10 @@ struct inode_operations ncp_dir_inode_operations =
create: ncp_create, create: ncp_create,
lookup: ncp_lookup, lookup: ncp_lookup,
unlink: ncp_unlink, unlink: ncp_unlink,
#ifdef CONFIG_NCPFS_EXTRAS
symlink: ncp_symlink, symlink: ncp_symlink,
#endif
mkdir: ncp_mkdir, mkdir: ncp_mkdir,
rmdir: ncp_rmdir, rmdir: ncp_rmdir,
mknod: ncp_mknod,
rename: ncp_rename, rename: ncp_rename,
setattr: ncp_notify_change, setattr: ncp_notify_change,
}; };
...@@ -73,7 +77,7 @@ static int ncp_hash_dentry(struct dentry *, struct qstr *); ...@@ -73,7 +77,7 @@ static int ncp_hash_dentry(struct dentry *, struct qstr *);
static int ncp_compare_dentry (struct dentry *, struct qstr *, struct qstr *); static int ncp_compare_dentry (struct dentry *, struct qstr *, struct qstr *);
static int ncp_delete_dentry(struct dentry *); static int ncp_delete_dentry(struct dentry *);
struct dentry_operations ncp_dentry_operations = static struct dentry_operations ncp_dentry_operations =
{ {
d_revalidate: ncp_lookup_validate, d_revalidate: ncp_lookup_validate,
d_hash: ncp_hash_dentry, d_hash: ncp_hash_dentry,
...@@ -81,6 +85,13 @@ struct dentry_operations ncp_dentry_operations = ...@@ -81,6 +85,13 @@ struct dentry_operations ncp_dentry_operations =
d_delete: ncp_delete_dentry, d_delete: ncp_delete_dentry,
}; };
struct dentry_operations ncp_root_dentry_operations =
{
d_hash: ncp_hash_dentry,
d_compare: ncp_compare_dentry,
d_delete: ncp_delete_dentry,
};
/* /*
* Note: leave the hash unchanged if the directory * Note: leave the hash unchanged if the directory
...@@ -300,6 +311,7 @@ __ncp_lookup_validate(struct dentry * dentry, int flags) ...@@ -300,6 +311,7 @@ __ncp_lookup_validate(struct dentry * dentry, int flags)
if (!res) if (!res)
res = ncp_obtain_info(server, dir, __name, &(finfo.i)); res = ncp_obtain_info(server, dir, __name, &(finfo.i));
} }
finfo.volume = finfo.i.volNumber;
DDPRINTK("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); dentry->d_parent->d_name.name, __name, res);
/* /*
...@@ -663,6 +675,7 @@ ncp_read_volume_list(struct file *filp, void *dirent, filldir_t filldir, ...@@ -663,6 +675,7 @@ ncp_read_volume_list(struct file *filp, void *dirent, filldir_t filldir,
info.volume_name); info.volume_name);
continue; continue;
} }
entry.volume = entry.i.volNumber;
if (!ncp_fill_cache(filp, dirent, filldir, ctl, &entry)) if (!ncp_fill_cache(filp, dirent, filldir, ctl, &entry))
return; return;
} }
...@@ -678,6 +691,9 @@ ncp_do_readdir(struct file *filp, void *dirent, filldir_t filldir, ...@@ -678,6 +691,9 @@ ncp_do_readdir(struct file *filp, void *dirent, filldir_t filldir,
struct nw_search_sequence seq; struct nw_search_sequence seq;
struct ncp_entry_info entry; struct ncp_entry_info entry;
int err; int err;
void* buf;
int more;
size_t bufsize;
DPRINTK("ncp_do_readdir: %s/%s, fpos=%ld\n", DPRINTK("ncp_do_readdir: %s/%s, fpos=%ld\n",
dentry->d_parent->d_name.name, dentry->d_name.name, dentry->d_parent->d_name.name, dentry->d_name.name,
...@@ -691,15 +707,57 @@ ncp_do_readdir(struct file *filp, void *dirent, filldir_t filldir, ...@@ -691,15 +707,57 @@ ncp_do_readdir(struct file *filp, void *dirent, filldir_t filldir,
DPRINTK("ncp_do_readdir: init failed, err=%d\n", err); DPRINTK("ncp_do_readdir: init failed, err=%d\n", err);
return; return;
} }
#ifdef USE_OLD_SLOW_DIRECTORY_LISTING
for (;;) { for (;;) {
err = ncp_search_for_file_or_subdir(server, &seq, &entry.i); err = ncp_search_for_file_or_subdir(server, &seq, &entry.i);
if (err) { if (err) {
DPRINTK("ncp_do_readdir: search failed, err=%d\n", err); DPRINTK("ncp_do_readdir: search failed, err=%d\n", err);
return; break;
} }
entry.volume = entry.i.volNumber;
if (!ncp_fill_cache(filp, dirent, filldir, ctl, &entry)) if (!ncp_fill_cache(filp, dirent, filldir, ctl, &entry))
return; break;
} }
#else
/* We MUST NOT use server->buffer_size handshaked with server if we are
using UDP, as for UDP server uses max. buffer size determined by
MTU, and for TCP server uses hardwired value 65KB (== 66560 bytes).
So we use 128KB, just to be sure, as there is no way how to know
this value in advance. */
bufsize = 131072;
buf = vmalloc(bufsize);
if (!buf)
return;
do {
int cnt;
char* rpl;
size_t rpls;
err = ncp_search_for_fileset(server, &seq, &more, &cnt, buf, bufsize, &rpl, &rpls);
if (err) /* Error */
break;
if (!cnt) /* prevent endless loop */
break;
while (cnt--) {
size_t onerpl;
if (rpls < offsetof(struct nw_info_struct, entryName))
break; /* short packet */
ncp_extract_file_info(rpl, &entry.i);
onerpl = offsetof(struct nw_info_struct, entryName) + entry.i.nameLen;
if (rpls < onerpl)
break; /* short packet */
(void)ncp_obtain_nfs_info(server, &entry.i);
rpl += onerpl;
rpls -= onerpl;
entry.volume = entry.i.volNumber;
if (!ncp_fill_cache(filp, dirent, filldir, ctl, &entry))
break;
}
} while (more);
vfree(buf);
#endif
return;
} }
int ncp_conn_logged_in(struct super_block *sb) int ncp_conn_logged_in(struct super_block *sb)
...@@ -781,6 +839,7 @@ static struct dentry *ncp_lookup(struct inode *dir, struct dentry *dentry) ...@@ -781,6 +839,7 @@ static struct dentry *ncp_lookup(struct inode *dir, struct dentry *dentry)
*/ */
finfo.opened = 0; finfo.opened = 0;
finfo.ino = iunique(dir->i_sb, 2); finfo.ino = iunique(dir->i_sb, 2);
finfo.volume = finfo.i.volNumber;
error = -EACCES; error = -EACCES;
inode = ncp_iget(dir->i_sb, &finfo); inode = ncp_iget(dir->i_sb, &finfo);
...@@ -824,7 +883,7 @@ static int ncp_instantiate(struct inode *dir, struct dentry *dentry, ...@@ -824,7 +883,7 @@ static int ncp_instantiate(struct inode *dir, struct dentry *dentry,
} }
int ncp_create_new(struct inode *dir, struct dentry *dentry, int mode, int ncp_create_new(struct inode *dir, struct dentry *dentry, int mode,
int attributes) int rdev, int attributes)
{ {
struct ncp_server *server = NCP_SERVER(dir); struct ncp_server *server = NCP_SERVER(dir);
struct ncp_entry_info finfo; struct ncp_entry_info finfo;
...@@ -870,6 +929,15 @@ int ncp_create_new(struct inode *dir, struct dentry *dentry, int mode, ...@@ -870,6 +929,15 @@ int ncp_create_new(struct inode *dir, struct dentry *dentry, int mode,
opmode = O_WRONLY; opmode = O_WRONLY;
} }
finfo.access = opmode; finfo.access = opmode;
if (ncp_is_nfs_extras(server, finfo.volume)) {
finfo.i.nfs.mode = mode;
finfo.i.nfs.rdev = rdev;
if (ncp_modify_nfs_info(server, finfo.volume,
finfo.i.dirEntNum,
mode, rdev) != 0)
goto out;
}
error = ncp_instantiate(dir, dentry, &finfo); error = ncp_instantiate(dir, dentry, &finfo);
out: out:
unlock_kernel(); unlock_kernel();
...@@ -878,7 +946,7 @@ int ncp_create_new(struct inode *dir, struct dentry *dentry, int mode, ...@@ -878,7 +946,7 @@ int ncp_create_new(struct inode *dir, struct dentry *dentry, int mode,
static int ncp_create(struct inode *dir, struct dentry *dentry, int mode) static int ncp_create(struct inode *dir, struct dentry *dentry, int mode)
{ {
return ncp_create_new(dir, dentry, mode, 0); return ncp_create_new(dir, dentry, mode, 0, 0);
} }
static int ncp_mkdir(struct inode *dir, struct dentry *dentry, int mode) static int ncp_mkdir(struct inode *dir, struct dentry *dentry, int mode)
...@@ -906,6 +974,15 @@ static int ncp_mkdir(struct inode *dir, struct dentry *dentry, int mode) ...@@ -906,6 +974,15 @@ static int ncp_mkdir(struct inode *dir, struct dentry *dentry, int mode)
OC_MODE_CREATE, aDIR, 0xffff, OC_MODE_CREATE, aDIR, 0xffff,
&finfo) == 0) &finfo) == 0)
{ {
if (ncp_is_nfs_extras(server, finfo.volume)) {
mode |= S_IFDIR;
finfo.i.nfs.mode = mode;
if (ncp_modify_nfs_info(server,
finfo.volume,
finfo.i.dirEntNum,
mode, 0) != 0)
goto out;
}
error = ncp_instantiate(dir, dentry, &finfo); error = ncp_instantiate(dir, dentry, &finfo);
} }
out: out:
...@@ -1091,6 +1168,16 @@ static int ncp_rename(struct inode *old_dir, struct dentry *old_dentry, ...@@ -1091,6 +1168,16 @@ static int ncp_rename(struct inode *old_dir, struct dentry *old_dentry,
return error; return error;
} }
static int ncp_mknod(struct inode * dir, struct dentry *dentry,
int mode, int rdev)
{
if (ncp_is_nfs_extras(NCP_SERVER(dir), NCP_FINFO(dir)->volNumber)) {
DPRINTK(KERN_DEBUG "ncp_mknod: mode = 0%o\n", mode);
return ncp_create_new(dir, dentry, mode, rdev, 0);
}
return -EPERM; /* Strange, but true */
}
/* The following routines are taken directly from msdos-fs */ /* The following routines are taken directly from msdos-fs */
/* Linear day numbers of the respective 1sts in non-leap years. */ /* Linear day numbers of the respective 1sts in non-leap years. */
......
...@@ -51,12 +51,10 @@ int ncp_make_open(struct inode *inode, int right) ...@@ -51,12 +51,10 @@ int ncp_make_open(struct inode *inode, int right)
struct ncp_entry_info finfo; struct ncp_entry_info finfo;
int result; int result;
finfo.i.dirEntNum = NCP_FINFO(inode)->dirEntNum;
finfo.i.volNumber = NCP_FINFO(inode)->volNumber;
/* tries max. rights */ /* tries max. rights */
finfo.access = O_RDWR; finfo.access = O_RDWR;
result = ncp_open_create_file_or_subdir(NCP_SERVER(inode), result = ncp_open_create_file_or_subdir(NCP_SERVER(inode),
NULL, NULL, OC_MODE_OPEN, inode, NULL, OC_MODE_OPEN,
0, AR_READ | AR_WRITE, &finfo); 0, AR_READ | AR_WRITE, &finfo);
if (!result) if (!result)
goto update; goto update;
...@@ -65,13 +63,13 @@ int ncp_make_open(struct inode *inode, int right) ...@@ -65,13 +63,13 @@ int ncp_make_open(struct inode *inode, int right)
case O_RDONLY: case O_RDONLY:
finfo.access = O_RDONLY; finfo.access = O_RDONLY;
result = ncp_open_create_file_or_subdir(NCP_SERVER(inode), result = ncp_open_create_file_or_subdir(NCP_SERVER(inode),
NULL, NULL, OC_MODE_OPEN, inode, NULL, OC_MODE_OPEN,
0, AR_READ, &finfo); 0, AR_READ, &finfo);
break; break;
case O_WRONLY: case O_WRONLY:
finfo.access = O_WRONLY; finfo.access = O_WRONLY;
result = ncp_open_create_file_or_subdir(NCP_SERVER(inode), result = ncp_open_create_file_or_subdir(NCP_SERVER(inode),
NULL, NULL, OC_MODE_OPEN, inode, NULL, OC_MODE_OPEN,
0, AR_WRITE, &finfo); 0, AR_WRITE, &finfo);
break; break;
} }
...@@ -115,30 +113,31 @@ ncp_file_read(struct file *file, char *buf, size_t count, loff_t *ppos) ...@@ -115,30 +113,31 @@ ncp_file_read(struct file *file, char *buf, size_t count, loff_t *ppos)
DPRINTK("ncp_file_read: enter %s/%s\n", DPRINTK("ncp_file_read: enter %s/%s\n",
dentry->d_parent->d_name.name, dentry->d_name.name); dentry->d_parent->d_name.name, dentry->d_name.name);
error = -EIO;
if (!ncp_conn_valid(NCP_SERVER(inode))) if (!ncp_conn_valid(NCP_SERVER(inode)))
goto out; return -EIO;
error = -EINVAL;
if (!S_ISREG(inode->i_mode)) { if (!S_ISREG(inode->i_mode)) {
DPRINTK("ncp_file_read: read from non-file, mode %07o\n", DPRINTK("ncp_file_read: read from non-file, mode %07o\n",
inode->i_mode); inode->i_mode);
goto out; return -EINVAL;
} }
pos = *ppos; pos = *ppos;
/* leave it out on server ...
if (pos + count > inode->i_size) { if ((ssize_t) count < 0) {
count = inode->i_size - pos; return -EINVAL;
}
if (!count)
return 0;
if (pos > inode->i_sb->s_maxbytes)
return 0;
if (pos + count > inode->i_sb->s_maxbytes) {
count = inode->i_sb->s_maxbytes - pos;
} }
*/
error = 0;
if (!count) /* size_t is never < 0 */
goto out;
error = ncp_make_open(inode, O_RDONLY); error = ncp_make_open(inode, O_RDONLY);
if (error) { if (error) {
DPRINTK(KERN_ERR "ncp_file_read: open failed, error=%d\n", error); DPRINTK(KERN_ERR "ncp_file_read: open failed, error=%d\n", error);
goto out; return error;
} }
bufsize = NCP_SERVER(inode)->buffer_size; bufsize = NCP_SERVER(inode)->buffer_size;
...@@ -184,7 +183,6 @@ ncp_file_read(struct file *file, char *buf, size_t count, loff_t *ppos) ...@@ -184,7 +183,6 @@ ncp_file_read(struct file *file, char *buf, size_t count, loff_t *ppos)
dentry->d_parent->d_name.name, dentry->d_name.name); dentry->d_parent->d_name.name, dentry->d_name.name);
outrel: outrel:
ncp_inode_close(inode); ncp_inode_close(inode);
out:
return already_read ? already_read : error; return already_read ? already_read : error;
} }
...@@ -201,28 +199,46 @@ ncp_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos) ...@@ -201,28 +199,46 @@ ncp_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
DPRINTK("ncp_file_write: enter %s/%s\n", DPRINTK("ncp_file_write: enter %s/%s\n",
dentry->d_parent->d_name.name, dentry->d_name.name); dentry->d_parent->d_name.name, dentry->d_name.name);
errno = -EIO;
if (!ncp_conn_valid(NCP_SERVER(inode))) if (!ncp_conn_valid(NCP_SERVER(inode)))
goto out; return -EIO;
if (!S_ISREG(inode->i_mode)) { if (!S_ISREG(inode->i_mode)) {
DPRINTK("ncp_file_write: write to non-file, mode %07o\n", DPRINTK("ncp_file_write: write to non-file, mode %07o\n",
inode->i_mode); inode->i_mode);
return -EINVAL; return -EINVAL;
} }
if ((ssize_t) count < 0)
return -EINVAL;
pos = *ppos;
if (file->f_flags & O_APPEND) {
pos = inode->i_size;
}
errno = 0; if (pos + count > MAX_NON_LFS && !(file->f_flags&O_LARGEFILE)) {
if (pos >= MAX_NON_LFS) {
send_sig(SIGXFSZ, current, 0);
return -EFBIG;
}
if (count > MAX_NON_LFS - (u32)pos) {
count = MAX_NON_LFS - (u32)pos;
}
}
if (pos >= inode->i_sb->s_maxbytes) {
if (count || pos > inode->i_sb->s_maxbytes) {
send_sig(SIGXFSZ, current, 0);
return -EFBIG;
}
}
if (pos + count > inode->i_sb->s_maxbytes) {
count = inode->i_sb->s_maxbytes - pos;
}
if (!count) if (!count)
goto out; return 0;
errno = ncp_make_open(inode, O_WRONLY); errno = ncp_make_open(inode, O_WRONLY);
if (errno) { if (errno) {
DPRINTK(KERN_ERR "ncp_file_write: open failed, error=%d\n", errno); DPRINTK(KERN_ERR "ncp_file_write: open failed, error=%d\n", errno);
return errno; return errno;
} }
pos = *ppos;
if (file->f_flags & O_APPEND) {
pos = inode->i_size;
}
bufsize = NCP_SERVER(inode)->buffer_size; bufsize = NCP_SERVER(inode)->buffer_size;
already_written = 0; already_written = 0;
...@@ -268,7 +284,6 @@ ncp_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos) ...@@ -268,7 +284,6 @@ ncp_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
dentry->d_parent->d_name.name, dentry->d_name.name); dentry->d_parent->d_name.name, dentry->d_name.name);
outrel: outrel:
ncp_inode_close(inode); ncp_inode_close(inode);
out:
return already_written ? already_written : errno; return already_written ? already_written : errno;
} }
......
This diff is collapsed.
...@@ -201,7 +201,7 @@ int ncp_ioctl(struct inode *inode, struct file *filp, ...@@ -201,7 +201,7 @@ int ncp_ioctl(struct inode *inode, struct file *filp,
case NCP_IOC_SETROOT: case NCP_IOC_SETROOT:
{ {
struct ncp_setroot_ioctl sr; struct ncp_setroot_ioctl sr;
struct nw_info_struct i; unsigned int vnum, de, dosde;
struct dentry* dentry; struct dentry* dentry;
if (!capable(CAP_SYS_ADMIN)) if (!capable(CAP_SYS_ADMIN))
...@@ -214,25 +214,31 @@ int ncp_ioctl(struct inode *inode, struct file *filp, ...@@ -214,25 +214,31 @@ int ncp_ioctl(struct inode *inode, struct file *filp,
sizeof(sr))) return -EFAULT; sizeof(sr))) return -EFAULT;
if (sr.volNumber < 0) { if (sr.volNumber < 0) {
server->m.mounted_vol[0] = 0; server->m.mounted_vol[0] = 0;
i.volNumber = NCP_NUMBER_OF_VOLUMES + 1; vnum = NCP_NUMBER_OF_VOLUMES;
i.dirEntNum = 0; de = 0;
i.DosDirNum = 0; dosde = 0;
} else if (sr.volNumber >= NCP_NUMBER_OF_VOLUMES) { } else if (sr.volNumber >= NCP_NUMBER_OF_VOLUMES) {
return -EINVAL; return -EINVAL;
} else } else {
if (ncp_mount_subdir(server, &i, sr.volNumber, struct nw_info_struct ni;
if (ncp_mount_subdir(server, &ni, sr.volNumber,
sr.namespace, sr.dirEntNum)) sr.namespace, sr.dirEntNum))
return -ENOENT; return -ENOENT;
vnum = ni.volNumber;
de = ni.dirEntNum;
dosde = ni.DosDirNum;
}
dentry = inode->i_sb->s_root; dentry = inode->i_sb->s_root;
server->root_setuped = 1; server->root_setuped = 1;
if (dentry) { if (dentry) {
struct inode* inode = dentry->d_inode; struct inode* inode = dentry->d_inode;
if (inode) { if (inode) {
NCP_FINFO(inode)->volNumber = i.volNumber; NCP_FINFO(inode)->volNumber = vnum;
NCP_FINFO(inode)->dirEntNum = i.dirEntNum; NCP_FINFO(inode)->dirEntNum = de;
NCP_FINFO(inode)->DosDirNum = i.DosDirNum; NCP_FINFO(inode)->DosDirNum = dosde;
} else } else
DPRINTK("ncpfs: s_root->d_inode==NULL\n"); DPRINTK("ncpfs: s_root->d_inode==NULL\n");
} else } else
......
This diff is collapsed.
...@@ -44,8 +44,13 @@ ...@@ -44,8 +44,13 @@
int ncp_negotiate_buffersize(struct ncp_server *, int, int *); int ncp_negotiate_buffersize(struct ncp_server *, int, int *);
int ncp_negotiate_size_and_options(struct ncp_server *server, int size, int ncp_negotiate_size_and_options(struct ncp_server *server, int size,
int options, int *ret_size, int *ret_options); int options, int *ret_size, int *ret_options);
int ncp_get_volume_info_with_number(struct ncp_server *, int,
struct ncp_volume_info *); int ncp_get_volume_info_with_number(struct ncp_server* server, int n,
struct ncp_volume_info *target);
int ncp_get_directory_info(struct ncp_server* server, __u8 dirhandle,
struct ncp_volume_info* target);
int ncp_close_file(struct ncp_server *, const char *); int ncp_close_file(struct ncp_server *, const char *);
static inline int ncp_read_bounce_size(__u32 size) { static inline int ncp_read_bounce_size(__u32 size) {
return sizeof(struct ncp_reply_header) + 2 + 2 + size + 8; return sizeof(struct ncp_reply_header) + 2 + 2 + size + 8;
...@@ -61,13 +66,17 @@ static inline void ncp_inode_close(struct inode *inode) { ...@@ -61,13 +66,17 @@ static inline void ncp_inode_close(struct inode *inode) {
atomic_dec(&NCP_FINFO(inode)->opened); atomic_dec(&NCP_FINFO(inode)->opened);
} }
void ncp_extract_file_info(void* src, struct nw_info_struct* target);
int ncp_obtain_info(struct ncp_server *server, struct inode *, char *, int ncp_obtain_info(struct ncp_server *server, struct inode *, char *,
struct nw_info_struct *target); struct nw_info_struct *target);
int ncp_obtain_nfs_info(struct ncp_server *server, struct nw_info_struct *target);
int ncp_lookup_volume(struct ncp_server *, char *, struct nw_info_struct *); int ncp_lookup_volume(struct ncp_server *, char *, struct nw_info_struct *);
int ncp_modify_file_or_subdir_dos_info(struct ncp_server *, struct inode *, int ncp_modify_file_or_subdir_dos_info(struct ncp_server *, struct inode *,
__u32, const struct nw_modify_dos_info *info); __u32, const struct nw_modify_dos_info *info);
int ncp_modify_file_or_subdir_dos_info_path(struct ncp_server *, struct inode *, int ncp_modify_file_or_subdir_dos_info_path(struct ncp_server *, struct inode *,
const char* path, __u32, const struct nw_modify_dos_info *info); const char* path, __u32, const struct nw_modify_dos_info *info);
int ncp_modify_nfs_info(struct ncp_server *, __u8 volnum, __u32 dirent,
__u32 mode, __u32 rdev);
int ncp_del_file_or_subdir2(struct ncp_server *, struct dentry*); int ncp_del_file_or_subdir2(struct ncp_server *, struct dentry*);
int ncp_del_file_or_subdir(struct ncp_server *, struct inode *, char *); int ncp_del_file_or_subdir(struct ncp_server *, struct inode *, char *);
...@@ -79,6 +88,11 @@ int ncp_initialize_search(struct ncp_server *, struct inode *, ...@@ -79,6 +88,11 @@ int ncp_initialize_search(struct ncp_server *, struct inode *,
int ncp_search_for_file_or_subdir(struct ncp_server *server, int ncp_search_for_file_or_subdir(struct ncp_server *server,
struct nw_search_sequence *seq, struct nw_search_sequence *seq,
struct nw_info_struct *target); struct nw_info_struct *target);
int ncp_search_for_fileset(struct ncp_server *server,
struct nw_search_sequence *seq,
int* more, int* cnt,
char* buffer, size_t bufsize,
char** rbuf, size_t* rsize);
int ncp_ren_or_mov_file_or_subdir(struct ncp_server *server, int ncp_ren_or_mov_file_or_subdir(struct ncp_server *server,
struct inode *, char *, struct inode *, char *); struct inode *, char *, struct inode *, char *);
...@@ -99,6 +113,20 @@ ncp_ClearPhysicalRecord(struct ncp_server *server, ...@@ -99,6 +113,20 @@ ncp_ClearPhysicalRecord(struct ncp_server *server,
int int
ncp_mount_subdir(struct ncp_server *, struct nw_info_struct *, ncp_mount_subdir(struct ncp_server *, struct nw_info_struct *,
__u8, __u8, __u32); __u8, __u8, __u32);
int ncp_dirhandle_alloc(struct ncp_server *, __u8 vol, __u32 dirent, __u8 *dirhandle);
int ncp_dirhandle_free(struct ncp_server *, __u8 dirhandle);
int ncp_create_new(struct inode *dir, struct dentry *dentry,
int mode, int rdev, int attributes);
static inline int ncp_is_nfs_extras(struct ncp_server* server, unsigned int volnum) {
#ifdef CONFIG_NCPFS_NFS_NS
return (server->m.flags & NCP_MOUNT_NFS_EXTRAS) &&
(server->name_space[volnum] == NW_NS_NFS);
#else
return 0;
#endif
}
#ifdef CONFIG_NCPFS_NLS #ifdef CONFIG_NCPFS_NLS
......
...@@ -7,19 +7,21 @@ ...@@ -7,19 +7,21 @@
* the file to make sure we don't accidentally use a non-link file * the file to make sure we don't accidentally use a non-link file
* as a link. * as a link.
* *
* When using the NFS namespace, we set the mode to indicate a symlink and
* don't bother with the magic numbers.
*
* from linux/fs/ext2/symlink.c * from linux/fs/ext2/symlink.c
* *
* Copyright (C) 1998-99, Frank A. Vorstenbosch * Copyright (C) 1998-99, Frank A. Vorstenbosch
* *
* ncpfs symlink handling code * ncpfs symlink handling code
* NLS support (c) 1999 Petr Vandrovec * NLS support (c) 1999 Petr Vandrovec
* Modified 2000 Ben Harris, University of Cambridge for NFS NS meta-info
* *
*/ */
#include <linux/config.h> #include <linux/config.h>
#ifdef CONFIG_NCPFS_EXTRAS
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <linux/errno.h> #include <linux/errno.h>
...@@ -28,7 +30,6 @@ ...@@ -28,7 +30,6 @@
#include <linux/time.h> #include <linux/time.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/stat.h> #include <linux/stat.h>
#include <linux/smp_lock.h>
#include "ncplib_kernel.h" #include "ncplib_kernel.h"
...@@ -38,30 +39,25 @@ ...@@ -38,30 +39,25 @@
#define NCP_SYMLINK_MAGIC0 le32_to_cpu(0x6c6d7973) /* "symlnk->" */ #define NCP_SYMLINK_MAGIC0 le32_to_cpu(0x6c6d7973) /* "symlnk->" */
#define NCP_SYMLINK_MAGIC1 le32_to_cpu(0x3e2d6b6e) #define NCP_SYMLINK_MAGIC1 le32_to_cpu(0x3e2d6b6e)
int ncp_create_new(struct inode *dir, struct dentry *dentry,
int mode,int attributes);
/* ----- read a symbolic link ------------------------------------------ */ /* ----- read a symbolic link ------------------------------------------ */
static int ncp_symlink_readpage(struct file *file, struct page *page) static int ncp_symlink_readpage(struct file *file, struct page *page)
{ {
struct inode *inode = page->mapping->host; struct inode *inode = page->mapping->host;
int error, length, len, cnt; int error, length, len;
char *link; char *link, *rawlink;
char *buf = kmap(page); char *buf = kmap(page);
error = -ENOMEM; error = -ENOMEM;
for (cnt = 0; (link=(char *)kmalloc(NCP_MAX_SYMLINK_SIZE, GFP_NFS))==NULL; cnt++) { rawlink=(char *)kmalloc(NCP_MAX_SYMLINK_SIZE, GFP_NFS);
if (cnt > 10) if (!rawlink)
goto fail; goto fail;
schedule();
}
if (ncp_make_open(inode,O_RDONLY)) if (ncp_make_open(inode,O_RDONLY))
goto failEIO; goto failEIO;
error=ncp_read_kernel(NCP_SERVER(inode),NCP_FINFO(inode)->file_handle, error=ncp_read_kernel(NCP_SERVER(inode),NCP_FINFO(inode)->file_handle,
0,NCP_MAX_SYMLINK_SIZE,link,&length); 0,NCP_MAX_SYMLINK_SIZE,rawlink,&length);
ncp_inode_close(inode); ncp_inode_close(inode);
/* Close file handle if no other users... */ /* Close file handle if no other users... */
...@@ -69,14 +65,20 @@ static int ncp_symlink_readpage(struct file *file, struct page *page) ...@@ -69,14 +65,20 @@ static int ncp_symlink_readpage(struct file *file, struct page *page)
if (error) if (error)
goto failEIO; goto failEIO;
if (length<NCP_MIN_SYMLINK_SIZE || if (NCP_FINFO(inode)->flags & NCPI_KLUDGE_SYMLINK) {
((__u32 *)link)[0]!=NCP_SYMLINK_MAGIC0 || if (length<NCP_MIN_SYMLINK_SIZE ||
((__u32 *)link)[1]!=NCP_SYMLINK_MAGIC1) ((__u32 *)rawlink)[0]!=NCP_SYMLINK_MAGIC0 ||
goto failEIO; ((__u32 *)rawlink)[1]!=NCP_SYMLINK_MAGIC1)
goto failEIO;
link = rawlink + 8;
length -= 8;
} else {
link = rawlink;
}
len = NCP_MAX_SYMLINK_SIZE; len = NCP_MAX_SYMLINK_SIZE;
error = ncp_vol2io(NCP_SERVER(inode), buf, &len, link+8, length-8, 0); error = ncp_vol2io(NCP_SERVER(inode), buf, &len, link, length, 0);
kfree(link); kfree(rawlink);
if (error) if (error)
goto fail; goto fail;
SetPageUptodate(page); SetPageUptodate(page);
...@@ -86,7 +88,7 @@ static int ncp_symlink_readpage(struct file *file, struct page *page) ...@@ -86,7 +88,7 @@ static int ncp_symlink_readpage(struct file *file, struct page *page)
failEIO: failEIO:
error = -EIO; error = -EIO;
kfree(link); kfree(rawlink);
fail: fail:
SetPageError(page); SetPageError(page);
kunmap(page); kunmap(page);
...@@ -105,62 +107,76 @@ struct address_space_operations ncp_symlink_aops = { ...@@ -105,62 +107,76 @@ struct address_space_operations ncp_symlink_aops = {
int ncp_symlink(struct inode *dir, struct dentry *dentry, const char *symname) { int ncp_symlink(struct inode *dir, struct dentry *dentry, const char *symname) {
struct inode *inode; struct inode *inode;
char *link; char *rawlink;
int length, err, i; int length, err, i, outlen;
int kludge;
int mode, attr;
unsigned int hdr;
#ifdef DEBUG DPRINTK("ncp_symlink(dir=%p,dentry=%p,symname=%s)\n",dir,dentry,symname);
PRINTK("ncp_symlink(dir=%p,dentry=%p,symname=%s)\n",dir,dentry,symname);
#endif
if (!(NCP_SERVER(dir)->m.flags & NCP_MOUNT_SYMLINKS)) if (ncp_is_nfs_extras(NCP_SERVER(dir), NCP_FINFO(dir)->volNumber))
return -EPERM; /* EPERM is returned by VFS if symlink procedure does not exist */ kludge = 0;
else
#ifdef CONFIG_NCPFS_EXTRAS
if (NCP_SERVER(dir)->m.flags & NCP_MOUNT_SYMLINKS)
kludge = 1;
else
#endif
/* EPERM is returned by VFS if symlink procedure does not exist */
return -EPERM;
rawlink=(char *)kmalloc(NCP_MAX_SYMLINK_SIZE, GFP_NFS);
if (!rawlink)
return -ENOMEM;
if ((length=strlen(symname))>NCP_MAX_SYMLINK_SIZE-8) if (kludge) {
return -EINVAL; mode = 0;
attr = aSHARED | aHIDDEN;
((__u32 *)rawlink)[0]=NCP_SYMLINK_MAGIC0;
((__u32 *)rawlink)[1]=NCP_SYMLINK_MAGIC1;
hdr = 8;
} else {
mode = S_IFLNK | S_IRWXUGO;
attr = 0;
hdr = 0;
}
length = strlen(symname);
/* map to/from server charset, do not touch upper/lower case as
symlink can point out of ncp filesystem */
outlen = NCP_MAX_SYMLINK_SIZE - hdr;
err = ncp_io2vol(NCP_SERVER(dir), rawlink + hdr, &outlen, symname, length, 0);
if (err)
goto failfree;
if ((link=(char *)kmalloc(length+9,GFP_NFS))==NULL) outlen += hdr;
return -ENOMEM;
err = -EIO; err = -EIO;
lock_kernel(); if (ncp_create_new(dir,dentry,mode,0,attr)) {
if (ncp_create_new(dir,dentry,0,aSHARED|aHIDDEN))
goto failfree; goto failfree;
}
inode=dentry->d_inode; inode=dentry->d_inode;
if (ncp_make_open(inode, O_WRONLY)) if (ncp_make_open(inode, O_WRONLY))
goto failfree; goto failfree;
((__u32 *)link)[0]=NCP_SYMLINK_MAGIC0; if (ncp_write_kernel(NCP_SERVER(inode), NCP_FINFO(inode)->file_handle,
((__u32 *)link)[1]=NCP_SYMLINK_MAGIC1; 0, outlen, rawlink, &i) || i!=outlen) {
/* map to/from server charset, do not touch upper/lower case as
symlink can point out of ncp filesystem */
length += 1;
err = ncp_io2vol(NCP_SERVER(inode),link+8,&length,symname,length-1,0);
if (err)
goto fail;
if(ncp_write_kernel(NCP_SERVER(inode), NCP_FINFO(inode)->file_handle,
0, length+8, link, &i) || i!=length+8) {
err = -EIO;
goto fail; goto fail;
} }
ncp_inode_close(inode); ncp_inode_close(inode);
ncp_make_closed(inode); ncp_make_closed(inode);
unlock_kernel(); kfree(rawlink);
kfree(link);
return 0; return 0;
fail:;
fail:
ncp_inode_close(inode); ncp_inode_close(inode);
ncp_make_closed(inode); ncp_make_closed(inode);
failfree: failfree:;
unlock_kernel(); kfree(rawlink);
kfree(link); return err;
return err;
} }
#endif
/* ----- EOF ----- */ /* ----- EOF ----- */
...@@ -44,7 +44,7 @@ struct ncp_reply_header { ...@@ -44,7 +44,7 @@ struct ncp_reply_header {
}; };
#define NCP_VOLNAME_LEN (16) #define NCP_VOLNAME_LEN (16)
#define NCP_NUMBER_OF_VOLUMES (64) #define NCP_NUMBER_OF_VOLUMES (256)
struct ncp_volume_info { struct ncp_volume_info {
__u32 total_blocks; __u32 total_blocks;
__u32 free_blocks; __u32 free_blocks;
...@@ -85,6 +85,18 @@ struct ncp_volume_info { ...@@ -85,6 +85,18 @@ struct ncp_volume_info {
#define RIM_ALL (ntohl(0xFF0F0000L)) #define RIM_ALL (ntohl(0xFF0F0000L))
#define RIM_COMPRESSED_INFO (ntohl(0x00000080L)) #define RIM_COMPRESSED_INFO (ntohl(0x00000080L))
/* Defines for NSInfoBitMask */
#define NSIBM_NFS_NAME 0x0001
#define NSIBM_NFS_MODE 0x0002
#define NSIBM_NFS_GID 0x0004
#define NSIBM_NFS_NLINKS 0x0008
#define NSIBM_NFS_RDEV 0x0010
#define NSIBM_NFS_LINK 0x0020
#define NSIBM_NFS_CREATED 0x0040
#define NSIBM_NFS_UID 0x0080
#define NSIBM_NFS_ACSFLAG 0x0100
#define NSIBM_NFS_MYFLAG 0x0200
/* open/create modes */ /* open/create modes */
#define OC_MODE_OPEN 0x01 #define OC_MODE_OPEN 0x01
#define OC_MODE_TRUNCATE 0x02 #define OC_MODE_TRUNCATE 0x02
...@@ -109,6 +121,11 @@ struct ncp_volume_info { ...@@ -109,6 +121,11 @@ struct ncp_volume_info {
#define AR_OPEN_COMPRESSED 0x0100 #define AR_OPEN_COMPRESSED 0x0100
#endif #endif
struct nw_nfs_info {
__u32 mode;
__u32 rdev;
};
struct nw_info_struct { struct nw_info_struct {
__u32 spaceAlloc __attribute__((packed)); __u32 spaceAlloc __attribute__((packed));
__u32 attributes __attribute__((packed)); __u32 attributes __attribute__((packed));
...@@ -136,6 +153,10 @@ struct nw_info_struct { ...@@ -136,6 +153,10 @@ struct nw_info_struct {
__u32 NSCreator __attribute__((packed)); __u32 NSCreator __attribute__((packed));
__u8 nameLen __attribute__((packed)); __u8 nameLen __attribute__((packed));
__u8 entryName[256] __attribute__((packed)); __u8 entryName[256] __attribute__((packed));
/* libncp may depend on there being nothing after entryName */
#ifdef __KERNEL__
struct nw_nfs_info nfs;
#endif
}; };
/* modify mask - use with MODIFY_DOS_INFO structure */ /* modify mask - use with MODIFY_DOS_INFO structure */
......
...@@ -182,9 +182,8 @@ struct ncp_entry_info { ...@@ -182,9 +182,8 @@ struct ncp_entry_info {
ino_t ino; ino_t ino;
int opened; int opened;
int access; int access;
__u32 server_file_handle __attribute__((packed)); unsigned int volume;
__u8 open_create_action __attribute__((packed)); __u8 file_handle[6];
__u8 file_handle[6] __attribute__((packed));
}; };
/* Guess, what 0x564c is :-) */ /* Guess, what 0x564c is :-) */
......
...@@ -22,7 +22,8 @@ struct ncp_inode_info { ...@@ -22,7 +22,8 @@ struct ncp_inode_info {
struct semaphore open_sem; struct semaphore open_sem;
atomic_t opened; atomic_t opened;
int access; int access;
__u32 server_file_handle; int flags;
#define NCPI_KLUDGE_SYMLINK 0x0001
__u8 file_handle[6]; __u8 file_handle[6];
struct inode vfs_inode; struct inode vfs_inode;
}; };
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#define NCP_MOUNT_NO_NFS 0x0010 /* do not use NFS namespace */ #define NCP_MOUNT_NO_NFS 0x0010 /* do not use NFS namespace */
#define NCP_MOUNT_EXTRAS 0x0020 #define NCP_MOUNT_EXTRAS 0x0020
#define NCP_MOUNT_SYMLINKS 0x0040 /* enable symlinks */ #define NCP_MOUNT_SYMLINKS 0x0040 /* enable symlinks */
#define NCP_MOUNT_NFS_EXTRAS 0x0080 /* Enable use of NFS NS meta-info */
struct ncp_mount_data { struct ncp_mount_data {
int version; int version;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment