/* * Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc. * * This file is part of Jam - see jam.c for Copyright information. */ /* This file is ALSO: * Copyright 2001-2004 David Abrahams. * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) */ # include "jam.h" # include "hash.h" # include "filesys.h" # include "pathsys.h" # include "timestamp.h" # include "newstr.h" # include "strings.h" /* * timestamp.c - get the timestamp of a file or archive member * * 09/22/00 (seiwald) - downshift names on OS2, too */ /* * BINDING - all known files */ typedef struct _binding BINDING; struct _binding { char *name; short flags; # define BIND_SCANNED 0x01 /* if directory or arch, has been scanned */ short progress; # define BIND_INIT 0 /* never seen */ # define BIND_NOENTRY 1 /* timestamp requested but file never found */ # define BIND_SPOTTED 2 /* file found but not timed yet */ # define BIND_MISSING 3 /* file found but can't get timestamp */ # define BIND_FOUND 4 /* file found and time stamped */ time_t time; /* update time - 0 if not exist */ }; static struct hash * bindhash = 0; static void time_enter( void *, char *, int, time_t ); static char * time_progress[] = { "INIT", "NOENTRY", "SPOTTED", "MISSING", "FOUND" }; /* * timestamp() - return timestamp on a file, if present. */ void timestamp( char * target, time_t * time ) { PROFILE_ENTER( timestamp ); PATHNAME f1; PATHNAME f2; BINDING binding; BINDING * b = &binding; string buf[ 1 ]; #ifdef DOWNSHIFT_PATHS string path; char * p; #endif #ifdef DOWNSHIFT_PATHS string_copy( &path, target ); p = path.value; do { *p = tolower( *p ); #ifdef NT /* On NT, we must use backslashes or the file will not be found. */ if ( *p == '/' ) *p = PATH_DELIM; #endif } while ( *p++ ); target = path.value; #endif /* #ifdef DOWNSHIFT_PATHS */ string_new( buf ); if ( !bindhash ) bindhash = hashinit( sizeof( BINDING ), "bindings" ); /* Quick path - is it there? */ b->name = target; b->time = b->flags = 0; b->progress = BIND_INIT; if ( hashenter( bindhash, (HASHDATA * *)&b ) ) b->name = newstr( target ); /* never freed */ if ( b->progress != BIND_INIT ) goto afterscanning; b->progress = BIND_NOENTRY; /* Not found - have to scan for it. */ path_parse( target, &f1 ); /* Scan directory if not already done so. */ { BINDING binding; BINDING * b = &binding; f2 = f1; f2.f_grist.len = 0; path_parent( &f2 ); path_build( &f2, buf, 0 ); b->name = buf->value; b->time = b->flags = 0; b->progress = BIND_INIT; if ( hashenter( bindhash, (HASHDATA * *)&b ) ) b->name = newstr( buf->value ); /* never freed */ if ( !( b->flags & BIND_SCANNED ) ) { file_dirscan( buf->value, time_enter, bindhash ); b->flags |= BIND_SCANNED; } } /* Scan archive if not already done so. */ if ( f1.f_member.len ) { BINDING binding; BINDING * b = &binding; f2 = f1; f2.f_grist.len = 0; f2.f_member.len = 0; string_truncate( buf, 0 ); path_build( &f2, buf, 0 ); b->name = buf->value; b->time = b->flags = 0; b->progress = BIND_INIT; if ( hashenter( bindhash, (HASHDATA * *)&b ) ) b->name = newstr( buf->value ); /* never freed */ if ( !( b->flags & BIND_SCANNED ) ) { file_archscan( buf->value, time_enter, bindhash ); b->flags |= BIND_SCANNED; } } afterscanning: if ( b->progress == BIND_SPOTTED ) { b->progress = file_time( b->name, &b->time ) < 0 ? BIND_MISSING : BIND_FOUND; } *time = b->progress == BIND_FOUND ? b->time : 0; string_free( buf ); #ifdef DOWNSHIFT_PATHS string_free( &path ); #endif PROFILE_EXIT( timestamp ); } static void time_enter( void * closure, char * target, int found, time_t time ) { BINDING binding; BINDING * b = &binding; struct hash * bindhash = (struct hash *)closure; #ifdef DOWNSHIFT_PATHS char path[ MAXJPATH ]; char * p = path; do *p++ = tolower( *target ); while ( *target++ ); target = path; #endif b->name = target; b->flags = 0; if ( hashenter( bindhash, (HASHDATA * *)&b ) ) b->name = newstr( target ); /* never freed */ b->time = time; b->progress = found ? BIND_FOUND : BIND_SPOTTED; if ( DEBUG_BINDSCAN ) printf( "time ( %s ) : %s\n", target, time_progress[ b->progress ] ); } /* * stamps_done() - free timestamp tables. */ void stamps_done() { hashdone( bindhash ); }