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

MultiPlatform

  1. /* iosLib.c - I/O system library */
  2. /* Copyright 1984-2001 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5. modification history
  6. --------------------
  7. 04n,03oct01,dcb  Fix SPR 20033.  iosFdSet uses malloc without checking return
  8.                  code.
  9. 04m,31aug98,ms   add _func_ioTaskStdSet initialization.
  10. 04l,24aug96,sgv  fix for spr 6802. Modified iosFdNew to check for maxFiles
  11.  after a fd value is chosen.
  12. 04k,23aug96,ms   writing to null device no longer an error (SPR 7076)
  13. 04k,11jan95,rhp  explain "default device" in iosDevFind() man page (SPR#2462)
  14. 04j,17oct94,rhp  removed obsolete reference to pathLib in doc (SPR#3712).
  15. 04i,26jul94,dvs  made iosWrite/iosRead consistant so they both return ERROR 
  16.  if no driver routine - also changed doc (SPR #2019 and 2020).
  17. 04h,14jul94,dvs  made write return 0 if no driver routine (SPR #2020).
  18. 04g,07dec93,elh  added asynchronous I/O support for Posix.
  19. 04f,21jan93,jdi  documentation cleanup for 5.1.
  20. 04e,13nov92,dnw  added include of semLibP.h
  21. 04d,23aug92,jcf  split show routines into iosShow.c. 
  22.  moved typedefs/defines to private/iosLibP.h.
  23.  changed semMInit->semBInit.  changed lst* to dll*.
  24. 04c,18jul92,smb  Changed errno.h to errnoLib.h.
  25. 04b,26may92,rrr  the tree shuffle
  26. 04a,25nov91,rrr  cleanup of some ansi warnings.
  27. 03z,04oct91,rrr  passed through the ansification filter
  28.                   -changed functions to ansi style
  29.   -changed includes to have absolute path from h/
  30.   -changed VOID to void
  31.   -changed copyright notice
  32. 03y,30apr91,jdi  documentation tweaks.
  33. 03x,26apr91,shl  fixed potential race in iosFdFree() (spr 997).
  34. 03w,05apr91,jdi  documentation -- removed header parens and x-ref numbers;
  35.  moved position of iosDrvShow(); doc review by dnw.
  36. 03v,08feb92,jaa  documentation cleanup.
  37. 03u,05oct90,dnw  made iosNextDevGet() be NOMANUAL
  38. 03t,10aug90,kdl  added forward declarations for functions returning void.
  39. 03s,26jun90,jcf  changed iosSemaphore to mutex.
  40. 03r,29may90,dnw  fixed iosDevDelete to free memory allocated for name string.
  41.  tweaked documentation for iosDevAdd & iosDevDelete.
  42. 03q,25may90,dnw  fixed printf format in ios{Dev,Fd}Show to show entire name
  43.    instead of just 1st 20 chars.
  44.  changed iosFdSet to malloc space for filename, unless filename
  45.    is same as device name.  Note that callers should NOT
  46.    malloc the name before calling iosFdSet anymore.
  47.    See doc in iosFdSet.
  48.  made several obscure iosFd... routines be "no manual".
  49. 03p,11may90,yao  added missing modification history (03o) for the last checkin.
  50. 03o,09may90,yao  typecasted malloc to (char *).
  51. 03n,07may90,hjb  added iosFdDevFind routine.
  52. 03m,14mar90,jdi  documentation cleanup.
  53. 03l,14nov88,dnw  changed ioTaskStdGet to take taskId arg.
  54. 03i,08oct88,gae  fixed checking for task specific std. input/output/error fd's.
  55. 03h,15aug88,jcf  lint.
  56. 03g,15jul88,llk  changed iosFdSet.  fd names are now allocated before iosFdSet
  57.    is called.
  58. 03f,30jun88,llk  added iosNextDevGet().
  59.  changed iosDevAdd() so that it will not add devices with
  60.    duplicate names.
  61. 03e,04jun88,llk  replaced ioDefDev with ioDefPath.
  62. 03d,30may88,dnw  changed to v4 names.
  63. 03c,28may88,dnw  made ios{Create,Delete,Open,Close,Read,Write,Ioctl} LOCAL.
  64. 03b,23apr88,jcf  fixed semaphore calls for new semLib.
  65. 03a,30mar88,gae  made drvTable & fdTable definition local.
  66.  made fd's 0, 1, & 2 be standard in/out/err a la UNIX.
  67.  added ios{Creat,Delete,Open,Read,Write,Ioctl,Close}() for use
  68.  by ioLib.c.  Got rid of iosFdGetFree() and added iosFdNew()
  69.  to simplify setting up of new file descriptor.
  70.  iosFdCheck() turned into a macro for speed/jsr overhead.
  71.  iosDevList() shows driver number.
  72.  iosFdList() shows driver number and indicates std. in/out/err.
  73. 02b,20feb88,dnw  fixed missing return value in iosDrvRemove().
  74. 02a,16dec87,jlf  added iosDevDelete (), iosDrvRemove (), and iosDrvList ().
  75.  changed iosDrvInstall to look for an unused entry, instead
  76.     of just adding new drivers at the end.
  77. 01p,05nov87,rdc  fixed documentation for iosDevFind.
  78. 01o,30sep87,gae  made fdTable LOCAL; added iosFdSet() to set values in
  79.    fdTable; now keep file name in table; added iosFdList().
  80. 01n,28apr87,gae  made iosLock() and iosUnlock() LOCAL.
  81. 01m,24mar87,jlf  documentation.
  82. 01l,20dec86,dnw  changed iosDevMatch() to find longest (instead of just first)
  83.    device name that is initial substring of file name.
  84.  changed to not get include files from default directories.
  85. 01k,01dec86,dnw  changed iosDevAdd() to put device name in allocated memory,
  86.    instead of in fixed length array.
  87. 01j,14apr86,rdc  changed memAllocates to mallocs.
  88. 01i,11oct85,dnw  de-linted.
  89. 01h,20jul85,jlf  documentation.
  90. 01g,19sep84,jlf  worked on the comments a little.
  91. 01f,05sep84,jlf  fixed iosDevMatch to work properly.  Added copyright.  Added
  92.  comments.
  93. 01e,04sep84,dnw  added iosDevList.
  94. 01d,10aug84,dnw  changed ioDevFind to include "default device" search
  95.    if device name not explicitly specified.
  96. 01c,07aug84,ecs  added calls to setStatus to iosDevFind, iosDrvInstall,
  97.    iosFdCheck, and iosFdGetFree
  98. 01b,29jun84,ecs  changed iosDevFind to use new version of cmpbuf
  99. 01a,11jun84,dnw  culled from old drvLib and ioLib
  100. */
  101. /*
  102. This library is the driver-level interface to the I/O system.  Its
  103. primary purpose is to route user I/O requests to the proper drivers, using
  104. the proper parameters.  To do this, iosLib keeps tables describing the
  105. available drivers (e.g., names, open files).
  106. The I/O system should be initialized by calling iosInit(), before calling
  107. any other routines in iosLib.  Each driver then installs itself by calling
  108. iosDrvInstall().  The devices serviced by each driver are added to the I/O
  109. system with iosDevAdd().
  110. The I/O system is described more fully in the 
  111. .I "I/O System"
  112. chapter of the
  113. .I "Programmer's Guide."
  114. INCLUDE FILES: iosLib.h
  115. SEE ALSO: intLib, ioLib,
  116. .pG "I/O System"
  117. */
  118. #include "vxWorks.h"
  119. #include "dllLib.h"
  120. #include "stdlib.h"
  121. #include "semLib.h"
  122. #include "ioLib.h"
  123. #include "string.h"
  124. #include "errnoLib.h"
  125. #include "stdio.h"
  126. #include "private/iosLibP.h"
  127. #include "private/semLibP.h"
  128. #include "private/funcBindP.h"
  129. /* globals */
  130. DL_LIST  iosDvList; /* list of I/O device headers */
  131. DRV_ENTRY * drvTable; /* driver entry point table */
  132. FD_ENTRY * fdTable; /* table of fd entries */
  133. int  maxDrivers; /* max installed drivers */
  134. int  maxFiles; /* max open files */
  135. char ioDefPath[MAX_FILENAME_LENGTH]; /* default I/O prefix */
  136. int mutexOptionsIosLib = SEM_Q_FIFO | SEM_DELETE_SAFE;
  137. BOOL iosLibInitialized = FALSE;
  138. VOIDFUNCPTR iosFdNewHookRtn = NULL;
  139. VOIDFUNCPTR iosFdFreeHookRtn = NULL;
  140. /* forward static functions */
  141. static DEV_HDR *iosDevMatch (char *name);
  142. static void  iosLock (void);
  143. static void  iosUnlock (void);
  144. /* locals */
  145. LOCAL SEMAPHORE iosSemaphore; /* semaphore to interlock access to io tables */
  146. LOCAL DEV_HDR nullDevHdr; /* device header for null device */
  147. /******************************************************************************
  148. *
  149. * nullWrite - NULL device write routine
  150. */ 
  151. static STATUS nullWrite
  152.     (
  153.     int    dummy,
  154.     char * pBuf,
  155.     int    nBytes
  156.     )
  157.     {
  158.     return (nBytes);
  159.     }
  160. /*******************************************************************************
  161. *
  162. * iosInit - initialize the I/O system
  163. *
  164. * This routine initializes the I/O system.
  165. * It must be called before any other I/O system routine.
  166. *
  167. * RETURNS: OK, or ERROR if memory is insufficient.
  168. */
  169. STATUS iosInit
  170.     (
  171.     int max_drivers,            /* maximum number of drivers allowed */
  172.     int max_files,              /* max number of files allowed open at once */
  173.     char *nullDevName           /* name of the null device (bit bucket) */
  174.     )
  175.     {
  176.     int i;
  177.     int size;
  178.     maxDrivers = max_drivers;
  179.     maxFiles = max_files;
  180.     ioDefPath [0] = EOS;
  181.     /* allocate file table and make all entries free */
  182.     size = maxFiles * sizeof (FD_ENTRY);
  183.     fdTable = (FD_ENTRY *) malloc ((unsigned) size);
  184.     if (fdTable == NULL)
  185. return (ERROR);
  186.     bzero ((char *)fdTable, size);
  187.     for (i = 0; i < maxFiles; i++)
  188. iosFdFree (STD_FIX(i));
  189.     /* allocate driver table and make all entries null */
  190.     size = maxDrivers * sizeof (DRV_ENTRY);
  191.     drvTable = (DRV_ENTRY *) malloc ((unsigned) size);
  192.     if (drvTable == NULL)
  193. return (ERROR);
  194.     bzero ((char *) drvTable, size);
  195.     for (i = 0; i < maxDrivers; i++)
  196. drvTable [i].de_inuse = FALSE;
  197.     /* initialize the device list and data structure semaphore;
  198.      * add the null device to the system 
  199.      */
  200.     semBInit (&iosSemaphore, SEM_Q_PRIORITY, SEM_FULL);
  201.     dllInit (&iosDvList);
  202.     drvTable [0].de_write = nullWrite;
  203.     iosDevAdd (&nullDevHdr, nullDevName, 0);
  204.     iosLibInitialized = TRUE;
  205.     _func_ioTaskStdSet = (FUNCPTR)ioTaskStdSet;
  206.     return (OK);
  207.     }
  208. /*******************************************************************************
  209. *
  210. * iosDrvInstall - install an I/O driver
  211. *
  212. * This routine should be called once by each I/O driver.  It hooks up the
  213. * various I/O service calls to the driver service routines, assigns
  214. * the driver a number, and adds the driver to the driver table.
  215. *
  216. * RETURNS:
  217. * The driver number of the new driver, or ERROR if there is no room for the
  218. * driver.
  219. */
  220. int iosDrvInstall
  221.     (
  222.     FUNCPTR pCreate,    /* pointer to driver create function */
  223.     FUNCPTR pDelete,    /* pointer to driver delete function */
  224.     FUNCPTR pOpen,      /* pointer to driver open function */
  225.     FUNCPTR pClose,     /* pointer to driver close function */
  226.     FUNCPTR pRead,      /* pointer to driver read function */
  227.     FUNCPTR pWrite,     /* pointer to driver write function */
  228.     FUNCPTR pIoctl      /* pointer to driver ioctl function */
  229.     )
  230.     {
  231.     FAST DRV_ENTRY *pDrvEntry = NULL;
  232.     FAST int drvnum;
  233.     iosLock ();
  234.     /* Find a free driver table entry.  Never assign driver number 0. */
  235.     for (drvnum = 1; drvnum < maxDrivers; drvnum++)
  236. if (! drvTable [drvnum].de_inuse)
  237.     {
  238.     /* We've got a free entry */
  239.     pDrvEntry = &drvTable [drvnum];
  240.     break;
  241.     }
  242.     if (pDrvEntry == NULL)
  243. {
  244. /* we couldn't find a free driver table entry */
  245. errnoSet (S_iosLib_DRIVER_GLUT);
  246. iosUnlock ();
  247. return (ERROR);
  248. }
  249.     pDrvEntry->de_inuse = TRUE;
  250.     pDrvEntry->de_create= pCreate;
  251.     pDrvEntry->de_delete= pDelete;
  252.     pDrvEntry->de_open = pOpen;
  253.     pDrvEntry->de_close = pClose;
  254.     pDrvEntry->de_read = pRead;
  255.     pDrvEntry->de_write = pWrite;
  256.     pDrvEntry->de_ioctl = pIoctl;
  257.     iosUnlock ();
  258.     return (drvnum);
  259.     }
  260. /*******************************************************************************
  261. *
  262. * iosDrvRemove - remove an I/O driver
  263. *
  264. * This routine removes an I/O driver (added by iosDrvInstall()) from 
  265. * the driver table.
  266. *
  267. * RETURNS: OK, or ERROR if the driver has open files.
  268. *
  269. * SEE ALSO: iosDrvInstall()
  270. */
  271. STATUS iosDrvRemove
  272.     (
  273.     int drvnum,       /* no. of driver to remove,             */
  274.       /* returned by iosDrvInstall()          */
  275.     BOOL forceClose   /* if TRUE, force closure of open files */
  276.     )
  277.     {
  278.     DEV_HDR *pDevHdr;
  279.     FAST int fd;
  280.     FAST FD_ENTRY *pFdEntry;
  281.     FAST DRV_ENTRY *pDrvEntry = &drvTable [drvnum];
  282.     FUNCPTR drvClose = pDrvEntry->de_close;
  283.     iosLock ();
  284.     /* See if there are any open fd's for this driver */
  285.     for (fd = 0; fd < maxFiles; fd++)
  286. {
  287. pFdEntry = &fdTable [fd];
  288. if (pFdEntry->inuse && pFdEntry->pDevHdr->drvNum == drvnum)
  289.     {
  290.     if (! forceClose)
  291. {
  292. iosUnlock ();
  293. return (ERROR);
  294. }
  295.     else
  296. {
  297. if (drvClose != NULL)
  298.     (* drvClose) (pFdEntry->value);
  299. iosFdFree (STD_FIX(fd));
  300. }
  301.     }
  302. }
  303.     /* remove any devices for this driver */
  304.     for (pDevHdr = (DEV_HDR *) DLL_FIRST (&iosDvList); pDevHdr != NULL;
  305. pDevHdr = (DEV_HDR *) DLL_NEXT (&pDevHdr->node))
  306. {
  307. if (pDevHdr->drvNum == drvnum)
  308.     {
  309.     free (pDevHdr->name);
  310.     dllRemove (&iosDvList, &pDevHdr->node);
  311.     }
  312. }
  313.     pDrvEntry->de_inuse = FALSE;
  314.     pDrvEntry->de_create= NULL;
  315.     pDrvEntry->de_delete= NULL;
  316.     pDrvEntry->de_open = NULL;
  317.     pDrvEntry->de_close = NULL;
  318.     pDrvEntry->de_read = NULL;
  319.     pDrvEntry->de_write = NULL;
  320.     pDrvEntry->de_ioctl = NULL;
  321.     iosUnlock ();
  322.     return (OK);
  323.     }
  324. /*******************************************************************************
  325. *
  326. * iosDevAdd - add a device to the I/O system
  327. *
  328. * This routine adds a device to the I/O system device list, making the
  329. * device available for subsequent open() and creat() calls.
  330. *
  331. * The parameter <pDevHdr> is a pointer to a device header, DEV_HDR (defined
  332. * in iosLib.h), which is used as the node in the device list.  Usually this
  333. * is the first item in a larger device structure for the specific device
  334. * type.  The parameters <name> and <drvnum> are entered in <pDevHdr>.
  335. *
  336. * RETURNS: OK, or ERROR if there is already a device with the specified name.
  337. */
  338. STATUS iosDevAdd
  339.     (
  340.     DEV_HDR *pDevHdr, /* pointer to device's structure */
  341.     char *name,       /* name of device */
  342.     int drvnum        /* no. of servicing driver, */
  343.       /* returned by iosDrvInstall() */
  344.     )
  345.     {
  346.     DEV_HDR *pDevMatch = iosDevMatch (name);
  347.     /* don't add a device with a name that already exists in the device list.
  348.      * iosDevMatch will return NULL if a device name is a substring of the
  349.      * named argument, so check that the two names really are identical.
  350.      */
  351.     if ((pDevMatch != NULL) && (strcmp (pDevMatch->name, name) == 0))
  352. {
  353. errnoSet (S_iosLib_DUPLICATE_DEVICE_NAME);
  354. return (ERROR);
  355. }
  356.     pDevHdr->name   = (char *) malloc ((unsigned) (strlen (name) + 1));
  357.     pDevHdr->drvNum = drvnum;
  358.     if (pDevHdr->name == NULL)
  359. return (ERROR);
  360.     strcpy (pDevHdr->name, name);
  361.     iosLock ();
  362.     dllAdd (&iosDvList, &pDevHdr->node);
  363.     iosUnlock ();
  364.     return (OK);
  365.     }
  366. /*******************************************************************************
  367. *
  368. * iosDevDelete - delete a device from the I/O system
  369. *
  370. * This routine deletes a device from the I/O system device list, making it
  371. * unavailable to subsequent open() or creat() calls.  No interaction with
  372. * the driver occurs, and any file descriptors open on the device or pending
  373. * operations are unaffected.
  374. *
  375. * If the device was never added to the device list, unpredictable results
  376. * may occur.
  377. *
  378. * RETURNS: N/A
  379. */
  380. void iosDevDelete
  381.     (
  382.     DEV_HDR *pDevHdr            /* pointer to device's structure */
  383.     )
  384.     {
  385.     iosLock ();
  386.     dllRemove (&iosDvList, &pDevHdr->node);
  387.     iosUnlock ();
  388.     free (pDevHdr->name);
  389.     }
  390. /*******************************************************************************
  391. *
  392. * iosDevFind - find an I/O device in the device list
  393. *
  394. * This routine searches the device list for a device whose name matches the
  395. * first portion of <name>.  If a device is found, iosDevFind() sets the
  396. * character pointer pointed to by <pNameTail> to point to the first
  397. * character in <name>, following the portion which matched the device name.
  398. * It then returns a pointer to the device.  If the routine fails, it returns
  399. * a pointer to the default device (that is, the device where the current
  400. * working directory is mounted) and sets <pNameTail> to point to the
  401. * beginning of <name>.  If there is no default device, iosDevFind() 
  402. * returns NULL.
  403. *
  404. * RETURNS:
  405. * A pointer to the device header, or NULL if the device is not found.
  406. *
  407. */
  408. DEV_HDR *iosDevFind
  409.     (
  410.     char *name,                 /* name of the device */
  411.     char **pNameTail            /* where to put ptr to tail of name */
  412.     )
  413.     {
  414.     FAST DEV_HDR *pDevHdr = iosDevMatch (name);
  415.     if (pDevHdr != NULL)
  416. *pNameTail = name + strlen (pDevHdr->name);
  417.     else
  418. {
  419. pDevHdr = iosDevMatch (ioDefPath);
  420. *pNameTail = name;
  421. }
  422.     if (pDevHdr == NULL)
  423. errnoSet (S_iosLib_DEVICE_NOT_FOUND);
  424.     return (pDevHdr);
  425.     }
  426. /**********************************************************************
  427. *
  428. * iosDevMatch - find device whose name matches specified string
  429. *
  430. * RETURNS: Pointer to device header, or NULL if device not found.
  431. */
  432. LOCAL DEV_HDR *iosDevMatch
  433.     (
  434.     char *name
  435.     )
  436.     {
  437.     FAST DEV_HDR *pDevHdr;
  438.     FAST int len;
  439.     DEV_HDR *pBestDevHdr = NULL;
  440.     int maxLen = 0;
  441.     iosLock ();
  442.     for (pDevHdr = (DEV_HDR *) DLL_FIRST (&iosDvList); pDevHdr != NULL;
  443. pDevHdr = (DEV_HDR *) DLL_NEXT (&pDevHdr->node))
  444. {
  445. len = strlen (pDevHdr->name);
  446. if (strncmp (pDevHdr->name, name, len) == 0)
  447.     {
  448.     /* this device name is initial substring of name;
  449.      *   if it is longer than any other such device name so far,
  450.      *   remember it.
  451.      */
  452.     if (len > maxLen)
  453. {
  454. pBestDevHdr = pDevHdr;
  455. maxLen = len;
  456. }
  457.     }
  458. }
  459.     iosUnlock ();
  460.     return (pBestDevHdr);
  461.     }
  462. /*******************************************************************************
  463. *
  464. * iosNextDevGet - get the next device in the device list
  465. *
  466. * This routine gets the next device in the device list.
  467. * If the passed pointer is NULL, it starts at the top of the list.
  468. *
  469. * RETURNS:  Pointer to a device, or NULL if <pDev> is
  470. * the last device in the device list.
  471. *
  472. * NOTE: This routine was public in 4.0.2 but is obsolete.  It is made
  473. * no-manual in 5.0 and should be removed in the next major release.
  474. *
  475. * NOMANUAL
  476. */
  477. DEV_HDR *iosNextDevGet
  478.     (
  479.     DEV_HDR *pDev
  480.     )
  481.     {
  482.     if (pDev == NULL)
  483. return ((DEV_HDR *) DLL_FIRST (&iosDvList));
  484.     else
  485. return ((DEV_HDR *) DLL_NEXT (&pDev->node));
  486.     }
  487. /*******************************************************************************
  488. *
  489. * iosFdValue - validate an open file descriptor and return the driver-specific value
  490. *
  491. * This routine checks to see if a file descriptor is valid and
  492. * returns the driver-specific value.
  493. *
  494. * RETURNS: The driver-specific value, or ERROR if the file descriptor is 
  495. * invalid.
  496. */
  497. int iosFdValue
  498.     (
  499.     FAST int fd         /* file descriptor to check */
  500.     )
  501.     {
  502.     int xfd = STD_MAP (fd);
  503.     if (xfd >= 0 && xfd < maxFiles && fdTable[xfd].inuse)
  504. return (fdTable[xfd].value);
  505.     else
  506. {
  507. errnoSet (S_iosLib_INVALID_FILE_DESCRIPTOR);
  508. return (ERROR);
  509. }
  510.     }
  511. /*******************************************************************************
  512. *
  513. * iosFdDevFind - verify if open file descriptor is valid and return a pointer to DEV_HDR
  514. *
  515. * NOMANUAL
  516. */
  517. DEV_HDR *iosFdDevFind
  518.     (
  519.     FAST int fd
  520.     )
  521.     {
  522.     int xfd = STD_MAP (fd);
  523.     if (xfd >= 0 && xfd < maxFiles && fdTable[xfd].inuse)
  524. return (fdTable[xfd].pDevHdr);
  525.     else
  526. {
  527. errnoSet (S_iosLib_INVALID_FILE_DESCRIPTOR);
  528. return (NULL);
  529. }
  530.     }
  531. /*******************************************************************************
  532. *
  533. * iosFdFree - free an file descriptor entry in the file descriptor table
  534. *
  535. * This routine frees a file descriptor table entry.
  536. *
  537. * NOMANUAL
  538. */
  539. void iosFdFree
  540.     (
  541.     int fd              /* fd to free up */
  542.     )
  543.     {
  544.     FAST FD_ENTRY *pFdEntry;
  545.     FAST int xfd = STD_MAP(fd);
  546.     if ((pFdEntry = FD_CHECK (xfd)) != NULL)
  547. {
  548. if (pFdEntry->name != NULL)
  549.     {
  550.     /* free name unless it is just the device name */
  551.     if (pFdEntry->name != pFdEntry->pDevHdr->name)
  552. free (pFdEntry->name);
  553.     pFdEntry->name = NULL;
  554.     }
  555. if (iosFdFreeHookRtn != NULL)
  556.     (* iosFdFreeHookRtn) (fd);
  557. pFdEntry->inuse = FALSE;
  558. }
  559.     }
  560. /*******************************************************************************
  561. *
  562. * iosFdSet - record file descriptor specifics in file descriptor table
  563. *
  564. * This routine records the passed information about an file descriptor 
  565. * into the file descriptor table.
  566. *
  567. * The file name should NOT have been malloc'd prior to calling this routine.
  568. * The file name is now treated as follows:
  569. *   if no file name is specified (NULL),
  570. * then the name pointer in the file descriptor entry is left NULL.
  571. *   if the file name is the same as the device name,
  572. * then the name pointer in the file descriptor entry is set to point 
  573. *       to the device name
  574. *   otherwise
  575. * space is malloc'd for the file name and it is copied to that space
  576. *
  577. * This routine and iosFdFree ensure that the proper free'ing is done in each
  578. * of the cases.
  579. *
  580. * This name handling eliminates the malloc/free in cases where the file name
  581. * is the device name (i.e. sockets, pipes, serial devices, etc).
  582. *
  583. * NOMANUAL
  584. */
  585. STATUS iosFdSet
  586.     (
  587.     int fd,             /* file descriptor */
  588.     DEV_HDR *pDevHdr,   /* associated driver header */
  589.     char *name,         /* name of file */
  590.     int value           /* arbitrary driver info */
  591.     )
  592.     {
  593.     FAST FD_ENTRY *pFdEntry = &fdTable [STD_UNFIX(fd)];
  594.     STATUS        returnVal = OK;
  595.     int           error = 0;
  596.     /* free name unless it is just the device name */
  597.     if ((pFdEntry->name != NULL) && (pFdEntry->name != pDevHdr->name))
  598. free (pFdEntry->name);
  599.     /* if no name specified, set it NULL;
  600.      * if name is same as device name, make fd name point to device name;
  601.      * otherwise malloc and copy file name
  602.      */
  603.     if (name == NULL)
  604. pFdEntry->name = NULL;
  605.     else if (strcmp (name, pDevHdr->name) == 0)
  606. pFdEntry->name = pDevHdr->name;
  607.     else
  608. {
  609. if ((pFdEntry->name = (char *) malloc ((unsigned) (strlen (name) + 1)))
  610.     == NULL)
  611.     {
  612.     error = 1;
  613.     goto handleError;
  614.     }
  615. strcpy (pFdEntry->name, name);
  616. }
  617.     pFdEntry->pDevHdr = pDevHdr;
  618.     pFdEntry->value   = value;
  619.     return returnVal;
  620.     
  621. handleError:
  622.     if (error > 0)
  623. {
  624. returnVal = ERROR;
  625. }
  626.     
  627.     return returnVal;
  628.     }
  629. /*******************************************************************************
  630. *
  631. * iosFdNew - allocate and initialize a new fd
  632. *
  633. * This routine gets the index of a free entry in the file descriptor table.  
  634. * The entry is marked as reserved and will not be available again until it is
  635. * explicitly freed with iosFdFree().
  636. *
  637. * RETURNS: The file descriptor or ERROR.
  638. *
  639. * NOMANUAL
  640. */
  641. int iosFdNew
  642.     (
  643.     DEV_HDR *pDevHdr,   /* associated driver header */
  644.     char *name,         /* name of file */
  645.     int value           /* arbitrary driver info */
  646.     )
  647.     {
  648.     FAST int      fd;
  649.     FAST FD_ENTRY *pFdEntry = NULL;
  650.     FAST int      error = 0;
  651.     iosLock ();
  652.     for (fd = 0; fd < maxFiles; fd++)
  653. {
  654. if (!fdTable[fd].inuse)
  655.     {
  656.     pFdEntry = &fdTable[fd];
  657.     pFdEntry->inuse  = TRUE; /* reserve this entry */
  658.     pFdEntry->name   = NULL;
  659.     break;
  660.     }
  661. }
  662.     iosUnlock ();
  663.     fd = STD_FIX(fd);
  664.     if (fd >= maxFiles)
  665. {
  666. errnoSet (S_iosLib_TOO_MANY_OPEN_FILES);
  667. error = 1;
  668. goto handleError;
  669. }
  670.     if ((iosFdSet (fd, pDevHdr, name, value)) == ERROR)
  671. {
  672. error = 1;
  673. goto handleError;
  674. }
  675.     if (iosFdNewHookRtn != NULL)
  676. {
  677. (* iosFdNewHookRtn) (fd);
  678. }
  679.     return fd;
  680.     
  681. handleError:
  682.     if (error > 0)
  683. {
  684. if (pFdEntry != NULL)
  685.     {
  686.     pFdEntry->inuse = FALSE;
  687.     pFdEntry->name  = NULL;
  688.     }
  689. fd = (int)ERROR;
  690. }
  691.     
  692.     
  693.     return (fd);
  694.     }
  695. /*******************************************************************************
  696. *
  697. * iosCreat - invoke driver to open file
  698. *
  699. * RETURNS: OK if there is no create routine, or a driver-specific value.
  700. *
  701. * NOMANUAL
  702. */
  703. int iosCreate
  704.     (
  705.     DEV_HDR *pDevHdr,
  706.     char *fileName,
  707.     int mode
  708.     )
  709.     {
  710.     FUNCPTR drvCreate = drvTable [pDevHdr->drvNum].de_create;
  711.     if (drvCreate != NULL)
  712. return ((*drvCreate)(pDevHdr, fileName, mode));
  713.     else
  714. return (OK);
  715.     }
  716. /*******************************************************************************
  717. *
  718. * iosDelete - invoke driver to delete file
  719. *
  720. * RETURNS: OK if there is no delete routine, or a driver-specific value.
  721. *
  722. * NOMANUAL
  723. */
  724. int iosDelete
  725.     (
  726.     DEV_HDR *pDevHdr,
  727.     char *fileName
  728.     )
  729.     {
  730.     FUNCPTR drvDelete = drvTable [pDevHdr->drvNum].de_delete;
  731.     if (drvDelete != NULL)
  732. return ((*drvDelete)(pDevHdr, fileName));
  733.     else
  734. return (OK);
  735.     }
  736. /*******************************************************************************
  737. *
  738. * iosOpen - invoke driver to open file
  739. *
  740. * RETURNS:
  741. * OK if the driver has no open routine, or
  742. * whatever the driver's open routine returns.
  743. *
  744. * NOMANUAL
  745. */
  746. int iosOpen
  747.     (
  748.     DEV_HDR *pDevHdr,
  749.     char *fileName,
  750.     int flags,
  751.     int mode
  752.     )
  753.     {
  754.     FUNCPTR drvOpen = drvTable [pDevHdr->drvNum].de_open;
  755.     if (drvOpen != NULL)
  756. return ((*drvOpen)(pDevHdr, fileName, flags, mode));
  757.     else
  758. return (OK);
  759.     }
  760. /*******************************************************************************
  761. *
  762. * iosClose - invoke driver to close file
  763. *
  764. * RETURNS:
  765. * OK if the driver has no close routine, or
  766. * whatever the driver's close routine returns, or
  767. * ERROR if the file descriptor is invalid.
  768. *
  769. * NOMANUAL
  770. */
  771. STATUS iosClose
  772.     (
  773.     int fd
  774.     )
  775.     {
  776.     STATUS status;
  777.     FUNCPTR drvClose;
  778.     FD_ENTRY *pFdEntry;
  779.     FAST int xfd = STD_MAP(fd);
  780.     if ((pFdEntry = FD_CHECK (xfd)) == NULL)
  781. status = ERROR; /* status set when bad fd */
  782.     else
  783. {
  784. drvClose = drvTable [pFdEntry->pDevHdr->drvNum].de_close;
  785. if (drvClose != NULL)
  786.     status = (*drvClose)(pFdEntry->value);
  787. else
  788.     status = OK;
  789. iosFdFree (STD_FIX(xfd));
  790. }
  791.     return (status);
  792.     }
  793. /*******************************************************************************
  794. *
  795. * iosRead - invoke driver read routine
  796. *
  797. * RETURNS:
  798. * Whatever the driver's read routine returns (number of bytes read), or
  799. * ERROR if the file descriptor is invalid or if the driver has no read 
  800. * routine.  If the driver has no read routine, errno is set to ENOTSUP.
  801. *
  802. * NOMANUAL
  803. */
  804. int iosRead
  805.     (
  806.     int fd,
  807.     char *buffer,
  808.     int maxbytes
  809.     )
  810.     {
  811.     FUNCPTR drvRead;
  812.     FAST FD_ENTRY *pFdEntry;
  813.     FAST int xfd = STD_MAP(fd);
  814.     if ((pFdEntry = FD_CHECK (xfd)) == NULL)
  815. return (ERROR);
  816.     drvRead = drvTable [pFdEntry->pDevHdr->drvNum].de_read;
  817.     if (drvRead == NULL)
  818. {
  819. errno = ENOTSUP;
  820. return (ERROR);
  821. }
  822.     else
  823. return ((* drvRead) (pFdEntry->value, buffer, maxbytes));
  824.     }
  825. /*******************************************************************************
  826. *
  827. * iosWrite - invoke driver write routine
  828. *
  829. * RETURNS:
  830. * Whatever the driver's write routine returns (number of bytes written), or
  831. * ERROR if the file descriptor is invalid or if the driver has no write
  832. * routine. If the driver has no write routine, errno is set to ENOTSUP.
  833. *
  834. * NOMANUAL
  835. */
  836. int iosWrite
  837.     (
  838.     int fd,
  839.     char *buffer,
  840.     int nbytes
  841.     )
  842.     {
  843.     FUNCPTR drvWrite;
  844.     FAST FD_ENTRY *pFdEntry;
  845.     FAST int xfd = STD_MAP(fd);
  846.     if ((pFdEntry = FD_CHECK (xfd)) == NULL)
  847. return (ERROR);
  848.     drvWrite = drvTable [pFdEntry->pDevHdr->drvNum].de_write;
  849.     if (drvWrite == NULL)
  850. {
  851. errno = ENOTSUP;
  852. return (ERROR);
  853. }
  854.     else
  855. return ((* drvWrite) (pFdEntry->value, buffer, nbytes));
  856.     }
  857. /*******************************************************************************
  858. *
  859. * iosIoctl - invoke driver ioctl routine
  860. *
  861. * RETURNS:
  862. * OK if the function is FIOGETNAME (and arg set to name), or
  863. * if driver has no ioctl routine and
  864. * function is FIONREAD then 0 otherwise ERROR, or
  865. * whatever driver ioctl routine returns, or
  866. * ERROR if invalid file descriptor
  867. *
  868. * NOMANUAL
  869. */
  870. int iosIoctl
  871.     (
  872.     int fd,
  873.     int function,
  874.     int arg
  875.     )
  876.     {
  877.     FUNCPTR drvIoctl;
  878.     FAST FD_ENTRY *pFdEntry;
  879.     FAST int xfd = STD_MAP(fd);
  880.     if ((pFdEntry = FD_CHECK (xfd)) == NULL)
  881. return (ERROR);
  882.     if (function == FIOGETNAME)
  883. {
  884. strcpy ((char *) arg, pFdEntry->name);
  885. return (OK);
  886. }
  887.     drvIoctl = drvTable [pFdEntry->pDevHdr->drvNum].de_ioctl;
  888.     if (drvIoctl == NULL)
  889. {
  890. if (function == FIONREAD)
  891.     {
  892.     * (char *) arg = 0;
  893.     return (OK);
  894.     }
  895. else
  896.     {
  897.     errnoSet (S_ioLib_UNKNOWN_REQUEST);
  898.     return (ERROR);
  899.     }
  900. }
  901.     else
  902. {
  903. return ((* drvIoctl) (pFdEntry->value, function, arg));
  904. }
  905.     }
  906. /*******************************************************************************
  907. *
  908. * iosLock - get exclusive use of I/O data structures
  909. *
  910. * This routine takes exclusive use of the I/O system's data structures,
  911. * by taking the semaphore used for that purpose.  If the semaphore
  912. * is already taken, the calling task will suspend until the
  913. * semaphore is available.
  914. */
  915. LOCAL void iosLock (void)
  916.     {
  917.     semTake (&iosSemaphore, WAIT_FOREVER);
  918.     }
  919. /*******************************************************************************
  920. *
  921. * iosUnlock - release exclusive use of I/O data structures
  922. *
  923. * This routine releases the semaphore which had been checked out by iosLock.
  924. * This routine should only be called by a task which currently has the
  925. * semaphore.
  926. */
  927. LOCAL void iosUnlock (void)
  928.     {
  929.     semGive (&iosSemaphore);
  930.     }