Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_33_1/tools/build/jam_src/fileunix.c @ 12

Last change on this file since 12 was 12, checked in by landauf, 18 years ago

added boost

File size: 10.4 KB
Line 
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 *  Distributed under the Boost Software License, Version 1.0.
10 *  (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
11 */
12
13# include "jam.h"
14# include "filesys.h"
15# include "strings.h"
16# include "pathsys.h"
17# include <stdio.h>
18
19#if defined(sun) || defined(__sun) || defined(linux)
20# include <unistd.h> /* needed for read and close prototype */
21#endif
22
23# ifdef USE_FILEUNIX
24
25#if defined(sun) || defined(__sun)
26# include <unistd.h> /* needed for read and close prototype */
27#endif
28
29# if defined( OS_SEQUENT ) || \
30     defined( OS_DGUX ) || \
31     defined( OS_SCO ) || \
32     defined( OS_ISC )
33# define PORTAR 1
34# endif
35
36# ifdef __EMX__
37# include <sys/types.h>
38# include <sys/stat.h>
39# endif
40
41# if defined( OS_RHAPSODY ) || \
42     defined( OS_MACOSX ) || \
43     defined( OS_NEXT )
44/* need unistd for rhapsody's proper lseek */
45# include <sys/dir.h>
46# include <unistd.h>
47# define STRUCT_DIRENT struct direct
48# else
49# include <dirent.h>
50# define STRUCT_DIRENT struct dirent
51# endif
52
53# ifdef OS_COHERENT
54# include <arcoff.h>
55# define HAVE_AR
56# endif
57
58# if defined( OS_MVS ) || \
59                 defined( OS_INTERIX )
60
61#define ARMAG   "!<arch>\n"
62#define SARMAG  8
63#define ARFMAG  "`\n"
64
65struct ar_hdr           /* archive file member header - printable ascii */
66{
67        char    ar_name[16];    /* file member name - `/' terminated */
68        char    ar_date[12];    /* file member date - decimal */
69        char    ar_uid[6];      /* file member user id - decimal */
70        char    ar_gid[6];      /* file member group id - decimal */
71        char    ar_mode[8];     /* file member mode - octal */
72        char    ar_size[10];    /* file member size - decimal */
73        char    ar_fmag[2];     /* ARFMAG - string to end header */
74};
75
76# define HAVE_AR
77# endif
78
79# if defined( OS_QNX ) || \
80     defined( OS_BEOS ) || \
81     defined( OS_MPEIX )
82# define NO_AR
83# define HAVE_AR
84# endif
85
86# ifndef HAVE_AR
87
88# ifdef OS_AIX
89/* Define those for AIX to get the definitions for both the small and the
90 * big variant of the archive file format. */
91#        define __AR_SMALL__
92#        define __AR_BIG__
93# endif
94
95# include <ar.h>
96# endif
97
98/*
99 * fileunix.c - manipulate file names and scan directories on UNIX/AmigaOS
100 *
101 * External routines:
102 *
103 *      file_dirscan() - scan a directory for files
104 *      file_time() - get timestamp of file, if not done by file_dirscan()
105 *      file_archscan() - scan an archive for files
106 *
107 * File_dirscan() and file_archscan() call back a caller provided function
108 * for each file found.  A flag to this callback function lets file_dirscan()
109 * and file_archscan() indicate that a timestamp is being provided with the
110 * file.   If file_dirscan() or file_archscan() do not provide the file's
111 * timestamp, interested parties may later call file_time().
112 *
113 * 04/08/94 (seiwald) - Coherent/386 support added.
114 * 12/19/94 (mikem) - solaris string table insanity support
115 * 02/14/95 (seiwald) - parse and build /xxx properly
116 * 05/03/96 (seiwald) - split into pathunix.c
117 * 11/21/96 (peterk) - BEOS does not have Unix-style archives
118 */
119
120/*
121 * file_dirscan() - scan a directory for files
122 */
123
124void
125file_dirscan( 
126        char *dir,
127        scanback func,
128        void *closure )
129{
130        PATHNAME f;
131        DIR *d;
132        STRUCT_DIRENT *dirent;
133        string filename[1];
134
135        /* First enter directory itself */
136
137        memset( (char *)&f, '\0', sizeof( f ) );
138
139        f.f_dir.ptr = dir;
140        f.f_dir.len = strlen(dir);
141
142        dir = *dir ? dir : ".";
143
144        /* Special case / : enter it */
145
146        if( f.f_dir.len == 1 && f.f_dir.ptr[0] == '/' )
147            (*func)( closure, dir, 0 /* not stat()'ed */, (time_t)0 );
148
149        /* Now enter contents of directory */
150
151        if( !( d = opendir( dir ) ) )
152            return;
153
154        if( DEBUG_BINDSCAN )
155            printf( "scan directory %s\n", dir );
156
157        string_new( filename );
158        while( dirent = readdir( d ) )
159        {
160# ifdef old_sinix
161            /* Broken structure definition on sinix. */
162            f.f_base.ptr = dirent->d_name - 2;
163# else
164            f.f_base.ptr = dirent->d_name;
165# endif
166            f.f_base.len = strlen( f.f_base.ptr );
167
168            string_truncate( filename, 0 );
169            path_build( &f, filename, 0 );
170
171            (*func)( closure, filename->value, 0 /* not stat()'ed */, (time_t)0 );
172        }
173        string_free( filename );
174
175        closedir( d );
176}
177
178/*
179 * file_time() - get timestamp of file, if not done by file_dirscan()
180 */
181
182int
183file_time(
184        char    *filename,
185        time_t  *time )
186{
187        struct stat statbuf;
188
189        if( stat( filename, &statbuf ) < 0 )
190            return -1;
191
192    /* Technically, existing files can have 0 as statbuf.st_mtime
193       --- in particular, the /cygdrive directory under cygwin. However,
194       though all the code jam assumes that timestamp of 0 means
195       "does not exist" and will try to create the "missing" target, causing
196       problems. Work around this problem by chanding 0 to 1.
197    */
198        *time = statbuf.st_mtime ? statbuf.st_mtime : 1 ;
199        return 0;
200}
201
202int file_is_file(char* filename)
203{
204        struct stat statbuf;
205
206        if( stat( filename, &statbuf ) < 0 )
207            return -1;
208
209    if (S_ISREG(statbuf.st_mode)) 
210        return 1;
211    else
212        return 0;   
213}
214
215
216/*
217 * file_archscan() - scan an archive for files
218 */
219
220# ifndef AIAMAG /* God-fearing UNIX */
221
222# define SARFMAG 2
223# define SARHDR sizeof( struct ar_hdr )
224
225void
226file_archscan(
227        char *archive,
228        scanback func,
229        void *closure )
230{
231# ifndef NO_AR
232        struct ar_hdr ar_hdr;
233        char buf[ MAXJPATH ];
234        long offset;
235        char    *string_table = 0;
236        int fd;
237
238        if( ( fd = open( archive, O_RDONLY, 0 ) ) < 0 )
239            return;
240
241        if( read( fd, buf, SARMAG ) != SARMAG ||
242            strncmp( ARMAG, buf, SARMAG ) )
243        {
244            close( fd );
245            return;
246        }
247
248        offset = SARMAG;
249
250        if( DEBUG_BINDSCAN )
251            printf( "scan archive %s\n", archive );
252
253        while( read( fd, &ar_hdr, SARHDR ) == SARHDR
254               && ! ( memcmp( ar_hdr.ar_fmag, ARFMAG, SARFMAG )
255#ifdef ARFZMAG
256                      /* OSF also has a compressed format */
257                      && memcmp( ar_hdr.ar_fmag, ARFZMAG, SARFMAG )
258#endif
259              ) )
260        {
261            char    lar_name_[257];
262            char*   lar_name = lar_name_ + 1;
263            long    lar_date;
264            long    lar_size;
265            long    lar_offset;
266            char *c;
267            char    *src, *dest;
268
269            strncpy( lar_name, ar_hdr.ar_name, sizeof(ar_hdr.ar_name) );
270
271            sscanf( ar_hdr.ar_date, "%ld", &lar_date );
272            sscanf( ar_hdr.ar_size, "%ld", &lar_size );
273
274            if (ar_hdr.ar_name[0] == '/')
275            {
276                if (ar_hdr.ar_name[1] == '/')
277                {
278                    /* this is the "string table" entry of the symbol table,
279                    ** which holds strings of filenames that are longer than
280                    ** 15 characters (ie. don't fit into a ar_name
281                    */
282
283                    string_table = (char *)malloc(lar_size);
284                    lseek(fd, offset + SARHDR, 0);
285                    if (read(fd, string_table, lar_size) != lar_size)
286                        printf("error reading string table\n");
287                }
288                else if (string_table && ar_hdr.ar_name[1] != ' ')
289                {
290                    /* Long filenames are recognized by "/nnnn" where nnnn is
291                    ** the offset of the string in the string table represented
292                    ** in ASCII decimals.
293                    */
294                    dest = lar_name;
295                    lar_offset = atoi(lar_name + 1);
296                    src = &string_table[lar_offset];
297                    while (*src != '/')
298                        *dest++ = *src++;
299                    *dest = '/';
300                }
301            }
302
303            c = lar_name - 1;
304            while( *++c != ' ' && *c != '/' )
305                ;
306            *c = '\0';
307
308            if ( DEBUG_BINDSCAN )
309                printf( "archive name %s found\n", lar_name );
310
311            sprintf( buf, "%s(%s)", archive, lar_name );
312
313            (*func)( closure, buf, 1 /* time valid */, (time_t)lar_date );
314
315            offset += SARHDR + ( ( lar_size + 1 ) & ~1 );
316            lseek( fd, offset, 0 );
317        }
318
319        if (string_table)
320            free(string_table);
321
322        close( fd );
323
324# endif /* NO_AR */
325
326}
327
328# else /* AIAMAG - RS6000 AIX */
329
330static void file_archscan_small(
331    int fd, char const *archive, scanback func, void *closure)
332{
333    struct fl_hdr fl_hdr;
334
335    struct {
336        struct ar_hdr hdr;
337        char pad[ 256 ];
338    } ar_hdr ;
339
340    char buf[ MAXJPATH ];
341    long offset;
342
343    if( read( fd, (char *)&fl_hdr, FL_HSZ ) != FL_HSZ)
344        return;
345
346    sscanf( fl_hdr.fl_fstmoff, "%ld", &offset );
347 
348    if( DEBUG_BINDSCAN )
349        printf( "scan archive %s\n", archive );
350 
351    while( offset > 0
352           && lseek( fd, offset, 0 ) >= 0
353           && read( fd, &ar_hdr, sizeof( ar_hdr ) ) >= sizeof( ar_hdr.hdr ) )
354    {
355        long    lar_date;
356        int     lar_namlen;
357   
358        sscanf( ar_hdr.hdr.ar_namlen, "%d", &lar_namlen );
359        sscanf( ar_hdr.hdr.ar_date, "%ld", &lar_date );
360        sscanf( ar_hdr.hdr.ar_nxtmem, "%ld", &offset );
361   
362        if( !lar_namlen )
363            continue;
364     
365        ar_hdr.hdr._ar_name.ar_name[ lar_namlen ] = '\0';
366
367        sprintf( buf, "%s(%s)", archive, ar_hdr.hdr._ar_name.ar_name );
368
369        (*func)( closure, buf, 1 /* time valid */, (time_t)lar_date );
370    }
371}
372
373/* Check for OS version which supports the big variant. */
374#ifdef AR_HSZ_BIG
375
376static void file_archscan_big(
377    int fd, char const *archive, scanback func, void *closure)
378{
379    struct fl_hdr_big fl_hdr;
380
381    struct {
382        struct ar_hdr_big hdr;
383        char pad[ 256 ];
384    } ar_hdr ;
385
386    char buf[ MAXJPATH ];
387    long long offset;
388
389    if( read( fd, (char *)&fl_hdr, FL_HSZ_BIG) != FL_HSZ_BIG)
390        return;
391
392    sscanf( fl_hdr.fl_fstmoff, "%lld", &offset );
393
394    if( DEBUG_BINDSCAN )
395        printf( "scan archive %s\n", archive );
396
397    while( offset > 0
398           && lseek( fd, offset, 0 ) >= 0
399           && read( fd, &ar_hdr, sizeof( ar_hdr ) ) >= sizeof( ar_hdr.hdr ) )
400    {
401        long    lar_date;
402        int     lar_namlen;
403
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, "%lld", &offset );
407
408        if( !lar_namlen )
409            continue;
410
411        ar_hdr.hdr._ar_name.ar_name[ lar_namlen ] = '\0';
412
413        sprintf( buf, "%s(%s)", archive, ar_hdr.hdr._ar_name.ar_name );
414
415        (*func)( closure, buf, 1 /* time valid */, (time_t)lar_date );
416    }
417
418}
419
420#endif /* AR_HSZ_BIG */
421
422void file_archscan(char *archive, scanback func, void *closure)
423{
424    int fd;
425    char fl_magic[SAIAMAG];
426
427    if(( fd = open(archive, O_RDONLY, 0)) < 0)
428        return;
429 
430    if(read( fd, fl_magic, SAIAMAG) != SAIAMAG
431       || lseek(fd, 0, SEEK_SET) == -1)
432    {
433        close(fd);
434        return;
435    }
436
437    if (strncmp(AIAMAG, fl_magic, SAIAMAG) == 0)
438    {
439        /* read small variant */
440        file_archscan_small(fd, archive, func, closure);
441    }
442#ifdef AR_HSZ_BIG
443    else if (strncmp(AIAMAGBIG, fl_magic, SAIAMAG) == 0)
444    {
445        /* read big variant */
446        file_archscan_big(fd, archive, func, closure);
447    }
448#endif
449 
450    close( fd );
451}
452
453# endif /* AIAMAG - RS6000 AIX */
454
455# endif /* USE_FILEUNIX */
Note: See TracBrowser for help on using the repository browser.