home *** CD-ROM | disk | FTP | other *** search
- /*
- * nfs.c --
- * NFS server implementation for PC. Runs on top of the
- * net daemon (netd.c).
- *
- * Author:
- * See-Mong Tan, 6/12/88.
- * Modified by:
- * Rich Braun @ Kronos, 2/15/91
- *
- * Revision history:
- *
- * $Log: nfs.c_v $
- * Revision 1.6 1991/05/13 17:45:56 richb
- * Correct the NFS_STATFS call so it doesn't return an error if there
- * are 0 free blocks in a filesystem.
- * Add support for '-b' command line option so the administrator can
- * specify read/write block sizes.
- *
- * Revision 1.5 1991/04/11 20:41:26 richb
- * Validate pathnames before invoking pntoin, to prevent crashes.
- *
- * Revision 1.4 1991/03/15 22:41:19 richb
- * Numerous patches.
- *
- * Revision 1.3 1991/02/20 19:15:39 richb
- * Minor changes for file_create; add RCS headers.
- *
- */
-
- #ifdef RCSID
- static char _rcsid_ = "$Id: nfs.c_v 1.6 1991/05/13 17:45:56 richb Exp $";
- #endif
-
- #include "common.h"
- #include "msc-dos.h" /* dos and ... */
- #include <direct.h> /* directory ops */
- #include "..\rpc\a_unix.h"
-
- static char *reply_err = "RPC error: cannot transmit\n";
- static char *mem_err = "malloc: no more memory\n";
-
- /*
- * bool_t nfs_init() --
- * Initializes NFS server. Creates and registers transport
- * handle for NFS server. Returns TRUE if successful, or FALSE
- * if an error occurred.
- */
- bool_t nfs_init()
- {
- SVCXPRT *transp;
- int nfs_sock;
- struct sockaddr_in addr;
- static void nfs_dispatch(struct svc_req *, SVCXPRT *);
-
- addr.sin_family = AF_INET;
- addr.sin_port = htons(NFS_PORT);
- addr.sin_addr.s_addr = INADDR_ANY;
- if ((nfs_sock = sock_create(SOCK_DGRAM, IPPROTO_UDP, &addr)) < 0) {
- (void) fprintf(stderr, "cannot create nfs socket\n");
- return FALSE;
- }
- if ((transp = svcudp_create(nfs_sock, 1)) == (SVCXPRT *) NULL) {
- (void) fprintf(stderr, "cannot create udp handle\n");
- sock_close(nfs_sock);
- return FALSE;
- }
- if (! svc_register(transp, NFS_PROGRAM, NFS_VERSION, nfs_dispatch,
- IPPROTO_UDP)) {
- (void) fprintf(stderr, "cannot register handle\n");
- sock_close(nfs_sock);
- return FALSE;
- }
-
- return TRUE;
- }
-
- /*
- * void nfs_dispatch(struct svc_req *req, SVCXPRT *transp) --
- * NFS server dispatch routine.
- */
- static void nfs_dispatch(req, transp)
- struct svc_req *req;
- SVCXPRT *transp;
- {
- #if DEBUG
- static char *names[] = {"NULL", "GETATTR", "SETATTR", "ROOT", "LOOKUP",
- "READLINK", "READ", "WRITECACHE", "WRITE", "CREATE",
- "REMOVE", "RENAME", "LINK", "SYMLINK", "MKDIR",
- "RMDIR", "READDIR", "STATFS", "<invalid>"};
- DBGPRT1 (nfsdisp, ">>> NFS_%s", names[(req->rq_proc > NFS_STATFS) ?
- NFS_STATFS+1 : req->rq_proc]);
- #endif
-
- /* find which procedure to call */
- switch((int) req->rq_proc) {
-
- case NFS_GETATTR: nfs_getattr(transp, req); break;
- case NFS_NULL: nfs_null(transp, req); break;
- case NFS_READ: nfs_read(transp, req); break;
- case NFS_WRITE: nfs_write(transp, req); break;
- case NFS_STATFS: nfs_statfs(transp, req); break;
- case NFS_LOOKUP: nfs_lookup(transp, req); break;
- case NFS_READDIR: nfs_readdir(transp, req); break;
- case NFS_CREATE: nfs_create(transp, req); break;
- case NFS_MKDIR: nfs_mkdir(transp, req); break;
- case NFS_REMOVE: nfs_remove(transp, req); break;
- case NFS_RMDIR: nfs_rmdir(transp, req); break;
- case NFS_RENAME: nfs_rename(transp, req); break;
- case NFS_SETATTR: nfs_setattr(transp, req); break;
- case NFS_LINK: nfs_link(transp, req); break;
- case NFS_SYMLINK: nfs_symlink(transp, req); break;
- default:
- DBGPRT1 (nfsdisp, "unsupp procedure %d",
- req->rq_proc);
- nfs_error(transp, req);
- break;
- }
- }
-
- /*
- * void nfs_null(SVCXPRT *xprt, struct svc_req *req) --
- * Sends an empty reply. Used for "ping-ing" the nfs server.
- */
- void nfs_null(xprt, req)
- SVCXPRT *xprt;
- struct svc_req *req;
- {
- if (! svc_sendreply(xprt, xdr_void, (char *) NULL))
- (void) fprintf(stderr, reply_err);
- }
-
- /*
- * void nfs_read(SVCXPRT *xprt, struct svc_req *req) --
- * Reads requested file and sends it over the wire.
- */
- void nfs_read(xprt, req)
- SVCXPRT *xprt;
- struct svc_req *req;
- {
- struct nfsreadargs *r_args; /* the argument */
- struct nfsrdresult r_rslt; /* the read result */
- char databuf [NFS_MAXDATA];
- u_long count; /* request size */
- int bytes; /* bytes read */
-
- r_args = (struct nfsreadargs *) malloc(sizeof(struct nfsreadargs));
- if (r_args == NULL) {
- (void) fprintf(stderr, mem_err);
- abort();
- }
- (void) bzero(r_args, sizeof(struct nfsreadargs));
- if (! svc_getargs(xprt, xdr_readargs, r_args)) {
- svcerr_decode(xprt);
- (void) free(r_args);
- return;
- }
- (void) bzero(&r_rslt, sizeof(struct nfsrdresult));
-
- /* set pointer to data in results struct */
- r_rslt.rr_data = databuf;
- count = r_args->ra_count;
-
- /* evaluate buffer count argument */
- if (count > nfsrd_size) {
- count = nfsrd_size;
- fprintf (stderr, "NFS_READ: truncating req. from %ld\n",
- r_args->ra_count);
- }
-
- /* get attributes */
- if (inattrget (r_args->ra_fhandle.f.fh_fno, &r_rslt.rr_attr) ==
- (struct nfsfattr *) NULL)
- r_rslt.rr_status = NFSERR_STALE;
- else {
- if ((bytes = file_read(r_args->ra_fhandle.f.fh_fno,
- r_args->ra_offset, count,
- r_rslt.rr_data)) == -1) {
- DBGPRT1 (nfserr, "file_read error %d", errno);
- r_rslt.rr_status = puterrno (errno);
- }
- else {
- char name [MAXPATHNAMELEN];
- DBGPRT4 (nfsread, "%s: %ld/%d bytes at %ld",
- intopn (r_args->ra_fhandle.f.fh_fno, name),
- r_args->ra_count, bytes, r_args->ra_offset);
- r_rslt.rr_bufsize = nfsrd_size;
- r_rslt.rr_count = bytes;
- r_rslt.rr_status = NFS_OK;
- r_rslt.rr_bp = NULL;
- r_rslt.rr_vp = NULL;
- }
- }
- if (! svc_sendreply(xprt, xdr_rdresult, &r_rslt))
- (void) fprintf(stderr, reply_err);
- else if (NFS_VERBOSE)
- (void) printf(">>> NFS_READ\n");
-
- /* free arguments */
- svc_freeargs(xprt, xdr_readargs, r_args);
- }
-
- /*
- * void nfs_error(SVCXPRT *xprt, struct svc_req *req) --
- * Returns nfs error message.
- */
- void nfs_error(xprt, req)
- SVCXPRT *xprt;
- struct svc_req *req;
- {
- (void) fprintf(stderr,
- ">>> NFS_ERROR: procedure %d not supported\n", req->rq_proc);
- svcerr_noproc(xprt); /* send server error reply msg */
- }
-
- /*
- * void nfs_getattr(SVCXPRT *xprt, struct svc_req *req) --
- * Gets file attributes.
- */
- void nfs_getattr(xprt, req)
- SVCXPRT *xprt;
- struct svc_req *req;
- {
- fhandle_t *fhp; /* file handle is argument */
- struct nfsattrstat attr; /* return attributes */
- char *fullpath, path[MAXPATHNAMELEN]; /* full DOS path name */
-
- fhp = (fhandle_t *) malloc(sizeof(fhandle_t));
- if (fhp == NULL) {
- (void) fprintf(stderr, mem_err);
- abort();
- }
- (void) bzero(fhp, sizeof(fhandle_t));
- if (! svc_getargs(xprt, xdr_fhandle, fhp)) {
- (void) fprintf(stderr, "nfs_getattr: cannot read args\n");
- svcerr_decode(xprt);
- (void) free(fhp);
- return;
- }
-
- /* Check the validity of the file handle */
- if (!checkfh (fhp))
- attr.ns_status = NFSERR_STALE;
- else {
- /* clear out return attributes */
- (void) bzero(&attr, sizeof(struct nfsattrstat));
- fullpath = intopn(fhp->f.fh_fno, path); /* path from inode */
-
- if (! file_getattr(fullpath, &(attr.ns_attr)))
- attr.ns_status = NFSERR_NOENT;
- else
- attr.ns_status = NFS_OK;
- }
- #if 1
- {
- /* Hack: tell the caller he is the owner */
- struct authunix_parms *unix_cred;
- unix_cred = (struct authunix_parms *) req->rq_clntcred;
- attr.ns_attr.na_uid = (u_long) unix_cred->aup_uid;
- }
- #endif
-
- if (! svc_sendreply(xprt, xdr_attrstat, &attr))
- (void) fprintf(stderr, reply_err);
- else if (NFS_VERBOSE)
- (void) printf(">>> NFS_GETATTR: %s\n", fullpath);
-
- svc_freeargs(xprt, xdr_fhandle, fhp);
- }
-
- /*
- * void nfs_statfs(SVCXPRT *xprt, struct svc_req *req) --
- * Returns file system status
- */
- void nfs_statfs(xprt, req)
- SVCXPRT *xprt;
- struct svc_req *req;
- {
- struct nfsstatfs fs;
- fhandle_t *fhp;
-
- fhp = (fhandle_t *) malloc(sizeof(fhandle_t));
- if (fhp == NULL) {
- (void) fprintf(stderr, mem_err);
- abort();
- }
- (void) bzero(fhp, sizeof(fhandle_t));
- if (! svc_getargs(xprt, xdr_fhandle, fhp)) {
- svcerr_decode(xprt);
- (void) free(fhp);
- return;
- }
-
- /* Check the validity of the file handle */
- if (!checkfh (fhp))
- fs.fs_status = NFSERR_STALE;
- else {
- /* clear out results struct */
- (void) bzero(&fs, sizeof(struct nfsstatfs));
- /* set up struct */
- if (file_freeblocks(fhp->f.fh_fsid, &(fs.fs_bfree),
- &(fs.fs_blocks)) != 0) {
- DBGPRT1 (nfserr, "statfs error %d", errno);
- fs.fs_status = NFSERR_IO;
- }
- else {
- fs.fs_tsize = NFS_MAXDATA;
- fs.fs_bsize = FS_BLOCKSIZE;
- fs.fs_status = NFS_OK;
- fs.fs_bavail = fs.fs_bfree;
- }
- }
- if (! svc_sendreply(xprt, xdr_statfs, &fs))
- (void) fprintf(stderr, reply_err);
- else if (NFS_VERBOSE)
- (void) printf(">>> NFS_STATFS: drive %d\n", fhp->f.fh_fsid);
- svc_freeargs(xprt, xdr_fhandle, fhp);
- }
-
- /*
- * void nfs_readdir(SVCXPRT *xprt, struct svc_req *req) --
- * Read a directory.
- */
- void nfs_readdir(xprt, req)
- SVCXPRT *xprt;
- struct svc_req *req;
- {
- struct nfsrddirargs *args; /* args */
- struct nfsrddirres res; /* results */
- u_long nodeid; /* inode number */
- static u_long offs; /* offset */
- static int bytes; /* # of dir bytes read */
- int maxbytes;
- struct udirect *udp; /* directory cookie array */
- #define SUD 32 /* increment for offsets */
- static u_long prevfh_no; /* previous path handle */
- static char prevudp[NFS_MAXDATA + sizeof (struct udirect)];
- static u_long prevoffs; /* previous offset */
- static int preveof; /* previous EOF flag */
-
- args = (struct nfsrddirargs *) malloc(sizeof(struct nfsrddirargs));
- if (args == NULL) {
- (void) fprintf(stderr, mem_err);
- abort();
- }
- (void) bzero(args, sizeof(struct nfsrddirargs));
- if (! svc_getargs(xprt, xdr_rddirargs, args)) {
- svcerr_decode(xprt);
- (void) free(args);
- return;
- }
- maxbytes = (args->rda_count > nfsrd_size ? nfsrd_size : args->rda_count);
- if (maxbytes == 0)
- maxbytes = nfsrd_size;
-
- nodeid = args->rda_fh.f.fh_fno;
-
- /* Check the validity of the file handle */
- if (!checkfh (&args->rda_fh))
- res.rd_status = NFSERR_STALE;
-
- else {
- /* clear out results */
- (void) bzero(&res, sizeof(struct nfsrddirres)); /* zero results */
- res.rd_bufsize = args->rda_count; /* size of clnt req */
- res.rd_status = NFS_OK;
-
- /* point to directory entries block */
- res.rd_entries = (struct udirect *) prevudp;
- udp = res.rd_entries;
-
- /* see if this is an identical request */
- if (args->rda_offset != 0L && args->rda_offset == prevoffs &&
- prevfh_no == nodeid) {
- res.rd_offset = offs;
- res.rd_size = bytes;
- res.rd_eof = preveof;
- DBGPRT1 (nfsread, "READDIR (same %ld)", args->rda_offset);
- }
- else {
- /* clear out the udp */
- (void) bzero(prevudp, sizeof prevudp);
-
- /* read until filled */
- res.rd_eof = FALSE;
- offs = args->rda_offset;
- prevoffs = offs;
- bytes = 0;
- prevfh_no = nodeid;
-
- while (bytes < maxbytes) {
- int rstat; /* read status */
-
- rstat = file_rddir(nodeid, offs, udp);
- if (rstat == -1) { /* error reading */
- res.rd_status = NFSERR_NOENT;
- break;
- }
-
- /* space for more? */
- if ((bytes + udp->d_reclen) <= maxbytes) {
- bytes += udp->d_reclen;
-
- /* Break out of loop if this is the last entry. */
- if (rstat == 0) {
- res.rd_eof = TRUE;
- break;
- }
-
- /* Point to next entry */
- udp = (struct udirect *) ((char *) udp + UDIRSIZ(udp));
- offs += SUD; /* next offset */
- }
- else
- break;
- }
- /* broke out of the loop */
- if (res.rd_status == NFS_OK) { /* good read */
- res.rd_offset = offs; /* next offset */
- res.rd_size = bytes; /* # of bytes */
- res.rd_bufsize = bytes + 128; /* Add enough extra for */
- /* XDR routine */
- }
- preveof = res.rd_eof;
- DBGPRT4 (nfsread, "READDIR offset = %ld..%ld, bytes = %d %s",
- prevoffs / SUD, offs / SUD,
- bytes, res.rd_eof ? "***EOF***" : "");
- }
- }
-
- if (! svc_sendreply(xprt, xdr_putrddirres, &res))
- (void) fprintf(stderr, reply_err);
- else if (NFS_VERBOSE)
- (void) printf(">>> NFS_READDIR\n");
-
- /* free space */
- svc_freeargs(xprt, xdr_rddirargs, args);
- #undef SUD
- }
-
- /*
- * void nfs_lookup(SVCXPRT *xprt, struct svc_req *req) --
- * Directory lookup.
- */
- void nfs_lookup(xprt, req)
- SVCXPRT *xprt;
- struct svc_req *req;
- {
- struct nfsdiropargs *args; /* arguments to call */
- struct nfsdiropres res; /* and results */
- struct nfsfattr attr; /* return attributes */
- char *fullpath, path[MAXPATHNAMELEN]; /* path of file looked up */
-
- args = (struct nfsdiropargs *) malloc(sizeof(struct nfsdiropargs));
- if (args == NULL) {
- (void) fprintf(stderr, mem_err);
- abort();
- }
- (void) bzero(args, sizeof(struct nfsdiropargs));
- if (! svc_getargs(xprt, xdr_diropargs, args)) {
- svcerr_decode(xprt);
- (void) free(args);
- return;
- }
-
- /* Check the validity of the parent's handle */
- if (!checkfh (&args->da_fhandle))
- res.dr_status = NFSERR_STALE;
- else {
- /* clear out return struct */
- (void) bzero(&res, sizeof(struct nfsdiropres));
- fullpath = intopn(args->da_fhandle.f.fh_fno, path);/* path from */
- /* inode of parent */
- if (fullpath != NULL) {
- /*
- * extra code here to handle XCOPY's brain-damaged
- * way of passing wildcards when it really shouldn't.
- */
- int i;
- int namelen;
-
- namelen = strlen(args->da_name);
- for(i = 0; i < namelen; i++) { /* scan the name */
- if ((args->da_name)[i] == '*' ||
- (args->da_name)[i] == '?') {
- res.dr_status = NFSERR_NOENT;
- goto end;
- }
- }
- /* end of extra code */
-
- if (strcmp(args->da_name, "..") == 0) { /* asking for parent */
- fullpath = intopn(parentinode(
- args->da_fhandle.f.fh_fno), path);
- }
- else if (strcmp(args->da_name , ".") != 0) {
- (void) strcat(fullpath, "\\"); /* append seperator */
- (void) strcat(fullpath, args->da_name);
- (void) strtolower(fullpath); /* all lower case */
- }
- }
- res.dr_status = validate_path (fullpath);
-
- DBGPRT1 (nfslookup, "fullpath = %s", fullpath);
-
- if (res.dr_status == NFS_OK) {
- if ( ! file_getattr(fullpath, &attr)) {
- DBGPRT0 (nfslookup, "no such file");
- res.dr_status = NFSERR_NOENT;
- }
- else { /* copy the attributes over */
- res.dr_attr = attr;
- res.dr_status = NFS_OK; /* set proper status */
- /* get a fhandle for it */
- if (strcmp(args->da_name, ".") != 0)
- res.dr_fhandle = pntofh(fullpath);
- else
- res.dr_fhandle = args->da_fhandle;
- #if 1
- {
- /* Hack: tell the caller he is the owner */
- struct authunix_parms *unix_cred;
- unix_cred = (struct authunix_parms *) req->rq_clntcred;
- res.dr_attr.na_uid = (u_long) unix_cred->aup_uid;
- }
- #endif
- }
- }
- }
- /* reply to caller */
- end: if (NFS_VERBOSE)
- (void) printf(">>> NFS_LOOKUP: %s\n", fullpath);
- if (! svc_sendreply(xprt, xdr_diropres, &res))
- (void) fprintf(stderr, reply_err);
-
- /* free used space */
- svc_freeargs(xprt, xdr_diropargs, args);
- }
-
- /*
- * void nfs_write(SVCXPRT *xprt, struct svc_req *req) --
- * Do an atomic write operation.
- */
- void nfs_write(xprt, req)
- SVCXPRT *xprt;
- struct svc_req *req;
- {
- struct nfswriteargs *args; /* args */
- struct nfsattrstat res; /* return stat */
-
- /* alloc space for args */
- args = (struct nfswriteargs *) malloc(sizeof(struct nfswriteargs));
- if (args == NULL) {
- (void) fprintf(stderr, mem_err);
- abort();
- }
- (void) bzero(args, sizeof(struct nfswriteargs));
- if (! svc_getargs(xprt, xdr_writeargs, args)) {
- svcerr_decode(xprt);
- (void) free(args);
- return;
- }
- if (NFS_READONLYFS) {
- nfserr_readonlyfs(xprt, xdr_writeargs, args);
- return;
- }
- (void) bzero(&res, sizeof(struct nfsattrstat));
- /* evaluate buffer count argument */
- if (args->wa_count > nfswr_size) {
- res.ns_status = NFSERR_IO;
- goto reply;
- }
- res.ns_status = file_write(args->wa_fhandle.f.fh_fno, args->wa_offset,
- args->wa_count, args->wa_data);
- if (res.ns_status == NFS_OK) {
- /* get file attributes */
- if (inattrget (args->wa_fhandle.f.fh_fno, &res.ns_attr) ==
- (struct nfsfattr *) NULL) {
- res.ns_status = NFSERR_STALE;
- }
- }
- else
- DBGPRT2 (nfserr, "write %ld, error %d",
- args->wa_fhandle.f.fh_fno, res.ns_status);
-
- reply:
- if (! svc_sendreply(xprt, xdr_attrstat, &res))
- (void) fprintf(stderr, reply_err);
- else if (NFS_VERBOSE)
- (void) printf(">>> NFS_WRITE: %ld\n",
- args->wa_fhandle.f.fh_fno);
-
- svc_freeargs(xprt, xdr_writeargs, args); /* free all data */
- }
-
- /*
- * void nfs_create(SVCXPRT *xprt, struct svc_req *req) --
- * Create a file.
- */
- void nfs_create(xprt, req)
- SVCXPRT *xprt;
- struct svc_req *req;
- {
- struct nfscreatargs *args; /* create args */
- struct nfsdiropres res; /* return result */
- char *fullpath, path[MAXPATHNAMELEN]; /* full name */
- int stat; /* create return stat */
- struct authunix_parms *unix_cred;
-
- args = (struct nfscreatargs *) malloc(sizeof(struct nfscreatargs));
- if (args == NULL) {
- (void) fprintf(stderr, mem_err);
- abort();
- }
- (void) bzero(args, sizeof(struct nfscreatargs));
- if (! svc_getargs(xprt, xdr_creatargs, args)) {
- svcerr_decode(xprt);
- (void) free(args);
- return;
- }
- if (NFS_READONLYFS) { /* read only file system */
- nfserr_readonlyfs(xprt, xdr_creatargs, args);
- return;
- }
-
- /* Check the validity of the file handle */
- if (!checkfh (&args->ca_da.da_fhandle))
- res.dr_status = NFSERR_STALE;
- else {
- /* clear out return struct */
- (void) bzero(&res, sizeof(struct nfsdiropres));
- fullpath = intopn(args->ca_da.da_fhandle.f.fh_fno, path);
- if (fullpath != NULL) {
- (void) strcat(fullpath, "\\"); /* make rest of name */
- (void) strcat(fullpath, args->ca_da.da_name);
- (void) strtolower (fullpath); /* force lower case */
- }
- if (file_getattr(fullpath, &(res.dr_attr))) { /* file exists */
- res.dr_status = NFSERR_EXIST;
- }
- /* fill in default UID/GID info */
- unix_cred = (struct authunix_parms *) req->rq_clntcred;
- if (args->ca_sa.sa_uid == -1)
- args->ca_sa.sa_uid = (u_long) unix_cred->aup_uid;
- if (args->ca_sa.sa_gid == -1)
- args->ca_sa.sa_gid = (u_long) unix_cred->aup_gid;
-
- /* create a file */
- res.dr_status = file_create(fullpath, &(args->ca_sa), &res.dr_attr);
- if (res.dr_status == NFS_OK) { /* no errors */
- /* make file handle */
- res.dr_fhandle = pntofh(fullpath);
- }
- }
- if (! svc_sendreply(xprt, xdr_diropres, &res))
- (void) fprintf(stderr, reply_err);
- else if (NFS_VERBOSE)
- (void) printf(">>> NFS_CREATE: %s\n", fullpath);
-
- /* free all data */
- svc_freeargs(xprt, xdr_creatargs, args);
- }
-
- /*
- * void nfs_mkdir(SVCXPRT *xprt, struct svc_req *req) --
- * Make a directory request. All DOS directories are readable and
- * writeable, hence the set attribute field is ignored.
- */
- void nfs_mkdir(xprt, req)
- SVCXPRT *xprt;
- struct svc_req *req;
- {
- struct nfscreatargs *args;
- struct nfsdiropres res;
- char *fullpath, path[MAXPATHNAMELEN];
-
- args = (struct nfscreatargs *) malloc(sizeof(struct nfscreatargs));
- if (args == NULL) {
- (void) fprintf(stderr, mem_err);
- abort();
- }
- (void) bzero(args, sizeof(struct nfscreatargs));
- if (! svc_getargs(xprt, xdr_diropargs, args)) {
- svcerr_decode(xprt);
- (void) free(args);
- return;
- }
- if (NFS_READONLYFS) {
- nfserr_readonlyfs(xprt, xdr_diropargs, args);
- return;
- }
- /* construct path name of new directory */
- fullpath = intopn(args->ca_da.da_fhandle.f.fh_fno, path);
- if (fullpath != NULL) {
- (void) strcat(fullpath, "\\");
- (void) strcat(fullpath, args->ca_da.da_name);
- (void) strtolower (fullpath); /* force lower case */
- }
-
- (void) bzero(&res, sizeof(struct nfsdiropres));
-
- /* validate path name */
- if ((res.dr_status = validate_path (fullpath)) == NFS_OK)
- res.dr_status = mkdir(fullpath);
-
- if (res.dr_status == NFS_OK) {
- res.dr_status = !file_getattr(fullpath, &(res.dr_attr));
-
- if (res.dr_status == NFS_OK) /* make new file handle */
- res.dr_fhandle = pntofh(fullpath);
- else
- res.dr_status = puterrno(errno);
- }
- if (! svc_sendreply(xprt, xdr_diropres, &res))
- (void) fprintf(stderr, reply_err);
- else if (NFS_VERBOSE)
- (void) printf(">>> NFS_MKDIR: %s\n", fullpath);
-
- /* free all data */
- svc_freeargs(xprt, xdr_creatargs, args);
- }
-
- /*
- * void nfs_remove(SVCXPRT *xprt, struct svc_req *req) --
- * Remove a file specified by the handle.
- */
- void nfs_remove(xprt, req)
- SVCXPRT *xprt;
- struct svc_req *req;
- {
- struct nfsdiropargs *args; /* dir op arguments */
- enum nfsstat stat; /* status of the remove */
- char *fullpath, path[MAXPATHNAMELEN]; /* full path of file */
-
- args = (struct nfsdiropargs *) malloc(sizeof(struct nfsdiropargs));
- if (args == NULL) {
- (void) fprintf(stderr, mem_err);
- abort();
- }
- (void) bzero(args, sizeof(struct nfsdiropargs)); /* zero it */
- if (! svc_getargs(xprt, xdr_diropargs, args)) {
- svcerr_decode(xprt);
- (void) free(args); /* couldn't decode it */
- return;
- }
- if (NFS_READONLYFS) {
- nfserr_readonlyfs(xprt, xdr_diropargs, &args);
- return;
- }
- /* get full directory name from inode number */
- fullpath = intopn(args->da_fhandle.f.fh_fno, path);
- if (fullpath == NULL)
- stat = NFSERR_NOENT;
- else {
- (void) strcat(fullpath, "\\"); /* append the name */
- (void) strcat(fullpath, args->da_name);
- stat = file_unlink(fullpath);
- }
- /* now reply to request */
- if (! svc_sendreply(xprt, xdr_enum, &stat))
- (void) fprintf(stderr, reply_err);
- else if (NFS_VERBOSE)
- (void) printf(">>> NFS_REMOVE: %s\n", fullpath);
-
- svc_freeargs(xprt, xdr_diropargs, args);
- }
-
- /*
- * void nfs_rmdir(SVCXPRT *xprt, struct svc_req *req) --
- * Remove a directory specified by the handle.
- */
- void nfs_rmdir(xprt, req)
- SVCXPRT *xprt;
- struct svc_req *req;
- {
- struct nfsdiropargs *args; /* dir op arguments */
- enum nfsstat stat; /* status of the remove */
- char *fullpath, path[MAXPATHNAMELEN]; /* full path of file */
- u_long node;
-
- args = (struct nfsdiropargs *) malloc(sizeof(struct nfsdiropargs));
- if (args == NULL) {
- (void) fprintf(stderr, mem_err);
- abort();
- }
- (void) bzero(args, sizeof(struct nfsdiropargs)); /* zero it */
- if (! svc_getargs(xprt, xdr_diropargs, args)) {
- svcerr_decode(xprt);
- (void) free(args); /* couldn't decode it */
- return;
- }
- /* get full path name from inode number */
- fullpath = intopn(args->da_fhandle.f.fh_fno, path);
- if (fullpath == NULL)
- stat = NFSERR_NOENT; /* doesn't exist */
- else {
- (void) strcat(fullpath, "\\"); /* append the name */
- (void) strcat(fullpath, args->da_name);
- if (rmdir(fullpath)) { /* remove it */
- stat = (enum nfsstat) errno;
-
- /* Translate the error code so the correct message */
- /* will be displayed. */
- if (stat == NFSERR_ACCES)
- stat = NFSERR_EXIST;
- }
- else {
- stat = NFS_OK;
- /* Remove the inode if assigned */
- if ((node = pntoin (fullpath)) != -1)
- inremnode (node);
- }
- }
- /* now reply to request */
- if (! svc_sendreply(xprt, xdr_enum, &stat))
- (void) fprintf(stderr, reply_err);
- else if (NFS_VERBOSE)
- (void) printf(">>> NFS_RMDIR: %s\n", fullpath);
-
- svc_freeargs(xprt, xdr_diropargs, args); /* free data */
- }
-
- /*
- * void nfs_rename(SVCXPRT *xprt, struct svc_req *req) --
- * Renames given file to new name specified in the args.
- */
- void nfs_rename(xprt, req)
- SVCXPRT *xprt;
- struct svc_req *req;
- {
- struct nfsrnmargs *args; /* arguments to rename */
- enum nfsstat stat; /* thr reply status */
- char *oldname, *newname, /* old and new filenames */
- opath[MAXPATHNAMELEN], npath[MAXPATHNAMELEN];
-
- args = (struct nfsrnmargs *) malloc(sizeof(struct nfsrnmargs));
- if (args == NULL) {
- (void) fprintf(stderr, mem_err);
- abort();
- }
- (void) bzero(args, sizeof(struct nfsrnmargs));
- if (! svc_getargs(xprt, xdr_rnmargs, args)) {
- svcerr_decode(xprt);
- (void) free(args);
- return;
- }
- if (NFS_READONLYFS) {
- nfserr_readonlyfs(xprt, xdr_rnmargs, args);
- return;
- }
- /* make old name from inode */
- oldname = intopn(args->rna_from.da_fhandle.f.fh_fno, opath);
- newname = intopn(args->rna_to.da_fhandle.f.fh_fno, npath);
- if (oldname == NULL || newname == NULL) /* cannot find path for file */
- stat = NFSERR_STALE; /* ==> stale file handle */
- else {
- /* complete specification for names */
- (void) strcat(oldname, "\\");
- (void) strcat(oldname, args->rna_from.da_name);
- (void) strcat(newname, "\\");
- (void) strcat(newname, args->rna_to.da_name);
-
- /* Perform the rename operation */
-
- stat = file_rename(oldname, newname);
- }
- /* reply to rename request */
- if (! svc_sendreply(xprt, xdr_enum, &stat))
- (void) fprintf(stderr, reply_err);
- else if (NFS_VERBOSE)
- (void) fprintf(stderr, ">>> NFS_RENAME: %s to %s\n",
- oldname, newname);
-
- /* free all data */
- svc_freeargs(xprt, xdr_rnmargs, args);
- }
-
- /*
- * void nfs_setattr(SVCXPRT *xprt, struct svc_req *req) --
- * Set file attributes.
- */
- void nfs_setattr(xprt, req)
- SVCXPRT *xprt;
- struct svc_req *req;
- {
- struct nfssaargs *args; /* arguments */
- struct nfsattrstat res; /* results */
-
- args = (struct nfssaargs *) malloc(sizeof(struct nfssaargs));
- if (args == NULL) {
- (void) fprintf(stderr, mem_err);
- abort();
- }
- (void) bzero(args, sizeof(struct nfssaargs));
- if (! svc_getargs(xprt, xdr_saargs, args)) {
- svcerr_decode(xprt);
- (void) free(args);
- return;
- }
- DBGPRT4 (nfsdebug, "SETATTR: size = %ld mode = %o%05o time = %ld",
- args->saa_sa.sa_size, (int) (args->saa_sa.sa_mode >> 15),
- (int) args->saa_sa.sa_mode & 077777,
- args->saa_sa.sa_mtime.tv_sec);
- if (NFS_READONLYFS) {
- nfserr_readonlyfs(xprt, xdr_saargs, args);
- return;
- }
-
- /* If a parameter in the argument block is not -1, set the */
- /* parameter within the file. */
-
- /* File mode / protection */
- res.ns_status = NFS_OK;
- if (args->saa_sa.sa_mode != -1)
- res.ns_status = file_setperm(args->saa_fh.f.fh_fno,
- args->saa_sa.sa_mode);
-
- /* Modification time */
- if (res.ns_status == NFS_OK && args->saa_sa.sa_mtime.tv_sec > 0)
- res.ns_status = file_settime(args->saa_fh.f.fh_fno,
- args->saa_sa.sa_mtime.tv_sec);
-
- /* Size */
- if (res.ns_status == NFS_OK && args->saa_sa.sa_size != -1)
- res.ns_status = file_setsize(args->saa_fh.f.fh_fno,
- args->saa_sa.sa_size);
-
- /* User ID / Group ID */
- if (res.ns_status == NFS_OK && (args->saa_sa.sa_uid != -1 ||
- args->saa_sa.sa_gid != -1))
- res.ns_status = file_setowner(args->saa_fh.f.fh_fno,
- args->saa_sa.sa_uid, args->saa_sa.sa_gid);
-
- (void) bzero(&res, sizeof(struct nfsattrstat));
- if (res.ns_status == NFS_OK &&
- !inattrget (args->saa_fh.f.fh_fno, &res.ns_attr)) {
- res.ns_status = NFSERR_NOENT;
- }
-
- if (! svc_sendreply(xprt, xdr_attrstat, &res))
- (void) fprintf(stderr, reply_err);
- else if (NFS_VERBOSE)
- (void) printf(">>> NFS_SETATTR\n");
-
- /* free data */
- svc_freeargs(xprt, xdr_saargs, args);
- }
-
- /*
- * void nfs_link(SVCXPRT *xprt, struct svc_req *req) --
- * Create file link (not supported under DOS)
- */
- void nfs_link(xprt, req)
- SVCXPRT *xprt;
- struct svc_req *req;
- {
- struct nfslinkargs *args; /* arguments to link */
- struct nfsdiropres res; /* return result */
- enum nfsstat stat; /* the reply status */
- char *oldname, *newname, /* old and new filenames */
- opath[MAXPATHNAMELEN], npath[MAXPATHNAMELEN];
-
- args = (struct nfslinkargs *) malloc(sizeof(struct nfslinkargs));
- if (args == NULL) {
- (void) fprintf(stderr, mem_err);
- abort();
- }
- (void) bzero(args, sizeof(struct nfslinkargs));
- (void) bzero(&res, sizeof(struct nfsdiropres));
- if (! svc_getargs(xprt, xdr_linkargs, args)) {
- svcerr_decode(xprt);
- (void) free(args);
- return;
- }
- if (NFS_READONLYFS) {
- nfserr_readonlyfs(xprt, xdr_linkargs, args);
- return;
- }
- /* Translate inodes into names */
- oldname = intopn(args->la_from.f.fh_fno, opath);
- newname = intopn(args->la_to.da_fhandle.f.fh_fno, npath);
- if (oldname == NULL || newname == NULL) /* cannot find path for file */
- stat = NFSERR_STALE; /* ==> stale file handle */
- else {
- /* not supported: return an error code */
-
- stat = NFSERR_ACCES;
- }
- res.dr_status = stat;
-
- if (! svc_sendreply(xprt, xdr_diropres, &res))
- (void) fprintf(stderr, reply_err);
- else if (NFS_VERBOSE)
- (void) fprintf(stderr, ">>> NFS_LINK: %s to %s\n",
- oldname, newname);
- svc_freeargs(xprt, xdr_linkargs, args);
- }
-
-
- /*
- * void nfs_symlink(SVCXPRT *xprt, struct svc_req *req) --
- * Create symbolic link (not supported under DOS)
- */
- void nfs_symlink(xprt, req)
- SVCXPRT *xprt;
- struct svc_req *req;
- {
- struct nfsslargs *args; /* arguments to sym link */
- struct nfsrdlnres res; /* return result */
- enum nfsstat stat; /* the reply status */
- char *oldname, opath[MAXPATHNAMELEN]; /* old filename */
-
- args = (struct nfsslargs *) malloc(sizeof(struct nfsslargs));
- if (args == NULL) {
- (void) fprintf(stderr, mem_err);
- abort();
- }
- (void) bzero(args, sizeof(struct nfsslargs));
- (void) bzero(&res, sizeof(struct nfsrdlnres));
- if (! svc_getargs(xprt, xdr_slargs, args)) {
- svcerr_decode(xprt);
- (void) free(args);
- return;
- }
-
- /* Translate inode into name */
- oldname = intopn(args->sla_from.da_fhandle.f.fh_fno, opath);
- if (oldname == NULL) /* cannot find path for file */
- stat = NFSERR_STALE; /* ==> stale file handle */
- else {
- /* not supported: return an error code */
-
- stat = NFSERR_ACCES;
- }
- res.rl_status = stat;
-
- if (! svc_sendreply(xprt, xdr_rdlnres, &res))
- (void) fprintf(stderr, reply_err);
- else if (NFS_VERBOSE)
- (void) fprintf(stderr, ">>> NFS_SYMLINK\n");
- svc_freeargs(xprt, xdr_linkargs, args);
- }
-
-
- /*
- * void nfserr_readonlyfs(SVCXPRT *xprt, xdrproc_t xproc, void *args) --
- * Return error status of NFSERR_ROFS. Write attempted on read only
- * file system.
- */
- void nfserr_readonlyfs(xprt, xproc, args)
- SVCXPRT *xprt;
- xdrproc_t xproc;
- void *args;
- {
- enum nfsstat err;
-
- err = NFSERR_ROFS;
- if (! svc_sendreply(xprt, xdr_enum, &err))
- (void) fprintf(stderr, reply_err);
- svc_freeargs(xprt, xproc, args);
- }
-