2
0
mirror of https://github.com/boostorg/build.git synced 2026-02-14 00:32:11 +00:00
Files
build/src/engine/timestamp.c
Steven Watanabe 0ec332fea3 Fix alias violations in hash.
[SVN r77190]
2012-03-03 21:46:53 +00:00

224 lines
4.8 KiB
C

/*
* 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 "object.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 {
OBJECT * 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 *, OBJECT *, int, time_t );
static char * time_progress[] =
{
"INIT",
"NOENTRY",
"SPOTTED",
"MISSING",
"FOUND"
};
/*
* timestamp() - return timestamp on a file, if present.
*/
void timestamp( OBJECT * target, time_t * time )
{
PROFILE_ENTER( timestamp );
PATHNAME f1;
PATHNAME f2;
int found;
BINDING * b;
string buf[ 1 ];
target = path_as_key( target );
string_new( buf );
if ( !bindhash )
bindhash = hashinit( sizeof( BINDING ), "bindings" );
/* Quick path - is it there? */
b = (BINDING *)hash_insert( bindhash, target, &found );
if ( !found )
{
b->name = object_copy( target ); /* never freed */
b->time = b->flags = 0;
b->progress = BIND_INIT;
}
if ( b->progress != BIND_INIT )
goto afterscanning;
b->progress = BIND_NOENTRY;
/* Not found - have to scan for it. */
path_parse( object_str( target ), &f1 );
/* Scan directory if not already done so. */
{
int found;
BINDING * b;
OBJECT * name;
f2 = f1;
f2.f_grist.len = 0;
path_parent( &f2 );
path_build( &f2, buf, 0 );
name = object_new( buf->value );
b = (BINDING *)hash_insert( bindhash, name, &found );
if ( !found )
{
b->name = object_copy( name );
b->time = b->flags = 0;
b->progress = BIND_INIT;
}
if ( !( b->flags & BIND_SCANNED ) )
{
file_dirscan( name, time_enter, bindhash );
b->flags |= BIND_SCANNED;
}
object_free( name );
}
/* Scan archive if not already done so. */
if ( f1.f_member.len )
{
int found;
BINDING * b;
OBJECT * name;
f2 = f1;
f2.f_grist.len = 0;
f2.f_member.len = 0;
string_truncate( buf, 0 );
path_build( &f2, buf, 0 );
name = object_new( buf->value );
b = (BINDING *)hash_insert( bindhash, name, &found );
if ( !found )
{
b->name = object_copy( name );
b->time = b->flags = 0;
b->progress = BIND_INIT;
}
if ( !( b->flags & BIND_SCANNED ) )
{
file_archscan( buf->value, time_enter, bindhash );
b->flags |= BIND_SCANNED;
}
object_free( name );
}
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 );
object_free( target );
PROFILE_EXIT( timestamp );
}
static void time_enter( void * closure, OBJECT * target, int found, time_t time )
{
int item_found;
BINDING * b;
struct hash * bindhash = (struct hash *)closure;
target = path_as_key( target );
b = (BINDING *)hash_insert( bindhash, target, &item_found );
if ( !item_found )
{
b->name = object_copy( target );
b->flags = 0;
}
b->time = time;
b->progress = found ? BIND_FOUND : BIND_SPOTTED;
if ( DEBUG_BINDSCAN )
printf( "time ( %s ) : %s\n", object_str( target ), time_progress[ b->progress ] );
object_free( target );
}
static void free_timestamps ( void * xbinding, void * data )
{
object_free( ((BINDING *)xbinding)->name );
}
/*
* stamps_done() - free timestamp tables.
*/
void stamps_done()
{
if ( bindhash )
{
hashenumerate( bindhash, free_timestamps, (void *)0 );
hashdone( bindhash );
}
}