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
69 do { *p
++ = tolower(*target
); } while (*target
++) ;
73 if (!bindhash
) bindhash
= hashinit(sizeof(BINDING
), "bindings");
74 /* quick path: is it there? */
76 b
->time
= b
->flags
= 0;
77 b
->progress
= BIND_INIT
;
78 if (hashenter(bindhash
, (HASHDATA
**)&b
)) b
->name
= newstr(target
); /* never freed */
79 if (b
->progress
!= BIND_INIT
) goto afterscanning
;
80 b
->progress
= BIND_NOENTRY
;
81 /* not found: have to scan for it */
82 path_parse(target
, &f1
);
83 /* scan directory if not already done so */
85 BINDING binding
, *b
= &binding
;
90 path_build(&f2
, buf
, 0);
92 b
->time
= b
->flags
= 0;
93 b
->progress
= BIND_INIT
;
94 if (hashenter(bindhash
, (HASHDATA
**)&b
)) b
->name
= newstr(buf
); /* never freed */
95 if (!(b
->flags
& BIND_SCANNED
)) {
96 file_dirscan(buf
, time_enter
, bindhash
);
97 b
->flags
|= BIND_SCANNED
;
100 /* scan archive if not already done so */
101 if (f1
.f_member
.len
) {
102 BINDING binding
, *b
= &binding
;
107 path_build(&f2
, buf
, 0);
109 b
->time
= b
->flags
= 0;
110 b
->progress
= BIND_INIT
;
111 if (hashenter(bindhash
, (HASHDATA
**)&b
)) b
->name
= newstr(buf
); /* never freed */
112 if (!(b
->flags
& BIND_SCANNED
)) {
113 file_archscan(buf
, time_enter
, bindhash
);
114 b
->flags
|= BIND_SCANNED
;
118 if (b
->progress
== BIND_SPOTTED
) {
119 if (file_time(b
->name
, &b
->time
) < 0) b
->progress
= BIND_MISSING
;
120 else b
->progress
= BIND_FOUND
;
122 *time
= b
->progress
== BIND_FOUND
? b
->time
: 0;
126 static void time_enter (void *closure
, const char *target
, int found
, time_t time
) {
127 BINDING binding
, *b
= &binding
;
128 struct hash
*bindhash
= (struct hash
*)closure
;
129 #ifdef DOWNSHIFT_PATHS
133 do { *p
++ = tolower(*target
); } while (*target
++) ;
138 if (hashenter(bindhash
, (HASHDATA
**)&b
)) b
->name
= newstr(target
); /* never freed */
140 b
->progress
= found
? BIND_FOUND
: BIND_SPOTTED
;
141 if (DEBUG_BINDSCAN
) printf("time ( %s ) : %s\n", target
, time_progress
[b
->progress
]);
146 * donestamps() - free timestamp tables
148 void donestamps (void) {