App-Fetchware

 view release on metacpan or  search on metacpan

README  view on Meta::CPAN

and so on.). If you have the need for fetchware (You already know how to install
source code distributions yourself.), then you should be able to figure out how
to answer the questions easily.


WHY DID YOU CREATE FETCHWARE?

I wanted an automated way of installing apache's constant security fixes, which
was necessary, because I compiled apache from source instead of using my Linux
distribution's default build. Most sysadmins these days just use their Linux
distribution's default packages, but Unix and Linux have a long history of
compiling yourself the software that you install. Fetchware follows in this
tradition, and makes managing compiled from source software easier.


WHAT IS A FETCHWAREFILE?

A Fetchwarefile is Fetchware's configuration file. Because Fetchware can be a
package manger for any source-code distribution, it requires a file to tell it
everything it needs to know in order to install, upgrade, and uninstall your
source-code distribution, and that is what a Fetchwarefile does.

README  view on Meta::CPAN

But perhaps I or someone else will create one in the future.

Also, creating your own Fetchwarefile's to use to create your own Fetchware
packages is quite simple and flexible. See perldoc App::Fetchware for all of the
details after installing Fetchware.


INSTALLATION INSTRUCTIONS

(Note: currently Windows is not supported, but it may be supported in the
future. But everything Linux or Unix is supported.)

Just use your platform's cpan command to install Fetchware and Fetchware's
dependencies.

cpan App::Fetchware

That should cause the CPAN client to install the App::Fetchware distribution
from Perl's CPAN. This will also take care of installing any of Fetchware's
dependencies, or any other external CPAN modules that don't come with Perl and
might not be installed on your computer. This method is recommended, and the

README  view on Meta::CPAN

URI
Getopt::Long
Archive::Tar
Archive::Zip
Term::UI
File::HomeDir
HTTP::Tiny
HTML::TreeBuilder
Digest::SHA
Digest::MD5
Privileges::Drop, which is only a Unix module, but it simply does nothing on
Windows; however it is still required even on Windows systems.
Text::ParseWords
Sub::Mage

Test::Deep is required for testing, but you could skip it if you skip make test,
which is not recommended.

Win32 is needed, but only on Windows systems. It's likely already installed on
most Windows systems.

bin/fetchware  view on Meta::CPAN

        ) {
            # If it's a directory add it to the queue of directories to delete
            # below.
            if (-d $fetchware_file_or_dir) {
                push @globbed_fetchware_temp_dirs, $fetchware_file_or_dir;
            # If it's just a file just delete right away.
            } else {
                ###BUGALERT### Should I check if the current user has perms to
                #delete the file before deleting it? What about root? Should
                #root delete all files found even for other users? I'll go with
                #the Unix default of just doing the operation, and dealing with
                #the error message you receive to avoid the complexity of
                #checking perms. Furthermore, what about Unix ACLs and Windows'
                #ACL style perms? It's not worth dealing with that hassel.
                unlink $fetchware_file_or_dir or die <<EOD;
fetchware: Failed to unlink file [$fetchware_file_or_dir]. OS error [$!].
EOD
                    vmsg <<EOM;
fetchware clean found and deleted file [$fetchware_file_or_dir].
EOM
            }
        }
    }

bin/fetchware  view on Meta::CPAN



sub fetchware_database_path {
    # If user specifically specifies their own fetchware database path in their
    # fetchwarefile use it instead of the default one.
    my $fetchware_database_path;
    if (defined config('fetchware_db_path')) {
        $fetchware_database_path = config('fetchware_db_path');
    } elsif (defined $ENV{FETCHWARE_DATABASE_PATH}) {
        $fetchware_database_path = $ENV{FETCHWARE_DATABASE_PATH};
    } elsif (is_os_type('Unix', $^O)) {
        # If we're effectively root use a "system" directory.
        if ($> == 0) {
            # Fetchware is modeled slightly after Slackware's package manager,
            # which keeps its package database under /var/log/packages.
            $fetchware_database_path = '/var/log/fetchware';
        # else use a "user" directory.
        } else {
            $fetchware_database_path
                =
                File::HomeDir->my_dist_data('fetchware', { create => 1 });

bin/fetchware  view on Meta::CPAN

            }
        }
        if (Win32::IsAdminUser()) {
            # Is this an appropriate default?
            $fetchware_database_path = 'C:\Fetchware'; 
        } else {
            $fetchware_database_path
                =
                File::HomeDir->my_dist_data('fetchware' , { create => 1 });
        }
    # Fall back on File::HomeDir's recommendation if not "Unix" or windows.
    ###BUGALERT### Is this appropriate for Mac OSX???? /Fetchware perhaps?????
    } else {
         $fetchware_database_path
            =
            File::HomeDir->my_dist_data('fetchware', { create => 1 });
    }
    vmsg <<EOM;
Determined fetchware database path to be: [$fetchware_database_path]
EOM
    return $fetchware_database_path;

bin/fetchware  view on Meta::CPAN



sub copy_fpkg_to_fpkg_database {
    my $fetchware_package_path = shift;

    my $fetchware_db_path = fetchware_database_path();

    unless (-e $fetchware_db_path) {
        # Just use make_path() from File::Path to avoid having to check if
        # directories that contain the fetchware db directory have been created
        # or not. I doubt /var and /var/log won't exist on *nix systems, but
        # they probably don't on Mac OSX, which is kinda *nix.
        make_path($fetchware_db_path) or die <<EOD;
fetchware: run-time error. fetchware failed to create the directory that it
needs to store its database of installed packages in [$fetchware_db_path].
Library function error [$@].
EOD
    }
    cp($fetchware_package_path, $fetchware_db_path) or die <<EOD;
fetchware: run-time error. fetchware failed to copy the specified
fetchware package path [$fetchware_package_path] to [$fetchware_db_path]. Please
see perldoc App::Fetchware.

bin/fetchware  view on Meta::CPAN

Extracts out the Fetchwarefile of the provided fetchware package as specified by
$fetchware_package_path, and returns the content of the Fetchwarefile as a
scalar reference. Throws an exception if it it fails.

=head2 copy_fpkg_to_fpkg_database()

    my $fetchware_package_path = copy_fpkg_to_fpkg_database($fetchwarefile_path);

Installs (just copies) the specified fetchware package to the fetchware
database, which is /var/log/fetchware on UNIX, C:\FETCHWARE on Windows with
root or Administrator. All others are whatever L<File::HomeDir> says. For Unix
or Unix-like systems such as linux, L<File::HomeDir> will put your own user
fetchware database independent of the system-wide one in C</var/log/fetchware>
in C<~/.local/share/Perl/dist/fetchware/>. This correctly follows some sort of
standard. XDG or FreeDesktop perhaps?

Creates the directory the fetchware database is stored in if it does not already
exist.

Returns the full path of the copied fetchware package.

=head2 uninstall_fetchware_package_from_database()

bin/fetchware  view on Meta::CPAN

=head1 FAQ

=head2 How does fetchware's database work?

The design of fetchware's database was copied after Slackware's package database
design. In Slackware each package is a file in C</var/log/packages>, an
example: C</var/log/packages/coreutils-8.14-x86_64_slack13.37>. And inside that
file is a list of files, whoose names are the locations of all of the files that
this Slackware package installed. This format is really simple and flexible.

Fetchware's database is simply the directory C</var/log/fetchware> (on Unix when
run as root), or whatever File::HomeDir recommends. When packages are installed
the final version of that package that ends with C<.fpkg> is copied to your
fetchware database path. So after you install apache your fetchware database
will look like:

    ls /var/log/fetchware
    httpd-2.4.3.fpkg

It's not a real database or anything cool like that. It is simply a directory
containting a list of fetchware packages that have been installed. However, this

bin/fetchware  view on Meta::CPAN

error codes; instead, all errors are die()'d if it's fetchware's
error, or croak()'d if its the caller's fault.

=head1 CAVEATS

=over

=item WINDOWS COMPATIBILITY

Fetchware was written on Linux and tested by its author B<only> on Linux.
However, it should work on popular Unixes without any changes. But it has B<not>
been ported or tested on Windows yet, so it may work, or parts of it may work,
but some might not. However, I have used File::Spec and Path::Class to support
path and file manipulation accross all Perl-supported platorms, so that code
should work on Windows. I intend to add Windows support, and add tests for Windows
in the future, but for now it is unsupported, but may work. This is likely to
improve in the future.

=back

=head1 SEE ALSO

dist.ini  view on Meta::CPAN

Archive::Tar = 0
Archive::Zip = 0
Term::UI = 0
; File::Homedir 0.93+ is needed for my_dist_data() method.
File::HomeDir = 0.93
HTTP::Tiny = 0
HTML::TreeBuilder = 0
Digest::SHA = 0
Digest::MD5 = 0
; Installs ok on Windows, but doesn't do much.
; Fetchware only uses it on Unix.
Privileges::Drop = 0
; Not counting core modules such as File::Spec, Text::Wrap, Data::Dumper,
; File::Find, Net::FTP, Fcntl, File::Path, File::Copy, and perhaps others.
Text::ParseWords = 0
Sub::Mage = 0

; Test::Deep is *only* used during testing, so say so.
[Prereqs / TestRequires]
Test::Deep = 0
; Test::Expect is also only used during testing, but I don't want it "required

lib/App/Fetchware.pm  view on Meta::CPAN

    ###BUGALERT### Ask user for a prefix if their running nonroot???
    vmsg 'Prompting for other options that may be needed.';
    my $other_options_hashref = prompt_for_other_options($term,
        temp_dir => {
            prompt => <<EOP,
What temp_dir configuration option would you like? 
EOP
            print_me => <<EOP
temp_dir is the directory where fetchware creates a temporary directory that
stores all of the temporary files it creates while it is building your software.
The default directory is /tmp on Unix systems and C:\\temp on Windows systems.
EOP
        },
        user => {
            prompt => <<EOP,
What user configuration option would you like? 
EOP
            print_me => <<EOP
user specifies what user fetchware will drop priveleges to on Unix systems
capable of doing so. This allows fetchware to download files from the internet
with user priveleges, and not do anything as the administrative root user until
after the downloaded software package has been verified as exactly the same as
the author of the package intended it to be. If you use this option, the only
thing that is run as root is 'make install' or whatever this package's
install_commands configuratio option is.
EOP
        },
        prefix => {
            prompt => <<EOP,
What prefix configuration option would you like? 
EOP
            print_me => <<EOP
prefix specifies the base path that will be used to install this software. The
default is /usr/local, which is acceptable for most unix users. Please note that
this difective only works for software packages that use GNU AutoTools, software
that uses ./configure --prefix=<your prefix will go here> to change the prefix.
EOP
        },
        configure_options => {
            prompt => <<EOP,
What configure_options configuration option would you like? 
EOP
            print_me => <<EOP
configure_options specifies what options fetchware should add when it configures

lib/App/Fetchware.pm  view on Meta::CPAN

directory that it uses to download, verify, unarchive, build, and install your
software. By default it uses your system temp directory, which is whatever
directory L<File::Temp's> tempdir() decides to use, which is whatever
L<File::Spec>'s tmpdir() decides to use.

=head2 fetchware_db_path '~/.fetchwaredb';

C<fetchware_db_path> tells fetchware to use a different directory other
than its default directory to store the installed fetchware package for the
particular fetchware package that this option is specified in your
Fetchwarefile. Fetchware's default is C</var/log/fetchware> on Unix when run as
root, and something like C</home/[username]/.local/share/Perl/dist/fetchware/>
when run nonroot.

This option is B<not> recommended unless you only want to change it for just one
fetchware package, because fetchware also consults the
C<FETCHWARE_DATABASE_PATH> environment variable that you should set in your
shell startup files if you want to change this globally for all of your
fetchware packages. For sh/bash like shells use:

    export FETCHWARE_DATABASE_PATH='/your/path/here'

lib/App/Fetchware.pm  view on Meta::CPAN

C<nobody>, but you can specify a different username with this configuration
option if you would like to.

Dropping privileges allows fetchware to avoid downloading files and executing
anything inside the downloaded archive as root. Except of course the commands
needed to install the software, which will still need root to able to write
to system directories. This improves security, because the downloaded software
won't have sytem privileges until after it is verified, providing that what you
downloaded is exactly what the author uploaded.

Note this only works for unix like systems, and is not used on Windows and
other non-unix systems.

Also note, that if you are running fetchware on Unix even if you do not specify
the C<user> configuration option to configure what user you will drop privileges
to, fetchware will still drop privileges using the ubiquitous C<nobody> user.
If you do B<not> want to drop privileges, then you must use the C<stay_root>
configuration option as described below.

=head2 stay_root 'On';

Tells fetchware to B<not> drop privileges. Dropping privileges when run as root
is fetchware's default behavior. It improves security, and allows fetchware to
avoid exposing the root account by downloading files as root.

lib/App/Fetchware.pm  view on Meta::CPAN

=head3 prompt_for_other_options()

    prompt_for_other_options($term,
        temp_dir => {
            prompt => <<EOP,
    What temp_dir configuration option would you like? 
    EOP
            print_me => <<EOP
    temp_dir is the directory where fetchware creates a temporary directory that
    stores all of the temporary files it creates while it is building your software.
    The default directory is /tmp on Unix systems and C:\\temp on Windows systems.
    EOP
        },
            ...
    );

Accepts a Term::Readline/Term::UI object as an argument to use to ask the user
questions, and a gigantic hash of hashes in list form. The hash of hashes,
%option_description, argument incluedes the C<prompt> and C<print_me> options
that are then passed through to Term::UI to ask the user what argument they want
for each specified option in the %option_description hash.

lib/App/Fetchware.pm  view on Meta::CPAN

anyone other than the owner who is executing them. It will also exit with a
fatal error if you try to use a Fetchwarefile that is not the same user as the
one who is running fetchware. These saftey measures help prevent fetchware being
abused to get unauthorized code executed on your computer.

App::Fetchware also features the C<user> configuration option that tells
fetchware what user you want fetchware to drop privileges to when it does
everything but install (install()) and clean up (end()). The configuration
option does B<not> tell fetchware to turn on the drop privelege code; that code
is B<always> on, but just uses the fairly ubuiquitous C<nobody> user by default.
This feature requires the OS to be some version of Unix, because Windows and
other OSes do not support the same fork()ing method of limiting what processes
can do. On non-Unix OSes, fetchware won't fork() or try to use some other way of
dropping privileges. It only does it on Unix. If you use some version of Unix,
and do not want fetchware to drop privileges, then specify the C<stay_root>
configuration option.

=head1 ERRORS

App::Fetchware does not return any error codes; instead, all errors are die()'d
if it's App::Fetchware::Config's error, or croak()'d if its the caller's fault.
These exceptions are short paragraphs that give full details about the error
instead of the vague one liner that perl's own errors give.

lib/App/Fetchware/Util.pm  view on Meta::CPAN

use Path::Class;
use Net::FTP;
use HTTP::Tiny;
use Perl::OSType 'is_os_type';
use Cwd;
use App::Fetchware::Config ':CONFIG';
use File::Copy 'cp';
use File::Temp 'tempdir';
use File::stat;
use Fcntl qw(S_ISDIR :flock S_IMODE);
# Privileges::Drop only works on Unix, so only load it on Unix.
use if is_os_type('Unix'), 'Privileges::Drop';
use POSIX '_exit';
use Sub::Mage;
use URI::Split qw(uri_split uri_join);
use Text::ParseWords 'quotewords';
use Data::Dumper;

# Enable Perl 6 knockoffs, and use 5.10.1, because smartmatching and other
# things in 5.10 were changed in 5.10.1+.
use 5.010001;

lib/App/Fetchware/Util.pm  view on Meta::CPAN

EOD


    my @file_listing;
    opendir my $dh, $local_lookup_url or die <<EOD;
App-Fetchware-Util: The directory that fetchware is trying to use to determine
if a new version of the software is availabe cannot be opened. This directory is
[$local_lookup_url], and the OS error is [$!].
EOD
    while (my $filename = readdir($dh)) {
        # Trim the useless '.' and '..' Unix convention fake files from the listing.
        unless ($filename eq '.' or $filename eq '..') {
            # Turn the relative filename into a full pathname.
            #
            # Full pathnames are required, because lookup()'s
            # file_parse_filelist() stat()s each file using just their filename,
            # and if it's relative instead of absolute these stat() checks will
            # fail.
            my $full_path = catfile($local_lookup_url, $filename);
            push @file_listing, $full_path;
        }

lib/App/Fetchware/Util.pm  view on Meta::CPAN

    return file($url)->basename();
}







###BUGALERT### safe_open() does not check extended file perms such as ext*'s
#crazy attributes, linux's (And other Unixs' too) MAC stuff or Windows NT's
#crazy file permissions. Could use Win32::Perms for just Windows, but its not
#on CPAN. And what about the other OSes.
###BUGALERT### Consier moving this to CPAN??? File::SafeOpen????
sub safe_open {
    my $file_to_check = shift;
    my $open_fail_message = shift // <<EOE;
Failed to open file [$file_to_check]. OS error [$!].
EOE

    my %opts = @_;

lib/App/Fetchware/Util.pm  view on Meta::CPAN


    # Execute $child_code without dropping privs if the user's configuration
    # file is configured to force fetchware to "stay_root."
    if (config('stay_root')) {
        msg <<EOM;
stay_root is set to true. NOT dropping privileges!
EOM
        return $dont_drop_privs->($child_code);
    }

    if (is_os_type('Unix') and ($< == 0 or $> == 0)) {
        # cmd_new() needs to skip the creation of this useless directory that it
        # does not use. Furthemore, the creation of this extra tempdir is not
        # needed by cmd_new(), and this tempdir presumes start() was called
        # before drop_privs(), which is always the case except for cmd_new().
        #
        # But another case where this temp dir's creations should be skipped is
        # if start() is overridden with hook() to make start() do something
        # other than create a temp dir, because in some cases such as using VCS
        # instead of Web sites and mirrors, you do not need to bother with
        # creating a tempdir, because the working dir of the repo can be used

lib/App/Fetchware/Util.pm  view on Meta::CPAN

                # and exit non-zero indicating failure.
                # Use POSIX's _exit() to avoid calling END{} blocks. This *must*
                # be done to prevent File::Temp's END{} block from attempting to
                # delete the temp directory that the parent still needs to
                # finish installing or uninstalling. The parent's END{} block's
                # will still be called, so this just turns off the child
                # deleting the temp dir not the parent.
                _exit 0;
            }
        }    
    # Non-Unix OSes just execute the $child_code.
    } else {
        return $dont_drop_privs->($child_code);
    }
}




###BUGALERT### Add quotemeta() support to pipe parsers to help prevent attacks.

lib/App/Fetchware/Util.pm  view on Meta::CPAN


=item *

Then safe_open() stat's each and every parent directory that is in this file's
full path, and runs the same checks that are run above on each parent directory.

=item *

_PC_CHOWN_RESTRICTED is not tested; instead what is_very_safe() does is simply
always done. Because even with A _PC_CHOWN_RESTRICTED test, /home, for example,
could be 777. This is Unix after all, and root can do anything including screw
up permissions on system directories.

=back

If you actually are some sort of security expert, please feel free to
double-check if the list of stuff to check for is complete, and perhaps even the
Perl implementation to see if the subroutine really does check if
safe_open($file_to_check) is actually safe.

=over

=item WARNING

According to L<perlport>'s chmod() documentation, on Win32 perl's Unixish file
permissions arn't supported only "owner" is:

"Only good for changing "owner" read-write access, "group", and "other" bits are
meaningless. (Win32)"

I'm not completely sure this means that under Win32 only owner perms mean
something, or if just chmod()ing group or ther bits don't do anything, but
testing if group and other are rwx does work. This needs testing.

And remember this only applies to Win32, and fetchware has not yet been properly

lib/App/Fetchware/Util.pm  view on Meta::CPAN

The output returned by drop_privs() is whatever the child wants it to be. If
somehow the child got hacked, the $output could be something that could cause
the parent (which has root perms!) to execute some code, or otherwise do
something that could cause the child to gain root access. So be sure to check
how you use drop_privs() return value, and definitley don't just string eval it.
Structure it so the return value can only be used as data for variables, and
that those variables are never executed by root.

=back

drop_privs() handles being on nonunix for you. On a platform that is not Unix
that does not have Unix's fork() and exec() security model, drop_privs() simply
executes the provided code reference I<without> dropping priveledges.

=over

=item USABILITY NOTICE 

drop_privs()'s implementation depends on start() creating a tempdir and
chdir()ing to it. Furthermore, drop_privs() sometimes creates a tempdir of its
own, and it does not do a chdir back to another directory, so drop_privs()
depends on end() to chdir back to original_cwd(). Therefore, do not use

lib/Test/Fetchware.pm  view on Meta::CPAN

Running make_clean() inside of fetchware's own directory! make_clean() should
only be called inside testing build directories, and perhaps also only called if
FETCHWARE_RELEASE_TESTING has been set.
EOF
    system('make', 'clean');
    chdir(updir()) or fail(q{Can't chdir(updir())!});
}



###BUGALERT### make_test_dist() only works properly on Unix, because of its
#dependencies on the shell and make, just replace those commands with perl
#itself, which we can pretty much guaranteed to be installed.
sub make_test_dist {
    my %opts = @_;

    # Validate options, and set defaults if they need to be set.
    if (not defined $opts{file_name}) {
        die <<EOD;
Test-Fetchware: file_name named parameter is a mandatory options, and must be
specified despite it pretty much always being just 'test-dist'. It is still

lib/Test/Fetchware.pm  view on Meta::CPAN

        'checked cleanup_tempdir() success.');
    ok(close $fh_sem,
        'checked cleanup_tempdir() released fetchware lock file success.');
}



sub add_prefix_if_nonroot {
    my $callback = shift;
    my $prefix;
    if (not is_os_type('Unix') or $> != 0 ) {
        if (not defined $callback) {
            $prefix = tempdir("fetchware-test-$$-XXXXXXXXXX",
                TMPDIR => 1, CLEANUP => 1);
            note("Running as nonroot or nonunix using prefix temp dir [$prefix]");
            config(prefix => $prefix);
        } else {
            ok(ref $callback eq 'CODE', <<EOD);
Received callback that is a proper coderef [$callback].
EOD
            $prefix = $callback->();
        }
        
        # Return the prefix that will be used.
        return $prefix;

lib/Test/Fetchware.pm  view on Meta::CPAN


    # Use a temp dir outside of the installation directory 
    my ($fh, $fetchwarefile_path)
        =
        tempfile("fetchware-$$-XXXXXXXXXXXXXX", TMPDIR => 1, UNLINK => 1);

    # Chmod 644 to ensure a possibly dropped priv child can still at least read
    # the file. It doesn't need write access just read.
    unless (chmod 0644, $fetchwarefile_path
        and
        # Only Unix drops privs. Nonunix does not.
        is_os_type('Unix')
    ) {
        die <<EOD;
fetchware: Failed to chmod 0644, [$fetchwarefile_path]! This is a fatal error,
because if the file is not chmod()ed, then fetchware cannot access the file if
it was created by root, and then tried to read it, but root on Unix dropped
privs. OS error [$!].
EOD
    }

    # Be sure to add a prefix to the generated Fetchwarefile if fetchware is not
    # running as root to ensure that our test installs succeed.
    #
    # Prepend a newline to ensure that prefix is not added to an existing line.
    add_prefix_if_nonroot(sub {
            my $prefix_dir = tempdir("fetchware-test-$$-XXXXXXXXXX",

lib/Test/Fetchware.pm  view on Meta::CPAN

=item * Then execute the coderef with a copy of the $printer's STDOUT and use the result of that expression to determine if the test passed or failed .

=back

=back

=over

NOTICE: C<print_ok()'s> manipuation of STDOUT only works for the current Perl
process. STDOUT may be inherited by forks, but for some reason my knowledge of
Perl and Unix lacks a better explanation other than that print_ok() does not
work for testing what C<fork()ed> and C<exec()ed> processes do such as those
executed with run_prog().

I also have not tested other possibilities, such as using IO::Handle to
manipulate STDOUT, or tie()ing STDOUT like Test::Output does. These methods
probably would not survive a fork() and an exec() though either.

=back

=head2 fork_ok()

t/App-Fetchware-Util.t  view on Meta::CPAN

    ok(open(my $fh_sem, '>', catfile($temp_dir, 'fetchware.sem')),
        'checked cleanup_tempdir() open fetchware lock file success.');
    ok( flock($fh_sem, LOCK_EX | LOCK_NB),
        'checked cleanup_tempdir() success.');
    ok(close $fh_sem,
        'checked cleanup_tempdir() released fetchware lock file success.');
};


subtest 'test drop_privs()' => sub {
    plan skip_all => 'Test suite not being run on Unix.' unless do {
        if (is_os_type('Unix')) {
            note('ISUNIX');
            1
        } else {
            # Return false
            note('ISNOTUNIX');
            0
        }
    };

    # If we're not running as root.

t/App-Fetchware-Util.t  view on Meta::CPAN

        # clear stay_root to avoid messing up other tests.
        config_delete('stay_root');


    } else {
        fail('Uhmmmm...this shouldn\'t happen...!?!');
    }



    if (is_os_type('Unix')) {

        subtest 'test pipe_{write,read}_newline()' => sub {
            my @expected = qw(Did it work ?);

            pipe (READONLY, WRITEONLY)
                or fail("Failed to create pipe??? Os error [$!]");
            for (scalar fork) {
                fail("Fork failed??? OS error [$!]") if not defined;
                # For worked. parent goes here.
                if (my $kidpid = $_) {

t/App-Fetchware-Util.t  view on Meta::CPAN


                    # End test start fork and pipe boilerplate.
                    close WRITEONLY
                        or fail("child writeonly pipe close failed??? [$!].");
                    exit 0;
                }
            }

        };
    } else {
        note("Should be skipped, because you're not running this on Unix! [$^O]");
    }


};


# Share these variables with safe_open()'s tests as root below in the SKIP
# block.
my $tempdir;
my ($fh, $filename);

t/App-Fetchware-Util.t  view on Meta::CPAN

        'checked safe_open() file group perms unsafe');

    # chdir back to $original_cwd so File::Temp can delete temp files.
    chdir $original_cwd;
};


subtest 'test safe_open() needs root' => sub {
    skip_all_unless_release_testing();
        plan skip_all =>  'Test suite not being run as root.' unless do {
            if (is_os_type('Unix')) {
                if ($< == 0 or $> == 0) {
                # Return true
                note('ISUNIXANDROOT');
                1
                } else {
                # Return false
                note('ISUNIXNOTROOT!!!');
                0
                }
            } else {

t/App-Fetchware-install.t  view on Meta::CPAN

    # Needed by all other subtests.
    my $package_path = $ENV{FETCHWARE_LOCAL_BUILD_URL};
    fail("FETCHWARE environment vars not set!!! Run frt()")
        if not defined $package_path;

    # Because these tests call App::Fetchware's API subs directly, and even skip
    # some steps such as verification, I need to add a prefix configuration
    # option manually with config(). This option enabled only when run non-root
    # causes fetchware to install its program to a different writable directory
    # other than the system ones, which are only writable by root. Also, do this
    # when running on an OS other than Unix.
    if (not is_os_type('Unix') or $> != 0 ) {
        my $temp_dir = tempdir("fetchware-test-$$-XXXXXXXXXX", TMPDIR => 1, CLEANUP => 1);
        note("Running as nonroot or nonunix using prefix temp dir [$temp_dir]");
        config(prefix => $temp_dir);
    }

    # Call start() to create & cd to a tempdir, so end() called later can delete all
    # of the files that will be downloaded.
    start();
    # Copy the $ENV{FETCHWARE_LOCAL_URL}/$package_path file to the temp dir, which
    # is what download would normally do for fetchware.
    cp("$package_path", '.') or die "copy $package_path failed: $!";

t/App-Fetchware-lookup.t  view on Meta::CPAN


    my $sorted_file_listing =
        lookup_by_versionstring($more_digits_than_higher_one);

    is_deeply($sorted_file_listing, $expected_more_digits_than_higher_one,
        'checked lookup_by_versionstring() unequal length bug fix.');

    # Also, test for duplicate version numbers--when two files have the same
    # version string. Note: real-world mirrors are not going to have duplicate
    # versions of the same program, but they might have multiple versions of the
    # same version of the same program. For example apache has a unix source
    # download, but also one for Windows, and one for dependencies.
    # NOTE: The "timestamp" info for each pair of duplicate version numbers
    # (for example, '111111111111111') must be the same, because some versions
    # of perl use a quicksort sort algorithm that does not preserve the original
    # order of equivelent entries. So, the order could change, which will break
    # the  simple is_deeply() test.
    my $same_version_number = [
        ['v4.0.0', '444444444444444'],
        ['v2.0.0', '222222222222222'],
        ['v1.0.0', '111111111111111'],

t/App-Fetchware-lookup.t  view on Meta::CPAN

% pgpv httpd-2.2.8.tar.gz.asc
<i>or</i>,
% pgp -ka KEYS
% pgp httpd-2.2.8.tar.gz.asc
<i>or</i>,
% gpg --import KEYS
% gpg --verify httpd-2.2.8.tar.gz.asc
</pre>

<p>We offer MD5 hashes as an alternative to validate the integrity
   of the downloaded files. A unix program called <code>md5</code> or
   <code>md5sum</code> is included in many unix distributions.  It is
   also available as part of <a
   href="http://www.gnu.org/software/textutils/textutils.html">GNU
   Textutils</a>.  Windows users can get binary md5 programs from <a
   href="http://www.fourmilab.ch/md5/">here</a>, <a
   href="http://www.pc-tools.net/win32/freeware/console/">here</a>, or
   <a href="http://www.slavasoft.com/fsum/">here</a>.</p>

<h2><a name="patches">Official Patches</a></h2>

<p>When we have patches to a minor bug or two, or features which we

t/App-Fetchware-new-prompt_for_other_options  view on Meta::CPAN

my $term = Term::ReadLine->new('testing fetchware new');

my $other_options_hashref = prompt_for_other_options($term,
        temp_dir => {
            prompt => <<EOP,
What temp_dir configuration option would you like? 
EOP
            print_me => <<EOP
temp_dir is the directory where fetchware creates a temporary directory that
stores all of the temporary files it creates while it is building your software.
The default directory is /tmp on Unix systems and C:\\temp on Windows systems.
EOP
        },
        user => {
            prompt => <<EOP,
What user configuration option would you like? 
EOP
            print_me => <<EOP
user specifies what user fetchware will drop priveleges to on Unix systems
capable of doing so. This allows fetchware to download files from the internet
with user priveleges, and not do anything as the administrative root user until
after the downloaded software package has been verified as exactly the same as
the author of the package intended it to be. If you use this option, the only
thing that is run as root is 'make install' or whatever this package's
install_commands configuratio option is.
EOP
        },
    );

t/bin-fetchware-util.t  view on Meta::CPAN

    # instead, they just return what it should be and test that the correct
    # things are being returned. Because fetchware_database_path()'s normal
    # behavior is needed to properly test this function even as root, we should
    # local delete $ENV{FETCHWARE_DATABASE_PATH} just for this one function,
    # fetchware_database_path(), because it needs "normal" behavior for proper
    # testing, and such proper testing has no side effects like messing witht he
    # filesystem.
    local $ENV{FETCHWARE_DATABASE_PATH};
    delete $ENV{FETCHWARE_DATABASE_PATH};

    if (is_os_type('Unix', $^O)) {
        # If we're effectively root use a "system" directory.
        if ($> == 0) {
            is(fetchware_database_path(), '/var/log/fetchware',
                'checked fetchware_database_path() as root');
        # else use a "user" directory.
        } else {
            like(fetchware_database_path(),
                # Add a generic "fetchware-test", because ~/.local and /tmp are
                # not the only possibilities especially among CPAN Testers, who
                # often have tempdirs set to cwd(), or other weird paths ending

t/bin-fetchware-util.t  view on Meta::CPAN

                Module->import();  # assuming you would not be passing arguments to "use Module"
            }
        }
        if (Win32::IsAdminUser()) {
            is(fetchware_database_path(), 'C:\fetchware',
                'checked fetchware_database_path() as Administrator on Win32');
        } else {
            ###BUGALERT### Add support for this test on Windows!
            fail('Must add support for non-admin on Windows!!!');
        }
    # Fall back on File::HomeDir's recommendation if not "Unix" or windows.
    } else {
            ###BUGALERT### Add support for everything else too!!!
            fail('Must add support for your OS!!!');
    }

    # Test fetchware_database_path() when the fetchware_database_path
    # configuration option has been specified.
    config(fetchware_db_path => cwd());
    is(fetchware_database_path(), cwd(),
        'check fetchware_database_path() config option success.');



( run in 3.229 seconds using v1.01-cache-2.11-cpan-64ef6c95b5d )