Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
59ece965
Commit
59ece965
authored
Jul 24, 2002
by
Linus Torvalds
Browse files
Options
Browse Files
Download
Plain Diff
Merge
bk://vana.vc.cvut.cz/ncpfs
into home.transmeta.com:/home/torvalds/v2.5/linux
parents
6eebabfa
41783de4
Changes
12
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
709 additions
and
272 deletions
+709
-272
fs/ncpfs/Makefile
fs/ncpfs/Makefile
+7
-1
fs/ncpfs/dir.c
fs/ncpfs/dir.c
+95
-8
fs/ncpfs/file.c
fs/ncpfs/file.c
+43
-28
fs/ncpfs/inode.c
fs/ncpfs/inode.c
+177
-140
fs/ncpfs/ioctl.c
fs/ncpfs/ioctl.c
+16
-10
fs/ncpfs/ncplib_kernel.c
fs/ncpfs/ncplib_kernel.c
+242
-22
fs/ncpfs/ncplib_kernel.h
fs/ncpfs/ncplib_kernel.h
+30
-2
fs/ncpfs/symlink.c
fs/ncpfs/symlink.c
+72
-56
include/linux/ncp.h
include/linux/ncp.h
+22
-1
include/linux/ncp_fs.h
include/linux/ncp_fs.h
+2
-3
include/linux/ncp_fs_i.h
include/linux/ncp_fs_i.h
+2
-1
include/linux/ncp_mount.h
include/linux/ncp_mount.h
+1
-0
No files found.
fs/ncpfs/Makefile
View file @
59ece965
...
@@ -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
...
...
fs/ncpfs/dir.c
View file @
59ece965
...
@@ -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
=
st
atic
st
ruct
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. */
...
...
fs/ncpfs/file.c
View file @
59ece965
...
@@ -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
;
}
}
...
...
fs/ncpfs/inode.c
View file @
59ece965
...
@@ -5,6 +5,7 @@
...
@@ -5,6 +5,7 @@
* Modified for big endian by J.F. Chadima and David S. Miller
* 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 1997 Peter Waltenberg, Bill Hawes, David Woodhouse for 2.1 dcache
* Modified 1998 Wolfram Pienkoss for NLS
* Modified 1998 Wolfram Pienkoss for NLS
* Modified 2000 Ben Harris, University of Cambridge for NFS NS meta-info
*
*
*/
*/
...
@@ -90,8 +91,8 @@ static struct super_operations ncp_sops =
...
@@ -90,8 +91,8 @@ static struct super_operations ncp_sops =
statfs:
ncp_statfs
,
statfs:
ncp_statfs
,
};
};
extern
struct
dentry_operations
ncp_dentry_operations
;
extern
struct
dentry_operations
ncp_
root_
dentry_operations
;
#if
def CONFIG_NCPFS_EXTRAS
#if
defined(CONFIG_NCPFS_EXTRAS) || defined(CONFIG_NCPFS_NFS_NS)
extern
struct
address_space_operations
ncp_symlink_aops
;
extern
struct
address_space_operations
ncp_symlink_aops
;
extern
int
ncp_symlink
(
struct
inode
*
,
struct
dentry
*
,
const
char
*
);
extern
int
ncp_symlink
(
struct
inode
*
,
struct
dentry
*
,
const
char
*
);
#endif
#endif
...
@@ -99,19 +100,18 @@ extern int ncp_symlink(struct inode*, struct dentry*, const char*);
...
@@ -99,19 +100,18 @@ extern int ncp_symlink(struct inode*, struct dentry*, const char*);
/*
/*
* Fill in the ncpfs-specific information in the inode.
* Fill in the ncpfs-specific information in the inode.
*/
*/
void
ncp_update_inode
(
struct
inode
*
inode
,
struct
ncp_entry_info
*
nwinfo
)
static
void
ncp_update_dirent
(
struct
inode
*
inode
,
struct
ncp_entry_info
*
nwinfo
)
{
{
NCP_FINFO
(
inode
)
->
DosDirNum
=
nwinfo
->
i
.
DosDirNum
;
NCP_FINFO
(
inode
)
->
DosDirNum
=
nwinfo
->
i
.
DosDirNum
;
NCP_FINFO
(
inode
)
->
dirEntNum
=
nwinfo
->
i
.
dirEntNum
;
NCP_FINFO
(
inode
)
->
dirEntNum
=
nwinfo
->
i
.
dirEntNum
;
NCP_FINFO
(
inode
)
->
volNumber
=
nwinfo
->
i
.
volNumber
;
NCP_FINFO
(
inode
)
->
volNumber
=
nwinfo
->
volume
;
}
#ifdef CONFIG_NCPFS_STRONG
void
ncp_update_inode
(
struct
inode
*
inode
,
struct
ncp_entry_info
*
nwinfo
)
NCP_FINFO
(
inode
)
->
nwattr
=
nwinfo
->
i
.
attributes
;
{
#else
ncp_update_dirent
(
inode
,
nwinfo
);
NCP_FINFO
(
inode
)
->
nwattr
=
nwinfo
->
i
.
attributes
;
NCP_FINFO
(
inode
)
->
nwattr
=
nwinfo
->
i
.
attributes
;
#endif
NCP_FINFO
(
inode
)
->
access
=
nwinfo
->
access
;
NCP_FINFO
(
inode
)
->
access
=
nwinfo
->
access
;
NCP_FINFO
(
inode
)
->
server_file_handle
=
nwinfo
->
server_file_handle
;
memcpy
(
NCP_FINFO
(
inode
)
->
file_handle
,
nwinfo
->
file_handle
,
memcpy
(
NCP_FINFO
(
inode
)
->
file_handle
,
nwinfo
->
file_handle
,
sizeof
(
nwinfo
->
file_handle
));
sizeof
(
nwinfo
->
file_handle
));
DPRINTK
(
"ncp_update_inode: updated %s, volnum=%d, dirent=%u
\n
"
,
DPRINTK
(
"ncp_update_inode: updated %s, volnum=%d, dirent=%u
\n
"
,
...
@@ -119,68 +119,27 @@ void ncp_update_inode(struct inode *inode, struct ncp_entry_info *nwinfo)
...
@@ -119,68 +119,27 @@ void ncp_update_inode(struct inode *inode, struct ncp_entry_info *nwinfo)
NCP_FINFO
(
inode
)
->
dirEntNum
);
NCP_FINFO
(
inode
)
->
dirEntNum
);
}
}
void
ncp_update_inode2
(
struct
inode
*
inode
,
struct
ncp_entry_info
*
nwinfo
)
static
void
ncp_update_dates
(
struct
inode
*
inode
,
struct
nw_info_struct
*
nwi
)
{
{
struct
nw_info_struct
*
nwi
=
&
nwinfo
->
i
;
/* NFS namespace mode overrides others if it's set. */
struct
ncp_server
*
server
=
NCP_SERVER
(
inode
);
DPRINTK
(
KERN_DEBUG
"ncp_update_dates_and_mode: (%s) nfs.mode=0%o
\n
"
,
nwi
->
entryName
,
nwi
->
nfs
.
mode
);
if
(
!
atomic_read
(
&
NCP_FINFO
(
inode
)
->
opened
))
{
if
(
nwi
->
nfs
.
mode
)
{
#ifdef CONFIG_NCPFS_STRONG
/* XXX Security? */
NCP_FINFO
(
inode
)
->
nwattr
=
nwi
->
attributes
;
inode
->
i_mode
=
nwi
->
nfs
.
mode
;
#endif
if
(
nwi
->
attributes
&
aDIR
)
{
inode
->
i_mode
=
server
->
m
.
dir_mode
;
inode
->
i_size
=
NCP_BLOCK_SIZE
;
}
else
{
inode
->
i_mode
=
server
->
m
.
file_mode
;
inode
->
i_size
=
le32_to_cpu
(
nwi
->
dataStreamSize
);
#ifdef CONFIG_NCPFS_EXTRAS
if
((
server
->
m
.
flags
&
(
NCP_MOUNT_EXTRAS
|
NCP_MOUNT_SYMLINKS
))
&&
(
nwi
->
attributes
&
aSHARED
))
{
switch
(
nwi
->
attributes
&
(
aHIDDEN
|
aSYSTEM
))
{
case
aHIDDEN
:
if
(
server
->
m
.
flags
&
NCP_MOUNT_SYMLINKS
)
{
if
(
/* (inode->i_size >= NCP_MIN_SYMLINK_SIZE)
&& */
(
inode
->
i_size
<=
NCP_MAX_SYMLINK_SIZE
))
{
inode
->
i_mode
=
(
inode
->
i_mode
&
~
S_IFMT
)
|
S_IFLNK
;
break
;
}
}
/* FALLTHROUGH */
case
0
:
if
(
server
->
m
.
flags
&
NCP_MOUNT_EXTRAS
)
inode
->
i_mode
|=
0444
;
break
;
case
aSYSTEM
:
if
(
server
->
m
.
flags
&
NCP_MOUNT_EXTRAS
)
inode
->
i_mode
|=
(
inode
->
i_mode
>>
2
)
&
0111
;
break
;
/* case aSYSTEM|aHIDDEN: */
default:
/* reserved combination */
break
;
}
}
#endif
}
if
(
nwi
->
attributes
&
aRONLY
)
inode
->
i_mode
&=
~
0222
;
}
}
inode
->
i_blocks
=
(
inode
->
i_size
+
NCP_BLOCK_SIZE
-
1
)
>>
NCP_BLOCK_SHIFT
;
inode
->
i_blocks
=
(
inode
->
i_size
+
NCP_BLOCK_SIZE
-
1
)
>>
NCP_BLOCK_SHIFT
;
inode
->
i_mtime
=
ncp_date_dos2unix
(
le16_to_cpu
(
nwi
->
modifyTime
),
inode
->
i_mtime
=
ncp_date_dos2unix
(
le16_to_cpu
(
nwi
->
modifyTime
),
le16_to_cpu
(
nwi
->
modifyDate
));
le16_to_cpu
(
nwi
->
modifyDate
));
inode
->
i_ctime
=
ncp_date_dos2unix
(
le16_to_cpu
(
nwi
->
creationTime
),
inode
->
i_ctime
=
ncp_date_dos2unix
(
le16_to_cpu
(
nwi
->
creationTime
),
le16_to_cpu
(
nwi
->
creationDate
));
le16_to_cpu
(
nwi
->
creationDate
));
inode
->
i_atime
=
ncp_date_dos2unix
(
0
,
le16_to_cpu
(
nwi
->
lastAccessDate
));
inode
->
i_atime
=
ncp_date_dos2unix
(
0
,
le16_to_cpu
(
nwi
->
lastAccessDate
));
NCP_FINFO
(
inode
)
->
DosDirNum
=
nwi
->
DosDirNum
;
NCP_FINFO
(
inode
)
->
dirEntNum
=
nwi
->
dirEntNum
;
NCP_FINFO
(
inode
)
->
volNumber
=
nwi
->
volNumber
;
}
}
/*
static
void
ncp_update_attrs
(
struct
inode
*
inode
,
struct
ncp_entry_info
*
nwinfo
)
* Fill in the inode based on the ncp_entry_info structure.
*/
static
void
ncp_set_attr
(
struct
inode
*
inode
,
struct
ncp_entry_info
*
nwinfo
)
{
{
struct
nw_info_struct
*
nwi
=
&
nwinfo
->
i
;
struct
nw_info_struct
*
nwi
=
&
nwinfo
->
i
;
struct
ncp_server
*
server
=
NCP_SERVER
(
inode
);
struct
ncp_server
*
server
=
NCP_SERVER
(
inode
);
...
@@ -202,17 +161,18 @@ static void ncp_set_attr(struct inode *inode, struct ncp_entry_info *nwinfo)
...
@@ -202,17 +161,18 @@ static void ncp_set_attr(struct inode *inode, struct ncp_entry_info *nwinfo)
if
(
/* (inode->i_size >= NCP_MIN_SYMLINK_SIZE)
if
(
/* (inode->i_size >= NCP_MIN_SYMLINK_SIZE)
&& */
(
inode
->
i_size
<=
NCP_MAX_SYMLINK_SIZE
))
{
&& */
(
inode
->
i_size
<=
NCP_MAX_SYMLINK_SIZE
))
{
inode
->
i_mode
=
(
inode
->
i_mode
&
~
S_IFMT
)
|
S_IFLNK
;
inode
->
i_mode
=
(
inode
->
i_mode
&
~
S_IFMT
)
|
S_IFLNK
;
NCP_FINFO
(
inode
)
->
flags
|=
NCPI_KLUDGE_SYMLINK
;
break
;
break
;
}
}
}
}
/* FALLTHROUGH */
/* FALLTHROUGH */
case
0
:
case
0
:
if
(
server
->
m
.
flags
&
NCP_MOUNT_EXTRAS
)
if
(
server
->
m
.
flags
&
NCP_MOUNT_EXTRAS
)
inode
->
i_mode
|=
0444
;
inode
->
i_mode
|=
S_IRUGO
;
break
;
break
;
case
aSYSTEM
:
case
aSYSTEM
:
if
(
server
->
m
.
flags
&
NCP_MOUNT_EXTRAS
)
if
(
server
->
m
.
flags
&
NCP_MOUNT_EXTRAS
)
inode
->
i_mode
|=
(
inode
->
i_mode
>>
2
)
&
0111
;
inode
->
i_mode
|=
(
inode
->
i_mode
>>
2
)
&
S_IXUGO
;
break
;
break
;
/* case aSYSTEM|aHIDDEN: */
/* case aSYSTEM|aHIDDEN: */
default:
default:
...
@@ -222,7 +182,31 @@ static void ncp_set_attr(struct inode *inode, struct ncp_entry_info *nwinfo)
...
@@ -222,7 +182,31 @@ static void ncp_set_attr(struct inode *inode, struct ncp_entry_info *nwinfo)
}
}
#endif
#endif
}
}
if
(
nwi
->
attributes
&
aRONLY
)
inode
->
i_mode
&=
~
0222
;
if
(
nwi
->
attributes
&
aRONLY
)
inode
->
i_mode
&=
~
S_IWUGO
;
}
void
ncp_update_inode2
(
struct
inode
*
inode
,
struct
ncp_entry_info
*
nwinfo
)
{
NCP_FINFO
(
inode
)
->
flags
=
0
;
if
(
!
atomic_read
(
&
NCP_FINFO
(
inode
)
->
opened
))
{
NCP_FINFO
(
inode
)
->
nwattr
=
nwinfo
->
i
.
attributes
;
ncp_update_attrs
(
inode
,
nwinfo
);
}
ncp_update_dates
(
inode
,
&
nwinfo
->
i
);
ncp_update_dirent
(
inode
,
nwinfo
);
}
/*
* Fill in the inode based on the ncp_entry_info structure.
*/
static
void
ncp_set_attr
(
struct
inode
*
inode
,
struct
ncp_entry_info
*
nwinfo
)
{
struct
ncp_server
*
server
=
NCP_SERVER
(
inode
);
NCP_FINFO
(
inode
)
->
flags
=
0
;
ncp_update_attrs
(
inode
,
nwinfo
);
DDPRINTK
(
"ncp_read_inode: inode->i_mode = %u
\n
"
,
inode
->
i_mode
);
DDPRINTK
(
"ncp_read_inode: inode->i_mode = %u
\n
"
,
inode
->
i_mode
);
...
@@ -232,14 +216,7 @@ static void ncp_set_attr(struct inode *inode, struct ncp_entry_info *nwinfo)
...
@@ -232,14 +216,7 @@ static void ncp_set_attr(struct inode *inode, struct ncp_entry_info *nwinfo)
inode
->
i_rdev
=
NODEV
;
inode
->
i_rdev
=
NODEV
;
inode
->
i_blksize
=
NCP_BLOCK_SIZE
;
inode
->
i_blksize
=
NCP_BLOCK_SIZE
;
inode
->
i_blocks
=
(
inode
->
i_size
+
NCP_BLOCK_SIZE
-
1
)
>>
NCP_BLOCK_SHIFT
;
ncp_update_dates
(
inode
,
&
nwinfo
->
i
);
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_update_inode
(
inode
,
nwinfo
);
ncp_update_inode
(
inode
,
nwinfo
);
}
}
...
@@ -274,11 +251,17 @@ ncp_iget(struct super_block *sb, struct ncp_entry_info *info)
...
@@ -274,11 +251,17 @@ ncp_iget(struct super_block *sb, struct ncp_entry_info *info)
}
else
if
(
S_ISDIR
(
inode
->
i_mode
))
{
}
else
if
(
S_ISDIR
(
inode
->
i_mode
))
{
inode
->
i_op
=
&
ncp_dir_inode_operations
;
inode
->
i_op
=
&
ncp_dir_inode_operations
;
inode
->
i_fop
=
&
ncp_dir_operations
;
inode
->
i_fop
=
&
ncp_dir_operations
;
#ifdef CONFIG_NCPFS_EXTRAS
#ifdef CONFIG_NCPFS_NFS_NS
}
else
if
(
S_ISCHR
(
inode
->
i_mode
)
||
S_ISBLK
(
inode
->
i_mode
)
||
S_ISFIFO
(
inode
->
i_mode
)
||
S_ISSOCK
(
inode
->
i_mode
))
{
init_special_inode
(
inode
,
inode
->
i_mode
,
info
->
i
.
nfs
.
rdev
);
#endif
#if defined(CONFIG_NCPFS_EXTRAS) || defined(CONFIG_NCPFS_NFS_NS)
}
else
if
(
S_ISLNK
(
inode
->
i_mode
))
{
}
else
if
(
S_ISLNK
(
inode
->
i_mode
))
{
inode
->
i_op
=
&
ncp_symlink_inode_operations
;
inode
->
i_op
=
&
ncp_symlink_inode_operations
;
inode
->
i_data
.
a_ops
=
&
ncp_symlink_aops
;
inode
->
i_data
.
a_ops
=
&
ncp_symlink_aops
;
#endif
#endif
}
else
{
make_bad_inode
(
inode
);
}
}
insert_inode_hash
(
inode
);
insert_inode_hash
(
inode
);
}
else
}
else
...
@@ -479,7 +462,7 @@ static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent)
...
@@ -479,7 +462,7 @@ static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent)
#ifdef CONFIG_NCPFS_SMALLDOS
#ifdef CONFIG_NCPFS_SMALLDOS
finfo
.
i
.
NSCreator
=
NW_NS_DOS
;
finfo
.
i
.
NSCreator
=
NW_NS_DOS
;
#endif
#endif
finfo
.
i
.
volNumber
=
NCP_NUMBER_OF_VOLUMES
+
1
;
/* illegal volnum */
finfo
.
volume
=
NCP_NUMBER_OF_VOLUMES
;
/* set dates of mountpoint to Jan 1, 1986; 00:00 */
/* set dates of mountpoint to Jan 1, 1986; 00:00 */
finfo
.
i
.
creationTime
=
finfo
.
i
.
modifyTime
finfo
.
i
.
creationTime
=
finfo
.
i
.
modifyTime
=
cpu_to_le16
(
0x0000
);
=
cpu_to_le16
(
0x0000
);
...
@@ -492,7 +475,7 @@ static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent)
...
@@ -492,7 +475,7 @@ static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent)
finfo
.
opened
=
0
;
finfo
.
opened
=
0
;
finfo
.
ino
=
2
;
/* tradition */
finfo
.
ino
=
2
;
/* tradition */
server
->
name_space
[
finfo
.
i
.
volNumber
]
=
NW_NS_DOS
;
server
->
name_space
[
finfo
.
volume
]
=
NW_NS_DOS
;
error
=
-
ENOMEM
;
error
=
-
ENOMEM
;
root_inode
=
ncp_iget
(
sb
,
&
finfo
);
root_inode
=
ncp_iget
(
sb
,
&
finfo
);
...
@@ -502,7 +485,7 @@ static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent)
...
@@ -502,7 +485,7 @@ static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent)
sb
->
s_root
=
d_alloc_root
(
root_inode
);
sb
->
s_root
=
d_alloc_root
(
root_inode
);
if
(
!
sb
->
s_root
)
if
(
!
sb
->
s_root
)
goto
out_no_root
;
goto
out_no_root
;
sb
->
s_root
->
d_op
=
&
ncp_dentry_operations
;
sb
->
s_root
->
d_op
=
&
ncp_
root_
dentry_operations
;
return
0
;
return
0
;
out_no_root:
out_no_root:
...
@@ -567,12 +550,60 @@ static void ncp_put_super(struct super_block *sb)
...
@@ -567,12 +550,60 @@ static void ncp_put_super(struct super_block *sb)
static
int
ncp_statfs
(
struct
super_block
*
sb
,
struct
statfs
*
buf
)
static
int
ncp_statfs
(
struct
super_block
*
sb
,
struct
statfs
*
buf
)
{
{
struct
dentry
*
d
;
struct
inode
*
i
;
struct
ncp_inode_info
*
ni
;
struct
ncp_server
*
s
;
struct
ncp_volume_info
vi
;
int
err
;
__u8
dh
;
d
=
sb
->
s_root
;
if
(
!
d
)
{
goto
dflt
;
}
i
=
d
->
d_inode
;
if
(
!
i
)
{
goto
dflt
;
}
ni
=
NCP_FINFO
(
i
);
if
(
!
ni
)
{
goto
dflt
;
}
s
=
NCP_SBP
(
sb
);
if
(
!
s
)
{
goto
dflt
;
}
if
(
!
s
->
m
.
mounted_vol
[
0
])
{
goto
dflt
;
}
err
=
ncp_dirhandle_alloc
(
s
,
ni
->
volNumber
,
ni
->
DosDirNum
,
&
dh
);
if
(
err
)
{
goto
dflt
;
}
err
=
ncp_get_directory_info
(
s
,
dh
,
&
vi
);
ncp_dirhandle_free
(
s
,
dh
);
if
(
err
)
{
goto
dflt
;
}
buf
->
f_type
=
NCP_SUPER_MAGIC
;
buf
->
f_bsize
=
vi
.
sectors_per_block
*
512
;
buf
->
f_blocks
=
vi
.
total_blocks
;
buf
->
f_bfree
=
vi
.
free_blocks
;
buf
->
f_bavail
=
vi
.
free_blocks
;
buf
->
f_files
=
vi
.
total_dir_entries
;
buf
->
f_ffree
=
vi
.
available_dir_entries
;
buf
->
f_namelen
=
12
;
return
0
;
/* We cannot say how much disk space is left on a mounted
/* We cannot say how much disk space is left on a mounted
NetWare Server, because free space is distributed over
NetWare Server, because free space is distributed over
volumes, and the current user might have disk quotas. So
volumes, and the current user might have disk quotas. So
free space is not that simple to determine. Our decision
free space is not that simple to determine. Our decision
here is to err conservatively. */
here is to err conservatively. */
dflt:
;
buf
->
f_type
=
NCP_SUPER_MAGIC
;
buf
->
f_type
=
NCP_SUPER_MAGIC
;
buf
->
f_bsize
=
NCP_BLOCK_SIZE
;
buf
->
f_bsize
=
NCP_BLOCK_SIZE
;
buf
->
f_blocks
=
0
;
buf
->
f_blocks
=
0
;
...
@@ -616,7 +647,7 @@ int ncp_notify_change(struct dentry *dentry, struct iattr *attr)
...
@@ -616,7 +647,7 @@ int ncp_notify_change(struct dentry *dentry, struct iattr *attr)
if
(((
attr
->
ia_valid
&
ATTR_MODE
)
&&
if
(((
attr
->
ia_valid
&
ATTR_MODE
)
&&
(
attr
->
ia_mode
&
(
attr
->
ia_mode
&
~
(
S_IFREG
|
S_IFDIR
|
S_IRWXU
|
S_IRWXG
|
S_IRWX
O
))))
~
(
S_IFREG
|
S_IFDIR
|
S_IRWXU
G
O
))))
goto
out
;
goto
out
;
info_mask
=
0
;
info_mask
=
0
;
...
@@ -625,58 +656,81 @@ int ncp_notify_change(struct dentry *dentry, struct iattr *attr)
...
@@ -625,58 +656,81 @@ int ncp_notify_change(struct dentry *dentry, struct iattr *attr)
#if 1
#if 1
if
((
attr
->
ia_valid
&
ATTR_MODE
)
!=
0
)
if
((
attr
->
ia_valid
&
ATTR_MODE
)
!=
0
)
{
{
umode_t
newmode
=
attr
->
ia_mode
;
info_mask
|=
DM_ATTRIBUTES
;
if
(
S_ISDIR
(
inode
->
i_mode
))
{
if
(
S_ISDIR
(
inode
->
i_mode
))
{
umode_t
newmode
;
newmode
&=
server
->
m
.
dir_mode
;
}
else
{
info_mask
|=
DM_ATTRIBUTES
;
newmode
=
attr
->
ia_mode
;
newmode
&=
NCP_SERVER
(
inode
)
->
m
.
dir_mode
;
if
(
newmode
&
0222
)
info
.
attributes
&=
~
(
aRONLY
|
aRENAMEINHIBIT
|
aDELETEINHIBIT
);
else
info
.
attributes
|=
(
aRONLY
|
aRENAMEINHIBIT
|
aDELETEINHIBIT
);
}
else
if
(
!
S_ISREG
(
inode
->
i_mode
))
{
result
=
-
EPERM
;
goto
out
;
}
else
{
umode_t
newmode
;
#ifdef CONFIG_NCPFS_EXTRAS
#ifdef CONFIG_NCPFS_EXTRAS
int
extras
;
if
(
server
->
m
.
flags
&
NCP_MOUNT_EXTRAS
)
{
/* any non-default execute bit set */
extras
=
server
->
m
.
flags
&
NCP_MOUNT_EXTRAS
;
if
(
newmode
&
~
server
->
m
.
file_mode
&
S_IXUGO
)
#endif
info_mask
|=
DM_ATTRIBUTES
;
newmode
=
attr
->
ia_mode
;
#ifdef CONFIG_NCPFS_EXTRAS
if
(
!
extras
)
#endif
newmode
&=
server
->
m
.
file_mode
;
if
(
newmode
&
0222
)
/* any write bit set */
{
info
.
attributes
&=
~
(
aRONLY
|
aRENAMEINHIBIT
|
aDELETEINHIBIT
);
}
else
{
info
.
attributes
|=
(
aRONLY
|
aRENAMEINHIBIT
|
aDELETEINHIBIT
);
}
#ifdef CONFIG_NCPFS_EXTRAS
if
(
extras
)
{
if
(
newmode
&
0111
)
/* any execute bit set */
info
.
attributes
|=
aSHARED
|
aSYSTEM
;
info
.
attributes
|=
aSHARED
|
aSYSTEM
;
/* read for group/world and not in default file_mode */
/* read for group/world and not in default file_mode */
else
if
(
newmode
&
~
server
->
m
.
file_mode
&
0444
)
else
if
(
newmode
&
~
server
->
m
.
file_mode
&
S_IRUGO
)
info
.
attributes
|=
aSHARED
;
info
.
attributes
|=
aSHARED
;
}
}
else
#endif
#endif
newmode
&=
server
->
m
.
file_mode
;
}
}
if
(
newmode
&
S_IWUGO
)
info
.
attributes
&=
~
(
aRONLY
|
aRENAMEINHIBIT
|
aDELETEINHIBIT
);
else
info
.
attributes
|=
(
aRONLY
|
aRENAMEINHIBIT
|
aDELETEINHIBIT
);
#ifdef CONFIG_NCPFS_NFS_NS
if
(
ncp_is_nfs_extras
(
server
,
NCP_FINFO
(
inode
)
->
volNumber
))
{
result
=
ncp_modify_nfs_info
(
server
,
NCP_FINFO
(
inode
)
->
volNumber
,
NCP_FINFO
(
inode
)
->
dirEntNum
,
attr
->
ia_mode
,
0
);
if
(
result
!=
0
)
goto
out
;
info
.
attributes
&=
~
(
aSHARED
|
aSYSTEM
);
{
/* mark partial success */
struct
iattr
tmpattr
;
tmpattr
.
ia_valid
=
ATTR_MODE
;
tmpattr
.
ia_mode
=
attr
->
ia_mode
;
inode_setattr
(
inode
,
&
tmpattr
);
}
}
#endif
}
}
#endif
#endif
/* Do SIZE before attributes, otherwise mtime together with size does not work...
*/
if
((
attr
->
ia_valid
&
ATTR_SIZE
)
!=
0
)
{
int
written
;
DPRINTK
(
"ncpfs: trying to change size to %ld
\n
"
,
attr
->
ia_size
);
if
((
result
=
ncp_make_open
(
inode
,
O_WRONLY
))
<
0
)
{
result
=
-
EACCES
;
goto
out
;
}
ncp_write_kernel
(
NCP_SERVER
(
inode
),
NCP_FINFO
(
inode
)
->
file_handle
,
attr
->
ia_size
,
0
,
""
,
&
written
);
/* According to ndir, the changes only take effect after
closing the file */
ncp_inode_close
(
inode
);
result
=
ncp_make_closed
(
inode
);
{
struct
iattr
tmpattr
;
tmpattr
.
ia_valid
=
ATTR_SIZE
;
tmpattr
.
ia_size
=
attr
->
ia_size
;
inode_setattr
(
inode
,
&
tmpattr
);
}
}
if
((
attr
->
ia_valid
&
ATTR_CTIME
)
!=
0
)
{
if
((
attr
->
ia_valid
&
ATTR_CTIME
)
!=
0
)
{
info_mask
|=
(
DM_CREATE_TIME
|
DM_CREATE_DATE
);
info_mask
|=
(
DM_CREATE_TIME
|
DM_CREATE_DATE
);
ncp_date_unix2dos
(
attr
->
ia_ctime
,
ncp_date_unix2dos
(
attr
->
ia_ctime
,
...
@@ -711,33 +765,16 @@ int ncp_notify_change(struct dentry *dentry, struct iattr *attr)
...
@@ -711,33 +765,16 @@ int ncp_notify_change(struct dentry *dentry, struct iattr *attr)
a terrible hack, but I do not know
a terrible hack, but I do not know
how to do this correctly. */
how to do this correctly. */
result
=
0
;
result
=
0
;
}
}
else
goto
out
;
}
}
#ifdef CONFIG_NCPFS_STRONG
#ifdef CONFIG_NCPFS_STRONG
if
((
!
result
)
&&
(
info_mask
&
DM_ATTRIBUTES
))
if
((
!
result
)
&&
(
info_mask
&
DM_ATTRIBUTES
))
NCP_FINFO
(
inode
)
->
nwattr
=
info
.
attributes
;
NCP_FINFO
(
inode
)
->
nwattr
=
info
.
attributes
;
#endif
#endif
}
}
if
((
attr
->
ia_valid
&
ATTR_SIZE
)
!=
0
)
{
if
(
!
result
)
int
written
;
inode_setattr
(
inode
,
attr
);
DPRINTK
(
"ncpfs: trying to change size to %ld
\n
"
,
attr
->
ia_size
);
if
((
result
=
ncp_make_open
(
inode
,
O_WRONLY
))
<
0
)
{
result
=
-
EACCES
;
goto
out
;
}
ncp_write_kernel
(
NCP_SERVER
(
inode
),
NCP_FINFO
(
inode
)
->
file_handle
,
attr
->
ia_size
,
0
,
""
,
&
written
);
/* According to ndir, the changes only take effect after
closing the file */
ncp_inode_close
(
inode
);
result
=
ncp_make_closed
(
inode
);
if
(
!
result
)
result
=
vmtruncate
(
inode
,
attr
->
ia_size
);
}
out:
out:
unlock_kernel
();
unlock_kernel
();
return
result
;
return
result
;
...
...
fs/ncpfs/ioctl.c
View file @
59ece965
...
@@ -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
...
...
fs/ncpfs/ncplib_kernel.c
View file @
59ece965
...
@@ -5,6 +5,7 @@
...
@@ -5,6 +5,7 @@
* Modified for big endian by J.F. Chadima and David S. Miller
* 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 1997 Peter Waltenberg, Bill Hawes, David Woodhouse for 2.1 dcache
* Modified 1999 Wolfram Pienkoss for NLS
* Modified 1999 Wolfram Pienkoss for NLS
* Modified 2000 Ben Harris, University of Cambridge for NFS NS meta-info
*
*
*/
*/
...
@@ -44,6 +45,10 @@ static void ncp_add_dword(struct ncp_server *server, __u32 x)
...
@@ -44,6 +45,10 @@ static void ncp_add_dword(struct ncp_server *server, __u32 x)
return
;
return
;
}
}
static
inline
void
ncp_add_dword_lh
(
struct
ncp_server
*
server
,
__u32
x
)
{
ncp_add_dword
(
server
,
cpu_to_le32
(
x
));
}
static
void
ncp_add_mem
(
struct
ncp_server
*
server
,
const
void
*
source
,
int
size
)
static
void
ncp_add_mem
(
struct
ncp_server
*
server
,
const
void
*
source
,
int
size
)
{
{
assert_server_locked
(
server
);
assert_server_locked
(
server
);
...
@@ -89,24 +94,43 @@ static inline char *
...
@@ -89,24 +94,43 @@ static inline char *
return
&
(
server
->
packet
[
sizeof
(
struct
ncp_reply_header
)
+
offset
]);
return
&
(
server
->
packet
[
sizeof
(
struct
ncp_reply_header
)
+
offset
]);
}
}
static
inline
__u8
BVAL
(
void
*
data
)
{
return
get_unaligned
((
__u8
*
)
data
);
}
static
__u8
static
__u8
ncp_reply_byte
(
struct
ncp_server
*
server
,
int
offset
)
ncp_reply_byte
(
struct
ncp_server
*
server
,
int
offset
)
{
{
return
get_unaligned
((
__u8
*
)
ncp_reply_data
(
server
,
offset
));
return
get_unaligned
((
__u8
*
)
ncp_reply_data
(
server
,
offset
));
}
}
static
inline
__u16
WVAL_LH
(
void
*
data
)
{
return
le16_to_cpu
(
get_unaligned
((
__u16
*
)
data
));
}
static
__u16
static
__u16
ncp_reply_word
(
struct
ncp_server
*
server
,
int
offset
)
ncp_reply_word
(
struct
ncp_server
*
server
,
int
offset
)
{
{
return
get_unaligned
((
__u16
*
)
ncp_reply_data
(
server
,
offset
));
return
get_unaligned
((
__u16
*
)
ncp_reply_data
(
server
,
offset
));
}
}
static
inline
__u32
DVAL_LH
(
void
*
data
)
{
return
le32_to_cpu
(
get_unaligned
((
__u32
*
)
data
));
}
static
__u32
static
__u32
ncp_reply_dword
(
struct
ncp_server
*
server
,
int
offset
)
ncp_reply_dword
(
struct
ncp_server
*
server
,
int
offset
)
{
{
return
get_unaligned
((
__u32
*
)
ncp_reply_data
(
server
,
offset
));
return
get_unaligned
((
__u32
*
)
ncp_reply_data
(
server
,
offset
));
}
}
static
inline
__u32
ncp_reply_dword_lh
(
struct
ncp_server
*
server
,
int
offset
)
{
return
le32_to_cpu
(
ncp_reply_dword
(
server
,
offset
));
}
int
int
ncp_negotiate_buffersize
(
struct
ncp_server
*
server
,
int
size
,
int
*
target
)
ncp_negotiate_buffersize
(
struct
ncp_server
*
server
,
int
size
,
int
*
target
)
{
{
...
@@ -159,10 +183,8 @@ ncp_negotiate_size_and_options(struct ncp_server *server,
...
@@ -159,10 +183,8 @@ ncp_negotiate_size_and_options(struct ncp_server *server,
return
0
;
return
0
;
}
}
int
int
ncp_get_volume_info_with_number
(
struct
ncp_server
*
server
,
ncp_get_volume_info_with_number
(
struct
ncp_server
*
server
,
int
n
,
int
n
,
struct
ncp_volume_info
*
target
)
{
struct
ncp_volume_info
*
target
)
{
int
result
;
int
result
;
int
len
;
int
len
;
...
@@ -172,12 +194,12 @@ ncp_get_volume_info_with_number(struct ncp_server *server, int n,
...
@@ -172,12 +194,12 @@ ncp_get_volume_info_with_number(struct ncp_server *server, int n,
if
((
result
=
ncp_request
(
server
,
22
))
!=
0
)
{
if
((
result
=
ncp_request
(
server
,
22
))
!=
0
)
{
goto
out
;
goto
out
;
}
}
target
->
total_blocks
=
ncp_reply_dword
(
server
,
0
);
target
->
total_blocks
=
ncp_reply_dword
_lh
(
server
,
0
);
target
->
free_blocks
=
ncp_reply_dword
(
server
,
4
);
target
->
free_blocks
=
ncp_reply_dword
_lh
(
server
,
4
);
target
->
purgeable_blocks
=
ncp_reply_dword
(
server
,
8
);
target
->
purgeable_blocks
=
ncp_reply_dword
_lh
(
server
,
8
);
target
->
not_yet_purgeable_blocks
=
ncp_reply_dword
(
server
,
12
);
target
->
not_yet_purgeable_blocks
=
ncp_reply_dword
_lh
(
server
,
12
);
target
->
total_dir_entries
=
ncp_reply_dword
(
server
,
16
);
target
->
total_dir_entries
=
ncp_reply_dword
_lh
(
server
,
16
);
target
->
available_dir_entries
=
ncp_reply_dword
(
server
,
20
);
target
->
available_dir_entries
=
ncp_reply_dword
_lh
(
server
,
20
);
target
->
sectors_per_block
=
ncp_reply_byte
(
server
,
28
);
target
->
sectors_per_block
=
ncp_reply_byte
(
server
,
28
);
memset
(
&
(
target
->
volume_name
),
0
,
sizeof
(
target
->
volume_name
));
memset
(
&
(
target
->
volume_name
),
0
,
sizeof
(
target
->
volume_name
));
...
@@ -195,6 +217,40 @@ ncp_get_volume_info_with_number(struct ncp_server *server, int n,
...
@@ -195,6 +217,40 @@ ncp_get_volume_info_with_number(struct ncp_server *server, int n,
return
result
;
return
result
;
}
}
int
ncp_get_directory_info
(
struct
ncp_server
*
server
,
__u8
n
,
struct
ncp_volume_info
*
target
)
{
int
result
;
int
len
;
ncp_init_request_s
(
server
,
45
);
ncp_add_byte
(
server
,
n
);
if
((
result
=
ncp_request
(
server
,
22
))
!=
0
)
{
goto
out
;
}
target
->
total_blocks
=
ncp_reply_dword_lh
(
server
,
0
);
target
->
free_blocks
=
ncp_reply_dword_lh
(
server
,
4
);
target
->
purgeable_blocks
=
0
;
target
->
not_yet_purgeable_blocks
=
0
;
target
->
total_dir_entries
=
ncp_reply_dword_lh
(
server
,
8
);
target
->
available_dir_entries
=
ncp_reply_dword_lh
(
server
,
12
);
target
->
sectors_per_block
=
ncp_reply_byte
(
server
,
20
);
memset
(
&
(
target
->
volume_name
),
0
,
sizeof
(
target
->
volume_name
));
result
=
-
EIO
;
len
=
ncp_reply_byte
(
server
,
21
);
if
(
len
>
NCP_VOLNAME_LEN
)
{
DPRINTK
(
"ncpfs: volume name too long: %d
\n
"
,
len
);
goto
out
;
}
memcpy
(
&
(
target
->
volume_name
),
ncp_reply_data
(
server
,
22
),
len
);
result
=
0
;
out:
ncp_unlock_server
(
server
);
return
result
;
}
int
int
ncp_close_file
(
struct
ncp_server
*
server
,
const
char
*
file_id
)
ncp_close_file
(
struct
ncp_server
*
server
,
const
char
*
file_id
)
{
{
...
@@ -248,10 +304,37 @@ static void ncp_add_handle_path(struct ncp_server *server, __u8 vol_num,
...
@@ -248,10 +304,37 @@ static void ncp_add_handle_path(struct ncp_server *server, __u8 vol_num,
}
}
}
}
static
void
ncp_extract_file_info
(
void
*
structure
,
struct
nw_info_struct
*
target
)
int
ncp_dirhandle_alloc
(
struct
ncp_server
*
server
,
__u8
volnum
,
__u32
dirent
,
__u8
*
dirhandle
)
{
int
result
;
ncp_init_request
(
server
);
ncp_add_byte
(
server
,
12
);
/* subfunction */
ncp_add_byte
(
server
,
NW_NS_DOS
);
ncp_add_byte
(
server
,
0
);
ncp_add_word
(
server
,
0
);
ncp_add_handle_path
(
server
,
volnum
,
dirent
,
1
,
NULL
);
if
((
result
=
ncp_request
(
server
,
87
))
==
0
)
{
*
dirhandle
=
ncp_reply_byte
(
server
,
0
);
}
ncp_unlock_server
(
server
);
return
result
;
}
int
ncp_dirhandle_free
(
struct
ncp_server
*
server
,
__u8
dirhandle
)
{
int
result
;
ncp_init_request_s
(
server
,
20
);
ncp_add_byte
(
server
,
dirhandle
);
result
=
ncp_request
(
server
,
22
);
ncp_unlock_server
(
server
);
return
result
;
}
void
ncp_extract_file_info
(
void
*
structure
,
struct
nw_info_struct
*
target
)
{
{
__u8
*
name_len
;
__u8
*
name_len
;
const
int
info_struct_size
=
sizeof
(
struct
nw_info_struct
)
-
257
;
const
int
info_struct_size
=
offsetof
(
struct
nw_info_struct
,
nameLen
)
;
memcpy
(
target
,
structure
,
info_struct_size
);
memcpy
(
target
,
structure
,
info_struct_size
);
name_len
=
structure
+
info_struct_size
;
name_len
=
structure
+
info_struct_size
;
...
@@ -261,6 +344,56 @@ static void ncp_extract_file_info(void *structure, struct nw_info_struct *target
...
@@ -261,6 +344,56 @@ static void ncp_extract_file_info(void *structure, struct nw_info_struct *target
return
;
return
;
}
}
#ifdef CONFIG_NCPFS_NFS_NS
static
inline
void
ncp_extract_nfs_info
(
unsigned
char
*
structure
,
struct
nw_nfs_info
*
target
)
{
target
->
mode
=
DVAL_LH
(
structure
);
target
->
rdev
=
DVAL_LH
(
structure
+
8
);
}
#endif
int
ncp_obtain_nfs_info
(
struct
ncp_server
*
server
,
struct
nw_info_struct
*
target
)
{
int
result
=
0
;
#ifdef CONFIG_NCPFS_NFS_NS
__u32
volnum
=
target
->
volNumber
;
if
(
ncp_is_nfs_extras
(
server
,
volnum
))
{
ncp_init_request
(
server
);
ncp_add_byte
(
server
,
19
);
/* subfunction */
ncp_add_byte
(
server
,
server
->
name_space
[
volnum
]);
ncp_add_byte
(
server
,
NW_NS_NFS
);
ncp_add_byte
(
server
,
0
);
ncp_add_byte
(
server
,
volnum
);
ncp_add_dword
(
server
,
target
->
dirEntNum
);
/* We must retrieve both nlinks and rdev, otherwise some server versions
report zeroes instead of valid data */
ncp_add_dword_lh
(
server
,
NSIBM_NFS_MODE
|
NSIBM_NFS_NLINKS
|
NSIBM_NFS_RDEV
);
if
((
result
=
ncp_request
(
server
,
87
))
==
0
)
{
ncp_extract_nfs_info
(
ncp_reply_data
(
server
,
0
),
&
target
->
nfs
);
DPRINTK
(
KERN_DEBUG
"ncp_obtain_nfs_info: (%s) mode=0%o, rdev=0x%x
\n
"
,
target
->
entryName
,
target
->
nfs
.
mode
,
target
->
nfs
.
rdev
);
}
else
{
target
->
nfs
.
mode
=
0
;
target
->
nfs
.
rdev
=
0
;
}
ncp_unlock_server
(
server
);
}
else
#endif
{
target
->
nfs
.
mode
=
0
;
target
->
nfs
.
rdev
=
0
;
}
return
result
;
}
/*
/*
* Returns information for a (one-component) name relative to
* Returns information for a (one-component) name relative to
* the specified directory.
* the specified directory.
...
@@ -287,6 +420,10 @@ int ncp_obtain_info(struct ncp_server *server, struct inode *dir, char *path,
...
@@ -287,6 +420,10 @@ int ncp_obtain_info(struct ncp_server *server, struct inode *dir, char *path,
if
((
result
=
ncp_request
(
server
,
87
))
!=
0
)
if
((
result
=
ncp_request
(
server
,
87
))
!=
0
)
goto
out
;
goto
out
;
ncp_extract_file_info
(
ncp_reply_data
(
server
,
0
),
target
);
ncp_extract_file_info
(
ncp_reply_data
(
server
,
0
),
target
);
ncp_unlock_server
(
server
);
result
=
ncp_obtain_nfs_info
(
server
,
target
);
return
result
;
out:
out:
ncp_unlock_server
(
server
);
ncp_unlock_server
(
server
);
...
@@ -463,6 +600,7 @@ ncp_lookup_volume(struct ncp_server *server, char *volname,
...
@@ -463,6 +600,7 @@ ncp_lookup_volume(struct ncp_server *server, char *volname,
/* set dates to Jan 1, 1986 00:00 */
/* set dates to Jan 1, 1986 00:00 */
target
->
creationTime
=
target
->
modifyTime
=
cpu_to_le16
(
0x0000
);
target
->
creationTime
=
target
->
modifyTime
=
cpu_to_le16
(
0x0000
);
target
->
creationDate
=
target
->
modifyDate
=
target
->
lastAccessDate
=
cpu_to_le16
(
0x0C21
);
target
->
creationDate
=
target
->
modifyDate
=
target
->
lastAccessDate
=
cpu_to_le16
(
0x0C21
);
target
->
nfs
.
mode
=
0
;
return
0
;
return
0
;
}
}
...
@@ -500,6 +638,34 @@ int ncp_modify_file_or_subdir_dos_info(struct ncp_server *server,
...
@@ -500,6 +638,34 @@ int ncp_modify_file_or_subdir_dos_info(struct ncp_server *server,
info_mask
,
info
);
info_mask
,
info
);
}
}
#ifdef CONFIG_NCPFS_NFS_NS
int
ncp_modify_nfs_info
(
struct
ncp_server
*
server
,
__u8
volnum
,
__u32
dirent
,
__u32
mode
,
__u32
rdev
)
{
int
result
=
0
;
if
(
server
->
name_space
[
volnum
]
==
NW_NS_NFS
)
{
ncp_init_request
(
server
);
ncp_add_byte
(
server
,
25
);
/* subfunction */
ncp_add_byte
(
server
,
server
->
name_space
[
volnum
]);
ncp_add_byte
(
server
,
NW_NS_NFS
);
ncp_add_byte
(
server
,
volnum
);
ncp_add_dword
(
server
,
dirent
);
/* we must always operate on both nlinks and rdev, otherwise
rdev is not set */
ncp_add_dword_lh
(
server
,
NSIBM_NFS_MODE
|
NSIBM_NFS_NLINKS
|
NSIBM_NFS_RDEV
);
ncp_add_dword_lh
(
server
,
mode
);
ncp_add_dword_lh
(
server
,
1
);
/* nlinks */
ncp_add_dword_lh
(
server
,
rdev
);
result
=
ncp_request
(
server
,
87
);
ncp_unlock_server
(
server
);
}
return
result
;
}
#endif
static
int
static
int
ncp_DeleteNSEntry
(
struct
ncp_server
*
server
,
ncp_DeleteNSEntry
(
struct
ncp_server
*
server
,
__u8
have_dir_base
,
__u8
volnum
,
__u32
dirent
,
__u8
have_dir_base
,
__u8
volnum
,
__u32
dirent
,
...
@@ -577,15 +743,12 @@ int ncp_open_create_file_or_subdir(struct ncp_server *server,
...
@@ -577,15 +743,12 @@ int ncp_open_create_file_or_subdir(struct ncp_server *server,
struct
ncp_entry_info
*
target
)
struct
ncp_entry_info
*
target
)
{
{
__u16
search_attribs
=
ntohs
(
0x0600
);
__u16
search_attribs
=
ntohs
(
0x0600
);
__u8
volnum
=
target
->
i
.
volNumber
;
__u8
volnum
;
__u32
dirent
=
target
->
i
.
dirEntNum
;
__u32
dirent
;
int
result
;
int
result
;
if
(
dir
)
volnum
=
NCP_FINFO
(
dir
)
->
volNumber
;
{
dirent
=
NCP_FINFO
(
dir
)
->
dirEntNum
;
volnum
=
NCP_FINFO
(
dir
)
->
volNumber
;
dirent
=
NCP_FINFO
(
dir
)
->
dirEntNum
;
}
if
((
create_attributes
&
aDIR
)
!=
0
)
{
if
((
create_attributes
&
aDIR
)
!=
0
)
{
search_attribs
|=
ntohs
(
0x0080
);
search_attribs
|=
ntohs
(
0x0080
);
...
@@ -606,12 +769,16 @@ int ncp_open_create_file_or_subdir(struct ncp_server *server,
...
@@ -606,12 +769,16 @@ int ncp_open_create_file_or_subdir(struct ncp_server *server,
goto
out
;
goto
out
;
if
(
!
(
create_attributes
&
aDIR
))
if
(
!
(
create_attributes
&
aDIR
))
target
->
opened
=
1
;
target
->
opened
=
1
;
target
->
server_file_handle
=
ncp_reply_dword
(
server
,
0
);
target
->
open_create_action
=
ncp_reply_byte
(
server
,
4
);
/* in target there's a new finfo to fill */
/* in target there's a new finfo to fill */
ncp_extract_file_info
(
ncp_reply_data
(
server
,
6
),
&
(
target
->
i
));
ncp_extract_file_info
(
ncp_reply_data
(
server
,
6
),
&
(
target
->
i
));
ConvertToNWfromDWORD
(
target
->
server_file_handle
,
target
->
file_handle
);
target
->
volume
=
target
->
i
.
volNumber
;
ConvertToNWfromDWORD
(
ncp_reply_dword
(
server
,
0
),
target
->
file_handle
);
ncp_unlock_server
(
server
);
(
void
)
ncp_obtain_nfs_info
(
server
,
&
(
target
->
i
));
return
0
;
out:
out:
ncp_unlock_server
(
server
);
ncp_unlock_server
(
server
);
...
@@ -672,11 +839,64 @@ int ncp_search_for_file_or_subdir(struct ncp_server *server,
...
@@ -672,11 +839,64 @@ int ncp_search_for_file_or_subdir(struct ncp_server *server,
memcpy
(
seq
,
ncp_reply_data
(
server
,
0
),
sizeof
(
*
seq
));
memcpy
(
seq
,
ncp_reply_data
(
server
,
0
),
sizeof
(
*
seq
));
ncp_extract_file_info
(
ncp_reply_data
(
server
,
10
),
target
);
ncp_extract_file_info
(
ncp_reply_data
(
server
,
10
),
target
);
ncp_unlock_server
(
server
);
result
=
ncp_obtain_nfs_info
(
server
,
target
);
return
result
;
out:
out:
ncp_unlock_server
(
server
);
ncp_unlock_server
(
server
);
return
result
;
return
result
;
}
}
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
result
;
ncp_init_request
(
server
);
ncp_add_byte
(
server
,
20
);
ncp_add_byte
(
server
,
server
->
name_space
[
seq
->
volNumber
]);
ncp_add_byte
(
server
,
0
);
/* datastream */
ncp_add_word
(
server
,
htons
(
0x0680
));
ncp_add_dword
(
server
,
RIM_ALL
);
ncp_add_word
(
server
,
32767
);
/* max returned items */
ncp_add_mem
(
server
,
seq
,
9
);
#ifdef CONFIG_NCPFS_NFS_NS
if
(
server
->
name_space
[
seq
->
volNumber
]
==
NW_NS_NFS
)
{
ncp_add_byte
(
server
,
0
);
/* 0 byte pattern */
}
else
#endif
{
ncp_add_byte
(
server
,
2
);
/* 2 byte pattern */
ncp_add_byte
(
server
,
0xff
);
/* following is a wildcard */
ncp_add_byte
(
server
,
'*'
);
}
result
=
ncp_request2
(
server
,
87
,
buffer
,
bufsize
);
if
(
result
)
{
ncp_unlock_server
(
server
);
return
result
;
}
if
(
server
->
ncp_reply_size
<
12
)
{
ncp_unlock_server
(
server
);
return
0xFF
;
}
*
rsize
=
server
->
ncp_reply_size
-
12
;
ncp_unlock_server
(
server
);
buffer
=
buffer
+
sizeof
(
struct
ncp_reply_header
);
*
rbuf
=
buffer
+
12
;
*
cnt
=
WVAL_LH
(
buffer
+
10
);
*
more
=
BVAL
(
buffer
+
9
);
memcpy
(
seq
,
buffer
,
9
);
return
0
;
}
int
int
ncp_RenameNSEntry
(
struct
ncp_server
*
server
,
ncp_RenameNSEntry
(
struct
ncp_server
*
server
,
struct
inode
*
old_dir
,
char
*
old_name
,
int
old_type
,
struct
inode
*
old_dir
,
char
*
old_name
,
int
old_type
,
...
...
fs/ncpfs/ncplib_kernel.h
View file @
59ece965
...
@@ -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
...
...
fs/ncpfs/symlink.c
View file @
59ece965
...
@@ -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
,
raw
link
,
&
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
(
raw
link
);
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
(
raw
link
);
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 ----- */
include/linux/ncp.h
View file @
59ece965
...
@@ -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 */
...
...
include/linux/ncp_fs.h
View file @
59ece965
...
@@ -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 :-) */
...
...
include/linux/ncp_fs_i.h
View file @
59ece965
...
@@ -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
;
};
};
...
...
include/linux/ncp_mount.h
View file @
59ece965
...
@@ -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
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment