FCBFNS.C
上传用户:dcs7469208
上传日期:2010-01-02
资源大小:443k
文件大小:33k
源码类别:

操作系统开发

开发平台:

DOS

  1. /****************************************************************/
  2. /*                                                              */
  3. /*                          fcbfns.c                            */
  4. /*                                                              */
  5. /*           Old CP/M Style Function Handlers for Kernel        */
  6. /*                                                              */
  7. /*                      Copyright (c) 1995                      */
  8. /*                      Pasquale J. Villani                     */
  9. /*                      All Rights Reserved                     */
  10. /*                                                              */
  11. /* This file is part of DOS-C.                                  */
  12. /*                                                              */
  13. /* DOS-C is free software; you can redistribute it and/or       */
  14. /* modify it under the terms of the GNU General Public License  */
  15. /* as published by the Free Software Foundation; either version */
  16. /* 2, or (at your option) any later version.                    */
  17. /*                                                              */
  18. /* DOS-C is distributed in the hope that it will be useful, but */
  19. /* WITHOUT ANY WARRANTY; without even the implied warranty of   */
  20. /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See    */
  21. /* the GNU General Public License for more details.             */
  22. /*                                                              */
  23. /* You should have received a copy of the GNU General Public    */
  24. /* License along with DOS-C; see the file COPYING.  If not,     */
  25. /* write to the Free Software Foundation, 675 Mass Ave,         */
  26. /* Cambridge, MA 02139, USA.                                    */
  27. /****************************************************************/
  28. #include "../../hdr/portab.h"
  29. #include "globals.h"
  30. /* $Logfile:   C:/dos-c/src/fs/fcbfns.c_v  $ */
  31. #ifdef VERSION_STRINGS
  32. static BYTE *RcsId = "$Header:   C:/dos-c/src/fs/fcbfns.c_v   1.6   04 Jan 1998 23:14:38   patv  $";
  33. #endif
  34. /* $Log:   C:/dos-c/src/fs/fcbfns.c_v  $
  35.  * 
  36.  *    Rev 1.6   04 Jan 1998 23:14:38   patv
  37.  * Changed Log for strip utility
  38.  * 
  39.  *    Rev 1.5   03 Jan 1998  8:36:02   patv
  40.  * Converted data area to SDA format
  41.  * 
  42.  *    Rev 1.4   16 Jan 1997 12:46:38   patv
  43.  * pre-Release 0.92 feature additions
  44.  * 
  45.  *    Rev 1.3   29 May 1996 21:15:14   patv
  46.  * bug fixes for v0.91a
  47.  * 
  48.  *    Rev 1.2   01 Sep 1995 17:48:44   patv
  49.  * First GPL release.
  50.  * 
  51.  *    Rev 1.1   30 Jul 1995 20:50:26   patv
  52.  * Eliminated version strings in ipl
  53.  * 
  54.  *    Rev 1.0   02 Jul 1995  8:06:06   patv
  55.  * Initial revision.
  56.  */
  57. /* $EndLog$ */
  58. #define FCB_SUCCESS     0
  59. #define FCB_ERR_NODATA  1
  60. #define FCB_ERR_EOF     3
  61. #define FCB_ERR_WRITE   1
  62. #define D_ALL   D_NORMAL | D_RDONLY | D_HIDDEN | D_SYSTEM | D_DIR | D_ARCHIVE
  63. #ifdef PROTO
  64. fcb FAR *ExtFcbToFcb(xfcb FAR *lpExtFcb);
  65. fcb FAR *CommonFcbInit(xfcb FAR *lpExtFcb, BYTE *pszBuffer, COUNT *pCurDrive);
  66. void FcbNameInit(fcb FAR *lpFcb, BYTE *pszBuffer, COUNT *pCurDrive);
  67. sft FAR *FcbGetSft(COUNT SftIndex);
  68. VOID FcbNextRecord(fcb FAR *lpFcb);
  69. sft FAR *FcbGetFreeSft(WORD FAR *sft_idx);
  70. BOOL FcbFnameMatch(BYTE FAR *s, BYTE FAR *d, COUNT n, COUNT mode);
  71. BOOL FcbCharMatch(COUNT s, COUNT d, COUNT mode);
  72. BOOL FcbCalcRec(xfcb FAR *lpXfcb);
  73. VOID MoveDirInfo(dmatch FAR *lpDmatch, struct dirent FAR *lpDir);
  74. #else
  75. fcb FAR *ExtFcbToFcb();
  76. fcb FAR *CommonFcbInit();
  77. void FcbNameInit();
  78. sft FAR *FcbGetSft();
  79. VOID FcbNextRecord();
  80. sft FAR *FcbGetFreeSft();
  81. BOOL FcbFnameMatch();
  82. BOOL FcbCharMatch();
  83. BOOL FcbCalcRec();
  84. VOID MoveDirInfo();
  85. #endif
  86. static dmatch Dmatch;
  87. VOID DosOutputString(BYTE FAR *s)
  88. {
  89. while(*s != '$')
  90. DosCharOutput(*s++);
  91. }
  92. static BYTE *con_name = "CON";
  93. int DosCharInputEcho(VOID)
  94. {
  95. BYTE cb;
  96. CharReqHdr.r_length = sizeof(request);
  97. CharReqHdr.r_command = C_INPUT;
  98. CharReqHdr.r_count = 1;
  99. CharReqHdr.r_trans = (VOID FAR *)&cb;
  100. CharReqHdr.r_status = 0;
  101. execrh((request FAR *)&CharReqHdr, syscon);
  102. if(CharReqHdr.r_status & S_ERROR)
  103. return char_error(&CharReqHdr, con_name);
  104. DosCharOutput(cb);
  105. return cb;
  106. }
  107. int DosCharInput(VOID)
  108. {
  109. BYTE cb;
  110. CharReqHdr.r_length = sizeof(request);
  111. CharReqHdr.r_command = C_INPUT;
  112. CharReqHdr.r_count = 1;
  113. CharReqHdr.r_trans = (VOID FAR *)&cb;
  114. CharReqHdr.r_status = 0;
  115. execrh((request FAR *)&CharReqHdr, syscon);
  116. if(CharReqHdr.r_status & S_ERROR)
  117. return char_error(&CharReqHdr, con_name);
  118. return cb;
  119. }
  120. VOID DosDirectConsoleIO(iregs FAR *r)
  121. {
  122. BYTE buf;
  123. if(r -> DL == 0xff)
  124. {
  125. r -> FLAGS &= ~FLG_ZERO;
  126. CharReqHdr.r_length = sizeof(request);
  127. CharReqHdr.r_command = C_ISTAT;
  128. CharReqHdr.r_status = 0;
  129. execrh((request FAR *)&CharReqHdr, syscon);
  130. if(CharReqHdr.r_status & S_ERROR)
  131. {
  132. char_error(&CharReqHdr, con_name);
  133. return;
  134. }
  135. if(CharReqHdr.r_status & S_BUSY)
  136. {
  137. CharReqHdr.r_length = sizeof(request);
  138. CharReqHdr.r_command = C_INPUT;
  139. CharReqHdr.r_count = 1;
  140. CharReqHdr.r_trans = (VOID FAR *)&buf;
  141. CharReqHdr.r_status = 0;
  142. execrh((request FAR *)&CharReqHdr, syscon);
  143. if(CharReqHdr.r_status & S_ERROR)
  144. {
  145. char_error(&CharReqHdr, con_name);
  146. return;
  147. }
  148. r -> AL = buf;
  149. r -> FLAGS |= FLG_ZERO;
  150. }
  151. }
  152. else
  153. {
  154. CharReqHdr.r_length = sizeof(request);
  155. CharReqHdr.r_command = C_OUTPUT;
  156. CharReqHdr.r_count = 1;
  157. CharReqHdr.r_trans = (VOID FAR *)(&buf);
  158. CharReqHdr.r_status = 0;
  159. execrh((request FAR *)&CharReqHdr, syscon);
  160. if(CharReqHdr.r_status & S_ERROR)
  161. char_error(&CharReqHdr, con_name);
  162. }
  163. }
  164. /* Console output with printer echo                                     */
  165. VOID DosCharOutput(COUNT c)
  166. {
  167. BYTE buf = c;
  168. /* Test for break first                                         */
  169. if(con_break())
  170. return;
  171. /* Now do an output directly to the console                     */
  172. CharReqHdr.r_length = sizeof(request);
  173. CharReqHdr.r_command = C_OUTPUT;
  174. CharReqHdr.r_count = 1;
  175. CharReqHdr.r_trans = (VOID FAR *)(&buf);
  176. CharReqHdr.r_status = 0;
  177. execrh((request FAR *)&CharReqHdr, syscon);
  178. if(CharReqHdr.r_status & S_ERROR)
  179. char_error(&CharReqHdr, con_name);
  180. ++scr_pos;
  181. /* printer echo stuff                                   */
  182. }
  183. VOID DosDisplayOutput(COUNT c)
  184. {
  185. /* Non-portable construct                                       */
  186. if(c < ' ' || c == 0x7f)
  187. {
  188. switch(c)
  189. {
  190. case 'r':
  191. scr_pos = 0;
  192. break;
  193. case 0x7f:
  194. ++scr_pos;
  195. break;
  196. case 'b':
  197. if(scr_pos > 0)
  198. --scr_pos;
  199. break;
  200. case 't':
  201. do
  202. DosCharOutput(' ');
  203. while(scr_pos & 7);
  204. return;
  205. default:
  206. break;
  207. }
  208. DosCharOutput(c);
  209. }
  210. else
  211. {
  212. DosCharOutput(c);
  213. }
  214. }
  215. VOID 
  216. FatGetDrvData (COUNT drive, COUNT FAR *spc, COUNT FAR *bps, COUNT FAR *nc, BYTE FAR **mdp)
  217. {
  218. struct dpb *dpbp;
  219. /* first check for valid drive                                  */
  220. if(drive < 0 || drive > NDEVS)
  221. {
  222. *spc = -1;
  223. return;
  224. }
  225. /* next - "log" in the drive                                    */
  226. drive = (drive == 0 ? default_drive : drive - 1);
  227. dpbp = &blk_devices[drive];
  228. ++(dpbp -> dpb_count);
  229. dpbp -> dpb_flags = -1;
  230. if((media_check(dpbp) < 0) || (dpbp -> dpb_count <= 0))
  231. {
  232. *spc = -1;
  233. return;
  234. }
  235. /* get the data vailable from dpb                       */
  236. *nc = dpbp -> dpb_size;
  237. *spc = dpbp -> dpb_clsmask;
  238. *bps = dpbp -> dpb_secsize;
  239. /* Point to the media desctriptor fotr this drive               */
  240. *mdp = &(dpbp -> dpb_mdb);
  241. --(dpbp -> dpb_count);
  242. }
  243. #define PARSE_SEP_STOP          0x01
  244. #define PARSE_DFLT_DRIVE        0x02
  245. #define PARSE_BLNK_FNAME        0x04
  246. #define PARSE_BLNK_FEXT         0x08
  247. #define PARSE_RET_NOWILD        0
  248. #define PARSE_RET_WILD          1
  249. #define PARSE_RET_BADDRIVE      0xff
  250. #ifndef IPL
  251. WORD FcbParseFname(wTestMode, lpFileName, lpFcb)
  252. REG WORD wTestMode;
  253. BYTE FAR **lpFileName;
  254. fcb FAR *lpFcb;
  255. {
  256. COUNT   nIndex;
  257. WORD    wRetCode = PARSE_RET_NOWILD;
  258. /* pjv -- ExtFcbToFcb?                                          */
  259. /* Start out with some simple stuff first.  Check if we are     */
  260. /* going to use a default drive specificaton.                   */
  261. if(!(wTestMode & PARSE_DFLT_DRIVE))
  262. lpFcb -> fcb_drive = FDFLT_DRIVE;
  263. if(!(wTestMode & PARSE_BLNK_FNAME))
  264. {
  265. for(nIndex = 0; nIndex < FNAME_SIZE; ++nIndex)
  266. lpFcb -> fcb_fname[nIndex] = ' ';
  267. }
  268. if(!(wTestMode & PARSE_BLNK_FEXT))
  269. {
  270. for(nIndex = 0; nIndex < FEXT_SIZE; ++nIndex)
  271. lpFcb -> fcb_fext[nIndex] = ' ';
  272. }                              
  273. /* Undocumented behavior, set record number & record size to 0  */
  274. lpFcb -> fcb_cublock = lpFcb -> fcb_recsiz = 0;
  275. if(!(wTestMode & PARSE_SEP_STOP))
  276. {
  277. *lpFileName = ParseSkipWh(*lpFileName);
  278. if(TestCmnSeps(*lpFileName))
  279. ++*lpFileName;
  280. }
  281. /* Undocumented "feature," we skip white space anyway           */
  282. *lpFileName = ParseSkipWh(*lpFileName);
  283. /* Now check for drive specification                            */
  284. if(*(*lpFileName + 1) == ':')
  285. {
  286. REG BYTE Drive = upChar(**lpFileName);
  287. /* non-portable construct to be changed                 */
  288. if(Drive < 'A' || Drive > 'Z')
  289. return PARSE_RET_BADDRIVE;
  290. Drive -= ('A' - 1);
  291. if(Drive > nblkdev)
  292. return PARSE_RET_BADDRIVE;
  293. else
  294. lpFcb -> fcb_drive = Drive;
  295. *lpFileName += 2;
  296. }
  297. /* Now to format the file name into the string                  */
  298. *lpFileName = GetNameField(*lpFileName, (BYTE FAR *)lpFcb -> fcb_fname, FNAME_SIZE, (BOOL *)&wRetCode);
  299. /* Do we have an extension? If do, format it else return        */
  300. if(**lpFileName == '.')
  301. *lpFileName = GetNameField(++*lpFileName, (BYTE FAR *)lpFcb -> fcb_fext, FEXT_SIZE, (BOOL *)&wRetCode);
  302. return wRetCode ? PARSE_RET_WILD : PARSE_RET_NOWILD;
  303. }
  304. BYTE FAR *
  305. ParseSkipWh (BYTE FAR *lpFileName)
  306. {
  307. while(*lpFileName == ' ' || *lpFileName == 't')
  308. ++lpFileName;
  309. return lpFileName;
  310. }
  311. BOOL 
  312. TestCmnSeps (BYTE FAR *lpFileName)
  313. {
  314. BYTE *pszTest, *pszCmnSeps = ":<|>+=,";
  315. for(pszTest = pszCmnSeps; *pszTest != ''; ++pszTest)
  316. if(*lpFileName == *pszTest)
  317. return TRUE;
  318. return FALSE;
  319. }
  320. BOOL 
  321. TestFieldSeps (BYTE FAR *lpFileName)
  322. {
  323. BYTE *pszTest, *pszCmnSeps = "/"[]<>|.";
  324. /* Another non-portable construct                               */
  325. if(*lpFileName <= ' ')
  326. return TRUE;
  327. for(pszTest = pszCmnSeps; *pszTest != ''; ++pszTest)
  328. if(*lpFileName == *pszTest)
  329. return TRUE;
  330. return FALSE;
  331. }
  332. BYTE FAR *
  333. GetNameField (BYTE FAR *lpFileName, BYTE FAR *lpDestField, COUNT nFieldSize, BOOL *pbWildCard)
  334. {
  335. COUNT nIndex = 0;
  336. BYTE cFill = ' ';
  337. *pbWildCard = FALSE;
  338. while(*lpFileName != '' && !TestFieldSeps(lpFileName) && nIndex< nFieldSize)
  339. {
  340. if(*lpFileName == ' ')
  341. break;
  342. if(*lpFileName == '*')
  343. {
  344. *pbWildCard = TRUE;
  345. cFill = '?';
  346. ++lpFileName;
  347. break;
  348. }
  349. if(*lpFileName == '?')
  350. *pbWildCard = TRUE;
  351. *lpDestField++ = upChar(*lpFileName++);
  352. ++nIndex;
  353. }
  354. /* Blank out remainder of field on exit                         */
  355. for( ; nIndex < nFieldSize; ++nIndex)
  356. *lpDestField++ = cFill;
  357. return lpFileName;
  358. }
  359. static sft FAR *FcbGetSft(SftIndex)
  360. COUNT SftIndex;
  361. {
  362. /* Get the SFT block that contains the SFT      */
  363. for(lpCurSft = sfthead; lpCurSft != (sfttbl FAR *)-1;
  364.  lpCurSft = lpCurSft -> sftt_next)
  365. {
  366. if(SftIndex < lpCurSft -> sftt_count)
  367. break;
  368. else
  369. SftIndex -= lpCurSft -> sftt_count;
  370. }
  371. /* If not found, return an error                */
  372. if(lpCurSft == (sfttbl FAR *)-1)
  373. return (sft FAR *)-1;
  374. /* finally, point to the right entry            */
  375. return (sft FAR *)&(lpCurSft -> sftt_table[SftIndex]);
  376. }
  377. static VOID FcbNextRecord(lpFcb)
  378. fcb FAR *lpFcb;
  379. {
  380. if(++lpFcb -> fcb_curec > 128)
  381. {
  382. lpFcb -> fcb_curec = 0;
  383. ++lpFcb -> fcb_cublock;
  384. }
  385. }
  386. BOOL FcbRead(lpXfcb, nErrorCode)
  387. xfcb FAR *lpXfcb;
  388. COUNT *nErrorCode;
  389. {
  390. sft FAR *s;
  391. LONG lPosit;
  392. COUNT nRead;
  393. psp FAR *p = MK_FP(cu_psp,0);
  394. /* Convert to fcb if necessary                                  */
  395. lpFcb = ExtFcbToFcb(lpXfcb);
  396. /* Get the SFT block that contains the SFT      */
  397. if((s = FcbGetSft(lpFcb -> fcb_sftno)) == (sft FAR *)-1)
  398. return FALSE;
  399. /* If this is not opened another error          */
  400. if(s -> sft_count == 0)
  401. return FALSE;
  402. /* Now update the fcb and compute where we need to position     */
  403. /* to.                                                          */
  404. lPosit = ((lpFcb -> fcb_cublock * 128) + lpFcb -> fcb_curec)
  405.  * lpFcb -> fcb_recsiz;
  406. if(dos_lseek(s -> sft_status, lPosit, 0) < 0)
  407. {
  408. *nErrorCode = FCB_ERR_EOF;
  409. return FALSE;
  410. }
  411. /* Do the read                                                  */
  412. nRead = dos_read(s -> sft_status,
  413.  p -> ps_dta, lpFcb -> fcb_recsiz);
  414. /* Now find out how we will return and do it.                   */
  415. if(nRead == lpFcb -> fcb_recsiz)
  416. {
  417. *nErrorCode = FCB_SUCCESS;
  418. FcbNextRecord(lpFcb);
  419. return TRUE;
  420. }
  421. else if(nRead < 0)
  422. {
  423. *nErrorCode = FCB_ERR_EOF;
  424. return TRUE;
  425. }
  426. else if(nRead == 0)
  427. {
  428. *nErrorCode = FCB_ERR_NODATA;
  429. return FALSE;
  430. }
  431. else
  432. {
  433. COUNT nIdx, nCount;
  434. BYTE FAR *lpDta;
  435. nCount = lpFcb -> fcb_recsiz - nRead;
  436. lpDta = (BYTE FAR *)&(p -> ps_dta[nRead]);
  437. for(nIdx = 0; nIdx < nCount; nIdx++)
  438. *lpDta++ = 0;
  439. *nErrorCode = FCB_ERR_EOF;
  440. FcbNextRecord(lpFcb);
  441. return FALSE;
  442. }
  443. }
  444. BOOL FcbWrite(lpXfcb, nErrorCode)
  445. xfcb FAR *lpXfcb;
  446. COUNT *nErrorCode;
  447. {
  448. sft FAR *s;
  449. LONG lPosit;
  450. COUNT nWritten;
  451. psp FAR *p = MK_FP(cu_psp,0);
  452. /* Convert to fcb if necessary                                  */
  453. lpFcb = ExtFcbToFcb(lpXfcb);
  454. /* Get the SFT block that contains the SFT      */
  455. if((s = FcbGetSft(lpFcb -> fcb_sftno)) == (sft FAR *)-1)
  456. return FALSE;
  457. /* If this is not opened another error          */
  458. if(s -> sft_count == 0)
  459. return FALSE;
  460. /* Now update the fcb and compute where we need to position     */
  461. /* to.                                                          */
  462. lPosit = ((lpFcb -> fcb_cublock * 128) + lpFcb -> fcb_curec)
  463.  * lpFcb -> fcb_recsiz;
  464. if(dos_lseek(s -> sft_status, lPosit, 0) < 0)
  465. {
  466. *nErrorCode = FCB_ERR_EOF;
  467. return FALSE;
  468. }
  469. /* Do the read                                                  */
  470. nWritten = dos_write(s -> sft_status,
  471.  p -> ps_dta, lpFcb -> fcb_recsiz);
  472. /* Now find out how we will return and do it.                   */
  473. if(nWritten == lpFcb -> fcb_recsiz)
  474. {
  475. lpFcb -> fcb_fsize = dos_getcufsize(s -> sft_status);
  476. FcbNextRecord(lpFcb);
  477. *nErrorCode = FCB_SUCCESS;
  478. return TRUE;
  479. }
  480. else if(nWritten <= 0)
  481. {
  482. *nErrorCode = FCB_ERR_WRITE;
  483. return TRUE;
  484. }
  485. *nErrorCode = FCB_ERR_WRITE;
  486. return FALSE;
  487. }
  488. BOOL FcbGetFileSize(lpXfcb)
  489. xfcb FAR *lpXfcb;
  490. {
  491. COUNT FcbDrive, FileNum;
  492. /* Build a traditional DOS file name                            */
  493. lpFcb = CommonFcbInit(lpXfcb, PriPathName, &FcbDrive);
  494. /* check for a device                                           */
  495. /* if we have an extension, can't be a device                   */
  496. if(IsDevice(PriPathName) || (lpFcb -> fcb_recsiz == 0))
  497. {
  498. return FALSE;
  499. }
  500. FileNum = dos_open(PriPathName, O_RDONLY);
  501. if(FileNum >= 0)
  502. {
  503. LONG fsize;
  504. /* Get the size                                         */
  505. fsize = dos_getfsize(FileNum);
  506. /* compute the size and update the fcb                  */
  507. lpFcb -> fcb_rndm = fsize / lpFcb -> fcb_recsiz;
  508. if((fsize % lpFcb -> fcb_recsiz) != 0)
  509. ++lpFcb -> fcb_rndm;
  510. /* close the file and leave                             */
  511. return dos_close(FileNum) == SUCCESS;
  512. }
  513. else
  514. return FALSE;
  515. }
  516. BOOL FcbSetRandom(lpXfcb)
  517. xfcb FAR *lpXfcb;
  518. {
  519. LONG lPosit;
  520. /* Convert to fcb if necessary                                  */
  521. lpFcb = ExtFcbToFcb(lpXfcb);
  522. /* Now update the fcb and compute where we need to position     */
  523. /* to.                                                          */
  524. lpFcb -> fcb_rndm = (lpFcb -> fcb_cublock * 128)
  525.  + lpFcb -> fcb_curec;
  526. return TRUE;
  527. }
  528. BOOL FcbCalcRec(lpXfcb)
  529. xfcb FAR *lpXfcb;
  530. {
  531. LONG lPosit;
  532. /* Convert to fcb if necessary                                  */
  533. lpFcb = ExtFcbToFcb(lpXfcb);
  534. /* Now update the fcb and compute where we need to position     */
  535. /* to.                                                          */
  536. lpFcb -> fcb_cublock =  lpFcb -> fcb_rndm / 128;
  537. lpFcb -> fcb_curec =  lpFcb -> fcb_rndm % 128;
  538. return TRUE;
  539. }
  540. BOOL FcbRandomBlockRead(lpXfcb, nRecords, nErrorCode)
  541. xfcb FAR *lpXfcb;
  542. COUNT nRecords;
  543. COUNT *nErrorCode;
  544. {
  545. FcbCalcRec(lpXfcb);
  546. /* Convert to fcb if necessary                                  */
  547. lpFcb = ExtFcbToFcb(lpXfcb);
  548. do
  549. FcbRead(lpXfcb, nErrorCode);
  550. while ((--nRecords > 0) && (*nErrorCode == 0));
  551. /* Now update the fcb                                           */
  552. lpFcb -> fcb_rndm = lpFcb -> fcb_cublock * 128 + lpFcb -> fcb_curec;
  553. return TRUE;
  554. }
  555. BOOL FcbRandomBlockWrite(lpXfcb, nRecords, nErrorCode)
  556. xfcb FAR *lpXfcb;
  557. COUNT nRecords;
  558. COUNT *nErrorCode;
  559. {
  560. FcbCalcRec(lpXfcb);
  561. /* Convert to fcb if necessary                                  */
  562. lpFcb = ExtFcbToFcb(lpXfcb);
  563. do
  564. FcbWrite(lpXfcb, nErrorCode);
  565. while ((--nRecords > 0) && (*nErrorCode == 0));
  566. /* Now update the fcb                                           */
  567. lpFcb -> fcb_rndm = lpFcb -> fcb_cublock * 128 + lpFcb -> fcb_curec;
  568. return TRUE;
  569. }
  570. BOOL FcbRandomRead(lpXfcb, nErrorCode)
  571. xfcb FAR *lpXfcb;
  572. COUNT *nErrorCode;
  573. {
  574. UWORD uwCurrentBlock;
  575. UBYTE ucCurrentRecord;
  576. FcbCalcRec(lpXfcb);
  577. /* Convert to fcb if necessary                                  */
  578. lpFcb = ExtFcbToFcb(lpXfcb);
  579. uwCurrentBlock = lpFcb -> fcb_cublock;
  580. ucCurrentRecord = lpFcb -> fcb_curec;
  581. FcbRead(lpXfcb, nErrorCode);
  582. lpFcb -> fcb_cublock = uwCurrentBlock;
  583. lpFcb -> fcb_curec = ucCurrentRecord;
  584. return TRUE;
  585. }
  586. BOOL FcbRandomWrite(lpXfcb, nErrorCode)
  587. xfcb FAR *lpXfcb;
  588. COUNT *nErrorCode;
  589. {
  590. UWORD uwCurrentBlock;
  591. UBYTE ucCurrentRecord;
  592. FcbCalcRec(lpXfcb);
  593. /* Convert to fcb if necessary                                  */
  594. lpFcb = ExtFcbToFcb(lpXfcb);
  595. uwCurrentBlock = lpFcb -> fcb_cublock;
  596. ucCurrentRecord = lpFcb -> fcb_curec;
  597. FcbWrite(lpXfcb, nErrorCode);
  598. lpFcb -> fcb_cublock = uwCurrentBlock;
  599. lpFcb -> fcb_curec = ucCurrentRecord;
  600. return TRUE;
  601. }
  602. static sft FAR *FcbGetFreeSft(sft_idx)
  603. WORD FAR *sft_idx;
  604. {
  605. WORD sys_idx = 0;
  606. sfttbl FAR *sp;
  607. /* Get the SFT block that contains the SFT      */
  608. for(sp = sfthead; sp != (sfttbl FAR *)-1; sp = sp -> sftt_next)
  609. {
  610. REG WORD i;
  611. for(i = 0; i < sp -> sftt_count; i++)
  612. {
  613. if(sp -> sftt_table[i].sft_count == 0)
  614. {
  615. *sft_idx = sys_idx + i;
  616. return (sft FAR *)&sp -> sftt_table[sys_idx + i];
  617. }
  618. }
  619. sys_idx += i;
  620. }
  621. /* If not found, return an error                */
  622. return (sft FAR *)-1;
  623. }
  624. BOOL FcbCreate(lpXfcb)
  625. xfcb FAR *lpXfcb;
  626. {
  627. WORD sft_idx;
  628. sft FAR *sftp;
  629. struct dhdr FAR *dhp;
  630. COUNT FcbDrive;
  631. /* get a free system file table entry                           */
  632. if((sftp = FcbGetFreeSft((WORD FAR *)&sft_idx)) == (sft FAR *)-1)
  633. return DE_TOOMANY;
  634. /* Build a traditional DOS file name                            */
  635. lpFcb = CommonFcbInit(lpXfcb, PriPathName, &FcbDrive);
  636. /* check for a device                                           */
  637. /* if we have an extension, can't be a device                   */
  638. if(IsDevice(PriPathName))
  639. {
  640. for(dhp = (struct dhdr FAR *)&nul_dev; dhp != (struct dhdr FAR *)-1; dhp = dhp -> dh_next)
  641. {
  642. if(FcbFnameMatch((BYTE FAR *)PriPathName, (BYTE FAR *)dhp -> dh_name, FNAME_SIZE, FALSE))
  643. {
  644. sftp -> sft_count += 1;
  645. sftp -> sft_mode = O_RDWR;
  646. sftp -> sft_attrib = 0;
  647. sftp -> sft_flags =
  648.   (dhp -> dh_attr & ~SFT_MASK) | SFT_FDEVICE | SFT_FEOF;
  649. sftp -> sft_psp = cu_psp;
  650. fbcopy(lpFcb -> fcb_fname, sftp -> sft_name, FNAME_SIZE+FEXT_SIZE);
  651. sftp -> sft_dev = dhp;
  652. lpFcb -> fcb_sftno = sft_idx;
  653. lpFcb -> fcb_curec = 0;
  654. lpFcb -> fcb_recsiz = 0;
  655. lpFcb -> fcb_fsize = 0;
  656. lpFcb -> fcb_date = dos_getdate();
  657. lpFcb -> fcb_time = dos_gettime();
  658. lpFcb -> fcb_rndm = 0;
  659. return TRUE;
  660. }
  661. }
  662. }
  663. sftp -> sft_status = dos_creat(PriPathName, 0);
  664. if(sftp -> sft_status >= 0)
  665. {
  666. lpFcb -> fcb_drive = FcbDrive;
  667. lpFcb -> fcb_sftno = sft_idx;
  668. lpFcb -> fcb_curec = 0;
  669. lpFcb -> fcb_recsiz = 128;
  670. lpFcb -> fcb_fsize = 0;
  671. lpFcb -> fcb_date = dos_getdate();
  672. lpFcb -> fcb_time = dos_gettime();
  673. lpFcb -> fcb_rndm = 0;
  674. sftp -> sft_count += 1;
  675. sftp -> sft_mode = O_RDWR;
  676. sftp -> sft_attrib = 0;
  677. sftp -> sft_flags = 0;
  678. sftp -> sft_psp = cu_psp;
  679. fbcopy((BYTE FAR *)&lpFcb -> fcb_fname, (BYTE FAR *)&sftp -> sft_name, FNAME_SIZE+FEXT_SIZE);
  680. return TRUE;
  681. }
  682. else
  683. return FALSE;
  684. }
  685. static fcb FAR *ExtFcbToFcb(xfcb FAR *lpExtFcb)
  686. {
  687. if(*((UBYTE FAR *)lpExtFcb) == 0xff)
  688. return &lpExtFcb -> xfcb_fcb;
  689. else
  690. return (fcb FAR *)lpExtFcb;
  691. }
  692. static fcb FAR *CommonFcbInit(lpExtFcb, pszBuffer, pCurDrive)
  693. xfcb FAR *lpExtFcb;
  694. BYTE *pszBuffer;
  695. COUNT *pCurDrive;
  696. {
  697. BYTE FAR *lpszFcbFname, *lpszFcbFext;
  698. COUNT nDrvIdx, nFnameIdx, nFextIdx;
  699. fcb FAR *lpFcb;
  700. /* convert to fcb if needed first                               */
  701. lpFcb = ExtFcbToFcb(lpExtFcb);
  702. /* Build a traditional DOS file name                            */
  703. FcbNameInit(lpFcb, pszBuffer, pCurDrive);
  704. /* and return the fcb pointer                                   */
  705. return lpFcb;
  706. }
  707. void FcbNameInit(lpFcb, pszBuffer, pCurDrive)
  708. fcb FAR *lpFcb;
  709. BYTE *pszBuffer;
  710. COUNT *pCurDrive;
  711. {
  712. BYTE FAR *lpszFcbFname, FAR *lpszFcbFext;
  713. COUNT nDrvIdx, nFnameIdx, nFextIdx;
  714. /* Build a traditional DOS file name                            */
  715. lpszFcbFname = (BYTE FAR *)lpFcb -> fcb_fname;
  716. if(lpFcb -> fcb_drive != 0)
  717. {
  718. *pCurDrive = lpFcb -> fcb_drive;
  719. pszBuffer[0] = 'A' + lpFcb -> fcb_drive - 1;
  720. pszBuffer[1] = ':';
  721. nDrvIdx = 2;
  722. }           
  723. else
  724. {
  725. *pCurDrive = default_drive + 1;
  726. nDrvIdx = 0;
  727. }
  728. for(nFnameIdx = 0; nFnameIdx < FNAME_SIZE; nFnameIdx++)
  729. {
  730. if(*lpszFcbFname != ' ')
  731. pszBuffer[nDrvIdx + nFnameIdx] = *lpszFcbFname++;
  732. else
  733. break;
  734. }
  735. lpszFcbFext = (BYTE FAR *)lpFcb -> fcb_fext;
  736. if(*lpszFcbFext != ' ')
  737. {
  738. pszBuffer[nDrvIdx + nFnameIdx++] = '.';
  739. for(nFextIdx = 0; nFextIdx < FEXT_SIZE; nFextIdx++)
  740. {
  741. if(*lpszFcbFext != ' ')
  742. pszBuffer[nDrvIdx + nFnameIdx + nFextIdx] =
  743.  *lpszFcbFext++;
  744. else
  745. break;
  746. }
  747. }
  748. else
  749. nFextIdx = 0;
  750. pszBuffer[nDrvIdx + nFnameIdx + nFextIdx] = '';
  751. }
  752. /* Ascii only file name match routines                  */
  753. static BOOL 
  754. FcbCharMatch (COUNT s, COUNT d, COUNT mode)
  755. {
  756. if(s >= 'a' && s <= 'z')
  757. s -= 'a' - 'A';
  758. if(d >= 'a' && d <= 'z')
  759. d -= 'a' - 'A';
  760. if(mode && s == '?' && (d >= 'A' && s <= 'Z'))
  761. return TRUE;
  762. return s == d;
  763. }
  764. static BOOL 
  765. FcbFnameMatch (BYTE FAR *s, BYTE FAR *d, COUNT n, COUNT mode)
  766. {
  767. while(n--)
  768. {
  769. if(!FcbCharMatch(*s++, *d++, mode))
  770. return FALSE;
  771. }
  772. return TRUE;
  773. }
  774. BOOL FcbOpen(lpXfcb)
  775. xfcb FAR *lpXfcb;
  776. {
  777. WORD sft_idx;
  778. sft FAR *sftp;
  779. struct dhdr FAR *dhp;
  780. COUNT FcbDrive;
  781. /* get a free system file table entry                           */
  782. if((sftp = FcbGetFreeSft((WORD FAR *)&sft_idx)) == (sft FAR *)-1)
  783. return DE_TOOMANY;
  784. /* Build a traditional DOS file name                            */
  785. lpFcb = CommonFcbInit(lpXfcb, PriPathName, &FcbDrive);
  786. /* check for a device                                           */
  787. /* if we have an extension, can't be a device                   */
  788. if(IsDevice(PriPathName))
  789. {
  790. for(dhp = (struct dhdr FAR *)&nul_dev; dhp != (struct dhdr FAR *)-1; dhp = dhp -> dh_next)
  791. {
  792. if(FcbFnameMatch((BYTE FAR *)PriPathName, (BYTE FAR *)dhp -> dh_name, FNAME_SIZE, FALSE))
  793. {
  794. sftp -> sft_count += 1;
  795. sftp -> sft_mode = O_RDWR;
  796. sftp -> sft_attrib = 0;
  797. sftp -> sft_flags =
  798.   (dhp -> dh_attr & ~SFT_MASK) | SFT_FDEVICE | SFT_FEOF;
  799. sftp -> sft_psp = cu_psp;
  800. fbcopy(lpFcb -> fcb_fname, sftp -> sft_name, FNAME_SIZE+FEXT_SIZE);
  801. sftp -> sft_dev = dhp;
  802. lpFcb -> fcb_sftno = sft_idx;
  803. lpFcb -> fcb_curec = 0;
  804. lpFcb -> fcb_recsiz = 0;
  805. lpFcb -> fcb_fsize = 0;
  806. lpFcb -> fcb_date = dos_getdate();
  807. lpFcb -> fcb_time = dos_gettime();
  808. lpFcb -> fcb_rndm = 0;
  809. return TRUE;
  810. }
  811. }
  812. }
  813. sftp -> sft_status = dos_open(PriPathName, O_RDWR);
  814. if(sftp -> sft_status >= 0)
  815. {
  816. lpFcb -> fcb_drive = FcbDrive;
  817. lpFcb -> fcb_sftno = sft_idx;
  818. lpFcb -> fcb_curec = 0;
  819. lpFcb -> fcb_recsiz = 128;
  820. lpFcb -> fcb_fsize = dos_getfsize(sftp -> sft_status);
  821. dos_getftime(sftp -> sft_status,
  822.  (date FAR *)&lpFcb -> fcb_date,
  823.  (time FAR *)&lpFcb -> fcb_time);
  824. lpFcb -> fcb_rndm = 0;
  825. sftp -> sft_count += 1;
  826. sftp -> sft_mode = O_RDWR;
  827. sftp -> sft_attrib = 0;
  828. sftp -> sft_flags = 0;
  829. sftp -> sft_psp = cu_psp;
  830. fbcopy((BYTE FAR *)&lpFcb -> fcb_fname, (BYTE FAR *)&sftp -> sft_name, FNAME_SIZE+FEXT_SIZE);
  831. return TRUE;
  832. }
  833. else
  834. return FALSE;
  835. }
  836. BOOL FcbDelete(lpXfcb)
  837. xfcb FAR *lpXfcb;
  838. {
  839. COUNT FcbDrive;
  840. /* Build a traditional DOS file name                            */
  841. CommonFcbInit(lpXfcb, PriPathName, &FcbDrive);
  842. /* check for a device                                           */
  843. /* if we have an extension, can't be a device                   */
  844. if(IsDevice(PriPathName))
  845. {
  846. return FALSE;
  847. }
  848. else
  849. {
  850. BYTE FAR *lpOldDta = dta;
  851. dmatch Dmatch;
  852. dta = (BYTE FAR *)&Dmatch;
  853. if(dos_findfirst(D_ALL, PriPathName[1] == ':' ? &PriPathName[2] : PriPathName) != SUCCESS)
  854. {
  855. dta = lpOldDta;
  856. return FALSE;
  857. }
  858. do
  859. {
  860. if(dos_delete(Dmatch.dm_name) != SUCCESS)
  861. {
  862. dta = lpOldDta;
  863. return FALSE;
  864. }
  865. }
  866. while(dos_findnext() == SUCCESS);
  867. dta = lpOldDta;
  868. return TRUE;
  869. }
  870. }
  871. BOOL FcbRename(lpXfcb)
  872. xfcb FAR *lpXfcb;
  873. {
  874. rfcb FAR *lpRenameFcb;
  875. COUNT FcbDrive;
  876. /* Build a traditional DOS file name                            */
  877. lpRenameFcb = (rfcb FAR *)CommonFcbInit(lpXfcb, PriPathName, &FcbDrive);
  878. /* check for a device                                           */
  879. /* if we have an extension, can't be a device                   */
  880. if(IsDevice(PriPathName))
  881. {
  882. return FALSE;
  883. }
  884. else
  885. {
  886. BYTE FAR *lpOldDta = dta;
  887. dmatch Dmatch;
  888. dta = (BYTE FAR *)&Dmatch;
  889. if(dos_findfirst(D_ALL, PriPathName[1] == ':' ? &PriPathName[2] : PriPathName) != SUCCESS)
  890. {
  891. dta = lpOldDta;
  892. return FALSE;
  893. }
  894. do
  895. {
  896. fcb LocalFcb;
  897. BYTE *pToName, *pszFrom;
  898. BYTE FAR *pFromPattern;
  899. COUNT nIndex;
  900. /* First, expand the find match into fcb style  */
  901. /* file name entry                              */
  902. /* Fill with blanks first                       */
  903. for(pToName = LocalFcb.fcb_fname, nIndex = 0;
  904.  nIndex < FNAME_SIZE; nIndex++)
  905. {
  906. *pToName++ = ' ';
  907. }
  908. for(pToName = LocalFcb.fcb_fext, nIndex = 0;
  909.  nIndex < FEXT_SIZE; nIndex++)
  910. {
  911. *pToName++ = ' ';
  912. }
  913. /* next move in the file name while overwriting */
  914. /* the filler blanks                            */
  915. pszFrom = Dmatch.dm_name;
  916. pToName = LocalFcb.fcb_fname;
  917. for(nIndex = 0; nIndex < FNAME_SIZE; nIndex++)
  918. {
  919. if(*pszFrom != 0 && *pszFrom != '.')
  920. *pToName++ = *pszFrom++;
  921. else if(*pszFrom == '.')
  922. {
  923. ++pszFrom;
  924. break;
  925. }
  926. else
  927. break;
  928. }
  929. if(*pszFrom != '')
  930. {
  931. pToName = LocalFcb.fcb_fext;
  932. for(nIndex = 0; nIndex < FEXT_SIZE; nIndex++)
  933. {
  934. if(*pszFrom != '')
  935. *pToName++ = *pszFrom++;
  936. else
  937. break;
  938. }
  939. }
  940. /* Overlay the pattern, skipping '?'            */
  941. /* I'm cheating because this assumes that the   */
  942. /* struct alignments are on byte boundaries     */
  943. pToName = LocalFcb.fcb_fname;
  944. for(pFromPattern = lpRenameFcb -> renNewName,
  945.  nIndex = 0; nIndex < FNAME_SIZE + FEXT_SIZE; nIndex++)
  946. {
  947. if(*pFromPattern != '?')
  948. *pToName++ = *pFromPattern++;
  949. else
  950. ++pFromPattern;
  951. }
  952. /* now to build a dos name again                */
  953. LocalFcb.fcb_drive = 0;
  954. FcbNameInit((fcb FAR *)&LocalFcb, PriPathName, &FcbDrive);
  955. if(dos_rename(Dmatch.dm_name,
  956.  PriPathName[1] == ':' ? &PriPathName[2] : PriPathName) != SUCCESS)
  957. {
  958. dta = lpOldDta;
  959. return FALSE;
  960. }
  961. }
  962. while(dos_findnext() == SUCCESS);
  963. dta = lpOldDta;
  964. return TRUE;
  965. }
  966. }
  967. void MoveDirInfo(lpDmatch, lpDir)
  968. dmatch FAR *lpDmatch;
  969. struct dirent FAR *lpDir;
  970. {
  971. BYTE FAR *lpToName, FAR *lpszFrom;
  972. COUNT nIndex;
  973. /* First, expand the find match into dir style  */
  974. /* file name entry                              */
  975. /* Fill with blanks first                       */
  976. for(lpToName = lpDir -> dir_name, nIndex = 0;
  977.  nIndex < FNAME_SIZE; nIndex++)
  978. {
  979. *lpToName++ = ' ';
  980. }
  981. for(lpToName = lpDir -> dir_ext, nIndex = 0;
  982.  nIndex < FEXT_SIZE; nIndex++)
  983. {
  984. *lpToName++ = ' ';
  985. }
  986. /* next move in the file name while overwriting */
  987. /* the filler blanks                            */
  988. lpszFrom = lpDmatch -> dm_name;
  989. lpToName = lpDir -> dir_name;
  990. for(nIndex = 0; nIndex < FNAME_SIZE; nIndex++)
  991. {
  992. if(*lpszFrom != 0 && *lpszFrom != '.')
  993. *lpToName++ = *lpszFrom++;
  994. else
  995. break;
  996. }
  997.     
  998. if(*lpszFrom != '')
  999. {
  1000. if(*lpszFrom == '.')
  1001. ++lpszFrom;
  1002. lpToName = lpDir -> dir_ext;
  1003. for(nIndex = 0; nIndex < FEXT_SIZE; nIndex++)
  1004. {
  1005. if(*lpszFrom != '')
  1006. *lpToName++ = *lpszFrom++;
  1007. else
  1008. break;
  1009. }
  1010. }
  1011. for(nIndex = 0; nIndex < 10; nIndex++)
  1012. lpDir -> dir_reserved[nIndex] = 0;
  1013. lpDir -> dir_attrib = lpDmatch ->dm_attr_fnd;
  1014. lpDir -> dir_time = lpDmatch ->dm_time;
  1015. lpDir -> dir_date = lpDmatch ->dm_date;
  1016. lpDir -> dir_start = lpDmatch ->dm_cluster;
  1017. lpDir -> dir_size = lpDmatch ->dm_size;
  1018. }
  1019. BOOL FcbClose(lpXfcb)
  1020. xfcb FAR *lpXfcb;
  1021. {
  1022. sft FAR *s;
  1023. /* Convert to fcb if necessary                                  */
  1024. lpFcb = ExtFcbToFcb(lpXfcb);
  1025. /* Get the SFT block that contains the SFT      */
  1026. if((s = FcbGetSft(lpFcb -> fcb_sftno)) == (sft FAR *)-1)
  1027. return FALSE;
  1028. /* If this is not opened another error          */
  1029. if(s -> sft_count == 0)
  1030. return FALSE;
  1031. /* now just drop the count if a device, else    */
  1032. /* call file system handler                     */
  1033. if(s -> sft_flags & SFT_FDEVICE)
  1034. {
  1035. s -> sft_count -= 1;
  1036. return TRUE;
  1037. }
  1038. else
  1039. {
  1040. s -> sft_count -= 1;
  1041. if(s -> sft_count > 0)
  1042. return SUCCESS;
  1043. else
  1044. {
  1045. /* change time and set file size                */
  1046. dos_setftime(s -> sft_status,
  1047.  (date FAR *)&lpFcb -> fcb_date,
  1048.  (time FAR *)&lpFcb -> fcb_time);
  1049. dos_setfsize(s -> sft_status,
  1050.  lpFcb -> fcb_fsize);
  1051. return dos_close(s -> sft_status) == SUCCESS;
  1052. }
  1053. }
  1054. }
  1055. BOOL FcbFindFirst(lpXfcb)
  1056. xfcb FAR *lpXfcb;
  1057. {
  1058. BYTE FAR *lpOldDta;
  1059. BYTE FAR *lpDir;
  1060. COUNT nIdx, FcbDrive;
  1061. psp FAR *lpPsp = MK_FP(cu_psp,0);
  1062. /* First, move the dta to a local and change it around to match */
  1063. /* our functions.                                               */
  1064. lpDir = (BYTE FAR *)dta;
  1065. dta = (BYTE FAR *)&Dmatch;
  1066. /* Next initialze local variables by moving them from the fcb   */
  1067. lpFcb = CommonFcbInit(lpXfcb, PriPathName, &FcbDrive);
  1068. if(lpXfcb -> xfcb_flag == 0xff)
  1069. {
  1070. wAttr = lpXfcb -> xfcb_attrib;
  1071. fbcopy(lpXfcb, lpDir, 7);
  1072. lpDir += 7;
  1073. }
  1074. else
  1075. wAttr = D_ALL;
  1076. *lpDir++ = PriPathName[0] - 'A';
  1077. if(dos_findfirst(wAttr, PriPathName) != SUCCESS)       
  1078. {
  1079. dta = lpPsp -> ps_dta;
  1080. return FALSE;
  1081. }
  1082. MoveDirInfo((dmatch FAR *)&Dmatch, (struct dirent FAR *)lpDir);
  1083. lpFcb -> fcb_dirclst = Dmatch.dm_cluster;
  1084. lpFcb -> fcb_diroff = Dmatch.dm_entry;
  1085. dta = lpPsp -> ps_dta;
  1086. return TRUE;
  1087. }
  1088. BOOL FcbFindNext(lpXfcb)
  1089. xfcb FAR *lpXfcb;
  1090. {
  1091. BYTE FAR *lpOldDta;
  1092. BYTE FAR *lpDir;
  1093. COUNT nIdx, FcbDrive;
  1094. psp FAR *lpPsp = MK_FP(cu_psp,0);
  1095. /* First, move the dta to a local and change it around to match */
  1096. /* our functions.                                               */
  1097. lpDir = (BYTE FAR *)dta;
  1098. dta = (BYTE FAR *)&Dmatch;
  1099. /* Next initialze local variables by moving them from the fcb   */
  1100. lpFcb = CommonFcbInit(lpXfcb, PriPathName, &FcbDrive);
  1101. if((xfcb FAR *)lpFcb != lpXfcb)
  1102. {
  1103. wAttr = lpXfcb -> xfcb_attrib;
  1104. fbcopy(lpXfcb, lpDir, 7);
  1105. lpDir += 7;
  1106. }
  1107. else
  1108. wAttr = D_ALL;
  1109. /* Reconstrct the dirmatch structure from the fcb               */
  1110. *lpDir++ = FcbDrive;
  1111. Dmatch.dm_drive = FcbDrive? FcbDrive - 1 : default_drive;
  1112. fbcopy(lpFcb -> fcb_fname, (BYTE FAR *)Dmatch.dm_name_pat, FNAME_SIZE+FEXT_SIZE);
  1113. upMem((BYTE FAR *)Dmatch.dm_name_pat, FNAME_SIZE+FEXT_SIZE);
  1114. Dmatch.dm_attr_srch = wAttr;
  1115. Dmatch.dm_entry = lpFcb -> fcb_diroff;
  1116. Dmatch.dm_cluster = lpFcb -> fcb_dirclst;
  1117. if(dos_findnext() != SUCCESS)
  1118. {
  1119. dta = lpPsp -> ps_dta;
  1120. return FALSE;
  1121. }
  1122. MoveDirInfo((dmatch FAR *)&Dmatch, (struct dirent FAR *)lpDir);
  1123. lpFcb -> fcb_dirclst = Dmatch.dm_cluster;
  1124. lpFcb -> fcb_diroff = Dmatch.dm_entry;
  1125. dta = lpPsp -> ps_dta;
  1126. return TRUE;
  1127. }
  1128. #endif