* $Id: nfs_subr.c,v 5.2 90/06/23 22:19:50 jsp Rel $
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
* This code is derived from software contributed to Berkeley by
* Jan-Simon Pendry at Imperial College, London.
* Redistribution and use in source and binary forms are permitted provided
* that: (1) source distributions retain this entire copyright notice and
* comment, and (2) distributions including binaries display the following
* acknowledgement: ``This product includes software developed by the
* University of California, Berkeley and its contributors'' in the
* documentation or other materials provided with the distribution and in
* all advertising materials mentioning features or use of this software.
* Neither the name of the University nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
* @(#)nfs_subr.c 5.1 (Berkeley) 6/29/90
* Convert from UN*X to NFS error code
((nfsstat)((e) > NFS_LOMAP && (e) < NFS_HIMAP ? \
nfs_errormap[(e) - NFS_LOMAP] : (e)))
#define nfs_error(e) ((nfsstat)(e))
#endif /* NFS_ERROR_MAPPING */
static char *do_readlink(mp
, error_return
, attrpp
)
struct attrstat
**attrpp
;
* If there is a readlink method, then use
* that, otherwise if a link exists use
* that, otherwise use the mount point.
if (mp
->am_mnt
->mf_ops
->readlink
) {
mp
= (*mp
->am_mnt
->mf_ops
->readlink
)(mp
, &retry
);
/*reschedule_timeout_mp();*/
ln
= mp
->am_mnt
->mf_mount
;
*attrpp
= &mp
->am_mnt
->mf_attr
;
nfsproc_null_2(argp
, rqstp
)
nfsproc_getattr_2(argp
, rqstp
)
static struct attrstat res
;
plog(XLOG_DEBUG
, "gettattr:");
mp
= fh_to_mp2(argp
, &retry
);
#endif /* PRECISE_SYMLINKS */
res
.status
= nfs_error(retry
);
struct attrstat
*attrp
= &mp
->am_mnt
->mf_attr
;
if (mp
->am_mnt
->mf_fattr
.type
== NFLNK
) {
* Make sure we can read the link,
* and then determine the length.
char *ln
= do_readlink(mp
, &retry
, &attrp
);
#endif /* PRECISE_SYMLINKS */
plog(XLOG_DEBUG
, "\tstat(%s), size = %d", mp
->am_path
, attrp
->attrstat_u
.attributes
.size
);
mp
->am_stats
.s_getattr
++;
nfsproc_setattr_2(argp
, rqstp
)
static struct attrstat res
;
if (!fh_to_mp(&argp
->file
))
res
.status
= nfs_error(ESTALE
);
res
.status
= nfs_error(EROFS
);
nfsproc_root_2(argp
, rqstp
)
nfsproc_lookup_2(argp
, rqstp
)
static struct diropres res
;
plog(XLOG_DEBUG
, "lookup:");
mp
= fh_to_mp2(&argp
->dir
, &retry
);
res
.status
= nfs_error(retry
);
plog(XLOG_DEBUG
, "\tlookuppn(%s, %s)", mp
->am_path
, argp
->name
);
ap
= (*mp
->am_mnt
->mf_ops
->lookuppn
)(mp
, argp
->name
, &error
, VLOOK_CREATE
);
dlog("Not sending RPC reply");
res
.status
= nfs_error(error
);
if (ap
->am_mnt
->mf_fattr
.size
< 0)
dlog("\tERROR: size = %d!", ap
->am_mnt
->mf_fattr
.size
);
mp_to_fh(ap
, &res
.diropres_u
.diropres
.file
);
res
.diropres_u
.diropres
.attributes
= ap
->am_mnt
->mf_fattr
;
/*reschedule_timeout_mp();*/
nfsproc_readlink_2(argp
, rqstp
)
static struct readlinkres res
;
plog(XLOG_DEBUG
, "readlink:");
mp
= fh_to_mp2(argp
, &retry
);
res
.status
= nfs_error(retry
);
char *ln
= do_readlink(mp
, &retry
, (struct attrstat
*) 0);
plog(XLOG_DEBUG
, "\treadlink(%s) = %s", mp
->am_path
, ln
);
res
.readlinkres_u
.data
= ln
;
mp
->am_stats
.s_readlink
++;
nfsproc_read_2(argp
, rqstp
)
static struct readres res
;
bzero((char *)&res
, sizeof(res
));
res
.status
= nfs_error(EACCES
);
nfsproc_writecache_2(argp
, rqstp
)
nfsproc_write_2(argp
, rqstp
)
static struct attrstat res
;
if (!fh_to_mp(&argp
->file
))
res
.status
= nfs_error(ESTALE
);
res
.status
= nfs_error(EROFS
);
nfsproc_create_2(argp
, rqstp
)
static struct diropres res
;
if (!fh_to_mp(&argp
->where
.dir
))
res
.status
= nfs_error(ESTALE
);
res
.status
= nfs_error(EROFS
);
unlink_or_rmdir(argp
, rqstp
, unlinkp
)
am_node
*mp
= fh_to_mp3(&argp
->dir
, &retry
, VLOOK_DELETE
);
if (mf
->mf_fattr
.type
!= NFDIR
) {
res
= nfs_error(ENOTDIR
);
plog(XLOG_DEBUG
, "\tremove(%s, %s)", mp
->am_path
, argp
->name
);
mp
= (*mp
->am_mnt
->mf_ops
->lookuppn
)(mp
, argp
->name
, &retry
, VLOOK_DELETE
);
* Usual NFS workaround...
else if (retry
== ENOENT
)
nfsproc_remove_2(argp
, rqstp
)
return unlink_or_rmdir(argp
, rqstp
, 1);
nfsproc_rename_2(argp
, rqstp
)
if (!fh_to_mp(&argp
->from
.dir
) || !fh_to_mp(&argp
->to
.dir
))
* If the kernel is doing clever things with referenced files
else if (strncmp(argp
->to
.name
, ".nfs", 4) == 0)
nfsproc_link_2(argp
, rqstp
)
if (!fh_to_mp(&argp
->from
) || !fh_to_mp(&argp
->to
.dir
))
nfsproc_symlink_2(argp
, rqstp
)
if (!fh_to_mp(&argp
->from
.dir
))
nfsproc_mkdir_2(argp
, rqstp
)
static struct diropres res
;
if (!fh_to_mp(&argp
->where
.dir
))
res
.status
= nfs_error(ESTALE
);
res
.status
= nfs_error(EROFS
);
nfsproc_rmdir_2(argp
, rqstp
)
return unlink_or_rmdir(argp
, rqstp
, 0);
nfsproc_readdir_2(argp
, rqstp
)
plog(XLOG_DEBUG
, "readdir:");
mp
= fh_to_mp2(&argp
->dir
, &retry
);
res
.status
= nfs_error(retry
);
plog(XLOG_DEBUG
, "\treaddir(%s)", mp
->am_path
);
res
.status
= nfs_error((*mp
->am_mnt
->mf_ops
->readdir
)(mp
, argp
->cookie
,
&res
.readdirres_u
.reply
, e_res
));
mp
->am_stats
.s_readdir
++;
/* XXX - need to take argp->count into account */
nfsproc_statfs_2(argp
, rqstp
)
plog(XLOG_DEBUG
, "statfs:");
mp
= fh_to_mp2(argp
, &retry
);
res
.status
= nfs_error(retry
);
plog(XLOG_DEBUG
, "\tstat_fs(%s)", mp
->am_path
);
* just return faked up file system information
fp
= &res
.statfsres_u
.reply
;