2 * Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
4 * This file is part of Jam - see jam.c for Copyright information.
8 * Copyright 2001-2004 David Abrahams.
9 * Copyright 2005 Rene Rivera.
10 * Distributed under the Boost Software License, Version 1.0.
11 * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
20 # include <sys/stat.h>
22 #if defined(sun) || defined(__sun) || defined(linux)
23 # include <unistd.h> /* needed for read and close prototype */
28 #if defined(sun) || defined(__sun)
29 # include <unistd.h> /* needed for read and close prototype */
32 # if defined( OS_SEQUENT ) || \
33 defined( OS_DGUX ) || \
34 defined( OS_SCO ) || \
40 # include <sys/types.h>
41 # include <sys/stat.h>
44 # if defined( OS_RHAPSODY ) || \
45 defined( OS_MACOSX ) || \
47 /* need unistd for rhapsody's proper lseek */
50 # define STRUCT_DIRENT struct direct
53 # define STRUCT_DIRENT struct dirent
61 # if defined( OS_MVS ) || \
64 #define ARMAG "!<arch>\n"
68 struct ar_hdr /* archive file member header - printable ascii */
70 char ar_name[16]; /* file member name - `/' terminated */
71 char ar_date[12]; /* file member date - decimal */
72 char ar_uid[6]; /* file member user id - decimal */
73 char ar_gid[6]; /* file member group id - decimal */
74 char ar_mode[8]; /* file member mode - octal */
75 char ar_size[10]; /* file member size - decimal */
76 char ar_fmag[2]; /* ARFMAG - string to end header */
82 # if defined( OS_QNX ) || \
83 defined( OS_BEOS ) || \
92 /* Define those for AIX to get the definitions for both the small and the
93 * big variant of the archive file format. */
102 * fileunix.c - manipulate file names and scan directories on UNIX/AmigaOS
106 * file_dirscan() - scan a directory for files
107 * file_time() - get timestamp of file, if not done by file_dirscan()
108 * file_archscan() - scan an archive for files
110 * File_dirscan() and file_archscan() call back a caller provided function
111 * for each file found. A flag to this callback function lets file_dirscan()
112 * and file_archscan() indicate that a timestamp is being provided with the
113 * file. If file_dirscan() or file_archscan() do not provide the file's
114 * timestamp, interested parties may later call file_time().
116 * 04/08/94 (seiwald) - Coherent/386 support added.
117 * 12/19/94 (mikem) - solaris string table insanity support
118 * 02/14/95 (seiwald) - parse and build /xxx properly
119 * 05/03/96 (seiwald) - split into pathunix.c
120 * 11/21/96 (peterk) - BEOS does not have Unix-style archives
125 * file_dirscan() - scan a directory for files.
128 void file_dirscan( char * dir, scanback func, void * closure )
130 PROFILE_ENTER( FILE_DIRSCAN );
134 d = file_query( dir );
136 if ( !d || !d->is_dir )
138 PROFILE_EXIT( FILE_DIRSCAN );
147 STRUCT_DIRENT *dirent;
150 /* First enter directory itself */
152 memset( (char *)&f, '\0', sizeof( f ) );
155 f.f_dir.len = strlen(dir);
157 dir = *dir ? dir : ".";
159 /* Now enter contents of directory. */
161 if ( !( dd = opendir( dir ) ) )
163 PROFILE_EXIT( FILE_DIRSCAN );
167 if ( DEBUG_BINDSCAN )
168 printf( "scan directory %s\n", dir );
170 string_new( filename );
171 while ( ( dirent = readdir( dd ) ) )
174 /* Broken structure definition on sinix. */
175 f.f_base.ptr = dirent->d_name - 2;
177 f.f_base.ptr = dirent->d_name;
179 f.f_base.len = strlen( f.f_base.ptr );
181 string_truncate( filename, 0 );
182 path_build( &f, filename, 0 );
184 files = list_new( files, newstr(filename->value) );
185 file_query( filename->value );
187 string_free( filename );
194 /* Special case / : enter it */
196 unsigned long len = strlen(d->name);
197 if ( ( len == 1 ) && ( d->name[0] == '/' ) )
198 (*func)( closure, d->name, 1 /* stat()'ed */, d->time );
201 /* Now enter contents of directory */
204 LIST * files = d->files;
207 file_info_t * ff = file_info( files->string );
208 (*func)( closure, ff->name, 1 /* stat()'ed */, ff->time );
209 files = list_next( files );
213 PROFILE_EXIT( FILE_DIRSCAN );
217 file_info_t * file_query( char * filename )
219 file_info_t * ff = file_info( filename );
224 if ( stat( *filename ? filename : ".", &statbuf ) < 0 )
227 ff->is_file = statbuf.st_mode & S_IFREG ? 1 : 0;
228 ff->is_dir = statbuf.st_mode & S_IFDIR ? 1 : 0;
229 ff->size = statbuf.st_size;
230 ff->time = statbuf.st_mtime ? statbuf.st_mtime : 1;
236 * file_time() - get timestamp of file, if not done by file_dirscan()
244 file_info_t * ff = file_query( filename );
245 if ( !ff ) return -1;
250 int file_is_file(char* filename)
252 file_info_t * ff = file_query( filename );
253 if ( !ff ) return -1;
257 int file_mkdir(char* pathname)
259 return mkdir(pathname, 0766);
263 * file_archscan() - scan an archive for files
266 # ifndef AIAMAG /* God-fearing UNIX */
269 # define SARHDR sizeof( struct ar_hdr )
278 struct ar_hdr ar_hdr;
279 char buf[ MAXJPATH ];
281 char *string_table = 0;
284 if ( ( fd = open( archive, O_RDONLY, 0 ) ) < 0 )
287 if ( read( fd, buf, SARMAG ) != SARMAG ||
288 strncmp( ARMAG, buf, SARMAG ) )
296 if ( DEBUG_BINDSCAN )
297 printf( "scan archive %s\n", archive );
299 while ( ( read( fd, &ar_hdr, SARHDR ) == SARHDR )
300 && !( memcmp( ar_hdr.ar_fmag, ARFMAG, SARFMAG )
302 /* OSF also has a compressed format */
303 && memcmp( ar_hdr.ar_fmag, ARFZMAG, SARFMAG )
308 char * lar_name = lar_name_ + 1;
316 strncpy( lar_name, ar_hdr.ar_name, sizeof(ar_hdr.ar_name) );
318 sscanf( ar_hdr.ar_date, "%ld", &lar_date );
319 sscanf( ar_hdr.ar_size, "%ld", &lar_size );
321 if (ar_hdr.ar_name[0] == '/')
323 if (ar_hdr.ar_name[1] == '/')
325 /* this is the "string table" entry of the symbol table,
326 ** which holds strings of filenames that are longer than
327 ** 15 characters (ie. don't fit into a ar_name
330 string_table = (char *)BJAM_MALLOC_ATOMIC(lar_size);
331 lseek(fd, offset + SARHDR, 0);
332 if (read(fd, string_table, lar_size) != lar_size)
333 printf("error reading string table\n");
335 else if (string_table && ar_hdr.ar_name[1] != ' ')
337 /* Long filenames are recognized by "/nnnn" where nnnn is
338 ** the offset of the string in the string table represented
339 ** in ASCII decimals.
342 lar_offset = atoi(lar_name + 1);
343 src = &string_table[lar_offset];
351 while ( ( *++c != ' ' ) && ( *c != '/' ) ) ;
354 if ( DEBUG_BINDSCAN )
355 printf( "archive name %s found\n", lar_name );
357 sprintf( buf, "%s(%s)", archive, lar_name );
359 (*func)( closure, buf, 1 /* time valid */, (time_t)lar_date );
361 offset += SARHDR + ( ( lar_size + 1 ) & ~1 );
362 lseek( fd, offset, 0 );
366 BJAM_FREE(string_table);
374 # else /* AIAMAG - RS6000 AIX */
376 static void file_archscan_small(
377 int fd, char const *archive, scanback func, void *closure)
379 struct fl_hdr fl_hdr;
386 char buf[ MAXJPATH ];
389 if ( read( fd, (char *)&fl_hdr, FL_HSZ ) != FL_HSZ)
392 sscanf( fl_hdr.fl_fstmoff, "%ld", &offset );
394 if ( DEBUG_BINDSCAN )
395 printf( "scan archive %s\n", archive );
397 while ( ( offset > 0 )
398 && ( lseek( fd, offset, 0 ) >= 0 )
399 && ( read( fd, &ar_hdr, sizeof( ar_hdr ) ) >= sizeof( ar_hdr.hdr ) ) )
404 sscanf( ar_hdr.hdr.ar_namlen, "%d" , &lar_namlen );
405 sscanf( ar_hdr.hdr.ar_date , "%ld", &lar_date );
406 sscanf( ar_hdr.hdr.ar_nxtmem, "%ld", &offset );
411 ar_hdr.hdr._ar_name.ar_name[ lar_namlen ] = '\0';
413 sprintf( buf, "%s(%s)", archive, ar_hdr.hdr._ar_name.ar_name );
415 (*func)( closure, buf, 1 /* time valid */, (time_t)lar_date );
419 /* Check for OS version which supports the big variant. */
422 static void file_archscan_big(
423 int fd, char const *archive, scanback func, void *closure)
425 struct fl_hdr_big fl_hdr;
428 struct ar_hdr_big hdr;
432 char buf[ MAXJPATH ];
435 if ( read( fd, (char *)&fl_hdr, FL_HSZ_BIG) != FL_HSZ_BIG)
438 sscanf( fl_hdr.fl_fstmoff, "%lld", &offset );
440 if ( DEBUG_BINDSCAN )
441 printf( "scan archive %s\n", archive );
443 while ( ( offset > 0 )
444 && ( lseek( fd, offset, 0 ) >= 0 )
445 && ( read( fd, &ar_hdr, sizeof( ar_hdr ) ) >= sizeof( ar_hdr.hdr ) ) )
450 sscanf( ar_hdr.hdr.ar_namlen, "%d" , &lar_namlen );
451 sscanf( ar_hdr.hdr.ar_date , "%ld" , &lar_date );
452 sscanf( ar_hdr.hdr.ar_nxtmem, "%lld", &offset );
457 ar_hdr.hdr._ar_name.ar_name[ lar_namlen ] = '\0';
459 sprintf( buf, "%s(%s)", archive, ar_hdr.hdr._ar_name.ar_name );
461 (*func)( closure, buf, 1 /* time valid */, (time_t)lar_date );
466 #endif /* AR_HSZ_BIG */
468 void file_archscan(char *archive, scanback func, void *closure)
471 char fl_magic[SAIAMAG];
473 if (( fd = open(archive, O_RDONLY, 0)) < 0)
476 if (read( fd, fl_magic, SAIAMAG) != SAIAMAG
477 || lseek(fd, 0, SEEK_SET) == -1)
483 if (strncmp(AIAMAG, fl_magic, SAIAMAG) == 0)
485 /* read small variant */
486 file_archscan_small(fd, archive, func, closure);
489 else if (strncmp(AIAMAGBIG, fl_magic, SAIAMAG) == 0)
491 /* read big variant */
492 file_archscan_big(fd, archive, func, closure);
499 # endif /* AIAMAG - RS6000 AIX */
501 # endif /* USE_FILEUNIX */