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.

483 lines
13 KiB

  1. /* ************************************************************ *
  2. *
  3. * 'Packer.C
  4. *
  5. * Packer.C is a tool that packages the structure and data within
  6. * a given directory into two C header files. Currently this tool
  7. * is specific for the WorkGroup PostOffice. If there is some
  8. * interest in making this tool more general, I would be happy
  9. * to make it so, time permitting.
  10. *
  11. * ************************************************************ */
  12. #include <windows.h>
  13. #include <assert.h>
  14. #include <stdio.h>
  15. #include <stdlib.h>
  16. #include <string.h>
  17. #pragma pack(1)
  18. /* ************************************************************ *
  19. *
  20. * Constants and definitions
  21. *
  22. * ************************************************************ */
  23. #define rgbMaxBuffer 16 * 1024
  24. #define crgMaxFile 256
  25. #define cchMaxFile 64
  26. #define szCR "\n"
  27. typedef int FO;
  28. #define FO_Open 101
  29. #define FO_Write 102
  30. #define FO_Close 103
  31. /* ************************************************************ *
  32. *
  33. * Function prototypes
  34. *
  35. * ************************************************************ */
  36. int EcTravelDir(char *);
  37. int EcFileInfo(FO, char *);
  38. int EcFileData(FO, char *);
  39. /* ************************************************************ *
  40. *
  41. * Global variables
  42. *
  43. * ************************************************************ */
  44. // Store file info
  45. char rgszFile[crgMaxFile][cchMaxFile];
  46. int rgFileState[crgMaxFile];
  47. // Store file data
  48. unsigned char rgbBuffer[rgbMaxBuffer];
  49. /* ************************************************************ *
  50. *
  51. * void 'Main
  52. *
  53. * In: int cArg Count of arguments
  54. * In: char *rgszArg[] Argument string array
  55. *
  56. * Main returns void.
  57. *
  58. * Main checks if the command-line arguments are valid.
  59. * If so, it calls EcTravelDir to pack the given directory.
  60. *
  61. * Main causes no side-effects.
  62. *
  63. * Main indicates any error with a message to stdout.
  64. *
  65. * ************************************************************ */
  66. void
  67. __cdecl
  68. main(
  69. int cArg,
  70. char *rgszArg[]
  71. )
  72. {
  73. int ec = 0;
  74. // Check count of command-line arguments
  75. if (cArg != 2) {
  76. printf("USAGE: packer [directory]\n");
  77. exit(EXIT_FAILURE);
  78. }
  79. if (EcTravelDir(rgszArg[1]) != 0)
  80. exit(EXIT_FAILURE);
  81. exit(EXIT_SUCCESS);
  82. }
  83. /* ************************************************************ *
  84. *
  85. * int 'EcTravelDir
  86. *
  87. * In: char *szTravelDir Directory to pack
  88. *
  89. * EcTravelDir returns a standard exit code.
  90. *
  91. * EcTravelDir packages the directory structure and all files
  92. * within the given directory into two C header files. The
  93. * directory tree is travelled in a current node, "low" branch,
  94. * "high" branch pattern. This means the files and sub-directories
  95. * of the current directory are enumerated and saved, then the
  96. * sub-directories are traversed from the lowest to the highest
  97. * as they appear in the directory list. Directory structure
  98. * info is handled by EcFileInfo while file data is handled by
  99. * EcFileData.
  100. *
  101. * EcTravelDir causes a disk side-effect.
  102. *
  103. * EcTravelDir indicates any error via the exit code.
  104. *
  105. * ************************************************************ */
  106. int
  107. EcTravelDir(
  108. char *szTravelDir
  109. )
  110. {
  111. int ec = 0;
  112. int iFile = 0;
  113. int iFileParent;
  114. char szFile[cchMaxFile] = "";
  115. char szDir[cchMaxFile] = "";
  116. char szDrive[_MAX_DRIVE] = "";
  117. char szPath[_MAX_DIR] = "";
  118. char szFileName[_MAX_FNAME] = "";
  119. char szFileExt[_MAX_EXT] = "";
  120. int ixType;
  121. long lcbxFile;
  122. char szxFile[cchMaxFile];
  123. unsigned short us;
  124. HANDLE hdir;
  125. WIN32_FIND_DATA findbuf;
  126. _splitpath(szTravelDir, szDrive, szPath, szFileName, szFileExt);
  127. _makepath(szDir, "", szPath, szFileName, szFileExt);
  128. if (szDir[strlen(szDir)-1] != '\\')
  129. strcat(szDir, "\\");
  130. // *** Open header files ***
  131. ec = EcFileInfo(FO_Open, "_fileinf.h");
  132. if (ec != 0)
  133. goto RET;
  134. ec = EcFileData(FO_Open, "_filedat.h");
  135. if (ec != 0)
  136. goto RET;
  137. // *** Traverse directory tree ***
  138. // Initial directory
  139. strcpy(rgszFile[0], "");
  140. rgFileState[0] = '\0';
  141. while (1) {
  142. if (rgFileState[iFile] == 0) {
  143. // Keep track of parent directory
  144. rgFileState[iFile] = 1;
  145. iFileParent = iFile;
  146. // Prepare szFile and hdir
  147. strcpy(szFile, szDrive);
  148. strcat(szFile, szDir);
  149. strcat(szFile, rgszFile[iFile]);
  150. strcat(szFile, "*.*");
  151. // Skip . entry
  152. hdir = FindFirstFile(szFile, &findbuf);
  153. if (hdir == INVALID_HANDLE_VALUE) {
  154. ec = 1;
  155. goto CLOSE;
  156. }
  157. // Skip .. entry
  158. //FindNextFile(hdir, &findbuf);
  159. // *** Enumerate current directory ***
  160. while (1) {
  161. if(!FindNextFile(hdir, &findbuf) &&
  162. GetLastError() == ERROR_NO_MORE_FILES)
  163. break;
  164. //
  165. // Skip over any file that begins with '.'.
  166. //
  167. if (findbuf.cFileName[0] == '.')
  168. continue;
  169. //
  170. // Skip over hidden and system files.
  171. //
  172. if (findbuf.dwFileAttributes & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM))
  173. continue;
  174. // *** Set file info data ***
  175. if (findbuf.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
  176. iFile += 1;
  177. strcpy(rgszFile[iFile], rgszFile[iFileParent]);
  178. strcat(rgszFile[iFile], findbuf.cFileName);
  179. strcat(rgszFile[iFile], "\\");
  180. rgFileState[iFile] = 0;
  181. ixType = 0;
  182. lcbxFile = 0;
  183. strcpy(szxFile, rgszFile[iFile]);
  184. } else {
  185. ixType = 1;
  186. lcbxFile = findbuf.nFileSizeLow;
  187. strcpy(szxFile, rgszFile[iFileParent]);
  188. strcat(szxFile, findbuf.cFileName);
  189. }
  190. // *** Write file info ***
  191. sprintf(szFile, "%d, %4ld, \"%s\"," szCR,
  192. ixType, lcbxFile, szxFile);
  193. ec = EcFileInfo(FO_Write, szFile);
  194. if (ec != 0)
  195. goto CLOSE;
  196. if (lcbxFile == 0)
  197. continue;
  198. // *** Write file data ***
  199. strcpy(szFile, szDrive);
  200. strcat(szFile, szDir);
  201. strcat(szFile, szxFile);
  202. ec = EcFileData(FO_Write, szFile);
  203. if (ec != 0)
  204. goto CLOSE;
  205. }
  206. } else {
  207. iFile -= 1;
  208. }
  209. if (iFile == 0)
  210. break;
  211. }
  212. CLOSE:
  213. EcFileInfo(FO_Close, "");
  214. EcFileData(FO_Close, "");
  215. RET:
  216. if (ec != 0) {
  217. printf("ERROR: Disk error %d\n", ec);
  218. remove("_fileinf.h");
  219. remove("_filedat.h");
  220. }
  221. return ec;
  222. }
  223. /* ************************************************************ *
  224. *
  225. * int 'EcFileInfo
  226. *
  227. * In: FO foType File operation
  228. * In: char *szFileInfo File name or data string
  229. *
  230. * EcFileInfo returns a standard exit code.
  231. *
  232. * EcFileInfo opens, writes, and closes the directory structure
  233. * header file. The info is saved in an array of type HDR.
  234. * The array is rghdrFile and the constant chdrFile counts the
  235. * number of elements in the array.
  236. *
  237. * EcFileInfo causes a disk side-effect.
  238. *
  239. * EcFileInfo indicates any error via the exit code.
  240. *
  241. * ************************************************************ */
  242. int
  243. EcFileInfo(
  244. FO foType,
  245. char *szFileInfo
  246. )
  247. {
  248. int ec = 0, dos;
  249. char szT[cchMaxFile] = "";
  250. int iszT;
  251. static FILE *hfFileInfo;
  252. static int chdrFileInfo;
  253. unsigned iszFileInfo;
  254. switch (foType) {
  255. case FO_Open:
  256. // Open szFileInfo file
  257. hfFileInfo = fopen(szFileInfo, "wt");
  258. if (hfFileInfo == NULL) {
  259. printf("ERROR: Can't open %s\n", szFileInfo);
  260. exit(EXIT_FAILURE);
  261. }
  262. // Open rghdrFile declaration and set chdFileInfo to 0
  263. fprintf(hfFileInfo, szCR);
  264. fprintf(hfFileInfo, "static CSRG(HDR) rghdrFile[] =" szCR);
  265. fprintf(hfFileInfo, "{" szCR);
  266. chdrFileInfo = 0;
  267. break;
  268. case FO_Write:
  269. // Double every backlash in szFileInfo
  270. for (iszFileInfo = 0, iszT = 0; iszFileInfo < strlen(szFileInfo);
  271. iszFileInfo += 1)
  272. {
  273. szT[iszT++] = szFileInfo[iszFileInfo];
  274. if (szFileInfo[iszFileInfo] == '\\') szT[iszT++] = '\\';
  275. }
  276. szT[iszT] = '\0';
  277. // Write file info
  278. fwrite(szT, sizeof(char), iszT, hfFileInfo);
  279. chdrFileInfo += 1;
  280. break;
  281. case FO_Close:
  282. // Close rghdrFile definition and set chdrFile
  283. fprintf(hfFileInfo, szCR);
  284. fprintf(hfFileInfo, "// END" szCR);
  285. fprintf(hfFileInfo, szCR);
  286. fprintf(hfFileInfo, "0, 0, \"\"" szCR);
  287. fprintf(hfFileInfo, szCR);
  288. fprintf(hfFileInfo, "}; // rghdrFile" szCR);
  289. fprintf(hfFileInfo, szCR);
  290. fprintf(hfFileInfo, "#define chdrFile %d" szCR, chdrFileInfo);
  291. fprintf(hfFileInfo, szCR);
  292. // Close szFileInfo
  293. dos = fclose(hfFileInfo);
  294. assert(dos == 0);
  295. break;
  296. default:
  297. printf("ERROR: Unknown EcFileInfo foType %d\n", foType);
  298. break;
  299. }
  300. return ec;
  301. }
  302. /* ************************************************************ *
  303. *
  304. * int 'EcFileData
  305. *
  306. * In: FO foType File operation
  307. * In: char *szFileData File name or data string
  308. *
  309. * EcFileData returns a standard exit code.
  310. *
  311. * EcFileData opens, writes, and closes the file data header
  312. * file. The file data is saved in an array of char (bytes).
  313. * The array is named rgbFile and the constant cbFile counts
  314. * the number of elements in the array.
  315. *
  316. * EcFileData causes a disk side-effect.
  317. *
  318. * EcFileData indicates any error via the exit code.
  319. *
  320. * ************************************************************ */
  321. int
  322. EcFileData(
  323. FO foType,
  324. char *szFileData
  325. )
  326. {
  327. int ec = 0, dos;
  328. int fContinue;
  329. static FILE *hfFileData;
  330. static int cbFileData;
  331. FILE *hfSourceFile;
  332. long lcbRead;
  333. long ibBuffer, ibOffset, cbOffset;
  334. switch (foType) {
  335. case FO_Open:
  336. // Open szFileData file
  337. hfFileData = fopen(szFileData, "wt");
  338. if (hfFileData == NULL) {
  339. printf("ERROR: Can't open %s\n", szFileData);
  340. exit(EXIT_FAILURE);
  341. }
  342. // Write rgbFile declaration and set cbFiledata to 0
  343. fprintf(hfFileData, szCR);
  344. fprintf(hfFileData, "static CSRG(unsigned char) rgbFile[] =" szCR);
  345. fprintf(hfFileData, "{" szCR);
  346. cbFileData = 0;
  347. break;
  348. case FO_Write:
  349. // Open source file
  350. hfSourceFile = fopen(szFileData, "rb");
  351. if (!hfSourceFile) {
  352. break;
  353. }
  354. fprintf(hfFileData, szCR);
  355. fprintf(hfFileData, "// %s" szCR, szFileData);
  356. fprintf(hfFileData, szCR);
  357. // Write file data
  358. fContinue = 1;
  359. while (fContinue == 1) {
  360. // Read source file
  361. lcbRead = fread(rgbBuffer, sizeof(char),
  362. rgbMaxBuffer, hfSourceFile);
  363. assert(ferror(hfSourceFile) == 0);
  364. if (feof(hfSourceFile) != 0) fContinue = 0;
  365. // Write target file
  366. for (ibBuffer = 0; ibBuffer < lcbRead; ibBuffer += 16) {
  367. cbOffset = min((long) 16, lcbRead-ibBuffer);
  368. for (ibOffset = 0; ibOffset < cbOffset; ibOffset += 1) {
  369. fprintf(hfFileData, "%3u, ",
  370. rgbBuffer[ibBuffer+ibOffset]);
  371. cbFileData += 1;
  372. }
  373. fprintf(hfFileData, szCR);
  374. }
  375. }
  376. // Close source file
  377. dos = fclose(hfSourceFile);
  378. assert(dos == 0);
  379. break;
  380. case FO_Close:
  381. // Close rgbFile definition and set cbFile
  382. fprintf(hfFileData, szCR);
  383. fprintf(hfFileData, "// END" szCR);
  384. fprintf(hfFileData, szCR);
  385. fprintf(hfFileData, "000" szCR);
  386. fprintf(hfFileData, szCR);
  387. fprintf(hfFileData, "}; // rgbFile" szCR);
  388. fprintf(hfFileData, szCR);
  389. fprintf(hfFileData, "#define cbFile %d" szCR, cbFileData);
  390. fprintf(hfFileData, szCR);
  391. // Close szFileData
  392. dos = fclose(hfFileData);
  393. assert(dos == 0);
  394. break;
  395. default:
  396. printf("ERROR: Unknown EcFileData foType %d\n", foType);
  397. break;
  398. }
  399. return ec;
  400. }