CabUtil.cpp 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. #include "CabUtil.h"
  2. #ifdef BF_PLATFORM_WINDOWS
  3. #pragma warning(disable:4996)
  4. #pragma comment(lib, "cabinet.lib")
  5. #include <FDI.h>
  6. #include <io.h>
  7. #include <fcntl.h>
  8. #include <sys/stat.h>
  9. USING_NS_BF;
  10. static char* FDIErrorToString(FDIERROR err)
  11. {
  12. switch (err)
  13. {
  14. case FDIERROR_NONE:
  15. return "No error";
  16. case FDIERROR_CABINET_NOT_FOUND:
  17. return "Cabinet not found";
  18. case FDIERROR_NOT_A_CABINET:
  19. return "Not a cabinet";
  20. case FDIERROR_UNKNOWN_CABINET_VERSION:
  21. return "Unknown cabinet version";
  22. case FDIERROR_CORRUPT_CABINET:
  23. return "Corrupt cabinet";
  24. case FDIERROR_ALLOC_FAIL:
  25. return "Memory allocation failed";
  26. case FDIERROR_BAD_COMPR_TYPE:
  27. return "Unknown compression type";
  28. case FDIERROR_MDI_FAIL:
  29. return "Failure decompressing data";
  30. case FDIERROR_TARGET_FILE:
  31. return "Failure writing to target file";
  32. case FDIERROR_RESERVE_MISMATCH:
  33. return "Cabinets in set have different RESERVE sizes";
  34. case FDIERROR_WRONG_CABINET:
  35. return "Cabinet returned on fdintNEXT_CABINET is incorrect";
  36. case FDIERROR_USER_ABORT:
  37. return "Application aborted";
  38. default:
  39. return "Unknown error";
  40. }
  41. }
  42. CabFile::CabFile()
  43. {
  44. }
  45. static FNALLOC(CabMemAlloc)
  46. {
  47. return malloc(cb);
  48. }
  49. static FNFREE(CabMemFree)
  50. {
  51. free(pv);
  52. }
  53. static FNOPEN(CabFileOpen)
  54. {
  55. return _open(pszFile, oflag, pmode);
  56. }
  57. static FNREAD(CabFileRead)
  58. {
  59. return _read((int)hf, pv, cb);
  60. }
  61. static FNWRITE(CabFileWrite)
  62. {
  63. return _write((int)hf, pv, cb);
  64. }
  65. static FNCLOSE(CabFileClose)
  66. {
  67. return _close((int)hf);
  68. }
  69. static FNSEEK(CabFileSeek)
  70. {
  71. return _lseek((int)hf, dist, seektype);
  72. }
  73. static FNFDINOTIFY(CabFDINotify)
  74. {
  75. CabFile* cabFile = (CabFile*)pfdin->pv;
  76. switch (fdint)
  77. {
  78. case fdintCOPY_FILE:
  79. {
  80. String destName = cabFile->mDestDir;
  81. destName += "/";
  82. destName += pfdin->psz1;
  83. int fh = (int)CabFileOpen((LPSTR)destName.c_str(), _O_BINARY | _O_CREAT | _O_WRONLY | _O_SEQUENTIAL,
  84. _S_IREAD | _S_IWRITE);
  85. if (fh == -1)
  86. cabFile->Fail(StrFormat("Failed to create '%s'", destName.c_str()));
  87. return fh;
  88. }
  89. case fdintCLOSE_FILE_INFO:
  90. CabFileClose(pfdin->hf);
  91. return TRUE;
  92. default:
  93. break;
  94. }
  95. return 0;
  96. }
  97. void CabFile::Fail(const StringImpl& err)
  98. {
  99. if (mError.IsEmpty())
  100. mError = err;
  101. }
  102. bool CabFile::Load(const StringImpl& path)
  103. {
  104. if (!FileExists(path))
  105. {
  106. Fail(StrFormat("File '%s' not found", path.c_str()));
  107. return false;
  108. }
  109. mSrcFileName = path;
  110. return true;
  111. }
  112. bool CabFile::DecompressAll(const StringImpl& destDir)
  113. {
  114. if (mSrcFileName.IsEmpty())
  115. {
  116. Fail("No file specified");
  117. return false;
  118. }
  119. ERF erf = { 0 };
  120. HFDI fdi = FDICreate(CabMemAlloc, CabMemFree, CabFileOpen, CabFileRead, CabFileWrite, CabFileClose, CabFileSeek, cpu80386, &erf);
  121. if (!fdi)
  122. return false;
  123. RecursiveCreateDirectory(destDir);
  124. mDestDir = destDir;
  125. bool result = FDICopy(fdi, (LPSTR)GetFileName(mSrcFileName).c_str(), (LPSTR)(GetFileDir(mSrcFileName) + "/").c_str(), 0, CabFDINotify, NULL, this) != 0;
  126. if (!result)
  127. Fail(FDIErrorToString((FDIERROR)erf.erfOper));
  128. FDIDestroy(fdi);
  129. return result;
  130. }
  131. #endif