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