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