summaryrefslogtreecommitdiff
path: root/jam-files/engine/timestamp.c
diff options
context:
space:
mode:
Diffstat (limited to 'jam-files/engine/timestamp.c')
-rw-r--r--jam-files/engine/timestamp.c226
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 );
+}