Complete Yocto mirror with license table for TQMa6UL (2038-compliance)

- 264 license table entries with exact download URLs (224/264 resolved)
- Complete sources/ directory with all BitBake recipes
- Build configuration: tqma6ul-multi-mba6ulx, spaetzle (musl)
- Full traceability for Softwarefreigabeantrag
- GCC 13.4.0, Linux 6.6.102, U-Boot 2023.04, musl 1.2.4
- License distribution: GPL-2.0 (24), MIT (23), GPL-2.0+ (18), BSD-3 (16)
This commit is contained in:
Siggi (OpenClaw Agent)
2026-03-01 20:58:18 +00:00
commit 16accb6b24
15086 changed files with 1292356 additions and 0 deletions

View File

@@ -0,0 +1,29 @@
From 9023589317843df4e57f8ebef1d9a8398ddb929d Mon Sep 17 00:00:00 2001
From: Alexander Kanavin <alex.kanavin@gmail.com>
Date: Thu, 28 May 2020 15:34:05 +0000
Subject: [PATCH] CMakeLists.txt: avoid changing install paths based on host
distro
Upstream-Status: Inappropriate [oe-core specific]
Signed-off-by: Alexander Kanavin <alex.kanavin@gmail.com>
---
CMakeLists.txt | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 2cd4f8e..4759812 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -21,9 +21,9 @@ set(CMAKE_EXE_LINKER_FLAGS_COVERAGE "-lgcov")
set(CMAKE_SHARED_LINKER_FLAGS_COVERAGE "-lgcov")
# Work around bug in GNUInstallDirs
-if (EXISTS "/etc/debian_version")
- set(CMAKE_INSTALL_LIBEXECDIR "lib")
-endif()
+#if (EXISTS "/etc/debian_version")
+set(CMAKE_INSTALL_LIBEXECDIR "lib")
+#endif()
# Include stuff
include(Misc)

View File

@@ -0,0 +1,27 @@
From f629d1c3fcfb560ed24efc3e73d4e4999b1eab33 Mon Sep 17 00:00:00 2001
From: Alexander Kanavin <alex.kanavin@gmail.com>
Date: Fri, 10 May 2019 14:16:47 +0200
Subject: [PATCH] Disable documentation directory altogether
Even when WITH_DOC=False, the build requires po4a to generate manpages.
Upstream-Status: Inappropriate [oe-core specific]
Signed-off-by: Alexander Kanavin <alex.kanavin@gmail.com>
---
CMakeLists.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 668e2d762..62f441bfa 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -246,7 +246,7 @@ add_subdirectory(apt-private)
endif()
add_subdirectory(cmdline)
add_subdirectory(completions)
-add_subdirectory(doc)
+#add_subdirectory(doc)
add_subdirectory(dselect)
add_subdirectory(ftparchive)
add_subdirectory(methods)

View File

@@ -0,0 +1,29 @@
From b84280fec4e1d0d33eca78e76556023f8f8fe5b7 Mon Sep 17 00:00:00 2001
From: Alexander Kanavin <alex.kanavin@gmail.com>
Date: Fri, 10 May 2019 16:47:38 +0200
Subject: [PATCH] Do not init tables from dpkg configuration
This would require sysroot relocation logic, and it's easier to just disable them.
Upstream-Status: Inappropriate [oe-core specific]
Signed-off-by: Alexander Kanavin <alex.kanavin@gmail.com>
---
apt-pkg/init.cc | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/apt-pkg/init.cc b/apt-pkg/init.cc
index b9d9b15d2..1725c5966 100644
--- a/apt-pkg/init.cc
+++ b/apt-pkg/init.cc
@@ -281,8 +281,8 @@ bool pkgInitSystem(Configuration &Cnf,pkgSystem *&Sys)
return _error->Error(_("Unable to determine a suitable packaging system type"));
}
- if (pkgInitArchTupleMap() == false)
- return false;
+// if (pkgInitArchTupleMap() == false)
+// return false;
return Sys->Initialize(Cnf);
}

View File

@@ -0,0 +1,28 @@
From 6b8547161b902b01b639d05a4cdf849d7694556f Mon Sep 17 00:00:00 2001
From: Alexander Kanavin <alex.kanavin@gmail.com>
Date: Fri, 22 May 2020 15:29:23 +0000
Subject: [PATCH] apt-pkg/contrib/srvrec.h: Explicitly include sys/types.h
This avoids type errors with musl C library.
Upstream-Status: Submitted [https://salsa.debian.org/apt-team/apt/-/merge_requests/200]
Signed-off-by: Alexander Kanavin <alex.kanavin@gmail.com>
---
apt-pkg/contrib/srvrec.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/apt-pkg/contrib/srvrec.h b/apt-pkg/contrib/srvrec.h
index e5d0f43..2010184 100644
--- a/apt-pkg/contrib/srvrec.h
+++ b/apt-pkg/contrib/srvrec.h
@@ -9,6 +9,7 @@
#ifndef SRVREC_H
#define SRVREC_H
+#include <sys/types.h>
#include <string>
#include <vector>
#include <arpa/nameser.h>
--
2.20.1

View File

@@ -0,0 +1,48 @@
From e849b161ce1d87ab369b921438abcf5b3a03e186 Mon Sep 17 00:00:00 2001
From: Khem Raj <raj.khem@gmail.com>
Date: Sun, 25 Apr 2021 08:57:03 -0700
Subject: [PATCH] Hide fstatat64 and prlimit64 defines on musl
musl defines fstatat64 and prlimit64 as macros which confuses the
seccomp sysall rewiring since there are syscalls with same names
Upstream-Status: Pending
Signed-off-by: Khem Raj <raj.khem@gmail.com>
---
methods/aptmethod.h | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/methods/aptmethod.h b/methods/aptmethod.h
index bd50e80..3085aed 100644
--- a/methods/aptmethod.h
+++ b/methods/aptmethod.h
@@ -121,6 +121,12 @@ protected:
if (ctx == NULL)
return _error->FatalE("HttpMethod::Configuration", "Cannot init seccomp");
+#ifndef __GLIBC__
+#pragma push_macro("fstatat64")
+#pragma push_macro("prlimit64")
+#undef fstatat64
+#undef prlimit64
+#endif
#define ALLOW(what) \
if ((rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(what), 0))) \
return _error->FatalE("HttpMethod::Configuration", "Cannot allow %s: %s", #what, strerror(-rc));
@@ -320,9 +326,11 @@ protected:
if ((rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, seccomp_syscall_resolve_name(custom.c_str()), 0)))
return _error->FatalE("aptMethod::Configuration", "Cannot allow %s: %s", custom.c_str(), strerror(-rc));
}
-
#undef ALLOW
-
+#ifndef __GLIBC__
+#pragma pop_macro("fstatat64")
+#pragma pop_macro("prlimit64")
+#endif
rc = seccomp_load(ctx);
if (rc == -EINVAL)
{
--
2.31.1

View File

@@ -0,0 +1,87 @@
From e91fb0618ce0a5d42f239d0fca602544858f0819 Mon Sep 17 00:00:00 2001
From: Khem Raj <raj.khem@gmail.com>
Date: Tue, 16 Aug 2022 08:44:18 -0700
Subject: [PATCH] Remove using std::binary_function
std::binary_function and std::unary_function are deprecated since c++11
and removed in c++17, therefore remove it and use lambda functions to get same
functionality implemented.
Upstream-Status: Submitted [https://salsa.debian.org/apt-team/apt/-/merge_requests/253]
Signed-off-by: Khem Raj <raj.khem@gmail.com>
---
ftparchive/apt-ftparchive.cc | 33 ++++++++++-----------------------
1 file changed, 10 insertions(+), 23 deletions(-)
diff --git a/ftparchive/apt-ftparchive.cc b/ftparchive/apt-ftparchive.cc
index 0f6587281..0a253b12b 100644
--- a/ftparchive/apt-ftparchive.cc
+++ b/ftparchive/apt-ftparchive.cc
@@ -48,6 +48,11 @@
using namespace std;
unsigned Quiet = 0;
+auto ContentsCompare = [](const auto &a, const auto &b) { return a.ContentsMTime < b.ContentsMTime; };
+auto DBCompare = [](const auto &a, const auto &b) { return a.BinCacheDB < b.BinCacheDB; };
+auto SrcDBCompare = [](const auto &a, const auto &b) { return a.SrcCacheDB < b.SrcCacheDB; };
+
+
static struct timeval GetTimevalFromSteadyClock() /*{{{*/
{
auto const Time = std::chrono::steady_clock::now().time_since_epoch();
@@ -116,24 +121,6 @@ struct PackageMap
bool SrcDone;
time_t ContentsMTime;
- struct ContentsCompare
- {
- inline bool operator() (const PackageMap &x,const PackageMap &y)
- {return x.ContentsMTime < y.ContentsMTime;};
- };
-
- struct DBCompare
- {
- inline bool operator() (const PackageMap &x,const PackageMap &y)
- {return x.BinCacheDB < y.BinCacheDB;};
- };
-
- struct SrcDBCompare
- {
- inline bool operator() (const PackageMap &x,const PackageMap &y)
- {return x.SrcCacheDB < y.SrcCacheDB;};
- };
-
void GetGeneral(Configuration &Setup,Configuration &Block);
bool GenPackages(Configuration &Setup,struct CacheDB::Stats &Stats);
bool GenSources(Configuration &Setup,struct CacheDB::Stats &Stats);
@@ -869,7 +856,7 @@ static bool DoGenerateContents(Configuration &Setup,
else
I->ContentsMTime = A.st_mtime;
}
- stable_sort(PkgList.begin(),PkgList.end(),PackageMap::ContentsCompare());
+ stable_sort(PkgList.begin(),PkgList.end(),ContentsCompare);
/* Now for Contents.. The process here is to do a make-like dependency
check. Each contents file is verified to be newer than the package files
@@ -941,8 +928,8 @@ static bool Generate(CommandLine &CmdL)
LoadBinDir(PkgList,Setup);
// Sort by cache DB to improve IO locality.
- stable_sort(PkgList.begin(),PkgList.end(),PackageMap::DBCompare());
- stable_sort(PkgList.begin(),PkgList.end(),PackageMap::SrcDBCompare());
+ stable_sort(PkgList.begin(),PkgList.end(),DBCompare);
+ stable_sort(PkgList.begin(),PkgList.end(),SrcDBCompare);
// Generate packages
if (_config->FindB("APT::FTPArchive::ContentsOnly", false) == false)
@@ -993,8 +980,8 @@ static bool Clean(CommandLine &CmdL)
LoadBinDir(PkgList,Setup);
// Sort by cache DB to improve IO locality.
- stable_sort(PkgList.begin(),PkgList.end(),PackageMap::DBCompare());
- stable_sort(PkgList.begin(),PkgList.end(),PackageMap::SrcDBCompare());
+ stable_sort(PkgList.begin(),PkgList.end(),DBCompare);
+ stable_sort(PkgList.begin(),PkgList.end(),SrcDBCompare);
string CacheDir = Setup.FindDir("Dir::CacheDir");

View File

@@ -0,0 +1,48 @@
From a2dd661484536492b47d4c88998f2bf516749bc8 Mon Sep 17 00:00:00 2001
From: Alexander Kanavin <alex.kanavin@gmail.com>
Date: Thu, 21 May 2020 20:13:25 +0000
Subject: [PATCH] Revert "always run 'dpkg --configure -a' at the end of our
dpkg callings"
This reverts commit a2a75ff4516f7609f4c55b42270abb8d08943c60, which
always run 'dpkg --configure -a' at the end of our dpkg callings,
but it does not work for cross-compile, since the rootfs dir can not
be passed into dpkg, and lead to the below similar error:
-------
|mkdir: cannot create directory '/usr/lib/opkg': Permission denied
-------
Upstream-Status: Inappropriate [embedded specific]
Signed-off-by: Alexander Kanavin <alex.kanavin@gmail.com>
---
apt-pkg/deb/dpkgpm.cc | 9 ++-------
1 file changed, 2 insertions(+), 7 deletions(-)
diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc
index 93effa959..4375781d1 100644
--- a/apt-pkg/deb/dpkgpm.cc
+++ b/apt-pkg/deb/dpkgpm.cc
@@ -1199,12 +1199,6 @@ void pkgDPkgPM::BuildPackagesProgressMap()
}
}
}
- /* one extra: We don't want the progress bar to reach 100%, especially not
- if we call dpkg --configure --pending and process a bunch of triggers
- while showing 100%. Also, spindown takes a while, so never reaching 100%
- is way more correct than reaching 100% while still doing stuff even if
- doing it this way is slightly bending the rules */
- ++PackagesTotal;
}
/*}}}*/
void pkgDPkgPM::StartPtyMagic() /*{{{*/
@@ -1741,7 +1735,8 @@ bool pkgDPkgPM::Go(APT::Progress::PackageManager *progress)
// support subpressing of triggers processing for special
// cases like d-i that runs the triggers handling manually
- if (_config->FindB("DPkg::ConfigurePending", true))
+ bool const SmartConf = (_config->Find("PackageManager::Configure", "all") != "all");
+ if (0)
List.emplace_back(Item::ConfigurePending, pkgCache::PkgIterator());
}
bool const TriggersPending = _config->FindB("DPkg::TriggersPending", false);

View File

@@ -0,0 +1,30 @@
From 5985f366750a73c81c7d86893a2b959b4af062a5 Mon Sep 17 00:00:00 2001
From: Khem Raj <raj.khem@gmail.com>
Date: Wed, 26 May 2021 22:12:46 -0700
Subject: [PATCH] aptwebserver.cc: Include <array>
This helps getting std::array definition
Fixes
test/interactive-helper/aptwebserver.cc:36:55: error: constexpr variable cannot have non-literal type 'const std::array<std::array<const char *, 2>, 6>'
constexpr std::array<std::array<char const *,2>,6> htmlencode = {{
Upstream-Status: Submitted [https://github.com/Debian/apt/pull/133]
Signed-off-by: Khem Raj <raj.khem@gmail.com>
---
test/interactive-helper/aptwebserver.cc | 1 +
1 file changed, 1 insertion(+)
diff --git a/test/interactive-helper/aptwebserver.cc b/test/interactive-helper/aptwebserver.cc
index f4f8d95..361c7a9 100644
--- a/test/interactive-helper/aptwebserver.cc
+++ b/test/interactive-helper/aptwebserver.cc
@@ -23,6 +23,7 @@
#include <array>
#include <algorithm>
+#include <array>
#include <fstream>
#include <iostream>
#include <list>

View File

@@ -0,0 +1,36 @@
From 33347f9f8301633b01af4e208b7be5fdfcb0df0c Mon Sep 17 00:00:00 2001
From: Khem Raj <raj.khem@gmail.com>
Date: Sat, 20 Mar 2021 14:45:18 -0700
Subject: [PATCH] cmake: Do not build po files
Fixes
| CMake Error at CMakeLists.txt:252 (add_dependencies):
| The dependency target "update-po4a" of target "update-po" does not exist.
|
Upstream-Status: Inappropriate [Cross-compile specific]
Signed-off-by: Khem Raj <raj.khem@gmail.com>
---
CMakeLists.txt | 7 -------
1 file changed, 7 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index be157a55f..54163ae6c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -252,15 +252,6 @@ add_subdirectory(ftparchive)
add_subdirectory(methods)
add_subdirectory(test)
-if (USE_NLS)
-add_subdirectory(po)
-endif()
-
-if(TARGET update-po AND TARGET update-po4a)
-# Link update-po4a into the update-po target
-add_dependencies(update-po update-po4a)
-endif()
-
# Create our directories.
install_empty_directories(
${CONF_DIR}/apt.conf.d

View File

@@ -0,0 +1,728 @@
#!/usr/bin/perl -w
#
# Copyright (C) 2016 Julian Andres Klode <jak@jak-linux.org>
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
=encoding utf8
=head1 NAME
triehash - Generate a perfect hash function derived from a trie.
=cut
use strict;
use warnings;
use utf8;
use Getopt::Long;
=head1 SYNOPSIS
B<triehash> [S<I<option>>] [S<I<input file>>]
=head1 DESCRIPTION
triehash takes a list of words in input file and generates a function and
an enumeration to describe the word
=head1 INPUT FILE FORMAT
The file consists of multiple lines of the form:
[label ~ ] word [= value]
This maps word to value, and generates an enumeration with entries of the form:
label = value
If I<label> is undefined, the word will be used, the minus character will be
replaced by an underscore. If value is undefined it is counted upwards from
the last value.
There may also be one line of the format
[ label ~] = value
Which defines the value to be used for non-existing keys. Note that this also
changes default value for other keys, as for normal entries. So if you place
= 0
at the beginning of the file, unknown strings map to 0, and the other strings
map to values starting with 1. If label is not specified, the default is
I<Unknown>.
=head1 OPTIONS
=over 4
=item B<-C>I<.c file> B<--code>=I<.c file>
Generate code in the given file.
=item B<-H>I<header file> B<--header>=I<header file>
Generate a header in the given file, containing a declaration of the hash
function and an enumeration.
=item B<--enum-name=>I<word>
The name of the enumeration.
=item B<--function-name=>I<word>
The name of the function.
=item B<--label-prefix=>I<word>
The prefix to use for labels.
=item B<--label-uppercase>
Uppercase label names when normalizing them.
=item B<--namespace=>I<name>
Put the function and enum into a namespace (C++)
=item B<--class=>I<name>
Put the function and enum into a class (C++)
=item B<--enum-class>
Generate an enum class instead of an enum (C++)
=item B<--counter-name=>I<name>
Use I<name> for a counter that is set to the latest entry in the enumeration
+ 1. This can be useful for defining array sizes.
=item B<--ignore-case>
Ignore case for words.
=item B<--multi-byte>=I<value>
Generate code reading multiple bytes at once. The value is a string of power
of twos to enable. The default value is 320 meaning that 8, 4, and single byte
reads are enabled. Specify 0 to disable multi-byte completely, or add 2 if you
also want to allow 2-byte reads. 2-byte reads are disabled by default because
they negatively affect performance on older Intel architectures.
This generates code for both multiple bytes and single byte reads, but only
enables the multiple byte reads of GNU C compatible compilers, as the following
extensions are used:
=over 8
=item Byte-aligned integers
We must be able to generate integers that are aligned to a single byte using:
typedef uint64_t __attribute__((aligned (1))) triehash_uu64;
=item Byte-order
The macros __BYTE_ORDER__ and __ORDER_LITTLE_ENDIAN__ must be defined.
=back
We forcefully disable multi-byte reads on platforms where the variable
I<__ARM_ARCH> is defined and I<__ARM_FEATURE_UNALIGNED> is not defined,
as there is a measurable overhead from emulating the unaligned reads on
ARM.
=item B<--language=>I<language>
Generate a file in the specified language. Currently known are 'C' and 'tree',
the latter generating a tree.
=item B<--include=>I<header>
Add the header to the include statements of the header file. The value must
be surrounded by quotes or angle brackets for C code. May be specified multiple
times.
=back
=cut
my $unknown = -1;
my $unknown_label = undef;
my $counter_start = 0;
my $enum_name = 'PerfectKey';
my $function_name = 'PerfectHash';
my $enum_class = 0;
my $code_name = '-';
my $header_name = '-';
my $code;
my $header;
my $label_prefix = undef;
my $label_uppercase = 0;
my $ignore_case = 0;
my $multi_byte = '320';
my $language = 'C';
my $counter_name = undef;
my @includes = ();
Getopt::Long::config('default',
'bundling',
'no_getopt_compat',
'no_auto_abbrev',
'permute',
'auto_help');
GetOptions ('code|C=s' => \$code_name,
'header|H=s' => \$header_name,
'function-name=s' => \$function_name,
'label-prefix=s' => \$label_prefix,
'label-uppercase' => \$label_uppercase,
'ignore-case' => \$ignore_case,
'enum-name=s' => \$enum_name,
'language|l=s' => \$language,
'multi-byte=s' => \$multi_byte,
'enum-class' => \$enum_class,
'include=s' => \@includes,
'counter-name=s' => \$counter_name)
or die('Could not parse options!');
# This implements a simple trie. Each node has three attributes:
#
# children - A hash of keys to other nodes
# value - The value to be stored here
# label - A named representation of the value.
#
# The key at each level of the trie can consist of one or more bytes, and the
# trie can be normalized to a form where all keys at a level have the same
# length using rebuild_tree().
package Trie {
sub new {
my $class = shift;
my $self = {};
bless $self, $class;
$self->{children} = {};
$self->{value} = undef;
$self->{label} = undef;
return $self;
}
# Return the largest power of 2 smaller or equal to the argument
sub alignpower2 {
my ($self, $length) = @_;
return 8 if ($length >= 8 && $multi_byte =~ /3/);
return 4 if ($length >= 4 && $multi_byte =~ /2/);
return 2 if ($length >= 2 && $multi_byte =~ /1/);
return 1;
}
# Split the key into a head block and a tail
sub split_key {
my ($self, $key) = @_;
my $length = length $key;
my $split = $self->alignpower2($length);
return (substr($key, 0, $split), substr($key, $split));
}
# Given a key, a label, and a value, insert that into the tree, possibly
# replacing an existing node.
sub insert {
my ($self, $key, $label, $value) = @_;
if (length($key) == 0) {
$self->{label} = $label;
$self->{value} = $value;
return;
}
my ($child, $tail) = $self->split_key($key);
$self->{children}{$child} = Trie->new if (!defined($self->{children}{$child}));
$self->{children}{$child}->insert($tail, $label, $value);
}
# Construct a new trie that only contains words of a given length. This
# is used to split up the common trie after knowing all words, so we can
# switch on the expected word length first, and have the per-trie function
# implement simple longest prefix matching.
sub filter_depth {
my ($self, $togo) = @_;
my $new = Trie->new;
if ($togo != 0) {
my $found = 0;
foreach my $key (sort keys %{$self->{children}}) {
if ($togo > length($key) || defined $self->{children}{$key}->{value}) {
my $child = $self->{children}{$key}->filter_depth($togo - length($key));
$new->{children}{$key}= $child if defined $child;
$found = 1 if defined $child;
}
}
return if (!$found);
} else {
$new->{value} = $self->{value};
$new->{label} = $self->{label};
}
return $new;
}
# (helper for rebuild_tree)
# Reinsert all value nodes into the specified $trie, prepending $prefix
# to their $paths.
sub reinsert_value_nodes_into {
my ($self, $trie, $prefix) = @_;
$trie->insert($prefix, $self->{label}, $self->{value}) if (defined $self->{value});
foreach my $key (sort keys %{$self->{children}}) {
$self->{children}{$key}->reinsert_value_nodes_into($trie, $prefix . $key);
}
}
# (helper for rebuild_tree)
# Find the earliest point to split a key. Normally, we split at the maximum
# power of 2 that is greater or equal than the length of the key. When we
# are building an ASCII-optimised case-insensitive trie that simply ORs
# each byte with 0x20, we need to split at the first ambiguous character:
#
# For example, the words a-bc and a\rbc are identical in such a situation:
# '-' | 0x20 == '-' == '\r' | 0x20
# We cannot simply switch on all 4 bytes at once, but need to split before
# the ambiguous character so we can process the ambiguous character on its
# own.
sub find_earlier_split {
my ($self, $key) = @_;
if ($ignore_case) {
for my $i (0..length($key)-1) {
# If the key starts with an ambiguous character, we need to
# take only it. Otherwise, we need to take everything
# before the character.
return $self->alignpower2($i || 1) if (main::ambiguous(substr($key, $i, 1)));
}
}
return $self->alignpower2(length $key);
}
# This rebuilds the trie, splitting each key before ambiguous characters
# as explained in find_earlier_split(), and then chooses the smallest
# such split at each level, so that all keys at all levels have the same
# length (so we can use a multi-byte switch).
sub rebuild_tree {
my $self = shift;
# Determine if/where we need to split before an ambiguous character
my $new_split = 99999999999999999;
foreach my $key (sort keys %{$self->{children}}) {
my $special_length = $self->find_earlier_split($key);
$new_split = $special_length if ($special_length < $new_split);
}
# Start building a new uniform trie
my $newself = Trie->new;
$newself->{label} = $self->{label};
$newself->{value} = $self->{value};
$newself->{children} = {};
foreach my $key (sort keys %{$self->{children}}) {
my $head = substr($key, 0, $new_split);
my $tail = substr($key, $new_split);
# Rebuild the child node at $head, pushing $tail downwards
$newself->{children}{$head} //= Trie->new;
$self->{children}{$key}->reinsert_value_nodes_into($newself->{children}{$head}, $tail);
# We took up to one special character of each key label. There might
# be more, so we need to rebuild recursively.
$newself->{children}{$head} = $newself->{children}{$head}->rebuild_tree();
}
return $newself;
}
}
# Code generator for C and C++
package CCodeGen {
my $static = ($code_name eq $header_name) ? "static " : "";
my $enum_specifier = $enum_class ? "enum class" : "enum";
sub new {
my $class = shift;
my $self = {};
bless $self, $class;
return $self;
}
sub open_output {
my $self = shift;
if ($code_name ne '-') {
open($code, '>', $code_name) or die "Cannot open $code_name: $!" ;
} else {
$code = *STDOUT;
}
if($code_name eq $header_name) {
$header = $code;
} elsif ($header_name ne '-') {
open($header, '>', $header_name) or die "Cannot open $header_name: $!" ;
} else {
$header = *STDOUT;
}
}
sub mangle_label {
my ($self, $label) = @_;
$label = $label_prefix . $label if defined($label_prefix);
$label = uc $label if $label_uppercase;
return $label;
}
sub word_to_label {
my ($self, $word) = @_;
$word =~ s/_/__/g;
$word =~ s/-/_/g;
return $self->mangle_label($word);
}
# Return a case label, by shifting and or-ing bytes in the word
sub case_label {
my ($self, $key) = @_;
return sprintf("'%s'", substr($key, 0, 1)) if not $multi_byte;
my $output = '0';
for my $i (0..length($key)-1) {
$output .= sprintf("| onechar('%s', %d, %d)", substr($key, $i, 1), 8 * $i, 8*length($key));
}
return $output;
}
# Return an appropriate read instruction for $length bytes from $offset
sub switch_key {
my ($self, $offset, $length) = @_;
return "string[$offset]" if $length == 1;
return sprintf("*((triehash_uu%s*) &string[$offset])", $length * 8);
}
# Render the trie so that it matches the longest prefix.
sub print_table {
my ($self, $trie, $fh, $indent, $index) = @_;
$indent //= 0;
$index //= 0;
# If we have children, try to match them.
if (%{$trie->{children}}) {
# The difference between lowercase and uppercase alphabetical characters
# is that they have one bit flipped. If we have alphabetical characters
# in the search space, and the entire search space works fine if we
# always turn on the flip, just OR the character we are switching over
# with the bit.
my $want_use_bit = 0;
my $can_use_bit = 1;
my $key_length = 0;
foreach my $key (sort keys %{$trie->{children}}) {
$can_use_bit &= not main::ambiguous($key);
$want_use_bit |= ($key =~ /^[a-zA-Z]+$/);
$key_length = length($key);
}
if ($ignore_case && $can_use_bit && $want_use_bit) {
printf { $fh } ((' ' x $indent) . "switch(%s | 0x%s) {\n", $self->switch_key($index, $key_length), '20' x $key_length);
} else {
printf { $fh } ((' ' x $indent) . "switch(%s) {\n", $self->switch_key($index, $key_length));
}
my $notfirst = 0;
foreach my $key (sort keys %{$trie->{children}}) {
if ($notfirst) {
printf { $fh } (' ' x $indent . " break;\n");
}
if ($ignore_case) {
printf { $fh } (' ' x $indent . "case %s:\n", $self->case_label(lc($key)));
printf { $fh } (' ' x $indent . "case %s:\n", $self->case_label(uc($key))) if lc($key) ne uc($key) && !($can_use_bit && $want_use_bit);
} else {
printf { $fh } (' ' x $indent . "case %s:\n", $self->case_label($key));
}
$self->print_table($trie->{children}{$key}, $fh, $indent + 1, $index + length($key));
$notfirst=1;
}
printf { $fh } (' ' x $indent . "}\n");
}
# This node has a value, so it is a possible end point. If no children
# matched, we have found our longest prefix.
if (defined $trie->{value}) {
printf { $fh } (' ' x $indent . "return %s;\n", ($enum_class ? "${enum_name}::" : '').$trie->{label});
}
}
sub print_words {
my ($self, $trie, $fh, $indent, $sofar) = @_;
$indent //= 0;
$sofar //= '';
printf { $fh } (' ' x $indent."%s = %s,\n", $trie->{label}, $trie->{value}) if defined $trie->{value};
foreach my $key (sort keys %{$trie->{children}}) {
$self->print_words($trie->{children}{$key}, $fh, $indent, $sofar . $key);
}
}
sub print_functions {
my ($self, $trie, %lengths) = @_;
foreach my $local_length (sort { $a <=> $b } (keys %lengths)) {
print { $code } ("static enum ${enum_name} ${function_name}${local_length}(const char *string)\n");
print { $code } ("{\n");
$self->print_table($trie->filter_depth($local_length)->rebuild_tree(), $code, 1);
printf { $code } (" return %s$unknown_label;\n", ($enum_class ? "${enum_name}::" : ''));
print { $code } ("}\n");
}
}
sub main {
my ($self, $trie, $num_values, %lengths) = @_;
print { $header } ("#ifndef TRIE_HASH_${function_name}\n");
print { $header } ("#define TRIE_HASH_${function_name}\n");
print { $header } ("#include <stddef.h>\n");
print { $header } ("#include <stdint.h>\n");
foreach my $include (@includes) {
print { $header } ("#include $include\n");
}
printf { $header } ("enum { $counter_name = $num_values };\n") if (defined($counter_name));
print { $header } ("${enum_specifier} ${enum_name} {\n");
$self->print_words($trie, $header, 1);
printf { $header } (" $unknown_label = $unknown,\n");
print { $header } ("};\n");
print { $header } ("${static}enum ${enum_name} ${function_name}(const char *string, size_t length);\n");
print { $code } ("#include \"$header_name\"\n") if ($header_name ne $code_name);
if ($multi_byte) {
print { $code } ("#ifdef __GNUC__\n");
foreach my $i ((16, 32, 64)) {
print { $code } ("typedef uint${i}_t __attribute__((aligned (1))) triehash_uu${i};\n");
print { $code } ("typedef char static_assert${i}[__alignof__(triehash_uu${i}) == 1 ? 1 : -1];\n");
}
print { $code } ("#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__\n");
print { $code } ("#define onechar(c, s, l) (((uint64_t)(c)) << (s))\n");
print { $code } ("#else\n");
print { $code } ("#define onechar(c, s, l) (((uint64_t)(c)) << (l-8-s))\n");
print { $code } ("#endif\n");
print { $code } ("#if (!defined(__ARM_ARCH) || defined(__ARM_FEATURE_UNALIGNED)) && !defined(TRIE_HASH_NO_MULTI_BYTE)\n");
print { $code } ("#define TRIE_HASH_MULTI_BYTE\n");
print { $code } ("#endif\n");
print { $code } ("#endif /*GNUC */\n");
print { $code } ("#ifdef TRIE_HASH_MULTI_BYTE\n");
$self->print_functions($trie, %lengths);
$multi_byte = 0;
print { $code } ("#else\n");
$self->print_functions($trie, %lengths);
print { $code } ("#endif /* TRIE_HASH_MULTI_BYTE */\n");
} else {
$self->print_functions($trie, %lengths);
}
print { $code } ("${static}enum ${enum_name} ${function_name}(const char *string, size_t length)\n");
print { $code } ("{\n");
print { $code } (" switch (length) {\n");
foreach my $local_length (sort { $a <=> $b } (keys %lengths)) {
print { $code } (" case $local_length:\n");
print { $code } (" return ${function_name}${local_length}(string);\n");
}
print { $code } (" default:\n");
printf { $code } (" return %s$unknown_label;\n", ($enum_class ? "${enum_name}::" : ''));
print { $code } (" }\n");
print { $code } ("}\n");
# Print end of header here, in case header and code point to the same file
print { $header } ("#endif /* TRIE_HASH_${function_name} */\n");
}
}
# A character is ambiguous if the 1<<5 (0x20) bit does not correspond to the
# lower case bit. A word is ambiguous if any character is. This definition is
# used to check if we can perform the |0x20 optimization when building a case-
# insensitive trie.
sub ambiguous {
my $word = shift;
foreach my $char (split //, $word) {
# If 0x20 does not solely indicate lowercase, it is ambiguous
return 1 if ord(lc($char)) != (ord($char) | 0x20);
return 1 if ord(uc($char)) != (ord($char) & ~0x20);
}
return 0;
}
sub build_trie {
my $codegen = shift;
my $trie = Trie->new;
my $counter = $counter_start;
my $prev_value;
my %lengths;
open(my $input, '<', $ARGV[0]) or die "Cannot open $ARGV[0]: $!";
while (my $line = <$input>) {
my ($label, $word, $value) = $line =~ m{
(?:\s*([^~\s]+)\s*~)? # Label ~
(?:\s*([^~=\s]+))? # Word
(?:\s*=\s*([^\s]+)\s+)? # = Value
\s*
}x;
if (defined $word) {
$label //= $codegen->word_to_label($word);
$value //= defined $prev_value ? $prev_value + 1 : 0;
$trie->insert($word, $label, $value);
$lengths{length($word)} = 1;
} elsif (defined $value) {
$unknown = $value;
$unknown_label = $codegen->mangle_label($label) if defined $label;
} else {
die "Invalid line: $line";
}
$prev_value = $value;
$counter = $value + 1 if $value >= $counter;
}
$unknown_label //= $codegen->mangle_label('Unknown');
return ($trie, $counter, %lengths);
}
# Generates an ASCII art tree
package TreeCodeGen {
sub new {
my $class = shift;
my $self = {};
bless $self, $class;
return $self;
}
sub mangle_label {
my ($self, $label) = @_;
return $label;
}
sub word_to_label {
my ($self, $word) = @_;
return $word;
}
sub main {
my ($self, $trie, $counter, %lengths) = @_;
printf { $code } ("┌────────────────────────────────────────────────────┐\n");
printf { $code } ("│ Initial trie │\n");
printf { $code } ("└────────────────────────────────────────────────────┘\n");
$self->print($trie);
printf { $code } ("┌────────────────────────────────────────────────────┐\n");
printf { $code } ("│ Rebuilt trie │\n");
printf { $code } ("└────────────────────────────────────────────────────┘\n");
$self->print($trie->rebuild_tree());
foreach my $local_length (sort { $a <=> $b } (keys %lengths)) {
printf { $code } ("┌────────────────────────────────────────────────────┐\n");
printf { $code } ("│ Trie for words of length %-4d │\n", $local_length);
printf { $code } ("└────────────────────────────────────────────────────┘\n");
$self->print($trie->filter_depth($local_length)->rebuild_tree());
}
}
sub open_output {
my $self = shift;
if ($code_name ne '-') {
open($code, '>:encoding(utf8)', $code_name) or die "Cannot open $ARGV[0]: $!" ;
} else {
$code = *STDOUT;
binmode($code, ':encoding(utf8)');
}
}
# Print a trie
sub print {
my ($self, $trie, $depth) = @_;
$depth //= 0;
print { $code } (' → ') if defined($trie->{label});
print { $code } ($trie->{label} // '', "\n");
foreach my $key (sort keys %{$trie->{children}}) {
print { $code } ('│ ' x ($depth), "├── $key");
$self->print($trie->{children}{$key}, $depth + 1);
}
}
}
my %codegens = (
C => 'CCodeGen',
tree => 'TreeCodeGen',
);
defined($codegens{$language}) or die "Unknown language $language. Valid choices: ", join(', ', keys %codegens);
my $codegen = $codegens{$language}->new();
my ($trie, $counter, %lengths) = build_trie($codegen);
$codegen->open_output();
$codegen->main($trie, $counter, %lengths);
=head1 LICENSE
triehash is available under the MIT/Expat license, see the source code
for more information.
=head1 AUTHOR
Julian Andres Klode <jak@jak-linux.org>
=cut

View File

@@ -0,0 +1,142 @@
SUMMARY = "Advanced front-end for dpkg"
DESCRIPTION = "APT is the Advanced Package Tool, an advanced interface to the Debian packaging system which provides the apt-get program."
HOMEPAGE = "https://packages.debian.org/sid/apt"
LICENSE = "GPL-2.0-or-later"
SECTION = "base"
# Triehash script taken from https://github.com/julian-klode/triehash
SRC_URI = "${DEBIAN_MIRROR}/main/a/apt/${BPN}_${PV}.tar.xz \
file://triehash \
file://0001-Disable-documentation-directory-altogether.patch \
file://0001-Fix-musl-build.patch \
file://0001-CMakeLists.txt-avoid-changing-install-paths-based-on.patch \
file://0001-cmake-Do-not-build-po-files.patch \
file://0001-Hide-fstatat64-and-prlimit64-defines-on-musl.patch \
file://0001-aptwebserver.cc-Include-array.patch \
file://0001-Remove-using-std-binary_function.patch \
"
SRC_URI:append:class-native = " \
file://0001-Do-not-init-tables-from-dpkg-configuration.patch \
file://0001-Revert-always-run-dpkg-configure-a-at-the-end-of-our.patch \
"
SRC_URI:append:class-nativesdk = " \
file://0001-Do-not-init-tables-from-dpkg-configuration.patch \
file://0001-Revert-always-run-dpkg-configure-a-at-the-end-of-our.patch \
"
SRC_URI[sha256sum] = "86b888c901fa2e78f1bf52a2aaa2f400ff82a472b94ff0ac6631939ee68fa6fd"
LIC_FILES_CHKSUM = "file://COPYING.GPL;md5=b234ee4d69f5fce4486a80fdaf4a4263"
# the package is taken from snapshots.debian.org; that source is static and goes stale
# so we check the latest upstream from a directory that does get updated
UPSTREAM_CHECK_URI = "${DEBIAN_MIRROR}/main/a/apt/"
# apt seems to follow a peculiar version policy, where every *other* even version
# is considered stable, e.g. 1.0, 1.4, 1.8, 2.2, 2.6, etc. As there is no way
# to express 'divisible by 4 plus 2' in regex (that I know of), let's hardcode a few.
UPSTREAM_CHECK_REGEX = "[^\d\.](?P<pver>((2\.2)|(2\.6)|(3\.0)|(3\.4)|(3\.8)|(4\.2))(\.\d+)+)\.tar"
inherit cmake perlnative bash-completion useradd
# User is added to allow apt to drop privs, will runtime warn without
USERADD_PACKAGES = "${PN}"
USERADD_PARAM:${PN} = "--system --home /nonexistent --no-create-home _apt"
BBCLASSEXTEND = "native nativesdk"
DEPENDS += "db gnutls lz4 zlib bzip2 xz libgcrypt xxhash"
EXTRA_OECMAKE:append = " -DCURRENT_VENDOR=debian -DWITH_DOC=False \
-DDPKG_DATADIR=${datadir}/dpkg \
-DTRIEHASH_EXECUTABLE=${WORKDIR}/triehash \
-DCMAKE_DISABLE_FIND_PACKAGE_ZSTD=True \
-DCMAKE_DISABLE_FIND_PACKAGE_SECCOMP=True \
-DWITH_TESTS=False \
"
do_configure:prepend() {
echo "set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE BOTH )" >> ${WORKDIR}/toolchain.cmake
}
# Unfortunately apt hardcodes this all over the place
FILES:${PN} += "${prefix}/lib/dpkg ${prefix}/lib/apt"
RDEPENDS:${PN} += "bash perl dpkg"
customize_apt_conf_sample() {
cat > ${D}${sysconfdir}/apt/apt.conf.sample << EOF
Dir "${STAGING_DIR_NATIVE}/"
{
State "var/lib/apt/"
{
Lists "#APTCONF#/lists/";
status "#ROOTFS#/var/lib/dpkg/status";
};
Cache "var/cache/apt/"
{
Archives "archives/";
pkgcache "";
srcpkgcache "";
};
Bin "${STAGING_BINDIR_NATIVE}/"
{
methods "${STAGING_LIBDIR}/apt/methods/";
gzip "/bin/gzip";
dpkg "dpkg";
dpkg-source "dpkg-source";
dpkg-buildpackage "dpkg-buildpackage";
apt-get "apt-get";
apt-cache "apt-cache";
};
Etc "#APTCONF#"
{
Preferences "preferences";
};
Log "var/log/apt";
};
APT
{
Install-Recommends "true";
Immediate-Configure "false";
Architecture "i586";
Get
{
Assume-Yes "true";
};
};
Acquire
{
AllowInsecureRepositories "true";
};
DPkg::Options {"--root=#ROOTFS#";"--admindir=#ROOTFS#/var/lib/dpkg";"--force-all";"--no-force-overwrite";"--no-debsig"};
DPkg::Path "";
EOF
}
do_install:append:class-native() {
customize_apt_conf_sample
}
do_install:append:class-nativesdk() {
customize_apt_conf_sample
rm -rf ${D}${localstatedir}/log
}
do_install:append:class-target() {
# Write the correct apt-architecture to apt.conf
APT_CONF=${D}${sysconfdir}/apt/apt.conf
echo 'APT::Architecture "${DPKG_ARCH}";' > ${APT_CONF}
# Remove /var/log/apt. /var/log is normally a link to /var/volatile/log
# and /var/volatile is a tmpfs mount. So anything created in /var/log
# will not be available when the tmpfs is mounted.
rm -rf ${D}${localstatedir}/log
}
do_install:append() {
# Avoid non-reproducible -src package
sed -i -e "s,${B}/include/,,g" ${B}/apt-pkg/tagfile-keys.cc
}