mirror of
https://github.com/moses-smt/mosesdecoder.git
synced 2024-10-27 11:59:52 +03:00
465 lines
12 KiB
C
465 lines
12 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.
|
|
* Copyright 2005 Rene Rivera.
|
|
* 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)
|
|
*/
|
|
|
|
/*
|
|
* fileunix.c - manipulate file names and scan directories on UNIX/AmigaOS
|
|
*
|
|
* External routines:
|
|
* file_archscan() - scan an archive for files
|
|
* file_mkdir() - create a directory
|
|
* file_supported_fmt_resolution() - file modification timestamp resolution
|
|
*
|
|
* External routines called only via routines in filesys.c:
|
|
* file_collect_dir_content_() - collects directory content information
|
|
* file_dirscan_() - OS specific file_dirscan() implementation
|
|
* file_query_() - query information about a path from the OS
|
|
*/
|
|
|
|
#include "jam.h"
|
|
#ifdef USE_FILEUNIX
|
|
#include "filesys.h"
|
|
|
|
#include "object.h"
|
|
#include "pathsys.h"
|
|
#include "strings.h"
|
|
|
|
#include <assert.h>
|
|
#include <stdio.h>
|
|
#include <sys/stat.h> /* needed for mkdir() */
|
|
|
|
#if defined( sun ) || defined( __sun ) || defined( linux )
|
|
# include <unistd.h> /* needed for read and close prototype */
|
|
#endif
|
|
|
|
#if defined( OS_SEQUENT ) || \
|
|
defined( OS_DGUX ) || \
|
|
defined( OS_SCO ) || \
|
|
defined( OS_ISC )
|
|
# define PORTAR 1
|
|
#endif
|
|
|
|
#if defined( OS_RHAPSODY ) || defined( OS_MACOSX ) || defined( OS_NEXT )
|
|
# include <sys/dir.h>
|
|
# include <unistd.h> /* need unistd for rhapsody's proper lseek */
|
|
# define STRUCT_DIRENT struct direct
|
|
#else
|
|
# include <dirent.h>
|
|
# define STRUCT_DIRENT struct dirent
|
|
#endif
|
|
|
|
#ifdef OS_COHERENT
|
|
# include <arcoff.h>
|
|
# define HAVE_AR
|
|
#endif
|
|
|
|
#if defined( OS_MVS ) || defined( OS_INTERIX )
|
|
#define ARMAG "!<arch>\n"
|
|
#define SARMAG 8
|
|
#define ARFMAG "`\n"
|
|
#define HAVE_AR
|
|
|
|
struct ar_hdr /* archive file member header - printable ascii */
|
|
{
|
|
char ar_name[ 16 ]; /* file member name - `/' terminated */
|
|
char ar_date[ 12 ]; /* file member date - decimal */
|
|
char ar_uid[ 6 ]; /* file member user id - decimal */
|
|
char ar_gid[ 6 ]; /* file member group id - decimal */
|
|
char ar_mode[ 8 ]; /* file member mode - octal */
|
|
char ar_size[ 10 ]; /* file member size - decimal */
|
|
char ar_fmag[ 2 ]; /* ARFMAG - string to end header */
|
|
};
|
|
#endif
|
|
|
|
#if defined( OS_QNX ) || defined( OS_BEOS ) || defined( OS_MPEIX )
|
|
# define NO_AR
|
|
# define HAVE_AR
|
|
#endif
|
|
|
|
#ifndef HAVE_AR
|
|
# ifdef OS_AIX
|
|
/* Define these for AIX to get the definitions for both small and big archive
|
|
* file format variants.
|
|
*/
|
|
# define __AR_SMALL__
|
|
# define __AR_BIG__
|
|
# endif
|
|
# include <ar.h>
|
|
#endif
|
|
|
|
|
|
/*
|
|
* file_collect_dir_content_() - collects directory content information
|
|
*/
|
|
|
|
int file_collect_dir_content_( file_info_t * const d )
|
|
{
|
|
LIST * files = L0;
|
|
PATHNAME f;
|
|
DIR * dd;
|
|
STRUCT_DIRENT * dirent;
|
|
string path[ 1 ];
|
|
char const * dirstr;
|
|
|
|
assert( d );
|
|
assert( d->is_dir );
|
|
assert( list_empty( d->files ) );
|
|
|
|
dirstr = object_str( d->name );
|
|
|
|
memset( (char *)&f, '\0', sizeof( f ) );
|
|
f.f_dir.ptr = dirstr;
|
|
f.f_dir.len = strlen( dirstr );
|
|
|
|
if ( !*dirstr ) dirstr = ".";
|
|
|
|
if ( !( dd = opendir( dirstr ) ) )
|
|
return -1;
|
|
|
|
string_new( path );
|
|
while ( ( dirent = readdir( dd ) ) )
|
|
{
|
|
OBJECT * name;
|
|
f.f_base.ptr = dirent->d_name
|
|
#ifdef old_sinix
|
|
- 2 /* Broken structure definition on sinix. */
|
|
#endif
|
|
;
|
|
f.f_base.len = strlen( f.f_base.ptr );
|
|
|
|
string_truncate( path, 0 );
|
|
path_build( &f, path );
|
|
name = object_new( path->value );
|
|
/* Immediately stat the file to preserve invariants. */
|
|
if ( file_query( name ) )
|
|
files = list_push_back( files, name );
|
|
else
|
|
object_free( name );
|
|
}
|
|
string_free( path );
|
|
|
|
closedir( dd );
|
|
|
|
d->files = files;
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*
|
|
* file_dirscan_() - OS specific file_dirscan() implementation
|
|
*/
|
|
|
|
void file_dirscan_( file_info_t * const d, scanback func, void * closure )
|
|
{
|
|
assert( d );
|
|
assert( d->is_dir );
|
|
|
|
/* Special case / : enter it */
|
|
if ( !strcmp( object_str( d->name ), "/" ) )
|
|
(*func)( closure, d->name, 1 /* stat()'ed */, &d->time );
|
|
}
|
|
|
|
|
|
/*
|
|
* file_mkdir() - create a directory
|
|
*/
|
|
|
|
int file_mkdir( char const * const path )
|
|
{
|
|
/* Explicit cast to remove const modifiers and avoid related compiler
|
|
* warnings displayed when using the intel compiler.
|
|
*/
|
|
return mkdir( (char *)path, 0777 );
|
|
}
|
|
|
|
|
|
/*
|
|
* file_query_() - query information about a path from the OS
|
|
*/
|
|
|
|
void file_query_( file_info_t * const info )
|
|
{
|
|
file_query_posix_( info );
|
|
}
|
|
|
|
|
|
/*
|
|
* file_supported_fmt_resolution() - file modification timestamp resolution
|
|
*
|
|
* Returns the minimum file modification timestamp resolution supported by this
|
|
* Boost Jam implementation. File modification timestamp changes of less than
|
|
* the returned value might not be recognized.
|
|
*
|
|
* Does not take into consideration any OS or file system related restrictions.
|
|
*
|
|
* Return value 0 indicates that any value supported by the OS is also supported
|
|
* here.
|
|
*/
|
|
|
|
void file_supported_fmt_resolution( timestamp * const t )
|
|
{
|
|
/* The current implementation does not support file modification timestamp
|
|
* resolution of less than one second.
|
|
*/
|
|
timestamp_init( t, 1, 0 );
|
|
}
|
|
|
|
|
|
/*
|
|
* file_archscan() - scan an archive for files
|
|
*/
|
|
|
|
#ifndef AIAMAG /* God-fearing UNIX */
|
|
|
|
#define SARFMAG 2
|
|
#define SARHDR sizeof( struct ar_hdr )
|
|
|
|
void file_archscan( char const * archive, scanback func, void * closure )
|
|
{
|
|
#ifndef NO_AR
|
|
struct ar_hdr ar_hdr;
|
|
char * string_table = 0;
|
|
char buf[ MAXJPATH ];
|
|
long offset;
|
|
int fd;
|
|
|
|
if ( ( fd = open( archive, O_RDONLY, 0 ) ) < 0 )
|
|
return;
|
|
|
|
if ( read( fd, buf, SARMAG ) != SARMAG ||
|
|
strncmp( ARMAG, buf, SARMAG ) )
|
|
{
|
|
close( fd );
|
|
return;
|
|
}
|
|
|
|
offset = SARMAG;
|
|
|
|
if ( DEBUG_BINDSCAN )
|
|
printf( "scan archive %s\n", archive );
|
|
|
|
while ( ( read( fd, &ar_hdr, SARHDR ) == SARHDR ) &&
|
|
!( memcmp( ar_hdr.ar_fmag, ARFMAG, SARFMAG )
|
|
#ifdef ARFZMAG
|
|
/* OSF also has a compressed format */
|
|
&& memcmp( ar_hdr.ar_fmag, ARFZMAG, SARFMAG )
|
|
#endif
|
|
) )
|
|
{
|
|
char lar_name_[ 257 ];
|
|
char * lar_name = lar_name_ + 1;
|
|
long lar_date;
|
|
long lar_size;
|
|
long lar_offset;
|
|
char * c;
|
|
char * src;
|
|
char * dest;
|
|
|
|
strncpy( lar_name, ar_hdr.ar_name, sizeof( ar_hdr.ar_name ) );
|
|
|
|
sscanf( ar_hdr.ar_date, "%ld", &lar_date );
|
|
sscanf( ar_hdr.ar_size, "%ld", &lar_size );
|
|
|
|
if ( ar_hdr.ar_name[ 0 ] == '/' )
|
|
{
|
|
if ( ar_hdr.ar_name[ 1 ] == '/' )
|
|
{
|
|
/* This is the "string table" entry of the symbol table, holding
|
|
* filename strings longer than 15 characters, i.e. those that
|
|
* do not fit into ar_name.
|
|
*/
|
|
string_table = (char *)BJAM_MALLOC_ATOMIC( lar_size );
|
|
lseek( fd, offset + SARHDR, 0 );
|
|
if ( read( fd, string_table, lar_size ) != lar_size )
|
|
printf("error reading string table\n");
|
|
}
|
|
else if ( string_table && ar_hdr.ar_name[ 1 ] != ' ' )
|
|
{
|
|
/* Long filenames are recognized by "/nnnn" where nnnn is the
|
|
* offset of the string in the string table represented in ASCII
|
|
* decimals.
|
|
*/
|
|
dest = lar_name;
|
|
lar_offset = atoi( lar_name + 1 );
|
|
src = &string_table[ lar_offset ];
|
|
while ( *src != '/' )
|
|
*dest++ = *src++;
|
|
*dest = '/';
|
|
}
|
|
}
|
|
|
|
c = lar_name - 1;
|
|
while ( ( *++c != ' ' ) && ( *c != '/' ) );
|
|
*c = '\0';
|
|
|
|
if ( DEBUG_BINDSCAN )
|
|
printf( "archive name %s found\n", lar_name );
|
|
|
|
sprintf( buf, "%s(%s)", archive, lar_name );
|
|
|
|
{
|
|
OBJECT * const member = object_new( buf );
|
|
timestamp time;
|
|
timestamp_init( &time, (time_t)lar_date, 0 );
|
|
(*func)( closure, member, 1 /* time valid */, &time );
|
|
object_free( member );
|
|
}
|
|
|
|
offset += SARHDR + ( ( lar_size + 1 ) & ~1 );
|
|
lseek( fd, offset, 0 );
|
|
}
|
|
|
|
if ( string_table )
|
|
BJAM_FREE( string_table );
|
|
|
|
close( fd );
|
|
#endif /* NO_AR */
|
|
}
|
|
|
|
#else /* AIAMAG - RS6000 AIX */
|
|
|
|
static void file_archscan_small( int fd, char const * archive, scanback func,
|
|
void * closure )
|
|
{
|
|
struct fl_hdr fl_hdr;
|
|
|
|
struct {
|
|
struct ar_hdr hdr;
|
|
char pad[ 256 ];
|
|
} ar_hdr ;
|
|
|
|
char buf[ MAXJPATH ];
|
|
long offset;
|
|
|
|
if ( read( fd, (char *)&fl_hdr, FL_HSZ ) != FL_HSZ )
|
|
return;
|
|
|
|
sscanf( fl_hdr.fl_fstmoff, "%ld", &offset );
|
|
|
|
if ( DEBUG_BINDSCAN )
|
|
printf( "scan archive %s\n", archive );
|
|
|
|
while ( offset > 0 && lseek( fd, offset, 0 ) >= 0 &&
|
|
read( fd, &ar_hdr, sizeof( ar_hdr ) ) >= (int)sizeof( ar_hdr.hdr ) )
|
|
{
|
|
long lar_date;
|
|
int lar_namlen;
|
|
|
|
sscanf( ar_hdr.hdr.ar_namlen, "%d" , &lar_namlen );
|
|
sscanf( ar_hdr.hdr.ar_date , "%ld", &lar_date );
|
|
sscanf( ar_hdr.hdr.ar_nxtmem, "%ld", &offset );
|
|
|
|
if ( !lar_namlen )
|
|
continue;
|
|
|
|
ar_hdr.hdr._ar_name.ar_name[ lar_namlen ] = '\0';
|
|
|
|
sprintf( buf, "%s(%s)", archive, ar_hdr.hdr._ar_name.ar_name );
|
|
|
|
{
|
|
OBJECT * const member = object_new( buf );
|
|
timestamp time;
|
|
timestamp_init( &time, (time_t)lar_date, 0 );
|
|
(*func)( closure, member, 1 /* time valid */, &time );
|
|
object_free( member );
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Check for OS versions supporting the big variant. */
|
|
#ifdef AR_HSZ_BIG
|
|
|
|
static void file_archscan_big( int fd, char const * archive, scanback func,
|
|
void * closure )
|
|
{
|
|
struct fl_hdr_big fl_hdr;
|
|
|
|
struct {
|
|
struct ar_hdr_big hdr;
|
|
char pad[ 256 ];
|
|
} ar_hdr ;
|
|
|
|
char buf[ MAXJPATH ];
|
|
long long offset;
|
|
|
|
if ( read( fd, (char *)&fl_hdr, FL_HSZ_BIG ) != FL_HSZ_BIG )
|
|
return;
|
|
|
|
sscanf( fl_hdr.fl_fstmoff, "%lld", &offset );
|
|
|
|
if ( DEBUG_BINDSCAN )
|
|
printf( "scan archive %s\n", archive );
|
|
|
|
while ( offset > 0 && lseek( fd, offset, 0 ) >= 0 &&
|
|
read( fd, &ar_hdr, sizeof( ar_hdr ) ) >= sizeof( ar_hdr.hdr ) )
|
|
{
|
|
long lar_date;
|
|
int lar_namlen;
|
|
|
|
sscanf( ar_hdr.hdr.ar_namlen, "%d" , &lar_namlen );
|
|
sscanf( ar_hdr.hdr.ar_date , "%ld" , &lar_date );
|
|
sscanf( ar_hdr.hdr.ar_nxtmem, "%lld", &offset );
|
|
|
|
if ( !lar_namlen )
|
|
continue;
|
|
|
|
ar_hdr.hdr._ar_name.ar_name[ lar_namlen ] = '\0';
|
|
|
|
sprintf( buf, "%s(%s)", archive, ar_hdr.hdr._ar_name.ar_name );
|
|
|
|
{
|
|
OBJECT * const member = object_new( buf );
|
|
timestamp time;
|
|
timestamp_init( &time, (time_t)lar_date, 0 );
|
|
(*func)( closure, member, 1 /* time valid */, &time );
|
|
object_free( member );
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif /* AR_HSZ_BIG */
|
|
|
|
void file_archscan( char const * archive, scanback func, void * closure )
|
|
{
|
|
int fd;
|
|
char fl_magic[ SAIAMAG ];
|
|
|
|
if ( ( fd = open( archive, O_RDONLY, 0 ) ) < 0 )
|
|
return;
|
|
|
|
if ( read( fd, fl_magic, SAIAMAG ) != SAIAMAG ||
|
|
lseek( fd, 0, SEEK_SET ) == -1 )
|
|
{
|
|
close( fd );
|
|
return;
|
|
}
|
|
|
|
if ( !strncmp( AIAMAG, fl_magic, SAIAMAG ) )
|
|
{
|
|
/* read small variant */
|
|
file_archscan_small( fd, archive, func, closure );
|
|
}
|
|
#ifdef AR_HSZ_BIG
|
|
else if ( !strncmp( AIAMAGBIG, fl_magic, SAIAMAG ) )
|
|
{
|
|
/* read big variant */
|
|
file_archscan_big( fd, archive, func, closure );
|
|
}
|
|
#endif
|
|
|
|
close( fd );
|
|
}
|
|
|
|
#endif /* AIAMAG - RS6000 AIX */
|
|
|
|
#endif /* USE_FILEUNIX */
|