home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 5 Edit
/
05-Edit.zip
/
FILEINFO.ZIP
/
FILE.C
next >
Wrap
Text File
|
1990-08-14
|
16KB
|
527 lines
//
// file.c
//
// Portions of this program are taken from a program by Ray Duncan
// published in PC Magazine called SHOWEA. Those protions are:
//
// Copyright (C) 1989 Ziff-Davis Communications
//
// The original portions are:
//
// Copyright (C) 1990, Brady Flowers
//
// I compiled this with MSC 6.0 and the following compile command:
//
// cl -AL -Zep -Oxaz -Grs -Lp -W3 file.c file.def
//
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <memory.h>
#include <malloc.h>
#define INCL_DOS
#define INCL_DOSERRORS
#include <os2.h>
// --------------------------------------------------------------------------
#define dim(x) (sizeof(x)/sizeof(x[0])) // number of elements in structure
#define EABUF_SIZE 16384 // size of EA buffer
#define MAXPATHNAME 260 // maximum length of pathname
#define MAXFILENAME 255 // maximum length of filename
#define FILE_ANY (FILE_READONLY|FILE_HIDDEN|FILE_SYSTEM|FILE_DIRECTORY|FILE_ARCHIVED)
// --------------------------------------------------------------------------
void GetCountryInfo(void);
void ShowTimeStamp(PFDATE pD, PFTIME pT);
void ShowAttributes(USHORT attr);
void showapptype(char *filename);
void showeas(char *filename); // local function prototypes
void showea(void);
int findtype(unsigned EAtype);
void fmtUNKNOWN(void);
void fmtBINARY(void);
void fmtASCII(void);
void fmtBITMAP(void);
void fmtMETAFILE(void);
void fmtICON(void);
void fmtEA(void);
void fmtMVMT(void);
void fmtMVST(void);
void fmtASN1(void);
int _cdecl main(int argc, char **argv);
// --------------------------------------------------------------------------
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 _EAvalue // extended attribute value
{
unsigned type; // EA value type
unsigned size; // length of EA variable data
char data[1]; // actual data begins here
};
// --------------------------------------------------------------------------
struct _EAtable // lookup table of EA types
{
unsigned type; // binary type indicator
char *name; // descriptive text
void (*formatter)(void); // formatting routine
} EAtable[] = {
0, "unknown EA type", fmtUNKNOWN,
EAT_BINARY, "length-preceeded binary", fmtBINARY,
EAT_ASCII, "length-preceeded ASCII", fmtASCII,
EAT_BITMAP, "length-preceeded bitmap", fmtBITMAP,
EAT_METAFILE, "metafile", fmtMETAFILE,
EAT_ICON, "length-preceeded icon", fmtICON,
EAT_EA, "associated EA data", fmtEA,
EAT_MVMT, "multi-value multi-type", fmtMVMT,
EAT_MVST, "multi-value single-type", fmtMVST,
EAT_ASN1, "ASN.1", fmtASN1,
};
char *fname; // pointer to qualified pathname
FEALIST *FEAList; // pointer to EA buffer
struct _EA *pEA; // pointer to individual EA header
struct _EAvalue *pEAval; // pointer to individual EA value
char Argv[MAXPATHNAME];
PSZ pszDateSep;
PSZ pszTimeSep;
USHORT usDateFmt;
USHORT usTimeFmt;
USHORT usRecurLevel = 0;
// --------------------------------------------------------------------------
void GetCountryInfo()
{
COUNTRYCODE countryCode = { 0, 0 };
COUNTRYINFO countryInfo;
USHORT rVal, usInfo;
if (rVal = DosGetCtryInfo(sizeof(countryInfo), &countryCode, &countryInfo, &usInfo))
{
printf("ERROR 0x%04x: Getting country information.\n");
exit(1);
}
pszDateSep = strdup(countryInfo.szDateSeparator);
pszTimeSep = strdup(countryInfo.szTimeSeparator);
usDateFmt = countryInfo.fsDateFmt;
usTimeFmt = countryInfo.fsTimeFmt;
}
// --------------------------------------------------------------------------
void ShowTimeStamp(PFDATE pD, PFTIME pT)
{
PSZ p;
USHORT usTmp, usPM = FALSE;
p = pszDateSep;
switch (usDateFmt)
{
case DATEFMT_MM_DD_YY:
printf("%02d%s%02d%s%04d ", pD->month, p, pD->day, p, pD->year + 1980);
break;
case DATEFMT_DD_MM_YY:
printf("%02d%s%02d%s%04d ", pD->day, p, pD->month, p, pD->year + 1980);
break;
case DATEFMT_YY_MM_DD:
printf("%4d%s%02d%s%02d ", pD->year + 1980, p, pD->month, p, pD->day);
break;
}
p = pszTimeSep;
if (usTimeFmt)
printf("%02d%s%02d%s%0d", pT->hours, p, pT->minutes, p, pT->twosecs * 2);
else
{
if (pT->hours > 11) usPM = TRUE;
if (pT->hours > 12)
usTmp = pT->hours - 12;
else
usTmp = pT->hours;
printf("%2d%s%02d%s%02d %s", usTmp, p, pT->minutes, p, pT->twosecs * 2, usPM ? "pm" : "am");
}
puts("");
}
void ShowAttributes(USHORT attr)
{
if (attr)
{
printf("Attributes:");
if (attr & FILE_READONLY) printf(" READONLY");
if (attr & FILE_HIDDEN) printf(" HIDDEN");
if (attr & FILE_SYSTEM) printf(" SYSTEM");
if (attr & FILE_DIRECTORY) printf(" DIRECTORY");
if (attr & FILE_ARCHIVED) printf(" ARCHIVED");
puts("");
}
}
// --------------------------------------------------------------------------
void showapptype(char *filename)
{
USHORT rVal, usAppType;
if (rVal = DosQAppType(filename, &usAppType))
{
switch (rVal)
{
case ERROR_INVALID_EXE_SIGNATURE:
case ERROR_BAD_EXE_FORMAT:
// printf(" Not an Executable File\n");
break;
case ERROR_EXE_MARKED_INVALID:
printf("ERROR 0x%04x: Bad mark on Executable file\n", rVal);
break;
case ERROR_SHARING_VIOLATION:
printf("Cannot access file for Application Type\n");
break;
default:
printf("ERROR 0x%04x: execing DosQAppType.\n", rVal);
break;
}
return;
}
printf("Application type:");
if (usAppType == NOTSPECIFIED)
printf(" NOTSPECIFIED");
else
{
if ((usAppType & WINDOWAPI) == WINDOWAPI)
printf(" WINDOWAPI");
else
{
if ((usAppType & NOTWINDOCOMPAT) == NOTWINDOCOMPAT) printf(" NOTWINDOWCOMPAT");
if ((usAppType & WINDOWCOMPAT) == WINDOWCOMPAT) printf(" WINDOWCOMPAT");
}
if ((usAppType & BOUND) == BOUND) printf(" BOUND");
if ((usAppType & DYNAMICLINK) == DYNAMICLINK) printf(" DYNAMICLINK");
if ((usAppType & DOSFORMAT) == DOSFORMAT) printf(" DOSFORMAT");
}
puts(""); // extra blank line
}
// --------------------------------------------------------------------------
void showeas(char *filename)
{
EAOP eaop; // holds pointers for DosQPathInfo
int error; // error code from DosQPathInfo
if (!FEAList)
{
FEAList = malloc(EABUF_SIZE); // allocate EA buffer and
fname = malloc(MAXPATHNAME); // qualified pathname buffer
}
if ((FEAList == NULL) || (fname == NULL))
{
// ---- exit if not enough heap
printf("ERROR 0x%04x: heap allocation error\n", ERROR_NOT_ENOUGH_MEMORY);
exit(2);
}
eaop.fpGEAList = NULL; // initialize EAOP components
eaop.fpFEAList = FEAList; // and buffer to receive EAs
eaop.oError = 0L;
FEAList->cbList = EABUF_SIZE - sizeof(unsigned long);
if (error = DosQPathInfo(filename, // retrieve EAs using filename
4, // info level 4 = get all EAs
(PBYTE)&eaop, // buffer to receieve EAs
sizeof(eaop), // size of buffer
0L)) // reserved
{
if (error == ERROR_BUFFER_OVERFLOW)
{
printf("ERROR 0x04x: EA buffer too small\n", error);
exit(3);
}
else if (error == ERROR_SHARING_VIOLATION)
printf("Cannot access file for Extended Attributes\n");
else
printf("ERROR 0x%04x: execing DosQPathInfo for: \'%s\'\n", error, filename);
return;
}
// ---- display full pathname
DosQPathInfo(filename, 5, fname, MAXPATHNAME, 0L);
if (FEAList->cbList == sizeof(unsigned long))
{
// printf(" None found.\n");
return;
}
printf("Extended Attributes:\n");
printf("Name Type Value");
pEA = (struct _EA *) FEAList->list; // point to first EA
while((char *)pEA < ((char *)(FEAList->list)+FEAList->cbList-sizeof(unsigned long)))
{
(char *) pEAval = // point to EA value
pEA->name + pEA->nsize + 1;
showea(); // display this EA name & value
(char *) pEA = // go to next EA
pEA->name + pEA->nsize + pEA->vsize + 1;
}
puts(""); // extra blank line
}
/*
SHOWEA: format and display current extended attribute.
*/
void showea()
{
int i; // scratch variable
i = findtype(pEAval->type); // look up the EA type
printf("\n%-10.10s %-25.25s ", // display EA name, value type
pEA->name, EAtable[i].name);
(*(EAtable[i].formatter))(); // call type-specific routine
} // to display EA value
/*
FINDTYPE: look up extended attribute type in EAtable.
*/
int findtype(unsigned EAtype)
{
int i; // scratch variable
for(i = 1; i < dim(EAtable); i++) // skip dummy entry EAtable[0]
{
if(EAtable[i].type == EAtype) // if we matched EA type
return(i); // return EAtable index
}
return(0); // no match, return 0
}
/*
The routines below perform formatting and output of the value
for each EA type. In this version of the demo program only
the length-preceded ASCII, length-preceded simple binary, and
multi-type multi-value types are implemented.
The remainder are dummy functions that do nothing.
*/
void fmtUNKNOWN() // unknown EA type
{
fmtBINARY();
}
void fmtBINARY() // length-preceded binary
{
int i; // scratch variable
for(i = 0; i < min(8, pEAval->size); i++) // display binary data
printf("%02X ", pEAval->data[i]);
if(pEAval->size > 8) printf("..."); // indicate there is more
}
void fmtASCII() // length-preceded ASCII string
{
printf("%.*s", pEAval->size, pEAval->data);
}
void fmtBITMAP() // length-preceded bitmap
{
fmtBINARY();
}
void fmtMETAFILE() // length-preceded metafile
{
fmtBINARY();
}
void fmtICON() // length-preceded icon
{
fmtBINARY();
}
void fmtEA() // ASCIIZ extended attribute
{ // name of associated data
printf("%s", (char *) &pEAval->size);
}
void fmtMVMT() // multi-value multi-type
{
int i; // scratch variable
int fields; // number of value fields
strcpy(pEA->name, ""); // erase EA name
fields = *((int *)(pEAval->data)); // retrieve number of fields
(char *) pEAval = // point to first field
pEAval->data + sizeof(int);
for(i = 0; i < fields; i++) // loop across value fields
{
showea(); // display this value field
(char *) pEAval = // point to next value
pEAval->data + pEAval->size;
}
}
void fmtMVST() // multi-value single-type
{
return;
}
void fmtASN1() // ASN.1 field
{
return;
}
int _cdecl main(int argc, char **argv)
{
static char buffer[2048];
HDIR hDir = HDIR_CREATE;
FILEFINDBUF2 ffbuf;
USHORT usSearchCt = 1;
BOOL fRecurse = FALSE;
BOOL fCanRecurse = TRUE;
char c, *cp, *cpTail;
char *acp[3];
int i;
if (argc == 1) // check command line
{
printf("\nusage: file [-s] filename|pathname [[-s] filename|pathname ...]\n");
printf(" '-s' toggles subdirectory recursion on and off for subsequent\n");
printf(" arguments. Default is no recursion.\n");
exit(1);
}
if (usRecurLevel == 0)
GetCountryInfo();
for (i = 1; i < argc; i++)
{
if ((strcmp(argv[i], "-s") == 0) || (strcmp(argv[i], "/s") == 0))
{
fRecurse = !fRecurse;
continue;
}
while (cpTail = strchr(argv[i], '\\'))
*cpTail = '/';
if (strchr(argv[i], '*') || strchr(argv[i], '?'))
fCanRecurse = TRUE;
else
fCanRecurse = FALSE;
if (!(cpTail = strrchr(argv[i], '/')))
cpTail = strrchr(argv[i], ':');
if (cpTail)
++cpTail;
if (DosFindFirst2(argv[i], &hDir, FILE_ANY, &ffbuf, sizeof(ffbuf), &usSearchCt, FIL_QUERYEASIZE, 0L))
printf("No files matching \'%s\'\n\n", argv[i]);
else
{
do
{
if (cpTail)
{
c = *cpTail;
*cpTail = 0;
strcpy(buffer, argv[i]);
strcat(buffer, ffbuf.achName);
*cpTail = c;
}
else
strcpy(buffer, ffbuf.achName);
if (ffbuf.attrFile & FILE_DIRECTORY)
printf("Directory: %s\n", buffer);
else
{
printf("File: %s\n", buffer);
printf("Size: %ld bytes using %ld of disk space.\n", ffbuf.cbFile, ffbuf.cbFileAlloc);
}
printf("Created: ");
ShowTimeStamp(&(ffbuf.fdateCreation), &(ffbuf.ftimeCreation));
printf("Access: ");
ShowTimeStamp(&(ffbuf.fdateLastAccess), &(ffbuf.ftimeLastAccess));
printf("Modified: ");
ShowTimeStamp(&(ffbuf.fdateLastWrite), &(ffbuf.ftimeLastWrite));
ShowAttributes(ffbuf.attrFile);
if (!(ffbuf.attrFile & FILE_DIRECTORY) && ffbuf.cbFile)
showapptype(buffer);
showeas(buffer);
puts("");
if ((ffbuf.attrFile & FILE_DIRECTORY) && fRecurse && fCanRecurse)
{
if (strcmp(ffbuf.achName, ".") && strcmp(ffbuf.achName, ".."))
{
++usRecurLevel;
acp[0] = argv[0];
acp[1] = cp = malloc(strlen(buffer) + strlen(cpTail) + 2);
acp[2] = NULL;
strcpy(cp, buffer);
strcat(cp, "/");
strcat(cp, cpTail);
main(2, acp);
free(cp);
--usRecurLevel;
}
}
}
while (!DosFindNext(hDir, (PFILEFINDBUF)&ffbuf, sizeof(ffbuf), &usSearchCt));
}
DosFindClose(hDir);
}
return 0;
}