1/* 2 * Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc. 3 * 4 * This file is part of Jam - see jam.c for Copyright information. 5 */ 6 7/* 8 * timestamp.c - get the timestamp of a file or archive member 9 * 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 13 */ 14 15# include "jam.h" 16# include "hash.h" 17# include "filesys.h" 18# include "pathsys.h" 19# include "timestamp.h" 20# include "newstr.h" 21 22/* 23 * BINDING - all known files 24 */ 25 26typedef struct _binding BINDING; 27 28struct _binding { 29 const char *name; 30 short flags; 31 32# define BIND_SCANNED 0x01 /* if directory or arch, has been scanned */ 33 34 short progress; 35 36# define BIND_INIT 0 /* never seen */ 37# define BIND_NOENTRY 1 /* timestamp requested but file never found */ 38# define BIND_SPOTTED 2 /* file found but not timed yet */ 39# define BIND_MISSING 3 /* file found but can't get timestamp */ 40# define BIND_FOUND 4 /* file found and time stamped */ 41 42 time_t time; /* update time - 0 if not exist */ 43} ; 44 45static struct hash *bindhash = 0; 46static void time_enter( void *, const char *, int , time_t ); 47 48static const char *time_progress[] = 49{ 50 "INIT", 51 "NOENTRY", 52 "SPOTTED", 53 "MISSING", 54 "FOUND" 55} ; 56 57 58/* 59 * timestamp() - return timestamp on a file, if present 60 */ 61 62void 63timestamp( 64 char *target, 65 time_t *time ) 66{ 67 PATHNAME f1, f2; 68 BINDING binding, *b = &binding; 69 char buf[ MAXJPATH ]; 70 71# ifdef DOWNSHIFT_PATHS 72 char path[ MAXJPATH ]; 73 char *p = path; 74 75 do *p++ = tolower( *target ); 76 while( *target++ ); 77 78 target = path; 79# endif 80 81 if( !bindhash ) 82 bindhash = hashinit( sizeof( BINDING ), "bindings" ); 83 84 /* Quick path - is it there? */ 85 86 b->name = target; 87 b->time = b->flags = 0; 88 b->progress = BIND_INIT; 89 90 if( hashenter( bindhash, (HASHDATA **)&b ) ) 91 b->name = newstr( target ); /* never freed */ 92 93 if( b->progress != BIND_INIT ) 94 goto afterscanning; 95 96 b->progress = BIND_NOENTRY; 97 98 /* Not found - have to scan for it */ 99 100 path_parse( target, &f1 ); 101 102 /* Scan directory if not already done so */ 103 104 { 105 BINDING binding, *b = &binding; 106 107 f2 = f1; 108 f2.f_grist.len = 0; 109 path_parent( &f2 ); 110 path_build( &f2, buf, 0 ); 111 112 b->name = buf; 113 b->time = b->flags = 0; 114 b->progress = BIND_INIT; 115 116 if( hashenter( bindhash, (HASHDATA **)&b ) ) 117 b->name = newstr( buf ); /* never freed */ 118 119 if( !( b->flags & BIND_SCANNED ) ) 120 { 121 file_dirscan( buf, time_enter, bindhash ); 122 b->flags |= BIND_SCANNED; 123 } 124 } 125 126 /* Scan archive if not already done so */ 127 128 if( f1.f_member.len ) 129 { 130 BINDING binding, *b = &binding; 131 132 f2 = f1; 133 f2.f_grist.len = 0; 134 f2.f_member.len = 0; 135 path_build( &f2, buf, 0 ); 136 137 b->name = buf; 138 b->time = b->flags = 0; 139 b->progress = BIND_INIT; 140 141 if( hashenter( bindhash, (HASHDATA **)&b ) ) 142 b->name = newstr( buf ); /* never freed */ 143 144 if( !( b->flags & BIND_SCANNED ) ) 145 { 146 file_archscan( buf, time_enter, bindhash ); 147 b->flags |= BIND_SCANNED; 148 } 149 } 150 151 afterscanning: 152 153 if( b->progress == BIND_SPOTTED ) 154 { 155 if( file_time( b->name, &b->time ) < 0 ) 156 b->progress = BIND_MISSING; 157 else 158 b->progress = BIND_FOUND; 159 } 160 161 *time = b->progress == BIND_FOUND ? b->time : 0; 162} 163 164static void 165time_enter( 166 void *closure, 167 const char *target, 168 int found, 169 time_t time ) 170{ 171 BINDING binding, *b = &binding; 172 struct hash *bindhash = (struct hash *)closure; 173 174# ifdef DOWNSHIFT_PATHS 175 char path[ MAXJPATH ]; 176 char *p = path; 177 178 do *p++ = tolower( *target ); 179 while( *target++ ); 180 181 target = path; 182# endif 183 184 b->name = target; 185 b->flags = 0; 186 187 if( hashenter( bindhash, (HASHDATA **)&b ) ) 188 b->name = newstr( target ); /* never freed */ 189 190 b->time = time; 191 b->progress = found ? BIND_FOUND : BIND_SPOTTED; 192 193 if( DEBUG_BINDSCAN ) 194 printf( "time ( %s ) : %s\n", target, time_progress[b->progress] ); 195} 196 197/* 198 * donestamps() - free timestamp tables 199 */ 200 201void 202donestamps() 203{ 204 hashdone( bindhash ); 205} 206