file_info_t * filelist_back( FILELIST * list ) { if ( filelist_empty( list ) || list->tail == 0 ) return (file_info_t *)0; return list->tail->value; }
int file_collect_archive_content_( file_archive_info_t * const archive ) { int fd; char fl_magic[ SAIAMAG ]; const char * path = object_str( archive->file->name ); if ( ! filelist_empty( archive->members ) ) filelist_free( archive->members ); if ( ( fd = open( path, O_RDONLY, 0 ) ) < 0 ) return -1; if ( read( fd, fl_magic, SAIAMAG ) != SAIAMAG || lseek( fd, 0, SEEK_SET ) == -1 ) { close( fd ); return -1; } if ( !strncmp( AIAMAG, fl_magic, SAIAMAG ) ) { /* read small variant */ collect_archive_content_small( fd, archive ); } #ifdef AR_HSZ_BIG else if ( !strncmp( AIAMAGBIG, fl_magic, SAIAMAG ) ) { /* read big variant */ collect_archive_content_big( fd, archive ); } #endif close( fd ); return 0; }
FILELISTITER filelist_begin( FILELIST * list ) { if ( filelist_empty( list ) || list->head == 0 ) return (FILELISTITER)0; return &list->head->value; }
file_info_t * filelist_front( FILELIST * list ) { if ( filelist_empty( list ) || list->head == 0 ) return (file_info_t *)0; return list->head->value; }
int filelist_length( FILELIST * list ) { int result = 0; if ( !filelist_empty( list ) ) result = list->size; return result; }
void filelist_free( FILELIST * list ) { FILELISTITER iter; if ( filelist_empty( list ) ) return; while ( filelist_length( list ) ) filelist_pop_front( list ); #ifdef BJAM_NO_MEM_CACHE BJAM_FREE( list ); #endif }
static void file_archivescan_impl( OBJECT * path, archive_scanback func, void * closure ) { file_archive_info_t * const archive = file_archive_query( path ); if ( !archive || !archive->file->is_file ) return; /* Lazy collect the archive content information. */ if ( filelist_empty( archive->members ) ) { if ( DEBUG_BINDSCAN ) printf( "scan archive %s\n", object_str( archive->file->name ) ); if ( file_collect_archive_content_( archive ) < 0 ) return; } /* OS specific part of the file_archivescan operation. */ file_archivescan_( archive, func, closure ); /* Report the collected archive content. */ { FILELISTITER iter = filelist_begin( archive->members ); FILELISTITER const end = filelist_end( archive->members ); char buf[ MAXJPATH ]; for ( ; iter != end ; iter = filelist_next( iter ) ) { file_info_t * member_file = filelist_item( iter ); LIST * symbols = member_file->files; /* Construct member path: 'archive-path(member-name)' */ sprintf( buf, "%s(%s)", object_str( archive->file->name ), object_str( member_file->name ) ); { OBJECT * const member = object_new( buf ); (*func)( closure, member, symbols, 1, &member_file->time ); object_free( member ); } } } }
FILELIST * filelist_pop_front( FILELIST * list ) { FILEITEM * item; if ( filelist_empty( list ) ) return list; item = list->head; if ( item ) { if ( item->value ) free_file_info( item->value, 0 ); list->head = item->next; list->size--; if ( !list->size ) list->tail = list->head; #ifdef BJAM_NO_MEM_CACHE BJAM_FREE( item ); #endif } return list; }
/* * file_archscan() - scan an archive for files */ void file_archscan( char const * arch, scanback func, void * closure ) { OBJECT * path = object_new( arch ); file_archive_info_t * archive = file_archive_query( path ); object_free( path ); if ( filelist_empty( archive->members ) ) { if ( file_collect_archive_content_( archive ) < 0 ) return; } /* Report the collected archive content. */ { FILELISTITER iter = filelist_begin( archive->members ); FILELISTITER const end = filelist_end( archive->members ); char buf[ MAXJPATH ]; for ( ; iter != end ; iter = filelist_next( iter ) ) { file_info_t * member_file = filelist_item( iter ); LIST * symbols = member_file->files; /* Construct member path: 'archive-path(member-name)' */ sprintf( buf, "%s(%s)", object_str( archive->file->name ), object_str( member_file->name ) ); { OBJECT * const member = object_new( buf ); (*func)( closure, member, 1 /* time valid */, &member_file->time ); object_free( member ); } } } }
FILELIST * filelist_push_front( FILELIST * list, OBJECT * path ) { FILEITEM * item; file_info_t * file; /* Lazy initialization */ if ( filelist_empty( list ) ) { list = filelist_new( path ); return list; } item = (FILEITEM *)BJAM_MALLOC( sizeof( FILEITEM ) ); memset( item, 0, sizeof( *item ) ); item->value = (file_info_t *)BJAM_MALLOC( sizeof( file_info_t ) ); file = item->value; memset( file, 0, sizeof( *file ) ); file->name = path; file->files = L0; if ( list->head ) { item->next = list->head; } else { list->tail = item; } list->head = item; list->size++; return list; }
int file_collect_archive_content_( file_archive_info_t * const archive ) { #ifndef NO_AR struct ar_hdr ar_hdr; char * string_table = 0; char buf[ MAXJPATH ]; long offset; int fd; const char * path = object_str( archive->file->name ); if ( ! filelist_empty( archive->members ) ) filelist_free( archive->members ); if ( ( fd = open( path, O_RDONLY, 0 ) ) < 0 ) return -1; if ( read( fd, buf, SARMAG ) != SARMAG || strncmp( ARMAG, buf, SARMAG ) ) { close( fd ); return -1; } offset = SARMAG; if ( DEBUG_BINDSCAN ) out_printf( "scan archive %s\n", path ); 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 ) out_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 ) out_printf( "archive name %s found\n", lar_name ); sprintf( buf, "%s", lar_name ); if ( strcmp( buf, "") != 0 ) { file_info_t * member = 0; archive->members = filelist_push_back( archive->members, object_new( buf ) ); member = filelist_back( archive->members ); member->is_file = 1; member->is_dir = 0; member->exists = 0; timestamp_init( &member->time, (time_t)lar_date, 0 ); } offset += SARHDR + ( ( lar_size + 1 ) & ~1 ); lseek( fd, offset, 0 ); } if ( string_table ) BJAM_FREE( string_table ); close( fd ); #endif /* NO_AR */ return 0; }