token type renamed to token_t
[k8jam.git] / src / timestamp.c
blobc4ab09b46c8bac42430a7958eb7e9649519e6908
1 /*
2 * Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
4 * This file is part of Jam - see jam.c for Copyright information.
5 */
6 /*
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
13 #include "jam.h"
14 #include "hash.h"
15 #include "filesys.h"
16 #include "pathsys.h"
17 #include "timestamp.h"
18 #include "newstr.h"
22 * BINDING - all known files
25 #define BIND_SCANNED 0x01 /* if directory or arch, has been scanned */
27 enum {
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;
37 struct _binding {
38 const char *name;
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[] = {
50 "INIT",
51 "NOENTRY",
52 "SPOTTED",
53 "MISSING",
54 "FOUND"
59 * timestamp() - return timestamp on a file, if present
61 void timestamp (char *target, time_t *time) {
62 PATHNAME f1, f2;
63 BINDING binding, *b = &binding;
64 char buf[MAXJPATH];
65 #ifdef DOWNSHIFT_PATHS
66 char path[MAXJPATH];
67 char *p = path;
68 do { *p++ = tolower(*target); } while (*target++) ;
69 target = path;
70 #endif
71 if (!bindhash) bindhash = hashinit(sizeof(BINDING), "bindings");
72 /* quick path: is it there? */
73 b->name = target;
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;
85 f2 = f1;
86 f2.f_grist.len = 0;
87 path_parent(&f2);
88 path_build(&f2, buf, 0);
89 b->name = buf;
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;
101 f2 = f1;
102 f2.f_grist.len = 0;
103 f2.f_member.len = 0;
104 path_build(&f2, buf, 0);
105 b->name = buf;
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;
114 afterscanning:
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
127 char path[MAXJPATH];
128 char *p = path;
129 do { *p++ = tolower(*target); } while (*target++) ;
130 target = path;
131 #endif
132 b->name = target;
133 b->flags = 0;
134 if (hashenter(bindhash, (HASHDATA **)&b)) b->name = newstr(target); /* never freed */
135 b->time = time;
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) {
145 hashdone(bindhash);