The Machine Perception Toolbox

[Introduction]- [News]- [Download]- [Screenshots]- [Manual (pdf)]- [Forums]- [API Reference]- [Repository ]

 

Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

fileunix.c

Go to the documentation of this file.
00001 /*
00002  * Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
00003  *
00004  * This file is part of Jam - see jam.c for Copyright information.
00005  */
00006 
00007 /*  This file is ALSO:
00008  *  (C) Copyright David Abrahams 2001. Permission to copy, use,
00009  *  modify, sell and distribute this software is granted provided this
00010  *  copyright notice appears in all copies. This software is provided
00011  *  "as is" without express or implied warranty, and with no claim as
00012  *  to its suitability for any purpose.
00013  */
00014 
00015 # include "jam.h"
00016 # include "filesys.h"
00017 # include "strings.h"
00018 # include "pathsys.h"
00019 # include <stdio.h>
00020 
00021 #if defined(sun) || defined(__sun)
00022 # include <unistd.h> // needed for read and close prototype
00023 #endif
00024 
00025 # ifdef USE_FILEUNIX
00026 
00027 #if defined(sun) || defined(__sun)
00028 # include <unistd.h> // needed for read and close prototype
00029 #endif
00030 
00031 # if defined( OS_SEQUENT ) || \
00032      defined( OS_DGUX ) || \
00033      defined( OS_SCO ) || \
00034      defined( OS_ISC ) 
00035 # define PORTAR 1
00036 # endif
00037 
00038 # ifdef __EMX__
00039 # include <sys/types.h>
00040 # include <sys/stat.h>
00041 # endif
00042 
00043 # if defined( OS_RHAPSODY ) || \
00044      defined( OS_MACOSX ) || \
00045      defined( OS_NEXT )
00046 /* need unistd for rhapsody's proper lseek */
00047 # include <sys/dir.h>
00048 # include <unistd.h>
00049 # define STRUCT_DIRENT struct direct 
00050 # else
00051 # include <dirent.h>
00052 # define STRUCT_DIRENT struct dirent 
00053 # endif
00054 
00055 # ifdef OS_COHERENT
00056 # include <arcoff.h>
00057 # define HAVE_AR
00058 # endif
00059 
00060 # if defined( OS_MVS ) || \
00061                  defined( OS_INTERIX )
00062 
00063 #define ARMAG   "!<arch>\n"
00064 #define SARMAG  8
00065 #define ARFMAG  "`\n"
00066 
00067 struct ar_hdr           /* archive file member header - printable ascii */
00068 {
00069         char    ar_name[16];    /* file member name - `/' terminated */
00070         char    ar_date[12];    /* file member date - decimal */
00071         char    ar_uid[6];      /* file member user id - decimal */
00072         char    ar_gid[6];      /* file member group id - decimal */
00073         char    ar_mode[8];     /* file member mode - octal */
00074         char    ar_size[10];    /* file member size - decimal */
00075         char    ar_fmag[2];     /* ARFMAG - string to end header */
00076 };
00077 
00078 # define HAVE_AR
00079 # endif
00080 
00081 # if defined( OS_QNX ) || \
00082      defined( OS_BEOS ) || \
00083      defined( OS_MPEIX )
00084 # define NO_AR
00085 # define HAVE_AR
00086 # endif
00087 
00088 # ifndef HAVE_AR
00089 
00090 # ifdef OS_AIX
00091 /* Define those for AIX to get the definitions for both the small and the
00092  * big variant of the archive file format. */
00093 #        define __AR_SMALL__
00094 #        define __AR_BIG__
00095 # endif
00096 
00097 # include <ar.h>
00098 # endif 
00099 
00100 /*
00101  * fileunix.c - manipulate file names and scan directories on UNIX/AmigaOS
00102  *
00103  * External routines:
00104  *
00105  *      file_dirscan() - scan a directory for files
00106  *      file_time() - get timestamp of file, if not done by file_dirscan()
00107  *      file_archscan() - scan an archive for files
00108  *
00109  * File_dirscan() and file_archscan() call back a caller provided function
00110  * for each file found.  A flag to this callback function lets file_dirscan()
00111  * and file_archscan() indicate that a timestamp is being provided with the
00112  * file.   If file_dirscan() or file_archscan() do not provide the file's
00113  * timestamp, interested parties may later call file_time().
00114  *
00115  * 04/08/94 (seiwald) - Coherent/386 support added.
00116  * 12/19/94 (mikem) - solaris string table insanity support
00117  * 02/14/95 (seiwald) - parse and build /xxx properly
00118  * 05/03/96 (seiwald) - split into pathunix.c
00119  * 11/21/96 (peterk) - BEOS does not have Unix-style archives
00120  */
00121 
00122 /*
00123  * file_dirscan() - scan a directory for files
00124  */
00125 
00126 void
00127 file_dirscan( 
00128         char *dir,
00129         scanback func,
00130         void *closure )
00131 {
00132         PATHNAME f;
00133         DIR *d;
00134         STRUCT_DIRENT *dirent;
00135         string filename[1];
00136 
00137         /* First enter directory itself */
00138 
00139         memset( (char *)&f, '\0', sizeof( f ) );
00140 
00141         f.f_dir.ptr = dir;
00142         f.f_dir.len = strlen(dir);
00143 
00144         dir = *dir ? dir : ".";
00145 
00146         /* Special case / : enter it */
00147 
00148         if( f.f_dir.len == 1 && f.f_dir.ptr[0] == '/' )
00149             (*func)( closure, dir, 0 /* not stat()'ed */, (time_t)0 );
00150 
00151         /* Now enter contents of directory */
00152 
00153         if( !( d = opendir( dir ) ) )
00154             return;
00155 
00156         if( DEBUG_BINDSCAN )
00157             printf( "scan directory %s\n", dir );
00158 
00159         string_new( filename );
00160         while( dirent = readdir( d ) )
00161         {
00162 # ifdef old_sinix
00163             /* Broken structure definition on sinix. */
00164             f.f_base.ptr = dirent->d_name - 2;
00165 # else
00166             f.f_base.ptr = dirent->d_name;
00167 # endif
00168             f.f_base.len = strlen( f.f_base.ptr );
00169 
00170             string_truncate( filename, 0 );
00171             path_build( &f, filename, 0 );
00172 
00173             (*func)( closure, filename->value, 0 /* not stat()'ed */, (time_t)0 );
00174         }
00175         string_free( filename );
00176 
00177         closedir( d );
00178 }
00179 
00180 /*
00181  * file_time() - get timestamp of file, if not done by file_dirscan()
00182  */
00183 
00184 int
00185 file_time(
00186         char    *filename,
00187         time_t  *time )
00188 {
00189         struct stat statbuf;
00190 
00191         if( stat( filename, &statbuf ) < 0 )
00192             return -1;
00193 
00194     /* Technically, existing files can have 0 as statbuf.st_mtime 
00195        --- in particular, the /cygdrive directory under cygwin. However, 
00196        though all the code jam assumes that timestamp of 0 means
00197        "does not exist" and will try to create the "missing" target, causing
00198        problems. Work around this problem by chanding 0 to 1.
00199     */
00200         *time = statbuf.st_mtime ? statbuf.st_mtime : 1 ;
00201         return 0;
00202 }
00203 
00204 /*
00205  * file_archscan() - scan an archive for files
00206  */
00207 
00208 # ifndef AIAMAG /* God-fearing UNIX */
00209 
00210 # define SARFMAG 2
00211 # define SARHDR sizeof( struct ar_hdr )
00212 
00213 void
00214 file_archscan(
00215         char *archive,
00216         scanback func,
00217         void *closure )
00218 {
00219 # ifndef NO_AR
00220         struct ar_hdr ar_hdr;
00221         char buf[ MAXJPATH ];
00222         long offset;
00223         char    *string_table = 0;
00224         int fd;
00225 
00226         if( ( fd = open( archive, O_RDONLY, 0 ) ) < 0 )
00227             return;
00228 
00229         if( read( fd, buf, SARMAG ) != SARMAG ||
00230             strncmp( ARMAG, buf, SARMAG ) )
00231         {
00232             close( fd );
00233             return;
00234         }
00235 
00236         offset = SARMAG;
00237 
00238         if( DEBUG_BINDSCAN )
00239             printf( "scan archive %s\n", archive );
00240 
00241         while( read( fd, &ar_hdr, SARHDR ) == SARHDR &&
00242                !memcmp( ar_hdr.ar_fmag, ARFMAG, SARFMAG ) )
00243         {
00244             char    lar_name_[257];
00245             char*   lar_name = lar_name_ + 1;
00246             long    lar_date;
00247             long    lar_size;
00248             long    lar_offset;
00249             char *c;
00250             char    *src, *dest;
00251 
00252             strncpy( lar_name, ar_hdr.ar_name, sizeof(ar_hdr.ar_name) );
00253 
00254             sscanf( ar_hdr.ar_date, "%ld", &lar_date );
00255             sscanf( ar_hdr.ar_size, "%ld", &lar_size );
00256 
00257             if (ar_hdr.ar_name[0] == '/')
00258             {
00259                 if (ar_hdr.ar_name[1] == '/')
00260                 {
00261                     /* this is the "string table" entry of the symbol table,
00262                     ** which holds strings of filenames that are longer than
00263                     ** 15 characters (ie. don't fit into a ar_name
00264                     */
00265 
00266                     string_table = (char *)malloc(lar_size);
00267                     lseek(fd, offset + SARHDR, 0);
00268                     if (read(fd, string_table, lar_size) != lar_size)
00269                         printf("error reading string table\n");
00270                 }
00271                 else if (string_table && ar_hdr.ar_name[1] != ' ')
00272                 {
00273                     /* Long filenames are recognized by "/nnnn" where nnnn is
00274                     ** the offset of the string in the string table represented
00275                     ** in ASCII decimals.
00276                     */
00277                     dest = lar_name;
00278                     lar_offset = atoi(lar_name + 1);
00279                     src = &string_table[lar_offset];
00280                     while (*src != '/')
00281                         *dest++ = *src++;
00282                     *dest = '/';
00283                 }
00284             }
00285 
00286             c = lar_name - 1;
00287             while( *++c != ' ' && *c != '/' )
00288                 ;
00289             *c = '\0';
00290 
00291             if ( DEBUG_BINDSCAN )
00292                 printf( "archive name %s found\n", lar_name );
00293 
00294             sprintf( buf, "%s(%s)", archive, lar_name );
00295 
00296             (*func)( closure, buf, 1 /* time valid */, (time_t)lar_date );
00297 
00298             offset += SARHDR + ( ( lar_size + 1 ) & ~1 );
00299             lseek( fd, offset, 0 );
00300         }
00301 
00302         if (string_table)
00303             free(string_table);
00304 
00305         close( fd );
00306 
00307 # endif /* NO_AR */
00308 
00309 }
00310 
00311 # else /* AIAMAG - RS6000 AIX */
00312 
00313 static void file_archscan_small(
00314     int fd, char const *archive, scanback func, void *closure)
00315 {
00316     struct fl_hdr fl_hdr;
00317 
00318     struct {
00319         struct ar_hdr hdr;
00320         char pad[ 256 ];
00321     } ar_hdr ;
00322 
00323     char buf[ MAXJPATH ];
00324     long offset;
00325 
00326     if( read( fd, (char *)&fl_hdr, FL_HSZ ) != FL_HSZ)
00327         return;
00328 
00329     sscanf( fl_hdr.fl_fstmoff, "%ld", &offset );
00330   
00331     if( DEBUG_BINDSCAN )
00332         printf( "scan archive %s\n", archive );
00333   
00334     while( offset > 0
00335            && lseek( fd, offset, 0 ) >= 0
00336            && read( fd, &ar_hdr, sizeof( ar_hdr ) ) >= sizeof( ar_hdr.hdr ) )
00337     {
00338         long    lar_date;
00339         int     lar_namlen;
00340     
00341         sscanf( ar_hdr.hdr.ar_namlen, "%d", &lar_namlen );
00342         sscanf( ar_hdr.hdr.ar_date, "%ld", &lar_date );
00343         sscanf( ar_hdr.hdr.ar_nxtmem, "%ld", &offset );
00344     
00345         if( !lar_namlen )
00346             continue;
00347       
00348         ar_hdr.hdr._ar_name.ar_name[ lar_namlen ] = '\0';
00349 
00350         sprintf( buf, "%s(%s)", archive, ar_hdr.hdr._ar_name.ar_name );
00351 
00352         (*func)( closure, buf, 1 /* time valid */, (time_t)lar_date );
00353     }
00354 }
00355 
00356 /* Check for OS version which supports the big variant. */
00357 #ifdef AR_HSZ_BIG
00358 
00359 static void file_archscan_big(
00360     int fd, char const *archive, scanback func, void *closure)
00361 {
00362     struct fl_hdr_big fl_hdr;
00363 
00364     struct {
00365         struct ar_hdr_big hdr;
00366         char pad[ 256 ];
00367     } ar_hdr ;
00368 
00369     char buf[ MAXJPATH ];
00370     long long offset;
00371 
00372     if( read( fd, (char *)&fl_hdr, FL_HSZ_BIG) != FL_HSZ_BIG)
00373         return;
00374 
00375     sscanf( fl_hdr.fl_fstmoff, "%lld", &offset );
00376 
00377     if( DEBUG_BINDSCAN )
00378         printf( "scan archive %s\n", archive );
00379 
00380     while( offset > 0
00381            && lseek( fd, offset, 0 ) >= 0
00382            && read( fd, &ar_hdr, sizeof( ar_hdr ) ) >= sizeof( ar_hdr.hdr ) )
00383     {
00384         long    lar_date;
00385         int     lar_namlen;
00386 
00387         sscanf( ar_hdr.hdr.ar_namlen, "%d", &lar_namlen );
00388         sscanf( ar_hdr.hdr.ar_date, "%ld", &lar_date );
00389         sscanf( ar_hdr.hdr.ar_nxtmem, "%lld", &offset );
00390 
00391         if( !lar_namlen )
00392             continue;
00393 
00394         ar_hdr.hdr._ar_name.ar_name[ lar_namlen ] = '\0';
00395 
00396         sprintf( buf, "%s(%s)", archive, ar_hdr.hdr._ar_name.ar_name );
00397 
00398         (*func)( closure, buf, 1 /* time valid */, (time_t)lar_date );
00399     }
00400 
00401 }
00402 
00403 #endif /* AR_HSZ_BIG */
00404 
00405 void file_archscan(char *archive, scanback func, void *closure)
00406 {
00407     int fd;
00408     char fl_magic[SAIAMAG];
00409 
00410     if(( fd = open(archive, O_RDONLY, 0)) < 0)
00411         return;
00412   
00413     if(read( fd, fl_magic, SAIAMAG) != SAIAMAG
00414        || lseek(fd, 0, SEEK_SET) == -1)
00415     {
00416         close(fd);
00417         return;
00418     }
00419 
00420     if (strncmp(AIAMAG, fl_magic, SAIAMAG) == 0)
00421     {
00422         /* read small variant */
00423         file_archscan_small(fd, archive, func, closure);
00424     }
00425 #ifdef AR_HSZ_BIG
00426     else if (strncmp(AIAMAGBIG, fl_magic, SAIAMAG) == 0)
00427     {
00428         /* read big variant */
00429         file_archscan_big(fd, archive, func, closure);
00430     }
00431 #endif
00432   
00433     close( fd );
00434 }
00435 
00436 # endif /* AIAMAG - RS6000 AIX */
00437 
00438 # endif /* USE_FILEUNIX */

Generated on Mon Nov 8 17:07:34 2004 for MPT by  doxygen 1.3.9.1