2 * Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
4 * This file is part of Jam - see jam.c for Copyright information.
8 * timestamp.c - get the timestamp of a file or archive member
10 * 09/22/00 (seiwald) - downshift names on OS2, too
11 * 01/08/01 (seiwald) - closure param for file_dirscan/file_archscan
12 * 11/04/02 (seiwald) - const-ing for string literals
19 # include "timestamp.h"
23 * BINDING - all known files
26 typedef struct _binding BINDING
;
31 # define BIND_SCANNED 0x01 /* if directory or arch, has been scanned */
35 # define BIND_INIT 0 /* never seen */
36 # define BIND_NOENTRY 1 /* timestamp requested but file never found */
37 # define BIND_SPOTTED 2 /* file found but not timed yet */
38 # define BIND_MISSING 3 /* file found but can't get timestamp */
39 # define BIND_FOUND 4 /* file found and time stamped */
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);
48 static const char *time_progress
[] = {
58 * timestamp() - return timestamp on a file, if present
60 void timestamp (char *target
, time_t *time
) {
62 BINDING binding
, *b
= &binding
;
65 # ifdef DOWNSHIFT_PATHS
69 do { *p
++ = tolower( *target
); } while (*target
++);
74 if (!bindhash
) bindhash
= hashinit(sizeof( BINDING
), "bindings");
75 /* Quick path - is it there? */
77 b
->time
= b
->flags
= 0;
78 b
->progress
= BIND_INIT
;
79 if (hashenter(bindhash
, (HASHDATA
**)&b
)) b
->name
= newstr(target
); /* never freed */
80 if (b
->progress
!= BIND_INIT
) goto afterscanning
;
81 b
->progress
= BIND_NOENTRY
;
82 /* Not found - have to scan for it */
83 path_parse(target
, &f1
);
84 /* Scan directory if not already done so */
86 BINDING binding
, *b
= &binding
;
91 path_build(&f2
, buf
, 0);
93 b
->time
= b
->flags
= 0;
94 b
->progress
= BIND_INIT
;
95 if (hashenter(bindhash
, (HASHDATA
**)&b
)) b
->name
= newstr(buf
); /* never freed */
96 if (!(b
->flags
& BIND_SCANNED
)) {
97 file_dirscan(buf
, time_enter
, bindhash
);
98 b
->flags
|= BIND_SCANNED
;
101 /* Scan archive if not already done so */
102 if (f1
.f_member
.len
) {
103 BINDING binding
, *b
= &binding
;
108 path_build(&f2
, buf
, 0);
110 b
->time
= b
->flags
= 0;
111 b
->progress
= BIND_INIT
;
112 if (hashenter(bindhash
, (HASHDATA
**)&b
)) b
->name
= newstr(buf
); /* never freed */
113 if (!(b
->flags
& BIND_SCANNED
)) {
114 file_archscan(buf
, time_enter
, bindhash
);
115 b
->flags
|= BIND_SCANNED
;
119 if (b
->progress
== BIND_SPOTTED
) {
120 if (file_time(b
->name
, &b
->time
) < 0) b
->progress
= BIND_MISSING
;
121 else b
->progress
= BIND_FOUND
;
123 *time
= b
->progress
== BIND_FOUND
? b
->time
: 0;
127 static void time_enter (void *closure
, const char *target
, int found
, time_t time
) {
128 BINDING binding
, *b
= &binding
;
129 struct hash
*bindhash
= (struct hash
*)closure
;
131 # ifdef DOWNSHIFT_PATHS
135 do { *p
++ = tolower(*target
); } while (*target
++);
141 if (hashenter(bindhash
, (HASHDATA
**)&b
)) b
->name
= newstr(target
); /* never freed */
143 b
->progress
= found
? BIND_FOUND
: BIND_SPOTTED
;
144 if (DEBUG_BINDSCAN
) printf("time ( %s ) : %s\n", target
, time_progress
[b
->progress
]);
149 * donestamps() - free timestamp tables
151 void donestamps (void) {