summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Vogt <michael.vogt@ubuntu.com>2009-12-14 09:22:29 +0100
committerMichael Vogt <michael.vogt@ubuntu.com>2009-12-14 09:22:29 +0100
commit4407a02f4ead0c8c7906ba2fa96021890237f7d9 (patch)
tree6fa68d5510b537a28cdb677298a8f4e8d1fb42a6
parentd4d9f5399244f5c7e698cc4860d1d9ab8f63992f (diff)
parent5d70f74c114450f001d415eea101610eedaee05b (diff)
merged patches from david (many thanks)
-rw-r--r--apt-inst/makefile2
-rw-r--r--apt-pkg/init.h4
-rw-r--r--buildlib/library.mak14
-rw-r--r--buildlib/libversion.mak7
-rw-r--r--debian/apt.cron.daily6
-rw-r--r--debian/changelog40
-rwxr-xr-xdebian/rules14
-rw-r--r--doc/apt-ftparchive.1.xml6
-rw-r--r--doc/apt-get.8.xml6
-rw-r--r--doc/apt.conf.5.xml15
-rw-r--r--doc/examples/configure-index34
-rw-r--r--ftparchive/apt-ftparchive.cc4
-rw-r--r--ftparchive/cachedb.cc6
-rw-r--r--ftparchive/contents.cc2
-rw-r--r--ftparchive/multicompress.cc2
-rw-r--r--ftparchive/writer.cc2
-rw-r--r--methods/connect.cc1
-rw-r--r--methods/http.cc3
-rw-r--r--methods/https.cc88
-rw-r--r--methods/rred.cc648
20 files changed, 619 insertions, 285 deletions
diff --git a/apt-inst/makefile b/apt-inst/makefile
index c0ff3d886..18637d749 100644
--- a/apt-inst/makefile
+++ b/apt-inst/makefile
@@ -11,7 +11,7 @@ include ../buildlib/defaults.mak
# The library name
LIBRARY=apt-inst
-MAJOR=1.2
+MAJOR=1.1
MINOR=0
SLIBS=$(PTHREADLIB) -lapt-pkg
APT_DOMAIN:=libapt-inst$(MAJOR)
diff --git a/apt-pkg/init.h b/apt-pkg/init.h
index f892e7ff4..f0757f644 100644
--- a/apt-pkg/init.h
+++ b/apt-pkg/init.h
@@ -21,9 +21,7 @@
// reverse-dependencies of libapt-pkg against the new SONAME.
// Non-ABI-Breaks should only increase RELEASE number.
// See also buildlib/libversion.mak
-// FIXME: this needs to be changed to "4" (without quotes) on the next
-// ABI break
-#define APT_PKG_MAJOR libc6.9-6-4
+#define APT_PKG_MAJOR 4
#define APT_PKG_MINOR 8
#define APT_PKG_RELEASE 0
diff --git a/buildlib/library.mak b/buildlib/library.mak
index 029e87463..2a4bb782a 100644
--- a/buildlib/library.mak
+++ b/buildlib/library.mak
@@ -16,11 +16,11 @@
# See defaults.mak for information about LOCAL
# Some local definitions
-LOCAL := lib$(LIBRARY).so.$(MAJOR).$(MINOR)
+LOCAL := lib$(LIBRARY)$(LIBEXT).so.$(MAJOR).$(MINOR)
$(LOCAL)-OBJS := $(addprefix $(OBJ)/,$(addsuffix .opic,$(notdir $(basename $(SOURCE)))))
$(LOCAL)-DEP := $(addprefix $(DEP)/,$(addsuffix .opic.d,$(notdir $(basename $(SOURCE)))))
$(LOCAL)-HEADERS := $(addprefix $(INCLUDE)/,$(HEADERS))
-$(LOCAL)-SONAME := lib$(LIBRARY).so.$(MAJOR)
+$(LOCAL)-SONAME := lib$(LIBRARY)$(LIBEXT).so.$(MAJOR)
$(LOCAL)-SLIBS := $(SLIBS)
$(LOCAL)-LIBRARY := $(LIBRARY)
@@ -29,7 +29,7 @@ include $(PODOMAIN_H)
# Install the command hooks
headers: $($(LOCAL)-HEADERS)
-library: $(LIB)/lib$(LIBRARY).so $(LIB)/lib$(LIBRARY).so.$(MAJOR)
+library: $(LIB)/lib$(LIBRARY).so $(LIB)/lib$(LIBRARY)$(LIBEXT).so.$(MAJOR)
clean: clean/$(LOCAL)
veryclean: veryclean/$(LOCAL)
@@ -44,14 +44,14 @@ veryclean/$(LOCAL): clean/$(LOCAL)
-rm -f $($(@F)-HEADERS) $(LIB)/lib$($(@F)-LIBRARY)*.so*
# Build rules for the two symlinks
-.PHONY: $(LIB)/lib$(LIBRARY).so.$(MAJOR) $(LIB)/lib$(LIBRARY).so
-$(LIB)/lib$(LIBRARY).so.$(MAJOR): $(LIB)/lib$(LIBRARY).so.$(MAJOR).$(MINOR)
+.PHONY: $(LIB)/lib$(LIBRARY)$(LIBEXT).so.$(MAJOR) $(LIB)/lib$(LIBRARY).so
+$(LIB)/lib$(LIBRARY)$(LIBEXT).so.$(MAJOR): $(LIB)/lib$(LIBRARY)$(LIBEXT).so.$(MAJOR).$(MINOR)
ln -sf $(<F) $@
-$(LIB)/lib$(LIBRARY).so: $(LIB)/lib$(LIBRARY).so.$(MAJOR).$(MINOR)
+$(LIB)/lib$(LIBRARY).so: $(LIB)/lib$(LIBRARY)$(LIBEXT).so.$(MAJOR).$(MINOR)
ln -sf $(<F) $@
# The binary build rule
-$(LIB)/lib$(LIBRARY).so.$(MAJOR).$(MINOR): $($(LOCAL)-HEADERS) $($(LOCAL)-OBJS)
+$(LIB)/lib$(LIBRARY)$(LIBEXT).so.$(MAJOR).$(MINOR): $($(LOCAL)-HEADERS) $($(LOCAL)-OBJS)
-rm -f $(LIB)/lib$($(@F)-LIBRARY)*.so* 2> /dev/null
echo Building shared library $@
$(CXX) $(CXXFLAGS) $(LDFLAGS) $(PICFLAGS) $(LFLAGS) $(LFLAGS_SO)\
diff --git a/buildlib/libversion.mak b/buildlib/libversion.mak
index 796c956e7..26ca86ced 100644
--- a/buildlib/libversion.mak
+++ b/buildlib/libversion.mak
@@ -12,3 +12,10 @@ LIBAPTPKG_RELEASE=$(shell grep -E '^\#define APT_PKG_RELEASE' $(BASE)/apt-pkg/in
# The versionnumber is extracted from apt-inst/makefile - see also there.
LIBAPTINST_MAJOR=$(shell egrep '^MAJOR=' $(BASE)/apt-inst/makefile |cut -d '=' -f 2)
LIBAPTINST_MINOR=$(shell egrep '^MINOR=' $(BASE)/apt-inst/makefile |cut -d '=' -f 2)
+
+# FIXME: In previous releases this lovely variable includes
+# the detected libc and libdc++ version. As this is bogus we
+# want to drop this, but this a ABI break.
+# And we don't want to do this now. So we hardcode a value here,
+# and drop it later on (hopefully as fast as possible).
+LIBEXT=-libc6.9-6
diff --git a/debian/apt.cron.daily b/debian/apt.cron.daily
index b6099ee75..e59b05ee4 100644
--- a/debian/apt.cron.daily
+++ b/debian/apt.cron.daily
@@ -401,12 +401,16 @@ eval $(apt-config shell BackupArchiveInterval APT::Periodic::BackupArchiveInterv
Debdelta=1
eval $(apt-config shell Debdelta APT::Periodic::Download-Upgradeable-Packages-Debdelta)
-# check if we actually have to do anything
+# check if we actually have to do anything that requires locking the cache
if [ $UpdateInterval -eq 0 ] &&
[ $DownloadUpgradeableInterval -eq 0 ] &&
[ $UnattendedUpgradeInterval -eq 0 ] &&
[ $BackupArchiveInterval -eq 0 ] &&
[ $AutocleanInterval -eq 0 ]; then
+
+ # check cache size
+ check_size_constraints
+
exit 0
fi
diff --git a/debian/changelog b/debian/changelog
index 64e676709..cd4573468 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -13,8 +13,6 @@ apt (0.7.25) UNRELEASED; urgency=low
Closes: #548571
* German translation update by Holger Wansing
Closes: #551534
- * German translation of manpages by Chris Leick
- Closes: #552606
* Italian translation update by Milo Casagrande
Closes: #555797
* Simplified Chinese translation update by Aron Xu
@@ -37,7 +35,7 @@ apt (0.7.25) UNRELEASED; urgency=low
* apt-pkg/deb/dpkgpm.cc:
- add "purge" to list of known actions
* apt-pkg/init.h:
- - add compatibilty with old ABI name until the next ABI break
+ - add compatibility with old ABI name until the next ABI break
[ Brian Murray ]
* apt-pkg/depcache.cc, apt-pkg/indexcopy.cc:
@@ -56,18 +54,21 @@ apt (0.7.25) UNRELEASED; urgency=low
* doc/po4a.conf: activate translation of guide.sgml and offline.sgml
* doc/apt.conf.5.xml:
- provide a few more details about APT::Immediate-Configure
+ - briefly document the behaviour of the new https options
* doc/sources.list.5.xml:
- add note about additional apt-transport-methods
* doc/apt-mark.8.xml:
- correct showauto synopsis, thanks Andrew Schulman (Closes: #551440)
* cmdline/apt-get.cc:
- - source should displays his final pkg pick (Closes: #249383, #550952)
+ - source should display his final pkg pick (Closes: #249383, #550952)
- source doesn't need the complete version for match (Closes: #245250)
- source ignores versions/releases if not available (Closes: #377424)
- only warn if (free) space overflows (Closes: #522238)
- add --debian-only as alias for --diff-only
* methods/connect.cc:
- display also strerror of "wicked" getaddrinfo errors
+ - add AI_ADDRCONFIG to ai_flags as suggested by Aurelien Jarno
+ in response to Bernhard R. Link, thanks! (Closes: #505020)
* buildlib/configure.mak, buildlib/config.{sub,guess}:
- remove (outdated) config.{sub,guess} and use the ones provided
by the new added build-dependency autotools-dev instead
@@ -81,21 +82,42 @@ apt (0.7.25) UNRELEASED; urgency=low
- bump policy to 3.8.3 as we have no outdated manpages anymore
* debian/NEWS:
- fix a typo in 0.7.24: Allready -> Already (Closes: #557674)
- * cmdline/apt-mark:
- - print an error if a new state file can't be created,
- thanks Carl Chenet! (Closes: #521289)
- - print an error and exit if python-apt is not installed,
- thanks Carl Chenet! (Closes: #521284)
* ftparchive/writer.{cc,h}:
- add APT::FTPArchive::LongDescription to be able to disable them
* apt-pkg/deb/debsrcrecords.cc:
- use "diff" filetype for .debian.tar.* files (Closes: #554898)
+ * methods/rred.cc:
+ - rewrite to be able to handle even big patch files
+ - adopt optional mmap+iovec patch from Morten Hustveit
+ (Closes: #463354) which should speed up a bit. Thanks!
+ * methods/http{,s}.cc
+ - add config setting for User-Agent to the Acquire group,
+ thanks Timothy J. Miller! (Closes: #355782)
+ - add https options which default to http ones (Closes: #557085)
+ * debian/apt.cron.daily:
+ - check cache size even if we do nothing else otherwise, thanks
+ Francesco Poli for patch(s) and patience! (Closes: #459344)
+ * ftparchive/*:
+ - fix a few typos in strings, comments and manpage,
+ thanks Karl Goetz! (Closes: #558757)
+
+ [ Carl Chenet ]
+ * cmdline/apt-mark:
+ - print an error if a new state file can't be created
+ (Closes: #521289) and
+ - exit nicely if python-apt is not installed (Closes: #521284)
[ Chris Leick ]
+ * doc/de: German translation of manpages (Closes: #552606)
* doc/ various manpages:
- correct various errors, typos and oddities (Closes: #552535)
* doc/apt-secure.8.xml:
- replace literal with emphasis tags in Archive configuration
+ * doc/apt-ftparchive.1.xml:
+ - remove informalexample tag which hides the programlisting
+ * doc/apt-get.8.xml:
+ - change equivalent "for" to "to the" (purge command)
+ - clarify --fix-broken sentence about specifying packages
[ Eugene V. Lyubimkin ]
* apt-pkg/contib/strutl.h
diff --git a/debian/rules b/debian/rules
index f69c0cffb..d01b57cd6 100755
--- a/debian/rules
+++ b/debian/rules
@@ -78,21 +78,21 @@ APT_UTILS=ftparchive sortpkgs extracttemplates
include buildlib/libversion.mak
# Determine which package we should provide in the control files
-LIBAPTPKG_PROVIDE=libapt-pkg-$(LIBAPTPKG_MAJOR)
-LIBAPTINST_PROVIDE=libapt-inst-$(LIBAPTINST_MAJOR)
+LIBAPTPKG_PROVIDE=libapt-pkg$(LIBEXT)-$(LIBAPTPKG_MAJOR)
+LIBAPTINST_PROVIDE=libapt-inst$(LIBEXT)-$(LIBAPTINST_MAJOR)
debian/shlibs.local: apt-pkg/makefile
# We have 3 shlibs.local files.. One for 'apt', one for 'apt-utils' and
# one for the rest of the packages. This ensures that each package gets
# the right overrides..
rm -rf $@ $@.apt $@.apt-utils
- echo "libapt-pkg $(LIBAPTPKG_MAJOR)" > $@.apt
+ echo "libapt-pkg$(LIBEXT) $(LIBAPTPKG_MAJOR)" > $@.apt
- echo "libapt-pkg $(LIBAPTPKG_MAJOR) $(LIBAPTPKG_PROVIDE)" > $@.apt-utils
- echo "libapt-inst $(LIBAPTINST_MAJOR)" >> $@.apt-utils
+ echo "libapt-pkg$(LIBEXT) $(LIBAPTPKG_MAJOR) $(LIBAPTPKG_PROVIDE)" > $@.apt-utils
+ echo "libapt-inst$(LIBEXT) $(LIBAPTINST_MAJOR)" >> $@.apt-utils
- echo "libapt-pkg $(LIBAPTPKG_MAJOR) $(LIBAPTPKG_PROVIDE)" > $@
- echo "libapt-inst $(LIBAPTINST_MAJOR) $(LIBAPTINST_PROVIDE)" >> $@
+ echo "libapt-pkg$(LIBEXT) $(LIBAPTPKG_MAJOR) $(LIBAPTPKG_PROVIDE)" > $@
+ echo "libapt-inst$(LIBEXT) $(LIBAPTINST_MAJOR) $(LIBAPTINST_PROVIDE)" >> $@
build: build/build-stamp
build-doc: build/build-doc-stamp
diff --git a/doc/apt-ftparchive.1.xml b/doc/apt-ftparchive.1.xml
index d47df957a..c56ff235a 100644
--- a/doc/apt-ftparchive.1.xml
+++ b/doc/apt-ftparchive.1.xml
@@ -285,7 +285,7 @@
<varlistentry><term>Sources</term>
<listitem><para>
- Sets the output Packages file. Defaults to
+ Sets the output Sources file. Defaults to
<filename>$(DIST)/$(SECTION)/source/Sources</filename></para></listitem>
</varlistentry>
@@ -350,11 +350,11 @@
<para>
When processing a <literal>Tree</literal> section <command>apt-ftparchive</command>
performs an operation similar to:
-<informalexample><programlisting>
+ <programlisting>
for i in Sections do
for j in Architectures do
Generate for DIST=scope SECTION=i ARCH=j
-</programlisting></informalexample></para>
+ </programlisting></para>
<variablelist>
<varlistentry><term>Sections</term>
diff --git a/doc/apt-get.8.xml b/doc/apt-get.8.xml
index d3c3772bd..3d22f262c 100644
--- a/doc/apt-get.8.xml
+++ b/doc/apt-get.8.xml
@@ -333,8 +333,8 @@
<varlistentry><term><option>-f</option></term><term><option>--fix-broken</option></term>
<listitem><para>Fix; attempt to correct a system with broken dependencies in
place. This option, when used with install/remove, can omit any packages
- to permit APT to deduce a likely solution. Any Package that are specified
- must completely correct the problem. The option is sometimes necessary when
+ to permit APT to deduce a likely solution. If packages are specified,
+ these have to completely correct the problem. The option is sometimes necessary when
running APT for the first time; APT itself does not allow broken package
dependencies to exist on a system. It is possible that a system's
dependency structure can be so corrupt as to require manual intervention
@@ -466,7 +466,7 @@
<varlistentry><term><option>--purge</option></term>
<listitem><para>Use purge instead of remove for anything that would be removed.
An asterisk ("*") will be displayed next to packages which are
- scheduled to be purged. <option>remove --purge</option> is equivalent for
+ scheduled to be purged. <option>remove --purge</option> is equivalent to the
<option>purge</option> command.
Configuration Item: <literal>APT::Get::Purge</literal>.</para></listitem>
</varlistentry>
diff --git a/doc/apt.conf.5.xml b/doc/apt.conf.5.xml
index e2db9defb..d7ad51cfb 100644
--- a/doc/apt.conf.5.xml
+++ b/doc/apt.conf.5.xml
@@ -275,13 +275,20 @@ DPkg::Pre-Install-Pkgs {"/usr/sbin/dpkg-preconfigure --apt";};
<para>The used bandwidth can be limited with <literal>Acquire::http::Dl-Limit</literal>
which accepts integer values in kilobyte. The default value is 0 which deactivates
the limit and tries uses as much as possible of the bandwidth (Note that this option implicit
- deactivates the download from multiple servers at the same time.)</para></listitem>
+ deactivates the download from multiple servers at the same time.)</para>
+
+ <para><literal>Acquire::http::User-Agent</literal> can be used to set a different
+ User-Agent for the http download method as some proxies allow access for clients
+ only if the client uses a known identifier.</para>
+ </listitem>
</varlistentry>
<varlistentry><term>https</term>
- <listitem><para>HTTPS URIs. Cache-control and proxy options are the same as for
- <literal>http</literal> method.
- <literal>Pipeline-Depth</literal> option is not supported yet.</para>
+ <listitem><para>HTTPS URIs. Cache-control, Timeout, AllowRedirect, Dl-Limit and
+ proxy options are the same as for <literal>http</literal> method and will also
+ default to the options from the <literal>http</literal> method if they are not
+ explicitly set for https. <literal>Pipeline-Depth</literal> option is not
+ supported yet.</para>
<para><literal>CaInfo</literal> suboption specifies place of file that
holds info about trusted certificates.
diff --git a/doc/examples/configure-index b/doc/examples/configure-index
index f5f996460..ced390447 100644
--- a/doc/examples/configure-index
+++ b/doc/examples/configure-index
@@ -191,19 +191,37 @@ Acquire
Max-Age "86400"; // 1 Day age on index files
No-Store "false"; // Prevent the cache from storing archives
Dl-Limit "7"; // 7Kb/sec maximum download rate
+ User-Agent "Debian APT-HTTP/1.3";
};
- // HTTPS method configuration:
- // - uses the http proxy config
- // - uses the http cache-control values
- // - uses the http Dl-Limit values
- https
+
+
+ // HTTPS method configuration: uses the http
+ // - proxy config
+ // - cache-control values
+ // - Dl-Limit, Timout, ... values
+ // if not set explicit for https
+ //
+ // see /usr/share/doc/apt/examples/apt-https-method-example.conf.gz
+ // for more examples
+ https
{
Verify-Peer "false";
SslCert "/etc/apt/some.pem";
- CaPath "/etc/ssl/certs";
- Verify-Host" "true";
- AllowRedirect "true";
+ CaPath "/etc/ssl/certs";
+ Verify-Host" "true";
+ AllowRedirect "true";
+
+ Timeout "120";
+ AllowRedirect "true";
+
+ // Cache Control. Note these do not work with Squid 2.0.2
+ No-Cache "false";
+ Max-Age "86400"; // 1 Day age on index files
+ No-Store "false"; // Prevent the cache from storing archives
+ Dl-Limit "7"; // 7Kb/sec maximum download rate
+
+ User-Agent "Debian APT-CURL/1.0";
};
ftp
diff --git a/ftparchive/apt-ftparchive.cc b/ftparchive/apt-ftparchive.cc
index d0dea7768..5b6b3940c 100644
--- a/ftparchive/apt-ftparchive.cc
+++ b/ftparchive/apt-ftparchive.cc
@@ -3,7 +3,7 @@
// $Id: apt-ftparchive.cc,v 1.8.2.3 2004/01/02 22:01:48 mdz Exp $
/* ######################################################################
- apt-scanpackages - Efficient work-alike for dpkg-scanpackages
+ apt-ftparchive - Efficient work-alike for dpkg-scanpackages
Let contents be disabled from the conf
@@ -792,7 +792,7 @@ bool Generate(CommandLine &CmdL)
if (_config->FindB("APT::FTPArchive::Contents",true) == false)
return true;
- c1out << "Done Packages, Starting contents." << endl;
+ c1out << "Packages done, Starting contents." << endl;
// Sort the contents file list by date
string ArchiveDir = Setup.FindDir("Dir::ArchiveDir");
diff --git a/ftparchive/cachedb.cc b/ftparchive/cachedb.cc
index dfda827b6..e02f0e1b6 100644
--- a/ftparchive/cachedb.cc
+++ b/ftparchive/cachedb.cc
@@ -69,7 +69,7 @@ bool CacheDB::ReadyDB(string DB)
// apt 0.6.44
if (err == EINVAL)
{
- _error->Error(_("DB format is invalid. If you upgraded from a older version of apt, please remove and re-create the database."));
+ _error->Error(_("DB format is invalid. If you upgraded from an older version of apt, please remove and re-create the database."));
}
if (err)
{
@@ -83,7 +83,7 @@ bool CacheDB::ReadyDB(string DB)
return true;
}
/*}}}*/
-// CacheDB::OpenFile - Open the filei /*{{{*/
+// CacheDB::OpenFile - Open the file /*{{{*/
// ---------------------------------------------------------------------
/* */
bool CacheDB::OpenFile()
@@ -139,7 +139,7 @@ bool CacheDB::GetCurStat()
if (DBLoaded)
{
- /* First see if thre is anything about it
+ /* First see if there is anything about it
in the database */
/* Get the flags (and mtime) */
diff --git a/ftparchive/contents.cc b/ftparchive/contents.cc
index 1f2cbcc3d..fb1438f74 100644
--- a/ftparchive/contents.cc
+++ b/ftparchive/contents.cc
@@ -13,7 +13,7 @@
removing the massive sort time overhead.
By breaking all the pathnames into components and storing them
- separately a space savings is realized by not duplicating the string
+ separately a space saving is realized by not duplicating the string
over and over again. Ultimately this saving is sacrificed to storage of
the tree structure itself but the tree structure yields a speed gain
in the sorting and processing. Ultimately it takes about 5 seconds to
diff --git a/ftparchive/multicompress.cc b/ftparchive/multicompress.cc
index 2fc8efcbf..16cef9769 100644
--- a/ftparchive/multicompress.cc
+++ b/ftparchive/multicompress.cc
@@ -365,7 +365,7 @@ bool MultiCompress::CloseOld(int Fd,pid_t Proc)
// MultiCompress::Child - The writer child /*{{{*/
// ---------------------------------------------------------------------
/* The child process forks a bunch of compression children and takes
- input on FD and passes it to all the compressor childer. On the way it
+ input on FD and passes it to all the compressor child. On the way it
computes the MD5 of the raw data. After this the raw data in the
original files is compared to see if this data is new. If the data
is new then the temp files are renamed, otherwise they are erased. */
diff --git a/ftparchive/writer.cc b/ftparchive/writer.cc
index b2ebdca8a..4e6c9a77d 100644
--- a/ftparchive/writer.cc
+++ b/ftparchive/writer.cc
@@ -463,7 +463,7 @@ bool PackagesWriter::DoPackage(string FileName)
SetTFRewriteData(Changes[End++], "Maintainer", NewMaint.c_str());
/* Get rid of the Optional tag. This is an ugly, ugly, ugly hack that
- dpkg-scanpackages does.. Well sort of. dpkg-scanpackages just does renaming
+ dpkg-scanpackages does. Well sort of. dpkg-scanpackages just does renaming
but dpkg does this append bit. So we do the append bit, at least that way the
status file and package file will remain similar. There are other transforms
but optional is the only legacy one still in use for some lazy reason. */
diff --git a/methods/connect.cc b/methods/connect.cc
index 74e670ebd..adb16a199 100644
--- a/methods/connect.cc
+++ b/methods/connect.cc
@@ -158,6 +158,7 @@ bool Connect(string Host,int Port,const char *Service,int DefPort,int &Fd,
struct addrinfo Hints;
memset(&Hints,0,sizeof(Hints));
Hints.ai_socktype = SOCK_STREAM;
+ Hints.ai_flags = AI_ADDRCONFIG;
Hints.ai_protocol = 0;
// if we couldn't resolve the host before, we don't try now
diff --git a/methods/http.cc b/methods/http.cc
index 3b210f6b6..2dae87a02 100644
--- a/methods/http.cc
+++ b/methods/http.cc
@@ -731,7 +731,8 @@ void HttpMethod::SendReq(FetchItem *Itm,CircleBuf &Out)
Req += string("Authorization: Basic ") +
Base64Encode(Uri.User + ":" + Uri.Password) + "\r\n";
}
- Req += "User-Agent: Debian APT-HTTP/1.3 ("VERSION")\r\n\r\n";
+ Req += "User-Agent: " + _config->Find("Acquire::http::User-Agent",
+ "Debian APT-HTTP/1.3 ("VERSION")") + "\r\n\r\n";
if (Debug == true)
cerr << Req << endl;
diff --git a/methods/https.cc b/methods/https.cc
index 86d7f3a6b..5d8e63f47 100644
--- a/methods/https.cc
+++ b/methods/https.cc
@@ -1,4 +1,4 @@
-// -*- mode: cpp; mode: fold -*-
+//-*- mode: cpp; mode: fold -*-
// Description /*{{{*/
// $Id: http.cc,v 1.59 2004/05/08 19:42:35 mdz Exp $
/* ######################################################################
@@ -57,54 +57,41 @@ HttpsMethod::progress_callback(void *clientp, double dltotal, double dlnow,
return 0;
}
-void HttpsMethod::SetupProxy()
+void HttpsMethod::SetupProxy() /*{{{*/
{
URI ServerName = Queue->Uri;
- // Determine the proxy setting
- string SpecificProxy = _config->Find("Acquire::http::Proxy::" + ServerName.Host);
- if (!SpecificProxy.empty())
- {
- if (SpecificProxy == "DIRECT")
- Proxy = "";
- else
- Proxy = SpecificProxy;
- }
- else
- {
- string DefProxy = _config->Find("Acquire::http::Proxy");
- if (!DefProxy.empty())
- {
- Proxy = DefProxy;
- }
- else
- {
- char* result = getenv("http_proxy");
- Proxy = result ? result : "";
- }
- }
-
- // Parse no_proxy, a , separated list of domains
- if (getenv("no_proxy") != 0)
+ // Determine the proxy setting - try https first, fallback to http and use env at last
+ string UseProxy = _config->Find("Acquire::https::Proxy::" + ServerName.Host,
+ _config->Find("Acquire::http::Proxy::" + ServerName.Host).c_str());
+
+ if (UseProxy.empty() == true)
+ UseProxy = _config->Find("Acquire::https::Proxy", _config->Find("Acquire::http::Proxy").c_str());
+
+ // User want to use NO proxy, so nothing to setup
+ if (UseProxy == "DIRECT")
+ return;
+
+ if (UseProxy.empty() == false)
{
- if (CheckDomainList(ServerName.Host,getenv("no_proxy")) == true)
- Proxy = "";
+ // Parse no_proxy, a comma (,) separated list of domains we don't want to use
+ // a proxy for so we stop right here if it is in the list
+ if (getenv("no_proxy") != 0 && CheckDomainList(ServerName.Host,getenv("no_proxy")) == true)
+ return;
+ } else {
+ const char* result = getenv("http_proxy");
+ UseProxy = result == NULL ? "" : result;
}
-
+
// Determine what host and port to use based on the proxy settings
- string Host;
- if (Proxy.empty() == true || Proxy.Host.empty() == true)
- {
- }
- else
+ if (UseProxy.empty() == false)
{
- if (Proxy.Port != 0)
+ Proxy = UseProxy;
+ if (Proxy.Port != 1)
curl_easy_setopt(curl, CURLOPT_PROXYPORT, Proxy.Port);
curl_easy_setopt(curl, CURLOPT_PROXY, Proxy.Host.c_str());
}
-}
-
-
+} /*}}}*/
// HttpsMethod::Fetch - Fetch an item /*{{{*/
// ---------------------------------------------------------------------
/* This adds an item to the pipeline. We keep the pipeline at a fixed
@@ -191,12 +178,15 @@ bool HttpsMethod::Fetch(FetchItem *Itm)
curl_easy_setopt(curl, CURLOPT_SSLVERSION, final_version);
// cache-control
- if(_config->FindB("Acquire::http::No-Cache",false) == false)
+ if(_config->FindB("Acquire::https::No-Cache",
+ _config->FindB("Acquire::http::No-Cache",false)) == false)
{
// cache enabled
- if (_config->FindB("Acquire::http::No-Store",false) == true)
+ if (_config->FindB("Acquire::https::No-Store",
+ _config->FindB("Acquire::http::No-Store",false)) == true)
headers = curl_slist_append(headers,"Cache-Control: no-store");
- ioprintf(ss, "Cache-Control: max-age=%u", _config->FindI("Acquire::http::Max-Age",0));
+ ioprintf(ss, "Cache-Control: max-age=%u", _config->FindI("Acquire::https::Max-Age",
+ _config->FindI("Acquire::http::Max-Age",0)));
headers = curl_slist_append(headers, ss.str().c_str());
} else {
// cache disabled by user
@@ -206,22 +196,28 @@ bool HttpsMethod::Fetch(FetchItem *Itm)
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
// speed limit
- int dlLimit = _config->FindI("Acquire::http::Dl-Limit",0)*1024;
+ int dlLimit = _config->FindI("Acquire::https::Dl-Limit",
+ _config->FindI("Acquire::http::Dl-Limit",0))*1024;
if (dlLimit > 0)
curl_easy_setopt(curl, CURLOPT_MAX_RECV_SPEED_LARGE, dlLimit);
// set header
- curl_easy_setopt(curl, CURLOPT_USERAGENT,"Debian APT-CURL/1.0 ("VERSION")");
+ curl_easy_setopt(curl, CURLOPT_USERAGENT,
+ _config->Find("Acquire::https::User-Agent",
+ _config->Find("Acquire::http::User-Agent",
+ "Debian APT-CURL/1.0 ("VERSION")").c_str()).c_str());
// set timeout
- int timeout = _config->FindI("Acquire::http::Timeout",120);
+ int timeout = _config->FindI("Acquire::https::Timeout",
+ _config->FindI("Acquire::http::Timeout",120));
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, timeout);
//set really low lowspeed timeout (see #497983)
curl_easy_setopt(curl, CURLOPT_LOW_SPEED_LIMIT, DL_MIN_SPEED);
curl_easy_setopt(curl, CURLOPT_LOW_SPEED_TIME, timeout);
// set redirect options and default to 10 redirects
- bool AllowRedirect = _config->FindI("Acquire::https::AllowRedirect", true);
+ bool AllowRedirect = _config->FindB("Acquire::https::AllowRedirect",
+ _config->FindB("Acquire::http::AllowRedirect",true));
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, AllowRedirect);
curl_easy_setopt(curl, CURLOPT_MAXREDIRS, 10);
diff --git a/methods/rred.cc b/methods/rred.cc
index 27d95bdde..262c78cab 100644
--- a/methods/rred.cc
+++ b/methods/rred.cc
@@ -1,202 +1,443 @@
+// Includes /*{{{*/
#include <apt-pkg/fileutl.h>
+#include <apt-pkg/mmap.h>
#include <apt-pkg/error.h>
#include <apt-pkg/acquire-method.h>
#include <apt-pkg/strutl.h>
#include <apt-pkg/hashes.h>
#include <sys/stat.h>
+#include <sys/uio.h>
#include <unistd.h>
#include <utime.h>
#include <stdio.h>
#include <errno.h>
#include <apti18n.h>
-
-/* this method implements a patch functionality similar to "patch --ed" that is
- * used by the "tiffany" incremental packages download stuff. it differs from
- * "ed" insofar that it is way more restricted (and therefore secure). in the
- * moment only the "c", "a" and "d" commands of ed are implemented (diff
- * doesn't output any other). additionally the records must be reverse sorted
- * by line number and may not overlap (diff *seems* to produce this kind of
- * output).
+ /*}}}*/
+/** \brief RredMethod - ed-style incremential patch method {{{
+ *
+ * This method implements a patch functionality similar to "patch --ed" that is
+ * used by the "tiffany" incremental packages download stuff. It differs from
+ * "ed" insofar that it is way more restricted (and therefore secure).
+ * The currently supported ed commands are "<em>c</em>hange", "<em>a</em>dd" and
+ * "<em>d</em>elete" (diff doesn't output any other).
+ * Additionally the records must be reverse sorted by line number and
+ * may not overlap (diff *seems* to produce this kind of output).
* */
+class RredMethod : public pkgAcqMethod {
+ bool Debug;
+ // the size of this doesn't really matter (except for performance)
+ const static int BUF_SIZE = 1024;
+ // the supported ed commands
+ enum Mode {MODE_CHANGED='c', MODE_DELETED='d', MODE_ADDED='a'};
+ // return values
+ enum State {ED_OK, ED_ORDERING, ED_PARSER, ED_FAILURE, MMAP_FAILED};
-const char *Prog;
+ State applyFile(FILE *ed_cmds, FILE *in_file, FILE *out_file,
+ unsigned long &line, char *buffer, Hashes *hash) const;
+ void ignoreLineInFile(FILE *fin, char *buffer) const;
+ void copyLinesFromFileToFile(FILE *fin, FILE *fout, unsigned int lines,
+ Hashes *hash, char *buffer) const;
-class RredMethod : public pkgAcqMethod
-{
- bool Debug;
- // the size of this doesn't really matter (except for performance)
- const static int BUF_SIZE = 1024;
- // the ed commands
- enum Mode {MODE_CHANGED, MODE_DELETED, MODE_ADDED};
- // return values
- enum State {ED_OK, ED_ORDERING, ED_PARSER, ED_FAILURE};
- // this applies a single hunk, it uses a tail recursion to
- // reverse the hunks in the file
- int ed_rec(FILE *ed_cmds, FILE *in_file, FILE *out_file, int line,
- char *buffer, unsigned int bufsize, Hashes *hash);
- // apply a patch file
- int ed_file(FILE *ed_cmds, FILE *in_file, FILE *out_file, Hashes *hash);
- // the methods main method
- virtual bool Fetch(FetchItem *Itm);
-
- public:
-
- RredMethod() : pkgAcqMethod("1.1",SingleInstance | SendConfig) {};
+ State patchFile(FileFd &Patch, FileFd &From, FileFd &out_file, Hashes *hash) const;
+ State patchMMap(FileFd &Patch, FileFd &From, FileFd &out_file, Hashes *hash) const;
+
+protected:
+ // the methods main method
+ virtual bool Fetch(FetchItem *Itm);
+
+public:
+ RredMethod() : pkgAcqMethod("1.1",SingleInstance | SendConfig) {};
};
+ /*}}}*/
+/** \brief applyFile - in reverse order with a tail recursion {{{
+ *
+ * As it is expected that the commands are in reversed order in the patch file
+ * we check in the first half if the command is valid, but doesn't execute it
+ * and move a step deeper. After reaching the end of the file we apply the
+ * patches in the correct order: last found command first.
+ *
+ * \param ed_cmds patch file to apply
+ * \param in_file base file we want to patch
+ * \param out_file file to write the patched result to
+ * \param line of command operation
+ * \param buffer internal used read/write buffer
+ * \param hash the created file for correctness
+ * \return the success State of the ed command executor
+ */
+RredMethod::State RredMethod::applyFile(FILE *ed_cmds, FILE *in_file, FILE *out_file,
+ unsigned long &line, char *buffer, Hashes *hash) const {
+ // get the current command and parse it
+ if (fgets(buffer, BUF_SIZE, ed_cmds) == NULL) {
+ if (Debug == true)
+ std::clog << "rred: encounter end of file - we can start patching now." << std::endl;
+ line = 0;
+ return ED_OK;
+ }
-int RredMethod::ed_rec(FILE *ed_cmds, FILE *in_file, FILE *out_file, int line,
- char *buffer, unsigned int bufsize, Hashes *hash) {
- int pos;
- int startline;
- int stopline;
- int mode;
- int written;
- char *idx;
-
- /* get the current command and parse it*/
- if (fgets(buffer, bufsize, ed_cmds) == NULL) {
- return line;
- }
- startline = strtol(buffer, &idx, 10);
- if (startline < line) {
- return ED_ORDERING;
- }
- if (*idx == ',') {
- idx++;
- stopline = strtol(idx, &idx, 10);
- }
- else {
- stopline = startline;
- }
- if (*idx == 'c') {
- mode = MODE_CHANGED;
- if (Debug == true) {
- std::clog << "changing from line " << startline
- << " to " << stopline << std::endl;
- }
- }
- else if (*idx == 'a') {
- mode = MODE_ADDED;
- if (Debug == true) {
- std::clog << "adding after line " << startline << std::endl;
- }
- }
- else if (*idx == 'd') {
- mode = MODE_DELETED;
- if (Debug == true) {
- std::clog << "deleting from line " << startline
- << " to " << stopline << std::endl;
- }
- }
- else {
- return ED_PARSER;
- }
- /* get the current position */
- pos = ftell(ed_cmds);
- /* if this is add or change then go to the next full stop */
- if ((mode == MODE_CHANGED) || (mode == MODE_ADDED)) {
- do {
- fgets(buffer, bufsize, ed_cmds);
- while ((strlen(buffer) == (bufsize - 1))
- && (buffer[bufsize - 2] != '\n')) {
- fgets(buffer, bufsize, ed_cmds);
- buffer[0] = ' ';
- }
- } while (strncmp(buffer, ".", 1) != 0);
- }
- /* do the recursive call */
- line = ed_rec(ed_cmds, in_file, out_file, line, buffer, bufsize,
- hash);
- /* pass on errors */
- if (line < 0) {
- return line;
- }
- /* apply our hunk */
- fseek(ed_cmds, pos, SEEK_SET);
- /* first wind to the current position */
- if (mode != MODE_ADDED) {
- startline -= 1;
- }
- while (line < startline) {
- fgets(buffer, bufsize, in_file);
- written = fwrite(buffer, 1, strlen(buffer), out_file);
- hash->Add((unsigned char*)buffer, written);
- while ((strlen(buffer) == (bufsize - 1))
- && (buffer[bufsize - 2] != '\n')) {
- fgets(buffer, bufsize, in_file);
- written = fwrite(buffer, 1, strlen(buffer), out_file);
- hash->Add((unsigned char*)buffer, written);
- }
- line++;
- }
- /* include from ed script */
- if ((mode == MODE_ADDED) || (mode == MODE_CHANGED)) {
- do {
- fgets(buffer, bufsize, ed_cmds);
- if (strncmp(buffer, ".", 1) != 0) {
- written = fwrite(buffer, 1, strlen(buffer), out_file);
- hash->Add((unsigned char*)buffer, written);
- while ((strlen(buffer) == (bufsize - 1))
- && (buffer[bufsize - 2] != '\n')) {
- fgets(buffer, bufsize, ed_cmds);
- written = fwrite(buffer, 1, strlen(buffer), out_file);
- hash->Add((unsigned char*)buffer, written);
- }
- }
- else {
- break;
- }
- } while (1);
- }
- /* ignore the corresponding number of lines from input */
- if ((mode == MODE_DELETED) || (mode == MODE_CHANGED)) {
- while (line < stopline) {
- fgets(buffer, bufsize, in_file);
- while ((strlen(buffer) == (bufsize - 1))
- && (buffer[bufsize - 2] != '\n')) {
- fgets(buffer, bufsize, in_file);
- }
- line++;
- }
- }
- return line;
-}
+ // parse in the effected linenumbers
+ char* idx;
+ errno=0;
+ unsigned long const startline = strtol(buffer, &idx, 10);
+ if (errno == ERANGE || errno == EINVAL) {
+ _error->Errno("rred", "startline is an invalid number");
+ return ED_PARSER;
+ }
+ if (startline > line) {
+ _error->Error("rred: The start line (%lu) of the next command is higher than the last line (%lu). This is not allowed.", startline, line);
+ return ED_ORDERING;
+ }
+ unsigned long stopline;
+ if (*idx == ',') {
+ idx++;
+ errno=0;
+ stopline = strtol(idx, &idx, 10);
+ if (errno == ERANGE || errno == EINVAL) {
+ _error->Errno("rred", "stopline is an invalid number");
+ return ED_PARSER;
+ }
+ }
+ else {
+ stopline = startline;
+ }
+ line = startline;
+
+ // which command to execute on this line(s)?
+ switch (*idx) {
+ case MODE_CHANGED:
+ if (Debug == true)
+ std::clog << "Change from line " << startline << " to " << stopline << std::endl;
+ break;
+ case MODE_ADDED:
+ if (Debug == true)
+ std::clog << "Insert after line " << startline << std::endl;
+ break;
+ case MODE_DELETED:
+ if (Debug == true)
+ std::clog << "Delete from line " << startline << " to " << stopline << std::endl;
+ break;
+ default:
+ _error->Error("rred: Unknown ed command '%c'. Abort.", *idx);
+ return ED_PARSER;
+ }
+ unsigned char mode = *idx;
+
+ // save the current position
+ unsigned const long pos = ftell(ed_cmds);
+
+ // if this is add or change then go to the next full stop
+ unsigned int data_length = 0;
+ if (mode == MODE_CHANGED || mode == MODE_ADDED) {
+ do {
+ ignoreLineInFile(ed_cmds, buffer);
+ data_length++;
+ }
+ while (strncmp(buffer, ".", 1) != 0);
+ data_length--; // the dot should not be copied
+ }
+
+ // do the recursive call - the last command is the one we need to execute at first
+ const State child = applyFile(ed_cmds, in_file, out_file, line, buffer, hash);
+ if (child != ED_OK) {
+ return child;
+ }
+
+ // change and delete are working on "line" - add is done after "line"
+ if (mode != MODE_ADDED)
+ line++;
+
+ // first wind to the current position and copy over all unchanged lines
+ if (line < startline) {
+ copyLinesFromFileToFile(in_file, out_file, (startline - line), hash, buffer);
+ line = startline;
+ }
-int RredMethod::ed_file(FILE *ed_cmds, FILE *in_file, FILE *out_file,
- Hashes *hash) {
+ if (mode != MODE_ADDED)
+ line--;
+
+ // include data from ed script
+ if (mode == MODE_CHANGED || mode == MODE_ADDED) {
+ fseek(ed_cmds, pos, SEEK_SET);
+ copyLinesFromFileToFile(ed_cmds, out_file, data_length, hash, buffer);
+ }
+
+ // ignore the corresponding number of lines from input
+ if (mode == MODE_CHANGED || mode == MODE_DELETED) {
+ while (line < stopline) {
+ ignoreLineInFile(in_file, buffer);
+ line++;
+ }
+ }
+ return ED_OK;
+}
+ /*}}}*/
+void RredMethod::copyLinesFromFileToFile(FILE *fin, FILE *fout, unsigned int lines,/*{{{*/
+ Hashes *hash, char *buffer) const {
+ while (0 < lines--) {
+ do {
+ fgets(buffer, BUF_SIZE, fin);
+ size_t const written = fwrite(buffer, 1, strlen(buffer), fout);
+ hash->Add((unsigned char*)buffer, written);
+ } while (strlen(buffer) == (BUF_SIZE - 1) &&
+ buffer[BUF_SIZE - 2] != '\n');
+ }
+}
+ /*}}}*/
+void RredMethod::ignoreLineInFile(FILE *fin, char *buffer) const { /*{{{*/
+ fgets(buffer, BUF_SIZE, fin);
+ while (strlen(buffer) == (BUF_SIZE - 1) &&
+ buffer[BUF_SIZE - 2] != '\n') {
+ fgets(buffer, BUF_SIZE, fin);
+ buffer[0] = ' ';
+ }
+}
+ /*}}}*/
+RredMethod::State RredMethod::patchFile(FileFd &Patch, FileFd &From, /*{{{*/
+ FileFd &out_file, Hashes *hash) const {
char buffer[BUF_SIZE];
- int result;
- int written;
-
+ FILE* fFrom = fdopen(From.Fd(), "r");
+ FILE* fPatch = fdopen(Patch.Fd(), "r");
+ FILE* fTo = fdopen(out_file.Fd(), "w");
+
/* we do a tail recursion to read the commands in the right order */
- result = ed_rec(ed_cmds, in_file, out_file, 0, buffer, BUF_SIZE,
- hash);
+ unsigned long line = -1; // assign highest possible value
+ State const result = applyFile(fPatch, fFrom, fTo, line, buffer, hash);
/* read the rest from infile */
- if (result >= 0) {
- while (fgets(buffer, BUF_SIZE, in_file) != NULL) {
- written = fwrite(buffer, 1, strlen(buffer), out_file);
+ if (result == ED_OK) {
+ while (fgets(buffer, BUF_SIZE, fFrom) != NULL) {
+ size_t const written = fwrite(buffer, 1, strlen(buffer), fTo);
hash->Add((unsigned char*)buffer, written);
}
+ fflush(fTo);
}
- else {
- return ED_FAILURE;
- }
- return ED_OK;
+ return result;
}
+ /*}}}*/
+struct EdCommand { /*{{{*/
+ size_t data_start;
+ size_t data_end;
+ size_t data_lines;
+ size_t first_line;
+ size_t last_line;
+ char type;
+};
+#define IOV_COUNT 1024 /* Don't really want IOV_MAX since it can be arbitrarily large */
+ /*}}}*/
+RredMethod::State RredMethod::patchMMap(FileFd &Patch, FileFd &From, /*{{{*/
+ FileFd &out_file, Hashes *hash) const {
+#ifdef _POSIX_MAPPED_FILES
+ MMap ed_cmds(Patch, MMap::ReadOnly);
+ MMap in_file(From, MMap::ReadOnly);
+
+ if (ed_cmds.Size() == 0 || in_file.Size() == 0)
+ return MMAP_FAILED;
+
+ EdCommand* commands = 0;
+ size_t command_count = 0;
+ size_t command_alloc = 0;
+
+ const char* begin = (char*) ed_cmds.Data();
+ const char* end = begin;
+ const char* ed_end = (char*) ed_cmds.Data() + ed_cmds.Size();
+
+ const char* input = (char*) in_file.Data();
+ const char* input_end = (char*) in_file.Data() + in_file.Size();
+
+ size_t i;
+
+ /* 1. Parse entire script. It is executed in reverse order, so we cather it
+ * in the `commands' buffer first
+ */
+
+ for(;;) {
+ EdCommand cmd;
+ cmd.data_start = 0;
+ cmd.data_end = 0;
+
+ while(begin != ed_end && *begin == '\n')
+ ++begin;
+ while(end != ed_end && *end != '\n')
+ ++end;
+ if(end == ed_end && begin == end)
+ break;
+
+ /* Determine command range */
+ const char* tmp = begin;
+
+ for(;;) {
+ /* atoll is safe despite lacking NUL-termination; we know there's an
+ * alphabetic character at end[-1]
+ */
+ if(tmp == end) {
+ cmd.first_line = atol(begin);
+ cmd.last_line = cmd.first_line;
+ break;
+ }
+ if(*tmp == ',') {
+ cmd.first_line = atol(begin);
+ cmd.last_line = atol(tmp + 1);
+ break;
+ }
+ ++tmp;
+ }
+
+ // which command to execute on this line(s)?
+ switch (end[-1]) {
+ case MODE_CHANGED:
+ if (Debug == true)
+ std::clog << "Change from line " << cmd.first_line << " to " << cmd.last_line << std::endl;
+ break;
+ case MODE_ADDED:
+ if (Debug == true)
+ std::clog << "Insert after line " << cmd.first_line << std::endl;
+ break;
+ case MODE_DELETED:
+ if (Debug == true)
+ std::clog << "Delete from line " << cmd.first_line << " to " << cmd.last_line << std::endl;
+ break;
+ default:
+ _error->Error("rred: Unknown ed command '%c'. Abort.", end[-1]);
+ free(commands);
+ return ED_PARSER;
+ }
+ cmd.type = end[-1];
+
+ /* Determine the size of the inserted text, so we don't have to scan this
+ * text again later.
+ */
+ begin = end + 1;
+ end = begin;
+ cmd.data_lines = 0;
+
+ if(cmd.type == MODE_ADDED || cmd.type == MODE_CHANGED) {
+ cmd.data_start = begin - (char*) ed_cmds.Data();
+ while(end != ed_end) {
+ if(*end == '\n') {
+ if(end[-1] == '.' && end[-2] == '\n')
+ break;
+ ++cmd.data_lines;
+ }
+ ++end;
+ }
+ cmd.data_end = end - (char*) ed_cmds.Data() - 1;
+ begin = end + 1;
+ end = begin;
+ }
+ if(command_count == command_alloc) {
+ command_alloc = (command_alloc + 64) * 3 / 2;
+ commands = (EdCommand*) realloc(commands, command_alloc * sizeof(EdCommand));
+ }
+ commands[command_count++] = cmd;
+ }
+
+ struct iovec* iov = new struct iovec[IOV_COUNT];
+ size_t iov_size = 0;
+
+ size_t amount, remaining;
+ size_t line = 1;
+ EdCommand* cmd;
+
+ /* 2. Execute script. We gather writes in a `struct iov' array, and flush
+ * using writev to minimize the number of system calls. Data is read
+ * directly from the memory mappings of the input file and the script.
+ */
+
+ for(i = command_count; i-- > 0; ) {
+ cmd = &commands[i];
+ if(cmd->type == MODE_ADDED)
+ amount = cmd->first_line + 1;
+ else
+ amount = cmd->first_line;
+
+ if(line < amount) {
+ begin = input;
+ while(line != amount) {
+ input = (const char*) memchr(input, '\n', input_end - input);
+ if(!input)
+ break;
+ ++line;
+ ++input;
+ }
+ iov[iov_size].iov_base = (void*) begin;
+ iov[iov_size].iov_len = input - begin;
+ hash->Add((const unsigned char*) begin, input - begin);
-bool RredMethod::Fetch(FetchItem *Itm)
+ if(++iov_size == IOV_COUNT) {
+ writev(out_file.Fd(), iov, IOV_COUNT);
+ iov_size = 0;
+ }
+ }
+
+ if(cmd->type == MODE_DELETED || cmd->type == MODE_CHANGED) {
+ remaining = (cmd->last_line - cmd->first_line) + 1;
+ line += remaining;
+ while(remaining) {
+ input = (const char*) memchr(input, '\n', input_end - input);
+ if(!input)
+ break;
+ --remaining;
+ ++input;
+ }
+ }
+
+ if(cmd->type == MODE_CHANGED || cmd->type == MODE_ADDED) {
+ if(cmd->data_end != cmd->data_start) {
+ iov[iov_size].iov_base = (void*) ((char*)ed_cmds.Data() + cmd->data_start);
+ iov[iov_size].iov_len = cmd->data_end - cmd->data_start;
+ hash->Add((const unsigned char*) ((char*)ed_cmds.Data() + cmd->data_start),
+ iov[iov_size].iov_len);
+
+ if(++iov_size == IOV_COUNT) {
+ writev(out_file.Fd(), iov, IOV_COUNT);
+ iov_size = 0;
+ }
+ }
+ }
+ }
+
+ if(input != input_end) {
+ iov[iov_size].iov_base = (void*) input;
+ iov[iov_size].iov_len = input_end - input;
+ hash->Add((const unsigned char*) input, input_end - input);
+ ++iov_size;
+ }
+
+ if(iov_size) {
+ writev(out_file.Fd(), iov, iov_size);
+ iov_size = 0;
+ }
+
+ for(i = 0; i < iov_size; i += IOV_COUNT) {
+ if(iov_size - i < IOV_COUNT)
+ writev(out_file.Fd(), iov + i, iov_size - i);
+ else
+ writev(out_file.Fd(), iov + i, IOV_COUNT);
+ }
+
+ delete [] iov;
+ free(commands);
+
+ return ED_OK;
+#else
+ return MMAP_FAILED;
+#endif
+}
+ /*}}}*/
+bool RredMethod::Fetch(FetchItem *Itm) /*{{{*/
{
- Debug = _config->FindB("Debug::pkgAcquire::RRed",false);
+ Debug = _config->FindB("Debug::pkgAcquire::RRed", false);
URI Get = Itm->Uri;
string Path = Get.Host + Get.Path; // To account for relative paths
- // Path contains the filename to patch
+
FetchResult Res;
Res.Filename = Itm->DestFile;
- URIStart(Res);
- // Res.Filename the destination filename
+ if (Itm->Uri.empty() == true) {
+ Path = Itm->DestFile;
+ Itm->DestFile.append(".result");
+ } else
+ URIStart(Res);
if (Debug == true)
std::clog << "Patching " << Path << " with " << Path
@@ -211,19 +452,27 @@ bool RredMethod::Fetch(FetchItem *Itm)
return false;
Hashes Hash;
- FILE* fFrom = fdopen(From.Fd(), "r");
- FILE* fPatch = fdopen(Patch.Fd(), "r");
- FILE* fTo = fdopen(To.Fd(), "w");
// now do the actual patching
- if (ed_file(fPatch, fFrom, fTo, &Hash) != ED_OK) {
- _error->Errno("rred", _("Could not patch file"));
- return false;
+ State const result = patchMMap(Patch, From, To, &Hash);
+ if (result == MMAP_FAILED) {
+ // retry with patchFile
+ lseek(Patch.Fd(), 0, SEEK_SET);
+ lseek(From.Fd(), 0, SEEK_SET);
+ To.Open(Itm->DestFile,FileFd::WriteEmpty);
+ if (_error->PendingError() == true)
+ return false;
+ if (patchFile(Patch, From, To, &Hash) != ED_OK) {
+ return _error->WarningE("rred", _("Could not patch %s with mmap and with file operation usage - the patch seems to be corrupt."), Path.c_str());
+ } else if (Debug == true) {
+ std::clog << "rred: finished file patching of " << Path << " after mmap failed." << std::endl;
+ }
+ } else if (result != ED_OK) {
+ return _error->Errno("rred", _("Could not patch %s with mmap (but no mmap specific fail) - the patch seems to be corrupt."), Path.c_str());
+ } else if (Debug == true) {
+ std::clog << "rred: finished mmap patching of " << Path << std::endl;
}
// write out the result
- fflush(fFrom);
- fflush(fPatch);
- fflush(fTo);
From.Close();
Patch.Close();
To.Close();
@@ -250,13 +499,44 @@ bool RredMethod::Fetch(FetchItem *Itm)
return true;
}
-
-int main(int argc, char *argv[])
-{
- RredMethod Mth;
-
- Prog = strrchr(argv[0],'/');
- Prog++;
-
- return Mth.Run();
+ /*}}}*/
+/** \brief Wrapper class for testing rred */ /*{{{*/
+class TestRredMethod : public RredMethod {
+public:
+ /** \brief Run rred in debug test mode
+ *
+ * This method can be used to run the rred method outside
+ * of the "normal" acquire environment for easier testing.
+ *
+ * \param base basename of all files involved in this rred test
+ */
+ bool Run(char const *base) {
+ _config->CndSet("Debug::pkgAcquire::RRed", "true");
+ FetchItem *test = new FetchItem;
+ test->DestFile = base;
+ return Fetch(test);
+ }
+};
+ /*}}}*/
+/** \brief Starter for the rred method (or its test method) {{{
+ *
+ * Used without parameters is the normal behavior for methods for
+ * the APT acquire system. While this works great for the acquire system
+ * it is very hard to test the method and therefore the method also
+ * accepts one parameter which will switch it directly to debug test mode:
+ * The test mode expects that if "Testfile" is given as parameter
+ * the file "Testfile" should be ed-style patched with "Testfile.ed"
+ * and will write the result to "Testfile.result".
+ */
+int main(int argc, char *argv[]) {
+ if (argc <= 1) {
+ RredMethod Mth;
+ return Mth.Run();
+ } else {
+ TestRredMethod Mth;
+ bool result = Mth.Run(argv[1]);
+ _error->DumpErrors();
+ return result;
+ }
}
+ /*}}}*/