first in 2.5.10 series
[k8jam.git] / src / timestamp.c
blob806aedf758d76c10f693f5011d5049bf244a7292
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 */
7 /*
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
15 # include "jam.h"
16 # include "hash.h"
17 # include "filesys.h"
18 # include "pathsys.h"
19 # include "timestamp.h"
20 # include "newstr.h"
23 * BINDING - all known files
26 typedef struct _binding BINDING;
28 struct _binding {
29 const char *name;
30 short flags;
31 # define BIND_SCANNED 0x01 /* if directory or arch, has been scanned */
33 short progress;
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[] = {
49 "INIT",
50 "NOENTRY",
51 "SPOTTED",
52 "MISSING",
53 "FOUND"
58 * timestamp() - return timestamp on a file, if present
60 void timestamp (char *target, time_t *time) {
61 PATHNAME f1, f2;
62 BINDING binding, *b = &binding;
63 char buf[MAXJPATH];
65 # ifdef DOWNSHIFT_PATHS
66 char path[MAXJPATH];
67 char *p = path;
69 do { *p++ = tolower( *target ); } while (*target++);
71 target = path;
72 # endif
74 if (!bindhash) bindhash = hashinit(sizeof( BINDING ), "bindings");
75 /* Quick path - is it there? */
76 b->name = target;
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;
88 f2 = f1;
89 f2.f_grist.len = 0;
90 path_parent(&f2);
91 path_build(&f2, buf, 0);
92 b->name = buf;
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;
105 f2 = f1;
106 f2.f_grist.len = 0;
107 f2.f_member.len = 0;
108 path_build(&f2, buf, 0);
109 b->name = buf;
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;
118 afterscanning:
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
132 char path[MAXJPATH];
133 char *p = path;
135 do { *p++ = tolower(*target); } while (*target++);
136 target = path;
137 # endif
139 b->name = target;
140 b->flags = 0;
141 if (hashenter(bindhash, (HASHDATA **)&b)) b->name = newstr(target); /* never freed */
142 b->time = time;
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) {
152 hashdone(bindhash);