]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/tools/build/src/engine/fileunix.c
update sources to ceph Nautilus 14.2.1
[ceph.git] / ceph / src / boost / tools / build / src / engine / fileunix.c
1 /*
2 * Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
3 *
4 * This file is part of Jam - see jam.c for Copyright information.
5 */
6
7 /* This file is ALSO:
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)
12 */
13
14 /*
15 * fileunix.c - manipulate file names and scan directories on UNIX/AmigaOS
16 *
17 * External routines:
18 * file_archscan() - scan an archive for files
19 * file_mkdir() - create a directory
20 * file_supported_fmt_resolution() - file modification timestamp resolution
21 *
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
28 */
29
30 #include "jam.h"
31 #ifdef USE_FILEUNIX
32 #include "filesys.h"
33
34 #include "object.h"
35 #include "pathsys.h"
36 #include "strings.h"
37 #include "output.h"
38
39 #include <assert.h>
40 #include <stdio.h>
41 #include <sys/stat.h> /* needed for mkdir() */
42
43 #if defined( sun ) || defined( __sun ) || defined( linux )
44 # include <unistd.h> /* needed for read and close prototype */
45 #endif
46
47 #if defined( OS_SEQUENT ) || \
48 defined( OS_DGUX ) || \
49 defined( OS_SCO ) || \
50 defined( OS_ISC )
51 # define PORTAR 1
52 #endif
53
54 #if defined( OS_RHAPSODY ) || defined( OS_MACOSX ) || defined( OS_NEXT )
55 # include <sys/dir.h>
56 # include <unistd.h> /* need unistd for rhapsody's proper lseek */
57 # define STRUCT_DIRENT struct direct
58 #else
59 # include <dirent.h>
60 # define STRUCT_DIRENT struct dirent
61 #endif
62
63 #ifdef OS_COHERENT
64 # include <arcoff.h>
65 # define HAVE_AR
66 #endif
67
68 #if defined( OS_MVS ) || defined( OS_INTERIX )
69 #define ARMAG "!<arch>\n"
70 #define SARMAG 8
71 #define ARFMAG "`\n"
72 #define HAVE_AR
73
74 struct ar_hdr /* archive file member header - printable ascii */
75 {
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 */
83 };
84 #endif
85
86 #if defined( OS_QNX ) || \
87 defined( OS_BEOS ) || \
88 defined( OS_HAIKU ) || \
89 defined( OS_MPEIX )
90 # define NO_AR
91 # define HAVE_AR
92 #endif
93
94 #ifndef HAVE_AR
95 # ifdef OS_AIX
96 /* Define these for AIX to get the definitions for both small and big archive
97 * file format variants.
98 */
99 # define __AR_SMALL__
100 # define __AR_BIG__
101 # endif
102 # include <ar.h>
103 #endif
104
105
106 /*
107 * file_collect_dir_content_() - collects directory content information
108 */
109
110 int file_collect_dir_content_( file_info_t * const d )
111 {
112 LIST * files = L0;
113 PATHNAME f;
114 int n;
115 STRUCT_DIRENT ** namelist;
116 STRUCT_DIRENT * dirent;
117 string path[ 1 ];
118 char const * dirstr;
119
120 assert( d );
121 assert( d->is_dir );
122 assert( list_empty( d->files ) );
123
124 dirstr = object_str( d->name );
125
126 memset( (char *)&f, '\0', sizeof( f ) );
127 f.f_dir.ptr = dirstr;
128 f.f_dir.len = strlen( dirstr );
129
130 if ( !*dirstr ) dirstr = ".";
131
132 if ( -1 == ( n = scandir( dirstr, &namelist, NULL, alphasort ) ) )
133 return -1;
134
135 string_new( path );
136 while ( n-- )
137 {
138 OBJECT * name;
139 dirent = namelist[ n ];
140 f.f_base.ptr = dirent->d_name
141 #ifdef old_sinix
142 - 2 /* Broken structure definition on sinix. */
143 #endif
144 ;
145 f.f_base.len = strlen( f.f_base.ptr );
146
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 );
153 else
154 object_free( name );
155 free( dirent );
156 }
157 string_free( path );
158
159 free( namelist );
160
161 d->files = files;
162 return 0;
163 }
164
165
166 /*
167 * file_dirscan_() - OS specific file_dirscan() implementation
168 */
169
170 void file_dirscan_( file_info_t * const d, scanback func, void * closure )
171 {
172 assert( d );
173 assert( d->is_dir );
174
175 /* Special case / : enter it */
176 if ( !strcmp( object_str( d->name ), "/" ) )
177 (*func)( closure, d->name, 1 /* stat()'ed */, &d->time );
178 }
179
180
181 /*
182 * file_mkdir() - create a directory
183 */
184
185 int file_mkdir( char const * const path )
186 {
187 /* Explicit cast to remove const modifiers and avoid related compiler
188 * warnings displayed when using the intel compiler.
189 */
190 return mkdir( (char *)path, 0777 );
191 }
192
193
194 /*
195 * file_query_() - query information about a path from the OS
196 */
197
198 void file_query_( file_info_t * const info )
199 {
200 file_query_posix_( info );
201 }
202
203
204 int file_collect_archive_content_( file_archive_info_t * const archive );
205
206 /*
207 * file_archscan() - scan an archive for files
208 */
209 void file_archscan( char const * arch, scanback func, void * closure )
210 {
211 OBJECT * path = object_new( arch );
212 file_archive_info_t * archive = file_archive_query( path );
213
214 object_free( path );
215
216 if ( filelist_empty( archive->members ) )
217 {
218 if ( file_collect_archive_content_( archive ) < 0 )
219 return;
220 }
221
222 /* Report the collected archive content. */
223 {
224 FILELISTITER iter = filelist_begin( archive->members );
225 FILELISTITER const end = filelist_end( archive->members );
226 char buf[ MAXJPATH ];
227
228 for ( ; iter != end ; iter = filelist_next( iter ) )
229 {
230 file_info_t * member_file = filelist_item( iter );
231 LIST * symbols = member_file->files;
232
233 /* Construct member path: 'archive-path(member-name)'
234 */
235 sprintf( buf, "%s(%s)",
236 object_str( archive->file->name ),
237 object_str( member_file->name ) );
238 {
239 OBJECT * const member = object_new( buf );
240 (*func)( closure, member, 1 /* time valid */, &member_file->time );
241 object_free( member );
242 }
243 }
244 }
245 }
246
247
248 /*
249 * file_archivescan_() - OS specific file_archivescan() implementation
250 */
251
252 void file_archivescan_( file_archive_info_t * const archive, archive_scanback func,
253 void * closure )
254 {
255 }
256
257
258 /*
259 * file_collect_archive_content_() - collects information about archive members
260 */
261
262 #ifndef AIAMAG /* God-fearing UNIX */
263
264 #define SARFMAG 2
265 #define SARHDR sizeof( struct ar_hdr )
266
267 int file_collect_archive_content_( file_archive_info_t * const archive )
268 {
269 #ifndef NO_AR
270 struct ar_hdr ar_hdr;
271 char * string_table = 0;
272 char buf[ MAXJPATH ];
273 long offset;
274 int fd;
275 const char * path = object_str( archive->file->name );
276
277 if ( ! filelist_empty( archive->members ) ) filelist_free( archive->members );
278
279 if ( ( fd = open( path, O_RDONLY, 0 ) ) < 0 )
280 return -1;
281
282 if ( read( fd, buf, SARMAG ) != SARMAG ||
283 strncmp( ARMAG, buf, SARMAG ) )
284 {
285 close( fd );
286 return -1;
287 }
288
289 offset = SARMAG;
290
291 if ( DEBUG_BINDSCAN )
292 out_printf( "scan archive %s\n", path );
293
294 while ( ( read( fd, &ar_hdr, SARHDR ) == SARHDR ) &&
295 !( memcmp( ar_hdr.ar_fmag, ARFMAG, SARFMAG )
296 #ifdef ARFZMAG
297 /* OSF also has a compressed format */
298 && memcmp( ar_hdr.ar_fmag, ARFZMAG, SARFMAG )
299 #endif
300 ) )
301 {
302 char lar_name_[ 257 ];
303 char * lar_name = lar_name_ + 1;
304 long lar_date;
305 long lar_size;
306 long lar_offset;
307 char * c;
308 char * src;
309 char * dest;
310
311 strncpy( lar_name, ar_hdr.ar_name, sizeof( ar_hdr.ar_name ) );
312
313 sscanf( ar_hdr.ar_date, "%ld", &lar_date );
314 sscanf( ar_hdr.ar_size, "%ld", &lar_size );
315
316 if ( ar_hdr.ar_name[ 0 ] == '/' )
317 {
318 if ( ar_hdr.ar_name[ 1 ] == '/' )
319 {
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.
323 */
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");
328 }
329 else if ( string_table && ar_hdr.ar_name[ 1 ] != ' ' )
330 {
331 /* Long filenames are recognized by "/nnnn" where nnnn is the
332 * offset of the string in the string table represented in ASCII
333 * decimals.
334 */
335 dest = lar_name;
336 lar_offset = atoi( lar_name + 1 );
337 src = &string_table[ lar_offset ];
338 while ( *src != '/' )
339 *dest++ = *src++;
340 *dest = '/';
341 }
342 }
343
344 c = lar_name - 1;
345 while ( ( *++c != ' ' ) && ( *c != '/' ) );
346 *c = '\0';
347
348 if ( DEBUG_BINDSCAN )
349 out_printf( "archive name %s found\n", lar_name );
350
351 sprintf( buf, "%s", lar_name );
352
353 if ( strcmp( buf, "") != 0 )
354 {
355 file_info_t * member = 0;
356
357 archive->members = filelist_push_back( archive->members, object_new( buf ) );
358 member = filelist_back( archive->members );
359 member->is_file = 1;
360 member->is_dir = 0;
361 member->exists = 0;
362 timestamp_init( &member->time, (time_t)lar_date, 0 );
363 }
364
365 offset += SARHDR + ( ( lar_size + 1 ) & ~1 );
366 lseek( fd, offset, 0 );
367 }
368
369 if ( string_table )
370 BJAM_FREE( string_table );
371
372 close( fd );
373 #endif /* NO_AR */
374
375 return 0;
376 }
377
378 #else /* AIAMAG - RS6000 AIX */
379
380 static void collect_archive_content_small( int fd, file_archive_info_t * const archive )
381 {
382 struct fl_hdr fl_hdr;
383
384 struct {
385 struct ar_hdr hdr;
386 char pad[ 256 ];
387 } ar_hdr ;
388
389 char buf[ MAXJPATH ];
390 long offset;
391 const char * path = object_str( archive->file->name );
392
393 if ( read( fd, (char *)&fl_hdr, FL_HSZ ) != FL_HSZ )
394 return;
395
396 sscanf( fl_hdr.fl_fstmoff, "%ld", &offset );
397
398 if ( DEBUG_BINDSCAN )
399 out_printf( "scan archive %s\n", path );
400
401 while ( offset > 0 && lseek( fd, offset, 0 ) >= 0 &&
402 read( fd, &ar_hdr, sizeof( ar_hdr ) ) >= (int)sizeof( ar_hdr.hdr ) )
403 {
404 long lar_date;
405 int lar_namlen;
406
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 );
410
411 if ( !lar_namlen )
412 continue;
413
414 ar_hdr.hdr._ar_name.ar_name[ lar_namlen ] = '\0';
415
416 sprintf( buf, "%s", ar_hdr.hdr._ar_name.ar_name );
417
418 if ( strcmp( buf, "") != 0 )
419 {
420 file_info_t * member = 0;
421
422 archive->members = filelist_push_back( archive->members, object_new( buf ) );
423 member = filelist_back( archive->members );
424 member->is_file = 1;
425 member->is_dir = 0;
426 member->exists = 0;
427 timestamp_init( &member->time, (time_t)lar_date, 0 );
428 }
429 }
430 }
431
432 /* Check for OS versions supporting the big variant. */
433 #ifdef AR_HSZ_BIG
434
435 static void collect_archive_content_big( int fd, file_archive_info_t * const archive )
436 {
437 struct fl_hdr_big fl_hdr;
438
439 struct {
440 struct ar_hdr_big hdr;
441 char pad[ 256 ];
442 } ar_hdr ;
443
444 char buf[ MAXJPATH ];
445 long long offset;
446 const char * path = object_str( archive->file->name );
447
448 if ( read( fd, (char *)&fl_hdr, FL_HSZ_BIG ) != FL_HSZ_BIG )
449 return;
450
451 sscanf( fl_hdr.fl_fstmoff, "%lld", &offset );
452
453 if ( DEBUG_BINDSCAN )
454 out_printf( "scan archive %s\n", path );
455
456 while ( offset > 0 && lseek( fd, offset, 0 ) >= 0 &&
457 read( fd, &ar_hdr, sizeof( ar_hdr ) ) >= sizeof( ar_hdr.hdr ) )
458 {
459 long lar_date;
460 int lar_namlen;
461
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 );
465
466 if ( !lar_namlen )
467 continue;
468
469 ar_hdr.hdr._ar_name.ar_name[ lar_namlen ] = '\0';
470
471 sprintf( buf, "%s", ar_hdr.hdr._ar_name.ar_name );
472
473 if ( strcmp( buf, "") != 0 )
474 {
475 file_info_t * member = 0;
476
477 archive->members = filelist_push_back( archive->members, object_new( buf ) );
478 member = filelist_back( archive->members );
479 member->is_file = 1;
480 member->is_dir = 0;
481 member->exists = 0;
482 timestamp_init( &member->time, (time_t)lar_date, 0 );
483 }
484 }
485 }
486
487 #endif /* AR_HSZ_BIG */
488
489 int file_collect_archive_content_( file_archive_info_t * const archive )
490 {
491 int fd;
492 char fl_magic[ SAIAMAG ];
493 const char * path = object_str( archive->file->name );
494
495 if ( ! filelist_empty( archive->members ) ) filelist_free( archive->members );
496
497 if ( ( fd = open( path, O_RDONLY, 0 ) ) < 0 )
498 return -1;
499
500 if ( read( fd, fl_magic, SAIAMAG ) != SAIAMAG ||
501 lseek( fd, 0, SEEK_SET ) == -1 )
502 {
503 close( fd );
504 return -1;
505 }
506
507 if ( !strncmp( AIAMAG, fl_magic, SAIAMAG ) )
508 {
509 /* read small variant */
510 collect_archive_content_small( fd, archive );
511 }
512 #ifdef AR_HSZ_BIG
513 else if ( !strncmp( AIAMAGBIG, fl_magic, SAIAMAG ) )
514 {
515 /* read big variant */
516 collect_archive_content_big( fd, archive );
517 }
518 #endif
519
520 close( fd );
521
522 return 0;
523 }
524
525 #endif /* AIAMAG - RS6000 AIX */
526
527 #endif /* USE_FILEUNIX */