2 * Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
4 * This file is part of Jam - see jam.c for Copyright information.
7 * timestamp.c - get the timestamp of a file or archive member
9 * 09/22/00 (seiwald) - downshift names on OS2, too
10 * 01/08/01 (seiwald) - closure param for file_dirscan/file_archscan
11 * 11/04/02 (seiwald) - const-ing for string literals
17 #include "timestamp.h"
22 * BINDING - all known files
25 #define BIND_SCANNED 0x01 /* if directory or arch, has been scanned */
28 BIND_INIT
, /* never seen */
29 BIND_NOENTRY
, /* timestamp requested but file never found */
30 BIND_SPOTTED
, /* file found but not timed yet */
31 BIND_MISSING
, /* file found but can't get timestamp */
32 BIND_FOUND
/* file found and time stamped */
36 typedef struct _binding BINDING
;
39 short flags
; // BIND_SCANNED
40 short progress
; // enum
41 time_t time
; /* update time - 0 if not exist */
45 static struct hash
*bindhash
= 0;
46 static void time_enter (void *, const char *, int, time_t);
49 static const char *time_progress
[] = {
59 * timestamp() - return timestamp on a file, if present
61 void timestamp (char *target
, time_t *time
) {
63 BINDING binding
, *b
= &binding
;
65 #ifdef DOWNSHIFT_PATHS
68 do { *p
++ = tolower(*target
); } while (*target
++) ;
71 if (!bindhash
) bindhash
= hashinit(sizeof(BINDING
), "bindings");
72 /* quick path: is it there? */
74 b
->time
= b
->flags
= 0;
75 b
->progress
= BIND_INIT
;
76 if (hashenter(bindhash
, (HASHDATA
**)&b
)) b
->name
= newstr(target
); /* never freed */
77 if (b
->progress
!= BIND_INIT
) goto afterscanning
;
78 b
->progress
= BIND_NOENTRY
;
79 /* not found: have to scan for it */
80 path_parse(target
, &f1
);
81 /* scan directory if not already done so */
83 BINDING binding
, *b
= &binding
;
88 path_build(&f2
, buf
, 0);
90 b
->time
= b
->flags
= 0;
91 b
->progress
= BIND_INIT
;
92 if (hashenter(bindhash
, (HASHDATA
**)&b
)) b
->name
= newstr(buf
); /* never freed */
93 if (!(b
->flags
& BIND_SCANNED
)) {
94 file_dirscan(buf
, time_enter
, bindhash
);
95 b
->flags
|= BIND_SCANNED
;
98 /* scan archive if not already done so */
99 if (f1
.f_member
.len
) {
100 BINDING binding
, *b
= &binding
;
104 path_build(&f2
, buf
, 0);
106 b
->time
= b
->flags
= 0;
107 b
->progress
= BIND_INIT
;
108 if (hashenter(bindhash
, (HASHDATA
**)&b
)) b
->name
= newstr(buf
); /* never freed */
109 if (!(b
->flags
& BIND_SCANNED
)) {
110 file_archscan(buf
, time_enter
, bindhash
);
111 b
->flags
|= BIND_SCANNED
;
115 if (b
->progress
== BIND_SPOTTED
) {
116 if (file_time(b
->name
, &b
->time
) < 0) b
->progress
= BIND_MISSING
;
117 else b
->progress
= BIND_FOUND
;
119 *time
= b
->progress
== BIND_FOUND
? b
->time
: 0;
123 static void time_enter (void *closure
, const char *target
, int found
, time_t time
) {
124 BINDING binding
, *b
= &binding
;
125 struct hash
*bindhash
= (struct hash
*)closure
;
126 #ifdef DOWNSHIFT_PATHS
129 do { *p
++ = tolower(*target
); } while (*target
++) ;
134 if (hashenter(bindhash
, (HASHDATA
**)&b
)) b
->name
= newstr(target
); /* never freed */
136 b
->progress
= found
? BIND_FOUND
: BIND_SPOTTED
;
137 if (DEBUG_BINDSCAN
) printf("time ( %s ) : %s\n", target
, time_progress
[b
->progress
]);
142 * donestamps() - free timestamp tables
144 void donestamps (void) {