📄 proc.c
字号:
if (!(p = nfs_rpc_verify(p0)))
status = NFSERR_IO;
else if ((status = ntohl(*p++)) == NFS_OK) {
p = xdr_decode_fhandle(p, fhandle);
p = xdr_decode_fattr(p, fattr);
PRINTK("NFS reply create\n");
}
else {
if (!ruid && current->euid == 0 && current->uid != 0) {
ruid = 1;
goto retry;
}
PRINTK("NFS reply create failed = %d\n", status);
}
nfs_rpc_free(p0);
return -nfs_stat_to_errno(status);
}
int nfs_proc_remove(struct nfs_server *server, struct nfs_fh *dir, const char *name)
{
int *p, *p0;
int status;
int ruid = 0;
PRINTK("NFS call remove %s\n", name);
if (!(p0 = nfs_rpc_alloc()))
return -EIO;
retry:
p = nfs_rpc_header(p0, NFSPROC_REMOVE, ruid);
p = xdr_encode_fhandle(p, dir);
p = xdr_encode_string(p, name);
if ((status = nfs_rpc_call(server, p0, p)) < 0) {
nfs_rpc_free(p0);
return status;
}
if (!(p = nfs_rpc_verify(p0)))
status = NFSERR_IO;
else if ((status = ntohl(*p++)) == NFS_OK) {
PRINTK("NFS reply remove\n");
}
else {
if (!ruid && current->euid == 0 && current->uid != 0) {
ruid = 1;
goto retry;
}
PRINTK("NFS reply remove failed = %d\n", status);
}
nfs_rpc_free(p0);
return -nfs_stat_to_errno(status);
}
int nfs_proc_rename(struct nfs_server *server,
struct nfs_fh *old_dir, const char *old_name,
struct nfs_fh *new_dir, const char *new_name)
{
int *p, *p0;
int status;
int ruid = 0;
PRINTK("NFS call rename %s -> %s\n", old_name, new_name);
if (!(p0 = nfs_rpc_alloc()))
return -EIO;
retry:
p = nfs_rpc_header(p0, NFSPROC_RENAME, ruid);
p = xdr_encode_fhandle(p, old_dir);
p = xdr_encode_string(p, old_name);
p = xdr_encode_fhandle(p, new_dir);
p = xdr_encode_string(p, new_name);
if ((status = nfs_rpc_call(server, p0, p)) < 0) {
nfs_rpc_free(p0);
return status;
}
if (!(p = nfs_rpc_verify(p0)))
status = NFSERR_IO;
else if ((status = ntohl(*p++)) == NFS_OK) {
PRINTK("NFS reply rename\n");
}
else {
if (!ruid && current->euid == 0 && current->uid != 0) {
ruid = 1;
goto retry;
}
PRINTK("NFS reply rename failed = %d\n", status);
}
nfs_rpc_free(p0);
return -nfs_stat_to_errno(status);
}
int nfs_proc_link(struct nfs_server *server, struct nfs_fh *fhandle,
struct nfs_fh *dir, const char *name)
{
int *p, *p0;
int status;
int ruid = 0;
PRINTK("NFS call link %s\n", name);
if (!(p0 = nfs_rpc_alloc()))
return -EIO;
retry:
p = nfs_rpc_header(p0, NFSPROC_LINK, ruid);
p = xdr_encode_fhandle(p, fhandle);
p = xdr_encode_fhandle(p, dir);
p = xdr_encode_string(p, name);
if ((status = nfs_rpc_call(server, p0, p)) < 0) {
nfs_rpc_free(p0);
return status;
}
if (!(p = nfs_rpc_verify(p0)))
status = NFSERR_IO;
else if ((status = ntohl(*p++)) == NFS_OK) {
PRINTK("NFS reply link\n");
}
else {
if (!ruid && current->euid == 0 && current->uid != 0) {
ruid = 1;
goto retry;
}
PRINTK("NFS reply link failed = %d\n", status);
}
nfs_rpc_free(p0);
return -nfs_stat_to_errno(status);
}
int nfs_proc_symlink(struct nfs_server *server, struct nfs_fh *dir,
const char *name, const char *path, struct nfs_sattr *sattr)
{
int *p, *p0;
int status;
int ruid = 0;
PRINTK("NFS call symlink %s -> %s\n", name, path);
if (!(p0 = nfs_rpc_alloc()))
return -EIO;
retry:
p = nfs_rpc_header(p0, NFSPROC_SYMLINK, ruid);
p = xdr_encode_fhandle(p, dir);
p = xdr_encode_string(p, name);
p = xdr_encode_string(p, path);
p = xdr_encode_sattr(p, sattr);
if ((status = nfs_rpc_call(server, p0, p)) < 0) {
nfs_rpc_free(p0);
return status;
}
if (!(p = nfs_rpc_verify(p0)))
status = NFSERR_IO;
else if ((status = ntohl(*p++)) == NFS_OK) {
PRINTK("NFS reply symlink\n");
}
else {
if (!ruid && current->euid == 0 && current->uid != 0) {
ruid = 1;
goto retry;
}
PRINTK("NFS reply symlink failed = %d\n", status);
}
nfs_rpc_free(p0);
return -nfs_stat_to_errno(status);
}
int nfs_proc_mkdir(struct nfs_server *server, struct nfs_fh *dir,
const char *name, struct nfs_sattr *sattr,
struct nfs_fh *fhandle, struct nfs_fattr *fattr)
{
int *p, *p0;
int status;
int ruid = 0;
PRINTK("NFS call mkdir %s\n", name);
if (!(p0 = nfs_rpc_alloc()))
return -EIO;
retry:
p = nfs_rpc_header(p0, NFSPROC_MKDIR, ruid);
p = xdr_encode_fhandle(p, dir);
p = xdr_encode_string(p, name);
p = xdr_encode_sattr(p, sattr);
if ((status = nfs_rpc_call(server, p0, p)) < 0) {
nfs_rpc_free(p0);
return status;
}
if (!(p = nfs_rpc_verify(p0)))
status = NFSERR_IO;
else if ((status = ntohl(*p++)) == NFS_OK) {
p = xdr_decode_fhandle(p, fhandle);
p = xdr_decode_fattr(p, fattr);
PRINTK("NFS reply mkdir\n");
}
else {
if (!ruid && current->euid == 0 && current->uid != 0) {
ruid = 1;
goto retry;
}
PRINTK("NFS reply mkdir failed = %d\n", status);
}
nfs_rpc_free(p0);
return -nfs_stat_to_errno(status);
}
int nfs_proc_rmdir(struct nfs_server *server, struct nfs_fh *dir, const char *name)
{
int *p, *p0;
int status;
int ruid = 0;
PRINTK("NFS call rmdir %s\n", name);
if (!(p0 = nfs_rpc_alloc()))
return -EIO;
retry:
p = nfs_rpc_header(p0, NFSPROC_RMDIR, ruid);
p = xdr_encode_fhandle(p, dir);
p = xdr_encode_string(p, name);
if ((status = nfs_rpc_call(server, p0, p)) < 0) {
nfs_rpc_free(p0);
return status;
}
if (!(p = nfs_rpc_verify(p0)))
status = NFSERR_IO;
else if ((status = ntohl(*p++)) == NFS_OK) {
PRINTK("NFS reply rmdir\n");
}
else {
if (!ruid && current->euid == 0 && current->uid != 0) {
ruid = 1;
goto retry;
}
PRINTK("NFS reply rmdir failed = %d\n", status);
}
nfs_rpc_free(p0);
return -nfs_stat_to_errno(status);
}
int nfs_proc_readdir(struct nfs_server *server, struct nfs_fh *fhandle,
int cookie, int count, struct nfs_entry *entry)
{
int *p, *p0;
int status;
int ruid = 0;
int i = 0; /* = 0 is for gcc */
int size;
int eof;
PRINTK("NFS call readdir %d @ %d\n", count, cookie);
size = server->rsize;
if (!(p0 = nfs_rpc_alloc()))
return -EIO;
retry:
p = nfs_rpc_header(p0, NFSPROC_READDIR, ruid);
p = xdr_encode_fhandle(p, fhandle);
*p++ = htonl(cookie);
*p++ = htonl(size);
if ((status = nfs_rpc_call(server, p0, p)) < 0) {
nfs_rpc_free(p0);
return status;
}
if (!(p = nfs_rpc_verify(p0)))
status = NFSERR_IO;
else if ((status = ntohl(*p++)) == NFS_OK) {
for (i = 0; i < count && *p++; i++) {
if (!(p = xdr_decode_entry(p, entry++)))
break;
}
if (!p) {
printk("nfs_proc_readdir: giant filename\n");
status = NFSERR_IO;
}
else {
eof = (i == count && !*p++ && *p++)
|| (i < count && *p++);
if (eof && i)
entry[-1].eof = 1;
PRINTK("NFS reply readdir %d %s\n", i,
eof ? "eof" : "");
}
}
else {
if (!ruid && current->euid == 0 && current->uid != 0) {
ruid = 1;
goto retry;
}
PRINTK("NFS reply readdir failed = %d\n", status);
}
nfs_rpc_free(p0);
return (status == NFS_OK) ? i : -nfs_stat_to_errno(status);
}
int nfs_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle,
struct nfs_fsinfo *res)
{
int *p, *p0;
int status;
int ruid = 0;
PRINTK("NFS call statfs\n");
if (!(p0 = nfs_rpc_alloc()))
return -EIO;
retry:
p = nfs_rpc_header(p0, NFSPROC_STATFS, ruid);
p = xdr_encode_fhandle(p, fhandle);
if ((status = nfs_rpc_call(server, p0, p)) < 0) {
nfs_rpc_free(p0);
return status;
}
if (!(p = nfs_rpc_verify(p0)))
status = NFSERR_IO;
else if ((status = ntohl(*p++)) == NFS_OK) {
p = xdr_decode_fsinfo(p, res);
PRINTK("NFS reply statfs\n");
}
else {
if (!ruid && current->euid == 0 && current->uid != 0) {
ruid = 1;
goto retry;
}
PRINTK("NFS reply statfs failed = %d\n", status);
}
nfs_rpc_free(p0);
return -nfs_stat_to_errno(status);
}
/*
* Here are a few RPC-assist functions.
*/
static int *nfs_rpc_header(int *p, int procedure, int ruid)
{
int *p1, *p2;
int i;
static int xid = 0;
unsigned char *sys = (unsigned char *) system_utsname.nodename;
if (xid == 0) {
xid = CURRENT_TIME;
xid ^= (sys[3]<<24) | (sys[2]<<16) | (sys[1]<<8) | sys[0];
}
*p++ = htonl(++xid);
*p++ = htonl(RPC_CALL);
*p++ = htonl(RPC_VERSION);
*p++ = htonl(NFS_PROGRAM);
*p++ = htonl(NFS_VERSION);
*p++ = htonl(procedure);
*p++ = htonl(RPC_AUTH_UNIX);
p1 = p++;
*p++ = htonl(CURRENT_TIME); /* traditional, could be anything */
p = xdr_encode_string(p, (char *) sys);
*p++ = htonl(ruid ? current->uid : current->euid);
*p++ = htonl(current->egid);
p2 = p++;
for (i = 0; i < 16 && i < NGROUPS && current->groups[i] != NOGROUP; i++)
*p++ = htonl(current->groups[i]);
*p2 = htonl(i);
*p1 = htonl((p - (p1 + 1)) << 2);
*p++ = htonl(RPC_AUTH_NULL);
*p++ = htonl(0);
return p;
}
static int *nfs_rpc_verify(int *p)
{
unsigned int n;
p++;
if ((n = ntohl(*p++)) != RPC_REPLY) {
printk("nfs_rpc_verify: not an RPC reply: %d\n", n);
return NULL;
}
if ((n = ntohl(*p++)) != RPC_MSG_ACCEPTED) {
printk("nfs_rpc_verify: RPC call rejected: %d\n", n);
return NULL;
}
switch (n = ntohl(*p++)) {
case RPC_AUTH_NULL: case RPC_AUTH_UNIX: case RPC_AUTH_SHORT:
break;
default:
printk("nfs_rpc_verify: bad RPC authentication type: %d\n", n);
return NULL;
}
if ((n = ntohl(*p++)) > 400) {
printk("nfs_rpc_verify: giant auth size\n");
return NULL;
}
p += (n + 3) >> 2;
if ((n = ntohl(*p++)) != RPC_SUCCESS) {
printk("nfs_rpc_verify: RPC call failed: %d\n", n);
return NULL;
}
return p;
}
/*
* We need to translate between nfs status return values and
* the local errno values which may not be the same.
*/
#ifndef EDQUOT
#define EDQUOT ENOSPC
#endif
static struct {
int stat;
int errno;
} nfs_errtbl[] = {
{ NFS_OK, 0 },
{ NFSERR_PERM, EPERM },
{ NFSERR_NOENT, ENOENT },
{ NFSERR_IO, EIO },
{ NFSERR_NXIO, ENXIO },
{ NFSERR_ACCES, EACCES },
{ NFSERR_EXIST, EEXIST },
{ NFSERR_NODEV, ENODEV },
{ NFSERR_NOTDIR, ENOTDIR },
{ NFSERR_ISDIR, EISDIR },
{ NFSERR_INVAL, EINVAL },
{ NFSERR_FBIG, EFBIG },
{ NFSERR_NOSPC, ENOSPC },
{ NFSERR_ROFS, EROFS },
{ NFSERR_NAMETOOLONG, ENAMETOOLONG },
{ NFSERR_NOTEMPTY, ENOTEMPTY },
{ NFSERR_DQUOT, EDQUOT },
{ NFSERR_STALE, ESTALE },
#ifdef EWFLUSH
{ NFSERR_WFLUSH, EWFLUSH },
#endif
{ -1, EIO }
};
static int nfs_stat_to_errno(int stat)
{
int i;
for (i = 0; nfs_errtbl[i].stat != -1; i++) {
if (nfs_errtbl[i].stat == stat)
return nfs_errtbl[i].errno;
}
printk("nfs_stat_to_errno: bad nfs status return value: %d\n", stat);
return nfs_errtbl[i].errno;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -