Guest User

Untitled

a guest
Aug 5th, 2007
893
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.48 KB | None | 0 0
  1. #include <zlib.h>
  2. #include <dirent.h>
  3. #include <vector>
  4. #include <string>
  5. #include <stdio.h>
  6. #include <unistd.h>
  7. #include <sys/stat.h>
  8. using namespace std;
  9.  
  10. // make a file archive
  11.  
  12. typedef unsigned int u32;
  13.  
  14. const size_t FILENAME_LEN = 64;
  15. const size_t BLOCKSIZE = 128;
  16.  
  17. const u32 VERSION = 0x10001000;
  18.  
  19. // 16 bytes
  20. struct Header {
  21.     char id[4];
  22.     u32 version;
  23.     u32 size;
  24.     u32 files;
  25. };
  26.  
  27. // 96 bytes
  28. struct FileEntry {
  29.     char filename[FILENAME_LEN];
  30.     u32 size;
  31.     u32 offset;
  32.     u32 namehash;
  33.     u32 checksum;
  34.     u32 flags;
  35.     u32 locale;
  36.     u32 reserved1;
  37.     u32 reserved2;
  38. };
  39.  
  40. enum FLAGS
  41. {
  42.     FLAG_LOCALIZED = 1<<0,
  43.     FLAG_TSC = 1<<1
  44. };
  45.  
  46.  
  47.  
  48.  
  49. u32 calc_crc32(const void *data, u32 size)
  50. {
  51.     u32 crc = crc32(0L, Z_NULL, 0);
  52.     crc = crc32(crc, (const Bytef*)data, size);
  53.     return crc;
  54. }
  55.  
  56. vector<FileEntry> files;
  57. vector<string> filepaths;
  58. u32 gsize;
  59.  
  60. void addFile(const char *filename, const struct stat *st)
  61. {
  62.     assert(filename);
  63.     size_t namelen = strlen(filename);
  64.     if (namelen>FILENAME_LEN) {
  65.         fprintf(stderr, "Skipping file: %s (filename too long)\n", filename);
  66.         return;
  67.     }
  68.  
  69.     string origname(filename);
  70.  
  71.     FileEntry fe;
  72.     memset(&fe, 0, sizeof(FileEntry));
  73.  
  74.     // check name for a locale?
  75.     if (!strcmp(filename+namelen-3,".en")) fe.locale = 1;
  76.     else if (!strcmp(filename+namelen-3,".jp")) fe.locale = 2;
  77.  
  78.     if (fe.locale) {
  79.         namelen -= 3;
  80.         fe.flags |= FLAG_LOCALIZED;
  81.     }
  82.  
  83.     strncpy(fe.filename, filename, namelen);
  84.  
  85.     fe.size = st->st_size;
  86.     fe.namehash = calc_crc32(filename, namelen);
  87.  
  88.     if (!strncmp(filename+namelen-4,".tsc",4)) fe.flags |= FLAG_TSC;
  89.  
  90.     FILE *f = fopen(origname.c_str(),"rb");
  91.     char *buf = new char[fe.size];
  92.     fread(buf, fe.size, 1, f);
  93.     fclose(f);
  94.     fe.checksum = calc_crc32(buf,fe.size);
  95.     delete[] buf;
  96.  
  97.     files.push_back(fe);
  98.     filepaths.push_back(origname);
  99. }
  100.  
  101. void scanDir(const char *dirname) {
  102.     assert(dirname);
  103.  
  104.     string basepath(dirname);
  105.     DIR *dir = opendir(dirname);
  106.     while (dirent *de = readdir(dir)) {
  107.         const char *filename = de->d_name;
  108.  
  109.         string fullpath = basepath + "/";
  110.         fullpath += filename;
  111.  
  112.         if (filename[0]!='.') {
  113.             //printf("%s\n",fullpath.c_str());
  114.  
  115.             struct stat st;
  116.             stat(fullpath.c_str(), &st);
  117.             if (S_ISDIR(st.st_mode)) {
  118.                 // recurse
  119.                 scanDir(fullpath.c_str());
  120.             } else {
  121.                 addFile(fullpath.c_str(), &st);
  122.             }
  123.         }
  124.  
  125.     }
  126.     closedir(dir);
  127. }
  128.  
  129. int roundUp(int value, int block = BLOCKSIZE)
  130. {
  131.     int rem = value % block;
  132.     return rem ? (value + block - rem) : value;
  133. }
  134.  
  135. void buildFile(const char *nameOut)
  136. {
  137.     int num = files.size();
  138.     static char dummy[BLOCKSIZE];
  139.     memset(dummy, 0, BLOCKSIZE);
  140.  
  141.     // fix up offsets
  142.     int headersize = sizeof(Header) + num * sizeof(FileEntry);
  143.     int firstoffset = roundUp(headersize);
  144.     int of = firstoffset;
  145.  
  146.     for (vector<FileEntry>::iterator it = files.begin(); it != files.end(); ++it) {
  147.         it->offset = of;
  148.         of = roundUp(of+it->size);
  149.     }
  150.  
  151.     Header h;
  152.     strncpy(h.id, "Cave", 4);
  153.     h.version = VERSION;
  154.     h.size = of;
  155.     gsize = of;
  156.     h.files = num;
  157.  
  158.     FILE *fo = fopen(nameOut,"wb");
  159.     // write header
  160.     fwrite(&h, sizeof(Header), 1, fo);
  161.     // write file entries
  162.     for (vector<FileEntry>::iterator it = files.begin(); it != files.end(); ++it) {
  163.         FileEntry *fe = &(*it);
  164.         fwrite(fe, sizeof(FileEntry), 1, fo);
  165.     }
  166.     // pad
  167.     fwrite(dummy, firstoffset-headersize, 1, fo);
  168.  
  169.     // write the files
  170.     for (u32 i=0; i<num; i++) {
  171.         FileEntry &fe = files[i];
  172.         string &name = filepaths[i];
  173.  
  174.         FILE *fi = fopen(name.c_str(), "rb");
  175.         char *buf = new char[fe.size];
  176.         fread(buf, fe.size, 1, fi);
  177.         fclose(fi);
  178.  
  179.         fwrite(buf, fe.size, 1, fo);
  180.         delete[] buf;
  181.  
  182.         // pad
  183.         int toPad = roundUp(fe.size) - fe.size;
  184.         if (toPad) fwrite(dummy, toPad, 1, fo);
  185.     }
  186.  
  187.     fclose(fo);
  188.     printf("%d files packed.\n", num);
  189. }
  190.  
  191. void compressFile(const char *nameIn, const char *nameOut)
  192. {
  193.     FILE *f = fopen(nameIn, "rb");
  194.     char *buf = new char[gsize];
  195.     fread(buf, gsize, 1, f);
  196.     fclose(f);
  197.  
  198.     u32 len = compressBound(gsize);
  199.     char *buf2 = new char[len];
  200.     int res = compress2((Bytef*)buf2, (uLongf*)&len, (const Bytef*)buf, gsize, 9);
  201.     if (res != Z_OK) {
  202.         fprintf(stderr, "Couldn't compress data\n");
  203.     } else {
  204.         f = fopen(nameOut, "wb");
  205.         fwrite(&gsize, sizeof(u32), 1, f);
  206.         fwrite(buf2, len, 1, f);
  207.         fclose(f);
  208.  
  209.         delete[] buf;
  210.         delete[] buf2;
  211.         printf("Compressed %d -> %d bytes\n", gsize, len);
  212.     }
  213. }
  214.  
  215. int main(int argc, char *argv[])
  216. {
  217.     scanDir("data");
  218.     buildFile("archive.dat");
  219.     compressFile("archive.dat", "data.csz");
  220.     return 0;
  221. }
  222.  
  223.  
  224.  
Advertisement
Add Comment
Please, Sign In to add comment