This is nfs_funcs.c in view mode; [Download] [Up]
/*
* Name: nfs_funcs.c
* Description: This module contains the dispatcher for the nfs server
* functions and stubs for these functions. They provide their service
* based on the functions of 'fo_nfs.c'. The common interface is
* defined in 'my_defines.h'.
* Author: Christian Starkjohann <cs@hal.kph.tuwien.ac.at>
* Date: 1996-12-14
* Copyright: GNU-GPL
* Tabsize: 4
*/
#define NFSCLIENT
#include "syshdr.h"
#include <rpc/rpc.h>
#include "my_defines.h"
#include "nfs_prot.h"
#define DPRINTF(arg) if(debug_mode & DEBUG_NFS) dprintf arg
#define NDPRINTF(arg) if(debug_mode & DEBUG_NFS_NOISY) dprintf arg
#define NFS_MAX_GROUPS 50
int nfs_uid;
int nfs_gid;
short nfs_gids[NFS_MAX_GROUPS];
int nfs_gidslen; /* gids in nfs_gids */
/* ------------------------------------------------------------------------- */
#define FH(fh) (*(fh_t *)(fh))
#define FHP(fh) ((fh_t *)(fh))
/* ------------------------------------------------------------------------- */
static inline void set_ids(struct svc_req *rqstp)
{
#if 0 /* currently no authentication used */
int i;
if (rqstp->rq_cred.oa_flavor == AUTH_UNIX) {
struct authunix_parms *unix_cred;
unix_cred = (struct authunix_parms *) rqstp->rq_clntcred;
nfs_uid = unix_cred->aup_uid;
nfs_gid = unix_cred->aup_gid;
nfs_gidslen = unix_cred->aup_len > NFS_MAX_GROUPS ?
NFS_MAX_GROUPS : unix_cred->aup_len;
for(i=0;i<nfs_gidslen;i++)
nfs_gids[i] = unix_cred->aup_gids[i];
} else {
nfs_uid = -1;
nfs_gid = -1;
/* Construct a list of one gid. */
nfs_gidslen = 1;
nfs_gids[0] = -1;
}
/* set_current_ids(nfs_uid, nfs_gid);*/
#endif
}
/* ------------------------------------------------------------------------- */
static void input_attr(my_attr_t *ma, sattr *sa)
{
ma->mode = sa->mode;
ma->nlink = -1;
ma->uid = sa->uid;
ma->gid = sa->gid;
ma->size = sa->size;
ma->blocksize = -1;
ma->blocks = -1;
ma->fileid = -1;
ma->atime = sa->atime.seconds; /* ignored in lower level */
ma->mtime = sa->mtime.seconds;
ma->ctime = -1;
}
/* ------------------------------------------------------------------------- */
static void output_attr(my_attr_t *ma, fattr *fa)
{
fa->type = NFNON;
if((ma->mode & NFSMODE_FMT) == NFSMODE_DIR)
fa->type = NFDIR;
else if((ma->mode & NFSMODE_FMT) == NFSMODE_REG)
fa->type = NFREG;
else if((ma->mode & NFSMODE_FMT) == NFSMODE_LNK)
fa->type = NFLNK;
else if((ma->mode & NFSMODE_FMT) == NFSMODE_CHR)
fa->type = NFCHR;
else if((ma->mode & NFSMODE_FMT) == NFSMODE_BLK)
fa->type = NFBLK;
else if((ma->mode & NFSMODE_FMT) == NFSMODE_SOCK)
fa->type = NFSOCK;
else if((ma->mode & NFSMODE_FMT) == NFSMODE_FIFO)
fa->type = NFFIFO;
else{
eprintf("** output_attr(): file type unknown: mode=0%o\n", ma->mode);
}
fa->mode = ma->mode;
fa->nlink = ma->nlink;
fa->uid = ma->uid;
fa->gid = ma->gid;
fa->size = ma->size;
fa->blocksize = ma->blocksize;
fa->blocks = ma->blocks;
fa->fsid = 562654; /* dummy non zero value */
fa->fileid = ma->fileid;
fa->atime.seconds = ma->atime;
fa->mtime.seconds = ma->mtime;
fa->ctime.seconds = ma->ctime;
fa->rdev = ma->rdev;
NDPRINTF(("output_attr(): attributes are:\n"));
NDPRINTF((" type = %d\n", fa->type));
NDPRINTF((" mode = 0%o\n", fa->mode));
NDPRINTF((" nlink = %d\n", fa->nlink));
NDPRINTF((" uid = %d\n", fa->uid));
NDPRINTF((" gid = %d\n", fa->gid));
NDPRINTF((" size = %d\n", fa->size));
NDPRINTF((" blocksize = %d\n", fa->blocksize));
NDPRINTF((" blocks = %d\n", fa->blocks));
NDPRINTF((" fileid = %d\n", fa->fileid));
}
/* ------------------------------------------------------------------------- */
static int nfs_errno(int sys_errno)
{
switch(sys_errno){
case 0:
return NFS_OK;
case EPERM:
return NFSERR_PERM;
case ENOENT:
return NFSERR_NOENT;
case ENXIO:
return NFSERR_NXIO;
case ETXTBSY:
case EWOULDBLOCK:
case EACCES:
return NFSERR_ACCES;
case EEXIST:
return NFSERR_EXIST;
case ENODEV:
return NFSERR_NODEV;
case ENOTDIR:
return NFSERR_NOTDIR;
case EISDIR:
return NFSERR_ISDIR;
case E2BIG:
case EFBIG:
return NFSERR_FBIG;
case ENOSPC:
return NFSERR_NOSPC;
case EROFS:
return NFSERR_ROFS;
case ENAMETOOLONG:
return NFSERR_NAMETOOLONG;
case ENOTEMPTY:
return NFSERR_NOTEMPTY;
case EDQUOT:
return NFSERR_DQUOT;
case MY_NFSERR_STALE:
return NFSERR_STALE;
default: /* this is general enough for a reasonable error default */
return NFSERR_IO;
}
}
/* ------------------------------------------------------------------------- */
static struct diropres *nfsproc_create(createargs *ca)
{
static diropres res;
my_attr_t fa, sa;
bzero(&res, sizeof(res));
input_attr(&sa, &ca->attributes);
res.status = nfs_errno(-fo_create(FHP(&res.diropres_u.diropres.file),
&fa,
FH(&ca->where.dir),
ca->where.name,
&sa));
DPRINTF(("nfsproc_create(dir=%d, name=%s, size=%d)->%d, inode=%d\n",
(int)FH(&ca->where.dir), ca->where.name, ca->attributes.size,
res.status, (int)FH(&res.diropres_u.diropres.file)));
if(res.status == NFS_OK)
output_attr(&fa, &res.diropres_u.diropres.attributes);
return &res;
}
/* ------------------------------------------------------------------------- */
static struct diropres *nfsproc_mkdir(createargs *ca)
{
static diropres res;
my_attr_t fa, sa;
bzero(&res, sizeof(res));
input_attr(&sa, &ca->attributes);
res.status = nfs_errno(-fo_mkdir(FHP(&res.diropres_u.diropres.file),
&fa,
FH(&(ca->where.dir)),
ca->where.name,
&sa));
DPRINTF(("nfsproc_mkdir(dir=%d, name=%s)->%d, inode=%d\n",
(int)FH(&ca->where.dir), ca->where.name, res.status,
(int)FH(&res.diropres_u.diropres.file)));
if(res.status == NFS_OK)
output_attr(&fa, &res.diropres_u.diropres.attributes);
return &res;
}
/* ------------------------------------------------------------------------- */
static struct attrstat *nfsproc_getattr(struct nfs_fh *fh)
{
static attrstat res;
my_attr_t fa;
bzero(&res, sizeof(res));
res.status = nfs_errno(-fo_getattr(&fa, FH(fh)));
DPRINTF(("nfsproc_getattr(fh=%d)->%d\n", (int)FH(fh), res.status));
if(res.status == NFS_OK)
output_attr(&fa, &res.attrstat_u.attributes);
return &res;
}
/* ------------------------------------------------------------------------- */
static struct diropres *nfsproc_lookup(diropargs *da)
{
static diropres res;
my_attr_t fa;
bzero(&res, sizeof(res));
res.status = nfs_errno(-fo_lookup(FHP(&res.diropres_u.diropres.file),
&fa,
FH(&(da->dir)),
da->name));
DPRINTF(("nfsproc_lookup(dir=%d, name=%s)->%d, inode=%d\n",
(int)FH(&da->dir), da->name, res.status,
(int)FH(&res.diropres_u.diropres.file)));
if(res.status == NFS_OK)
output_attr(&fa, &res.diropres_u.diropres.attributes);
return &res;
}
/* ------------------------------------------------------------------------- */
static struct readdirres *nfsproc_readdir(readdirargs *ra)
{
static readdirres res;
struct entry *p, *q;
int eof, rval;
for(p=res.readdirres_u.reply.entries; p!=NULL; p=q){
q = p->nextentry;
free(p->name);
free(p);
}
bzero(&res, sizeof(res));
rval = fo_readdir((my_direntry_t **)&res.readdirres_u.reply.entries,
&eof,
ra->count,
FH(&(ra->dir)),
ntohl(*(int *)(ra->cookie)));
for(p=res.readdirres_u.reply.entries; p!=NULL; p=p->nextentry){
*(int *)p->cookie = htonl(*(int *)p->cookie);
}
res.status = rval < 0 ? nfs_errno(-rval) : NFS_OK;
res.readdirres_u.reply.eof = eof;
DPRINTF(("nfsproc_readdir(dir=%d, max=%d)->%d, EOF=%d\n",
(int)FH(&ra->dir), ra->count, res.status, eof));
return &res;
}
/* ------------------------------------------------------------------------- */
static struct attrstat *nfsproc_setattr(sattrargs *sa)
{
static attrstat res;
my_attr_t msa, fa;
bzero(&res, sizeof(res));
input_attr(&msa, &sa->attributes);
res.status = nfs_errno(-fo_setattr(&fa, FH(&(sa->file)), &msa));
DPRINTF(("nfsproc_setattr(fh=%d)->%d\n", (int)FH(&sa->file),res.status));
if(res.status == NFS_OK)
output_attr(&fa, &res.attrstat_u.attributes);
return &res;
}
/* ------------------------------------------------------------------------- */
static nfsstat *nfsproc_remove(diropargs *da)
{
static nfsstat res;
bzero(&res, sizeof(res));
res = nfs_errno(-fo_remove(FH(&(da->dir)), da->name));
DPRINTF(("nfsproc_remove(dir=%d, name=%s)->%d\n",
(int)FH(&da->dir), da->name, res));
return &res;
}
/* ------------------------------------------------------------------------- */
static nfsstat *nfsproc_rmdir(diropargs *da)
{
static nfsstat res;
bzero(&res, sizeof(res));
res = nfs_errno(-fo_rmdir(FH(&(da->dir)), da->name));
DPRINTF(("nfsproc_rmdir(dir=%d, name=%s)->%d\n",
(int)FH(&da->dir), da->name, res));
return &res;
}
/* ------------------------------------------------------------------------- */
static nfsstat *nfsproc_rename(renameargs *ra)
{
static nfsstat res;
bzero(&res, sizeof(res));
res = nfs_errno(-fo_rename(FH(&(ra->from.dir)), ra->from.name,
FH(&(ra->to.dir)), ra->to.name));
DPRINTF(("nfsproc_rename(dir=%d, name=%s -> dir=%d, name=%s)->%d\n",
(int)FH(&ra->from.dir), ra->from.name,
(int)FH(&ra->to.dir), ra->to.name, res));
return &res;
}
/* ------------------------------------------------------------------------- */
static struct statfsres *nfsproc_statfs(struct nfs_fh *fh)
{
static statfsres res;
my_statfs_t my_stat;
bzero(&res, sizeof(res));
res.status = nfs_errno(-fo_statfs(&my_stat));
res.statfsres_u.reply.tsize = 32768;
res.statfsres_u.reply.bsize = my_stat.bsize;
res.statfsres_u.reply.blocks = my_stat.blocks;
res.statfsres_u.reply.bfree = my_stat.bfree;
res.statfsres_u.reply.bavail = my_stat.bavail;
DPRINTF(("nfsproc_statfs()->%d\n", res.status));
DPRINTF(("bsize=%ld blocks=%ld free=%ld avail=%ld\n",
my_stat.bsize, my_stat.blocks, my_stat.bfree, my_stat.bavail));
return &res;
}
/* ------------------------------------------------------------------------- */
static struct readres *nfsproc_read(struct readargs *ra)
{
static readres res;
my_attr_t fa;
bzero(&res, sizeof(res));
res.status = nfs_errno(-fo_read(&fa,
&res.readres_u.reply.data.data_len,
&res.readres_u.reply.data.data_val,
FH(&(ra->file)),
ra->offset,
ra->count));
DPRINTF(("nfsproc_read(fh=%d, offs=%d, len=%d)->%d, len=%d\n",
(int)FH(&ra->file), (int)ra->offset, (int)ra->count,
res.status, (int)res.readres_u.reply.data.data_len));
if(res.status == NFS_OK)
output_attr(&fa, &res.readres_u.reply.attributes);
return &res;
}
/* ------------------------------------------------------------------------- */
static struct attrstat *nfsproc_write(writeargs *wa)
{
static attrstat res;
my_attr_t fa;
bzero(&res, sizeof(res));
res.status = nfs_errno(-fo_write(&fa,
FH(&(wa->file)),
wa->offset,
wa->data.data_len,
wa->data.data_val));
DPRINTF(("nfsproc_write(fh=%d, offs=%d, len=%d)->%d, len=%d\n",
(int)FH(&wa->file), (int)wa->offset, (int)wa->data.data_len,
res.status, fa.size));
if(res.status == NFS_OK)
output_attr(&fa, &res.attrstat_u.attributes);
return &res;
}
/* ------------------------------------------------------------------------- */
static nfsstat *nfsproc_link(linkargs *la)
{
static nfsstat res;
bzero(&res, sizeof(res));
res = nfs_errno(-fo_link(FH(&(la->from)), FH(&(la->to.dir)), la->to.name));
DPRINTF(("nfsproc_link(fh=%d, todir=%d, toname=%s)->%d\n",
(int)FH(&la->from), (int)FH(&la->to.dir), la->to.name, res));
return &res;
}
/* ------------------------------------------------------------------------- */
static struct readlinkres *nfsproc_readlink(struct nfs_fh *fh)
{
static readlinkres res;
int rval;
bzero(&res, sizeof(res));
rval = fo_readlink(&res.readlinkres_u.data, FH(fh));
res.status = rval < 0 ? nfs_errno(-rval) : NFS_OK;
DPRINTF(("nfsproc_readlink(fh=%d)->%d, path=%s\n",
(int)FH(fh), res.status, res.readlinkres_u.data));
return &res;
}
/* ------------------------------------------------------------------------- */
static nfsstat *nfsproc_symlink(symlinkargs *sa)
{
static nfsstat res;
my_attr_t msa;
bzero(&res, sizeof(res));
input_attr(&msa, &sa->attributes);
res = nfs_errno(-fo_symlink(FH(&sa->from.dir), sa->from.name,sa->to,&msa));
DPRINTF(("nfsproc_symlink(dir=%d, name=%s, path=%s)->%d\n",
(int)FH(&sa->from.dir), sa->from.name, sa->to, res));
return &res;
}
/* ------------------------------------------------------------------------- */
/* Dummy routines */
static void *nfsproc_writecache()
{
static nfsstat res;
eprintf("** nfsproc_writecache()\n");
res = NFSERR_FBIG;
return &res;
}
/* ------------------------------------------------------------------------- */
static void *nfsproc_null()
{
static nfsstat res;
eprintf("** nfsproc_null()\n");
res = NFSERR_FBIG;
return &res;
}
/* ------------------------------------------------------------------------- */
static void *nfsproc_root()
{
static nfsstat res;
eprintf("** nfsproc_root()\n");
res = NFSERR_FBIG;
return &res;
}
/* ------------------------------------------------------------------------- */
#define ENTRY(res_type, arg_type, funct) { \
sizeof(res_type), sizeof(arg_type), \
xdr_##res_type, xdr_##arg_type, \
(void *(*)())nfsproc_##funct, #funct \
}
#define nil char
#define xdr_nil xdr_void
struct dentry {
int res_size, arg_size; /* sizeof the res/arg structs */
bool_t (*xdr_result)();
bool_t (*xdr_argument)();
void *(*function)(); /* function handler */
char *name; /* name of function */
};
/* ------------------------------------------------------------------------- */
static struct dentry dispatch_table[] = {
ENTRY(nil, nil, null), /* NULL */
ENTRY(attrstat, nfs_fh, getattr), /* GETATTR */
ENTRY(attrstat, sattrargs, setattr), /* SETATTR */
ENTRY(nil, nil, root), /* ROOT */
ENTRY(diropres, diropargs, lookup), /* LOOKUP */
ENTRY(readlinkres, nfs_fh, readlink), /* READLINK */
ENTRY(readres, readargs, read), /* READ */
ENTRY(nil, nil, writecache), /* WRITECACHE */
ENTRY(attrstat, writeargs, write), /* WRITE */
ENTRY(diropres, createargs, create), /* CREATE */
ENTRY(nfsstat, diropargs, remove), /* REMOVE */
ENTRY(nfsstat, renameargs, rename), /* RENAME */
ENTRY(nfsstat, linkargs, link), /* LINK */
ENTRY(nfsstat, symlinkargs, symlink), /* SYMLINK */
ENTRY(diropres, createargs, mkdir), /* MKDIR */
ENTRY(nfsstat, diropargs, rmdir), /* RMDIR */
ENTRY(readdirres, readdirargs, readdir),/* READDIR */
ENTRY(statfsres, nfs_fh, statfs), /* STATFS */
};
/* ------------------------------------------------------------------------- */
void nfs_dispatch(struct svc_req *rqstp, SVCXPRT *transp)
{
unsigned int proc_i = rqstp->rq_proc;
struct dentry *dent;
void *result;
union {
nfs_fh nfsproc_getattr_2_arg;
sattrargs nfsproc_setattr_2_arg;
diropargs nfsproc_lookup_2_arg;
nfs_fh nfsproc_readlink_2_arg;
readargs nfsproc_read_2_arg;
writeargs nfsproc_write_2_arg;
createargs nfsproc_create_2_arg;
diropargs nfsproc_remove_2_arg;
renameargs nfsproc_rename_2_arg;
linkargs nfsproc_link_2_arg;
symlinkargs nfsproc_symlink_2_arg;
createargs nfsproc_mkdir_2_arg;
diropargs nfsproc_rmdir_2_arg;
readdirargs nfsproc_readdir_2_arg;
nfs_fh nfsproc_statfs_2_arg;
} argument;
if (proc_i >= (sizeof(dispatch_table) / sizeof(struct entry))){
svcerr_noproc(transp);
DPRINTF(("nfs_dispatch(): illegal procedure %d\n", proc_i));
return;
}
dent = &dispatch_table[proc_i];
bzero(&argument, dent->arg_size);
if (!svc_getargs(transp, dent->xdr_argument, &argument)){
svcerr_decode(transp);
DPRINTF(("nfs_dispatch(): error decoding arguments for %d\n", proc_i));
return;
}
set_ids(rqstp);
result = (*dent->function) (&argument);
if (result != NULL && !svc_sendreply(transp, dent->xdr_result, result)){
svcerr_systemerr(transp);
}
if (!svc_freeargs(transp, dent->xdr_argument, &argument)){
eprintf("nfs_dispatch: unable to free arguments\n");
terminate(1);
}
}
/* ------------------------------------------------------------------------- */
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.