📄 proc.c
字号:
if (!(p = nfs_rpc_verify(p0))) status = -errno_NFSERR_IO; else if ((status = ntohl(*p++)) == NFS_OK) { update_vm_cache(inode, offset, kdata, count); p = xdr_decode_fattr(p, fattr); PRINTK("NFS reply write\n"); /* status = 0; */ } else { if (!ruid && current->fsuid == 0 && current->uid != 0) { ruid = 1; goto retry; } PRINTK("NFS reply write failed = %d\n", status); status = -nfs_stat_to_errno(status); } nfs_rpc_free(p0); return status;}int nfs_proc_create(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 create %s\n", name); if (!(p0 = nfs_rpc_alloc(server->wsize))) return -EIO;retry: p = nfs_rpc_header(p0, NFSPROC_CREATE, 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, server->wsize)) < 0) { nfs_rpc_free(p0); return status; } if (!(p = nfs_rpc_verify(p0))) status = -errno_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"); /* status = 0; */ } else { if (!ruid && current->fsuid == 0 && current->uid != 0) { ruid = 1; goto retry; } PRINTK("NFS reply create failed = %d\n", status); status = -nfs_stat_to_errno(status); } nfs_rpc_free(p0); return 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(server->wsize))) 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, server->wsize)) < 0) { nfs_rpc_free(p0); return status; } if (!(p = nfs_rpc_verify(p0))) status = -errno_NFSERR_IO; else if ((status = ntohl(*p++)) == NFS_OK) { PRINTK("NFS reply remove\n"); /* status = 0; */ } else { if (!ruid && current->fsuid == 0 && current->uid != 0) { ruid = 1; goto retry; } PRINTK("NFS reply remove failed = %d\n", status); status = -nfs_stat_to_errno(status); } nfs_rpc_free(p0); return 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 must_be_dir){ int *p, *p0; int status; int ruid = 0; /* * Disallow "rename()" with trailing slashes over NFS: getting * POSIX.1 behaviour is just too unlikely. */ if (must_be_dir) return -EINVAL; PRINTK("NFS call rename %s -> %s\n", old_name, new_name); if (!(p0 = nfs_rpc_alloc(server->wsize))) 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, server->wsize)) < 0) { nfs_rpc_free(p0); return status; } if (!(p = nfs_rpc_verify(p0))) status = -errno_NFSERR_IO; else if ((status = ntohl(*p++)) == NFS_OK) { PRINTK("NFS reply rename\n"); /* status = 0; */ } else { if (!ruid && current->fsuid == 0 && current->uid != 0) { ruid = 1; goto retry; } PRINTK("NFS reply rename failed = %d\n", status); status = -nfs_stat_to_errno(status); } nfs_rpc_free(p0); return 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(server->wsize))) 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, server->wsize)) < 0) { nfs_rpc_free(p0); return status; } if (!(p = nfs_rpc_verify(p0))) status = -errno_NFSERR_IO; else if ((status = ntohl(*p++)) == NFS_OK) { PRINTK("NFS reply link\n"); /* status = 0; */ } else { if (!ruid && current->fsuid == 0 && current->uid != 0) { ruid = 1; goto retry; } PRINTK("NFS reply link failed = %d\n", status); status = -nfs_stat_to_errno(status); } nfs_rpc_free(p0); return 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(server->wsize))) 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, server->wsize)) < 0) { nfs_rpc_free(p0); return status; } if (!(p = nfs_rpc_verify(p0))) status = -errno_NFSERR_IO; else if ((status = ntohl(*p++)) == NFS_OK) { PRINTK("NFS reply symlink\n"); /* status = 0; */ } else { if (!ruid && current->fsuid == 0 && current->uid != 0) { ruid = 1; goto retry; } PRINTK("NFS reply symlink failed = %d\n", status); status = -nfs_stat_to_errno(status); } nfs_rpc_free(p0); return 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(server->wsize))) 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, server->wsize)) < 0) { nfs_rpc_free(p0); return status; } if (!(p = nfs_rpc_verify(p0))) status = -errno_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"); /* status = 0; */ } else { if (!ruid && current->fsuid == 0 && current->uid != 0) { ruid = 1; goto retry; } PRINTK("NFS reply mkdir failed = %d\n", status); status = -nfs_stat_to_errno(status); } nfs_rpc_free(p0); return 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(server->wsize))) 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, server->wsize)) < 0) { nfs_rpc_free(p0); return status; } if (!(p = nfs_rpc_verify(p0))) status = -errno_NFSERR_IO; else if ((status = ntohl(*p++)) == NFS_OK) { PRINTK("NFS reply rmdir\n"); /* status = 0; */ } else { if (!ruid && current->fsuid == 0 && current->uid != 0) { ruid = 1; goto retry; } PRINTK("NFS reply rmdir failed = %d\n", status); status = -nfs_stat_to_errno(status); } nfs_rpc_free(p0); return 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; int size; int eof; PRINTK("NFS call readdir %d @ %d\n", count, cookie); size = server->rsize; if (!(p0 = nfs_rpc_alloc(server->rsize))) 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, server->rsize)) < 0) { nfs_rpc_free(p0); return status; } if (!(p = nfs_rpc_verify(p0))) status = -errno_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 = -errno_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" : ""); status = i; } } else { if (!ruid && current->fsuid == 0 && current->uid != 0) { ruid = 1; goto retry; } PRINTK("NFS reply readdir failed = %d\n", status); status = -nfs_stat_to_errno(status); } nfs_rpc_free(p0); return 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(server->rsize))) 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, server->rsize)) < 0) { nfs_rpc_free(p0); return status; } if (!(p = nfs_rpc_verify(p0))) status = -errno_NFSERR_IO; else if ((status = ntohl(*p++)) == NFS_OK) { p = xdr_decode_fsinfo(p, res); PRINTK("NFS reply statfs\n"); /* status = 0; */ } else { if (!ruid && current->fsuid == 0 && current->uid != 0) { ruid = 1; goto retry; } PRINTK("NFS reply statfs failed = %d\n", status); status = -nfs_stat_to_errno(status); } nfs_rpc_free(p0); return status;}/* * Here are a few RPC-assist functions. */int *rpc_header(int *p, int procedure, int program, int version, int uid, int gid, int *groups){ 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(program); *p++ = htonl(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(uid); *p++ = htonl(gid); p2 = p++; for (i = 0; i < 16 && i < NGROUPS && groups[i] != NOGROUP; i++) *p++ = htonl(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_header(int *p, int procedure, int ruid){ return rpc_header(p, procedure, NFS_PROGRAM, NFS_VERSION, (ruid ? current->uid : current->fsuid), current->egid, current->groups);}int *rpc_verify(int *p){ unsigned int n; p++; if ((n = ntohl(*p++)) != RPC_REPLY) { printk("nfs_rpc_verify: not an RPC reply: %x\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 += QUADLEN(n); if ((n = ntohl(*p++)) != RPC_SUCCESS) { printk("nfs_rpc_verify: RPC call failed: %d\n", n); return NULL; } return p;}static int *nfs_rpc_verify(int *p){ return rpc_verify(p);}/* * We need to translate between nfs status return values and * the local errno values which may not be the same. */static struct { int stat; int errno;} nfs_errtbl[] = { { NFS_OK, 0 }, { NFSERR_PERM, EPERM }, { NFSERR_NOENT, ENOENT }, { NFSERR_IO, errno_NFSERR_IO }, { NFSERR_NXIO, ENXIO }, { NFSERR_EAGAIN, EAGAIN }, { NFSERR_ACCES, EACCES }, { NFSERR_EXIST, EEXIST }, { NFSERR_XDEV, EXDEV }, { 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 + -