Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

281 lines
7.2 KiB

  1. /*
  2. ** expand.c - Main expansion routine for LZA file expansion program.
  3. **
  4. ** Author: DavidDi
  5. */
  6. // Headers
  7. ///////////
  8. #ifndef LZA_DLL
  9. #include <dos.h>
  10. #include <errno.h>
  11. #include <io.h>
  12. #include <stdio.h>
  13. #include <string.h>
  14. #endif
  15. #include "lz_common.h"
  16. #include "lzcommon.h"
  17. #include "lz_buffers.h"
  18. #include "lz_header.h"
  19. /*
  20. ** N.b., one reason DOS file handles are used for file references in this
  21. ** module is that using FILE *'s for file references poses a problem.
  22. ** fclose()'ing a file which was fopen()'ed in write "w" or append "a" mode
  23. ** stamps the file with the current date. This undoes the intended effect of
  24. ** CopyDateTimeStamp(). We could also get around this fclose() problem by
  25. ** first fclose()'ing the file, and then fopen()'ing it again in read "r"
  26. ** mode.
  27. **
  28. ** Using file handles also allows us to bypass stream buffering, so reads and
  29. ** writes may be done with whatever buffer size we choose. Also, the
  30. ** lower-level DOS file handle functions are faster than their stream
  31. ** counterparts.
  32. */
  33. /*
  34. ** int CopyFile(int doshSource, int doshDest);
  35. **
  36. ** Copy file.
  37. **
  38. ** Arguments: doshSource - source DOS file handle
  39. ** doshDest - destination DOS file handle
  40. **
  41. ** Returns: int - TRUE if successful. One of the LZERROR_ codes if
  42. ** unsuccessful.
  43. **
  44. ** Globals: none
  45. */
  46. /* WIN32 MOD, CopyFile is a win32 API!*/
  47. INT lz_CopyFile(INT doshSource, INT doshDest, PLZINFO pLZI)
  48. {
  49. DWORD ucbRead, ucbWritten;
  50. // !!! Assumes pLZI parm is valid. No sanity check (should be done above in caller).
  51. // Rewind input file again.
  52. if (FSEEK(doshSource, 0L, SEEK_SET) != 0L) {
  53. return(LZERROR_BADINHANDLE);
  54. }
  55. // Rewind output file.
  56. if (doshDest != NO_DOSH &&
  57. FSEEK(doshDest, 0L, SEEK_SET) != 0L) {
  58. return( LZERROR_BADOUTHANDLE );
  59. }
  60. // Set up a fresh buffer state.
  61. ResetBuffers();
  62. while ((ucbRead = FREAD(doshSource, pLZI->rgbyteInBuf, pLZI->ucbInBufLen)) > 0U &&
  63. #ifdef LZA_DLL
  64. ucbRead != (DWORD)(-1))
  65. #else
  66. FERROR() == 0)
  67. #endif
  68. {
  69. if ((ucbWritten = FWRITE(doshDest, pLZI->rgbyteInBuf, ucbRead)) != ucbRead)
  70. #ifdef LZA_DLL
  71. if (ucbWritten != (DWORD)(-1)) {
  72. #else
  73. if (FERROR() != 0) {
  74. #endif
  75. return(LZERROR_BADOUTHANDLE);
  76. }
  77. else {
  78. return(LZERROR_WRITE);
  79. }
  80. pLZI->cblOutSize += ucbWritten;
  81. if (ucbRead != pLZI->ucbInBufLen)
  82. break;
  83. }
  84. #ifdef LZA_DLL
  85. // here, ucbRead == 0, EOF (proper loop termination)
  86. // == -1, bad DOS handle
  87. if (ucbRead == (DWORD)(-1)) {
  88. #else
  89. // here, FERROR() == 0U, EOF (proper loop termination)
  90. // != 0U, bad DOS handle
  91. if (FERROR() != 0U) {
  92. #endif
  93. return(LZERROR_BADINHANDLE);
  94. }
  95. // Copy successful - return number of bytes copied.
  96. return(TRUE);
  97. }
  98. /*
  99. ** int ExpandOrCopyFile(int doshDource, int doshDest);
  100. **
  101. ** Expands one file to another.
  102. **
  103. ** Arguments: doshSource - source DOS file handle
  104. ** doshDest - destination DOS file handle
  105. **
  106. ** Returns: int - TRUE if expansion finished successfully. One of the
  107. ** LZERROR_ codes if not.
  108. **
  109. ** Globals: none
  110. */
  111. INT ExpandOrCopyFile(INT doshSource, INT doshDest, PLZINFO pLZI)
  112. {
  113. INT f;
  114. FH FHInfo; // compressed header info struct
  115. BOOL bExpandingFile;
  116. // !!! Assumes pLZI parm is valid. No sanity check (should be done above in caller).
  117. // Get compressed file header.
  118. if (GetHdr(&FHInfo, doshSource, &pLZI->cblInSize) != TRUE
  119. && pLZI->cblInSize >= (LONG)HEADER_LEN)
  120. // read error occurred
  121. return(LZERROR_BADINHANDLE);
  122. // Expand or copy input file to output file.
  123. bExpandingFile = (IsCompressed(& FHInfo) == TRUE);
  124. if (bExpandingFile)
  125. {
  126. switch (FHInfo.byteAlgorithm)
  127. {
  128. case ALG_FIRST:
  129. f = LZDecode(doshSource, doshDest, (LONG)FHInfo.cbulUncompSize - 1L,
  130. TRUE, TRUE, pLZI);
  131. break;
  132. #if 0
  133. case ALG_LZ:
  134. f = LZDecode(doshSource, doshDest, (LONG)FHInfo.cbulUncompSize - 1L,
  135. TRUE, FALSE, pLZI);
  136. break;
  137. #endif
  138. default:
  139. f = LZERROR_UNKNOWNALG;
  140. break;
  141. }
  142. }
  143. else
  144. f = lz_CopyFile(doshSource, doshDest, pLZI);
  145. if (f != TRUE)
  146. return(f);
  147. // Flush output buffer to file.
  148. if ((f = FlushOutputBuffer(doshDest, pLZI)) != TRUE)
  149. return(f);
  150. // Copy date and time stamp from source file to destination file.
  151. if ((f = CopyDateTimeStamp(doshSource, doshDest)) != TRUE)
  152. return(f);
  153. // Did we expand the exact number of bytes we expected to from the
  154. // compressed file header entry?
  155. if (bExpandingFile &&
  156. (DWORD)pLZI->cblOutSize != FHInfo.cbulUncompSize)
  157. return(LZERROR_READ);
  158. // Expansion / copying finished successfully.
  159. return(TRUE);
  160. }
  161. /*
  162. ** int Expand(char ARG_PTR *pszSource, char ARG_PTR *pszDest, BOOL bDoRename);
  163. **
  164. ** Expands one file to another.
  165. **
  166. ** Arguments: pszSource - name of file to compress
  167. ** pszDest - name of compressed output file
  168. ** bDoRename - flag for output file renaming
  169. **
  170. ** Returns: int - TRUE if expansion finished successfully. One of the
  171. ** LZERROR_ codes if not.
  172. **
  173. ** Globals: none
  174. */
  175. INT Expand(
  176. NOTIFYPROC pfnNotify,
  177. CHAR ARG_PTR *pszSource,
  178. CHAR ARG_PTR *pszDest,
  179. BOOL bDoRename,
  180. PLZINFO pLZI)
  181. {
  182. INT doshSource, // input file handle
  183. doshDest, // output file handle
  184. f;
  185. FH FHInfo; // compressed header info struct
  186. CHAR szDestFileName[MAX_PATH];
  187. // Sanity check
  188. if (!pLZI) {
  189. return(LZERROR_GLOBLOCK);
  190. }
  191. // Set up input file handle. Set cblInSize to length of input file.
  192. if ((f = GetIOHandle(pszSource, READ_IT, & doshSource, &pLZI->cblInSize)) != TRUE)
  193. return(f);
  194. if (GetHdr(&FHInfo, doshSource, &pLZI->cblInSize) != TRUE &&
  195. pLZI->cblInSize >= (LONG)HEADER_LEN)
  196. {
  197. // Read error occurred.
  198. FCLOSE(doshSource);
  199. return(LZERROR_BADINHANDLE);
  200. }
  201. // Create destination file name.
  202. STRCPY(szDestFileName, pszDest);
  203. #if 0
  204. if (bDoRename == TRUE && FHInfo.byteAlgorithm != ALG_FIRST)
  205. #else
  206. if (bDoRename == TRUE)
  207. #endif
  208. {
  209. // Rename output file using expanded file name extension character
  210. // stored in compressed file header.
  211. MakeExpandedName(szDestFileName, FHInfo.byteExtensionChar);
  212. }
  213. // Ask if we should compress this file.
  214. if (! (*pfnNotify)(pszSource, szDestFileName, (WORD)
  215. (IsCompressed(&FHInfo) ? NOTIFY_START_EXPAND : NOTIFY_START_COPY)))
  216. {
  217. // Don't expand / copy file. This error condition should be handled in
  218. // pfnNotify, so indicate that it is not necessary for the caller to
  219. // display an error message.
  220. FCLOSE(doshSource);
  221. return(BLANK_ERROR);
  222. }
  223. // Set up output file handle.
  224. if ((f = GetIOHandle(szDestFileName, WRITE_IT, & doshDest, &pLZI->cblInSize)) != TRUE)
  225. {
  226. FCLOSE(doshSource);
  227. return(f);
  228. }
  229. // Expand or copy input file into output file.
  230. f = ExpandOrCopyFile(doshSource, doshDest, pLZI);
  231. // Close files.
  232. FCLOSE(doshSource);
  233. FCLOSE(doshDest);
  234. return(f);
  235. }