1299 lines
27 KiB
C
1299 lines
27 KiB
C
#include "cmd.h"
|
|
|
|
extern TCHAR ThousandSeparator[];
|
|
|
|
STATUS
|
|
FormatFileSize(
|
|
IN DWORD rgfSwitchs,
|
|
IN PLARGE_INTEGER FileSize,
|
|
IN DWORD Width,
|
|
OUT PTCHAR FormattedSize
|
|
);
|
|
|
|
// Entry is displayed.
|
|
// If not /b,
|
|
// Cursor is left at end of entry on screen.
|
|
// FileCnt, FileCntTotal, FileSiz, FileSizTotal are updated.
|
|
// If /b,
|
|
// Cursor is left at beginning of next line.
|
|
// Cnt's and Siz's aren't updated.
|
|
//
|
|
// Create a manager for these totals
|
|
|
|
#define DIR_SIZE_WIDTH 17
|
|
#define DIR_OLD_TO_SIZE 14
|
|
#define DIR_OLD_PAST_SIZE 32
|
|
|
|
#define DIR_NEW_DIR_PAST_TIME_DATE 24
|
|
#define DIR_NEW_FILE_PAST_TIME_DATE 21
|
|
#define DIR_NEW_PAST_SIZE 39
|
|
|
|
extern TCHAR Fmt00[], Fmt01[], Fmt03[], Fmt08[], Fmt09[], Fmt14[], Fmt19[], Fmt26[] ;
|
|
extern BOOL CtrlCSeen;
|
|
|
|
BOOLEAN GetDrive( PTCHAR , PTCHAR );
|
|
|
|
STATUS
|
|
DisplayFileListHeader(
|
|
IN PSCREEN pscr,
|
|
IN ULONG rgfSwitchs,
|
|
IN PTCHAR pszDir
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Display the header for a complete file list. This will include
|
|
the current directory.
|
|
|
|
Arguments:
|
|
|
|
pscr - screen handle
|
|
rgfSwtichs - switchs from command line.
|
|
pszDir - directory to print.
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
{
|
|
|
|
//
|
|
// If /b then do not display the header
|
|
// you want just a file list.
|
|
//
|
|
if (rgfSwitchs & BAREFORMATSWITCH) {
|
|
|
|
return( SUCCESS );
|
|
|
|
}
|
|
|
|
if (rgfSwitchs & RECURSESWITCH) {
|
|
|
|
//
|
|
// recursing down a tree so put a blank line before header
|
|
// and last listing
|
|
//
|
|
CHECKSTATUS ( WriteEol( pscr ));
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
return( WriteMsgString(pscr, MSG_DIR_OF, ONEARG, pszDir) );
|
|
|
|
}
|
|
|
|
STATUS
|
|
DisplayFileList (
|
|
IN PSCREEN pscr,
|
|
OUT PULONG pcffTotal,
|
|
OUT PLARGE_INTEGER pcbFileTotal,
|
|
IN ULONG rgfSwitchs,
|
|
IN ULONG dwTimeType,
|
|
IN PFS pfsFiles
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Displays a list of files and directories in the specified format.
|
|
|
|
Arguments:
|
|
|
|
pscr - screen handle
|
|
rgfSwitchs - command line switch (controls formating)
|
|
pfsFile - pointer to files to display
|
|
|
|
|
|
Return Value:
|
|
|
|
return SUCCESS
|
|
FAILURE
|
|
pcffTotal - number of files displayed
|
|
pcbFileTotal - number of bytes for all files displayed.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
ULONG cff;
|
|
ULONG irgpff;
|
|
ULONG cffColMax;
|
|
ULONG crowMax;
|
|
ULONG crow, cffCol;
|
|
STATUS rc=SUCCESS;
|
|
BOOL notPrintedEarly;
|
|
|
|
//
|
|
// check if we already printed early
|
|
//
|
|
notPrintedEarly = (rgfSwitchs & (RECURSESWITCH | WIDEFORMATSWITCH | SORTDOWNFORMATSWITCH | SORTSWITCH));
|
|
|
|
//
|
|
// Number of things we are going to display
|
|
//
|
|
cff = pfsFiles->cff;
|
|
|
|
//
|
|
// Do not display any header information if there are no files
|
|
//
|
|
if ((notPrintedEarly && cff == 0) || (!notPrintedEarly && pfsFiles->cffDisplayed == 0)) {
|
|
|
|
return( SUCCESS );
|
|
|
|
} else {
|
|
|
|
//
|
|
// if it is not the bare format (no header, no tail)
|
|
// then display which directory, volume etc.
|
|
//
|
|
|
|
if (notPrintedEarly && !(rgfSwitchs & BAREFORMATSWITCH )) {
|
|
|
|
CHECKSTATUS(DisplayFileListHeader(pscr, rgfSwitchs, pfsFiles->pszDir ));
|
|
}
|
|
|
|
}
|
|
|
|
//
|
|
// Setting tabs to 0 forces single line output
|
|
//
|
|
SetTab(pscr, 0);
|
|
|
|
//
|
|
// Compute the tab spacing on the line from the size of the file names.
|
|
// add 3 spaces to seperate each field
|
|
//
|
|
// If multiple files per line then base tabs on the max file/dir size
|
|
//
|
|
if (rgfSwitchs & WIDEFORMATSWITCH) {
|
|
|
|
SetTab(pscr, (USHORT)(GetMaxCbFileSize( pfsFiles ) + 3));
|
|
|
|
}
|
|
|
|
DEBUG((ICGRP, DISLVL, "\t count of files %d",cff));
|
|
|
|
if (rgfSwitchs & SORTDOWNFORMATSWITCH) {
|
|
|
|
//
|
|
// no. of files on a line.
|
|
//
|
|
cffColMax = (pscr->ccolMax / pscr->ccolTab);
|
|
//
|
|
// number of row required for entire list
|
|
//
|
|
if (cffColMax == 0) // wider than a line
|
|
goto abort_wide; // abort wide format for this list
|
|
else
|
|
crowMax = (cff + cffColMax) / cffColMax;
|
|
|
|
//
|
|
// move down each rown picking the elements cffCols aport down the list.
|
|
//
|
|
for (crow = 0; crow < crowMax; crow++) {
|
|
for (cffCol = 0, irgpff = crow;
|
|
cffCol < cffColMax;
|
|
cffCol++, irgpff += crowMax) {
|
|
|
|
if (CtrlCSeen) {
|
|
return( FAILURE );
|
|
}
|
|
|
|
if (irgpff < cff) {
|
|
|
|
rc = DisplayFile(pscr,
|
|
rgfSwitchs,
|
|
dwTimeType,
|
|
&pfsFiles->cbFileTotal,
|
|
pfsFiles,
|
|
pfsFiles->prgpff[irgpff]);
|
|
|
|
|
|
|
|
if (rc != SUCCESS) {
|
|
return( rc );
|
|
}
|
|
|
|
} else {
|
|
|
|
//
|
|
// If we have run past the end of the file list terminate
|
|
// line and start over back inside the line
|
|
//
|
|
CHECKSTATUS( WriteEol(pscr) );
|
|
break;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
} else {
|
|
if (notPrintedEarly) {
|
|
abort_wide:
|
|
if (CtrlCSeen) {
|
|
return( FAILURE );
|
|
}
|
|
|
|
for(irgpff = 0; irgpff < cff; irgpff++) {
|
|
|
|
if (CtrlCSeen) {
|
|
return( FAILURE );
|
|
}
|
|
|
|
rc = DisplayFile(pscr,
|
|
rgfSwitchs,
|
|
dwTimeType,
|
|
&pfsFiles->cbFileTotal,
|
|
pfsFiles,
|
|
pfsFiles->prgpff[irgpff]);
|
|
|
|
|
|
if (rc != SUCCESS) {
|
|
return( rc );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Before writing the tailer make sure buffer is
|
|
// empty. (Could have something from doing WIDEFORMATSWITCH
|
|
//
|
|
CHECKSTATUS( WriteFlushAndEol( pscr ) );
|
|
|
|
|
|
pcbFileTotal->QuadPart = pfsFiles->cbFileTotal.QuadPart + pcbFileTotal->QuadPart;
|
|
*pcffTotal += pfsFiles->cffDisplayed;
|
|
|
|
if (!(rgfSwitchs & BAREFORMATSWITCH)) {
|
|
|
|
CHECKSTATUS( DisplayFileSizes(pscr, &pfsFiles->cbFileTotal, pfsFiles->cffDisplayed, rgfSwitchs) );
|
|
|
|
}
|
|
|
|
return( SUCCESS );
|
|
|
|
|
|
}
|
|
|
|
STATUS
|
|
DisplayFile (
|
|
|
|
IN PSCREEN pscr,
|
|
IN ULONG rgfSwitchs,
|
|
IN ULONG dwTimeType,
|
|
OUT PLARGE_INTEGER pcbFileTotal,
|
|
IN PFS pfs,
|
|
IN PFF pff
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Displays a single file in 1 of several formats.
|
|
|
|
Arguments:
|
|
|
|
pscr - screen handle
|
|
rgfSwitchs - command line switch (controls formating)
|
|
pfs - current directory (used for full path information)
|
|
pff - current file
|
|
|
|
|
|
Return Value:
|
|
|
|
return SUCCESS
|
|
FAILURE
|
|
pcbFileTotal - number of bytes for displayed file is added to this large integer.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
STATUS rc = SUCCESS;
|
|
ULONG obFileName;
|
|
PWIN32_FIND_DATA pdata;
|
|
LARGE_INTEGER cbFile;
|
|
|
|
pdata = &(pff->data);
|
|
//
|
|
// Do any checks here to see if file should not be printed.
|
|
//
|
|
cbFile.LowPart = pdata->nFileSizeLow;
|
|
cbFile.HighPart = pdata->nFileSizeHigh;
|
|
|
|
if (rgfSwitchs & BAREFORMATSWITCH) {
|
|
|
|
rc = DisplayBare(pscr, rgfSwitchs, pfs->pszDir, pdata);
|
|
|
|
} else {
|
|
|
|
// dos5 has a call to DisplayNext here (to move to next field)
|
|
// I do this inside of DisplayWide. May want to change this.
|
|
if (rgfSwitchs & WIDEFORMATSWITCH) {
|
|
|
|
rc = DisplayWide(pscr, rgfSwitchs, pdata);
|
|
|
|
} else {
|
|
|
|
if ((rgfSwitchs & NEWFORMATSWITCH) ||
|
|
(rgfSwitchs & SHORTFORMATSWITCH)) {
|
|
|
|
rc = DisplayNewRest(pscr, dwTimeType, rgfSwitchs, pdata);
|
|
obFileName = 32;
|
|
if (rc == SUCCESS) {
|
|
|
|
if (rgfSwitchs & SHORTFORMATSWITCH) {
|
|
|
|
if (pff->obAlternate) {
|
|
|
|
FillToCol(pscr, DIR_NEW_PAST_SIZE);
|
|
rc = DisplayDotForm(pscr,
|
|
rgfSwitchs,
|
|
&(pdata->cFileName[pff->obAlternate]));
|
|
|
|
}
|
|
|
|
FillToCol(pscr, DIR_NEW_PAST_SIZE + 16);
|
|
rc = DisplayDotForm(pscr, rgfSwitchs, pdata->cFileName);
|
|
|
|
} else {
|
|
FillToCol(pscr, DIR_NEW_PAST_SIZE);
|
|
rc = DisplayDotForm(pscr, rgfSwitchs, pdata->cFileName);
|
|
}
|
|
}
|
|
|
|
} else {
|
|
|
|
rc = DisplaySpacedForm(pscr, rgfSwitchs, pdata);
|
|
if (rc == SUCCESS) {
|
|
FillToCol(pscr, DIR_OLD_TO_SIZE);
|
|
rc = DisplayOldRest(pscr, dwTimeType, rgfSwitchs, pdata);
|
|
}
|
|
}
|
|
|
|
rc = WriteEol(pscr);
|
|
}
|
|
|
|
}
|
|
|
|
if (rc == SUCCESS) {
|
|
pcbFileTotal->QuadPart = cbFile.QuadPart + pcbFileTotal->QuadPart;
|
|
pfs->cffDisplayed += 1;
|
|
}
|
|
|
|
return( rc );
|
|
}
|
|
|
|
STATUS
|
|
DisplayBare (
|
|
|
|
IN PSCREEN pscr,
|
|
IN ULONG rgfSwitchs,
|
|
IN PTCHAR pszDir,
|
|
IN PWIN32_FIND_DATA pdata
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Displays a single file in bare format. This is with no header, tail and
|
|
no file information other then it's name. If it is a recursive catalog
|
|
then the full file path is displayed. This mode is used to feed other
|
|
utitilies such as grep.
|
|
|
|
Arguments:
|
|
|
|
pscr - screen handle
|
|
rgfSwitchs - command line switch (controls formating)
|
|
pszDir - current directory (used for full path information)
|
|
pdata - data gotten back from FindNext API
|
|
|
|
|
|
Return Value:
|
|
|
|
return SUCCESS
|
|
FAILURE
|
|
|
|
--*/
|
|
|
|
|
|
{
|
|
|
|
TCHAR szDirString[MAX_PATH + 2];
|
|
STATUS rc;
|
|
|
|
DEBUG((ICGRP, DISLVL, "DisplayBare `%ws'", pdata->cFileName));
|
|
|
|
//
|
|
// Do not display '.' and '..' in a bare listing
|
|
//
|
|
if ((_tcscmp(pdata->cFileName, TEXT(".")) == 0) || (_tcscmp(pdata->cFileName, TEXT("..")) == 0)) {
|
|
|
|
return( SUCCESS );
|
|
|
|
}
|
|
|
|
//
|
|
// If we are recursing down then display full name else just the
|
|
// name in the find buffer
|
|
//
|
|
//
|
|
// BUGBUG What happens if you can fit the directory on the line
|
|
// but you can not fit the filename. construct the full
|
|
// name locally before you try and write it out.
|
|
//
|
|
if (rgfSwitchs & RECURSESWITCH) {
|
|
|
|
mystrcpy(szDirString, pszDir);
|
|
if (rgfSwitchs & LOWERCASEFORMATSWITCH) {
|
|
|
|
//
|
|
// BUGBUG Unicode translation issue!
|
|
//
|
|
_tcslwr(szDirString);
|
|
}
|
|
|
|
CHECKSTATUS( WriteString(pscr, szDirString) );
|
|
|
|
if (*lastc(szDirString) != BSLASH) {
|
|
CHECKSTATUS( WriteString(pscr, TEXT("\\")));
|
|
}
|
|
|
|
}
|
|
|
|
if ((rc = DisplayDotForm(pscr, rgfSwitchs, pdata->cFileName)) == SUCCESS) {
|
|
|
|
return( WriteEol(pscr));
|
|
|
|
} else {
|
|
|
|
return( rc );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
VOID
|
|
SetDotForm (
|
|
IN PTCHAR pszFileName,
|
|
IN ULONG rgfSwitchs
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
If FATFORMAT and there is a '.' with a blank extension, the '.' is
|
|
removed so it does not get displayed. This is by convension and is very
|
|
silly but that's life. Also a lower case mapping is done.
|
|
|
|
Arguments:
|
|
|
|
pszFileName - file to remove '.' from.
|
|
rgfSwitchs - command line switches (tell wither in FATFORMAT or not)
|
|
|
|
|
|
Return Value:
|
|
|
|
return SUCCESS
|
|
FAILURE
|
|
|
|
--*/
|
|
|
|
|
|
{
|
|
PTCHAR pszT;
|
|
|
|
if (rgfSwitchs & FATFORMAT) {
|
|
|
|
//
|
|
// Under DOS if there is a . with a blank extension
|
|
// then do not display '.'.
|
|
//
|
|
if (pszT = mystrrchr(pszFileName, DOT)) {
|
|
//
|
|
// FAT will not allow foo. ba as a valid name so
|
|
// see of any blanks in extensions and if so then assume
|
|
// the entire extension is blank
|
|
//
|
|
if (mystrchr(pszT, SPACE)) {
|
|
*pszT = NULLC;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
STATUS
|
|
DisplayDotForm (
|
|
|
|
IN PSCREEN pscr,
|
|
IN ULONG rgfSwitchs,
|
|
IN PTCHAR pszFileName
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Displays a single file in DOT form (see SetDotForm).
|
|
|
|
Arguments:
|
|
|
|
pscr - screen handle
|
|
rgfSwitchs - command line switch (tell wither to lowercase or not)
|
|
pdata - data gotten back from FindNext API
|
|
|
|
|
|
Return Value:
|
|
|
|
return SUCCESS
|
|
FAILURE
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
TCHAR szFileName[MAX_PATH + 2];
|
|
|
|
mystrcpy(szFileName, pszFileName);
|
|
SetDotForm(szFileName, rgfSwitchs);
|
|
if (rgfSwitchs & LOWERCASEFORMATSWITCH) {
|
|
|
|
_tcslwr(szFileName);
|
|
}
|
|
|
|
return( WriteString( pscr, szFileName ) );
|
|
|
|
}
|
|
|
|
STATUS
|
|
DisplaySpacedForm(
|
|
|
|
IN PSCREEN pscr,
|
|
IN ULONG rgfSwitchs,
|
|
IN PWIN32_FIND_DATA pdata
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Display name in expanded format. name <spaces> ext.
|
|
This is ONLY called for a FAT partition. This is controled by the
|
|
NEWFORMATSWITCH. This is set for any file system other then FAT. There
|
|
is no OLDFORMATSWITCH so we can never be called on an HPFS or NTFS
|
|
volume. If this is changed then the entire spacing of the display will
|
|
be blown due to non-fixed max file names. (i.e. 8.3).
|
|
|
|
Arguments:
|
|
|
|
pscr - screen handle
|
|
rgfSwitchs - command line switch (tell wither to lowercase or not)
|
|
pdata - data gotten back from FindNext API
|
|
|
|
|
|
Return Value:
|
|
|
|
return SUCCESS
|
|
FAILURE
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
TCHAR szFileName[MAX_PATH + 2];
|
|
PTCHAR pszExt, pszName;
|
|
USHORT cbName;
|
|
#if defined(JAPAN) && defined(UNICODE)
|
|
int i;
|
|
int l;
|
|
#endif /* defined(JAPAN) && defined(UNICODE) */
|
|
|
|
mytcsnset(szFileName, SPACE, MAX_PATH + 2);
|
|
|
|
pszName = pdata->cFileName;
|
|
|
|
cbName = 0;
|
|
if ((_tcscmp(pszName, TEXT(".")) == 0) || (_tcscmp(pszName, TEXT("..")) == 0)) {
|
|
|
|
//
|
|
// If it is either of these then do not get it
|
|
// confused with extensions
|
|
//
|
|
pszExt = NULL;
|
|
|
|
} else {
|
|
|
|
pszExt = mystrrchr(pszName, (int)DOT);
|
|
cbName = (USHORT)(pszExt - pszName)*sizeof(WCHAR);
|
|
}
|
|
|
|
//
|
|
// if no extension or name is extension only
|
|
//
|
|
if ((pszExt == NULL) || (cbName == 0)) {
|
|
|
|
cbName = (USHORT)_tcslen(pszName)*sizeof(TCHAR);
|
|
|
|
}
|
|
|
|
memcpy(szFileName, pszName, cbName );
|
|
|
|
#if defined(JAPAN) && defined(UNICODE)
|
|
//
|
|
// If we had an extension then print it after
|
|
// all the spaces
|
|
//
|
|
i = 9;
|
|
for (l=0 ; l<8 ; l++) {
|
|
if (IsFullWidth(szFileName[l]))
|
|
i--;
|
|
}
|
|
|
|
if (pszExt) {
|
|
|
|
mystrcpy(szFileName + i, pszExt + 1);
|
|
}
|
|
|
|
//
|
|
// terminate at max end for a FAT name
|
|
//
|
|
|
|
szFileName[i+3] = NULLC;
|
|
if (pszExt) {
|
|
//
|
|
// Only 1 of three can be full width, since 3/2=1.
|
|
// If the first isn't, only the second could be.
|
|
//
|
|
if (IsFullWidth(*(pszExt+1)) || IsFullWidth(*(pszExt+2)))
|
|
szFileName[i+2] = NULLC;
|
|
}
|
|
#else /* defined(JAPAN) && defined(UNICODE) */
|
|
if (pszExt) {
|
|
|
|
//
|
|
// move pszExt past dot. use 9 not 8 to pass
|
|
// over 1 space between name and extension
|
|
//
|
|
mystrcpy(szFileName + 9, pszExt + 1);
|
|
|
|
}
|
|
|
|
//
|
|
// terminate at max end for a FAT name
|
|
//
|
|
szFileName[12] = NULLC;
|
|
#endif /* defined(JAPAN) && defined(UNICODE) */
|
|
|
|
if (rgfSwitchs & LOWERCASEFORMATSWITCH) {
|
|
|
|
//
|
|
// BUGBUG this _tcslwr is not dbcs will have to covert later
|
|
//
|
|
_tcslwr(szFileName);
|
|
}
|
|
|
|
return( WriteString( pscr, szFileName ) );
|
|
|
|
}
|
|
|
|
STATUS
|
|
DisplayOldRest(
|
|
|
|
IN PSCREEN pscr,
|
|
IN ULONG dwTimeType,
|
|
IN ULONG rgfSwitchs,
|
|
IN PWIN32_FIND_DATA pdata
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Used with DisplaySpacedForm to write out file information such as size
|
|
and last write time.
|
|
|
|
Arguments:
|
|
|
|
pscr - screen handle
|
|
pdata - data gotten back from FindNext API
|
|
|
|
|
|
Return Value:
|
|
|
|
return SUCCESS
|
|
FAILURE
|
|
|
|
--*/
|
|
|
|
{
|
|
TCHAR szSize [ MAX_PATH];
|
|
DWORD Length;
|
|
LARGE_INTEGER FileSize;
|
|
|
|
//
|
|
// If directory put <DIR> after name instead of file size
|
|
//
|
|
if (pdata->dwFileAttributes & A_D) {
|
|
|
|
|
|
CHECKSTATUS( WriteMsgString(pscr, MSG_DIR,0) );
|
|
|
|
} else {
|
|
|
|
FileSize.LowPart = pdata->nFileSizeLow;
|
|
FileSize.HighPart = pdata->nFileSizeHigh;
|
|
Length = FormatFileSize( rgfSwitchs, &FileSize, 0, szSize );
|
|
if (Length < DIR_SIZE_WIDTH) {
|
|
FillToCol(pscr, DIR_OLD_TO_SIZE+DIR_SIZE_WIDTH-Length);
|
|
}
|
|
WriteFmtString(pscr, Fmt14, (PVOID)szSize);
|
|
|
|
}
|
|
|
|
FillToCol(pscr, DIR_OLD_PAST_SIZE);
|
|
return( DisplayTimeDate( pscr, dwTimeType, pdata) );
|
|
|
|
}
|
|
|
|
STATUS
|
|
DisplayTimeDate (
|
|
|
|
IN PSCREEN pscr,
|
|
IN ULONG dwTimeType,
|
|
IN PWIN32_FIND_DATA pdata
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Display time/data information for a file
|
|
|
|
Arguments:
|
|
|
|
pscr - screen handle
|
|
pdata - data gotten back from FindNext API
|
|
|
|
|
|
Return Value:
|
|
|
|
return SUCCESS
|
|
FAILURE
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
struct tm FileTime;
|
|
TCHAR szT[MAX_PATH + 2];
|
|
FILETIME ft;
|
|
|
|
switch (dwTimeType) {
|
|
|
|
case LAST_ACCESS_TIME:
|
|
|
|
ft = pdata->ftLastAccessTime;
|
|
break;
|
|
|
|
case LAST_WRITE_TIME:
|
|
|
|
ft = pdata->ftLastWriteTime;
|
|
break;
|
|
|
|
case CREATE_TIME:
|
|
|
|
ft = pdata->ftCreationTime;
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
if (ConvertFileTimeToTime( &ft, &FileTime )) {
|
|
PrintDate(&FileTime, PD_DIR, szT, MAX_PATH) ;
|
|
CHECKSTATUS( WriteFmtString(pscr, TEXT("%s "), (PVOID)szT));
|
|
PrintTime(&FileTime, PT_DIR, szT, MAX_PATH) ;
|
|
CHECKSTATUS( WriteFmtString(pscr, TEXT("%s "), (PVOID)szT) );
|
|
|
|
} else {
|
|
|
|
return( FAILURE );
|
|
}
|
|
|
|
return( SUCCESS );
|
|
}
|
|
|
|
STATUS
|
|
DisplayNewRest(
|
|
IN PSCREEN pscr,
|
|
IN ULONG dwTimeType,
|
|
IN ULONG rgfSwitchs,
|
|
IN PWIN32_FIND_DATA pdata
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Display file information for new format (comes before file name).
|
|
This is used with NEWFORMATSWITCH which is active on any non-FAT
|
|
partition.
|
|
|
|
Arguments:
|
|
|
|
pscr - screen handle
|
|
pdata - data gotten back from FindNext API
|
|
|
|
|
|
Return Value:
|
|
|
|
return SUCCESS
|
|
FAILURE
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
STATUS rc;
|
|
LARGE_INTEGER FileSize;
|
|
|
|
rc = DisplayTimeDate( pscr, dwTimeType, pdata);
|
|
|
|
if (rc == SUCCESS) {
|
|
|
|
//
|
|
// If directory put <DIR> after name instead of file size
|
|
//
|
|
if (pdata->dwFileAttributes & A_D) {
|
|
|
|
FillToCol(pscr, DIR_NEW_DIR_PAST_TIME_DATE);
|
|
rc = WriteMsgString(pscr, MSG_DIR,0);
|
|
|
|
} else {
|
|
TCHAR szSize [ MAX_PATH];
|
|
DWORD Length;
|
|
|
|
FillToCol(pscr, DIR_NEW_FILE_PAST_TIME_DATE);
|
|
|
|
FileSize.LowPart = pdata->nFileSizeLow;
|
|
FileSize.HighPart = pdata->nFileSizeHigh;
|
|
Length = FormatFileSize( rgfSwitchs, &FileSize, 0, szSize );
|
|
if (Length < DIR_SIZE_WIDTH) {
|
|
FillToCol(pscr, DIR_NEW_FILE_PAST_TIME_DATE+DIR_SIZE_WIDTH-Length);
|
|
}
|
|
rc = WriteFmtString(pscr, Fmt14, (PVOID)szSize);
|
|
}
|
|
|
|
}
|
|
|
|
return( rc );
|
|
|
|
}
|
|
|
|
|
|
STATUS
|
|
DisplayWide (
|
|
|
|
IN PSCREEN pscr,
|
|
IN ULONG rgfSwitchs,
|
|
IN PWIN32_FIND_DATA pdata
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Displays a single file used in the /w or /d switchs. That is with a
|
|
multiple file column display.
|
|
|
|
Arguments:
|
|
|
|
pscr - screen handle
|
|
rgfSwitchs - command line switchs (controls formating)
|
|
pdata - data gotten back from FindNext API
|
|
|
|
|
|
Return Value:
|
|
|
|
return SUCCESS
|
|
FAILURE
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
TCHAR szFileName[MAX_PATH + 2];
|
|
PTCHAR pszFmt;
|
|
STATUS rc;
|
|
|
|
pszFmt = Fmt14; // assume non-dir format
|
|
|
|
//
|
|
// Provides [] around directories
|
|
//
|
|
if (pdata->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
|
|
|
|
pszFmt = Fmt09;
|
|
|
|
}
|
|
|
|
mystrcpy(szFileName, pdata->cFileName);
|
|
SetDotForm(szFileName, rgfSwitchs);
|
|
if (rgfSwitchs & LOWERCASEFORMATSWITCH) {
|
|
|
|
//
|
|
// BUGBUG this _tcslwr is not dbcs will have to covert later
|
|
//
|
|
_tcslwr(szFileName);
|
|
}
|
|
rc = WriteFmtString(pscr, pszFmt, szFileName);
|
|
|
|
if (rc == SUCCESS) {
|
|
|
|
rc = WriteTab(pscr);
|
|
|
|
}
|
|
return( rc );
|
|
|
|
}
|
|
|
|
USHORT
|
|
GetMaxCbFileSize(
|
|
IN PFS pfsFiles
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Determines the longest string size in a file list. Used in computing
|
|
the number of possible columns in a catalog listing.
|
|
|
|
Arguments:
|
|
|
|
pfsFiles - file list.
|
|
|
|
Return Value:
|
|
|
|
return # of characters in largest file name
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
|
|
ULONG cff;
|
|
ULONG irgff;
|
|
USHORT cb;
|
|
PFF pffCur;
|
|
|
|
cb = 0;
|
|
for(irgff = 0, cff = pfsFiles->cff, pffCur = pfsFiles->prgpff[irgff];
|
|
irgff < cff;
|
|
irgff++) {
|
|
|
|
#if defined(JAPAN) && defined(UNICODE)
|
|
cb = max(cb, (USHORT)SizeOfHalfWidthString(((pfsFiles->prgpff[irgff])->data).cFileName));
|
|
#else /* defined(JAPAN) && defined(UNICODE) */
|
|
cb = max(cb, (USHORT)mystrlen( ((pfsFiles->prgpff[irgff])->data).cFileName ));
|
|
#endif /* defined(JAPAN) && defined(UNICODE) */
|
|
|
|
}
|
|
|
|
return( cb );
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
STATUS
|
|
DisplayFileSizes(
|
|
IN PSCREEN pscr,
|
|
IN PLARGE_INTEGER cbFileTotal,
|
|
IN ULONG cffTotal,
|
|
IN ULONG rgfSwitchs
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Does tailer display of # of files displayed and # of bytes
|
|
in all files displayed.
|
|
|
|
Arguments:
|
|
|
|
pscr - screen handle
|
|
cbFileTotal - bytes in all files displayed
|
|
cffTotal - number of files displayed.
|
|
|
|
Return Value:
|
|
|
|
return SUCCESS
|
|
FAILURE
|
|
|
|
--*/
|
|
|
|
{
|
|
TCHAR szSize [ MAX_PATH];
|
|
|
|
FillToCol(pscr, 6);
|
|
|
|
FormatFileSize( rgfSwitchs, cbFileTotal, 14, szSize );
|
|
return( WriteMsgString(pscr, MSG_FILES_COUNT_FREE, TWOARGS,
|
|
(ULONG)argstr1(TEXT("%5lu"), cffTotal ),
|
|
szSize ) );
|
|
}
|
|
|
|
STATUS
|
|
DisplayTotals(
|
|
IN PSCREEN pscr,
|
|
IN ULONG cffTotal,
|
|
IN PLARGE_INTEGER cbFileTotal,
|
|
IN ULONG rgfSwitchs
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Does tailer display of # of files displayed and # of bytes
|
|
in all files displayed.
|
|
|
|
Arguments:
|
|
|
|
pscr - screen handle
|
|
cbFileTotal - bytes in all files displayed
|
|
cffTotal - number of files displayed.
|
|
|
|
Return Value:
|
|
|
|
return SUCCESS
|
|
FAILURE
|
|
|
|
--*/
|
|
|
|
|
|
{
|
|
|
|
STATUS rc;
|
|
|
|
if ((rc = WriteMsgString(pscr, MSG_FILE_TOTAL, 0) ) == SUCCESS ) {
|
|
|
|
if ((rc = DisplayFileSizes( pscr, cbFileTotal, cffTotal, rgfSwitchs )) == SUCCESS) {
|
|
|
|
rc = WriteFlush(pscr) ;
|
|
|
|
}
|
|
|
|
}
|
|
return ( rc );
|
|
|
|
|
|
}
|
|
|
|
STATUS
|
|
DisplayDiskFreeSpace(
|
|
IN PSCREEN pscr,
|
|
IN PTCHAR pszDrive,
|
|
IN ULONG rgfSwitchs
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Displays total free space on volume.
|
|
|
|
Arguments:
|
|
|
|
pscr - screen handle
|
|
pszDrive - volume drive letter
|
|
|
|
Return Value:
|
|
|
|
return SUCCESS
|
|
FAILURE
|
|
|
|
--*/
|
|
{
|
|
TCHAR szPath [ MAX_PATH + 2];
|
|
DWORD dwSectorsPerCluster;
|
|
DWORD dwBytesPerSector;
|
|
DWORD dwNumberOfFreeClusters;
|
|
DWORD dwTotalNumberOfClusters;
|
|
LARGE_INTEGER cbFree;
|
|
DWORD Length;
|
|
|
|
CheckPause( pscr );
|
|
|
|
//
|
|
// If no drive do not print total
|
|
//
|
|
if (!GetDrive(pszDrive, szPath)) {
|
|
return ( SUCCESS );
|
|
}
|
|
|
|
mystrcat(szPath, TEXT("\\"));
|
|
|
|
cbFree.LowPart = cbFree.HighPart = 0;
|
|
if (GetDiskFreeSpace( szPath,&dwSectorsPerCluster, &dwBytesPerSector,
|
|
&dwNumberOfFreeClusters, &dwTotalNumberOfClusters)) {
|
|
|
|
cbFree.QuadPart = UInt32x32To64(dwSectorsPerCluster, dwNumberOfFreeClusters);
|
|
cbFree.QuadPart = cbFree.QuadPart * dwBytesPerSector;
|
|
}
|
|
|
|
Length = FormatFileSize( rgfSwitchs, &cbFree, 0, szPath );
|
|
if (Length <= DIR_SIZE_WIDTH) {
|
|
FillToCol(pscr, DIR_SIZE_WIDTH-Length);
|
|
}
|
|
return( WriteMsgString(pscr,
|
|
MSG_FILES_TOTAL_FREE,
|
|
ONEARG,
|
|
szPath ));
|
|
|
|
}
|
|
|
|
STATUS
|
|
DisplayVolInfo(
|
|
IN PSCREEN pscr,
|
|
IN PTCHAR pszDrive
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Displays the volume trailer information. Used before switching to
|
|
a catalog of another drive (dir a:* b:*)
|
|
|
|
Arguments:
|
|
|
|
pscr - screen handle
|
|
pszDrive - volume drive letter
|
|
|
|
Return Value:
|
|
|
|
return SUCCESS
|
|
FAILURE
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
DWORD Vsn[2];
|
|
TCHAR szVolName[MAX_PATH + 2];
|
|
TCHAR szVolRoot[MAX_PATH + 2];
|
|
TCHAR szT[256];
|
|
STATUS rc = SUCCESS;
|
|
|
|
if (!GetDrive(pszDrive, szVolRoot)) {
|
|
return( SUCCESS );
|
|
}
|
|
|
|
mystrcat(szVolRoot, TEXT("\\"));
|
|
if (!GetVolumeInformation(szVolRoot,szVolName,MAX_PATH,Vsn,NULL,NULL,NULL,0)) {
|
|
|
|
DEBUG((ICGRP, DISLVL, "DisplayVolInfo: GetVolumeInformation ret'd %d", GetLastError())) ;
|
|
// don't fail if we're a substed drive
|
|
if (GetLastError() == ERROR_DIR_NOT_ROOT) {
|
|
return SUCCESS;
|
|
}
|
|
PutStdErr(GetLastError(), NOARGS);
|
|
return( FAILURE ) ;
|
|
|
|
} else {
|
|
|
|
if (szVolRoot[0] == BSLASH) {
|
|
*lastc(szVolRoot) = NULLC;
|
|
} else {
|
|
|
|
szVolRoot[1] = NULLC;
|
|
}
|
|
|
|
if (szVolName[0]) {
|
|
|
|
rc = WriteMsgString(pscr,
|
|
MSG_DR_VOL_LABEL,
|
|
TWOARGS,
|
|
argstr1(TEXT("%s"), (ULONG)(szVolRoot)),
|
|
argstr2(TEXT("%s"), (ULONG)szVolName ) ) ;
|
|
} else {
|
|
|
|
rc = WriteMsgString(pscr,
|
|
MSG_HAS_NO_LABEL,
|
|
ONEARG,
|
|
argstr1(TEXT("%s"), (ULONG)(szVolRoot)) ) ;
|
|
|
|
}
|
|
|
|
if ((rc == SUCCESS) && (Vsn)) {
|
|
|
|
wsprintf(szT,Fmt26,(Vsn[0] & 0xffff0000)>>16, (Vsn[0] & 0xffff) );
|
|
rc = WriteMsgString(pscr, MSG_DR_VOL_SERIAL, ONEARG, szT);
|
|
}
|
|
}
|
|
|
|
return( rc );
|
|
}
|
|
|
|
|
|
ULONG
|
|
FormatFileSize(
|
|
IN DWORD rgfSwitchs,
|
|
IN PLARGE_INTEGER FileSize,
|
|
IN DWORD Width,
|
|
OUT PTCHAR FormattedSize
|
|
)
|
|
{
|
|
TCHAR Buffer[ 100 ];
|
|
PTCHAR s, s1;
|
|
ULONG DigitIndex, Digit;
|
|
ULONG nThousandSeparator;
|
|
ULONGLONG Size;
|
|
|
|
nThousandSeparator = _tcslen(ThousandSeparator);
|
|
s = &Buffer[ 99 ];
|
|
*s = TEXT('\0');
|
|
DigitIndex = 0;
|
|
Size = FileSize->QuadPart;
|
|
while (Size != 0) {
|
|
Digit = (ULONG)(Size % 10);
|
|
Size = Size / 10;
|
|
*--s = (TCHAR)(TEXT('0') + Digit);
|
|
if ((++DigitIndex % 3) == 0 && (rgfSwitchs & THOUSANDSEPSWITCH)) {
|
|
// If non-null Thousand separator, insert it.
|
|
if (nThousandSeparator) {
|
|
s -= nThousandSeparator;
|
|
_tcsncpy(s, ThousandSeparator, nThousandSeparator);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (DigitIndex == 0) {
|
|
*--s = TEXT('0');
|
|
}
|
|
else
|
|
if ((rgfSwitchs & THOUSANDSEPSWITCH) && !_tcsncmp(s, ThousandSeparator, nThousandSeparator)) {
|
|
s += nThousandSeparator;
|
|
}
|
|
|
|
Size = _tcslen( s );
|
|
if (Width != 0 && Size < Width) {
|
|
s1 = FormattedSize;
|
|
while (Width > Size) {
|
|
Width -= 1;
|
|
*s1++ = SPACE;
|
|
}
|
|
_tcscpy( s1, s );
|
|
} else {
|
|
_tcscpy( FormattedSize, s );
|
|
}
|
|
|
|
return _tcslen( FormattedSize );
|
|
}
|