📄 fileunix.c
字号:
/* * Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc. * * This file is part of Jam - see jam.c for Copyright information. *//* This file is ALSO: * Copyright 2001-2004 David Abrahams. * Copyright 2005 Rene Rivera. * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) */# include "jam.h"# include "filesys.h"# include "strings.h"# include "pathsys.h"# include "newstr.h"# include <stdio.h>#if defined(sun) || defined(__sun) || defined(linux)# include <unistd.h> /* needed for read and close prototype */#endif# ifdef USE_FILEUNIX#if defined(sun) || defined(__sun)# include <unistd.h> /* needed for read and close prototype */#endif# if defined( OS_SEQUENT ) || \ defined( OS_DGUX ) || \ defined( OS_SCO ) || \ defined( OS_ISC ) # define PORTAR 1# endif# ifdef __EMX__# include <sys/types.h># include <sys/stat.h># endif# if defined( OS_RHAPSODY ) || \ defined( OS_MACOSX ) || \ defined( OS_NEXT )/* need unistd for rhapsody's proper lseek */# include <sys/dir.h># include <unistd.h># define STRUCT_DIRENT struct direct # else# include <dirent.h># define STRUCT_DIRENT struct dirent # endif# ifdef OS_COHERENT# include <arcoff.h># define HAVE_AR# endif# if defined( OS_MVS ) || \ defined( OS_INTERIX )#define ARMAG "!<arch>\n"#define SARMAG 8#define ARFMAG "`\n"struct ar_hdr /* archive file member header - printable ascii */{ char ar_name[16]; /* file member name - `/' terminated */ char ar_date[12]; /* file member date - decimal */ char ar_uid[6]; /* file member user id - decimal */ char ar_gid[6]; /* file member group id - decimal */ char ar_mode[8]; /* file member mode - octal */ char ar_size[10]; /* file member size - decimal */ char ar_fmag[2]; /* ARFMAG - string to end header */};# define HAVE_AR# endif# if defined( OS_QNX ) || \ defined( OS_BEOS ) || \ defined( OS_MPEIX )# define NO_AR# define HAVE_AR# endif# ifndef HAVE_AR# ifdef OS_AIX/* Define those for AIX to get the definitions for both the small and the * big variant of the archive file format. */# define __AR_SMALL__# define __AR_BIG__# endif# include <ar.h># endif /* * fileunix.c - manipulate file names and scan directories on UNIX/AmigaOS * * External routines: * * file_dirscan() - scan a directory for files * file_time() - get timestamp of file, if not done by file_dirscan() * file_archscan() - scan an archive for files * * File_dirscan() and file_archscan() call back a caller provided function * for each file found. A flag to this callback function lets file_dirscan() * and file_archscan() indicate that a timestamp is being provided with the * file. If file_dirscan() or file_archscan() do not provide the file's * timestamp, interested parties may later call file_time(). * * 04/08/94 (seiwald) - Coherent/386 support added. * 12/19/94 (mikem) - solaris string table insanity support * 02/14/95 (seiwald) - parse and build /xxx properly * 05/03/96 (seiwald) - split into pathunix.c * 11/21/96 (peterk) - BEOS does not have Unix-style archives *//* * file_dirscan() - scan a directory for files */voidfile_dirscan( char *dir, scanback func, void *closure ){ PROFILE_ENTER(FILE_DIRSCAN); file_info_t * d = 0; d = file_query( dir ); if ( ! d || ! d->is_dir ) { PROFILE_EXIT(FILE_DIRSCAN); return; } if ( ! d->files ) { LIST* files = L0; PATHNAME f; DIR *dd; STRUCT_DIRENT *dirent; string filename[1]; /* First enter directory itself */ memset( (char *)&f, '\0', sizeof( f ) ); f.f_dir.ptr = dir; f.f_dir.len = strlen(dir); dir = *dir ? dir : "."; /* Now enter contents of directory */ if( !( dd = opendir( dir ) ) ) { PROFILE_EXIT(FILE_DIRSCAN); return; } if( DEBUG_BINDSCAN ) printf( "scan directory %s\n", dir ); string_new( filename ); while( dirent = readdir( dd ) ) { file_info_t * ff = 0; # ifdef old_sinix /* Broken structure definition on sinix. */ f.f_base.ptr = dirent->d_name - 2; # else f.f_base.ptr = dirent->d_name; # endif f.f_base.len = strlen( f.f_base.ptr ); string_truncate( filename, 0 ); path_build( &f, filename, 0 ); files = list_new( files, newstr(filename->value) ); file_query( filename->value ); } string_free( filename ); closedir( dd ); d->files = files; } /* Special case / : enter it */ { unsigned long len = strlen(d->name); if( len == 1 && d->name[0] == '/' ) (*func)( closure, d->name, 1 /* stat()'ed */, d->time ); } /* Now enter contents of directory */ if ( d->files ) { LIST * files = d->files; while ( files ) { file_info_t * ff = file_info( files->string ); (*func)( closure, ff->name, 1 /* stat()'ed */, ff->time ); files = list_next( files ); } } PROFILE_EXIT(FILE_DIRSCAN);}file_info_t * file_query( char * filename ){ file_info_t * ff = file_info( filename ); if ( ! ff->time ) { struct stat statbuf; if( stat( *filename ? filename : ".", &statbuf ) < 0 ) return 0; ff->is_file = statbuf.st_mode & S_IFREG ? 1 : 0; ff->is_dir = statbuf.st_mode & S_IFDIR ? 1 : 0; ff->size = statbuf.st_size; ff->time = statbuf.st_mtime ? statbuf.st_mtime : 1; } return ff;}/* * file_time() - get timestamp of file, if not done by file_dirscan() */intfile_time( char *filename, time_t *time ){ file_info_t * ff = file_query( filename ); if ( !ff ) return -1; *time = ff->time; return 0;}int file_is_file(char* filename){ file_info_t * ff = file_query( filename ); if ( !ff ) return -1; return ff->is_file;}/* * file_archscan() - scan an archive for files */# ifndef AIAMAG /* God-fearing UNIX */# define SARFMAG 2# define SARHDR sizeof( struct ar_hdr )voidfile_archscan( char *archive, scanback func, void *closure ){# ifndef NO_AR struct ar_hdr ar_hdr; char buf[ MAXJPATH ]; long offset; char *string_table = 0; int fd; if( ( fd = open( archive, O_RDONLY, 0 ) ) < 0 ) return; if( read( fd, buf, SARMAG ) != SARMAG || strncmp( ARMAG, buf, SARMAG ) ) { close( fd ); return; } offset = SARMAG; if( DEBUG_BINDSCAN ) printf( "scan archive %s\n", archive ); while( read( fd, &ar_hdr, SARHDR ) == SARHDR && ! ( memcmp( ar_hdr.ar_fmag, ARFMAG, SARFMAG )#ifdef ARFZMAG /* OSF also has a compressed format */ && memcmp( ar_hdr.ar_fmag, ARFZMAG, SARFMAG )#endif ) ) { char lar_name_[257]; char* lar_name = lar_name_ + 1; long lar_date; long lar_size; long lar_offset; char *c; char *src, *dest; strncpy( lar_name, ar_hdr.ar_name, sizeof(ar_hdr.ar_name) ); sscanf( ar_hdr.ar_date, "%ld", &lar_date ); sscanf( ar_hdr.ar_size, "%ld", &lar_size ); if (ar_hdr.ar_name[0] == '/') { if (ar_hdr.ar_name[1] == '/') { /* this is the "string table" entry of the symbol table, ** which holds strings of filenames that are longer than ** 15 characters (ie. don't fit into a ar_name */ string_table = (char *)BJAM_MALLOC_ATOMIC(lar_size); lseek(fd, offset + SARHDR, 0); if (read(fd, string_table, lar_size) != lar_size) printf("error reading string table\n"); } else if (string_table && ar_hdr.ar_name[1] != ' ') { /* Long filenames are recognized by "/nnnn" where nnnn is ** the offset of the string in the string table represented ** in ASCII decimals. */ dest = lar_name; lar_offset = atoi(lar_name + 1); src = &string_table[lar_offset]; while (*src != '/') *dest++ = *src++; *dest = '/'; } } c = lar_name - 1; while( *++c != ' ' && *c != '/' ) ; *c = '\0'; if ( DEBUG_BINDSCAN ) printf( "archive name %s found\n", lar_name ); sprintf( buf, "%s(%s)", archive, lar_name ); (*func)( closure, buf, 1 /* time valid */, (time_t)lar_date ); offset += SARHDR + ( ( lar_size + 1 ) & ~1 ); lseek( fd, offset, 0 ); } if (string_table) BJAM_FREE(string_table); close( fd );# endif /* NO_AR */}# else /* AIAMAG - RS6000 AIX */static void file_archscan_small( int fd, char const *archive, scanback func, void *closure){ struct fl_hdr fl_hdr; struct { struct ar_hdr hdr; char pad[ 256 ]; } ar_hdr ; char buf[ MAXJPATH ]; long offset; if( read( fd, (char *)&fl_hdr, FL_HSZ ) != FL_HSZ) return; sscanf( fl_hdr.fl_fstmoff, "%ld", &offset ); if( DEBUG_BINDSCAN ) printf( "scan archive %s\n", archive ); while( offset > 0 && lseek( fd, offset, 0 ) >= 0 && read( fd, &ar_hdr, sizeof( ar_hdr ) ) >= sizeof( ar_hdr.hdr ) ) { long lar_date; int lar_namlen; sscanf( ar_hdr.hdr.ar_namlen, "%d", &lar_namlen ); sscanf( ar_hdr.hdr.ar_date, "%ld", &lar_date ); sscanf( ar_hdr.hdr.ar_nxtmem, "%ld", &offset ); if( !lar_namlen ) continue; ar_hdr.hdr._ar_name.ar_name[ lar_namlen ] = '\0'; sprintf( buf, "%s(%s)", archive, ar_hdr.hdr._ar_name.ar_name ); (*func)( closure, buf, 1 /* time valid */, (time_t)lar_date ); }}/* Check for OS version which supports the big variant. */#ifdef AR_HSZ_BIGstatic void file_archscan_big( int fd, char const *archive, scanback func, void *closure){ struct fl_hdr_big fl_hdr; struct { struct ar_hdr_big hdr; char pad[ 256 ]; } ar_hdr ; char buf[ MAXJPATH ]; long long offset; if( read( fd, (char *)&fl_hdr, FL_HSZ_BIG) != FL_HSZ_BIG) return; sscanf( fl_hdr.fl_fstmoff, "%lld", &offset ); if( DEBUG_BINDSCAN ) printf( "scan archive %s\n", archive ); while( offset > 0 && lseek( fd, offset, 0 ) >= 0 && read( fd, &ar_hdr, sizeof( ar_hdr ) ) >= sizeof( ar_hdr.hdr ) ) { long lar_date; int lar_namlen; sscanf( ar_hdr.hdr.ar_namlen, "%d", &lar_namlen ); sscanf( ar_hdr.hdr.ar_date, "%ld", &lar_date ); sscanf( ar_hdr.hdr.ar_nxtmem, "%lld", &offset ); if( !lar_namlen ) continue; ar_hdr.hdr._ar_name.ar_name[ lar_namlen ] = '\0'; sprintf( buf, "%s(%s)", archive, ar_hdr.hdr._ar_name.ar_name ); (*func)( closure, buf, 1 /* time valid */, (time_t)lar_date ); }}#endif /* AR_HSZ_BIG */void file_archscan(char *archive, scanback func, void *closure){ int fd; char fl_magic[SAIAMAG]; if(( fd = open(archive, O_RDONLY, 0)) < 0) return; if(read( fd, fl_magic, SAIAMAG) != SAIAMAG || lseek(fd, 0, SEEK_SET) == -1) { close(fd); return; } if (strncmp(AIAMAG, fl_magic, SAIAMAG) == 0) { /* read small variant */ file_archscan_small(fd, archive, func, closure); }#ifdef AR_HSZ_BIG else if (strncmp(AIAMAGBIG, fl_magic, SAIAMAG) == 0) { /* read big variant */ file_archscan_big(fd, archive, func, closure); }#endif close( fd );}# endif /* AIAMAG - RS6000 AIX */# endif /* USE_FILEUNIX */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -