home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Crawly Crypt Collection 1
/
crawlyvol1.bin
/
utility
/
disk
/
undelete
/
undel.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-02-14
|
27KB
|
893 lines
/**********************************************************************
*
* undel -- a file undelete utility
*
* Written in GNU c by Trevor Blight, Jan 93
*
* Portions of this program are based (loosely) on the program RESCUE2,
* published in "The MS-DOS Developer's Guide", 2nd ed., by Howard W. Sams & Co.
*
* This software may be used freely for any purpose whatsoever.
* Please enhance and return it to the public domain.
*
***********************************************************************/
#include <osbind.h>
#include <aesbind.h>
#include <vdibind.h>
#include <gemfast.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <errno.h>
#include <assert.h>
#include "undel.h"
#define MAX_CLUSTERS 4078 /* max nr clusters for 12 bit FAT */
#define CHAIN_END 1 /* used by get_cluster() to indicate eof */
typedef unsigned char BYTE;
typedef unsigned short WORD;
typedef unsigned long LONG;
typedef struct {
char name[8]; /* name */
char ext[3]; /* extension */
BYTE attrib; /* attribute */
BYTE reserved[10];
WORD time; /* time: hhhhh mmm - mmm sssss */
WORD date; /* date: yyyyyyy m - mmm ddddd */
WORD cluster; /* starting cluster (Intel format) */
LONG fsize; /* total size in bytes (Intel format) */
} DENTRY;
BYTE *FatBuffer; /* FAT table buffer address */
DENTRY *dirBuffer; /* directory buffer address */
DENTRY *dirend;
int wi_handle; /* window handle */
/*** forward declarations ***/
PRIVATE void win_tidy( void );
PRIVATE BOOL fill_dta( WORD srch_att );
PRIVATE void undelete_file( const char *pathp );
PRIVATE WORD next_cluster( const WORD clust );
PRIVATE BOOL match( const char *sname, const char *fname );
PRIVATE WORD swap_word( const WORD word );
PRIVATE LONG swap_long( const LONG l );
PRIVATE void fnmcpy( char* d, const char *s );
PRIVATE int find_subdir( WORD dnum, const char *pathp, WORD *snump );
/*** sector <--> cluster conversion macros ***/
#define sector_of(cl) ((cl - 2)*bpbp->clsiz + bpbp->datrec)
#define cluster_of(s) (2 + (s - bpbp->datrec)/bpbp->clsiz)
/********************************************************
*
* call this function at end of program to tidy up AES windows
*
*******************************************************/
PRIVATE void win_tidy( void )
{
wind_close(wi_handle);
wind_delete(wi_handle);
appl_exit();
} /* win_tidy() */
/*********************************************************
*
* main entry point
*
*********************************************************/
int main(void) /* ignore params */
{
#define WI_KIND 0
char dname[80]; /* directory name buffer */
int dnum; /* drive nr, A: = 0, etc */
int r; /* fsel return value */
int sextn;
char fname[64];
int xdesk,ydesk,hdesk,wdesk;
char extn3str[4];
char extn4str[4];
appl_init();
wind_get(0, WF_WORKXYWH, &xdesk, &ydesk, &wdesk, &hdesk);
wi_handle = wind_create(WI_KIND, xdesk, ydesk, wdesk, hdesk);
if( wi_handle < 0 ) {
form_alert(1, "[1][too many windows open][QUIT]" );
appl_exit();
exit(1); /* quit */
} /* if */
wind_open(wi_handle,xdesk,ydesk,wdesk,hdesk);
if (atexit(win_tidy) != 0 ) {
form_alert(1, "[1][can't arrange tidy up at exit][QUIT]" );
win_tidy();
exit(1);
} /* if */
graf_mouse(ARROW, 0x0L);
strcpy (dname, "\\");
dnum = -1;
sextn = 0x0001; /* select extension 1 */
strcpy( extn3str, "c " );
strcpy( extn4str, "h " );
r = fsel("Select a file to undelete ...", /* I display title for box */
dname, /* IO initial path spec \ ... \ no drive; returns selected path */
&dnum, /* IO selects drive -1=default 0=A: .. 5=F: */
&sextn, /* IO bitmap selected extn boxes :
* 0x0001 = extn0 0x0002 = extn1 0x0004 = extn2
* 0x0008 = extn3 0x0010 = extn4
*/
"* ", /* I extension text not including "." for each of 1st 3 extn boxes */
"PRG", /* NOTE for all 5 boxes this should be 3 chars long, even if spaces */
"DOC",
extn3str,
extn4str, /* IO extension text for last 2 extn boxes (editable) */
fname); /* O returns complete path and file */
if (r != 0) {
undelete_file( fname );
} /* if */
return 0; /* successful completion */
} /* main */
/********************************************************
*
* replacement for Fsfirst() & Fsnext() to recognise deleted files
*
********************************************************/
struct BPB {
short recsiz; /* physical sector size in bytes */
short clsiz; /* cluster size in sectors */
short clsizb; /* cluster size in bytes */
short rdlen; /* root directory length in sectors */
short fsiz; /* FAT size in sectors */
short fatrec; /* second FAT starts at this sector */
short datrec; /* data sectors start here */
short numcl; /* nr of data clusters on disk */
short bflags; /* flags */
};
/*** custom dta buffer for d_First() & d_Next() ***/
struct DTA {
WORD dta_sector;
DENTRY *dta_dirBuffer;
DENTRY *dta_entryp;
DENTRY *dta_dirend;
unsigned short dta_srchattr;
char dta_buf[4];
char dta_drv;
char dta_attribute;
unsigned short dta_time;
unsigned short dta_date;
long dta_size;
char dta_name[14];
};
PRIVATE struct BPB *bpbp;
PRIVATE struct DTA *dtap;
short d_First(char *drvp, char *pathp, short attr)
{
WORD dnum; /* drive nr, A: = 0, etc */
int error;
WORD snum; /* sector number */
dnum = toupper(*drvp) - 'A';
if( (Drvmap() & (1 << dnum)) == 0 ) {
return ENXIO;
} /* if */
if( *pathp == '\\' ) {
pathp++;
} /* if */
/*** get FAT size, root directory sector, etc from Bios Parameter Block... ***/
if( (bpbp = (struct BPB *)Getbpb(dnum)) == 0 ) {
char emsg[80];
sprintf( emsg, "[1][can't get parameters for drive %c:][QUIT]", 'A'+dnum);
form_alert(1, emsg );
exit(1); /* quit */
} /* if */
/*** allocate memory for directory buffers & FAT tables ***/
if( ((dirBuffer = (DENTRY *)malloc(bpbp->clsizb)) == NULL
OR (FatBuffer = (BYTE *)malloc(bpbp->fsiz * bpbp->recsiz)) == NULL) )
{
form_alert(1, "[1][can't allocate enough memory][QUIT]" );
exit(1); /* quit */
} /* if */
dirend = &dirBuffer[bpbp->clsizb/sizeof(*dirBuffer)];
/*** read in FAT ***/
error = Rwabs( 0 /* read mode */, FatBuffer, bpbp->fsiz,
bpbp->fatrec - bpbp->fsiz, /* first FAT starts here */
dnum );
if (error != 0) {
char emsg[80];
sprintf( emsg, "[1][%s|while reading FAT on drive %c][QUIT]",
strerror(-error), dnum + 'A' );
form_alert(1, emsg);
exit(1); /* quit */
} /* if */
if( (error = find_subdir( dnum, pathp, &snum )) != 0 )
{
return error;
} /* if */
if( (attr & FA_DIR) == 0 ) {
char emsg[80];
sprintf( emsg, "[1][path is not a directory:|%s][QUIT]", pathp );
form_alert(1, emsg);
exit(1); /* quit */
} /* if */
/*******************************************************
*
* snum is the sector which has the directory entries
*
*******************************************************/
error = Rwabs( 0 /* read mode */, dirBuffer, bpbp->clsiz, snum, dnum );
if (error != 0) {
char emsg[80];
sprintf( emsg, "[1][%s|while reading|directory entries on drive %c][QUIT]",
strerror(-error), dnum + 'A' );
form_alert(1, emsg);
exit(1); /* quit */
} /* if */
/*** fill the dta buffer with the first directory entry in dirBuffer ***/
dtap = (struct DTA *)Fgetdta();
dtap->dta_sector = snum;
dtap->dta_dirBuffer = dirBuffer;
dtap->dta_entryp = dirBuffer;
dtap->dta_dirend = dirend;
dtap->dta_drv = dnum;
return fill_dta(0) ? 0 : -ENOENT;
} /* d_First() */
short d_Next()
{
return fill_dta(0) ? 0 : -ENMFILES; /* OK ? */
} /* d_Next() */
/*************************************************************
*
* copy next subdirectory entry into dta
*
*************************************************************/
PRIVATE BOOL fill_dta( WORD srch_att )
{
DENTRY *dptr; /* current directory entry */
WORD cluster;
int error;
struct DTA *dtap;
dtap = (struct DTA *)Fgetdta();
dptr = dtap->dta_entryp++;
if( dptr >= dtap->dta_dirend ) {
/*** all entries in this cluster exhausted, get next cluster ***/
if( dtap->dta_sector >= bpbp->datrec ) {
/*** this is a subdirectory ***/
cluster = cluster_of( dtap->dta_sector );
if( (cluster = next_cluster( cluster )) <= CHAIN_END ) {
return( FALSE ); /* no more files */
}
else {
dtap->dta_sector = sector_of( cluster );
} /* if */
}
else if( dtap->dta_sector >= bpbp->fatrec + bpbp->fsiz ) {
/*** this is the root directory ***/
dtap->dta_sector += bpbp->clsiz; /* next cluster in root dir */
if( dtap->dta_sector >= bpbp->datrec ) {
return( FALSE ); /* no more files */
} /* if */
}
else {
/*** this shouldn't happen ***/
char emsg[80];
sprintf( emsg, "[1][error while reading FAT on drive %c][QUIT]",
dtap->dta_drv + 'A' );
form_alert(1, emsg);
exit(1); /* quit */
} /* if */
error = Rwabs( 0 /* read mode */, dtap->dta_dirBuffer,
bpbp->clsiz, dtap->dta_sector, dtap->dta_drv );
if (error != 0) {
char emsg[80];
sprintf( emsg, "[1][%s|while reading|directory entries on drive %c][QUIT]",
strerror(-error), dtap->dta_drv + 'A' );
form_alert(1, emsg);
exit(1); /* quit */
} /* if */
dtap->dta_entryp = dtap->dta_dirBuffer;
dptr = dtap->dta_entryp++;
} /* if */
if( dptr->name[0] == '\0' ) {
return( FALSE ); /* no more files */
} /* if */
dtap->dta_attribute = dptr->attrib;
dtap->dta_time = dptr->time;
dtap->dta_date = dptr->date;
dtap->dta_size = dptr->fsize;
fnmcpy( dtap->dta_name, dptr->name );
assert( strlen(dtap->dta_name) < sizeof(dtap->dta_name) ); /* in case overflow */
return TRUE;
} /* fill_dta() */
/*************************************************************
*
* find the first sector for a pathname
* (the sector contains the subdirectory list)
*
**************************************************************/
PRIVATE int find_subdir( WORD dnum, const char *pathp, WORD *snump )
{
WORD snum;
WORD attr;
WORD cluster;
int error;
DENTRY *dptr; /* current directory entry */
/*** follow the chain of directory entries to match path name ***/
snum = bpbp->fatrec + bpbp->fsiz; /* root directory starts here */
if( *pathp == '\\' ) {
pathp++;
} /* if */
while( *pathp != '\0' ) { /* loop thru all subdirectories in the path */
error = Rwabs( 0 /* read mode */, dirBuffer, bpbp->clsiz, snum, dnum );
if (error != 0) {
char emsg[80];
sprintf( emsg, "[1][%s|while reading|directory entries on drive %c][QUIT]",
strerror(-error), dnum + 'A' );
form_alert(1, emsg);
exit(1); /* quit */
} /* if */
dptr = dirBuffer;
/*** loop thru all directory entries until the name is found ***/
while( ((dptr->attrib & FA_DIR) == 0) /* not a directory ? */
OR NOT match( pathp, dptr->name ) ) { /* names don't match ? */
if( ++dptr >= dirend ) {
/*** name not found in this cluster, get next cluster ***/
if( snum >= bpbp->datrec ) {
/*** this is a subdirectory ***/
cluster = cluster_of( snum );
if( (cluster = next_cluster( cluster )) <= CHAIN_END ) {
return( -EPATH ); /* path not found */
}
else {
snum = sector_of( cluster );
} /* if */
}
else if( snum >= bpbp->fatrec + bpbp->fsiz ) {
/*** this is the root directory ***/
snum += bpbp->clsiz; /* next cluster in root dir */
if( snum >= bpbp->datrec ) {
return( -EPATH ); /* path not found */
} /* if */
}
else {
/*** this shouldn't happen ***/
char emsg[80];
sprintf( emsg, "[1][error while reading|directory on drive %c][QUIT]",
dnum + 'A' );
form_alert(1, emsg);
exit(1); /* quit */
} /* if */
error = Rwabs( 0 /* read mode */, dirBuffer, bpbp->clsiz, snum, dnum );
if (error != 0) {
char emsg[80];
sprintf( emsg, "[1][%s|while reading|directory entries on drive %c][QUIT]",
strerror(-error), dnum + 'A' );
form_alert(1, emsg);
exit(1); /* quit */
} /* if */
dptr = dirBuffer;
} /* if */
} /* while */
/*** the next subdirectory name has been found ***/
snum = sector_of( swap_word(dptr->cluster) );
attr = dptr->attrib;
while( (*pathp != '\0') AND (*pathp != '\\') ) {
pathp++;
} /* while */
if( *pathp == '\\' ) {
pathp++;
} /* if */
} /* while */
*snump = snum;
return 0;
} /* find_subdir() */
/**************************************************************
*
* undelete_file
* pathp -- points to full pathname of file
* eg A:\..dir_path..\file_name
*
* - find the directory entry of the file
* - assume the file contents are in the empty clusters following the starting
* cluster of the file.
* - build an image of the file in data_buffer
* - write out data_buffer to a new file
*
***************************************************************/
PRIVATE void undelete_file( const char *pathp )
{
WORD snum; /* sector number of directory entry */
WORD dnum; /* disk drive number */
WORD cluster;
WORD current; /* current cluster in chain of deleted file */
WORD previous; /* unused ??? */
unsigned nrcl; /* number of clusters in deleted file */
void *data_buffer; /* put copy of restored file here */
void *datap; /* points into data_buffer */
int i;
int error; /* error return code for various functions */
char fname[13]; /* name of file to be undeleted */
char dir_path[80]; /* directory path of file to be undeleted */
long file_size; /* size of the file */
DENTRY *dptr; /* points to a copy of the directory entry of file */
int fh; /* file handle for restored copy of file */
char restored_fn[80]; /* name of restored file */
char Path[80]; /* used for fsel_input() */
int ExitButton; /* used for fsel_input() */
long bytes_written; /* returned by Fwrite() */
assert( pathp[1] == ':' );
dnum = toupper(*pathp) - 'A';
if( (Drvmap() & (1 << dnum)) == 0 ) {
char emsg[80];
sprintf( emsg, "[1][drive %c: doesn't exist!][QUIT]", *pathp );
form_alert(1, emsg );
exit(1); /* quit */
} /* if */
/*** split pathp into directory path & filename path ***/
strcpy (dir_path, pathp+2);
i = strlen( dir_path );
while( i >= 0 ) {
if( dir_path[i] == '\\' ) {
strcpy(fname, dir_path+i+1);
dir_path[i+1] = '\0';
break;
} /* if */
i--;
} /* while */
if( find_subdir( dnum, dir_path, &snum ) != 0 ) {
char emsg[80];
sprintf( emsg, "[1][can't find file|%s][QUIT]", fname);
form_alert(1, emsg );
exit(1); /* quit */
} /* if */
/*** look for file name in directory sector ***/
if (Rwabs( 0 /* read mode */, dirBuffer, bpbp->clsiz, snum, dnum ) != 0) {
char emsg[80];
sprintf( emsg, "[1][%s|while reading|directory entries on drive %c][QUIT]",
strerror(-error), dtap->dta_drv + 'A' );
form_alert(1, emsg);
exit(1); /* quit */
} /* if */
dptr = dirBuffer;
while( NOT match( fname, dptr->name ) ) {
dptr++; /* point to next name */
if( dptr >= dirend ) {
/*** all entries in this cluster exhausted, get next cluster ***/
if( snum >= bpbp->datrec ) {
/*** this is a subdirectory ***/
cluster = cluster_of( snum );
if( (cluster = next_cluster( cluster )) <= CHAIN_END ) {
char emsg[80];
sprintf( emsg, "[1][can't find file|\"%s\"][QUIT]", fname);
form_alert(1, emsg );
exit(1); /* quit */
}
else {
snum = sector_of( cluster );
} /* if */
}
else if( snum >= bpbp->fatrec + bpbp->fsiz ) {
/*** this is the root directory ***/
snum += bpbp->clsiz; /* next cluster in root dir */
if( snum >= bpbp->datrec ) {
char emsg[80];
sprintf( emsg, "[1][can't find file|\"%s\"][QUIT]", fname);
form_alert(1, emsg );
exit(1); /* quit */
} /* if */
}
else {
/*** this shouldn't happen ***/
char emsg[80];
sprintf( emsg, "[1][error while reading|root directory on drive %c][QUIT]",
dnum + 'A' );
form_alert(1, emsg);
exit(1); /* quit */
} /* if */
if (Rwabs(0 /* read mode */, dirBuffer, bpbp->clsiz, snum, dnum) != 0) {
char emsg[80];
sprintf( emsg, "[1][%s|while reading|directory entries on drive %c][QUIT]",
strerror(-error), dtap->dta_drv + 'A' );
form_alert(1, emsg);
exit(1); /* quit */
} /* if */
dptr = dirBuffer;
} /* if */
if( dptr->name[0] == '\0' ) {
char emsg[80];
sprintf( emsg, "[1][can't find file|\"%s\"][QUIT]", fname);
form_alert(1, emsg );
exit(1); /* quit */
} /* if */
} /* while */
/********************************************************
*
* found the file to be undeleted:
* - dptr points to a copy of the directory entry
*
********************************************************/
if( (char)dptr->name[0] != (char)0xe5) {
char emsg[80];
sprintf( emsg, "[1][file is not deleted|\"%s\"][QUIT]", pathp);
form_alert(1, emsg );
exit(1); /* quit */
} /* if */
current = previous = swap_word(dptr->cluster);
if( next_cluster(current) != 0 ) {
char emsg[80];
sprintf( emsg, "[1][\"%s\"|has been overwritten][QUIT]", pathp);
form_alert(1, emsg );
exit(1); /* quit */
} /* if */
if( dptr->attrib == FA_DIR ) {
nrcl = 0; /* directories have file size = 0 */
}
else {
file_size = swap_long(dptr->fsize);
nrcl = (file_size + bpbp->clsizb - 1)/bpbp->clsizb;
} /* if */
if( (datap = data_buffer = malloc( nrcl*bpbp->clsizb )) == NULL ) {
form_alert(1, "[1][can't allocate enough memory][QUIT]" );
exit(1); /* quit */
} /* if */
while( nrcl > 0 ) {
if( current > bpbp->numcl ) {
char emsg[80];
sprintf( emsg, "[1][can't recover all of|\"%s\"][Carry On][QUIT]", pathp );
if( form_alert(1, emsg ) == 2 ) {
exit(1); /* quit */
} /* if */
file_size = (datap-data_buffer)*sizeof(*datap);
} /* if */
if( next_cluster( current ) == 0 ) {
error = Rwabs( 0 /* read mode */, datap, bpbp->clsiz, sector_of(current), dnum );
if (error != 0) {
char emsg[80];
sprintf( emsg, "[1][%s|while reading|file sectors on drive %c][QUIT]",
strerror(-error), dtap->dta_drv + 'A' );
form_alert(1, emsg);
exit(1); /* quit */
} /* if */
datap += bpbp->clsizb;
previous = current;
nrcl--;
} /* if */
current++;
} /* while */
/*** now write the file out ***/
strcpy(Path, "A:\\*.*");
Path[0] += Dgetdrv();
if( fsel_input(Path, restored_fn, &ExitButton) == 0 )
{
form_alert(1, "[1]can't select a name|for restored file[oh dear]");
} /* if */
if( ExitButton == 0 )
{
/* user has cancelled !!! */
exit(1);
} /* if */
/*** merge Path & restored file name ***/
i = strlen( Path );
while( i >= 0 ) {
if( Path[i] == '\\' ) {
strcpy(Path+i+1, restored_fn);
strcpy(restored_fn, Path);
break;
} /* if */
i--;
} /* while */
if( (fh = Fopen( restored_fn, 1)) < 0 ) {
if( fh != -ENOENT ) {
char emsg[80];
sprintf( emsg, "[1][%s|while opening %s][QUIT]",
strerror(-fh), restored_fn );
form_alert(1, emsg);
exit(1); /* quit */
} /* if */
if( (fh = Fcreate( restored_fn, 0)) < 0 ) {
char emsg[80];
sprintf( emsg, "[1][%s|while creating %s][QUIT]",
strerror(-fh), restored_fn );
form_alert(1, emsg);
exit(1); /* quit */
} /* if */
} /* if */
if( (bytes_written = Fwrite(fh, file_size, data_buffer)) < 0 ) {
char emsg[80];
error = (int)bytes_written;
sprintf( emsg, "[1][%s|while writing %s][QUIT]",
strerror(-error), restored_fn );
form_alert(1, emsg);
exit(1); /* quit */
} /* if */
if( (error = Fclose(fh)) != 0 ) {
char emsg[80];
sprintf( emsg, "[1][%s|while trying to close %s][QUIT]",
strerror(-error), restored_fn );
form_alert(1, emsg);
exit(1); /* quit */
} /* if */
} /* undelete_file() */
/**************************************************************
*
* find next cluster in a chain of FAT entries ...
*
* FAT entries: 12-bit 16-bit meaning
* ------ ------ -------
* 000 0000 free cluster
* 001 0001 shouldn't happen
* 002 - FEF 0002 - 7FFF next cluster nr
* 8000 - FFEF shouldn't happen
* FF0 - FF7 FFF0 - FFF7 bad cluster
* FF8 - FFF FFF8 - FFFF end of chain
*
* max nr clusters for 12 bit FAT = 4078
*
**************************************************************/
PRIVATE WORD next_cluster( const WORD clust )
{
int index; /* index into FAT */
WORD newclust; /* next cluster */
/*** if nr clusters on disk > MAX_CLUSTERS use 16-bit FATs ***/
if( bpbp->numcl > MAX_CLUSTERS ) {
/*** 16-bit FATs ***/
index = clust;
newclust = FatBuffer[index] + (FatBuffer[index+1] << 8); /* byte swap */
if( newclust >= 0xfff8 ) {
return CHAIN_END;
}
else if( newclust >= 0x8000 )
{
/*** there is a file system problem if this happens ***/
char emsg[128];
sprintf(emsg, "[1][file system problem|bad cluster chain|"
"at cluster %1d, value is %1d][QUIT]", (int)clust, (int)newclust );
form_alert(1, emsg );
exit(1); /* quit */
} /* if */
}
else {
/*** 12-bit FATs ***/
index = clust + (clust >> 1);
newclust = FatBuffer[index] + (FatBuffer[index+1] << 8); /* byte swap */
if( clust & 1) { /* is clust odd ?? */
newclust >>= 4;
} /* if */
newclust &= 0x0fff;
if( newclust >= 0xff8 ) {
return CHAIN_END;
}
else if( newclust >= 0x0ff0 )
{
/*** there is a file system problem if this happens ***/
char emsg[128];
sprintf(emsg, "[1][file system problem|bad cluster chain|"
"at cluster %1d, value is %1d][QUIT]", (int)clust, (int)newclust );
form_alert(1, emsg );
exit(1); /* quit */
} /* if */
} /* if */
return newclust;
} /* next_cluster() */
/********************************************************
*
* check names for a match.
* fname in format 'nnnnnnnneee', ie 8 chars name + 3 chars extension
* sname is a null terminated string.
* match up to first directory separator (ie '\') in sname
* return TRUE if match found, FALSE otherwise
*
********************************************************/
PRIVATE BOOL match( const char *sname, /* search match name */
const char *fname /* file or directory name */
)
{
const char *fext; /* file or dir extension */
fext = fname + 8;
while( fname < fext+3 ) {
if( *fname == *sname ) {
fname++;
sname++;
}
else {
/*** check why names differ ***/
switch( *sname++ ) {
case '.':
if( (*fname == ' ') OR (fname == fext) ) {
fname = fext;
}
else {
return FALSE;
} /* if */
break;
case '\\':
case '\0':
if( *fname == ' ' ) {
return TRUE;
} /* if */
break;
default:
return FALSE;
} /* switch */
} /* if */
} /* while */
return TRUE;
} /* match() */
/*******************************
*
* swap bytes the bytes in a word argument
*
*******************************/
PRIVATE WORD swap_word( const WORD word )
{
WORD r;
((char *)&r)[0] = ((char *)&word)[1];
((char *)&r)[1] = ((char *)&word)[0];
return r;
} /* swap_word() */
PRIVATE LONG swap_long( const LONG l )
{
LONG r;
((char *)&r)[0] = ((char *)&l)[3];
((char *)&r)[1] = ((char *)&l)[2];
((char *)&r)[2] = ((char *)&l)[1];
((char *)&r)[3] = ((char *)&l)[0];
return r;
} /* swap_word() */
/********************************************
*
* copy filename from directory entry to dta
*
********************************************/
PRIVATE void fnmcpy(char* d, const char *s)
{
int i; /* character counter */
const char *extp; /* pointer to extension */
extp = s+8;
i = 8; /* copy up to 8 chars for name */
while( (i > 0) AND ((unsigned)*s > ' ') ) { /* stop at '\0' or ' ' */
*d++ = *s++;
i--;
} /* while */
if( (unsigned)*extp > ' ' ) {
*d++ = '.';
i = 3; /* copy up to 3 chars for extension */
while( (i > 0) AND ((unsigned)*extp > ' ') ) {
*d++ = *extp++;
i--;
} /* while */
} /* if */
*d = '\0';
} /* fnmcpy() */
/************************* end of undel.c *************************/