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