?? archiver.cpp
字號:
// Created:11-16-98
// By Jeff Connelly
// An archiver using ComprLib
#if 0
************************** Archive structure ******************************
This header is present only at the beginning:
OFFSET Count TYPE Description
0x0000 4 char ID="ARCH"
0x0004 4 char ID="IVE" followed by 1Ah
0x0008 1 dword Files in archive (up to over a million!)
For each file, there is:
OFFSET Count TYPE Description
0x0000 1 byte Misc flags, bitmapped:
Bits numbered: 7654 3210
0 - Compressed
1 - CRC-32 stored
2 - Comment
3 - File is deleted
4 to 7 - Compression method if compressed
(see table 0x0000)
0x0000 1 dword Size of file in the archive (not orig size)
???? 1 dword If compressed: original size
???? 1 dword If CRC-32 stored: CRC-32
???? 1 word If comment: comment length
???? ? char If comment: comment text
???? ? char Filename, ASCIIZ
???? ? byte File contents
TABLE 0x0000: Compression methods
0000 - Not used, set if not compressed
0001 - RLE method 1
0010 - RLE method 2
0011 - LZSS
0100 - LZW
0101 - Inverted (encryption sort of)
#endif
#include "comprlib.h"
#include <stdio.h>
#include <stdlib.h>
#include <io.h>
FILE* arc; // The archive
char* archive; // Filename of archive
bool flag_recover_deleted = false; // Extract deleted files?
bool flag_verbose = true; // Verbose output?
// Class representing a file in this archive
struct Member
{
public:
Member():flags(0), size(0), origsize(0), crc32(0), commentlen(0),
comment(NULL), data(NULL) { };
void Destroy();
~Member() { Destroy(); };
void Write();
void Read();
// 'flags' can be ANDed with these values to see if the bits are set:
#define FLAG_COMPRESSED 0x01
#define FLAG_CRC32 0x02
#define FLAG_COMMENT 0x04
#define FLAG_DELETED 0x08
unsigned char flags;
unsigned long size;
unsigned long origsize;
unsigned long crc32;
unsigned short commentlen;
char* comment;
char* filename;
char* data;
};
// Free memory allocated by this
void Member::Destroy()
{
xfree(data);
xfree(filename);
xfree(comment);
}
// Write this member to the archive
void Member::Write()
{
fwrite (&flags, 1, 1, arc);
fwrite (&size, 1, 4, arc);
if (flags & FLAG_COMPRESSED)
fwrite (&origsize, 1, 4, arc);
if (flags & FLAG_CRC32)
fwrite (&crc32, 1, 4, arc);
if (flags & FLAG_COMMENT)
{
fwrite (&commentlen, 1, 2, arc);
fwrite (comment, 1, commentlen, arc);
}
fwrite (filename, 1, strlen(filename) + 1, arc);
fwrite (data, 1, size, arc);
}
// Read the member from the archive
void Member::Read()
{
register char c;
int i;
fread (&flags, 1, 1, arc);
fread (&size, 1, 4, arc);
if (flags & FLAG_COMPRESSED)
fread (&origsize, 1, 4, arc);
if (flags & FLAG_CRC32)
fread (&crc32, 1, 4, arc);
if (flags & FLAG_COMMENT)
{
fread (&commentlen, 1, 2, arc);
fread (comment, 1, commentlen, arc);
}
// Read the null-terminated filename
{
int i = 0;
register char c;
filename = NULL;
filename = (char*)xmalloc(1);
do
{
c = getc(arc);
filename[i] = c;
filename = (char*)xrealloc(filename, (i++) + 1);
} while (c);
filename[i - 2] = 0;
}
fread (data, 1, size, arc);
}
// Deturmine size of file 'fp'
long file_size(FILE* fp)
{
unsigned long pos, ret;
pos = ftell(fp);
fseek (fp, 0, SEEK_END);
ret = ftell(fp);
fseek (fp, pos, SEEK_SET);
return ret;
}
// Does the option 'opt'
void CheckOption(char* opt)
{
if (opt[0] != '-' && opt[0] != '/')
return;
switch (tolower(opt[1]))
{
case 'R': flag_recover_deleted = true; break;
case 'V': flag_verbose = true; break;
case 'Q': flag_verbose = false; break;
}
}
void add_files(int count, char* files[])
{
int i;
FILE* fp;
Member file;
arc = fopen(archive, "ab");
if (!file_size(arc)) // New archive
{
{
char* sig = (char*)xmalloc(8);
int count = 0; // Initialized to zero
strcpy (sig, "ARCHIVE\032");
fwrite(sig, 1, 8, arc);
fwrite(&count, 1, 4, arc);
}
}
for (i = 0; i < count && files[i]; ++i)
{
if (files[i][0] == '-' || files[i][0] == '/')
{
CheckOption(files[i]);
continue;
}
printf ("\nArchiving %s...\n", files[i]);
fp = fopen(files[i], "rb");
if (!fp)
{
printf ("Cannot open %s\n", files[i]);
exit (2);
}
// Read the entire file
file.size = file_size(fp);
file.data = (char*)xmalloc(file.size);
fread(file.data, 1, file.size, fp);
fclose(fp);
// Set the filename
file.filename = (char*)xmalloc(strlen(files[i]));
strcpy (file.filename, files[i]);
file.Write(); // Archive the file
}
// We're not done yet. We need to write the file count.
fseek(arc, 9, SEEK_SET);
fwrite(&count, 1, 4, arc);
}
// Extracts all the files
void extract_files()
{
FILE* fp;
unsigned long count;
Member file;
register int i;
arc = fopen(archive, "rb");
if (!arc)
{
printf ("Cannot open %s\n", archive);
exit (2);
}
// Read the header
{
char* sig = (char*)xmalloc(9);
fread (sig, 1, 8, arc);
sig[8] = 0;
if (strcmp(sig, "ARCHIVE\032"))
{
printf ("Invalid archive\n");
exit (3);
}
fread (&count, 1, 4, arc);
}
// Read the files
for (i = 0; i < count && !feof(arc); ++i)
{
file.Read();
if (file.flags & FLAG_DELETED)
{
if (!flag_recover_deleted)
{
// Not to be extracted
printf ("\nIgnoring %s\n", file.filename);
continue;
}
}
printf ("\nExtracting %s...", file.filename);
fp = fopen(file.filename, "wb");
if (!fp)
{
printf ("Cannot open %s\n", file.filename);
exit (1);
}
fwrite (file.data, 1, file.size, fp);
fclose(fp);
}
}
// List all the files
void list_files()
{
Member file;
char* filename;
unsigned long count;
char deleted;
char* comment;
// Open and initialize archive
{
char* sig;
arc = fopen(archive, "rb");
if (!arc)
{
printf ("Cannot open %s\n", arc);
exit (1);
}
sig = (char*)xmalloc(9);
sig[8] = 0; // Null-terminated string
fread (sig, 1, 8, arc);
if (strcmp(sig, "ARCHIVE\032"))
{
printf ("Invalid archive\n");
exit (3);
}
xfree(sig);
fread (&count, 1, 4, arc);
}
// Print the header
printf (" Filename Size Packed Ratio CRC32 Deleted Comment");
while(!feof(arc))
{
file.Read();
// If the file is not compressed, 'origsize' will not be set, but
// we need to know it to calculate the ratio
if (!(file.flags & FLAG_COMPRESSED))
file.origsize = file.size;
if (file.flags & FLAG_COMMENT)
{
comment = (char*)xmalloc(file.commentlen + 1);
strcpy (comment, file.comment);
comment[file.commentlen + 1] = 0; // Null-terminated
}
if (file.flags & FLAG_DELETED)
deleted = '*';
else
deleted = ' ';
printf (" %s %U %U %d %x %s %c\n",
file.filename,
file.size,
file.origsize,
(double)file.size / (double)file.origsize,
file.crc32,
deleted,
comment);
xfree(comment);
}
}
const char* help = "Archives files to archives\n"
"\tARCHIVE command archive [files]\n"
"Commands are: \n"
"a Add files (no files specified -> create archive)\n"
"x Extract files\n"
"l List files\n"
"Options can be specified within the file list: \n"
"\n";
int main(int argc, char* argv[])
{
register int i;
if (argc == 1)
{
printf(help);
exit(0);
}
char cmd;
cmd = tolower(argv[1][0]);
archive = (char*)xmalloc(strlen(argv[2]));
strcpy (archive, argv[2]);
// Parse the flags
for (i = 3; i < argc; ++i)
{
CheckOption(argv[i]);
}
switch(cmd)
{
case 'a': add_files(argc - 2, &argv[3]); break;
case 'x': extract_files(); break;
case 'l': list_files(); break;
default: printf ("Bad command '%c'\n", cmd); exit (3); break;
}
return 0;
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -