summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMake/Misc.cmake20
-rw-r--r--CMakeLists.txt6
-rw-r--r--apt-pkg/CMakeLists.txt2
-rw-r--r--apt-pkg/acquire-item.cc21
-rw-r--r--apt-pkg/acquire.cc21
-rw-r--r--apt-pkg/aptconfiguration.cc2
-rw-r--r--apt-pkg/cachefile.cc18
-rw-r--r--apt-pkg/cacheiterators.h33
-rw-r--r--apt-pkg/contrib/error.cc9
-rw-r--r--apt-pkg/contrib/error.h20
-rw-r--r--apt-pkg/contrib/fileutl.cc9
-rw-r--r--apt-pkg/contrib/fileutl.h22
-rw-r--r--apt-pkg/contrib/hashes.cc4
-rw-r--r--apt-pkg/contrib/macros.h2
-rw-r--r--apt-pkg/contrib/mmap.cc29
-rw-r--r--apt-pkg/contrib/mmap.h2
-rw-r--r--apt-pkg/contrib/progress.cc2
-rw-r--r--apt-pkg/contrib/srvrec.cc5
-rw-r--r--apt-pkg/contrib/string_view.h13
-rw-r--r--apt-pkg/contrib/strutl.h21
-rw-r--r--apt-pkg/deb/debindexfile.cc6
-rw-r--r--apt-pkg/deb/deblistparser.cc57
-rw-r--r--apt-pkg/deb/deblistparser.h1
-rw-r--r--apt-pkg/deb/debmetaindex.cc14
-rw-r--r--apt-pkg/deb/debmetaindex.h4
-rw-r--r--apt-pkg/deb/debrecords.cc21
-rw-r--r--apt-pkg/deb/debrecords.h2
-rw-r--r--apt-pkg/deb/debsrcrecords.cc2
-rw-r--r--apt-pkg/deb/dpkgpm.cc9
-rw-r--r--apt-pkg/edsp.cc4
-rw-r--r--apt-pkg/endian.h118
-rw-r--r--apt-pkg/getservbyport_r.cc59
-rw-r--r--apt-pkg/indexcopy.cc2
-rw-r--r--apt-pkg/init.cc2
-rw-r--r--apt-pkg/memrchr.cc157
-rw-r--r--apt-pkg/missing.h26
-rw-r--r--apt-pkg/nameser_compat.h187
-rw-r--r--apt-pkg/pkgcache.cc1
-rw-r--r--apt-pkg/pkgcache.h20
-rw-r--r--apt-pkg/pkgcachegen.cc110
-rw-r--r--apt-pkg/pkgcachegen.h5
-rw-r--r--apt-pkg/pkgrecords.h4
-rw-r--r--apt-pkg/policy.cc3
-rw-r--r--apt-pkg/rawmemchr.cc139
-rw-r--r--apt-pkg/strchrnul.cc147
-rw-r--r--apt-pkg/tagfile.cc435
-rw-r--r--apt-pkg/tagfile.h21
-rw-r--r--debian/libapt-pkg5.0.symbols4
-rw-r--r--ftparchive/apt-ftparchive.cc2
-rw-r--r--ftparchive/byhash.cc4
-rw-r--r--ftparchive/cachedb.cc1
-rw-r--r--methods/CMakeLists.txt2
-rw-r--r--methods/connect.cc4
-rw-r--r--methods/gpgv.cc2
-rw-r--r--methods/http.cc1466
-rw-r--r--methods/http.h96
-rw-r--r--test/CMakeLists.txt1
57 files changed, 1870 insertions, 1529 deletions
diff --git a/CMake/Misc.cmake b/CMake/Misc.cmake
index 6ad0b9479..45a00ae0c 100644
--- a/CMake/Misc.cmake
+++ b/CMake/Misc.cmake
@@ -66,16 +66,16 @@ endfunction()
# Generates a simple version script versioning everything with current SOVERSION
function(add_version_script target)
- get_target_property(soversion ${target} SOVERSION)
- set(script "${CMAKE_CURRENT_BINARY_DIR}/${target}.versionscript")
- string(REPLACE "-" "" name "${target}_${soversion}")
- string(TOUPPER "${name}" name)
- add_custom_command(OUTPUT "${script}"
- COMMAND echo "${name} {global: *; };" > "${script}"
- VERBATIM )
- add_custom_target(${target}-versionscript DEPENDS "${script}")
- target_link_libraries(${target} PRIVATE -Wl,-version-script="${script}")
- add_dependencies(${target} ${target}-versionscript)
+ #get_target_property(soversion ${target} SOVERSION)
+ #set(script "${CMAKE_CURRENT_BINARY_DIR}/${target}.versionscript")
+ #string(REPLACE "-" "" name "${target}_${soversion}")
+ #string(TOUPPER "${name}" name)
+ #add_custom_command(OUTPUT "${script}"
+ # COMMAND echo "${name} {global: *; };" > "${script}"
+ # VERBATIM )
+ #add_custom_target(${target}-versionscript DEPENDS "${script}")
+ #target_link_libraries(${target} PRIVATE -Wl,-version-script="${script}")
+ #add_dependencies(${target} ${target}-versionscript)
endfunction()
function(path_join out path1 path2)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 4117aebe4..979202702 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -17,8 +17,8 @@ set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/CMake")
# Add coverage target
set(CMAKE_CXX_FLAGS_COVERAGE "-g -fprofile-arcs -ftest-coverage")
-set(CMAKE_EXE_LINKER_FLAGS_COVERAGE "-lgcov")
-set(CMAKE_SHARED_LINKER_FLAGS_COVERAGE "-lgcov")
+set(CMAKE_EXE_LINKER_FLAGS_COVERAGE "-lgcov -lSystem")
+set(CMAKE_SHARED_LINKER_FLAGS_COVERAGE "-lgcov -lSystem")
# Work around bug in GNUInstallDirs
if (EXISTS "/etc/debian_version")
@@ -232,7 +232,9 @@ add_subdirectory(apt-private)
add_subdirectory(apt-inst)
add_subdirectory(cmdline)
add_subdirectory(completions)
+if (WITH_DOC)
add_subdirectory(doc)
+endif()
add_subdirectory(dselect)
add_subdirectory(ftparchive)
add_subdirectory(methods)
diff --git a/apt-pkg/CMakeLists.txt b/apt-pkg/CMakeLists.txt
index ce73c6a34..318c6d798 100644
--- a/apt-pkg/CMakeLists.txt
+++ b/apt-pkg/CMakeLists.txt
@@ -37,7 +37,7 @@ file(GLOB_RECURSE headers "*.h")
# Create a library using the C++ files
add_library(apt-pkg SHARED ${library})
-add_dependencies(apt-pkg apt-pkg-versionscript)
+#add_dependencies(apt-pkg apt-pkg-versionscript)
# Link the library and set the SONAME
target_include_directories(apt-pkg
PRIVATE ${ZLIB_INCLUDE_DIRS}
diff --git a/apt-pkg/acquire-item.cc b/apt-pkg/acquire-item.cc
index bb3bc1b56..fbd561107 100644
--- a/apt-pkg/acquire-item.cc
+++ b/apt-pkg/acquire-item.cc
@@ -257,7 +257,7 @@ static bool APT_NONNULL(3, 4, 5) AllowInsecureRepositories(InsecureType const ms
if (TargetIsAllowedToBe(TransactionManager->Target, msg) == true)
{
- MessageInsecureRepository(false, msgstr, repo);
+ //MessageInsecureRepository(false, msgstr, repo);
return true;
}
@@ -1455,7 +1455,6 @@ bool pkgAcqMetaBase::CheckDownloadDone(pkgAcqTransactionItem * const I, const st
{
// for simplicity, the transaction manager is always InRelease
// even if it doesn't exist.
- TransactionManager->IMSHit = true;
I->PartialFile = I->DestFile = I->GetFinalFilename();
}
@@ -1608,7 +1607,7 @@ void pkgAcqMetaClearSig::QueueIndexes(bool const verify) /*{{{*/
}
// optional targets that we do not have in the Release file are skipped
- if (hasHashes == true && Target.IsOptional)
+ if (Target.IsOptional)
{
new CleanupItem(Owner, TransactionManager, Target);
continue;
@@ -1724,6 +1723,13 @@ void pkgAcqMetaClearSig::QueueIndexes(bool const verify) /*{{{*/
}
else
{
+ // if the source wanted these files they should have given us a release file :/
+ if (Target.IsOptional)
+ {
+ new CleanupItem(Owner, TransactionManager, Target);
+ continue;
+ }
+
// if we have no file to patch, no point in trying
trypdiff &= (GetExistingFilename(GetFinalFileNameFromURI(Target.URI)).empty() == false);
}
@@ -3275,6 +3281,8 @@ void pkgAcqIndex::StageDownloadDone(string const &Message)
{
// copy FinalFile into partial/ so that we check the hash again
string const FinalFile = GetExistingFilename(GetFinalFileNameFromURI(Target.URI));
+ DestFile = GetKeepCompressedFileName(GetPartialFileNameFromURI(Target.URI), Target);
+ unlink(DestFile.c_str());
if (symlink(FinalFile.c_str(), DestFile.c_str()) != 0)
_error->WarningE("pkgAcqIndex::StageDownloadDone", "Symlinking final file %s back to %s failed", FinalFile.c_str(), DestFile.c_str());
else
@@ -3283,7 +3291,10 @@ void pkgAcqIndex::StageDownloadDone(string const &Message)
Filename = DestFile;
}
Stage = STAGE_DECOMPRESS_AND_VERIFY;
- Desc.URI = "store:" + Filename;
+ if (Filename != DestFile && flExtension(Filename) == flExtension(DestFile))
+ Desc.URI = "copy:" + Filename;
+ else
+ Desc.URI = "store:" + Filename;
QueueURI(Desc);
SetActiveSubprocess(::URI(Desc.URI).Access);
return;
@@ -3782,7 +3793,7 @@ std::string pkgAcqChangelog::URITemplate(pkgCache::RlsFileIterator const &Rls)
should be so this could produce request order-dependent anomalies */
if (OpenMaybeClearSignedFile(Rls.FileName(), rf) == true)
{
- pkgTagFile TagFile(&rf, rf.Size());
+ pkgTagFile TagFile(&rf);
pkgTagSection Section;
if (TagFile.Step(Section) == true)
server = Section.FindS("Changelogs");
diff --git a/apt-pkg/acquire.cc b/apt-pkg/acquire.cc
index 541785b03..6a6167f3b 100644
--- a/apt-pkg/acquire.cc
+++ b/apt-pkg/acquire.cc
@@ -450,6 +450,24 @@ string pkgAcquire::QueueName(string Uri,MethodConfig const *&Config)
} else
{
FullQueueName = AccessSchema + U.Host;
+
+ int parallel(_config->FindI("Acquire::"+U.Access+"::MaxParallel",8));
+ if (parallel > 0) {
+ typedef map<string, int> indexmap;
+ static indexmap indices;
+
+ pair<indexmap::iterator, bool> cache(indices.insert(indexmap::value_type(FullQueueName, -1)));
+ if (cache.second || cache.first->second == -1) {
+ int &index(indices[U.Access]);
+ if (index >= parallel)
+ index = 0;
+ cache.first->second = index++;
+ }
+
+ ostringstream value;
+ value << U.Access << "::" << cache.first->second;
+ FullQueueName = value.str();
+ }
}
unsigned int Instances = 0, SchemaLength = AccessSchema.length();
@@ -609,7 +627,6 @@ static void CheckDropPrivsMustBeDisabled(pkgAcquire const &Fetcher)
struct passwd const * const pw = getpwnam(SandboxUser.c_str());
if (pw == NULL)
{
- _error->Warning(_("No sandbox user '%s' on the system, can not drop privileges"), SandboxUser.c_str());
_config->Set("APT::Sandbox::User", "");
return;
}
@@ -1262,7 +1279,7 @@ static struct timeval GetTimevalFromSteadyClock()
auto const Time = std::chrono::steady_clock::now().time_since_epoch();
auto const Time_sec = std::chrono::duration_cast<std::chrono::seconds>(Time);
auto const Time_usec = std::chrono::duration_cast<std::chrono::microseconds>(Time - Time_sec);
- return { Time_sec.count(), Time_usec.count() };
+ return { static_cast<time_t>(Time_sec.count()), static_cast<suseconds_t>(Time_usec.count()) };
}
bool pkgAcquireStatus::Pulse(pkgAcquire *Owner)
{
diff --git a/apt-pkg/aptconfiguration.cc b/apt-pkg/aptconfiguration.cc
index 61e53ec3a..d4e90bba1 100644
--- a/apt-pkg/aptconfiguration.cc
+++ b/apt-pkg/aptconfiguration.cc
@@ -200,7 +200,7 @@ std::vector<std::string> const Configuration::getLanguages(bool const &All,
// FIXME: Remove support for the old APT::Acquire::Translation
// it was undocumented and so it should be not very widthly used
string const oldAcquire = _config->Find("APT::Acquire::Translation","");
- if (oldAcquire.empty() == false && oldAcquire != "environment") {
+ if (oldAcquire.empty() == false && oldAcquire != "environment" && !_config->Exists("Acquire::Languages")) {
// TRANSLATORS: the two %s are APT configuration options
_error->Notice("Option '%s' is deprecated. Please use '%s' instead, see 'man 5 apt.conf' for details.",
"APT::Acquire::Translation", "Acquire::Languages");
diff --git a/apt-pkg/cachefile.cc b/apt-pkg/cachefile.cc
index 9a1a6cfa9..8168a9af3 100644
--- a/apt-pkg/cachefile.cc
+++ b/apt-pkg/cachefile.cc
@@ -97,7 +97,7 @@ bool pkgCacheFile::BuildCaches(OpProgress *Progress, bool WithLock)
return false;
Cache.reset(new pkgCache(Map.get()));
if (_error->PendingError() == true)
- return false;
+ return _error->ReturnError();
this->Cache = Cache.release();
this->Map = Map.release();
@@ -112,7 +112,7 @@ bool pkgCacheFile::BuildCaches(OpProgress *Progress, bool WithLock)
}
if (_error->PendingError() == true)
- return false;
+ return _error->ReturnError();
if (BuildSourceList(Progress) == false)
return false;
@@ -128,14 +128,8 @@ bool pkgCacheFile::BuildCaches(OpProgress *Progress, bool WithLock)
if (Res == false)
return _error->Error(_("The package lists or status file could not be parsed or opened."));
- /* This sux, remove it someday */
- if (_error->PendingError() == true)
- _error->Warning(_("You may want to run apt-get update to correct these problems"));
-
if (Cache == nullptr)
Cache.reset(new pkgCache(Map.get()));
- if (_error->PendingError() == true)
- return false;
this->Map = Map.release();
this->Cache = Cache.release();
@@ -169,7 +163,7 @@ bool pkgCacheFile::BuildPolicy(OpProgress * /*Progress*/)
Policy.reset(new pkgPolicy(Cache));
if (_error->PendingError() == true)
- return false;
+ return _error->ReturnError();
ReadPinFile(*Policy);
ReadPinDir(*Policy);
@@ -195,7 +189,7 @@ bool pkgCacheFile::BuildDepCache(OpProgress *Progress)
DCache.reset(new pkgDepCache(Cache,Policy));
if (_error->PendingError() == true)
- return false;
+ return _error->ReturnError();
if (DCache->Init(Progress) == false)
return false;
@@ -219,8 +213,6 @@ bool pkgCacheFile::Open(OpProgress *Progress, bool WithLock)
if (Progress != NULL)
Progress->Done();
- if (_error->PendingError() == true)
- return false;
return true;
}
@@ -266,7 +258,7 @@ bool pkgCacheFile::AddIndexFile(pkgIndexFile * const File) /*{{{*/
if (_error->PendingError() == true) {
delete Cache;
Cache = nullptr;
- return false;
+ return _error->ReturnError();
}
return true;
}
diff --git a/apt-pkg/cacheiterators.h b/apt-pkg/cacheiterators.h
index 20853061e..8ed001d21 100644
--- a/apt-pkg/cacheiterators.h
+++ b/apt-pkg/cacheiterators.h
@@ -59,7 +59,7 @@ template<typename Str, typename Itr> class pkgCache::Iterator :
Str* OwnerPointer() const { return static_cast<Itr const*>(this)->OwnerPointer(); }
protected:
- Str *S;
+ Str *volatile S;
pkgCache *Owner;
public:
@@ -216,6 +216,7 @@ class pkgCache::VerIterator : public Iterator<Version, VerIterator> {
// Accessors
inline const char *VerStr() const {return S->VerStr == 0?0:Owner->StrP + S->VerStr;}
inline const char *Section() const {return S->Section == 0?0:Owner->StrP + S->Section;}
+ inline const char *Display() const {return S->Display == 0?0:Owner->StrP + S->Display;}
/** \brief source package name this version comes from
Always contains the name, even if it is the same as the binary name */
inline const char *SourcePkgName() const {return Owner->StrP + S->SourcePkgName;}
@@ -233,6 +234,7 @@ class pkgCache::VerIterator : public Iterator<Version, VerIterator> {
DescIterator TranslatedDescription() const;
inline DepIterator DependsList() const;
inline PrvIterator ProvidesList() const;
+ inline TagIterator TagList() const;
inline VerFileIterator FileList() const;
bool Downloadable() const;
inline const char *PriorityType() const {return Owner->Priority(S->Priority);}
@@ -249,6 +251,33 @@ class pkgCache::VerIterator : public Iterator<Version, VerIterator> {
inline VerIterator() : Iterator<Version, VerIterator>() {}
};
/*}}}*/
+// Tag Iterator /*{{{*/
+class pkgCache::TagIterator : public Iterator<Tag, TagIterator> {
+ public:
+ inline Tag* OwnerPointer() const {
+ return (Owner != 0) ? Owner->TagP : 0;
+ }
+
+ // Iteration
+ void operator ++(int) {if (S != Owner->TagP) S = Owner->TagP + S->NextTag;};
+ inline void operator ++() {operator ++(0);};
+
+ // Comparison
+ inline bool operator ==(const TagIterator &B) const {return S == B.S;};
+ inline bool operator !=(const TagIterator &B) const {return S != B.S;};
+ int CompareTag(const TagIterator &B) const;
+
+ // Accessors
+ inline const char *Name() const {return Owner->StrP + S->Name;};
+ inline unsigned long Index() const {return S - Owner->TagP;};
+
+ inline TagIterator(pkgCache &Owner,Tag *Trg = 0) : Iterator<Tag, TagIterator>(Owner, Trg) {
+ if (S == 0)
+ S = OwnerPointer();
+ }
+ inline TagIterator() : Iterator<Tag, TagIterator>() {}
+};
+ /*}}}*/
// Description Iterator /*{{{*/
class pkgCache::DescIterator : public Iterator<Description, DescIterator> {
public:
@@ -519,6 +548,8 @@ inline pkgCache::DescIterator pkgCache::VerIterator::DescriptionList() const
{return DescIterator(*Owner,Owner->DescP + S->DescriptionList);}
inline pkgCache::PrvIterator pkgCache::VerIterator::ProvidesList() const
{return PrvIterator(*Owner,Owner->ProvideP + S->ProvidesList,S);}
+inline pkgCache::TagIterator pkgCache::VerIterator::TagList() const
+ {return TagIterator(*Owner,Owner->TagP + S->TagList);};
inline pkgCache::DepIterator pkgCache::VerIterator::DependsList() const
{return DepIterator(*Owner,Owner->DepP + S->DependsList,S);}
inline pkgCache::VerFileIterator pkgCache::VerIterator::FileList() const
diff --git a/apt-pkg/contrib/error.cc b/apt-pkg/contrib/error.cc
index 3c397eaf8..143b99557 100644
--- a/apt-pkg/contrib/error.cc
+++ b/apt-pkg/contrib/error.cc
@@ -206,6 +206,15 @@ void GlobalError::Discard() {
PendingFlag = false;
}
/*}}}*/
+// GlobalError::ReturnError - convert a stored error to a return code /*{{{*/
+bool GlobalError::ReturnError() {
+ for (auto &message : Messages)
+ if (message.Type == ERROR)
+ message.Type = WARNING;
+ PendingFlag = false;
+ return false;
+}
+ /*}}}*/
// GlobalError::empty - does our error list include anything? /*{{{*/
bool GlobalError::empty(MsgType const &threshold) const {
if (PendingFlag == true)
diff --git a/apt-pkg/contrib/error.h b/apt-pkg/contrib/error.h
index d0f450742..bab7a67b2 100644
--- a/apt-pkg/contrib/error.h
+++ b/apt-pkg/contrib/error.h
@@ -226,6 +226,26 @@ public: /*{{{*/
*/
inline bool PendingError() const APT_PURE {return PendingFlag;};
+ /** \brief convert a stored error to a return code
+ *
+ * Put simply, the entire concept of PendingError() is flawed :/.
+ *
+ * The typical "if (PendingError()) return false;" check that is
+ * strewn throughout the codebase "compounds", making it impossible
+ * for there to be any nuance about the notion of "error" when a
+ * subsystem needs to fail but a higher-level system needs to work.
+ *
+ * However, the codebase is also horribly broken with respect to
+ * errors, as it fails to use C++ exceptions when warranted and
+ * instead relies on this insane indirect error mechanism to check
+ * the failure status of a constructor. What is thereby needed is
+ * a way to clear the PendingError() flag without also discarding
+ * the underlying errors, so we have to convert them to warnings.
+ *
+ * \return \b false
+ */
+ bool ReturnError() APT_COLD;
+
/** \brief is the list empty?
*
* Can be used to check if the current stack level doesn't include
diff --git a/apt-pkg/contrib/fileutl.cc b/apt-pkg/contrib/fileutl.cc
index 4f123491b..7e80e251c 100644
--- a/apt-pkg/contrib/fileutl.cc
+++ b/apt-pkg/contrib/fileutl.cc
@@ -27,6 +27,7 @@
#include <apt-pkg/pkgsystem.h>
#include <apt-pkg/sptr.h>
#include <apt-pkg/strutl.h>
+#include <apt-pkg/endian.h>
#include <cstdio>
#include <cstdlib>
@@ -2210,12 +2211,6 @@ public:
dup2(compressed_fd,STDIN_FILENO);
dup2(Pipe[1],STDOUT_FILENO);
}
- int const nullfd = open("/dev/null", O_WRONLY);
- if (nullfd != -1)
- {
- dup2(nullfd,STDERR_FILENO);
- close(nullfd);
- }
SetCloseExec(STDOUT_FILENO,false);
SetCloseExec(STDIN_FILENO,false);
@@ -3071,7 +3066,7 @@ static std::string APT_NONNULL(1) GetTempDirEnv(char const * const env) /*{{{*/
stat(tmpdir, &st) != 0 || (st.st_mode & S_IFDIR) == 0) // exists and is directory
tmpdir = "/tmp";
else if (geteuid() != 0 && // root can do everything anyway
- faccessat(AT_FDCWD, tmpdir, R_OK | W_OK | X_OK, AT_EACCESS) != 0) // current user has rwx access to directory
+ access(tmpdir, R_OK | W_OK | X_OK) != 0) // current user has rwx access to directory
tmpdir = "/tmp";
return string(tmpdir);
diff --git a/apt-pkg/contrib/fileutl.h b/apt-pkg/contrib/fileutl.h
index 9005b81b5..92861ef76 100644
--- a/apt-pkg/contrib/fileutl.h
+++ b/apt-pkg/contrib/fileutl.h
@@ -30,6 +30,28 @@
#include <zlib.h>
+#include <errno.h>
+static inline int _execvp(const char *file, char *const argv[]) {
+ int rv = execvp(file, argv);
+ fprintf(stderr, "execvp failed, trying shell\n");
+ if (errno == ENOEXEC || errno == EPERM) {
+ int argc;
+ for (argc = 0; argv[argc] != NULL; argc++);
+ const char *newargv[argc+4];
+ newargv[0] = "/bin/sh";
+ newargv[1] = "-c";
+ newargv[2] = "exec \"$0\" \"$@\"";
+ for (int i = 0; i<argc; i++) {
+ newargv[i+3] = argv[i];
+ }
+ newargv[argc+3] = NULL;
+ return execvp(newargv[0], (char * const *)newargv);
+ }
+ return rv;
+}
+
+#define execvp(x, y) _execvp(x, y)
+
#ifndef APT_8_CLEANER_HEADERS
using std::string;
#endif
diff --git a/apt-pkg/contrib/hashes.cc b/apt-pkg/contrib/hashes.cc
index 98b92cc81..da74ada0b 100644
--- a/apt-pkg/contrib/hashes.cc
+++ b/apt-pkg/contrib/hashes.cc
@@ -140,8 +140,8 @@ APT_PURE bool HashString::usable() const /*{{{*/
{
return (
(Type != "Checksum-FileSize") &&
- (Type != "MD5Sum") &&
- (Type != "SHA1") &&
+ //(Type != "MD5Sum") &&
+ //(Type != "SHA1") &&
!IsConfigured(Type.c_str(), "Untrusted")
);
}
diff --git a/apt-pkg/contrib/macros.h b/apt-pkg/contrib/macros.h
index 57d3f6c22..13020a129 100644
--- a/apt-pkg/contrib/macros.h
+++ b/apt-pkg/contrib/macros.h
@@ -119,7 +119,7 @@
#ifndef APT_10_CLEANER_HEADERS
#if APT_GCC_VERSION >= 0x0300
#define __must_check __attribute__ ((warn_unused_result))
- #define __deprecated __attribute__ ((deprecated))
+ #define __deprecated __attribute__((deprecated))
#define __attrib_const __attribute__ ((__const__))
#define __like_printf(n) __attribute__((format(printf, n, n + 1)))
#else
diff --git a/apt-pkg/contrib/mmap.cc b/apt-pkg/contrib/mmap.cc
index ee6a21c83..a6414e530 100644
--- a/apt-pkg/contrib/mmap.cc
+++ b/apt-pkg/contrib/mmap.cc
@@ -38,7 +38,6 @@
MMap::MMap(FileFd &F,unsigned long Flags) : Flags(Flags), iSize(0),
Base(nullptr), SyncToFd(nullptr)
{
- if ((Flags & NoImmMap) != NoImmMap)
Map(F);
}
/*}}}*/
@@ -105,14 +104,14 @@ bool MMap::Map(FileFd &Fd)
if (unlikely(Base == nullptr))
return _error->Errno("MMap-malloc", _("Couldn't make mmap of %llu bytes"), iSize);
SyncToFd = new FileFd();
- return Fd.Read(Base, iSize);
+ return Fd.Seek(0L) && Fd.Read(Base, iSize);
}
// FIXME: Writing to compressed fd's ?
int const dupped_fd = dup(Fd.Fd());
if (dupped_fd == -1)
return _error->Errno("mmap", _("Couldn't duplicate file descriptor %i"), Fd.Fd());
- Base = calloc(iSize, 1);
+ Base = malloc(iSize);
if (unlikely(Base == nullptr))
return _error->Errno("MMap-calloc", _("Couldn't make mmap of %llu bytes"), iSize);
SyncToFd = new FileFd (dupped_fd);
@@ -193,7 +192,7 @@ bool MMap::Sync(unsigned long Start,unsigned long Stop)
{
if (SyncToFd != 0)
{
- if (!SyncToFd->Seek(0) ||
+ if (!SyncToFd->Seek(Start) ||
!SyncToFd->Write (((char *)Base)+Start, Stop-Start))
return false;
}
@@ -201,7 +200,8 @@ bool MMap::Sync(unsigned long Start,unsigned long Stop)
{
#ifdef _POSIX_SYNCHRONIZED_IO
unsigned long long const PSize = sysconf(_SC_PAGESIZE);
- if (msync((char *)Base+(Start/PSize)*PSize, Stop - Start, MS_SYNC) < 0)
+ Start = (Start/PSize)*PSize;
+ if (msync((char *)Base+Start, Stop - Start, MS_SYNC) < 0)
return _error->Errno("msync", _("Unable to synchronize mmap"));
#endif
}
@@ -215,7 +215,7 @@ bool MMap::Sync(unsigned long Start,unsigned long Stop)
/* */
DynamicMMap::DynamicMMap(FileFd &F,unsigned long Flags,unsigned long const &Workspace,
unsigned long const &Grow, unsigned long const &Limit) :
- MMap(F,Flags | NoImmMap), Fd(&F), WorkSpace(Workspace),
+ MMap(Flags), Fd(&F), WorkSpace(Workspace),
GrowFactor(Grow), Limit(Limit)
{
// disable Moveable if we don't grow
@@ -249,7 +249,7 @@ DynamicMMap::DynamicMMap(FileFd &F,unsigned long Flags,unsigned long const &Work
and could come in handy later than we are able to grow such an mmap */
DynamicMMap::DynamicMMap(unsigned long Flags,unsigned long const &WorkSpace,
unsigned long const &Grow, unsigned long const &Limit) :
- MMap(Flags | NoImmMap | UnMapped), Fd(0), WorkSpace(WorkSpace),
+ MMap(Flags | UnMapped), Fd(0), WorkSpace(WorkSpace),
GrowFactor(Grow), Limit(Limit)
{
// disable Moveable if we don't grow
@@ -305,10 +305,11 @@ DynamicMMap::~DynamicMMap()
if (validData() == false)
return;
#ifdef _POSIX_MAPPED_FILES
- munmap(Base, WorkSpace);
-#else
- free(Base);
+ if ((Flags & Fallback) != Fallback) {
+ munmap(Base, WorkSpace);
+ } else
#endif
+ free(Base);
return;
}
@@ -487,12 +488,14 @@ bool DynamicMMap::Grow() {
if ((Flags & Moveable) != Moveable)
return false;
- Base = realloc(Base, newSize);
- if (Base == NULL)
+ auto Temp = realloc(Base, newSize);
+ if (Temp == NULL)
return false;
- else
+ else {
+ Base = Temp;
/* Set new memory to 0 */
memset((char*)Base + WorkSpace, 0, newSize - WorkSpace);
+ }
}
Pools =(Pool*) Base + poolOffset;
diff --git a/apt-pkg/contrib/mmap.h b/apt-pkg/contrib/mmap.h
index 63d54d27c..25967600e 100644
--- a/apt-pkg/contrib/mmap.h
+++ b/apt-pkg/contrib/mmap.h
@@ -59,7 +59,7 @@ class MMap
public:
- enum OpenFlags {NoImmMap = (1<<0),Public = (1<<1),ReadOnly = (1<<2),
+ enum OpenFlags {Public = (1<<1),ReadOnly = (1<<2),
UnMapped = (1<<3), Moveable = (1<<4), Fallback = (1 << 5)};
// Simple accessors
diff --git a/apt-pkg/contrib/progress.cc b/apt-pkg/contrib/progress.cc
index 806bd47f8..bd604c5b0 100644
--- a/apt-pkg/contrib/progress.cc
+++ b/apt-pkg/contrib/progress.cc
@@ -119,7 +119,7 @@ bool OpProgress::CheckChange(float Interval)
auto const Now = std::chrono::steady_clock::now().time_since_epoch();
auto const Now_sec = std::chrono::duration_cast<std::chrono::seconds>(Now);
auto const Now_usec = std::chrono::duration_cast<std::chrono::microseconds>(Now - Now_sec);
- struct timeval NowTime = { Now_sec.count(), Now_usec.count() };
+ struct timeval NowTime = { static_cast<time_t>(Now_sec.count()), static_cast<suseconds_t>(Now_usec.count()) };
std::chrono::duration<decltype(Interval)> Delta =
std::chrono::seconds(NowTime.tv_sec - LastTime.tv_sec) +
diff --git a/apt-pkg/contrib/srvrec.cc b/apt-pkg/contrib/srvrec.cc
index a97d9c615..c0fc5dd8f 100644
--- a/apt-pkg/contrib/srvrec.cc
+++ b/apt-pkg/contrib/srvrec.cc
@@ -13,6 +13,7 @@
#include <arpa/nameser.h>
#include <arpa/inet.h>
#include <netinet/in.h>
+#include <apt-pkg/nameser_compat.h>
#include <resolv.h>
#include <time.h>
@@ -58,7 +59,7 @@ bool GetSrvRecords(std::string host, int port, std::vector<SrvRec> &Result)
bool GetSrvRecords(std::string name, std::vector<SrvRec> &Result)
{
- unsigned char answer[PACKETSZ];
+ unsigned char answer[NS_PACKETSZ];
int answer_len, compressed_name_len;
int answer_count;
@@ -85,7 +86,7 @@ bool GetSrvRecords(std::string name, std::vector<SrvRec> &Result)
return _error->Warning("dn_skipname failed %i", compressed_name_len);
// pt points to the first answer record, go over all of them now
- unsigned char *pt = answer+sizeof(HEADER)+compressed_name_len+QFIXEDSZ;
+ unsigned char *pt = answer+sizeof(HEADER)+compressed_name_len+NS_QFIXEDSZ;
while ((int)Result.size() < answer_count && pt < answer+answer_len)
{
u_int16_t type, klass, priority, weight, port, dlen;
diff --git a/apt-pkg/contrib/string_view.h b/apt-pkg/contrib/string_view.h
index 536744e32..aee49f1a7 100644
--- a/apt-pkg/contrib/string_view.h
+++ b/apt-pkg/contrib/string_view.h
@@ -12,6 +12,7 @@
#if !defined(APT_STRINGVIEW_H) && defined(APT_PKG_EXPOSE_STRING_VIEW)
#define APT_STRINGVIEW_H
#include <apt-pkg/macros.h>
+#include <apt-pkg/missing.h>
#include <string>
#include <string.h>
@@ -112,18 +113,6 @@ public:
constexpr size_t length() const { return size_; }
};
-/**
- * \brief Faster comparison for string views (compare size before data)
- *
- * Still stable, but faster than the normal ordering. */
-static inline int StringViewCompareFast(StringView a, StringView b) {
- if (a.size() != b.size())
- return a.size() - b.size();
-
- return memcmp(a.data(), b.data(), a.size());
-}
-
-
}
inline bool operator ==(const char *other, APT::StringView that);
diff --git a/apt-pkg/contrib/strutl.h b/apt-pkg/contrib/strutl.h
index 9f74f8c2a..790fc061a 100644
--- a/apt-pkg/contrib/strutl.h
+++ b/apt-pkg/contrib/strutl.h
@@ -157,6 +157,27 @@ static inline int isspace_ascii_inline(int const c)
return (c >= 9 && c <= 13) || c == ' ';
}
+// StringViewCompareFast - awkward attempt to optimize cache generation /*{{{*/
+#ifdef APT_PKG_EXPOSE_STRING_VIEW
+/**
+ * \brief Faster comparison for string views (compare size before data)
+ *
+ * Still stable, but faster than the normal ordering.
+ * As this is used for package comparison this *MUST* be case insensitive,
+ * as the alternative is to lower case all dependency fields which is slow. */
+static inline int StringViewCompareFast(APT::StringView a, APT::StringView b) {
+ if (a.size() != b.size())
+ return a.size() - b.size();
+ auto l(a.data()), r(b.data());
+ for (auto e(a.size()), i(decltype(e)(0)); i != e; ++i)
+ if (tolower_ascii_inline(l[i]) != tolower_ascii_inline(r[i]))
+ return tolower_ascii(l[i]) < tolower_ascii(r[i]) ? -1 : 1;
+ return 0;
+}
+#endif
+ /*}}}*/
+
+
std::string StripEpoch(const std::string &VerStr);
#define APT_MKSTRCMP(name,func) \
diff --git a/apt-pkg/deb/debindexfile.cc b/apt-pkg/deb/debindexfile.cc
index 25e0a3312..78e3eecb7 100644
--- a/apt-pkg/deb/debindexfile.cc
+++ b/apt-pkg/deb/debindexfile.cc
@@ -130,7 +130,7 @@ pkgCacheListParser * debTranslationsIndex::CreateListParser(FileFd &Pkg)
std::unique_ptr<pkgCacheListParser> Parser(new debTranslationsParser(&Pkg));
bool const newError = _error->PendingError();
_error->MergeWithStack();
- return newError ? nullptr : Parser.release();
+ return newError ? ((void)_error->ReturnError(), nullptr) : Parser.release();
}
/*}}}*/
// dpkg/status Index /*{{{*/
@@ -158,7 +158,7 @@ pkgCacheListParser * debStatusIndex::CreateListParser(FileFd &Pkg)
std::unique_ptr<pkgCacheListParser> Parser(new debStatusListParser(&Pkg));
bool const newError = _error->PendingError();
_error->MergeWithStack();
- return newError ? nullptr : Parser.release();
+ return newError ? ((void)_error->ReturnError(), nullptr) : Parser.release();
}
/*}}}*/
// DebPkgFile Index - a single .deb file as an index /*{{{*/
@@ -228,7 +228,7 @@ pkgCacheListParser * debDebPkgFileIndex::CreateListParser(FileFd &Pkg)
std::unique_ptr<pkgCacheListParser> Parser(new debDebFileParser(&Pkg, DebFile));
bool const newError = _error->PendingError();
_error->MergeWithStack();
- return newError ? nullptr : Parser.release();
+ return newError ? ((void)_error->ReturnError(), nullptr) : Parser.release();
}
uint8_t debDebPkgFileIndex::GetIndexFlags() const
{
diff --git a/apt-pkg/deb/deblistparser.cc b/apt-pkg/deb/deblistparser.cc
index 80ca10e37..b737a9207 100644
--- a/apt-pkg/deb/deblistparser.cc
+++ b/apt-pkg/deb/deblistparser.cc
@@ -86,7 +86,7 @@ string debListParser::Package() {
}
if(unlikely(Result.empty() == true))
- _error->Error("Encountered a section with no Package: header");
+ _error->Warning("Encountered a section with no Package: header");
return Result;
}
/*}}}*/
@@ -158,6 +158,15 @@ bool debListParser::NewVersion(pkgCache::VerIterator &Ver)
const char *Start;
const char *Stop;
+ if (Section.Find("Name",Start,Stop) == true)
+ {
+ Ver->Display = WriteString(Start, Stop - Start);
+ }
+ else if (Section.Find("Maemo-Display-Name",Start,Stop) == true)
+ {
+ Ver->Display = WriteString(Start, Stop - Start);
+ }
+
// Parse the section
if (Section.Find(pkgTagSection::Key::Section,Start,Stop) == true)
{
@@ -254,6 +263,8 @@ bool debListParser::NewVersion(pkgCache::VerIterator &Ver)
if (ParseProvides(Ver) == false)
return false;
+ if (ParseTag(Ver) == false)
+ return false;
return true;
}
@@ -850,7 +861,7 @@ bool debListParser::ParseDepends(pkgCache::VerIterator &Ver,
Start = ParseDepends(Start, Stop, Package, Version, Op, false, false, false, myArch);
if (Start == 0)
- return _error->Error("Problem parsing dependency %zu",static_cast<size_t>(Key)); // TODO
+ return _error->Warning("Problem parsing dependency %zu",static_cast<size_t>(Key)); // TODO
size_t const found = Package.rfind(':');
if (found == string::npos)
@@ -918,7 +929,7 @@ bool debListParser::ParseProvides(pkgCache::VerIterator &Ver)
Start = ParseDepends(Start,Stop,Package,Version,Op, false, false, false);
const size_t archfound = Package.rfind(':');
if (Start == 0)
- return _error->Error("Problem parsing Provides line");
+ return _error->Warning("Problem parsing Provides line");
if (unlikely(Op != pkgCache::Dep::NoOp && Op != pkgCache::Dep::Equals)) {
_error->Warning("Ignoring Provides line with non-equal DepCompareOp for package %s", Package.to_string().c_str());
} else if (archfound != string::npos) {
@@ -989,6 +1000,46 @@ bool debListParser::ParseProvides(pkgCache::VerIterator &Ver)
return true;
}
/*}}}*/
+// ListParser::ParseTag - Parse the tag list /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+bool debListParser::ParseTag(pkgCache::VerIterator &Ver)
+{
+ const char *Start;
+ const char *Stop;
+ if (Section.Find("Tag",Start,Stop) == false)
+ return true;
+
+ while (1) {
+ while (1) {
+ if (Start == Stop)
+ return true;
+ if (Stop[-1] != ' ' && Stop[-1] != '\t')
+ break;
+ --Stop;
+ }
+
+ const char *Begin = Stop - 1;
+ while (Begin != Start && Begin[-1] != ' ' && Begin[-1] != ',')
+ --Begin;
+
+ if (NewTag(Ver, Begin, Stop - Begin) == false)
+ return false;
+
+ while (1) {
+ if (Begin == Start)
+ return true;
+ if (Begin[-1] == ',')
+ break;
+ --Begin;
+ }
+
+ Stop = Begin - 1;
+ }
+
+ return true;
+}
+ /*}}}*/
// ListParser::GrabWord - Matches a word and returns /*{{{*/
// ---------------------------------------------------------------------
/* Looks for a word in a list of words - for ParseStatus */
diff --git a/apt-pkg/deb/deblistparser.h b/apt-pkg/deb/deblistparser.h
index f02252d58..456548501 100644
--- a/apt-pkg/deb/deblistparser.h
+++ b/apt-pkg/deb/deblistparser.h
@@ -56,6 +56,7 @@ class APT_HIDDEN debListParser : public pkgCacheListParser
bool ParseDepends(pkgCache::VerIterator &Ver, pkgTagSection::Key Key,
unsigned int Type);
bool ParseProvides(pkgCache::VerIterator &Ver);
+ bool ParseTag(pkgCache::VerIterator &Ver);
#ifdef APT_PKG_EXPOSE_STRING_VIEW
APT_HIDDEN static bool GrabWord(APT::StringView Word,const WordList *List,unsigned char &Out);
diff --git a/apt-pkg/deb/debmetaindex.cc b/apt-pkg/deb/debmetaindex.cc
index f88076abf..a1b7a2198 100644
--- a/apt-pkg/deb/debmetaindex.cc
+++ b/apt-pkg/deb/debmetaindex.cc
@@ -428,7 +428,7 @@ bool debReleaseIndex::Load(std::string const &Filename, std::string * const Erro
if (OpenMaybeClearSignedFile(Filename, Fd) == false)
return false;
- pkgTagFile TagFile(&Fd, Fd.Size());
+ pkgTagFile TagFile(&Fd);
if (Fd.IsOpen() == false || Fd.Failed())
{
if (ErrorText != NULL)
@@ -524,18 +524,15 @@ bool debReleaseIndex::Load(std::string const &Filename, std::string * const Erro
bool AuthPossible = false;
if(FoundHashSum == false)
- _error->Warning(_("No Hash entry in Release file %s"), Filename.c_str());
+ /*_error->Warning(_("No Hash entry in Release file %s"), Filename.c_str())*/;
else if(FoundStrongHashSum == false)
- _error->Warning(_("No Hash entry in Release file %s which is considered strong enough for security purposes"), Filename.c_str());
+ /*_error->Warning(_("No Hash entry in Release file %s which is considered strong enough for security purposes"), Filename.c_str())*/;
else
AuthPossible = true;
std::string const StrDate = Section.FindS("Date");
if (RFC1123StrToTime(StrDate.c_str(), Date) == false)
- {
- _error->Warning( _("Invalid '%s' entry in Release file %s"), "Date", Filename.c_str());
Date = 0;
- }
bool CheckDate = _config->FindB("Acquire::Check-Date", true);
if (d->CheckDate == metaIndex::TRI_NO)
@@ -596,6 +593,9 @@ bool debReleaseIndex::Load(std::string const &Filename, std::string * const Erro
if (MinAge != 0 || ValidUntil != 0 || MaxAge != 0)
{
+ if (Date == 0)
+ _error->Warning( _("Invalid '%s' entry in Release file %s"), "Date", Filename.c_str());
+
if (MinAge != 0 && ValidUntil != 0)
{
time_t const min_date = Date + MinAge;
@@ -896,7 +896,7 @@ bool debReleaseIndex::Merge(pkgCacheGenerator &Gen,OpProgress * /*Prog*/) const/
File->Size = Buf.st_size;
File->mtime = Buf.st_mtime;
- pkgTagFile TagFile(&Rel, Rel.Size());
+ pkgTagFile TagFile(&Rel);
pkgTagSection Section;
if (Rel.IsOpen() == false || Rel.Failed() || TagFile.Step(Section) == false)
return false;
diff --git a/apt-pkg/deb/debmetaindex.h b/apt-pkg/deb/debmetaindex.h
index 864ac3eba..1365716a4 100644
--- a/apt-pkg/deb/debmetaindex.h
+++ b/apt-pkg/deb/debmetaindex.h
@@ -34,8 +34,8 @@ class APT_HIDDEN debReleaseIndex : public metaIndex
APT_HIDDEN std::string MetaIndexFile(const char *Types) const;
APT_HIDDEN std::string MetaIndexURI(const char *Type) const;
- debReleaseIndex(std::string const &URI, std::string const &Dist, std::map<std::string,std::string> const &Options);
- debReleaseIndex(std::string const &URI, std::string const &Dist, bool const Trusted, std::map<std::string,std::string> const &Options);
+ debReleaseIndex(std::string const &URI, std::string const &Dist, std::map<std::string,std::string> const &Options = std::map<std::string,std::string>());
+ debReleaseIndex(std::string const &URI, std::string const &Dist, bool const Trusted, std::map<std::string,std::string> const &Options = std::map<std::string,std::string>());
virtual ~debReleaseIndex();
virtual std::string ArchiveURI(std::string const &File) const APT_OVERRIDE {return URI + File;};
diff --git a/apt-pkg/deb/debrecords.cc b/apt-pkg/deb/debrecords.cc
index 22ac219ba..360000479 100644
--- a/apt-pkg/deb/debrecords.cc
+++ b/apt-pkg/deb/debrecords.cc
@@ -33,7 +33,7 @@ using std::string;
// RecordParser::debRecordParser - Constructor /*{{{*/
debRecordParser::debRecordParser(string FileName,pkgCache &Cache) :
debRecordParserBase(), d(NULL), File(FileName, FileFd::ReadOnly, FileFd::Extension),
- Tags(&File, std::max(Cache.Head().MaxVerFileSize, Cache.Head().MaxDescFileSize) + 200)
+ Tags(&File)
{
}
/*}}}*/
@@ -72,6 +72,15 @@ string debRecordParserBase::Name()
return Result;
}
/*}}}*/
+// RecordParserBase::Display - Return the package homepage /*{{{*/
+string debRecordParserBase::Display()
+{
+ string display(Section.FindS("Name"));
+ if (display.empty())
+ display = Section.FindS("Maemo-Display-Name");
+ return display;
+}
+ /*}}}*/
// RecordParserBase::Homepage - Return the package homepage /*{{{*/
string debRecordParserBase::Homepage()
{
@@ -151,7 +160,7 @@ string debRecordParserBase::LongDesc(std::string const &lang)
}
char const * const codeset = nl_langinfo(CODESET);
- if (strcmp(codeset,"UTF-8") != 0) {
+ if (strcmp(codeset,"US-ASCII") != 0 && strcmp(codeset,"UTF-8") != 0) {
string dest;
UTF8ToCodeset(codeset, orig, &dest);
return dest;
@@ -199,6 +208,12 @@ void debRecordParserBase::GetRec(const char *&Start,const char *&Stop)
Section.GetSection(Start,Stop);
}
/*}}}*/
+// RecordParserBase::Find - Locate a tag /*{{{*/
+bool debRecordParserBase::Find(const char *Tag,const char *&Start, const char *&End)
+{
+ return Section.Find(Tag,Start,End);
+}
+ /*}}}*/
debRecordParserBase::~debRecordParserBase() {}
bool debDebFileRecordParser::LoadContent()
@@ -215,7 +230,7 @@ bool debDebFileRecordParser::LoadContent()
content << "\n\n";
controlContent = content.str();
- if (Section.Scan(controlContent.c_str(), controlContent.length()) == false)
+ if (Section.Scan(controlContent.c_str(), controlContent.length(), false) == false)
return _error->Error(_("Unable to parse package file %s (%d)"), debFileName.c_str(), 3);
return true;
}
diff --git a/apt-pkg/deb/debrecords.h b/apt-pkg/deb/debrecords.h
index 7c3b9020c..def580223 100644
--- a/apt-pkg/deb/debrecords.h
+++ b/apt-pkg/deb/debrecords.h
@@ -43,12 +43,14 @@ class APT_HIDDEN debRecordParserBase : public pkgRecords::Parser
virtual std::string ShortDesc(std::string const &lang) APT_OVERRIDE;
virtual std::string LongDesc(std::string const &lang) APT_OVERRIDE;
virtual std::string Name() APT_OVERRIDE;
+ virtual std::string Display() APT_OVERRIDE;
virtual std::string Homepage() APT_OVERRIDE;
// An arbitrary custom field
virtual std::string RecordField(const char *fieldName) APT_OVERRIDE;
virtual void GetRec(const char *&Start,const char *&Stop) APT_OVERRIDE;
+ virtual bool Find(const char *Tag,const char *&Start, const char *&End) APT_OVERRIDE;
debRecordParserBase();
virtual ~debRecordParserBase();
diff --git a/apt-pkg/deb/debsrcrecords.cc b/apt-pkg/deb/debsrcrecords.cc
index 9656fcac3..3c025aae6 100644
--- a/apt-pkg/deb/debsrcrecords.cc
+++ b/apt-pkg/deb/debsrcrecords.cc
@@ -38,7 +38,7 @@ debSrcRecordParser::debSrcRecordParser(std::string const &File,pkgIndexFile cons
if (File.empty() == false)
{
if (Fd.Open(File, FileFd::ReadOnly, FileFd::Extension))
- Tags.Init(&Fd, 102400);
+ Tags.Init(&Fd);
}
}
std::string debSrcRecordParser::Package() const /*{{{*/
diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc
index ffa880df2..50af6c7b8 100644
--- a/apt-pkg/deb/dpkgpm.cc
+++ b/apt-pkg/deb/dpkgpm.cc
@@ -1403,7 +1403,9 @@ static void cleanUpTmpDir(char * const tmpdir) /*{{{*/
if (unlikely(Ent->d_type != DT_LNK && Ent->d_type != DT_UNKNOWN))
continue;
#endif
- if (unlikely(unlinkat(dfd, Ent->d_name, 0) != 0))
+ char path[strlen(tmpdir) + 1 + strlen(Ent->d_name) + 1];
+ sprintf(path, "%s/%s", tmpdir, Ent->d_name);
+ if (unlikely(unlink(path) != 0))
break;
}
closedir(D);
@@ -1729,7 +1731,7 @@ bool pkgDPkgPM::Go(APT::Progress::PackageManager *progress)
bool dpkgMultiArch = debSystem::SupportsMultiArch();
// start pty magic before the loop
- StartPtyMagic();
+ //StartPtyMagic(); or not...
// Tell the progress that its starting and fork dpkg
d->progress->Start(d->master);
@@ -1790,6 +1792,7 @@ bool pkgDPkgPM::Go(APT::Progress::PackageManager *progress)
case Item::Remove:
case Item::Purge:
ADDARGC("--force-depends");
+ ADDARGC("--force-remove-reinstreq");
if (std::any_of(I, J, ItemIsEssential))
{
ADDARGC("--force-remove-essential");
@@ -2149,7 +2152,7 @@ bool pkgDPkgPM::Go(APT::Progress::PackageManager *progress)
}
}
// dpkg is done at this point
- StopPtyMagic();
+ //StopPtyMagic();
CloseLog();
if (d->dpkg_error.empty() == false)
diff --git a/apt-pkg/edsp.cc b/apt-pkg/edsp.cc
index 2e39be377..532d2684d 100644
--- a/apt-pkg/edsp.cc
+++ b/apt-pkg/edsp.cc
@@ -628,7 +628,7 @@ bool EDSP::ReadResponse(int const input, pkgDepCache &Cache, OpProgress *Progres
FileFd in;
in.OpenDescriptor(input, FileFd::ReadOnly, true);
- pkgTagFile response(&in, 100);
+ pkgTagFile response(&in);
pkgTagSection section;
std::set<decltype(Cache.PkgBegin()->ID)> seenOnce;
@@ -1336,7 +1336,7 @@ bool EIPP::ReadResponse(int const input, pkgPackageManager * const PM, OpProgres
FileFd in;
in.OpenDescriptor(input, FileFd::ReadOnly);
- pkgTagFile response(&in, 100);
+ pkgTagFile response(&in);
pkgTagSection section;
while (response.Step(section) == true) {
diff --git a/apt-pkg/endian.h b/apt-pkg/endian.h
new file mode 100644
index 000000000..e89694a44
--- /dev/null
+++ b/apt-pkg/endian.h
@@ -0,0 +1,118 @@
+// "License": Public Domain
+// I, Mathias Panzenbรถck, place this file hereby into the public domain. Use it at your own risk for whatever you like.
+// In case there are jurisdictions that don't support putting things in the public domain you can also consider it to
+// be "dual licensed" under the BSD, MIT and Apache licenses, if you want to. This code is trivial anyway. Consider it
+// an example on how to get the endian conversion functions on different platforms.
+
+#ifndef PORTABLE_ENDIAN_H__
+#define PORTABLE_ENDIAN_H__
+
+#if (defined(_WIN16) || defined(_WIN32) || defined(_WIN64)) && !defined(__WINDOWS__)
+
+# define __WINDOWS__
+
+#endif
+
+#if defined(__linux__) || defined(__CYGWIN__)
+
+# include <endian.h>
+
+#elif defined(__APPLE__)
+
+# include <libkern/OSByteOrder.h>
+
+# define htobe16(x) OSSwapHostToBigInt16(x)
+# define htole16(x) OSSwapHostToLittleInt16(x)
+# define be16toh(x) OSSwapBigToHostInt16(x)
+# define le16toh(x) OSSwapLittleToHostInt16(x)
+
+# define htobe32(x) OSSwapHostToBigInt32(x)
+# define htole32(x) OSSwapHostToLittleInt32(x)
+# define be32toh(x) OSSwapBigToHostInt32(x)
+# define le32toh(x) OSSwapLittleToHostInt32(x)
+
+# define htobe64(x) OSSwapHostToBigInt64(x)
+# define htole64(x) OSSwapHostToLittleInt64(x)
+# define be64toh(x) OSSwapBigToHostInt64(x)
+# define le64toh(x) OSSwapLittleToHostInt64(x)
+
+# define __BYTE_ORDER BYTE_ORDER
+# define __BIG_ENDIAN BIG_ENDIAN
+# define __LITTLE_ENDIAN LITTLE_ENDIAN
+# define __PDP_ENDIAN PDP_ENDIAN
+
+#elif defined(__OpenBSD__)
+
+# include <sys/endian.h>
+
+#elif defined(__NetBSD__) || defined(__FreeBSD__) || defined(__DragonFly__)
+
+# include <sys/endian.h>
+
+# define be16toh(x) betoh16(x)
+# define le16toh(x) letoh16(x)
+
+# define be32toh(x) betoh32(x)
+# define le32toh(x) letoh32(x)
+
+# define be64toh(x) betoh64(x)
+# define le64toh(x) letoh64(x)
+
+#elif defined(__WINDOWS__)
+
+# include <winsock2.h>
+# include <sys/param.h>
+
+# if BYTE_ORDER == LITTLE_ENDIAN
+
+# define htobe16(x) htons(x)
+# define htole16(x) (x)
+# define be16toh(x) ntohs(x)
+# define le16toh(x) (x)
+
+# define htobe32(x) htonl(x)
+# define htole32(x) (x)
+# define be32toh(x) ntohl(x)
+# define le32toh(x) (x)
+
+# define htobe64(x) htonll(x)
+# define htole64(x) (x)
+# define be64toh(x) ntohll(x)
+# define le64toh(x) (x)
+
+# elif BYTE_ORDER == BIG_ENDIAN
+
+ /* that would be xbox 360 */
+# define htobe16(x) (x)
+# define htole16(x) __builtin_bswap16(x)
+# define be16toh(x) (x)
+# define le16toh(x) __builtin_bswap16(x)
+
+# define htobe32(x) (x)
+# define htole32(x) __builtin_bswap32(x)
+# define be32toh(x) (x)
+# define le32toh(x) __builtin_bswap32(x)
+
+# define htobe64(x) (x)
+# define htole64(x) __builtin_bswap64(x)
+# define be64toh(x) (x)
+# define le64toh(x) __builtin_bswap64(x)
+
+# else
+
+# error byte order not supported
+
+# endif
+
+# define __BYTE_ORDER BYTE_ORDER
+# define __BIG_ENDIAN BIG_ENDIAN
+# define __LITTLE_ENDIAN LITTLE_ENDIAN
+# define __PDP_ENDIAN PDP_ENDIAN
+
+#else
+
+# error platform not supported
+
+#endif
+
+#endif
diff --git a/apt-pkg/getservbyport_r.cc b/apt-pkg/getservbyport_r.cc
new file mode 100644
index 000000000..cf78ad514
--- /dev/null
+++ b/apt-pkg/getservbyport_r.cc
@@ -0,0 +1,59 @@
+#define _GNU_SOURCE
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <string.h>
+
+#ifndef HAVE_GETSERVBYPORT_R
+
+extern "C" int getservbyport_r(int port, const char *prots,
+ struct servent *se, char *buf, size_t buflen, struct servent **res)
+{
+ int i;
+ struct sockaddr_in sin = {
+ .sin_family = AF_INET,
+ .sin_port = (in_port_t) port,
+ };
+
+ if (!prots) {
+ int r = getservbyport_r(port, "tcp", se, buf, buflen, res);
+ if (r) r = getservbyport_r(port, "udp", se, buf, buflen, res);
+ return r;
+ }
+
+ /* Align buffer */
+ i = (uintptr_t)buf & sizeof(char *)-1;
+ if (!i) i = sizeof(char *);
+ if (buflen < 3*sizeof(char *)-i)
+ return ERANGE;
+ buf += sizeof(char *)-i;
+ buflen -= sizeof(char *)-i;
+
+ if (strcmp(prots, "tcp") && strcmp(prots, "udp")) return EINVAL;
+
+ se->s_port = port;
+ se->s_proto = (char *)prots;
+ se->s_aliases = (char **)buf;
+ buf += 2*sizeof(char *);
+ buflen -= 2*sizeof(char *);
+ se->s_aliases[1] = 0;
+ se->s_aliases[0] = se->s_name = buf;
+
+ switch (getnameinfo((const struct sockaddr *) &sin, sizeof sin, 0, 0, buf, buflen,
+ strcmp(prots, "udp") ? 0 : NI_DGRAM)) {
+ case EAI_MEMORY:
+ case EAI_SYSTEM:
+ return ENOMEM;
+ default:
+ return ENOENT;
+ case 0:
+ break;
+ }
+
+ *res = se;
+ return 0;
+}
+#endif
diff --git a/apt-pkg/indexcopy.cc b/apt-pkg/indexcopy.cc
index 41cecdec1..cfadca78a 100644
--- a/apt-pkg/indexcopy.cc
+++ b/apt-pkg/indexcopy.cc
@@ -562,7 +562,7 @@ bool SigVerify::CopyAndVerify(string CDROM,string Name,vector<string> &SigList,
if(Debug)
cout << "Signature verify for: " << *I << endl;
- metaIndex *MetaIndex = new debReleaseIndex("","", {});
+ metaIndex *MetaIndex = new debReleaseIndex("","");
string prefix = *I;
string const releasegpg = *I+"Release.gpg";
diff --git a/apt-pkg/init.cc b/apt-pkg/init.cc
index a619368ec..d69d7da32 100644
--- a/apt-pkg/init.cc
+++ b/apt-pkg/init.cc
@@ -177,7 +177,7 @@ bool pkgInitConfig(Configuration &Cnf)
Cnf.Set("Dir::Ignore-Files-Silently::", "\\.distUpgrade$");
// Repository security
- Cnf.CndSet("Acquire::AllowInsecureRepositories", false);
+ Cnf.CndSet("Acquire::AllowInsecureRepositories", true);
Cnf.CndSet("Acquire::AllowWeakRepositories", false);
Cnf.CndSet("Acquire::AllowDowngradeToInsecureRepositories", false);
diff --git a/apt-pkg/memrchr.cc b/apt-pkg/memrchr.cc
new file mode 100644
index 000000000..edf8f346a
--- /dev/null
+++ b/apt-pkg/memrchr.cc
@@ -0,0 +1,157 @@
+/* memrchr -- find the last occurrence of a byte in a memory block
+
+ Copyright (C) 1991, 1993, 1996-1997, 1999-2000, 2003-2015 Free Software
+ Foundation, Inc.
+
+ Based on strlen implementation by Torbjorn Granlund (tege@sics.se),
+ with help from Dan Sahlin (dan@sics.se) and
+ commentary by Jim Blandy (jimb@ai.mit.edu);
+ adaptation to memchr suggested by Dick Karpinski (dick@cca.ucsf.edu),
+ and implemented by Roland McGrath (roland@ai.mit.edu).
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+#ifndef HAVE_MEMRCHR
+#define reg_char char
+
+#include <string.h>
+#include <limits.h>
+
+#undef __memrchr
+#ifdef _LIBC
+# undef memrchr
+#endif
+
+#ifndef weak_alias
+# define __memrchr memrchr
+#endif
+
+/* Search no more than N bytes of S for C. */
+extern "C" void *
+memrchr (const void *s, int c_in, size_t n)
+{
+ /* On 32-bit hardware, choosing longword to be a 32-bit unsigned
+ long instead of a 64-bit uintmax_t tends to give better
+ performance. On 64-bit hardware, unsigned long is generally 64
+ bits already. Change this typedef to experiment with
+ performance. */
+ typedef unsigned long int longword;
+
+ const unsigned char *char_ptr;
+ const longword *longword_ptr;
+ longword repeated_one;
+ longword repeated_c;
+ unsigned reg_char c;
+
+ c = (unsigned char) c_in;
+
+ /* Handle the last few bytes by reading one byte at a time.
+ Do this until CHAR_PTR is aligned on a longword boundary. */
+ for (char_ptr = (const unsigned char *) s + n;
+ n > 0 && (size_t) char_ptr % sizeof (longword) != 0;
+ --n)
+ if (*--char_ptr == c)
+ return (void *) char_ptr;
+
+ longword_ptr = (const longword *) char_ptr;
+
+ /* All these elucidatory comments refer to 4-byte longwords,
+ but the theory applies equally well to any size longwords. */
+
+ /* Compute auxiliary longword values:
+ repeated_one is a value which has a 1 in every byte.
+ repeated_c has c in every byte. */
+ repeated_one = 0x01010101;
+ repeated_c = c | (c << 8);
+ repeated_c |= repeated_c << 16;
+ if (0xffffffffU < (longword) -1)
+ {
+ repeated_one |= repeated_one << 31 << 1;
+ repeated_c |= repeated_c << 31 << 1;
+ if (8 < sizeof (longword))
+ {
+ size_t i;
+
+ for (i = 64; i < sizeof (longword) * 8; i *= 2)
+ {
+ repeated_one |= repeated_one << i;
+ repeated_c |= repeated_c << i;
+ }
+ }
+ }
+
+ /* Instead of the traditional loop which tests each byte, we will test a
+ longword at a time. The tricky part is testing if *any of the four*
+ bytes in the longword in question are equal to c. We first use an xor
+ with repeated_c. This reduces the task to testing whether *any of the
+ four* bytes in longword1 is zero.
+
+ We compute tmp =
+ ((longword1 - repeated_one) & ~longword1) & (repeated_one << 7).
+ That is, we perform the following operations:
+ 1. Subtract repeated_one.
+ 2. & ~longword1.
+ 3. & a mask consisting of 0x80 in every byte.
+ Consider what happens in each byte:
+ - If a byte of longword1 is zero, step 1 and 2 transform it into 0xff,
+ and step 3 transforms it into 0x80. A carry can also be propagated
+ to more significant bytes.
+ - If a byte of longword1 is nonzero, let its lowest 1 bit be at
+ position k (0 <= k <= 7); so the lowest k bits are 0. After step 1,
+ the byte ends in a single bit of value 0 and k bits of value 1.
+ After step 2, the result is just k bits of value 1: 2^k - 1. After
+ step 3, the result is 0. And no carry is produced.
+ So, if longword1 has only non-zero bytes, tmp is zero.
+ Whereas if longword1 has a zero byte, call j the position of the least
+ significant zero byte. Then the result has a zero at positions 0, ...,
+ j-1 and a 0x80 at position j. We cannot predict the result at the more
+ significant bytes (positions j+1..3), but it does not matter since we
+ already have a non-zero bit at position 8*j+7.
+
+ So, the test whether any byte in longword1 is zero is equivalent to
+ testing whether tmp is nonzero. */
+
+ while (n >= sizeof (longword))
+ {
+ longword longword1 = *--longword_ptr ^ repeated_c;
+
+ if ((((longword1 - repeated_one) & ~longword1)
+ & (repeated_one << 7)) != 0)
+ {
+ longword_ptr++;
+ break;
+ }
+ n -= sizeof (longword);
+ }
+
+ char_ptr = (const unsigned char *) longword_ptr;
+
+ /* At this point, we know that either n < sizeof (longword), or one of the
+ sizeof (longword) bytes starting at char_ptr is == c. On little-endian
+ machines, we could determine the first such byte without any further
+ memory accesses, just by looking at the tmp result from the last loop
+ iteration. But this does not work on big-endian machines. Choose code
+ that works in both cases. */
+
+ while (n-- > 0)
+ {
+ if (*--char_ptr == c)
+ return (void *) char_ptr;
+ }
+
+ return NULL;
+}
+#endif
diff --git a/apt-pkg/missing.h b/apt-pkg/missing.h
new file mode 100644
index 000000000..441b47ce1
--- /dev/null
+++ b/apt-pkg/missing.h
@@ -0,0 +1,26 @@
+#define _GNU_SOURCE
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <string.h>
+
+#ifndef PKGLIB_MISSING_H
+#define PKGLIB_MISSING_H
+
+extern "C" {
+ void *memrchr(const void *s, int c, size_t n);
+ void *rawmemchr(const void *s, int c);
+ char *strchrnul(const char *s, int c);
+ int getservbyport_r(int port, const char *prots, struct servent *se, char *buf, size_t buflen, struct servent **res);
+}
+
+typedef void (*sighandler_t)(int);
+
+extern char **environ;
+
+#define AI_IDN 0x0040
+
+#endif
+
diff --git a/apt-pkg/nameser_compat.h b/apt-pkg/nameser_compat.h
new file mode 100644
index 000000000..b2cf2ffaa
--- /dev/null
+++ b/apt-pkg/nameser_compat.h
@@ -0,0 +1,187 @@
+/* Copyright (c) 1983, 1989
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*%
+ * from nameser.h 8.1 (Berkeley) 6/2/93
+ * $BINDId: nameser_compat.h,v 8.11 1999/01/02 08:00:58 vixie Exp $
+ */
+
+#ifndef _ARPA_NAMESER_COMPAT_
+#define _ARPA_NAMESER_COMPAT_
+
+#define __BIND 19950621 /*%< (DEAD) interface version stamp. */
+
+#include <apt-pkg/endian.h>
+
+/*%
+ * Structure for query header. The order of the fields is machine- and
+ * compiler-dependent, depending on the byte/bit order and the layout
+ * of bit fields. We use bit fields only in int variables, as this
+ * is all ANSI requires. This requires a somewhat confusing rearrangement.
+ */
+
+typedef struct {
+ unsigned id :16; /*%< query identification number */
+#if BYTE_ORDER == BIG_ENDIAN
+ /* fields in third byte */
+ unsigned qr: 1; /*%< response flag */
+ unsigned opcode: 4; /*%< purpose of message */
+ unsigned aa: 1; /*%< authoritive answer */
+ unsigned tc: 1; /*%< truncated message */
+ unsigned rd: 1; /*%< recursion desired */
+ /* fields in fourth byte */
+ unsigned ra: 1; /*%< recursion available */
+ unsigned unused :1; /*%< unused bits (MBZ as of 4.9.3a3) */
+ unsigned ad: 1; /*%< authentic data from named */
+ unsigned cd: 1; /*%< checking disabled by resolver */
+ unsigned rcode :4; /*%< response code */
+#endif
+#if BYTE_ORDER == LITTLE_ENDIAN || BYTE_ORDER == PDP_ENDIAN
+ /* fields in third byte */
+ unsigned rd :1; /*%< recursion desired */
+ unsigned tc :1; /*%< truncated message */
+ unsigned aa :1; /*%< authoritive answer */
+ unsigned opcode :4; /*%< purpose of message */
+ unsigned qr :1; /*%< response flag */
+ /* fields in fourth byte */
+ unsigned rcode :4; /*%< response code */
+ unsigned cd: 1; /*%< checking disabled by resolver */
+ unsigned ad: 1; /*%< authentic data from named */
+ unsigned unused :1; /*%< unused bits (MBZ as of 4.9.3a3) */
+ unsigned ra :1; /*%< recursion available */
+#endif
+ /* remaining bytes */
+ unsigned qdcount :16; /*%< number of question entries */
+ unsigned ancount :16; /*%< number of answer entries */
+ unsigned nscount :16; /*%< number of authority entries */
+ unsigned arcount :16; /*%< number of resource entries */
+} HEADER;
+
+#define PACKETSZ NS_PACKETSZ
+#define MAXDNAME NS_MAXDNAME
+#define MAXCDNAME NS_MAXCDNAME
+#define MAXLABEL NS_MAXLABEL
+#define HFIXEDSZ NS_HFIXEDSZ
+#define QFIXEDSZ NS_QFIXEDSZ
+#define RRFIXEDSZ NS_RRFIXEDSZ
+#define INT32SZ NS_INT32SZ
+#define INT16SZ NS_INT16SZ
+#define INT8SZ NS_INT8SZ
+#define INADDRSZ NS_INADDRSZ
+#define IN6ADDRSZ NS_IN6ADDRSZ
+#define INDIR_MASK NS_CMPRSFLGS
+#define NAMESERVER_PORT NS_DEFAULTPORT
+
+#define S_ZONE ns_s_zn
+#define S_PREREQ ns_s_pr
+#define S_UPDATE ns_s_ud
+#define S_ADDT ns_s_ar
+
+#define QUERY ns_o_query
+#define IQUERY ns_o_iquery
+#define STATUS ns_o_status
+#define NS_NOTIFY_OP ns_o_notify
+#define NS_UPDATE_OP ns_o_update
+
+#define NOERROR ns_r_noerror
+#define FORMERR ns_r_formerr
+#define SERVFAIL ns_r_servfail
+#define NXDOMAIN ns_r_nxdomain
+#define NOTIMP ns_r_notimpl
+#define REFUSED ns_r_refused
+#define YXDOMAIN ns_r_yxdomain
+#define YXRRSET ns_r_yxrrset
+#define NXRRSET ns_r_nxrrset
+#define NOTAUTH ns_r_notauth
+#define NOTZONE ns_r_notzone
+/*#define BADSIG ns_r_badsig*/
+/*#define BADKEY ns_r_badkey*/
+/*#define BADTIME ns_r_badtime*/
+
+
+#define DELETE ns_uop_delete
+#define ADD ns_uop_add
+
+#define T_A ns_t_a
+#define T_NS ns_t_ns
+#define T_MD ns_t_md
+#define T_MF ns_t_mf
+#define T_CNAME ns_t_cname
+#define T_SOA ns_t_soa
+#define T_MB ns_t_mb
+#define T_MG ns_t_mg
+#define T_MR ns_t_mr
+#define T_NULL ns_t_null
+#define T_WKS ns_t_wks
+#define T_PTR ns_t_ptr
+#define T_HINFO ns_t_hinfo
+#define T_MINFO ns_t_minfo
+#define T_MX ns_t_mx
+#define T_TXT ns_t_txt
+#define T_RP ns_t_rp
+#define T_AFSDB ns_t_afsdb
+#define T_X25 ns_t_x25
+#define T_ISDN ns_t_isdn
+#define T_RT ns_t_rt
+#define T_NSAP ns_t_nsap
+#define T_NSAP_PTR ns_t_nsap_ptr
+#define T_SIG ns_t_sig
+#define T_KEY ns_t_key
+#define T_PX ns_t_px
+#define T_GPOS ns_t_gpos
+#define T_AAAA ns_t_aaaa
+#define T_LOC ns_t_loc
+#define T_NXT ns_t_nxt
+#define T_EID ns_t_eid
+#define T_NIMLOC ns_t_nimloc
+#define T_SRV ns_t_srv
+#define T_ATMA ns_t_atma
+#define T_NAPTR ns_t_naptr
+#define T_A6 ns_t_a6
+#define T_DNAME ns_t_dname
+#define T_TSIG ns_t_tsig
+#define T_IXFR ns_t_ixfr
+#define T_AXFR ns_t_axfr
+#define T_MAILB ns_t_mailb
+#define T_MAILA ns_t_maila
+#define T_ANY ns_t_any
+
+#define C_IN ns_c_in
+#define C_CHAOS ns_c_chaos
+#define C_HS ns_c_hs
+/* BIND_UPDATE */
+#define C_NONE ns_c_none
+#define C_ANY ns_c_any
+
+#define GETSHORT NS_GET16
+#define GETLONG NS_GET32
+#define PUTSHORT NS_PUT16
+#define PUTLONG NS_PUT32
+
+#endif /* _ARPA_NAMESER_COMPAT_ */
+/*! \file */
diff --git a/apt-pkg/pkgcache.cc b/apt-pkg/pkgcache.cc
index 80dd1d1fa..a23bfa2d5 100644
--- a/apt-pkg/pkgcache.cc
+++ b/apt-pkg/pkgcache.cc
@@ -153,6 +153,7 @@ bool pkgCache::ReMap(bool const &Errorchecks)
VerP = (Version *)Map.Data();
DescP = (Description *)Map.Data();
ProvideP = (Provides *)Map.Data();
+ TagP = (Tag *)Map.Data();
DepP = (Dependency *)Map.Data();
DepDataP = (DependencyData *)Map.Data();
StrP = (char *)Map.Data();
diff --git a/apt-pkg/pkgcache.h b/apt-pkg/pkgcache.h
index 787e3995f..de3d49227 100644
--- a/apt-pkg/pkgcache.h
+++ b/apt-pkg/pkgcache.h
@@ -123,6 +123,7 @@ class pkgCache /*{{{*/
struct StringItem;
struct VerFile;
struct DescFile;
+ struct Tag;
// Iterators
template<typename Str, typename Itr> class Iterator;
@@ -136,6 +137,7 @@ class pkgCache /*{{{*/
class PkgFileIterator;
class VerFileIterator;
class DescFileIterator;
+ class TagIterator;
class Namespace;
@@ -216,6 +218,7 @@ class pkgCache /*{{{*/
ReleaseFile *RlsFileP;
PackageFile *PkgFileP;
Version *VerP;
+ Tag *TagP;
Description *DescP;
Provides *ProvideP;
Dependency *DepP;
@@ -322,6 +325,7 @@ struct pkgCache::Header
map_number_t ReleaseFileSz;
map_number_t PackageFileSz;
map_number_t VersionSz;
+ map_number_t TagSz;
map_number_t DescriptionSz;
map_number_t DependencySz;
map_number_t DependencyDataSz;
@@ -337,6 +341,7 @@ struct pkgCache::Header
map_id_t GroupCount;
map_id_t PackageCount;
map_id_t VersionCount;
+ map_id_t TagCount;
map_id_t DescriptionCount;
map_id_t DependsCount;
map_id_t DependsDataCount;
@@ -587,6 +592,16 @@ struct pkgCache::VerFile
map_filesize_t Size;
};
/*}}}*/
+// TagFile structure /*{{{*/
+/** \brief associates a tag with something */
+struct pkgCache::Tag
+{
+ /** \brief name of this tag */
+ map_stringitem_t Name;
+ /** \brief next step in the linked list */
+ map_pointer_t NextTag; // Tag
+};
+ /*}}}*/
// DescFile structure /*{{{*/
/** \brief associates a description with a Translation file */
struct pkgCache::DescFile
@@ -614,6 +629,8 @@ struct pkgCache::Version
map_stringitem_t VerStr;
/** \brief section this version is filled in */
map_stringitem_t Section;
+ /** \brief high-level name used to display package */
+ map_stringitem_t Display;
/** \brief source package name this version comes from
Always contains the name, even if it is the same as the binary name */
map_stringitem_t SourcePkgName;
@@ -658,6 +675,8 @@ struct pkgCache::Version
map_pointer_t ParentPkg; // Package
/** \brief list of pkgCache::Provides */
map_pointer_t ProvidesList; // Provides
+ /** \brief list of pkgCache::Tag */
+ map_pointer_t TagList; // Tag
/** \brief archive size for this version
@@ -813,6 +832,7 @@ class pkgCache::Namespace /*{{{*/
typedef pkgCache::GrpIterator GrpIterator;
typedef pkgCache::PkgIterator PkgIterator;
typedef pkgCache::VerIterator VerIterator;
+ typedef pkgCache::TagIterator TagIterator;
typedef pkgCache::DescIterator DescIterator;
typedef pkgCache::DepIterator DepIterator;
typedef pkgCache::PrvIterator PrvIterator;
diff --git a/apt-pkg/pkgcachegen.cc b/apt-pkg/pkgcachegen.cc
index 5a3b65b3a..6a409f991 100644
--- a/apt-pkg/pkgcachegen.cc
+++ b/apt-pkg/pkgcachegen.cc
@@ -68,7 +68,7 @@ bool pkgCacheGenerator::Start()
bool const newError = _error->PendingError();
_error->MergeWithStack();
if (newError)
- return false;
+ return _error->ReturnError();
if (Map.Size() <= 0)
return false;
@@ -132,7 +132,7 @@ bool pkgCacheGenerator::Start()
advoid a problem during a crash */
pkgCacheGenerator::~pkgCacheGenerator()
{
- if (_error->PendingError() == true || Map.validData() == false)
+ if (Map.validData() == false)
return;
if (Map.Sync() == false)
return;
@@ -175,6 +175,10 @@ void pkgCacheGenerator::ReMap(void const * const oldMap, void const * const newM
i != Dynamic<pkgCache::VerIterator>::toReMap.end(); ++i)
if (std::get<1>(seen.insert(*i)) == true)
(*i)->ReMap(oldMap, newMap);
+ for (std::vector<pkgCache::TagIterator*>::const_iterator i = Dynamic<pkgCache::TagIterator>::toReMap.begin();
+ i != Dynamic<pkgCache::TagIterator>::toReMap.end(); ++i)
+ if (std::get<1>(seen.insert(*i)) == true)
+ (*i)->ReMap(oldMap, newMap);
for (std::vector<pkgCache::DepIterator*>::const_iterator i = Dynamic<pkgCache::DepIterator>::toReMap.begin();
i != Dynamic<pkgCache::DepIterator>::toReMap.end(); ++i)
if (std::get<1>(seen.insert(*i)) == true)
@@ -250,7 +254,7 @@ bool pkgCacheGenerator::MergeList(ListParser &List,
{
string const PackageName = List.Package();
if (PackageName.empty() == true)
- return false;
+ continue;
Counter++;
if (Counter % 100 == 0 && Progress != 0)
@@ -264,24 +268,26 @@ bool pkgCacheGenerator::MergeList(ListParser &List,
{
// package descriptions
if (MergeListGroup(List, PackageName) == false)
- return false;
+ continue;
continue;
}
// Get a pointer to the package structure
pkgCache::PkgIterator Pkg;
Dynamic<pkgCache::PkgIterator> DynPkg(Pkg);
- if (NewPackage(Pkg, PackageName, Arch) == false)
+ if (NewPackage(Pkg, PackageName, Arch) == false) {
// TRANSLATOR: The first placeholder is a package name,
// the other two should be copied verbatim as they include debug info
- return _error->Error(_("Error occurred while processing %s (%s%d)"),
+ _error->Error(_("Error occurred while processing %s (%s%d)"),
PackageName.c_str(), "NewPackage", 1);
+ continue;
+ }
if (Version.empty() == true)
{
if (MergeListPackage(List, Pkg) == false)
- return false;
+ continue;
}
else
{
@@ -1274,6 +1280,38 @@ bool pkgCacheGenerator::SelectReleaseFile(const string &File,const string &Site,
return true;
}
/*}}}*/
+// ListParser::NewTag - Create a Tag element /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+bool pkgCacheListParser::NewTag(pkgCache::VerIterator &Ver,
+ const char *NameStart,
+ unsigned int NameSize)
+{
+ return Owner->NewTag(Ver, NameStart, NameSize);
+}
+bool pkgCacheGenerator::NewTag(pkgCache::VerIterator &Ver,
+ const char *NameStart,
+ unsigned int NameSize)
+{
+ // Get a structure
+ map_pointer_t const idxTag = AllocateInMap(sizeof(pkgCache::Tag));
+ if (unlikely(idxTag == 0))
+ return false;
+
+ // Fill it in
+ pkgCache::TagIterator Tg(Cache,Cache.TagP + idxTag);
+ map_pointer_t const idxName = StoreString(TAG,NameStart,NameSize);
+ if (idxName == 0)
+ return false;
+ Tg->Name = idxName;
+
+ Tg->NextTag = Ver->TagList;
+ Ver->TagList = Tg.Index();
+ Cache.HeaderP->TagCount++;
+
+ return true;
+}
+ /*}}}*/
// CacheGenerator::SelectFile - Select the current file being parsed /*{{{*/
// ---------------------------------------------------------------------
/* This is used to select which file is to be associated with all newly
@@ -1342,6 +1380,7 @@ map_stringitem_t pkgCacheGenerator::StoreString(enum StringType const type, cons
case PKGNAME: strings = &strPkgNames; break;
case VERSIONNUMBER: strings = &strVersions; break;
case SECTION: strings = &strSections; break;
+ case TAG: strings = &strTags; break;
default: _error->Fatal("Unknown enum type used for string storage of '%.*s'", Size, S); return 0;
}
@@ -1401,7 +1440,7 @@ static bool CheckValidity(FileFd &CacheFile, std::string const &CacheFileName,
{
if (Debug == true)
std::clog << "Errors are pending or Map is empty() for " << CacheFileName << std::endl;
- return false;
+ return _error->ReturnError();
}
std::unique_ptr<bool[]> RlsVisited(new bool[Cache.HeaderP->ReleaseFileCount]);
@@ -1481,7 +1520,7 @@ static bool CheckValidity(FileFd &CacheFile, std::string const &CacheFileName,
std::clog << "Validity failed because of pending errors:" << std::endl;
_error->DumpErrors(std::clog, GlobalError::DEBUG, false);
}
- return false;
+ return _error->ReturnError();
}
if (OutMap != 0)
@@ -1519,16 +1558,14 @@ static map_filesize_t ComputeSize(pkgSourceList const * const List, FileIterator
}
/*}}}*/
// BuildCache - Merge the list of index files into the cache /*{{{*/
-static bool BuildCache(pkgCacheGenerator &Gen,
+static void BuildCache(pkgCacheGenerator &Gen,
OpProgress * const Progress,
map_filesize_t &CurrentSize,map_filesize_t TotalSize,
pkgSourceList const * const List,
FileIterator const Start, FileIterator const End)
{
- bool mergeFailure = false;
-
auto const indexFileMerge = [&](pkgIndexFile * const I) {
- if (I->HasPackages() == false || mergeFailure)
+ if (I->HasPackages() == false)
return;
if (I->Exists() == false)
@@ -1546,8 +1583,10 @@ static bool BuildCache(pkgCacheGenerator &Gen,
Progress->OverallProgress(CurrentSize, TotalSize, Size, _("Reading package lists"));
CurrentSize += Size;
- if (I->Merge(Gen,Progress) == false)
- mergeFailure = true;
+ if (I->Merge(Gen,Progress) == false) {
+ _error->ReturnError();
+ return;
+ }
};
if (List != NULL)
@@ -1561,14 +1600,14 @@ static bool BuildCache(pkgCacheGenerator &Gen,
continue;
}
- if ((*i)->Merge(Gen, Progress) == false)
- return false;
+ if ((*i)->Merge(Gen, Progress) == false) {
+ _error->ReturnError();
+ continue;
+ }
std::vector <pkgIndexFile *> *Indexes = (*i)->GetIndexFiles();
if (Indexes != NULL)
std::for_each(Indexes->begin(), Indexes->end(), indexFileMerge);
- if (mergeFailure)
- return false;
}
}
@@ -1576,10 +1615,7 @@ static bool BuildCache(pkgCacheGenerator &Gen,
{
Gen.SelectReleaseFile("", "");
std::for_each(Start, End, indexFileMerge);
- if (mergeFailure)
- return false;
}
- return true;
}
/*}}}*/
// CacheGenerator::MakeStatusCache - Construct the status cache /*{{{*/
@@ -1638,7 +1674,7 @@ static bool loadBackMMapFromFile(std::unique_ptr<pkgCacheGenerator> &Gen,
bool const newError = _error->PendingError();
_error->MergeWithStack();
if (alloc == 0 && newError)
- return false;
+ return _error->ReturnError();
if (CacheF.Read((unsigned char *)Map->Data() + alloc, CacheF.Size()) == false)
return false;
Gen.reset(new pkgCacheGenerator(Map.get(),Progress));
@@ -1754,9 +1790,8 @@ bool pkgCacheGenerator::MakeStatusCache(pkgSourceList &List,OpProgress *Progress
return false;
TotalSize += ComputeSize(&List, Files.begin(),Files.end());
- if (BuildCache(*Gen, Progress, CurrentSize, TotalSize, &List,
- Files.end(),Files.end()) == false)
- return false;
+ BuildCache(*Gen, Progress, CurrentSize, TotalSize, &List,
+ Files.end(),Files.end());
if (Writeable == true && SrcCacheFileName.empty() == false)
if (writeBackMMapToFile(Gen.get(), Map.get(), SrcCacheFileName) == false)
@@ -1767,9 +1802,8 @@ bool pkgCacheGenerator::MakeStatusCache(pkgSourceList &List,OpProgress *Progress
{
if (Debug == true)
std::clog << "Building status cache in pkgcache.bin now" << std::endl;
- if (BuildCache(*Gen, Progress, CurrentSize, TotalSize, NULL,
- Files.begin(), Files.end()) == false)
- return false;
+ BuildCache(*Gen, Progress, CurrentSize, TotalSize, NULL,
+ Files.begin(), Files.end());
if (Writeable == true && CacheFileName.empty() == false)
if (writeBackMMapToFile(Gen.get(), Map.get(), CacheFileName) == false)
@@ -1790,9 +1824,8 @@ bool pkgCacheGenerator::MakeStatusCache(pkgSourceList &List,OpProgress *Progress
}
Files = List.GetVolatileFiles();
- if (BuildCache(*Gen, Progress, CurrentSize, TotalSize, NULL,
- Files.begin(), Files.end()) == false)
- return false;
+ BuildCache(*Gen, Progress, CurrentSize, TotalSize, NULL,
+ Files.begin(), Files.end());
}
if (OutMap != nullptr)
@@ -1829,14 +1862,15 @@ bool pkgCacheGenerator::MakeOnlyStatusCache(OpProgress *Progress,DynamicMMap **O
if (Progress != NULL)
Progress->OverallProgress(0,1,1,_("Reading package lists"));
pkgCacheGenerator Gen(Map.get(),Progress);
- if (Gen.Start() == false || _error->PendingError() == true)
- return false;
- if (BuildCache(Gen,Progress,CurrentSize,TotalSize, NULL,
- Files.begin(), Files.end()) == false)
+ if (Gen.Start() == false)
return false;
-
if (_error->PendingError() == true)
- return false;
+ return _error->ReturnError();
+ BuildCache(Gen,Progress,CurrentSize,TotalSize, NULL,
+ Files.begin(), Files.end());
+ // We've passed the point of no return
+ _error->ReturnError();
+
*OutMap = Map.release();
return true;
diff --git a/apt-pkg/pkgcachegen.h b/apt-pkg/pkgcachegen.h
index e11e97e09..44c54269d 100644
--- a/apt-pkg/pkgcachegen.h
+++ b/apt-pkg/pkgcachegen.h
@@ -77,6 +77,7 @@ class APT_HIDDEN pkgCacheGenerator /*{{{*/
std::unordered_set<string_pointer, hash> strPkgNames;
std::unordered_set<string_pointer, hash> strVersions;
std::unordered_set<string_pointer, hash> strSections;
+ std::unordered_set<string_pointer, hash> strTags;
#endif
friend class pkgCacheListParser;
@@ -127,10 +128,11 @@ class APT_HIDDEN pkgCacheGenerator /*{{{*/
uint8_t const Type, map_pointer_t* &OldDepLast);
bool NewProvides(pkgCache::VerIterator &Ver, pkgCache::PkgIterator &Pkg,
map_stringitem_t const ProvidesVersion, uint8_t const Flags);
+ bool NewTag(pkgCache::VerIterator &Ver,const char *NameStart,unsigned int NameSize);
public:
- enum StringType { MIXED, PKGNAME, VERSIONNUMBER, SECTION };
+ enum StringType { MIXED, PKGNAME, VERSIONNUMBER, SECTION, TAG };
map_stringitem_t StoreString(StringType const type, const char * S, unsigned int const Size);
#ifdef APT_PKG_EXPOSE_STRING_VIEW
@@ -208,6 +210,7 @@ class APT_HIDDEN pkgCacheListParser
uint8_t const Flags);
bool NewProvidesAllArch(pkgCache::VerIterator &Ver, APT::StringView Package,
APT::StringView Version, uint8_t const Flags);
+ bool NewTag(pkgCache::VerIterator &Ver,const char *NameStart,unsigned int NameSize);
#endif
public:
diff --git a/apt-pkg/pkgrecords.h b/apt-pkg/pkgrecords.h
index 6d1342d45..f78a6229f 100644
--- a/apt-pkg/pkgrecords.h
+++ b/apt-pkg/pkgrecords.h
@@ -91,6 +91,7 @@ class pkgRecords::Parser /*{{{*/
std::string LongDesc() {return LongDesc("");};
virtual std::string Name() {return std::string();};
+ virtual std::string Display() {return std::string();}
virtual std::string Homepage() {return std::string();}
// An arbitrary custom field
@@ -99,6 +100,9 @@ class pkgRecords::Parser /*{{{*/
// The record in binary form
virtual void GetRec(const char *&Start,const char *&Stop) {Start = Stop = 0;};
+ // Locate a tag
+ virtual bool Find(const char *Tag,const char *&Start, const char *&End) {Start = End = 0; return false;};
+
Parser();
virtual ~Parser();
diff --git a/apt-pkg/policy.cc b/apt-pkg/policy.cc
index 7986aa506..614539266 100644
--- a/apt-pkg/policy.cc
+++ b/apt-pkg/policy.cc
@@ -333,7 +333,7 @@ bool ReadPinDir(pkgPolicy &Plcy,string Dir)
bool const PendingErrors = _error->PendingError();
_error->MergeWithStack();
if (PendingErrors)
- return false;
+ return _error->ReturnError();
// Read the files
bool good = true;
@@ -415,6 +415,7 @@ bool ReadPinFile(pkgPolicy &Plcy,string File)
if (priority < std::numeric_limits<short>::min() ||
priority > std::numeric_limits<short>::max() ||
newError) {
+ _error->ReturnError();
return _error->Error(_("%s: Value %s is outside the range of valid pin priorities (%d to %d)"),
File.c_str(), Tags.FindS("Pin-Priority").c_str(),
std::numeric_limits<short>::min(),
diff --git a/apt-pkg/rawmemchr.cc b/apt-pkg/rawmemchr.cc
new file mode 100644
index 000000000..8f7669b6c
--- /dev/null
+++ b/apt-pkg/rawmemchr.cc
@@ -0,0 +1,139 @@
+/* Searching in a string.
+ Copyright (C) 2008-2015 Free Software Foundation, Inc.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+#ifndef HAVE_RAWMEMCHR
+
+/* Specification. */
+#include <string.h>
+
+/* Find the first occurrence of C in S. */
+extern "C" void *
+rawmemchr (const void *s, int c_in)
+{
+ /* On 32-bit hardware, choosing longword to be a 32-bit unsigned
+ long instead of a 64-bit uintmax_t tends to give better
+ performance. On 64-bit hardware, unsigned long is generally 64
+ bits already. Change this typedef to experiment with
+ performance. */
+ typedef unsigned long int longword;
+
+ const unsigned char *char_ptr;
+ const longword *longword_ptr;
+ longword repeated_one;
+ longword repeated_c;
+ unsigned char c;
+
+ c = (unsigned char) c_in;
+
+ /* Handle the first few bytes by reading one byte at a time.
+ Do this until CHAR_PTR is aligned on a longword boundary. */
+ for (char_ptr = (const unsigned char *) s;
+ (size_t) char_ptr % sizeof (longword) != 0;
+ ++char_ptr)
+ if (*char_ptr == c)
+ return (void *) char_ptr;
+
+ longword_ptr = (const longword *) char_ptr;
+
+ /* All these elucidatory comments refer to 4-byte longwords,
+ but the theory applies equally well to any size longwords. */
+
+ /* Compute auxiliary longword values:
+ repeated_one is a value which has a 1 in every byte.
+ repeated_c has c in every byte. */
+ repeated_one = 0x01010101;
+ repeated_c = c | (c << 8);
+ repeated_c |= repeated_c << 16;
+ if (0xffffffffU < (longword) -1)
+ {
+ repeated_one |= repeated_one << 31 << 1;
+ repeated_c |= repeated_c << 31 << 1;
+ if (8 < sizeof (longword))
+ {
+ size_t i;
+
+ for (i = 64; i < sizeof (longword) * 8; i *= 2)
+ {
+ repeated_one |= repeated_one << i;
+ repeated_c |= repeated_c << i;
+ }
+ }
+ }
+
+ /* Instead of the traditional loop which tests each byte, we will
+ test a longword at a time. The tricky part is testing if *any of
+ the four* bytes in the longword in question are equal to NUL or
+ c. We first use an xor with repeated_c. This reduces the task
+ to testing whether *any of the four* bytes in longword1 is zero.
+
+ We compute tmp =
+ ((longword1 - repeated_one) & ~longword1) & (repeated_one << 7).
+ That is, we perform the following operations:
+ 1. Subtract repeated_one.
+ 2. & ~longword1.
+ 3. & a mask consisting of 0x80 in every byte.
+ Consider what happens in each byte:
+ - If a byte of longword1 is zero, step 1 and 2 transform it into 0xff,
+ and step 3 transforms it into 0x80. A carry can also be propagated
+ to more significant bytes.
+ - If a byte of longword1 is nonzero, let its lowest 1 bit be at
+ position k (0 <= k <= 7); so the lowest k bits are 0. After step 1,
+ the byte ends in a single bit of value 0 and k bits of value 1.
+ After step 2, the result is just k bits of value 1: 2^k - 1. After
+ step 3, the result is 0. And no carry is produced.
+ So, if longword1 has only non-zero bytes, tmp is zero.
+ Whereas if longword1 has a zero byte, call j the position of the least
+ significant zero byte. Then the result has a zero at positions 0, ...,
+ j-1 and a 0x80 at position j. We cannot predict the result at the more
+ significant bytes (positions j+1..3), but it does not matter since we
+ already have a non-zero bit at position 8*j+7.
+
+ The test whether any byte in longword1 is zero is equivalent
+ to testing whether tmp is nonzero.
+
+ This test can read beyond the end of a string, depending on where
+ C_IN is encountered. However, this is considered safe since the
+ initialization phase ensured that the read will be aligned,
+ therefore, the read will not cross page boundaries and will not
+ cause a fault. */
+
+ while (1)
+ {
+ longword longword1 = *longword_ptr ^ repeated_c;
+
+ if ((((longword1 - repeated_one) & ~longword1)
+ & (repeated_one << 7)) != 0)
+ break;
+ longword_ptr++;
+ }
+
+ char_ptr = (const unsigned char *) longword_ptr;
+
+ /* At this point, we know that one of the sizeof (longword) bytes
+ starting at char_ptr is == c. On little-endian machines, we
+ could determine the first such byte without any further memory
+ accesses, just by looking at the tmp result from the last loop
+ iteration. But this does not work on big-endian machines.
+ Choose code that works in both cases. */
+
+ char_ptr = (unsigned char *) longword_ptr;
+ while (*char_ptr != c)
+ char_ptr++;
+ return (void *) char_ptr;
+}
+#endif
diff --git a/apt-pkg/strchrnul.cc b/apt-pkg/strchrnul.cc
new file mode 100644
index 000000000..b68b8501b
--- /dev/null
+++ b/apt-pkg/strchrnul.cc
@@ -0,0 +1,147 @@
+/* Searching in a string.
+ Copyright (C) 2003, 2007-2015 Free Software Foundation, Inc.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+#ifndef HAVE_STRCHRNUL
+
+/* Specification. */
+#include <string.h>
+
+#include <apt-pkg/missing.h>
+
+/* Find the first occurrence of C in S or the final NUL byte. */
+extern "C" char *
+strchrnul (const char *s, int c_in)
+{
+ /* On 32-bit hardware, choosing longword to be a 32-bit unsigned
+ long instead of a 64-bit uintmax_t tends to give better
+ performance. On 64-bit hardware, unsigned long is generally 64
+ bits already. Change this typedef to experiment with
+ performance. */
+ typedef unsigned long int longword;
+
+ const unsigned char *char_ptr;
+ const longword *longword_ptr;
+ longword repeated_one;
+ longword repeated_c;
+ unsigned char c;
+
+ c = (unsigned char) c_in;
+ if (!c)
+ return (char*) rawmemchr (s, 0);
+
+ /* Handle the first few bytes by reading one byte at a time.
+ Do this until CHAR_PTR is aligned on a longword boundary. */
+ for (char_ptr = (const unsigned char *) s;
+ (size_t) char_ptr % sizeof (longword) != 0;
+ ++char_ptr)
+ if (!*char_ptr || *char_ptr == c)
+ return (char *) char_ptr;
+
+ longword_ptr = (const longword *) char_ptr;
+
+ /* All these elucidatory comments refer to 4-byte longwords,
+ but the theory applies equally well to any size longwords. */
+
+ /* Compute auxiliary longword values:
+ repeated_one is a value which has a 1 in every byte.
+ repeated_c has c in every byte. */
+ repeated_one = 0x01010101;
+ repeated_c = c | (c << 8);
+ repeated_c |= repeated_c << 16;
+ if (0xffffffffU < (longword) -1)
+ {
+ repeated_one |= repeated_one << 31 << 1;
+ repeated_c |= repeated_c << 31 << 1;
+ if (8 < sizeof (longword))
+ {
+ size_t i;
+
+ for (i = 64; i < sizeof (longword) * 8; i *= 2)
+ {
+ repeated_one |= repeated_one << i;
+ repeated_c |= repeated_c << i;
+ }
+ }
+ }
+
+ /* Instead of the traditional loop which tests each byte, we will
+ test a longword at a time. The tricky part is testing if *any of
+ the four* bytes in the longword in question are equal to NUL or
+ c. We first use an xor with repeated_c. This reduces the task
+ to testing whether *any of the four* bytes in longword1 or
+ longword2 is zero.
+
+ Let's consider longword1. We compute tmp =
+ ((longword1 - repeated_one) & ~longword1) & (repeated_one << 7).
+ That is, we perform the following operations:
+ 1. Subtract repeated_one.
+ 2. & ~longword1.
+ 3. & a mask consisting of 0x80 in every byte.
+ Consider what happens in each byte:
+ - If a byte of longword1 is zero, step 1 and 2 transform it into 0xff,
+ and step 3 transforms it into 0x80. A carry can also be propagated
+ to more significant bytes.
+ - If a byte of longword1 is nonzero, let its lowest 1 bit be at
+ position k (0 <= k <= 7); so the lowest k bits are 0. After step 1,
+ the byte ends in a single bit of value 0 and k bits of value 1.
+ After step 2, the result is just k bits of value 1: 2^k - 1. After
+ step 3, the result is 0. And no carry is produced.
+ So, if longword1 has only non-zero bytes, tmp is zero.
+ Whereas if longword1 has a zero byte, call j the position of the least
+ significant zero byte. Then the result has a zero at positions 0, ...,
+ j-1 and a 0x80 at position j. We cannot predict the result at the more
+ significant bytes (positions j+1..3), but it does not matter since we
+ already have a non-zero bit at position 8*j+7.
+
+ The test whether any byte in longword1 or longword2 is zero is equivalent
+ to testing whether tmp1 is nonzero or tmp2 is nonzero. We can combine
+ this into a single test, whether (tmp1 | tmp2) is nonzero.
+
+ This test can read more than one byte beyond the end of a string,
+ depending on where the terminating NUL is encountered. However,
+ this is considered safe since the initialization phase ensured
+ that the read will be aligned, therefore, the read will not cross
+ page boundaries and will not cause a fault. */
+
+ while (1)
+ {
+ longword longword1 = *longword_ptr ^ repeated_c;
+ longword longword2 = *longword_ptr;
+
+ if (((((longword1 - repeated_one) & ~longword1)
+ | ((longword2 - repeated_one) & ~longword2))
+ & (repeated_one << 7)) != 0)
+ break;
+ longword_ptr++;
+ }
+
+ char_ptr = (const unsigned char *) longword_ptr;
+
+ /* At this point, we know that one of the sizeof (longword) bytes
+ starting at char_ptr is == 0 or == c. On little-endian machines,
+ we could determine the first such byte without any further memory
+ accesses, just by looking at the tmp result from the last loop
+ iteration. But this does not work on big-endian machines.
+ Choose code that works in both cases. */
+
+ char_ptr = (unsigned char *) longword_ptr;
+ while (*char_ptr && (*char_ptr != c))
+ char_ptr++;
+ return (char *) char_ptr;
+}
+#endif
diff --git a/apt-pkg/tagfile.cc b/apt-pkg/tagfile.cc
index 1e7f2867c..5f39e5757 100644
--- a/apt-pkg/tagfile.cc
+++ b/apt-pkg/tagfile.cc
@@ -12,6 +12,7 @@
// Include Files /*{{{*/
#include <config.h>
+#include <apt-pkg/mmap.h>
#include <apt-pkg/error.h>
#include <apt-pkg/fileutl.h>
#include <apt-pkg/string_view.h>
@@ -36,10 +37,11 @@ using APT::StringView;
class APT_HIDDEN pkgTagFilePrivate /*{{{*/
{
public:
- void Reset(FileFd * const pFd, unsigned long long const pSize, pkgTagFile::Flags const pFlags)
+ void Reset(FileFd * const pFd, pkgTagFile::Flags const pFlags)
{
- if (Buffer != NULL)
- free(Buffer);
+ if (Map != NULL)
+ delete Map;
+ Map = NULL;
Buffer = NULL;
Fd = pFd;
Flags = pFlags;
@@ -47,14 +49,11 @@ public:
End = NULL;
Done = false;
iOffset = 0;
- Size = pSize;
- isCommentedLine = false;
- chunks.clear();
}
- pkgTagFilePrivate(FileFd * const pFd, unsigned long long const Size, pkgTagFile::Flags const pFlags) : Buffer(NULL)
+ pkgTagFilePrivate(FileFd * const pFd, pkgTagFile::Flags const pFlags) : Map(NULL)
{
- Reset(pFd, Size, pFlags);
+ Reset(pFd, pFlags);
}
FileFd * Fd;
pkgTagFile::Flags Flags;
@@ -63,20 +62,12 @@ public:
char *End;
bool Done;
unsigned long long iOffset;
- unsigned long long Size;
- bool isCommentedLine;
- struct FileChunk
- {
- bool const good;
- size_t length;
- FileChunk(bool const pgood, size_t const plength) : good(pgood), length(plength) {}
- };
- std::list<FileChunk> chunks;
+ MMap *Map;
~pkgTagFilePrivate()
{
- if (Buffer != NULL)
- free(Buffer);
+ if (Map != NULL)
+ delete Map;
}
};
/*}}}*/
@@ -115,42 +106,38 @@ static unsigned long BetaHash(const char *Text, size_t Length) /*{{{*/
/*}}}*/
// TagFile::pkgTagFile - Constructor /*{{{*/
-pkgTagFile::pkgTagFile(FileFd * const pFd,pkgTagFile::Flags const pFlags, unsigned long long const Size)
- : d(new pkgTagFilePrivate(pFd, Size + 4, pFlags))
+pkgTagFile::pkgTagFile(FileFd * const pFd,pkgTagFile::Flags const pFlags)
+ : d(new pkgTagFilePrivate(pFd, pFlags))
{
- Init(pFd, pFlags, Size);
+ Init(pFd, pFlags);
}
-pkgTagFile::pkgTagFile(FileFd * const pFd,unsigned long long const Size)
- : pkgTagFile(pFd, pkgTagFile::STRICT, Size)
+pkgTagFile::pkgTagFile(FileFd * const pFd)
+ : pkgTagFile(pFd, pkgTagFile::STRICT)
{
}
-void pkgTagFile::Init(FileFd * const pFd, pkgTagFile::Flags const pFlags, unsigned long long Size)
+void pkgTagFile::Init(FileFd * const pFd, pkgTagFile::Flags const pFlags)
{
- /* The size is increased by 4 because if we start with the Size of the
- filename we need to try to read 1 char more to see an EOF faster, 1
- char the end-pointer can be on and maybe 2 newlines need to be added
- to the end of the file -> 4 extra chars */
- Size += 4;
- d->Reset(pFd, Size, pFlags);
-
- if (d->Fd->IsOpen() == false)
- d->Start = d->End = d->Buffer = 0;
- else
- d->Buffer = (char*)malloc(sizeof(char) * Size);
+ d->Reset(pFd, pFlags);
+
+ if (d->Fd->IsOpen() == false || d->Fd->Size() == 0)
+ _error->Discard();
+ else {
+ d->Map = new MMap(*d->Fd, MMap::ReadOnly);
+ d->Buffer = static_cast<char *>(d->Map->Data());
+ }
if (d->Buffer == NULL)
d->Done = true;
- else
+ else {
d->Done = false;
+ d->End = d->Buffer + d->Map->Size();
+ }
- d->Start = d->End = d->Buffer;
- d->iOffset = 0;
- if (d->Done == false)
- Fill();
+ d->Start = d->Buffer;
}
-void pkgTagFile::Init(FileFd * const pFd,unsigned long long Size)
+void pkgTagFile::Init(FileFd * const pFd)
{
- Init(pFd, pkgTagFile::STRICT, Size);
+ Init(pFd, pkgTagFile::STRICT);
}
/*}}}*/
// TagFile::~pkgTagFile - Destructor /*{{{*/
@@ -165,36 +152,6 @@ APT_PURE unsigned long pkgTagFile::Offset()
return d->iOffset;
}
/*}}}*/
-// TagFile::Resize - Resize the internal buffer /*{{{*/
-// ---------------------------------------------------------------------
-/* Resize the internal buffer (double it in size). Fail if a maximum size
- * size is reached.
- */
-bool pkgTagFile::Resize()
-{
- // fail is the buffer grows too big
- if(d->Size > 1024*1024+1)
- return false;
-
- return Resize(d->Size * 2);
-}
-bool pkgTagFile::Resize(unsigned long long const newSize)
-{
- unsigned long long const EndSize = d->End - d->Start;
-
- // get new buffer and use it
- char* const newBuffer = static_cast<char*>(realloc(d->Buffer, sizeof(char) * newSize));
- if (newBuffer == NULL)
- return false;
- d->Buffer = newBuffer;
- d->Size = newSize;
-
- // update the start/end pointers to the new buffer
- d->Start = d->Buffer;
- d->End = d->Start + EndSize;
- return true;
-}
- /*}}}*/
// TagFile::Step - Advance to the next section /*{{{*/
// ---------------------------------------------------------------------
/* If the Section Scanner fails we refill the buffer and try again.
@@ -203,225 +160,18 @@ bool pkgTagFile::Resize(unsigned long long const newSize)
*/
bool pkgTagFile::Step(pkgTagSection &Tag)
{
- if(Tag.Scan(d->Start,d->End - d->Start) == false)
+ if(Tag.Scan(d->Start,d->End - d->Start,(d->Flags & SUPPORT_COMMENTS) != 0) == false)
{
- do
- {
- if (Fill() == false)
- return false;
-
- if(Tag.Scan(d->Start,d->End - d->Start, false))
- break;
-
- if (Resize() == false)
- return _error->Error(_("Unable to parse package file %s (%d)"),
+ if (d->Start == d->End)
+ return false;
+ else
+ return _error->Warning(_("Unable to parse package file %s (%d)"),
d->Fd->Name().c_str(), 1);
-
- } while (Tag.Scan(d->Start,d->End - d->Start, false) == false);
}
size_t tagSize = Tag.size();
d->Start += tagSize;
-
- if ((d->Flags & pkgTagFile::SUPPORT_COMMENTS) == 0)
- d->iOffset += tagSize;
- else
- {
- auto first = d->chunks.begin();
- for (; first != d->chunks.end(); ++first)
- {
- if (first->good == false)
- d->iOffset += first->length;
- else
- {
- if (tagSize < first->length)
- {
- first->length -= tagSize;
- d->iOffset += tagSize;
- break;
- }
- else
- {
- tagSize -= first->length;
- d->iOffset += first->length;
- }
- }
- }
- d->chunks.erase(d->chunks.begin(), first);
- }
-
- if ((d->Flags & pkgTagFile::SUPPORT_COMMENTS) == 0 || Tag.Count() != 0)
- {
- Tag.Trim();
- return true;
- }
- return Step(Tag);
-}
- /*}}}*/
-// TagFile::Fill - Top up the buffer /*{{{*/
-// ---------------------------------------------------------------------
-/* This takes the bit at the end of the buffer and puts it at the start
- then fills the rest from the file */
-static bool FillBuffer(pkgTagFilePrivate * const d)
-{
- unsigned long long Actual = 0;
- // See if only a bit of the file is left
- unsigned long long const dataSize = d->Size - ((d->End - d->Buffer) + 1);
- if (d->Fd->Read(d->End, dataSize, &Actual) == false)
- return false;
- if (Actual != dataSize)
- d->Done = true;
- d->End += Actual;
- return true;
-}
-static void RemoveCommentsFromBuffer(pkgTagFilePrivate * const d)
-{
- // look for valid comments in the buffer
- char * good_start = nullptr, * bad_start = nullptr;
- char * current = d->Start;
- if (d->isCommentedLine == false)
- {
- if (d->Start == d->Buffer)
- {
- // the start of the buffer is a newline as a record can't start
- // in the middle of a line by definition.
- if (*d->Start == '#')
- {
- d->isCommentedLine = true;
- ++current;
- if (current > d->End)
- d->chunks.emplace_back(false, 1);
- }
- }
- if (d->isCommentedLine == false)
- good_start = d->Start;
- else
- bad_start = d->Start;
- }
- else
- bad_start = d->Start;
-
- std::vector<std::pair<char*, size_t>> good_parts;
- while (current <= d->End)
- {
- size_t const restLength = (d->End - current);
- if (d->isCommentedLine == false)
- {
- current = static_cast<char*>(memchr(current, '#', restLength));
- if (current == nullptr)
- {
- size_t const goodLength = d->End - good_start;
- d->chunks.emplace_back(true, goodLength);
- if (good_start != d->Start)
- good_parts.push_back(std::make_pair(good_start, goodLength));
- break;
- }
- bad_start = current;
- --current;
- // ensure that this is really a comment and not a '#' in the middle of a line
- if (*current == '\n')
- {
- size_t const goodLength = (current - good_start) + 1;
- d->chunks.emplace_back(true, goodLength);
- good_parts.push_back(std::make_pair(good_start, goodLength));
- good_start = nullptr;
- d->isCommentedLine = true;
- }
- current += 2;
- }
- else // the current line is a comment
- {
- current = static_cast<char*>(memchr(current, '\n', restLength));
- if (current == nullptr)
- {
- d->chunks.emplace_back(false, (d->End - bad_start));
- break;
- }
- ++current;
- // is the next line a comment, too?
- if (current >= d->End || *current != '#')
- {
- d->chunks.emplace_back(false, (current - bad_start));
- good_start = current;
- bad_start = nullptr;
- d->isCommentedLine = false;
- }
- ++current;
- }
- }
-
- if (good_parts.empty() == false)
- {
- // we found comments, so move later parts over them
- current = d->Start;
- for (auto const &good: good_parts)
- {
- memmove(current, good.first, good.second);
- current += good.second;
- }
- d->End = current;
- }
-
- if (d->isCommentedLine == true)
- {
- // deal with a buffer containing only comments
- // or an (unfinished) comment at the end
- if (good_parts.empty() == true)
- d->End = d->Start;
- else
- d->Start = d->End;
- }
- else
- {
- // the buffer was all comment, but ended with the buffer
- if (good_parts.empty() == true && good_start >= d->End)
- d->End = d->Start;
- else
- d->Start = d->End;
- }
-}
-bool pkgTagFile::Fill()
-{
- unsigned long long const EndSize = d->End - d->Start;
- if (EndSize != 0)
- {
- memmove(d->Buffer,d->Start,EndSize);
- d->Start = d->End = d->Buffer + EndSize;
- }
- else
- d->Start = d->End = d->Buffer;
-
- unsigned long long Actual = 0;
- while (d->Done == false && d->Size > (Actual + 1))
- {
- if (FillBuffer(d) == false)
- return false;
- if ((d->Flags & pkgTagFile::SUPPORT_COMMENTS) != 0)
- RemoveCommentsFromBuffer(d);
- Actual = d->End - d->Buffer;
- }
- d->Start = d->Buffer;
-
- if (d->Done == true)
- {
- if (EndSize <= 3 && Actual == 0)
- return false;
- if (d->Size - (d->End - d->Buffer) < 4)
- return true;
-
- // Append a double new line if one does not exist
- unsigned int LineCount = 0;
- for (const char *E = d->End - 1; E - d->End < 6 && (*E == '\n' || *E == '\r'); E--)
- if (*E == '\n')
- ++LineCount;
- if (LineCount < 2)
- {
- if (static_cast<unsigned long long>(d->End - d->Buffer) >= d->Size)
- Resize(d->Size + 3);
- for (; LineCount < 2; ++LineCount)
- *d->End++ = '\n';
- }
- }
+ d->iOffset += tagSize;
return true;
}
/*}}}*/
@@ -431,43 +181,16 @@ bool pkgTagFile::Fill()
that is there */
bool pkgTagFile::Jump(pkgTagSection &Tag,unsigned long long Offset)
{
- if ((d->Flags & pkgTagFile::SUPPORT_COMMENTS) == 0 &&
- // We are within a buffer space of the next hit..
- Offset >= d->iOffset && d->iOffset + (d->End - d->Start) > Offset)
- {
- unsigned long long Dist = Offset - d->iOffset;
- d->Start += Dist;
- d->iOffset += Dist;
- // if we have seen the end, don't ask for more
- if (d->Done == true)
- return Tag.Scan(d->Start, d->End - d->Start);
- else
- return Step(Tag);
- }
+ unsigned int Size(d->Map->Size());
+ if (Offset >= Size)
+ return false;
// Reposition and reload..
d->iOffset = Offset;
d->Done = false;
- if (d->Fd->Seek(Offset) == false)
- return false;
- d->End = d->Start = d->Buffer;
- d->isCommentedLine = false;
- d->chunks.clear();
-
- if (Fill() == false)
- return false;
+ d->Start = d->Buffer + d->iOffset;
- if (Tag.Scan(d->Start, d->End - d->Start) == true)
- return true;
-
- // This appends a double new line (for the real eof handling)
- if (Fill() == false)
- return false;
-
- if (Tag.Scan(d->Start, d->End - d->Start, false) == false)
- return _error->Error(_("Unable to parse package file %s (%d)"),d->Fd->Name().c_str(), 2);
-
- return true;
+ return Step(Tag);
}
/*}}}*/
// pkgTagSection::pkgTagSection - Constructor /*{{{*/
@@ -483,32 +206,20 @@ pkgTagSection::pkgTagSection()
APT_IGNORE_DEPRECATED_POP
/*}}}*/
// TagSection::Scan - Scan for the end of the header information /*{{{*/
-bool pkgTagSection::Scan(const char *Start,unsigned long MaxLength, bool const Restart)
+bool pkgTagSection::Scan(const char *Start,unsigned long MaxLength,bool const SupportComments)
{
Section = Start;
const char *End = Start + MaxLength;
- if (Restart == false && d->Tags.empty() == false)
- {
- Stop = Section + d->Tags.back().StartTag;
- if (End <= Stop)
- return false;
- Stop = (const char *)memchr(Stop,'\n',End - Stop);
- if (Stop == NULL)
- return false;
- ++Stop;
- }
- else
+ Stop = Section;
+ if (d->Tags.empty() == false)
{
- Stop = Section;
- if (d->Tags.empty() == false)
- {
- memset(&AlphaIndexes, 0, sizeof(AlphaIndexes));
- memset(&BetaIndexes, 0, sizeof(BetaIndexes));
- d->Tags.clear();
- }
- d->Tags.reserve(0x100);
+ memset(&AlphaIndexes, 0, sizeof(AlphaIndexes));
+ memset(&BetaIndexes, 0, sizeof(BetaIndexes));
+ d->Tags.clear();
}
+ d->Tags.reserve(0x100);
+
unsigned int TagCount = d->Tags.size();
if (Stop == 0)
@@ -520,12 +231,12 @@ bool pkgTagSection::Scan(const char *Start,unsigned long MaxLength, bool const R
unsigned int lastTagHash = 0;
while (Stop < End)
{
- TrimRecord(true,End);
+ TrimRecord(true,End,SupportComments);
// this can happen when TrimRecord trims away the entire Record
// (e.g. because it just contains comments)
if(Stop == End)
- return true;
+ goto end;
// Start a new index and add it to the hash
if (isspace_ascii(Stop[0]) == 0)
@@ -564,17 +275,17 @@ bool pkgTagSection::Scan(const char *Start,unsigned long MaxLength, bool const R
// find the beginning of the value
Stop = Colon + 1;
for (; Stop < End && isspace_ascii(*Stop) != 0; ++Stop)
- if (*Stop == '\n' && Stop[1] != ' ')
+ if (*Stop == '\n' && (Stop+1 == End || Stop[1] != ' '))
break;
- if (Stop >= End)
- return false;
lastTagData.StartValue = Stop - Section;
}
Stop = (const char *)memchr(Stop,'\n',End - Stop);
- if (Stop == 0)
- return false;
+ if (Stop == 0) {
+ Stop = End;
+ goto end;
+ }
for (; Stop+1 < End && Stop[1] == '\r'; Stop++)
/* nothing */
@@ -582,7 +293,7 @@ bool pkgTagSection::Scan(const char *Start,unsigned long MaxLength, bool const R
// Double newline marks the end of the record
if (Stop+1 < End && Stop[1] == '\n')
- {
+ end: {
if (lastTagData.EndTag != 0)
{
if (lastTagKey != Key::Unknown) {
@@ -595,26 +306,32 @@ bool pkgTagSection::Scan(const char *Start,unsigned long MaxLength, bool const R
d->Tags.push_back(lastTagData);
}
+ if (d->Tags.empty())
+ return false;
+
pkgTagSectionPrivate::TagData const td(Stop - Section);
d->Tags.push_back(td);
- TrimRecord(false,End);
+ TrimRecord(false,End,SupportComments);
return true;
}
Stop++;
}
- return false;
+ goto end;
}
/*}}}*/
// TagSection::TrimRecord - Trim off any garbage before/after a record /*{{{*/
// ---------------------------------------------------------------------
/* There should be exactly 2 newline at the end of the record, no more. */
-void pkgTagSection::TrimRecord(bool BeforeRecord, const char*& End)
-{
- if (BeforeRecord == true)
- return;
- for (; Stop < End && (Stop[0] == '\n' || Stop[0] == '\r'); Stop++);
+void pkgTagSection::TrimRecord(bool BeforeRecord, const char*& End, bool SupportComments)
+{ trim:
+ if (BeforeRecord == false)
+ for (; Stop < End && (Stop[0] == '\n' || Stop[0] == '\r'); Stop++);
+ if (SupportComments && Stop < End && Stop[0] == '#') {
+ Stop = (const char*) memchr(Stop,'\n',End-Stop) ?: End;
+ goto trim;
+ }
}
/*}}}*/
// TagSection::Trim - Trim off any trailing garbage /*{{{*/
@@ -624,7 +341,7 @@ void pkgTagSection::Trim()
{
for (; Stop > Section + 2 && (Stop[-2] == '\n' || Stop[-2] == '\r'); Stop--);
}
- /*}}}*/
+
// TagSection::Exists - return True if a tag exists /*{{{*/
bool pkgTagSection::Exists(StringView Tag) const
{
@@ -679,7 +396,7 @@ bool pkgTagSection::FindInternal(unsigned int Pos, const char *&Start,
if (unlikely(Start > End))
return _error->Error("Internal parsing error");
- for (; isspace_ascii(End[-1]) != 0 && End > Start; --End);
+ for (; End > Start && isspace_ascii(End[-1]) != 0; --End);
return true;
}
@@ -1065,14 +782,6 @@ bool pkgTagSection::Write(FileFd &File, char const * const * const Order, std::v
}
/*}}}*/
-void pkgUserTagSection::TrimRecord(bool /*BeforeRecord*/, const char* &End)/*{{{*/
-{
- for (; Stop < End && (Stop[0] == '\n' || Stop[0] == '\r' || Stop[0] == '#'); Stop++)
- if (Stop[0] == '#')
- Stop = (const char*) memchr(Stop,'\n',End-Stop);
-}
- /*}}}*/
-
#include "tagfile-order.c"
// TFRewrite - Rewrite a control record /*{{{*/
diff --git a/apt-pkg/tagfile.h b/apt-pkg/tagfile.h
index 8b59c43de..a96262e34 100644
--- a/apt-pkg/tagfile.h
+++ b/apt-pkg/tagfile.h
@@ -138,11 +138,11 @@ class pkgTagSection
* @return \b true if section end was found, \b false otherwise.
* Beware that internal state will be inconsistent if \b false is returned!
*/
- APT_MUSTCHECK bool Scan(const char *Start, unsigned long MaxLength, bool const Restart = true);
+ APT_MUSTCHECK bool Scan(const char *Start, unsigned long MaxLength, bool const SupportComments = true);
inline unsigned long size() const {return Stop - Section;};
void Trim();
- virtual void TrimRecord(bool BeforeRecord, const char* &End);
+ void TrimRecord(bool BeforeRecord, const char* &End, bool SupportComments);
/** \brief amount of Tags in the current section
*
@@ -187,11 +187,6 @@ class pkgTagSection
};
-class APT_DEPRECATED_MSG("Use pkgTagFile with the SUPPORT_COMMENTS flag instead") pkgUserTagSection : public pkgTagSection
-{
- virtual void TrimRecord(bool BeforeRecord, const char* &End) APT_OVERRIDE;
-};
-
/** \class pkgTagFile reads and prepares a deb822 formatted file for parsing
* via #pkgTagSection. The default mode tries to be as fast as possible and
* assumes perfectly valid (machine generated) files like Packages. Support
@@ -200,10 +195,6 @@ class pkgTagFile
{
pkgTagFilePrivate * const d;
- APT_HIDDEN bool Fill();
- APT_HIDDEN bool Resize();
- APT_HIDDEN bool Resize(unsigned long long const newSize);
-
public:
bool Step(pkgTagSection &Section);
@@ -216,11 +207,11 @@ public:
SUPPORT_COMMENTS = 1 << 0,
};
- void Init(FileFd * const F, pkgTagFile::Flags const Flags, unsigned long long Size = 32*1024);
- void Init(FileFd * const F,unsigned long long const Size = 32*1024);
+ void Init(FileFd * const F, pkgTagFile::Flags const Flags);
+ void Init(FileFd * const F);
- pkgTagFile(FileFd * const F, pkgTagFile::Flags const Flags, unsigned long long Size = 32*1024);
- pkgTagFile(FileFd * const F,unsigned long long Size = 32*1024);
+ pkgTagFile(FileFd * const F, pkgTagFile::Flags const Flags);
+ pkgTagFile(FileFd * const F);
virtual ~pkgTagFile();
};
diff --git a/debian/libapt-pkg5.0.symbols b/debian/libapt-pkg5.0.symbols
index 882180c78..830570d87 100644
--- a/debian/libapt-pkg5.0.symbols
+++ b/debian/libapt-pkg5.0.symbols
@@ -1294,7 +1294,6 @@ libapt-pkg.so.5.0 libapt-pkg5.0 #MINVER#
(c++)"pkgTagSection::Tag::Rename(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@APTPKG_5.0" 1.1~exp9
(c++)"pkgTagSection::Tag::Rewrite(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@APTPKG_5.0" 1.1~exp9
(c++)"pkgTagSection::Write(FileFd&, char const* const*, std::vector<pkgTagSection::Tag, std::allocator<pkgTagSection::Tag> > const&) const@APTPKG_5.0" 1.1~exp9
- (c++)"pkgUserTagSection::TrimRecord(bool, char const*&)@APTPKG_5.0" 1.1~exp9
(c++)"pkgVersioningSystem::~pkgVersioningSystem()@APTPKG_5.0" 1.1~exp9
(c++)"SigVerify::~SigVerify()@APTPKG_5.0" 1.1~exp9
(c++)"SigVerify::SigVerify()@APTPKG_5.0" 1.1~exp9
@@ -1323,7 +1322,6 @@ libapt-pkg.so.5.0 libapt-pkg5.0 #MINVER#
(c++)"typeinfo for pkgProblemResolver@APTPKG_5.0" 1.1~exp9
(c++)"typeinfo for pkgRecords@APTPKG_5.0" 1.1~exp9
(c++)"typeinfo for pkgSourceList@APTPKG_5.0" 1.1~exp9
- (c++)"typeinfo for pkgUserTagSection@APTPKG_5.0" 1.1~exp9
(c++)"typeinfo for SigVerify@APTPKG_5.0" 1.1~exp9
(c++)"typeinfo for TranslationsCopy@APTPKG_5.0" 1.1~exp9
(c++)"typeinfo name for APT::PackageUniverse@APTPKG_5.0" 1.1~exp9
@@ -1347,7 +1345,6 @@ libapt-pkg.so.5.0 libapt-pkg5.0 #MINVER#
(c++)"typeinfo name for pkgProblemResolver@APTPKG_5.0" 1.1~exp9
(c++)"typeinfo name for pkgRecords@APTPKG_5.0" 1.1~exp9
(c++)"typeinfo name for pkgSourceList@APTPKG_5.0" 1.1~exp9
- (c++)"typeinfo name for pkgUserTagSection@APTPKG_5.0" 1.1~exp9
(c++)"typeinfo name for SigVerify@APTPKG_5.0" 1.1~exp9
(c++)"typeinfo name for TranslationsCopy@APTPKG_5.0" 1.1~exp9
(c++)"URI::ArchiveOnly(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@APTPKG_5.0" 1.1~exp9
@@ -1372,7 +1369,6 @@ libapt-pkg.so.5.0 libapt-pkg5.0 #MINVER#
(c++)"vtable for pkgProblemResolver@APTPKG_5.0" 1.1~exp9
(c++)"vtable for pkgRecords@APTPKG_5.0" 1.1~exp9
(c++)"vtable for pkgSourceList@APTPKG_5.0" 1.1~exp9
- (c++)"vtable for pkgUserTagSection@APTPKG_5.0" 1.1~exp9
(c++)"vtable for SigVerify@APTPKG_5.0" 1.1~exp9
(c++)"vtable for TranslationsCopy@APTPKG_5.0" 1.1~exp9
### dpkg selection state changer & general dpkg interfacing
diff --git a/ftparchive/apt-ftparchive.cc b/ftparchive/apt-ftparchive.cc
index 077701cc0..018df3d8c 100644
--- a/ftparchive/apt-ftparchive.cc
+++ b/ftparchive/apt-ftparchive.cc
@@ -53,7 +53,7 @@ static struct timeval GetTimevalFromSteadyClock() /*{{{*/
auto const Time = std::chrono::steady_clock::now().time_since_epoch();
auto const Time_sec = std::chrono::duration_cast<std::chrono::seconds>(Time);
auto const Time_usec = std::chrono::duration_cast<std::chrono::microseconds>(Time - Time_sec);
- return { Time_sec.count(), Time_usec.count() };
+ return { static_cast<time_t>(Time_sec.count()), static_cast<suseconds_t>(Time_usec.count()) };
}
/*}}}*/
diff --git a/ftparchive/byhash.cc b/ftparchive/byhash.cc
index b24f6158e..5af0ef163 100644
--- a/ftparchive/byhash.cc
+++ b/ftparchive/byhash.cc
@@ -18,6 +18,10 @@
#include <unistd.h>
#include "byhash.h"
+#ifdef __APPLE__
+#define st_mtim st_mtimespec
+#endif
+
#include <apt-pkg/fileutl.h>
#include <apt-pkg/hashes.h>
diff --git a/ftparchive/cachedb.cc b/ftparchive/cachedb.cc
index 1890c28d0..8496f44c1 100644
--- a/ftparchive/cachedb.cc
+++ b/ftparchive/cachedb.cc
@@ -21,6 +21,7 @@
#include <apt-pkg/sha1.h>
#include <apt-pkg/sha2.h>
#include <apt-pkg/strutl.h>
+#include <apt-pkg/missing.h>
#include <ctype.h>
#include <netinet/in.h> // htonl, etc
diff --git a/methods/CMakeLists.txt b/methods/CMakeLists.txt
index c4a32b4f5..6c4c8d4af 100644
--- a/methods/CMakeLists.txt
+++ b/methods/CMakeLists.txt
@@ -19,7 +19,7 @@ target_compile_definitions(connectlib PRIVATE ${GNUTLS_DEFINITIONS})
target_include_directories(connectlib PRIVATE ${GNUTLS_INCLUDE_DIR})
# Additional libraries to link against for networked stuff
-target_link_libraries(http ${GNUTLS_LIBRARIES})
+target_link_libraries(http apt-pkg lockdown "-framework CoreFoundation" "-framework CFNetwork" "-framework SystemConfiguration" ${GNUTLS_LIBRARIES})
target_link_libraries(ftp ${GNUTLS_LIBRARIES})
# Install the library
diff --git a/methods/connect.cc b/methods/connect.cc
index 1d6f8919d..0e01e5ca4 100644
--- a/methods/connect.cc
+++ b/methods/connect.cc
@@ -273,8 +273,8 @@ static ResultState WaitAndCheckErrors(std::list<Connection> &Conns, std::unique_
struct timeval tv = {
// Split our millisecond timeout into seconds and microseconds
- .tv_sec = TimeoutMsec / 1000,
- .tv_usec = (TimeoutMsec % 1000) * 1000,
+ .tv_sec = static_cast<time_t>(TimeoutMsec / 1000),
+ .tv_usec = static_cast<suseconds_t>((TimeoutMsec % 1000) * 1000),
};
// We will return once we have no more connections, a time out, or
diff --git a/methods/gpgv.cc b/methods/gpgv.cc
index f66e3356f..91417f308 100644
--- a/methods/gpgv.cc
+++ b/methods/gpgv.cc
@@ -68,7 +68,7 @@ struct Digest {
static constexpr Digest Digests[] = {
{Digest::State::Untrusted, "Invalid digest"},
{Digest::State::Untrusted, "MD5"},
- {Digest::State::Untrusted, "SHA1"},
+ {Digest::State::Trusted, "SHA1"},
{Digest::State::Untrusted, "RIPE-MD/160"},
{Digest::State::Trusted, "Reserved digest"},
{Digest::State::Trusted, "Reserved digest"},
diff --git a/methods/http.cc b/methods/http.cc
index d75e9fe84..ab62ee20c 100644
--- a/methods/http.cc
+++ b/methods/http.cc
@@ -16,7 +16,7 @@
##################################################################### */
/*}}}*/
// Include Files /*{{{*/
-#include <config.h>
+// #include <config.h>
#include <apt-pkg/configuration.h>
#include <apt-pkg/error.h>
@@ -35,7 +35,9 @@
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
+#include <sys/fcntl.h>
#include <sys/select.h>
+#include <sys/sysctl.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <unistd.h>
@@ -44,998 +46,592 @@
#include "connect.h"
#include "http.h"
-#include <apti18n.h>
+#include <netdb.h>
+#include <dlfcn.h>
+#include <lockdown.h>
+#include <CoreFoundation/CoreFoundation.h>
+#include <CFNetwork/CFNetwork.h>
+#include <TargetConditionals.h>
+
+extern "C" CFDictionaryRef SCDynamicStoreCopyProxies(void *);
/*}}}*/
using namespace std;
-unsigned long long CircleBuf::BwReadLimit=0;
-unsigned long long CircleBuf::BwTickReadData=0;
-std::chrono::steady_clock::duration CircleBuf::BwReadTick{0};
-const unsigned int CircleBuf::BW_HZ=10;
-
-// CircleBuf::CircleBuf - Circular input buffer /*{{{*/
-// ---------------------------------------------------------------------
-/* */
-CircleBuf::CircleBuf(HttpMethod const * const Owner, unsigned long long Size)
- : Size(Size), Hash(NULL), TotalWriten(0)
-{
- Buf = new unsigned char[Size];
- Reset();
-
- CircleBuf::BwReadLimit = Owner->ConfigFindI("Dl-Limit", 0) * 1024;
-}
- /*}}}*/
-// CircleBuf::Reset - Reset to the default state /*{{{*/
-// ---------------------------------------------------------------------
-/* */
-void CircleBuf::Reset()
-{
- InP = 0;
- OutP = 0;
- StrPos = 0;
- TotalWriten = 0;
- MaxGet = (unsigned long long)-1;
- OutQueue = string();
- if (Hash != NULL)
- {
- delete Hash;
- Hash = NULL;
+#define _(str) str
+
+CFStringRef Firmware_ = NULL;
+CFStringRef Product_ = NULL;
+CFStringRef Arch_ = NULL;
+const char *Machine_ = NULL;
+CFStringRef UniqueID_ = NULL;
+CFStringRef UserAgent_ = NULL;
+
+void CfrsError(const char *name, CFReadStreamRef rs) {
+ CFStreamError se = CFReadStreamGetError(rs);
+
+ if (se.domain == kCFStreamErrorDomainCustom) {
+ } else if (se.domain == kCFStreamErrorDomainPOSIX) {
+ _error->Error("POSIX: %s", strerror(se.error));
+ } else if (se.domain == kCFStreamErrorDomainMacOSStatus) {
+ _error->Error("MacOSStatus: %d", (int)se.error);
+ } else if (se.domain == kCFStreamErrorDomainNetDB) {
+ _error->Error("NetDB: %s %s", name, gai_strerror(se.error));
+ } else if (se.domain == kCFStreamErrorDomainMach) {
+ _error->Error("Mach: %d", (int)se.error);
+ } else if (se.domain == kCFStreamErrorDomainHTTP) {
+ switch (se.error) {
+ case kCFStreamErrorHTTPParseFailure:
+ _error->Error("Parse failure");
+ break;
+
+ case kCFStreamErrorHTTPRedirectionLoop:
+ _error->Error("Redirection loop");
+ break;
+
+ case kCFStreamErrorHTTPBadURL:
+ _error->Error("Bad URL");
+ break;
+
+ default:
+ _error->Error("Unknown HTTP error: %d", (int)se.error);
+ break;
+ }
+ } else if (se.domain == kCFStreamErrorDomainSOCKS) {
+ _error->Error("SOCKS: %d", (int)se.error);
+ } else if (se.domain == kCFStreamErrorDomainSystemConfiguration) {
+ _error->Error("SystemConfiguration: %d", (int)se.error);
+ } else if (se.domain == kCFStreamErrorDomainSSL) {
+ _error->Error("SSL: %d", (int)se.error);
+ } else {
+ _error->Error("Domain #%d: %d", (int)se.domain, (int)se.error);
}
}
- /*}}}*/
-// CircleBuf::Read - Read from a FD into the circular buffer /*{{{*/
-// ---------------------------------------------------------------------
-/* This fills up the buffer with as much data as is in the FD, assuming it
- is non-blocking.. */
-bool CircleBuf::Read(std::unique_ptr<MethodFd> const &Fd)
-{
- while (1)
- {
- // Woops, buffer is full
- if (InP - OutP == Size)
- return true;
-
- // what's left to read in this tick
- unsigned long long const BwReadMax = CircleBuf::BwReadLimit/BW_HZ;
-
- if(CircleBuf::BwReadLimit) {
- auto const now = std::chrono::steady_clock::now().time_since_epoch();
- auto const d = now - CircleBuf::BwReadTick;
-
- auto const tickLen = std::chrono::microseconds(std::chrono::seconds(1)) / BW_HZ;
- if(d > tickLen) {
- CircleBuf::BwReadTick = now;
- CircleBuf::BwTickReadData = 0;
- }
-
- if(CircleBuf::BwTickReadData >= BwReadMax) {
- usleep(tickLen.count());
- return true;
- }
- }
- // Write the buffer segment
- ssize_t Res;
- if(CircleBuf::BwReadLimit) {
- Res = Fd->Read(Buf + (InP % Size),
- BwReadMax > LeftRead() ? LeftRead() : BwReadMax);
- } else
- Res = Fd->Read(Buf + (InP % Size), LeftRead());
+unsigned long TimeOut = 120;
- if(Res > 0 && BwReadLimit > 0)
- CircleBuf::BwTickReadData += Res;
-
- if (Res == 0)
- return false;
- if (Res < 0)
- {
- if (errno == EAGAIN)
- return true;
- return false;
- }
+static const CFOptionFlags kNetworkEvents =
+ kCFStreamEventOpenCompleted |
+ kCFStreamEventHasBytesAvailable |
+ kCFStreamEventEndEncountered |
+ kCFStreamEventErrorOccurred |
+0;
- InP += Res;
- }
-}
- /*}}}*/
-// CircleBuf::Read - Put the string into the buffer /*{{{*/
-// ---------------------------------------------------------------------
-/* This will hold the string in and fill the buffer with it as it empties */
-bool CircleBuf::Read(string const &Data)
-{
- OutQueue.append(Data);
- FillOut();
- return true;
-}
- /*}}}*/
-// CircleBuf::FillOut - Fill the buffer from the output queue /*{{{*/
-// ---------------------------------------------------------------------
-/* */
-void CircleBuf::FillOut()
-{
- if (OutQueue.empty() == true)
- return;
- while (1)
- {
- // Woops, buffer is full
- if (InP - OutP == Size)
- return;
-
- // Write the buffer segment
- unsigned long long Sz = LeftRead();
- if (OutQueue.length() - StrPos < Sz)
- Sz = OutQueue.length() - StrPos;
- memcpy(Buf + (InP%Size),OutQueue.c_str() + StrPos,Sz);
-
- // Advance
- StrPos += Sz;
- InP += Sz;
- if (OutQueue.length() == StrPos)
- {
- StrPos = 0;
- OutQueue = "";
- return;
- }
+static void CFReadStreamCallback(CFReadStreamRef stream, CFStreamEventType event, void *arg) {
+ switch (event) {
+ case kCFStreamEventOpenCompleted:
+ break;
+
+ case kCFStreamEventHasBytesAvailable:
+ case kCFStreamEventEndEncountered:
+ *reinterpret_cast<int *>(arg) = 1;
+ CFRunLoopStop(CFRunLoopGetCurrent());
+ break;
+
+ case kCFStreamEventErrorOccurred:
+ *reinterpret_cast<int *>(arg) = -1;
+ CFRunLoopStop(CFRunLoopGetCurrent());
+ break;
}
}
- /*}}}*/
-// CircleBuf::Write - Write from the buffer into a FD /*{{{*/
-// ---------------------------------------------------------------------
-/* This empties the buffer into the FD. */
-bool CircleBuf::Write(std::unique_ptr<MethodFd> const &Fd)
-{
- while (1)
- {
- FillOut();
-
- // Woops, buffer is empty
- if (OutP == InP)
- return true;
-
- if (OutP == MaxGet)
- return true;
-
- // Write the buffer segment
- ssize_t Res;
- Res = Fd->Write(Buf + (OutP % Size), LeftWrite());
- if (Res == 0)
- return false;
- if (Res < 0)
- {
- if (errno == EAGAIN)
- return true;
-
- return false;
- }
+/* http://lists.apple.com/archives/Macnetworkprog/2006/Apr/msg00014.html */
+int CFReadStreamOpen(CFReadStreamRef stream, double timeout) {
+ CFStreamClientContext context;
+ int value(0);
- TotalWriten += Res;
-
- if (Hash != NULL)
- Hash->Add(Buf + (OutP%Size),Res);
-
- OutP += Res;
+ memset(&context, 0, sizeof(context));
+ context.info = &value;
+
+ if (CFReadStreamSetClient(stream, kNetworkEvents, CFReadStreamCallback, &context)) {
+ CFReadStreamScheduleWithRunLoop(stream, CFRunLoopGetCurrent(), kCFRunLoopCommonModes);
+ if (CFReadStreamOpen(stream))
+ CFRunLoopRunInMode(kCFRunLoopDefaultMode, timeout, false);
+ else
+ value = -1;
+ CFReadStreamSetClient(stream, kCFStreamEventNone, NULL, NULL);
}
+
+ return value;
}
- /*}}}*/
-// CircleBuf::WriteTillEl - Write from the buffer to a string /*{{{*/
+
+// HttpMethod::SendReq - Send the HTTP request /*{{{*/
// ---------------------------------------------------------------------
-/* This copies till the first empty line */
-bool CircleBuf::WriteTillEl(string &Data,bool Single)
+/* This places the http request in the outbound buffer */
+void HttpMethod::SendReq(FetchItem *Itm)
{
- // We cheat and assume it is unneeded to have more than one buffer load
- for (unsigned long long I = OutP; I < InP; I++)
- {
- if (Buf[I%Size] != '\n')
- continue;
- ++I;
-
- if (Single == false)
- {
- if (I < InP && Buf[I%Size] == '\r')
- ++I;
- if (I >= InP || Buf[I%Size] != '\n')
- continue;
- ++I;
- }
-
- Data = "";
- while (OutP < I)
- {
- unsigned long long Sz = LeftWrite();
- if (Sz == 0)
- return false;
- if (I - OutP < Sz)
- Sz = I - OutP;
- Data += string((char *)(Buf + (OutP%Size)),Sz);
- OutP += Sz;
- }
- return true;
- }
- return false;
}
/*}}}*/
-// CircleBuf::Write - Write from the buffer to a string /*{{{*/
-// ---------------------------------------------------------------------
-/* This copies everything */
-bool CircleBuf::Write(string &Data)
+std::unique_ptr<ServerState> HttpMethod::CreateServerState(URI const &uri)/*{{{*/
{
- Data = std::string((char *)Buf + (OutP % Size), LeftWrite());
- OutP += LeftWrite();
- return true;
+ return NULL;
}
/*}}}*/
-CircleBuf::~CircleBuf() /*{{{*/
+void HttpMethod::RotateDNS() /*{{{*/
{
- delete [] Buf;
- delete Hash;
}
- /*}}}*/
-// UnwrapHTTPConnect - Does the HTTP CONNECT handshake /*{{{*/
-// ---------------------------------------------------------------------
-/* Performs a TLS handshake on the socket */
-struct HttpConnectFd : public MethodFd
-{
- std::unique_ptr<MethodFd> UnderlyingFd;
- std::string Buffer;
-
- int Fd() APT_OVERRIDE { return UnderlyingFd->Fd(); }
-
- ssize_t Read(void *buf, size_t count) APT_OVERRIDE
- {
- if (!Buffer.empty())
- {
- auto read = count < Buffer.size() ? count : Buffer.size();
+#if TARGET_OS_TV
+char * createCookie() {
+ FILE *fp;
+ long lSize;
+ char *buffer;
+ const char *tp = "/var/mobile/Documents/nitoStoreToken";
+ if (access(tp, R_OK)) return NULL;
+ fp = fopen ( tp , "rb" );
+ if( !fp ) {
+ perror(tp);
+ return NULL;
+ }
+ fseek( fp , 0L , SEEK_END);
+ lSize = ftell( fp );
+ rewind( fp );
+
+ /* allocate memory for entire content */
+ buffer = static_cast<char*>(calloc( 1, lSize+1 ));
+ if( !buffer ) {
+ fclose(fp);
+ return NULL;
+ }
+
+ /* copy the file into the buffer */
+ if( 1!=fread( buffer , lSize, 1 , fp) )
+ {
+ fclose(fp);
+ free(buffer);
+ return NULL;
+ }
+ /* do your work here, buffer is a string contains the whole text */
+
+ fclose(fp);
+
+ return buffer;
+}
+#endif
- memcpy(buf, Buffer.data(), read);
- Buffer.erase(Buffer.begin(), Buffer.begin() + read);
- return read;
- }
+ /*}}}*/
+BaseHttpMethod::DealWithHeadersResult HttpMethod::DealWithHeaders(FetchResult &Res, RequestState &Req)/*{{{*/
+{
+ auto ret = BaseHttpMethod::DealWithHeaders(Res, Req);
+ if (ret != BaseHttpMethod::FILE_IS_OPEN)
+ return ret;
+ if (Req.File.Open(Queue->DestFile, FileFd::WriteAny) == false)
+ return ERROR_NOT_FROM_SERVER;
- return UnderlyingFd->Read(buf, count);
- }
- ssize_t Write(void *buf, size_t count) APT_OVERRIDE
- {
- return UnderlyingFd->Write(buf, count);
- }
+ FailFile = Queue->DestFile;
+ FailFile.c_str(); // Make sure we don't do a malloc in the signal handler
+ FailFd = Req.File.Fd();
+ FailTime = Req.Date;
- int Close() APT_OVERRIDE
+ if (Server->InitHashes(Queue->ExpectedHashes) == false || Req.AddPartialFileToHashes(Req.File) == false)
{
- return UnderlyingFd->Close();
+ _error->Errno("read",_("Problem hashing file"));
+ return ERROR_NOT_FROM_SERVER;
}
+ if (Req.StartPos > 0)
+ Res.ResumePoint = Req.StartPos;
- bool HasPending() APT_OVERRIDE
- {
- return !Buffer.empty();
- }
-};
+ SetNonBlock(Req.File.Fd(),true);
+ return FILE_IS_OPEN;
+}
-static ResultState UnwrapHTTPConnect(std::string Host, int Port, URI Proxy, std::unique_ptr<MethodFd> &Fd,
- unsigned long Timeout, aptAuthConfMethod *Owner)
+// HttpMethod::Loop - Main loop /*{{{*/
+int HttpMethod::Loop()
{
- Owner->Status(_("Connecting to %s (%s)"), "HTTP proxy", URI::SiteOnly(Proxy).c_str());
- // The HTTP server expects a hostname with a trailing :port
- std::stringstream Req;
- std::string ProperHost;
-
- if (Host.find(':') != std::string::npos)
- ProperHost = '[' + Proxy.Host + ']';
- else
- ProperHost = Proxy.Host;
-
- // Build the connect
- Req << "CONNECT " << Host << ":" << std::to_string(Port) << " HTTP/1.1\r\n";
- if (Proxy.Port != 0)
- Req << "Host: " << ProperHost << ":" << std::to_string(Proxy.Port) << "\r\n";
- else
- Req << "Host: " << ProperHost << "\r\n";
-
- Owner->MaybeAddAuthTo(Proxy);
- if (Proxy.User.empty() == false || Proxy.Password.empty() == false)
- Req << "Proxy-Authorization: Basic "
- << Base64Encode(Proxy.User + ":" + Proxy.Password) << "\r\n";
-
- Req << "User-Agent: " << Owner->ConfigFind("User-Agent", "Debian APT-HTTP/1.3 (" PACKAGE_VERSION ")") << "\r\n";
-
- Req << "\r\n";
-
- CircleBuf In(dynamic_cast<HttpMethod *>(Owner), 4096);
- CircleBuf Out(dynamic_cast<HttpMethod *>(Owner), 4096);
- std::string Headers;
-
- if (Owner->DebugEnabled() == true)
- cerr << Req.str() << endl;
- Out.Read(Req.str());
-
- // Writing from proxy
- while (Out.WriteSpace() > 0)
- {
- if (WaitFd(Fd->Fd(), true, Timeout) == false)
- {
- _error->Errno("select", "Writing to proxy failed");
- return ResultState::TRANSIENT_ERROR;
- }
- if (Out.Write(Fd) == false)
- {
- _error->Errno("write", "Writing to proxy failed");
- return ResultState::TRANSIENT_ERROR;
- }
- }
+ signal(SIGTERM,SigTerm);
+ signal(SIGINT,SigTerm);
+
+ Server = 0;
- while (In.ReadSpace() > 0)
- {
- if (WaitFd(Fd->Fd(), false, Timeout) == false)
+ std::set<std::string> cached;
+
+ int FailCounter = 0;
+ while (1)
+ {
+ // We have no commands, wait for some to arrive
+ if (Queue == 0)
{
- _error->Errno("select", "Reading from proxy failed");
- return ResultState::TRANSIENT_ERROR;
+ if (WaitFd(STDIN_FILENO) == false)
+ return 0;
}
- if (In.Read(Fd) == false)
+
+ /* Run messages, we can accept 0 (no message) if we didn't
+ do a WaitFd above.. Otherwise the FD is closed. */
+ int Result = Run(true);
+ if (Result != -1 && (Result != 0 || Queue == 0))
{
- _error->Errno("read", "Reading from proxy failed");
- return ResultState::TRANSIENT_ERROR;
+ if(FailReason.empty() == false ||
+ ConfigFindB("DependOnSTDIN", true) == true)
+ return 100;
+ else
+ return 0;
}
- if (In.WriteTillEl(Headers))
- break;
- }
-
- if (Owner->DebugEnabled() == true)
- cerr << Headers << endl;
-
- if (!(APT::String::Startswith(Headers, "HTTP/1.0 200") || APT::String::Startswith(Headers, "HTTP/1.1 200")))
- {
- _error->Error("Invalid response from proxy: %s", Headers.c_str());
- return ResultState::TRANSIENT_ERROR;
- }
-
- if (In.WriteSpace() > 0)
- {
- // Maybe there is actual data already read, if so we need to buffer it
- std::unique_ptr<HttpConnectFd> NewFd(new HttpConnectFd());
- In.Write(NewFd->Buffer);
- NewFd->UnderlyingFd = std::move(Fd);
- Fd = std::move(NewFd);
- }
+ if (Queue == 0)
+ continue;
- return ResultState::SUCCESSFUL;
-}
- /*}}}*/
+ CFStringEncoding se = kCFStringEncodingUTF8;
-// HttpServerState::HttpServerState - Constructor /*{{{*/
-HttpServerState::HttpServerState(URI Srv,HttpMethod *Owner) : ServerState(Srv, Owner), In(Owner, 64*1024), Out(Owner, 4*1024)
-{
- TimeOut = Owner->ConfigFindI("Timeout", TimeOut);
- ServerFd = MethodFd::FromFd(-1);
- Reset();
-}
- /*}}}*/
-// HttpServerState::Open - Open a connection to the server /*{{{*/
-// ---------------------------------------------------------------------
-/* This opens a connection to the server. */
-ResultState HttpServerState::Open()
-{
- // Use the already open connection if possible.
- if (ServerFd->Fd() != -1)
- return ResultState::SUCCESSFUL;
-
- Close();
- In.Reset();
- Out.Reset();
- Persistent = true;
-
- bool tls = (ServerName.Access == "https" || APT::String::Endswith(ServerName.Access, "+https"));
-
- // Determine the proxy setting
- // Used to run AutoDetectProxy(ServerName) here, but we now send a Proxy
- // header in the URI Acquire request and set "Acquire::"+uri.Access+"::proxy::"+uri.Host
- // to it in BaseHttpMethod::Loop()
- string SpecificProxy = Owner->ConfigFind("Proxy::" + ServerName.Host, "");
- if (!SpecificProxy.empty())
- {
- if (SpecificProxy == "DIRECT")
- Proxy = "";
- else
- Proxy = SpecificProxy;
- }
- else
- {
- string DefProxy = Owner->ConfigFind("Proxy", "");
- if (!DefProxy.empty())
- {
- Proxy = DefProxy;
- }
- else
- {
- char *result = getenv("http_proxy");
- Proxy = result ? result : "";
- if (tls == true)
- {
- char *result = getenv("https_proxy");
- if (result != nullptr)
- {
- Proxy = result;
- }
- }
- }
- }
-
- // Parse no_proxy, a , separated list of domains
- if (getenv("no_proxy") != 0)
- {
- if (CheckDomainList(ServerName.Host,getenv("no_proxy")) == true)
- Proxy = "";
- }
+ URI uri2 = Queue->Uri;
+ string uriString = static_cast<string>(uri2);
+
+ char *url = strdup(uriString.c_str());
+ url:
+ URI uri = std::string(url);
+ std::string hs = uri.Host;
+
+ if (cached.find(hs) != cached.end()) {
+ _error->Error("Cached Failure");
+ Fail(true);
+ free(url);
+ FailCounter = 0;
+ continue;
+ }
- if (Proxy.empty() == false)
- Owner->AddProxyAuth(Proxy, ServerName);
+ std::string urs = uri;
- auto const DefaultService = tls ? "https" : "http";
- auto const DefaultPort = tls ? 443 : 80;
- if (Proxy.Access == "socks5h")
- {
- auto result = Connect(Proxy.Host, Proxy.Port, "socks", 1080, ServerFd, TimeOut, Owner);
- if (result != ResultState::SUCCESSFUL)
- return result;
-
- result = UnwrapSocks(ServerName.Host, ServerName.Port == 0 ? DefaultPort : ServerName.Port,
- Proxy, ServerFd, Owner->ConfigFindI("TimeOut", 30), Owner);
- if (result != ResultState::SUCCESSFUL)
- return result;
- }
- else
- {
- // Determine what host and port to use based on the proxy settings
- int Port = 0;
- string Host;
- if (Proxy.empty() == true || Proxy.Host.empty() == true)
- {
- if (ServerName.Port != 0)
- Port = ServerName.Port;
- Host = ServerName.Host;
- }
- else if (Proxy.Access != "http" && Proxy.Access != "https")
- {
- _error->Error("Unsupported proxy configured: %s", URI::SiteOnly(Proxy).c_str());
- return ResultState::FATAL_ERROR;
+ for (;;) {
+ size_t bad = urs.find_first_of("+");
+ if (bad == std::string::npos)
+ break;
+ // XXX: generalize
+ urs = urs.substr(0, bad) + "%2b" + urs.substr(bad + 1);
}
- else
- {
- if (Proxy.Port != 0)
- Port = Proxy.Port;
- Host = Proxy.Host;
- if (Proxy.Access == "https" && Port == 0)
- Port = 443;
+ CFStringRef sr = CFStringCreateWithCString(kCFAllocatorDefault, urs.c_str(), se);
+#if TARGET_OS_TV
+ bool isNito = false;
+ if (sr) {
+ CFStringRef nitoBaseURL = CFSTR("https://nito.tv/");
+ size_t nitoURLLength = CFStringGetLength(nitoBaseURL);
+ size_t srLength = CFStringGetLength(sr);
+ if (srLength >= nitoURLLength && CFStringCompareWithOptions(sr, nitoBaseURL, CFRangeMake(0, nitoURLLength), kCFCompareCaseInsensitive) == kCFCompareEqualTo) {
+ isNito = true;
+ // NitoTV's webserver is broken... hack around it
+ CFRange range = CFRangeMake(0, CFStringGetLength(CFSTR("https://nito.tv/repo/./")));
+ if (CFStringCompareWithOptions(sr, CFSTR("https://nito.tv/repo/./"), range, kCFCompareCaseInsensitive) == kCFCompareEqualTo) {
+ range = CFRangeMake(CFStringGetLength(CFSTR("https://nito.tv/repo/./")), CFStringGetLength(sr) - CFStringGetLength(CFSTR("https://nito.tv/repo/./")));
+ if (range.length>0) {
+ CFStringRef subsr = CFStringCreateWithSubstring(NULL, sr, range);
+ CFStringRef newsr = CFStringCreateWithFormat(NULL, NULL, CFSTR("https://nito.tv/repo/%@"), subsr);
+ CFRelease(subsr);
+ CFRelease(sr);
+ sr = newsr;
+ }
+ }
+ }
}
- auto result = Connect(Host, Port, DefaultService, DefaultPort, ServerFd, TimeOut, Owner);
- if (result != ResultState::SUCCESSFUL)
- return result;
- if (Host == Proxy.Host && Proxy.Access == "https")
- {
- result = UnwrapTLS(Proxy.Host, ServerFd, TimeOut, Owner);
- if (result != ResultState::SUCCESSFUL)
- return result;
- }
- if (Host == Proxy.Host && tls)
- {
- result = UnwrapHTTPConnect(ServerName.Host, ServerName.Port == 0 ? DefaultPort : ServerName.Port, Proxy, ServerFd, Owner->ConfigFindI("TimeOut", 30), Owner);
- if (result != ResultState::SUCCESSFUL)
- return result;
+#endif
+ CFURLRef ur = CFURLCreateWithString(kCFAllocatorDefault, sr, NULL);
+ CFRelease(sr);
+ CFHTTPMessageRef hm = CFHTTPMessageCreateRequest(kCFAllocatorDefault, CFSTR("GET"), ur, kCFHTTPVersion1_1);
+ CFRelease(ur);
+
+ struct stat SBuf;
+ if (stat(Queue->DestFile.c_str(), &SBuf) >= 0 && SBuf.st_size > 0) {
+ sr = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("bytes=%li-"), (long) SBuf.st_size - 1);
+ CFHTTPMessageSetHeaderFieldValue(hm, CFSTR("Range"), sr);
+ CFRelease(sr);
+
+ sr = CFStringCreateWithCString(kCFAllocatorDefault, TimeRFC1123(SBuf.st_mtime, false).c_str(), se);
+ CFHTTPMessageSetHeaderFieldValue(hm, CFSTR("If-Range"), sr);
+ CFRelease(sr);
+
+ CFHTTPMessageSetHeaderFieldValue(hm, CFSTR("Cache-Control"), CFSTR("no-cache"));
+ } else if (Queue->LastModified != 0) {
+ sr = CFStringCreateWithCString(kCFAllocatorDefault, TimeRFC1123(Queue->LastModified, true).c_str(), se);
+ CFHTTPMessageSetHeaderFieldValue(hm, CFSTR("If-Modified-Since"), sr);
+ CFRelease(sr);
+
+ CFHTTPMessageSetHeaderFieldValue(hm, CFSTR("Cache-Control"), CFSTR("no-cache"));
+ } else
+ CFHTTPMessageSetHeaderFieldValue(hm, CFSTR("Cache-Control"), CFSTR("max-age=0"));
+
+ if (Firmware_ != NULL)
+ CFHTTPMessageSetHeaderFieldValue(hm, CFSTR("X-Firmware"), Firmware_);
+
+ sr = CFStringCreateWithCString(kCFAllocatorDefault, Machine_, se);
+ CFHTTPMessageSetHeaderFieldValue(hm, CFSTR("X-Machine"), sr);
+ CFRelease(sr);
+
+ if (UniqueID_ != NULL)
+ CFHTTPMessageSetHeaderFieldValue(hm, CFSTR("X-Unique-ID"), UniqueID_);
+
+ CFHTTPMessageSetHeaderFieldValue(hm, CFSTR("User-Agent"), UserAgent_);
+
+#if TARGET_OS_TV
+ if (isNito) {
+ char *cookie = createCookie();
+ if (cookie) {
+ size_t cookie_len = strlen(cookie);
+ CFStringRef cookieString = CFStringCreateWithBytesNoCopy(kCFAllocatorDefault, (unsigned char *)cookie, cookie_len, kCFStringEncodingUTF8, false, kCFAllocatorDefault);
+ if (cookieString) {
+ CFHTTPMessageSetHeaderFieldValue(hm, CFSTR("Cookie"), cookieString);
+ CFRelease(cookieString);
+ }
+ }
}
- }
+#endif
- if (tls)
- return UnwrapTLS(ServerName.Host, ServerFd, TimeOut, Owner);
+ CFReadStreamRef rs = CFReadStreamCreateForHTTPRequest(kCFAllocatorDefault, hm);
+ CFRelease(hm);
- return ResultState::SUCCESSFUL;
-}
- /*}}}*/
-// HttpServerState::Close - Close a connection to the server /*{{{*/
-// ---------------------------------------------------------------------
-/* */
-bool HttpServerState::Close()
-{
- ServerFd->Close();
- return true;
-}
- /*}}}*/
-// HttpServerState::RunData - Transfer the data from the socket /*{{{*/
-ResultState HttpServerState::RunData(RequestState &Req)
-{
- Req.State = RequestState::Data;
-
- // Chunked transfer encoding is fun..
- if (Req.Encoding == RequestState::Chunked)
- {
- while (1)
- {
- // Grab the block size
- ResultState Last = ResultState::SUCCESSFUL;
- string Data;
- In.Limit(-1);
- do
- {
- if (In.WriteTillEl(Data,true) == true)
- break;
- } while ((Last = Go(false, Req)) == ResultState::SUCCESSFUL);
-
- if (Last != ResultState::SUCCESSFUL)
- return Last;
-
- // See if we are done
- unsigned long long Len = strtoull(Data.c_str(),0,16);
- if (Len == 0)
- {
- In.Limit(-1);
-
- // We have to remove the entity trailer
- Last = ResultState::SUCCESSFUL;
- do
- {
- if (In.WriteTillEl(Data,true) == true && Data.length() <= 2)
- break;
- } while ((Last = Go(false, Req)) == ResultState::SUCCESSFUL);
- return Last;
- }
-
- // Transfer the block
- In.Limit(Len);
- while (Go(true, Req) == ResultState::SUCCESSFUL)
- if (In.IsLimit() == true)
- break;
-
- // Error
- if (In.IsLimit() == false)
- return ResultState::TRANSIENT_ERROR;
-
- // The server sends an extra new line before the next block specifier..
- In.Limit(-1);
- Last = ResultState::SUCCESSFUL;
- do
- {
- if (In.WriteTillEl(Data,true) == true)
- break;
- } while ((Last = Go(false, Req)) == ResultState::SUCCESSFUL);
- if (Last != ResultState::SUCCESSFUL)
- return Last;
- }
- }
- else
- {
- /* Closes encoding is used when the server did not specify a size, the
- loss of the connection means we are done */
- if (Req.JunkSize != 0)
- In.Limit(Req.JunkSize);
- else if (Req.DownloadSize != 0)
- {
- if (Req.MaximumSize != 0 && Req.DownloadSize > Req.MaximumSize)
- {
- Owner->SetFailReason("MaximumSizeExceeded");
- _error->Error(_("File has unexpected size (%llu != %llu). Mirror sync in progress?"),
- Req.DownloadSize, Req.MaximumSize);
- return ResultState::FATAL_ERROR;
- }
- In.Limit(Req.DownloadSize);
- }
- else if (Persistent == false)
- In.Limit(-1);
+#define _kCFStreamPropertyReadTimeout CFSTR("_kCFStreamPropertyReadTimeout")
+#define _kCFStreamPropertyWriteTimeout CFSTR("_kCFStreamPropertyWriteTimeout")
+#define _kCFStreamPropertySocketImmediateBufferTimeOut CFSTR("_kCFStreamPropertySocketImmediateBufferTimeOut")
- // Just transfer the whole block.
- while (true)
- {
- if (In.IsLimit() == false)
- {
- auto const result = Go(true, Req);
- if (result == ResultState::SUCCESSFUL)
- continue;
- return result;
- }
-
- In.Limit(-1);
- return _error->PendingError() ? ResultState::FATAL_ERROR : ResultState::SUCCESSFUL;
- }
- }
+ /*SInt32 to(TimeOut);
+ CFNumberRef nm(CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &to));os_log(OS_LOG_DEFAULT, "[%{public}s:%{public}d]",__BASE_FILE__,__LINE__);*/
+ double to = TimeOut;
+ CFNumberRef nm(CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, &to));
- if (Flush(&Req.File) == false)
- return ResultState::TRANSIENT_ERROR;
- return ResultState::SUCCESSFUL;
-}
- /*}}}*/
-ResultState HttpServerState::RunDataToDevNull(RequestState &Req) /*{{{*/
-{
- // no need to clean up if we discard the connection anyhow
- if (Persistent == false)
- return ResultState::SUCCESSFUL;
- Req.File.Open("/dev/null", FileFd::WriteOnly);
- return RunData(Req);
-}
- /*}}}*/
-bool HttpServerState::ReadHeaderLines(std::string &Data) /*{{{*/
-{
- return In.WriteTillEl(Data);
-}
- /*}}}*/
-ResultState HttpServerState::LoadNextResponse(bool const ToFile, RequestState &Req) /*{{{*/
-{
- return Go(ToFile, Req);
-}
- /*}}}*/
-bool HttpServerState::WriteResponse(const std::string &Data) /*{{{*/
-{
- return Out.Read(Data);
-}
- /*}}}*/
-APT_PURE bool HttpServerState::IsOpen() /*{{{*/
-{
- return (ServerFd->Fd() != -1);
-}
- /*}}}*/
-bool HttpServerState::InitHashes(HashStringList const &ExpectedHashes) /*{{{*/
-{
- delete In.Hash;
- In.Hash = new Hashes(ExpectedHashes);
- return true;
-}
- /*}}}*/
-void HttpServerState::Reset() /*{{{*/
-{
- ServerState::Reset();
- ServerFd->Close();
-}
- /*}}}*/
+ CFReadStreamSetProperty(rs, _kCFStreamPropertyReadTimeout, nm);
+ CFReadStreamSetProperty(rs, _kCFStreamPropertyWriteTimeout, nm);
+ CFReadStreamSetProperty(rs, _kCFStreamPropertySocketImmediateBufferTimeOut, nm);
+ CFRelease(nm);
-APT_PURE Hashes * HttpServerState::GetHashes() /*{{{*/
-{
- return In.Hash;
-}
- /*}}}*/
-// HttpServerState::Die - The server has closed the connection. /*{{{*/
-ResultState HttpServerState::Die(RequestState &Req)
-{
- unsigned int LErrno = errno;
+ CFDictionaryRef dr = SCDynamicStoreCopyProxies(NULL);
+ CFReadStreamSetProperty(rs, kCFStreamPropertyHTTPProxy, dr);
+ CFRelease(dr);
- // Dump the buffer to the file
- if (Req.State == RequestState::Data)
- {
- if (Req.File.IsOpen() == false)
- return ResultState::SUCCESSFUL;
- // on GNU/kFreeBSD, apt dies on /dev/null because non-blocking
- // can't be set
- if (Req.File.Name() != "/dev/null")
- SetNonBlock(Req.File.Fd(),false);
- while (In.WriteSpace() == true)
- {
- if (In.Write(MethodFd::FromFd(Req.File.Fd())) == false)
- {
- _error->Errno("write", _("Error writing to the file"));
- return ResultState::TRANSIENT_ERROR;
- }
-
- // Done
- if (In.IsLimit() == true)
- return ResultState::SUCCESSFUL;
- }
- }
+ //CFReadStreamSetProperty(rs, kCFStreamPropertyHTTPShouldAutoredirect, kCFBooleanTrue);
+ CFReadStreamSetProperty(rs, kCFStreamPropertyHTTPAttemptPersistentConnection, kCFBooleanTrue);
- // See if this is because the server finished the data stream
- if (In.IsLimit() == false && Req.State != RequestState::Header &&
- Persistent == true)
- {
- Close();
- if (LErrno == 0)
- {
- _error->Error(_("Error reading from server. Remote end closed connection"));
- return ResultState::TRANSIENT_ERROR;
- }
- errno = LErrno;
- _error->Errno("read", _("Error reading from server"));
- return ResultState::TRANSIENT_ERROR;
- }
- else
- {
- In.Limit(-1);
+ FetchResult Res;
+ CFIndex rd;
+ UInt32 sc;
- // Nothing left in the buffer
- if (In.WriteSpace() == false)
- return ResultState::TRANSIENT_ERROR;
+ uint8_t data[10240];
+ size_t offset = 0;
- // We may have got multiple responses back in one packet..
- Close();
- return ResultState::SUCCESSFUL;
- }
+ Status("Connecting to %s", hs.c_str());
- return ResultState::TRANSIENT_ERROR;
-}
- /*}}}*/
-// HttpServerState::Flush - Dump the buffer into the file /*{{{*/
-// ---------------------------------------------------------------------
-/* This takes the current input buffer from the Server FD and writes it
- into the file */
-bool HttpServerState::Flush(FileFd * const File)
-{
- if (File != nullptr)
- {
- // on GNU/kFreeBSD, apt dies on /dev/null because non-blocking
- // can't be set
- if (File->Name() != "/dev/null")
- SetNonBlock(File->Fd(),false);
- if (In.WriteSpace() == false)
- return true;
-
- while (In.WriteSpace() == true)
- {
- if (In.Write(MethodFd::FromFd(File->Fd())) == false)
- return _error->Errno("write",_("Error writing to file"));
- if (In.IsLimit() == true)
- return true;
- }
+ switch (CFReadStreamOpen(rs, to)) {
+ case -1:
+ CfrsError("Open", rs);
+ goto fail;
- if (In.IsLimit() == true || Persistent == false)
- return true;
- }
- return false;
-}
- /*}}}*/
-// HttpServerState::Go - Run a single loop /*{{{*/
-// ---------------------------------------------------------------------
-/* This runs the select loop over the server FDs, Output file FDs and
- stdin. */
-ResultState HttpServerState::Go(bool ToFile, RequestState &Req)
-{
- // Server has closed the connection
- if (ServerFd->Fd() == -1 && (In.WriteSpace() == false ||
- ToFile == false))
- return ResultState::TRANSIENT_ERROR;
+ case 0:
+ _error->Error("Host Unreachable");
+ cached.insert(hs);
+ goto fail;
- // Handle server IO
- if (ServerFd->HasPending() && In.ReadSpace() == true)
- {
- errno = 0;
- if (In.Read(ServerFd) == false)
- return Die(Req);
- }
+ case 1:
+ /* success */
+ break;
- fd_set rfds,wfds;
- FD_ZERO(&rfds);
- FD_ZERO(&wfds);
-
- /* Add the server. We only send more requests if the connection will
- be persisting */
- if (Out.WriteSpace() == true && ServerFd->Fd() != -1 && Persistent == true)
- FD_SET(ServerFd->Fd(), &wfds);
- if (In.ReadSpace() == true && ServerFd->Fd() != -1)
- FD_SET(ServerFd->Fd(), &rfds);
-
- // Add the file
- auto FileFD = MethodFd::FromFd(-1);
- if (Req.File.IsOpen())
- FileFD = MethodFd::FromFd(Req.File.Fd());
-
- if (In.WriteSpace() == true && ToFile == true && FileFD->Fd() != -1)
- FD_SET(FileFD->Fd(), &wfds);
-
- // Add stdin
- if (Owner->ConfigFindB("DependOnSTDIN", true) == true)
- FD_SET(STDIN_FILENO,&rfds);
-
- // Figure out the max fd
- int MaxFd = FileFD->Fd();
- if (MaxFd < ServerFd->Fd())
- MaxFd = ServerFd->Fd();
-
- // Select
- struct timeval tv;
- tv.tv_sec = TimeOut;
- tv.tv_usec = 0;
- int Res = 0;
- if ((Res = select(MaxFd+1,&rfds,&wfds,0,&tv)) < 0)
- {
- if (errno == EINTR)
- return ResultState::SUCCESSFUL;
- _error->Errno("select", _("Select failed"));
- return ResultState::TRANSIENT_ERROR;
- }
-
- if (Res == 0)
- {
- _error->Error(_("Connection timed out"));
- return Die(Req);
- }
-
- // Handle server IO
- if (ServerFd->Fd() != -1 && FD_ISSET(ServerFd->Fd(), &rfds))
- {
- errno = 0;
- if (In.Read(ServerFd) == false)
- return Die(Req);
- }
+ fail:
+ Fail(true);
+ goto done;
+ }
- if (ServerFd->Fd() != -1 && FD_ISSET(ServerFd->Fd(), &wfds))
- {
- errno = 0;
- if (Out.Write(ServerFd) == false)
- return Die(Req);
- }
+ rd = CFReadStreamRead(rs, data, sizeof(data));
- // Send data to the file
- if (FileFD->Fd() != -1 && FD_ISSET(FileFD->Fd(), &wfds))
- {
- if (In.Write(FileFD) == false)
- {
- _error->Errno("write", _("Error writing to output file"));
- return ResultState::TRANSIENT_ERROR;
+ if (rd == -1) {
+ CfrsError(uri.Host.c_str(), rs);
+ cached.insert(hs);
+ Fail(true);
+ goto done;
}
- }
- if (Req.MaximumSize > 0 && Req.File.IsOpen() && Req.File.Failed() == false && Req.File.Tell() > Req.MaximumSize)
- {
- Owner->SetFailReason("MaximumSizeExceeded");
- _error->Error(_("File has unexpected size (%llu != %llu). Mirror sync in progress?"),
- Req.File.Tell(), Req.MaximumSize);
- return ResultState::FATAL_ERROR;
- }
+ Res.Filename = Queue->DestFile;
+
+ hm = (CFHTTPMessageRef) CFReadStreamCopyProperty(rs, kCFStreamPropertyHTTPResponseHeader);
+ sc = CFHTTPMessageGetResponseStatusCode(hm);
+
+ if (sc == 301 || sc == 302) {
+ sr = CFHTTPMessageCopyHeaderFieldValue(hm, CFSTR("Location"));
+ if (sr == NULL) {
+ Fail();
+ goto done_;
+ } else {
+ size_t ln = CFStringGetLength(sr) + 1;
+ free(url);
+ url = static_cast<char *>(malloc(ln));
+
+ if (!CFStringGetCString(sr, url, ln, se)) {
+ Fail();
+ goto done_;
+ }
+
+ CFRelease(sr);
+ goto url;
+ }
+ }
- // Handle commands from APT
- if (FD_ISSET(STDIN_FILENO,&rfds))
- {
- if (Owner->Run(true) != -1)
- exit(100);
- }
+ sr = CFHTTPMessageCopyHeaderFieldValue(hm, CFSTR("Content-Range"));
+ if (sr != NULL) {
+ size_t ln = CFStringGetLength(sr) + 1;
+ char cr[ln];
+
+ if (!CFStringGetCString(sr, cr, ln, se)) {
+ Fail();
+ goto done_;
+ }
+
+ CFRelease(sr);
+
+ if (sscanf(cr, "bytes %lu-%*u/%llu", &offset, &Res.Size) != 2) {
+ _error->Error(_("The HTTP server sent an invalid Content-Range header"));
+ Fail();
+ goto done_;
+ }
+
+ if (offset > Res.Size) {
+ _error->Error(_("This HTTP server has broken range support"));
+ Fail();
+ goto done_;
+ }
+ } else {
+ sr = CFHTTPMessageCopyHeaderFieldValue(hm, CFSTR("Content-Length"));
+ if (sr != NULL) {
+ Res.Size = CFStringGetIntValue(sr);
+ CFRelease(sr);
+ }
+ }
- return ResultState::SUCCESSFUL;
-}
- /*}}}*/
+ time(&Res.LastModified);
-// HttpMethod::SendReq - Send the HTTP request /*{{{*/
-// ---------------------------------------------------------------------
-/* This places the http request in the outbound buffer */
-void HttpMethod::SendReq(FetchItem *Itm)
-{
- URI Uri = Itm->Uri;
- {
- auto const plus = Binary.find('+');
- if (plus != std::string::npos)
- Uri.Access = Binary.substr(plus + 1);
- }
+ sr = CFHTTPMessageCopyHeaderFieldValue(hm, CFSTR("Last-Modified"));
+ if (sr != NULL) {
+ size_t ln = CFStringGetLength(sr) + 1;
+ char cr[ln];
- // The HTTP server expects a hostname with a trailing :port
- std::stringstream Req;
- string ProperHost;
-
- if (Uri.Host.find(':') != string::npos)
- ProperHost = '[' + Uri.Host + ']';
- else
- ProperHost = Uri.Host;
-
- /* RFC 2616 ยง5.1.2 requires absolute URIs for requests to proxies,
- but while its a must for all servers to accept absolute URIs,
- it is assumed clients will sent an absolute path for non-proxies */
- std::string requesturi;
- if ((Server->Proxy.Access != "http" && Server->Proxy.Access != "https") || APT::String::Endswith(Uri.Access, "https") || Server->Proxy.empty() == true || Server->Proxy.Host.empty())
- requesturi = Uri.Path;
- else
- requesturi = Uri;
-
- // The "+" is encoded as a workaround for a amazon S3 bug
- // see LP bugs #1003633 and #1086997.
- requesturi = QuoteString(requesturi, "+~ ");
-
- /* Build the request. No keep-alive is included as it is the default
- in 1.1, can cause problems with proxies, and we are an HTTP/1.1
- client anyway.
- C.f. https://tools.ietf.org/wg/httpbis/trac/ticket/158 */
- Req << "GET " << requesturi << " HTTP/1.1\r\n";
- if (Uri.Port != 0)
- Req << "Host: " << ProperHost << ":" << std::to_string(Uri.Port) << "\r\n";
- else
- Req << "Host: " << ProperHost << "\r\n";
-
- // generate a cache control header (if needed)
- if (ConfigFindB("No-Cache",false) == true)
- Req << "Cache-Control: no-cache\r\n"
- << "Pragma: no-cache\r\n";
- else if (Itm->IndexFile == true)
- Req << "Cache-Control: max-age=" << std::to_string(ConfigFindI("Max-Age", 0)) << "\r\n";
- else if (ConfigFindB("No-Store", false) == true)
- Req << "Cache-Control: no-store\r\n";
-
- // If we ask for uncompressed files servers might respond with content-
- // negotiation which lets us end up with compressed files we do not support,
- // see 657029, 657560 and co, so if we have no extension on the request
- // ask for text only. As a sidenote: If there is nothing to negotate servers
- // seem to be nice and ignore it.
- if (ConfigFindB("SendAccept", true) == true)
- {
- size_t const filepos = Itm->Uri.find_last_of('/');
- string const file = Itm->Uri.substr(filepos + 1);
- if (flExtension(file) == file)
- Req << "Accept: text/*\r\n";
- }
+ if (!CFStringGetCString(sr, cr, ln, se)) {
+ Fail();
+ goto done_;
+ }
- // Check for a partial file and send if-queries accordingly
- struct stat SBuf;
- if (Server->RangesAllowed && stat(Itm->DestFile.c_str(),&SBuf) >= 0 && SBuf.st_size > 0)
- Req << "Range: bytes=" << std::to_string(SBuf.st_size) << "-\r\n"
- << "If-Range: " << TimeRFC1123(SBuf.st_mtime, false) << "\r\n";
- else if (Itm->LastModified != 0)
- Req << "If-Modified-Since: " << TimeRFC1123(Itm->LastModified, false).c_str() << "\r\n";
+ CFRelease(sr);
- if ((Server->Proxy.Access == "http" || Server->Proxy.Access == "https") &&
- (Server->Proxy.User.empty() == false || Server->Proxy.Password.empty() == false))
- Req << "Proxy-Authorization: Basic "
- << Base64Encode(Server->Proxy.User + ":" + Server->Proxy.Password) << "\r\n";
+ if (!RFC1123StrToTime(cr, Res.LastModified)) {
+ _error->Error(_("Unknown date format"));
+ Fail();
+ goto done_;
+ }
+ }
- MaybeAddAuthTo(Uri);
- if (Uri.User.empty() == false || Uri.Password.empty() == false)
- Req << "Authorization: Basic "
- << Base64Encode(Uri.User + ":" + Uri.Password) << "\r\n";
+ if (sc < 200 || (sc >= 300 && sc != 304)) {
+ sr = CFHTTPMessageCopyResponseStatusLine(hm);
- Req << "User-Agent: " << ConfigFind("User-Agent",
- "Debian APT-HTTP/1.3 (" PACKAGE_VERSION ")") << "\r\n";
+ size_t ln = CFStringGetLength(sr) + 1;
+ char cr[ln];
- auto const referer = ConfigFind("Referer", "");
- if (referer.empty() == false)
- Req << "Referer: " << referer << "\r\n";
+ if (!CFStringGetCString(sr, cr, ln, se)) {
+ Fail();
+ goto done;
+ }
- Req << "\r\n";
+ CFRelease(sr);
- if (Debug == true)
- cerr << Req.str() << endl;
+ _error->Error("%s", cr);
- Server->WriteResponse(Req.str());
-}
- /*}}}*/
-std::unique_ptr<ServerState> HttpMethod::CreateServerState(URI const &uri)/*{{{*/
-{
- return std::unique_ptr<ServerState>(new HttpServerState(uri, this));
-}
- /*}}}*/
-void HttpMethod::RotateDNS() /*{{{*/
-{
- ::RotateDNS();
-}
- /*}}}*/
-BaseHttpMethod::DealWithHeadersResult HttpMethod::DealWithHeaders(FetchResult &Res, RequestState &Req)/*{{{*/
-{
- auto ret = BaseHttpMethod::DealWithHeaders(Res, Req);
- if (ret != BaseHttpMethod::FILE_IS_OPEN)
- return ret;
- if (Req.File.Open(Queue->DestFile, FileFd::WriteAny) == false)
- return ERROR_NOT_FROM_SERVER;
+ Fail();
+ goto done_;
+ }
- FailFile = Queue->DestFile;
- FailFile.c_str(); // Make sure we don't do a malloc in the signal handler
- FailFd = Req.File.Fd();
- FailTime = Req.Date;
+ CFRelease(hm);
+
+ if (sc == 304) {
+ unlink(Queue->DestFile.c_str());
+ Res.IMSHit = true;
+ Res.LastModified = Queue->LastModified;
+ URIDone(Res);
+ } else {
+ Hashes hash;
+
+ File = new FileFd(Queue->DestFile, FileFd::WriteAny);
+ if (_error->PendingError() == true) {
+ delete File;
+ File = NULL;
+ Fail();
+ goto done;
+ }
+
+ FailFile = Queue->DestFile;
+ FailFile.c_str(); // Make sure we dont do a malloc in the signal handler
+ FailFd = File->Fd();
+ FailTime = Res.LastModified;
+
+ Res.ResumePoint = offset;
+ ftruncate(File->Fd(), offset);
+
+ if (offset != 0) {
+ lseek(File->Fd(), 0, SEEK_SET);
+ if (!hash.AddFD(File->Fd(), offset)) {
+ _error->Errno("read", _("Problem hashing file"));
+ delete File;
+ File = NULL;
+ Fail();
+ goto done;
+ }
+ }
+
+ lseek(File->Fd(), 0, SEEK_END);
+
+ URIStart(Res);
+
+ read: if (rd == -1) {
+ CfrsError("rd", rs);
+ Fail(true);
+ } else if (rd == 0) {
+ if (Res.Size == 0)
+ Res.Size = File->Size();
+
+ // Timestamp
+ struct timeval times[2];
+ times[0].tv_sec = times[1].tv_sec = Res.LastModified;
+ times[0].tv_usec = times[1].tv_usec = 0;
+ utimes(Queue->DestFile.c_str(), times);
+
+ Res.TakeHashes(hash);
+ URIDone(Res);
+ } else {
+ hash.Add(data, rd);
+
+ uint8_t *dt = data;
+ while (rd != 0) {
+ int sz = write(File->Fd(), dt, rd);
+
+ if (sz == -1) {
+ delete File;
+ File = NULL;
+ Fail();
+ goto done;
+ }
+
+ dt += sz;
+ rd -= sz;
+ }
+
+ rd = CFReadStreamRead(rs, data, sizeof(data));
+ goto read;
+ }
+ }
- if (Server->InitHashes(Queue->ExpectedHashes) == false || Req.AddPartialFileToHashes(Req.File) == false)
- {
- _error->Errno("read",_("Problem hashing file"));
- return ERROR_NOT_FROM_SERVER;
- }
- if (Req.StartPos > 0)
- Res.ResumePoint = Req.StartPos;
+ goto done;
- SetNonBlock(Req.File.Fd(),true);
- return FILE_IS_OPEN;
+ done_:
+ CFRelease(hm);
+ done:
+ CFReadStreamClose(rs);
+ CFRelease(rs);
+ free(url);
+
+ FailCounter = 0;
+ }
+
+ return 0;
}
- /*}}}*/
-HttpMethod::HttpMethod(std::string &&pProg) : BaseHttpMethod(std::move(pProg), "1.2", Pipeline | SendConfig) /*{{{*/
+HttpMethod::HttpMethod(std::string &&pProg) : BaseHttpMethod(pProg.c_str(), "1.2", Pipeline | SendConfig)/*{{{*/
{
- SeccompFlags = aptMethod::BASE | aptMethod::NETWORK;
-
auto addName = std::inserter(methodNames, methodNames.begin());
- if (Binary != "http")
+ if (Binary != "http" && Binary != "https")
addName = "http";
auto const plus = Binary.find('+');
if (plus != std::string::npos)
- {
- auto name2 = Binary.substr(plus + 1);
- if (std::find(methodNames.begin(), methodNames.end(), name2) == methodNames.end())
- addName = std::move(name2);
addName = Binary.substr(0, plus);
- }
+ File = 0;
+ Server = 0;
}
/*}}}*/
@@ -1044,6 +640,60 @@ int main(int, const char *argv[])
// ignore SIGPIPE, this can happen on write() if the socket
// closes the connection (this is dealt with via ServerDie())
signal(SIGPIPE, SIG_IGN);
+
+ size_t size;
+ sysctlbyname("hw.machine", NULL, &size, NULL, 0);
+ char *machine = new char[size];
+ sysctlbyname("hw.machine", machine, &size, NULL, 0);
+ Machine_ = machine;
+
+ const char *path = "/System/Library/CoreServices/SystemVersion.plist";
+ CFURLRef url = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, (uint8_t *) path, strlen(path), false);
+
+ CFPropertyListRef plist; {
+ CFReadStreamRef stream = CFReadStreamCreateWithFile(kCFAllocatorDefault, url);
+ CFReadStreamOpen(stream);
+ plist = CFPropertyListCreateFromStream(kCFAllocatorDefault, stream, 0, kCFPropertyListImmutable, NULL, NULL);
+ CFReadStreamClose(stream);
+ }
+
+ CFRelease(url);
+
+ if (plist != NULL) {
+ Firmware_ = (CFStringRef) CFRetain(CFDictionaryGetValue((CFDictionaryRef) plist, CFSTR("ProductVersion")));
+ Product_ = (CFStringRef) CFRetain(CFDictionaryGetValue((CFDictionaryRef) plist, CFSTR("ProductName")));
+ CFRelease(plist);
+ }
+
+ if (UniqueID_ == NULL)
+ if (void *libMobileGestalt = dlopen("/usr/lib/libMobileGestalt.dylib", RTLD_GLOBAL | RTLD_LAZY))
+ if (CFStringRef (*$MGCopyAnswer)(CFStringRef) = (CFStringRef (*)(CFStringRef)) dlsym(libMobileGestalt, "MGCopyAnswer")) {
+ UniqueID_ = $MGCopyAnswer(CFSTR("UniqueDeviceID"));
+ Arch_ = $MGCopyAnswer(CFSTR("CPUArchitecture"));
+ }
+
+ if (UniqueID_ == NULL)
+ if (void *lockdown = lockdown_connect()) {
+ UniqueID_ = (CFStringRef)lockdown_copy_value(lockdown, NULL, kLockdownUniqueDeviceIDKey);
+ lockdown_disconnect(lockdown);
+ }
+
+ if (Arch_ == NULL)
+ Arch_ = CFSTR("Unknown");
+
+ if (Firmware_ == NULL)
+ Firmware_ = CFSTR("Unknown");
+
+ if (Product_ == NULL)
+ Product_ = CFSTR("Unknown");
+
+ if (UniqueID_ == NULL)
+ UniqueID_ = CFSTR("Unknown");
+
+ UserAgent_ = CFStringCreateWithFormat(NULL, NULL, CFSTR("Telesphoreo APT/%s (Darwin; %@ %@; %@; Elucubratus)"), PACKAGE_VERSION, Product_, Firmware_, Arch_);
+ if (UserAgent_ == NULL)
+ UserAgent_ = CFSTR("Telesphoreo APT/" PACKAGE_VERSION " (Darwin; Unknown Unknown; Unknown; Elucubratus)");
+
std::string Binary = flNotDir(argv[0]);
if (Binary.find('+') == std::string::npos && Binary != "https" && Binary != "http")
Binary.append("+http");
diff --git a/methods/http.h b/methods/http.h
index 5668f0b87..15691379d 100644
--- a/methods/http.h
+++ b/methods/http.h
@@ -28,99 +28,6 @@ class FileFd;
class HttpMethod;
class Hashes;
-class CircleBuf
-{
- unsigned char *Buf;
- unsigned long long Size;
- unsigned long long InP;
- unsigned long long OutP;
- std::string OutQueue;
- unsigned long long StrPos;
- unsigned long long MaxGet;
-
- static unsigned long long BwReadLimit;
- static unsigned long long BwTickReadData;
- static std::chrono::steady_clock::duration BwReadTick;
- static const unsigned int BW_HZ;
-
- unsigned long long LeftRead() const
- {
- unsigned long long Sz = Size - (InP - OutP);
- if (Sz > Size - (InP%Size))
- Sz = Size - (InP%Size);
- return Sz;
- }
- unsigned long long LeftWrite() const
- {
- unsigned long long Sz = InP - OutP;
- if (InP > MaxGet)
- Sz = MaxGet - OutP;
- if (Sz > Size - (OutP%Size))
- Sz = Size - (OutP%Size);
- return Sz;
- }
- void FillOut();
-
- public:
- Hashes *Hash;
- // total amount of data that got written so far
- unsigned long long TotalWriten;
-
- // Read data in
- bool Read(std::unique_ptr<MethodFd> const &Fd);
- bool Read(std::string const &Data);
-
- // Write data out
- bool Write(std::unique_ptr<MethodFd> const &Fd);
- bool Write(std::string &Data);
- bool WriteTillEl(std::string &Data,bool Single = false);
-
- // Control the write limit
- void Limit(long long Max) {if (Max == -1) MaxGet = 0-1; else MaxGet = OutP + Max;}
- bool IsLimit() const {return MaxGet == OutP;};
- void Print() const {cout << MaxGet << ',' << OutP << endl;};
-
- // Test for free space in the buffer
- bool ReadSpace() const {return Size - (InP - OutP) > 0;};
- bool WriteSpace() const {return InP - OutP > 0;};
-
- void Reset();
-
- CircleBuf(HttpMethod const * const Owner, unsigned long long Size);
- ~CircleBuf();
-};
-
-struct HttpServerState: public ServerState
-{
- // This is the connection itself. Output is data FROM the server
- CircleBuf In;
- CircleBuf Out;
- std::unique_ptr<MethodFd> ServerFd;
-
- protected:
- virtual bool ReadHeaderLines(std::string &Data) APT_OVERRIDE;
- virtual ResultState LoadNextResponse(bool const ToFile, RequestState &Req) APT_OVERRIDE;
- virtual bool WriteResponse(std::string const &Data) APT_OVERRIDE;
-
- public:
- virtual void Reset() APT_OVERRIDE;
-
- virtual ResultState RunData(RequestState &Req) APT_OVERRIDE;
- virtual ResultState RunDataToDevNull(RequestState &Req) APT_OVERRIDE;
-
- virtual ResultState Open() APT_OVERRIDE;
- virtual bool IsOpen() APT_OVERRIDE;
- virtual bool Close() APT_OVERRIDE;
- virtual bool InitHashes(HashStringList const &ExpectedHashes) APT_OVERRIDE;
- virtual Hashes * GetHashes() APT_OVERRIDE;
- virtual ResultState Die(RequestState &Req) APT_OVERRIDE;
- virtual bool Flush(FileFd * const File) APT_OVERRIDE;
- virtual ResultState Go(bool ToFile, RequestState &Req) APT_OVERRIDE;
-
- HttpServerState(URI Srv, HttpMethod *Owner);
- virtual ~HttpServerState() {Close();};
-};
-
class HttpMethod : public BaseHttpMethod
{
public:
@@ -131,11 +38,14 @@ class HttpMethod : public BaseHttpMethod
virtual DealWithHeadersResult DealWithHeaders(FetchResult &Res, RequestState &Req) APT_OVERRIDE;
protected:
+ FileFd *File;
std::string AutoDetectProxyCmd;
public:
friend struct HttpServerState;
+ int Loop();
+
explicit HttpMethod(std::string &&pProg);
};
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 2f47b5c32..d7a0a0dbf 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -1,2 +1 @@
add_subdirectory(libapt)
-add_subdirectory(interactive-helper)