Welcome to Soft32 Linux Forums!
FAQFAQ    SearchSearch      ProfileProfile    Private MessagesPrivate Messages   Log inLog in

Rewrite of dpkg-divert to C

 
   Soft32 Home -> Linux -> PacKaGe RSS
Next:  alpha 2.6.31.4 mixart gcc ICE  
Author Message
Mikhail Gusarov

External


Since: Dec 02, 2006
Posts: 27



(Msg. 1) Posted: Thu Oct 15, 2009 7:22 pm
Post subject: Rewrite of dpkg-divert to C
Archived from groups: linux>debian>maint>dpkg (more info?)

This patchset adds testsuite for dpkg-divert which is passed by
Perl implementation of dpkg-divert and then replaces Perl
implementation by C implementation which passes the same
testsuite.


--
To UNSUBSCRIBE, email to debian-dpkg-REQUEST.DeleteThis@lists.debian.org
with a subject of "unsubscribe". Trouble? Contact listmaster.DeleteThis@lists.debian.org
Back to top
Login to vote
Mikhail Gusarov

External


Since: Dec 02, 2006
Posts: 27



(Msg. 2) Posted: Thu Oct 15, 2009 7:22 pm
Post subject: [PATCH 2/2] Reimplement dpkg-divert in C [Login to view extended thread Info.]
Archived from groups: per prev. post (more info?)

Also remove dpkg-divert.pl and switch testsuite to
test C implementation of dpkg-divert.
---
scripts/.gitignore | 1 -
scripts/Makefile.am | 2 -
scripts/dpkg-divert.pl | 353 ---------------------
scripts/t/950_dpkg_divert.t | 4 +-
src/.gitignore | 1 +
src/Makefile.am | 11 +-
src/divert.c | 734 +++++++++++++++++++++++++++++++++++++++++++
7 files changed, 747 insertions(+), 359 deletions(-)
delete mode 100755 scripts/dpkg-divert.pl
create mode 100644 src/divert.c

diff --git a/scripts/.gitignore b/scripts/.gitignore
index 3fc292e..7d08324 100644
--- a/scripts/.gitignore
+++ b/scripts/.gitignore
@@ -2,7 +2,6 @@ dpkg-architecture
dpkg-buildpackage
dpkg-checkbuilddeps
dpkg-distaddfile
-dpkg-divert
dpkg-genchanges
dpkg-gencontrol
dpkg-gensymbols
diff --git a/scripts/Makefile.am b/scripts/Makefile.am
index 9b287a0..3eadfb5 100644
--- a/scripts/Makefile.am
+++ b/scripts/Makefile.am
@@ -7,7 +7,6 @@ bin_SCRIPTS = \
dpkg-buildpackage \
dpkg-checkbuilddeps \
dpkg-distaddfile \
- dpkg-divert \
dpkg-genchanges \
dpkg-gencontrol \
dpkg-gensymbols \
@@ -39,7 +38,6 @@ EXTRA_DIST = \
dpkg-scansources.pl \
dpkg-shlibdeps.pl \
dpkg-source.pl \
- dpkg-divert.pl \
dpkg-vendor.pl \
update-alternatives.pl \
changelog/debian.pl \
diff --git a/scripts/dpkg-divert.pl b/scripts/dpkg-divert.pl
deleted file mode 100755
index 0da77de..0000000
--- a/scripts/dpkg-divert.pl
+++ /dev/null
@@ -1,353 +0,0 @@
-#!/usr/bin/perl --
-
-BEGIN { # Work-around for bug #479711 in perl
- $ENV{PERL_DL_NONLAZY} = 1;
-}
-
-use strict;
-use warnings;
-
-use POSIX qw(:errno_h);
-use Dpkg;
-use Dpkg::Gettext;
-
-textdomain("dpkg");
-
-sub version {
- printf _g("Debian %s version %s.\n"), $progname, $version;
-
- printf _g("
-Copyright (C) 1995 Ian Jackson.
-Copyright (C) 2000,2001 Wichert Akkerman.");
-
- printf _g("
-This is free software; see the GNU General Public Licence version 2 or
-later for copying conditions. There is NO warranty.
-");
-}
-
-sub usage {
- printf(_g(
-"Usage: %s [<option> ...] <command>
-
-Commands:
- [--add] <file> add a diversion.
- --remove <file> remove the diversion.
- --list [<glob-pattern>] show file diversions.
- --listpackage <file> show what package diverts the file.
- --truename <file> return the diverted file.
-
-Options:
- --package <package> name of the package whose copy of <file> will not
- be diverted.
- --local all packages' versions are diverted.
- --divert <divert-to> the name used by other packages' versions.
- --rename actually move the file aside (or back).
- --admindir <directory> set the directory with the diversions file.
- --test don't do anything, just demonstrate.
- --quiet quiet operation, minimal output.
- --help show this help message.
- --version show the version.
-
-When adding, default is --local and --divert <original>.distrib.
-When removing, --package or --local and --divert must match if specified.
-Package preinst/postrm scripts should always specify --package and --divert.
-"), $progname);
-}
-
-my $testmode = 0;
-my $dorename = 0;
-my $verbose = 1;
-my $mode = '';
-my $package = undef;
-my $divertto = undef;
-my @contest;
-my @altname;
-my @package;
-my $file;
-$|=1;
-
-
-# FIXME: those should be local.
-my ($rsrc, $rdest);
-my (@ssrc, @sdest);
-
-sub checkmanymodes {
- return unless $mode;
- badusage(sprintf(_g("two commands specified: %s and --%s"), $_, $mode));
-}
-
-while (@ARGV) {
- $_= shift(@ARGV);
- last if m/^--$/;
- if (!m/^-/) {
- unshift(@ARGV,$_); last;
- } elsif (m/^--help$/) {
- usage();
- exit(0);
- } elsif (m/^--version$/) {
- version();
- exit(0);
- } elsif (m/^--test$/) {
- $testmode= 1;
- } elsif (m/^--rename$/) {
- $dorename= 1;
- } elsif (m/^--quiet$/) {
- $verbose= 0;
- } elsif (m/^--local$/) {
- $package= ':';
- } elsif (m/^--add$/) {
- checkmanymodes();
- $mode= 'add';
- } elsif (m/^--remove$/) {
- checkmanymodes();
- $mode= 'remove';
- } elsif (m/^--list$/) {
- checkmanymodes();
- $mode= 'list';
- } elsif (m/^--listpackage$/) {
- checkmanymodes();
- $mode= 'listpackage';
- } elsif (m/^--truename$/) {
- checkmanymodes();
- $mode= 'truename';
- } elsif (m/^--divert$/) {
- @ARGV || badusage(sprintf(_g("--%s needs a divert-to argument"), "divert"));
- $divertto= shift(@ARGV);
- $divertto =~ m/\n/ && badusage(_g("divert-to may not contain newlines"));
- } elsif (m/^--package$/) {
- @ARGV || badusage(sprintf(_g("--%s needs a <package> argument"), "package"));
- $package= shift(@ARGV);
- $package =~ m/\n/ && badusage(_g("package may not contain newlines"));
- } elsif (m/^--admindir$/) {
- @ARGV || badusage(sprintf(_g("--%s needs a <directory> argument"), "admindir"));
- $admindir= shift(@ARGV);
- } else {
- badusage(sprintf(_g("unknown option \`%s'"), $_));
- }
-}
-
-$mode='add' unless $mode;
-
-open(O, "$admindir/diversions") || quit(sprintf(_g("cannot open diversions: %s"), $!));
-while(<O>) {
- s/\n$//; push(@contest,$_);
- $_ = <O>;
- s/\n$// || badfmt(_g("missing altname"));
- push(@altname,$_);
- $_ = <O>;
- s/\n$// || badfmt(_g("missing package"));
- push(@package,$_);
-}
-close(O);
-
-if ($mode eq 'add') {
- @ARGV == 1 || badusage(sprintf(_g("--%s needs a single argument"), "add"));
- $file= $ARGV[0];
- $file =~ m#^/# || badusage(sprintf(_g("filename \"%s\" is not absolute"), $file));
- $file =~ m/\n/ && badusage(_g("file may not contain newlines"));
- -d $file && badusage(_g("Cannot divert directories"));
- $divertto= "$file.distrib" unless defined($divertto);
- $divertto =~ m#^/# || badusage(sprintf(_g("filename \"%s\" is not absolute"), $divertto));
- $package= ':' unless defined($package);
- for (my $i = 0; $i <= $#contest; $i++) {
- if ($contest[$i] eq $file || $altname[$i] eq $file ||
- $contest[$i] eq $divertto || $altname[$i] eq $divertto) {
- if ($contest[$i] eq $file && $altname[$i] eq $divertto &&
- $package[$i] eq $package) {
- printf(_g("Leaving \`%s'")."\n", infon($i)) if $verbose > 0;
- exit(0);
- }
- quit(sprintf(_g("\`%s' clashes with \`%s'"), infoa(), infon($i)));
- }
- }
- push(@contest,$file);
- push(@altname,$divertto);
- push(@package,$package);
- printf(_g("Adding \`%s'")."\n", infon($#contest)) if $verbose > 0;
- checkrename($file, $divertto);
- save();
- dorename($file, $divertto);
- exit(0);
-} elsif ($mode eq 'remove') {
- @ARGV == 1 || badusage(sprintf(_g("--%s needs a single argument"), "remove"));
- $file= $ARGV[0];
- for (my $i = 0; $i <= $#contest; $i++) {
- next unless $file eq $contest[$i];
- quit(sprintf(_g("mismatch on divert-to\n when removing \`%s'\n found \`%s'"), infoa(), infon($i)))
- if defined($divertto) && $altname[$i] ne $divertto;
- quit(sprintf(_g("mismatch on package\n when removing \`%s'\n found \`%s'"), infoa(), infon($i)))
- if defined($package) && $package[$i] ne $package;
- printf(_g("Removing \`%s'")."\n", infon($i)) if $verbose > 0;
- my $orgfile = $contest[$i];
- my $orgdivertto = $altname[$i];
- @contest= (($i > 0 ? @contest[0..$i-1] : ()),
- ($i < $#contest ? @contest[$i+1..$#contest] : ()));
- @altname= (($i > 0 ? @altname[0..$i-1] : ()),
- ($i < $#altname ? @altname[$i+1..$#altname] : ()));
- @package= (($i > 0 ? @package[0..$i-1] : ()),
- ($i < $#package ? @package[$i+1..$#package] : ()));
- checkrename($orgdivertto, $orgfile);
- dorename($orgdivertto, $orgfile);
- save();
- exit(0);
- }
- printf(_g("No diversion \`%s', none removed")."\n", infoa())
- if $verbose > 0;
- exit(0);
-} elsif ($mode eq 'list') {
- my @list;
- my @ilist = @ARGV ? @ARGV : ('*');
- while (defined($_=shift(@ilist))) {
- s/\W/\\$&/g;
- s/\\\?/./g;
- s/\\\*/.*/g;
- push(@list,"^$_\$");
- }
- my $pat = join('|', @list);
- for (my $i = 0; $i <= $#contest; $i++) {
- next unless ($contest[$i] =~ m/$pat/o ||
- $altname[$i] =~ m/$pat/o ||
- $package[$i] =~ m/$pat/o);
- print infon($i), "\n";
- }
- exit(0);
-} elsif ($mode eq 'truename') {
- @ARGV == 1 || badusage(sprintf(_g("--%s needs a single argument"), "truename"));
- $file= $ARGV[0];
- for (my $i = 0; $i <= $#contest; $i++) {
- next unless $file eq $contest[$i];
- print $altname[$i], "\n";
- exit(0);
- }
- print $file, "\n";
- exit(0);
-} elsif ($mode eq 'listpackage') {
- @ARGV == 1 || badusage(sprintf(_g("--%s needs a single argument"), $mode));
- $file= $ARGV[0];
- for (my $i = 0; $i <= $#contest; $i++) {
- next unless $file eq $contest[$i];
- if ($package[$i] eq ':') {
- # indicate package is local using something not in package namespace
- print "LOCAL\n";
- } else {
- print $package[$i], "\n";
- }
- exit(0);
- }
- # print nothing if file is not diverted
- exit(0);
-} else {
- quit(sprintf(_g("internal error - bad mode \`%s'"), $mode));
-}
-
-sub infol {
- return ((defined($_[2]) ? ($_[2] eq ':' ? "local " : "") : "any ").
- "diversion of $_[0]".
- (defined($_[1]) ? " to $_[1]" : "").
- (defined($_[2]) && $_[2] ne ':' ? " by $_[2]" : ""));
-}
-
-sub checkrename {
- return unless $dorename;
- ($rsrc,$rdest) = @_;
- (@ssrc = lstat($rsrc)) || $! == ENOENT ||
- quit(sprintf(_g("cannot stat old name \`%s': %s"), $rsrc, $!));
- (@sdest = lstat($rdest)) || $! == ENOENT ||
- quit(sprintf(_g("cannot stat new name \`%s': %s"), $rdest, $!));
- # Unfortunately we have to check for write access in both
- # places, just having +w is not enough, since people do
- # mount things RO, and we need to fail before we start
- # mucking around with things. So we open a file with the
- # same name as the diversions but with an extension that
- # (hopefully) wont overwrite anything. If it succeeds, we
- # assume a writable filesystem.
- if (open (TMP, ">>", "${rsrc}.dpkg-devert.tmp")) {
- close TMP;
- unlink ("${rsrc}.dpkg-devert.tmp");
- } elsif ($! == ENOENT) {
- $dorename = !$dorename;
- # If the source file is not present and we are not going to do the
- # rename anyway there's no point in checking the target.
- return;
- } else {
- quit(sprintf(_g("error checking \`%s': %s"), $rsrc, $!));
- }
-
- if (open (TMP, ">>", "${rdest}.dpkg-devert.tmp")) {
- close TMP;
- unlink ("${rdest}.dpkg-devert.tmp");
- } else {
- quit(sprintf(_g("error checking \`%s': %s"), $rdest, $!));
- }
- if (@ssrc && @sdest &&
- !($ssrc[0] == $sdest[0] && $ssrc[1] == $sdest[1])) {
- quit(sprintf(_g("rename involves overwriting \`%s' with\n".
- " different file \`%s', not allowed"), $rdest, $rsrc));
- }
-}
-
-sub rename_mv($$)
-{
- return (rename($_[0], $_[1]) || (system(("mv", $_[0], $_[1])) == 0));
-}
-
-sub dorename {
- return unless $dorename;
- return if $testmode;
- if (@ssrc) {
- if (@sdest) {
- unlink($rsrc) || quit(sprintf(_g("rename: remove duplicate old link \`%s': %s"), $rsrc, $!));
- } else {
- rename_mv($rsrc, $rdest) ||
- quit(sprintf(_g("rename: rename \`%s' to \`%s': %s"), $rsrc, $rdest, $!));
- }
- }
-}
-
-sub save {
- return if $testmode;
- open(N, "> $admindir/diversions-new") || quit(sprintf(_g("create diversions-new: %s"), $!));
- chmod 0644, "$admindir/diversions-new";
- for (my $i = 0; $i <= $#contest; $i++) {
- print(N "$contest[$i]\n$altname[$i]\n$package[$i]\n")
- || quit(sprintf(_g("write diversions-new: %s"), $!));
- }
- close(N) || quit(sprintf(_g("close diversions-new: %s"), $!));
- unlink("$admindir/diversions-old") ||
- $! == ENOENT || quit(sprintf(_g("remove old diversions-old: %s"), $!));
- link("$admindir/diversions","$admindir/diversions-old") ||
- $! == ENOENT || quit(sprintf(_g("create new diversions-old: %s"), $!));
- rename("$admindir/diversions-new","$admindir/diversions")
- || quit(sprintf(_g("install new diversions: %s"), $!));
-}
-
-sub infoa
-{
- infol($file, $divertto, $package);
-}
-
-sub infon
-{
- my $i = shift;
- infol($contest[$i], $altname[$i], $package[$i]);
-}
-
-sub quit
-{
- printf STDERR "%s: %s\n", $progname, "@_";
- exit(2);
-}
-
-sub badusage
-{
- printf STDERR "%s: %s\n\n", $progname, "@_";
- usage();
- exit(2);
-}
-
-sub badfmt
-{
- quit(sprintf(_g("internal error: %s corrupt: %s"), "$admindir/diversions", $_[0]));
-}
-
diff --git a/scripts/t/950_dpkg_divert.t b/scripts/t/950_dpkg_divert.t
index df96849..2b82766 100644
--- a/scripts/t/950_dpkg_divert.t
+++ b/scripts/t/950_dpkg_divert.t
@@ -11,8 +11,8 @@ my $srcdir = $ENV{srcdir} || '.';
my $admindir = File::Spec->rel2abs('t.tmp/dpkg-divert/admindir');
my $testdir = File::Spec->rel2abs('t.tmp/dpkg-divert/testdir');

-my @dd = ("perl", "$srcdir/dpkg-divert.pl");
-#my @dd = ("$srcdir/../src/dpkg-divert");
+#my @dd = ("perl", "$srcdir/dpkg-divert.pl");
+my @dd = ("$srcdir/../src/dpkg-divert");

plan tests => 248;

diff --git a/src/.gitignore b/src/.gitignore
index 10f60e9..8a6411e 100644
--- a/src/.gitignore
+++ b/src/.gitignore
@@ -2,3 +2,4 @@ dpkg
dpkg-query
dpkg-statoverride
dpkg-trigger
+dpkg-divert
diff --git a/src/Makefile.am b/src/Makefile.am
index a29b629..0971482 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -15,7 +15,8 @@ bin_PROGRAMS = \
dpkg \
dpkg-query \
dpkg-statoverride \
- dpkg-trigger
+ dpkg-trigger \
+ dpkg-divert

dpkg_SOURCES = \
archives.c archives.h \
@@ -74,6 +75,14 @@ dpkg_trigger_LDADD = \
../lib/compat/libcompat.a \
$(LIBINTL)

+dpkg_divert_SOURCES = \
+ divert.c
+
+dpkg_divert_LDADD = \
+ ../lib/dpkg/libdpkg.a \
+ ../lib/compat/libcompat.a \
+ $(LIBINTL)
+
install-data-local:
$(mkdir_p) $(DESTDIR)$(pkgconfdir)/dpkg.cfg.d
$(mkdir_p) $(DESTDIR)$(admindir)/alternatives
diff --git a/src/divert.c b/src/divert.c
new file mode 100644
index 0000000..6fb8a25
--- /dev/null
+++ b/src/divert.c
@@ -0,0 +1,734 @@
+/*
+ * dpkg - main program for package management
+ * divert.c - implementation of dpkg-divert(Cool
+ *
+ * Copyright © 2009 Mikhail Gusarov
+ *
+ * This 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,
+ * or (at your option) any later version.
+ *
+ * This 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 dpkg; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <config.h>
+#include <compat.h>
+
+#include <getopt.h>
+#include <fnmatch.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+
+#include <dpkg/dpkg.h>
+#include <dpkg/i18n.h>
+#include <dpkg/dpkg-db.h>
+
+const char thisname[]= "dpkg-divert";
+
+static int quiet;
+static int testmode;
+static int dorename_;
+static const char *divertto;
+static const char *package;
+static const char *admindir;
+
+typedef struct _diversion {
+ const char *contest;
+ const char *altname;
+ const char *package;
+ struct _diversion *next;
+} diversion;
+
+static void
+usage()
+{
+ printf(_(
+"Usage: %s [<option> ...] <command>\n"
+"\n"
+"Commands:\n"
+" [--add] <file> add a diversion.\n"
+" --remove <file> remove the diversion.\n"
+" --list [<glob-pattern>] show file diversions.\n"
+" --listpackage <file> show what package diverts the file.\n"
+" --truename <file> return the diverted file.\n"
+"\n"
+"Options:\n"
+" --package <package> name of the package whose copy of <file> will not\n"
+" be diverted.\n"
+" --local all packages' versions are diverted.\n"
+" --divert <divert-to> the name used by other packages' versions.\n"
+" --rename actually move the file aside (or back).\n"
+" --admindir <directory> set the directory with the diversions file.\n"
+" --test don't do anything, just demonstrate.\n"
+" --quiet quiet operation, minimal output.\n"
+" --help show this help message.\n"
+" --version show the version.\n"
+"\n"
+"When adding, default is --local and --divert <original>.distrib.\n"
+"When removing, --package or --local and --divert must match if specified.\n"
+"Package preinst/postrm scripts should always specify --package and --divert.\n"
+ ), thisname;
+}
+
+static void
+badusage(const char *fmt, ...)
+{
+ if (fmt) {
+ fprintf(stderr, "%s: ", thisname);
+ va_list arg;
+ va_start(arg, fmt);
+ vfprintf(stderr, fmt, arg);
+ va_end(arg);
+ fprintf(stderr, "\n\n");
+ }
+ usage();
+ exit(2);
+}
+
+static void
+infol(const char *file, const char *divertto, const char *package,
+ struct varbuf *ret)
+{
+ if (package) {
+ if (strcmp(package, ":") == 0)
+ varbufaddstr(ret, "local ");
+ }
+ else
+ varbufaddstr(ret, "any ");
+
+ varbufaddstr(ret, "diversion of ");
+ varbufaddstr(ret, file);
+
+ if (divertto) {
+ varbufaddstr(ret, " to ");
+ varbufaddstr(ret, divertto);
+ }
+
+ if (package && strcmp(package, ":") != 0) {
+ varbufaddstr(ret, " by ");
+ varbufaddstr(ret, package);
+ }
+
+ varbufaddc(ret, 0);
+}
+
+
+/* Returned value will be overwritten by next call to infoa() */
+static const char *
+infoa(const char *file)
+{
+ static struct varbuf ret;
+ varbufreset(&ret);
+ infol(file, divertto, package, &ret);
+ return ret.buf;
+}
+
+/* Returned value will be overwritten by next call to infon() */
+static const char *
+infon(const diversion *d)
+{
+ static struct varbuf ret;
+ varbufreset(&ret);
+ infol(d->contest, d->altname, d->package, &ret);
+ return ret.buf;
+}
+
+static void
+checkrename(const char *rsrc, const char *rdest)
+{
+ struct stat ssrc;
+ struct stat sdest;
+ int has_src;
+ int has_dest;
+ static struct varbuf tmpfilename;
+ int tmpfile;
+
+ if (!dorename_) return;
+
+ has_src = !lstat(rsrc, &ssrc);
+ if (!has_src && errno != ENOENT)
+ ohshite(_("cannot stat old name '%s'"), rsrc);
+ has_dest = !lstat(rdest, &sdest);
+ if (!has_dest && errno != ENOENT)
+ ohshite(_("cannot state new name '%s'"), rdest);
+
+ /* Unfortunately we have to check for write access in both places, just
+ * having +w is not enough, since people do mount things RO, and we need
+ * to fail before we start mucking around with things. So we open a file
+ * with the same name as the diversions but with an extension that
+ * (hopefully) wont overwrite anything. If it succeeds, we assume a
+ * writable filesystem.
+ */
+
+ varbufreset(&tmpfilename);
+ varbufaddstr(&tmpfilename, rsrc);
+ varbufaddstr(&tmpfilename, ".dpkg-devert.tmp");
+ varbufaddc(&tmpfilename, 0);
+
+ tmpfile = open(tmpfilename.buf, O_WRONLY | O_CREAT);
+ if (tmpfile != -1) {
+ unlink(tmpfilename.buf);
+ close(tmpfile);
+ }
+ else if (errno == ENOENT) {
+ dorename_ = 0;
+ /* If the source file is not present and we are not going to do
+ the rename anyway there's no point in checking the target. */
+ return;
+ }
+ else
+ ohshite(_("error checking '%s'"), rsrc);
+
+ varbufreset(&tmpfilename);
+ varbufaddstr(&tmpfilename, rdest);
+ varbufaddstr(&tmpfilename, ".dpkg-devert.tmp");
+ varbufaddc(&tmpfilename, 0);
+
+ tmpfile = open(tmpfilename.buf, O_WRONLY | O_CREAT);
+ if (tmpfile != -1) {
+ unlink(tmpfilename.buf);
+ close(tmpfile);
+ }
+ else
+ ohshite(_("error checking '%s'"), rdest);
+
+ if (has_src && has_dest &&
+ !(ssrc.st_dev == sdest.st_dev && ssrc.st_ino == sdest.st_ino)) {
+ ohshite(_("rename involves overwriting '%s' with \n"
+ " different file '%s', not allowed"), rdest, rsrc);
+ }
+}
+
+static int
+rename_mv(const char *src, const char *dest)
+{
+ pid_t pid;
+
+ if (rename(src, dest) == 0)
+ return 0;
+
+ pid = fork();
+ if(pid == -1)
+ return -1;
+
+ if (!pid) {
+ /* child */
+ execlp("mv", "mv", src, dest, NULL);
+ exit(EXIT_FAILURE);
+ }
+
+ /* parent */
+ int status;
+ if(waitpid(pid, &status, 0) == -1)
+ return -1;
+
+ return !(WIFEXITED(status) && WEXITSTATUS(status) == 0);
+}
+
+static void
+dorename(const char *rsrc, const char *rdest)
+{
+ if (!dorename_) return;
+ if (testmode) return;
+
+ struct stat ssrc;
+ struct stat sdest;
+
+ int has_src = !lstat(rsrc, &ssrc);
+ int has_dest = !lstat(rdest, &sdest);
+
+ if (!has_src) return;
+
+ if (has_dest) {
+ if (-1 == unlink(rsrc))
+ ohshite(_("rename: remove duplicate old link '%s'"),
+ rsrc);
+ } else {
+ if (-1 == rename_mv(rsrc, rdest))
+ ohshite(_("rename: rename '%s' to '%s'"), rsrc, rdest);
+ }
+}
+
+static void
+save(diversion *diversions)
+{
+ diversion *d;
+ static struct varbuf filename;
+ static struct varbuf new_filename;
+ static struct varbuf old_filename;
+ FILE *new_file;
+
+ if (testmode) return;
+
+ varbufreset(&new_filename);
+ varbufaddstr(&new_filename, admindir);
+ varbufaddstr(&new_filename, "/" DIVERSIONSFILE "-new");
+ varbufaddc(&new_filename, 0);
+ new_file = fopen(new_filename.buf, "w");
+ if (!new_file)
+ ohshite(_("create diversions-new"));
+ chmod(new_filename.buf, 0644);
+
+ for (d = diversions; d; d = d->next)
+ {
+ if (fprintf(new_file, "%s\n%s\n%s\n",
+ d->contest,
+ d->altname,
+ d->package) < 0)
+ ohshite(_("write diversions-new"));
+ }
+
+ if (fclose(new_file) == EOF)
+ ohshite(_("close diversions-new"));
+
+ varbufreset(&old_filename);
+ varbufaddstr(&old_filename, admindir);
+ varbufaddstr(&old_filename, "/" DIVERSIONSFILE "-old");
+ varbufaddc(&old_filename, 0);
+
+ if (unlink(old_filename.buf) != 0 && errno != ENOENT)
+ ohshite(_("remove old diversions-old"));
+
+ varbufreset(&filename);
+ varbufaddstr(&filename, admindir);
+ varbufaddstr(&filename, "/" DIVERSIONSFILE);
+ varbufaddc(&filename, 0);
+
+ if (link(filename.buf, old_filename.buf) != 0 && errno != ENOENT)
+ ohshite(_("create new diversions-old"));
+
+ if (rename(new_filename.buf, filename.buf) != 0)
+ ohshite(_("install new diversions"));
+}
+
+static void
+chomp(char *s)
+{
+ for (; *s; s++)
+ if (*s == '\n') {
+ *s = 0;
+ return;
+ }
+}
+
+static diversion *
+invert_diversions_list(diversion *diversions)
+{
+ diversion *n = NULL;
+ while (diversions)
+ {
+ diversion *newhead = diversions;
+ diversions = newhead->next;
+ newhead->next = n;
+ n = newhead;
+ }
+ return n;
+}
+
+static diversion *
+read_diversions()
+{
+ diversion *diversions = NULL;
+ char linebuf[MAXDIVERTFILENAME];
+
+ static struct varbuf vb;
+ varbufreset(&vb);
+ varbufaddstr(&vb, admindir);
+ varbufaddstr(&vb, "/" DIVERSIONSFILE);
+ varbufaddc(&vb, 0);
+
+ FILE *file = fopen(vb.buf, "r");
+ if (!file)
+ ohshite(_("failed to open diversions file"));
+
+ for (;Wink
+ {
+ diversion *next = nfmalloc(sizeof(diversion));
+
+ if (fgets_checked(linebuf, sizeof(linebuf), file, vb.buf) < 0)
+ break;
+ chomp(linebuf);
+ next->contest = strdup(linebuf);
+ fgets_must(linebuf, sizeof(linebuf), file, vb.buf);
+ chomp(linebuf);
+ next->altname = strdup(linebuf);
+ fgets_must(linebuf, sizeof(linebuf), file, vb.buf);
+ chomp(linebuf);
+ next->package = strdup(linebuf);
+
+ next->next = diversions;
+ diversions = next;
+ }
+
+ fclose(file);
+
+ return invert_diversions_list(diversions);
+}
+
+static diversion *diversions_remove(diversion *diversions, diversion *d)
+{
+ diversion *c;
+
+ if (d == diversions)
+ return diversions->next;
+
+ c = diversions;
+ while (c && c->next != d)
+ c = c->next;
+
+ if (!c)
+ ohshit(_("Internal error: trying to remove non-existent diversion"));
+
+ c->next = d->next;
+ d->next = NULL;
+ return diversions;
+}
+
+static int
+match_diversion(diversion *diversion, char *const *patterns)
+{
+ for (; *patterns; patterns++) {
+ if(!fnmatch(*patterns, diversion->contest, FNM_NOESCAPE))
+ return 0;
+ if(!fnmatch(*patterns, diversion->altname, FNM_NOESCAPE))
+ return 0;
+ if(!fnmatch(*patterns, diversion->package, FNM_NOESCAPE))
+ return 0;
+ }
+ return -1;
+}
+
+static void
+op_add(diversion *diversions, const char *file)
+{
+ diversion *d;
+
+ if (file[0] != '/')
+ badusage(_("filename \"%s\" is not absolute"), file);
+ if (strchr(file, '\n'))
+ badusage(_("filename may not contain newlines"));
+ struct stat file_stat;
+ if (stat(file, &file_stat) == 0 && S_ISDIR(file_stat.st_mode))
+ badusage(_("Cannot divert directories"));
+
+ if (!divertto) {
+ static struct varbuf vb;
+ varbufreset(&vb);
+ varbufaddstr(&vb, file);
+ varbufaddstr(&vb, ".distrib");
+ divertto = vb.buf;
+ }
+
+ if (divertto[0] != '/')
+ badusage(_("filename \"%s\" is not absolute"), divertto);
+
+ if (!package)
+ package = ":";
+
+ diversions = invert_diversions_list(diversions);
+
+ for (d = diversions; d; d = d->next) {
+ if (strcmp(d->contest, file) == 0 ||
+ strcmp(d->altname, file) == 0 ||
+ strcmp(d->contest, divertto) == 0 ||
+ strcmp(d->altname, divertto) == 0) {
+ if (strcmp(d->contest, file) == 0 &&
+ strcmp(d->altname, divertto) == 0 &&
+ strcmp(d->package, package) == 0) {
+ if (!quiet)
+ printf(_("Leaving '%s'\n"), infon(d));
+ exit(0);
+ }
+ else
+ ohshit(_("'%s' clashes with '%s'"), infoa(file),
+ infon(d));
+ }
+ }
+
+ d = nfmalloc(sizeof(diversion));
+ d->contest = file;
+ d->altname = divertto;
+ d->package = package;
+ d->next = diversions;
+ diversions = d;
+
+ diversions = invert_diversions_list(diversions);
+
+ if (!quiet)
+ printf(_("Adding '%s'"), infon(d));
+
+ checkrename(file, divertto);
+ save(diversions);
+ dorename(file, divertto);
+ exit(0);
+}
+
+static void
+op_remove(diversion *diversions, const char *file)
+{
+ diversion *d;
+ for (d = diversions; d; d = d->next) {
+ if (strcmp(d->contest, file) == 0) {
+ if (divertto && strcmp(d->altname, divertto) != 0)
+ ohshit(_("mismatch on divert-to\n"
+ "when removing '%s'\n"
+ "found '%s"), infoa(file), infon(d));
+ if (package && strcmp(d->package, package) != 0)
+ ohshit(_("mismatch on package\n"
+ "when removing '%s'\n"
+ "found '%s'"), infoa(file), infon(d));
+ if (!quiet)
+ printf(_("Removing '%s'\n"), infon(d));
+
+ checkrename(d->altname, d->contest);
+ dorename(d->altname, d->contest);
+
+ diversions = diversions_remove(diversions, d);
+ save(diversions);
+ exit(0);
+ }
+ }
+
+ if (!quiet) {
+ printf(_("No diversion '%s', none removed"), infoa(file));
+ putchar('\n');
+ }
+ exit(0);
+}
+
+static void
+op_list(diversion *diversions, char *const *patterns)
+{
+ diversion *d;
+ for (d = diversions; d; d = d->next)
+ if (match_diversion(d, patterns) == 0)
+ printf("%s\n", infon(d));
+
+ exit(0);
+}
+
+static void
+op_truename(diversion *diversions, const char *file)
+{
+ diversion *d;
+ for (d = diversions; d; d = d->next)
+ if (strcmp(d->contest, file) == 0) {
+ printf("%s\n", d->altname);
+ exit(0);
+ }
+
+ printf("%s\n", file);
+ exit(0);
+}
+
+static void
+op_listpackage(diversion *diversions, const char *file)
+{
+ diversion *d;
+ for (d = diversions; d; d = d->next) {
+ if (strcmp(d->contest, file) == 0) {
+ if (strcmp(d->package, ":") == 0) {
+ /* indicate package is local using something not
+ * in package namespace */
+ printf("LOCAL\n");
+ }
+ else
+ printf("%s\n", d->package);
+ exit(0);
+ }
+ }
+ /* print nothing if file is not diverted */
+ exit(0);
+}
+
+static void
+version()
+{
+ printf(_("Debian %s version %s.\n"), thisname, DPKG_VERSION_ARCH);
+ puts(_("\n"
+ "Copyright (C) 1995 Ian Jackson.\n"
+ "Copyright (C) 2000,2001 Wichert Akkerman.\n"
+ "Copyright (C) 2009 Mikhail Gusarov."));
+ puts(_("This is free software; see the GNU General Public Licence "
+ "version 2 or\n"
+ "later for copying conditions. There is NO warranty."));
+}
+
+typedef enum {
+ OPT_ADD = 1,
+ OPT_REMOVE,
+ OPT_LIST,
+ OPT_LISTPACKAGE,
+ OPT_TRUENAME,
+ OPT_PACKAGE,
+ OPT_LOCAL,
+ OPT_DIVERT,
+ OPT_RENAME,
+ OPT_ADMINDIR,
+ OPT_TEST,
+ OPT_QUIET,
+ OPT_HELP,
+ OPT_VERSION,
+} options;
+
+static struct option long_options[] = {
+ { "add", no_argument, NULL, OPT_ADD },
+ { "remove", no_argument, NULL, OPT_REMOVE },
+ { "list", no_argument, NULL, OPT_LIST },
+ { "listpackage", no_argument, NULL, OPT_LISTPACKAGE },
+ { "truename", no_argument, NULL, OPT_TRUENAME },
+
+ { "package", required_argument, NULL, OPT_PACKAGE },
+ { "local", no_argument, NULL, OPT_LOCAL },
+ { "divert", required_argument, NULL, OPT_DIVERT },
+ { "rename", no_argument, NULL, OPT_RENAME },
+ { "admindir", required_argument, NULL, OPT_ADMINDIR },
+ { "test", no_argument, NULL, OPT_TEST },
+ { "quiet", no_argument, NULL, OPT_QUIET },
+ { "help", no_argument, NULL, OPT_HELP },
+ { "version", no_argument, NULL, OPT_VERSION },
+ { NULL, 0, NULL, 0 },
+};
+
+static void
+checkmanymodes(const char *curmode, const char *newmode)
+{
+ if (!curmode)
+ return;
+ badusage(_("two commands specified: --%s and --%s"), newmode, curmode);
+}
+
+int
+main(int argc, char *const *argv)
+{
+ jmp_buf ejbuf;
+
+ standard_startup(&ejbuf);
+
+ const char *mode = NULL;
+ admindir = ADMINDIR;
+
+ int opt;
+ while ((opt = getopt_long(argc, argv, ":", long_options, NULL)) != -1) {
+ switch (opt) {
+ case OPT_HELP:
+ usage();
+ return 0;
+ case OPT_VERSION:
+ version();
+ return 0;
+ case OPT_TEST:
+ testmode = 1;
+ break;
+ case OPT_RENAME:
+ dorename_ = 1;
+ break;
+ case OPT_QUIET:
+ quiet = 1;
+ break;
+ case OPT_LOCAL:
+ package = ":";
+ break;
+ case OPT_ADD:
+ checkmanymodes(mode, "add");
+ mode = "add";
+ break;
+ case OPT_REMOVE:
+ checkmanymodes(mode, "remove");
+ mode = "remove";
+ break;
+ case OPT_LIST:
+ checkmanymodes(mode, "list");
+ mode = "list";
+ break;
+ case OPT_LISTPACKAGE:
+ checkmanymodes(mode, "listpackage");
+ mode = "listpackage";
+ break;
+ case OPT_TRUENAME:
+ checkmanymodes(mode, "truename");
+ mode = "truename";
+ break;
+ case OPT_DIVERT:
+ if(strchr(optarg, '\n'))
+ badusage(_("divert-to may not contain newlines"));
+ divertto = optarg;
+ break;
+ case OPT_PACKAGE:
+ if(strchr(optarg, '\n'))
+ badusage(_("package may not contain newlines"));
+ package = optarg;
+ break;
+ case OPT_ADMINDIR:
+ admindir = optarg;
+ break;
+ case ':':
+ if(optopt == OPT_DIVERT)
+ badusage(_("--divert needs a divert-to argument"));
+ if(optopt == OPT_PACKAGE)
+ badusage(_("--package needs a package argument"));
+ if(optopt == OPT_ADMINDIR)
+ badusage(_("--admindir needs an admindir argument"));
+ ohshit(_("internal error: unknown option %d"), optopt);
+ default:
+ badusage(_("unknown option '%s'"), argv[optind]);
+ }
+ }
+
+ diversion* diversions = read_diversions();
+
+ if (!mode || !strcmp(mode, "add")) {
+ if (optind != argc - 1)
+ badusage(_("--%s needs a single argument"), "add");
+ op_add(diversions, argv[optind]);
+ }
+ if (!strcmp(mode, "remove")) {
+ if (optind != argc - 1)
+ badusage(_("--%s needs a single argument"), "remove");
+ op_remove(diversions, argv[optind]);
+ }
+ if (!strcmp(mode, "list")) {
+ if (optind >= argc) {
+ char *const null_pattern[] = { "*", NULL };
+ op_list(diversions, null_pattern);
+ } else {
+ op_list(diversions, argv + optind);
+ }
+ }
+
+ if (!strcmp(mode, "truename")) {
+ if (optind != argc - 1)
+ badusage(_("--%s needs a single argument"), mode);
+ op_truename(diversions, argv[optind]);
+ }
+
+ if (!strcmp(mode, "listpackage")) {
+ if (optind != argc - 1)
+ badusage(_("--%s needs a single argument"), mode);
+ op_listpackage(diversions, argv[optind]);
+ }
+
+ ohshit(_("internal error - bad mode '%s'"), mode);
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-file-style: "linux"
+ * c-basic-offset: 8
+ * tab-width: 8
+ * indent-tabs-mode: t
+ * End:
+ */
--
1.6.3.3


--
To UNSUBSCRIBE, email to debian-dpkg-REQUEST DeleteThis @lists.debian.org
with a subject of "unsubscribe". Trouble? Contact listmaster DeleteThis @lists.debian.org
Back to top
Login to vote
Mikhail Gusarov

External


Since: Dec 02, 2006
Posts: 27



(Msg. 3) Posted: Thu Oct 15, 2009 7:22 pm
Post subject: [PATCH 1/2] Add new testsuite for dpkg-divert [Login to view extended thread Info.]
Archived from groups: per prev. post (more info?)

Devel::Cover reports 97% coverage. Remaining branches is hard-to-test
without root privileges error handling.
---
scripts/t/950_dpkg_divert.t | 497 +++++++++++++++++++++++++++++++++++++++++++
1 files changed, 497 insertions(+), 0 deletions(-)
create mode 100644 scripts/t/950_dpkg_divert.t

diff --git a/scripts/t/950_dpkg_divert.t b/scripts/t/950_dpkg_divert.t
new file mode 100644
index 0000000..df96849
--- /dev/null
+++ b/scripts/t/950_dpkg_divert.t
@@ -0,0 +1,497 @@
+#!/usr/bin/perl
+# -*- mode: cperl; cperl-indent-level: 4; -*-
+use Test::More;
+use File::Spec;
+use Dpkg::IPC;
+
+use strict;
+use warnings;
+
+my $srcdir = $ENV{srcdir} || '.';
+my $admindir = File::Spec->rel2abs('t.tmp/dpkg-divert/admindir');
+my $testdir = File::Spec->rel2abs('t.tmp/dpkg-divert/testdir');
+
+my @dd = ("perl", "$srcdir/dpkg-divert.pl");
+#my @dd = ("$srcdir/../src/dpkg-divert");
+
+plan tests => 248;
+
+sub cleanup {
+ system("rm -rf t.tmp/dpkg-divert && mkdir -p $admindir && mkdir -p $testdir");
+}
+
+sub install_diversions {
+ my ($txt) = @_;
+ open(O, "> $admindir/diversions");
+ print O $txt;
+ close(O);
+}
+
+sub call {
+ my ($prog, $args, %opts) = @_;
+
+ my ($output, $error);
+ fork_and_exec(exec => [@$prog, @$args], wait_child => 1, nocheck => 1,
+ to_pipe => \$output, error_to_pipe => \$error, %opts);
+
+ if ($opts{'expect_failure'}) {
+ ok($? != 0, "@$args should fail");
+ } else {
+ ok($? == 0, "@$args should not fail");
+ }
+
+ if (defined $opts{'expect_stdout'}) {
+ is(join('', <$output>), $opts{'expect_stdout'}, "@$args stdout");
+ }
+ if (defined $opts{'expect_stdout_like'}) {
+ like(join('', <$output>), $opts{'expect_stdout_like'}, "@$args stdout");
+ }
+ if (defined $opts{'expect_stderr'}) {
+ is(join('', <$error>), $opts{'expect_stderr'}, "@$args stderr");
+ }
+ if (defined $opts{'expect_stderr_like'}) {
+ like(join('', <$error>), $opts{'expect_stderr_like'}, "@$args stderr");
+ }
+
+ close($output);
+ close($error);
+}
+
+sub call_divert {
+ my ($params, %opts) = @_;
+ call([@dd, '--admindir', $admindir], $params, %opts);
+}
+
+sub diversions_eq {
+ my ($expected) = @_;
+ open(O, "$admindir/diversions");
+ my ($contents) = join '', <O>;
+ close(O);
+ is($contents, $expected, "diversions contents");
+}
+
+### Tests
+
+cleanup();
+
+diag("Command line parsing testing");
+
+my $usagere = qr/.*Usage.*dpkg-divert.*Commands.*Options.*/s;
+
+sub call_divert_badusage {
+ my ($args, $err) = @_;
+ call_divert($args, expect_failure => 1, expect_stdout_like => $usagere, expect_stderr_like => $err);
+}
+
+call_divert(['--help'], expect_stdout_like => $usagere,
+ expect_stderr => '');
+call_divert(['--version'], expect_stdout_like => qr/.*dpkg-divert.*Copyright.*free software.*/s,
+ expect_stderr => '');
+
+call_divert_badusage(['--jachsmitbju'], qr/unknown option/);
+call_divert_badusage(['--add', '--remove'], qr/.*two.*remove.*add.*/s);
+call_divert_badusage(['--divert'], qr/needs.*argument/);
+call_divert_badusage(['--divert', "foo\nbar"], qr/newline/);
+call_divert_badusage(['--package'], qr/needs.*argument/);
+call_divert_badusage(['--package', "foo\nbar"], qr/newline/);
+
+install_diversions('');
+
+call_divert_badusage(['--add',], qr/needs a single argument/);
+call_divert_badusage(['--add', 'foo'], qr/absolute/);
+call_divert_badusage(['--add', "/foo\nbar"], qr/newline/);
+call_divert_badusage(['--add', "/etc"], qr/director(y|ies)/);
+call_divert_badusage(['--add', "--divert", "bar", "/foo/bar"], qr/absolute/);
+call_divert_badusage(['--remove'], qr/needs a single argument/);
+call([@dd, '--admindir'], [], expect_failure => 1, expect_stderr_like => qr/needs.*argument/,
+ expect_stdout_like => $usagere);
+
+cleanup();
+
+diag("Querying information from diverts db (empty one)");
+
+install_diversions('');
+
+call_divert(['--list'], expect_stdout => '', expect_stderr => '');
+call_divert(['--list', '*'], expect_stdout => '', expect_stderr => '');
+call_divert(['--list', 'baz'], expect_stdout => '', expect_stderr => '');
+
+cleanup();
+
+diag("Querying information from diverts db (1)");
+
+install_diversions(<<EOF);
+/bin/sh
+/bin/sh.distrib
+dash
+/usr/share/man/man1/sh.1.gz
+/usr/share/man/man1/sh.distrib.1.gz
+dash
+/usr/bin/nm
+/usr/bin/nm.single
+binutils-multiarch
+EOF
+
+my $di_dash = "diversion of /bin/sh to /bin/sh.distrib by dash\n";
+my $di_dashman = "diversion of /usr/share/man/man1/sh.1.gz to /usr/share/man/man1/sh.distrib.1.gz by dash\n";
+my $di_nm = "diversion of /usr/bin/nm to /usr/bin/nm.single by binutils-multiarch\n";
+
+my $all_di = $di_dash . $di_dashman . $di_nm;
+
+call_divert(['--list'], expect_stdout => $all_di, expect_stderr => '');
+call_divert(['--list', '*'], expect_stdout => $all_di, expect_stderr => '');
+call_divert(['--list', ''], expect_stdout => '', expect_stderr => '');
+
+call_divert(['--list', '???????'], expect_stdout => $di_dash, expect_stderr => '');
+call_divert(['--list', '*/sh'], expect_stdout => $di_dash, expect_stderr => '');
+call_divert(['--list', '/bin/*'], expect_stdout => $di_dash, expect_stderr => '');
+call_divert(['--list', 'binutils-multiarch'], expect_stdout => $di_nm, expect_stderr => '');
+call_divert(['--list', '/bin/sh'], expect_stdout => $di_dash, expect_stderr => '');
+call_divert(['--list', '--', '/bin/sh'], expect_stdout => $di_dash, expect_stderr => '');
+call_divert(['--list', '/usr/bin/nm.single'], expect_stdout => $di_nm, expect_stderr => '');
+call_divert(['--list', '/bin/sh', '/usr/share/man/man1/sh.1.gz'], expect_stdout => $di_dash . $di_dashman,
+ expect_stderr => '');
+
+cleanup();
+
+diag("Querying information from diverts db (2)");
+
+install_diversions(<<EOF);
+/bin/sh
+/bin/sh.distrib
+dash
+/bin/true
+/bin/true.coreutils
+:
+EOF
+
+call_divert(['--listpackage'], expect_failure => 1);
+call_divert(['--listpackage', 'foo', 'bar'], expect_failure => 1);
+call_divert(['--listpackage', '/bin/sh'], expect_stdout => "dash\n", expect_stderr => '');
+call_divert(['--listpackage', '/bin/true'], expect_stdout => "LOCAL\n", expect_stderr => '');
+call_divert(['--listpackage', '/bin/false'], expect_stdout => '', expect_stderr => '');
+
+call_divert(['--truename'], expect_failure => 1);
+call_divert(['--truename', '/bin/sh'], expect_stdout => "/bin/sh.distrib\n", expect_stderr => '');
+call_divert(['--truename', '/bin/sh.distrib'], expect_stdout => "/bin/sh.distrib\n", expect_stderr => '');
+call_divert(['--truename', '/bin/something'], expect_stdout => "/bin/something\n", expect_stderr => '');
+
+cleanup();
+
+diag("Adding diversion");
+
+my $diversions_added_foo_local = <<EOF;
+$testdir/foo
+$testdir/foo.distrib
+:
+EOF
+
+install_diversions('');
+
+system("touch $testdir/foo");
+call_divert(['--rename', '--add', "$testdir/foo"],
+ expect_stdout_like => qr,Adding.*local.*diversion.*$testdir/foo.*$testdir/foo.distrib,,
+ expect_stderr => '');
+ok(-e "$testdir/foo.distrib", "foo diverted");
+ok(!-e "$testdir/foo", "foo diverted");
+diversions_eq($diversions_added_foo_local);
+
+cleanup();
+
+diag("Adding diversion (2)");
+
+install_diversions('');
+
+system("touch $testdir/foo");
+call_divert(['--add', "$testdir/foo"],
+ expect_stdout_like => qr,Adding.*local.*diversion.*$testdir/foo.*$testdir/foo.distrib,,
+ expect_stderr => '');
+ok(!-e "$testdir/foo.distrib", "foo diverted");
+ok(-e "$testdir/foo", "foo diverted");
+diversions_eq($diversions_added_foo_local);
+
+cleanup();
+
+diag("Adding diversion (3)");
+
+install_diversions('');
+
+system("touch $testdir/foo");
+call_divert(['--quiet', '--rename', '--add', "$testdir/foo"],
+ expect_stdout => '', expect_stderr => '');
+ok(-e "$testdir/foo.distrib", "foo diverted");
+ok(!-e "$testdir/foo", "foo diverted");
+diversions_eq($diversions_added_foo_local);
+
+cleanup();
+
+diag("Adding diversion (4)");
+
+install_diversions('');
+system("touch $testdir/foo");
+call_divert(['--quiet', '--rename', '--test', "$testdir/foo"],
+ expect_stdout => '', expect_stderr => '');
+ok(-e "$testdir/foo", "foo not diverted");
+ok(!-e "$testdir/foo.distrib", "foo diverted");
+diversions_eq('');
+
+cleanup();
+
+diag("Adding diversion (5)");
+
+install_diversions('');
+call_divert(['--quiet', '--rename', "$testdir/foo"],
+ expect_stdout => '', expect_stderr => '');
+ok(!-e "$testdir/foo", "foo does not exist");
+ok(!-e "$testdir/foo.distrib", "foo was not created out of thin air");
+
+cleanup();
+
+diag("Adding diversion (6)");
+
+install_diversions('');
+system("touch $testdir/foo");
+call_divert(['--quiet', '--local', '--rename', "$testdir/foo"],
+ expect_stdout => '', expect_stderr => '');
+
+ok(-e "$testdir/foo.distrib", "foo diverted");
+ok(!-e "$testdir/foo", "foo diverted");
+diversions_eq($diversions_added_foo_local);
+
+cleanup();
+
+diag("Adding diversion (7)");
+
+install_diversions('');
+call_divert(['--quiet', '--rename', '--package', 'bash', "$testdir/foo"],
+ expect_stdout => '', expect_stderr => '');
+diversions_eq(<<EOF);
+$testdir/foo
+$testdir/foo.distrib
+bash
+EOF
+
+diag("Adding diversion (Cool");
+
+install_diversions('');
+system("touch $testdir/foo; ln $testdir/foo $testdir/foo.distrib");
+call_divert(["--rename", "$testdir/foo"]);
+diversions_eq($diversions_added_foo_local);
+ok(!-e "$testdir/foo", "foo diverted");
+ok(-e "$testdir/foo.distrib", "foo diverted");
+
+cleanup();
+
+diag("Adding diversion (9)");
+
+install_diversions('');
+system("touch $testdir/foo $testdir/foo.distrib");
+call_divert(["--rename", "$testdir/foo"], expect_failure => 1,
+ expect_stderr_like => qr/overwriting/);
+diversions_eq('');
+
+cleanup();
+
+diag("Adding second diversion");
+
+install_diversions('');
+call_divert(["$testdir/foo"]);
+
+call_divert(["$testdir/foo"], expect_stdout_like => qr/Leaving/);
+call_divert(['--quiet', "$testdir/foo"], expect_stdout => '');
+call_divert(['--divert', "$testdir/foo.bar", "$testdir/foo"],
+ expect_failure => 1, expect_stderr_like => qr/clashes/);
+call_divert(['--package', 'foobar', "$testdir/foo"], expect_failure => 1,
+ expect_stderr_like => qr/clashes/);
+call_divert(['--divert', "$testdir/foo.distrib", "$testdir/bar"],
+ expect_failure => 1, expect_stderr_like => qr/clashes/);
+call_divert(["$testdir/foo.distrib"],
+ expect_failure => 1, expect_stderr_like => qr/clashes/);
+call_divert(['--divert', "$testdir/foo", "$testdir/bar"],
+ expect_failure => 1, expect_stderr_like => qr/clashes/);
+
+cleanup();
+
+diag("Adding third diversion");
+
+install_diversions('');
+call_divert(["$testdir/foo"]);
+call_divert(["$testdir/bar"]);
+
+call_divert(['--quiet', "$testdir/foo"], expect_stdout => '');
+call_divert(['--package', 'foobar', "$testdir/bar"], expect_failure => 1,
+ expect_stderr_like => qr/clashes/);
+
+cleanup();
+
+diag("Adding diversion in non-existing directory");
+
+install_diversions('');
+
+call_divert(['--quiet', '--rename', '--add', "$testdir/zoo/foo"],
+ expect_stderr => '', expect_stdout => '');
+diversions_eq(<<EOF);
+$testdir/zoo/foo
+$testdir/zoo/foo.distrib
+:
+EOF
+
+cleanup();
+
+diag("Remove diversions");
+
+install_diversions('');
+
+call_divert(['--remove', '/bin/sh'], expect_stdout_like => qr/No diversion/, expect_stderr => '');
+call_divert(['--remove', '--quiet', '/bin/sh'], expect_stdout => '', expect_stderr => '');
+
+cleanup();
+
+diag("Remove diversion (2)");
+
+install_diversions('');
+call_divert(["$testdir/foo"]);
+call_divert(["$testdir/bar"]);
+call_divert(["$testdir/baz"]);
+
+call_divert(["--divert", "$testdir/foo.my", "--remove", "$testdir/foo"],
+ expect_failure => 1, expect_stderr_like => qr/mismatch on divert-to/);
+call_divert(["--package", "baz", "--remove", "$testdir/foo"],
+ expect_failure => 1, expect_stderr_like => qr/mismatch on package/);
+call_divert(["--package", "baz", "--divert", "$testdir/foo.my", "--remove", "$testdir/foo"],
+ expect_failure => 1, expect_stderr_like =>qr/mismatch on (package|divert-to)/);
+
+call_divert(["--divert", "$testdir/foo.distrib", "--remove", "$testdir/foo"],
+ expect_stdout_like => qr,Removing.*$testdir/foo,);
+diversions_eq(<<EOF);
+$testdir/bar
+$testdir/bar.distrib
+:
+$testdir/baz
+$testdir/baz.distrib
+:
+EOF
+
+cleanup();
+
+diag("Remove diversion (3)");
+
+install_diversions('');
+
+call_divert(["$testdir/foo"]);
+call_divert(["$testdir/bar"]);
+call_divert(["$testdir/baz"]);
+
+call_divert(["--remove", "$testdir/bar"],
+ expect_stdout_like => qr,Removing.*$testdir/bar,);
+diversions_eq(<<EOF);
+$testdir/foo
+$testdir/foo.distrib
+:
+$testdir/baz
+$testdir/baz.distrib
+:
+EOF
+
+cleanup();
+
+diag("Remove diversion (4)");
+
+install_diversions('');
+
+call_divert(["$testdir/foo"]);
+call_divert(["$testdir/bar"]);
+call_divert(["--package", "bash", "$testdir/baz"]);
+
+call_divert(["--quiet", "--package", "bash", "--remove", "$testdir/baz"],
+ expect_stdout => '', expect_stderr => '');
+diversions_eq(<<EOF);
+$testdir/foo
+$testdir/foo.distrib
+:
+$testdir/bar
+$testdir/bar.distrib
+:
+EOF
+
+cleanup();
+
+diag("Remove diversion(5)");
+
+install_diversions('');
+system("touch $testdir/foo");
+call_divert(["--rename", "$testdir/foo"]);
+
+call_divert(["--test", "--rename", "--remove", "$testdir/foo"],
+ expect_stdout_like => qr,Removing.*$testdir/foo,, expect_stderr => '');
+ok(-e "$testdir/foo.distrib");
+ok(!-e "$testdir/foo");
+diversions_eq($diversions_added_foo_local);
+
+call_divert(["--quiet", "--rename", "--remove", "$testdir/foo"],
+ expect_stdout => '', expect_stderr => '');
+ok(-e "$testdir/foo");
+ok(!-e "$testdir/foo.distrib");
+diversions_eq('');
+
+cleanup();
+
+diag("Corrupted divertions db handling");
+
+call_divert(['--list'], expect_failure => 1,
+ expect_stderr_like => qr/(cannot|failed).*open/, expect_stdout => '');
+
+install_diversions(<<EOF);
+/bin/sh
+EOF
+
+call_divert(['--list'], expect_failure => 1,
+ expect_stderr_like => qr/(corrupt|unexpected eof)/, expect_stdout => '');
+
+install_diversions(<<EOF);
+/bin/sh
+bash
+EOF
+
+call_divert(['--list'], expect_failure => 1,
+ expect_stderr_like => qr/(corrupt|unexpected eof)/, expect_stdout => '');
+
+cleanup();
+
+diag("R/O directory");
+
+install_diversions('');
+system("mkdir $testdir/rodir && touch $testdir/rodir/foo $testdir/bar && chmod 500 $testdir/rodir");
+# FIXME: do not output anything here
+call_divert(['--rename', '--add', "$testdir/rodir/foo"],
+ expect_failure => 1, expect_stderr_like => qr/error/);
+# FIXME: do not output anything here
+call_divert(['--rename', '--divert', "$testdir/rodir/bar", '--add', "$testdir/bar"],
+ expect_failure => 1, expect_stderr_like => qr/error/);
+diversions_eq('');
+
+system("chmod 755 $testdir/rodir");
+cleanup();
+
+diag("Unavailable file");
+
+install_diversions('');
+system("mkdir $testdir/nadir && chmod 000 $testdir/nadir");
+call_divert(['--rename', '--add', "$testdir/nadir/foo"],
+ expect_failure => 1, expect_stderr_like => qr/Permission denied/);
+system("touch $testdir/foo");
+call_divert(['--rename', '--divert', "$testdir/nadir/foo", '--add', "$testdir/foo"],
+ expect_failure => 1, expect_stderr_like => qr/Permission denied/);
+diversions_eq('');
+
+cleanup();
+
+diag("Errors during saving diversions db");
+
+install_diversions('');
+system("chmod 500 $admindir");
+call_divert(["$testdir/foo"], expect_failure => 1, expect_stderr_like => qr/create.*new/);
+system("chmod 755 $admindir; ln -s /dev/full $admindir/diversions-new");
+call_divert(["$testdir/foo"], expect_failure => 1, expect_stderr_like => qr/(write|close).*new/);
+system("rm $admindir/diversions-new; mkdir $admindir/diversions-old");
+call_divert(["$testdir/foo"], expect_failure => 1, expect_stderr_like => qr/remove.*old/);
--
1.6.3.3


--
To UNSUBSCRIBE, email to debian-dpkg-REQUEST.RemoveThis@lists.debian.org
with a subject of "unsubscribe". Trouble? Contact listmaster.RemoveThis@lists.debian.org
Back to top
Login to vote
Display posts from previous:   
Related Topics:
dpkg-cross, dpkg-architecture and arch names - I noticed that dpkg-cross didn't automatically recognise armel when provided with an updated dpkg-architecture. This i...

dpkg-scanpackages - where is it? - Hi, Trying to install a deb file with dkpg-scanpackages ./ /dev/null |gzip -c -9 > packages.gz I don't have..

how to get dpkg to work from scratch? - Hi, I have an ARM Embedded Linux filesystem where I want to add debian packages. How could I install dpkg from scratch...

new dpkg packages up for testing - Hi, I've assembled a new dpkg package based on the last revision in Debian (1.10.20) and a couple of patches from the....

dpkg FTBFS on mips - Hello, dpkg currently FTBFS on mips, probably because of po4a or because of a missing locale on mips. Can anybody hel...

Use of negated arches for dpkg dependencies - Hi there, We need to find a consensus on what to do when a package has linux-specific build dependencies and we want t...
       Soft32 Home -> Linux -> PacKaGe All times are: Pacific Time (US & Canada) (change)
Page 1 of 1

 
You can post new topics in this forum
You can reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum

Categories:
 Windows
  Linux
 Mac
 PDA


[ Contact us | Terms of Service/Privacy Policy ]