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