2000-05-06 21:34:20 +02:00
|
|
|
/****************************************************************/
|
|
|
|
/* */
|
|
|
|
/* fatdir.c */
|
|
|
|
/* DOS-C */
|
|
|
|
/* */
|
|
|
|
/* FAT File System dir Functions */
|
|
|
|
/* */
|
|
|
|
/* Copyright (c) 1995 */
|
|
|
|
/* Pasquale J. Villani */
|
|
|
|
/* All Rights Reserved */
|
|
|
|
/* */
|
|
|
|
/* This file is part of DOS-C. */
|
|
|
|
/* */
|
|
|
|
/* DOS-C is free software; you can redistribute it and/or */
|
|
|
|
/* modify it under the terms of the GNU General Public License */
|
|
|
|
/* as published by the Free Software Foundation; either version */
|
|
|
|
/* 2, or (at your option) any later version. */
|
|
|
|
/* */
|
|
|
|
/* DOS-C is distributed in the hope that it will be useful, but */
|
|
|
|
/* WITHOUT ANY WARRANTY; without even the implied warranty of */
|
|
|
|
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See */
|
|
|
|
/* the GNU General Public License for more details. */
|
|
|
|
/* */
|
|
|
|
/* You should have received a copy of the GNU General Public */
|
|
|
|
/* License along with DOS-C; see the file COPYING. If not, */
|
|
|
|
/* write to the Free Software Foundation, 675 Mass Ave, */
|
|
|
|
/* Cambridge, MA 02139, USA. */
|
|
|
|
/****************************************************************/
|
|
|
|
|
|
|
|
#include "portab.h"
|
|
|
|
#include "globals.h"
|
|
|
|
|
|
|
|
#ifdef VERSION_STRINGS
|
2001-11-18 15:01:12 +01:00
|
|
|
static BYTE *fatdirRcsId =
|
|
|
|
"$Id$";
|
2000-05-06 21:34:20 +02:00
|
|
|
#endif
|
|
|
|
|
2001-11-04 20:47:39 +01:00
|
|
|
/* Description.
|
|
|
|
* Initialize a fnode so that it will point to the directory with
|
|
|
|
* dirstart starting cluster; in case of passing dirstart == 0
|
|
|
|
* fnode will point to the start of a root directory */
|
|
|
|
VOID dir_init_fnode(f_node_ptr fnp, CLUSTER dirstart)
|
|
|
|
{
|
|
|
|
/* reset the directory flags */
|
2009-06-05 01:40:17 +02:00
|
|
|
fnp->f_sft_idx = 0xff;
|
2009-06-10 18:10:54 +02:00
|
|
|
fnp->f_dmp = &sda_tmp_dm;
|
|
|
|
if (fnp == &fnode[1])
|
|
|
|
fnp->f_dmp = &sda_tmp_dm_ren;
|
2004-03-22 11:29:26 +01:00
|
|
|
fnp->f_offset = 0l;
|
2002-12-09 01:17:15 +01:00
|
|
|
fnp->f_cluster_offset = 0;
|
2001-11-04 20:47:39 +01:00
|
|
|
|
|
|
|
/* root directory */
|
|
|
|
#ifdef WITHFAT32
|
2004-04-13 12:46:37 +02:00
|
|
|
if (dirstart == 0)
|
2001-11-18 15:01:12 +01:00
|
|
|
if (ISFAT32(fnp->f_dpb))
|
2004-04-13 12:46:37 +02:00
|
|
|
dirstart = fnp->f_dpb->dpb_xrootclst;
|
2001-11-04 20:47:39 +01:00
|
|
|
#endif
|
2009-06-10 18:10:54 +02:00
|
|
|
fnp->f_cluster = fnp->f_dmp->dm_dircluster = dirstart;
|
2001-11-04 20:47:39 +01:00
|
|
|
}
|
|
|
|
|
2009-05-20 20:13:37 +02:00
|
|
|
f_node_ptr dir_open(register const char *dirname, f_node_ptr fnp)
|
2000-05-06 21:34:20 +02:00
|
|
|
{
|
2002-08-04 03:14:18 +02:00
|
|
|
int i;
|
2009-06-10 23:08:16 +02:00
|
|
|
char *fcbname;
|
2000-05-06 21:34:20 +02:00
|
|
|
|
2002-08-04 03:14:18 +02:00
|
|
|
/* determine what drive and dpb we are using... */
|
2002-10-22 04:40:19 +02:00
|
|
|
fnp->f_dpb = get_dpb(dirname[0]-'A');
|
2000-05-06 21:34:20 +02:00
|
|
|
/* Perform all directory common handling after all special */
|
|
|
|
/* handling has been performed. */
|
|
|
|
|
2001-07-22 03:58:58 +02:00
|
|
|
if (media_check(fnp->f_dpb) < 0)
|
2001-11-18 15:01:12 +01:00
|
|
|
return (f_node_ptr) 0;
|
2000-05-06 21:34:20 +02:00
|
|
|
|
|
|
|
/* Walk the directory tree to find the starting cluster */
|
|
|
|
/* */
|
2001-11-04 20:47:39 +01:00
|
|
|
/* Start from the root directory (dirstart = 0) */
|
2000-05-06 21:34:20 +02:00
|
|
|
|
2002-08-04 03:14:18 +02:00
|
|
|
/* The CDS's cdsStartCls may be used to shorten the search
|
|
|
|
beginning at the CWD, see mapPath() and CDS.H in order
|
|
|
|
to enable this behaviour there.
|
|
|
|
-- 2001/09/04 ska*/
|
|
|
|
|
2001-11-04 20:47:39 +01:00
|
|
|
dir_init_fnode(fnp, 0);
|
2009-06-10 18:10:54 +02:00
|
|
|
fnp->f_dmp->dm_entry = 0;
|
2001-09-23 22:39:44 +02:00
|
|
|
|
2002-08-04 03:14:18 +02:00
|
|
|
dirname += 2; /* Assume FAT style drive */
|
2009-06-10 23:08:16 +02:00
|
|
|
fcbname = fnp->f_dmp->dm_name_pat;
|
2002-08-04 03:14:18 +02:00
|
|
|
while(*dirname != '\0')
|
2000-05-06 21:34:20 +02:00
|
|
|
{
|
|
|
|
/* skip all path seperators */
|
2002-08-04 03:14:18 +02:00
|
|
|
while (*dirname == '\\')
|
|
|
|
++dirname;
|
2000-05-06 21:34:20 +02:00
|
|
|
/* don't continue if we're at the end */
|
2002-08-04 03:14:18 +02:00
|
|
|
if (*dirname == '\0')
|
2000-05-06 21:34:20 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
/* Convert the name into an absolute name for */
|
|
|
|
/* comparison... */
|
2001-03-21 03:56:26 +01:00
|
|
|
|
2009-06-10 21:02:24 +02:00
|
|
|
dirname = ConvertNameSZToName83(fcbname, dirname);
|
2000-05-06 21:34:20 +02:00
|
|
|
|
|
|
|
/* Now search through the directory to */
|
|
|
|
/* find the entry... */
|
|
|
|
i = FALSE;
|
|
|
|
|
2001-11-04 20:47:39 +01:00
|
|
|
while (dir_read(fnp) == 1)
|
2000-05-06 21:34:20 +02:00
|
|
|
{
|
2002-08-04 03:14:18 +02:00
|
|
|
if (!(fnp->f_dir.dir_attrib & D_VOLID) &&
|
2002-10-22 04:40:19 +02:00
|
|
|
fcbmatch(fcbname, fnp->f_dir.dir_name))
|
2000-05-06 21:34:20 +02:00
|
|
|
{
|
2002-08-04 03:14:18 +02:00
|
|
|
i = TRUE;
|
|
|
|
break;
|
2000-05-06 21:34:20 +02:00
|
|
|
}
|
2009-06-10 18:10:54 +02:00
|
|
|
fnp->f_dmp->dm_entry++;
|
2000-05-06 21:34:20 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!i || !(fnp->f_dir.dir_attrib & D_DIR))
|
|
|
|
{
|
2001-11-18 15:01:12 +01:00
|
|
|
return (f_node_ptr) 0;
|
2000-05-06 21:34:20 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* make certain we've moved off */
|
|
|
|
/* root */
|
2004-01-26 01:51:49 +01:00
|
|
|
dir_init_fnode(fnp, getdstart(fnp->f_dpb, &fnp->f_dir));
|
2009-06-10 18:10:54 +02:00
|
|
|
fnp->f_dmp->dm_entry = 0;
|
2000-05-06 21:34:20 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return fnp;
|
|
|
|
}
|
|
|
|
|
2002-08-04 03:14:18 +02:00
|
|
|
/* swap internal and external delete flags */
|
|
|
|
STATIC void swap_deleted(char *name)
|
|
|
|
{
|
2004-05-23 20:28:18 +02:00
|
|
|
if (name[0] == DELETED || name[0] == EXT_DELETED)
|
|
|
|
name[0] ^= EXT_DELETED - DELETED; /* 0xe0 */
|
2002-08-04 03:14:18 +02:00
|
|
|
}
|
|
|
|
|
2001-11-04 20:47:39 +01:00
|
|
|
/* Description.
|
|
|
|
* Read next consequitive directory entry, pointed by fnp.
|
|
|
|
* If some error occures the other critical
|
|
|
|
* fields aren't changed, except those used for caching.
|
2009-06-10 18:10:54 +02:00
|
|
|
* The fnp->f_dmp->dm_entry always corresponds to the directory entry
|
2001-11-04 20:47:39 +01:00
|
|
|
* which has been read.
|
|
|
|
* Return value.
|
|
|
|
* 1 - all OK, directory entry having been read is not empty.
|
|
|
|
* 0 - Directory entry is empty.
|
2001-11-14 00:36:45 +01:00
|
|
|
* DE_SEEK - Attempt to read beyound the end of the directory.
|
|
|
|
* DE_BLKINVLD - Invalid block.
|
2001-11-04 20:47:39 +01:00
|
|
|
* Note. Empty directory entries always resides at the end of the directory. */
|
2001-06-03 16:16:18 +02:00
|
|
|
COUNT dir_read(REG f_node_ptr fnp)
|
2000-05-06 21:34:20 +02:00
|
|
|
{
|
|
|
|
struct buffer FAR *bp;
|
2001-07-23 14:47:42 +02:00
|
|
|
REG UWORD secsize = fnp->f_dpb->dpb_secsize;
|
2009-05-21 14:57:37 +02:00
|
|
|
unsigned sector;
|
2009-06-10 18:10:54 +02:00
|
|
|
unsigned entry = fnp->f_dmp->dm_entry;
|
2004-03-22 11:29:26 +01:00
|
|
|
|
2004-04-30 19:14:33 +02:00
|
|
|
/* can't have more than 65535 directory entries */
|
2009-06-10 18:10:54 +02:00
|
|
|
if (entry >= 65535U)
|
2004-03-22 16:43:56 +01:00
|
|
|
return DE_SEEK;
|
2000-05-06 21:34:20 +02:00
|
|
|
|
|
|
|
/* Determine if we hit the end of the directory. If we have, */
|
|
|
|
/* bump the offset back to the end and exit. If not, fill the */
|
2009-06-05 02:06:05 +02:00
|
|
|
/* dirent portion of the fnode, set the SFT_FCLEAN bit and leave,*/
|
2000-05-06 21:34:20 +02:00
|
|
|
/* but only for root directories */
|
2001-11-04 20:47:39 +01:00
|
|
|
|
2009-06-10 18:10:54 +02:00
|
|
|
if (fnp->f_dmp->dm_dircluster == 0)
|
2000-05-06 21:34:20 +02:00
|
|
|
{
|
2009-06-10 18:10:54 +02:00
|
|
|
if (entry >= fnp->f_dpb->dpb_dirents)
|
2001-11-14 00:36:45 +01:00
|
|
|
return DE_SEEK;
|
2000-05-06 21:34:20 +02:00
|
|
|
|
2009-06-10 18:10:54 +02:00
|
|
|
fnp->f_dirsector = entry / (secsize / DIRENT_SIZE) +
|
2009-05-21 14:57:37 +02:00
|
|
|
fnp->f_dpb->dpb_dirstrt;
|
2001-11-04 20:47:39 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Do a "seek" to the directory position */
|
2009-06-10 18:10:54 +02:00
|
|
|
fnp->f_offset = entry * (ULONG)DIRENT_SIZE;
|
2000-05-06 21:34:20 +02:00
|
|
|
|
2001-11-04 20:47:39 +01:00
|
|
|
/* Search through the FAT to find the block */
|
|
|
|
/* that this entry is in. */
|
2001-11-14 00:36:45 +01:00
|
|
|
if (map_cluster(fnp, XFR_READ) != SUCCESS)
|
|
|
|
return DE_SEEK;
|
2000-05-06 21:34:20 +02:00
|
|
|
|
2009-05-21 14:57:37 +02:00
|
|
|
/* Compute the block within the cluster and the */
|
|
|
|
/* offset within the block. */
|
|
|
|
sector = (UBYTE)(fnp->f_offset / secsize) & fnp->f_dpb->dpb_clsmask;
|
|
|
|
|
|
|
|
fnp->f_dirsector = clus2phys(fnp->f_cluster, fnp->f_dpb) + sector;
|
|
|
|
/* Get the block we need from cache */
|
|
|
|
}
|
|
|
|
|
|
|
|
bp = getblock(fnp->f_dirsector, fnp->f_dpb->dpb_unit);
|
|
|
|
|
2000-05-06 21:34:20 +02:00
|
|
|
#ifdef DISPLAY_GETBLOCK
|
2009-05-21 14:57:37 +02:00
|
|
|
printf("DIR (dir_read)\n");
|
2000-05-06 21:34:20 +02:00
|
|
|
#endif
|
|
|
|
|
2001-11-04 20:47:39 +01:00
|
|
|
/* Now that we have the block for our entry, get the */
|
|
|
|
/* directory entry. */
|
|
|
|
if (bp == NULL)
|
|
|
|
return DE_BLKINVLD;
|
2000-05-06 21:34:20 +02:00
|
|
|
|
2001-11-04 20:47:39 +01:00
|
|
|
bp->b_flag &= ~(BFR_DATA | BFR_FAT);
|
|
|
|
bp->b_flag |= BFR_DIR | BFR_VALID;
|
2001-07-23 14:47:42 +02:00
|
|
|
|
2009-06-10 18:10:54 +02:00
|
|
|
fnp->f_diridx = entry % (secsize / DIRENT_SIZE);
|
2009-05-21 14:57:37 +02:00
|
|
|
getdirent(&bp->b_buffer[fnp->f_diridx * DIRENT_SIZE], &fnp->f_dir);
|
2001-07-23 14:47:42 +02:00
|
|
|
|
2002-08-04 03:14:18 +02:00
|
|
|
swap_deleted(fnp->f_dir.dir_name);
|
|
|
|
|
2001-11-04 20:47:39 +01:00
|
|
|
/* and for efficiency, stop when we hit the first */
|
|
|
|
/* unused entry. */
|
|
|
|
/* either returns 1 or 0 */
|
|
|
|
return (fnp->f_dir.dir_name[0] != '\0');
|
2000-05-06 21:34:20 +02:00
|
|
|
}
|
|
|
|
|
2001-11-04 20:47:39 +01:00
|
|
|
/* Description.
|
|
|
|
* Writes directory entry pointed by fnp to disk. In case of erroneous
|
|
|
|
* situation fnode is released.
|
2002-01-23 23:29:41 +01:00
|
|
|
* The caller should set
|
2004-04-13 12:46:37 +02:00
|
|
|
* 1. F_DMOD flag if original directory entry was modified.
|
2001-11-04 20:47:39 +01:00
|
|
|
* Return value.
|
|
|
|
* TRUE - all OK.
|
|
|
|
* FALSE - error occured (fnode is released).
|
|
|
|
*/
|
2009-05-22 02:25:11 +02:00
|
|
|
BOOL dir_write_update(REG f_node_ptr fnp, BOOL update)
|
2000-05-06 21:34:20 +02:00
|
|
|
{
|
|
|
|
struct buffer FAR *bp;
|
2009-05-22 02:25:11 +02:00
|
|
|
UBYTE FAR *vp;
|
2000-05-06 21:34:20 +02:00
|
|
|
|
|
|
|
/* Update the entry if it was modified by a write or create... */
|
2009-06-11 14:33:30 +02:00
|
|
|
if (!update || (fnp->f_flags & (SFT_FCLEAN|SFT_FDATE)) != SFT_FCLEAN)
|
2000-05-06 21:34:20 +02:00
|
|
|
{
|
2009-05-21 14:57:37 +02:00
|
|
|
bp = getblock(fnp->f_dirsector, fnp->f_dpb->dpb_unit);
|
2000-05-06 21:34:20 +02:00
|
|
|
|
2001-04-29 19:34:41 +02:00
|
|
|
/* Now that we have a block, transfer the directory */
|
2000-05-06 21:34:20 +02:00
|
|
|
/* entry into the block. */
|
|
|
|
if (bp == NULL)
|
2001-11-04 20:47:39 +01:00
|
|
|
return FALSE;
|
2001-11-18 15:01:12 +01:00
|
|
|
|
2009-05-21 14:57:37 +02:00
|
|
|
#ifdef DISPLAY_GETBLOCK
|
|
|
|
printf("DIR (dir_write)\n");
|
|
|
|
#endif
|
|
|
|
|
2002-08-04 03:14:18 +02:00
|
|
|
swap_deleted(fnp->f_dir.dir_name);
|
|
|
|
|
2009-05-22 02:25:11 +02:00
|
|
|
vp = &bp->b_buffer[fnp->f_diridx * DIRENT_SIZE];
|
|
|
|
|
|
|
|
if (update)
|
|
|
|
{
|
|
|
|
/* only update fields that are also in the SFT, for dos_close/commit */
|
|
|
|
fmemcpy(&vp[DIR_NAME], fnp->f_dir.dir_name, FNAME_SIZE + FEXT_SIZE);
|
|
|
|
fputbyte(&vp[DIR_ATTRIB], fnp->f_dir.dir_attrib);
|
|
|
|
fputword(&vp[DIR_TIME], fnp->f_dir.dir_time);
|
|
|
|
fputword(&vp[DIR_DATE], fnp->f_dir.dir_date);
|
|
|
|
fputword(&vp[DIR_START], fnp->f_dir.dir_start);
|
|
|
|
#ifdef WITHFAT32
|
|
|
|
if (ISFAT32(fnp->f_dpb))
|
|
|
|
fputword(&vp[DIR_START_HIGH], fnp->f_dir.dir_start_high);
|
|
|
|
#endif
|
|
|
|
fputlong(&vp[DIR_SIZE], fnp->f_dir.dir_size);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
putdirent(&fnp->f_dir, vp);
|
|
|
|
}
|
2001-07-23 14:47:42 +02:00
|
|
|
|
2002-08-04 03:14:18 +02:00
|
|
|
swap_deleted(fnp->f_dir.dir_name);
|
|
|
|
|
2001-07-23 14:47:42 +02:00
|
|
|
bp->b_flag &= ~(BFR_DATA | BFR_FAT);
|
|
|
|
bp->b_flag |= BFR_DIR | BFR_DIRTY | BFR_VALID;
|
2000-05-06 21:34:20 +02:00
|
|
|
}
|
2009-05-29 02:25:38 +02:00
|
|
|
/* Clear buffers after directory write or DOS close */
|
|
|
|
/* hazard: no error checking! */
|
2002-01-23 23:29:41 +01:00
|
|
|
flush_buffers(fnp->f_dpb->dpb_unit);
|
2009-05-29 02:25:38 +02:00
|
|
|
return TRUE;
|
2000-05-06 21:34:20 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#ifndef IPL
|
2001-11-18 15:01:12 +01:00
|
|
|
COUNT dos_findfirst(UCOUNT attr, BYTE * name)
|
2000-05-06 21:34:20 +02:00
|
|
|
{
|
2001-06-03 16:16:18 +02:00
|
|
|
REG f_node_ptr fnp;
|
2002-10-22 04:40:19 +02:00
|
|
|
REG dmatch *dmp = &sda_tmp_dm;
|
2000-05-06 21:34:20 +02:00
|
|
|
REG COUNT i;
|
2001-07-10 00:19:33 +02:00
|
|
|
|
|
|
|
/* printf("ff %Fs\n", name);*/
|
|
|
|
|
2000-05-06 21:34:20 +02:00
|
|
|
/* The findfirst/findnext calls are probably the worst of the */
|
|
|
|
/* DOS calls. They must work somewhat on the fly (i.e. - open */
|
2009-05-29 02:25:38 +02:00
|
|
|
/* but never close). The near fnodes now work this way. Every */
|
2000-05-06 21:34:20 +02:00
|
|
|
/* time a directory is searched, we will initialize the DOS */
|
|
|
|
/* dirmatch structure and then for every find, we will open the */
|
2009-05-29 02:25:38 +02:00
|
|
|
/* current directory, do a seek and read. */
|
2000-05-06 21:34:20 +02:00
|
|
|
|
2004-03-07 13:59:38 +01:00
|
|
|
/* Parse out the file name */
|
2009-06-10 21:02:24 +02:00
|
|
|
i = ParseDosName(name, TRUE);
|
2002-08-04 03:14:18 +02:00
|
|
|
if (i < SUCCESS)
|
2000-05-06 21:34:20 +02:00
|
|
|
return i;
|
2000-06-01 08:46:57 +02:00
|
|
|
/*
|
2000-06-01 08:37:38 +02:00
|
|
|
printf("\nff %s", Tname);
|
2002-08-04 03:14:18 +02:00
|
|
|
printf("ff %s", fcbname);
|
2000-06-01 08:46:57 +02:00
|
|
|
*/
|
2000-05-06 21:34:20 +02:00
|
|
|
|
|
|
|
/* Now search through the directory to find the entry... */
|
2001-04-15 05:21:50 +02:00
|
|
|
|
2000-05-06 21:34:20 +02:00
|
|
|
/* Special handling - the volume id is only in the root */
|
|
|
|
/* directory and only searched for once. So we need to open */
|
|
|
|
/* the root and return only the first entry that contains the */
|
2007-05-21 04:17:44 +02:00
|
|
|
/* volume id bit set (while ignoring LFN entries). */
|
|
|
|
/* RBIL: ignore ReaDONLY and ARCHIVE bits */
|
|
|
|
/* For compatibility with bad search requests, only treat as */
|
|
|
|
/* volume search if only volume bit set, else ignore it. */
|
|
|
|
if ((attr & ~(D_RDONLY | D_ARCHIVE))==D_VOLID) /* if ONLY label wanted */
|
|
|
|
i = 3; /* redirect search to root dir (?) in volume label case */
|
|
|
|
else
|
|
|
|
attr &= ~D_VOLID; /* ignore volume mask */
|
|
|
|
|
2001-04-15 05:21:50 +02:00
|
|
|
/* Now open this directory so that we can read the */
|
|
|
|
/* fnode entry and do a match on it. */
|
2001-11-18 15:01:12 +01:00
|
|
|
|
2001-07-22 03:58:58 +02:00
|
|
|
/* printf("dir_open %s\n", szDirName);*/
|
2002-08-04 03:14:18 +02:00
|
|
|
{
|
|
|
|
char tmp = name[i];
|
|
|
|
name[i] = '\0';
|
2009-05-20 20:13:37 +02:00
|
|
|
if ((fnp = dir_open(name, &fnode[0])) == NULL)
|
2002-08-04 03:14:18 +02:00
|
|
|
return DE_PATHNOTFND;
|
|
|
|
name[i] = tmp;
|
|
|
|
}
|
2000-05-06 21:34:20 +02:00
|
|
|
|
2001-07-24 18:56:29 +02:00
|
|
|
/* Now initialize the dirmatch structure. */
|
2009-06-10 21:02:24 +02:00
|
|
|
ConvertNameSZToName83(dmp->dm_name_pat, &name[i]);
|
2002-08-04 03:14:18 +02:00
|
|
|
dmp->dm_drive = name[0] - 'A';
|
2001-07-24 18:56:29 +02:00
|
|
|
dmp->dm_attr_srch = attr;
|
|
|
|
|
2003-06-15 20:47:25 +02:00
|
|
|
if ((attr & (D_VOLID|D_DIR))==D_VOLID)
|
2001-04-15 05:21:50 +02:00
|
|
|
{
|
2000-05-06 21:34:20 +02:00
|
|
|
/* Now do the search */
|
2001-11-04 20:47:39 +01:00
|
|
|
while (dir_read(fnp) == 1)
|
2000-05-06 21:34:20 +02:00
|
|
|
{
|
|
|
|
/* Test the attribute and return first found */
|
2002-02-16 20:20:20 +01:00
|
|
|
if ((fnp->f_dir.dir_attrib & ~(D_RDONLY | D_ARCHIVE)) == D_VOLID &&
|
|
|
|
fnp->f_dir.dir_name[0] != DELETED)
|
2000-05-06 21:34:20 +02:00
|
|
|
{
|
2001-07-24 18:56:29 +02:00
|
|
|
memcpy(&SearchDir, &fnp->f_dir, sizeof(struct dirent));
|
2002-01-23 23:29:41 +01:00
|
|
|
#ifdef DEBUG
|
|
|
|
printf("dos_findfirst: %11s\n", fnp->f_dir.dir_name);
|
|
|
|
#endif
|
2000-05-06 21:34:20 +02:00
|
|
|
return SUCCESS;
|
|
|
|
}
|
2009-06-10 18:10:54 +02:00
|
|
|
dmp->dm_entry++;
|
2000-05-06 21:34:20 +02:00
|
|
|
}
|
|
|
|
|
2009-05-29 02:25:38 +02:00
|
|
|
/* Now that we've done our failed search, return an error. */
|
2002-11-09 20:13:56 +01:00
|
|
|
return DE_NFILES;
|
2000-05-06 21:34:20 +02:00
|
|
|
}
|
|
|
|
/* Otherwise just do a normal find next */
|
2009-06-10 18:10:54 +02:00
|
|
|
return dos_findnext();
|
2000-05-06 21:34:20 +02:00
|
|
|
}
|
2001-11-18 15:01:12 +01:00
|
|
|
|
2001-07-10 00:19:33 +02:00
|
|
|
/*
|
|
|
|
BUGFIX TE 06/28/01
|
|
|
|
|
|
|
|
when using FcbFindXxx, the only information available is
|
|
|
|
the cluster number + entrycount. everything else MUST\
|
|
|
|
be recalculated.
|
|
|
|
a good test for this is MSDOS CHKDSK, which now (seems too) work
|
|
|
|
*/
|
2000-05-06 21:34:20 +02:00
|
|
|
|
|
|
|
COUNT dos_findnext(void)
|
|
|
|
{
|
2001-06-03 16:16:18 +02:00
|
|
|
REG f_node_ptr fnp;
|
2009-06-10 18:10:54 +02:00
|
|
|
REG dmatch *dmp;
|
2000-05-06 21:34:20 +02:00
|
|
|
|
|
|
|
/* Select the default to help non-drive specified path */
|
|
|
|
/* searches... */
|
2009-06-10 18:10:54 +02:00
|
|
|
fnp = &fnode[0];
|
2009-06-10 21:02:24 +02:00
|
|
|
dmp = &sda_tmp_dm;
|
2002-10-22 04:40:19 +02:00
|
|
|
fnp->f_dpb = get_dpb(dmp->dm_drive);
|
2000-05-06 21:34:20 +02:00
|
|
|
if (media_check(fnp->f_dpb) < 0)
|
2001-04-15 05:21:50 +02:00
|
|
|
return DE_NFILES;
|
2000-05-06 21:34:20 +02:00
|
|
|
|
2001-11-04 20:47:39 +01:00
|
|
|
dir_init_fnode(fnp, dmp->dm_dircluster);
|
2000-05-06 21:34:20 +02:00
|
|
|
|
|
|
|
/* Search through the directory to find the entry, but do a */
|
|
|
|
/* seek first. */
|
|
|
|
/* Loop through the directory */
|
2001-11-04 20:47:39 +01:00
|
|
|
while (dir_read(fnp) == 1)
|
2000-05-06 21:34:20 +02:00
|
|
|
{
|
|
|
|
++dmp->dm_entry;
|
2001-09-23 22:39:44 +02:00
|
|
|
if (fnp->f_dir.dir_name[0] != '\0' && fnp->f_dir.dir_name[0] != DELETED
|
2004-05-23 20:28:18 +02:00
|
|
|
&& !(fnp->f_dir.dir_attrib & D_VOLID))
|
2000-05-06 21:34:20 +02:00
|
|
|
{
|
2002-08-04 03:14:18 +02:00
|
|
|
if (fcmp_wild(dmp->dm_name_pat, fnp->f_dir.dir_name, FNAME_SIZE + FEXT_SIZE))
|
2000-05-06 21:34:20 +02:00
|
|
|
{
|
2000-06-21 20:16:46 +02:00
|
|
|
/*
|
2001-11-18 15:01:12 +01:00
|
|
|
MSD Command.com uses FCB FN 11 & 12 with attrib set to 0x16.
|
|
|
|
Bits 0x21 seem to get set some where in MSD so Rd and Arc
|
|
|
|
files are returned.
|
|
|
|
RdOnly + Archive bits are ignored
|
2000-06-21 20:16:46 +02:00
|
|
|
*/
|
2001-11-18 15:01:12 +01:00
|
|
|
|
2000-05-06 21:34:20 +02:00
|
|
|
/* Test the attribute as the final step */
|
2001-08-19 14:58:36 +02:00
|
|
|
if (!(fnp->f_dir.dir_attrib & D_VOLID) &&
|
2003-06-15 20:47:25 +02:00
|
|
|
!(~dmp->dm_attr_srch & (D_DIR | D_SYSTEM | D_HIDDEN) &
|
|
|
|
fnp->f_dir.dir_attrib))
|
2000-05-06 21:34:20 +02:00
|
|
|
{
|
2003-06-15 20:47:25 +02:00
|
|
|
/* If found, transfer it to the dmatch structure */
|
|
|
|
memcpy(&SearchDir, &fnp->f_dir, sizeof(struct dirent));
|
|
|
|
/* return the result */
|
|
|
|
return SUCCESS;
|
2000-05-06 21:34:20 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-01-23 23:29:41 +01:00
|
|
|
#ifdef DEBUG
|
|
|
|
printf("dos_findnext: %11s\n", fnp->f_dir.dir_name);
|
|
|
|
#endif
|
2000-05-06 21:34:20 +02:00
|
|
|
/* return the result */
|
2003-06-15 20:47:25 +02:00
|
|
|
return DE_NFILES;
|
2000-05-06 21:34:20 +02:00
|
|
|
}
|
2001-03-21 03:56:26 +01:00
|
|
|
#endif
|
|
|
|
/*
|
|
|
|
this receives a name in 11 char field NAME+EXT and builds
|
|
|
|
a zeroterminated string
|
2001-06-03 16:16:18 +02:00
|
|
|
|
|
|
|
unfortunately, blanks are allowed in filenames. like
|
|
|
|
"test e", " test .y z",...
|
|
|
|
|
|
|
|
so we have to work from the last blank backward
|
2001-11-18 15:01:12 +01:00
|
|
|
*/
|
|
|
|
void ConvertName83ToNameSZ(BYTE FAR * destSZ, BYTE FAR * srcFCBName)
|
2001-03-21 03:56:26 +01:00
|
|
|
{
|
2001-11-18 15:01:12 +01:00
|
|
|
int loop;
|
|
|
|
int noExtension = FALSE;
|
2001-06-03 16:16:18 +02:00
|
|
|
|
2001-11-18 15:01:12 +01:00
|
|
|
if (*srcFCBName == '.')
|
|
|
|
{
|
|
|
|
noExtension = TRUE;
|
|
|
|
}
|
2001-06-03 16:16:18 +02:00
|
|
|
|
2001-11-18 15:01:12 +01:00
|
|
|
fmemcpy(destSZ, srcFCBName, FNAME_SIZE);
|
|
|
|
|
|
|
|
srcFCBName += FNAME_SIZE;
|
|
|
|
|
|
|
|
for (loop = FNAME_SIZE; --loop >= 0;)
|
|
|
|
{
|
|
|
|
if (destSZ[loop] != ' ')
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
destSZ += loop + 1;
|
|
|
|
|
|
|
|
if (!noExtension) /* not for ".", ".." */
|
|
|
|
{
|
|
|
|
|
|
|
|
for (loop = FEXT_SIZE; --loop >= 0;)
|
2000-05-06 21:34:20 +02:00
|
|
|
{
|
2001-11-18 15:01:12 +01:00
|
|
|
if (srcFCBName[loop] != ' ')
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (loop >= 0)
|
|
|
|
{
|
|
|
|
*destSZ++ = '.';
|
|
|
|
fmemcpy(destSZ, srcFCBName, loop + 1);
|
|
|
|
destSZ += loop + 1;
|
2000-05-06 21:34:20 +02:00
|
|
|
}
|
2001-11-18 15:01:12 +01:00
|
|
|
}
|
|
|
|
*destSZ = '\0';
|
2000-05-06 21:34:20 +02:00
|
|
|
}
|
2001-06-03 16:16:18 +02:00
|
|
|
|
2002-08-04 03:14:18 +02:00
|
|
|
#if 0
|
2001-06-03 16:16:18 +02:00
|
|
|
/*
|
|
|
|
returns the asciiSZ length of a 8.3 filename
|
2001-11-18 15:01:12 +01:00
|
|
|
*/
|
2001-06-03 16:16:18 +02:00
|
|
|
|
2001-11-18 15:01:12 +01:00
|
|
|
int FileName83Length(BYTE * filename83)
|
2001-06-03 16:16:18 +02:00
|
|
|
{
|
2001-11-18 15:01:12 +01:00
|
|
|
BYTE buff[13];
|
2001-06-03 16:16:18 +02:00
|
|
|
|
2001-11-18 15:01:12 +01:00
|
|
|
ConvertName83ToNameSZ(buff, filename83);
|
|
|
|
|
|
|
|
return strlen(buff);
|
2001-07-24 18:56:29 +02:00
|
|
|
}
|
2002-08-04 03:14:18 +02:00
|
|
|
#endif
|
2001-11-18 00:26:45 +01:00
|
|
|
|
2009-06-10 21:02:24 +02:00
|
|
|
/* this routine converts a name portion of a fully qualified path */
|
|
|
|
/* name, so . and .. are not allowed, only straightforward 8+3 names */
|
|
|
|
const char *ConvertNameSZToName83(char *fcbname, const char *dirname)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
memset(fcbname, ' ', FNAME_SIZE + FEXT_SIZE);
|
|
|
|
|
|
|
|
for (i = 0; i < FNAME_SIZE + FEXT_SIZE; i++, dirname++)
|
|
|
|
{
|
|
|
|
char c = *dirname;
|
|
|
|
if (c == '.')
|
|
|
|
i = FNAME_SIZE - 1;
|
|
|
|
else if (c != '\0' && c != '\\')
|
|
|
|
fcbname[i] = c;
|
|
|
|
else
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return dirname;
|
|
|
|
}
|
|
|
|
|