mirror of
https://github.com/peteratebs/rtfsprorelease.git
synced 2025-06-19 01:05:39 -04:00
416 lines
14 KiB
C
416 lines
14 KiB
C
/*
|
|
* EBS - RTFS (Real Time File Manager)
|
|
*
|
|
* Copyright EBS Inc. 1987-2003
|
|
* All rights reserved.
|
|
* This code may not be redistributed in source or linkable object form
|
|
* without the consent of its author.
|
|
*/
|
|
/* APIGFRST.C - Contains user api level source code.
|
|
|
|
The following routines are included:
|
|
|
|
pc_gfirst - Get stats on the first file to match a pattern.
|
|
pc_gnext - Get stats on the next file to match a pattern.
|
|
pc_gdone - Free resources used by pc_gfirst/pc_gnext.
|
|
pc_upstat - Copy directory entry info to a user s stat buffer
|
|
|
|
|
|
*/
|
|
|
|
#include "rtfs.h"
|
|
|
|
|
|
#if (INCLUDE_CS_UNICODE)
|
|
static BOOLEAN _pc_gfirst_cs(DSTAT *statobj, byte *name, int use_charset);
|
|
#else
|
|
static BOOLEAN _pc_gfirst(DSTAT *statobj, byte *name);
|
|
#endif
|
|
#if (INCLUDE_REVERSEDIR)
|
|
#if (INCLUDE_CS_UNICODE)
|
|
BOOLEAN pc_glast_cs(DSTAT *statobj, byte *name, int use_charset)
|
|
#else
|
|
BOOLEAN pc_glast(DSTAT *statobj, byte *name) /*__apifn__*/
|
|
#endif
|
|
{
|
|
statobj->search_backwards_if_magic = SEARCH_BACKWARDS_MAGIC_NUMBER;
|
|
#if (INCLUDE_CS_UNICODE)
|
|
return (_pc_gfirst_cs(statobj, name, use_charset));
|
|
#else
|
|
return(_pc_gfirst(statobj, name));
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
|
|
/***************************************************************************
|
|
PC_GFIRST - Get first entry in a directory to match a pattern.
|
|
|
|
Description
|
|
Given a pattern which contains both a path specifier and a search pattern
|
|
fill in the structure at statobj with information about the file and set
|
|
up internal parts of statobj to supply appropriate information for calls
|
|
to pc_gnext.
|
|
|
|
Examples of patterns are:
|
|
D:\USR\RELEASE\NETWORK\*.C
|
|
D:\USR\BIN\UU*.*
|
|
D:MEMO_?.*
|
|
D:*.*
|
|
|
|
Returns
|
|
Returns TRUE if a match was found otherwise FALSE. (see also the pcls.c
|
|
utility.)
|
|
|
|
errno is set to one of the following
|
|
0 - No error
|
|
PEINVALIDDRIVEID- Drive component is invalid
|
|
PEINVALIDPATH - Path specified badly formed.
|
|
PENOENT - Not found, no match
|
|
An ERTFS system error
|
|
|
|
****************************************************************************/
|
|
|
|
static void pc_upstat(DSTAT *statobj, int use_charset);
|
|
|
|
#if (INCLUDE_CS_UNICODE)
|
|
BOOLEAN pc_gfirst_cs(DSTAT *statobj, byte *name, int use_charset)
|
|
#else
|
|
BOOLEAN pc_gfirst(DSTAT *statobj, byte *name) /*__apifn__*/
|
|
#endif
|
|
{
|
|
#if (INCLUDE_EXFATORFAT64)
|
|
if (statobj->search_backwards_if_magic!=SYS_SCAN_MAGIC_NUMBER) /* system scan overrides default behavior */
|
|
#endif
|
|
statobj->search_backwards_if_magic = 0;
|
|
#if (INCLUDE_CS_UNICODE)
|
|
return (_pc_gfirst_cs(statobj, name, use_charset));
|
|
#else
|
|
return(_pc_gfirst(statobj, name));
|
|
#endif
|
|
}
|
|
|
|
#if (INCLUDE_CS_UNICODE)
|
|
static BOOLEAN _pc_gfirst_cs(DSTAT *statobj, byte *name, int use_charset)
|
|
#else
|
|
static BOOLEAN _pc_gfirst(DSTAT *statobj, byte *name) /*__apifn__*/
|
|
#endif
|
|
{
|
|
byte *mompath;
|
|
byte *filename;
|
|
byte fileext[4];
|
|
int driveno;
|
|
DDRIVE *pdrive;
|
|
BOOLEAN ret_val;
|
|
|
|
|
|
|
|
CHECK_MEM(BOOLEAN, 0) /* Make sure memory is initted */
|
|
|
|
rtfs_clear_errno(); /* po_gfirst: clear error status */
|
|
|
|
{
|
|
dword save_magic = statobj->search_backwards_if_magic;
|
|
rtfs_memset((byte *) statobj,0,sizeof(*statobj));
|
|
/* statobj->pobj = 0; */
|
|
/* statobj->pmom = 0; */
|
|
statobj->search_backwards_if_magic = save_magic;
|
|
}
|
|
|
|
|
|
/* Get the drive and make sure it is mounted */
|
|
driveno = check_drive_name_mount(name, CS_CHARSET_ARGS);
|
|
if (driveno < 0)
|
|
{
|
|
/* errno was set by check_drive */
|
|
return(FALSE);
|
|
}
|
|
pdrive = pc_drno2dr(driveno);
|
|
ret_val = FALSE;
|
|
/* Allocate scratch buffers in the DRIVE structure. */
|
|
if (!pc_alloc_path_buffers(pdrive))
|
|
goto errex;
|
|
mompath = pdrive->pathname_buffer;
|
|
filename = pdrive->filename_buffer;
|
|
rtfs_memset((byte *)&fileext[0],0,sizeof(fileext)); /* Zero fill fileext because we will not use it */
|
|
/* Get out the filename and d:parent */
|
|
if (!pc_parsepath(mompath,filename,fileext,name, CS_CHARSET_ARGS))
|
|
{
|
|
rtfs_set_errno(PEINVALIDPATH, __FILE__, __LINE__);
|
|
goto errex;
|
|
}
|
|
|
|
/* Save the pattern. we will need it in pc_gnext */
|
|
copybuff(statobj->pname, filename, FILENAMESIZE_BYTES);
|
|
copybuff(statobj->pext, fileext, 4);
|
|
/* Copy over the path. we will need it later */
|
|
copybuff(statobj->path, mompath, EMAXPATH_BYTES);
|
|
/* Find the file and init the structure */
|
|
statobj->pmom = (void *) pc_fndnode(mompath, CS_CHARSET_ARGS);
|
|
/* pc_fndnode will set errno */
|
|
if (statobj->pmom)
|
|
/* Found it. Check access permissions */
|
|
{
|
|
if(pc_isadir((DROBJ *)(statobj->pmom)))
|
|
{
|
|
#if (INCLUDE_REVERSEDIR)
|
|
/* Now find pattern in the directory */
|
|
if (statobj->search_backwards_if_magic == SEARCH_BACKWARDS_MAGIC_NUMBER)
|
|
statobj->pobj = (void *) pc_rget_inode(0, (DROBJ *)(statobj->pmom), filename, (byte*) fileext, GET_INODE_WILD, CS_CHARSET_ARGS);
|
|
else
|
|
#endif
|
|
statobj->pobj = (void *) pc_get_inode(0, (DROBJ *)(statobj->pmom), filename, (byte*) fileext, GET_INODE_WILD, CS_CHARSET_ARGS);
|
|
|
|
if (statobj->pobj)
|
|
{
|
|
/* And update the stat structure */
|
|
pc_upstat(statobj, CS_CHARSET_ARGS);
|
|
/* remember the drive number. used by gnext et al. */
|
|
statobj->driveno = driveno;
|
|
#if (INCLUDE_EXFATORFAT64)
|
|
if (statobj->search_backwards_if_magic!=SYS_SCAN_MAGIC_NUMBER) /* EXFAT system scan uses and then frees the finode at a higher layer */
|
|
#endif
|
|
{
|
|
pc_freei(((DROBJ *)(statobj->pobj))->finode); /* Release the current */
|
|
((DROBJ *)(statobj->pobj))->finode = 0;
|
|
}
|
|
statobj->drive_opencounter = pdrive->drive_opencounter;
|
|
ret_val = TRUE;
|
|
goto errex;
|
|
}
|
|
else
|
|
{
|
|
/* pc_gfirst: if statobj->pobj is 0 pc_get_inode() has set errno to PENOENT or
|
|
to an internal or IO error status
|
|
if PENOENT set we will clear errno */
|
|
if (get_errno() == PENOENT)
|
|
rtfs_clear_errno(); /* pc_gfirst: file not found in directory
|
|
set errno to zero and return FALSE */
|
|
}
|
|
}
|
|
else
|
|
rtfs_set_errno(PENOENT, __FILE__, __LINE__); /* pc_gfirst: Path not a directory, report not found */
|
|
}
|
|
/* If it gets here we had a problem ret_val is false */
|
|
if (statobj->pmom)
|
|
pc_freeobj((DROBJ *)statobj->pmom);
|
|
rtfs_memset((byte *) statobj,0,sizeof(*statobj));
|
|
errex:
|
|
pc_release_path_buffers(pdrive);
|
|
release_drive_mount(driveno);/* Release lock, unmount if aborted */
|
|
return(ret_val);
|
|
}
|
|
|
|
/****************************************************************************
|
|
PC_GNEXT - Get next entry in a directory that matches a pattern.
|
|
|
|
Description
|
|
Given a pointer to a DSTAT structure that has been set up by a call to
|
|
pc_gfirst(), search for the next match of the original pattern in the
|
|
original path. Return TRUE if found and update statobj for subsequent
|
|
calls to pc_gnext.
|
|
|
|
Returns
|
|
Returns TRUE if a match was found otherwise FALSE.
|
|
|
|
errno is set to one of the following
|
|
0 - No error
|
|
PEINVALIDPARMS - statobj argument is not valid
|
|
PENOENT - Not found, no match (normal termination of scan)
|
|
An ERTFS system error
|
|
****************************************************************************/
|
|
#if (INCLUDE_REVERSEDIR)
|
|
#if (INCLUDE_CS_UNICODE)
|
|
BOOLEAN pc_gprev_cs(DSTAT *statobj, int use_charset)
|
|
#else
|
|
BOOLEAN pc_gprev(DSTAT *statobj)
|
|
#endif
|
|
{
|
|
statobj->search_backwards_if_magic = SEARCH_BACKWARDS_MAGIC_NUMBER;
|
|
|
|
#if (INCLUDE_CS_UNICODE)
|
|
return pc_gnext_cs(statobj, use_charset);
|
|
#else
|
|
return pc_gnext(statobj);
|
|
#endif
|
|
}
|
|
#endif
|
|
#if (INCLUDE_CS_UNICODE)
|
|
BOOLEAN pc_gnext_cs(DSTAT *statobj, int use_charset)
|
|
#else
|
|
BOOLEAN pc_gnext(DSTAT *statobj)
|
|
#endif
|
|
{
|
|
DROBJ *nextobj;
|
|
DDRIVE *pdrive;
|
|
CHECK_MEM(BOOLEAN, 0) /* Make sure memory is initted */
|
|
/* see if the drive is still mounted. Do not use pmom et al. since they
|
|
may be purged */
|
|
if (!statobj || !statobj->pmom)
|
|
{
|
|
rtfs_set_errno(PEINVALIDPARMS, __FILE__, __LINE__); /* pc_gnext: statobj is not valid */
|
|
return(FALSE);
|
|
}
|
|
pdrive = check_drive_by_number(statobj->driveno, TRUE);
|
|
if (!pdrive)
|
|
return(FALSE);
|
|
if (statobj->drive_opencounter != pdrive->drive_opencounter)
|
|
{
|
|
rtfs_set_errno(PEINVALIDPARMS, __FILE__, __LINE__); /* pc_gnext: statobj is not valid */
|
|
release_drive_mount(statobj->driveno);/* Release lock, unmount if aborted */
|
|
return(FALSE);
|
|
}
|
|
|
|
rtfs_clear_errno(); /* po_gnext: clear error status */
|
|
#if (INCLUDE_REVERSEDIR)
|
|
/* Now find the next instance of pattern in the directory */
|
|
if (statobj->search_backwards_if_magic == SEARCH_BACKWARDS_MAGIC_NUMBER)
|
|
nextobj = pc_rget_inode((DROBJ *)(statobj->pobj), (DROBJ *)(statobj->pmom), statobj->pname, statobj->pext, GET_INODE_WILD, CS_CHARSET_ARGS);
|
|
else
|
|
#endif
|
|
nextobj = pc_get_inode((DROBJ *)(statobj->pobj), (DROBJ *)(statobj->pmom),
|
|
statobj->pname, statobj->pext, GET_INODE_WILD, CS_CHARSET_ARGS);
|
|
if (nextobj)
|
|
{
|
|
statobj->pobj = (void *)nextobj;
|
|
/* And update the stat structure */
|
|
pc_upstat(statobj, CS_CHARSET_ARGS);
|
|
#if (INCLUDE_EXFATORFAT64)
|
|
if (statobj->search_backwards_if_magic!=SYS_SCAN_MAGIC_NUMBER) /* EXFAT system scan uses and then frees the finode at a higher layer */
|
|
#endif
|
|
{
|
|
pc_freei(((DROBJ *)(statobj->pobj))->finode); /* Release the current */
|
|
((DROBJ *)(statobj->pobj))->finode = 0;
|
|
}
|
|
release_drive_mount(statobj->driveno);/* Release lock, unmount if aborted */
|
|
return(TRUE);
|
|
}
|
|
else
|
|
{
|
|
if (get_errno() == PENOENT)
|
|
rtfs_clear_errno(); /* get_inode: file not found in directory
|
|
set errno to zero and return FALSE */
|
|
/* pc_gnext: nextobj is 0 pc_get_inode() has set errno to PENOENT or to an internal or IO error status */
|
|
release_drive_mount(statobj->driveno);/* Release lock, unmount if aborted */
|
|
return(FALSE);
|
|
}
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
PC_GDONE - Free internal resources used by pc_gnext and pc_gfirst.
|
|
|
|
Description
|
|
Given a pointer to a DSTAT structure that has been set up by a call to
|
|
pc_gfirst() free internal elements used by the statobj.
|
|
|
|
NOTE: You MUST call this function when done searching through a
|
|
directory.
|
|
|
|
Returns
|
|
Nothing
|
|
|
|
errno is set to one of the following
|
|
0 - No error
|
|
PEINVALIDPARMS - statobj argument is not valid
|
|
****************************************************************************/
|
|
|
|
void pc_gdone(DSTAT *statobj) /*__apifn__*/
|
|
{
|
|
DDRIVE *pdrive;
|
|
VOID_CHECK_MEM() /* Make sure memory is initted */
|
|
/* see if the drive is still mounted. Do not use pmom et al. since they
|
|
may be purged */
|
|
/* see if the drive is still mounted. Do not use pmom et al. since they
|
|
may be purged */
|
|
if (!statobj || !statobj->pmom)
|
|
{
|
|
return;
|
|
}
|
|
pdrive = check_drive_by_number(statobj->driveno, TRUE);
|
|
if (!pdrive)
|
|
return;
|
|
if (statobj->drive_opencounter != pdrive->drive_opencounter)
|
|
{
|
|
release_drive_mount(statobj->driveno);/* Release lock, unmount if aborted */
|
|
return;
|
|
}
|
|
if (statobj->pobj)
|
|
{
|
|
pc_freeobj((DROBJ *)statobj->pobj);
|
|
}
|
|
if (statobj->pmom)
|
|
pc_freeobj((DROBJ *)statobj->pmom);
|
|
release_drive_mount(statobj->driveno);/* Release lock, unmount if aborted */
|
|
rtfs_memset((byte *) statobj,0,sizeof(*statobj));
|
|
}
|
|
|
|
/****************************************************************************
|
|
PC_UPSTAT - Copy private information to public fields for a DSTAT struc.
|
|
|
|
Description
|
|
Given a pointer to a DSTAT structure that contains a pointer to an
|
|
initialized DROBJ structure, load the public elements of DSTAT with
|
|
name filesize, date of modification et al. (Called by pc_gfirst &
|
|
pc_gnext)
|
|
|
|
Returns
|
|
Nothing
|
|
|
|
|
|
****************************************************************************/
|
|
|
|
/* Copy internal stuf so the outside world can see it */
|
|
static void pc_upstat(DSTAT *statobj, int use_charset) /*__fn__*/
|
|
{
|
|
DROBJ *pobj;
|
|
FINODE *pi;
|
|
pobj = (DROBJ *)(statobj->pobj);
|
|
|
|
pi = pobj->finode;
|
|
|
|
copybuff( statobj->fname, pi->fname, 8);
|
|
statobj->fname[8] = 0;
|
|
copybuff( statobj->fext, pi->fext, 3);
|
|
statobj->fext[3] = 0;
|
|
/* put null termed 8.3 file.ext into statobj */
|
|
pc_cs_mfile((byte *)statobj->filename, (byte *)statobj->fname,
|
|
(byte *)statobj->fext, CS_CHARSET_NOT_UNICODE);
|
|
|
|
statobj->fattribute = pi->fattribute;
|
|
statobj->ftime = pi->ftime;
|
|
statobj->fdate = pi->fdate;
|
|
statobj->ctime = pi->ctime;
|
|
statobj->cdate = pi->cdate;
|
|
statobj->adate = pi->adate;
|
|
statobj->atime = pi->atime;
|
|
|
|
#if (INCLUDE_EXFATORFAT64)
|
|
if (ISEXFATORFAT64(pobj->pdrive))
|
|
{
|
|
statobj->fsize = M64LOWDW(pi->fsizeu.fsize64);
|
|
statobj->fsize_hi = M64HIGHDW(pi->fsizeu.fsize64);
|
|
statobj->fname[0] = 0;
|
|
statobj->fext[0] = 0;
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
statobj->fsize = pi->fsizeu.fsize;
|
|
statobj->fsize_hi = 0;
|
|
}
|
|
|
|
statobj->my_block = pi->my_block;
|
|
statobj->my_index = pi->my_index;
|
|
|
|
|
|
/* Get the lfn value for this object. If none available make
|
|
an ASCII or UNICODE copy of the short name in lfn */
|
|
if (!pc_get_lfn_filename(pobj, (byte *)statobj->lfname, use_charset))
|
|
{
|
|
statobj->lfname[0] = statobj->lfname[1] = 0;
|
|
pc_cs_mfileNT((byte *)statobj->lfname, (byte *)statobj->fname,
|
|
(byte *)statobj->fext, use_charset,pobj->finode->reservednt);
|
|
}
|
|
}
|