PageRenderTime 60ms CodeModel.GetById 29ms RepoModel.GetById 0ms app.codeStats 1ms

/edk2/EdkCompatibilityPkg/Sample/Tools/Source/SetStamp/SetStamp.c

https://gitlab.com/envieidoc/Clover
C | 491 lines | 253 code | 31 blank | 207 comment | 86 complexity | c583aaac7fe7291d331b35d3baf7a1a5 MD5 | raw file
  1. /*++
  2. Copyright (c) 2004 - 2010, Intel Corporation. All rights reserved.<BR>
  3. This program and the accompanying materials
  4. are licensed and made available under the terms and conditions of the BSD License
  5. which accompanies this distribution. The full text of the license may be found at
  6. http://opensource.org/licenses/bsd-license.php
  7. THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
  8. WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
  9. Module Name:
  10. SetStamp.c
  11. Abstract:
  12. Set Date/Time Stamp of Portable Executable (PE) format file
  13. --*/
  14. #include <stdio.h>
  15. #include <string.h>
  16. #include <time.h>
  17. #define LINE_MAXLEN 80
  18. #define UTILITY_NAME "SetStamp"
  19. #define UTILITY_VERSION "v1.0"
  20. void
  21. PrintUsage (
  22. void
  23. )
  24. /*++
  25. Routine Description:
  26. print usage of setstamp command
  27. Arguments:
  28. void
  29. Returns:
  30. None
  31. --*/
  32. {
  33. int Index;
  34. const char *Str[] = {
  35. UTILITY_NAME" "UTILITY_VERSION" - Intel Set Time Stamp Utility",
  36. " Copyright (C), 2004 - 2008 Intel Corporation",
  37. #if ( defined(UTILITY_BUILD) && defined(UTILITY_VENDOR) )
  38. " Built from "UTILITY_BUILD", project of "UTILITY_VENDOR,
  39. #endif
  40. "",
  41. "Usage:",
  42. " "UTILITY_NAME" PEFILE TIMEFILE",
  43. "Description:",
  44. " Set Date/Time Stamp of Portable Executable (PE) format file",
  45. NULL
  46. };
  47. for (Index = 0; Str[Index] != NULL; Index++) {
  48. fprintf (stdout, "%s\n", Str[Index]);
  49. }
  50. }
  51. int
  52. GetDateTime (
  53. FILE *fp,
  54. time_t *ltime
  55. )
  56. /*++
  57. Routine Description:
  58. Read the date and time from TIME file. If the date/time string is
  59. "NOW NOW", write the current date and time to TIME file and set it to
  60. ltime. Else, set the date and time of TIME file to ltime.
  61. Arguments:
  62. fp - The pointer of TIME file
  63. ltime - Date and time
  64. Returns:
  65. = 0 - Success
  66. = -1 - Failed
  67. --*/
  68. {
  69. char buffer[LINE_MAXLEN];
  70. struct tm stime;
  71. struct tm *now;
  72. if (fgets (buffer, LINE_MAXLEN, fp) == NULL) {
  73. printf ("Error: Cannot read TIME file.\n");
  74. return -1;
  75. }
  76. //
  77. // compare the value with "NOW NOW", write TIME file if equal
  78. //
  79. if (strncmp (buffer, "NOW NOW", 7) == 0) {
  80. //
  81. // get system current time and date
  82. //
  83. time (ltime);
  84. now = localtime (ltime);
  85. if (now == NULL) {
  86. printf ("Error: Cannot get local time.\n");
  87. return -1;
  88. }
  89. if (strftime (buffer, LINE_MAXLEN, "%Y-%m-%d %H:%M:%S", now) == 0) {
  90. printf ("Error: Cannot format time string.\n");
  91. return -1;
  92. }
  93. //
  94. // write TIME file
  95. //
  96. if (fseek (fp, 0, SEEK_SET) != 0) {
  97. printf ("Error: Cannot move location of TIME file.\n");
  98. return -1;
  99. }
  100. if (fputs (buffer, fp) == EOF) {
  101. printf ("Error: Cannot write time string to TIME file.\n");
  102. return -1;
  103. }
  104. //
  105. // ltime has been set as current time and date, return
  106. //
  107. return 0;
  108. }
  109. //
  110. // get the date and time from buffer
  111. //
  112. if (6 != sscanf (
  113. buffer,
  114. "%d-%d-%d %d:%d:%d",
  115. &stime.tm_year,
  116. &stime.tm_mon,
  117. &stime.tm_mday,
  118. &stime.tm_hour,
  119. &stime.tm_min,
  120. &stime.tm_sec
  121. )) {
  122. printf ("Error: Invaild date or time!\n");
  123. return -1;
  124. }
  125. //
  126. // in struct, Month (0 - 11; Jan = 0). So decrease 1 from it
  127. //
  128. stime.tm_mon -= 1;
  129. //
  130. // in struct, Year (current year minus 1900)
  131. // and only the dates can be handled from Jan 1, 1970 to Jan 18, 2038
  132. //
  133. //
  134. // convert 0 -> 100 (2000), 1 -> 101 (2001), ..., 38 -> 138 (2038)
  135. //
  136. if (stime.tm_year <= 38) {
  137. stime.tm_year += 100;
  138. }
  139. //
  140. // convert 1970 -> 70, 2000 -> 100, ...
  141. //
  142. else if (stime.tm_year >= 1970) {
  143. stime.tm_year -= 1900;
  144. }
  145. //
  146. // convert the date and time to time_t format
  147. //
  148. *ltime = mktime (&stime);
  149. if (*ltime == (time_t) - 1) {
  150. printf ("Error: Invalid date or time!\n");
  151. return -1;
  152. }
  153. return 0;
  154. }
  155. int
  156. ReadFromFile (
  157. FILE *fp,
  158. long offset,
  159. void *buffer,
  160. int size
  161. )
  162. /*++
  163. Routine Description:
  164. read data from a specified location of file
  165. Arguments:
  166. fp - file pointer
  167. offset - number of bytes from beginning of file
  168. buffer - buffer used to store data
  169. size - size of buffer
  170. Returns:
  171. = 0 - Success
  172. = -1 - Failed
  173. --*/
  174. {
  175. //
  176. // set file pointer to the specified location of file
  177. //
  178. if (fseek (fp, offset, SEEK_SET) != 0) {
  179. printf ("Error: Cannot move the current location of the file.\n");
  180. return -1;
  181. }
  182. //
  183. // read data from the file
  184. //
  185. if (fread (buffer, size, 1, fp) != 1) {
  186. printf ("Error: Cannot read data from the file.\n");
  187. return -1;
  188. }
  189. return 0;
  190. }
  191. int
  192. WriteToFile (
  193. FILE *fp,
  194. long offset,
  195. void *buffer,
  196. int size
  197. )
  198. /*++
  199. Routine Description:
  200. write data to a specified location of file
  201. Arguments:
  202. fp - file pointer
  203. offset - number of bytes from beginning of file
  204. buffer - buffer used to store data
  205. size - size of buffer
  206. Returns:
  207. = 0 - Success
  208. = -1 - Failed
  209. --*/
  210. {
  211. //
  212. // set file pointer to the specified location of file
  213. //
  214. if (fseek (fp, offset, SEEK_SET) != 0) {
  215. printf ("Error: Cannot move the current location of the file.\n");
  216. return -1;
  217. }
  218. //
  219. // write data to the file
  220. //
  221. if (fwrite (buffer, size, 1, fp) != 1) {
  222. perror ("Error: Cannot write data to the file.\n");
  223. return -1;
  224. }
  225. return 0;
  226. }
  227. int
  228. SetStamp (
  229. FILE *fp,
  230. time_t ltime
  231. )
  232. /*++
  233. Routine Description:
  234. set Date/Time Stamp of the file
  235. Arguments:
  236. fp - file pointer
  237. ltime - time and date
  238. Returns:
  239. = 0 - Success
  240. = -1 - Failed
  241. --*/
  242. {
  243. unsigned char header[4];
  244. unsigned long offset;
  245. unsigned long NumberOfRvaAndSizes;
  246. unsigned int nvalue;
  247. unsigned long lvalue;
  248. //
  249. // read the header of file
  250. //
  251. if (ReadFromFile (fp, 0, header, 2) != 0) {
  252. return -1;
  253. }
  254. //
  255. // "MZ" -- the header of image file (PE)
  256. //
  257. if (strncmp ((char *) header, "MZ", 2) != 0) {
  258. printf ("Error: Invalid Image file.\n");
  259. return -1;
  260. }
  261. //
  262. // At location 0x3C, the stub has the file offset to the
  263. // PE signature.
  264. //
  265. if (ReadFromFile (fp, 0x3C, &offset, 4) != 0) {
  266. return -1;
  267. }
  268. //
  269. // read the header of optional
  270. //
  271. if (ReadFromFile (fp, offset, header, 4) != 0) {
  272. return -1;
  273. }
  274. //
  275. // "PE\0\0" -- the signature of optional header
  276. //
  277. if (strncmp ((char *) header, "PE\0\0", 4) != 0) {
  278. printf ("Error: Invalid PE format file.\n");
  279. return -1;
  280. }
  281. //
  282. // Add 8 to skip PE signature (4-byte), Machine (2-byte) and
  283. // NumberOfSection (2-byte)
  284. //
  285. offset += 8;
  286. if (WriteToFile (fp, offset, &ltime, 4) != 0) {
  287. return -1;
  288. }
  289. //
  290. // Add 16 to skip COFF file header, and get to optional header.
  291. //
  292. offset += 16;
  293. //
  294. // Check the magic field, 0x10B for PE32 and 0x20B for PE32+
  295. //
  296. if (ReadFromFile (fp, offset, &nvalue, 2) != 0) {
  297. return -1;
  298. }
  299. //
  300. // If this is PE32 image file, offset of NumberOfRvaAndSizes is 92.
  301. // Else it is 108.
  302. //
  303. switch (nvalue & 0xFFFF) {
  304. case 0x10B:
  305. offset += 92;
  306. break;
  307. case 0x20B:
  308. offset += 108;
  309. break;
  310. default:
  311. printf ("Error: Sorry! The Magic value is unknown.\n");
  312. return -1;
  313. }
  314. //
  315. // get the value of NumberOfRvaAndSizes
  316. //
  317. if (ReadFromFile (fp, offset, &NumberOfRvaAndSizes, 4) != 0) {
  318. return -1;
  319. }
  320. //
  321. // Date/time stamp exists in Export Table, Import Table, Resource Table,
  322. // Debug Table and Delay Import Table. And in Import Table and Delay Import
  323. // Table, it will be set when bound. So here only set the date/time stamp
  324. // of Export Table, Resource Table and Debug Table.
  325. //
  326. //
  327. // change date/time stamp of Export Table, the offset of Export Table
  328. // is 4 + 0 * 8 = 4. And the offset of stamp is 4.
  329. //
  330. if (NumberOfRvaAndSizes >= 1) {
  331. if (ReadFromFile (fp, offset + 4, &lvalue, 4) != 0) {
  332. return -1;
  333. }
  334. if (lvalue != 0) {
  335. if (WriteToFile (fp, lvalue + 4, &ltime, 4) != 0) {
  336. return -1;
  337. }
  338. }
  339. }
  340. //
  341. // change date/time stamp of Resource Table, the offset of Resource Table
  342. // is 4 + 2 * 8 = 20. And the offset of stamp is 4.
  343. //
  344. if (NumberOfRvaAndSizes >= 3) {
  345. if (ReadFromFile (fp, offset + 20, &lvalue, 4) != 0) {
  346. return -1;
  347. }
  348. if (lvalue != 0) {
  349. if (WriteToFile (fp, lvalue + 4, &ltime, 4) != 0) {
  350. return -1;
  351. }
  352. }
  353. }
  354. //
  355. // change date/time stamp of Debug Table, offset of Debug Table
  356. // is 4 + 6 * 8 = 52. And the offset of stamp is 4.
  357. //
  358. if (NumberOfRvaAndSizes >= 7) {
  359. if (ReadFromFile (fp, offset + 52, &lvalue, 4) != 0) {
  360. return -1;
  361. }
  362. if (lvalue != 0) {
  363. if (WriteToFile (fp, lvalue + 4, &ltime, 4) != 0) {
  364. return -1;
  365. }
  366. }
  367. //
  368. // change the date/time stamp of Debug Data
  369. //
  370. if (ReadFromFile (fp, lvalue + 24, &lvalue, 4) != 0) {
  371. return -1;
  372. }
  373. //
  374. // get the signature of debug data
  375. //
  376. if (ReadFromFile (fp, lvalue, header, 2) != 0) {
  377. return -1;
  378. }
  379. //
  380. // "NB" - the signature of Debug Data
  381. // Need Review: (From Spec. is "NB05", From .dll is "NB10")
  382. //
  383. if (strncmp ((char *) header, "NB", 2) == 0) {
  384. if (WriteToFile (fp, lvalue + 8, &ltime, 4) != 0) {
  385. return -1;
  386. }
  387. }
  388. }
  389. return 0;
  390. }
  391. int
  392. main (
  393. int argc,
  394. char *argv[]
  395. )
  396. {
  397. FILE *fp;
  398. time_t ltime;
  399. //
  400. // check the number of parameters
  401. //
  402. if (argc != 3) {
  403. PrintUsage ();
  404. return -1;
  405. }
  406. //
  407. // open the TIME file, if not exists, return
  408. //
  409. fp = fopen (argv[2], "r+");
  410. if (fp == NULL) {
  411. return 0;
  412. }
  413. //
  414. // get time and date from file
  415. //
  416. if (GetDateTime (fp, &ltime) != 0) {
  417. fclose (fp);
  418. return -1;
  419. }
  420. //
  421. // close the TIME file
  422. //
  423. fclose (fp);
  424. //
  425. // open the PE file
  426. //
  427. fp = fopen (argv[1], "r+b");
  428. if (fp == NULL) {
  429. printf ("Error: Cannot open the PE file!\n");
  430. return -1;
  431. }
  432. //
  433. // set time and date stamp to the PE file
  434. //
  435. if (SetStamp (fp, ltime) != 0) {
  436. fclose (fp);
  437. return -1;
  438. }
  439. printf ("Set Date/Time Stamp to %s", ctime (&ltime));
  440. //
  441. // close the PE file
  442. //
  443. fclose (fp);
  444. return 0;
  445. }