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

操作系统开发

开发平台:

DOS

  1. /****************************************************************/
  2. /*                                                              */
  3. /*                          fatdir.c                            */
  4. /*                            DOS-C                             */
  5. /*                                                              */
  6. /*                 FAT File System dir Functions                */
  7. /*                                                              */
  8. /*                      Copyright (c) 1995                      */
  9. /*                      Pasquale J. Villani                     */
  10. /*                      All Rights Reserved                     */
  11. /*                                                              */
  12. /* This file is part of DOS-C.                                  */
  13. /*                                                              */
  14. /* DOS-C is free software; you can redistribute it and/or       */
  15. /* modify it under the terms of the GNU General Public License  */
  16. /* as published by the Free Software Foundation; either version */
  17. /* 2, or (at your option) any later version.                    */
  18. /*                                                              */
  19. /* DOS-C is distributed in the hope that it will be useful, but */
  20. /* WITHOUT ANY WARRANTY; without even the implied warranty of   */
  21. /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See    */
  22. /* the GNU General Public License for more details.             */
  23. /*                                                              */
  24. /* You should have received a copy of the GNU General Public    */
  25. /* License along with DOS-C; see the file COPYING.  If not,     */
  26. /* write to the Free Software Foundation, 675 Mass Ave,         */
  27. /* Cambridge, MA 02139, USA.                                    */
  28. /****************************************************************/
  29. #include "../../hdr/portab.h"
  30. #include "globals.h"
  31. /* $Logfile:   C:/dos-c/src/fs/fatdir.c_v  $ */
  32. #ifdef VERSION_STRINGS
  33. static BYTE *fatdirRcsId = "$Header:   C:/dos-c/src/fs/fatdir.c_v   1.9   22 Jan 1998  4:09:00   patv  $";
  34. #endif
  35. /* $Log:   C:/dos-c/src/fs/fatdir.c_v  $
  36.  * 
  37.  *    Rev 1.9   22 Jan 1998  4:09:00   patv
  38.  * Fixed pointer problems affecting SDA
  39.  * 
  40.  *    Rev 1.8   04 Jan 1998 23:14:36   patv
  41.  * Changed Log for strip utility
  42.  * 
  43.  *    Rev 1.7   03 Jan 1998  8:36:02   patv
  44.  * Converted data area to SDA format
  45.  * 
  46.  *    Rev 1.6   16 Jan 1997 12:46:30   patv
  47.  * pre-Release 0.92 feature additions
  48.  * 
  49.  *    Rev 1.5   29 May 1996 21:15:18   patv
  50.  * bug fixes for v0.91a
  51.  * 
  52.  *    Rev 1.4   19 Feb 1996  3:20:12   patv
  53.  * Added NLS, int2f and config.sys processing
  54.  * 
  55.  *    Rev 1.2   01 Sep 1995 17:48:38   patv
  56.  * First GPL release.
  57.  * 
  58.  *    Rev 1.1   30 Jul 1995 20:50:24   patv
  59.  * Eliminated version strings in ipl
  60.  * 
  61.  *    Rev 1.0   02 Jul 1995  8:04:34   patv
  62.  * Initial revision.
  63.  */
  64. /* $EndLog$ */
  65. VOID pop_dmp(dmatch FAR *, struct f_node FAR *);
  66. struct f_node FAR *
  67. dir_open (BYTE FAR *dirname)
  68. {
  69. struct f_node FAR *fnp;
  70. COUNT drive;
  71. BYTE *p;
  72. WORD i;
  73. BYTE *s, *pszPath = &TempCDS.cdsCurrentPath[2];
  74. /* Allocate an fnode if possible - error return (0) if not.     */
  75. if((fnp = get_f_node()) == (struct f_node FAR *)0)
  76. {
  77. return (struct f_node FAR *)NULL;
  78. }
  79. /* Force the fnode into read-write mode                         */
  80. fnp -> f_mode = RDWR;
  81. /* and initialize temporary CDS */
  82. TempCDS.cdsFlags = 0;
  83. /* determine what drive we are using...                         */
  84. dirname = adjust_far(dirname);
  85. ParseDosName(dirname, &drive, (BYTE *)0, (BYTE *)0, (BYTE *)0);
  86. /* If the drive was specified, drive is non-negative and */
  87. /* corresponds to the one passed in, i.e., 0 = A, 1 = B, etc. */
  88. /* We use that and skip the "D:" part of the string. */
  89. /* Otherwise, just use the default drive */ 
  90. if(drive >= 0)
  91. {
  92. dirname += 2; /* Assume FAT style drive */
  93. TempCDS.cdsDpb = &blk_devices[drive];
  94. }
  95. else
  96. {
  97. TempCDS.cdsDpb = &blk_devices[drive = default_drive];
  98. }
  99. fnp -> f_dpb = (struct dpb *)TempCDS.cdsDpb;
  100. TempCDS.cdsCurrentPath[0] = 'A' + drive;
  101. TempCDS.cdsCurrentPath[1] = ':';
  102. TempCDS.cdsJoinOffset = 2;
  103. if (drive >= nblkdev)
  104. {
  105. release_f_node(fnp);
  106. return NULL;
  107. }
  108. /* Generate full path name                                      */
  109. ParseDosPath(dirname,
  110.  (COUNT *)0, pszPath, (BYTE *)TempCDS.cdsDpb -> dpb_path);
  111. /* Perform all directory common handling after all special */
  112. /* handling has been performed. */
  113. ++TempCDS.cdsDpb -> dpb_count;
  114. if(media_check((struct dpb *)TempCDS.cdsDpb) < 0)
  115. {
  116. --TempCDS.cdsDpb -> dpb_count;
  117. release_f_node(fnp);
  118. return (struct f_node FAR *)0;
  119. }
  120. fnp -> f_diroff = 0l;
  121. fnp -> f_flags.f_dmod = FALSE;  /* a brand new fnode */
  122. fnp -> f_flags.f_dnew = TRUE;
  123. fnp -> f_dsize = DIRENT_SIZE * TempCDS.cdsDpb -> dpb_dirents;
  124. /* Walk the directory tree to find the starting cluster */
  125. /* */
  126. /* Set the root flags since we always start from the root */
  127. fnp -> f_flags.f_droot = TRUE;
  128. for(p = pszPath; *p != ''; )
  129. {
  130. /* skip all path seperators */
  131. while(*p == '\')
  132. ++p;
  133. /* don't continue if we're at the end */
  134. if(*p == '')
  135. break;
  136. /* Convert the name into an absolute name for */
  137. /* comparison... */
  138. /* first the file name with trailing spaces... */
  139. for(i = 0; i < FNAME_SIZE; i++)
  140. {
  141. if(*p != '' && *p != '.' && *p != '/' && *p != '\')
  142. TempBuffer[i] = *p++;
  143. else
  144. break;
  145. }
  146. for( ; i < FNAME_SIZE; i++)
  147. TempBuffer[i] = ' ';
  148. /* and the extension (don't forget to   */
  149. /* add trailing spaces)...              */
  150. if(*p == '.')
  151. ++p;
  152. for(i = 0; i < FEXT_SIZE; i++)
  153. {
  154. if(*p != '' && *p != '.' && *p != '/' && *p != '\')
  155. TempBuffer[i+FNAME_SIZE] = *p++;
  156. else
  157. break;
  158. }
  159. for( ; i < FEXT_SIZE; i++)
  160. TempBuffer[i+FNAME_SIZE] = ' ';
  161. /* Now search through the directory to  */
  162. /* find the entry...                    */
  163. i = FALSE;
  164. upMem((BYTE FAR *)TempBuffer, FNAME_SIZE+FEXT_SIZE);
  165. while(dir_read(fnp) == DIRENT_SIZE)
  166. {
  167. if(fnp -> f_dir.dir_name[0] != '' && fnp -> f_dir.dir_name[0] != DELETED)
  168. {
  169. if(fcmp((BYTE FAR *)TempBuffer, (BYTE FAR *)fnp -> f_dir.dir_name, FNAME_SIZE+FEXT_SIZE))
  170. {
  171. i = TRUE;
  172. break;
  173. }
  174. }
  175. }
  176. if(!i || !(fnp -> f_dir.dir_attrib & D_DIR))
  177. {
  178. --TempCDS.cdsDpb -> dpb_count;
  179. release_f_node(fnp);
  180. return (struct f_node FAR *)0;
  181. }
  182. else
  183. {
  184. /* make certain we've moved off */
  185. /* root                         */
  186. fnp -> f_flags.f_droot = FALSE;
  187. fnp -> f_flags.f_ddir = TRUE;
  188. /* set up for file read/write   */
  189. fnp -> f_offset = 0l;
  190. fnp -> f_highwater = 0l;
  191. fnp -> f_cluster = fnp -> f_dir.dir_start;
  192. fnp -> f_dirstart = fnp -> f_dir.dir_start;
  193. /* reset the directory flags    */
  194. fnp -> f_diroff = 0l;
  195. fnp -> f_flags.f_dmod = FALSE;
  196. fnp -> f_flags.f_dnew = TRUE;
  197. fnp -> f_dsize = DIRENT_SIZE * TempCDS.cdsDpb -> dpb_dirents;
  198. }
  199. }
  200. return fnp;
  201. }
  202. COUNT 
  203. dir_read (REG struct f_node FAR *fnp)
  204. {
  205. REG i, j;
  206. struct buffer FAR *bp;
  207. /* Directories need to point to their current offset, not for   */
  208. /* next op. Therefore, if it is anything other than the first   */
  209. /* directory entry, we will update the offset on entry rather   */
  210. /* than wait until exit. If it was new, clear the special new   */
  211. /* flag.                                                        */
  212. if(fnp -> f_flags.f_dnew)
  213. fnp -> f_flags.f_dnew = FALSE;
  214. else
  215. fnp -> f_diroff += DIRENT_SIZE;
  216. /* Determine if we hit the end of the directory. If we have,    */
  217. /* bump the offset back to the end and exit. If not, fill the   */
  218. /* dirent portion of the fnode, clear the f_dmod bit and leave, */
  219. /* but only for root directories                                */
  220. if(!(fnp -> f_flags.f_droot)
  221.   && fnp -> f_diroff >= fnp -> f_dsize)
  222. {
  223. fnp -> f_diroff -= DIRENT_SIZE;
  224. return 0;
  225. }
  226. else
  227. {
  228. if(fnp -> f_flags.f_droot)
  229. {
  230. if((fnp -> f_diroff / fnp -> f_dpb -> dpb_secsize
  231.   + fnp -> f_dpb -> dpb_dirstrt)
  232.   >= fnp -> f_dpb -> dpb_data)
  233. {
  234. fnp -> f_flags.f_dfull = TRUE;
  235. return 0;
  236. }
  237. bp = getblock((LONG)(fnp -> f_diroff / fnp -> f_dpb -> dpb_secsize
  238. + fnp -> f_dpb -> dpb_dirstrt),
  239. fnp -> f_dpb -> dpb_unit);
  240. bp -> b_flag &= ~(BFR_DATA | BFR_FAT);
  241. bp -> b_flag |= BFR_DIR;
  242. }
  243. else
  244. {
  245. REG UWORD secsize = fnp -> f_dpb -> dpb_secsize;
  246. /* Do a "seek" to the directory position        */
  247. fnp -> f_offset = fnp -> f_diroff;
  248. /* Search through the FAT to find the block     */
  249. /* that this entry is in.                       */
  250. if(map_cluster(fnp, XFR_READ) != SUCCESS)
  251. {
  252. fnp -> f_flags.f_dfull = TRUE;
  253. return 0;
  254. }
  255. /* If the returned cluster is FREE, return zero */
  256. /* bytes read.                                  */
  257. if(fnp -> f_cluster == FREE)
  258. return 0;
  259. /* If the returned cluster is LAST_CLUSTER or   */
  260. /* LONG_LAST_CLUSTER, return zero bytes read    */
  261. /* and set the directory as full.               */
  262. if(last_link(fnp))
  263. {
  264. fnp -> f_diroff -= DIRENT_SIZE;
  265. fnp -> f_flags.f_dfull = TRUE;
  266. return 0;
  267. }
  268. /* Compute the block within the cluster and the */
  269. /* offset within the block.                     */
  270. fnp -> f_sector =
  271.  (fnp -> f_offset / secsize)
  272.   & fnp -> f_dpb -> dpb_clsmask;
  273. fnp -> f_boff = fnp -> f_offset % secsize;
  274. /* Get the block we need from cache             */
  275. bp = getblock(
  276. (LONG)clus2phys(fnp -> f_cluster,
  277. fnp -> f_dpb -> dpb_clssize,
  278. fnp -> f_dpb -> dpb_data)
  279.  + fnp -> f_sector,
  280. fnp -> f_dpb -> dpb_unit);
  281. bp -> b_flag &= ~(BFR_DATA | BFR_FAT);
  282. bp -> b_flag |= BFR_DIR;
  283. }
  284. /* Now that we have the block for our entry, get the    */
  285. /* directory entry.                                     */
  286. if(bp != NULL)
  287. getdirent((BYTE FAR *)&bp -> b_buffer[fnp -> f_diroff % fnp -> f_dpb -> dpb_secsize],
  288. (struct dirent FAR *)&fnp -> f_dir);
  289. else
  290. {
  291. fnp -> f_flags.f_dfull = TRUE;
  292. return 0;
  293. }
  294. /* Update the fnode's directory info                    */
  295. fnp -> f_flags.f_dfull = FALSE;
  296. fnp -> f_flags.f_dmod = FALSE;
  297. /* and for efficiency, stop when we hit the first       */
  298. /* unused entry.                                        */
  299. if(fnp -> f_dir.dir_name[0] == '')
  300. return 0;
  301. else
  302. return DIRENT_SIZE;
  303. }
  304. }
  305. #ifndef IPL
  306. COUNT 
  307. dir_write (REG struct f_node FAR *fnp)
  308. {
  309. struct buffer FAR *bp;
  310. /* Update the entry if it was modified by a write or create...  */
  311. if(fnp -> f_flags.f_dmod)
  312. {
  313. /* Root is a consecutive set of blocks, so handling is  */
  314. /* simple.                                              */
  315. if(fnp -> f_flags.f_droot)
  316. {
  317. bp =
  318.  getblock(
  319.   (LONG)(fnp -> f_diroff / fnp -> f_dpb -> dpb_secsize
  320.    + fnp -> f_dpb -> dpb_dirstrt),
  321.     fnp -> f_dpb -> dpb_unit);
  322. bp -> b_flag &= ~(BFR_DATA | BFR_FAT);
  323. bp -> b_flag |= BFR_DIR;
  324. }
  325. /* All other directories are just files. The only       */
  326. /* special handling is resetting the offset so that we  */
  327. /* can continually update the same directory entry.     */
  328. else
  329. {
  330. REG UWORD secsize = fnp -> f_dpb -> dpb_secsize;
  331. /* Do a "seek" to the directory position        */
  332. /* and convert the fnode to a directory fnode.  */
  333. fnp -> f_offset = fnp -> f_diroff;
  334. fnp -> f_back = LONG_LAST_CLUSTER;
  335. fnp -> f_cluster = fnp -> f_dirstart;
  336. /* Search through the FAT to find the block     */
  337. /* that this entry is in.                       */
  338. if(map_cluster(fnp, XFR_READ) != SUCCESS)
  339. {
  340. fnp -> f_flags.f_dfull = TRUE;
  341. release_f_node(fnp);
  342. return 0;
  343. }
  344. /* If the returned cluster is FREE, return zero */
  345. /* bytes read.                                  */
  346. if(fnp -> f_cluster == FREE)
  347. {
  348. release_f_node(fnp);
  349. return 0;
  350. }
  351. /* Compute the block within the cluster and the */
  352. /* offset within the block.                     */
  353. fnp -> f_sector =
  354.  (fnp -> f_offset / secsize)
  355.   & fnp -> f_dpb -> dpb_clsmask;
  356. fnp -> f_boff = fnp -> f_offset % secsize;
  357. /* Get the block we need from cache             */
  358. bp = getblock(
  359. (LONG)clus2phys(fnp -> f_cluster,
  360. fnp -> f_dpb -> dpb_clssize,
  361. fnp -> f_dpb -> dpb_data)
  362.  + fnp -> f_sector,
  363. fnp -> f_dpb -> dpb_unit);
  364. bp -> b_flag &= ~(BFR_DATA | BFR_FAT);
  365. bp -> b_flag |= BFR_DIR;
  366. }
  367. /* Now that we have a block, transfer the diectory      */
  368. /* entry into the block.                                */
  369. if(bp == NULL)
  370. {
  371. release_f_node(fnp);
  372. return 0;
  373. }
  374. putdirent((struct dirent FAR *)&fnp -> f_dir,
  375.  (VOID FAR *)&bp -> b_buffer[fnp -> f_diroff % fnp -> f_dpb -> dpb_secsize]);
  376. bp -> b_flag |= BFR_DIRTY;
  377. }
  378. return DIRENT_SIZE;
  379. }
  380. #endif
  381. VOID 
  382. dir_close (REG struct f_node FAR *fnp)
  383. {
  384. REG COUNT disk = fnp -> f_dpb -> dpb_unit;
  385. /* Test for invalid f_nodes                                     */
  386. if(fnp == NULL)
  387. return;
  388. #ifndef IPL
  389. /* Write out the entry                                          */
  390. dir_write(fnp);
  391. #endif 
  392. /* Clear buffers after release                                  */
  393. flush_buffers(disk);
  394. setinvld(disk);
  395. /* and release this instance of the fnode                       */
  396. --(fnp -> f_dpb) -> dpb_count;
  397. release_f_node(fnp);
  398. }
  399. #ifndef IPL
  400. COUNT 
  401. dos_findfirst (UCOUNT attr, BYTE FAR *name)
  402. {
  403. REG struct f_node FAR *fnp;
  404. REG dmatch FAR *dmp = (dmatch FAR *)dta;
  405. REG COUNT i;
  406. COUNT nDrive;
  407. BYTE *p;
  408. /* The findfirst/findnext calls are probably the worst of the   */
  409. /* DOS calls. They must work somewhat on the fly (i.e. - open   */
  410. /* but never close). Since we don't want to lose fnodes every   */
  411. /* time a directory is searched, we will initialize the DOS     */
  412. /* dirmatch structure and then for every find, we will open the */
  413. /* current directory, do a seek and read, then close the fnode. */
  414.    
  415. /* Start out by initializing the dirmatch structure.            */
  416. dmp -> dm_drive = default_drive;
  417. dmp -> dm_entry = 0;
  418. dmp -> dm_cluster = 0;
  419. dmp -> dm_attr_srch = attr;
  420. /* Parse out the drive, file name and file extension. */
  421. ParseDosName(name, &nDrive, &LocalPath[2],
  422. SearchDir.dir_name, SearchDir.dir_ext);
  423. if(nDrive >= 0)
  424. {
  425. dmp -> dm_drive = nDrive;
  426. }
  427. else
  428. nDrive = default_drive;
  429. /* Now build a directory. */
  430. if(!LocalPath[2])
  431. strcpy(&LocalPath[2], ".");
  432. /* Build the match pattern out of the passed string             */
  433. for(p = SearchDir.dir_name, i = 0; i < FNAME_SIZE; i++)
  434. {
  435. /* test for a valid file name terminator                */
  436. if(*p != '')
  437. {
  438. /* If not a wildcard ('*'), just transfer       */
  439. if(*p != '*')
  440. dmp -> dm_name_pat[i] = *p++;
  441. else
  442. {
  443. /* swallow the wildcard                 */
  444. ++p;
  445. /* fill with character wildcard (?)     */
  446. for( ; i < FNAME_SIZE; i++)
  447. dmp -> dm_name_pat[i] = '?';
  448. /* and skip to seperator                */
  449. while(*p != ''
  450.  && *p != '.' && *p != '/' && *p != '\')
  451. ++p;
  452. break;
  453. }
  454. }
  455. else
  456. break;
  457. }
  458. for( ; i < FNAME_SIZE; i++)
  459. dmp -> dm_name_pat[i] = ' ';
  460. /* and the extension (don't forget to add trailing spaces)...   */
  461. i = 0;
  462. for(p = SearchDir.dir_ext; i < FEXT_SIZE; i++)
  463. {
  464. if(*p != '' && *p != '.' && *p != '/' && *p != '\')
  465. {
  466. if(*p != '*')
  467. dmp -> dm_name_pat[i+FNAME_SIZE] = *p++;
  468. else
  469. {
  470. for( ; i < FEXT_SIZE; i++)
  471. dmp -> dm_name_pat[i+FNAME_SIZE] = '?';
  472. break;
  473. }
  474. }
  475. else
  476. break;
  477. }
  478. for( ; i < FEXT_SIZE; i++)
  479. dmp -> dm_name_pat[i+FNAME_SIZE] = ' ';
  480. /* Now search through the directory to find the entry...        */
  481. upMem((BYTE FAR *)dmp -> dm_name_pat, FNAME_SIZE+FEXT_SIZE);
  482. /* Special handling - the volume id is only in the root         */
  483. /* directory and only searched for once.  So we need to open    */
  484. /* the root and return only the first entry that contains the   */
  485. /* volume id bit set.                                           */
  486. if(attr & D_VOLID)
  487. {
  488. /* Now open this directory so that we can read the      */
  489. /* fnode entry and do a match on it.                    */
  490. if((fnp = dir_open((BYTE FAR *)"\")) == NULL)
  491. return DE_PATHNOTFND;
  492. /* Now do the search                                    */
  493. while(dir_read(fnp) == DIRENT_SIZE)
  494. {
  495. /* Test the attribute and return first found    */
  496. if(fnp -> f_dir.dir_attrib & D_VOLID)
  497. {
  498. pop_dmp(dmp, fnp);
  499. dir_close(fnp);
  500. return SUCCESS;
  501. }
  502. }
  503. /* Now that we've done our failed search, close it and  */
  504. /* return an error.                                     */
  505. dir_close(fnp);
  506. return DE_FILENOTFND;
  507. }
  508. /* Otherwise just do a normal find next                         */
  509. else
  510. {
  511. /* Complete building the directory from the passed in */
  512. /* name */
  513. if(nDrive >= 0)
  514. {
  515. LocalPath[0] = 'A' + nDrive;
  516. }
  517. else
  518. {
  519. LocalPath[0] = 'A' + default_drive;
  520. }
  521. LocalPath[1] = ':';
  522. /* Now open this directory so that we can read the      */
  523. /* fnode entry and do a match on it.                    */
  524. if((fnp = dir_open((BYTE FAR *)LocalPath)) == NULL)
  525. return DE_PATHNOTFND;
  526. pop_dmp(dmp, fnp);
  527. dmp -> dm_entry = 0;
  528. if(!fnp -> f_flags.f_droot)
  529. {        
  530. dmp -> dm_cluster = fnp -> f_dirstart;
  531. dmp -> dm_dirstart = fnp -> f_dirstart;
  532. }
  533. else
  534. {
  535. dmp -> dm_cluster = 0;
  536. dmp -> dm_dirstart = 0;
  537. }
  538. dir_close(fnp);
  539. return dos_findnext();
  540. }
  541. }
  542. COUNT 
  543. dos_findnext (void)
  544. {
  545. REG dmatch FAR *dmp = (dmatch FAR *)dta;
  546. REG struct f_node FAR *fnp;
  547. BOOL found = FALSE;
  548. BYTE FAR *p, *q;
  549. /* assign our match parameters pointer.                         */
  550. dmp = (dmatch FAR *)dta;
  551. /* Allocate an fnode if possible - error return (0) if not.     */
  552. if((fnp = get_f_node()) == (struct f_node FAR *)0)
  553. {
  554. return DE_FILENOTFND;
  555. }
  556. /* Force the fnode into read-write mode                         */
  557. fnp -> f_mode = RDWR;
  558. /* Select the default to help non-drive specified path          */
  559. /* searches...                                                  */
  560. fnp -> f_dpb = &blk_devices[dmp -> dm_drive];
  561. ++(fnp -> f_dpb) -> dpb_count;
  562. if(media_check(fnp -> f_dpb) < 0)
  563. {
  564. --(fnp -> f_dpb) -> dpb_count;
  565. release_f_node(fnp);
  566. return DE_FILENOTFND;
  567. }
  568. fnp -> f_dsize = DIRENT_SIZE * (fnp -> f_dpb) -> dpb_dirents;
  569. /* Search through the directory to find the entry, but do a     */
  570. /* seek first.                                                  */
  571. if(dmp -> dm_entry > 0)
  572. fnp -> f_diroff = (dmp -> dm_entry - 1) * DIRENT_SIZE;
  573. fnp -> f_offset = fnp -> f_highwater = fnp -> f_diroff;
  574. fnp -> f_cluster = dmp -> dm_cluster;
  575. fnp -> f_flags.f_dmod = dmp -> dm_flags.f_dmod;
  576. fnp -> f_flags.f_droot = dmp -> dm_flags.f_droot;
  577. fnp -> f_flags.f_dnew = dmp -> dm_flags.f_dnew;
  578. fnp -> f_flags.f_ddir = dmp -> dm_flags.f_ddir;
  579. fnp -> f_flags.f_dfull = dmp -> dm_flags.f_dfull;
  580. fnp -> f_dirstart = dmp -> dm_dirstart;
  581. /* Loop through the directory                                   */
  582. while(dir_read(fnp) == DIRENT_SIZE)
  583. {
  584. ++dmp -> dm_entry;
  585. if(fnp -> f_dir.dir_name[0] != '' && fnp -> f_dir.dir_name[0] != DELETED)
  586. {
  587. if(fcmp_wild((BYTE FAR *)(dmp -> dm_name_pat), (BYTE FAR *)fnp -> f_dir.dir_name, FNAME_SIZE+FEXT_SIZE))
  588. {
  589. /* Test the attribute as the final step */
  590. if(fnp -> f_dir.dir_attrib & D_VOLID)
  591. continue;
  592. else if(
  593.  ((~(dmp -> dm_attr_srch | D_ARCHIVE | D_RDONLY) 
  594.   & fnp -> f_dir.dir_attrib)
  595.  & (D_DIR | D_SYSTEM | D_HIDDEN)) == 0)
  596. {
  597. found = TRUE;
  598. break;
  599. }
  600. else
  601. continue;
  602. }
  603. }
  604. }
  605. /* If found, transfer it to the dmatch structure                */
  606. if(found)
  607. pop_dmp(dmp, fnp);
  608. /* return the result                                            */
  609. --(fnp -> f_dpb) -> dpb_count;
  610. release_f_node(fnp);
  611. return found ? SUCCESS : DE_FILENOTFND;
  612. }
  613. static VOID pop_dmp(dmp, fnp)
  614. dmatch FAR *dmp;
  615. struct f_node FAR *fnp;
  616. {
  617. COUNT idx;
  618. BYTE FAR *p;
  619. BYTE FAR *q;
  620. dmp -> dm_attr_fnd = fnp -> f_dir.dir_attrib;
  621. dmp -> dm_time = fnp -> f_dir.dir_time;
  622. dmp -> dm_date = fnp -> f_dir.dir_date;
  623. dmp -> dm_size = fnp -> f_dir.dir_size;
  624. /* dmp -> dm_cluster = fnp -> f_cluster; */
  625. dmp -> dm_flags.f_droot = fnp -> f_flags.f_droot;
  626. dmp -> dm_flags.f_ddir = fnp -> f_flags.f_ddir;
  627. dmp -> dm_flags.f_dmod = fnp -> f_flags.f_dmod;
  628. dmp -> dm_flags.f_dnew = fnp -> f_flags.f_dnew;
  629. p = dmp -> dm_name;
  630. if(fnp -> f_dir.dir_name[0] == '.')
  631. {
  632. for(idx = 0, q = (BYTE FAR *)fnp -> f_dir.dir_name;
  633.  idx < FNAME_SIZE; idx++)
  634. {
  635. if(*q == ' ')
  636. break;
  637. *p++ = *q++;
  638. }
  639. }
  640. else
  641. {
  642. for(idx = 0, q = (BYTE FAR *)fnp -> f_dir.dir_name;
  643.  idx < FNAME_SIZE; idx++)
  644. {
  645. if(*q == ' ')
  646. break;
  647. *p++ = *q++;
  648. }
  649. if(fnp -> f_dir.dir_ext[0] != ' ')
  650. {
  651. *p++ = '.';
  652. for(idx = 0, q = (BYTE FAR *)fnp -> f_dir.dir_ext; idx < FEXT_SIZE; idx++)
  653. {
  654. if(*q == ' ')
  655. break;
  656. *p++ = *q++;
  657. }
  658. }
  659. }
  660. *p++ = NULL;
  661. }
  662. #endif