]>
git.proxmox.com Git - ceph.git/blob - ceph/src/boost/tools/build/src/engine/fileunix.c
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)
15 * fileunix.c - manipulate file names and scan directories on UNIX/AmigaOS
18 * file_archscan() - scan an archive for files
19 * file_mkdir() - create a directory
20 * file_supported_fmt_resolution() - file modification timestamp resolution
22 * External routines called only via routines in filesys.c:
23 * file_collect_dir_content_() - collects directory content information
24 * file_dirscan_() - OS specific file_dirscan() implementation
25 * file_query_() - query information about a path from the OS
26 * file_collect_archive_content_() - collects information about archive members
27 * file_archivescan_() - OS specific file_archivescan() implementation
41 #include <sys/stat.h> /* needed for mkdir() */
43 #if defined( sun ) || defined( __sun ) || defined( linux )
44 # include <unistd.h> /* needed for read and close prototype */
47 #if defined( OS_SEQUENT ) || \
48 defined( OS_DGUX ) || \
49 defined( OS_SCO ) || \
54 #if defined( OS_RHAPSODY ) || defined( OS_MACOSX ) || defined( OS_NEXT )
56 # include <unistd.h> /* need unistd for rhapsody's proper lseek */
57 # define STRUCT_DIRENT struct direct
60 # define STRUCT_DIRENT struct dirent
68 #if defined( OS_MVS ) || defined( OS_INTERIX )
69 #define ARMAG "!<arch>\n"
74 struct ar_hdr
/* archive file member header - printable ascii */
76 char ar_name
[ 16 ]; /* file member name - `/' terminated */
77 char ar_date
[ 12 ]; /* file member date - decimal */
78 char ar_uid
[ 6 ]; /* file member user id - decimal */
79 char ar_gid
[ 6 ]; /* file member group id - decimal */
80 char ar_mode
[ 8 ]; /* file member mode - octal */
81 char ar_size
[ 10 ]; /* file member size - decimal */
82 char ar_fmag
[ 2 ]; /* ARFMAG - string to end header */
86 #if defined( OS_QNX ) || \
87 defined( OS_BEOS ) || \
88 defined( OS_HAIKU ) || \
96 /* Define these for AIX to get the definitions for both small and big archive
97 * file format variants.
107 * file_collect_dir_content_() - collects directory content information
110 int file_collect_dir_content_( file_info_t
* const d
)
115 STRUCT_DIRENT
** namelist
;
116 STRUCT_DIRENT
* dirent
;
122 assert( list_empty( d
->files
) );
124 dirstr
= object_str( d
->name
);
126 memset( (char *)&f
, '\0', sizeof( f
) );
127 f
.f_dir
.ptr
= dirstr
;
128 f
.f_dir
.len
= strlen( dirstr
);
130 if ( !*dirstr
) dirstr
= ".";
132 if ( -1 == ( n
= scandir( dirstr
, &namelist
, NULL
, alphasort
) ) )
139 dirent
= namelist
[ n
];
140 f
.f_base
.ptr
= dirent
->d_name
142 - 2 /* Broken structure definition on sinix. */
145 f
.f_base
.len
= strlen( f
.f_base
.ptr
);
147 string_truncate( path
, 0 );
148 path_build( &f
, path
);
149 name
= object_new( path
->value
);
150 /* Immediately stat the file to preserve invariants. */
151 if ( file_query( name
) )
152 files
= list_push_back( files
, name
);
167 * file_dirscan_() - OS specific file_dirscan() implementation
170 void file_dirscan_( file_info_t
* const d
, scanback func
, void * closure
)
175 /* Special case / : enter it */
176 if ( !strcmp( object_str( d
->name
), "/" ) )
177 (*func
)( closure
, d
->name
, 1 /* stat()'ed */, &d
->time
);
182 * file_mkdir() - create a directory
185 int file_mkdir( char const * const path
)
187 /* Explicit cast to remove const modifiers and avoid related compiler
188 * warnings displayed when using the intel compiler.
190 return mkdir( (char *)path
, 0777 );
195 * file_query_() - query information about a path from the OS
198 void file_query_( file_info_t
* const info
)
200 file_query_posix_( info
);
204 int file_collect_archive_content_( file_archive_info_t
* const archive
);
207 * file_archscan() - scan an archive for files
209 void file_archscan( char const * arch
, scanback func
, void * closure
)
211 OBJECT
* path
= object_new( arch
);
212 file_archive_info_t
* archive
= file_archive_query( path
);
216 if ( filelist_empty( archive
->members
) )
218 if ( file_collect_archive_content_( archive
) < 0 )
222 /* Report the collected archive content. */
224 FILELISTITER iter
= filelist_begin( archive
->members
);
225 FILELISTITER
const end
= filelist_end( archive
->members
);
226 char buf
[ MAXJPATH
];
228 for ( ; iter
!= end
; iter
= filelist_next( iter
) )
230 file_info_t
* member_file
= filelist_item( iter
);
231 LIST
* symbols
= member_file
->files
;
233 /* Construct member path: 'archive-path(member-name)'
235 sprintf( buf
, "%s(%s)",
236 object_str( archive
->file
->name
),
237 object_str( member_file
->name
) );
239 OBJECT
* const member
= object_new( buf
);
240 (*func
)( closure
, member
, 1 /* time valid */, &member_file
->time
);
241 object_free( member
);
249 * file_archivescan_() - OS specific file_archivescan() implementation
252 void file_archivescan_( file_archive_info_t
* const archive
, archive_scanback func
,
259 * file_collect_archive_content_() - collects information about archive members
262 #ifndef AIAMAG /* God-fearing UNIX */
265 #define SARHDR sizeof( struct ar_hdr )
267 int file_collect_archive_content_( file_archive_info_t
* const archive
)
270 struct ar_hdr ar_hdr
;
271 char * string_table
= 0;
272 char buf
[ MAXJPATH
];
275 const char * path
= object_str( archive
->file
->name
);
277 if ( ! filelist_empty( archive
->members
) ) filelist_free( archive
->members
);
279 if ( ( fd
= open( path
, O_RDONLY
, 0 ) ) < 0 )
282 if ( read( fd
, buf
, SARMAG
) != SARMAG
||
283 strncmp( ARMAG
, buf
, SARMAG
) )
291 if ( DEBUG_BINDSCAN
)
292 out_printf( "scan archive %s\n", path
);
294 while ( ( read( fd
, &ar_hdr
, SARHDR
) == SARHDR
) &&
295 !( memcmp( ar_hdr
.ar_fmag
, ARFMAG
, SARFMAG
)
297 /* OSF also has a compressed format */
298 && memcmp( ar_hdr
.ar_fmag
, ARFZMAG
, SARFMAG
)
302 char lar_name_
[ 257 ];
303 char * lar_name
= lar_name_
+ 1;
311 strncpy( lar_name
, ar_hdr
.ar_name
, sizeof( ar_hdr
.ar_name
) );
313 sscanf( ar_hdr
.ar_date
, "%ld", &lar_date
);
314 sscanf( ar_hdr
.ar_size
, "%ld", &lar_size
);
316 if ( ar_hdr
.ar_name
[ 0 ] == '/' )
318 if ( ar_hdr
.ar_name
[ 1 ] == '/' )
320 /* This is the "string table" entry of the symbol table, holding
321 * filename strings longer than 15 characters, i.e. those that
322 * do not fit into ar_name.
324 string_table
= (char *)BJAM_MALLOC_ATOMIC( lar_size
);
325 lseek( fd
, offset
+ SARHDR
, 0 );
326 if ( read( fd
, string_table
, lar_size
) != lar_size
)
327 out_printf("error reading string table\n");
329 else if ( string_table
&& ar_hdr
.ar_name
[ 1 ] != ' ' )
331 /* Long filenames are recognized by "/nnnn" where nnnn is the
332 * offset of the string in the string table represented in ASCII
336 lar_offset
= atoi( lar_name
+ 1 );
337 src
= &string_table
[ lar_offset
];
338 while ( *src
!= '/' )
345 while ( ( *++c
!= ' ' ) && ( *c
!= '/' ) );
348 if ( DEBUG_BINDSCAN
)
349 out_printf( "archive name %s found\n", lar_name
);
351 sprintf( buf
, "%s", lar_name
);
353 if ( strcmp( buf
, "") != 0 )
355 file_info_t
* member
= 0;
357 archive
->members
= filelist_push_back( archive
->members
, object_new( buf
) );
358 member
= filelist_back( archive
->members
);
362 timestamp_init( &member
->time
, (time_t)lar_date
, 0 );
365 offset
+= SARHDR
+ ( ( lar_size
+ 1 ) & ~1 );
366 lseek( fd
, offset
, 0 );
370 BJAM_FREE( string_table
);
378 #else /* AIAMAG - RS6000 AIX */
380 static void collect_archive_content_small( int fd
, file_archive_info_t
* const archive
)
382 struct fl_hdr fl_hdr
;
389 char buf
[ MAXJPATH
];
391 const char * path
= object_str( archive
->file
->name
);
393 if ( read( fd
, (char *)&fl_hdr
, FL_HSZ
) != FL_HSZ
)
396 sscanf( fl_hdr
.fl_fstmoff
, "%ld", &offset
);
398 if ( DEBUG_BINDSCAN
)
399 out_printf( "scan archive %s\n", path
);
401 while ( offset
> 0 && lseek( fd
, offset
, 0 ) >= 0 &&
402 read( fd
, &ar_hdr
, sizeof( ar_hdr
) ) >= (int)sizeof( ar_hdr
.hdr
) )
407 sscanf( ar_hdr
.hdr
.ar_namlen
, "%d" , &lar_namlen
);
408 sscanf( ar_hdr
.hdr
.ar_date
, "%ld", &lar_date
);
409 sscanf( ar_hdr
.hdr
.ar_nxtmem
, "%ld", &offset
);
414 ar_hdr
.hdr
._ar_name
.ar_name
[ lar_namlen
] = '\0';
416 sprintf( buf
, "%s", ar_hdr
.hdr
._ar_name
.ar_name
);
418 if ( strcmp( buf
, "") != 0 )
420 file_info_t
* member
= 0;
422 archive
->members
= filelist_push_back( archive
->members
, object_new( buf
) );
423 member
= filelist_back( archive
->members
);
427 timestamp_init( &member
->time
, (time_t)lar_date
, 0 );
432 /* Check for OS versions supporting the big variant. */
435 static void collect_archive_content_big( int fd
, file_archive_info_t
* const archive
)
437 struct fl_hdr_big fl_hdr
;
440 struct ar_hdr_big hdr
;
444 char buf
[ MAXJPATH
];
446 const char * path
= object_str( archive
->file
->name
);
448 if ( read( fd
, (char *)&fl_hdr
, FL_HSZ_BIG
) != FL_HSZ_BIG
)
451 sscanf( fl_hdr
.fl_fstmoff
, "%lld", &offset
);
453 if ( DEBUG_BINDSCAN
)
454 out_printf( "scan archive %s\n", path
);
456 while ( offset
> 0 && lseek( fd
, offset
, 0 ) >= 0 &&
457 read( fd
, &ar_hdr
, sizeof( ar_hdr
) ) >= sizeof( ar_hdr
.hdr
) )
462 sscanf( ar_hdr
.hdr
.ar_namlen
, "%d" , &lar_namlen
);
463 sscanf( ar_hdr
.hdr
.ar_date
, "%ld" , &lar_date
);
464 sscanf( ar_hdr
.hdr
.ar_nxtmem
, "%lld", &offset
);
469 ar_hdr
.hdr
._ar_name
.ar_name
[ lar_namlen
] = '\0';
471 sprintf( buf
, "%s", ar_hdr
.hdr
._ar_name
.ar_name
);
473 if ( strcmp( buf
, "") != 0 )
475 file_info_t
* member
= 0;
477 archive
->members
= filelist_push_back( archive
->members
, object_new( buf
) );
478 member
= filelist_back( archive
->members
);
482 timestamp_init( &member
->time
, (time_t)lar_date
, 0 );
487 #endif /* AR_HSZ_BIG */
489 int file_collect_archive_content_( file_archive_info_t
* const archive
)
492 char fl_magic
[ SAIAMAG
];
493 const char * path
= object_str( archive
->file
->name
);
495 if ( ! filelist_empty( archive
->members
) ) filelist_free( archive
->members
);
497 if ( ( fd
= open( path
, O_RDONLY
, 0 ) ) < 0 )
500 if ( read( fd
, fl_magic
, SAIAMAG
) != SAIAMAG
||
501 lseek( fd
, 0, SEEK_SET
) == -1 )
507 if ( !strncmp( AIAMAG
, fl_magic
, SAIAMAG
) )
509 /* read small variant */
510 collect_archive_content_small( fd
, archive
);
513 else if ( !strncmp( AIAMAGBIG
, fl_magic
, SAIAMAG
) )
515 /* read big variant */
516 collect_archive_content_big( fd
, archive
);
525 #endif /* AIAMAG - RS6000 AIX */
527 #endif /* USE_FILEUNIX */