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