home *** CD-ROM | disk | FTP | other *** search
/ Black Box 4 / BlackBox.cdr / lan / soss.arj / SRC / NFS.C < prev    next >
C/C++ Source or Header  |  1991-04-11  |  31KB  |  1,056 lines

  1. /*
  2.  *  nfs.c --
  3.  *      NFS server implementation for PC.  Runs on top of the
  4.  *      net daemon (netd.c).
  5.  *
  6.  *  Author:
  7.  *      See-Mong Tan, 6/12/88.
  8.  *  Modified by:
  9.  *    Rich Braun @ Kronos, 2/15/91
  10.  *
  11.  *  Revision history:
  12.  *  
  13.  * $Log: nfs.c_v $
  14.  * Revision 1.5  1991/04/11  20:41:26  richb
  15.  * Validate pathnames before invoking pntoin, to prevent crashes.
  16.  *
  17.  * Revision 1.4  1991/03/15  22:41:19  richb
  18.  * Numerous patches.
  19.  *
  20.  * Revision 1.3  1991/02/20  19:15:39  richb
  21.  * Minor changes for file_create; add RCS headers.
  22.  *
  23.  */
  24.  
  25. #ifdef RCSID
  26. static char _rcsid_ = "$Id: nfs.c_v 1.5 1991/04/11 20:41:26 richb Exp $";
  27. #endif
  28.  
  29. #include "common.h"
  30. #include "msc-dos.h"        /* dos and ... */
  31. #include <direct.h>        /* directory ops */
  32. #include "..\rpc\a_unix.h"
  33.  
  34. static char *reply_err = "RPC error:  cannot transmit\n";
  35. static char *mem_err   = "malloc:  no more memory\n";
  36.  
  37. /*
  38.  *  bool_t nfs_init() --
  39.  *      Initializes NFS server.  Creates and registers transport
  40.  *      handle for NFS server.  Returns TRUE if successful, or FALSE
  41.  *      if an error occurred.
  42.  */
  43. bool_t nfs_init()
  44. {
  45.     SVCXPRT *transp;
  46.     int nfs_sock;
  47.     struct sockaddr_in addr;
  48.     static void nfs_dispatch(struct svc_req *, SVCXPRT *);
  49.  
  50.     addr.sin_family = AF_INET;
  51.     addr.sin_port = htons(NFS_PORT);
  52.     addr.sin_addr.s_addr = INADDR_ANY;
  53.     if ((nfs_sock = sock_create(SOCK_DGRAM, IPPROTO_UDP, &addr)) < 0) {
  54.         (void) fprintf(stderr, "cannot create nfs socket\n");
  55.         return FALSE;
  56.     }
  57.     if ((transp = svcudp_create(nfs_sock, 1)) == (SVCXPRT *) NULL) {
  58.         (void) fprintf(stderr, "cannot create udp handle\n");
  59.         sock_close(nfs_sock);
  60.         return FALSE;
  61.     }
  62.     if (! svc_register(transp, NFS_PROGRAM, NFS_VERSION, nfs_dispatch, 
  63.                IPPROTO_UDP)) {
  64.         (void) fprintf(stderr, "cannot register handle\n");
  65.         sock_close(nfs_sock);
  66.         return FALSE;
  67.     }
  68.  
  69.     return TRUE;
  70. }
  71.  
  72. /*
  73.  *  void nfs_dispatch(struct svc_req *req, SVCXPRT *transp) --
  74.  *      NFS server dispatch routine.
  75.  */
  76. static void nfs_dispatch(req, transp)
  77.      struct svc_req *req;
  78.      SVCXPRT *transp;
  79. {
  80. #if DEBUG
  81. static char *names[] = {"NULL", "GETATTR", "SETATTR", "ROOT", "LOOKUP",
  82.             "READLINK", "READ", "WRITECACHE", "WRITE", "CREATE",
  83.             "REMOVE", "RENAME", "LINK", "SYMLINK", "MKDIR",
  84.             "RMDIR", "READDIR", "STATFS", "<invalid>"};
  85.     DBGPRT1 (nfsdisp, ">>> NFS_%s", names[(req->rq_proc > NFS_STATFS) ?
  86.                   NFS_STATFS+1 : req->rq_proc]);
  87. #endif
  88.  
  89.     /* find which procedure to call */
  90.     switch((int) req->rq_proc) {    
  91.  
  92.       case NFS_GETATTR: nfs_getattr(transp, req);    break;
  93.       case NFS_NULL:    nfs_null(transp, req);        break;
  94.       case NFS_READ:    nfs_read(transp, req);        break;
  95.       case NFS_WRITE:    nfs_write(transp, req);        break;
  96.       case NFS_STATFS:    nfs_statfs(transp, req);    break;
  97.       case NFS_LOOKUP:    nfs_lookup(transp, req);    break;
  98.       case NFS_READDIR:    nfs_readdir(transp, req);    break;
  99.       case NFS_CREATE:    nfs_create(transp, req);    break;
  100.       case NFS_MKDIR:    nfs_mkdir(transp, req);        break;
  101.       case NFS_REMOVE:    nfs_remove(transp, req);    break;
  102.       case NFS_RMDIR:    nfs_rmdir(transp, req);        break;
  103.       case NFS_RENAME:    nfs_rename(transp, req);    break;
  104.       case NFS_SETATTR:    nfs_setattr(transp, req);    break;
  105.       case NFS_LINK:    nfs_link(transp, req);        break;
  106.       case NFS_SYMLINK:    nfs_symlink(transp, req);    break;
  107.       default:
  108.     DBGPRT1 (nfsdisp, "unsupp procedure %d",
  109.          req->rq_proc);
  110.     nfs_error(transp, req);
  111.     break;
  112.     }
  113. }
  114.  
  115. /*
  116.  *  void nfs_null(SVCXPRT *xprt, struct svc_req *req) --
  117.  *      Sends an empty reply.  Used for "ping-ing" the nfs server.
  118.  */
  119. void nfs_null(xprt, req)
  120.     SVCXPRT *xprt;
  121.     struct svc_req *req;
  122. {
  123.     if (! svc_sendreply(xprt, xdr_void, (char *) NULL))
  124.         (void) fprintf(stderr, reply_err);
  125. }
  126.  
  127. /*
  128.  *  void nfs_read(SVCXPRT *xprt, struct svc_req *req) --
  129.  *      Reads requested file and sends it over the wire.
  130.  */
  131. void nfs_read(xprt, req)
  132.     SVCXPRT *xprt;
  133.     struct svc_req *req;
  134. {
  135.     struct nfsreadargs *r_args;        /* the argument */
  136.     struct nfsrdresult r_rslt;        /* the read result */
  137.     char   databuf [RD_SIZ];
  138.     u_long count;            /* request size */
  139.     int    bytes;            /* bytes read */
  140.  
  141.     r_args = (struct nfsreadargs *) malloc(sizeof(struct nfsreadargs));
  142.     if (r_args == NULL) {
  143.     (void) fprintf(stderr, mem_err);
  144.     abort();
  145.     }
  146.     (void) bzero(r_args, sizeof(struct nfsreadargs));
  147.     if (! svc_getargs(xprt, xdr_readargs, r_args)) {
  148.     svcerr_decode(xprt);
  149.     (void) free(r_args);
  150.     return;
  151.     }
  152.     (void) bzero(&r_rslt, sizeof(struct nfsrdresult));
  153.  
  154.     /* set pointer to data in results struct */
  155.     r_rslt.rr_data = databuf;
  156.     count = r_args->ra_count;
  157.  
  158.     /* evaluate buffer count argument */
  159.     if (count > RD_SIZ) {
  160.     count = RD_SIZ;
  161.     fprintf (stderr, "NFS_READ: truncating req. from %ld\n",
  162.          r_args->ra_count);
  163.     }
  164.  
  165.     /* get attributes */
  166.     if (inattrget (r_args->ra_fhandle.f.fh_fno, &r_rslt.rr_attr) ==
  167.     (struct nfsfattr *) NULL)
  168.       r_rslt.rr_status = NFSERR_STALE;
  169.     else  {
  170.     if ((bytes = file_read(r_args->ra_fhandle.f.fh_fno,
  171.                    r_args->ra_offset, count,
  172.                    r_rslt.rr_data)) == -1) {
  173.         DBGPRT1 (nfserr, "file_read error %d", errno);
  174.         r_rslt.rr_status = puterrno (errno);
  175.     }
  176.     else {
  177.         char name [MAXPATHNAMELEN];
  178.         DBGPRT4 (nfsread, "%s: %ld/%d bytes at %ld",
  179.              intopn (r_args->ra_fhandle.f.fh_fno, name),
  180.              r_args->ra_count, bytes, r_args->ra_offset);
  181.         r_rslt.rr_bufsize = RD_SIZ;
  182.         r_rslt.rr_count = bytes;
  183.         r_rslt.rr_status = NFS_OK;
  184.         r_rslt.rr_bp = NULL;
  185.         r_rslt.rr_vp = NULL;
  186.     }
  187.     }
  188.     if (! svc_sendreply(xprt, xdr_rdresult, &r_rslt))
  189.       (void) fprintf(stderr, reply_err);
  190.     else if (NFS_VERBOSE)
  191.       (void) printf(">>> NFS_READ\n");
  192.  
  193.     /* free arguments */    
  194.     svc_freeargs(xprt, xdr_readargs, r_args);
  195. }
  196.  
  197. /*
  198.  *  void nfs_error(SVCXPRT *xprt, struct svc_req *req) --
  199.  *      Returns nfs error message.
  200.  */
  201. void nfs_error(xprt, req)
  202.     SVCXPRT *xprt;
  203.     struct svc_req *req;
  204. {
  205.     (void) fprintf(stderr, 
  206.         ">>> NFS_ERROR: procedure %d not supported\n", req->rq_proc);
  207.     svcerr_noproc(xprt);        /* send server error reply msg */
  208. }
  209.  
  210. /*
  211.  *  void nfs_getattr(SVCXPRT *xprt, struct svc_req *req) --
  212.  *      Gets file attributes.
  213.  */
  214. void nfs_getattr(xprt, req)
  215.     SVCXPRT *xprt;
  216.     struct svc_req *req;
  217. {
  218.     fhandle_t *fhp;            /* file handle is argument */
  219.     struct nfsattrstat attr;    /* return attributes */    
  220.     char *fullpath, path[MAXPATHNAMELEN];    /* full DOS path name */
  221.  
  222.     fhp = (fhandle_t *) malloc(sizeof(fhandle_t));
  223.     if (fhp == NULL) {
  224.     (void) fprintf(stderr, mem_err);
  225.     abort();
  226.     }
  227.     (void) bzero(fhp, sizeof(fhandle_t));
  228.     if (! svc_getargs(xprt, xdr_fhandle, fhp)) {
  229.     (void) fprintf(stderr, "nfs_getattr: cannot read args\n");
  230.     svcerr_decode(xprt);
  231.     (void) free(fhp);
  232.     return;
  233.     }
  234.  
  235.     /* Check the validity of the file handle */
  236.     if (!checkfh (fhp))
  237.       attr.ns_status = NFSERR_STALE;
  238.     else {
  239.     /* clear out return attributes */
  240.     (void) bzero(&attr, sizeof(struct nfsattrstat));
  241.     fullpath = intopn(fhp->f.fh_fno, path);    /* path from inode */
  242.  
  243.     if (! file_getattr(fullpath, &(attr.ns_attr)))
  244.       attr.ns_status = NFSERR_NOENT;
  245.     else
  246.       attr.ns_status = NFS_OK;
  247.     }
  248. #if 1
  249.     {
  250.       /* Hack:  tell the caller he is the owner */
  251.       struct authunix_parms *unix_cred;
  252.       unix_cred = (struct authunix_parms *) req->rq_clntcred;
  253.       attr.ns_attr.na_uid =  (u_long) unix_cred->aup_uid;
  254.     }
  255. #endif
  256.  
  257.     if (! svc_sendreply(xprt, xdr_attrstat, &attr))
  258.       (void) fprintf(stderr, reply_err);
  259.     else if (NFS_VERBOSE)
  260.       (void) printf(">>> NFS_GETATTR: %s\n", fullpath);
  261.  
  262.     svc_freeargs(xprt, xdr_fhandle, fhp);
  263. }
  264.  
  265. /*
  266.  *  void nfs_statfs(SVCXPRT *xprt, struct svc_req *req) --
  267.  *      Returns file system status
  268.  */
  269. void nfs_statfs(xprt, req)
  270.     SVCXPRT *xprt;
  271.     struct svc_req *req;
  272. {
  273.     struct nfsstatfs fs;
  274.     fhandle_t *fhp;
  275.  
  276.     fhp = (fhandle_t *) malloc(sizeof(fhandle_t));
  277.     if (fhp == NULL) {
  278.     (void) fprintf(stderr, mem_err);
  279.     abort();
  280.     }
  281.     (void) bzero(fhp, sizeof(fhandle_t));
  282.     if (! svc_getargs(xprt, xdr_fhandle, fhp)) {
  283.     svcerr_decode(xprt);
  284.     (void) free(fhp);
  285.     return;
  286.     }
  287.  
  288.     /* Check the validity of the file handle */
  289.     if (!checkfh (fhp))
  290.       fs.fs_status = NFSERR_STALE;
  291.     else {
  292.     /* clear out results struct */
  293.     (void) bzero(&fs, sizeof(struct nfsstatfs));
  294.     /* set up struct */
  295.     if (! file_freeblocks(fhp->f.fh_fsid, &(fs.fs_bfree), 
  296.                   &(fs.fs_blocks))) {
  297.         DBGPRT1 (nfserr, "statfs error %d", errno);
  298.         fs.fs_status = NFSERR_IO;
  299.     }
  300.     else {
  301.         fs.fs_tsize = NFS_MAXDATA;
  302.         fs.fs_bsize = FS_BLOCKSIZE;
  303.         fs.fs_status = NFS_OK;
  304.         fs.fs_bavail = fs.fs_bfree;
  305.     }
  306.     }
  307.     if (! svc_sendreply(xprt, xdr_statfs, &fs))
  308.       (void) fprintf(stderr, reply_err);
  309.     else if (NFS_VERBOSE)
  310.       (void) printf(">>> NFS_STATFS: drive %d\n", fhp->f.fh_fsid);
  311.     svc_freeargs(xprt, xdr_fhandle, fhp);
  312. }
  313.  
  314. /*
  315.  *  void nfs_readdir(SVCXPRT *xprt, struct svc_req *req) --
  316.  *      Read a directory.
  317.  */
  318. void nfs_readdir(xprt, req)
  319.     SVCXPRT *xprt;
  320.     struct svc_req *req;
  321. {
  322.     struct nfsrddirargs *args;        /* args */
  323.     struct nfsrddirres res;            /* results */
  324.     u_long nodeid;                /* inode number */
  325.     static u_long offs;                /* offset */
  326.     static int bytes;                /* # of dir bytes read */
  327.     int maxbytes;
  328.     struct udirect *udp;            /* directory cookie array */
  329. #define SUD    32                /* increment for offsets */
  330.     static u_long prevfh_no;            /* previous path handle */
  331.     static char prevudp[NFS_MAXDATA + sizeof (struct udirect)];
  332.     static u_long prevoffs;            /* previous offset */
  333.     static int  preveof;            /* previous EOF flag */
  334.  
  335.     args = (struct nfsrddirargs *) malloc(sizeof(struct nfsrddirargs));
  336.     if (args == NULL) {
  337.     (void) fprintf(stderr, mem_err);
  338.     abort();
  339.     }
  340.     (void) bzero(args, sizeof(struct nfsrddirargs));
  341.     if (! svc_getargs(xprt, xdr_rddirargs, args)) {
  342.     svcerr_decode(xprt);
  343.     (void) free(args);
  344.     return;
  345.     }
  346.     maxbytes = (args->rda_count > RD_SIZ ? RD_SIZ : args->rda_count);
  347.     if (maxbytes == 0)
  348.       maxbytes = RD_SIZ;
  349.  
  350.     nodeid   = args->rda_fh.f.fh_fno;
  351.  
  352.     /* Check the validity of the file handle */
  353.     if (!checkfh (&args->rda_fh))
  354.       res.rd_status = NFSERR_STALE;
  355.  
  356.     else {
  357.     /* clear out results */
  358.     (void) bzero(&res, sizeof(struct nfsrddirres));    /* zero results */
  359.     res.rd_bufsize = args->rda_count;             /* size of clnt req */
  360.     res.rd_status  = NFS_OK;
  361.  
  362.     /* point to directory entries block */
  363.     res.rd_entries = (struct udirect *) prevudp;
  364.     udp = res.rd_entries;
  365.  
  366.     /* see if this is an identical request */
  367.     if (args->rda_offset != 0L && args->rda_offset == prevoffs &&
  368.           prevfh_no == nodeid) {
  369.         res.rd_offset = offs;
  370.         res.rd_size   = bytes;
  371.         res.rd_eof    = preveof;
  372.         DBGPRT1 (nfsread, "READDIR (same %ld)", args->rda_offset);
  373.     }
  374.     else {
  375.         /* clear out the udp */
  376.         (void) bzero(prevudp, sizeof prevudp);
  377.  
  378.         /* read until filled */
  379.         res.rd_eof    = FALSE;
  380.         offs          = args->rda_offset;
  381.         prevoffs      = offs;
  382.         bytes          = 0;
  383.         prevfh_no     = nodeid;
  384.  
  385.         while (bytes < maxbytes) {
  386.         int rstat;        /* read status */
  387.  
  388.         rstat = file_rddir(nodeid, offs, udp);
  389.         if (rstat == -1) {            /* error reading */
  390.             res.rd_status = NFSERR_NOENT;
  391.             break;
  392.         }
  393.  
  394.         /* space for more? */
  395.         if ((bytes + udp->d_reclen) <= maxbytes) {
  396.             bytes += udp->d_reclen;
  397.  
  398.             /* Break out of loop if this is the last entry. */
  399.             if (rstat == 0) {
  400.             res.rd_eof = TRUE;
  401.             break;
  402.             }
  403.  
  404.             /* Point to next entry */
  405.             udp = (struct udirect *) ((char *) udp + UDIRSIZ(udp));
  406.             offs += SUD;            /* next offset */
  407.         }
  408.         else
  409.           break;
  410.         }
  411.         /* broke out of the loop */
  412.         if (res.rd_status == NFS_OK) {        /* good read */
  413.         res.rd_offset = offs;        /* next offset */
  414.         res.rd_size = bytes;        /* # of bytes */
  415.         res.rd_bufsize = bytes + 128;   /* Add enough extra for */
  416.                         /* XDR routine */
  417.         }
  418.         preveof = res.rd_eof;
  419.         DBGPRT4 (nfsread, "READDIR offset = %ld..%ld, bytes = %d  %s",
  420.              prevoffs / SUD, offs / SUD,
  421.              bytes, res.rd_eof ? "***EOF***" : "");
  422.     }
  423.     }
  424.  
  425.     if (! svc_sendreply(xprt, xdr_putrddirres, &res))
  426.       (void) fprintf(stderr, reply_err);
  427.     else if (NFS_VERBOSE)
  428.       (void) printf(">>> NFS_READDIR\n");
  429.  
  430.     /* free space */
  431.     svc_freeargs(xprt, xdr_rddirargs, args);
  432. #undef SUD
  433. }
  434.  
  435. /*
  436.  *  void nfs_lookup(SVCXPRT *xprt, struct svc_req *req) --
  437.  *      Directory lookup.
  438.  */
  439. void nfs_lookup(xprt, req)
  440.     SVCXPRT *xprt;
  441.     struct svc_req *req;
  442. {
  443.     struct nfsdiropargs *args;    /* arguments to call */
  444.     struct nfsdiropres res;        /* and results */
  445.     struct nfsfattr attr;        /* return attributes */
  446.     char *fullpath, path[MAXPATHNAMELEN]; /* path of file looked up */
  447.     
  448.     args = (struct nfsdiropargs *) malloc(sizeof(struct nfsdiropargs));
  449.     if (args == NULL) {
  450.         (void) fprintf(stderr, mem_err);
  451.         abort();
  452.     }
  453.     (void) bzero(args, sizeof(struct nfsdiropargs));
  454.     if (! svc_getargs(xprt, xdr_diropargs, args)) {
  455.         svcerr_decode(xprt);
  456.         (void) free(args);
  457.         return;
  458.     }
  459.  
  460.     /* Check the validity of the parent's handle */
  461.     if (!checkfh (&args->da_fhandle))
  462.       res.dr_status = NFSERR_STALE;
  463.     else {
  464.         /* clear out return struct */
  465.         (void) bzero(&res, sizeof(struct nfsdiropres));
  466.         fullpath = intopn(args->da_fhandle.f.fh_fno, path);/* path from */
  467.                                 /* inode of parent */
  468.         if (fullpath != NULL) {
  469.         /* 
  470.          * extra code here to handle XCOPY's brain-damaged
  471.          * way of passing wildcards when it really shouldn't.
  472.          */
  473.         int i;
  474.         int namelen;
  475.  
  476.         namelen = strlen(args->da_name);
  477.         for(i = 0; i < namelen; i++) {     /* scan the name */
  478.             if ((args->da_name)[i] == '*' || 
  479.                 (args->da_name)[i] == '?') {
  480.                 res.dr_status = NFSERR_NOENT;
  481.                 goto end;
  482.             }
  483.         }
  484.         /* end of extra code */
  485.         
  486.         if (strcmp(args->da_name, "..") == 0) {    /* asking for parent */
  487.             fullpath = intopn(parentinode(
  488.                     args->da_fhandle.f.fh_fno), path);
  489.         }
  490.         else if (strcmp(args->da_name , ".") != 0) {
  491.             (void) strcat(fullpath, "\\");    /* append seperator */
  492.             (void) strcat(fullpath, args->da_name);    
  493.             (void) strtolower(fullpath);    /* all lower case */
  494.         }
  495.         }
  496.         res.dr_status = validate_path (fullpath);
  497.  
  498.         DBGPRT1 (nfslookup, "fullpath = %s", fullpath);
  499.  
  500.         if (res.dr_status == NFS_OK) {
  501.         if ( ! file_getattr(fullpath, &attr)) {
  502.             DBGPRT0 (nfslookup, "no such file");
  503.             res.dr_status = NFSERR_NOENT;
  504.         }
  505.         else {        /* copy the attributes over */
  506.             res.dr_attr = attr;
  507.             res.dr_status = NFS_OK;        /* set proper status */
  508.             /* get a fhandle for it */
  509.             if (strcmp(args->da_name, ".") != 0)
  510.               res.dr_fhandle = pntofh(fullpath);
  511.             else
  512.               res.dr_fhandle = args->da_fhandle;
  513. #if 1
  514.             {
  515.             /* Hack:  tell the caller he is the owner */
  516.             struct authunix_parms *unix_cred;
  517.             unix_cred = (struct authunix_parms *) req->rq_clntcred;
  518.             res.dr_attr.na_uid =  (u_long) unix_cred->aup_uid;
  519.             }
  520. #endif
  521.         }
  522.         }
  523.     }
  524.     /* reply to caller */
  525. end:    if (NFS_VERBOSE)
  526.         (void) printf(">>> NFS_LOOKUP: %s\n", fullpath);
  527.     if (! svc_sendreply(xprt, xdr_diropres, &res))
  528.         (void) fprintf(stderr, reply_err);
  529.  
  530.     /* free used space */
  531.     svc_freeargs(xprt, xdr_diropargs, args);
  532. }
  533.  
  534. /*
  535.  *   void nfs_write(SVCXPRT *xprt, struct svc_req *req) --
  536.  *      Do an atomic write operation.
  537.  */
  538. void nfs_write(xprt, req)
  539.     SVCXPRT *xprt;
  540.     struct svc_req *req;
  541. {
  542.     struct nfswriteargs *args;        /* args */
  543.     struct nfsattrstat res;            /* return stat */
  544.  
  545.     /* alloc space for args */
  546.     args = (struct nfswriteargs *) malloc(sizeof(struct nfswriteargs));
  547.     if (args == NULL) {
  548.         (void) fprintf(stderr, mem_err);
  549.         abort();
  550.     }
  551.     (void) bzero(args, sizeof(struct nfswriteargs));
  552.     if (! svc_getargs(xprt, xdr_writeargs, args)) {
  553.         svcerr_decode(xprt);
  554.         (void) free(args);
  555.         return;
  556.     }
  557.     if (NFS_READONLYFS) {
  558.         nfserr_readonlyfs(xprt, xdr_writeargs, args);
  559.         return;
  560.     }
  561.     (void) bzero(&res, sizeof(struct nfsattrstat));
  562.     /* evaluate buffer count argument */
  563.     if (args->wa_count > NFS_MAXDATA) {
  564.         res.ns_status = NFSERR_IO;
  565.         goto reply;
  566.     }
  567.     res.ns_status = file_write(args->wa_fhandle.f.fh_fno, args->wa_offset,
  568.                    args->wa_count, args->wa_data);
  569.     if (res.ns_status == NFS_OK) {
  570.         /* get file attributes */
  571.         if (inattrget (args->wa_fhandle.f.fh_fno, &res.ns_attr) ==
  572.             (struct nfsfattr *) NULL) {
  573.             res.ns_status = NFSERR_STALE;
  574.         }
  575.     }
  576.     else
  577.         DBGPRT2 (nfserr, "write %ld, error %d",
  578.              args->wa_fhandle.f.fh_fno, res.ns_status);
  579.  
  580.       reply:
  581.     if (! svc_sendreply(xprt, xdr_attrstat, &res))
  582.         (void) fprintf(stderr, reply_err);
  583.     else if (NFS_VERBOSE)
  584.         (void) printf(">>> NFS_WRITE: %ld\n",
  585.                   args->wa_fhandle.f.fh_fno);
  586.  
  587.     svc_freeargs(xprt, xdr_writeargs, args);    /* free all data */
  588. }
  589.  
  590. /*
  591.  *  void nfs_create(SVCXPRT *xprt, struct svc_req *req) --
  592.  *      Create a file.
  593.  */
  594. void nfs_create(xprt, req)
  595.     SVCXPRT *xprt;
  596.     struct svc_req *req;
  597. {
  598.     struct nfscreatargs *args;            /* create args */
  599.     struct nfsdiropres res;            /* return result */
  600.     char *fullpath, path[MAXPATHNAMELEN];    /* full name */
  601.     int stat;                    /* create return stat */
  602.     struct authunix_parms *unix_cred;
  603.  
  604.     args = (struct nfscreatargs *) malloc(sizeof(struct nfscreatargs));
  605.     if (args == NULL) {
  606.         (void) fprintf(stderr, mem_err);
  607.         abort();
  608.     }
  609.     (void) bzero(args, sizeof(struct nfscreatargs));
  610.     if (! svc_getargs(xprt, xdr_creatargs, args)) {
  611.     svcerr_decode(xprt);
  612.     (void) free(args);
  613.     return;
  614.     }
  615.     if (NFS_READONLYFS) {        /* read only file system */
  616.     nfserr_readonlyfs(xprt, xdr_creatargs, args);
  617.     return;
  618.     }
  619.  
  620.     /* Check the validity of the file handle */
  621.     if (!checkfh (&args->ca_da.da_fhandle))
  622.       res.dr_status = NFSERR_STALE;
  623.     else {
  624.     /* clear out return struct */
  625.     (void) bzero(&res, sizeof(struct nfsdiropres));
  626.     fullpath = intopn(args->ca_da.da_fhandle.f.fh_fno, path);
  627.     if (fullpath != NULL) {
  628.         (void) strcat(fullpath, "\\");        /* make rest of name */
  629.         (void) strcat(fullpath, args->ca_da.da_name);
  630.         (void) strtolower (fullpath);        /* force lower case */
  631.     }
  632.     if (file_getattr(fullpath, &(res.dr_attr))) {    /* file exists */
  633.         res.dr_status = NFSERR_EXIST;
  634.     }
  635.     /* fill in default UID/GID info */
  636.     unix_cred = (struct authunix_parms *) req->rq_clntcred;
  637.     if (args->ca_sa.sa_uid == -1)
  638.       args->ca_sa.sa_uid = (u_long) unix_cred->aup_uid;
  639.     if (args->ca_sa.sa_gid == -1)
  640.       args->ca_sa.sa_gid = (u_long) unix_cred->aup_gid;
  641.  
  642.     /* create a file */
  643.     res.dr_status = file_create(fullpath, &(args->ca_sa), &res.dr_attr);
  644.     if (res.dr_status == NFS_OK) {            /* no errors */
  645.         /* make file handle */
  646.         res.dr_fhandle = pntofh(fullpath);
  647.     }
  648.     }
  649.     if (! svc_sendreply(xprt, xdr_diropres, &res))
  650.       (void) fprintf(stderr, reply_err);
  651.     else if (NFS_VERBOSE)
  652.       (void) printf(">>> NFS_CREATE: %s\n", fullpath);
  653.  
  654.     /* free all data */
  655.     svc_freeargs(xprt, xdr_creatargs, args);
  656. }
  657.     
  658. /*
  659.  *  void nfs_mkdir(SVCXPRT *xprt, struct svc_req *req) --
  660.  *      Make a directory request.  All DOS directories are readable and
  661.  *    writeable, hence the set attribute field is ignored.
  662.  */
  663. void nfs_mkdir(xprt, req)
  664.     SVCXPRT *xprt;
  665.     struct svc_req *req;
  666. {
  667.     struct nfscreatargs *args;
  668.     struct nfsdiropres res;
  669.     char *fullpath, path[MAXPATHNAMELEN];
  670.  
  671.     args = (struct nfscreatargs *) malloc(sizeof(struct nfscreatargs));
  672.     if (args == NULL) {
  673.         (void) fprintf(stderr, mem_err);
  674.         abort();
  675.     }
  676.     (void) bzero(args, sizeof(struct nfscreatargs));
  677.     if (! svc_getargs(xprt, xdr_diropargs, args)) {
  678.         svcerr_decode(xprt);
  679.         (void) free(args);
  680.         return;
  681.     }
  682.     if (NFS_READONLYFS) {
  683.         nfserr_readonlyfs(xprt, xdr_diropargs, args);
  684.         return;
  685.     }
  686.     /* construct path name of new directory */
  687.     fullpath = intopn(args->ca_da.da_fhandle.f.fh_fno, path);
  688.     if (fullpath != NULL) {
  689.         (void) strcat(fullpath, "\\");
  690.         (void) strcat(fullpath, args->ca_da.da_name);
  691.         (void) strtolower (fullpath);        /* force lower case */
  692.     }
  693.  
  694.     (void) bzero(&res, sizeof(struct nfsdiropres));
  695.  
  696.     /* validate path name */
  697.     if ((res.dr_status = validate_path (fullpath)) == NFS_OK)
  698.         res.dr_status = mkdir(fullpath);
  699.  
  700.     if (res.dr_status == NFS_OK) {
  701.         res.dr_status = !file_getattr(fullpath, &(res.dr_attr));
  702.  
  703.         if (res.dr_status == NFS_OK)    /* make new file handle */
  704.           res.dr_fhandle = pntofh(fullpath);
  705.         else
  706.           res.dr_status = puterrno(errno);
  707.     }
  708.     if (! svc_sendreply(xprt, xdr_diropres, &res)) 
  709.         (void) fprintf(stderr, reply_err);
  710.     else if (NFS_VERBOSE)
  711.         (void) printf(">>> NFS_MKDIR: %s\n", fullpath);
  712.  
  713.     /* free all data */
  714.     svc_freeargs(xprt, xdr_creatargs, args);
  715. }
  716.  
  717. /*
  718.  *  void nfs_remove(SVCXPRT *xprt, struct svc_req *req) --
  719.  *      Remove a file specified by the handle.
  720.  */
  721. void nfs_remove(xprt, req)
  722.     SVCXPRT *xprt;
  723.     struct svc_req *req;
  724. {
  725.     struct nfsdiropargs *args;        /* dir op arguments */
  726.     enum nfsstat stat;            /* status of the remove */
  727.     char *fullpath, path[MAXPATHNAMELEN];    /* full path of file */
  728.  
  729.     args = (struct nfsdiropargs *) malloc(sizeof(struct nfsdiropargs));
  730.     if (args == NULL) {
  731.         (void) fprintf(stderr, mem_err);
  732.         abort();
  733.     }
  734.     (void) bzero(args, sizeof(struct nfsdiropargs));    /* zero it */
  735.     if (! svc_getargs(xprt, xdr_diropargs, args)) {
  736.         svcerr_decode(xprt);
  737.         (void) free(args);        /* couldn't decode it */
  738.         return;
  739.     }
  740.     if (NFS_READONLYFS) {
  741.         nfserr_readonlyfs(xprt, xdr_diropargs, &args);
  742.         return;
  743.     }
  744.     /* get full directory name from inode number */
  745.     fullpath = intopn(args->da_fhandle.f.fh_fno, path);
  746.     if (fullpath == NULL)
  747.         stat = NFSERR_NOENT;
  748.     else {
  749.         (void) strcat(fullpath, "\\");    /* append the name */
  750.         (void) strcat(fullpath, args->da_name);
  751.         stat = file_unlink(fullpath);
  752.     }
  753.     /* now reply to request */
  754.     if (! svc_sendreply(xprt, xdr_enum, &stat))
  755.         (void) fprintf(stderr, reply_err);
  756.     else if (NFS_VERBOSE)
  757.         (void) printf(">>> NFS_REMOVE: %s\n", fullpath);
  758.  
  759.     svc_freeargs(xprt, xdr_diropargs, args);
  760. }
  761.  
  762. /*
  763.  *  void nfs_rmdir(SVCXPRT *xprt, struct svc_req *req) --
  764.  *      Remove a directory specified by the handle.
  765.  */
  766. void nfs_rmdir(xprt, req)
  767.     SVCXPRT *xprt;
  768.     struct svc_req *req;
  769. {
  770.     struct nfsdiropargs *args;        /* dir op arguments */
  771.     enum nfsstat stat;            /* status of the remove */
  772.     char *fullpath, path[MAXPATHNAMELEN];    /* full path of file */
  773.     u_long node;
  774.  
  775.     args = (struct nfsdiropargs *) malloc(sizeof(struct nfsdiropargs));
  776.     if (args == NULL) {
  777.         (void) fprintf(stderr, mem_err);
  778.         abort();
  779.     }
  780.     (void) bzero(args, sizeof(struct nfsdiropargs));    /* zero it */
  781.     if (! svc_getargs(xprt, xdr_diropargs, args)) {
  782.         svcerr_decode(xprt);
  783.         (void) free(args);        /* couldn't decode it */
  784.         return;
  785.     }
  786.     /* get full path name from inode number */
  787.     fullpath = intopn(args->da_fhandle.f.fh_fno, path);
  788.     if (fullpath == NULL)
  789.         stat = NFSERR_NOENT;            /* doesn't exist */
  790.     else {
  791.         (void) strcat(fullpath, "\\");        /* append the name */
  792.         (void) strcat(fullpath, args->da_name);
  793.         if (rmdir(fullpath)) {    /* remove it */
  794.             stat = (enum nfsstat) errno;
  795.  
  796.             /* Translate the error code so the correct message */
  797.             /* will be displayed. */
  798.             if (stat == NFSERR_ACCES)
  799.               stat = NFSERR_EXIST;
  800.         }
  801.         else {
  802.             stat = NFS_OK;
  803.             /* Remove the inode if assigned */
  804.             if ((node = pntoin (fullpath)) != -1)
  805.               inremnode (node);
  806.         }
  807.     }
  808.     /* now reply to request */
  809.     if (! svc_sendreply(xprt, xdr_enum, &stat))
  810.         (void) fprintf(stderr, reply_err);
  811.     else if (NFS_VERBOSE)
  812.         (void) printf(">>> NFS_RMDIR: %s\n", fullpath);
  813.  
  814.     svc_freeargs(xprt, xdr_diropargs, args);    /* free data */
  815. }
  816.  
  817. /*
  818.  *  void nfs_rename(SVCXPRT *xprt, struct svc_req *req) --
  819.  *      Renames given file to new name specified in the args.
  820.  */
  821. void nfs_rename(xprt, req)
  822.     SVCXPRT *xprt;
  823.     struct svc_req *req;
  824. {
  825.     struct nfsrnmargs *args;        /* arguments to rename */
  826.     enum nfsstat stat;            /* thr reply status */
  827.     char *oldname, *newname,        /* old and new filenames */
  828.       opath[MAXPATHNAMELEN], npath[MAXPATHNAMELEN];
  829.  
  830.     args = (struct nfsrnmargs *) malloc(sizeof(struct nfsrnmargs));
  831.     if (args == NULL) {
  832.         (void) fprintf(stderr, mem_err);
  833.         abort();
  834.     }
  835.     (void) bzero(args, sizeof(struct nfsrnmargs));
  836.     if (! svc_getargs(xprt, xdr_rnmargs, args)) {
  837.         svcerr_decode(xprt);
  838.         (void) free(args);
  839.         return;
  840.     }
  841.     if (NFS_READONLYFS) {
  842.         nfserr_readonlyfs(xprt, xdr_rnmargs, args);
  843.         return;
  844.     }
  845.     /* make old name from inode */
  846.     oldname = intopn(args->rna_from.da_fhandle.f.fh_fno, opath);
  847.     newname = intopn(args->rna_to.da_fhandle.f.fh_fno, npath);
  848.     if (oldname == NULL || newname == NULL)    /* cannot find path for file */
  849.         stat = NFSERR_STALE;        /* ==> stale file handle */
  850.     else {
  851.         /* complete specification for names */
  852.         (void) strcat(oldname, "\\");
  853.         (void) strcat(oldname, args->rna_from.da_name);
  854.         (void) strcat(newname, "\\");
  855.         (void) strcat(newname, args->rna_to.da_name);
  856.  
  857.         /* Perform the rename operation */
  858.  
  859.         stat = file_rename(oldname, newname);
  860.     }
  861.     /* reply to rename request */
  862.     if (! svc_sendreply(xprt, xdr_enum, &stat))
  863.         (void) fprintf(stderr, reply_err);
  864.     else if (NFS_VERBOSE)
  865.         (void) fprintf(stderr, ">>> NFS_RENAME: %s to %s\n", 
  866.                 oldname, newname);
  867.     
  868.     /* free all data */
  869.     svc_freeargs(xprt, xdr_rnmargs, args);
  870. }
  871.  
  872. /*
  873.  *  void nfs_setattr(SVCXPRT *xprt, struct svc_req *req) --
  874.  *      Set file attributes.
  875.  */
  876. void nfs_setattr(xprt, req)
  877.     SVCXPRT *xprt;
  878.     struct svc_req *req;
  879. {
  880.     struct nfssaargs *args;            /* arguments */
  881.     struct nfsattrstat res;            /* results */
  882.  
  883.     args = (struct nfssaargs *) malloc(sizeof(struct nfssaargs));
  884.     if (args == NULL) {
  885.     (void) fprintf(stderr, mem_err);
  886.     abort();
  887.     }
  888.     (void) bzero(args, sizeof(struct nfssaargs));
  889.     if (! svc_getargs(xprt, xdr_saargs, args)) {
  890.     svcerr_decode(xprt);
  891.     (void) free(args);
  892.     return;
  893.     }
  894.     DBGPRT4 (nfsdebug, "SETATTR: size = %ld  mode = %o%05o  time = %ld",
  895.          args->saa_sa.sa_size, (int) (args->saa_sa.sa_mode >> 15),
  896.          (int) args->saa_sa.sa_mode & 077777,
  897.          args->saa_sa.sa_mtime.tv_sec);
  898.     if (NFS_READONLYFS) {
  899.     nfserr_readonlyfs(xprt, xdr_saargs, args);
  900.     return;
  901.     }
  902.  
  903.     /* If a parameter in the argument block is not -1, set the  */
  904.     /* parameter within the file.                */
  905.  
  906.     /* File mode / protection */
  907.     res.ns_status = NFS_OK;
  908.     if (args->saa_sa.sa_mode != -1)
  909.       res.ns_status = file_setperm(args->saa_fh.f.fh_fno,
  910.                    args->saa_sa.sa_mode);
  911.  
  912.     /* Modification time */
  913.     if (res.ns_status == NFS_OK && args->saa_sa.sa_mtime.tv_sec > 0)
  914.       res.ns_status = file_settime(args->saa_fh.f.fh_fno,
  915.                    args->saa_sa.sa_mtime.tv_sec);
  916.  
  917.     /* Size */
  918.     if (res.ns_status == NFS_OK && args->saa_sa.sa_size != -1)
  919.       res.ns_status = file_setsize(args->saa_fh.f.fh_fno,
  920.                    args->saa_sa.sa_size);
  921.  
  922.     /* User ID / Group ID */
  923.     if (res.ns_status == NFS_OK && (args->saa_sa.sa_uid != -1 ||
  924.     args->saa_sa.sa_gid != -1))
  925.       res.ns_status = file_setowner(args->saa_fh.f.fh_fno,
  926.                     args->saa_sa.sa_uid, args->saa_sa.sa_gid);
  927.  
  928.     (void) bzero(&res, sizeof(struct nfsattrstat));
  929.     if (res.ns_status == NFS_OK &&
  930.     !inattrget (args->saa_fh.f.fh_fno, &res.ns_attr)) {
  931.     res.ns_status = NFSERR_NOENT;
  932.     }
  933.  
  934.     if (! svc_sendreply(xprt, xdr_attrstat, &res))
  935.       (void) fprintf(stderr, reply_err);
  936.     else if (NFS_VERBOSE)
  937.       (void) printf(">>> NFS_SETATTR\n");
  938.     
  939.     /* free data */
  940.     svc_freeargs(xprt, xdr_saargs, args);
  941. }
  942.  
  943. /*
  944.  *  void nfs_link(SVCXPRT *xprt, struct svc_req *req) --
  945.  *      Create file link (not supported under DOS)
  946.  */
  947. void nfs_link(xprt, req)
  948.      SVCXPRT *xprt;
  949.      struct svc_req *req;
  950. {
  951.     struct nfslinkargs *args;        /* arguments to link */
  952.     struct nfsdiropres res;        /* return result */
  953.     enum nfsstat stat;            /* the reply status */
  954.     char *oldname, *newname,        /* old and new filenames */
  955.           opath[MAXPATHNAMELEN], npath[MAXPATHNAMELEN];
  956.  
  957.     args = (struct nfslinkargs *) malloc(sizeof(struct nfslinkargs));
  958.     if (args == NULL) {
  959.     (void) fprintf(stderr, mem_err);
  960.     abort();
  961.     }
  962.     (void) bzero(args, sizeof(struct nfslinkargs));
  963.     (void) bzero(&res, sizeof(struct nfsdiropres));
  964.     if (! svc_getargs(xprt, xdr_linkargs, args)) {
  965.     svcerr_decode(xprt);
  966.     (void) free(args);
  967.     return;
  968.     }
  969.     if (NFS_READONLYFS) {
  970.     nfserr_readonlyfs(xprt, xdr_linkargs, args);
  971.     return;
  972.     }
  973.     /* Translate inodes into names */
  974.     oldname = intopn(args->la_from.f.fh_fno, opath);
  975.     newname = intopn(args->la_to.da_fhandle.f.fh_fno, npath);
  976.     if (oldname == NULL || newname == NULL)    /* cannot find path for file */
  977.       stat = NFSERR_STALE;        /* ==> stale file handle */
  978.     else {
  979.     /* not supported:  return an error code */
  980.  
  981.     stat = NFSERR_ACCES;
  982.     }
  983.     res.dr_status = stat;
  984.  
  985.     if (! svc_sendreply(xprt, xdr_diropres, &res))
  986.       (void) fprintf(stderr, reply_err);
  987.     else if (NFS_VERBOSE)
  988.       (void) fprintf(stderr, ">>> NFS_LINK: %s to %s\n", 
  989.              oldname, newname);
  990.     svc_freeargs(xprt, xdr_linkargs, args);
  991. }
  992.  
  993.  
  994. /*
  995.  *  void nfs_symlink(SVCXPRT *xprt, struct svc_req *req) --
  996.  *      Create symbolic link (not supported under DOS)
  997.  */
  998. void nfs_symlink(xprt, req)
  999.      SVCXPRT *xprt;
  1000.      struct svc_req *req;
  1001. {
  1002.     struct nfsslargs  *args;        /* arguments to sym link */
  1003.     struct nfsrdlnres res;        /* return result */
  1004.     enum nfsstat stat;            /* the reply status */
  1005.     char *oldname, opath[MAXPATHNAMELEN]; /* old filename */
  1006.  
  1007.     args = (struct nfsslargs *) malloc(sizeof(struct nfsslargs));
  1008.     if (args == NULL) {
  1009.     (void) fprintf(stderr, mem_err);
  1010.     abort();
  1011.     }
  1012.     (void) bzero(args, sizeof(struct nfsslargs));
  1013.     (void) bzero(&res, sizeof(struct nfsrdlnres));
  1014.     if (! svc_getargs(xprt, xdr_slargs, args)) {
  1015.     svcerr_decode(xprt);
  1016.     (void) free(args);
  1017.     return;
  1018.     }
  1019.  
  1020.     /* Translate inode into name */
  1021.     oldname = intopn(args->sla_from.da_fhandle.f.fh_fno, opath);
  1022.     if (oldname == NULL)        /* cannot find path for file */
  1023.       stat = NFSERR_STALE;        /* ==> stale file handle */
  1024.     else {
  1025.     /* not supported:  return an error code */
  1026.  
  1027.     stat = NFSERR_ACCES;
  1028.     }
  1029.     res.rl_status = stat;
  1030.  
  1031.     if (! svc_sendreply(xprt, xdr_rdlnres, &res))
  1032.       (void) fprintf(stderr, reply_err);
  1033.     else if (NFS_VERBOSE)
  1034.       (void) fprintf(stderr, ">>> NFS_SYMLINK\n");
  1035.     svc_freeargs(xprt, xdr_linkargs, args);
  1036. }
  1037.  
  1038.  
  1039. /*
  1040.  *  void nfserr_readonlyfs(SVCXPRT *xprt, xdrproc_t xproc, void *args) --
  1041.  *      Return error status of NFSERR_ROFS.   Write attempted on read only
  1042.  *    file system.
  1043.  */
  1044. void nfserr_readonlyfs(xprt, xproc, args)
  1045.     SVCXPRT *xprt;
  1046.     xdrproc_t xproc;
  1047.     void *args;
  1048. {
  1049.     enum nfsstat err;
  1050.  
  1051.     err = NFSERR_ROFS;
  1052.     if (! svc_sendreply(xprt, xdr_enum, &err))
  1053.         (void) fprintf(stderr, reply_err);
  1054.     svc_freeargs(xprt, xproc, args);
  1055. }
  1056.