passFsLib.c
上传用户:nvosite88
上传日期:2007-01-17
资源大小:4983k
文件大小:24k
源码类别:

VxWorks

开发平台:

C/C++

  1. /* passFsLib.c - pass-through (to UNIX) file system library (VxSim) */
  2. /* Copyright 1992-2001 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5. modification history
  6. --------------------
  7. 01r,06dec01,hbh  Fixed FIONREAD (SPR #22476 & #23615).
  8. 01q,14mar99,jdi  doc: removed refs to config.h and/or configAll.h (SPR 25663).
  9. 01p,17mar98,jmb  Merge my patch from HPSIM, 28oct97, fix bug in FIONREAD ioctl
  10.                  so that number of bytes remaining includes number of bytes
  11.                  in cache. (SPR 9628)
  12. 01o,11jul97,dgp  doc: ad (VxSim) to title line
  13. 01n,09jan97,pr   moved simsolaris macros and prototype in simLib.h 
  14.  moved solarisCvtFlags function in simLib.c
  15. 01n,23nov96,dvs  during merge fixed bug in ARCHCVTFLAGS for sunos,hppa 
  16. 01m,12jul95,ism  added support for simsolaris
  17. 01l,28mar95,kdl  changed to use POSIX date format during fstat().
  18. 01k,31oct94,kdl  made conditional for SIMSPARCSUNOS and SIMHPPA.
  19. 01j,24oct93,gae  documentation tweaks.
  20. 01i,18aug93,gae  modified unix_stat for hp.
  21. 01h,30jul93,gae  more doc touchups.
  22. 01g,05jun93,gae  fixed doc about number of passFs's allowed.
  23. 01f,23jan93,gae  removed u_printf; ANSIfied.
  24. 01e,31aug92,gae  changed mkdir to use 755 per smeg.
  25.  displayed unknown ioctl function code; ignored FIOSETOPTIONS.
  26. 01d,10aug92,gae  set drvnum to usual 0 initially.
  27. 01c,29jul92,gae  cleanup.
  28. 01b,01jun92,gae  minor WRS revision.
  29. 01a,04feb92,smeg written.
  30. */
  31. /*
  32. DESCRIPTION
  33. This module is only used with VxSim simulated versions of VxWorks.
  34. This library provides services for file-oriented device drivers to use
  35. the UNIX file standard.  This module takes care of all the buffering,
  36. directory maintenance, and file system details that are necessary.
  37. In general, the routines in this library are not to be called directly 
  38. by users, but rather by the VxWorks I/O System.
  39. INITIALIZING PASSFSLIB
  40. Before any other routines in passFsLib can be used, the routine passFsInit()
  41. must be called to initialize this library.
  42. The passFsDevInit() routine associates a device name with the passFsLib
  43. functions.  The parameter expected by passFsDevInit() is a pointer to
  44. a name string, to be used to identify the volume/device.  This will be part of
  45. the pathname for I/O operations which operate on the device.  This
  46. name will appear in the I/O system device table, which may be displayed
  47. using the iosDevShow() routine.
  48. As an example:
  49. .CS
  50.     passFsInit (1);
  51.     passFsDevInit ("host:");
  52. .CE
  53. After the passFsDevInit() call has been made, when passFsLib receives a request 
  54. from the I/O system, it calls the UNIX I/O system to service
  55. the request.  Only one volume may be created.
  56. READING DIRECTORY ENTRIES
  57. Directories on a passFs volume may be searched using the opendir(),
  58. readdir(), rewinddir(), and closedir() routines.  These calls allow the
  59. names of files and sub-directories to be determined.
  60. To obtain more detailed information about a specific file, use the fstat()
  61. or stat() function.  Along with standard file information, the structure
  62. used by these routines also returns the file attribute byte from a passFs
  63. directory entry.
  64. FILE DATE AND TIME
  65. UNIX file date and time are passed though to VxWorks.
  66. INCLUDE FILES: passFsLib.h
  67. SEE ALSO
  68. ioLib, iosLib, dirLib, ramDrv
  69. */
  70. #include "vxWorks.h"
  71. #include "ctype.h"
  72. #include "dirent.h"
  73. #include "iosLib.h"
  74. #include "lstLib.h"
  75. #include "semLib.h"
  76. #include "stat.h"
  77. #include "string.h"
  78. #include "stdlib.h"
  79. #include "passFsLib.h"
  80. /* ONLY USED FOR SIMULATOR */
  81. #if (CPU_FAMILY==SIMSPARCSUNOS || CPU_FAMILY==SIMHPPA || CPU_FAMILY==SIMSPARCSOLARIS)
  82. #include "simLib.h"
  83. #include "u_Lib.h"
  84. extern int printErr ();
  85. /* globals */
  86. int passFsUnixFilePerm = 0666;
  87. int passFsUnixDirPerm  = 0775;
  88. /* locals */
  89. LOCAL int passFsDrvNum; /* driver number assigned to passFsLib */
  90. #define CACHE_SIZE 8192 /* size of read-ahead buffer */
  91. /* Volume descriptor */
  92. typedef struct          /* VOL_DESC */
  93.     {
  94.     DEV_HDR passDevHdr; /* tracks the device: only one passFs device */
  95.     char passDevName [MAX_FILENAME_LENGTH];
  96.     } VOL_DESC;
  97. typedef struct
  98.     {
  99.     VOL_DESC *passVdptr;
  100.     UNIX_DIR *passDir;
  101.     char passName[MAX_FILENAME_LENGTH]; /* so we can do a UNIX stat() later */
  102.     int unixFd;
  103.     char *readCache;
  104.     int cacheOffset;
  105.     int cacheBytes;
  106.     } PASS_FILE_DESC;
  107. VOL_DESC *passVolume; /* only 1 permitted */
  108. LOCAL PASS_FILE_DESC *passFsDirCreate ();
  109. LOCAL STATUS      passFsDirMake ();
  110. LOCAL STATUS      passFsIoctl ();
  111. LOCAL PASS_FILE_DESC *passFsOpen ();
  112. LOCAL int      passFsRead ();
  113. LOCAL int      passFsWrite ();
  114. /*******************************************************************************
  115. *
  116. * passFsClose - close a passFs file
  117. *
  118. * This routine closes the specified passFs file.
  119. *
  120. * The remainder of the file I/O buffer beyond the end of file is cleared out,
  121. * the buffer is flushed, and the directory is updated if necessary.
  122. *
  123. * RETURNS: OK, or ERROR if directory couldn't be flushed or entry couldn't 
  124. * be found.
  125. */
  126. LOCAL STATUS passFsClose
  127.     (
  128.     PASS_FILE_DESC *pPassFd /* passthough file descriptor */
  129.     )
  130.     {
  131.     int status = OK;
  132.     if ((int)pPassFd != -1)
  133.      status = u_close (pPassFd->unixFd);
  134.     if (pPassFd->passDir != (UNIX_DIR *)0)
  135.      status = u_closedir (pPassFd->passDir);
  136.     if (pPassFd->readCache != (char *)0)
  137. free (pPassFd->readCache);
  138.     free (pPassFd);
  139.     return (status);
  140.     }
  141. /*******************************************************************************
  142. *
  143. * passFsCreate - create a UNIX file
  144. *
  145. * RETURNS: passthrough file descriptor, or ERROR if error in create.
  146. */
  147. LOCAL PASS_FILE_DESC *passFsCreate
  148.     (
  149.     VOL_DESC *vdptr, /* pointer to volume descriptor */
  150.     char *fullName, /* passFs path/filename string */
  151.     int flags /* file flags (READ/WRITE/UPDATE) */
  152.     )
  153.     {
  154.     PASS_FILE_DESC *pPassFd;
  155.     if ((pPassFd = (PASS_FILE_DESC *) calloc (1, sizeof (PASS_FILE_DESC)))
  156. == (PASS_FILE_DESC *)0)
  157. {
  158. return ((PASS_FILE_DESC *)ERROR);
  159. }
  160.     pPassFd->unixFd = u_open (fullName, L_CREAT | ARCHCVTFLAGS(flags),
  161. passFsUnixFilePerm);
  162.     if (pPassFd->unixFd == -1)
  163. {
  164. free (pPassFd);
  165. return ((PASS_FILE_DESC *) ERROR);
  166. }
  167.     strcpy (pPassFd->passName, fullName);
  168.     pPassFd->passDir     = (UNIX_DIR *)0;
  169.     pPassFd->readCache   = (char *)0;
  170.     pPassFd->cacheBytes  = 0;
  171.     pPassFd->cacheOffset = 0;
  172.     pPassFd->passVdptr   = vdptr;
  173.     return (pPassFd);
  174.     }
  175. /*******************************************************************************
  176. *
  177. * passFsDelete - delete a passFs file
  178. *
  179. * This routine deletes the file <name> from the specified passFs volume.
  180. *
  181. * RETURNS: OK, or ERROR if the file not found
  182. */
  183. LOCAL STATUS passFsDelete
  184.     (
  185.     VOL_DESC *vdptr, /* pointer to volume descriptor */
  186.     char *name /* passFs path/filename */
  187.     )
  188.     {
  189.     /* XXX everything should relative to vdptr */
  190.     if (u_unlink (name) == -1)
  191. {
  192. /* try rmdir if unlink failed */
  193. if (u_rmdir (name) == -1)
  194.     return (ERROR);
  195. }
  196.     return (OK);
  197.     }
  198. /*******************************************************************************
  199. *
  200. * passFsDevInit - associate a device with passFs file system functions
  201. *
  202. * This routine associates the name <devName> with the file system and installs 
  203. * it in the I/O System's device table.  The driver number used when
  204. * the device is added to the table is that which was assigned to the
  205. * passFs library during passFsInit().
  206. *
  207. * RETURNS: A pointer to the volume descriptor, or NULL if there is an error.
  208. */
  209. void *passFsDevInit
  210.     (
  211.     char *devName /* device name */
  212.     )
  213.     {
  214.     /* Add device to system device table */
  215.     if (iosDevAdd (&passVolume->passDevHdr, devName, passFsDrvNum) != OK)
  216. {
  217. return (NULL); /* can't add device */
  218. }
  219.     strcpy (passVolume->passDevName, devName);
  220.     return ((void*)passVolume);
  221.     }
  222. /*******************************************************************************
  223. *
  224. * passFsDirCreate - create a passFs directory
  225. *
  226. * This routine creates a new sub-directory on a passFs volume and
  227. * returns a open file descriptor for it.  It calls passFsDirMake to
  228. * actually create the directory; the remainder of this routine simply
  229. * sets up the file descriptor.
  230. *
  231. * RETURNS: Pointer to passFs file descriptor (PASS_FILE_DESC),
  232. * or ERROR if error.
  233. */
  234. LOCAL PASS_FILE_DESC *passFsDirCreate
  235.     (
  236.     VOL_DESC *vdptr, /* pointer to volume descriptor */
  237.     char *name          /* directory name */
  238.     )
  239.     {
  240.     PASS_FILE_DESC *pPassFd;
  241.     if (passFsDirMake (vdptr, name, TRUE) == ERROR)
  242. return ((PASS_FILE_DESC *)ERROR);
  243.     if ((pPassFd = (PASS_FILE_DESC *) calloc (1, sizeof (PASS_FILE_DESC)))
  244. == (PASS_FILE_DESC *)0)
  245. {
  246. return ((PASS_FILE_DESC *)ERROR);
  247. }
  248.     strcpy (pPassFd->passName, name);
  249.     pPassFd->unixFd      = -1;
  250.     pPassFd->passDir     = (UNIX_DIR *)u_opendir (name);
  251.     pPassFd->readCache   = (char *)0;
  252.     pPassFd->cacheBytes  = 0;
  253.     pPassFd->cacheOffset = 0;
  254.     pPassFd->passVdptr   = vdptr;
  255.     if (pPassFd->passDir == (UNIX_DIR *)0)
  256. {
  257. free (pPassFd);
  258. return ((PASS_FILE_DESC *)ERROR);
  259. }
  260.     return (pPassFd);
  261.     }
  262. /*******************************************************************************
  263. *
  264. * passFsDirMake - make a passFs directory
  265. *
  266. * This routine creates ("makes") a new passFs directory. 
  267. *
  268. * Since this routine may be called as a result of either an open() call
  269. * or an ioctl() call, the level of filename expansion will vary.  A
  270. * boolean flag set by the calling routine (passFsOpen or passFsIoctl) indicates
  271. * whether the name has already been expanded (and the device name stripped).
  272. *
  273. * RETURNS: status indicating success
  274. */
  275. LOCAL STATUS passFsDirMake
  276.     (
  277.     VOL_DESC *vdptr, /* pointer to volume descriptor */
  278.     char *name, /* directory name */
  279.     BOOL nameExpanded /* TRUE if name was already expanded */
  280.     )
  281.     {
  282.     DEV_HDR *pCurDev; /* ptr to current dev hdr (ignored) */
  283.     char fullName [MAX_FILENAME_LENGTH];
  284.     /* Get full expanded dir name (no device name) unless already done */
  285.     if (nameExpanded == FALSE)
  286. {
  287.      if (ioFullFileNameGet (name, &pCurDev, fullName) != OK)
  288.     return (ERROR); /* cannot expand filename */
  289. }
  290.     else
  291. {
  292. (void) strcpy (fullName, name);
  293. }
  294.     if (u_mkdir (fullName, passFsUnixDirPerm) == -1)
  295. return (ERROR);
  296.     return (OK);
  297.     }
  298. /*******************************************************************************
  299. *
  300. * passFsDirRead - read directory and return next filename
  301. *
  302. * This routine is called via an ioctl() call with the FIOREADDIR function
  303. * code.  The "dirent" field in the passed directory descriptor (DIR) is
  304. * filled with the null-terminated name of the next file in the directory.
  305. *
  306. * RETURNS: OK, or ERROR.
  307. */
  308. LOCAL STATUS passFsDirRead
  309.     (
  310.     PASS_FILE_DESC  *pPassFd, /* ptr to passFs file descriptor */
  311.     DIR   *pDir /* ptr to directory descriptor */
  312.     )
  313.     {
  314.     struct unix_dirent *dirent;
  315.     if (pPassFd->passDir == (UNIX_DIR *)0)
  316.      pPassFd->passDir = (UNIX_DIR *)u_opendir (pPassFd->passName);
  317.     if (pPassFd->passDir == (UNIX_DIR *)0)
  318. return (ERROR);
  319.     dirent = (struct unix_dirent *) u_readdir (pPassFd->passDir);
  320.     if (dirent == (struct unix_dirent *)0)
  321. return (ERROR);
  322.     strcpy (pDir->dd_dirent.d_name, dirent->d_name);
  323.     return (OK);
  324.     }
  325. /*******************************************************************************
  326. *
  327. * passFsFileStatGet - get file status (directory entry data)
  328. *
  329. * This routine is called via an ioctl() call, using the FIOFSTATGET
  330. * function code.  The passed stat structure is filled, using data
  331. * obtained from the directory entry which describes the file.
  332. *
  333. * RETURNS: ERROR or OK
  334. */
  335. LOCAL STATUS passFsFileStatGet
  336.     (
  337.     PASS_FILE_DESC *pPassFd, /* pointer to file descriptor */
  338.     struct stat *pStat /* structure to fill with data */
  339.     )
  340.     {
  341.     struct unix_stat unixbuf;
  342.     if (u_stat (pPassFd->passName, (char*)&unixbuf) == -1)
  343. return (ERROR);
  344.     bzero ((char *) pStat, sizeof (struct stat)); /* zero out stat struct */
  345.     /* Fill stat structure */
  346.     pStat->st_dev     = (ULONG) passVolume;
  347. /* device ID = DEV_HDR addr */
  348.     pStat->st_ino     = 0; /* no file serial number */
  349.     pStat->st_nlink   = 1; /* always only one link */
  350.     pStat->st_uid     = 0; /* no user ID */
  351.     pStat->st_gid     = 0; /* no group ID */
  352.     pStat->st_rdev    = 0; /* no special device ID */
  353.     pStat->st_size    = unixbuf.st_size; /* file size, in bytes */
  354.     pStat->st_atime   = 0; /* no last-access time */
  355.     pStat->st_mtime   = 0; /* no last-modified time */
  356.     pStat->st_ctime   = 0; /* no last-change time */
  357.     pStat->st_attrib  = 0; /* file attribute byte */
  358.     
  359.     pStat->st_mtime = unixbuf.st_mtime; /* file modified time */
  360.     /* Set file type in mode field, mark whole volume (raw mode) as directory */
  361.     pStat->st_mode = 0; /* clear field */
  362.     if (unixbuf.st_mode & 0x4000) /* if directory */
  363. {
  364. pStat->st_mode |= S_IFDIR; /*  set bits in mode field */
  365. }
  366.     else if (unixbuf.st_mode & 0x8000) /* if reg file */
  367. {
  368. pStat->st_mode |= S_IFREG; /*  it is a regular file */
  369. }
  370.     pStat->st_mode |= unixbuf.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
  371.     return (OK);
  372.     }
  373. /*******************************************************************************
  374. *
  375. * passFsInit - prepare to use the passFs library
  376. *
  377. * This routine initializes the passFs library.  It must be called exactly once,
  378. * before any other routines in the library.  The argument specifies the number
  379. * of passFs devices that may be open at once.  This routine installs
  380. * passFsLib as a driver in the I/O system driver table, allocates and sets 
  381. * up the necessary memory structures, and initializes semaphores.
  382. *
  383. * Normally this routine is called from the root task, usrRoot(),
  384. * in usrConfig().  This initialization is enabled when the
  385. * configuration macro INCLUDE_PASSFS is defined.
  386. *
  387. * NOTE
  388. * Maximum number of pass-through file systems is 1.
  389. *
  390. * RETURNS: OK, or ERROR.
  391. */
  392. STATUS passFsInit
  393.     (
  394.     int nPassfs /* number of pass-through file systems */
  395.     )
  396.     {
  397.     if (passFsDrvNum != 0)
  398. return (ERROR); /* can't call more than once */
  399.     /* Install passFsLib routines in I/O system driver table */
  400.     passFsDrvNum = iosDrvInstall ((FUNCPTR) passFsCreate, passFsDelete, 
  401.          (FUNCPTR) passFsOpen, passFsClose, 
  402.          passFsRead, passFsWrite, passFsIoctl);
  403.     if (passFsDrvNum == ERROR)
  404. return (ERROR); /* can't install as driver */
  405.     if (nPassfs < 0 || nPassfs > 1)
  406. return (ERROR); /* can't install as driver */
  407.     if ((passVolume = calloc (nPassfs, sizeof (VOL_DESC))) == NULL)
  408. return (ERROR);
  409.     return (OK);
  410.     }
  411. /*******************************************************************************
  412. *
  413. * passFsIoctl - do device specific control function
  414. *
  415. * This routine performs the following ioctl() functions:
  416. *
  417. * .CS
  418. *    FIODISKINIT:   Initialize the disk volume.  This routine does not
  419. *                   format the disk, that must be done by the driver.
  420. *    FIORENAME:     Rename the file to the string pointed to by arg.
  421. *    FIOSEEK:       Sets the file's current byte position to
  422. *                   the position specified by arg.
  423. *    FIOWHERE:      Returns the current byte position in the file.
  424. *    FIOFLUSH:      Flush file output buffer.
  425. *                   Guarantees that any output that has been requested
  426. *                   is actually written to the device.
  427. *    FIONREAD:      Return in arg the number of unread bytes.
  428. *    FIODISKCHANGE: Indicate media change.  See passFsReadyChange().
  429. *    FIOUNMOUNT:    Unmount disk volume.  See passFsVolUnmount().
  430. *    FIONFREE:     Return amount of free space on volume.
  431. *    FIOMKDIR:     Create a new directory.
  432. *    FIORMDIR:     Remove a directory.
  433. *    FIOLABELGET:   Get volume label (located in root directory).
  434. *    FIOLABELSET:   Set volume label.
  435. *    FIOATTRIBSET:  Set file attribute.
  436. *    FIOCONTIG:     Allocate contiguous disk space for file or directory.
  437. *    FIOSYNC:     Write all modified files and data structures to device.
  438. *    FIOREADDIR:    Read next directory entry, uses DIR directory descriptor.
  439. *    FIOFSTATGET:   Get file status info (directory enty data).
  440. * .CE
  441. *
  442. * Any other ioctl function codes are passed to the block device driver
  443. * for handling.
  444. *
  445. * If an ioctl fails, the task's status (see errnoGet()) indicates
  446. * the nature of the error.
  447. *
  448. * RETURNS: OK, or ERROR if function failed or driver returned error, or
  449. *   current byte pointer for FIOWHERE.
  450. */
  451. LOCAL STATUS passFsIoctl
  452.     (
  453.     PASS_FILE_DESC *pPassFd, /* file descriptor of file to control */
  454.     int function, /* function code */
  455.     int arg /* some argument */
  456.     )
  457.     {
  458.     int retValue = OK;
  459.     int whereCur; /* current byte position in file, could include cache */
  460.     int where; /* exact current byte position in file */
  461.     int end;
  462.     
  463.     switch (function)
  464. {
  465. case FIODISKINIT:
  466.     break;
  467. case FIORENAME:
  468.     if (u_rename (pPassFd->passName, (char *)arg) == -1)
  469. retValue = ERROR;
  470.     break;
  471. case FIOSEEK:
  472.     /* invalidate any read cache */
  473.     pPassFd->cacheBytes = 0;
  474.          pPassFd->cacheOffset = 0;
  475.     /* do a lseek with offset arg0 from beginning of file */
  476.     if (u_lseek (pPassFd->unixFd, (int)arg, 0) == -1)
  477. retValue = ERROR;
  478.     break;
  479. case FIOWHERE:
  480.     /* do a lseek with offset 0 from current to get current offset */
  481.     retValue = u_lseek (pPassFd->unixFd, 0, 1/*SEEK_CUR*/);
  482.     /* Adjust since we cache ahead, so LSEEK returns too far */
  483.     if (retValue > 0 && pPassFd->cacheBytes != 0)
  484. retValue -= (pPassFd->cacheBytes - pPassFd->cacheOffset);
  485.     break;
  486. case FIOSYNC:
  487. case FIOFLUSH:
  488.     break;
  489. case FIONREAD:
  490.     /* 
  491.      * compute the number of bytes between the current location and
  492.      * the end of this file.
  493.      * We uses this method rather than a call to :
  494.      * u_ioctl (pPassFd->unixFd, U_FIONREAD, 0);
  495.      * because FIONREAD is not officially supported on Solaris and it
  496.      * does not work on Solaris 2.5. (SPR #22476 & 23615).
  497.      */
  498.     
  499.     whereCur = u_lseek (pPassFd->unixFd, 0, 1/*SEEK_CUR*/);
  500.     if (whereCur == ERROR)
  501.      retValue = ERROR;
  502.     else
  503.      {
  504. /* Adjust since we cache ahead, so LSEEK returns too far */
  505. if (pPassFd->cacheBytes != 0)
  506.     where = whereCur - 
  507.      (pPassFd->cacheBytes - pPassFd->cacheOffset);
  508. else
  509.    where = whereCur;
  510.      end = u_lseek (pPassFd->unixFd, 0, 2/*SEEK_END*/);
  511. if (end == ERROR)
  512.     retValue = ERROR;
  513. else
  514.     {
  515.     /* go back to the current location */
  516.     if (u_lseek (pPassFd->unixFd, whereCur, 0/*SEEK_SET*/) 
  517.      == ERROR)
  518. retValue = ERROR;
  519.       else
  520.              *((int *) arg) = end - where;
  521.     }
  522.      }
  523.     break;
  524. case FIODISKCHANGE:
  525.     break;
  526. case FIOUNMOUNT:
  527.     break;
  528. case FIONFREE:
  529.     /* this is hard to do on a UNIX file system - lie */
  530.     *((int *) arg) = 0x1000000;
  531.     break;
  532. case FIOMKDIR:
  533.     if (passFsDirMake (pPassFd->passVdptr, (char *) arg, FALSE) 
  534.      == ERROR)
  535. retValue = ERROR;
  536.     break;
  537. case FIORMDIR:
  538.     if (u_rmdir (pPassFd->passName) == -1)
  539. retValue = ERROR;
  540.     break;
  541. case FIOLABELGET:
  542.     strcpy ((char *)arg, passVolume->passDevName);
  543.     break;
  544. case FIOLABELSET:
  545.     break;
  546. case FIOATTRIBSET:
  547.     break;
  548. case FIOCONTIG:
  549.     break;
  550. case FIOREADDIR:
  551.     retValue = passFsDirRead (pPassFd, (DIR *) arg);
  552.     break;
  553. case FIOFSTATGET:
  554.     retValue = passFsFileStatGet (pPassFd, (struct stat *) arg);
  555.     break;
  556. case FIOSETOPTIONS:
  557.     /* XXX usually trying to set OPT_TERMINAL -- just ignore */
  558.     break;
  559. default:
  560.     printErr ("passFsLib: unknown ioctl = %#xn", function);
  561.     retValue = ERROR;
  562.     break;
  563. }
  564.     return (retValue);
  565.     }
  566. /*******************************************************************************
  567. *
  568. * passFsOpen - open a file on a passFs volume
  569. *
  570. * This routine opens the file <name> with the specified mode 
  571. * (READ/WRITE/UPDATE/CREATE/TRUNC).  The directory structure is 
  572. * searched, and if the file is found a passFs file descriptor 
  573. * is initialized for it.
  574. *
  575. * RETURNS: A pointer to a passFs file descriptor, or ERROR 
  576. *   if the volume is not available 
  577. *   or there are no available passFs file descriptors 
  578. *   or there is no such file.
  579. */
  580. LOCAL PASS_FILE_DESC *passFsOpen
  581.     (
  582.     VOL_DESC *vdptr, /* pointer to volume descriptor */
  583.     char *name, /* passFs full path/filename */
  584.     int flags, /* file open flags */
  585.     int mode /* file open permissions (mode) */
  586.     )
  587.     {
  588.     PASS_FILE_DESC *pPassFd; /* file descriptor pointer */
  589.     /* Check if creating dir */
  590.     if ((flags & O_CREAT)  &&  (mode & FSTAT_DIR))
  591.         {
  592. return (passFsDirCreate (vdptr, name));
  593. }
  594.     /* Get a free file descriptor */
  595.     if ((pPassFd = (PASS_FILE_DESC *) calloc (1, sizeof (PASS_FILE_DESC)))
  596. == NULL)
  597. {
  598. return ((PASS_FILE_DESC *) ERROR);
  599. }
  600.     if ((pPassFd->unixFd = u_open (name, ARCHCVTFLAGS(flags), mode)) == -1)
  601. {
  602. free (pPassFd);
  603. return ((PASS_FILE_DESC *) ERROR);
  604. }
  605.     strcpy (pPassFd->passName, name);
  606.     pPassFd->passDir     = (UNIX_DIR *)0;
  607.     pPassFd->readCache   = (char *)0;
  608.     pPassFd->cacheBytes  = 0;
  609.     pPassFd->cacheOffset = 0;
  610.     pPassFd->passVdptr   = vdptr;
  611.     return (pPassFd);
  612.     }
  613. /*******************************************************************************
  614. *
  615. * passFsRead - read from a passFs file
  616. *
  617. * This routine reads from the file specified by the file descriptor
  618. * (returned by passFsOpen()) into the specified buffer.
  619. * <maxbytes> bytes will be read, if there is that much data in the file
  620. * and the file I/O buffer is large enough.
  621. *
  622. * RETURNS: Number of bytes actually read, or 0 if end of file, or
  623. *    ERROR if <maxbytes> is <= 0 or unable to get next cluster.
  624. */
  625. LOCAL int passFsRead
  626.     (
  627.     PASS_FILE_DESC *pPassFd, /* file descriptor pointer */
  628.     char *pBuf, /* addr of input buffer */
  629.     int maxBytes /* maximum bytes to read into buffer */
  630.     )
  631.     {
  632.     int ret;
  633.     int bytesRead = 0;
  634.     int readableCacheBytes;
  635.     char *cachePtr;
  636.     /* attempt to service the read from cache first */
  637.     if (pPassFd->cacheBytes)
  638. {
  639.         readableCacheBytes = pPassFd->cacheBytes - pPassFd->cacheOffset;
  640. cachePtr = pPassFd->readCache + pPassFd->cacheOffset;
  641. /* if we have more cached data than asked for */
  642. if (readableCacheBytes > maxBytes) {
  643.    readableCacheBytes = maxBytes;
  644.    pPassFd->cacheOffset += readableCacheBytes;
  645. } else {
  646.    /* invalidate cache since its all going to be read */
  647.    pPassFd->cacheBytes = 0;
  648.    pPassFd->cacheOffset = 0;
  649. }
  650. bcopy (cachePtr, pBuf, readableCacheBytes);
  651. /* if we are done, bail now */
  652. if (readableCacheBytes == maxBytes)
  653. return (maxBytes);
  654. maxBytes -= readableCacheBytes;
  655. bytesRead += readableCacheBytes;
  656. pBuf += readableCacheBytes;
  657. }
  658.     /* initialize read cache if first read */
  659.     if (pPassFd->readCache == (char *)0)
  660. {
  661. if ((pPassFd->readCache = (char*)calloc (1, CACHE_SIZE)) == (char *)0)
  662.     return (ERROR);
  663. }
  664.     /* ok, here we know the cache is allocated and invalidated */
  665.     /* caching can't help if they want a huge chunk */
  666.     if (maxBytes >= CACHE_SIZE)
  667. {
  668.      if ((ret = u_read (pPassFd->unixFd, pBuf, maxBytes)) == -1)
  669.     return (bytesRead ? bytesRead : ERROR);
  670. bytesRead += ret;
  671. }
  672.     else
  673. {
  674. ret = u_read (pPassFd->unixFd,pPassFd->readCache, CACHE_SIZE);
  675.         if ( ret == -1)
  676.     return (bytesRead ? bytesRead : ERROR);
  677. pPassFd->cacheBytes = ret;
  678. /* If there wasn't as much as asked for */
  679. if (ret < maxBytes)
  680.     maxBytes = ret;
  681. bcopy (pPassFd->readCache, pBuf, maxBytes);
  682. bytesRead += maxBytes;
  683. pPassFd->cacheOffset = maxBytes;
  684. }
  685.     return (bytesRead);
  686.     }
  687. /*******************************************************************************
  688. *
  689. * passFsWrite - write to a passFs file
  690. *
  691. * This routine writes to the file specified by the file descriptor
  692. * (returned by passFsOpen()) from the specified buffer. 
  693. *
  694. * RETURNS: Number of bytes written (error if != nBytes), or ERROR if 
  695. *    nBytes < 0, or no more space for the file, or can't write cluster.
  696. */
  697. LOCAL int passFsWrite 
  698.     (
  699.     PASS_FILE_DESC *pPassFd, /* file descriptor pointer */
  700.     char *pBuf, /* data to be written */
  701.     int maxBytes /* number of bytes to write */
  702.     )
  703.     {
  704.     int nBytes;
  705.     /* invalidate read cache */
  706.     pPassFd->cacheBytes = 0;
  707.     pPassFd->cacheOffset = 0;
  708.     if ((nBytes = u_write (pPassFd->unixFd, pBuf, maxBytes)) == -1)
  709. return (ERROR);
  710.     return (nBytes);
  711.     }
  712. #endif /* (CPU_FAMILY==SIMSPARCSUNOS || CPU_FAMILY==SIMHPPA || CPU_FAMILY==SIMSPARCSOLARIS) */