diff options
Diffstat (limited to 'jam-files/engine/timestamp.c')
-rw-r--r-- | jam-files/engine/timestamp.c | 226 |
1 files changed, 226 insertions, 0 deletions
diff --git a/jam-files/engine/timestamp.c b/jam-files/engine/timestamp.c new file mode 100644 index 00000000..8a59c8c0 --- /dev/null +++ b/jam-files/engine/timestamp.c @@ -0,0 +1,226 @@ +/* + * 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 ); +} |