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 @@
obj-$(CONFIG_NCP_FS) += ncpfs.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
# EXTRA_CFLAGS += -DDEBUG_NCP=1
......
......@@ -6,6 +6,7 @@
* Modified 1997 Peter Waltenberg, Bill Hawes, David Woodhouse for 2.1 dcache
* Modified 1998, 1999 Wolfram Pienkoss for NLS
* 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);
static int ncp_rmdir(struct inode *, struct dentry *);
static int ncp_rename(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 *);
#else
#define ncp_symlink NULL
#endif
struct file_operations ncp_dir_operations =
......@@ -56,11 +61,10 @@ struct inode_operations ncp_dir_inode_operations =
create: ncp_create,
lookup: ncp_lookup,
unlink: ncp_unlink,
#ifdef CONFIG_NCPFS_EXTRAS
symlink: ncp_symlink,
#endif
mkdir: ncp_mkdir,
rmdir: ncp_rmdir,
mknod: ncp_mknod,
rename: ncp_rename,
setattr: ncp_notify_change,
};
......@@ -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_delete_dentry(struct dentry *);
struct dentry_operations ncp_dentry_operations =
static struct dentry_operations ncp_dentry_operations =
{
d_revalidate: ncp_lookup_validate,
d_hash: ncp_hash_dentry,
......@@ -81,6 +85,13 @@ struct dentry_operations ncp_dentry_operations =
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
......@@ -300,6 +311,7 @@ __ncp_lookup_validate(struct dentry * dentry, int flags)
if (!res)
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",
dentry->d_parent->d_name.name, __name, res);
/*
......@@ -663,6 +675,7 @@ ncp_read_volume_list(struct file *filp, void *dirent, filldir_t filldir,
info.volume_name);
continue;
}
entry.volume = entry.i.volNumber;
if (!ncp_fill_cache(filp, dirent, filldir, ctl, &entry))
return;
}
......@@ -678,6 +691,9 @@ ncp_do_readdir(struct file *filp, void *dirent, filldir_t filldir,
struct nw_search_sequence seq;
struct ncp_entry_info entry;
int err;
void* buf;
int more;
size_t bufsize;
DPRINTK("ncp_do_readdir: %s/%s, fpos=%ld\n",
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,
DPRINTK("ncp_do_readdir: init failed, err=%d\n", err);
return;
}
#ifdef USE_OLD_SLOW_DIRECTORY_LISTING
for (;;) {
err = ncp_search_for_file_or_subdir(server, &seq, &entry.i);
if (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))
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)
......@@ -781,6 +839,7 @@ static struct dentry *ncp_lookup(struct inode *dir, struct dentry *dentry)
*/
finfo.opened = 0;
finfo.ino = iunique(dir->i_sb, 2);
finfo.volume = finfo.i.volNumber;
error = -EACCES;
inode = ncp_iget(dir->i_sb, &finfo);
......@@ -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 attributes)
int rdev, int attributes)
{
struct ncp_server *server = NCP_SERVER(dir);
struct ncp_entry_info finfo;
......@@ -870,6 +929,15 @@ int ncp_create_new(struct inode *dir, struct dentry *dentry, int mode,
opmode = O_WRONLY;
}
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);
out:
unlock_kernel();
......@@ -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)
{
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)
......@@ -906,6 +974,15 @@ static int ncp_mkdir(struct inode *dir, struct dentry *dentry, int mode)
OC_MODE_CREATE, aDIR, 0xffff,
&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);
}
out:
......@@ -1091,6 +1168,16 @@ static int ncp_rename(struct inode *old_dir, struct dentry *old_dentry,
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 */
/* Linear day numbers of the respective 1sts in non-leap years. */
......
......@@ -51,12 +51,10 @@ int ncp_make_open(struct inode *inode, int right)
struct ncp_entry_info finfo;
int result;
finfo.i.dirEntNum = NCP_FINFO(inode)->dirEntNum;
finfo.i.volNumber = NCP_FINFO(inode)->volNumber;
/* tries max. rights */
finfo.access = O_RDWR;
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);
if (!result)
goto update;
......@@ -65,13 +63,13 @@ int ncp_make_open(struct inode *inode, int right)
case O_RDONLY:
finfo.access = O_RDONLY;
result = ncp_open_create_file_or_subdir(NCP_SERVER(inode),
NULL, NULL, OC_MODE_OPEN,
inode, NULL, OC_MODE_OPEN,
0, AR_READ, &finfo);
break;
case O_WRONLY:
finfo.access = O_WRONLY;
result = ncp_open_create_file_or_subdir(NCP_SERVER(inode),
NULL, NULL, OC_MODE_OPEN,
inode, NULL, OC_MODE_OPEN,
0, AR_WRITE, &finfo);
break;
}
......@@ -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",
dentry->d_parent->d_name.name, dentry->d_name.name);
error = -EIO;
if (!ncp_conn_valid(NCP_SERVER(inode)))
goto out;
error = -EINVAL;
return -EIO;
if (!S_ISREG(inode->i_mode)) {
DPRINTK("ncp_file_read: read from non-file, mode %07o\n",
inode->i_mode);
goto out;
return -EINVAL;
}
pos = *ppos;
/* leave it out on server ...
if (pos + count > inode->i_size) {
count = inode->i_size - pos;
if ((ssize_t) count < 0) {
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);
if (error) {
DPRINTK(KERN_ERR "ncp_file_read: open failed, error=%d\n", error);
goto out;
return error;
}
bufsize = NCP_SERVER(inode)->buffer_size;
......@@ -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);
outrel:
ncp_inode_close(inode);
out:
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)
DPRINTK("ncp_file_write: enter %s/%s\n",
dentry->d_parent->d_name.name, dentry->d_name.name);
errno = -EIO;
if (!ncp_conn_valid(NCP_SERVER(inode)))
goto out;
return -EIO;
if (!S_ISREG(inode->i_mode)) {
DPRINTK("ncp_file_write: write to non-file, mode %07o\n",
inode->i_mode);
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)
goto out;
return 0;
errno = ncp_make_open(inode, O_WRONLY);
if (errno) {
DPRINTK(KERN_ERR "ncp_file_write: open failed, error=%d\n", errno);
return errno;
}
pos = *ppos;
if (file->f_flags & O_APPEND) {
pos = inode->i_size;
}
bufsize = NCP_SERVER(inode)->buffer_size;
already_written = 0;
......@@ -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);
outrel:
ncp_inode_close(inode);
out:
return already_written ? already_written : errno;
}
......
This diff is collapsed.
......@@ -201,7 +201,7 @@ int ncp_ioctl(struct inode *inode, struct file *filp,
case NCP_IOC_SETROOT:
{
struct ncp_setroot_ioctl sr;
struct nw_info_struct i;
unsigned int vnum, de, dosde;
struct dentry* dentry;
if (!capable(CAP_SYS_ADMIN))
......@@ -214,25 +214,31 @@ int ncp_ioctl(struct inode *inode, struct file *filp,
sizeof(sr))) return -EFAULT;
if (sr.volNumber < 0) {
server->m.mounted_vol[0] = 0;
i.volNumber = NCP_NUMBER_OF_VOLUMES + 1;
i.dirEntNum = 0;
i.DosDirNum = 0;
vnum = NCP_NUMBER_OF_VOLUMES;
de = 0;
dosde = 0;
} else if (sr.volNumber >= NCP_NUMBER_OF_VOLUMES) {
return -EINVAL;
} else
if (ncp_mount_subdir(server, &i, sr.volNumber,
} else {
struct nw_info_struct ni;
if (ncp_mount_subdir(server, &ni, sr.volNumber,
sr.namespace, sr.dirEntNum))
return -ENOENT;
vnum = ni.volNumber;
de = ni.dirEntNum;
dosde = ni.DosDirNum;
}
dentry = inode->i_sb->s_root;
server->root_setuped = 1;
if (dentry) {
struct inode* inode = dentry->d_inode;
if (inode) {
NCP_FINFO(inode)->volNumber = i.volNumber;
NCP_FINFO(inode)->dirEntNum = i.dirEntNum;
NCP_FINFO(inode)->DosDirNum = i.DosDirNum;
NCP_FINFO(inode)->volNumber = vnum;
NCP_FINFO(inode)->dirEntNum = de;
NCP_FINFO(inode)->DosDirNum = dosde;
} else
DPRINTK("ncpfs: s_root->d_inode==NULL\n");
} else
......
This diff is collapsed.
......@@ -44,8 +44,13 @@
int ncp_negotiate_buffersize(struct ncp_server *, int, int *);
int ncp_negotiate_size_and_options(struct ncp_server *server, int size,
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 *);
static inline int ncp_read_bounce_size(__u32 size) {
return sizeof(struct ncp_reply_header) + 2 + 2 + size + 8;
......@@ -61,13 +66,17 @@ static inline void ncp_inode_close(struct inode *inode) {
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 *,
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_modify_file_or_subdir_dos_info(struct ncp_server *, struct inode *,
__u32, const struct nw_modify_dos_info *info);
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);
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_subdir(struct ncp_server *, struct inode *, char *);
......@@ -79,6 +88,11 @@ int ncp_initialize_search(struct ncp_server *, struct inode *,
int ncp_search_for_file_or_subdir(struct ncp_server *server,
struct nw_search_sequence *seq,
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,
struct inode *, char *, struct inode *, char *);
......@@ -99,6 +113,20 @@ ncp_ClearPhysicalRecord(struct ncp_server *server,
int
ncp_mount_subdir(struct ncp_server *, struct nw_info_struct *,
__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
......
......@@ -7,19 +7,21 @@
* the file to make sure we don't accidentally use a non-link file
* 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
*
* Copyright (C) 1998-99, Frank A. Vorstenbosch
*
* ncpfs symlink handling code
* NLS support (c) 1999 Petr Vandrovec
* Modified 2000 Ben Harris, University of Cambridge for NFS NS meta-info
*
*/
#include <linux/config.h>
#ifdef CONFIG_NCPFS_EXTRAS
#include <asm/uaccess.h>
#include <linux/errno.h>
......@@ -28,7 +30,6 @@
#include <linux/time.h>
#include <linux/mm.h>
#include <linux/stat.h>
#include <linux/smp_lock.h>
#include "ncplib_kernel.h"
......@@ -38,30 +39,25 @@
#define NCP_SYMLINK_MAGIC0 le32_to_cpu(0x6c6d7973) /* "symlnk->" */
#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 ------------------------------------------ */
static int ncp_symlink_readpage(struct file *file, struct page *page)
{
struct inode *inode = page->mapping->host;
int error, length, len, cnt;
char *link;
int error, length, len;
char *link, *rawlink;
char *buf = kmap(page);
error = -ENOMEM;
for (cnt = 0; (link=(char *)kmalloc(NCP_MAX_SYMLINK_SIZE, GFP_NFS))==NULL; cnt++) {
if (cnt > 10)
goto fail;
schedule();
}
rawlink=(char *)kmalloc(NCP_MAX_SYMLINK_SIZE, GFP_NFS);
if (!rawlink)
goto fail;
if (ncp_make_open(inode,O_RDONLY))
goto failEIO;
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);
/* Close file handle if no other users... */
......@@ -69,14 +65,20 @@ static int ncp_symlink_readpage(struct file *file, struct page *page)
if (error)
goto failEIO;
if (length<NCP_MIN_SYMLINK_SIZE ||
((__u32 *)link)[0]!=NCP_SYMLINK_MAGIC0 ||
((__u32 *)link)[1]!=NCP_SYMLINK_MAGIC1)
goto failEIO;
if (NCP_FINFO(inode)->flags & NCPI_KLUDGE_SYMLINK) {
if (length<NCP_MIN_SYMLINK_SIZE ||
((__u32 *)rawlink)[0]!=NCP_SYMLINK_MAGIC0 ||
((__u32 *)rawlink)[1]!=NCP_SYMLINK_MAGIC1)
goto failEIO;
link = rawlink + 8;
length -= 8;
} else {
link = rawlink;
}
len = NCP_MAX_SYMLINK_SIZE;
error = ncp_vol2io(NCP_SERVER(inode), buf, &len, link+8, length-8, 0);
kfree(link);
error = ncp_vol2io(NCP_SERVER(inode), buf, &len, link, length, 0);
kfree(rawlink);
if (error)
goto fail;
SetPageUptodate(page);
......@@ -86,7 +88,7 @@ static int ncp_symlink_readpage(struct file *file, struct page *page)
failEIO:
error = -EIO;
kfree(link);
kfree(rawlink);
fail:
SetPageError(page);
kunmap(page);
......@@ -105,62 +107,76 @@ struct address_space_operations ncp_symlink_aops = {
int ncp_symlink(struct inode *dir, struct dentry *dentry, const char *symname) {
struct inode *inode;
char *link;
int length, err, i;
char *rawlink;
int length, err, i, outlen;
int kludge;
int mode, attr;
unsigned int hdr;
#ifdef DEBUG
PRINTK("ncp_symlink(dir=%p,dentry=%p,symname=%s)\n",dir,dentry,symname);
#endif
DPRINTK("ncp_symlink(dir=%p,dentry=%p,symname=%s)\n",dir,dentry,symname);
if (!(NCP_SERVER(dir)->m.flags & NCP_MOUNT_SYMLINKS))
return -EPERM; /* EPERM is returned by VFS if symlink procedure does not exist */
if (ncp_is_nfs_extras(NCP_SERVER(dir), NCP_FINFO(dir)->volNumber))
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)
return -EINVAL;
if (kludge) {
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)
return -ENOMEM;
outlen += hdr;
err = -EIO;
lock_kernel();
if (ncp_create_new(dir,dentry,0,aSHARED|aHIDDEN))
if (ncp_create_new(dir,dentry,mode,0,attr)) {
goto failfree;
}
inode=dentry->d_inode;
if (ncp_make_open(inode, O_WRONLY))
goto failfree;
((__u32 *)link)[0]=NCP_SYMLINK_MAGIC0;
((__u32 *)link)[1]=NCP_SYMLINK_MAGIC1;
/* 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;
if (ncp_write_kernel(NCP_SERVER(inode), NCP_FINFO(inode)->file_handle,
0, outlen, rawlink, &i) || i!=outlen) {
goto fail;
}
ncp_inode_close(inode);
ncp_make_closed(inode);
unlock_kernel();
kfree(link);
kfree(rawlink);
return 0;
fail:
fail:;
ncp_inode_close(inode);
ncp_make_closed(inode);
failfree:
unlock_kernel();
kfree(link);
return err;
failfree:;
kfree(rawlink);
return err;
}
#endif
/* ----- EOF ----- */
......@@ -44,7 +44,7 @@ struct ncp_reply_header {
};
#define NCP_VOLNAME_LEN (16)
#define NCP_NUMBER_OF_VOLUMES (64)
#define NCP_NUMBER_OF_VOLUMES (256)
struct ncp_volume_info {
__u32 total_blocks;
__u32 free_blocks;
......@@ -85,6 +85,18 @@ struct ncp_volume_info {
#define RIM_ALL (ntohl(0xFF0F0000L))
#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 */
#define OC_MODE_OPEN 0x01
#define OC_MODE_TRUNCATE 0x02
......@@ -109,6 +121,11 @@ struct ncp_volume_info {
#define AR_OPEN_COMPRESSED 0x0100
#endif
struct nw_nfs_info {
__u32 mode;
__u32 rdev;
};
struct nw_info_struct {
__u32 spaceAlloc __attribute__((packed));
__u32 attributes __attribute__((packed));
......@@ -136,6 +153,10 @@ struct nw_info_struct {
__u32 NSCreator __attribute__((packed));
__u8 nameLen __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 */
......
......@@ -182,9 +182,8 @@ struct ncp_entry_info {
ino_t ino;
int opened;
int access;
__u32 server_file_handle __attribute__((packed));
__u8 open_create_action __attribute__((packed));
__u8 file_handle[6] __attribute__((packed));
unsigned int volume;
__u8 file_handle[6];
};
/* Guess, what 0x564c is :-) */
......
......@@ -22,7 +22,8 @@ struct ncp_inode_info {
struct semaphore open_sem;
atomic_t opened;
int access;
__u32 server_file_handle;
int flags;
#define NCPI_KLUDGE_SYMLINK 0x0001
__u8 file_handle[6];
struct inode vfs_inode;
};
......
......@@ -21,6 +21,7 @@
#define NCP_MOUNT_NO_NFS 0x0010 /* do not use NFS namespace */
#define NCP_MOUNT_EXTRAS 0x0020
#define NCP_MOUNT_SYMLINKS 0x0040 /* enable symlinks */
#define NCP_MOUNT_NFS_EXTRAS 0x0080 /* Enable use of NFS NS meta-info */
struct ncp_mount_data {
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