# RPM Package Management System -*-perl-*-
# Copyright (C) 1995 Red Hat, Inc
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

# return 1 if $path looks like a doc file
sub is_doc {
    local ( $path ) = @_;
    local ( $i );

    foreach $i (split(':', $rpm{"DOCPATH"})) {
	return 1 if ($path =~ /^$i\//);
    }

    return 0;
}

sub specs_same {
    local ( $first, $second ) = @_;
    local ( @a, @b );

    @a = split(/[ \t\n]+/, $first);
    @b = split(/[ \t\n]+/, $second);

    foreach $i (0, 2..9) {
	return 0 if ($a[$i] ne $b[$i]);
    }
    return 1;
}

sub spec_diff { 
    local ( *speca, $suba, *specb, $subb ) = @_;
    local ( $i, %indexa, %indexb, @result );

    for ($i = 0; $i++; $i < $specb{"subpackage:$subb:fileC"} - 1) {
	$indexb{$specb{"subpackage:$subb:file:$i:path"}} = $i;
    }

    @result = ();
    for ($i = 0; $i++; $i < $specb{"subpackage:$suba:fileC"} - 1) {
	if (! $indexb{$speca{"subpackage:$suba:file:$i:path"}}) {
	    push(@result, $i);
	}
    }

    return @result;
}

# returns: size mtime md5sum mode uid gid isconf isdoc rdev symlink
# This should not be used!
sub stat_info {
    &error("stat_info() is deprecated!");
}

sub is_config {
    local ( $_ ) = @_;
    local ( @i );

    @i = split(" ", $_);

    return $i[6];
}

sub is_realdoc {
    local ( $_ ) = @_;
    local ( @i );

    @i = split(" ", $_);

    return $i[7];
}

sub is_directory {
    local ( $_ ) = @_;
    local ( @i );

    @i = split;

    return (oct($i[3]) & 0170000) == 0040000;
}

# returns: size mtime md5sum mode uid gid isconf isdoc rdev symlink
# same as stat_info() but takes a precomputed assoc array of md5sums
sub stat_info_array {
    local ( $path, $isconf, $isdoc, *md5sum_array ) = @_;
    local ( $md5, $link, $res );

    if ($rpm{'root'}) {
	$path = $rpm{'root'} . $path;
    }

    local ( $dev, $ino, $mode, $nlink, $uid, $gid, $rdev, $size,
	   $atime, $mtime, $ctime, $blksize, $blocks ) = lstat($path);

    if (! $mode) {
	return "missing";
    }
    
    $md5 = 0;
    $link = "X";
    if (-l $path) {
	$link = readlink($path);
    } else {
	if (-f $path) {
	    if (! ($md5 = $md5sum_array{$path})) {
		$md5 = &md5($path);
	    }
	}
    }
	
    $res = sprintf ("%d %d %s %o %d %d %d %d %x %s", $size, $mtime, $md5, $mode, $uid, $gid, $isconf, $isdoc, $rdev, $link);

    return $res;
}

sub md5sum_array {
    local ( *list, *result, $fail ) = @_;
    local ( $args, $a, $f, $md5, $path );

    &debug("ENTERING: md5sum_array()");

    # Build the arg array
    undef($args);
    undef($result);
    foreach $path (@list) {
	$a = $path;
	if ($rpm{'root'}) {
	    $a = $rpm{'root'} . $a;
	}
	if (! -e $a) {
	    if ($fail) {
		&error("file $a does not exist");
	    } else {
		next;
	    }
	};
	if (-f $a) { $args .= "$a "; }
    }

    if (! $args) {
	return;
    }

    # Call md5sum
    open(MD5, "md5sum $args |");
    while (<MD5>) {
	chop;
#	&debug("$_");
	($md5, $f) = split;
	$result{$f} = $md5;
    }
    close MD5;

    &debug("EXITING: md5sum_array()");
}

sub by_number {
    return -1 if ($a < $b);
    return 0 if ($a == $b);
    return 1 if ($a > $b);
}

$PACK_MAGIC     = pack("CC", 0037, 0036); # packed files
$GZIP_MAGIC     = pack("CC", 0037, 0213); # gzip files, 1F 8B
$OLD_GZIP_MAGIC = pack("CC", 0037, 0236); # gzip 0.5 = freeze 1.x
$LZH_MAGIC      = pack("CC", 0037, 0240); # SCO LZH Compress files
$COMPRESS_MAGIC = pack("CC", 0037, 0235); # compress-ed files
$PKZIP_MAGIC    = pack("CCCC", 0120, 0113, 0003, 0004); # pkzip files

sub is_compressed {
    local ( $filename ) = @_;
    local ( $magic );

    &debug("ENTERING: is_compressed()");
    
    open(FD, $filename);
    read(FD, $magic, 4);
    close FD;

    &debug("EXITING: is_compressed()");

    return 1 if (substr($magic, 0, 2) eq $PACK_MAGIC);
    return 1 if (substr($magic, 0, 2) eq $GZIP_MAGIC);
    return 1 if (substr($magic, 0, 2) eq $OLD_GZIP_MAGIC);
    return 1 if (substr($magic, 0, 2) eq $LZH_MAGIC);
    return 1 if (substr($magic, 0, 2) eq $COMPRESS_MAGIC);
    return 1 if (substr($magic, 0, 4) eq $PKZIP_MAGIC);
    return 0;
}

$_tmpname_counter = 0;
@tempname_array = ();
sub tempname {
    $_tmpname_counter++;
    push(@tempname_array, "/tmp/rpm-$$-$_tmpname_counter");
    return "/tmp/rpm-$$-$_tmpname_counter";
}

sub remove_temps {
    local ( $arg );

    &debug("ENTERING: remove_temps()");
    # Some of these can be directories, so we can't just do unlink()
    $arg = join(' ', @tempname_array);
    system("rm -rf $arg");
    &debug("EXITING: remove_temps()");
}

sub rpmglob {
    local ( $_ ) = @_;
    local ( @res ) = ();

    if (/\*/) {
	@res = glob($_);
    } elsif (/\?/) {
	@res = glob($_);
    } else {
	@res = ($_);
    }
    if (@res == ()) {
	return ($_);
    } else {
	return @res;
    }
}

sub md5 {
    local($filename) = @_;

    &debug("computing md5 checksum of $filename");

    pipe(READ, WRITE);
    if (!fork()) {
	close(READ);
	&debug("child execing /usr/bin/md5sum $filename");
	open(STDOUT, ">&WRITE");
	exec "md5sum $filename";
    }

    close(WRITE);

    $line = <READ>;
    chop $line;

    &debug("got $line from md5sum");

    $_ = $line;
    if (/([0-9a-f]+) +(.*)$/) {
	$md5 = $1;
	$file = $2;
	($file eq $filename) || &warning("md5's output looks weird");
	&debug("$file has md5 of $md5");
    } else { die "Bad output from md5sum" };
    close READ;
    wait;
    return $md5;
}

sub stdinlist {
    local (@list);

    while (<STDIN>) {
	chop;
	push(@list, $_);
    }

    return @list;
}

sub member {
    local ( $i, @l ) = @local;

    foreach (@l) {
	return 1 if ($i eq $_);
    }
    return 0;
}

1;
