mountLib.c
上传用户:baixin
上传日期:2008-03-13
资源大小:4795k
文件大小:33k
开发平台:

MultiPlatform

  1. /* mountLib.c - Mount protocol library */
  2. /* Copyright 1994 - 2001 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5. modification history
  6. --------------------
  7. 01s,10may02,kbw  making man page edits
  8. 01r,07may02,kbw  making man page edits
  9. 01q,05nov01,vvv  made max. path length configurable (SPR #63551)
  10. 01p,05nov01,wap  Fix memory leak in mountproc_umnt_1 and mountproc_umntall_1
  11.                  (SPR #63489)
  12. 01o,15oct01,rae  merge from truestack ver 01v, base 01m (SPRs 62705,
  13.                  29301/29362, 32821/31223)
  14. 01n,04dec00,ijm  fixed file descriptor leak in nfsUnexport (SPR# 7531)
  15. 01n,21jun00,rsh  upgrade to dosFs 2.0
  16. 01l,05nov98,rjc  modifications for dosfs2.
  17. 01m,14mar99,jdi  doc: removed refs to config.h and/or configAll.h (SPR 25663).
  18. 01l,05feb99,dgp  document errno values
  19. 01k,26aug97,spm  removed compiler warnings (SPR #7866)
  20. 01j,12dec96,jag  fix spr 7601 on procedure mountproc_umnt_1, deleted unused
  21.  variable deleteThis.
  22. 01i,30aug95,rch  fix for spr 4333.
  23. 01h,27feb95,jdi  doc: changed dosFsMode to dosFsFileMode (doc only) (SPR 4085).
  24. 01g,11feb95,jdi  doc format repair.
  25. 01f,24jan95,rhp  update initialization info for exportable file systems,
  26.                  and misc doc tweaks
  27. 01e,11may94,jmm  integrated Roland's doc changes
  28. 01d,25apr94,jmm  doc cleanup; changed mode to readOnly in NFS_EXPORT_ENTRY
  29. 01c,21apr94,jmm  fixed problem with mountproc_dump_1 overwritting strings
  30.                  documentation cleanup, reordered routines
  31. 01b,20apr94,jmm  formatting cleanup, mountproc_dump_1 and mountproc_exports_1
  32.                  fixed
  33. 01a,07mar94,jmm  written
  34. */
  35. /*
  36. DESCRIPTION
  37. This library implements a mount server to support mounting VxWorks
  38. file systems remotely.  The mount server is an implementation of
  39. version 1 of the mount protocol as defined in RFC 1094.  It is closely
  40. connected with version 2 of the Network File System Protocol
  41. Specification, which in turn is implemented by the library nfsdLib.
  42. &NOTE: The only routines in this library that are normally called by
  43. applications are nfsExport() and nfsUnexport().  The mount daemon is
  44. normally initialized indirectly by nfsdInit().
  45. The mount server is initialized by calling mountdInit().  Normally,
  46. this is done by nfsdInit(), although it is possible to call
  47. mountdInit() directly if the NFS server is not being initialized.
  48. Defining INCLUDE_NFS_SERVER enables the call to nfsdInit() during
  49. the boot process, which in turn calls mountdInit(), so there is
  50. normally no need to call either routine manually.  mountdInit() spawns
  51. one task, `tMountd', which registers as an RPC service with the
  52. portmapper.
  53. Currently, only the dosFsLib file system is supported.
  54. File systems are exported with the nfsExport() call.
  55. To export VxWorks file systems via NFS, you need facilities from both
  56. this library and from nfsdLib.  To include both, add INCLUDE_NFS_SERVER
  57. and rebuild VxWorks.
  58. .SS Example
  59. The following example illustrates how to export an
  60. existing dosFs file system.
  61. First, initialize the block device containing your file system.
  62. Then assuming the dosFs system is called "/export" execute the following 
  63. code on the target:
  64. .CS
  65. nfsExport ("/export", 0, FALSE, 0);           /@ make available remotely @/
  66. .CE
  67. This makes it available to all
  68. clients to be mounted using the client's NFS mounting command.  (On
  69. UNIX systems, mounting file systems normally requires root privileges.)
  70. VxWorks does not normally provide authentication services for NFS
  71. requests, and the DOS file system does not provide file permissions.
  72. If you need to authenticate incoming requests, see the documentation
  73. for nfsdInit() and mountdInit() for information about authorization
  74. hooks.
  75. The following requests are accepted from clients.  For details of
  76. their use, see Appendix A of RFC 1094, "NFS: Network File System
  77. Protocol Specification."
  78. .TS
  79. tab(|);
  80. lf3 lf3
  81. l n.
  82.  Procedure Name     |   Procedure Number
  83. _
  84.  MOUNTPROC_NULL     |   0
  85.  MOUNTPROC_MNT      |   1
  86.  MOUNTPROC_DUMP     |   2
  87.  MOUNTPROC_UMNT     |   3
  88.  MOUNTPROC_UMNTALL  |   4
  89.  MOUNTPROC_EXPORT   |   5
  90. .TE
  91. SEE ALSO: dosFsLib, nfsdLib, RFC 1094
  92. INTERNAL: mountd is not reentrant, and there cannot be more than one
  93. mountd task running at any one time.
  94. The routines called by mountd are named mountproc_ROUTINENAME_1.  This
  95. is the standard RPC naming convention used by code generated from
  96. rpcgen.
  97. */
  98. /* LINTLIBRARY */
  99. #include "vxWorks.h"
  100. #include "sys/stat.h"
  101. #include "ioLib.h"
  102. #include "taskLib.h"
  103. #include "lstLib.h"
  104. #include "mountLib.h"
  105. #include "nfsdLib.h"
  106. #include "pathLib.h"
  107. #include "rpcLib.h"
  108. #include "rpc/pmap_clnt.h"
  109. #include "rpc/rpc.h"
  110. #include "rpcLib.h"
  111. #include "inetLib.h"
  112. #include "semLib.h"
  113. #include "hostLib.h"
  114. #include "stdio.h"
  115. #include "stdlib.h"
  116. #include "string.h"
  117. #include "xdr_nfsserv.h"
  118. #include "private/nfsHashP.h"
  119. #include "memPartLib.h"
  120. /* defines */
  121. #ifndef KHEAP_REALLOC
  122. #define KHEAP_REALLOC(pBuf,newsize)  memPartRealloc(memPartIdKernel,pBuf,newsize)
  123. #endif /* KHEAP_REALLOC */
  124. #ifdef __GNUC__
  125. # ifndef alloca
  126. #  define alloca __builtin_alloca
  127. # endif
  128. #endif
  129. /* IMPORTS */
  130. IMPORT int nfsMaxPath;  /* max. length of file path */
  131. /* DATA STRUCTURES */
  132. typedef struct
  133.     {
  134.     char * next;           /* next and prev are used by lstLib */
  135.     char * prev;
  136.     char   clientName [MAXHOSTNAMELEN + 1]; /* name of the host mounting this
  137.      * directory */
  138.     /*
  139.      * Mounted directory. Though it appears a single character, it is a char
  140.      * array. The array is allocated when a MOUNT_CLIENT struct is allocated.
  141.      * This change was required for adding configurable path length support.
  142.      */
  143.     char   directory [1];        
  144.     } MOUNT_CLIENT;
  145. /* GLOBALS */
  146. int     mountdNExports = MAX_EXPORTED_FILESYSTEMS; /* max. num. exported FS's */
  147. int     mountdTaskId           = 0;         /* Task ID of the mountd task */
  148. int     mountdPriorityDefault  = MOUNTD_PRIORITY_DEFAULT; /* default priority */
  149. int     mountdStackSizeDefault = MOUNTD_STACKSIZE_DEFAULT; /* default stack   */
  150. /* LOCALS */
  151. LOCAL FUNCPTR mountdAuthHook = NULL; /* Hook to run to authorize packets */
  152. LOCAL LIST *  mountPoints = NULL; /* Linked list of exported mount points */
  153. LOCAL SEM_ID  mountSem    = NULL; /* Sem controlling access to mountPoints */
  154. LOCAL LIST *  nfsClients  = NULL; /* Linked list of clients mounting fs's */
  155. LOCAL SEM_ID  clientsSem  = NULL; /* Sem controlling access to nfsClients */
  156. LOCAL int     fsIdNumber  = 1; /* ID number for exported file systems */
  157. /* forward LOCAL functions */
  158. LOCAL void mountdRequestProcess (struct svc_req * rqstp,
  159.  register SVCXPRT * transp);
  160. LOCAL char * svc_reqToHostName (struct svc_req * rqstp, char * hostName);
  161. LOCAL MOUNT_CLIENT * mountListFind (struct svc_req * rqstp, dirpath * path);
  162. /******************************************************************************
  163. *
  164. * mountdInit - initialize the mount daemon
  165. * This routine spawns a mount daemon if one does not already
  166. * exist.  Defaults for the <priority> and <stackSize> arguments are
  167. * in the global variables `mountdPriorityDefault' and
  168. * `mountdStackSizeDefault', and are initially set to
  169. * MOUNTD_PRIORITY_DEFAULT and MOUNTD_STACKSIZE_DEFAULT respectively.
  170. *
  171. * Normally, no authorization checking is performed by either mountd or
  172. * nfsd.  To add authorization checking, set <authHook> to point to a
  173. * routine declared as follows:
  174. *
  175. * .CS
  176. * nfsstat routine
  177. *     (
  178. *     int                progNum,       /@ RPC program number @/
  179. *     int                versNum, /@ RPC program version number @/
  180. *     int                procNum, /@ RPC procedure number @/
  181. *     struct sockaddr_in clientAddr,    /@ address of the client @/
  182. *     MOUNTD_ARGUMENT *  mountdArg    /@ argument of the call @/
  183. *     )
  184. * .CE
  185. * The <authHook> callback must return OK if the request is authorized,
  186. * and any defined NFS error code (usually NFSERR_ACCES) if not.
  187. *
  188. * VXWORKS AE PROTECTION DOMAINS
  189. * Under VxWorks AE, you can call mountdInit() from within the kernel 
  190. * protection domain only, and the function referenced in the <authHook> 
  191. * parameter must reside in the kernel protection domain.  
  192. * This restriction does not apply under non-AE versions of VxWorks.  
  193. *
  194. * RETURNS: OK, or ERROR if the mount daemon could not be correctly
  195. * initialized.
  196. */
  197. STATUS mountdInit
  198.     (
  199.     int priority, /* priority of the mount daemon            */
  200.     int stackSize, /* stack size of the mount daemon          */
  201.     FUNCPTR authHook, /* hook to run to authorize each request   */
  202.     int nExports, /* maximum number of exported file systems */
  203.     int options /* currently unused - set to 0             */
  204.     )
  205.     {
  206.     if (0 != mountdTaskId)
  207. {
  208. printf ("Mount daemon already initializedn");
  209. return (ERROR);
  210. }
  211.     mountdAuthHook = authHook;
  212.     if (nExports > 0)
  213.         mountdNExports = nExports;
  214.     if ((nfsClients = KHEAP_ALLOC (sizeof (*nfsClients))) == NULL)
  215.         return (ERROR);
  216.     if ((clientsSem = semMCreate (SEM_Q_PRIORITY)) == NULL)
  217. {
  218. KHEAP_FREE ((char *)nfsClients);
  219. return (ERROR);
  220. }
  221.     lstInit (nfsClients);
  222.     
  223.     if ((mountPoints = KHEAP_ALLOC (sizeof (*mountPoints))) == NULL)
  224.             return (ERROR);
  225.     if ((mountSem = semMCreate (SEM_Q_PRIORITY)) == NULL)
  226.         {
  227.         KHEAP_FREE ((char *)mountPoints);
  228.         return (ERROR);
  229.         } 
  230.     lstInit (mountPoints);
  231.     if (priority == 0)
  232. priority = mountdPriorityDefault;
  233.     if (stackSize == 0)
  234. stackSize = mountdStackSizeDefault;
  235.     
  236.     if ((mountdTaskId = taskSpawn ("tMountd", priority, 0, stackSize,
  237. (FUNCPTR) mountd, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0))
  238. == ERROR)
  239. {
  240. perror ("Could not spawn mountd task");
  241. return (ERROR);
  242. }
  243.     return (OK);
  244.     }
  245. /******************************************************************************
  246. *
  247. * mountd - mount daemon process
  248. *
  249. * This routine processes incoming mount daemon requests.  It is
  250. * normally used as the entry point of a task by mountdInit() and
  251. * should not be called directly.  It will only return if svc_run()
  252. * returns, which should only happen if select() returns an error.
  253. * This routine is global only so that its name will appear in the
  254. * task display list.
  255. * Most of this routine was generated by rpcgen.
  256. *
  257. * RETURNS: N/A
  258. * NOMANUAL
  259. */
  260. void mountd
  261.     (
  262.     void
  263.     )
  264.     {
  265.     register SVCXPRT *transp;
  266.     
  267.     rpcTaskInit ();
  268.     
  269.     (void) pmap_unset(MOUNTPROG, MOUNTVERS);
  270.     transp = svcudp_create(RPC_ANYSOCK);
  271.     if (transp == NULL)
  272. {
  273. fprintf(stderr, "cannot create udp service.");
  274. exit(1);
  275. }
  276.     
  277.     if (!svc_register(transp, MOUNTPROG, MOUNTVERS, mountdRequestProcess,
  278.       IPPROTO_UDP))
  279. {
  280. fprintf(stderr, "unable to register (MOUNTPROG, MOUNTVERS, udp).");
  281. exit(1);
  282. }
  283.     
  284.     svc_run();
  285.     /* Should never reach this point */
  286.     
  287.     fprintf(stderr, "svc_run returned");
  288.     exit(1);
  289.     }
  290. /******************************************************************************
  291. *
  292. * mountdRequestProcess - process mount requests
  293. * This routine is registered from the mountd process via
  294. * svc_register().  It parses the incoming request, decides which
  295. * mountproc_*_1 routine to call, calls it, and sends the reply back
  296. * to the client.
  297. * NOTE:  Most of this routine was generated by rpcgen.
  298. * RETURNS:  N/A.
  299. * NOMANUAL
  300. */
  301. LOCAL void mountdRequestProcess
  302.     (
  303.     struct svc_req *   rqstp,
  304.     register SVCXPRT * transp
  305.     )
  306.     {
  307.     MOUNTD_ARGUMENT argument;
  308.     char *          result = NULL;
  309.     bool_t          (*xdr_argument)(), (*xdr_result)();
  310.     char *          (*local)();
  311.     nfsstat         authorized; /* return val of user auth routine */
  312.     switch (rqstp->rq_proc)
  313. {
  314. case MOUNTPROC_NULL:
  315.     xdr_argument = xdr_void;
  316.     xdr_result = xdr_void;
  317.     local = (char *(*)()) mountproc_null_1;
  318.     break;
  319. case MOUNTPROC_MNT:
  320.     xdr_argument = xdr_dirpath;
  321.     xdr_result = xdr_fhstatus;
  322.     local = (char *(*)()) mountproc_mnt_1;
  323.     break;
  324. case MOUNTPROC_DUMP:
  325.     xdr_argument = xdr_void;
  326.     xdr_result = xdr_mountlist;
  327.     local = (char *(*)()) mountproc_dump_1;
  328.     break;
  329. case MOUNTPROC_UMNT:
  330.     xdr_argument = xdr_dirpath;
  331.     xdr_result = xdr_void;
  332.     local = (char *(*)()) mountproc_umnt_1;
  333.     break;
  334. case MOUNTPROC_UMNTALL:
  335.     xdr_argument = xdr_void;
  336.     xdr_result = xdr_void;
  337.     local = (char *(*)()) mountproc_umntall_1;
  338.     break;
  339. case MOUNTPROC_EXPORT:
  340.     xdr_argument = xdr_void;
  341.     xdr_result = xdr_exports;
  342.     local = (char *(*)()) mountproc_export_1;
  343.     break;
  344. default:
  345.     svcerr_noproc(transp);
  346.     return;
  347. }
  348.     bzero((char *)&argument, sizeof(argument));
  349.     if (!svc_getargs(transp, xdr_argument, &argument)) 
  350. {
  351. svcerr_decode(transp);
  352. return;
  353. }
  354.     /* Check authorization if hook exists */
  355.     if (mountdAuthHook)
  356. authorized = (*mountdAuthHook) (MOUNTPROG, MOUNTVERS, rqstp->rq_proc,
  357. transp->xp_raddr, argument);
  358.     else
  359. authorized = NFS_OK;
  360.     if (authorized  != NFS_OK)
  361. {
  362. switch (rqstp->rq_proc)
  363.     {
  364.     /* there's no way to return a mount error for null, dump,
  365.      * umnt, umntall, or export.  Can only return an empty list.
  366.      */
  367.     case MOUNTPROC_NULL:
  368.     case MOUNTPROC_DUMP:
  369.     case MOUNTPROC_UMNT:
  370.     case MOUNTPROC_UMNTALL:
  371.     case MOUNTPROC_EXPORT:
  372. result = NULL;
  373. break;
  374.     /* Can return a real error for mnt */
  375.     case MOUNTPROC_MNT:
  376. result =(char *) &authorized;
  377. break;
  378.     }
  379. }
  380.     else
  381. result = (char *) (*local)(&argument, rqstp);
  382.     if (!svc_sendreply(transp, xdr_result, result)) 
  383. {
  384. svcerr_systemerr(transp);
  385. }
  386.     if (!svc_freeargs(transp, xdr_argument, &argument)) 
  387. {
  388. fprintf(stderr, "unable to free arguments");
  389. exit(1);
  390. }
  391.     return;
  392.     }
  393. /******************************************************************************
  394. *
  395. * mountproc_null_1 - do nothing
  396. * This procedure does no work.  It is made available in all RPC
  397. * services to allow server response testing and timing.
  398. * NOMANUAL
  399. */
  400. void * mountproc_null_1
  401.     (
  402.     void
  403.     )
  404.     {
  405.     return (NULL);
  406.     }
  407. /******************************************************************************
  408. *
  409. * mountproc_mnt_1 -
  410. * If the reply "status" is 0, then the reply "directory" contains the
  411. * file handle for the directory "dirname".  This file handle may be
  412. * used in the NFS protocol.  This procedure also adds a new entry to
  413. * the mount list for this client mounting "dirname".
  414. * NOMANUAL
  415. */
  416. fhstatus * mountproc_mnt_1
  417.     (
  418.     dirpath *        path,
  419.     struct svc_req * rqstp /* Client information */
  420.     )
  421.     {
  422.     static fhstatus    fstatus;   /* Status information to return */
  423.     NFS_FILE_HANDLE    fh;   /* file handle of mount point */
  424.     NFS_EXPORT_ENTRY * mntPoint = NULL;  /* export entry for exported FS */
  425.     char *             reducedPath;      /* path after removing extra dots */
  426.     char *             lastChar;  /* loop variable used to reduce path */
  427.     MOUNT_CLIENT *     newClient; /* info about client mounting directory */
  428.     if (strlen ((char *) path) >= nfsMaxPath)
  429. return (NULL);
  430.     if ((reducedPath = (char *) alloca (nfsMaxPath)) == NULL)
  431. return (NULL);
  432.     /* Reduce any pathnames that look like "/foo/bar/.." */
  433.     
  434.     strcpy (reducedPath, *path);
  435.     pathCondense (reducedPath);
  436.     /* Any directory under a mount point is also eligible to be mounted.
  437.      * If a requested directory isn't a mount point, see if any of its
  438.      * parents are.
  439.      */
  440.      
  441.     while (strlen (reducedPath) != 0)
  442. {
  443. mntPoint = nfsExportFindByName (reducedPath);
  444. if (mntPoint == NULL)
  445.     {
  446.     /* Get a pointer to the last char of reducedPath, and move
  447.      * to the left until you get to a slash.  Replace the slash
  448.      * with EOS, then see if that's a mount point.
  449.      */
  450.     
  451.     lastChar = reducedPath + strlen (reducedPath) - 1;
  452.     while ((lastChar > reducedPath) && (*--lastChar != '/'));
  453.     *lastChar = EOS;
  454.     }
  455. else
  456.     /* found the mount point */
  457.     break;
  458. }
  459.     /* If we still didn't find a mount point, it isn't exported */
  460.     
  461.     if (mntPoint == NULL)
  462. {
  463. fstatus.fhs_status = ENOENT;
  464. return (&fstatus);
  465. }
  466.     memset (&fh, 0, sizeof (fh));
  467.     fh.volumeId = mntPoint->volumeId;
  468.     if ((fh.inode = fh.fsId = nameToInode (fh.volumeId, *path)) == ERROR)
  469. {
  470. fstatus.fhs_status = nfsdErrToNfs (errno);
  471. return (&fstatus);
  472. }
  473.     /* See if we have an entry already in the mount list for
  474.      * this client/path pair. If so, then re-use it. Otherwise,
  475.      * allocate a new entry.
  476.      */
  477.     if (mountListFind (rqstp, path) == NULL)
  478.         {
  479.         newClient = KHEAP_ALLOC((sizeof (*newClient) + nfsMaxPath - 1));
  480.         if (NULL == newClient)
  481.        {
  482.     fstatus.fhs_status = ENOMEM;
  483.     return (&fstatus);
  484.     }
  485.         else
  486.     {
  487.     bzero ((char *)newClient, (sizeof (*newClient)));
  488.     }
  489.         /* Set client name and directory fields of new client record */
  490.         svc_reqToHostName (rqstp, newClient->clientName);
  491.         strncpy (newClient->directory, *path, nfsMaxPath - 1);
  492.         /* Add to the client list */
  493.         semTake (clientsSem, WAIT_FOREVER);
  494.         lstAdd (nfsClients, (NODE *) newClient);
  495.         semGive (clientsSem);
  496.         }
  497.     /* Convert outgoing file handle to network byte order */
  498.     nfsdFhHton (&fh);
  499.     
  500.     memcpy (&fstatus.fhstatus_u.fhs_fhandle, &fh, FHSIZE);
  501.     fstatus.fhs_status = 0;
  502.     return (&fstatus);
  503.     }
  504. /******************************************************************************
  505. *
  506. * mountproc_dump_1 -
  507. * Returns the list of remote mounted file systems.  The "mountlist"
  508. * contains one entry for each "hostname" and "directory" pair.
  509. * NOMANUAL
  510. */
  511. mountlist * mountproc_dump_1
  512.     (
  513.     void
  514.     )
  515.     {
  516.     static mountlist         mountList = NULL;
  517.     int                      lstPos = 0;
  518.     MOUNT_CLIENT *            mountEntry;
  519.     MOUNT_CLIENT *            nextEntry;
  520.     char *                   strTbl;
  521.     int                      nClients;
  522.     semTake (clientsSem, WAIT_FOREVER);
  523.     nClients = lstCount (nfsClients);
  524.     /* If there are no clients, free the semaphore and memory, return NULL */
  525.     
  526.     if (nClients == 0)
  527.         {
  528. semGive (clientsSem);
  529. /* if mountList has been allocated, free it */
  530. if (mountList != NULL)
  531.     KHEAP_FREE ((char *)mountList);
  532.         mountList = NULL;
  533. return ((mountlist *) &mountList);
  534. }
  535.     if (mountList == NULL)
  536. {
  537. mountList = KHEAP_ALLOC (((nClients *
  538. (sizeof(mountbody) + nfsMaxPath + MAXHOSTNAMELEN+2))));
  539. if (NULL != mountList)
  540.     {
  541.     bzero ((char *)mountList,((nClients *
  542.                         (sizeof(mountbody) + nfsMaxPath + MAXHOSTNAMELEN+2))));
  543.     }
  544. }
  545.     else
  546. {
  547.         mountList = KHEAP_REALLOC((char *)mountList,  (unsigned)
  548. ((sizeof (mountbody) + nfsMaxPath +
  549.  MAXHOSTNAMELEN + 2) * nClients));
  550. }
  551.     
  552.     if (mountList == NULL)
  553.         return ((mountlist *) &mountList);
  554.     
  555.     strTbl = (char *) &mountList[lstCount(nfsClients)];
  556.     for (mountEntry =  (MOUNT_CLIENT *) lstFirst (nfsClients);
  557.  mountEntry != NULL;
  558.  mountEntry = (MOUNT_CLIENT *) lstNext ((NODE *) mountEntry))
  559. {
  560. nextEntry = (MOUNT_CLIENT *) lstNext ((NODE *) mountEntry);
  561. mountList [lstPos].ml_hostname = strTbl;
  562. strncpy (strTbl, mountEntry->clientName, MAXHOSTNAMELEN);
  563. strTbl [MAXHOSTNAMELEN] = EOS;
  564. strTbl += strlen (strTbl) + 1;
  565. strTbl = (char *) MEM_ROUND_UP (strTbl);
  566. mountList [lstPos].ml_directory = strTbl;
  567. strncpy (strTbl, mountEntry->directory, nfsMaxPath - 1);
  568. strTbl [nfsMaxPath - 1] = EOS;
  569. strTbl += strlen (strTbl) + 1;
  570. strTbl = (char *) MEM_ROUND_UP (strTbl);
  571. if (nextEntry != NULL)
  572.     mountList [lstPos].ml_next = &mountList [lstPos + 1];
  573. else
  574.     mountList [lstPos].ml_next = NULL;
  575. lstPos++;
  576. }
  577.     
  578.     semGive (clientsSem);
  579.     return ((mountlist *) &mountList);
  580.     }
  581. /******************************************************************************
  582. *
  583. * mountproc_umnt_1 -
  584. * Removes the mount list entry for the input "dirpath".
  585. * NOMANUAL
  586. */
  587. void * mountproc_umnt_1
  588.     (
  589.     dirpath *        path,
  590.     struct svc_req * rqstp /* Client information */
  591.     )
  592.     {
  593.     MOUNT_CLIENT *   clientEntry;
  594.     /* See if we have an entry for this client/path pair
  595.      * in the mount list, and if so, remove it.
  596.      */
  597.     if ((clientEntry = mountListFind (rqstp, path)) != NULL)
  598.         {
  599.         semTake (clientsSem, WAIT_FOREVER);
  600.         lstDelete (nfsClients, (NODE *) clientEntry);
  601.         KHEAP_FREE (clientEntry);
  602.         semGive (clientsSem);
  603.         }
  604.     return ((void *) TRUE);
  605.     }
  606. /******************************************************************************
  607. *
  608. * mountproc_umntall_1 -
  609. * Removes all of the mount list entries for this client.
  610. * NOMANUAL
  611. */
  612. void * mountproc_umntall_1
  613.     (
  614.     char *           nothing, /* unused */
  615.     struct svc_req * rqstp /* Client information */
  616.     )
  617.     {
  618.     MOUNT_CLIENT *   clientEntry;
  619.     char             clientName [MAXHOSTNAMELEN + 1];
  620.     MOUNT_CLIENT *   deleteThis;
  621.     BOOL             completePass = FALSE;
  622.     semTake (clientsSem, WAIT_FOREVER);
  623.     while (!completePass)
  624. {
  625. deleteThis = NULL;
  626. for (clientEntry = (MOUNT_CLIENT *) lstFirst (nfsClients);
  627.      clientEntry != NULL;
  628.      clientEntry = (MOUNT_CLIENT *) lstNext ((NODE *) clientEntry))
  629.     {
  630.     svc_reqToHostName (rqstp, clientName);
  631.     if (strncmp(clientName, clientEntry->clientName, MAXHOSTNAMELEN)
  632. == 0)
  633. {
  634. /* Found it */
  635. deleteThis = clientEntry;
  636. break;
  637. }
  638.     }
  639. completePass = (clientEntry == NULL);
  640. if (deleteThis)
  641.     {
  642.     lstDelete (nfsClients, (NODE *) deleteThis);
  643.             KHEAP_FREE (deleteThis); 
  644.     }
  645. }
  646.     semGive (clientsSem);
  647.     return ((void *) TRUE);
  648.     }
  649. /******************************************************************************
  650. *
  651. * mountproc_export_1 -
  652. * Returns a variable number of export list entries.  Each entry
  653. * contains a file system name and a list of groups that are allowed to
  654. * import it.  The file system name is in "filesys", and the group name
  655. * is in the list "groups".
  656. * NOMANUAL
  657. */
  658. exports * mountproc_export_1
  659.     (
  660.     void
  661.     )
  662.     {
  663.     static exportnode *      exportList = NULL;
  664.     int                      lstPos = 0;
  665.     NFS_EXPORT_ENTRY *       exportEntry;
  666.     NFS_EXPORT_ENTRY *       nextEntry;
  667.     static struct groupnode  aGroup;
  668.     char *                   strTbl;
  669.     /* If there are no exported file systems, return NULL 
  670.      * The check for exportList removes any stale exportList that 
  671.      * are present  
  672.      */
  673.     if(mountPoints == NULL || lstCount(mountPoints) == 0) 
  674.       {
  675.       if(exportList != NULL) 
  676.         {
  677. KHEAP_FREE((char *)exportList);
  678. exportList = NULL;
  679.         }
  680.       return (&exportList);
  681.     }
  682.     if (exportList == NULL)
  683. {
  684. exportList = KHEAP_ALLOC((mountdNExports * 
  685. (sizeof (exportnode) + nfsMaxPath)));
  686. if (exportList == NULL)
  687.     {
  688.     return (&exportList);
  689.     }
  690. else
  691.     {
  692.     bzero ((char *)exportList,(mountdNExports *
  693.                         (sizeof (exportnode) + nfsMaxPath)));
  694.     }
  695. }
  696.     strTbl = (char *) &exportList[mountdNExports];
  697.     
  698.     /* Bogus group information */
  699.     aGroup.gr_name = NULL;
  700.     aGroup.gr_next = NULL;
  701.     semTake (mountSem, WAIT_FOREVER);
  702.     for (exportEntry =  (NFS_EXPORT_ENTRY *) lstFirst (mountPoints);
  703.  exportEntry != NULL;
  704.  exportEntry = (NFS_EXPORT_ENTRY *) lstNext ((NODE *) exportEntry))
  705. {
  706. nextEntry = (NFS_EXPORT_ENTRY *) lstNext ((NODE *) exportEntry);
  707. exportList [lstPos].ex_dir = strTbl;
  708. strncpy (strTbl, exportEntry->dirName, nfsMaxPath - 1);
  709. strTbl += strlen (strTbl);
  710. *strTbl++ = EOS;
  711. exportList [lstPos].ex_groups = NULL;
  712. if (nextEntry != NULL)
  713.     exportList [lstPos].ex_next = &exportList [lstPos + 1];
  714. else
  715.     exportList [lstPos].ex_next = NULL;
  716. lstPos++;
  717. }
  718.     
  719.     semGive (mountSem);
  720.     return ((exports *) &exportList);
  721.     }
  722. /******************************************************************************
  723. *
  724. * nfsExport - specify a file system to be NFS exported
  725. *
  726. * This routine makes a file system available for mounting by a client.
  727. * The client should be in the local host table (see hostAdd()),
  728. * although this is not required.
  729. * The <id> parameter can either be set to a specific value, or to 0.
  730. * If it is set to 0, an ID number is assigned sequentially.
  731. * Every time a file system is exported, it must have the same ID
  732. * number, or clients currently mounting the file system will not be
  733. * able to access files.
  734. *
  735. * To display a list of exported file systems, use:
  736. * .CS
  737. *     -> nfsExportShow "localhost"
  738. * .CE
  739. * RETURNS: OK, or ERROR if the file system could not be exported.
  740. *
  741. * SEE ALSO: nfsLib, nfsExportShow(), nfsUnexport()
  742. */
  743. STATUS nfsExport
  744.     (
  745.     char * directory,  /* Directory to export - FS must support NFS */
  746.     int    id,     /* ID number for file system */
  747.     BOOL   readOnly,     /* TRUE if file system is exported read-only */
  748.     int    options  /* Reserved for future use - set to 0 */
  749.     )
  750.     {
  751.     NFS_EXPORT_ENTRY * exportFs; /* The file system to be exported */
  752.     int        exportDirFd; /* File descriptor for the exported dir */
  753.     struct stat statInfo; /* information from fstat() call */
  754.     if (strlen (directory) >= nfsMaxPath)
  755. return (ERROR);
  756.     /* Create the export point */
  757.     
  758.     if ((exportFs = KHEAP_ALLOC (sizeof (*exportFs) + nfsMaxPath)) == NULL)
  759.         return (ERROR);
  760.     if ((exportDirFd = open (directory, O_RDONLY, 0666)) == ERROR)
  761.         {
  762. KHEAP_FREE ((char *)exportFs);
  763.         return (ERROR);
  764. }
  765.     /* Set up the NFS_EXPORT_ENTRY structure */
  766.     
  767.     strncpy (exportFs->dirName, directory, nfsMaxPath - 1);
  768.     exportFs->dirFd = exportDirFd;
  769.     /* Set the ID number for the exported system */
  770.     
  771.     if (id == 0)
  772.         exportFs->volumeId = fsIdNumber++;
  773.     else
  774.         exportFs->volumeId = id;
  775.     exportFs->readOnly = readOnly;
  776.     /* Add it to the list */
  777.     semTake (mountSem, WAIT_FOREVER);
  778.     lstAdd (mountPoints, (NODE *)exportFs);
  779.     semGive (mountSem);
  780.     if (fstat (exportDirFd, &statInfo) != OK)
  781. {
  782. semTake (mountSem, WAIT_FOREVER);
  783. lstDelete (mountPoints, (NODE *)exportFs);
  784. semGive (mountSem);
  785.         KHEAP_FREE ((char *) exportFs);
  786. close (exportDirFd);
  787.         return (ERROR);
  788. }
  789.     else
  790. {
  791.         nfsHashTblSet (exportFs->dirName, exportFs->volumeId, statInfo.st_dev);
  792. }
  793.     if ((exportFs->fsId = nameToInode (exportFs->volumeId, directory)) == ERROR)
  794. {
  795. semTake (mountSem, WAIT_FOREVER);
  796. lstDelete (mountPoints, (NODE *) exportFs);
  797. semGive (mountSem);
  798.         nfsHashTblUnset (exportFs->dirName, exportFs->volumeId);  
  799. KHEAP_FREE ((char *)exportFs);
  800. close (exportDirFd);
  801.         return (ERROR);
  802. }
  803.     return (OK);
  804.     }
  805. /******************************************************************************
  806. *
  807. * nfsUnexport - remove a file system from the list of exported file systems
  808. *
  809. * This routine removes a file system from the list of file systems
  810. * exported from the target.  Any client attempting to mount a file
  811. * system that is not exported will receive an error (NFSERR_ACCESS).
  812. * RETURNS: OK, or ERROR if the file system could not be removed from
  813. * the exports list.
  814. * ERRNO: ENOENT
  815. *
  816. * SEE ALSO: nfsLib, nfsExportShow(), nfsExport()
  817. */
  818. STATUS nfsUnexport
  819.     (
  820.     char * dirName /* Name of the directory to unexport */
  821.     )
  822.     {
  823.     NFS_EXPORT_ENTRY * mntPoint; /* Mount point from mountPoints list */
  824.     /* Make sure the directory name is mentioned */
  825.     if ((dirName == NULL) || (strlen (dirName) >= nfsMaxPath))
  826. return(ERROR);
  827.     
  828.     /* Make sure there's a list of file systems */
  829.     if (mountPoints == NULL)
  830.         return (ERROR);
  831.     /* Find it and take it off the list */
  832.     if ((mntPoint = nfsExportFindByName (dirName)) != NULL)
  833.         {
  834. semTake (mountSem, WAIT_FOREVER);
  835. lstDelete (mountPoints, (NODE *) mntPoint);
  836.         nfsHashTblUnset (mntPoint->dirName, mntPoint->volumeId);
  837. semGive (mountSem);
  838. close(mntPoint->dirFd);
  839.         KHEAP_FREE ((char *)mntPoint);
  840. return (OK);
  841. }
  842.     else
  843. {
  844. /* Didn't find it, set errno and return ERROR */
  845. semGive (mountSem);
  846. errno = ENOENT;
  847. return (ERROR);
  848. }
  849.     }
  850. /******************************************************************************
  851. *
  852. * nfsExportFindByName - find a pointer to an exported file system
  853. *
  854. * Given a directory name, return a pointer to the corresponding
  855. * NFS_EXPORT_ENTRY structure.
  856. * RETURNS:  OK, or NULL if the file system could not be found.
  857. * NOMANUAL 
  858. */
  859. NFS_EXPORT_ENTRY * nfsExportFindByName
  860.     (
  861.     char * dirName /* name of file system to find */
  862.     )
  863.     {
  864.     NFS_EXPORT_ENTRY * mntPoint = NULL; /* mount point from mountPoints list */
  865.     char *             matchName;       /* fs name to find */
  866.     /* Make sure the list exists */
  867.     if (mountPoints == NULL)
  868.         return (NULL);
  869.     
  870.     if ((matchName = (char *) alloca (nfsMaxPath)) == NULL)
  871. return (NULL);
  872.     /* Make sure matchName doesn't have ending slash */
  873.     strcpy (matchName, dirName);
  874.     if (matchName[strlen (matchName) - 1] == '/')
  875.         matchName[strlen (matchName) - 1] = EOS;
  876.     
  877.     /* Search through the list */
  878.     semTake (mountSem, WAIT_FOREVER);
  879.     for (mntPoint = (NFS_EXPORT_ENTRY *) lstFirst (mountPoints);
  880.  mntPoint != NULL;
  881.  mntPoint = (NFS_EXPORT_ENTRY *) lstNext ((NODE *) mntPoint))
  882. {
  883. if (strcmp(mntPoint->dirName, matchName) == 0)
  884.     {
  885.     /* Found it, give the semaphore and return */
  886.     semGive (mountSem);
  887.     return (mntPoint);
  888.     }
  889. }
  890.     /* Didn't find a match, return NULL */
  891.     semGive (mountSem);
  892.     return (NULL);
  893.     }
  894. /******************************************************************************
  895. *
  896. * nfsExportFindById - find a pointer to an exported file system
  897. * Given a directory ID number, return a pointer to the corresponding
  898. * NFS_EXPORT_ENTRY structure.
  899. * RETURNS:  OK, or NULL if the file system could not be found.
  900. * NOMANUAL
  901. */
  902. NFS_EXPORT_ENTRY * nfsExportFindById
  903.     (
  904.     int volumeId /* volume ID number */
  905.     )
  906.     {
  907.     NFS_EXPORT_ENTRY * mntPoint; /* mount point from mountPoints list */
  908.     /* Make sure the list exists */
  909.     if (mountPoints == NULL)
  910.         return (NULL);
  911.     
  912.     /* Search through the list */
  913.     semTake (mountSem, WAIT_FOREVER);
  914.     for (mntPoint = (NFS_EXPORT_ENTRY *) lstFirst (mountPoints);
  915.  mntPoint != NULL;
  916.  mntPoint = (NFS_EXPORT_ENTRY *) lstNext ((NODE *) mntPoint))
  917. {
  918. if (volumeId == mntPoint->volumeId)
  919.     {
  920.     /* Found it, give the semaphore and return */
  921.     semGive (mountSem);
  922.     return (mntPoint);
  923.     }
  924. }
  925.     /* Didn't find a match, return NULL */
  926.     semGive (mountSem);
  927.     return (NULL);
  928.     }
  929. /******************************************************************************
  930. *
  931. * nameToInode - file name to inode number
  932. * Given a file name, return the inode number associated with it.
  933. * RETURNS: the inode number for the file descriptor, or ERROR.
  934. *
  935. * NOMANUAL
  936. */
  937. int nameToInode
  938.     (
  939.     int    mntId,               /* mount id */
  940.     char * fileName /* name of the file */
  941.     )
  942.     {
  943.     int    fd; /* File descriptor */
  944.     int    inode; /* inode of file */
  945.     
  946.     if ((fd = open (fileName, O_RDONLY, 0)) == ERROR)
  947.         return (ERROR);
  948.     else
  949. {
  950. inode = nfsNmLkupIns (mntId, fileName);
  951. }
  952.     close (fd);
  953.     return (inode);
  954.     }
  955. /******************************************************************************
  956. *
  957. * svc_reqToHostName - convert svc_req struct to host name
  958. * Given a pointer to a svc_req structure, fill in a string with the
  959. * host name of the client associated with that svc_req structure.
  960. * The calling routine is responsible for allocating space for the
  961. * name string, which should be NAME_MAX characters long.
  962. *
  963. * RETURNS:  A pointer to the name of the client.
  964. * NOMANUAL
  965. */
  966. LOCAL char * svc_reqToHostName
  967.     (
  968.     struct svc_req * rqstp, /* Client information */
  969.     char *           hostName /* String to fill in with client name */
  970.     )
  971.     {
  972.     /* Convert the callers address to a host name.  If hostGetByAddr()
  973.      * returns ERROR, convert the address to a numeric string
  974.      */
  975.     if (hostGetByAddr (rqstp->rq_xprt->xp_raddr.sin_addr.s_addr, hostName)!= OK)
  976.         inet_ntoa_b (rqstp->rq_xprt->xp_raddr.sin_addr, hostName);
  977.     return (hostName);
  978.     }
  979. /******************************************************************************
  980. *
  981. * mountListFind - find an entry in the NFS mount list
  982. *
  983. * Given a pointer to a svc_req structure and a path name, search
  984. * the client mount list to see if the client already has this
  985. * particular path mounted.
  986. *
  987. * RETURNS:  A pointer to the mount list entry which we found,
  988. *           or NULL if there was no match.
  989. * NOMANUAL
  990. */
  991. LOCAL MOUNT_CLIENT * mountListFind
  992.     (
  993.     struct svc_req * rqstp, /* Client information */
  994.     dirpath *        path /* path to search for */
  995.     )
  996.     {
  997.     MOUNT_CLIENT *   clientEntry;
  998.     char             clientName [MAXHOSTNAMELEN + 1];
  999.     semTake (clientsSem, WAIT_FOREVER);
  1000.     for (clientEntry = (MOUNT_CLIENT *) lstFirst (nfsClients);
  1001.          clientEntry != NULL;
  1002.          clientEntry = (MOUNT_CLIENT *) lstNext ((NODE *) clientEntry))
  1003.         {
  1004.         svc_reqToHostName (rqstp, clientName);
  1005.         if ((strncmp(clientName, clientEntry->clientName, MAXHOSTNAMELEN) == 0)
  1006.             && strncmp (*path, clientEntry->directory, PATH_MAX) == 0)
  1007.             {
  1008.             semGive (clientsSem);
  1009.             return (clientEntry);
  1010.             }
  1011.         }
  1012.     semGive (clientsSem);
  1013.     return(NULL);
  1014.     }