home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Hall of Fame
/
HallofFameCDROM.cdr
/
pcmag
/
v9n09.lzh
/
WHEREIS.C
< prev
next >
Wrap
Text File
|
1989-12-24
|
13KB
|
301 lines
/*
WHEREIS.C for OS/2 version 1.2
A file finder utility that searches the current or specified drive,
starting with the root directory (\), for the specified pathname.
Wildcard characters can be included. Long filenames are supported.
If an extended attribute name and value is also supplied, that
information is also used as a match criterion. Blanks can be
embedded in the EA value by quoting. The current version of
the program only knows how to handle length-preceded ASCII EAs.
This program does not require Microsoft or IBM Programmer's Toolkit
header files, but must be linked using LINK.EXE and DOSCALLS.LIB
from retail OS/2 version 1.2.
Compile: cl -c /Zi whereis.c
link /CO whereis,whereis,,doscalls,whereis.def;
Usage: whereis pathname [EAname=EAvalue]
Examples: whereis *.ico (match filename only)
whereis * .TYPE=Icon (match EA only)
whereis *.ico .TYPE=Icon (match both)
whereis *.txt ".TYPE=Plain Text" (match both)
Copyright (C) 1989 Ziff-Davis Communications
PC Magazine * Ray Duncan
*/
#include <stdio.h>
#include <string.h>
#include <memory.h>
#include <malloc.h>
#define API unsigned extern far pascal // OS/2 API function prototypes
API DosChDir(char far *, unsigned long);
API DosFindClose(unsigned);
API DosFindFirst2(char far *, unsigned far *, unsigned, void far *,
unsigned, int far *, int, unsigned long);
API DosFindNext(unsigned, void far *, int, int far *);
API DosQPathInfo(void far *, unsigned, char far *, int, unsigned long);
API DosSelectDisk(int);
API DosWrite(unsigned, void far *, unsigned, unsigned far *);
void showfile(char far *); // local function prototypes
void schdir(char *);
void schfile(void);
#define NORM 0x00 // old file attribute bits
#define RD_ONLY 0x01
#define HIDDEN 0x02
#define SYSTEM 0x04
#define DIR 0x10
#define ARCHIVE 0x20
// EA predefined value types
#define EAT_BINARY 0x0fffe // Length-preceeded binary
#define EAT_ASCII 0x0fffd // Length-preceeded ASCII
#define EAT_BITMAP 0x0fffb // Length-preceeded bitmap
#define EAT_METAFILE 0x0fffa // Metafile
#define EAT_ICON 0x0fff9 // Length-preceeded icon
#define EAT_EA 0x0ffee // ASCIIZ name of associated EA
#define EAT_MVMT 0x0ffdf // Multi-value multi-type
#define EAT_MVST 0x0ffde // Multi-value single-type
#define EAT_ASN1 0x0ffdd // ASN.1 field
// arbitrary buffer sizes
#define SCHBUF_SIZE 4096 // size of search buffer
#define TEAVAL_SIZE 260 // max size of EA target value
#define GEALIST_SIZE 260 // max size of target GEAList
#define MAXPATHNAME 260 // max length of pathname
#define MAXFILENAME 255 // max length of filename
struct _EA { // extended attribute header
unsigned char flags; // critical flag etc.
unsigned char nsize; // length of EA name (without null)
unsigned vsize; // total size of EA value
char name[1]; } ; // EA name and value begin here
struct _EAval { // extended attribute value
unsigned type; // EA value type
unsigned size; // length of EA variable data
char data[1]; } ; // actual data begins here
struct _FEAList { // receives extended attributes
unsigned long size; // total size of structure
char data[1]; } ; // extended attributes begin here
struct _GEA { // extended attribute target name
unsigned char size; // length of name
char name[1]; } ; // actual name begins here
struct _GEAList { // holds names of EAs to get
unsigned long size; // total size of structure
struct _GEA GEA; } ; // name length and name text
struct _EAOP { // used by all EA functions
void far *pGEAList; // pointer to GEAList structure
void far *pFEAList; // pointer to FEAList structure
unsigned long oError; } ; // offset of error, if any
struct _info1 { // result buffer format for
unsigned cdate; // DosFindFirst2 info level 1
unsigned ctime;
unsigned adate;
unsigned atime;
unsigned wdate;
unsigned wtime;
long fsize;
long falloc;
unsigned fattr;
char fcount;
char fname[MAXFILENAME];
} ;
struct _info3 { // result buffer format for
struct _EAOP EAOP; // DosFindFirst2 info level 3
unsigned cdate;
unsigned ctime;
unsigned adate;
unsigned atime;
unsigned wdate;
unsigned wtime;
long fsize;
long falloc;
unsigned fattr;
long easize;
struct _EA EA;
} ;
union _sbuf {
struct _info1 info1;
struct _info3 info3;
} ;
struct _GEAList *GEAList = NULL; // pointer to EA name buffer
union _sbuf *sbuf = NULL; // pointer to search result buffer
struct _EAval *tEAval = NULL; // pointer to EA value buffer
char *tfname = NULL; // pointer to filename buffer
int count = 0; // total files matched
main(int argc, char *argv[])
{
if((argc < 2) || (argc > 3)) // check command line
{
printf("\nUsage: whereis filename [EAname=EAvalue]\n");
printf("\n EA name is case-sensitive, EA value is not.");
printf("\n Use quotes to embed blanks in EA value.\n");
printf("\nExamples: whereis *.ico");
printf("\n whereis * .TYPE=Icon");
printf("\n whereis *.ico .TYPE=Icon");
printf("\n whereis *.txt \".TYPE=Plain Text\"\n");
exit(1);
}
sbuf = malloc(SCHBUF_SIZE); // allocate buffers; note that
GEAList = malloc(GEALIST_SIZE); // these sizes are arbitrary
tEAval = malloc(TEAVAL_SIZE);
tfname = malloc(MAXFILENAME);
if((sbuf==NULL) || (GEAList==NULL) || (tEAval==NULL) || (tfname==NULL))
{
printf("\nwhereis: heap allocation error\n");
exit(1);
}
if(((strlen(argv[1])) >= 2) && ((argv[1])[1] == ':'))
{
if(DosSelectDisk(((argv[1]) [0] | 0x20) - ('a'-1)))
{
printf("\nwhereis: bad drive\n");
exit(1);
}
argv[1] += 2; // advance past drive
}
strncpy(tfname, argv[1], MAXFILENAME); // save target filename
if(argc == 3) // parse EA search target
{ // into name and value strings
strcpy(GEAList->GEA.name, strtok(argv[2], " =\x0a"));
GEAList->GEA.size = strlen(GEAList->GEA.name);
GEAList->size = GEAList->GEA.size + 6;
strcpy(tEAval->data, strtok(NULL, "\x0a"));
tEAval->size = strlen(tEAval->data);
}
else // if no EA search target
{ // supplied, force length
GEAList->GEA.size = 0; // of name and value to 0
tEAval->size = 0;
GEAList->size = sizeof(GEAList->size);
}
schdir("\\"); // start search with root
if(count == 0) // advise if no matches
printf("\nwhereis: no files\n");
}
/*
SCHDIR: search specified directory for matching files and
any other directories which can be searched recursively.
*/
void schdir(char *dirname)
{
unsigned shandle = -1; // search handle
int scount = 1; // max search matches
DosChDir(dirname, 0L); // select new directory
schfile(); // find and list files
// search for directories
if(!DosFindFirst2("*.*", // match any name
&shandle, // receives search handle
NORM|DIR, // match normal files & dirs
sbuf, // buffer receives match info
SCHBUF_SIZE, // size of search buffer
&scount, // receives match count
1, // info level 1 = no EAs
0L)) // reserved
{
do // recurse to search directories
{ // other than . and .. aliases
if((sbuf->info1.fattr & DIR) && (sbuf->info1.fname[0] != '.'))
{
schdir(sbuf->info1.fname);
DosChDir("..", 0L); // restore previous directory
}
// look for more directories
} while(DosFindNext(shandle, sbuf, SCHBUF_SIZE, &scount) == 0);
}
DosFindClose(shandle); // close search handle
}
/*
SCHFILE: search current directory for files matching supplied
filename, also matching extended attribute name and value if any.
*/
void schfile(void)
{
struct _EAval *pEAval; // pointer to EA value in sbuf
char far *pfname; // pointer to filename
unsigned shandle = -1; // search handle
int scount = 1; // max search matches
sbuf->info3.EAOP.oError = 0L; // initialize EAOP pointers
sbuf->info3.EAOP.pGEAList = GEAList;
sbuf->info3.EAOP.pFEAList = NULL;
if(!DosFindFirst2(tfname, // target filename for search
&shandle, // receives search handle
NORM, // match normal files only
sbuf, // buffer receives match info
SCHBUF_SIZE, // size of search buffer
&scount, // receives match count
3, // info level 3 = get EAs too
0L)) // reserved
{
do
{
pfname = (char far *) // calc address of filename
&sbuf->info3.easize + sbuf->info3.easize + 1;
if(tEAval->size) // if EA entered, does it match?
{
(char *) pEAval = // calc address of EA value
sbuf->info3.EA.name + sbuf->info3.EA.nsize + 1;
if((sbuf->info3.EA.vsize) &&
(pEAval->size == tEAval->size) &&
(pEAval->type == EAT_ASCII) &&
(! memicmp(pEAval->data, tEAval->data, tEAval->size)))
showfile(pfname); // EA matches, display filename
}
else showfile(pfname); // no EA entered, display filename
} while(DosFindNext(shandle, sbuf, SCHBUF_SIZE, &scount) == 0);
}
DosFindClose(shandle); // close search handle
}
/*
SHOWFILE: called with filename, displays fully qualified pathname.
*/
void showfile(char far *pfname)
{
char pathname[MAXPATHNAME]; // receives full pathname
count++; // count matched files
// qualify the filename
DosQPathInfo(pfname, 5, pathname, sizeof(pathname), 0L);
printf("%s\n", strlwr(pathname)); // and display it
}