⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 proc.c

📁 Linux 1.0 内核C源代码 Linux最早版本代码 由Linus Torvalds亲自书写的
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
 *  linux/fs/nfs/proc.c
 *
 *  Copyright (C) 1992, 1993, 1994  Rick Sladkey
 *
 *  OS-independent nfs remote procedure call functions
 */

/*
 * Defining NFS_PROC_DEBUG causes a lookup of a file named
 * "xyzzy" to toggle debugging.  Just cd to an NFS-mounted
 * filesystem and type 'ls xyzzy' to turn on debugging.
 */

#if 0
#define NFS_PROC_DEBUG
#endif

#include <linux/config.h>
#include <linux/param.h>
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/nfs_fs.h>
#include <linux/utsname.h>
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/in.h>

#ifdef NFS_PROC_DEBUG

static int proc_debug = 0;
#define PRINTK(format, args...) \
	do {						\
		if (proc_debug)				\
			printk(format , ## args);	\
	} while (0)

#else /* !NFS_PROC_DEBUG */

#define PRINTK(format, args...) do ; while (0)

#endif /* !NFS_PROC_DEBUG */

static int *nfs_rpc_header(int *p, int procedure, int ruid);
static int *nfs_rpc_verify(int *p);
static int nfs_stat_to_errno(int stat);

/*
 * Our memory allocation and release functions.
 */

static inline int *nfs_rpc_alloc(void)
{
	return (int *) __get_free_page(GFP_KERNEL);
}

static inline void nfs_rpc_free(int *p)
{
	free_page((long) p);
}

/*
 * Here are a bunch of xdr encode/decode functions that convert
 * between machine dependent and xdr data formats.
 */

static inline int *xdr_encode_fhandle(int *p, struct nfs_fh *fhandle)
{
	*((struct nfs_fh *) p) = *fhandle;
	p += (sizeof (*fhandle) + 3) >> 2;
	return p;
}

static inline int *xdr_decode_fhandle(int *p, struct nfs_fh *fhandle)
{
	*fhandle = *((struct nfs_fh *) p);
	p += (sizeof (*fhandle) + 3) >> 2;
	return p;
}

static inline int *xdr_encode_string(int *p, const char *string)
{
	int len, quadlen;
	
	len = strlen(string);
	quadlen = (len + 3) >> 2;
	*p++ = htonl(len);
	memcpy((char *) p, string, len);
	memset(((char *) p) + len, '\0', (quadlen << 2) - len);
	p += quadlen;
	return p;
}

static inline int *xdr_decode_string(int *p, char *string, int maxlen)
{
	unsigned int len;

	len = ntohl(*p++);
	if (len > maxlen)
		return NULL;
	memcpy(string, (char *) p, len);
	string[len] = '\0';
	p += (len + 3) >> 2;
	return p;
}

static inline int *xdr_encode_data(int *p, char *data, int len)
{
	int quadlen;
	
	quadlen = (len + 3) >> 2;
	*p++ = htonl(len);
	memcpy((char *) p, data, len);
	memset(((char *) p) + len, '\0', (quadlen << 2) - len);
	p += quadlen;
	return p;
}

static inline int *xdr_decode_data(int *p, char *data, int *lenp, int maxlen)
{
	unsigned int len;

	len = *lenp = ntohl(*p++);
	if (len > maxlen)
		return NULL;
	memcpy(data, (char *) p, len);
	p += (len + 3) >> 2;
	return p;
}

static int *xdr_decode_fattr(int *p, struct nfs_fattr *fattr)
{
	fattr->type = (enum nfs_ftype) ntohl(*p++);
	fattr->mode = ntohl(*p++);
	fattr->nlink = ntohl(*p++);
	fattr->uid = ntohl(*p++);
	fattr->gid = ntohl(*p++);
	fattr->size = ntohl(*p++);
	fattr->blocksize = ntohl(*p++);
	fattr->rdev = ntohl(*p++);
	fattr->blocks = ntohl(*p++);
	fattr->fsid = ntohl(*p++);
	fattr->fileid = ntohl(*p++);
	fattr->atime.seconds = ntohl(*p++);
	fattr->atime.useconds = ntohl(*p++);
	fattr->mtime.seconds = ntohl(*p++);
	fattr->mtime.useconds = ntohl(*p++);
	fattr->ctime.seconds = ntohl(*p++);
	fattr->ctime.useconds = ntohl(*p++);
	return p;
}

static int *xdr_encode_sattr(int *p, struct nfs_sattr *sattr)
{
	*p++ = htonl(sattr->mode);
	*p++ = htonl(sattr->uid);
	*p++ = htonl(sattr->gid);
	*p++ = htonl(sattr->size);
	*p++ = htonl(sattr->atime.seconds);
	*p++ = htonl(sattr->atime.useconds);
	*p++ = htonl(sattr->mtime.seconds);
	*p++ = htonl(sattr->mtime.useconds);
	return p;
}

static int *xdr_decode_entry(int *p, struct nfs_entry *entry)
{
	entry->fileid = ntohl(*p++);
	if (!(p = xdr_decode_string(p, entry->name, NFS_MAXNAMLEN)))
		return NULL;
	entry->cookie = ntohl(*p++);
	entry->eof = 0;
	return p;
}

static int *xdr_decode_fsinfo(int *p, struct nfs_fsinfo *res)
{
	res->tsize = ntohl(*p++);
	res->bsize = ntohl(*p++);
	res->blocks = ntohl(*p++);
	res->bfree = ntohl(*p++);
	res->bavail = ntohl(*p++);
	return p;
}

/*
 * One function for each procedure in the NFS protocol.
 */

int nfs_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,
		     struct nfs_fattr *fattr)
{
	int *p, *p0;
	int status;
	int ruid = 0;

	PRINTK("NFS call  getattr\n");
	if (!(p0 = nfs_rpc_alloc()))
		return -EIO;
retry:
	p = nfs_rpc_header(p0, NFSPROC_GETATTR, 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_fattr(p, fattr);
		PRINTK("NFS reply getattr\n");
	}
	else {
		if (!ruid && current->euid == 0 && current->uid != 0) {
			ruid = 1;
			goto retry;
		}
		PRINTK("NFS reply getattr failed = %d\n", status);
	}
	nfs_rpc_free(p0);
	return -nfs_stat_to_errno(status);
}

int nfs_proc_setattr(struct nfs_server *server, struct nfs_fh *fhandle,
		     struct nfs_sattr *sattr, struct nfs_fattr *fattr)
{
	int *p, *p0;
	int status;
	int ruid = 0;

	PRINTK("NFS call  setattr\n");
	if (!(p0 = nfs_rpc_alloc()))
		return -EIO;
retry:
	p = nfs_rpc_header(p0, NFSPROC_SETATTR, ruid);
	p = xdr_encode_fhandle(p, fhandle);
	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_fattr(p, fattr);
		PRINTK("NFS reply setattr\n");
	}
	else {
		if (!ruid && current->euid == 0 && current->uid != 0) {
			ruid = 1;
			goto retry;
		}
		PRINTK("NFS reply setattr failed = %d\n", status);
	}
	nfs_rpc_free(p0);
	return -nfs_stat_to_errno(status);
}

int nfs_proc_lookup(struct nfs_server *server, struct nfs_fh *dir, const char *name,
		    struct nfs_fh *fhandle, struct nfs_fattr *fattr)
{
	int *p, *p0;
	int status;
	int ruid = 0;

	PRINTK("NFS call  lookup %s\n", name);
#ifdef NFS_PROC_DEBUG
	if (!strcmp(name, "xyzzy"))
		proc_debug = 1 - proc_debug;
#endif
	if (!(p0 = nfs_rpc_alloc()))
		return -EIO;
retry:
	p = nfs_rpc_header(p0, NFSPROC_LOOKUP, 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) {
		p = xdr_decode_fhandle(p, fhandle);
		p = xdr_decode_fattr(p, fattr);
		PRINTK("NFS reply lookup\n");
	}
	else {
		if (!ruid && current->euid == 0 && current->uid != 0) {
			ruid = 1;
			goto retry;
		}
		PRINTK("NFS reply lookup failed = %d\n", status);
	}
	nfs_rpc_free(p0);
	return -nfs_stat_to_errno(status);
}

int nfs_proc_readlink(struct nfs_server *server, struct nfs_fh *fhandle,
		      char *res)
{
	int *p, *p0;
	int status;
	int ruid = 0;

	PRINTK("NFS call  readlink\n");
	if (!(p0 = nfs_rpc_alloc()))
		return -EIO;
retry:
	p = nfs_rpc_header(p0, NFSPROC_READLINK, 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) {
		if (!(p = xdr_decode_string(p, res, NFS_MAXPATHLEN))) {
			printk("nfs_proc_readlink: giant pathname\n");
			status = NFSERR_IO;
		}
		else
			PRINTK("NFS reply readlink %s\n", res);
	}
	else {
		if (!ruid && current->euid == 0 && current->uid != 0) {
			ruid = 1;
			goto retry;
		}
		PRINTK("NFS reply readlink failed = %d\n", status);
	}
	nfs_rpc_free(p0);
	return -nfs_stat_to_errno(status);
}

int nfs_proc_read(struct nfs_server *server, struct nfs_fh *fhandle,
		  int offset, int count, char *data, struct nfs_fattr *fattr)
{
	int *p, *p0;
	int status;
	int ruid = 0;
	int len = 0; /* = 0 is for gcc */

	PRINTK("NFS call  read %d @ %d\n", count, offset);
	if (!(p0 = nfs_rpc_alloc()))
		return -EIO;
retry:
	p = nfs_rpc_header(p0, NFSPROC_READ, ruid);
	p = xdr_encode_fhandle(p, fhandle);
	*p++ = htonl(offset);
	*p++ = htonl(count);
	*p++ = htonl(count); /* traditional, could be any value */
	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_fattr(p, fattr);
		if (!(p = xdr_decode_data(p, data, &len, count))) {
			printk("nfs_proc_read: giant data size\n"); 
			status = NFSERR_IO;
		}
		else
			PRINTK("NFS reply read %d\n", len);
	}
	else {
		if (!ruid && current->euid == 0 && current->uid != 0) {
			ruid = 1;
			goto retry;
		}
		PRINTK("NFS reply read failed = %d\n", status);
	}
	nfs_rpc_free(p0);
	return (status == NFS_OK) ? len : -nfs_stat_to_errno(status);
}

int nfs_proc_write(struct nfs_server *server, struct nfs_fh *fhandle,
		   int offset, int count, char *data, struct nfs_fattr *fattr)
{
	int *p, *p0;
	int status;
	int ruid = 0;

	PRINTK("NFS call  write %d @ %d\n", count, offset);
	if (!(p0 = nfs_rpc_alloc()))
		return -EIO;
retry:
	p = nfs_rpc_header(p0, NFSPROC_WRITE, ruid);
	p = xdr_encode_fhandle(p, fhandle);
	*p++ = htonl(offset); /* traditional, could be any value */
	*p++ = htonl(offset);
	*p++ = htonl(count); /* traditional, could be any value */
	p = xdr_encode_data(p, data, count);
	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_fattr(p, fattr);
		PRINTK("NFS reply write\n");
	}
	else {
		if (!ruid && current->euid == 0 && current->uid != 0) {
			ruid = 1;
			goto retry;
		}
		PRINTK("NFS reply write failed = %d\n", status);
	}
	nfs_rpc_free(p0);
	return -nfs_stat_to_errno(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()))
		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)) < 0) {
		nfs_rpc_free(p0);
		return status;
	}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -