📄 expand.c
字号:
* returned FIND_BUF structure. (Versions of DOS prior to 3.1 did
* not support networks, so we can be fairly certain that the
* reserved fields will be consistent.)
*
* If we experience an error during this function, we skip the
* verification test and exit FALSE, as if the files were different.
*
* HISTORY: M001 Created.
*
*/
BOOL IsSourceDest( char *pszSource, char *pszDest )
{
int i;
union REGS inregs, outregs;
struct SREGS segregs;
char szSrcAbs[MAXFILESPECLEN]; /* Absolute source pathname */
char szDestAbs[MAXFILESPECLEN]; /* Absolute dest. pathname */
struct find_t SrcFileInfo; /* Source file information buffer */
struct find_t DestFileInfo; /* Dest. file information buffer */
#ifdef DEBUG
struct FIND_BUF * s;
#endif
/* For DOS versions >= 3.1, use DOS Truename function */
if( _osmajor > 3 || (_osmajor == 3 && _osminor >= 1) )
{
/* Get segment register values, and ensure they are the same (for safety:
* they should be the same since this is SMALL model).
*/
segread( &segregs );
if( segregs.ds != segregs.es || segregs.ds != segregs.ss )
return(FALSE); /* Skip test */
/* Get absolute source pathname */
inregs.h.ah = 0x60; /* DOS Truename function */
inregs.x.si = (unsigned) pszSource; /* Relative source path */
inregs.x.di = (unsigned) szSrcAbs; /* Buffer */
intdosx( &inregs, &outregs, &segregs );
if( outregs.x.cflag != 0 )
return(FALSE); /* Skip test */
/* Get absolute destination pathname */
inregs.h.ah = 0x60; /* DOS Truename function */
inregs.x.si = (unsigned) pszDest; /* Relative dest path */
inregs.x.di = (unsigned) szDestAbs; /* Buffer */
intdosx( &inregs, &outregs, &segregs );
if( outregs.x.cflag != 0 )
return(FALSE); /* Skip test */
#ifdef DEBUG
printf("Source = %s, Dest = %s\n", szSrcAbs, szDestAbs);
#endif
if( strcmpi(szSrcAbs, szDestAbs) == 0 )
return(TRUE); /* Source == Destination */
}
else /* DOS version >= 2.1 */
if( (_osmajor == 3 && _osminor == 0) || (_osmajor == 2 && _osminor >= 1) )
{
/* Use _dos_findfirst(); compare file information structures. */
/* Clear File Information Buffers */
memset(&SrcFileInfo, 0, sizeof(struct find_t));
memset(&DestFileInfo, 0, sizeof(struct find_t));
/* Source file */
if( _dos_findfirst(pszSource, _A_NORMAL, &SrcFileInfo) != 0 )
return(FALSE); /* Skip test */
/* Dest. file */
if( _dos_findfirst(pszDest, _A_NORMAL, &DestFileInfo) != 0 )
return(FALSE); /* Skip test */
#ifdef DEBUG
s = (struct FIND_BUF *) &SrcFileInfo;
printf( "Source: Drive=0x%hx Name=%.11s SAttr=0x%hx\n" \
"LastEnt=0x%hx DirStart=0x%hx NetId=%.4s Attr=0x%hx\n" \
"Time=0x%hx Date=0x%hx Size=0x%lx Name=%s\n\n",
s->FIND_BUF_DRIVE, /* drive of search */
s->FIND_BUF_NAME, /* formatted name */
s->FIND_BUF_SATTR, /* attribute of search */
s->FIND_BUF_LASTENT, /* LastEnt */
s->FIND_BUF_DIRSTART, /* DirStart */
s->FIND_BUF_NETID, /* Reserved for NET */
SrcFileInfo.attrib, /* attribute found */
SrcFileInfo.wr_time, /* time */
SrcFileInfo.wr_date, /* date */
SrcFileInfo.size, /* size */
SrcFileInfo.name ); /* packed name */
s = (struct FIND_BUF *) &DestFileInfo;
printf( "Dest: Drive=0x%hx Name=%.11s SAttr=0x%hx\n" \
"LastEnt=0x%hx DirStart=0x%hx NetId=%.4s Attr=0x%hx\n" \
"Time=0x%hx Date=0x%hx Size=0x%lx Name=%s\n\n",
s->FIND_BUF_DRIVE, /* drive of search */
s->FIND_BUF_NAME, /* formatted name */
s->FIND_BUF_SATTR, /* attribute of search */
s->FIND_BUF_LASTENT, /* LastEnt */
s->FIND_BUF_DIRSTART, /* DirStart */
s->FIND_BUF_NETID, /* Reserved for NET */
DestFileInfo.attrib, /* attribute found */
DestFileInfo.wr_time, /* time */
DestFileInfo.wr_date, /* date */
DestFileInfo.size, /* size */
DestFileInfo.name ); /* packed name */
#endif
/* Zero-out NET_ID members, in case they contain garbage. */
for(i=0; i<4; i++)
{
((struct FIND_BUF *) &SrcFileInfo)->FIND_BUF_NETID[i] = '\0';
((struct FIND_BUF *) &DestFileInfo)->FIND_BUF_NETID[i] = '\0';
}
if( memcmp(&SrcFileInfo, &DestFileInfo, sizeof(struct find_t)) == 0 )
return(TRUE); /* Source == Destination */
}
return(FALSE); /* Source != Destination */
}
/* BOOL PromptUser( int argc, char *$argv[] );
*
* Prompt the user for the source and destination files.
*
* ENTRY: $argv[] array of pointers to input parameters.
*
* EXIT: TRUE if user entered valid parameters; FALSE otherwise.
* If TRUE, then $argv[1] -> source parameter
* and $argv[2] -> destination parameter
*
* HISTORY: M001 Created.
*
*/
BOOL PromptUser( int argc, char *$argv[] )
{
int i;
/* Prompt for Source file, if needed. */
if( argc == 1 )
{
printf(pszSRC_PROMPT1);
while(TRUE)
{
printf(pszSRC_PROMPT2);
i = GetString( $argv[1], MAX_ROW_LEN - sizeof(pszSRC_PROMPT2) );
if( i == ABORT )
return(FALSE);
else
if( i > 0 )
break;
}
}
/* Prompt for Destination file */
printf(pszDEST_PROMPT1);
while(TRUE)
{
printf(pszDEST_PROMPT2);
i = GetString( $argv[2], MAX_ROW_LEN - sizeof(pszDEST_PROMPT2) );
if( i == ABORT )
return(FALSE);
else
if( i > 0 )
break;
}
return(TRUE);
}
/* int Quit(int);
*
* Cleanup and exit program.
*
* ENTRY: Exit code.
*
* EXIT: None
*
* NOTES: NULL memory pointers are ignored by the free() and _ffree()
* functions, so we always exit through Quit(), even if the
* memory pointers haven't been initialized yet. (All the global
* memory pointers are static or external, so they are initialized
* to NULL by default.)
*
* HISTORY: M001 Created.
*
*/
int Quit(int rc)
{
FreeBuffers();
return(rc);
}
/* int GetString(char *chBuf, int iBufSiz)
*
* Read a line from STDIN into a buffer (chBuf). The line is
* terminated when the buffer is full (buffer size is specified by
* iBufSiz and includes a terminating NULL character) or when a newline
* is encountered ('\n'). The line is terminated by a NULL character ('\0');
* the newline ('\n') is not retained. The function returns the number of
* characters in the buffer chBuf, not including the NULL ('\0'), or ABORT
* if the CHAR_ABORT character is encountered.
*
* ENTRY: chBuf -> destination buffer
* iBufSize = Maximum buffer size (including terminating NULL char.)
*
* EXIT: returns number of characters in the buffer chBuf, not including
* the terminating NULL char., or ABORT if the CHAR_ABORT is
* encountered.
*
* NOTES: This function does not handle the case of strings which wrap.
* So, in order for the BACKSPACE key to erase all the input
* characters, the value of iBufSiz should limit input to 1
* screen row.
*
* HISTORY: M001 Created.
*
*/
int GetString(char *chBuf, int iBufSiz)
{
int i;
char chIn;
int iBufEnd = iBufSiz - 1;
/* Save characters in chBuf[] until buffer is full. Don't
* exit loop until Carriage return or EOF or ABORT received.
*/
for( i=0;
((chIn = (char) getch()) != CHAR_EOF) &&
(chIn != '\r') &&
(chIn != CHAR_ABORT); )
{
if( isprint(chIn) )
{
if( i < iBufEnd )
{
putch(chIn);
chBuf[i++] = chIn;
}
else
putch('\a');
}
else
if( chIn == '\b' )
{
if( i > 0 )
{
putch('\b');
putch(' ');
putch('\b');
chBuf[i--] = NULL;
continue;
}
}
else
putch('\a');
}
chBuf[i] = EOL; /* Zero-terminate string */
if( chIn == CHAR_ABORT )
i = ABORT;
printf("\n");
#ifdef DEBUG0
printf("i=%d, input=%s\n", i, chBuf);
#endif
fflush(stdin); /* Flush input buffer */
return(i);
}
/* ProcessInput( int $argc, char *$argv[] )
*
* Decompress source file(s) to destination.
*
* ENTRY: $argc Number of input parameters
* $argv[] Array of ptrs to input parameters
*
* EXIT: EXIT_SUCCESS or EXIT_FAILURE.
*
* NOTES:
*
* HISTORY: M001 Created.
*
*/
int ProcessInput( int $argc, char *$argv[] )
{
int i;
int rc = EXIT_SUCCESS;
char rgchDestFileName[MAXFILESPECLEN]; /* destination file name */
BOOL bIsDir; /* IsDir() return value */
long cblTotIn = 0L,
cblTotOut = 0L;
// initialize globals
uchAlgorithm = uchALG_LEMPEL_ZIV;
uchVersion = uchVER_1;
// keep track of original drive
wOriginalDrive = GetCurDrive();
// Is the last parameter a directory?
bIsDir = IsDir((LPSTR)$argv[$argc - 1]);
if ($argc != 3 && ! bIsDir)
{
printf(pszNO_DEST_DIR, $argv[$argc - 1]);
return(EXIT_FAILURE);
}
// Set up input, output, and ring buffers, and associated work
// pointers.
if (! InitBuffers())
{
printf(pszNOT_ENOUGH_MEM);
return(EXIT_FAILURE);
}
if ($argc == 3 && ! bIsDir)
{
// CASE 1: expand a file to a different file
if ( !Decompress($argv[1], $argv[2]) )
rc = EXIT_FAILURE;
}
else
{
// CASE 2: expand a file or files to a file or files with the same name
// in a different directory specified in $argv[$argc - 1].
for (i = 1; i < $argc - 1; i++)
{
InitBufferPtrs();
cblOutSize = 0L;
strcpy(rgchDestFileName, $argv[$argc - 1]);
CatPathAndFileName(rgchDestFileName, ExtractFileName($argv[i]));
if ( !Decompress($argv[i], rgchDestFileName) )
{
rc = EXIT_FAILURE;
break;
}
cblTotIn += cblInSize;
cblTotOut += cblOutSize;
}
#ifdef DEBUG0
printf("\n %ld bytes expanded to %ld bytes, savings: %d%%\n",
cblTotIn, cblTotOut, (int)(100 - 100 * cblTotOut / cblTotIn));
#endif
}
if( iFiles == 1 )
printf( pszONE_FILE, iFiles);
else
if( iFiles > 1 )
printf( pszTOTAL_FILES, iFiles);
return(rc);
}
/* main(int argc, char *argv[] )
*
* Decompress source file(s) to destination.
*
* ENTRY: argc Number of input parameters
* argv[] Array of ptrs to input parameters
*
* EXIT: EXIT_SUCCESS or EXIT_FAILURE.
*
* NOTES: This function primarily parses the command-line. The function
* ProcessInput() does most of the real work.
*
* HISTORY: M001 main() now does command-line parsing; ProcessInput() does
* most everything else.
*
*/
int main(int argc, char *argv[])
{
int i;
char *$argv[3]; /* Dummy argv[] for user prompted input. */
char szSource[MAXFILESPECLEN]; /* Prompted source input. */
char szDest[MAXFILESPECLEN]; /* Prompted destination input. */
/* Parse command-line */
if( HelpSwitchPresent(argc, argv) ) /* EXPAND /?: display help */
{
PrintInstructions1(); // IPG - These two lines used to be one macro
PrintInstructions2(); // IPG - called PrintInstructions()
Quit(EXIT_FAILURE);
}
else
if( argc == 1 || argc == 2 ) /* Missing parameters: prompt user */
{
/* Init. dummy argv[] so user input can be treated
* as command-line input parameters.
*/
$argv[0] = argv[0]; /* program name */
if( argc == 2 ) /* Use cmd-line source input, if available */
$argv[1] = argv[1];
else
$argv[1] = szSource; /* source input buffer */
$argv[2] = szDest; /* destination input buffer */
/* Prompt user for source, $argv[1], and destination, $argv[2]. */
if ( !PromptUser(argc, $argv) )
Quit(EXIT_FAILURE);
Quit( ProcessInput( 3, $argv ) );
}
else
if( argc > 2 )
{
Quit( ProcessInput( argc, argv ) );
}
else
{
printf(pszINVALID);
Quit(EXIT_FAILURE);
}
return(EXIT_SUCCESS);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -