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

VxWorks

开发平台:

C/C++

  1. /* netDrv.c - network remote file I/O driver */
  2. /* Copyright 1984 - 2002 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5. modification history
  6. --------------------
  7. 05j,10jun02,elr  Correct unresolved reference to netDrvFileDoesNotExist()
  8. 05i,06jun02,elr  Documentation corrections (SPRs 78010, 78020)
  9. 05h,07may02,kbw  man page edits
  10. 05g,31mar02,jkf  SPR#74251, increase path length
  11. 05f,14mar02,elr  added more debugging facilities via netDrvDebugLevelSet()
  12.                  split if statements for more precise debugging
  13.                  fixed compilation warnings concerning checking of print 
  14.                   specifiers
  15.                  fixed netFileExists with new configlette for flexibility
  16.                  fixed netOpen so that O_CREAT now works (SPR 8283)
  17.                  Made all error messages optional (SPR 71496)
  18. 05e,05nov01,vvv  fixed compilation warnings
  19. 05d,15oct01,rae  merge from truestack ver 05k, base 05b (compile warnings, etc.)
  20. 05c,21jun00,rsh  upgrade to dosFs 2.0
  21. 05c,28seo99,jkf  fixed SPR#28927, netLsByName() causes exception.
  22. 05b,14mar99,jdi  doc: removed refs to config.h and/or configAll.h (SPR 25663).
  23. 05a,12mar99,p_m  Fixed SPR 8295 by adding documentation on FIOFSTATGET.
  24. 04z,24mar95,jag  netLs ftpXfer call was change to send just "NLST" when the
  25.  remote directory is "." (SPR #4160)
  26. 04x,18jan95,rhp  doc: explain cannot always distinguish directories over netDrv
  27. 04w,11aug94,dzb  initialize variables.
  28. 04v,22apr93,caf  ansification: added cast to netIoctl().
  29. 04u,30sep93,jmm  netLsByName now frees the NET_FD it uses
  30. 04t,30aug93,jag  Changed netCreate to delete the end slash from a directory
  31.  name (SPR #2492)
  32. 04s,11aug93,jmm  Changed ioctl.h and socket.h to sys/ioctl.h and sys/socket.h
  33. 04r,23jul93,jmm  added netLsByName() (spr 2305)
  34. 04q,08feb93,jmm  added doc for FIOFSTATGET ioctl call
  35. 04p,08feb93,jmm  added support for FIOFSTATGET ioctl call (needed for windX)
  36.                  SPR #1856
  37. 04o,01feb93,jdi  documentation cleanup for 5.1; added third param to ioctl()
  38.  examples.
  39. 04n,13nov92,dnw  added include of semLibP.h
  40. 04m,21oct92,jdi  removed mangen SECTION designation.
  41. 04l,02oct92,srh  added ioctl(FIOGETFL) to return file's open mode
  42. 04k,19jul92,smb  added include fcntl.h.
  43. 04j,18jul92,smb  Changed errno.h to errnoLib.h.
  44. 04i,26may92,rrr  the tree shuffle
  45. 04h,08may92,jmm  Fixed ansi prototype warnings
  46. 04g,04oct91,rrr  passed through the ansification filter
  47.                   -changed functions to ansi style
  48.   -changed includes to have absolute path from h/
  49.   -changed READ, WRITE and UPDATE to O_RDONLY O_WRONLY and ...
  50.   -changed VOID to void
  51.   -changed copyright notice
  52. 04f,05apr91,jdi  documentation -- removed header parens and x-ref numbers;
  53.  doc review by dnw.
  54. 04e,20feb91,jaa  documentation cleanup.
  55. 04d,01oct90,jcf  changed network fd semaphore to not be inversion safe.
  56. 04c,18sep90,kdl  removed forward declaration of netWhere().
  57. 04b,30jul90,dnw  changed pathLastName() to pathLastNamePtr().
  58.  added forward declaration of void routines.
  59. 04a,26jun90,jcf  changed network fd semaphore to mutex.
  60.  removed super semaphores.
  61. 03z,20jun90,jcf  changed binary semaphore interface.
  62. 03y,11may90,yao  added missing modification history (03x) for the last checkin.
  63. 03x,09may90,yao  typecasted malloc to (char *).
  64. 03w,01may90,llk  changed call to pathCat().  Now, pathCat() checks if a name
  65.    is too long, and returns ERROR if it is.  03v,17apr90,jcf  changed semaphores to binary for efficiency.  03u,25aug89,dab  fixed coding convention violations.  03t,23aug89,dab  lint.
  66. 03s,11jul89,dab  made netOpen() check for O_CREAT flag and create a file that
  67.  doesn't already exist.  made netLs() check for ftp protocol.
  68.  added netFileExists().  added netDelete ().  closed all data
  69.  sockets before calling ftpReplyGet(). QUIT ftp command now
  70.  sent before closing a ftp control socket. made netOpen()
  71.  check for O_TRUNC flag.
  72. 03r,06jul89,llk  included pathLib.h.
  73.  changed call to pathLastName().
  74. 03q,04apr89,gae  allowed open() to succeed for NFS directories so that ls()
  75.    +dab  would work correctly.  Added NET_LS_STRING variable.
  76. 03p,07jul88,jcf  lint.
  77. 03o,22jun88,dnw  name tweaks.
  78.  coalesced 3 malloc's into 1 in netCreate().
  79. 03n,16jun88,llk  added netLs.
  80. 03m,04jun88,llk  changed how netCreate retrieves directory and file name.
  81.  moved pathCat to pathLib.
  82. 03l,30may88,dnw  changed to v4 names.
  83. 03k,04may88,jcf  changed semaphores to be compatible with new semLib.
  84. 03j,21apr88,gae  fixed documentation about fseek().
  85. 03i,17mar88,gae  fixed netPut() bug.
  86.  fixed potential ssemGive() & releaseNetFd() ordering bug.
  87.  fixed bug in netCreate() - file not created if nothing written.
  88. 03h,28jan88,jcf  made kernel independent.
  89. 03g,18nov87,ecs  documentation.
  90. 03f,06nov87,ecs  documentation.
  91. 03e,16oct87,gae  fixed bug in netClose() - return value indeterminate.
  92.  changed "cd/cat" to use pathCat to construct UNIX filename.
  93.  Added pathCat().  Semaphored fd usage.
  94.  Added "super semaphores" to allow successive semTake's on
  95.  the same semaphore by the same task (needed for recursion).
  96. 03d,25mar87,jlf  documentation
  97.     dnw  added missing parameter on ftpGetReply calls.
  98.  prepended FTP_ to ftp reply codes.
  99. 03c,12feb86,dnw  fixed bug in netPut.  This time for sure.
  100. 03b,14jan87,dnw  fixed bug in netPut.
  101. 03a,01dec86,dnw  added ftp protocol option.
  102.  changed to not get include files from default directories.
  103. 02h,08nov86,llk  documentation.
  104. 02g,07oct86,gae  made netCreate() use ioGetDefDevTail() instead of global
  105.  'currentDirectory' to conclude the remote directory name.
  106.  Use remGetCurId() to get 'currentIdentity'...included remLib.h
  107. 02f,05sep86,jlf  made netIoctrl return nbytes for FIONREAD in arg.
  108.  minor documentation.
  109. 02e,29jul86,llk  cleaned up netGet.
  110. 02d,27jul86,llk  receives standard error messages from Unix when giving
  111.  a remote command (remRcmd).  Forwards it on to user.
  112.  Added getNetStatus.
  113. 02c,02jul86,jlf  documentation
  114. 02b,21jun86,rdc  fixed bug in netCreate - wasn't allocating sufficient space
  115.  for strings.
  116. 02a,21may86,llk  got rid of ram disk.  Implemented network file desciptors.
  117.  Wrote all routines except netDrv and netDevCreate.
  118. 01c,03mar86,jlf  changed ioctrl calls to ioctl.
  119.  changed netIoctrl to netIoctl.
  120. 01b,28jan86,jlf  documentation, made netIoctrl be LOCAL.
  121. 01a,14sep85,rdc  written.
  122. */
  123. /*
  124. This driver provides facilities for accessing files transparently over the
  125. network via FTP or RSH.  By creating a network device with netDevCreate(),
  126. files on a remote UNIX machine may be accessed as if they were local.
  127. When a remote file is opened, the entire file is copied over the network
  128. to a local buffer.  When a remote file is created, an empty local buffer
  129. is opened.  Any reads, writes, or ioctl() calls are performed on the local
  130. copy of the file.  If the file was opened with the flags O_WRONLY or O_RDWR
  131. and modified, the local copy is sent back over the network to the UNIX
  132. machine when the file is closed.
  133. Note that this copying of the entire file back and forth can make netDrv
  134. devices awkward to use.  A preferable mechanism is NFS as provided by
  135. nfsDrv.
  136. USER-CALLABLE ROUTINES
  137. Most of the routines in this driver are accessible only through the I/O
  138. system.  However, two routines must be called directly: netDrv() to
  139. initialize the driver and netDevCreate() to create devices.
  140. FILE OPERATIONS
  141. This driver supports the creation, deletion, opening, reading,
  142. writing, and appending of files.  The renaming of files is not
  143. supported.
  144. INITIALIZATION
  145. Before using the driver, it must be initialized by calling the routine
  146. netDrv().  This routine should be called only once, before any reads,
  147. writes, netDevCreate(), or netDevCreate2() calls.  Initialization is
  148. performed automatically when INCLUDE_NET_DRV is defined.
  149. CREATING NETWORK DEVICES
  150. To access files on a remote host, a network device must be created by
  151. calling netDevCreate() or netDevCreate2().  The arguments to netDevCreate()
  152. are the name of the device, the name of the host the device will access,
  153. and the remote file access protocol to be used -- RSH or FTP.
  154. The arguments to netDevCreate2() are ones described above and a size of
  155. buffer used in the network device as a fourth argument.
  156. By convention, a network device name is the remote machine name followed
  157. by a colon ":".  For example, for a UNIX host on the network "wrs", files
  158. can be accessed by creating a device called "wrs:".  For more information,
  159. see the manual entry for netDevCreate() and netDevCreate2().
  160. IOCTL FUNCTIONS
  161. The network driver responds to the following ioctl() functions:
  162. .iP "FIOGETNAME" 18 3
  163. Gets the file name of the file descriptor <fd> and copies it to the buffer
  164. specified by <nameBuf>:
  165. .CS
  166.     status = ioctl (fd, FIOGETNAME, &nameBuf);
  167. .CE
  168. .iP "FIONREAD"
  169. Copies to <nBytesUnread> the number of bytes remaining in the file
  170. specified by <fd>:
  171. .CS
  172.     status = ioctl (fd, FIONREAD, &nBytesUnread);
  173. .CE
  174. .iP "FIOSEEK"
  175. Sets the current byte offset in the file to the position specified by
  176. <newOffset>.  If the seek goes beyond the end-of-file, the file grows.
  177. The end-of-file pointer changes to the new position, and the new space is
  178. filled with zeroes:
  179. .CS
  180.     status = ioctl (fd, FIOSEEK, newOffset);
  181. .CE
  182. .iP "FIOWHERE"
  183. Returns the current byte position in the file.
  184. This is the byte offset of the next byte to be read or written.
  185. It takes no additional argument:
  186. .CS
  187.     position = ioctl (fd, FIOWHERE, 0);
  188. .CE
  189. .iP "FIOFSTATGET"
  190. Gets file status information.  The argument <statStruct> is a pointer
  191. to a stat structure that is filled with data describing the specified
  192. file.  Normally, the stat() or fstat() routine is used to obtain file
  193. information, rather than using the FIOFSTATGET function directly.
  194. netDrv only fills in three fields of the stat structure: st_dev,
  195. st_mode, and st_size. st_mode is always filled with S_IFREG.
  196. .CS
  197.     struct stat statStruct;
  198.     fd = open ("file", O_RDONLY);
  199.     status = ioctl (fd, FIOFSTATGET, &statStruct);
  200. .CE
  201. LIMITATIONS
  202. The netDrv implementation strategy implies that directories cannot
  203. always be distinguished from plain files.  Thus, opendir() does not
  204. work for directories mounted on netDrv devices, and ll() does not flag
  205. subdirectories with the label "DIR" in listings from netDrv devices.
  206. When the access method is FTP, operations can only be done on files that
  207. the FTP server allows to download. In particular it is not possible to
  208. 'stat' a directory, doing so will result in "<dirname>: not a plain file"
  209. error.
  210. INCLUDE FILES: netDrv.h
  211. SEE ALSO: remLib, netLib, sockLib, hostAdd()
  212. */
  213. #include "vxWorks.h"
  214. #include "sys/socket.h"
  215. #include "iosLib.h"
  216. #include "ioLib.h"
  217. #include "logLib.h"
  218. #include "memLib.h"
  219. #include "memPartLib.h"
  220. #include "semLib.h"
  221. #include "string.h"
  222. #include "remLib.h"
  223. #include "fcntl.h"
  224. #include "ftpLib.h"
  225. #include "lstLib.h"
  226. #include "netDrv.h"
  227. #include "errnoLib.h"
  228. #include "unistd.h"
  229. #include "stdio.h"
  230. #include "pathLib.h"
  231. #include "fioLib.h"
  232. #include "stdlib.h"
  233. #include "private/semLibP.h"
  234. #include "private/iosLibP.h"
  235. #include "private/funcBindP.h"
  236. #include "sys/stat.h"
  237. #define FD_DIRTY 4 /* mask for the dirty bit */
  238. /* in the options field of NET_FD, bit [2] */
  239. #define DATASIZE 512 /* bytes per block of data */
  240. /* remote file access protocols */
  241. #define PROTO_RSH 0 /* UNIX RSH protocol */
  242. #define PROTO_FTP 1 /* ARPA FTP protocol */
  243. #define RSHD 514 /* rshd service */
  244. #define NETDRV_DEBUG(string, param1, param2, param3, param4, param5, param6)
  245.     {
  246.     if ((_func_logMsg != NULL) && (netDrvDebugErrors ))
  247.         (* _func_logMsg) (string, param1, param2, param3, param4, param5, 
  248.         param6);
  249.     }
  250. STATUS netDrvFileDoesNotExist (char *filename, char *response);
  251. FUNCPTR _func_fileDoesNotExist  = netDrvFileDoesNotExist; /* Use default configlette */
  252. typedef struct /* NET_DEV */
  253.     {
  254.     DEV_HDR devHdr; /* device header */
  255.     char host[MAX_FILENAME_LENGTH]; /* host for this device */
  256.     int protocol; /* remote file access protocol*/
  257.     UINT bufSize; /* size of buffer */
  258.     int fdMode; /* FD_MODE of this device */
  259.     } NET_DEV;
  260. /* A network file descriptor consists of a NET_FD header with a linked list
  261.  * of DATABLOCKs maintained by lstLib.  The file pointer (filePtrByte) and
  262.  * end of file pointer (endOfFile) contain absolute byte numbers starting
  263.  * at 0.  For instance, the first byte in the first block is #0.  The first
  264.  * byte in the second block is #512 for 512 byte blocks.  The first byte in
  265.  * the third block is #1024, etc.  Therefore, a byte number modulo 512 gives
  266.  * the index of the byte in databuf.
  267.  */
  268. typedef struct /* DATA_BLOCK */
  269.     {
  270.     NODE link; /* link to adjacent BLOCKs in file */
  271.     int used; /* bytes used in databuf (offset) */
  272.     char databuf[DATASIZE]; /* store data here */
  273.     } DATABLOCK;
  274. /* network file descriptor */
  275. typedef struct /* NET_FD */
  276.     {
  277.     LIST  dataLst; /* list of data blocks */
  278.     NET_DEV *  pNetDev; /* file descriptors network device */
  279.     DATABLOCK *  filePtrBlock; /* pointer to current datablock */
  280.     int  filePtrByte; /* number of current byte */
  281.     int  endOfFile; /* byte number after last file byte */
  282.     int  options; /* contains mode and dirty bit */
  283.     char *  remDirName;    /* directory name on remote machine */
  284.     char *  remFileName;   /* file name on remote machine */
  285.     SEM_ID  netFdSem; /* mutex semaphore */
  286.     char *  buf; /* read buffer */
  287.     int  bufBytes; /* available bytes in the buffer */
  288.     int  bufOffset; /* current offset in the buffer */
  289.     int  dataSock; /* data socket */
  290.     int  ctrlSock; /* control socket */
  291.     int  status [8]; /* status counter */
  292.     } NET_FD;
  293. /* globals */
  294. #define NET_LS_STRING "/bin/ls -a %s"
  295. int mutexOptionsNetDrv = SEM_Q_PRIORITY | SEM_DELETE_SAFE;
  296. /* locals */
  297. LOCAL BOOL netDrvDebugStats = FALSE; 
  298. LOCAL BOOL netDrvDebugErrors = FALSE; 
  299. LOCAL int netDrvNum; /* this particular driver number */
  300. /* forward static functions */
  301. static int netCreate (NET_DEV *pNetDev, char *name, int mode);
  302. static int netCreate2 (NET_FD *pNetFd, char *name, int mode);
  303. static STATUS netDelete (NET_DEV *pNetDev, char *name);
  304. static int netOpen (NET_DEV *pNetDev, char *name, int mode, int perm);
  305. static STATUS netClose (NET_FD *pNetFd);
  306. static STATUS netLs (NET_FD *pNetFd);
  307. static STATUS netFileExists (NET_DEV *pNetDev, char *name);
  308. static void getNetStatus (char *buf);
  309. static int netRead (NET_FD *pNetFd, char *buf, int maxBytes);
  310. static int netWrite (NET_FD *pNetFd, char *buffer, int nBytes);
  311. static int netIoctl (NET_FD *pNetFd, int function, int arg);
  312. static int netFdCreate (NET_DEV *pNetDev, char *name, int mode);
  313. static void netFdRelease (NET_FD *pNetFd);
  314. static STATUS netGet (NET_FD *pNetFd);
  315. static STATUS netPut (NET_FD *pNetFd);
  316. static int netSeek (NET_FD *pNetFd, int newPos);
  317. static STATUS moveEndOfFile (NET_FD *pNetFd, int newPos);
  318. static STATUS netSockOpen (NET_FD *pNetFd);
  319. static STATUS netSockClose (NET_FD *pNetFd);
  320. extern STATUS netDevCreate2 (char *devName, char *host, int protocol, 
  321.      UINT bufSize);
  322. /* forward declarations */
  323. IMPORT void lstInternalFree (LIST *pList, VOIDFUNCPTR freeFunc);
  324. /*******************************************************************************
  325. *
  326. * netDrv - install the network remote file driver
  327. *
  328. * This routine initializes and installs the network driver.
  329. * It must be called before other network remote file functions are performed.
  330. * It is called automatically when INCLUDE_NET_DRV is defined.
  331. *
  332. * VXWORKS AE PROTECTION DOMAINS
  333. * Under VxWorks AE, you can call this function from within the kernel 
  334. * protection domain only.  This restriction does not apply under non-AE 
  335. * versions of VxWorks.  
  336. *
  337. * RETURNS: OK or ERROR.
  338. */
  339. STATUS netDrv (void)
  340.     {
  341.     if (netDrvNum > 0)
  342.         return (OK); /* driver already installed */
  343.     netDrvNum = iosDrvInstall (netCreate, netDelete, netOpen, netClose,
  344.                                 netRead, netWrite, netIoctl);
  345.     return (netDrvNum == ERROR ? ERROR : OK);
  346.     }
  347. /*******************************************************************************
  348. *
  349. * netDevCreate - create a remote file device
  350. *
  351. * This routine creates a remote file device.  Normally, a network device is
  352. * created for each remote machine whose files are to be accessed.  By
  353. * convention, a network device name is the remote machine name followed by a
  354. * colon ":".  For example, for a UNIX host on the network whose name is
  355. * "wrs", files can be accessed by creating a device called "wrs:".  Files
  356. * can be accessed via RSH as follows:
  357. *
  358. * .CS
  359. *     netDevCreate ("wrs:", "wrs", rsh);
  360. * .CE
  361. *
  362. * The file /usr/dog on the UNIX system "wrs" can now be accessed as
  363. * "wrs:/usr/dog" via RSH.
  364. *
  365. * Before creating a device, the host must have already been created with
  366. * hostAdd().
  367. *
  368. * RETURNS: OK or ERROR.
  369. *
  370. * SEE ALSO: hostAdd()
  371. */
  372. STATUS netDevCreate
  373.     (
  374.     char *devName,      /* name of device to create */
  375.     char *host,         /* host this device will talk to */
  376.     int protocol        /* remote file access protocol 0 = RSH, 1 = FTP */
  377.     )
  378.     {
  379.     return (netDevCreate2 (devName, host, protocol, 0));
  380.     }
  381. /*******************************************************************************
  382. *
  383. * netDevCreate2 - create a remote file device with fixed buffer size
  384. *
  385. * This routine creates a remote file device, just like netDevCreate(),  but it allows
  386. * very large files to be accessed without loading the entire file to memory.
  387. * The fourth parameter <bufSize> specifies the amount of memory. If the <bufSize> is 
  388. * zero, then the behavior is exactly the same as netDevCreate().  If <bufSize>
  389. * is not zero, the following restrictions apply:
  390. * ml
  391. * m - O_RDONLY, O_WRONLY open modes are supported, but not O_RDWR open mode.
  392. * m - seek is supported in O_RDONLY open mode, but not in O_WRONLY open mode.
  393. * m - backward seek will be slow if it is beyond the buffer.
  394. * me
  395. *
  396. * RETURNS: OK or ERROR.
  397. *
  398. * SEE ALSO: netDevCreate()
  399. */
  400. STATUS netDevCreate2
  401.     (
  402.     char *devName,      /* name of device to create */
  403.     char *host,         /* host this device will talk to */
  404.     int protocol,       /* remote file access protocol 0 = RSH, 1 = FTP */
  405.     UINT bufSize        /* size of buffer in NET_FD */
  406.     )
  407.     {
  408.     FAST NET_DEV *pNetDev;
  409.     if (netDrvNum < 1)
  410.         {
  411.         errno = S_ioLib_NO_DRIVER;
  412.         return (ERROR);
  413.         }
  414.     pNetDev = (NET_DEV *) KHEAP_ALLOC (sizeof (NET_DEV));
  415.     if (pNetDev == NULL)
  416.         return (ERROR);
  417.     (void) strcpy (pNetDev->host, host);
  418.     pNetDev->protocol = protocol;
  419.     pNetDev->bufSize = bufSize;     /* if it is not zero, we use the buf */
  420.     if (bufSize == 0)
  421.         pNetDev->fdMode = 3;        /* O_RDONLY, O_WRONLY or O_RDWR */
  422.     else
  423.         pNetDev->fdMode = 1;        /* O_RDONLY, O_WRONLY */
  424.     if (iosDevAdd ((DEV_HDR *) pNetDev, devName, netDrvNum) != OK)
  425.         {
  426.         KHEAP_FREE ((char *) pNetDev); 
  427.         return ERROR; 
  428.         }
  429.   
  430.     return OK;
  431.     }
  432. /* routines supplied to I/O system */
  433. /*******************************************************************************
  434. *
  435. * netCreate - create a remote file
  436. *
  437. * Returns an open network file descriptor.
  438. *
  439. * Called only by the I/O system.
  440. *
  441. * RETURNS: Pointer to open network file descriptor or ERROR.
  442. */
  443. LOCAL int netCreate
  444.     (
  445.     NET_DEV *pNetDev,
  446.     char *name,         /* remote file name */
  447.     int mode            /* ignored, always set to O_WRONLY */
  448.     )
  449.     {
  450.     FAST NET_FD *pNetFd;
  451.     pNetFd = (NET_FD *) netFdCreate (pNetDev, name, mode);
  452.     if (pNetFd == (NET_FD *) ERROR)
  453.         {
  454.         return (ERROR);
  455.         }
  456.     if (netCreate2 (pNetFd, name, mode) == ERROR)
  457.         {
  458.         NETDRV_DEBUG ("netCreate:  error calling netCreate2()  errno:0x%08xn", errno,1,2,3,4,5);
  459.         return ERROR;
  460.         }
  461.     return ((int) pNetFd);
  462.     }
  463. /*******************************************************************************
  464. *
  465. * netCreate2 - create a remote file with an existing net file descriptor
  466. *
  467. * Returns an open network file descriptor.
  468. *
  469. * Called only by netCreate and netOpen
  470. *
  471. * RETURNS: Pointer to open network file descriptor or ERROR.
  472. */
  473. LOCAL int netCreate2
  474.     (
  475.     NET_FD *pNetFd,
  476.     char *name,         /* remote file name */
  477.     int mode            /* ignored, always set to O_WRONLY */
  478.     )
  479.     {
  480.     if (pNetFd == (NET_FD *) ERROR)
  481.         {
  482.         NETDRV_DEBUG ("netCreate2:  pNetFd == NULL errno:0x%08xn", errno,1,2,3,4,5);
  483.         return (ERROR);
  484.         }
  485.     if (pNetFd->pNetDev->bufSize > 0)
  486.         {
  487.         char command[MAX_FILENAME_LENGTH];
  488.         char buffer [MAX_FILENAME_LENGTH];
  489.         char usr [MAX_IDENTITY_LEN];
  490.         char passwd [MAX_IDENTITY_LEN];
  491.         /* open the remote file */
  492.         remCurIdGet (usr, passwd);
  493.         if (pNetFd->pNetDev->protocol == PROTO_FTP)
  494.             {
  495.             if (ftpXfer (pNetFd->pNetDev->host, usr, passwd, "",
  496.                 "STOR %s", pNetFd->remDirName, pNetFd->remFileName,
  497.                 &pNetFd->ctrlSock, &pNetFd->dataSock) == ERROR)
  498.                 {
  499.                 NETDRV_DEBUG ("netCreate2:  error calling ftpXfer()  errno:0x%08xn", 
  500.                               errno,1,2,3,4,5);
  501.                 return (ERROR);
  502.                 }
  503.             }
  504.         else
  505.             {
  506.             if (pathCat (pNetFd->remDirName, pNetFd->remFileName, buffer) ==
  507.                     ERROR)
  508.                 {
  509.                 NETDRV_DEBUG ("netCreate2:  error calling pathCat()  errno:0x%08xn", 
  510.                               errno,1,2,3,4,5);
  511.                 return (ERROR);
  512.                 }
  513.             sprintf (command, "/bin/cat > %s", buffer);
  514.             pNetFd->dataSock = rcmd (pNetFd->pNetDev->host, RSHD, usr,
  515.                                      usr, command, &pNetFd->ctrlSock);
  516.     
  517.             if (pNetFd->dataSock == ERROR)
  518.                 {
  519.                 NETDRV_DEBUG ("netCreate2:  error calling rcmd()  errno:0x%08xn", 
  520.                               errno,1,2,3,4,5);
  521.                 return (ERROR);
  522.                 }
  523.             }
  524.         }
  525.     return ((int) pNetFd);
  526.     }
  527. /*******************************************************************************
  528. *
  529. * netDelete - delete a file from a remote machine via the network.
  530. *
  531. * The remote shell daemon on the machine 'host' is used to delete
  532. * the given file.  The remote userId should have been set previously
  533. * by a call to iam().
  534. *
  535. * RETURNS: OK or ERROR.
  536. */
  537. LOCAL STATUS netDelete
  538.     (
  539.     NET_DEV *pNetDev,
  540.     char *name          /* remote file name */
  541.     )
  542.     {
  543.     int dataSock;
  544.     int ctrlSock;
  545.     char buf [DATASIZE];    /* make buf the same size as NET_FD's databuf */
  546.     FAST int nBytes;
  547.     char command[MAX_FILENAME_LENGTH];
  548.     STATUS status = OK;
  549.     char usr [MAX_IDENTITY_LEN];
  550.     char passwd [MAX_IDENTITY_LEN];
  551.     char *pDirName;
  552.     char *pFileName;
  553.     pDirName  = (char *) KHEAP_ALLOC ((unsigned) (strlen (name) + 1));
  554.     pFileName = (char *) KHEAP_ALLOC ((unsigned) (strlen (name) + 1));
  555.     remCurIdGet (usr, passwd);
  556.     /* get directory name and file name */
  557.     pathSplit (name, pDirName, pFileName);
  558.     if (pNetDev->protocol == PROTO_FTP)
  559.         {
  560.     
  561.         if (ftpXfer (pNetDev->host, usr, passwd, "",
  562.             "DELE %s", pDirName, pFileName,
  563.             &ctrlSock, (int *) NULL) == ERROR)
  564.             {
  565.             NETDRV_DEBUG ("netDelete:  error calling ftpXfer()  errno:0x%08xn", 
  566.                           errno,1,2,3,4,5);
  567.             KHEAP_FREE (pDirName);
  568.             KHEAP_FREE (pFileName);
  569.             return (ERROR);
  570.             }
  571.         }
  572.     else
  573.         {
  574.         sprintf (command, "/bin/rm %s", name);
  575.         dataSock = rcmd (pNetDev->host, RSHD, usr, usr, command, &ctrlSock);
  576.         if (dataSock == ERROR)
  577.             {
  578.             NETDRV_DEBUG ("netDelete:  error calling rcmd()  errno:0x%08xn", 
  579.                           errno,1,2,3,4,5);
  580.             KHEAP_FREE (pDirName);
  581.             KHEAP_FREE (pFileName);
  582.             return (ERROR);
  583.             }
  584.         close (dataSock);
  585.         /* check control socket for error */
  586.         if ((nBytes = fioRead (ctrlSock, buf, sizeof (buf) - 1)) > 0)
  587.             {
  588.             NETDRV_DEBUG ("netDelete:  error fioread()  errno:0x%08xn", 
  589.                           errno,1,2,3,4,5);
  590.             /* print error message on standard error fd */
  591.             buf [nBytes] = EOS; /* insure string termination */
  592.             NETDRV_DEBUG ("%s:%s errno:0x%08x", pNetDev->host, buf, errno,3,4,5);
  593.             /* set the task's status according to the UNIX error */
  594.             getNetStatus (buf);
  595.             status = ERROR;
  596.             }
  597.         }
  598.     if (pNetDev->protocol == PROTO_FTP &&
  599.         ftpCommand (ctrlSock, "QUIT",0,0,0,0,0,0) != FTP_COMPLETE)
  600.         {
  601.         NETDRV_DEBUG ( 
  602.             "netDelete:  error calling ftpCommand("QUIT")  errno:0x%08xn",  
  603.             errno,1,2,3,4,5);
  604.         status = ERROR;
  605.         }
  606.     close (ctrlSock);
  607.     KHEAP_FREE (pDirName);
  608.     KHEAP_FREE (pFileName);
  609.     return (status);
  610.     }
  611. /*******************************************************************************
  612. *
  613. * netOpen - open a remote file
  614. *
  615. * netOpen loads the remote file from the host into a network file descriptor.
  616. * If the file does not exist and the O_CREAT flag is not specifed, or the file
  617. * is not readable on the UNIX machine, then the UNIX error message is printed
  618. * on the standard error file descriptor and ERROR is returned.
  619. *
  620. * Called only by the I/O system.
  621. *
  622. * RETURNS: Pointer to open network file descriptor, or ERROR.
  623. */
  624. LOCAL int netOpen
  625.     (
  626.     FAST NET_DEV *pNetDev,    /* pointer to network device */
  627.     char         *name,       /* remote file name to open */
  628.     int           mode,       /* O_RDONLY, O_WRONLY or O_RDWR, and O_CREAT */
  629.     int           perm        /* UNIX permissions, includes directory flag */
  630.     )
  631.     {
  632.     FAST NET_FD *pNetFd;
  633.     STATUS status;
  634.     NETDRV_DEBUG ("**** netOpen: name:%s mode:0x%x perm:0x%x Entered ***n", 
  635.                   1,2,3,4,5,6);
  636.     pNetFd = (NET_FD *) netFdCreate (pNetDev, name, mode);
  637.     if (pNetFd == (NET_FD *) ERROR)
  638.         {
  639.         NETDRV_DEBUG ("netOpen:  error calling netFdCreate()  errno:0x%08xn",  
  640.                       errno,1,2,3,4,5);
  641.         return (ERROR);
  642.         }
  643.     /* Leave file at 0 length. */
  644.     if ((mode & O_TRUNC))
  645.         {
  646.         return ((int) pNetFd); 
  647.         }
  648.     if ((mode & O_CREAT))
  649.         {
  650.         NETDRV_DEBUG ("**** netOpen: calling netFileExists ***n", 1,2,3,4,5,6);
  651.         }
  652.     else
  653.         {
  654.         NETDRV_DEBUG ("**** O_CREATE NOT USED!!! ***n", 1,2,3,4,5,6);
  655.         }
  656.     if (mode & O_CREAT) 
  657.         {
  658.         if (netFileExists (pNetDev, name) == ERROR)
  659.             {
  660.             NETDRV_DEBUG ("netOpen: calling netCreate2 n", 1,2,3,4,5,6);
  661.             errno = 0; /* reset errno after netFileNetExists() */
  662.             if (netCreate2 (pNetFd, name, mode) == ERROR)
  663.                 {
  664.                 NETDRV_DEBUG ("**** netOpen: netCreate2 return error ***n", 1,2,3,4,5,6);
  665.                 return (ERROR);
  666.                 }
  667.             NETDRV_DEBUG ("netOpen: returning file descriptor pointer 0x%08x after creating filen", pNetFd,1,2,3,4,5);
  668.             return ((int) pNetFd); 
  669.             }
  670.         else
  671.             {
  672.             NETDRV_DEBUG ("netOpen: netFileExists - returned OK - file existsn", 
  673.                           1,2,3,4,5,6);
  674.             }
  675.         NETDRV_DEBUG ("netOpen: CREAT called, but file already existsn", 
  676.                       pNetFd,1,2,3,4,5);
  677.         }
  678.     semTake (pNetFd->netFdSem, WAIT_FOREVER);
  679.     /* netFdCreate sets a O_RDONLY mode to O_RDWR and sets dirty bit,
  680.      * set it back to original mode. */
  681.     pNetFd->options = mode & pNetFd->pNetDev->fdMode;
  682.     if (pNetFd->pNetDev->bufSize == 0)
  683.         {
  684.         NETDRV_DEBUG ("netOpen:  calling netGet() n", 0,1,2,3,4,5);
  685.         if (netGet (pNetFd) != OK)
  686.             {
  687.             /* not able to get file from host */
  688.             semGive (pNetFd->netFdSem);
  689.             netFdRelease (pNetFd);
  690.             NETDRV_DEBUG ("netOpen:  netGet() return !OK - errno:0x%08xn", 
  691.                           errno,1,2,3,4,5);
  692.             return (ERROR);
  693.             }
  694.         /* netGet might have moved the file pointer, so reset to beginning */
  695.         status = netSeek (pNetFd, 0);
  696.         if (status == ERROR)
  697.             {
  698.             NETDRV_DEBUG ("netOpen:  error calling netSeek()  errno:0x%08xn", 
  699.                           errno,1,2,3,4,5);
  700.             semGive (pNetFd->netFdSem);
  701.             netFdRelease (pNetFd);
  702.             return (ERROR);
  703.             }
  704.         }
  705.     else
  706.         {
  707.         if ((status = netSockOpen (pNetFd)) != OK) /* open the connection */
  708.             {
  709.             NETDRV_DEBUG ("netOpen:  error calling netSockOpen()  errno:0x%08xn", 
  710.                           errno,1,2,3,4,5);
  711.             /* not able to open file from host */
  712.             semGive (pNetFd->netFdSem);
  713.             netFdRelease (pNetFd);
  714.             return (ERROR);
  715.             }
  716.         pNetFd->filePtrByte = 0;
  717.         pNetFd->bufBytes    = 0;
  718.         pNetFd->bufOffset   = 0;
  719.         }
  720.     semGive (pNetFd->netFdSem);
  721.     return ((int) pNetFd);
  722.     }
  723. /*******************************************************************************
  724. *
  725. * netClose - close a remote file.  Copy it to the remote machine.
  726. *
  727. * If the file is O_WRONLY or O_RDWR mode and it has been written to (it's
  728. * dirty bit is set), then the file is copied over to UNIX.
  729. *
  730. * Called only by the I/O system.
  731. *
  732. * RETURNS: OK or ERROR.
  733. */
  734. LOCAL STATUS netClose
  735.     (
  736.     FAST NET_FD *pNetFd
  737.     )
  738.     {
  739.     STATUS status = OK;
  740.    NETDRV_DEBUG ("netClose: enteredn",0,0,0,0,0,0);
  741.     semTake (pNetFd->netFdSem, WAIT_FOREVER);
  742.     if (pNetFd->pNetDev->bufSize == 0)
  743.         {
  744.         /* if file has dirty bit set, it's been changed. Copy it to the host */
  745.         if (pNetFd->options & FD_DIRTY)
  746.             status = netPut (pNetFd);
  747.         if (status == ERROR)
  748.             {
  749.             NETDRV_DEBUG ("netClose: error calling netPut to flush file errno=0x%08xn",
  750.                           errno,2,3,4,5,6);
  751.             }
  752.         }
  753.     else
  754.         {
  755.         status = netSockClose (pNetFd); /* close the connection */
  756.         if (status != OK)
  757.             {
  758.             NETDRV_DEBUG ("netClose: error calling netSockClose errno=0x%08xn",  
  759.                           errno,2,3,4,5,6);
  760.             }
  761.         }
  762.     semGive (pNetFd->netFdSem);
  763.     /* print out the statistic if the debug flag is on */
  764.     if ((netDrvDebugStats) && (pNetFd->pNetDev->bufSize > 0))
  765.         {
  766.         NETDRV_DEBUG ("read[hit=%d mis=%d] fseek[hit=%d mis=%d] bseek[hit=%d mis=%d]n",
  767.                       pNetFd->status[0], pNetFd->status[1], pNetFd->status[2],
  768.                       pNetFd->status[3], pNetFd->status[4], pNetFd->status[5]);
  769.         }
  770.     netFdRelease (pNetFd);
  771.     return (status);
  772.     }
  773. /*******************************************************************************
  774. *
  775. * netLs - list a remote directory.
  776. *
  777. * RETURNS: OK or ERROR.
  778. */
  779. LOCAL STATUS netLs
  780.     (
  781.     FAST NET_FD *pNetFd
  782.     )
  783.     {
  784.     int dataSock;
  785.     int ctrlSock;
  786.     char buf [DATASIZE]; /* make buf the same size as NET_FD's databuf */
  787.     FAST int nBytes = -1;
  788.     char command[MAX_FILENAME_LENGTH];
  789.     char buffer [MAX_FILENAME_LENGTH];
  790.     STATUS status = OK;
  791.     char usr [MAX_IDENTITY_LEN];
  792.     char passwd [MAX_IDENTITY_LEN];
  793.     remCurIdGet (usr, passwd);
  794.     if (pNetFd->pNetDev->protocol == PROTO_FTP)
  795.         {
  796.         if (pNetFd->remFileName[0] == '.')
  797.             {
  798.             if (ftpXfer (pNetFd->pNetDev->host, usr, passwd, "", "NLST",
  799.                          pNetFd->remDirName, pNetFd->remFileName,
  800.                          &ctrlSock, &dataSock) == ERROR)
  801.                 {
  802.                     NETDRV_DEBUG ("netLs:  error calling ftpXfer("NLST")  errno:0x%08xn", errno,1,2,3,4,5);
  803.                 return (ERROR);
  804.                 }
  805.             }
  806.         else
  807.            {
  808.            if (ftpXfer (pNetFd->pNetDev->host, usr, passwd, "", "NLST %s",
  809.                         pNetFd->remDirName, pNetFd->remFileName,
  810.                         &ctrlSock, &dataSock) == ERROR)
  811.                {
  812.                NETDRV_DEBUG ("netLs:  error calling ftpXfer("NLST")  errno:0x%08xn", errno,1,2,3,4,5);
  813.                return (ERROR);
  814.                }
  815.            }
  816.         }
  817.     else
  818.         {
  819.         if (pathCat (pNetFd->remDirName, pNetFd->remFileName, buffer) == ERROR)
  820.             {
  821.             NETDRV_DEBUG ("netLs:  error calling pathCat("%s", "%s")  errno:0x%08xn", 
  822.             pNetFd->remDirName, pNetFd->remFileName,errno,1,2,3);
  823.             return (ERROR);
  824.             }
  825.         sprintf (command, NET_LS_STRING, buffer);
  826.         dataSock = rcmd (pNetFd->pNetDev->host, RSHD, usr,
  827.                           usr, command, &ctrlSock);
  828.         if (dataSock == ERROR)
  829.             {
  830.             NETDRV_DEBUG ("netLs:  error calling rcmd() errno:0x%08xn", errno,1,2,3,4,5);
  831.             return (ERROR);
  832.             }
  833.         }
  834.     /* read bytes from socket and write them
  835.      * to standard out one block at a time
  836.      */
  837.     while ((status == OK) &&
  838.            ((nBytes = read (dataSock, buf, sizeof (buf))) > 0))
  839.         {
  840.         if (write (STD_OUT, buf, nBytes) != nBytes)
  841.             {
  842.                 NETDRV_DEBUG ("netLs:  error calling write()  errno:0x%08xn", 
  843.                               errno,1,2,3,4,5);
  844.                 status = ERROR;
  845.              }
  846.         }
  847.     if (nBytes < 0) /* recv error */
  848.         {
  849.         NETDRV_DEBUG ("netLs:  error calling read()  errno:0x%08xn", errno,1,2,3,4,5);
  850.         status = ERROR;
  851.         }
  852.     close (dataSock);
  853.     if (pNetFd->pNetDev->protocol == PROTO_FTP)
  854.        {
  855.        if (ftpReplyGet (ctrlSock, TRUE) != FTP_COMPLETE)
  856.            {
  857.            NETDRV_DEBUG ("netLs:  error calling ftpReplyGet()  errno:0x%08xn", 
  858.                          errno,1,2,3,4,5);
  859.            status = ERROR;
  860.            }
  861.        }
  862.     else
  863.        {
  864.        /* check control socket for error */
  865.        if ((nBytes = fioRead (ctrlSock, buf, sizeof (buf) - 1)) > 0)
  866.            {
  867.            /* print error message */
  868.            buf [nBytes] = EOS; /* insure string termination */
  869.            NETDRV_DEBUG ("netLs: %s:%s errno:0x%08x error calling fioread() n",  
  870.                          pNetFd->pNetDev->host, buf, errno,1,2,3);
  871.            /* set the task's status according to the UNIX error */
  872.            getNetStatus (buf);
  873.            status = ERROR;
  874.            }
  875.        }
  876.     if (pNetFd->pNetDev->protocol == PROTO_FTP &&
  877.        ftpCommand (ctrlSock, "QUIT",0,0,0,0,0,0) != FTP_COMPLETE)
  878.        {
  879.            NETDRV_DEBUG ("netLs:  error calling ftpCommand()  errno:0x%08xn", 
  880.                          errno,1,2,3,4,5);
  881.            status = ERROR;
  882.        }
  883.     close (ctrlSock);
  884.     return (status);
  885.     }
  886. /******************************************************************************
  887. *
  888. * netLsByName - list a remote directory by name
  889. *
  890. * RETURNS: OK if successful, otherwise ERROR.  If the device is not a netDrv
  891. * device, errno is set to S_netDrv_UNKNOWN_REQUEST.
  892. *
  893. * ERRNO
  894. *   S_netDrv_UNKNOWN_REQUEST
  895. *
  896. * NOMANUAL
  897. */
  898. STATUS netLsByName
  899.     (
  900.     char * dirName /* name of the directory */
  901.     )
  902.     {
  903.     DEV_HDR * pDevHdr; /* device header */
  904.     char      fullFileName [MAX_FILENAME_LENGTH];
  905.     NET_FD *  pNetFd;
  906.     STATUS    netLsReturn;
  907.     if (ioFullFileNameGet (dirName, &pDevHdr, fullFileName) == ERROR)
  908.         {
  909.         NETDRV_DEBUG ("netLsByName:  error calling ioFullFileNameGet()  errno:0x%08xn",
  910.                       errno,1,2,3,4,5);
  911.         return (ERROR);
  912.         }
  913.     /* make sure the device is a netDrv device */
  914.     if (drvTable [pDevHdr->drvNum].de_open != netOpen)
  915.         {
  916.         NETDRV_DEBUG ("netLsByName:  error UNKNOWN_REQUEST errno:0x%08xn", 
  917.                       errno,1,2,3,4,5);
  918.         errno = S_netDrv_UNKNOWN_REQUEST;
  919.         return (ERROR);
  920.         }
  921.     /* create a NET_FD to pass to netLs */
  922.     pNetFd = (NET_FD *) netFdCreate ((NET_DEV *) pDevHdr, fullFileName, 0);
  923.     if (pNetFd == (NET_FD *)ERROR)
  924.         {
  925.         NETDRV_DEBUG ("netFdCreate:  error callinf netFdCreate errno:0x%08xn", 
  926.                       errno,1,2,3,4,5);
  927.         return (ERROR);             /* SPR #28927 */
  928.         }
  929.     netLsReturn = netLs (pNetFd);
  930.     netFdRelease (pNetFd);
  931.     return (netLsReturn);
  932.     }
  933. /*******************************************************************************
  934. *
  935. * netFileExists - check for the existence of a file.
  936. *
  937. * RETURNS: OK if the file exists, or ERROR.
  938. */
  939. LOCAL STATUS netFileExists
  940.     (
  941.     NET_DEV *pNetDev,
  942.     char *name          /* remote file name */
  943.     )
  944.     {
  945.     int dataSock;
  946.     int ctrlSock;
  947.     char buf [DATASIZE];        /* make buf the same size as NET_FD's databuf */
  948.     char command[MAX_FILENAME_LENGTH];
  949.     STATUS status = OK;
  950.     char usr [MAX_IDENTITY_LEN];
  951.     char passwd [MAX_IDENTITY_LEN];
  952.     char *pDirName  = (char *) KHEAP_ALLOC ((unsigned) (strlen (name) + 1));
  953.     char *pFileName = (char *) KHEAP_ALLOC ((unsigned) (strlen (name) + 1));
  954.     /* don't allow null filenames */
  955.     if (name[0] == EOS)
  956.         {
  957.         errno = S_ioLib_NO_FILENAME;
  958.         NETDRV_DEBUG ("netFileExists:  error S_ioLib_NO_FILENAME errno:0x%08xn", 
  959.                       errno,1,2,3,4,5);
  960.         return (ERROR);
  961.         }
  962.     /* get directory and filename */
  963.     pathSplit (name, pDirName, pFileName);
  964.     remCurIdGet (usr, passwd);
  965.     if (pNetDev->protocol == PROTO_FTP)
  966.         {
  967.         if (ftpXfer (pNetDev->host, usr, passwd, "",
  968.                      "NLST %s", pDirName, pFileName,
  969.                      &ctrlSock, &dataSock) == ERROR)
  970.             {
  971.             NETDRV_DEBUG ("netFileExists:  error calling ftpXfer(). errno:0x%08xn", 
  972.                           errno,1,2,3,4,5);
  973.             KHEAP_FREE (pDirName);
  974.             KHEAP_FREE (pFileName);
  975.             return (ERROR);
  976.             }
  977.         }
  978.     else
  979.         {
  980.         sprintf (command, NET_LS_STRING, name);
  981.         dataSock = rcmd (pNetDev->host, RSHD, usr, usr, command, &ctrlSock);
  982.         if (dataSock == ERROR)
  983.             {
  984.             NETDRV_DEBUG ("netFileExists:  error calling rcmd(). errno:0x%08xn", 
  985.                           errno,1,2,3,4,5);
  986.             KHEAP_FREE (pDirName);
  987.             KHEAP_FREE (pFileName);
  988.             return (ERROR);
  989.             }
  990.         }
  991.     if (pNetDev->protocol == PROTO_FTP)
  992.         {
  993.         /* check dataSock for ls error message */
  994.         if (read (dataSock, buf, sizeof (buf)) <= 0)
  995.             {
  996.             NETDRV_DEBUG ("netFileExists:  error calling read() on data socket for ls. errno:0x%08xn", errno,1,2,3,4,5);
  997.             status = ERROR;
  998.             }
  999.         NETDRV_DEBUG ("netFileExists:  full message:%sn", buf, 1,2,3,4,5);
  1000.         NETDRV_DEBUG ("netFileExists:  message:%sn", buf+ strlen (pFileName) + 1,
  1001.                        1,2,3,4,5);
  1002.         if ((_func_fileDoesNotExist != NULL))
  1003.             {
  1004.             if ((* _func_fileDoesNotExist) (pFileName, buf) == OK)
  1005.                 {
  1006.                 NETDRV_DEBUG ("netFileExists:  match error on ls n", 
  1007.                               errno,1,2,3,4,5);
  1008.                 status = ERROR;
  1009.                 }
  1010.             else
  1011.                 {
  1012.                 NETDRV_DEBUG ("netFileExists:  file does not existn", errno,1,2,3,4,5);
  1013.                 }
  1014.             }
  1015.         if (close (dataSock) == ERROR)
  1016.             {
  1017.             status = ERROR;
  1018.             NETDRV_DEBUG ("netFileExists:  error calling close() on dataSock. errno:0x%08xn", errno,1,2,3,4,5);
  1019.             }
  1020.         if (ftpReplyGet (ctrlSock, FALSE) != FTP_COMPLETE)
  1021.             {
  1022.             NETDRV_DEBUG ("netFileExists: error calling ftpReplyGet(). errno:0x%08xn",
  1023.                           errno,1,2,3,4,5);
  1024.             status = ERROR;
  1025.             }
  1026.         }
  1027.     else
  1028.         {
  1029.         /* check control socket for error */
  1030.         if (read (ctrlSock, buf, sizeof (buf)) > 0)
  1031.             {
  1032.             /* set the task's status according to the UNIX error */
  1033.    
  1034.             getNetStatus (buf);
  1035.             NETDRV_DEBUG ("netFileExists:  error calling read() on control socket. errno:0x%08xn", errno,1,2,3,4,5);
  1036.             status = ERROR;
  1037.             }
  1038.         close (dataSock);
  1039.         }
  1040.     if (pNetDev->protocol == PROTO_FTP &&
  1041.         ftpCommand (ctrlSock, "QUIT",0,0,0,0,0,0) != FTP_COMPLETE)
  1042.         {
  1043.         NETDRV_DEBUG ("netFileExists:  error calling ftpCommand("QUIT"). errno:0x%08xn", errno,1,2,3,4,5);
  1044.         status = ERROR;
  1045.         }
  1046.     close (ctrlSock);
  1047.     KHEAP_FREE (pDirName);
  1048.     KHEAP_FREE (pFileName);
  1049.     NETDRV_DEBUG ("netFileExists:  returning (%d)n", status,1,2,3,4,5);
  1050.     return (status);
  1051.     }
  1052. /*******************************************************************************
  1053. *
  1054. * netGet - downLoad a file from a remote machine via the network.
  1055. *
  1056. * The remote shell daemon on the machine 'host' is used to download
  1057. * the given file to the specified previously opened network file descriptor.
  1058. * The remote userId should have been set previously by a call to iam().
  1059. * If the file does not exist, the error message from the UNIX 'host'
  1060. * is printed to the VxWorks standard error file descriptor and ERROR
  1061. * is returned.
  1062. *
  1063. * RETURNS: OK or ERROR.
  1064. */
  1065. LOCAL STATUS netGet
  1066.     (
  1067.     FAST NET_FD *pNetFd
  1068.     )
  1069.     {
  1070.     int dataSock;
  1071.     int ctrlSock;
  1072.     char buf [DATASIZE]; /* make buf the same size as NET_FD's databuf */
  1073.     FAST int nBytes = -1;
  1074.     char command[MAX_FILENAME_LENGTH];
  1075.     char buffer [MAX_FILENAME_LENGTH];
  1076.     int saveOptions;
  1077.     STATUS status = OK;
  1078.     char usr [MAX_IDENTITY_LEN];
  1079.     char passwd [MAX_IDENTITY_LEN];
  1080.     char *errMsg = "cat: read error: Is a directory";
  1081.     int errMsgLen = strlen (errMsg);
  1082.     remCurIdGet (usr, passwd);
  1083.     if (pNetFd->pNetDev->protocol == PROTO_FTP)
  1084.         {
  1085.         if (ftpXfer (pNetFd->pNetDev->host, usr, passwd, "",
  1086.                      "RETR %s", pNetFd->remDirName, pNetFd->remFileName,
  1087.                      &ctrlSock, &dataSock) == ERROR)
  1088.             {
  1089.             NETDRV_DEBUG ("netGet:  error calling ftpXfer(). errno:0x%08xn", errno,1,2,3,4,5);
  1090.             return (ERROR);
  1091.             }
  1092.         }
  1093.     else
  1094.         {
  1095.         if (pathCat (pNetFd->remDirName, pNetFd->remFileName, buffer) == ERROR)
  1096.            {
  1097.            NETDRV_DEBUG ("netGet:  error calling pathCat(). errno:0x%08xn", errno,1,2,3,4,5);
  1098.            return (ERROR);
  1099.            } 
  1100.         sprintf (command, "/bin/cat < %s", buffer);
  1101.         dataSock = rcmd (pNetFd->pNetDev->host, RSHD, usr,
  1102.                          usr, command, &ctrlSock);
  1103.         if (dataSock == ERROR)
  1104.             {
  1105.             NETDRV_DEBUG ("netGet:  error calling rcmd(). errno:0x%08xn", errno,1,2,3,4,5);
  1106.             return (ERROR);
  1107.             }
  1108.         }
  1109.     /* Set file pointer to beginning of file */
  1110.     if (netSeek (pNetFd, 0) == ERROR)
  1111.         {
  1112.         if (pNetFd->pNetDev->protocol == PROTO_FTP &&
  1113.             ftpCommand (ctrlSock, "QUIT",0,0,0,0,0,0) != FTP_COMPLETE)
  1114.             {
  1115.             NETDRV_DEBUG ("netGet:  error calling ftpCommand("QUIT"). errno:0x%08xn",
  1116.                           errno,1,2,3,4,5);
  1117.             status = ERROR;
  1118.             }
  1119.         close (dataSock);
  1120.         close (ctrlSock);
  1121.         return (ERROR);
  1122.         }
  1123.     /* set mode to write so that file can be written to,
  1124.     *  save original options so they can be restored later
  1125.     */
  1126.     saveOptions = pNetFd->options;
  1127.     pNetFd->options = O_WRONLY & pNetFd->pNetDev->fdMode;
  1128.     /* read bytes from socket and write them
  1129.      * out to file descriptor one block at a time
  1130.      */
  1131.     while ((status == OK) &&
  1132.            ((nBytes = read (dataSock, buf, sizeof (buf))) > 0))
  1133.         {
  1134.         if (netWrite (pNetFd, buf, nBytes) != nBytes)
  1135.             {
  1136.             NETDRV_DEBUG ("netGet:  error calling netWrite(). errno:0x%08xn", 
  1137.                           errno,1,2,3,4,5);
  1138.             status = ERROR;
  1139.             }
  1140.         }
  1141.     if (nBytes < 0)   /* recv error */
  1142.             status = ERROR;
  1143.     close (dataSock);
  1144.     if (pNetFd->pNetDev->protocol == PROTO_FTP)
  1145.         {
  1146.         if (ftpReplyGet (ctrlSock, FALSE) != FTP_COMPLETE)
  1147.             {
  1148.             NETDRV_DEBUG ("netGet:  error calling ftpReplyGet(). errno:0x%08xn", 
  1149.                           errno,1,2,3,4,5);
  1150.             status = ERROR;
  1151.             }
  1152.         }
  1153.     else
  1154.         {
  1155.         /* check control socket for error */
  1156.         if ((nBytes = fioRead (ctrlSock, buf, sizeof (buf) - 1)) > 0)
  1157.             {
  1158.             /* print error message on standard error fd */
  1159.             buf [nBytes] = EOS; /* insure string termination */
  1160.             /* check error message indicating cat of NFS mounted directory */
  1161.             if (strncmp (buf, errMsg, errMsgLen) != 0)
  1162.                 {
  1163.                 NETDRV_DEBUG ("netGet: %s:%s  . errno:0x%08xn",  
  1164.                                  pNetFd->pNetDev->host, buf, errno,1,2,3);
  1165.                 /* set the task's status according to the UNIX error */
  1166.                 getNetStatus (buf);
  1167.                 status = ERROR;
  1168.                 }
  1169.             }
  1170.     }
  1171.     if (pNetFd->pNetDev->protocol == PROTO_FTP &&
  1172.         ftpCommand (ctrlSock, "QUIT",0,0,0,0,0,0) != FTP_COMPLETE)
  1173.         {
  1174.         NETDRV_DEBUG ("netGet:  error calling ftpCommand("QUIT"). errno:0x%08xn", 
  1175.                       errno,1,2,3,4,5);
  1176.         status = ERROR;
  1177.         }
  1178.     close (ctrlSock);
  1179.     pNetFd->options = saveOptions; /* restore original options */
  1180.     return (status);
  1181.     }
  1182. /*******************************************************************************
  1183. *
  1184. * netPut - upload a file to a remote machine via the network.
  1185. *
  1186. * The remote shell daemon on the machine 'host' is used to upload
  1187. * from the open network file descriptor to a remote file.
  1188. * The remote userId should have been set previously be a call
  1189. * to iam().  If an error occurs, the UNIX error is output to the
  1190. * VxWorks standard error fd.
  1191. *
  1192. * RETURNS: OK or ERROR.
  1193. */
  1194. LOCAL STATUS netPut
  1195.     (
  1196.     FAST NET_FD *pNetFd
  1197.     )
  1198.     {
  1199.     int dataSock;
  1200.     int ctrlSock;
  1201.     char buf [DATASIZE]; /* make buf the same size as NET_FD's databuf */
  1202.     FAST int nBytes = -1;
  1203.     char command[MAX_FILENAME_LENGTH];
  1204.     char buffer[MAX_FILENAME_LENGTH];
  1205.     int saveOptions;
  1206.     STATUS status = OK;
  1207.     char usr [MAX_IDENTITY_LEN];
  1208.     char passwd [MAX_IDENTITY_LEN];
  1209.     remCurIdGet (usr, passwd);
  1210.     if (pNetFd->pNetDev->protocol == PROTO_FTP)
  1211.         {
  1212.         if (ftpXfer (pNetFd->pNetDev->host, usr, passwd, "",
  1213.                      "STOR %s", pNetFd->remDirName, pNetFd->remFileName,
  1214.                       &ctrlSock, &dataSock) == ERROR)
  1215.             {
  1216.             NETDRV_DEBUG ("netPut:  error calling ftpXfer()  errno:0x%08xn", 
  1217.                           errno,1,2,3,4,5);
  1218.             return (ERROR);
  1219.             }
  1220.         }
  1221.     else
  1222.         {
  1223.         if (pathCat (pNetFd->remDirName, pNetFd->remFileName, buffer) == ERROR)
  1224.             {
  1225.             NETDRV_DEBUG ("netPut:  error calling pathCat(). errno:0x%08xn", 
  1226.                           errno,1,2,3,4,5);
  1227.             return (ERROR);
  1228.             }
  1229.         sprintf (command, "/bin/cat > %s", buffer);
  1230.         dataSock = rcmd (pNetFd->pNetDev->host, RSHD, usr,
  1231.                          usr, command, &ctrlSock);
  1232.         if (dataSock == ERROR)
  1233.             {
  1234.             NETDRV_DEBUG ("netPut:  error calling rcmd(). errno:0x%08xn", 
  1235.                           errno,1,2,3,4,5);
  1236.             return (ERROR);
  1237.             }
  1238.         }
  1239.     /* Set file pointer to beginning of file */
  1240.     if (netSeek (pNetFd, 0) == ERROR)
  1241.         {
  1242.         if (pNetFd->pNetDev->protocol == PROTO_FTP &&
  1243.             ftpCommand (ctrlSock, "QUIT",0,0,0,0,0,0) != FTP_COMPLETE)
  1244.             {
  1245.             NETDRV_DEBUG ("netPut: error calling ftpCommand("QUIT").  errno:0x%08xn",
  1246.                           errno,1,2,3,4,5);
  1247.             status = ERROR;
  1248.             }
  1249.         close (dataSock);
  1250.         close (ctrlSock);
  1251.         return (ERROR);
  1252.         }
  1253.     /* set mode to write so that file can be written to,
  1254.      * save original options so they can be restored later
  1255.      */
  1256.         saveOptions = pNetFd->options;
  1257.         pNetFd->options = O_RDONLY & pNetFd->pNetDev->fdMode;
  1258.     /* Read the data from one DATABLOCK into buffer.
  1259.      *  Continue until file pointer reaches the end of file.
  1260.      */
  1261.     while (status == OK && (nBytes = netRead (pNetFd, buf, sizeof (buf))) > 0)
  1262.         {
  1263.         if (write (dataSock, buf, nBytes) != nBytes)
  1264.             {
  1265.             NETDRV_DEBUG ("netPut:  error calling write(). errno:0x%08xn", 
  1266.                           errno,1,2,3,4,5);
  1267.             status = ERROR;
  1268.             }
  1269.         }
  1270.     if (nBytes < 0) /* netRead error */
  1271.         {
  1272.         NETDRV_DEBUG ("netPut:  error calling netRead(). errno:0x%08xn", 
  1273.                       errno,1,2,3,4,5);
  1274.         status = ERROR;
  1275.         }
  1276.     if (close (dataSock) == ERROR)
  1277.         {
  1278.         NETDRV_DEBUG ("netPut:  error calling close(). errno:0x%08xn", errno,1,2,3,4,5);
  1279.         status = ERROR;
  1280.         }
  1281.     if (pNetFd->pNetDev->protocol == PROTO_FTP)
  1282.         {
  1283.         if (ftpReplyGet (ctrlSock, FALSE) != FTP_COMPLETE)
  1284.             {
  1285.             NETDRV_DEBUG ("netPut:  error calling ftpReplyGet(). errno:0x%08xn", 
  1286.                           errno,1,2,3,4,5);
  1287.             status = ERROR;
  1288.             }
  1289.         }
  1290.     else
  1291.         {
  1292.         /* check control socket for error */
  1293.         if ((nBytes = fioRead (ctrlSock, buf, sizeof (buf) - 1)) > 0)
  1294.             {
  1295.             /* print error message */
  1296.             buf [nBytes] = EOS; /* insure string termination */
  1297.             NETDRV_DEBUG ("netPut: %s:%s  . errno:0x%08xn",  
  1298.                           pNetFd->pNetDev->host, buf, errno,1,2,3);
  1299.             /* set the task's status according to the UNIX error */
  1300.             getNetStatus (buf);
  1301.             NETDRV_DEBUG ("netPut:  error calling fioRead(). errno:0x%08xn", 
  1302.                           errno,1,2,3,4,5);
  1303.             status = ERROR;
  1304.             }
  1305.         }
  1306.     if (pNetFd->pNetDev->protocol == PROTO_FTP &&
  1307.         ftpCommand (ctrlSock, "QUIT",0,0,0,0,0,0) != FTP_COMPLETE)
  1308.         {
  1309.         NETDRV_DEBUG ("netPut:  error calling ftpCommand(). errno:0x%08xn", 
  1310.                       errno,1,2,3,4,5);
  1311.         status = ERROR;
  1312.         }
  1313.     close (ctrlSock);
  1314.     pNetFd->options = saveOptions; /* restore original options */
  1315.     return (status);
  1316.     }
  1317. /****************************************************************************
  1318. *
  1319. * getNetStatus - set task status according to network error
  1320. *
  1321. * Compares string in buf with some known UNIX errors that can occur when
  1322. * copying files over the network.  Sets task status accordingly.
  1323. */
  1324. LOCAL void getNetStatus
  1325.     (
  1326.     char *buf           /* buffer containing string with UNIX error */
  1327.     )
  1328.     {
  1329.     FAST char *pErr;
  1330.     pErr = (char *) index (buf, ':');
  1331.     if (pErr == NULL)
  1332.         errno = S_netDrv_UNIX_FILE_ERROR;
  1333.     else if (strcmp (pErr, ": Permission deniedn") == 0)
  1334.         errno = S_netDrv_PERMISSION_DENIED;
  1335.     else if (strcmp (pErr, ": No such file or directoryn") == 0)
  1336.         errno = S_netDrv_NO_SUCH_FILE_OR_DIR;
  1337.     else if (strcmp (pErr, ": Is a directoryn") == 0)
  1338.         errno = S_netDrv_IS_A_DIRECTORY;
  1339.     else
  1340.         errno = S_netDrv_UNIX_FILE_ERROR;
  1341.     }
  1342. /*******************************************************************************
  1343. *
  1344. * netRead - read bytes from remote file
  1345. *
  1346. * netRead reads up to the specified number of bytes from the open network
  1347. * file descriptor and puts them into a buffer.  Bytes are read starting
  1348. * from the point marked by the file pointer.  The file pointer is then
  1349. * updated to point immediately after the last character that was read.
  1350. *
  1351. * Called only by the I/O system.
  1352. *
  1353. * SIDE EFFECTS: moves file pointer
  1354. *
  1355. * RETURNS: Number of bytes read, or ERROR.
  1356. */
  1357. LOCAL int netRead
  1358.     (
  1359.     FAST NET_FD *pNetFd,        /* pointer to open network file descriptor */
  1360.     char *buf,                  /* pointer to buffer to receive bytes   */
  1361.     FAST int maxBytes           /* max number of bytes to read into buffer */
  1362.     )
  1363.     {
  1364.     STATUS status = OK;
  1365.     FAST int byteCount = 0; /* number of bytes read so far */
  1366.     /* check for valid maxbytes */
  1367.     if (maxBytes <= 0)
  1368.         {
  1369.         errno = S_netDrv_INVALID_NUMBER_OF_BYTES;
  1370.         return (ERROR);
  1371.         }
  1372.     /* if file opened for O_WRONLY, don't read */
  1373.     if ((pNetFd->options & pNetFd->pNetDev->fdMode) == O_WRONLY)
  1374.         {
  1375.         errno = S_netDrv_WRITE_ONLY_CANNOT_READ;
  1376.         return (ERROR);
  1377.         }
  1378.     semTake (pNetFd->netFdSem, WAIT_FOREVER);
  1379.     if (pNetFd->pNetDev->bufSize == 0)
  1380.         {
  1381.         FAST DATABLOCK *dptr; /* points to current datablock */
  1382.         FAST int cindex; /* character index datablock's databuf */
  1383.         FAST char *cptr; /* points to character being read in the file */
  1384.         FAST char *bptr; /* points to current position in buffer */
  1385.         /* if file pointer is at end of file, can't read any characters */
  1386.         if (pNetFd->filePtrByte == pNetFd->endOfFile)
  1387.             {
  1388.             semGive (pNetFd->netFdSem);
  1389.             return (0);
  1390.             }
  1391.         cindex = pNetFd->filePtrByte % DATASIZE;   /* char index in datablock */
  1392.         dptr = pNetFd->filePtrBlock;
  1393.         cptr = &dptr->databuf [cindex]; /* point to current char in datablock */
  1394.         bptr = buf; /* point to beginning of read buffer */
  1395.         /* read until maxBytes characters have been read */
  1396.         while (byteCount < maxBytes)
  1397.             {
  1398.             if ((maxBytes - byteCount) < (dptr->used - cindex))
  1399.                 {
  1400.                 /* stop reading when maxBytes characters have been read.
  1401.                 *  This is the last block to read from in order to finish
  1402.                 *  filling up the buffer.
  1403.                 */
  1404.                 bcopy (cptr, bptr, maxBytes - byteCount);
  1405.                 byteCount = maxBytes;
  1406.                 }
  1407.             else
  1408.                 {
  1409.                 /* copy the rest of the datablock into buffer */
  1410.                 bcopy (cptr, bptr, dptr->used - cindex);
  1411.                 byteCount = byteCount + dptr->used - cindex;
  1412.                 if (dptr == (DATABLOCK *) lstLast (&pNetFd->dataLst))
  1413.                     {
  1414.                     /* this is the last block in the file. Seek to the end. */
  1415.                     status = netSeek (pNetFd, pNetFd->endOfFile);
  1416.                     semGive (pNetFd->netFdSem);
  1417.                     return (status == ERROR ? ERROR : byteCount);
  1418.                     }
  1419.                 else /* get next block */
  1420.                     {
  1421.                     dptr = (DATABLOCK *) lstNext ((NODE *) dptr);
  1422.                     cindex = 0;
  1423.                     cptr = dptr->databuf; /* point to 1st char in block */
  1424.                     bptr = buf + byteCount; /* move buffer pointer */
  1425.                     }
  1426.                 }
  1427.             }   /* end of while */
  1428.         status = netSeek (pNetFd, pNetFd->filePtrByte + byteCount);
  1429.         }
  1430.     else
  1431.         {
  1432.         FAST int nBytes = 0;
  1433.         FAST int bytes = 0;
  1434.         FAST int bufOffset = 0;
  1435.         /* if it is in the cache, read it from the cache */
  1436.         if (pNetFd->bufOffset < pNetFd->bufBytes)
  1437.             {
  1438.             if ((pNetFd->bufOffset + maxBytes) <= (pNetFd->bufBytes))
  1439.                 {
  1440.                 bcopy (pNetFd->buf + pNetFd->bufOffset, buf, maxBytes);
  1441.                 pNetFd->bufOffset   += maxBytes; /* move the cache pointer */
  1442.                 pNetFd->filePtrByte += maxBytes; /* move the file pointer */
  1443.                 pNetFd->status[0]++;  /* increment read[hit] */
  1444.                 semGive (pNetFd->netFdSem);
  1445.                 return (maxBytes);
  1446.                 }
  1447.             else
  1448.                 {
  1449.                 bytes = pNetFd->bufBytes - pNetFd->bufOffset;
  1450.                 bcopy (pNetFd->buf + pNetFd->bufOffset, buf, bytes);
  1451.                 pNetFd->bufOffset   += bytes; /* move the cache pointer */
  1452.                 pNetFd->filePtrByte += bytes; /* move the file pointer */
  1453.                 bufOffset = bytes; /* set the buf offset */
  1454.                 }
  1455.             }
  1456.         while ((nBytes = maxBytes - bufOffset) > 0)
  1457.             {
  1458.             /* read bytes from socket into the cache */
  1459.             pNetFd->status[1]++; /* increment read[mis] */
  1460.             byteCount = 0;
  1461.             while ((bytes = pNetFd->pNetDev->bufSize - byteCount) > 0)
  1462.                 {
  1463.                 bytes = read (pNetFd->dataSock, pNetFd->buf + byteCount, bytes);
  1464.                 if (bytes <= 0)
  1465.                     break;
  1466.                 else
  1467.                     byteCount += bytes;
  1468.                 }
  1469.             pNetFd->bufOffset = 0; /* set the cache pointer */
  1470.             pNetFd->bufBytes  = byteCount; /* set the cache size */
  1471.             /* read bytes from the cache */
  1472.             if (bytes < 0) /* recv error */
  1473.                 {
  1474.                 status = ERROR;
  1475.                 break;
  1476.                 }
  1477.             if (pNetFd->bufBytes == 0) /* the cache is empty, i.e. EOF */
  1478.                 break;
  1479.             else /* the cache is not empty */
  1480.                 {
  1481.                 bytes = (pNetFd->bufBytes < nBytes) ? pNetFd->bufBytes : nBytes;
  1482.                 bcopy (pNetFd->buf, buf + bufOffset, bytes);
  1483.                 pNetFd->bufOffset   += bytes; /* move the cache pointer */
  1484.                 pNetFd->filePtrByte += bytes; /* move the file pointer */
  1485.                 bufOffset           += bytes; /* move the buf offset */
  1486.                 }
  1487.             }
  1488.         byteCount = bufOffset; /* set the byte count */
  1489.         }
  1490.     semGive (pNetFd->netFdSem);
  1491.     return (status == ERROR ? ERROR : byteCount);
  1492.     }
  1493. /*******************************************************************************
  1494. *
  1495. * netWrite - write bytes to remote file
  1496. *
  1497. * netWrite copies up to the specified number of bytes from the buffer
  1498. * to the open network file descriptor.  Bytes are written starting
  1499. * at the spot pointed to by the file's block and byte pointers.
  1500. * The file pointer is updated to point immediately after the last
  1501. * character that was written.
  1502. *
  1503. * Called only by the I/O system.
  1504. *
  1505. * SIDE EFFECTS: moves file pointer
  1506. *
  1507. * RETURNS:
  1508. * Number of bytes written (error if != nbytes), or
  1509. * ERROR if nBytes < 0, or no more space can be allocated.
  1510. */
  1511. LOCAL int netWrite
  1512.     (
  1513.     FAST NET_FD *pNetFd,        /* open file descriptor */
  1514.     char *buf,                  /* buffer being written from */
  1515.     FAST int nBytes             /* number of bytes to write to file */
  1516.     )
  1517.     {
  1518.     STATUS status = OK;
  1519.     FAST int byteCount = 0; /* number of written read so far */
  1520.     /* check for valid number of bytes */
  1521.     if (nBytes < 0)
  1522.         {
  1523.         errno = S_netDrv_INVALID_NUMBER_OF_BYTES;
  1524.         return (ERROR);
  1525.         }
  1526.     /* if file opened for O_RDONLY, don't write */
  1527.     if ((pNetFd->options & pNetFd->pNetDev->fdMode) == O_RDONLY)
  1528.         {
  1529.         errno = S_netDrv_READ_ONLY_CANNOT_WRITE;
  1530.         return (ERROR);
  1531.         }
  1532.     semTake (pNetFd->netFdSem, WAIT_FOREVER);
  1533.     if (pNetFd->pNetDev->bufSize == 0)
  1534.         {
  1535.         FAST DATABLOCK *dptr; /* points to current datablock */
  1536.         FAST int cindex; /* character index datablock's databuf */
  1537.         FAST char *cptr; /* points to char being overwritten in file */
  1538.         FAST char *bptr; /* points to current position in buffer */
  1539.         cindex = pNetFd->filePtrByte % DATASIZE;
  1540.         dptr   = pNetFd->filePtrBlock;
  1541.         cptr   = &dptr->databuf [cindex];
  1542.         bptr   = buf;
  1543.         while (byteCount < nBytes)
  1544.             {
  1545.             if ((nBytes - byteCount) < (DATASIZE - cindex))
  1546.                 {
  1547.                 /* almost done writing nBytes. This is the last block */
  1548.                 bcopy (bptr, cptr, nBytes - byteCount);
  1549.                 byteCount = nBytes;
  1550.                 /* if we wrote past end of file, adjust end of file pointer */
  1551.             if ((pNetFd->filePtrByte + byteCount > pNetFd->endOfFile) &&
  1552.                 moveEndOfFile (pNetFd, pNetFd->filePtrByte + byteCount)
  1553.                 == ERROR)
  1554.                 {
  1555.                 semGive (pNetFd->netFdSem);
  1556.                 return (ERROR);
  1557.                 }
  1558.            }
  1559.            else /* not last block to write to */
  1560.                {
  1561.                bcopy (bptr, cptr, DATASIZE - cindex);
  1562.                byteCount = byteCount + DATASIZE - cindex;
  1563.                 /* if we wrote past end of file, adjust end of file pointer.
  1564.                 *  If necessary, moveEndOfFile will attach a new datablock
  1565.                 *  to the end of the data chain.
  1566.                 */
  1567.                 if ((pNetFd->filePtrByte + byteCount > pNetFd->endOfFile) &&
  1568.                     moveEndOfFile (pNetFd, pNetFd->filePtrByte + byteCount)
  1569.                     == ERROR)
  1570.                     {
  1571.                     semGive (pNetFd->netFdSem);
  1572.                     return (ERROR);
  1573.                     }
  1574.                 /* point to first character in next datablock */
  1575.                 dptr   = (DATABLOCK *) lstNext ((NODE *) dptr);
  1576.                 cindex = 0;
  1577.                 cptr   = dptr->databuf;
  1578.                 /* adjust buffer pointer */
  1579.                 bptr = buf + byteCount;
  1580.                 }
  1581.             } /* end of while loop */
  1582.         pNetFd->options |= FD_DIRTY;
  1583.         status = netSeek (pNetFd, pNetFd->filePtrByte + byteCount);
  1584.         }
  1585.     else
  1586.         {
  1587.         /* write the data to socket */
  1588.         if ((byteCount = write (pNetFd->dataSock, buf, nBytes)) != nBytes)
  1589.             status = ERROR;
  1590.         pNetFd->filePtrByte += byteCount;
  1591.         }
  1592.     semGive (pNetFd->netFdSem);
  1593.     return (status == ERROR ? ERROR : byteCount);
  1594.     }
  1595. /*******************************************************************************
  1596. *
  1597. * netIoctl - do device specific control function
  1598. *
  1599. * Called only by the I/O system.
  1600. *
  1601. * RETURNS: Whatever the called function returns.
  1602. */
  1603. LOCAL int netIoctl
  1604.     (
  1605.     FAST NET_FD *pNetFd,        /* open network file descriptor */
  1606.     FAST int function,          /* function code */
  1607.     FAST int arg                /* argument for function */
  1608.     )
  1609.     {
  1610.     struct stat *pStat;         /* pointer to struct for stat() call */
  1611.     switch (function)
  1612. {
  1613. case FIOSEEK:
  1614.     if (pNetFd->pNetDev->bufSize == 0)
  1615.                 return (netSeek (pNetFd, arg));
  1616.     {
  1617.     int status = OK;
  1618.             FAST int bytes = 0;
  1619.             FAST int byteCount = 0;
  1620.     if ((arg < 0) ||
  1621. (pNetFd->options & O_WRONLY)) /* no seek in WR_ONLY mode */
  1622. {
  1623. errno = S_netDrv_BAD_SEEK;
  1624. return (ERROR);
  1625. }
  1626.     if (pNetFd->filePtrByte == arg)
  1627.         return (OK);
  1628.     /* forward seek */
  1629.     if (pNetFd->filePtrByte < arg)
  1630. {
  1631.         if ((arg - pNetFd->filePtrByte) <
  1632.     (pNetFd->bufBytes - pNetFd->bufOffset))
  1633.     {
  1634.             /* forward seek in the cache. move the file pointer */
  1635.     pNetFd->status[2]++; /* increment fseek[hit] */
  1636.     pNetFd->bufOffset  += (arg - pNetFd->filePtrByte);
  1637.             pNetFd->filePtrByte = arg;
  1638.     return (OK);
  1639.     }
  1640.         else
  1641.     {
  1642.             /* forward seek beyond the cache. read the file */
  1643.     pNetFd->status[3]++; /* increment fseek[mis] */
  1644.                     byteCount = pNetFd->filePtrByte +
  1645.         (pNetFd->bufBytes - pNetFd->bufOffset);
  1646.     }
  1647. }
  1648.     /* backward seek */
  1649.     if (pNetFd->filePtrByte > arg)
  1650. {
  1651.         if ((pNetFd->filePtrByte - arg) < pNetFd->bufOffset)
  1652.     {
  1653.             /* backward seek in the cache. move the file pointer */
  1654.     pNetFd->status[4]++; /* increment bseek[hit] */
  1655.     pNetFd->bufOffset  -= (pNetFd->filePtrByte - arg);
  1656.             pNetFd->filePtrByte = arg;
  1657.     return (OK);
  1658.     }
  1659.         else
  1660.     {
  1661.             /* backward seek beyond the cache. re-open the file */
  1662.                  if ((netSockClose (pNetFd) == ERROR) || /* close it */
  1663.                      (netSockOpen (pNetFd) == ERROR)) /* reopen it */
  1664.     return (ERROR);
  1665.     pNetFd->status[5]++; /* increment bseek[mis] */
  1666.     byteCount = 0;
  1667.     }
  1668. }
  1669.             /* read until it reaches the new file pointer */
  1670.             while ((bytes = arg - byteCount) > 0)
  1671.         {
  1672.         bytes = (bytes > pNetFd->pNetDev->bufSize) ?
  1673. pNetFd->pNetDev->bufSize : bytes;
  1674.                 bytes = read (pNetFd->dataSock, pNetFd->buf, bytes);
  1675.         if (bytes <= 0)
  1676.     {
  1677.     pNetFd->filePtrByte = byteCount;
  1678.     return (ERROR);
  1679.             break;
  1680.     }
  1681.         else
  1682.             byteCount += bytes;
  1683.         }
  1684.     /* set the file pointer and flush the cache */
  1685.     pNetFd->filePtrByte = arg;
  1686.     pNetFd->bufOffset = 0;
  1687.     pNetFd->bufBytes  = 0;
  1688.     return (status);
  1689.     }
  1690. case FIOWHERE:
  1691.          return (pNetFd->filePtrByte);
  1692. case FIONREAD:
  1693.     if (pNetFd->pNetDev->bufSize > 0)
  1694. return (ERROR);
  1695.     else
  1696. {
  1697.              *((int *) arg) = pNetFd->endOfFile - pNetFd->filePtrByte;
  1698.         return (OK);
  1699.         }
  1700. case FIODIRENTRY:
  1701.     /* this is a kludge for 'ls'.  Do the listing, then return
  1702.        ERROR so that 'ls' doesn't try listing an rt-11 device */
  1703.     netLs (pNetFd);
  1704.     return (ERROR);
  1705. case FIOGETFL:
  1706.     *((int *) arg) = pNetFd->options & pNetFd->pNetDev->fdMode;
  1707.     return (OK);
  1708.         case FIOFSTATGET:
  1709.             /* get status of a file */
  1710.             pStat = (struct stat *) arg;
  1711.             /* get file attributes returned in pStat */
  1712.             /* zero out the pStat structure */
  1713.             bzero ((char *) pStat, sizeof (*pStat));
  1714.             /* fill in the elements of the stat struct that we have */
  1715.             pStat->st_dev = (ULONG) pNetFd->pNetDev;
  1716.             pStat->st_mode = S_IFREG;
  1717.             pStat->st_size = pNetFd->endOfFile;
  1718.             return (OK);
  1719.             break;
  1720. default:
  1721.     errno = S_netDrv_UNKNOWN_REQUEST;
  1722.     return (ERROR);
  1723. }
  1724.     }
  1725. /*******************************************************************************
  1726. *
  1727. * netSeek - change file's current character position
  1728. *
  1729. * This routine moves the file pointer by the offset to a new
  1730. * position.  If the new position is past the end of file, fill the
  1731. * unused space with 0's.  The end of file pointer gets moved to the
  1732. * position immediately following the last '0' written.
  1733. * If the resulting file pointer would be negative, ERROR is returned.
  1734. *
  1735. * Called only by the I/O system.
  1736. *
  1737. * INTERNAL
  1738. * There is deliberate co-recursion between netSeek and netWrite.
  1739. *
  1740. * RETURNS: OK or ERROR.
  1741. */
  1742. LOCAL int netSeek
  1743.     (
  1744.     FAST NET_FD *pNetFd,
  1745.     FAST int newPos
  1746.     )
  1747.     {
  1748.     FAST DATABLOCK *saveFilePtrBlock;
  1749.     FAST int saveFilePtrByte;
  1750.     int endOfFile;
  1751.     int newBlock;
  1752.     int curBlock;
  1753.     char *buf;
  1754.     DATABLOCK *dptr;
  1755.     int nbytes;
  1756.     if (newPos < 0)
  1757.         {
  1758.         errno = S_netDrv_BAD_SEEK;
  1759.         return (ERROR);
  1760.         }
  1761.     saveFilePtrBlock = pNetFd->filePtrBlock;
  1762.     saveFilePtrByte  = pNetFd->filePtrByte;
  1763.     endOfFile        = pNetFd->endOfFile;
  1764.     newBlock         = newPos / DATASIZE;
  1765.     curBlock         = pNetFd->filePtrByte / DATASIZE;
  1766.     /* if new position is past end of file */
  1767.     if (newPos > endOfFile)
  1768. {
  1769. /* put 0's at the end of the file */
  1770. if ((buf = (char *) KHEAP_ALLOC ((unsigned) (newPos - endOfFile))) == NULL)
  1771.     {
  1772.     return (ERROR);
  1773.     }
  1774. bzero (buf, newPos - endOfFile);
  1775. /* move file pointer to end of file before writing 0's */
  1776. pNetFd->filePtrBlock = (DATABLOCK *) lstLast (&pNetFd->dataLst);
  1777. pNetFd->filePtrByte = endOfFile;
  1778. /* netWrite will update the file pointer and end of file pointer */
  1779. nbytes = netWrite (pNetFd, buf, (newPos - endOfFile));
  1780. if (nbytes != (newPos - endOfFile))
  1781.     {
  1782.     if (nbytes != ERROR)
  1783.      errno = S_netDrv_SEEK_PAST_EOF_ERROR;
  1784.     pNetFd->filePtrBlock = saveFilePtrBlock;
  1785.     pNetFd->filePtrByte = saveFilePtrByte;
  1786.     KHEAP_FREE (buf);
  1787.     return (ERROR);
  1788.     }
  1789. KHEAP_FREE (buf);
  1790. }
  1791.     else /* else, new position is within current file size */
  1792. {
  1793.      /* point to new block */
  1794. /* system error if we go out of range of the datablocks */
  1795. dptr = (DATABLOCK *) lstNStep ((NODE *) pNetFd->filePtrBlock,
  1796.        newBlock - curBlock);
  1797. if (dptr == NULL)
  1798.     {
  1799.     errno = S_netDrv_SEEK_FATAL_ERROR;
  1800.     return (ERROR);
  1801.     }
  1802. pNetFd->filePtrBlock = dptr;
  1803. /* point to new byte */
  1804.      pNetFd->filePtrByte = newPos;
  1805. }
  1806.     return (OK);
  1807.     }
  1808. /*******************************************************************************
  1809. *
  1810. * moveEndOfFile - moves end of file pointer to new position
  1811. *
  1812. * Adds a new datablock to the end of the datablock list if necessary.
  1813. * Assumes that end of file moves at most to the first position of
  1814. * the next datablock.
  1815. *
  1816. * RETURNS: OK or ERROR.
  1817. */
  1818. LOCAL STATUS moveEndOfFile
  1819.     (
  1820.     FAST NET_FD *pNetFd,
  1821.     FAST int newPos
  1822.     )
  1823.     {
  1824.     FAST DATABLOCK *dptr; /* pointer to new datablock */
  1825.     /*
  1826.     *  As soon as system error handling is implemented, a message should
  1827.     *  be put here.
  1828.     *
  1829.     *  If the new position is before the current end of file,
  1830.     *  OR more than one datablock ahead,
  1831.     *  OR further away than the first byte of the next datablock,
  1832.     *  this is a system error ....looks awful, I know
  1833.     */
  1834.     if ((newPos <= pNetFd->endOfFile) ||
  1835. ((newPos - pNetFd->endOfFile) > DATASIZE) ||
  1836. ((newPos % DATASIZE < pNetFd->endOfFile % DATASIZE) &&
  1837. (newPos % DATASIZE != 0)))
  1838. {
  1839. errno = S_netDrv_BAD_EOF_POSITION;
  1840. return (ERROR);
  1841. }
  1842.     /* if new position is in datablock after end of file,
  1843.     *  add another datablock to the file
  1844.     */
  1845.     if ((newPos / DATASIZE) > (pNetFd->endOfFile / DATASIZE))
  1846. {
  1847. /* current datablock is full.
  1848. *  New position is in the block after the current
  1849. *  end of file.
  1850. */
  1851. ((DATABLOCK *) lstLast (&pNetFd->dataLst))->used = DATASIZE;
  1852. if ((dptr = (DATABLOCK *) KHEAP_ALLOC (sizeof (DATABLOCK))) == NULL)
  1853.     return (ERROR);
  1854.      dptr->used = 0;
  1855. lstAdd (&pNetFd->dataLst, (NODE *) dptr);
  1856. }
  1857.     else
  1858. ((DATABLOCK *) lstLast (&pNetFd->dataLst))->used = newPos % DATASIZE;
  1859.     pNetFd->endOfFile = newPos;
  1860.     return (OK);
  1861.     }
  1862. /*******************************************************************************
  1863. *
  1864. * netFdCreate - create a network file descriptor
  1865. *
  1866. * Returns an open network file descriptor.
  1867. * Files are created with O_WRONLY or O_RDWR modes.
  1868. * A O_RDONLY mode defaults to O_RDWR.
  1869. *
  1870. * RETURNS: Pointer to open network file descriptor or ERROR.
  1871. */
  1872. LOCAL int netFdCreate
  1873.     (
  1874.     NET_DEV *pNetDev,
  1875.     char *name,         /* remote file name */
  1876.     int mode            /* ignored, always set to O_WRONLY */
  1877.     )
  1878.     {
  1879.     FAST NET_FD *pNetFd;
  1880.     DATABLOCK *pData;
  1881.     char *pFileName;
  1882.     FAST int fileNameLen;
  1883.     FAST int dirNameLen;
  1884.     char *ptr;
  1885.     /* don't allow null filenames */
  1886.     if (name[0] == EOS)
  1887. {
  1888. errno = S_ioLib_NO_FILENAME;
  1889. return (ERROR);
  1890. }
  1891.     /* get directory and filename pointers and lengths */
  1892.     pFileName   = pathLastNamePtr (name);
  1893.     fileNameLen = strlen (pFileName);
  1894.     dirNameLen  = pFileName - name;
  1895.     /* Some machines don't like to have a directory name terminated by "/" or
  1896.      * "", unless is the root directory.  This code clips the extra slash.
  1897.      */
  1898.     if ((dirNameLen > 1) &&
  1899. (name[dirNameLen-1] == '/' || name[dirNameLen-1] == '\'))
  1900. dirNameLen--;
  1901.     /* allocate and initialize net file descriptor;
  1902.      * leave room for directory and file name and both EOSs
  1903.      *
  1904.      * Make sure the file descriptor structure is allocated from the Kernel
  1905.      * heap since this structure includes a Mutex which is a Wind object and
  1906.      * as for all Wind object should be allocated from an location visible
  1907.      * by Kernel tasks.
  1908.      */
  1909.     if ((ptr = (char *) KHEAP_ALLOC ((unsigned) (sizeof (NET_FD) + fileNameLen +
  1910.    dirNameLen + 2))) == NULL)
  1911. return (ERROR);
  1912.     pNetFd = (NET_FD *) ptr;
  1913.     pNetFd->pNetDev      = pNetDev;
  1914.     pNetFd->filePtrByte  = 0;
  1915.     pNetFd->endOfFile    = 0; /* XXX should be determined when O_RDWR! */
  1916.     pNetFd->options      = pNetFd->pNetDev->fdMode & ((mode == O_WRONLY) ? O_WRONLY : O_RDWR);
  1917.     pNetFd->options     |= FD_DIRTY; /* set dirty */
  1918.     /* set remote directory name and file name */
  1919.     pNetFd->remFileName = ptr + sizeof (NET_FD);
  1920.     (void) strcpy (pNetFd->remFileName, pFileName);
  1921.     pNetFd->remDirName = pNetFd->remFileName + fileNameLen + 1;
  1922.     (void) strncpy (pNetFd->remDirName, name, dirNameLen);
  1923.     pNetFd->remDirName [dirNameLen] = EOS;
  1924.     /* attach first empty datablock */
  1925.     pData = (DATABLOCK *) KHEAP_ALLOC(sizeof (DATABLOCK));
  1926.     pData->used = 0;
  1927.     pNetFd->filePtrBlock = pData;
  1928.     lstInit (&pNetFd->dataLst);
  1929.     lstAdd (&pNetFd->dataLst, (NODE *) pData);
  1930.     bzero ((char *)pNetFd->status, sizeof (pNetFd->status));
  1931.     if ((pNetFd->pNetDev->bufSize > 0) &&
  1932. ((pNetFd->buf = KHEAP_ALLOC(pNetFd->pNetDev->bufSize)) == NULL))
  1933. return (ERROR);
  1934.     pNetFd->netFdSem = semMCreate (mutexOptionsNetDrv);
  1935.     return ((int) pNetFd);
  1936.     }
  1937. /*******************************************************************************
  1938. *
  1939. * netFdRelease - free up NetFd
  1940. */
  1941. LOCAL void netFdRelease
  1942.     (
  1943.     FAST NET_FD *pNetFd
  1944.     )
  1945.     {
  1946. #ifdef _WRS_VXWORKS_5_X
  1947.     lstFree (&pNetFd->dataLst); /* free up data list */
  1948. #else
  1949.     lstInternalFree (&pNetFd->dataLst, kHeapFree); /* free up data list */
  1950. #endif /* _WRS_VXWORKS_5_X */
  1951.     
  1952.     if (pNetFd->pNetDev->bufSize > 0) /* free the read buffer */
  1953. KHEAP_FREE(pNetFd->buf);
  1954.     semDelete (pNetFd->netFdSem); /* terminate netFdSem */
  1955.     KHEAP_FREE ((char *) pNetFd); /* deallocate network fd */
  1956.     }
  1957. /*******************************************************************************
  1958. *
  1959. * netSockOpen - open the socket connection
  1960. */
  1961. LOCAL STATUS netSockOpen
  1962.     (
  1963.     NET_FD *pNetFd
  1964.     )
  1965.     {
  1966.     char command[MAX_FILENAME_LENGTH];
  1967.     char buffer [MAX_FILENAME_LENGTH];
  1968.     char usr [MAX_IDENTITY_LEN];
  1969.     char passwd [MAX_IDENTITY_LEN];
  1970.     char * p;
  1971.     /* open the remote file */
  1972.     remCurIdGet (usr, passwd);
  1973.     if (pNetFd->pNetDev->protocol == PROTO_FTP)
  1974. {
  1975. p = ((pNetFd->options & pNetFd->pNetDev->fdMode) == O_RDONLY) ?
  1976.     "RETR %s" : "STOR %s";
  1977. if (ftpXfer (pNetFd->pNetDev->host, usr, passwd, "",
  1978.      p, pNetFd->remDirName, pNetFd->remFileName,
  1979.      &pNetFd->ctrlSock, &pNetFd->dataSock) == ERROR)
  1980.     {
  1981.     NETDRV_DEBUG ("netSockOpen:  error calling ftpXfer()  errno:0x%08xn", errno,1,2,3,4,5);
  1982.     return (ERROR);
  1983.     }
  1984. }
  1985.     else
  1986. {
  1987. if (pathCat (pNetFd->remDirName, pNetFd->remFileName, buffer) == ERROR)
  1988.     return (ERROR);
  1989. if ((pNetFd->options & pNetFd->pNetDev->fdMode) == O_RDONLY) 
  1990. sprintf (command, "/bin/cat < %s", buffer);
  1991. else
  1992. sprintf (command, "/bin/cat > %s", buffer);
  1993. pNetFd->dataSock = rcmd (pNetFd->pNetDev->host, RSHD, usr,
  1994.     usr, command, &pNetFd->ctrlSock);
  1995. if (pNetFd->dataSock == ERROR)
  1996.     return (ERROR);
  1997. }
  1998.     return (OK);
  1999.     }
  2000. /*******************************************************************************
  2001. *
  2002. * netSockClose - close the socket connection
  2003. */
  2004. LOCAL STATUS netSockClose
  2005.     (
  2006.     NET_FD *pNetFd
  2007.     )
  2008.     {
  2009.     int status = OK;
  2010.     int nBytes;
  2011.     char errBuf [DATASIZE];
  2012.     char *errMsg0 = "cat: read error: Is a directory";
  2013.     char *errMsg1 = "cat: write error: Broken pipe";
  2014.     int errMsgLen0 = strlen (errMsg0);
  2015.     int errMsgLen1 = strlen (errMsg1);
  2016.     /* complete the FTP transfer before closing the dataSock */
  2017.     if ((pNetFd->pNetDev->bufSize > 0) &&
  2018.         (pNetFd->pNetDev->protocol == PROTO_FTP))
  2019.            {
  2020.            char buf [1024];
  2021.            while ((nBytes = read (pNetFd->dataSock, buf, sizeof (buf))) > 0)
  2022.             ;
  2023.            }
  2024.     status = close (pNetFd->dataSock);
  2025.     
  2026.     if (status == ERROR )
  2027.         {
  2028.         NETDRV_DEBUG ("netSockClose: error closing fd:%d errno=0x%08xn", pNetFd->dataSock, errno,3,4,5,6);
  2029.         }
  2030.     if (pNetFd->pNetDev->protocol == PROTO_FTP)
  2031.         {
  2032.         status = ftpReplyGet (pNetFd->ctrlSock, FALSE);
  2033.         /* Check for specific status types */
  2034.         if (status != FTP_COMPLETE)
  2035.             {
  2036.             NETDRV_DEBUG ("netSockClose: error during ftpReplyGet ctrlSock:%d errno=0x%08x return value:%dn",
  2037.                             pNetFd->ctrlSock, errno,status,4,5,6);
  2038.             status = ERROR;
  2039.             }
  2040.         }
  2041.     else
  2042.         {
  2043.         /* check control socket for error */
  2044.         if ((nBytes = fioRead (pNetFd->ctrlSock, errBuf, sizeof (errBuf) - 1))
  2045.             > 0)
  2046.             {
  2047.             /* print error message on standard error fd */
  2048.             errBuf [nBytes] = EOS; /* insure string termination */
  2049.             /* check error message indicating cat of NFS mounted directory */
  2050.             if ((((pNetFd->options & pNetFd->pNetDev->fdMode) == O_RDONLY) &&
  2051.                  (strncmp (errBuf, errMsg0, errMsgLen0) != 0) &&
  2052.                  (strncmp (errBuf, errMsg1, errMsgLen1) != 0)) ||
  2053.                 ((pNetFd->options & pNetFd->pNetDev->fdMode) == O_WRONLY))
  2054.                 {
  2055.                 NETDRV_DEBUG ("netSockClose: %s:%s   errno:0x%08xn",  
  2056.                 pNetFd->pNetDev->host, errBuf, errno,1,2,3);
  2057.                 /* set the task's status according to the UNIX error */
  2058.                 getNetStatus (errBuf);
  2059.                 status = ERROR;
  2060.                 }
  2061.             }
  2062.         else
  2063.             {
  2064.             NETDRV_DEBUG ("netSockClose: error during fioread ctrlSock:%d errno=0x%08x return value:%dn", 
  2065.             pNetFd->ctrlSock, errno,status,4,5,6);
  2066.             }
  2067.         }
  2068.     if (pNetFd->pNetDev->protocol == PROTO_FTP &&
  2069.         ftpCommand (pNetFd->ctrlSock, "QUIT",0,0,0,0,0,0) != FTP_COMPLETE)
  2070.         {
  2071.         NETDRV_DEBUG ("netSockClose: error during ftpCommand (QUIT) ctrlSock:%d errno=0x%08x return value:%dn", 
  2072.         pNetFd->ctrlSock, errno,status,4,5,6);
  2073.         status = ERROR;
  2074.         }
  2075.         status = close (pNetFd->ctrlSock);
  2076.         if (status == ERROR )
  2077.             {
  2078.             NETDRV_DEBUG ("netSockClose: error closing ctrl sock fd:%d errno=0x%08xn", 
  2079.             pNetFd->ctrlSock, errno,3,4,5,6);
  2080.             }
  2081.         return (status);
  2082.     }
  2083. /*******************************************************************************
  2084. *
  2085. * netDrvDebugLevelSet - set the debug level of the netDrv library routines
  2086. *
  2087. * This routine enables the debugging of calls to the net driver.  The argument
  2088. * NETLIB_DEBUG_ERRORS will display only error messages to the console.  The 
  2089. * argument NETLIB_DEBUG_ALL will display warnings and errors to the console.
  2090. *
  2091. * RETURNS : OK, or ERROR if the debug level is invalid
  2092. */
  2093. STATUS netDrvDebugLevelSet
  2094.     (
  2095.     UINT32 debugLevel /* NETDRV_DEBUG_OFF, NETDRV_DEBUG_ERRORS, NETDRV_DEBUG_ALL */
  2096.     )
  2097.     {
  2098.     switch (debugLevel)
  2099.         {
  2100.         case (NETLIB_DEBUG_OFF):    /* No debugging messages */ 
  2101.             netDrvDebugErrors = debugLevel;
  2102.             return (OK);
  2103.             break;
  2104.         case (NETLIB_DEBUG_ERRORS): /* Display all errors and warnings  */
  2105.             netDrvDebugErrors = debugLevel;
  2106.             return (OK);
  2107.             break;
  2108.         case (NETLIB_DEBUG_ALL):    /* Display all errors, warning and statistics */
  2109.             netDrvDebugErrors = debugLevel;
  2110.             netDrvDebugStats = 1;
  2111.             return (OK);
  2112.             break;
  2113.         default:
  2114.             errno = S_netDrv_ILLEGAL_VALUE;
  2115.             return (ERROR);
  2116.         }
  2117.     }
  2118. /*******************************************************************************
  2119. *
  2120. * netDrvFileDoesNotExist - Applette to test if a file does not exist
  2121. *
  2122. * This routine is used to parse the text of a remote FTP server stating a file does
  2123. *    not exist.   This routine is only used during an open() with the O_CREAT
  2124. *    option specified.  An 'NLST' command is issued and the response is compared
  2125. *    against various text strings.
  2126. *
  2127. * RETURNS : OK if the file does not exist, or ERROR if the file exists
  2128. *
  2129. * NOMANUAL
  2130. */
  2131. STATUS netDrvFileDoesNotExist 
  2132.     (
  2133.     char *filename,
  2134.     char *response
  2135.     )
  2136.     {
  2137. /* XXX this function needs to move to usrNetDrv.c after veloce freeze */
  2138. #define SUNOS_ERRMSG "not found"
  2139. #define SOLARIS_ERRMSG " No such file"
  2140.     /* SunOs 1.x */
  2141.     if (strncmp (response + strlen (filename) + 1, 
  2142.         SUNOS_ERRMSG, 
  2143.         strlen (SUNOS_ERRMSG)
  2144.         ) == 0)
  2145.         {
  2146.         NETDRV_DEBUG ("fileDoesNotExist:matches SunOs 1.xn", errno,1,2,3,4,5);
  2147.         return (OK);
  2148.         }
  2149.     /* Solaris (SunOs 5.7) */
  2150.     if (strncmp (response + strlen (filename) + 1, 
  2151.         SOLARIS_ERRMSG, 
  2152.         strlen (SOLARIS_ERRMSG)
  2153.         ) == 0)
  2154.         {
  2155.         NETDRV_DEBUG ("fileDoesNotExist:matches Solarisn", errno,1,2,3,4,5);
  2156.         return (OK);
  2157.         }
  2158.         NETDRV_DEBUG ("fileDoesNotExist:NO MATCH - file must existn", errno,1,2,3,4,5);
  2159.         return ERROR;
  2160.     }
  2161. /*******************************************************************************
  2162. *
  2163. * netDrvFileDoesNotExistInstall - install an applette to test if the file exists
  2164. *
  2165. * Install a function which will test if a given file exists.
  2166. *
  2167. * The <pAppletteRtn> argument provides a routine using the following interface:
  2168. * cs
  2169. * STATUS appletteRoutine
  2170. *     (
  2171. *     char *filename, /@ file name queried @/
  2172. *     char *response  /@ server response string @/
  2173. *     )
  2174. * ce
  2175. * The netDrv routine calls the applette routine during an open with O_CREAT
  2176. * specified. The system will perform an NLST command and then use the applette 
  2177. * routine to parse the response.  The routine compensates for server response
  2178. * implementaion variations.   The applette should return 'OK' if the file is 
  2179. * not found and 'ERROR'  if the file is found.
  2180. *
  2181. * RETURNS : OK, installation successful; ERROR, installation error.
  2182. *
  2183. * SEE ALSO : open()
  2184. *
  2185. */
  2186. STATUS netDrvFileDoesNotExistInstall  
  2187.     (
  2188.     FUNCPTR pAppletteRtn /* Function that returns TRUE or FALSE */
  2189.     )
  2190.     {
  2191.     /* At least prevent this from being a disaster */
  2192.     if (pAppletteRtn == NULL)
  2193.         return (ERROR); 
  2194.     _func_fileDoesNotExist    = pAppletteRtn;
  2195.     return (OK); 
  2196.     }