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