diff options
author | abs <abs@pkgsrc.org> | 2012-07-13 21:09:43 +0000 |
---|---|---|
committer | abs <abs@pkgsrc.org> | 2012-07-13 21:09:43 +0000 |
commit | 86aaa572f624f66b8a6694bce9f57720e69ca076 (patch) | |
tree | 51e2d510f927bcea4e02ee61c0d48fcf1228155c /pkgtools | |
parent | f49f73ec1d78f8bebc6221a3c500426e44b8944b (diff) | |
download | pkgsrc-86aaa572f624f66b8a6694bce9f57720e69ca076.tar.gz |
lintpkgsrc files do not belong here. One could argue that a description of
where they do belong would be unsuitable for polite conversation, but that
is not the goal today...
Diffstat (limited to 'pkgtools')
-rw-r--r-- | pkgtools/pkglint/files/lintpkgsrc.0 | 131 | ||||
-rw-r--r-- | pkgtools/pkglint/files/lintpkgsrc.1 | 194 | ||||
-rwxr-xr-x | pkgtools/pkglint/files/lintpkgsrc.pl | 1833 |
3 files changed, 0 insertions, 2158 deletions
diff --git a/pkgtools/pkglint/files/lintpkgsrc.0 b/pkgtools/pkglint/files/lintpkgsrc.0 deleted file mode 100644 index 9ee45180428..00000000000 --- a/pkgtools/pkglint/files/lintpkgsrc.0 +++ /dev/null @@ -1,131 +0,0 @@ -LINTPKGSRC(1) NetBSD General Commands Manual LINTPKGSRC(1) - -NNAAMMEE - lliinnttppkkggssrrcc -- verifier for the pkgsrc tree - -SSYYNNOOPPSSIISS - lliinnttppkkggssrrcc [--BBDDLLOORRSSVVddhhiillmmoopprruu] [--EE _f_i_l_e] [--gg _p_k_g_s_r_c_m_a_p] [--II _f_i_l_e] - [--KK _P_A_C_K_A_G_E_S] [--MM _D_I_S_T_D_I_R] [--PP _P_K_G_S_R_C_D_I_R] [_m_a_k_e_f_i_l_e _._._.] - -DDEESSCCRRIIPPTTIIOONN - lliinnttppkkggssrrcc tries to verify the entire contents of the pkgsrc tree. - lliinnttppkkggssrrcc uses simple regular-expression matching for verifying files - that make up a pkgsrc directory. Note that it does NOT implement com- - plete Makefile parser. - - OOppttiioonnss - --BB List packages marked as BROKEN. - - --DD _p_a_t_h_s Parse Makefiles and output contents (useful for debugging). - - --dd Extract the `DEPENDS' listing from each pkgsrc package - Makefile, then verify the version specified in each DEPEND - correctly matches a current pkgsrc package. - - --EE _f_i_l_e Exports the internal database generated from the pkgsrc - Makefiles to a file for faster loading at a later time. - Note that some of the stored data is, in all likelihood, - dependent on the architecture and operating system of the - machine where it is generated. However, the database does - make the task of, eg, checking for out of date packages on - a set of similarly configured machines (in the absence of - extra copies of the pkgsrc tree) both quick and possible. - - --gg _p_k_g_s_r_c_m_a_p Generate pkgsrcmap file containing an entry for each pack- - age of `pkgname pkgdir pkgver'. - - --hh Basic help and usage. - - --II _f_i_l_e Imports the data to construct the internal database for - checking the installed versions of packages, among other - things, against the current version found in pkgsrc. This - database provides most or all of the data required for run- - ning lliinnttppkkggssrrcc with any combination of --BB, --OO, --RR, --SS, --VV, - --dd, --gg, --ii, --pp, or --uu. - - --ii Check the version of each installed package against the - current version in pkgsrc. - - --KK _P_A_C_K_A_G_E_S Override binary packages base directory, normally set from - _/_e_t_c_/_m_k_._c_o_n_f or defaulted to _$_{_P_K_G_S_R_C_D_I_R_}_/_p_a_c_k_a_g_e_s. - - Note: lintpkgsrc treats _P_A_C_K_A_G_E_S slightly differently to - the pkgsrc build system. --pp, --RR and --VV check for binary - packages in any depth of PACKAGES subdirs - this allows - packages for all architectures/OS versions to be checked - simultaneously with an _/_e_t_c_/_m_k_._c_o_n_f construct of the form: - - .ifdef LINTPKGSRC - PACKAGES=${PKGSRCDIR}/packages - .else - PACKAGES=${PKGSRCDIR}/packages/${OS_VERSION}/${MACHINE_ARCH} - .endif - - Which would be an alternative to --KK. - - --LL List the filenames of Makefiles as they are parsed (for - debugging). - - --MM _D_I_S_T_D_I_R Set directory for distfiles, defaults to - _$_{_P_K_G_S_R_C_D_I_R_}_/_d_i_s_t_f_i_l_e_s. - - --mm For each current distfile, verify its checksum against the - appropriate package's distinfo file. Also report if any - package's distinfo file references the same distfile with a - different distinfo checksum. - - --OO Report any binary packages in any subdirs of _P_A_C_K_A_G_E_S, for - whom the source Makefile lists _O_S_V_E_R_S_I_O_N___S_P_E_C_I_F_I_C. This is - intended to help those making binary packages available for - ftp. - - --oo Report any old distfiles (not referenced by any package's - distinfo file). - - --PP _P_K_G_S_R_C_D_I_R Set base of pkgsrc tree, normally set from _/_e_t_c_/_m_k_._c_o_n_f or - defaulted to _/_u_s_r_/_p_k_g_s_r_c. - - --pp Report any old binary packages in any subdirs of _P_A_C_K_A_G_E_S. - - --RR Report any binary packages in any subdirs of _P_A_C_K_A_G_E_S, for - whom the source Makefile lists _N_O___B_I_N___O_N___F_T_P or _R_E_S_T_R_I_C_T_E_D. - This is intended to help those making binary packages - available for ftp. - - --rr Remove distfiles which are not referenced from any pack- - age's distinfo file, or have an incorrect checksum (usually - due to an interrupted download), and any old binary pack- - ages. To remove any given type, additionally specify the - --oo, --mm, or --pp flags respectively. - - --SS List packages missing from category _S_U_B_D_I_R lists. - - --uu As --ii plus for mismatched packages, display REQUIRED - details and run `@MAKE@ fetch-list | sh' to ensure all the - distfiles needed for the latest version are present. - - Warning: The behaviour of this command may change in a - later version. - - --VV List any prebuilt packages in any subdirs of _P_A_C_K_A_G_E_S with - known vulnerabilities, based on the data in - _$_{_P_K_G_S_R_C_D_I_R_}_/_d_i_s_t_f_i_l_e_s_/_p_k_g_-_v_u_l_n_e_r_a_b_i_l_i_t_i_e_s. - -AAUUTTHHOORRSS - David Brownlee <abs@netbsd.org> - -BBUUGGSS - The --RR, --VV, and --pp options default to using _P_A_C_K_A_G_E_S as the base direc- - tory from which to search for binary packages. If this includes OS or - architecture information then packages for other OS/architecture combina- - tions will be missed. In this case _P_A_C_K_A_G_E_S can be overridden with --KK or - set conditionally in _/_e_t_c_/_m_k_._c_o_n_f based on the value of _L_I_N_T_P_K_G_S_R_C. - - The `Makefile parsing' algorithm used to obtain package versions and - DEPENDS information is geared towards speed rather than perfection, - though it has got somewhat better over time, it only parses the simplest - Makefile conditionals. (a == b, no && etc). - - Potentially others, but non serious to date. - -pkgsrc November 8, 2005 pkgsrc diff --git a/pkgtools/pkglint/files/lintpkgsrc.1 b/pkgtools/pkglint/files/lintpkgsrc.1 deleted file mode 100644 index 2cb3c491afa..00000000000 --- a/pkgtools/pkglint/files/lintpkgsrc.1 +++ /dev/null @@ -1,194 +0,0 @@ -.\" $NetBSD: lintpkgsrc.1,v 1.29 2006/07/30 00:22:18 wiz Exp $ -.\" -.\" Copyright (c) 1999 by David Brownlee (abs@netbsd.org) -.\" Absolutely no warranty. -.\" -.Dd November 8, 2005 -.Dt LINTPKGSRC 1 -.Sh NAME -.Nm lintpkgsrc -.Nd verifier for the pkgsrc tree -.Sh SYNOPSIS -.Nm -.Op Fl BDLORSVdhilmopru -.Op Fl E Ar file -.Op Fl g Ar pkgsrcmap -.Op Fl I Ar file -.Op Fl K Ar PACKAGES -.Op Fl M Ar DISTDIR -.Op Fl P Ar PKGSRCDIR -.Op Pa makefile ... -.Sh DESCRIPTION -.Nm -tries to verify the entire contents of the pkgsrc tree. -.Nm -uses simple regular-expression matching for verifying -files that make up a pkgsrc directory. -Note that it does NOT implement complete Makefile parser. -.Ss Options -.Bl -tag -width xxxxxxxxxxxx -.It Fl B -List packages marked as BROKEN. -.It Fl D Ar paths -Parse Makefiles and output contents (useful for debugging). -.It Fl d -Extract the -.Ql DEPENDS -listing from each pkgsrc package Makefile, then -verify the version specified in each DEPEND correctly matches a current -pkgsrc package. -.It Fl E Ar file -Exports the internal database generated from the pkgsrc Makefiles to a -file for faster loading at a later time. -Note that some of the stored data is, in all likelihood, dependent on -the architecture and operating system of the machine where it is -generated. -However, the database does make the task of, eg, checking for out of -date packages on a set of similarly configured machines (in the -absence of extra copies of the pkgsrc tree) both quick and possible. -.It Fl g Ar pkgsrcmap -Generate pkgsrcmap file containing an entry for each package of -.Ql pkgname pkgdir pkgver . -.It Fl h -Basic help and usage. -.It Fl I Ar file -Imports the data to construct the internal database for checking the -installed versions of packages, among other things, against the -current version found in pkgsrc. -This database provides most or all of the data required for running -.Nm -with any combination of -.Fl B , -.Fl O , -.Fl R , -.Fl S , -.Fl V , -.Fl d , -.Fl g , -.Fl i , -.Fl p , -or -.Fl u . -.It Fl i -Check the version of each installed package against the current version in -pkgsrc. -.It Fl K Ar PACKAGES -Override binary packages base directory, normally set from -.Pa /etc/mk.conf -or defaulted to -.Pa ${PKGSRCDIR}/packages . -.Pp -Note: lintpkgsrc treats -.Em PACKAGES -slightly differently to the pkgsrc build system. -.Fl p , -.Fl R -and -.Fl V -check for -binary packages in any depth of PACKAGES subdirs - this allows packages for all -architectures/OS versions to be checked simultaneously with an -.Pa /etc/mk.conf -construct of the form: -.Bd -literal -\&.ifdef LINTPKGSRC -PACKAGES=${PKGSRCDIR}/packages -\&.else -PACKAGES=${PKGSRCDIR}/packages/${OS_VERSION}/${MACHINE_ARCH} -\&.endif -.Ed -.Pp -Which would be an alternative to -.Fl K . -.It Fl L -List the filenames of Makefiles as they are parsed (for debugging). -.It Fl M Ar DISTDIR -Set directory for distfiles, defaults to -.Pa ${PKGSRCDIR}/distfiles . -.It Fl m -For each current distfile, verify its checksum against the appropriate -package's distinfo file. Also report if any package's distinfo file references -the same distfile with a different distinfo checksum. -.It Fl O -Report any binary packages in any subdirs of -.Em PACKAGES , -for whom the source Makefile lists -.Em OSVERSION_SPECIFIC . -This is intended to help those making binary packages available for ftp. -.It Fl o -Report any old distfiles (not referenced by any package's distinfo file). -.It Fl P Ar PKGSRCDIR -Set base of pkgsrc tree, normally set from -.Pa /etc/mk.conf -or defaulted to -.Pa /usr/pkgsrc . -.It Fl p -Report any old binary packages in any subdirs of -.Em PACKAGES . -.It Fl R -Report any binary packages in any subdirs of -.Em PACKAGES , -for whom the source Makefile lists -.Em NO_BIN_ON_FTP -or -.Em RESTRICTED . -This is intended to help those making binary packages available for ftp. -.It Fl r -Remove distfiles which are not referenced from any package's distinfo file, -or have an incorrect checksum (usually due to an interrupted download), -and any old binary packages. To remove any given type, additionally -specify the -.Fl o , -.Fl m , -or -.Fl p -flags respectively. -.It Fl S -List packages missing from category -.Em SUBDIR -lists. -.It Fl u -As -.Fl i -plus for mismatched packages, display REQUIRED details and run -.Ql @MAKE@ fetch-list | sh -to ensure all the distfiles needed for -the latest version are present. -.Pp -Warning: The behaviour of this command may change in a later version. -.It Fl V -List any prebuilt packages in any subdirs of -.Em PACKAGES -with known vulnerabilities, based on the data in -.Pa ${PKGSRCDIR}/distfiles/pkg-vulnerabilities . -.El -.Sh AUTHORS -.An David Brownlee Aq abs@netbsd.org -.Sh BUGS -The -.Fl R , -.Fl V , -and -.Fl p -options default to using -.Em PACKAGES -as the base directory from which to -search for binary packages. If this includes OS or architecture information -then packages for other OS/architecture combinations will be missed. -In this case -.Em PACKAGES -can be overridden with -.Fl K -or set conditionally in -.Pa /etc/mk.conf -based on the value of -.Em LINTPKGSRC . -.Pp -The -.Ql Makefile parsing -algorithm used to obtain package versions -and DEPENDS information is geared towards speed rather than -perfection, though it has got somewhat better over time, it only -parses the simplest Makefile conditionals. (a == b, no \*[Am]\*[Am] etc). -.Pp -Potentially others, but non serious to date. diff --git a/pkgtools/pkglint/files/lintpkgsrc.pl b/pkgtools/pkglint/files/lintpkgsrc.pl deleted file mode 100755 index eb9aeb4afea..00000000000 --- a/pkgtools/pkglint/files/lintpkgsrc.pl +++ /dev/null @@ -1,1833 +0,0 @@ -#! @PERL@ - -# $NetBSD: lintpkgsrc.pl,v 1.116 2012/05/08 23:11:48 sbd Exp $ - -# Written by David Brownlee <abs@netbsd.org>. -# -# Caveats: -# The 'Makefile parsing' algorithm used to obtain package versions and -# DEPENDS information is geared towards speed rather than perfection, -# though it has gotten somewhat better over time, it only parses the -# simpler Makefile conditionals. -# -# TODO: Handle fun DEPENDS like avifile-devel with -# {qt2-designer>=2.2.4,qt2-designer-kde>=2.3.1nb1} - -$^W = 1; -use locale; -use strict; -use Getopt::Std; -use File::Find; -use File::Basename; -use IPC::Open3; -use Cwd 'realpath', 'getcwd'; - -# Buildtime configuration -my $conf_make = '@MAKE@'; -my $conf_pkgsrcdir = '@PKGSRCDIR@'; -my $conf_prefix = '@PREFIX@'; - -my ( - $pkglist, # list of Pkg packages - $pkg_installver, # installed version of pkg_install pseudo-pkg - $default_vars, # Set for Makefiles, inc PACKAGES & PKGSRCDIR - %opt, # Command line options - %vuln, # vulnerability data - @matched_prebuiltpackages, # List of obsolete prebuilt package paths - @prebuilt_pkgdirs, # Use to follow symlinks in prebuilt pkgdirs - %prebuilt_pkgdir_cache, # To avoid symlink loops in prebuilt_pkgdirs -); - -$ENV{PATH} .= - ":/bin:/usr/bin:/sbin:/usr/sbin:${conf_prefix}/sbin:${conf_prefix}/bin"; - -if ( - !getopts( 'BDE:I:K:LM:OP:RSVdg:himopru', \%opt ) - || $opt{h} - || !( - defined $opt{d} - || defined $opt{g} - || defined $opt{i} - || defined $opt{m} - || defined $opt{o} - || defined $opt{p} - || defined $opt{r} - || defined $opt{u} - || defined $opt{B} - || defined $opt{D} - || defined $opt{R} - || defined $opt{O} - || defined $opt{S} - || defined $opt{V} - || defined $opt{E} - ) - ) -{ - - usage_and_exit(); -} -$| = 1; - -# Horrible kludge to ensure we have a value for testing in conditionals, but -# gets removed in the final evaluation -my $magic_undefined = 'M_a_G_i_C_UNDEFINED'; - -get_default_makefile_vars(); # $default_vars - -if ( $opt{D} && @ARGV ) { - foreach my $file (@ARGV) { - if ( -d $file ) { - $file .= "/Makefile"; - } - if ( !-f $file ) { - fail("No such file: $file"); - } - my ( $pkgname, $vars ) = parse_makefile_pkgsrc($file); - $pkgname ||= 'UNDEFINED'; - print "$file -> $pkgname\n"; - foreach my $varname ( sort keys %{$vars} ) { - print "\t$varname = $vars->{$varname}\n"; - } - - #if ($opt{d}) { - # pkgsrc_check_depends(); - #} - } - exit; -} - -sub main() { - my ( $pkgsrcdir, $pkgdistdir ); - - $pkgsrcdir = $default_vars->{PKGSRCDIR}; - $pkgdistdir = $default_vars->{DISTDIR}; - - if ( $opt{r} && !$opt{o} && !$opt{m} && !$opt{p} ) { - $opt{o} = $opt{m} = $opt{p} = 1; - } - if ( $opt{o} || $opt{m} ) { - my (@baddist); - - @baddist = - scan_pkgsrc_distfiles_vs_distinfo( $pkgsrcdir, $pkgdistdir, $opt{o}, - $opt{m} ); - if ( $opt{r} ) { - verbose("Unlinking 'bad' distfiles\n"); - foreach my $distfile (@baddist) { - unlink("$pkgdistdir/$distfile"); - } - } - } - - # List BROKEN packages - if ( $opt{B} ) { - scan_pkgsrc_makefiles($pkgsrcdir); - foreach my $pkgver ( $pkglist->pkgver ) { - $pkgver->var('BROKEN') || next; - print $pkgver->pkgname . ': ' . $pkgver->var('BROKEN') . "\n"; - } - } - - # List obsolete or NO_BIN_ON_FTP/RESTRICTED prebuilt packages - # - if ( $opt{p} || $opt{O} || $opt{R} || $opt{V} ) { - if ( $opt{V} ) { - my ($vuln) = "$pkgdistdir/pkg-vulnerabilities"; - - if ( !open( VULN, $vuln ) ) { - fail("Unable to open '$vuln': $!"); - } - while (<VULN>) { - s/#.*//; - if (/([^*?[]+)(<|>|<=|>=)(\d\S+)/) { - my ( $pkg, $cmp, $ver ) = ( $1, $2, $3 ); - push( @{ $vuln{$pkg} }, "$cmp $ver" ); - } - } - close(VULN); - } - - if ( $opt{p} || $opt{O} || $opt{R} || $opt{V} ) { - scan_pkgsrc_makefiles($pkgsrcdir); - } - @prebuilt_pkgdirs = ( $default_vars->{PACKAGES} ); - %prebuilt_pkgdir_cache = (); - - while (@prebuilt_pkgdirs) { - find( \&check_prebuilt_packages, shift @prebuilt_pkgdirs ); - } - - if ( $opt{r} ) { - verbose("Unlinking listed prebuiltpackages\n"); - foreach my $pkgfile (@matched_prebuiltpackages) { - unlink($pkgfile); - } - } - } - - if ( $opt{S} ) { - my (%in_subdir); - - foreach my $cat ( list_pkgsrc_categories($pkgsrcdir) ) { - my $vars = parse_makefile_vars("$pkgsrcdir/$cat/Makefile"); - - if ( !$vars->{SUBDIR} ) { - print "Warning - no SUBDIR for $cat\n"; - next; - } - foreach my $pkgdir ( split( /\s+/, $vars->{SUBDIR} ) ) { - $in_subdir{"$cat/$pkgdir"} = 1; - } - } - - scan_pkgsrc_makefiles($pkgsrcdir); - foreach my $pkgver ( $pkglist->pkgver ) { - if ( !defined $in_subdir{ $pkgver->var('dir') } ) { - print $pkgver->var('dir') . ": Not in SUBDIR\n"; - } - } - } - - if ( $opt{g} ) { - my $tmpfile = "$opt{g}.tmp.$$"; - - scan_pkgsrc_makefiles($pkgsrcdir); - if ( !open( TABLE, ">$tmpfile" ) ) { - fail("Unable to write '$tmpfile': $!"); - } - foreach my $pkgver ( $pkglist->pkgver ) { - print TABLE $pkgver->pkg . "\t" - . $pkgver->var('dir') . "\t" - . $pkgver->ver . "\n"; - } - if ( !close(TABLE) ) { - fail("Error while writing '$tmpfile': $!"); - } - if ( !rename( $tmpfile, $opt{g} ) ) { - fail("Error in rename('$tmpfile','$opt{g}'): $!"); - } - } - - if ( $opt{d} ) { - scan_pkgsrc_makefiles($pkgsrcdir); - pkgsrc_check_depends(); - } - - if ( $opt{i} || $opt{u} ) { - my ( @pkgs, @update ); - - @pkgs = list_installed_packages(); - scan_pkgsrc_makefiles($pkgsrcdir); - - foreach my $pkgname ( sort @pkgs ) { - if ( $_ = invalid_version($pkgname) ) { - print $_; - - if ( $pkgname =~ /^([^*?[]+)-([\d*?[].*)/ ) { - foreach my $pkgver ( $pkglist->pkgver($1) ) { - $pkgver->var('dir') =~ /-current/ && next; - push( @update, $pkgver ); - last; - } - } - } - } - - if ( $opt{u} ) { - print "\nREQUIRED details for packages that could be updated:\n"; - - foreach my $pkgver (@update) { - print $pkgver->pkg . ':'; - if ( open( PKGINFO, 'pkg_info -R ' . $pkgver->pkg . '|' ) ) { - my ($list); - - while (<PKGINFO>) { - if (/Required by:/) { - $list = 1; - } - elsif ($list) { - chomp; - s/-\d.*//; - print " $_"; - } - } - close(PKGINFO); - } - print "\n"; - } - - print - "\nRunning '${conf_make} fetch-list | sh' for each package:\n"; - foreach my $pkgver (@update) { - my ($pkgdir); - - $pkgdir = $pkgver->var('dir'); - if ( !defined($pkgdir) ) { - fail( - 'Unable to determine ' . $pkgver->pkg . ' directory' ); - } - - print "$pkgsrcdir/$pkgdir\n"; - safe_chdir("$pkgsrcdir/$pkgdir"); - system("${conf_make} fetch-list | sh"); - } - } - } - - if ( $opt{E} ) { - scan_pkgsrc_makefiles($pkgsrcdir); - store_pkgsrc_makefiles( $opt{E} ); - } -} - -sub canonicalize_pkgname($) { - my ($pkgname) = @_; - - $pkgname =~ s,^py\d+(?:pth|)-,py-,; - $pkgname =~ s,^ruby\d+-,ruby-,; - $pkgname =~ s,^php\d+-,php-,; - return $pkgname; -} - -# Could speed up by building a cache of package names to paths, then processing -# each package name once against the tests. -sub check_prebuilt_packages() { - - if ( $_ eq 'distfiles' || $_ eq 'pkgsrc' ) { - - # Skip these subdirs if present - $File::Find::prune = 1; - - } - elsif (/(.+)-(\d.*)\.t[bg]z$/) { - my ( $pkg, $ver ) = ( $1, $2 ); - - $pkg = canonicalize_pkgname($pkg); - - if ( $opt{V} && $vuln{$pkg} ) { - foreach my $chk ( @{ $vuln{$pkg} } ) { - my ( $test, $matchver ) = split( ' ', $chk ); - - if ( deweycmp( $ver, $test, $matchver ) ) { - print "$File::Find::dir/$_\n"; - push( @matched_prebuiltpackages, "$File::Find::dir/$_" ); - last; - } - } - } - - my ($pkgs); - if ( $pkgs = $pkglist->pkgs($pkg) ) { - my ($pkgver) = $pkgs->pkgver($ver); - - if ( !defined $pkgver ) { - if ( $opt{p} ) { - print "$File::Find::dir/$_\n"; - push( @matched_prebuiltpackages, "$File::Find::dir/$_" ); - } - - # Pick probably the last version - $pkgver = $pkgs->latestver; - } - - if ( $opt{R} && $pkgver->var('RESTRICTED') ) { - print "$File::Find::dir/$_\n"; - push( @matched_prebuiltpackages, "$File::Find::dir/$_" ); - } - - if ( $opt{O} && $pkgver->var('OSVERSION_SPECIFIC') ) { - print "$File::Find::dir/$_\n"; - push( @matched_prebuiltpackages, "$File::Find::dir/$_" ); - } - } - - } - elsif ( -d $_ ) { - if ( $prebuilt_pkgdir_cache{"$File::Find::dir/$_"} ) { - $File::Find::prune = 1; - return; - } - - $prebuilt_pkgdir_cache{"$File::Find::dir/$_"} = 1; - if ( -l $_ ) { - my ($dest) = readlink($_); - - if ( substr( $dest, 0, 1 ) ne '/' ) { - $dest = "$File::Find::dir/$dest"; - } - if ( !$prebuilt_pkgdir_cache{$dest} ) { - push( @prebuilt_pkgdirs, $dest ); - } - } - } -} - -# Dewey decimal verson number matching - or thereabouts -# Also handles 'nb<N>' suffix (checked iff values otherwise identical) -# -sub deweycmp($$$) { - my ( $match, $test, $val ) = @_; - my ( $cmp, $match_nb, $val_nb ); - - $match_nb = $val_nb = 0; - if ( $match =~ /(.*)nb(.*)/ ) { - - # Handle nb<N> suffix - $match = $1; - $match_nb = $2; - } - - if ( $val =~ /(.*)nb(.*)/ ) { - - # Handle nb<N> suffix - $val = $1; - $val_nb = $2; - } - - $cmp = deweycmp_extract( $match, $val ); - - if ( !$cmp ) { - - # Iff otherwise identical, check nb suffix - $cmp = deweycmp_extract( $match_nb, $val_nb ); - } - - eval "$cmp $test 0"; -} - -sub convert_to_standard_dewey(@) { - my ( $elem, $underscore, @temp ); - - # According to the current implementation in pkg_install/lib/str.c - # as of 2002/06/02, '_' before a number, '.', and 'pl' get treated as 0, - # while 'rc' and 'pre' get treated as -1; beta as '-2', alpha as '-3'. - # Other characters are converted to lower - # case and then to a number: a->1, b->2, c->3, etc. Numbers stay the same. - # 'nb' is a special case that's already been handled when we are here. - foreach $elem (@_) { - if ( $elem =~ /\d+/ ) { - push( @temp, $elem ); - - } - elsif ( $elem =~ /^pl$/ or $elem =~ /^\.$/ ) { - push( @temp, 0 ); - - } - elsif ( $elem =~ /^_$/ ) { - push( @temp, 0 ); - - } - elsif ( $elem =~ /^pre$/ ) { - push( @temp, -1 ); - - } - elsif ( $elem =~ /^rc$/ ) { - push( @temp, -1 ); - - } - elsif ( $elem =~ /^beta$/ ) { - push( @temp, -2 ); - - } - elsif ( $elem =~ /^alpha$/ ) { - push( @temp, -3 ); - - } - else { - push( @temp, 0 ); - push( @temp, ord($elem) - ord("a") + 1 ); - } - } - @temp; -} - -sub deweycmp_extract($$) { - my ( $match, $val ) = @_; - my ( $cmp, @matchlist, @vallist, $i, $len ); - - @matchlist = convert_to_standard_dewey( split( /(\D+)/, lc($match) ) ); - @vallist = convert_to_standard_dewey( split( /(\D+)/, lc($val) ) ); - $cmp = 0; - $i = 0; - if ( $#matchlist > $#vallist ) { - $len = $#matchlist; - } - else { - $len = $#vallist; - } - while ( !$cmp && ( $i++ <= $len ) ) { - if ( !@matchlist ) { - push( @matchlist, 0 ); - } - if ( !@vallist ) { - push( @vallist, 0 ); - } - $cmp = ( shift @matchlist <=> shift @vallist ); - } - $cmp; -} - -sub fail(@) { - - print STDERR @_, "\n"; - exit(3); -} - -sub get_default_makefile_vars() { - - chomp( $pkg_installver = `pkg_info -V 2>/dev/null || echo 20010302` ); - - chomp( $_ = `uname -srm` ); - ( - $default_vars->{OPSYS}, - $default_vars->{OS_VERSION}, - $default_vars->{MACHINE} - ) = (split); - if ( !$default_vars->{MACHINE} ) { - die('Unable to extract machine from uname'); - } - - # Handle systems without uname -p (NetBSD pre 1.4) - chomp( $default_vars->{MACHINE_ARCH} = `uname -p 2>/dev/null` ); - - if ( !$default_vars->{MACHINE_ARCH} - && $default_vars->{OS_VERSION} eq 'NetBSD' ) - { - chomp( $default_vars->{MACHINE_ARCH} = `sysctl -n hw.machine_arch` ); - } - - if ( !$default_vars->{MACHINE_ARCH} ) { - $default_vars->{MACHINE_ARCH} = $default_vars->{MACHINE}; - } - - $default_vars->{OBJECT_FMT} = 'x'; - $default_vars->{LOWER_OPSYS} = lc( $default_vars->{OPSYS} ); - - if ( $opt{P} ) { - $default_vars->{PKGSRCDIR} = $opt{P}; - } - else { - $default_vars->{PKGSRCDIR} = $conf_pkgsrcdir; - } - - $default_vars->{DESTDIR} = ''; - $default_vars->{LOCALBASE} = '/usr/pkg'; - $default_vars->{X11BASE} = '/usr/X11R6'; - - my ($vars); - if ( -f '/etc/mk.conf' && ( $vars = parse_makefile_vars('/etc/mk.conf') ) ) - { - foreach my $var ( keys %{$vars} ) { - $default_vars->{$var} = $vars->{$var}; - } - } - - if ( $opt{P} ) { - $default_vars->{PKGSRCDIR} = $opt{P}; - } - - if ( $opt{M} ) { - $default_vars->{DISTDIR} = $opt{M}; - } - else { - $default_vars->{DISTDIR} ||= $default_vars->{PKGSRCDIR} . '/distfiles'; - } - - if ( $opt{K} ) { - $default_vars->{PACKAGES} = $opt{K}; - } - - # Extract some variables from bsd.pkg.mk - my ($mkvars); - $mkvars = parse_makefile_vars( - "$default_vars->{PKGSRCDIR}/mk/bsd.pkg.mk", - "$default_vars->{PKGSRCDIR}/mk/scripts" - ); - foreach my $varname ( keys %{$mkvars} ) { - if ( $varname =~ /_REQD$/ || $varname eq 'EXTRACT_SUFX' ) { - $default_vars->{$varname} = $mkvars->{$varname}; - } - } - - $default_vars->{PACKAGES} ||= $default_vars->{PKGSRCDIR} . '/packages'; -} - -# Determine if a package version is current. If not, report correct version -# if found -# -sub invalid_version($) { - my ($pkgmatch) = @_; - my ( $fail, $ok ); - my ( @pkgmatches, @todo ); - - @todo = ($pkgmatch); - - # We handle {} here, everything else in package_globmatch - while ( $pkgmatch = shift @todo ) { - if ( $pkgmatch =~ /(.*){([^{}]+)}(.*)/ ) { - foreach ( split( ',', $2 ) ) { - push( @todo, "$1$_$3" ); - } - } - else { - push( @pkgmatches, $pkgmatch ); - } - } - - foreach $pkgmatch (@pkgmatches) { - my ( $pkg, $badver ) = package_globmatch($pkgmatch); - - if ( defined($badver) ) { - my ($pkgs); - - if ( $pkgs = $pkglist->pkgs($pkg) ) { - $fail .= - "Version mismatch: '$pkg' $badver vs " - . join( ',', $pkgs->versions ) . "\n"; - } - else { - $fail .= "Unknown package: '$pkg' version $badver\n"; - } - } - else { - - # If we find one match, don't bitch about others - $ok = 1; - } - } - $ok && ( $fail = undef ); - $fail; -} - -# List (recursive) non directory contents of specified directory -# -sub listdir($$) { - my ( $base, $dir ) = @_; - my ($thisdir); - my ( @list, @thislist ); - - $thisdir = $base; - if ( defined($dir) ) { - $thisdir .= "/$dir"; - $dir .= '/'; - } - else { - $dir = ''; - } - - opendir( DIR, $thisdir ) || fail("Unable to opendir($thisdir): $!"); - @thislist = grep( substr( $_, 0, 1 ) ne '.' && $_ ne 'CVS', readdir(DIR) ); - closedir(DIR); - foreach my $entry (@thislist) { - if ( -d "$thisdir/$entry" ) { - push( @list, listdir( $base, "$dir$entry" ) ); - } - else { - push( @list, "$dir$entry" ); - } - } - @list; -} - -# Use pkg_info to list installed packages -# -sub list_installed_packages() { - my (@pkgs); - - open(PKG_INFO, 'pkg_info -e "*" |') || fail("Unable to run pkg_info: $!"); - while (defined(my $pkg = <PKG_INFO>)) { - chomp($pkg); - push(@pkgs, canonicalize_pkgname($pkg)); - } - close(PKG_INFO); - - @pkgs; -} - -# List top level pkgsrc categories -# -sub list_pkgsrc_categories($) { - my ($pkgsrcdir) = @_; - my (@categories); - - opendir( BASE, $pkgsrcdir ) || die("Unable to opendir($pkgsrcdir): $!"); - @categories = - grep( substr( $_, 0, 1 ) ne '.' - && $_ ne 'CVS' - && -f "$pkgsrcdir/$_/Makefile", - readdir(BASE) ); - closedir(BASE); - @categories; -} - -# For a given category, list potentially valid pkgdirs -# -sub list_pkgsrc_pkgdirs($$) { - my ( $pkgsrcdir, $cat ) = @_; - my (@pkgdirs); - - if ( !opendir( CAT, "$pkgsrcdir/$cat" ) ) { - die("Unable to opendir($pkgsrcdir/cat): $!"); - } - @pkgdirs = - sort grep( $_ ne 'Makefile' - && $_ ne 'pkg' - && $_ ne 'CVS' - && substr( $_, 0, 1 ) ne '.', - readdir(CAT) ); - close(CAT); - @pkgdirs; -} - -sub glob2regex($) { - my ($glob) = @_; - my ( @chars, $in_alt ); - my ($regex); - - @chars = split( //, $glob ); - while ( defined( $_ = shift @chars ) ) { - if ( $_ eq '*' ) { - $regex .= '.*'; - } - elsif ( $_ eq '?' ) { - $regex .= '.'; - } - elsif ( $_ eq '+' ) { - $regex .= '.'; - } - elsif ( $_ eq '\\+' ) { - $regex .= $_ . shift @chars; - } - elsif ( $_ eq '.' || $_ eq '|' ) { - $regex .= quotemeta; - } - elsif ( $_ eq '{' ) { - $regex .= '('; - ++$in_alt; - } - elsif ( $_ eq '}' ) { - if ( !$in_alt ) { - - # Error - return undef; - } - $regex .= ')'; - --$in_alt; - } - elsif ( $_ eq ',' && $in_alt ) { - $regex .= '|'; - } - else { - $regex .= $_; - } - } - - if ($in_alt) { - - # Error - return undef; - } - if ( $regex eq $glob ) { - return (''); - } - if ( $opt{D} ) { - print "glob2regex: $glob -> $regex\n"; - } - '^' . $regex . '$'; -} - -# Perform some (reasonable) subset of 'pkg_info -e' / glob(3) -# Returns (sometimes best guess at) package name, -# and either 'problem version' or undef if all OK -# -sub package_globmatch($) { - my ($pkgmatch) = @_; - my ( $matchpkgname, $matchver, $regex ); - - if ( $pkgmatch =~ /^([^*?[]+)(<|>|<=|>=|-)(\d[^*?[{]*)$/ ) { - - # (package)(cmp)(dewey) - my ( $test, @pkgvers ); - - ( $matchpkgname, $test, $matchver ) = ( $1, $2, $3 ); - if ( @pkgvers = $pkglist->pkgver($matchpkgname) ) { - foreach my $pkgver (@pkgvers) { - if ( $test eq '-' ) { - if ( $pkgver->ver eq $matchver ) { - $matchver = undef; - last; - } - } - else { - if ( deweycmp( $pkgver->ver, $test, $matchver ) ) { - $matchver = undef; - last; - } - } - } - - if ( $matchver && $test ne '-' ) { - $matchver = "$test$matchver"; - } - } - - } - elsif ( $pkgmatch =~ /^([^[]+)-([\d*?{[].*)$/ ) { - - # (package)-(globver) - my (@pkgnames); - - ( $matchpkgname, $matchver ) = ( $1, $2 ); - - if ( defined $pkglist->pkgs($matchpkgname) ) { - push( @pkgnames, $matchpkgname ); - - } - elsif ( $regex = glob2regex($matchpkgname) ) { - foreach my $pkg ( $pkglist->pkgs ) { - ( $pkg->pkg() =~ /$regex/ ) && push( @pkgnames, $pkg->pkg() ); - } - } - - # Try to convert $matchver into regex version - # - $regex = glob2regex($matchver); - - foreach my $pkg (@pkgnames) { - if ( defined $pkglist->pkgver( $pkg, $matchver ) ) { - return ($matchver); - } - - if ($regex) { - foreach my $ver ( $pkglist->pkgs($pkg)->versions ) { - if ( $ver =~ /$regex/ ) { - $matchver = undef; - last; - } - } - } - - $matchver || last; - } - - # last ditch attempt to handle the whole DEPENDS as a glob - # - if ( $matchver && ( $regex = glob2regex($pkgmatch) ) ) { - - # (large-glob) - foreach my $pkgver ( $pkglist->pkgver ) { - if ( $pkgver->pkgname =~ /$regex/ ) { - $matchver = undef; - last; - } - } - } - - } - else { - ( $matchpkgname, $matchver ) = ( $pkgmatch, 'missing' ); - } - - ( $matchpkgname, $matchver ); -} - -# Parse a pkgsrc package makefile and return the pkgname and set variables -# -sub parse_makefile_pkgsrc($) { - my ($file) = @_; - my ( $pkgname, $vars ); - - $vars = parse_makefile_vars($file); - - if ( !$vars ) { - - # Missing Makefile - return undef; - } - - if ( defined $vars->{PKGNAME} ) { - $pkgname = $vars->{PKGNAME}; - - } - elsif ( defined $vars->{DISTNAME} ) { - $pkgname = $vars->{DISTNAME}; - } - - if ( defined $vars->{PKGNAME} ) { - debug("$file: PKGNAME=$vars->{PKGNAME}\n"); - } - if ( defined $vars->{DISTNAME} ) { - debug("$file: DISTNAME=$vars->{DISTNAME}\n"); - } - - if ( !defined $pkgname || $pkgname !~ /(.*)-(\d.*)/ ) { - - # invoke make here as a last resort - my ($pkgsrcdir) = ( $file =~ m:(/.*)/: ); - my $pid = open3( \*WTR, \*RDR, \*ERR, - "cd $pkgsrcdir ; ${conf_make} show-vars VARNAMES=PKGNAME" ); - if ( !$pid ) { - warn "$file: Unable to run make: $!"; - } - else { - close(WTR); - my @errors = <ERR>; - close(ERR); - my ($makepkgname) = <RDR>; - close(RDR); - wait; - chomp @errors; - if (@errors) { warn "\n$file: @errors\n"; } - - if ( $makepkgname =~ /(.*)-(\d.*)/ ) { - $pkgname = $makepkgname; - } - } - } - - if ( defined $pkgname ) { - if ( $pkgname =~ /^pkg_install-(\d+)$/ && $1 < $pkg_installver ) { - $pkgname = "pkg_install-$pkg_installver"; - } - - $pkgname = canonicalize_pkgname($pkgname); - - if ( defined $vars->{PKGREVISION} - and not $vars->{PKGREVISION} =~ /^\s*$/ ) - { - if ( $vars->{PKGREVISION} =~ /\D/ ) { - print - "\nBogus: PKGREVISION $vars->{PKGREVISION} (from $file)\n"; - - } - elsif ( $vars->{PKGREVISION} ) { - $pkgname .= "nb"; - $pkgname .= $vars->{PKGREVISION}; - } - } - - if ( $pkgname =~ /\$/ ) { - print "\nBogus: $pkgname (from $file)\n"; - - } - elsif ( $pkgname =~ /(.*)-(\d.*)/ ) { - if ($pkglist) { - my ($pkgver) = $pkglist->add( $1, $2 ); - - debug("add $1 $2\n"); - - foreach - my $var (qw(DEPENDS RESTRICTED OSVERSION_SPECIFIC BROKEN)) - { - $pkgver->var( $var, $vars->{$var} ); - } - - if ( defined $vars->{NO_BIN_ON_FTP} ) { - $pkgver->var( 'RESTRICTED', 'NO_BIN_ON_FTP' ); - } - - if ( $file =~ m:([^/]+/[^/]+)/Makefile$: ) { - $pkgver->var( 'dir', $1 ); - } - else { - $pkgver->var( 'dir', 'unknown' ); - } - } - } - else { - print "Cannot extract $pkgname version ($file)\n"; - } - - return ( $pkgname, $vars ); - - } - else { - return (undef); - } -} - -# Extract variable assignments from Makefile -# Much unpalatable magic to avoid having to use make (all for speed) -# -sub parse_makefile_vars($$) { - my ( $file, $cwd ) = @_; - my ( - $pkgname, %vars, $plus, $value, @data, - %incfiles, # Cache of previously included fils - %incdirs, # Directories in which to check for includes - @if_false - ); # 0:true 1:false 2:nested-false&nomore-elsif - - if ( !open( FILE, $file ) ) { - return (undef); - } - @data = map { chomp; $_ } <FILE>; - close(FILE); - - $incdirs{"."} = 1; - $incdirs{ dirname($file) } = 1; - - # Some Makefiles depend on these being set - if ( $file eq '/etc/mk.conf' ) { - $vars{LINTPKGSRC} = 'YES'; - } - else { - %vars = %{$default_vars}; - } - $vars{BSD_PKG_MK} = 'YES'; - - if ($cwd) { - $vars{'.CURDIR'} = $cwd; - - } - elsif ( $file =~ m#(.*)/# ) { - $vars{'.CURDIR'} = $1; - - } - else { - $vars{'.CURDIR'} = getcwd; - } - - $incdirs{ $vars{'.CURDIR'} } = 1; - if ( $opt{L} ) { - print "$file\n"; - } - - while ( defined( $_ = shift(@data) ) ) { - s/\s*[^\\]#.*//; - - # Continuation lines - # - while ( substr( $_, -1 ) eq "\\" ) { - substr( $_, -2 ) = shift @data; - } - - # Conditionals - # - if (m#^\.\s*if(|def|ndef)\s+(.*)#) { - my ( $type, $false ); - - $type = $1; - if ( $if_false[$#if_false] ) { - push( @if_false, 2 ); - - } - elsif ( $type eq '' ) { - - # Straight if - push( @if_false, parse_eval_make_false( $2, \%vars ) ); - - } - else { - $false = !defined( $vars{ parse_expand_vars( $2, \%vars ) } ); - if ( $type eq 'ndef' ) { - $false = !$false; - } - push( @if_false, $false ? 1 : 0 ); - } - debug("$file: .if$type (! @if_false)\n"); - next; - } - - if ( m#^\.\s*elif\s+(.*)# && @if_false ) { - if ( $if_false[$#if_false] == 0 ) { - $if_false[$#if_false] = 2; - } - elsif ( $if_false[$#if_false] == 1 - && !parse_eval_make_false( $1, \%vars ) ) - { - $if_false[$#if_false] = 0; - } - debug("$file: .elif (! @if_false)\n"); - next; - } - - if ( m#^\.\s*else\b# && @if_false ) { - $if_false[$#if_false] = $if_false[$#if_false] == 1 ? 0 : 1; - debug("$file: .else (! @if_false)\n"); - next; - } - - if (m#^\.\s*endif\b#) { - pop(@if_false); - debug("$file: .endif (! @if_false)\n"); - next; - } - - $if_false[$#if_false] && next; - - # Included files (just unshift onto @data) - # - if (m#^\.\s*include\s+"([^"]+)"#) { - my ($incfile) = parse_expand_vars( $1, \%vars ); - - # At this point just skip any includes which we were not able to - # fully expand - if ( $incfile =~ m#/mk/bsd# - || $incfile =~ /$magic_undefined/ - || ( !$opt{d} && $incfile =~ m#/(buildlink[^/]*\.mk)# ) ) - { - debug("$file: .include \"$incfile\" skipped\n"); - } - else { - debug("$file: .include \"$incfile\"\n"); - - # Expand any simple vars in $incfile - # - - if ( substr( $incfile, 0, 1 ) ne '/' ) { - foreach my $dir ( keys %incdirs ) { - if ( -f "$dir/$incfile" ) { - $incfile = "$dir/$incfile"; - last; - } - } - } - - # perl 5.6.1 realpath() cannot handle files, only directories - # If the last component is a symlink this will give a false - # negative, but that is not a problem as the duplicate check - # is for performance - $incfile =~ m#^(.+)(/[^/]+)$#; - - if ( !-f $incfile ) { - if ( !$opt{L} ) { - verbose("\n"); - } - - verbose("$file: Cannot locate $incfile in " - . join( " ", sort keys %incdirs ) - . "\n" ); - - } - else { - $incfile = realpath($1) . $2; - - if ( !$incfiles{$incfile} ) { - if ( $opt{L} ) { - print "inc $incfile\n"; - } - $incfiles{$incfile} = 1; - - if ( !open( FILE, $incfile ) ) { - verbose( - "Cannot open '$incfile' (from $file): $_ $!\n"); - } - else { - my $NEWCURDIR = $incfile; - $NEWCURDIR =~ s#/[^/]*$##; - $incdirs{$NEWCURDIR} = 1; - unshift( @data, ".CURDIR=$vars{'.CURDIR'}" ); - unshift( @data, map { chomp; $_ } <FILE> ); - unshift( @data, ".CURDIR=$NEWCURDIR" ); - close(FILE); - } - } - } - } - next; - } - - if (/^ *([-\w\.]+)\s*([:+?]?)=\s*(.*)/) { - my ($key); - - $key = $1; - $plus = $2; - $value = $3; - - if ( $plus eq ':' ) { - $vars{$key} = parse_expand_vars( $value, \%vars ); - } - elsif ( $plus eq '+' && defined $vars{$key} ) { - $vars{$key} .= " $value"; - } - elsif ( $plus ne '?' || !defined $vars{$key} ) { - $vars{$key} = $value; - } - debug("assignment: $key$plus=[$value] ($vars{$key})\n"); - - # Give python a little hand (XXX - do we wanna consider actually - # implementing make .for loops, etc? - # - if ( $key eq "PYTHON_VERSIONS_ACCEPTED" ) { - my ($pv); - - foreach $pv ( split( /\s+/, $vars{PYTHON_VERSIONS_ACCEPTED} ) ) - { - $vars{"_PYTHON_VERSION_FIRSTACCEPTED"} ||= $pv; - $vars{"_PYTHON_VERSION_${pv}_OK"} = "yes"; - } - } - } - } - - debug("$file: expand\n"); - - # Handle variable substitutions FRED = a-${JIM:S/-/-b-/} - # - my ($loop); - - for ( $loop = 1 ; $loop ; ) { - $loop = 0; - foreach my $key ( keys %vars ) { - if ( index( $vars{$key}, '$' ) == -1 ) { - next; - } - - $_ = parse_expand_vars( $vars{$key}, \%vars ); - if ( $_ ne $vars{$key} ) { - $vars{$key} = $_; - $loop = 1; - - } - elsif ( $vars{$key} =~ - m#\${(\w+):([CS]([^{}])[^{}\3]+\3[^{}\3]*\3[g1]*(|:[^{}]+))}# ) - { - my ( $left, $subvar, $right ) = ( $`, $1, $' ); - my (@patterns) = split( ':', $2 ); - my ($result); - - $result = $vars{$subvar}; - $result ||= ''; - - # If $vars{$subvar} contains a $ skip it on this pass. - # Hopefully it will get substituted and we can catch it - # next time around. - if ( index( $result, '${' ) != -1 ) { - next; - } - - debug( - "$file: substitutelist $key ($result) $subvar (@patterns)\n" - ); - foreach (@patterns) { - if ( !m#([CS])(.)([^/]+)\2([^/]*)\2([1g]*)# ) { - next; - } - - my ( $how, $from, $to, $global ) = ( $1, $3, $4, $5 ); - - debug( -"$file: substituteglob $subvar, $how, $from, $to, $global\n" - ); - if ( $how eq 'S' ) { - - # Limited substitution - keep ^ and $ - $from =~ s/([?.{}\]\[*+])/\\$1/g; - } - $to =~ s/\\(\d)/\$$1/g; # Change \1 etc to $1 - $to =~ s/\&/\$&/g; # Change & to $1 - - my ($notfirst); - if ( $global =~ s/1// ) { - ( $from, $notfirst ) = split( '\s', $from, 2 ); - } - - debug("$file: substituteperl $subvar, $how, $from, $to\n"); - eval "\$result =~ s/$from/$to/$global"; - if ( defined $notfirst ) { - $result .= " $notfirst"; - } - } - - $vars{$key} = $left . $result . $right; - $loop = 1; - } - } - } - - foreach my $key ( keys %vars ) { - $vars{$key} =~ s/$magic_undefined//; - } - \%vars; -} - -sub parse_expand_vars($$) { - my ( $line, $vars ) = @_; - - while ( $line =~ /\$\{([-\w.]+)\}/ ) { - if ( defined( ${$vars}{$1} ) ) { - $line = $` . ${$vars}{$1} . $'; - } - else { - $line = $` . $magic_undefined . $'; - } - } - $line; -} - -sub parse_expand_vars_dumb($$) { - my ( $line, $vars ) = @_; - - while ( $line =~ /\$\{([-\w.]+)\}/ ) { - if ( defined( ${$vars}{$1} ) ) { - $line = $` . ${$vars}{$1} . $'; - } - else { - $line = $` . $magic_undefined . $'; - } - } - $line; -} - -sub parse_eval_make_false($$) { - my ( $line, $vars ) = @_; - my ( $false, $test ); - - $false = 0; - $test = parse_expand_vars_dumb( $line, $vars ); - - # XXX This is _so_ wrong - need to parse this correctly - $test =~ s/""/\r/g; - $test =~ s/"//g; # " - $test =~ s/\r/""/g; - - debug("conditional: $test\n"); - - # XXX Could do something with target - while ( $test =~ /(target|empty|make|defined|exists)\s*\(([^()]+)\)/ ) { - my $testname = $1; - my $varname = $2; - my $var; - - # Implement (some of) make's :M modifier - if ( $varname =~ /^([^:]+):M(.+)$/ ) { - $varname = $1; - my $match = $2; - - $var = $${vars}{$varname}; - $var = parse_expand_vars( $var, $vars ) if defined $var; - - $match =~ s/([.+])/\\$1/g; - $match =~ s/\*/.*/g; - $match =~ s/\?/./g; - $match = '^' . $match . '$'; - $var = ( $var =~ /$match/ ) if defined $var; - } - else { - $var = $${vars}{$varname}; - $var = parse_expand_vars( $var, $vars ) if defined $var; - } - - if ( defined $var && $var eq $magic_undefined ) { - $var = undef; - } - - if ( $testname eq 'exists' ) { - $_ = ( -e $varname ) ? 1 : 0; - - } - elsif ( $testname eq 'defined' ) { - $_ = defined($var) ? 1 : 0; - - } - elsif ( $testname eq 'empty' ) { - $_ = ( ( not defined($var) or ( length($var) == 0 ) ) ? 1 : 0 ); - - } - else { - $_ = 0; - } - - $test =~ s/$testname\s*\([^()]+\)/$_/; - debug("conditional: update to $test\n"); - } - - while ( $test =~ /([^\s()\|\&]+)\s+(!=|==)\s+([^\s()]+)/ ) { - if ( $2 eq '==' ) { - $_ = ( $1 eq $3 ) ? 1 : 0; - } - else { - $_ = ( $1 ne $3 ) ? 1 : 0; - } - $test =~ s/[^\s()\|\&]+\s+(!=|==)\s+[^\s()]+/$_/; - } - - if ( $test !~ /[^<>\d()\s&|.!]/ ) { - $false = eval "($test)?0:1"; - if ( !defined $false ) { - fail("Eval failed $line - $test"); - } - debug( "conditional: evaluated to " . ( $false ? 0 : 1 ) . "\n" ); - - } - else { - $false = 0; - debug("conditional: defaulting to 0\n"); - } - $false; -} - -# chdir() || fail() -# -sub safe_chdir($) { - my ($dir) = @_; - - debug("chdir: $dir"); - if ( !chdir($dir) ) { - fail("Unable to chdir($dir): $!"); - } -} - -# Generate pkgname->category/pkg mapping, optionally check DEPENDS -# -sub scan_pkgsrc_makefiles($$) { - my ( $pkgsrcdir, $check_depends ) = @_; - my (@categories); - - if ($pkglist) { - - # Already done - return; - } - - if ( $opt{I} ) { - load_pkgsrc_makefiles( $opt{I} ); - return; - } - - $pkglist = new PkgList; - @categories = list_pkgsrc_categories($pkgsrcdir); - verbose('Scan Makefiles: '); - - if ( !$opt{L} ) { - verbose( '_' x @categories . "\b" x @categories ); - } - else { - verbose("\n"); - } - - foreach my $cat ( sort @categories ) { - foreach my $pkgdir ( list_pkgsrc_pkgdirs( $pkgsrcdir, $cat ) ) { - my ( $pkg, $vars ) = - parse_makefile_pkgsrc("$pkgsrcdir/$cat/$pkgdir/Makefile"); - } - - if ( !$opt{L} ) { - verbose('.'); - } - } - - if ( !$opt{L} ) { - my ($len); - - $_ = $pkglist->numpkgver() . ' packages'; - $len = @categories - length($_); - verbose( "\b" x @categories, $_, ' ' x $len, "\b" x $len, "\n" ); - } -} - -# Cross reference all depends -# -sub pkgsrc_check_depends() { - - foreach my $pkgver ( $pkglist->pkgver ) { - my ( $err, $msg ); - - defined $pkgver->var('DEPENDS') || next; - foreach my $depend ( split( " ", $pkgver->var('DEPENDS') ) ) { - - $depend =~ s/:.*// || next; - - $depend = canonicalize_pkgname($depend); - if ( ( $msg = invalid_version($depend) ) ) { - if ( !defined($err) ) { - print $pkgver->pkgname . " DEPENDS errors:\n"; - } - $err = 1; - $msg =~ s/(\n)(.)/$1\t$2/g; - print "\t$msg"; - } - } - } -} - -# Extract all distinfo entries, then verify contents of distfiles -# -sub scan_pkgsrc_distfiles_vs_distinfo($$$$) { - my ( $pkgsrcdir, $pkgdistdir, $check_unref, $check_distinfo ) = @_; - my (@categories); - my ( %distfiles, %sumfiles, @distwarn, $numpkg ); - my (%bad_distfiles); - - @categories = list_pkgsrc_categories($pkgsrcdir); - - verbose( 'Scan distinfo: ' . '_' x @categories . "\b" x @categories ); - $numpkg = 0; - foreach my $cat ( sort @categories ) { - foreach my $pkgdir ( list_pkgsrc_pkgdirs( $pkgsrcdir, $cat ) ) { - if ( open( DISTINFO, "$pkgsrcdir/$cat/$pkgdir/distinfo" ) ) { - ++$numpkg; - while (<DISTINFO>) { - if (m/^(\w+) ?\(([^\)]+)\) = (\S+)/) { - my ( $dn, $ds, $dt ); - $dt = $1; - $dn = $2; - $ds = $3; - if ( $dn =~ /^patch-[\w.\-]+$/ ) { - next; - } - - # Strip leading ./ which sometimes gets added - # because of DISTSUBDIR=. - $dn =~ s/^(\.\/)*//; - if ( !defined $distfiles{$dn} ) { - $distfiles{$dn}{sumtype} = $dt; - $distfiles{$dn}{sum} = $ds; - $distfiles{$dn}{path} = "$cat/$pkgdir"; - - } - elsif ($distfiles{$dn}{sumtype} eq $dt - && $distfiles{$dn}{sum} ne $ds ) - { - push( @distwarn, - "checksum mismatch between '$dt' for '$dn' " - . "in $cat/$pkgdir and $distfiles{$dn}{path}\n" - ); - } - } - } - close(DISTINFO); - } - } - verbose('.'); - } - verbose(" ($numpkg packages)\n"); - - # Do not mark the vulnerabilities file as unknown - $distfiles{'pkg-vulnerabilities'} = { - path => 'pkg-vulnerabilities', - sum => 'IGNORE' - }; - - foreach my $file ( listdir( "$pkgdistdir", undef ) ) { - my ($dist); - - if ( !defined( $dist = $distfiles{$file} ) ) { - $bad_distfiles{$file} = 1; - - } - else { - if ( $dist->{sum} ne 'IGNORE' ) { - push( @{ $sumfiles{ $dist->{sumtype} } }, $file ); - } - } - } - - if ( $check_unref && %bad_distfiles ) { - verbose( scalar( keys %bad_distfiles ), - " unreferenced file(s) in '$pkgdistdir':\n" ); - print join( "\n", sort keys %bad_distfiles ), "\n"; - } - - if ($check_distinfo) { - if (@distwarn) { - verbose(@distwarn); - } - - verbose("checksum mismatches\n"); - safe_chdir($pkgdistdir); - foreach my $sum ( keys %sumfiles ) { - if ( $sum eq 'Size' ) { - foreach my $file ( @{ $sumfiles{$sum} } ) { - if ( !-f $file || -S $file != $distfiles{$file}{sum} ) { - print $file, " (Size)\n"; - $bad_distfiles{$file} = 1; - } - } - next; - } - - open( DIGEST, "digest $sum @{$sumfiles{$sum}}|" ) - || fail("Run digest: $!"); - while (<DIGEST>) { - if (m/^$sum ?\(([^\)]+)\) = (\S+)/) { - if ( $distfiles{$1}{sum} ne $2 ) { - print $1, " ($sum)\n"; - $bad_distfiles{$1} = 1; - } - } - } - close(DIGEST); - } - safe_chdir('/'); # Do not want to stay in $pkgdistdir - } - ( sort keys %bad_distfiles ); -} - -sub load_pkgsrc_makefiles() { - - open( STORE, "<$_[0]" ) || die("Cannot read pkgsrc store from $_[0]: $!\n"); - my ($pkgver); - our ( $pkgcnt, $pkgnum, $subpkgcnt, $subpkgnum ); - $pkglist = new PkgList; - while (<STORE>) { - eval $_; - } - close(STORE); -} - -sub store_pkgsrc_makefiles() { - open( STORE, ">$_[0]" ) || die("Cannot save pkgsrc store to $_[0]: $!\n"); - my $was = select(STORE); - print( - 'sub __pkgcount { $subpkgnum += $_[0]; ', - 'verbose("\rReading pkgsrc database: ', - '$pkgnum / $pkgcnt ($subpkgnum / $subpkgcnt) pkgs"); }', - "\n" - ); - $pkglist->store; - print("verbose(\"...done\\n\");\n"); - select($was); - close(STORE); -} - -# Remember to update manual page when modifying option list -# -sub usage_and_exit() { - print "Usage: lintpkgsrc [opts] [makefiles] -opts: - -h : This help. [see lintpkgsrc(1) for more information] - -Installed package options: Distfile options: - -i : Check version against pkgsrc -m : List distinfo mismatches - -u : As -i + fetch dist (may change) -o : List obsolete (no distinfo) - -Prebuilt package options: Makefile options: - -p : List old/obsolete -B : List packages marked as 'BROKEN' - -O : List OSVERSION_SPECIFIC -d : Check 'DEPENDS' up to date - -R : List NO_BIN_ON_FTP/RESTRICTED -S : List packages not in 'SUBDIRS' - -V : List known vulnerabilities - -Misc: - -E file : Export the internal pkgsrc database to file - -I file : Import the internal pkgsrc database to file (for use with -i) - -g file : Generate 'pkgname pkgdir pkgver' map in file - -r : Remove bad files (Without -m -o -p or -V implies all, can use -R) - -Modifiers: - -K path : Set PACKAGES basedir (default PKGSRCDIR/packages) - -M path : Set DISTDIR (default PKGSRCDIR/distfiles) - -P path : Set PKGSRCDIR (default $conf_pkgsrcdir) - -D : Debug makefile and glob parsing - -L : List each Makefile when scanned -"; - exit; -} - -sub verbose(@) { - - if ( -t STDERR ) { - print STDERR @_; - } -} - -sub debug(@) { - - ( $opt{D} ) && print STDERR 'DEBUG: ', @_; -} - -# PkgList is the master list of all packages in pkgsrc. -# -package PkgList; - -sub add($@) { - my $self = shift; - - if ( !$self->pkgs( $_[0] ) ) { - $self->{_pkgs}{ $_[0] } = new Pkgs $_[0]; - } - $self->pkgs( $_[0] )->add(@_); -} - -sub new($) { - my $class = shift; - my $self = {}; - bless $self, $class; - return $self; -} - -sub numpkgver($) { - my $self = shift; - scalar( $self->pkgver ); -} - -sub pkgver($@) { - my $self = shift; - - if ( @_ == 0 ) { - my (@list); - foreach my $pkg ( $self->pkgs ) { - push( @list, $pkg->pkgver ); - } - return (@list); - } - - if ( defined $self->{_pkgs}{ $_[0] } ) { - return ( @_ > 1 ) - ? $self->{_pkgs}{ $_[0] }->pkgver( $_[1] ) - : $self->{_pkgs}{ $_[0] }->pkgver(); - } - return; -} - -sub pkgs($@) { - my $self = shift; - - if (@_) { - return $self->{_pkgs}{ $_[0] }; - } - else { - return ( sort { $a->pkg cmp $b->pkg } values %{ $self->{_pkgs} } ); - } - return; -} - -sub store($) { - my $self = shift; - my @pkgs = keys %{ $self->{_pkgs} }; - my ( $cnt, $subcnt ) = $self->count; - - print("\$pkgcnt = $cnt;\n"); - print("\$subpkgcnt = $subcnt;\n"); - map( $self->{_pkgs}{$_}->store, keys %{ $self->{_pkgs} } ); -} - -sub count($) { - my $self = shift; - my ( $pkgcnt, $pkgsubcnt ); - - map { - $pkgcnt++; - $pkgsubcnt += $self->{_pkgs}{$_}->count; - } keys %{ $self->{_pkgs} }; - wantarray ? ( $pkgcnt, $pkgsubcnt ) : $pkgcnt; -} - -# Pkgs is all versions of a given package (eg: apache-1.x and apache-2.x) -# -package Pkgs; - -sub add($@) { - my $self = shift; - - $self->{_pkgver}{ $_[1] } = new PkgVer @_; -} - -sub new($@) { - my $class = shift; - my $self = {}; - - bless $self, $class; - $self->{_pkg} = $_[0]; - return $self; -} - -sub versions($) { - my $self = shift; - - return sort { $b cmp $a } keys %{ $self->{_pkgver} }; -} - -sub pkg($) { - my $self = shift; - $self->{_pkg}; -} - -sub pkgver($@) { - my $self = shift; - - if (@_) { - if ( $self->{_pkgver}{ $_[0] } ) { - return ( $self->{_pkgver}{ $_[0] } ); - } - return; - } - return sort { $b->ver() cmp $a->ver() } values %{ $self->{_pkgver} }; -} - -sub latestver($) { - my $self = shift; - - ( $self->pkgver() )[0]; -} - -sub store($) { - my $self = shift; - - print("\$pkgnum++;\n"); - map( $self->{_pkgver}{$_}->store, keys %{ $self->{_pkgver} } ); -} - -sub count($) { - my $self = shift; - - scalar( keys %{ $self->{_pkgver} } ); -} - -# PkgVer is a unique package+version -# -package PkgVer; - -sub new($$$) { - my $class = shift; - my $self = {}; - - bless $self, $class; - $self->{_pkg} = $_[0]; - $self->{_ver} = $_[1]; - return $self; -} - -sub pkgname($) { - my $self = shift; - - $self->pkg . '-' . $self->ver; -} - -sub pkg($) { - my $self = shift; - - $self->{_pkg}; -} - -sub var($$$) { - my $self = shift; - my ( $key, $val ) = @_; - - ( defined $val ) - ? ( $self->{$key} = $val ) - : $self->{$key}; -} - -sub ver($) { - my $self = shift; - - $self->{_ver}; -} - -sub vars($) { - my $self = shift; - - grep( !/^_(pkg|ver)$/, keys %{$self} ); -} - -sub store($) { - my $self = shift; - my $data; - - ( $data = $self->{_pkg} ) =~ s/([\\\$\@\%\"])/\\$1/g; - print("\$pkgver = \$pkglist->add(\"$data\", \""); - - ( $data = $self->{_ver} ) =~ s/([\\\$\@\%\"])/\\$1/g; - print("$data\"); __pkgcount(1);\n"); - - foreach ( $self->vars ) { - ( $data = $self->{$_} ) =~ s/([\\\$\@\%\"])/\\$1/g; - print("\$pkgver->var(\"$_\", \"$data\");\n"); - } -} - -package main; - -main(); |