summaryrefslogtreecommitdiffstats
path: root/meta/lib
diff options
context:
space:
mode:
Diffstat (limited to 'meta/lib')
-rw-r--r--meta/lib/bblayers/buildconf.py85
-rw-r--r--meta/lib/bblayers/create.py81
-rw-r--r--meta/lib/bblayers/makesetup.py107
-rw-r--r--meta/lib/bblayers/setupwriters/oe-setup-layers.py50
-rw-r--r--meta/lib/bblayers/templates/README41
-rw-r--r--meta/lib/bblayers/templates/example.bb13
-rw-r--r--meta/lib/bblayers/templates/layer.conf13
-rw-r--r--meta/lib/buildstats.py215
-rw-r--r--meta/lib/oe/__init__.py10
-rw-r--r--meta/lib/oe/buildcfg.py49
-rw-r--r--meta/lib/oe/buildhistory_analysis.py379
-rw-r--r--meta/lib/oe/cachedpath.py4
-rw-r--r--meta/lib/oe/classextend.py58
-rw-r--r--meta/lib/oe/classutils.py7
-rw-r--r--meta/lib/oe/copy_buildsystem.py105
-rw-r--r--meta/lib/oe/cve_check.py181
-rw-r--r--meta/lib/oe/data.py40
-rw-r--r--meta/lib/oe/distro_check.py315
-rw-r--r--meta/lib/oe/elf.py145
-rw-r--r--meta/lib/oe/gpg_sign.py120
-rw-r--r--meta/lib/oe/license.py96
-rw-r--r--meta/lib/oe/lsb.py93
-rw-r--r--meta/lib/oe/maketype.py9
-rw-r--r--meta/lib/oe/manifest.py162
-rw-r--r--meta/lib/oe/npm_registry.py175
-rw-r--r--meta/lib/oe/overlayfs.py54
-rw-r--r--meta/lib/oe/package.py1983
-rw-r--r--meta/lib/oe/package_manager.py2276
-rw-r--r--meta/lib/oe/package_manager/__init__.py558
-rw-r--r--meta/lib/oe/package_manager/deb/__init__.py522
-rw-r--r--meta/lib/oe/package_manager/deb/manifest.py28
-rw-r--r--meta/lib/oe/package_manager/deb/rootfs.py212
-rw-r--r--meta/lib/oe/package_manager/deb/sdk.py102
-rw-r--r--meta/lib/oe/package_manager/ipk/__init__.py510
-rw-r--r--meta/lib/oe/package_manager/ipk/manifest.py76
-rw-r--r--meta/lib/oe/package_manager/ipk/rootfs.py352
-rw-r--r--meta/lib/oe/package_manager/ipk/sdk.py104
-rw-r--r--meta/lib/oe/package_manager/rpm/__init__.py421
-rw-r--r--meta/lib/oe/package_manager/rpm/manifest.py56
-rw-r--r--meta/lib/oe/package_manager/rpm/rootfs.py150
-rw-r--r--meta/lib/oe/package_manager/rpm/sdk.py116
-rw-r--r--meta/lib/oe/packagedata.py272
-rw-r--r--meta/lib/oe/packagegroup.py16
-rw-r--r--meta/lib/oe/patch.py263
-rw-r--r--meta/lib/oe/path.py159
-rw-r--r--meta/lib/oe/prservice.py119
-rw-r--r--meta/lib/oe/qa.py156
-rw-r--r--meta/lib/oe/recipeutils.py530
-rw-r--r--meta/lib/oe/reproducible.py194
-rw-r--r--meta/lib/oe/rootfs.py900
-rw-r--r--meta/lib/oe/rust.py13
-rw-r--r--meta/lib/oe/sbom.py80
-rw-r--r--meta/lib/oe/sdk.py349
-rw-r--r--meta/lib/oe/spdx.py344
-rw-r--r--meta/lib/oe/sstatesig.py522
-rw-r--r--meta/lib/oe/terminal.py133
-rw-r--r--meta/lib/oe/tests/test_license.py68
-rw-r--r--meta/lib/oe/tests/test_utils.py51
-rw-r--r--meta/lib/oe/types.py39
-rw-r--r--meta/lib/oe/useradd.py71
-rw-r--r--meta/lib/oe/utils.py481
-rw-r--r--meta/lib/oeqa/buildperf/__init__.py18
-rw-r--r--meta/lib/oeqa/buildperf/base.py650
-rw-r--r--meta/lib/oeqa/buildperf/basic_tests.py133
-rw-r--r--meta/lib/oeqa/buildperf/test_basic.py120
-rw-r--r--meta/lib/oeqa/controllers/__init__.py5
-rw-r--r--meta/lib/oeqa/controllers/controllerimage.py (renamed from meta/lib/oeqa/controllers/masterimage.py)110
-rw-r--r--meta/lib/oeqa/controllers/testtargetloader.py8
-rw-r--r--meta/lib/oeqa/core/README76
-rw-r--r--meta/lib/oeqa/core/__init__.py (renamed from meta/lib/oe/tests/__init__.py)0
-rw-r--r--meta/lib/oeqa/core/case.py105
-rw-r--r--meta/lib/oeqa/core/cases/__init__.py0
-rw-r--r--meta/lib/oeqa/core/cases/example/data.json1
-rw-r--r--meta/lib/oeqa/core/cases/example/test_basic.py22
-rw-r--r--meta/lib/oeqa/core/context.py246
-rw-r--r--meta/lib/oeqa/core/decorator/__init__.py74
-rw-r--r--meta/lib/oeqa/core/decorator/data.py220
-rw-r--r--meta/lib/oeqa/core/decorator/depends.py98
-rw-r--r--meta/lib/oeqa/core/decorator/oetimeout.py29
-rw-r--r--meta/lib/oeqa/core/exception.py26
-rw-r--r--meta/lib/oeqa/core/loader.py342
-rw-r--r--meta/lib/oeqa/core/runner.py353
-rw-r--r--meta/lib/oeqa/core/target/__init__.py36
-rw-r--r--meta/lib/oeqa/core/target/qemu.py105
-rw-r--r--meta/lib/oeqa/core/target/ssh.py295
-rw-r--r--meta/lib/oeqa/core/tests/__init__.py0
-rw-r--r--meta/lib/oeqa/core/tests/cases/data.py23
-rw-r--r--meta/lib/oeqa/core/tests/cases/depends.py41
-rw-r--r--meta/lib/oeqa/core/tests/cases/loader/valid/another.py12
-rw-r--r--meta/lib/oeqa/core/tests/cases/oetag.py38
-rw-r--r--meta/lib/oeqa/core/tests/cases/timeout.py34
-rw-r--r--meta/lib/oeqa/core/tests/common.py38
-rwxr-xr-xmeta/lib/oeqa/core/tests/test_data.py55
-rwxr-xr-xmeta/lib/oeqa/core/tests/test_decorators.py143
-rwxr-xr-xmeta/lib/oeqa/core/tests/test_loader.py63
-rwxr-xr-xmeta/lib/oeqa/core/tests/test_runner.py40
-rw-r--r--meta/lib/oeqa/core/utils/__init__.py0
-rw-r--r--meta/lib/oeqa/core/utils/concurrencytest.py335
-rw-r--r--meta/lib/oeqa/core/utils/path.py22
-rw-r--r--meta/lib/oeqa/core/utils/test.py89
-rw-r--r--meta/lib/oeqa/files/buildhistory_filelist1.txt9214
-rw-r--r--meta/lib/oeqa/files/buildhistory_filelist2.txt9217
-rw-r--r--meta/lib/oeqa/files/test.c (renamed from meta/lib/oeqa/runtime/files/test.c)0
-rw-r--r--meta/lib/oeqa/files/test.cpp (renamed from meta/lib/oeqa/runtime/files/test.cpp)0
-rw-r--r--meta/lib/oeqa/files/test.rs2
-rw-r--r--meta/lib/oeqa/files/testresults/testresults.json40
-rw-r--r--meta/lib/oeqa/manual/abat.patch64
-rw-r--r--meta/lib/oeqa/manual/bsp-hw.json626
-rw-r--r--meta/lib/oeqa/manual/build-appliance.json96
-rw-r--r--meta/lib/oeqa/manual/crops.json294
-rw-r--r--meta/lib/oeqa/manual/eclipse-plugin.json322
-rw-r--r--meta/lib/oeqa/manual/kernel-dev.json200
-rw-r--r--meta/lib/oeqa/manual/oe-core.json158
-rw-r--r--meta/lib/oeqa/manual/sdk.json32
-rw-r--r--meta/lib/oeqa/manual/toaster-managed-mode.json2572
-rw-r--r--meta/lib/oeqa/manual/toaster-unmanaged-mode.json1170
-rw-r--r--meta/lib/oeqa/oetest.py211
-rwxr-xr-xmeta/lib/oeqa/runexported.py20
-rw-r--r--meta/lib/oeqa/runtime/_ptest.py125
-rw-r--r--meta/lib/oeqa/runtime/_qemutiny.py9
-rw-r--r--meta/lib/oeqa/runtime/buildcvs.py31
-rw-r--r--meta/lib/oeqa/runtime/buildgalculator.py23
-rw-r--r--meta/lib/oeqa/runtime/buildiptables.py31
-rw-r--r--meta/lib/oeqa/runtime/case.py20
-rw-r--r--meta/lib/oeqa/runtime/cases/_qemutiny.py14
-rw-r--r--meta/lib/oeqa/runtime/cases/apt.py79
-rw-r--r--meta/lib/oeqa/runtime/cases/boot.py35
-rw-r--r--meta/lib/oeqa/runtime/cases/buildcpio.py35
-rw-r--r--meta/lib/oeqa/runtime/cases/buildgalculator.py34
-rw-r--r--meta/lib/oeqa/runtime/cases/buildlzip.py36
-rw-r--r--meta/lib/oeqa/runtime/cases/connman.py33
-rw-r--r--meta/lib/oeqa/runtime/cases/date.py43
-rw-r--r--meta/lib/oeqa/runtime/cases/df.py21
-rw-r--r--meta/lib/oeqa/runtime/cases/dnf.py173
-rw-r--r--meta/lib/oeqa/runtime/cases/ethernet_ip_connman.py42
-rw-r--r--meta/lib/oeqa/runtime/cases/gcc.py71
-rw-r--r--meta/lib/oeqa/runtime/cases/gi.py21
-rw-r--r--meta/lib/oeqa/runtime/cases/go.py21
-rw-r--r--meta/lib/oeqa/runtime/cases/gstreamer.py20
-rw-r--r--meta/lib/oeqa/runtime/cases/kernelmodule.py48
-rw-r--r--meta/lib/oeqa/runtime/cases/ksample.py233
-rw-r--r--meta/lib/oeqa/runtime/cases/ldd.py28
-rw-r--r--meta/lib/oeqa/runtime/cases/logrotate.py73
-rw-r--r--meta/lib/oeqa/runtime/cases/ltp.py119
-rw-r--r--meta/lib/oeqa/runtime/cases/ltp_compliance.py97
-rw-r--r--meta/lib/oeqa/runtime/cases/ltp_stress.py97
-rw-r--r--meta/lib/oeqa/runtime/cases/multilib.py49
-rw-r--r--meta/lib/oeqa/runtime/cases/oe_syslog.py138
-rw-r--r--meta/lib/oeqa/runtime/cases/opkg.py60
-rw-r--r--meta/lib/oeqa/runtime/cases/pam.py40
-rw-r--r--meta/lib/oeqa/runtime/cases/parselogs.py393
-rw-r--r--meta/lib/oeqa/runtime/cases/perl.py19
-rw-r--r--meta/lib/oeqa/runtime/cases/ping.py32
-rw-r--r--meta/lib/oeqa/runtime/cases/ptest.py114
-rw-r--r--meta/lib/oeqa/runtime/cases/python.py21
-rw-r--r--meta/lib/oeqa/runtime/cases/rpm.py145
-rw-r--r--meta/lib/oeqa/runtime/cases/rt.py19
-rw-r--r--meta/lib/oeqa/runtime/cases/rtc.py43
-rw-r--r--meta/lib/oeqa/runtime/cases/runlevel.py27
-rw-r--r--meta/lib/oeqa/runtime/cases/rust.py62
-rw-r--r--meta/lib/oeqa/runtime/cases/scons.py39
-rw-r--r--meta/lib/oeqa/runtime/cases/scp.py39
-rw-r--r--meta/lib/oeqa/runtime/cases/skeletoninit.py37
-rw-r--r--meta/lib/oeqa/runtime/cases/ssh.py21
-rw-r--r--meta/lib/oeqa/runtime/cases/stap.py34
-rw-r--r--meta/lib/oeqa/runtime/cases/storage.py151
-rw-r--r--meta/lib/oeqa/runtime/cases/suspend.py38
-rw-r--r--meta/lib/oeqa/runtime/cases/systemd.py196
-rw-r--r--meta/lib/oeqa/runtime/cases/terminal.py26
-rw-r--r--meta/lib/oeqa/runtime/cases/usb_hid.py27
-rw-r--r--meta/lib/oeqa/runtime/cases/weston.py89
-rw-r--r--meta/lib/oeqa/runtime/cases/x32lib.py28
-rw-r--r--meta/lib/oeqa/runtime/cases/xorg.py23
-rw-r--r--meta/lib/oeqa/runtime/connman.py31
-rw-r--r--meta/lib/oeqa/runtime/context.py226
-rw-r--r--meta/lib/oeqa/runtime/date.py31
-rw-r--r--meta/lib/oeqa/runtime/decorator/package.py89
-rw-r--r--meta/lib/oeqa/runtime/df.py12
-rw-r--r--meta/lib/oeqa/runtime/files/SConstruct1
-rw-r--r--meta/lib/oeqa/runtime/files/hello.c5
-rw-r--r--meta/lib/oeqa/runtime/files/test.pl2
-rw-r--r--meta/lib/oeqa/runtime/files/test.py6
-rw-r--r--meta/lib/oeqa/runtime/gcc.py47
-rw-r--r--meta/lib/oeqa/runtime/kernelmodule.py34
-rw-r--r--meta/lib/oeqa/runtime/ldd.py21
-rw-r--r--meta/lib/oeqa/runtime/loader.py19
-rw-r--r--meta/lib/oeqa/runtime/logrotate.py28
-rw-r--r--meta/lib/oeqa/runtime/multilib.py42
-rw-r--r--meta/lib/oeqa/runtime/pam.py25
-rw-r--r--meta/lib/oeqa/runtime/parselogs.py277
-rw-r--r--meta/lib/oeqa/runtime/perl.py30
-rw-r--r--meta/lib/oeqa/runtime/ping.py22
-rw-r--r--meta/lib/oeqa/runtime/python.py35
-rw-r--r--meta/lib/oeqa/runtime/rpm.py101
-rw-r--r--meta/lib/oeqa/runtime/scanelf.py28
-rw-r--r--meta/lib/oeqa/runtime/scp.py22
-rw-r--r--meta/lib/oeqa/runtime/skeletoninit.py29
-rw-r--r--meta/lib/oeqa/runtime/smart.py175
-rw-r--r--meta/lib/oeqa/runtime/ssh.py19
-rw-r--r--meta/lib/oeqa/runtime/syslog.py44
-rw-r--r--meta/lib/oeqa/runtime/systemd.py178
-rw-r--r--meta/lib/oeqa/runtime/utils/__init__.py0
-rw-r--r--meta/lib/oeqa/runtime/utils/targetbuildproject.py44
-rw-r--r--meta/lib/oeqa/runtime/x32lib.py18
-rw-r--r--meta/lib/oeqa/runtime/xorg.py16
-rw-r--r--meta/lib/oeqa/sdk/__init__.py3
-rw-r--r--meta/lib/oeqa/sdk/buildcvs.py25
-rw-r--r--meta/lib/oeqa/sdk/buildgalculator.py24
-rw-r--r--meta/lib/oeqa/sdk/buildiptables.py26
-rw-r--r--meta/lib/oeqa/sdk/buildtools-cases/README2
-rw-r--r--meta/lib/oeqa/sdk/buildtools-cases/build.py32
-rw-r--r--meta/lib/oeqa/sdk/buildtools-cases/gcc.py31
-rw-r--r--meta/lib/oeqa/sdk/buildtools-cases/https.py22
-rw-r--r--meta/lib/oeqa/sdk/buildtools-cases/sanity.py24
-rw-r--r--meta/lib/oeqa/sdk/buildtools-docs-cases/README2
-rw-r--r--meta/lib/oeqa/sdk/buildtools-docs-cases/build.py19
-rw-r--r--meta/lib/oeqa/sdk/case.py54
-rw-r--r--meta/lib/oeqa/sdk/cases/assimp.py42
-rw-r--r--meta/lib/oeqa/sdk/cases/buildcpio.py38
-rw-r--r--meta/lib/oeqa/sdk/cases/buildepoxy.py44
-rw-r--r--meta/lib/oeqa/sdk/cases/buildgalculator.py46
-rw-r--r--meta/lib/oeqa/sdk/cases/buildlzip.py39
-rw-r--r--meta/lib/oeqa/sdk/cases/gcc.py52
-rw-r--r--meta/lib/oeqa/sdk/cases/perl.py22
-rw-r--r--meta/lib/oeqa/sdk/cases/python.py22
-rw-r--r--meta/lib/oeqa/sdk/cases/rust.py35
-rw-r--r--meta/lib/oeqa/sdk/context.py153
-rw-r--r--meta/lib/oeqa/sdk/files/rust/hello/Cargo.toml6
-rw-r--r--meta/lib/oeqa/sdk/files/rust/hello/build.rs3
-rw-r--r--meta/lib/oeqa/sdk/files/rust/hello/src/main.rs3
-rw-r--r--meta/lib/oeqa/sdk/files/testsdkmakefile (renamed from meta/lib/oeqa/runtime/files/testsdkmakefile)0
-rw-r--r--meta/lib/oeqa/sdk/gcc.py36
-rw-r--r--meta/lib/oeqa/sdk/perl.py28
-rw-r--r--meta/lib/oeqa/sdk/python.py32
-rw-r--r--meta/lib/oeqa/sdk/testmetaidesupport.py45
-rw-r--r--meta/lib/oeqa/sdk/testsdk.py145
-rw-r--r--meta/lib/oeqa/sdk/utils/__init__.py0
-rw-r--r--meta/lib/oeqa/sdk/utils/sdkbuildproject.py53
-rw-r--r--meta/lib/oeqa/sdkext/__init__.py3
-rw-r--r--meta/lib/oeqa/sdkext/case.py24
-rw-r--r--meta/lib/oeqa/sdkext/cases/devtool.py126
-rw-r--r--meta/lib/oeqa/sdkext/context.py32
-rw-r--r--meta/lib/oeqa/sdkext/devtool.py32
-rw-r--r--meta/lib/oeqa/sdkext/files/myapp_cmake/CMakeLists.txt11
-rw-r--r--meta/lib/oeqa/sdkext/files/myapp_cmake/myapp.c9
-rw-r--r--meta/lib/oeqa/sdkext/sdk_update.py36
-rw-r--r--meta/lib/oeqa/sdkext/testsdk.py107
-rw-r--r--meta/lib/oeqa/selftest/__init__.py2
-rw-r--r--meta/lib/oeqa/selftest/_toaster.py320
-rw-r--r--meta/lib/oeqa/selftest/archiver.py50
-rw-r--r--meta/lib/oeqa/selftest/base.py205
-rw-r--r--meta/lib/oeqa/selftest/bbtests.py272
-rw-r--r--meta/lib/oeqa/selftest/buildoptions.py215
-rw-r--r--meta/lib/oeqa/selftest/case.py262
-rw-r--r--meta/lib/oeqa/selftest/cases/_sstatetests_noauto.py (renamed from meta/lib/oeqa/selftest/_sstatetests_noauto.py)19
-rw-r--r--meta/lib/oeqa/selftest/cases/archiver.py345
-rw-r--r--meta/lib/oeqa/selftest/cases/baremetal.py14
-rw-r--r--meta/lib/oeqa/selftest/cases/bblayers.py (renamed from meta/lib/oeqa/selftest/bblayers.py)110
-rw-r--r--meta/lib/oeqa/selftest/cases/bblogging.py188
-rw-r--r--meta/lib/oeqa/selftest/cases/bbtests.py353
-rw-r--r--meta/lib/oeqa/selftest/cases/binutils.py51
-rw-r--r--meta/lib/oeqa/selftest/cases/buildhistory.py (renamed from meta/lib/oeqa/selftest/buildhistory.py)16
-rw-r--r--meta/lib/oeqa/selftest/cases/buildoptions.py239
-rw-r--r--meta/lib/oeqa/selftest/cases/containerimage.py89
-rw-r--r--meta/lib/oeqa/selftest/cases/cve_check.py207
-rw-r--r--meta/lib/oeqa/selftest/cases/debuginfod.py106
-rw-r--r--meta/lib/oeqa/selftest/cases/devtool.py (renamed from meta/lib/oeqa/selftest/devtool.py)1171
-rw-r--r--meta/lib/oeqa/selftest/cases/diffoscope/A/file.txt1
-rw-r--r--meta/lib/oeqa/selftest/cases/diffoscope/B/file.txt1
-rw-r--r--meta/lib/oeqa/selftest/cases/distrodata.py153
-rw-r--r--meta/lib/oeqa/selftest/cases/eSDK.py122
-rw-r--r--meta/lib/oeqa/selftest/cases/efibootpartition.py33
-rw-r--r--meta/lib/oeqa/selftest/cases/externalsrc.py44
-rw-r--r--meta/lib/oeqa/selftest/cases/fetch.py108
-rw-r--r--meta/lib/oeqa/selftest/cases/fitimage.py846
-rw-r--r--meta/lib/oeqa/selftest/cases/gcc.py163
-rw-r--r--meta/lib/oeqa/selftest/cases/gdbserver.py66
-rw-r--r--meta/lib/oeqa/selftest/cases/glibc.py94
-rw-r--r--meta/lib/oeqa/selftest/cases/gotoolchain.py74
-rw-r--r--meta/lib/oeqa/selftest/cases/image_typedep.py60
-rw-r--r--meta/lib/oeqa/selftest/cases/imagefeatures.py301
-rw-r--r--meta/lib/oeqa/selftest/cases/incompatible_lic.py162
-rw-r--r--meta/lib/oeqa/selftest/cases/intercept.py21
-rw-r--r--meta/lib/oeqa/selftest/cases/kerneldevelopment.py73
-rw-r--r--meta/lib/oeqa/selftest/cases/layerappend.py (renamed from meta/lib/oeqa/selftest/layerappend.py)34
-rw-r--r--meta/lib/oeqa/selftest/cases/liboe.py104
-rw-r--r--meta/lib/oeqa/selftest/cases/lic_checksum.py (renamed from meta/lib/oeqa/selftest/lic-checksum.py)35
-rw-r--r--meta/lib/oeqa/selftest/cases/locales.py54
-rw-r--r--meta/lib/oeqa/selftest/cases/manifest.py (renamed from meta/lib/oeqa/selftest/manifest.py)61
-rw-r--r--meta/lib/oeqa/selftest/cases/meta_ide.py59
-rw-r--r--meta/lib/oeqa/selftest/cases/minidebuginfo.py43
-rw-r--r--meta/lib/oeqa/selftest/cases/multiconfig.py87
-rw-r--r--meta/lib/oeqa/selftest/cases/newlib.py13
-rw-r--r--meta/lib/oeqa/selftest/cases/oelib/__init__.py0
-rw-r--r--meta/lib/oeqa/selftest/cases/oelib/buildhistory.py147
-rw-r--r--meta/lib/oeqa/selftest/cases/oelib/elf.py28
-rw-r--r--meta/lib/oeqa/selftest/cases/oelib/license.py105
-rw-r--r--meta/lib/oeqa/selftest/cases/oelib/path.py (renamed from meta/lib/oe/tests/test_path.py)20
-rw-r--r--meta/lib/oeqa/selftest/cases/oelib/types.py (renamed from meta/lib/oe/tests/test_types.py)24
-rw-r--r--meta/lib/oeqa/selftest/cases/oelib/utils.py104
-rw-r--r--meta/lib/oeqa/selftest/cases/oescripts.py185
-rw-r--r--meta/lib/oeqa/selftest/cases/overlayfs.py488
-rw-r--r--meta/lib/oeqa/selftest/cases/package.py177
-rw-r--r--meta/lib/oeqa/selftest/cases/pkgdata.py (renamed from meta/lib/oeqa/selftest/pkgdata.py)85
-rw-r--r--meta/lib/oeqa/selftest/cases/prservice.py (renamed from meta/lib/oeqa/selftest/prservice.py)49
-rw-r--r--meta/lib/oeqa/selftest/cases/pseudo.py29
-rw-r--r--meta/lib/oeqa/selftest/cases/recipetool.py (renamed from meta/lib/oeqa/selftest/recipetool.py)499
-rw-r--r--meta/lib/oeqa/selftest/cases/recipeutils.py138
-rw-r--r--meta/lib/oeqa/selftest/cases/reproducible.py316
-rw-r--r--meta/lib/oeqa/selftest/cases/resulttooltests.py100
-rw-r--r--meta/lib/oeqa/selftest/cases/rootfspostcommandstests.py97
-rw-r--r--meta/lib/oeqa/selftest/cases/rpmtests.py14
-rw-r--r--meta/lib/oeqa/selftest/cases/runcmd.py124
-rw-r--r--meta/lib/oeqa/selftest/cases/runqemu.py210
-rw-r--r--meta/lib/oeqa/selftest/cases/runtime_test.py480
-rw-r--r--meta/lib/oeqa/selftest/cases/selftest.py54
-rw-r--r--meta/lib/oeqa/selftest/cases/signing.py228
-rw-r--r--meta/lib/oeqa/selftest/cases/sstate.py (renamed from meta/lib/oeqa/selftest/sstate.py)41
-rw-r--r--meta/lib/oeqa/selftest/cases/sstatetests.py627
-rw-r--r--meta/lib/oeqa/selftest/cases/sysroot.py86
-rw-r--r--meta/lib/oeqa/selftest/cases/tinfoil.py229
-rw-r--r--meta/lib/oeqa/selftest/cases/wic.py1497
-rw-r--r--meta/lib/oeqa/selftest/cases/wrapper.py16
-rw-r--r--meta/lib/oeqa/selftest/context.py412
-rw-r--r--meta/lib/oeqa/selftest/imagefeatures.py127
-rw-r--r--meta/lib/oeqa/selftest/oescripts.py54
-rw-r--r--meta/lib/oeqa/selftest/signing.py178
-rw-r--r--meta/lib/oeqa/selftest/sstatetests.py467
-rw-r--r--meta/lib/oeqa/selftest/testexport.py44
-rw-r--r--meta/lib/oeqa/selftest/wic.py286
-rw-r--r--meta/lib/oeqa/targetcontrol.py157
-rw-r--r--meta/lib/oeqa/utils/__init__.py56
-rw-r--r--meta/lib/oeqa/utils/buildproject.py66
-rw-r--r--meta/lib/oeqa/utils/commands.py223
-rw-r--r--meta/lib/oeqa/utils/decorators.py110
-rw-r--r--meta/lib/oeqa/utils/dump.py91
-rw-r--r--meta/lib/oeqa/utils/ftools.py6
-rw-r--r--meta/lib/oeqa/utils/git.py54
-rw-r--r--meta/lib/oeqa/utils/gitarchive.py237
-rw-r--r--meta/lib/oeqa/utils/httpserver.py69
-rw-r--r--meta/lib/oeqa/utils/logparser.py260
-rw-r--r--meta/lib/oeqa/utils/metadata.py124
-rw-r--r--meta/lib/oeqa/utils/network.py10
-rw-r--r--meta/lib/oeqa/utils/nfs.py43
-rw-r--r--meta/lib/oeqa/utils/package_manager.py206
-rw-r--r--meta/lib/oeqa/utils/qemurunner.py689
-rw-r--r--meta/lib/oeqa/utils/qemutinyrunner.py30
-rw-r--r--meta/lib/oeqa/utils/sshcontrol.py33
-rw-r--r--meta/lib/oeqa/utils/subprocesstweak.py24
-rw-r--r--meta/lib/oeqa/utils/targetbuild.py37
-rw-r--r--meta/lib/oeqa/utils/testexport.py18
-rw-r--r--meta/lib/rootfspostcommands.py90
352 files changed, 56799 insertions, 10388 deletions
diff --git a/meta/lib/bblayers/buildconf.py b/meta/lib/bblayers/buildconf.py
new file mode 100644
index 0000000000..ccab332adf
--- /dev/null
+++ b/meta/lib/bblayers/buildconf.py
@@ -0,0 +1,85 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: GPL-2.0-only
+#
+
+import logging
+import os
+import stat
+import sys
+import shutil
+import json
+
+import bb.utils
+import bb.process
+
+from bblayers.common import LayerPlugin
+
+logger = logging.getLogger('bitbake-layers')
+
+sys.path.insert(0, os.path.dirname(os.path.dirname(__file__)))
+
+import oe.buildcfg
+
+def plugin_init(plugins):
+ return BuildConfPlugin()
+
+class BuildConfPlugin(LayerPlugin):
+ notes_fixme = """FIXME: Please place here the description of this build configuration.
+It will be shown to the users when they set up their builds via TEMPLATECONF.
+"""
+
+ def _save_conf(self, templatename, templatepath, oecorepath, relpaths_to_oecore):
+ confdir = os.path.join(os.environ["BBPATH"], "conf")
+ destdir = os.path.join(templatepath, "conf", "templates", templatename)
+ os.makedirs(destdir, exist_ok=True)
+
+ with open(os.path.join(confdir, "local.conf")) as src:
+ with open(os.path.join(destdir, "local.conf.sample"), 'w') as dest:
+ dest.write(src.read())
+
+ with open(os.path.join(confdir, "bblayers.conf")) as src:
+ with open(os.path.join(destdir, "bblayers.conf.sample"), 'w') as dest:
+ bblayers_data = src.read()
+
+ for (abspath, relpath) in relpaths_to_oecore:
+ bblayers_data = bblayers_data.replace(abspath, "##OEROOT##/" + relpath)
+ dest.write(bblayers_data)
+
+ with open(os.path.join(destdir, "conf-notes.txt"), 'w') as dest:
+ dest.write(self.notes_fixme)
+
+ logger.info("""Configuration template placed into {}
+Please review the files in there, and particularly provide a configuration description in {}
+You can try out the configuration with
+TEMPLATECONF={} . {}/oe-init-build-env build-try-{}"""
+.format(destdir, os.path.join(destdir, "conf-notes.txt"), destdir, oecorepath, templatename))
+
+ def do_save_build_conf(self, args):
+ """ Save the currently active build configuration (conf/local.conf, conf/bblayers.conf) as a template into a layer.\n This template can later be used for setting up builds via TEMPLATECONF. """
+ repos = {}
+ layers = oe.buildcfg.get_layer_revisions(self.tinfoil.config_data)
+ targetlayer = None
+ oecore = None
+
+ for l in layers:
+ if os.path.abspath(l[0]) == os.path.abspath(args.layerpath):
+ targetlayer = l[0]
+ if l[1] == 'meta':
+ oecore = os.path.dirname(l[0])
+
+ if not targetlayer:
+ logger.error("Layer {} not in one of the currently enabled layers:\n{}".format(args.layerpath, "\n".join([l[0] for l in layers])))
+ elif not oecore:
+ logger.error("Openembedded-core not in one of the currently enabled layers:\n{}".format("\n".join([l[0] for l in layers])))
+ else:
+ relpaths_to_oecore = [(l[0], os.path.relpath(l[0], start=oecore)) for l in layers]
+ self._save_conf(args.templatename, targetlayer, oecore, relpaths_to_oecore)
+
+ def register_commands(self, sp):
+ parser_build_conf = self.add_command(sp, 'save-build-conf', self.do_save_build_conf, parserecipes=False)
+ parser_build_conf.add_argument('layerpath',
+ help='The path to the layer where the configuration template should be saved.')
+ parser_build_conf.add_argument('templatename',
+ help='The name of the configuration template.')
diff --git a/meta/lib/bblayers/create.py b/meta/lib/bblayers/create.py
new file mode 100644
index 0000000000..c8f3f1b370
--- /dev/null
+++ b/meta/lib/bblayers/create.py
@@ -0,0 +1,81 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: GPL-2.0-only
+#
+
+import logging
+import os
+import sys
+import shutil
+
+import bb.utils
+
+from bblayers.common import LayerPlugin
+
+logger = logging.getLogger('bitbake-layers')
+
+def plugin_init(plugins):
+ return CreatePlugin()
+
+def read_template(template, template_dir='templates'):
+ lines = str()
+ with open(os.path.join(os.path.dirname(__file__), template_dir, template)) as fd:
+ lines = ''.join(fd.readlines())
+ return lines
+
+class CreatePlugin(LayerPlugin):
+ def do_create_layer(self, args):
+ """Create a basic layer"""
+ layerdir = os.path.abspath(args.layerdir)
+ if os.path.exists(layerdir):
+ sys.stderr.write("Specified layer directory exists\n")
+ return 1
+
+ # create dirs
+ conf = os.path.join(layerdir, 'conf')
+ bb.utils.mkdirhier(conf)
+
+ layername = os.path.basename(os.path.normpath(args.layerdir))
+ layerid = args.layerid if args.layerid is not None else layername
+
+ # Create the README from templates/README
+ readme_template = read_template('README').format(layername=layername)
+ readme = os.path.join(layerdir, 'README')
+ with open(readme, 'w') as fd:
+ fd.write(readme_template)
+
+ # Copy the MIT license from meta
+ copying = 'COPYING.MIT'
+ dn = os.path.dirname
+ license_src = os.path.join(dn(dn(dn(__file__))), copying)
+ license_dst = os.path.join(layerdir, copying)
+ shutil.copy(license_src, license_dst)
+
+ # Get the compat value for core layer.
+ compat = self.tinfoil.config_data.getVar('LAYERSERIES_CORENAMES') or ""
+
+ # Create the layer.conf from templates/layer.conf
+ layerconf_template = read_template('layer.conf').format(
+ layerid=layerid, priority=args.priority, compat=compat)
+ layerconf = os.path.join(conf, 'layer.conf')
+ with open(layerconf, 'w') as fd:
+ fd.write(layerconf_template)
+
+ # Create the example from templates/example.bb
+ example_template = read_template('example.bb')
+ example = os.path.join(layerdir, 'recipes-' + args.examplerecipe, args.examplerecipe)
+ bb.utils.mkdirhier(example)
+ with open(os.path.join(example, args.examplerecipe + '_%s.bb') % args.version, 'w') as fd:
+ fd.write(example_template)
+
+ logger.plain('Add your new layer with \'bitbake-layers add-layer %s\'' % args.layerdir)
+
+ def register_commands(self, sp):
+ parser_create_layer = self.add_command(sp, 'create-layer', self.do_create_layer, parserecipes=False)
+ parser_create_layer.add_argument('layerdir', help='Layer directory to create')
+ parser_create_layer.add_argument('--layerid', '-i', help='Layer id to use if different from layername')
+ parser_create_layer.add_argument('--priority', '-p', default=6, help='Priority of recipes in layer')
+ parser_create_layer.add_argument('--example-recipe-name', '-e', dest='examplerecipe', default='example', help='Filename of the example recipe')
+ parser_create_layer.add_argument('--example-recipe-version', '-v', dest='version', default='0.1', help='Version number for the example recipe')
+
diff --git a/meta/lib/bblayers/makesetup.py b/meta/lib/bblayers/makesetup.py
new file mode 100644
index 0000000000..834e9338bc
--- /dev/null
+++ b/meta/lib/bblayers/makesetup.py
@@ -0,0 +1,107 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: GPL-2.0-only
+#
+
+import logging
+import os
+import stat
+import sys
+import shutil
+
+import bb.utils
+import bb.process
+
+from bblayers.common import LayerPlugin
+
+logger = logging.getLogger('bitbake-layers')
+
+sys.path.insert(0, os.path.dirname(os.path.dirname(__file__)))
+
+import oe.buildcfg
+
+def plugin_init(plugins):
+ return MakeSetupPlugin()
+
+class MakeSetupPlugin(LayerPlugin):
+
+ def _get_repo_path(self, layer_path):
+ repo_path, _ = bb.process.run('git rev-parse --show-toplevel', cwd=layer_path)
+ return repo_path.strip()
+
+ def _get_remotes(self, repo_path):
+ remotes = {}
+ remotes_list,_ = bb.process.run('git remote', cwd=repo_path)
+ for r in remotes_list.split():
+ uri,_ = bb.process.run('git remote get-url {r}'.format(r=r), cwd=repo_path)
+ remotes[r] = {'uri':uri.strip()}
+ return remotes
+
+ def _get_describe(self, repo_path):
+ try:
+ describe,_ = bb.process.run('git describe --tags', cwd=repo_path)
+ except bb.process.ExecutionError:
+ return ""
+ return describe.strip()
+
+ def make_repo_config(self, destdir):
+ """ This is a helper function for the writer plugins that discovers currently configured layers.
+ The writers do not have to use it, but it can save a bit of work and avoid duplicated code, hence it is
+ available here. """
+ repos = {}
+ layers = oe.buildcfg.get_layer_revisions(self.tinfoil.config_data)
+ try:
+ destdir_repo = self._get_repo_path(destdir)
+ except bb.process.ExecutionError:
+ destdir_repo = None
+
+ for (l_path, l_name, l_branch, l_rev, l_ismodified) in layers:
+ if l_name == 'workspace':
+ continue
+ if l_ismodified:
+ logger.error("Layer {name} in {path} has uncommitted modifications or is not in a git repository.".format(name=l_name,path=l_path))
+ return
+ repo_path = self._get_repo_path(l_path)
+ if repo_path not in repos.keys():
+ repos[repo_path] = {'path':os.path.basename(repo_path),'git-remote':{'rev':l_rev, 'branch':l_branch, 'remotes':self._get_remotes(repo_path), 'describe':self._get_describe(repo_path)}}
+ if repo_path == destdir_repo:
+ repos[repo_path]['contains_this_file'] = True
+ if not repos[repo_path]['git-remote']['remotes'] and not repos[repo_path]['contains_this_file']:
+ logger.error("Layer repository in {path} does not have any remotes configured. Please add at least one with 'git remote add'.".format(path=repo_path))
+ return
+
+ top_path = os.path.commonpath([os.path.dirname(r) for r in repos.keys()])
+
+ repos_nopaths = {}
+ for r in repos.keys():
+ r_nopath = os.path.basename(r)
+ repos_nopaths[r_nopath] = repos[r]
+ r_relpath = os.path.relpath(r, top_path)
+ repos_nopaths[r_nopath]['path'] = r_relpath
+ return repos_nopaths
+
+ def do_make_setup(self, args):
+ """ Writes out a configuration file and/or a script that replicate the directory structure and revisions of the layers in a current build. """
+ for p in self.plugins:
+ if str(p) == args.writer:
+ p.do_write(self, args)
+
+ def register_commands(self, sp):
+ parser_setup_layers = self.add_command(sp, 'create-layers-setup', self.do_make_setup, parserecipes=False)
+ parser_setup_layers.add_argument('destdir',
+ help='Directory where to write the output\n(if it is inside one of the layers, the layer becomes a bootstrap repository and thus will be excluded from fetching).')
+ parser_setup_layers.add_argument('--output-prefix', '-o',
+ help='File name prefix for the output files, if the default (setup-layers) is undesirable.')
+
+ self.plugins = []
+
+ for path in (self.tinfoil.config_data.getVar('BBPATH').split(':')):
+ pluginpath = os.path.join(path, 'lib', 'bblayers', 'setupwriters')
+ bb.utils.load_plugins(logger, self.plugins, pluginpath)
+
+ parser_setup_layers.add_argument('--writer', '-w', choices=[str(p) for p in self.plugins], help="Choose the output format (defaults to oe-setup-layers).\n\nCurrently supported options are:\noe-setup-layers - a self-contained python script and a json config for it.\n\n", default="oe-setup-layers")
+
+ for plugin in self.plugins:
+ if hasattr(plugin, 'register_arguments'):
+ plugin.register_arguments(parser_setup_layers)
diff --git a/meta/lib/bblayers/setupwriters/oe-setup-layers.py b/meta/lib/bblayers/setupwriters/oe-setup-layers.py
new file mode 100644
index 0000000000..f6a484b766
--- /dev/null
+++ b/meta/lib/bblayers/setupwriters/oe-setup-layers.py
@@ -0,0 +1,50 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: GPL-2.0-only
+#
+
+import logging
+import os
+import json
+import stat
+
+logger = logging.getLogger('bitbake-layers')
+
+def plugin_init(plugins):
+ return OeSetupLayersWriter()
+
+class OeSetupLayersWriter():
+
+ def __str__(self):
+ return "oe-setup-layers"
+
+ def _write_python(self, input, output):
+ with open(input) as f:
+ script = f.read()
+ with open(output, 'w') as f:
+ f.write(script)
+ st = os.stat(output)
+ os.chmod(output, st.st_mode | stat.S_IEXEC | stat.S_IXGRP | stat.S_IXOTH)
+
+ def _write_json(self, repos, output):
+ with open(output, 'w') as f:
+ json.dump(repos, f, sort_keys=True, indent=4)
+
+ def do_write(self, parent, args):
+ """ Writes out a python script and a json config that replicate the directory structure and revisions of the layers in a current build. """
+ repos = parent.make_repo_config(args.destdir)
+ json = {"version":"1.0","sources":repos}
+ if not repos:
+ raise Exception("Could not determine layer sources")
+ output = args.output_prefix or "setup-layers"
+ output = os.path.join(os.path.abspath(args.destdir),output)
+ self._write_json(json, output + ".json")
+ logger.info('Created {}.json'.format(output))
+ if not args.json_only:
+ self._write_python(os.path.join(os.path.dirname(__file__),'../../../../scripts/oe-setup-layers'), output)
+ logger.info('Created {}'.format(output))
+
+ def register_arguments(self, parser):
+ parser.add_argument('--json-only', action='store_true',
+ help='When using the oe-setup-layers writer, write only the layer configuruation in json format. Otherwise, also a copy of scripts/oe-setup-layers (from oe-core or poky) is provided, which is a self contained python script that fetches all the needed layers and sets them to correct revisions using the data from the json.')
diff --git a/meta/lib/bblayers/templates/README b/meta/lib/bblayers/templates/README
new file mode 100644
index 0000000000..fb2d28e177
--- /dev/null
+++ b/meta/lib/bblayers/templates/README
@@ -0,0 +1,41 @@
+This README file contains information on the contents of the {layername} layer.
+
+Please see the corresponding sections below for details.
+
+Dependencies
+============
+
+ URI: <first dependency>
+ branch: <branch name>
+
+ URI: <second dependency>
+ branch: <branch name>
+
+ .
+ .
+ .
+
+Patches
+=======
+
+Please submit any patches against the {layername} layer to the xxxx mailing list (xxxx@zzzz.org)
+and cc: the maintainer:
+
+Maintainer: XXX YYYYYY <xxx.yyyyyy@zzzzz.com>
+
+Table of Contents
+=================
+
+ I. Adding the {layername} layer to your build
+ II. Misc
+
+
+I. Adding the {layername} layer to your build
+=================================================
+
+Run 'bitbake-layers add-layer {layername}'
+
+II. Misc
+========
+
+--- replace with specific information about the {layername} layer ---
diff --git a/meta/lib/bblayers/templates/example.bb b/meta/lib/bblayers/templates/example.bb
new file mode 100644
index 0000000000..facaae35d2
--- /dev/null
+++ b/meta/lib/bblayers/templates/example.bb
@@ -0,0 +1,13 @@
+SUMMARY = "bitbake-layers recipe"
+DESCRIPTION = "Recipe created by bitbake-layers"
+LICENSE = "MIT"
+
+python do_display_banner() {
+ bb.plain("***********************************************");
+ bb.plain("* *");
+ bb.plain("* Example recipe created by bitbake-layers *");
+ bb.plain("* *");
+ bb.plain("***********************************************");
+}
+
+addtask display_banner before do_build
diff --git a/meta/lib/bblayers/templates/layer.conf b/meta/lib/bblayers/templates/layer.conf
new file mode 100644
index 0000000000..dddfbf716e
--- /dev/null
+++ b/meta/lib/bblayers/templates/layer.conf
@@ -0,0 +1,13 @@
+# We have a conf and classes directory, add to BBPATH
+BBPATH .= ":${{LAYERDIR}}"
+
+# We have recipes-* directories, add to BBFILES
+BBFILES += "${{LAYERDIR}}/recipes-*/*/*.bb \
+ ${{LAYERDIR}}/recipes-*/*/*.bbappend"
+
+BBFILE_COLLECTIONS += "{layerid}"
+BBFILE_PATTERN_{layerid} = "^${{LAYERDIR}}/"
+BBFILE_PRIORITY_{layerid} = "{priority}"
+
+LAYERDEPENDS_{layerid} = "core"
+LAYERSERIES_COMPAT_{layerid} = "{compat}"
diff --git a/meta/lib/buildstats.py b/meta/lib/buildstats.py
new file mode 100644
index 0000000000..1ffe679801
--- /dev/null
+++ b/meta/lib/buildstats.py
@@ -0,0 +1,215 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# Implements system state sampling. Called by buildstats.bbclass.
+# Because it is a real Python module, it can hold persistent state,
+# like open log files and the time of the last sampling.
+
+import time
+import re
+import bb.event
+
+class SystemStats:
+ def __init__(self, d):
+ bn = d.getVar('BUILDNAME')
+ bsdir = os.path.join(d.getVar('BUILDSTATS_BASE'), bn)
+ bb.utils.mkdirhier(bsdir)
+ file_handlers = [('diskstats', self._reduce_diskstats),
+ ('meminfo', self._reduce_meminfo),
+ ('stat', self._reduce_stat)]
+
+ # Some hosts like openSUSE have readable /proc/pressure files
+ # but throw errors when these files are opened. Catch these error
+ # and ensure that the reduce_proc_pressure directory is not created.
+ if os.path.exists("/proc/pressure"):
+ try:
+ with open('/proc/pressure/cpu', 'rb') as source:
+ source.read()
+ pressuredir = os.path.join(bsdir, 'reduced_proc_pressure')
+ bb.utils.mkdirhier(pressuredir)
+ file_handlers.extend([('pressure/cpu', self._reduce_pressure),
+ ('pressure/io', self._reduce_pressure),
+ ('pressure/memory', self._reduce_pressure)])
+ except Exception:
+ pass
+
+ self.proc_files = []
+ for filename, handler in (file_handlers):
+ # The corresponding /proc files might not exist on the host.
+ # For example, /proc/diskstats is not available in virtualized
+ # environments like Linux-VServer. Silently skip collecting
+ # the data.
+ if os.path.exists(os.path.join('/proc', filename)):
+ # In practice, this class gets instantiated only once in
+ # the bitbake cooker process. Therefore 'append' mode is
+ # not strictly necessary, but using it makes the class
+ # more robust should two processes ever write
+ # concurrently.
+ destfile = os.path.join(bsdir, '%sproc_%s.log' % ('reduced_' if handler else '', filename))
+ self.proc_files.append((filename, open(destfile, 'ab'), handler))
+ self.monitor_disk = open(os.path.join(bsdir, 'monitor_disk.log'), 'ab')
+ # Last time that we sampled /proc data resp. recorded disk monitoring data.
+ self.last_proc = 0
+ self.last_disk_monitor = 0
+ # Minimum number of seconds between recording a sample. This becames relevant when we get
+ # called very often while many short tasks get started. Sampling during quiet periods
+ # depends on the heartbeat event, which fires less often.
+ # By default, the Heartbeat events occur roughly once every second but the actual time
+ # between these events deviates by a few milliseconds, in most cases. Hence
+ # pick a somewhat arbitary tolerance such that we sample a large majority
+ # of the Heartbeat events. This ignores rare events that fall outside the minimum
+ # and may lead an extra sample in a given second every so often. However, it allows for fairly
+ # consistent intervals between samples without missing many events.
+ self.tolerance = 0.01
+ self.min_seconds = 1.0 - self.tolerance
+
+ self.meminfo_regex = re.compile(rb'^(MemTotal|MemFree|Buffers|Cached|SwapTotal|SwapFree):\s*(\d+)')
+ self.diskstats_regex = re.compile(rb'^([hsv]d.|mtdblock\d|mmcblk\d|cciss/c\d+d\d+.*)$')
+ self.diskstats_ltime = None
+ self.diskstats_data = None
+ self.stat_ltimes = None
+ # Last time we sampled /proc/pressure. All resources stored in a single dict with the key as filename
+ self.last_pressure = {"pressure/cpu": None, "pressure/io": None, "pressure/memory": None}
+
+ def close(self):
+ self.monitor_disk.close()
+ for _, output, _ in self.proc_files:
+ output.close()
+
+ def _reduce_meminfo(self, time, data, filename):
+ """
+ Extracts 'MemTotal', 'MemFree', 'Buffers', 'Cached', 'SwapTotal', 'SwapFree'
+ and writes their values into a single line, in that order.
+ """
+ values = {}
+ for line in data.split(b'\n'):
+ m = self.meminfo_regex.match(line)
+ if m:
+ values[m.group(1)] = m.group(2)
+ if len(values) == 6:
+ return (time,
+ b' '.join([values[x] for x in
+ (b'MemTotal', b'MemFree', b'Buffers', b'Cached', b'SwapTotal', b'SwapFree')]) + b'\n')
+
+ def _diskstats_is_relevant_line(self, linetokens):
+ if len(linetokens) != 14:
+ return False
+ disk = linetokens[2]
+ return self.diskstats_regex.match(disk)
+
+ def _reduce_diskstats(self, time, data, filename):
+ relevant_tokens = filter(self._diskstats_is_relevant_line, map(lambda x: x.split(), data.split(b'\n')))
+ diskdata = [0] * 3
+ reduced = None
+ for tokens in relevant_tokens:
+ # rsect
+ diskdata[0] += int(tokens[5])
+ # wsect
+ diskdata[1] += int(tokens[9])
+ # use
+ diskdata[2] += int(tokens[12])
+ if self.diskstats_ltime:
+ # We need to compute information about the time interval
+ # since the last sampling and record the result as sample
+ # for that point in the past.
+ interval = time - self.diskstats_ltime
+ if interval > 0:
+ sums = [ a - b for a, b in zip(diskdata, self.diskstats_data) ]
+ readTput = sums[0] / 2.0 * 100.0 / interval
+ writeTput = sums[1] / 2.0 * 100.0 / interval
+ util = float( sums[2] ) / 10 / interval
+ util = max(0.0, min(1.0, util))
+ reduced = (self.diskstats_ltime, (readTput, writeTput, util))
+
+ self.diskstats_ltime = time
+ self.diskstats_data = diskdata
+ return reduced
+
+
+ def _reduce_nop(self, time, data, filename):
+ return (time, data)
+
+ def _reduce_stat(self, time, data, filename):
+ if not data:
+ return None
+ # CPU times {user, nice, system, idle, io_wait, irq, softirq} from first line
+ tokens = data.split(b'\n', 1)[0].split()
+ times = [ int(token) for token in tokens[1:] ]
+ reduced = None
+ if self.stat_ltimes:
+ user = float((times[0] + times[1]) - (self.stat_ltimes[0] + self.stat_ltimes[1]))
+ system = float((times[2] + times[5] + times[6]) - (self.stat_ltimes[2] + self.stat_ltimes[5] + self.stat_ltimes[6]))
+ idle = float(times[3] - self.stat_ltimes[3])
+ iowait = float(times[4] - self.stat_ltimes[4])
+
+ aSum = max(user + system + idle + iowait, 1)
+ reduced = (time, (user/aSum, system/aSum, iowait/aSum))
+
+ self.stat_ltimes = times
+ return reduced
+
+ def _reduce_pressure(self, time, data, filename):
+ """
+ Return reduced pressure: {avg10, avg60, avg300} and delta total compared to the previous sample
+ for the cpu, io and memory resources. A common function is used for all 3 resources since the
+ format of the /proc/pressure file is the same in each case.
+ """
+ if not data:
+ return None
+ tokens = data.split(b'\n', 1)[0].split()
+ avg10 = float(tokens[1].split(b'=')[1])
+ avg60 = float(tokens[2].split(b'=')[1])
+ avg300 = float(tokens[3].split(b'=')[1])
+ total = int(tokens[4].split(b'=')[1])
+
+ reduced = None
+ if self.last_pressure[filename]:
+ delta = total - self.last_pressure[filename]
+ reduced = (time, (avg10, avg60, avg300, delta))
+ self.last_pressure[filename] = total
+ return reduced
+
+ def sample(self, event, force):
+ """
+ Collect and log proc or disk_monitor stats periodically.
+ Return True if a new sample is collected and hence the value last_proc or last_disk_monitor
+ is changed.
+ """
+ retval = False
+ now = time.time()
+ if (now - self.last_proc > self.min_seconds) or force:
+ for filename, output, handler in self.proc_files:
+ with open(os.path.join('/proc', filename), 'rb') as input:
+ data = input.read()
+ if handler:
+ reduced = handler(now, data, filename)
+ else:
+ reduced = (now, data)
+ if reduced:
+ if isinstance(reduced[1], bytes):
+ # Use as it is.
+ data = reduced[1]
+ else:
+ # Convert to a single line.
+ data = (' '.join([str(x) for x in reduced[1]]) + '\n').encode('ascii')
+ # Unbuffered raw write, less overhead and useful
+ # in case that we end up with concurrent writes.
+ os.write(output.fileno(),
+ ('%.0f\n' % reduced[0]).encode('ascii') +
+ data +
+ b'\n')
+ self.last_proc = now
+ retval = True
+
+ if isinstance(event, bb.event.MonitorDiskEvent) and \
+ ((now - self.last_disk_monitor > self.min_seconds) or force):
+ os.write(self.monitor_disk.fileno(),
+ ('%.0f\n' % now).encode('ascii') +
+ ''.join(['%s: %d\n' % (dev, sample.total_bytes - sample.free_bytes)
+ for dev, sample in event.disk_usage.items()]).encode('ascii') +
+ b'\n')
+ self.last_disk_monitor = now
+ retval = True
+ return retval \ No newline at end of file
diff --git a/meta/lib/oe/__init__.py b/meta/lib/oe/__init__.py
index 3ad9513f40..47be7b51d7 100644
--- a/meta/lib/oe/__init__.py
+++ b/meta/lib/oe/__init__.py
@@ -1,2 +1,12 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: GPL-2.0-only
+#
+
from pkgutil import extend_path
__path__ = extend_path(__path__, __name__)
+
+BBIMPORTS = ["data", "path", "utils", "types", "package", \
+ "packagegroup", "sstatesig", "lsb", "cachedpath", "license", \
+ "qa", "reproducible", "rust", "buildcfg"]
diff --git a/meta/lib/oe/buildcfg.py b/meta/lib/oe/buildcfg.py
new file mode 100644
index 0000000000..90f5e05715
--- /dev/null
+++ b/meta/lib/oe/buildcfg.py
@@ -0,0 +1,49 @@
+
+import subprocess
+import bb.process
+
+def detect_revision(d):
+ path = get_scmbasepath(d)
+ return get_metadata_git_revision(path, d)
+
+def detect_branch(d):
+ path = get_scmbasepath(d)
+ return get_metadata_git_branch(path, d)
+
+def get_scmbasepath(d):
+ return os.path.join(d.getVar('COREBASE'), 'meta')
+
+def get_metadata_git_branch(path, d):
+ try:
+ rev, _ = bb.process.run('git rev-parse --abbrev-ref HEAD', cwd=path)
+ except bb.process.ExecutionError:
+ rev = '<unknown>'
+ return rev.strip()
+
+def get_metadata_git_revision(path, d):
+ try:
+ rev, _ = bb.process.run('git rev-parse HEAD', cwd=path)
+ except bb.process.ExecutionError:
+ rev = '<unknown>'
+ return rev.strip()
+
+def is_layer_modified(path):
+ try:
+ subprocess.check_output("""cd %s; export PSEUDO_UNLOAD=1; set -e;
+ git diff --quiet --no-ext-diff
+ git diff --quiet --no-ext-diff --cached""" % path,
+ shell=True,
+ stderr=subprocess.STDOUT)
+ return ""
+ except subprocess.CalledProcessError as ex:
+ # Silently treat errors as "modified", without checking for the
+ # (expected) return code 1 in a modified git repo. For example, we get
+ # output and a 129 return code when a layer isn't a git repo at all.
+ return " -- modified"
+
+def get_layer_revisions(d):
+ layers = (d.getVar("BBLAYERS") or "").split()
+ revisions = []
+ for i in layers:
+ revisions.append((i, os.path.basename(i), get_metadata_git_branch(i, None).strip(), get_metadata_git_revision(i, None), is_layer_modified(i)))
+ return revisions
diff --git a/meta/lib/oe/buildhistory_analysis.py b/meta/lib/oe/buildhistory_analysis.py
index b6c0265c15..b1856846b6 100644
--- a/meta/lib/oe/buildhistory_analysis.py
+++ b/meta/lib/oe/buildhistory_analysis.py
@@ -1,8 +1,10 @@
# Report significant differences in the buildhistory repository since a specific revision
#
-# Copyright (C) 2012 Intel Corporation
+# Copyright (C) 2012-2013, 2016-2017 Intel Corporation
# Author: Paul Eggleton <paul.eggleton@linux.intel.com>
#
+# SPDX-License-Identifier: GPL-2.0-only
+#
# Note: requires GitPython 0.3.1+
#
# You can use this from the command line by running scripts/buildhistory-diff
@@ -13,7 +15,11 @@ import os.path
import difflib
import git
import re
+import shlex
+import hashlib
+import collections
import bb.utils
+import bb.tinfoil
# How to display fields
@@ -28,15 +34,27 @@ ver_monitor_fields = ['PKGE', 'PKGV', 'PKGR']
monitor_numeric_threshold = 10
# Image files to monitor (note that image-info.txt is handled separately)
img_monitor_files = ['installed-package-names.txt', 'files-in-image.txt']
-# Related context fields for reporting (note: PE, PV & PR are always reported for monitored package fields)
-related_fields = {}
-related_fields['RDEPENDS'] = ['DEPENDS']
-related_fields['RRECOMMENDS'] = ['DEPENDS']
-related_fields['FILELIST'] = ['FILES']
-related_fields['PKGSIZE'] = ['FILELIST']
-related_fields['files-in-image.txt'] = ['installed-package-names.txt', 'USER_CLASSES', 'IMAGE_CLASSES', 'ROOTFS_POSTPROCESS_COMMAND', 'IMAGE_POSTPROCESS_COMMAND']
-related_fields['installed-package-names.txt'] = ['IMAGE_FEATURES', 'IMAGE_LINGUAS', 'IMAGE_INSTALL', 'BAD_RECOMMENDATIONS', 'NO_RECOMMENDATIONS', 'PACKAGE_EXCLUDE']
+colours = {
+ 'colour_default': '',
+ 'colour_add': '',
+ 'colour_remove': '',
+}
+
+def init_colours(use_colours):
+ global colours
+ if use_colours:
+ colours = {
+ 'colour_default': '\033[0m',
+ 'colour_add': '\033[1;32m',
+ 'colour_remove': '\033[1;31m',
+ }
+ else:
+ colours = {
+ 'colour_default': '',
+ 'colour_add': '',
+ 'colour_remove': '',
+ }
class ChangeRecord:
def __init__(self, path, fieldname, oldvalue, newvalue, monitored):
@@ -45,7 +63,6 @@ class ChangeRecord:
self.oldvalue = oldvalue
self.newvalue = newvalue
self.monitored = monitored
- self.related = []
self.filechanges = None
def __str__(self):
@@ -69,24 +86,77 @@ class ChangeRecord:
pkglist.append(k)
return pkglist
+ def detect_renamed_dirs(aitems, bitems):
+ adirs = set(map(os.path.dirname, aitems))
+ bdirs = set(map(os.path.dirname, bitems))
+ files_ab = [(name, sorted(os.path.basename(item) for item in aitems if os.path.dirname(item) == name)) \
+ for name in adirs - bdirs]
+ files_ba = [(name, sorted(os.path.basename(item) for item in bitems if os.path.dirname(item) == name)) \
+ for name in bdirs - adirs]
+ renamed_dirs = []
+ for dir1, files1 in files_ab:
+ rename = False
+ for dir2, files2 in files_ba:
+ if files1 == files2 and not rename:
+ renamed_dirs.append((dir1,dir2))
+ # Make sure that we don't use this (dir, files) pair again.
+ files_ba.remove((dir2,files2))
+ # If a dir has already been found to have a rename, stop and go no further.
+ rename = True
+
+ # remove files that belong to renamed dirs from aitems and bitems
+ for dir1, dir2 in renamed_dirs:
+ aitems = [item for item in aitems if os.path.dirname(item) not in (dir1, dir2)]
+ bitems = [item for item in bitems if os.path.dirname(item) not in (dir1, dir2)]
+ return renamed_dirs, aitems, bitems
+
if self.fieldname in list_fields or self.fieldname in list_order_fields:
+ renamed_dirs = []
+ changed_order = False
if self.fieldname in ['RPROVIDES', 'RDEPENDS', 'RRECOMMENDS', 'RSUGGESTS', 'RREPLACES', 'RCONFLICTS']:
(depvera, depverb) = compare_pkg_lists(self.oldvalue, self.newvalue)
aitems = pkglist_combine(depvera)
bitems = pkglist_combine(depverb)
else:
- aitems = self.oldvalue.split()
- bitems = self.newvalue.split()
+ if self.fieldname == 'FILELIST':
+ aitems = shlex.split(self.oldvalue)
+ bitems = shlex.split(self.newvalue)
+ renamed_dirs, aitems, bitems = detect_renamed_dirs(aitems, bitems)
+ else:
+ aitems = self.oldvalue.split()
+ bitems = self.newvalue.split()
+
removed = list(set(aitems) - set(bitems))
added = list(set(bitems) - set(aitems))
+ if not removed and not added and self.fieldname in ['RPROVIDES', 'RDEPENDS', 'RRECOMMENDS', 'RSUGGESTS', 'RREPLACES', 'RCONFLICTS']:
+ depvera = bb.utils.explode_dep_versions2(self.oldvalue, sort=False)
+ depverb = bb.utils.explode_dep_versions2(self.newvalue, sort=False)
+ for i, j in zip(depvera.items(), depverb.items()):
+ if i[0] != j[0]:
+ changed_order = True
+ break
+
+ lines = []
+ if renamed_dirs:
+ for dfrom, dto in renamed_dirs:
+ lines.append('directory renamed {colour_remove}{}{colour_default} -> {colour_add}{}{colour_default}'.format(dfrom, dto, **colours))
if removed or added:
if removed and not bitems:
- out = '%s: removed all items "%s"' % (self.fieldname, ' '.join(removed))
+ lines.append('removed all items "{colour_remove}{}{colour_default}"'.format(' '.join(removed), **colours))
else:
- out = '%s:%s%s' % (self.fieldname, ' removed "%s"' % ' '.join(removed) if removed else '', ' added "%s"' % ' '.join(added) if added else '')
+ if removed:
+ lines.append('removed "{colour_remove}{value}{colour_default}"'.format(value=' '.join(removed), **colours))
+ if added:
+ lines.append('added "{colour_add}{value}{colour_default}"'.format(value=' '.join(added), **colours))
+ else:
+ lines.append('changed order')
+
+ if not (removed or added or changed_order):
+ out = ''
else:
- out = '%s changed order' % self.fieldname
+ out = '%s: %s' % (self.fieldname, ', '.join(lines))
+
elif self.fieldname in numeric_fields:
aval = int(self.oldvalue or 0)
bval = int(self.newvalue or 0)
@@ -94,9 +164,9 @@ class ChangeRecord:
percentchg = ((bval - aval) / float(aval)) * 100
else:
percentchg = 100
- out = '%s changed from %s to %s (%s%d%%)' % (self.fieldname, self.oldvalue or "''", self.newvalue or "''", '+' if percentchg > 0 else '', percentchg)
+ out = '{} changed from {colour_remove}{}{colour_default} to {colour_add}{}{colour_default} ({}{:.0f}%)'.format(self.fieldname, self.oldvalue or "''", self.newvalue or "''", '+' if percentchg > 0 else '', percentchg, **colours)
elif self.fieldname in defaultval_map:
- out = '%s changed from %s to %s' % (self.fieldname, self.oldvalue, self.newvalue)
+ out = '{} changed from {colour_remove}{}{colour_default} to {colour_add}{}{colour_default}'.format(self.fieldname, self.oldvalue, self.newvalue, **colours)
if self.fieldname == 'PKG' and '[default]' in self.newvalue:
out += ' - may indicate debian renaming failure'
elif self.fieldname in ['pkg_preinst', 'pkg_postinst', 'pkg_prerm', 'pkg_postrm']:
@@ -111,34 +181,30 @@ class ChangeRecord:
diff = difflib.unified_diff(alines, blines, self.fieldname, self.fieldname, lineterm='')
out += '\n '.join(list(diff)[2:])
out += '\n --'
- elif self.fieldname in img_monitor_files or '/image-files/' in self.path:
- fieldname = self.fieldname
- if '/image-files/' in self.path:
- fieldname = os.path.join('/' + self.path.split('/image-files/')[1], self.fieldname)
- out = 'Changes to %s:\n ' % fieldname
- else:
- if outer:
- prefix = 'Changes to %s ' % self.path
- out = '(%s):\n ' % self.fieldname
- if self.filechanges:
- out += '\n '.join(['%s' % i for i in self.filechanges])
+ elif self.fieldname in img_monitor_files or '/image-files/' in self.path or self.fieldname == "sysroot":
+ if self.filechanges or (self.oldvalue and self.newvalue):
+ fieldname = self.fieldname
+ if '/image-files/' in self.path:
+ fieldname = os.path.join('/' + self.path.split('/image-files/')[1], self.fieldname)
+ out = 'Changes to %s:\n ' % fieldname
+ else:
+ if outer:
+ prefix = 'Changes to %s ' % self.path
+ out = '(%s):\n ' % self.fieldname
+ if self.filechanges:
+ out += '\n '.join(['%s' % i for i in self.filechanges])
+ else:
+ alines = self.oldvalue.splitlines()
+ blines = self.newvalue.splitlines()
+ diff = difflib.unified_diff(alines, blines, fieldname, fieldname, lineterm='')
+ out += '\n '.join(list(diff))
+ out += '\n --'
else:
- alines = self.oldvalue.splitlines()
- blines = self.newvalue.splitlines()
- diff = difflib.unified_diff(alines, blines, fieldname, fieldname, lineterm='')
- out += '\n '.join(list(diff))
- out += '\n --'
+ out = ''
else:
- out = '%s changed from "%s" to "%s"' % (self.fieldname, self.oldvalue, self.newvalue)
+ out = '{} changed from "{colour_remove}{}{colour_default}" to "{colour_add}{}{colour_default}"'.format(self.fieldname, self.oldvalue, self.newvalue, **colours)
- if self.related:
- for chg in self.related:
- if not outer and chg.fieldname in ['PE', 'PV', 'PR']:
- continue
- for line in chg._str_internal(False).splitlines():
- out += '\n * %s' % line
-
- return '%s%s' % (prefix, out)
+ return '%s%s' % (prefix, out) if out else ''
class FileChange:
changetype_add = 'A'
@@ -147,6 +213,7 @@ class FileChange:
changetype_perms = 'P'
changetype_ownergroup = 'O'
changetype_link = 'L'
+ changetype_move = 'M'
def __init__(self, path, changetype, oldvalue = None, newvalue = None):
self.path = path
@@ -185,10 +252,11 @@ class FileChange:
return '%s changed owner/group from %s to %s' % (self.path, self.oldvalue, self.newvalue)
elif self.changetype == self.changetype_link:
return '%s changed symlink target from %s to %s' % (self.path, self.oldvalue, self.newvalue)
+ elif self.changetype == self.changetype_move:
+ return '%s moved to %s' % (self.path, self.oldvalue)
else:
return '%s changed (unknown)' % self.path
-
def blob_to_dict(blob):
alines = [line for line in blob.data_stream.read().decode('utf-8').splitlines()]
adict = {}
@@ -215,11 +283,14 @@ def file_list_to_dict(lines):
adict[path] = splitv[0:3]
return adict
+numeric_removal = str.maketrans('0123456789', 'XXXXXXXXXX')
-def compare_file_lists(alines, blines):
+def compare_file_lists(alines, blines, compare_ownership=True):
adict = file_list_to_dict(alines)
bdict = file_list_to_dict(blines)
filechanges = []
+ additions = []
+ removals = []
for path, splitv in adict.items():
newsplitv = bdict.pop(path, None)
if newsplitv:
@@ -228,16 +299,20 @@ def compare_file_lists(alines, blines):
newvalue = newsplitv[0][0]
if oldvalue != newvalue:
filechanges.append(FileChange(path, FileChange.changetype_type, oldvalue, newvalue))
+
# Check permissions
oldvalue = splitv[0][1:]
newvalue = newsplitv[0][1:]
if oldvalue != newvalue:
filechanges.append(FileChange(path, FileChange.changetype_perms, oldvalue, newvalue))
- # Check owner/group
- oldvalue = '%s/%s' % (splitv[1], splitv[2])
- newvalue = '%s/%s' % (newsplitv[1], newsplitv[2])
- if oldvalue != newvalue:
- filechanges.append(FileChange(path, FileChange.changetype_ownergroup, oldvalue, newvalue))
+
+ if compare_ownership:
+ # Check owner/group
+ oldvalue = '%s/%s' % (splitv[1], splitv[2])
+ newvalue = '%s/%s' % (newsplitv[1], newsplitv[2])
+ if oldvalue != newvalue:
+ filechanges.append(FileChange(path, FileChange.changetype_ownergroup, oldvalue, newvalue))
+
# Check symlink target
if newsplitv[0][0] == 'l':
if len(splitv) > 3:
@@ -248,11 +323,67 @@ def compare_file_lists(alines, blines):
if oldvalue != newvalue:
filechanges.append(FileChange(path, FileChange.changetype_link, oldvalue, newvalue))
else:
- filechanges.append(FileChange(path, FileChange.changetype_remove))
+ removals.append(path)
# Whatever is left over has been added
for path in bdict:
- filechanges.append(FileChange(path, FileChange.changetype_add))
+ additions.append(path)
+
+ # Rather than print additions and removals, its nicer to print file 'moves'
+ # where names or paths are similar.
+ revmap_remove = {}
+ for removal in removals:
+ translated = removal.translate(numeric_removal)
+ if translated not in revmap_remove:
+ revmap_remove[translated] = []
+ revmap_remove[translated].append(removal)
+
+ #
+ # We want to detect renames of large trees of files like
+ # /lib/modules/5.4.40-yocto-standard to /lib/modules/5.4.43-yocto-standard
+ #
+ renames = {}
+ for addition in additions.copy():
+ if addition not in additions:
+ continue
+ translated = addition.translate(numeric_removal)
+ if translated in revmap_remove:
+ if len(revmap_remove[translated]) != 1:
+ continue
+ removal = revmap_remove[translated][0]
+ commondir = addition.split("/")
+ commondir2 = removal.split("/")
+ idx = None
+ for i in range(len(commondir)):
+ if commondir[i] != commondir2[i]:
+ idx = i
+ break
+ commondir = "/".join(commondir[:i+1])
+ commondir2 = "/".join(commondir2[:i+1])
+ # If the common parent is in one dict and not the other its likely a rename
+ # so iterate through those files and process as such
+ if commondir2 not in bdict and commondir not in adict:
+ if commondir not in renames:
+ renames[commondir] = commondir2
+ for addition2 in additions.copy():
+ if addition2.startswith(commondir):
+ removal2 = addition2.replace(commondir, commondir2)
+ if removal2 in removals:
+ additions.remove(addition2)
+ removals.remove(removal2)
+ continue
+ filechanges.append(FileChange(removal, FileChange.changetype_move, addition))
+ if addition in additions:
+ additions.remove(addition)
+ if removal in removals:
+ removals.remove(removal)
+ for rename in renames:
+ filechanges.append(FileChange(renames[rename], FileChange.changetype_move, rename))
+
+ for addition in additions:
+ filechanges.append(FileChange(addition, FileChange.changetype_add))
+ for removal in removals:
+ filechanges.append(FileChange(removal, FileChange.changetype_remove))
return filechanges
@@ -343,15 +474,19 @@ def compare_dict_blobs(path, ablob, bblob, report_all, report_ver):
if abs(percentchg) < monitor_numeric_threshold:
continue
elif (not report_all) and key in list_fields:
- if key == "FILELIST" and path.endswith("-dbg") and bstr.strip() != '':
+ if key == "FILELIST" and (path.endswith("-dbg") or path.endswith("-src")) and bstr.strip() != '':
continue
if key in ['RPROVIDES', 'RDEPENDS', 'RRECOMMENDS', 'RSUGGESTS', 'RREPLACES', 'RCONFLICTS']:
(depvera, depverb) = compare_pkg_lists(astr, bstr)
if depvera == depverb:
continue
- alist = astr.split()
+ if key == 'FILELIST':
+ alist = shlex.split(astr)
+ blist = shlex.split(bstr)
+ else:
+ alist = astr.split()
+ blist = bstr.split()
alist.sort()
- blist = bstr.split()
blist.sort()
# We don't care about the removal of self-dependencies
if pkgname in alist and not pkgname in blist:
@@ -382,13 +517,116 @@ def compare_dict_blobs(path, ablob, bblob, report_all, report_ver):
return changes
-def process_changes(repopath, revision1, revision2='HEAD', report_all=False, report_ver=False):
+def compare_siglists(a_blob, b_blob, taskdiff=False):
+ # FIXME collapse down a recipe's tasks?
+ alines = a_blob.data_stream.read().decode('utf-8').splitlines()
+ blines = b_blob.data_stream.read().decode('utf-8').splitlines()
+ keys = []
+ pnmap = {}
+ def readsigs(lines):
+ sigs = {}
+ for line in lines:
+ linesplit = line.split()
+ if len(linesplit) > 2:
+ sigs[linesplit[0]] = linesplit[2]
+ if not linesplit[0] in keys:
+ keys.append(linesplit[0])
+ pnmap[linesplit[1]] = linesplit[0].rsplit('.', 1)[0]
+ return sigs
+ adict = readsigs(alines)
+ bdict = readsigs(blines)
+ out = []
+
+ changecount = 0
+ addcount = 0
+ removecount = 0
+ if taskdiff:
+ with bb.tinfoil.Tinfoil() as tinfoil:
+ tinfoil.prepare(config_only=True)
+
+ changes = collections.OrderedDict()
+
+ def compare_hashfiles(pn, taskname, hash1, hash2):
+ hashes = [hash1, hash2]
+ hashfiles = bb.siggen.find_siginfo(pn, taskname, hashes, tinfoil.config_data)
+
+ if not taskname:
+ (pn, taskname) = pn.rsplit('.', 1)
+ pn = pnmap.get(pn, pn)
+ desc = '%s.%s' % (pn, taskname)
+
+ if len(hashfiles) == 0:
+ out.append("Unable to find matching sigdata for %s with hashes %s or %s" % (desc, hash1, hash2))
+ elif not hash1 in hashfiles:
+ out.append("Unable to find matching sigdata for %s with hash %s" % (desc, hash1))
+ elif not hash2 in hashfiles:
+ out.append("Unable to find matching sigdata for %s with hash %s" % (desc, hash2))
+ else:
+ out2 = bb.siggen.compare_sigfiles(hashfiles[hash1], hashfiles[hash2], recursecb, collapsed=True)
+ for line in out2:
+ m = hashlib.sha256()
+ m.update(line.encode('utf-8'))
+ entry = changes.get(m.hexdigest(), (line, []))
+ if desc not in entry[1]:
+ changes[m.hexdigest()] = (line, entry[1] + [desc])
+
+ # Define recursion callback
+ def recursecb(key, hash1, hash2):
+ compare_hashfiles(key, None, hash1, hash2)
+ return []
+
+ for key in keys:
+ siga = adict.get(key, None)
+ sigb = bdict.get(key, None)
+ if siga is not None and sigb is not None and siga != sigb:
+ changecount += 1
+ (pn, taskname) = key.rsplit('.', 1)
+ compare_hashfiles(pn, taskname, siga, sigb)
+ elif siga is None:
+ addcount += 1
+ elif sigb is None:
+ removecount += 1
+ for key, item in changes.items():
+ line, tasks = item
+ if len(tasks) == 1:
+ desc = tasks[0]
+ elif len(tasks) == 2:
+ desc = '%s and %s' % (tasks[0], tasks[1])
+ else:
+ desc = '%s and %d others' % (tasks[-1], len(tasks)-1)
+ out.append('%s: %s' % (desc, line))
+ else:
+ for key in keys:
+ siga = adict.get(key, None)
+ sigb = bdict.get(key, None)
+ if siga is not None and sigb is not None and siga != sigb:
+ out.append('%s changed from %s to %s' % (key, siga, sigb))
+ changecount += 1
+ elif siga is None:
+ out.append('%s was added' % key)
+ addcount += 1
+ elif sigb is None:
+ out.append('%s was removed' % key)
+ removecount += 1
+ out.append('Summary: %d tasks added, %d tasks removed, %d tasks modified (%.1f%%)' % (addcount, removecount, changecount, (changecount / float(len(bdict)) * 100)))
+ return '\n'.join(out)
+
+
+def process_changes(repopath, revision1, revision2='HEAD', report_all=False, report_ver=False,
+ sigs=False, sigsdiff=False, exclude_path=None):
repo = git.Repo(repopath)
assert repo.bare == False
commit = repo.commit(revision1)
diff = commit.diff(revision2)
changes = []
+
+ if sigs or sigsdiff:
+ for d in diff.iter_change_type('M'):
+ if d.a_blob.path == 'siglist.txt':
+ changes.append(compare_siglists(d.a_blob, d.b_blob, taskdiff=sigsdiff))
+ return changes
+
for d in diff.iter_change_type('M'):
path = os.path.dirname(d.a_blob.path)
if path.startswith('packages/'):
@@ -398,6 +636,15 @@ def process_changes(repopath, revision1, revision2='HEAD', report_all=False, rep
elif filename.startswith('latest.'):
chg = ChangeRecord(path, filename, d.a_blob.data_stream.read().decode('utf-8'), d.b_blob.data_stream.read().decode('utf-8'), True)
changes.append(chg)
+ elif filename == 'sysroot':
+ alines = d.a_blob.data_stream.read().decode('utf-8').splitlines()
+ blines = d.b_blob.data_stream.read().decode('utf-8').splitlines()
+ filechanges = compare_file_lists(alines,blines, compare_ownership=False)
+ if filechanges:
+ chg = ChangeRecord(path, filename, None, None, True)
+ chg.filechanges = filechanges
+ changes.append(chg)
+
elif path.startswith('images/'):
filename = os.path.basename(d.a_blob.path)
if filename in img_monitor_files:
@@ -457,16 +704,18 @@ def process_changes(repopath, revision1, revision2='HEAD', report_all=False, rep
chg = ChangeRecord(path, filename[7:], d.a_blob.data_stream.read().decode('utf-8'), '', True)
changes.append(chg)
- # Link related changes
- for chg in changes:
- if chg.monitored:
- for chg2 in changes:
- # (Check dirname in the case of fields from recipe info files)
- if chg.path == chg2.path or os.path.dirname(chg.path) == chg2.path:
- if chg2.fieldname in related_fields.get(chg.fieldname, []):
- chg.related.append(chg2)
- elif chg.path == chg2.path and chg.path.startswith('packages/') and chg2.fieldname in ['PE', 'PV', 'PR']:
- chg.related.append(chg2)
+ # filter out unwanted paths
+ if exclude_path:
+ for chg in changes:
+ if chg.filechanges:
+ fchgs = []
+ for fchg in chg.filechanges:
+ for epath in exclude_path:
+ if fchg.path.startswith(epath):
+ break
+ else:
+ fchgs.append(fchg)
+ chg.filechanges = fchgs
if report_all:
return changes
diff --git a/meta/lib/oe/cachedpath.py b/meta/lib/oe/cachedpath.py
index 0840cc4c3f..0138b791d4 100644
--- a/meta/lib/oe/cachedpath.py
+++ b/meta/lib/oe/cachedpath.py
@@ -1,4 +1,8 @@
#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: GPL-2.0-only
+#
# Based on standard python library functions but avoid
# repeated stat calls. Its assumed the files will not change from under us
# so we can cache stat calls.
diff --git a/meta/lib/oe/classextend.py b/meta/lib/oe/classextend.py
index 4c8a00070c..2013b29711 100644
--- a/meta/lib/oe/classextend.py
+++ b/meta/lib/oe/classextend.py
@@ -1,10 +1,26 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: GPL-2.0-only
+#
+
import collections
+def get_packages(d):
+ pkgs = d.getVar("PACKAGES_NONML")
+ extcls = d.getVar("EXTENDERCLASS")
+ return extcls.rename_packages_internal(pkgs)
+
+def get_depends(varprefix, d):
+ extcls = d.getVar("EXTENDERCLASS")
+ return extcls.map_depends_variable(varprefix + "_NONML")
+
class ClassExtender(object):
def __init__(self, extname, d):
self.extname = extname
self.d = d
self.pkgs_mapping = []
+ self.d.setVar("EXTENDERCLASS", self)
def extend_name(self, name):
if name.startswith("kernel-") or name == "virtual/kernel":
@@ -20,12 +36,14 @@ class ClassExtender(object):
if not subs.startswith(self.extname):
return "virtual/" + self.extname + "-" + subs
return name
+ if name.startswith("/") or (name.startswith("${") and name.endswith("}")):
+ return name
if not name.startswith(self.extname):
return self.extname + "-" + name
return name
def map_variable(self, varname, setvar = True):
- var = self.d.getVar(varname, True)
+ var = self.d.getVar(varname)
if not var:
return ""
var = var.split()
@@ -38,7 +56,7 @@ class ClassExtender(object):
return newdata
def map_regexp_variable(self, varname, setvar = True):
- var = self.d.getVar(varname, True)
+ var = self.d.getVar(varname)
if not var:
return ""
var = var.split()
@@ -60,7 +78,7 @@ class ClassExtender(object):
return dep
else:
# Do not extend for that already have multilib prefix
- var = self.d.getVar("MULTILIB_VARIANTS", True)
+ var = self.d.getVar("MULTILIB_VARIANTS")
if var:
var = var.split()
for v in var:
@@ -71,10 +89,10 @@ class ClassExtender(object):
def map_depends_variable(self, varname, suffix = ""):
# We need to preserve EXTENDPKGV so it can be expanded correctly later
if suffix:
- varname = varname + "_" + suffix
+ varname = varname + ":" + suffix
orig = self.d.getVar("EXTENDPKGV", False)
self.d.setVar("EXTENDPKGV", "EXTENDPKGV")
- deps = self.d.getVar(varname, True)
+ deps = self.d.getVar(varname)
if not deps:
self.d.setVar("EXTENDPKGV", orig)
return
@@ -83,11 +101,16 @@ class ClassExtender(object):
for dep in deps:
newdeps[self.map_depends(dep)] = deps[dep]
- self.d.setVar(varname, bb.utils.join_deps(newdeps, False).replace("EXTENDPKGV", "${EXTENDPKGV}"))
+ if not varname.endswith("_NONML"):
+ self.d.renameVar(varname, varname + "_NONML")
+ self.d.setVar(varname, "${@oe.classextend.get_depends('%s', d)}" % varname)
+ self.d.appendVarFlag(varname, "vardeps", " " + varname + "_NONML")
+ ret = bb.utils.join_deps(newdeps, False).replace("EXTENDPKGV", "${EXTENDPKGV}")
self.d.setVar("EXTENDPKGV", orig)
+ return ret
def map_packagevars(self):
- for pkg in (self.d.getVar("PACKAGES", True).split() + [""]):
+ for pkg in (self.d.getVar("PACKAGES").split() + [""]):
self.map_depends_variable("RDEPENDS", pkg)
self.map_depends_variable("RRECOMMENDS", pkg)
self.map_depends_variable("RSUGGESTS", pkg)
@@ -97,24 +120,37 @@ class ClassExtender(object):
self.map_depends_variable("PKG", pkg)
def rename_packages(self):
- for pkg in (self.d.getVar("PACKAGES", True) or "").split():
+ for pkg in (self.d.getVar("PACKAGES") or "").split():
+ if pkg.startswith(self.extname):
+ self.pkgs_mapping.append([pkg.split(self.extname + "-")[1], pkg])
+ continue
+ self.pkgs_mapping.append([pkg, self.extend_name(pkg)])
+
+ self.d.renameVar("PACKAGES", "PACKAGES_NONML")
+ self.d.setVar("PACKAGES", "${@oe.classextend.get_packages(d)}")
+
+ def rename_packages_internal(self, pkgs):
+ self.pkgs_mapping = []
+ for pkg in (self.d.expand(pkgs) or "").split():
if pkg.startswith(self.extname):
self.pkgs_mapping.append([pkg.split(self.extname + "-")[1], pkg])
continue
self.pkgs_mapping.append([pkg, self.extend_name(pkg)])
- self.d.setVar("PACKAGES", " ".join([row[1] for row in self.pkgs_mapping]))
+ return " ".join([row[1] for row in self.pkgs_mapping])
def rename_package_variables(self, variables):
for pkg_mapping in self.pkgs_mapping:
+ if pkg_mapping[0].startswith("${") and pkg_mapping[0].endswith("}"):
+ continue
for subs in variables:
- self.d.renameVar("%s_%s" % (subs, pkg_mapping[0]), "%s_%s" % (subs, pkg_mapping[1]))
+ self.d.renameVar("%s:%s" % (subs, pkg_mapping[0]), "%s:%s" % (subs, pkg_mapping[1]))
class NativesdkClassExtender(ClassExtender):
def map_depends(self, dep):
if dep.startswith(self.extname):
return dep
- if dep.endswith(("-gcc-initial", "-gcc", "-g++")):
+ if dep.endswith(("-gcc", "-g++")):
return dep + "-crosssdk"
elif dep.endswith(("-native", "-native-runtime")) or ('nativesdk-' in dep) or ('-cross-' in dep) or ('-crosssdk-' in dep):
return dep
diff --git a/meta/lib/oe/classutils.py b/meta/lib/oe/classutils.py
index e7856c86f2..ec3f6ad720 100644
--- a/meta/lib/oe/classutils.py
+++ b/meta/lib/oe/classutils.py
@@ -1,3 +1,8 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: GPL-2.0-only
+#
class ClassRegistryMeta(type):
"""Give each ClassRegistry their own registry"""
@@ -36,7 +41,7 @@ abstract base classes out of the registry)."""
@classmethod
def prioritized(tcls):
return sorted(list(tcls.registry.values()),
- key=lambda v: v.priority, reverse=True)
+ key=lambda v: (v.priority, v.name), reverse=True)
def unregister(cls):
for key in cls.registry.keys():
diff --git a/meta/lib/oe/copy_buildsystem.py b/meta/lib/oe/copy_buildsystem.py
index 4d3faf6681..a0d829054e 100644
--- a/meta/lib/oe/copy_buildsystem.py
+++ b/meta/lib/oe/copy_buildsystem.py
@@ -1,14 +1,30 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: GPL-2.0-only
+#
# This class should provide easy access to the different aspects of the
# buildsystem such as layers, bitbake location, etc.
+#
+# SDK_LAYERS_EXCLUDE: Layers which will be excluded from SDK layers.
+# SDK_LAYERS_EXCLUDE_PATTERN: The simiar to SDK_LAYERS_EXCLUDE, this supports
+# python regular expression, use space as separator,
+# e.g.: ".*-downloads closed-.*"
+#
+
import stat
import shutil
def _smart_copy(src, dest):
+ import subprocess
# smart_copy will choose the correct function depending on whether the
# source is a file or a directory.
mode = os.stat(src).st_mode
if stat.S_ISDIR(mode):
- shutil.copytree(src, dest, symlinks=True, ignore=shutil.ignore_patterns('.git'))
+ bb.utils.mkdirhier(dest)
+ cmd = "tar --exclude='.git' --exclude='__pycache__' --xattrs --xattrs-include='*' -chf - -C %s -p . \
+ | tar --xattrs --xattrs-include='*' -xf - -C %s" % (src, dest)
+ subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT)
else:
shutil.copyfile(src, dest)
shutil.copymode(src, dest)
@@ -17,23 +33,39 @@ class BuildSystem(object):
def __init__(self, context, d):
self.d = d
self.context = context
- self.layerdirs = d.getVar('BBLAYERS', True).split()
- self.layers_exclude = (d.getVar('SDK_LAYERS_EXCLUDE', True) or "").split()
+ self.layerdirs = [os.path.abspath(pth) for pth in d.getVar('BBLAYERS').split()]
+ self.layers_exclude = (d.getVar('SDK_LAYERS_EXCLUDE') or "").split()
+ self.layers_exclude_pattern = d.getVar('SDK_LAYERS_EXCLUDE_PATTERN')
def copy_bitbake_and_layers(self, destdir, workspace_name=None):
+ import re
# Copy in all metadata layers + bitbake (as repositories)
+ copied_corebase = None
layers_copied = []
bb.utils.mkdirhier(destdir)
layers = list(self.layerdirs)
- corebase = self.d.getVar('COREBASE', True)
+ corebase = os.path.abspath(self.d.getVar('COREBASE'))
layers.append(corebase)
+ # The bitbake build system uses the meta-skeleton layer as a layout
+ # for common recipies, e.g: the recipetool script to create kernel recipies
+ # Add the meta-skeleton layer to be included as part of the eSDK installation
+ layers.append(os.path.join(corebase, 'meta-skeleton'))
# Exclude layers
for layer_exclude in self.layers_exclude:
if layer_exclude in layers:
+ bb.note('Excluded %s from sdk layers since it is in SDK_LAYERS_EXCLUDE' % layer_exclude)
layers.remove(layer_exclude)
+ if self.layers_exclude_pattern:
+ layers_cp = layers[:]
+ for pattern in self.layers_exclude_pattern.split():
+ for layer in layers_cp:
+ if re.match(pattern, layer):
+ bb.note('Excluded %s from sdk layers since matched SDK_LAYERS_EXCLUDE_PATTERN' % layer)
+ layers.remove(layer)
+
workspace_newname = workspace_name
if workspace_newname:
layernames = [os.path.basename(layer) for layer in layers]
@@ -42,7 +74,7 @@ class BuildSystem(object):
extranum += 1
workspace_newname = '%s-%d' % (workspace_name, extranum)
- corebase_files = self.d.getVar('COREBASE_FILES', True).split()
+ corebase_files = self.d.getVar('COREBASE_FILES').split()
corebase_files = [corebase + '/' +x for x in corebase_files]
# Make sure bitbake goes in
bitbake_dir = bb.__file__.rsplit('/', 3)[0]
@@ -67,22 +99,30 @@ class BuildSystem(object):
layerdestpath = destdir
if corebase == os.path.dirname(layer):
layerdestpath += '/' + os.path.basename(corebase)
+ # If the layer is located somewhere under the same parent directory
+ # as corebase we keep the layer structure.
+ elif os.path.commonpath([layer, corebase]) == os.path.dirname(corebase):
+ layer_relative = os.path.relpath(layer, os.path.dirname(corebase))
+ if os.path.dirname(layer_relative) != layernewname:
+ layerdestpath += '/' + os.path.dirname(layer_relative)
+
layerdestpath += '/' + layernewname
layer_relative = os.path.relpath(layerdestpath,
destdir)
- layers_copied.append(layer_relative)
-
# Treat corebase as special since it typically will contain
# build directories or other custom items.
if corebase == layer:
+ copied_corebase = layer_relative
bb.utils.mkdirhier(layerdestpath)
for f in corebase_files:
f_basename = os.path.basename(f)
destname = os.path.join(layerdestpath, f_basename)
_smart_copy(f, destname)
else:
- if os.path.exists(layerdestpath):
+ layers_copied.append(layer_relative)
+
+ if os.path.exists(os.path.join(layerdestpath, 'conf/layer.conf')):
bb.note("Skipping layer %s, already handled" % layer)
else:
_smart_copy(layer, layerdestpath)
@@ -96,7 +136,7 @@ class BuildSystem(object):
# Drop all bbappends except the one for the image the SDK is being built for
# (because of externalsrc, the workspace bbappends will interfere with the
# locked signatures if present, and we don't need them anyway)
- image_bbappend = os.path.splitext(os.path.basename(self.d.getVar('FILE', True)))[0] + '.bbappend'
+ image_bbappend = os.path.splitext(os.path.basename(self.d.getVar('FILE')))[0] + '.bbappend'
appenddir = os.path.join(layerdestpath, 'appends')
if os.path.isdir(appenddir):
for fn in os.listdir(appenddir):
@@ -119,15 +159,23 @@ class BuildSystem(object):
line = line.replace('workspacelayer', workspace_newname)
f.write(line)
- return layers_copied
+ # meta-skeleton layer is added as part of the build system
+ # but not as a layer included in the build, therefore it is
+ # not reported to the function caller.
+ for layer in layers_copied:
+ if layer.endswith('/meta-skeleton'):
+ layers_copied.remove(layer)
+ break
+
+ return copied_corebase, layers_copied
def generate_locked_sigs(sigfile, d):
bb.utils.mkdirhier(os.path.dirname(sigfile))
depd = d.getVar('BB_TASKDEPDATA', False)
- tasks = ['%s.%s' % (v[2], v[1]) for v in depd.values()]
+ tasks = ['%s:%s' % (v[2], v[1]) for v in depd.values()]
bb.parse.siggen.dump_lockedsigs(sigfile, tasks)
-def prune_lockedsigs(excluded_tasks, excluded_targets, lockedsigs, pruned_output):
+def prune_lockedsigs(excluded_tasks, excluded_targets, lockedsigs, onlynative, pruned_output):
with open(lockedsigs, 'r') as infile:
bb.utils.mkdirhier(os.path.dirname(pruned_output))
with open(pruned_output, 'w') as f:
@@ -137,7 +185,11 @@ def prune_lockedsigs(excluded_tasks, excluded_targets, lockedsigs, pruned_output
if line.endswith('\\\n'):
splitval = line.strip().split(':')
if not splitval[1] in excluded_tasks and not splitval[0] in excluded_targets:
- f.write(line)
+ if onlynative:
+ if 'nativesdk' in splitval[0]:
+ f.write(line)
+ else:
+ f.write(line)
else:
f.write(line)
invalue = False
@@ -201,21 +253,25 @@ def merge_lockedsigs(copy_tasks, lockedsigs_main, lockedsigs_extra, merged_outpu
write_sigs_file(merged_output, arch_order, merged)
def create_locked_sstate_cache(lockedsigs, input_sstate_cache, output_sstate_cache, d, fixedlsbstring="", filterfile=None):
+ import shutil
bb.note('Generating sstate-cache...')
- nativelsbstring = d.getVar('NATIVELSBSTRING', True)
- bb.process.run("gen-lockedsig-cache %s %s %s %s %s" % (lockedsigs, input_sstate_cache, output_sstate_cache, nativelsbstring, filterfile or ''))
- if fixedlsbstring:
+ nativelsbstring = d.getVar('NATIVELSBSTRING')
+ bb.process.run("PYTHONDONTWRITEBYTECODE=1 gen-lockedsig-cache %s %s %s %s %s" % (lockedsigs, input_sstate_cache, output_sstate_cache, nativelsbstring, filterfile or ''))
+ if fixedlsbstring and nativelsbstring != fixedlsbstring:
nativedir = output_sstate_cache + '/' + nativelsbstring
if os.path.isdir(nativedir):
destdir = os.path.join(output_sstate_cache, fixedlsbstring)
- bb.utils.mkdirhier(destdir)
-
- dirlist = os.listdir(nativedir)
- for i in dirlist:
- src = os.path.join(nativedir, i)
- dest = os.path.join(destdir, i)
- os.rename(src, dest)
+ for root, _, files in os.walk(nativedir):
+ for fn in files:
+ src = os.path.join(root, fn)
+ dest = os.path.join(destdir, os.path.relpath(src, nativedir))
+ if os.path.exists(dest):
+ # Already exists, and it'll be the same file, so just delete it
+ os.unlink(src)
+ else:
+ bb.utils.mkdirhier(os.path.dirname(dest))
+ shutil.move(src, dest)
def check_sstate_task_list(d, targets, filteroutfile, cmdprefix='', cwd=None, logfile=None):
import subprocess
@@ -228,9 +284,10 @@ def check_sstate_task_list(d, targets, filteroutfile, cmdprefix='', cwd=None, lo
logparam = '-l %s' % logfile
else:
logparam = ''
- cmd = "%sBB_SETSCENE_ENFORCE=1 PSEUDO_DISABLED=1 oe-check-sstate %s -s -o %s %s" % (cmdprefix, targets, filteroutfile, logparam)
+ cmd = "%sPYTHONDONTWRITEBYTECODE=1 BB_SETSCENE_ENFORCE=1 PSEUDO_DISABLED=1 oe-check-sstate %s -s -o %s %s" % (cmdprefix, targets, filteroutfile, logparam)
env = dict(d.getVar('BB_ORIGENV', False))
env.pop('BUILDDIR', '')
+ env.pop('BBPATH', '')
pathitems = env['PATH'].split(':')
env['PATH'] = ':'.join([item for item in pathitems if not item.endswith('/bitbake/bin')])
bb.process.run(cmd, stderr=subprocess.STDOUT, env=env, cwd=cwd, executable='/bin/bash')
diff --git a/meta/lib/oe/cve_check.py b/meta/lib/oe/cve_check.py
new file mode 100644
index 0000000000..4f1d80f050
--- /dev/null
+++ b/meta/lib/oe/cve_check.py
@@ -0,0 +1,181 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
+import collections
+import re
+import itertools
+import functools
+
+_Version = collections.namedtuple(
+ "_Version", ["release", "patch_l", "pre_l", "pre_v"]
+)
+
+@functools.total_ordering
+class Version():
+
+ def __init__(self, version, suffix=None):
+
+ suffixes = ["alphabetical", "patch"]
+
+ if str(suffix) == "alphabetical":
+ version_pattern = r"""r?v?(?:(?P<release>[0-9]+(?:[-\.][0-9]+)*)(?P<patch>[-_\.]?(?P<patch_l>[a-z]))?(?P<pre>[-_\.]?(?P<pre_l>(rc|alpha|beta|pre|preview|dev))[-_\.]?(?P<pre_v>[0-9]+)?)?)(.*)?"""
+ elif str(suffix) == "patch":
+ version_pattern = r"""r?v?(?:(?P<release>[0-9]+(?:[-\.][0-9]+)*)(?P<patch>[-_\.]?(p|patch)(?P<patch_l>[0-9]+))?(?P<pre>[-_\.]?(?P<pre_l>(rc|alpha|beta|pre|preview|dev))[-_\.]?(?P<pre_v>[0-9]+)?)?)(.*)?"""
+ else:
+ version_pattern = r"""r?v?(?:(?P<release>[0-9]+(?:[-\.][0-9]+)*)(?P<pre>[-_\.]?(?P<pre_l>(rc|alpha|beta|pre|preview|dev))[-_\.]?(?P<pre_v>[0-9]+)?)?)(.*)?"""
+ regex = re.compile(r"^\s*" + version_pattern + r"\s*$", re.VERBOSE | re.IGNORECASE)
+
+ match = regex.search(version)
+ if not match:
+ raise Exception("Invalid version: '{0}'".format(version))
+
+ self._version = _Version(
+ release=tuple(int(i) for i in match.group("release").replace("-",".").split(".")),
+ patch_l=match.group("patch_l") if str(suffix) in suffixes and match.group("patch_l") else "",
+ pre_l=match.group("pre_l"),
+ pre_v=match.group("pre_v")
+ )
+
+ self._key = _cmpkey(
+ self._version.release,
+ self._version.patch_l,
+ self._version.pre_l,
+ self._version.pre_v
+ )
+
+ def __eq__(self, other):
+ if not isinstance(other, Version):
+ return NotImplemented
+ return self._key == other._key
+
+ def __gt__(self, other):
+ if not isinstance(other, Version):
+ return NotImplemented
+ return self._key > other._key
+
+def _cmpkey(release, patch_l, pre_l, pre_v):
+ # remove leading 0
+ _release = tuple(
+ reversed(list(itertools.dropwhile(lambda x: x == 0, reversed(release))))
+ )
+
+ _patch = patch_l.upper()
+
+ if pre_l is None and pre_v is None:
+ _pre = float('inf')
+ else:
+ _pre = float(pre_v) if pre_v else float('-inf')
+ return _release, _patch, _pre
+
+
+def get_patched_cves(d):
+ """
+ Get patches that solve CVEs using the "CVE: " tag.
+ """
+
+ import re
+ import oe.patch
+
+ pn = d.getVar("PN")
+ cve_match = re.compile("CVE:( CVE\-\d{4}\-\d+)+")
+
+ # Matches the last "CVE-YYYY-ID" in the file name, also if written
+ # in lowercase. Possible to have multiple CVE IDs in a single
+ # file name, but only the last one will be detected from the file name.
+ # However, patch files contents addressing multiple CVE IDs are supported
+ # (cve_match regular expression)
+
+ cve_file_name_match = re.compile(".*([Cc][Vv][Ee]\-\d{4}\-\d+)")
+
+ patched_cves = set()
+ bb.debug(2, "Looking for patches that solves CVEs for %s" % pn)
+ for url in oe.patch.src_patches(d):
+ patch_file = bb.fetch.decodeurl(url)[2]
+
+ # Remote compressed patches may not be unpacked, so silently ignore them
+ if not os.path.isfile(patch_file):
+ bb.warn("%s does not exist, cannot extract CVE list" % patch_file)
+ continue
+
+ # Check patch file name for CVE ID
+ fname_match = cve_file_name_match.search(patch_file)
+ if fname_match:
+ cve = fname_match.group(1).upper()
+ patched_cves.add(cve)
+ bb.debug(2, "Found CVE %s from patch file name %s" % (cve, patch_file))
+
+ with open(patch_file, "r", encoding="utf-8") as f:
+ try:
+ patch_text = f.read()
+ except UnicodeDecodeError:
+ bb.debug(1, "Failed to read patch %s using UTF-8 encoding"
+ " trying with iso8859-1" % patch_file)
+ f.close()
+ with open(patch_file, "r", encoding="iso8859-1") as f:
+ patch_text = f.read()
+
+ # Search for one or more "CVE: " lines
+ text_match = False
+ for match in cve_match.finditer(patch_text):
+ # Get only the CVEs without the "CVE: " tag
+ cves = patch_text[match.start()+5:match.end()]
+ for cve in cves.split():
+ bb.debug(2, "Patch %s solves %s" % (patch_file, cve))
+ patched_cves.add(cve)
+ text_match = True
+
+ if not fname_match and not text_match:
+ bb.debug(2, "Patch %s doesn't solve CVEs" % patch_file)
+
+ return patched_cves
+
+
+def get_cpe_ids(cve_product, version):
+ """
+ Get list of CPE identifiers for the given product and version
+ """
+
+ version = version.split("+git")[0]
+
+ cpe_ids = []
+ for product in cve_product.split():
+ # CVE_PRODUCT in recipes may include vendor information for CPE identifiers. If not,
+ # use wildcard for vendor.
+ if ":" in product:
+ vendor, product = product.split(":", 1)
+ else:
+ vendor = "*"
+
+ cpe_id = 'cpe:2.3:a:{}:{}:{}:*:*:*:*:*:*:*'.format(vendor, product, version)
+ cpe_ids.append(cpe_id)
+
+ return cpe_ids
+
+def cve_check_merge_jsons(output, data):
+ """
+ Merge the data in the "package" property to the main data file
+ output
+ """
+ if output["version"] != data["version"]:
+ bb.error("Version mismatch when merging JSON outputs")
+ return
+
+ for product in output["package"]:
+ if product["name"] == data["package"][0]["name"]:
+ bb.error("Error adding the same package twice")
+ return
+
+ output["package"].append(data["package"][0])
+
+def update_symlinks(target_path, link_path):
+ """
+ Update a symbolic link link_path to point to target_path.
+ Remove the link and recreate it if exist and is different.
+ """
+ if link_path != target_path and os.path.exists(target_path):
+ if os.path.exists(os.path.realpath(link_path)):
+ os.remove(link_path)
+ os.symlink(os.path.basename(target_path), link_path)
diff --git a/meta/lib/oe/data.py b/meta/lib/oe/data.py
index ee48950a82..37121cfad2 100644
--- a/meta/lib/oe/data.py
+++ b/meta/lib/oe/data.py
@@ -1,9 +1,16 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: GPL-2.0-only
+#
+
+import json
import oe.maketype
def typed_value(key, d):
"""Construct a value for the specified metadata variable, using its flags
to determine the type and parameters for construction."""
- var_type = d.getVarFlag(key, 'type', True)
+ var_type = d.getVarFlag(key, 'type')
flags = d.getVarFlags(key)
if flags is not None:
flags = dict((flag, d.expand(value))
@@ -12,6 +19,35 @@ def typed_value(key, d):
flags = {}
try:
- return oe.maketype.create(d.getVar(key, True) or '', var_type, **flags)
+ return oe.maketype.create(d.getVar(key) or '', var_type, **flags)
except (TypeError, ValueError) as exc:
bb.msg.fatal("Data", "%s: %s" % (key, str(exc)))
+
+def export2json(d, json_file, expand=True, searchString="",replaceString=""):
+ data2export = {}
+ keys2export = []
+
+ for key in d.keys():
+ if key.startswith("_"):
+ continue
+ elif key.startswith("BB"):
+ continue
+ elif key.startswith("B_pn"):
+ continue
+ elif key.startswith("do_"):
+ continue
+ elif d.getVarFlag(key, "func"):
+ continue
+
+ keys2export.append(key)
+
+ for key in keys2export:
+ try:
+ data2export[key] = d.getVar(key, expand).replace(searchString,replaceString)
+ except bb.data_smart.ExpansionError:
+ data2export[key] = ''
+ except AttributeError:
+ pass
+
+ with open(json_file, "w") as f:
+ json.dump(data2export, f, skipkeys=True, indent=4, sort_keys=True)
diff --git a/meta/lib/oe/distro_check.py b/meta/lib/oe/distro_check.py
index 87c52fae9c..3494520f40 100644
--- a/meta/lib/oe/distro_check.py
+++ b/meta/lib/oe/distro_check.py
@@ -1,32 +1,23 @@
-from contextlib import contextmanager
-
-from bb.utils import export_proxies
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: GPL-2.0-only
+#
def create_socket(url, d):
import urllib
+ from bb.utils import export_proxies
- socket = None
- try:
- export_proxies(d)
- socket = urllib.request.urlopen(url)
- except:
- bb.warn("distro_check: create_socket url %s can't access" % url)
-
- return socket
+ export_proxies(d)
+ return urllib.request.urlopen(url)
def get_links_from_url(url, d):
"Return all the href links found on the web location"
from bs4 import BeautifulSoup, SoupStrainer
+ soup = BeautifulSoup(create_socket(url,d), "html.parser", parse_only=SoupStrainer("a"))
hyperlinks = []
-
- webpage = ''
- sock = create_socket(url,d)
- if sock:
- webpage = sock.read()
-
- soup = BeautifulSoup(webpage, "html.parser", parse_only=SoupStrainer("a"))
for line in soup.find_all('a', href=True):
hyperlinks.append(line['href'].strip('/'))
return hyperlinks
@@ -37,6 +28,7 @@ def find_latest_numeric_release(url, d):
maxstr=""
for link in get_links_from_url(url, d):
try:
+ # TODO use bb.utils.vercmp_string_op()
release = float(link)
except:
release = 0
@@ -47,144 +39,105 @@ def find_latest_numeric_release(url, d):
def is_src_rpm(name):
"Check if the link is pointing to a src.rpm file"
- if name[-8:] == ".src.rpm":
- return True
- else:
- return False
+ return name.endswith(".src.rpm")
def package_name_from_srpm(srpm):
"Strip out the package name from the src.rpm filename"
- strings = srpm.split('-')
- package_name = strings[0]
- for i in range(1, len (strings) - 1):
- str = strings[i]
- if not str[0].isdigit():
- package_name += '-' + str
- return package_name
-
-def clean_package_list(package_list):
- "Removes multiple entries of packages and sorts the list"
- set = {}
- map(set.__setitem__, package_list, [])
- return set.keys()
-
-def get_latest_released_meego_source_package_list(d):
- "Returns list of all the name os packages in the latest meego distro"
-
- package_names = []
- try:
- f = open("/tmp/Meego-1.1", "r")
- for line in f:
- package_names.append(line[:-1] + ":" + "main") # Also strip the '\n' at the end
- except IOError: pass
- package_list=clean_package_list(package_names)
- return "1.0", package_list
+ # ca-certificates-2016.2.7-1.0.fc24.src.rpm
+ # ^name ^ver ^release^removed
+ (name, version, release) = srpm.replace(".src.rpm", "").rsplit("-", 2)
+ return name
def get_source_package_list_from_url(url, section, d):
"Return a sectioned list of package names from a URL list"
bb.note("Reading %s: %s" % (url, section))
links = get_links_from_url(url, d)
- srpms = list(filter(is_src_rpm, links))
- names_list = list(map(package_name_from_srpm, srpms))
+ srpms = filter(is_src_rpm, links)
+ names_list = map(package_name_from_srpm, srpms)
- new_pkgs = []
+ new_pkgs = set()
for pkgs in names_list:
- new_pkgs.append(pkgs + ":" + section)
-
+ new_pkgs.add(pkgs + ":" + section)
return new_pkgs
+def get_source_package_list_from_url_by_letter(url, section, d):
+ import string
+ from urllib.error import HTTPError
+ packages = set()
+ for letter in (string.ascii_lowercase + string.digits):
+ # Not all subfolders may exist, so silently handle 404
+ try:
+ packages |= get_source_package_list_from_url(url + "/" + letter, section, d)
+ except HTTPError as e:
+ if e.code != 404: raise
+ return packages
+
def get_latest_released_fedora_source_package_list(d):
"Returns list of all the name os packages in the latest fedora distro"
latest = find_latest_numeric_release("http://archive.fedoraproject.org/pub/fedora/linux/releases/", d)
-
- package_names = get_source_package_list_from_url("http://archive.fedoraproject.org/pub/fedora/linux/releases/%s/Fedora/source/SRPMS/" % latest, "main", d)
-
-# package_names += get_source_package_list_from_url("http://download.fedora.redhat.com/pub/fedora/linux/releases/%s/Everything/source/SPRMS/" % latest, "everything")
- package_names += get_source_package_list_from_url("http://archive.fedoraproject.org/pub/fedora/linux/updates/%s/SRPMS/" % latest, "updates", d)
-
- package_list=clean_package_list(package_names)
-
- return latest, package_list
+ package_names = get_source_package_list_from_url_by_letter("http://archive.fedoraproject.org/pub/fedora/linux/releases/%s/Everything/source/tree/Packages/" % latest, "main", d)
+ package_names |= get_source_package_list_from_url_by_letter("http://archive.fedoraproject.org/pub/fedora/linux/updates/%s/SRPMS/" % latest, "updates", d)
+ return latest, package_names
def get_latest_released_opensuse_source_package_list(d):
"Returns list of all the name os packages in the latest opensuse distro"
- latest = find_latest_numeric_release("http://download.opensuse.org/source/distribution/",d)
-
- package_names = get_source_package_list_from_url("http://download.opensuse.org/source/distribution/%s/repo/oss/suse/src/" % latest, "main", d)
- package_names += get_source_package_list_from_url("http://download.opensuse.org/update/%s/rpm/src/" % latest, "updates", d)
-
- package_list=clean_package_list(package_names)
- return latest, package_list
+ latest = find_latest_numeric_release("http://download.opensuse.org/source/distribution/leap", d)
-def get_latest_released_mandriva_source_package_list(d):
- "Returns list of all the name os packages in the latest mandriva distro"
- latest = find_latest_numeric_release("http://distrib-coffee.ipsl.jussieu.fr/pub/linux/MandrivaLinux/official/", d)
- package_names = get_source_package_list_from_url("http://distrib-coffee.ipsl.jussieu.fr/pub/linux/MandrivaLinux/official/%s/SRPMS/main/release/" % latest, "main", d)
-# package_names += get_source_package_list_from_url("http://distrib-coffee.ipsl.jussieu.fr/pub/linux/MandrivaLinux/official/%s/SRPMS/contrib/release/" % latest, "contrib")
- package_names += get_source_package_list_from_url("http://distrib-coffee.ipsl.jussieu.fr/pub/linux/MandrivaLinux/official/%s/SRPMS/main/updates/" % latest, "updates", d)
+ package_names = get_source_package_list_from_url("http://download.opensuse.org/source/distribution/leap/%s/repo/oss/suse/src/" % latest, "main", d)
+ package_names |= get_source_package_list_from_url("http://download.opensuse.org/update/leap/%s/oss/src/" % latest, "updates", d)
+ return latest, package_names
- package_list=clean_package_list(package_names)
- return latest, package_list
+def get_latest_released_clear_source_package_list(d):
+ latest = find_latest_numeric_release("https://download.clearlinux.org/releases/", d)
+ package_names = get_source_package_list_from_url("https://download.clearlinux.org/releases/%s/clear/source/SRPMS/" % latest, "main", d)
+ return latest, package_names
def find_latest_debian_release(url, d):
"Find the latest listed debian release on the given url"
- releases = []
- for link in get_links_from_url(url, d):
- if link[:6] == "Debian":
- if ';' not in link:
- releases.append(link)
+ releases = [link.replace("Debian", "")
+ for link in get_links_from_url(url, d)
+ if link.startswith("Debian")]
releases.sort()
try:
- return releases.pop()[6:]
+ return releases[-1]
except:
return "_NotFound_"
def get_debian_style_source_package_list(url, section, d):
"Return the list of package-names stored in the debian style Sources.gz file"
- import tempfile
import gzip
- webpage = ''
- sock = create_socket(url,d)
- if sock:
- webpage = sock.read()
-
- tmpfile = tempfile.NamedTemporaryFile(mode='wb', prefix='oecore.', suffix='.tmp', delete=False)
- tmpfilename=tmpfile.name
- tmpfile.write(sock.read())
- tmpfile.close()
- bb.note("Reading %s: %s" % (url, section))
-
- f = gzip.open(tmpfilename)
- package_names = []
- for line in f:
- if line[:9] == "Package: ":
- package_names.append(line[9:-1] + ":" + section) # Also strip the '\n' at the end
- os.unlink(tmpfilename)
-
+ package_names = set()
+ for line in gzip.open(create_socket(url, d), mode="rt"):
+ if line.startswith("Package:"):
+ pkg = line.split(":", 1)[1].strip()
+ package_names.add(pkg + ":" + section)
return package_names
def get_latest_released_debian_source_package_list(d):
- "Returns list of all the name os packages in the latest debian distro"
+ "Returns list of all the name of packages in the latest debian distro"
latest = find_latest_debian_release("http://ftp.debian.org/debian/dists/", d)
- url = "http://ftp.debian.org/debian/dists/stable/main/source/Sources.gz"
+ url = "http://ftp.debian.org/debian/dists/stable/main/source/Sources.gz"
package_names = get_debian_style_source_package_list(url, "main", d)
-# url = "http://ftp.debian.org/debian/dists/stable/contrib/source/Sources.gz"
-# package_names += get_debian_style_source_package_list(url, "contrib")
- url = "http://ftp.debian.org/debian/dists/stable-proposed-updates/main/source/Sources.gz"
- package_names += get_debian_style_source_package_list(url, "updates", d)
- package_list=clean_package_list(package_names)
- return latest, package_list
+ url = "http://ftp.debian.org/debian/dists/stable-proposed-updates/main/source/Sources.gz"
+ package_names |= get_debian_style_source_package_list(url, "updates", d)
+ return latest, package_names
def find_latest_ubuntu_release(url, d):
- "Find the latest listed ubuntu release on the given url"
+ """
+ Find the latest listed Ubuntu release on the given ubuntu/dists/ URL.
+
+ To avoid matching development releases look for distributions that have
+ updates, so the resulting distro could be any supported release.
+ """
url += "?C=M;O=D" # Descending Sort by Last Modified
for link in get_links_from_url(url, d):
- if link[-8:] == "-updates":
- return link[:-8]
+ if "-updates" in link:
+ distro = link.replace("-updates", "")
+ return distro
return "_NotFound_"
def get_latest_released_ubuntu_source_package_list(d):
@@ -192,52 +145,44 @@ def get_latest_released_ubuntu_source_package_list(d):
latest = find_latest_ubuntu_release("http://archive.ubuntu.com/ubuntu/dists/", d)
url = "http://archive.ubuntu.com/ubuntu/dists/%s/main/source/Sources.gz" % latest
package_names = get_debian_style_source_package_list(url, "main", d)
-# url = "http://archive.ubuntu.com/ubuntu/dists/%s/multiverse/source/Sources.gz" % latest
-# package_names += get_debian_style_source_package_list(url, "multiverse")
-# url = "http://archive.ubuntu.com/ubuntu/dists/%s/universe/source/Sources.gz" % latest
-# package_names += get_debian_style_source_package_list(url, "universe")
url = "http://archive.ubuntu.com/ubuntu/dists/%s-updates/main/source/Sources.gz" % latest
- package_names += get_debian_style_source_package_list(url, "updates", d)
- package_list=clean_package_list(package_names)
- return latest, package_list
+ package_names |= get_debian_style_source_package_list(url, "updates", d)
+ return latest, package_names
def create_distro_packages_list(distro_check_dir, d):
+ import shutil
+
pkglst_dir = os.path.join(distro_check_dir, "package_lists")
- if not os.path.isdir (pkglst_dir):
- os.makedirs(pkglst_dir)
- # first clear old stuff
- for file in os.listdir(pkglst_dir):
- os.unlink(os.path.join(pkglst_dir, file))
-
- per_distro_functions = [
- ["Debian", get_latest_released_debian_source_package_list],
- ["Ubuntu", get_latest_released_ubuntu_source_package_list],
- ["Fedora", get_latest_released_fedora_source_package_list],
- ["OpenSuSE", get_latest_released_opensuse_source_package_list],
- ["Mandriva", get_latest_released_mandriva_source_package_list],
- ["Meego", get_latest_released_meego_source_package_list]
- ]
-
- from datetime import datetime
- begin = datetime.now()
- for distro in per_distro_functions:
- name = distro[0]
- release, package_list = distro[1](d)
+ bb.utils.remove(pkglst_dir, True)
+ bb.utils.mkdirhier(pkglst_dir)
+
+ per_distro_functions = (
+ ("Debian", get_latest_released_debian_source_package_list),
+ ("Ubuntu", get_latest_released_ubuntu_source_package_list),
+ ("Fedora", get_latest_released_fedora_source_package_list),
+ ("openSUSE", get_latest_released_opensuse_source_package_list),
+ ("Clear", get_latest_released_clear_source_package_list),
+ )
+
+ for name, fetcher_func in per_distro_functions:
+ try:
+ release, package_list = fetcher_func(d)
+ except Exception as e:
+ bb.warn("Cannot fetch packages for %s: %s" % (name, e))
bb.note("Distro: %s, Latest Release: %s, # src packages: %d" % (name, release, len(package_list)))
+ if len(package_list) == 0:
+ bb.error("Didn't fetch any packages for %s %s" % (name, release))
+
package_list_file = os.path.join(pkglst_dir, name + "-" + release)
- f = open(package_list_file, "w+b")
- for pkg in package_list:
- f.write(pkg + "\n")
- f.close()
- end = datetime.now()
- delta = end - begin
- bb.note("package_list generatiosn took this much time: %d seconds" % delta.seconds)
+ with open(package_list_file, 'w') as f:
+ for pkg in sorted(package_list):
+ f.write(pkg + "\n")
def update_distro_data(distro_check_dir, datetime, d):
"""
- If distro packages list data is old then rebuild it.
- The operations has to be protected by a lock so that
- only one thread performes it at a time.
+ If distro packages list data is old then rebuild it.
+ The operations has to be protected by a lock so that
+ only one thread performes it at a time.
"""
if not os.path.isdir (distro_check_dir):
try:
@@ -264,71 +209,59 @@ def update_distro_data(distro_check_dir, datetime, d):
f.seek(0)
f.write(datetime)
- except OSError:
- raise Exception('Unable to read/write this file: %s' % (datetime_file))
+ except OSError as e:
+ raise Exception('Unable to open timestamp: %s' % e)
finally:
fcntl.lockf(f, fcntl.LOCK_UN)
f.close()
-
+
def compare_in_distro_packages_list(distro_check_dir, d):
if not os.path.isdir(distro_check_dir):
raise Exception("compare_in_distro_packages_list: invalid distro_check_dir passed")
-
+
localdata = bb.data.createCopy(d)
pkglst_dir = os.path.join(distro_check_dir, "package_lists")
matching_distros = []
- pn = d.getVar('PN', True)
- recipe_name = d.getVar('PN', True)
+ pn = recipe_name = d.getVar('PN')
bb.note("Checking: %s" % pn)
- trim_dict = dict({"-native":"-native", "-cross":"-cross", "-initial":"-initial"})
-
if pn.find("-native") != -1:
pnstripped = pn.split("-native")
- localdata.setVar('OVERRIDES', "pn-" + pnstripped[0] + ":" + d.getVar('OVERRIDES', True))
- bb.data.update_data(localdata)
+ localdata.setVar('OVERRIDES', "pn-" + pnstripped[0] + ":" + d.getVar('OVERRIDES'))
recipe_name = pnstripped[0]
if pn.startswith("nativesdk-"):
pnstripped = pn.split("nativesdk-")
- localdata.setVar('OVERRIDES', "pn-" + pnstripped[1] + ":" + d.getVar('OVERRIDES', True))
- bb.data.update_data(localdata)
+ localdata.setVar('OVERRIDES', "pn-" + pnstripped[1] + ":" + d.getVar('OVERRIDES'))
recipe_name = pnstripped[1]
if pn.find("-cross") != -1:
pnstripped = pn.split("-cross")
- localdata.setVar('OVERRIDES', "pn-" + pnstripped[0] + ":" + d.getVar('OVERRIDES', True))
- bb.data.update_data(localdata)
+ localdata.setVar('OVERRIDES', "pn-" + pnstripped[0] + ":" + d.getVar('OVERRIDES'))
recipe_name = pnstripped[0]
if pn.find("-initial") != -1:
pnstripped = pn.split("-initial")
- localdata.setVar('OVERRIDES', "pn-" + pnstripped[0] + ":" + d.getVar('OVERRIDES', True))
- bb.data.update_data(localdata)
+ localdata.setVar('OVERRIDES', "pn-" + pnstripped[0] + ":" + d.getVar('OVERRIDES'))
recipe_name = pnstripped[0]
bb.note("Recipe: %s" % recipe_name)
- tmp = localdata.getVar('DISTRO_PN_ALIAS', True)
distro_exceptions = dict({"OE-Core":'OE-Core', "OpenedHand":'OpenedHand', "Intel":'Intel', "Upstream":'Upstream', "Windriver":'Windriver', "OSPDT":'OSPDT Approved', "Poky":'poky'})
-
- if tmp:
- list = tmp.split(' ')
- for str in list:
- if str and str.find("=") == -1 and distro_exceptions[str]:
- matching_distros.append(str)
+ tmp = localdata.getVar('DISTRO_PN_ALIAS') or ""
+ for str in tmp.split():
+ if str and str.find("=") == -1 and distro_exceptions[str]:
+ matching_distros.append(str)
distro_pn_aliases = {}
- if tmp:
- list = tmp.split(' ')
- for str in list:
- if str.find("=") != -1:
- (dist, pn_alias) = str.split('=')
- distro_pn_aliases[dist.strip().lower()] = pn_alias.strip()
-
+ for str in tmp.split():
+ if "=" in str:
+ (dist, pn_alias) = str.split('=')
+ distro_pn_aliases[dist.strip().lower()] = pn_alias.strip()
+
for file in os.listdir(pkglst_dir):
(distro, distro_release) = file.split("-")
- f = open(os.path.join(pkglst_dir, file), "rb")
+ f = open(os.path.join(pkglst_dir, file), "r")
for line in f:
(pkg, section) = line.split(":")
if distro.lower() in distro_pn_aliases:
@@ -341,38 +274,34 @@ def compare_in_distro_packages_list(distro_check_dir, d):
break
f.close()
-
- if tmp != None:
- list = tmp.split(' ')
- for item in list:
- matching_distros.append(item)
+ for item in tmp.split():
+ matching_distros.append(item)
bb.note("Matching: %s" % matching_distros)
return matching_distros
def create_log_file(d, logname):
- import subprocess
- logpath = d.getVar('LOG_DIR', True)
+ logpath = d.getVar('LOG_DIR')
bb.utils.mkdirhier(logpath)
logfn, logsuffix = os.path.splitext(logname)
- logfile = os.path.join(logpath, "%s.%s%s" % (logfn, d.getVar('DATETIME', True), logsuffix))
+ logfile = os.path.join(logpath, "%s.%s%s" % (logfn, d.getVar('DATETIME'), logsuffix))
if not os.path.exists(logfile):
slogfile = os.path.join(logpath, logname)
if os.path.exists(slogfile):
os.remove(slogfile)
- subprocess.call("touch %s" % logfile, shell=True)
+ open(logfile, 'w+').close()
os.symlink(logfile, slogfile)
d.setVar('LOG_FILE', logfile)
return logfile
def save_distro_check_result(result, datetime, result_file, d):
- pn = d.getVar('PN', True)
- logdir = d.getVar('LOG_DIR', True)
+ pn = d.getVar('PN')
+ logdir = d.getVar('LOG_DIR')
if not logdir:
bb.error("LOG_DIR variable is not defined, can't write the distro_check results")
return
- if not os.path.isdir(logdir):
- os.makedirs(logdir)
+ bb.utils.mkdirhier(logdir)
+
line = pn
for i in result:
line = line + "," + i
diff --git a/meta/lib/oe/elf.py b/meta/lib/oe/elf.py
new file mode 100644
index 0000000000..eab2349a4f
--- /dev/null
+++ b/meta/lib/oe/elf.py
@@ -0,0 +1,145 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: GPL-2.0-only
+#
+
+def machine_dict(d):
+# TARGET_OS TARGET_ARCH MACHINE, OSABI, ABIVERSION, Little Endian, 32bit?
+ machdata = {
+ "darwin9" : {
+ "arm" : (40, 0, 0, True, 32),
+ },
+ "eabi" : {
+ "arm" : (40, 0, 0, True, 32),
+ },
+ "elf" : {
+ "aarch64" : (183, 0, 0, True, 64),
+ "aarch64_be" :(183, 0, 0, False, 64),
+ "i586" : (3, 0, 0, True, 32),
+ "i686" : (3, 0, 0, True, 32),
+ "x86_64": (62, 0, 0, True, 64),
+ "epiphany": (4643, 0, 0, True, 32),
+ "lm32": (138, 0, 0, False, 32),
+ "loongarch64":(258, 0, 0, True, 64),
+ "mips": ( 8, 0, 0, False, 32),
+ "mipsel": ( 8, 0, 0, True, 32),
+ "microblaze": (189, 0, 0, False, 32),
+ "microblazeel":(189, 0, 0, True, 32),
+ "powerpc": (20, 0, 0, False, 32),
+ "riscv32": (243, 0, 0, True, 32),
+ "riscv64": (243, 0, 0, True, 64),
+ },
+ "linux" : {
+ "aarch64" : (183, 0, 0, True, 64),
+ "aarch64_be" :(183, 0, 0, False, 64),
+ "arm" : (40, 97, 0, True, 32),
+ "armeb": (40, 97, 0, False, 32),
+ "powerpc": (20, 0, 0, False, 32),
+ "powerpc64": (21, 0, 0, False, 64),
+ "powerpc64le": (21, 0, 0, True, 64),
+ "i386": ( 3, 0, 0, True, 32),
+ "i486": ( 3, 0, 0, True, 32),
+ "i586": ( 3, 0, 0, True, 32),
+ "i686": ( 3, 0, 0, True, 32),
+ "x86_64": (62, 0, 0, True, 64),
+ "ia64": (50, 0, 0, True, 64),
+ "alpha": (36902, 0, 0, True, 64),
+ "hppa": (15, 3, 0, False, 32),
+ "loongarch64":(258, 0, 0, True, 64),
+ "m68k": ( 4, 0, 0, False, 32),
+ "mips": ( 8, 0, 0, False, 32),
+ "mipsel": ( 8, 0, 0, True, 32),
+ "mips64": ( 8, 0, 0, False, 64),
+ "mips64el": ( 8, 0, 0, True, 64),
+ "mipsisa32r6": ( 8, 0, 0, False, 32),
+ "mipsisa32r6el": ( 8, 0, 0, True, 32),
+ "mipsisa64r6": ( 8, 0, 0, False, 64),
+ "mipsisa64r6el": ( 8, 0, 0, True, 64),
+ "nios2": (113, 0, 0, True, 32),
+ "riscv32": (243, 0, 0, True, 32),
+ "riscv64": (243, 0, 0, True, 64),
+ "s390": (22, 0, 0, False, 32),
+ "sh4": (42, 0, 0, True, 32),
+ "sparc": ( 2, 0, 0, False, 32),
+ "microblaze": (189, 0, 0, False, 32),
+ "microblazeel":(189, 0, 0, True, 32),
+ },
+ "linux-android" : {
+ "aarch64" : (183, 0, 0, True, 64),
+ "i686": ( 3, 0, 0, True, 32),
+ "x86_64": (62, 0, 0, True, 64),
+ },
+ "linux-androideabi" : {
+ "arm" : (40, 97, 0, True, 32),
+ },
+ "linux-musl" : {
+ "aarch64" : (183, 0, 0, True, 64),
+ "aarch64_be" :(183, 0, 0, False, 64),
+ "arm" : ( 40, 97, 0, True, 32),
+ "armeb": ( 40, 97, 0, False, 32),
+ "powerpc": ( 20, 0, 0, False, 32),
+ "powerpc64": ( 21, 0, 0, False, 64),
+ "powerpc64le": (21, 0, 0, True, 64),
+ "i386": ( 3, 0, 0, True, 32),
+ "i486": ( 3, 0, 0, True, 32),
+ "i586": ( 3, 0, 0, True, 32),
+ "i686": ( 3, 0, 0, True, 32),
+ "x86_64": ( 62, 0, 0, True, 64),
+ "mips": ( 8, 0, 0, False, 32),
+ "mipsel": ( 8, 0, 0, True, 32),
+ "mips64": ( 8, 0, 0, False, 64),
+ "mips64el": ( 8, 0, 0, True, 64),
+ "microblaze": (189, 0, 0, False, 32),
+ "microblazeel":(189, 0, 0, True, 32),
+ "riscv32": (243, 0, 0, True, 32),
+ "riscv64": (243, 0, 0, True, 64),
+ "sh4": ( 42, 0, 0, True, 32),
+ },
+ "uclinux-uclibc" : {
+ "bfin": ( 106, 0, 0, True, 32),
+ },
+ "linux-gnueabi" : {
+ "arm" : (40, 0, 0, True, 32),
+ "armeb" : (40, 0, 0, False, 32),
+ },
+ "linux-musleabi" : {
+ "arm" : (40, 0, 0, True, 32),
+ "armeb" : (40, 0, 0, False, 32),
+ },
+ "linux-gnuspe" : {
+ "powerpc": (20, 0, 0, False, 32),
+ },
+ "linux-muslspe" : {
+ "powerpc": (20, 0, 0, False, 32),
+ },
+ "linux-gnu" : {
+ "powerpc": (20, 0, 0, False, 32),
+ "sh4": (42, 0, 0, True, 32),
+ },
+ "linux-gnu_ilp32" : {
+ "aarch64" : (183, 0, 0, True, 32),
+ },
+ "linux-gnux32" : {
+ "x86_64": (62, 0, 0, True, 32),
+ },
+ "linux-muslx32" : {
+ "x86_64": (62, 0, 0, True, 32),
+ },
+ "linux-gnun32" : {
+ "mips64": ( 8, 0, 0, False, 32),
+ "mips64el": ( 8, 0, 0, True, 32),
+ "mipsisa64r6": ( 8, 0, 0, False, 32),
+ "mipsisa64r6el":( 8, 0, 0, True, 32),
+ },
+ }
+
+ # Add in any extra user supplied data which may come from a BSP layer, removing the
+ # need to always change this class directly
+ extra_machdata = (d and d.getVar("PACKAGEQA_EXTRA_MACHDEFFUNCS" or None) or "").split()
+ for m in extra_machdata:
+ call = m + "(machdata, d)"
+ locs = { "machdata" : machdata, "d" : d}
+ machdata = bb.utils.better_eval(call, locs)
+
+ return machdata
diff --git a/meta/lib/oe/gpg_sign.py b/meta/lib/oe/gpg_sign.py
index 38eb0cb137..613dab8561 100644
--- a/meta/lib/oe/gpg_sign.py
+++ b/meta/lib/oe/gpg_sign.py
@@ -1,66 +1,86 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: GPL-2.0-only
+#
+
"""Helper module for GPG signing"""
import os
import bb
-import oe.utils
+import subprocess
+import shlex
class LocalSigner(object):
"""Class for handling local (on the build host) signing"""
def __init__(self, d):
- self.gpg_bin = d.getVar('GPG_BIN', True) or \
+ self.gpg_bin = d.getVar('GPG_BIN') or \
bb.utils.which(os.getenv('PATH'), 'gpg')
- self.gpg_path = d.getVar('GPG_PATH', True)
- self.rpm_bin = bb.utils.which(os.getenv('PATH'), "rpm")
+ self.gpg_cmd = [self.gpg_bin]
+ self.gpg_agent_bin = bb.utils.which(os.getenv('PATH'), "gpg-agent")
+ # Without this we see "Cannot allocate memory" errors when running processes in parallel
+ # It needs to be set for any gpg command since any agent launched can stick around in memory
+ # and this parameter must be set.
+ if self.gpg_agent_bin:
+ self.gpg_cmd += ["--agent-program=%s|--auto-expand-secmem" % (self.gpg_agent_bin)]
+ self.gpg_path = d.getVar('GPG_PATH')
+ self.rpm_bin = bb.utils.which(os.getenv('PATH'), "rpmsign")
+ self.gpg_version = self.get_gpg_version()
+
def export_pubkey(self, output_file, keyid, armor=True):
"""Export GPG public key to a file"""
- cmd = '%s --batch --yes --export -o %s ' % \
- (self.gpg_bin, output_file)
+ cmd = self.gpg_cmd + ["--no-permission-warning", "--batch", "--yes", "--export", "-o", output_file]
if self.gpg_path:
- cmd += "--homedir %s " % self.gpg_path
+ cmd += ["--homedir", self.gpg_path]
if armor:
- cmd += "--armor "
- cmd += keyid
- status, output = oe.utils.getstatusoutput(cmd)
- if status:
- raise bb.build.FuncFailed('Failed to export gpg public key (%s): %s' %
- (keyid, output))
-
- def sign_rpms(self, files, keyid, passphrase):
+ cmd += ["--armor"]
+ cmd += [keyid]
+ subprocess.check_output(cmd, stderr=subprocess.STDOUT)
+
+ def sign_rpms(self, files, keyid, passphrase, digest, sign_chunk, fsk=None, fsk_password=None):
"""Sign RPM files"""
cmd = self.rpm_bin + " --addsign --define '_gpg_name %s' " % keyid
- cmd += "--define '_gpg_passphrase %s' " % passphrase
+ gpg_args = '--no-permission-warning --batch --passphrase=%s --agent-program=%s|--auto-expand-secmem' % (passphrase, self.gpg_agent_bin)
+ if self.gpg_version > (2,1,):
+ gpg_args += ' --pinentry-mode=loopback'
+ cmd += "--define '_gpg_sign_cmd_extra_args %s' " % gpg_args
+ cmd += "--define '_binary_filedigest_algorithm %s' " % digest
if self.gpg_bin:
- cmd += "--define '%%__gpg %s' " % self.gpg_bin
+ cmd += "--define '__gpg %s' " % self.gpg_bin
if self.gpg_path:
cmd += "--define '_gpg_path %s' " % self.gpg_path
- cmd += ' '.join(files)
+ if fsk:
+ cmd += "--signfiles --fskpath %s " % fsk
+ if fsk_password:
+ cmd += "--define '_file_signing_key_password %s' " % fsk_password
- status, output = oe.utils.getstatusoutput(cmd)
- if status:
- raise bb.build.FuncFailed("Failed to sign RPM packages: %s" % output)
+ # Sign in chunks
+ for i in range(0, len(files), sign_chunk):
+ subprocess.check_output(shlex.split(cmd + ' '.join(files[i:i+sign_chunk])), stderr=subprocess.STDOUT)
- def detach_sign(self, input_file, keyid, passphrase_file, passphrase=None, armor=True):
+ def detach_sign(self, input_file, keyid, passphrase_file, passphrase=None, armor=True, output_suffix=None, use_sha256=False):
"""Create a detached signature of a file"""
- import subprocess
if passphrase_file and passphrase:
raise Exception("You should use either passphrase_file of passphrase, not both")
- cmd = [self.gpg_bin, '--detach-sign', '--batch', '--no-tty', '--yes',
- '--passphrase-fd', '0', '-u', keyid]
+ cmd = self.gpg_cmd + ['--detach-sign', '--no-permission-warning', '--batch',
+ '--no-tty', '--yes', '--passphrase-fd', '0', '-u', keyid]
if self.gpg_path:
cmd += ['--homedir', self.gpg_path]
if armor:
cmd += ['--armor']
+ if output_suffix:
+ cmd += ['-o', input_file + "." + output_suffix]
+ if use_sha256:
+ cmd += ['--digest-algo', "SHA256"]
#gpg > 2.1 supports password pipes only through the loopback interface
#gpg < 2.1 errors out if given unknown parameters
- dots = self.get_gpg_version().split('.')
- assert len(dots) >= 2
- if int(dots[0]) >= 2 and int(dots[1]) >= 1:
+ if self.gpg_version > (2,1,):
cmd += ['--pinentry-mode', 'loopback']
cmd += [input_file]
@@ -74,8 +94,7 @@ class LocalSigner(object):
(_, stderr) = job.communicate(passphrase.encode("utf-8"))
if job.returncode:
- raise bb.build.FuncFailed("GPG exited with code %d: %s" %
- (job.returncode, stderr.decode("utf-8")))
+ bb.fatal("GPG exited with code %d: %s" % (job.returncode, stderr.decode("utf-8")))
except IOError as e:
bb.error("IO error (%s): %s" % (e.errno, e.strerror))
@@ -87,23 +106,42 @@ class LocalSigner(object):
def get_gpg_version(self):
- """Return the gpg version"""
- import subprocess
+ """Return the gpg version as a tuple of ints"""
try:
- return subprocess.check_output((self.gpg_bin, "--version")).split()[2].decode("utf-8")
+ cmd = self.gpg_cmd + ["--version", "--no-permission-warning"]
+ ver_str = subprocess.check_output(cmd).split()[2].decode("utf-8")
+ return tuple([int(i) for i in ver_str.split("-")[0].split('.')])
except subprocess.CalledProcessError as e:
- raise bb.build.FuncFailed("Could not get gpg version: %s" % e)
+ bb.fatal("Could not get gpg version: %s" % e)
- def verify(self, sig_file):
+ def verify(self, sig_file, valid_sigs = ''):
"""Verify signature"""
- cmd = self.gpg_bin + " --verify "
+ cmd = self.gpg_cmd + ["--verify", "--no-permission-warning", "--status-fd", "1"]
if self.gpg_path:
- cmd += "--homedir %s " % self.gpg_path
- cmd += sig_file
- status, _ = oe.utils.getstatusoutput(cmd)
- ret = False if status else True
- return ret
+ cmd += ["--homedir", self.gpg_path]
+
+ cmd += [sig_file]
+ status = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ # Valid if any key matches if unspecified
+ if not valid_sigs:
+ ret = False if status.returncode else True
+ return ret
+
+ import re
+ goodsigs = []
+ sigre = re.compile(r'^\[GNUPG:\] GOODSIG (\S+)\s(.*)$')
+ for l in status.stdout.decode("utf-8").splitlines():
+ s = sigre.match(l)
+ if s:
+ goodsigs += [s.group(1)]
+
+ for sig in valid_sigs.split():
+ if sig in goodsigs:
+ return True
+ if len(goodsigs):
+ bb.warn('No accepted signatures found. Good signatures found: %s.' % ' '.join(goodsigs))
+ return False
def get_signer(d, backend):
diff --git a/meta/lib/oe/license.py b/meta/lib/oe/license.py
index 39ef9654fc..d9c8d94da4 100644
--- a/meta/lib/oe/license.py
+++ b/meta/lib/oe/license.py
@@ -1,4 +1,8 @@
-# vi:sts=4:sw=4:et
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: GPL-2.0-only
+#
"""Code for parsing OpenEmbedded license strings"""
import ast
@@ -8,17 +12,20 @@ from fnmatch import fnmatchcase as fnmatch
def license_ok(license, dont_want_licenses):
""" Return False if License exist in dont_want_licenses else True """
for dwl in dont_want_licenses:
- # If you want to exclude license named generically 'X', we
- # surely want to exclude 'X+' as well. In consequence, we
- # will exclude a trailing '+' character from LICENSE in
- # case INCOMPATIBLE_LICENSE is not a 'X+' license.
- lic = license
- if not re.search('\+$', dwl):
- lic = re.sub('\+', '', license)
- if fnmatch(lic, dwl):
+ if fnmatch(license, dwl):
return False
return True
+def obsolete_license_list():
+ return ["AGPL-3", "AGPL-3+", "AGPLv3", "AGPLv3+", "AGPLv3.0", "AGPLv3.0+", "AGPL-3.0", "AGPL-3.0+", "BSD-0-Clause",
+ "GPL-1", "GPL-1+", "GPLv1", "GPLv1+", "GPLv1.0", "GPLv1.0+", "GPL-1.0", "GPL-1.0+", "GPL-2", "GPL-2+", "GPLv2",
+ "GPLv2+", "GPLv2.0", "GPLv2.0+", "GPL-2.0", "GPL-2.0+", "GPL-3", "GPL-3+", "GPLv3", "GPLv3+", "GPLv3.0", "GPLv3.0+",
+ "GPL-3.0", "GPL-3.0+", "LGPLv2", "LGPLv2+", "LGPLv2.0", "LGPLv2.0+", "LGPL-2.0", "LGPL-2.0+", "LGPL2.1", "LGPL2.1+",
+ "LGPLv2.1", "LGPLv2.1+", "LGPL-2.1", "LGPL-2.1+", "LGPLv3", "LGPLv3+", "LGPL-3.0", "LGPL-3.0+", "MPL-1", "MPLv1",
+ "MPLv1.1", "MPLv2", "MIT-X", "MIT-style", "openssl", "PSF", "PSFv2", "Python-2", "Apachev2", "Apache-2", "Artisticv1",
+ "Artistic-1", "AFL-2", "AFL-1", "AFLv2", "AFLv1", "CDDLv1", "CDDL-1", "EPLv1.0", "FreeType", "Nauman",
+ "tcl", "vim", "SGIv1"]
+
class LicenseError(Exception):
pass
@@ -40,8 +47,8 @@ class InvalidLicense(LicenseError):
return "invalid characters in license '%s'" % self.license
license_operator_chars = '&|() '
-license_operator = re.compile('([' + license_operator_chars + '])')
-license_pattern = re.compile('[a-zA-Z0-9.+_\-]+$')
+license_operator = re.compile(r'([' + license_operator_chars + '])')
+license_pattern = re.compile(r'[a-zA-Z0-9.+_\-]+$')
class LicenseVisitor(ast.NodeVisitor):
"""Get elements based on OpenEmbedded license strings"""
@@ -79,6 +86,9 @@ class FlattenVisitor(LicenseVisitor):
def visit_Str(self, node):
self.licenses.append(node.s)
+ def visit_Constant(self, node):
+ self.licenses.append(node.value)
+
def visit_BinOp(self, node):
if isinstance(node.op, ast.BitOr):
left = FlattenVisitor(self.choose_licenses)
@@ -101,35 +111,43 @@ def flattened_licenses(licensestr, choose_licenses):
raise LicenseSyntaxError(licensestr, exc)
return flatten.licenses
-def is_included(licensestr, whitelist=None, blacklist=None):
- """Given a license string and whitelist and blacklist, determine if the
- license string matches the whitelist and does not match the blacklist.
+def is_included(licensestr, include_licenses=None, exclude_licenses=None):
+ """Given a license string, a list of licenses to include and a list of
+ licenses to exclude, determine if the license string matches the include
+ list and does not match the exclude list.
Returns a tuple holding the boolean state and a list of the applicable
- licenses which were excluded (or None, if the state is True)
- """
+ licenses that were excluded if state is False, or the licenses that were
+ included if the state is True."""
def include_license(license):
- return any(fnmatch(license, pattern) for pattern in whitelist)
+ return any(fnmatch(license, pattern) for pattern in include_licenses)
def exclude_license(license):
- return any(fnmatch(license, pattern) for pattern in blacklist)
+ return any(fnmatch(license, pattern) for pattern in exclude_licenses)
def choose_licenses(alpha, beta):
"""Select the option in an OR which is the 'best' (has the most
- included licenses)."""
- alpha_weight = len(list(filter(include_license, alpha)))
- beta_weight = len(list(filter(include_license, beta)))
- if alpha_weight > beta_weight:
+ included licenses and no excluded licenses)."""
+ # The factor 1000 below is arbitrary, just expected to be much larger
+ # than the number of licenses actually specified. That way the weight
+ # will be negative if the list of licenses contains an excluded license,
+ # but still gives a higher weight to the list with the most included
+ # licenses.
+ alpha_weight = (len(list(filter(include_license, alpha))) -
+ 1000 * (len(list(filter(exclude_license, alpha))) > 0))
+ beta_weight = (len(list(filter(include_license, beta))) -
+ 1000 * (len(list(filter(exclude_license, beta))) > 0))
+ if alpha_weight >= beta_weight:
return alpha
else:
return beta
- if not whitelist:
- whitelist = ['*']
+ if not include_licenses:
+ include_licenses = ['*']
- if not blacklist:
- blacklist = []
+ if not exclude_licenses:
+ exclude_licenses = []
licenses = flattened_licenses(licensestr, choose_licenses)
excluded = [lic for lic in licenses if exclude_license(lic)]
@@ -215,3 +233,29 @@ def manifest_licenses(licensestr, dont_want_licenses, canonical_license, d):
manifest.licensestr = manifest.licensestr.replace('[', '(').replace(']', ')')
return (manifest.licensestr, manifest.licenses)
+
+class ListVisitor(LicenseVisitor):
+ """Record all different licenses found in the license string"""
+ def __init__(self):
+ self.licenses = set()
+
+ def visit_Str(self, node):
+ self.licenses.add(node.s)
+
+ def visit_Constant(self, node):
+ self.licenses.add(node.value)
+
+def list_licenses(licensestr):
+ """Simply get a list of all licenses mentioned in a license string.
+ Binary operators are not applied or taken into account in any way"""
+ visitor = ListVisitor()
+ try:
+ visitor.visit_string(licensestr)
+ except SyntaxError as exc:
+ raise LicenseSyntaxError(licensestr, exc)
+ return visitor.licenses
+
+def apply_pkg_license_exception(pkg, bad_licenses, exceptions):
+ """Return remaining bad licenses after removing any package exceptions"""
+
+ return [lic for lic in bad_licenses if pkg + ':' + lic not in exceptions]
diff --git a/meta/lib/oe/lsb.py b/meta/lib/oe/lsb.py
index e0bdfba255..3ec03e5042 100644
--- a/meta/lib/oe/lsb.py
+++ b/meta/lib/oe/lsb.py
@@ -1,26 +1,67 @@
-def release_dict():
- """Return the output of lsb_release -ir as a dictionary"""
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: GPL-2.0-only
+#
+
+def get_os_release():
+ """Get all key-value pairs from /etc/os-release as a dict"""
+ from collections import OrderedDict
+
+ data = OrderedDict()
+ if os.path.exists('/etc/os-release'):
+ with open('/etc/os-release') as f:
+ for line in f:
+ try:
+ key, val = line.rstrip().split('=', 1)
+ except ValueError:
+ continue
+ data[key.strip()] = val.strip('"')
+ return data
+
+def release_dict_osr():
+ """ Populate a dict with pertinent values from /etc/os-release """
+ data = {}
+ os_release = get_os_release()
+ if 'ID' in os_release:
+ data['DISTRIB_ID'] = os_release['ID']
+ if 'VERSION_ID' in os_release:
+ data['DISTRIB_RELEASE'] = os_release['VERSION_ID']
+
+ return data
+
+def release_dict_lsb():
+ """ Return the output of lsb_release -ir as a dictionary """
from subprocess import PIPE
try:
output, err = bb.process.run(['lsb_release', '-ir'], stderr=PIPE)
except bb.process.CmdError as exc:
- return None
+ return {}
+
+ lsb_map = { 'Distributor ID': 'DISTRIB_ID',
+ 'Release': 'DISTRIB_RELEASE'}
+ lsb_keys = lsb_map.keys()
data = {}
for line in output.splitlines():
- if line.startswith("-e"): line = line[3:]
+ if line.startswith("-e"):
+ line = line[3:]
try:
key, value = line.split(":\t", 1)
except ValueError:
continue
- else:
- data[key] = value
+ if key in lsb_keys:
+ data[lsb_map[key]] = value
+
+ if len(data.keys()) != 2:
+ return None
+
return data
def release_dict_file():
- """ Try to gather LSB release information manually when lsb_release tool is unavailable """
- data = None
+ """ Try to gather release information manually when other methods fail """
+ data = {}
try:
if os.path.exists('/etc/lsb-release'):
data = {}
@@ -37,14 +78,6 @@ def release_dict_file():
if match:
data['DISTRIB_ID'] = match.group(1)
data['DISTRIB_RELEASE'] = match.group(2)
- elif os.path.exists('/etc/os-release'):
- data = {}
- with open('/etc/os-release') as f:
- for line in f:
- if line.startswith('NAME='):
- data['DISTRIB_ID'] = line[5:].rstrip().strip('"')
- if line.startswith('VERSION_ID='):
- data['DISTRIB_RELEASE'] = line[11:].rstrip().strip('"')
elif os.path.exists('/etc/SuSE-release'):
data = {}
data['DISTRIB_ID'] = 'SUSE LINUX'
@@ -55,7 +88,7 @@ def release_dict_file():
break
except IOError:
- return None
+ return {}
return data
def distro_identifier(adjust_hook=None):
@@ -64,22 +97,24 @@ def distro_identifier(adjust_hook=None):
import re
- lsb_data = release_dict()
- if lsb_data:
- distro_id, release = lsb_data['Distributor ID'], lsb_data['Release']
- else:
- lsb_data_file = release_dict_file()
- if lsb_data_file:
- distro_id, release = lsb_data_file['DISTRIB_ID'], lsb_data_file.get('DISTRIB_RELEASE', None)
- else:
- distro_id, release = None, None
+ # Try /etc/os-release first, then the output of `lsb_release -ir` and
+ # finally fall back on parsing various release files in order to determine
+ # host distro name and version.
+ distro_data = release_dict_osr()
+ if not distro_data:
+ distro_data = release_dict_lsb()
+ if not distro_data:
+ distro_data = release_dict_file()
+
+ distro_id = distro_data.get('DISTRIB_ID', '')
+ release = distro_data.get('DISTRIB_RELEASE', '')
if adjust_hook:
distro_id, release = adjust_hook(distro_id, release)
if not distro_id:
- return "Unknown"
- # Filter out any non-alphanumerics
- distro_id = re.sub(r'\W', '', distro_id)
+ return "unknown"
+ # Filter out any non-alphanumerics and convert to lowercase
+ distro_id = re.sub(r'\W', '', distro_id).lower()
if release:
id_str = '{0}-{1}'.format(distro_id, release)
diff --git a/meta/lib/oe/maketype.py b/meta/lib/oe/maketype.py
index f88981dd90..7a83bdf602 100644
--- a/meta/lib/oe/maketype.py
+++ b/meta/lib/oe/maketype.py
@@ -1,3 +1,8 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: GPL-2.0-only
+#
"""OpenEmbedded variable typing support
Types are defined in the metadata by name, using the 'type' flag on a
@@ -7,7 +12,7 @@ the arguments of the type's factory for details.
import inspect
import oe.types as types
-import collections
+from collections.abc import Callable
available_types = {}
@@ -96,7 +101,7 @@ for name in dir(types):
continue
obj = getattr(types, name)
- if not isinstance(obj, collections.Callable):
+ if not isinstance(obj, Callable):
continue
register(name, obj)
diff --git a/meta/lib/oe/manifest.py b/meta/lib/oe/manifest.py
index 95f8eb2df3..61f18adc4a 100644
--- a/meta/lib/oe/manifest.py
+++ b/meta/lib/oe/manifest.py
@@ -1,9 +1,14 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: GPL-2.0-only
+#
+
from abc import ABCMeta, abstractmethod
import os
import re
import bb
-
class Manifest(object, metaclass=ABCMeta):
"""
This is an abstract class. Do not instantiate this directly.
@@ -59,9 +64,9 @@ class Manifest(object, metaclass=ABCMeta):
if manifest_dir is None:
if manifest_type != self.MANIFEST_TYPE_IMAGE:
- self.manifest_dir = self.d.getVar('SDK_DIR', True)
+ self.manifest_dir = self.d.getVar('SDK_DIR')
else:
- self.manifest_dir = self.d.getVar('WORKDIR', True)
+ self.manifest_dir = self.d.getVar('WORKDIR')
else:
self.manifest_dir = manifest_dir
@@ -82,7 +87,7 @@ class Manifest(object, metaclass=ABCMeta):
This will be used for testing until the class is implemented properly!
"""
def _create_dummy_initial(self):
- image_rootfs = self.d.getVar('IMAGE_ROOTFS', True)
+ image_rootfs = self.d.getVar('IMAGE_ROOTFS')
pkg_list = dict()
if image_rootfs.find("core-image-sato-sdk") > 0:
pkg_list[self.PKG_TYPE_MUST_INSTALL] = \
@@ -104,7 +109,7 @@ class Manifest(object, metaclass=ABCMeta):
pkg_list['lgp'] = \
"locale-base-en-us locale-base-en-gb"
elif image_rootfs.find("core-image-minimal") > 0:
- pkg_list[self.PKG_TYPE_MUST_INSTALL] = "run-postinsts packagegroup-core-boot"
+ pkg_list[self.PKG_TYPE_MUST_INSTALL] = "packagegroup-core-boot"
with open(self.initial_manifest, "w+") as manifest:
manifest.write(self.initial_manifest_file_header)
@@ -185,154 +190,11 @@ class Manifest(object, metaclass=ABCMeta):
return installed_pkgs
-class RpmManifest(Manifest):
- """
- Returns a dictionary object with mip and mlp packages.
- """
- def _split_multilib(self, pkg_list):
- pkgs = dict()
-
- for pkg in pkg_list.split():
- pkg_type = self.PKG_TYPE_MUST_INSTALL
-
- ml_variants = self.d.getVar('MULTILIB_VARIANTS', True).split()
-
- for ml_variant in ml_variants:
- if pkg.startswith(ml_variant + '-'):
- pkg_type = self.PKG_TYPE_MULTILIB
-
- if not pkg_type in pkgs:
- pkgs[pkg_type] = pkg
- else:
- pkgs[pkg_type] += " " + pkg
-
- return pkgs
-
- def create_initial(self):
- pkgs = dict()
-
- with open(self.initial_manifest, "w+") as manifest:
- manifest.write(self.initial_manifest_file_header)
-
- for var in self.var_maps[self.manifest_type]:
- if var in self.vars_to_split:
- split_pkgs = self._split_multilib(self.d.getVar(var, True))
- if split_pkgs is not None:
- pkgs = dict(list(pkgs.items()) + list(split_pkgs.items()))
- else:
- pkg_list = self.d.getVar(var, True)
- if pkg_list is not None:
- pkgs[self.var_maps[self.manifest_type][var]] = self.d.getVar(var, True)
-
- for pkg_type in pkgs:
- for pkg in pkgs[pkg_type].split():
- manifest.write("%s,%s\n" % (pkg_type, pkg))
-
- def create_final(self):
- pass
-
- def create_full(self, pm):
- pass
-
-
-class OpkgManifest(Manifest):
- """
- Returns a dictionary object with mip and mlp packages.
- """
- def _split_multilib(self, pkg_list):
- pkgs = dict()
-
- for pkg in pkg_list.split():
- pkg_type = self.PKG_TYPE_MUST_INSTALL
-
- ml_variants = self.d.getVar('MULTILIB_VARIANTS', True).split()
-
- for ml_variant in ml_variants:
- if pkg.startswith(ml_variant + '-'):
- pkg_type = self.PKG_TYPE_MULTILIB
-
- if not pkg_type in pkgs:
- pkgs[pkg_type] = pkg
- else:
- pkgs[pkg_type] += " " + pkg
-
- return pkgs
-
- def create_initial(self):
- pkgs = dict()
-
- with open(self.initial_manifest, "w+") as manifest:
- manifest.write(self.initial_manifest_file_header)
-
- for var in self.var_maps[self.manifest_type]:
- if var in self.vars_to_split:
- split_pkgs = self._split_multilib(self.d.getVar(var, True))
- if split_pkgs is not None:
- pkgs = dict(list(pkgs.items()) + list(split_pkgs.items()))
- else:
- pkg_list = self.d.getVar(var, True)
- if pkg_list is not None:
- pkgs[self.var_maps[self.manifest_type][var]] = self.d.getVar(var, True)
-
- for pkg_type in pkgs:
- for pkg in pkgs[pkg_type].split():
- manifest.write("%s,%s\n" % (pkg_type, pkg))
-
- def create_final(self):
- pass
-
- def create_full(self, pm):
- if not os.path.exists(self.initial_manifest):
- self.create_initial()
-
- initial_manifest = self.parse_initial_manifest()
- pkgs_to_install = list()
- for pkg_type in initial_manifest:
- pkgs_to_install += initial_manifest[pkg_type]
- if len(pkgs_to_install) == 0:
- return
-
- output = pm.dummy_install(pkgs_to_install)
-
- with open(self.full_manifest, 'w+') as manifest:
- pkg_re = re.compile('^Installing ([^ ]+) [^ ].*')
- for line in set(output.split('\n')):
- m = pkg_re.match(line)
- if m:
- manifest.write(m.group(1) + '\n')
-
- return
-
-
-class DpkgManifest(Manifest):
- def create_initial(self):
- with open(self.initial_manifest, "w+") as manifest:
- manifest.write(self.initial_manifest_file_header)
-
- for var in self.var_maps[self.manifest_type]:
- pkg_list = self.d.getVar(var, True)
-
- if pkg_list is None:
- continue
-
- for pkg in pkg_list.split():
- manifest.write("%s,%s\n" %
- (self.var_maps[self.manifest_type][var], pkg))
-
- def create_final(self):
- pass
-
- def create_full(self, pm):
- pass
-
def create_manifest(d, final_manifest=False, manifest_dir=None,
manifest_type=Manifest.MANIFEST_TYPE_IMAGE):
- manifest_map = {'rpm': RpmManifest,
- 'ipk': OpkgManifest,
- 'deb': DpkgManifest}
-
- manifest = manifest_map[d.getVar('IMAGE_PKGTYPE', True)](d, manifest_dir, manifest_type)
+ import importlib
+ manifest = importlib.import_module('oe.package_manager.' + d.getVar('IMAGE_PKGTYPE') + '.manifest').PkgManifest(d, manifest_dir, manifest_type)
if final_manifest:
manifest.create_final()
diff --git a/meta/lib/oe/npm_registry.py b/meta/lib/oe/npm_registry.py
new file mode 100644
index 0000000000..db581e280e
--- /dev/null
+++ b/meta/lib/oe/npm_registry.py
@@ -0,0 +1,175 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
+import bb
+import json
+import subprocess
+
+_ALWAYS_SAFE = frozenset('ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+ 'abcdefghijklmnopqrstuvwxyz'
+ '0123456789'
+ '_.-~')
+
+MISSING_OK = object()
+
+REGISTRY = "https://registry.npmjs.org"
+
+# we can not use urllib.parse here because npm expects lowercase
+# hex-chars but urllib generates uppercase ones
+def uri_quote(s, safe = '/'):
+ res = ""
+ safe_set = set(safe)
+ for c in s:
+ if c in _ALWAYS_SAFE or c in safe_set:
+ res += c
+ else:
+ res += '%%%02x' % ord(c)
+ return res
+
+class PackageJson:
+ def __init__(self, spec):
+ self.__spec = spec
+
+ @property
+ def name(self):
+ return self.__spec['name']
+
+ @property
+ def version(self):
+ return self.__spec['version']
+
+ @property
+ def empty_manifest(self):
+ return {
+ 'name': self.name,
+ 'description': self.__spec.get('description', ''),
+ 'versions': {},
+ }
+
+ def base_filename(self):
+ return uri_quote(self.name, safe = '@')
+
+ def as_manifest_entry(self, tarball_uri):
+ res = {}
+
+ ## NOTE: 'npm install' requires more than basic meta information;
+ ## e.g. it takes 'bin' from this manifest entry but not the actual
+ ## 'package.json'
+ for (idx,dflt) in [('name', None),
+ ('description', ""),
+ ('version', None),
+ ('bin', MISSING_OK),
+ ('man', MISSING_OK),
+ ('scripts', MISSING_OK),
+ ('directories', MISSING_OK),
+ ('dependencies', MISSING_OK),
+ ('devDependencies', MISSING_OK),
+ ('optionalDependencies', MISSING_OK),
+ ('license', "unknown")]:
+ if idx in self.__spec:
+ res[idx] = self.__spec[idx]
+ elif dflt == MISSING_OK:
+ pass
+ elif dflt != None:
+ res[idx] = dflt
+ else:
+ raise Exception("%s-%s: missing key %s" % (self.name,
+ self.version,
+ idx))
+
+ res['dist'] = {
+ 'tarball': tarball_uri,
+ }
+
+ return res
+
+class ManifestImpl:
+ def __init__(self, base_fname, spec):
+ self.__base = base_fname
+ self.__spec = spec
+
+ def load(self):
+ try:
+ with open(self.filename, "r") as f:
+ res = json.load(f)
+ except IOError:
+ res = self.__spec.empty_manifest
+
+ return res
+
+ def save(self, meta):
+ with open(self.filename, "w") as f:
+ json.dump(meta, f, indent = 2)
+
+ @property
+ def filename(self):
+ return self.__base + ".meta"
+
+class Manifest:
+ def __init__(self, base_fname, spec):
+ self.__base = base_fname
+ self.__spec = spec
+ self.__lockf = None
+ self.__impl = None
+
+ def __enter__(self):
+ self.__lockf = bb.utils.lockfile(self.__base + ".lock")
+ self.__impl = ManifestImpl(self.__base, self.__spec)
+ return self.__impl
+
+ def __exit__(self, exc_type, exc_val, exc_tb):
+ bb.utils.unlockfile(self.__lockf)
+
+class NpmCache:
+ def __init__(self, cache):
+ self.__cache = cache
+
+ @property
+ def path(self):
+ return self.__cache
+
+ def run(self, type, key, fname):
+ subprocess.run(['oe-npm-cache', self.__cache, type, key, fname],
+ check = True)
+
+class NpmRegistry:
+ def __init__(self, path, cache):
+ self.__path = path
+ self.__cache = NpmCache(cache + '/_cacache')
+ bb.utils.mkdirhier(self.__path)
+ bb.utils.mkdirhier(self.__cache.path)
+
+ @staticmethod
+ ## This function is critical and must match nodejs expectations
+ def _meta_uri(spec):
+ return REGISTRY + '/' + uri_quote(spec.name, safe = '@')
+
+ @staticmethod
+ ## Exact return value does not matter; just make it look like a
+ ## usual registry url
+ def _tarball_uri(spec):
+ return '%s/%s/-/%s-%s.tgz' % (REGISTRY,
+ uri_quote(spec.name, safe = '@'),
+ uri_quote(spec.name, safe = '@/'),
+ spec.version)
+
+ def add_pkg(self, tarball, pkg_json):
+ pkg_json = PackageJson(pkg_json)
+ base = os.path.join(self.__path, pkg_json.base_filename())
+
+ with Manifest(base, pkg_json) as manifest:
+ meta = manifest.load()
+ tarball_uri = self._tarball_uri(pkg_json)
+
+ meta['versions'][pkg_json.version] = pkg_json.as_manifest_entry(tarball_uri)
+
+ manifest.save(meta)
+
+ ## Cache entries are a little bit dependent on the nodejs
+ ## version; version specific cache implementation must
+ ## mitigate differences
+ self.__cache.run('meta', self._meta_uri(pkg_json), manifest.filename);
+ self.__cache.run('tgz', tarball_uri, tarball);
diff --git a/meta/lib/oe/overlayfs.py b/meta/lib/oe/overlayfs.py
new file mode 100644
index 0000000000..8b88900f71
--- /dev/null
+++ b/meta/lib/oe/overlayfs.py
@@ -0,0 +1,54 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# This file contains common functions for overlayfs and its QA check
+
+# this function is based on https://github.com/systemd/systemd/blob/main/src/basic/unit-name.c
+def escapeSystemdUnitName(path):
+ escapeMap = {
+ '/': '-',
+ '-': "\\x2d",
+ '\\': "\\x5d"
+ }
+ return "".join([escapeMap.get(c, c) for c in path.strip('/')])
+
+def strForBash(s):
+ return s.replace('\\', '\\\\')
+
+def allOverlaysUnitName(d):
+ return d.getVar('PN') + '-overlays.service'
+
+def mountUnitName(unit):
+ return escapeSystemdUnitName(unit) + '.mount'
+
+def helperUnitName(unit):
+ return escapeSystemdUnitName(unit) + '-create-upper-dir.service'
+
+def unitFileList(d):
+ fileList = []
+ overlayMountPoints = d.getVarFlags("OVERLAYFS_MOUNT_POINT")
+
+ if not overlayMountPoints:
+ bb.fatal("A recipe uses overlayfs class but there is no OVERLAYFS_MOUNT_POINT set in your MACHINE configuration")
+
+ # check that we have required mount points set first
+ requiredMountPoints = d.getVarFlags('OVERLAYFS_WRITABLE_PATHS')
+ for mountPoint in requiredMountPoints:
+ if mountPoint not in overlayMountPoints:
+ bb.fatal("Missing required mount point for OVERLAYFS_MOUNT_POINT[%s] in your MACHINE configuration" % mountPoint)
+
+ for mountPoint in overlayMountPoints:
+ mountPointList = d.getVarFlag('OVERLAYFS_WRITABLE_PATHS', mountPoint)
+ if not mountPointList:
+ bb.debug(1, "No mount points defined for %s flag, don't add to file list", mountPoint)
+ continue
+ for path in mountPointList.split():
+ fileList.append(mountUnitName(path))
+ fileList.append(helperUnitName(path))
+
+ fileList.append(allOverlaysUnitName(d))
+
+ return fileList
+
diff --git a/meta/lib/oe/package.py b/meta/lib/oe/package.py
index 02642f29f0..c9eb75d852 100644
--- a/meta/lib/oe/package.py
+++ b/meta/lib/oe/package.py
@@ -1,16 +1,37 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: GPL-2.0-only
+#
+
+import errno
+import fnmatch
+import itertools
+import os
+import pipes
+import re
+import glob
+import stat
+import mmap
+import subprocess
+
+import oe.cachedpath
+
def runstrip(arg):
# Function to strip a single file, called from split_and_strip_files below
# A working 'file' (one which works on the target architecture)
#
- # The elftype is a bit pattern (explained in split_and_strip_files) to tell
+ # The elftype is a bit pattern (explained in is_elf below) to tell
# us what type of file we're processing...
# 4 - executable
# 8 - shared library
# 16 - kernel module
- import stat, subprocess
-
- (file, elftype, strip) = arg
+ if len(arg) == 3:
+ (file, elftype, strip) = arg
+ extra_strip_sections = ''
+ else:
+ (file, elftype, strip, extra_strip_sections) = arg
newmode = None
if not os.access(file, os.W_OK) or os.access(file, os.R_OK):
@@ -18,30 +39,160 @@ def runstrip(arg):
newmode = origmode | stat.S_IWRITE | stat.S_IREAD
os.chmod(file, newmode)
- extraflags = ""
-
+ stripcmd = [strip]
+ skip_strip = False
# kernel module
if elftype & 16:
- extraflags = "--strip-debug --remove-section=.comment --remove-section=.note --preserve-dates"
+ if is_kernel_module_signed(file):
+ bb.debug(1, "Skip strip on signed module %s" % file)
+ skip_strip = True
+ else:
+ stripcmd.extend(["--strip-debug", "--remove-section=.comment",
+ "--remove-section=.note", "--preserve-dates"])
# .so and shared library
elif ".so" in file and elftype & 8:
- extraflags = "--remove-section=.comment --remove-section=.note --strip-unneeded"
+ stripcmd.extend(["--remove-section=.comment", "--remove-section=.note", "--strip-unneeded"])
# shared or executable:
elif elftype & 8 or elftype & 4:
- extraflags = "--remove-section=.comment --remove-section=.note"
+ stripcmd.extend(["--remove-section=.comment", "--remove-section=.note"])
+ if extra_strip_sections != '':
+ for section in extra_strip_sections.split():
+ stripcmd.extend(["--remove-section=" + section])
- stripcmd = "'%s' %s '%s'" % (strip, extraflags, file)
+ stripcmd.append(file)
bb.debug(1, "runstrip: %s" % stripcmd)
- try:
- output = subprocess.check_output(stripcmd, stderr=subprocess.STDOUT, shell=True)
- except subprocess.CalledProcessError as e:
- bb.error("runstrip: '%s' strip command failed with %s (%s)" % (stripcmd, e.returncode, e.output))
+ if not skip_strip:
+ output = subprocess.check_output(stripcmd, stderr=subprocess.STDOUT)
if newmode:
os.chmod(file, origmode)
- return
+# Detect .ko module by searching for "vermagic=" string
+def is_kernel_module(path):
+ with open(path) as f:
+ return mmap.mmap(f.fileno(), 0, prot=mmap.PROT_READ).find(b"vermagic=") >= 0
+
+# Detect if .ko module is signed
+def is_kernel_module_signed(path):
+ with open(path, "rb") as f:
+ f.seek(-28, 2)
+ module_tail = f.read()
+ return "Module signature appended" in "".join(chr(c) for c in bytearray(module_tail))
+
+# Return type (bits):
+# 0 - not elf
+# 1 - ELF
+# 2 - stripped
+# 4 - executable
+# 8 - shared library
+# 16 - kernel module
+def is_elf(path):
+ exec_type = 0
+ result = subprocess.check_output(["file", "-b", path], stderr=subprocess.STDOUT).decode("utf-8")
+
+ if "ELF" in result:
+ exec_type |= 1
+ if "not stripped" not in result:
+ exec_type |= 2
+ if "executable" in result:
+ exec_type |= 4
+ if "shared" in result:
+ exec_type |= 8
+ if "relocatable" in result:
+ if path.endswith(".ko") and path.find("/lib/modules/") != -1 and is_kernel_module(path):
+ exec_type |= 16
+ return (path, exec_type)
+
+def is_static_lib(path):
+ if path.endswith('.a') and not os.path.islink(path):
+ with open(path, 'rb') as fh:
+ # The magic must include the first slash to avoid
+ # matching golang static libraries
+ magic = b'!<arch>\x0a/'
+ start = fh.read(len(magic))
+ return start == magic
+ return False
+
+def strip_execs(pn, dstdir, strip_cmd, libdir, base_libdir, d, qa_already_stripped=False):
+ """
+ Strip executable code (like executables, shared libraries) _in_place_
+ - Based on sysroot_strip in staging.bbclass
+ :param dstdir: directory in which to strip files
+ :param strip_cmd: Strip command (usually ${STRIP})
+ :param libdir: ${libdir} - strip .so files in this directory
+ :param base_libdir: ${base_libdir} - strip .so files in this directory
+ :param qa_already_stripped: Set to True if already-stripped' in ${INSANE_SKIP}
+ This is for proper logging and messages only.
+ """
+ import stat, errno, oe.path, oe.utils
+
+ elffiles = {}
+ inodes = {}
+ libdir = os.path.abspath(dstdir + os.sep + libdir)
+ base_libdir = os.path.abspath(dstdir + os.sep + base_libdir)
+ exec_mask = stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH
+ #
+ # First lets figure out all of the files we may have to process
+ #
+ checkelf = []
+ inodecache = {}
+ for root, dirs, files in os.walk(dstdir):
+ for f in files:
+ file = os.path.join(root, f)
+
+ try:
+ ltarget = oe.path.realpath(file, dstdir, False)
+ s = os.lstat(ltarget)
+ except OSError as e:
+ (err, strerror) = e.args
+ if err != errno.ENOENT:
+ raise
+ # Skip broken symlinks
+ continue
+ if not s:
+ continue
+ # Check its an excutable
+ if s[stat.ST_MODE] & exec_mask \
+ or ((file.startswith(libdir) or file.startswith(base_libdir)) and ".so" in f) \
+ or file.endswith('.ko'):
+ # If it's a symlink, and points to an ELF file, we capture the readlink target
+ if os.path.islink(file):
+ continue
+
+ # It's a file (or hardlink), not a link
+ # ...but is it ELF, and is it already stripped?
+ checkelf.append(file)
+ inodecache[file] = s.st_ino
+ results = oe.utils.multiprocess_launch(is_elf, checkelf, d)
+ for (file, elf_file) in results:
+ #elf_file = is_elf(file)
+ if elf_file & 1:
+ if elf_file & 2:
+ if qa_already_stripped:
+ bb.note("Skipping file %s from %s for already-stripped QA test" % (file[len(dstdir):], pn))
+ else:
+ bb.warn("File '%s' from %s was already stripped, this will prevent future debugging!" % (file[len(dstdir):], pn))
+ continue
+
+ if inodecache[file] in inodes:
+ os.unlink(file)
+ os.link(inodes[inodecache[file]], file)
+ else:
+ # break hardlinks so that we do not strip the original.
+ inodes[inodecache[file]] = file
+ bb.utils.break_hardlinks(file)
+ elffiles[file] = elf_file
+
+ #
+ # Now strip them (in parallel)
+ #
+ sfiles = []
+ for file in elffiles:
+ elf_file = int(elffiles[file])
+ sfiles.append((file, elf_file, strip_cmd))
+
+ oe.utils.multiprocess_launch(runstrip, sfiles, d)
def file_translate(file):
@@ -60,41 +211,63 @@ def filedeprunner(arg):
provides = {}
requires = {}
- r = re.compile(r'[<>=]+ +[^ ]*')
+ file_re = re.compile(r'\s+\d+\s(.*)')
+ dep_re = re.compile(r'\s+(\S)\s+(.*)')
+ r = re.compile(r'[<>=]+\s+\S*')
def process_deps(pipe, pkg, pkgdest, provides, requires):
- for line in pipe:
- f = line.decode("utf-8").split(" ", 1)[0].strip()
- line = line.decode("utf-8").split(" ", 1)[1].strip()
+ file = None
+ for line in pipe.split("\n"):
+
+ m = file_re.match(line)
+ if m:
+ file = m.group(1)
+ file = file.replace(pkgdest + "/" + pkg, "")
+ file = file_translate(file)
+ continue
+
+ m = dep_re.match(line)
+ if not m or not file:
+ continue
+
+ type, dep = m.groups()
- if line.startswith("Requires:"):
+ if type == 'R':
i = requires
- elif line.startswith("Provides:"):
+ elif type == 'P':
i = provides
else:
- continue
+ continue
- file = f.replace(pkgdest + "/" + pkg, "")
- file = file_translate(file)
- value = line.split(":", 1)[1].strip()
- value = r.sub(r'(\g<0>)', value)
+ if dep.startswith("python("):
+ continue
- if value.startswith("rpmlib("):
+ # Ignore all perl(VMS::...) and perl(Mac::...) dependencies. These
+ # are typically used conditionally from the Perl code, but are
+ # generated as unconditional dependencies.
+ if dep.startswith('perl(VMS::') or dep.startswith('perl(Mac::'):
continue
- if value == "python":
+
+ # Ignore perl dependencies on .pl files.
+ if dep.startswith('perl(') and dep.endswith('.pl)'):
continue
+
+ # Remove perl versions and perl module versions since they typically
+ # do not make sense when used as package versions.
+ if dep.startswith('perl') and r.search(dep):
+ dep = dep.split()[0]
+
+ # Put parentheses around any version specifications.
+ dep = r.sub(r'(\g<0>)',dep)
+
if file not in i:
i[file] = []
- i[file].append(value)
+ i[file].append(dep)
return provides, requires
- try:
- dep_popen = subprocess.Popen(shlex.split(rpmdeps) + pkgfiles, stdout=subprocess.PIPE)
- provides, requires = process_deps(dep_popen.stdout, pkg, pkgdest, provides, requires)
- except OSError as e:
- bb.error("rpmdeps: '%s' command failed, '%s'" % (shlex.split(rpmdeps) + pkgfiles, e))
- raise e
+ output = subprocess.check_output(shlex.split(rpmdeps) + pkgfiles, stderr=subprocess.STDOUT).decode("utf-8")
+ provides, requires = process_deps(output, pkg, pkgdest, provides, requires)
return (pkg, provides, requires)
@@ -103,14 +276,14 @@ def read_shlib_providers(d):
import re
shlib_provider = {}
- shlibs_dirs = d.getVar('SHLIBSDIRS', True).split()
- list_re = re.compile('^(.*)\.list$')
+ shlibs_dirs = d.getVar('SHLIBSDIRS').split()
+ list_re = re.compile(r'^(.*)\.list$')
# Go from least to most specific since the last one found wins
for dir in reversed(shlibs_dirs):
bb.debug(2, "Reading shlib providers in %s" % (dir))
if not os.path.exists(dir):
continue
- for file in os.listdir(dir):
+ for file in sorted(os.listdir(dir)):
m = list_re.match(file)
if m:
dep_pkg = m.group(1)
@@ -129,34 +302,1714 @@ def read_shlib_providers(d):
shlib_provider[s[0]][s[1]] = (dep_pkg, s[2])
return shlib_provider
+# We generate a master list of directories to process, we start by
+# seeding this list with reasonable defaults, then load from
+# the fs-perms.txt files
+def fixup_perms(d):
+ import pwd, grp
+
+ cpath = oe.cachedpath.CachedPath()
+ dvar = d.getVar('PKGD')
+
+ # init using a string with the same format as a line as documented in
+ # the fs-perms.txt file
+ # <path> <mode> <uid> <gid> <walk> <fmode> <fuid> <fgid>
+ # <path> link <link target>
+ #
+ # __str__ can be used to print out an entry in the input format
+ #
+ # if fs_perms_entry.path is None:
+ # an error occurred
+ # if fs_perms_entry.link, you can retrieve:
+ # fs_perms_entry.path = path
+ # fs_perms_entry.link = target of link
+ # if not fs_perms_entry.link, you can retrieve:
+ # fs_perms_entry.path = path
+ # fs_perms_entry.mode = expected dir mode or None
+ # fs_perms_entry.uid = expected uid or -1
+ # fs_perms_entry.gid = expected gid or -1
+ # fs_perms_entry.walk = 'true' or something else
+ # fs_perms_entry.fmode = expected file mode or None
+ # fs_perms_entry.fuid = expected file uid or -1
+ # fs_perms_entry_fgid = expected file gid or -1
+ class fs_perms_entry():
+ def __init__(self, line):
+ lsplit = line.split()
+ if len(lsplit) == 3 and lsplit[1].lower() == "link":
+ self._setlink(lsplit[0], lsplit[2])
+ elif len(lsplit) == 8:
+ self._setdir(lsplit[0], lsplit[1], lsplit[2], lsplit[3], lsplit[4], lsplit[5], lsplit[6], lsplit[7])
+ else:
+ msg = "Fixup Perms: invalid config line %s" % line
+ oe.qa.handle_error("perm-config", msg, d)
+ self.path = None
+ self.link = None
+
+ def _setdir(self, path, mode, uid, gid, walk, fmode, fuid, fgid):
+ self.path = os.path.normpath(path)
+ self.link = None
+ self.mode = self._procmode(mode)
+ self.uid = self._procuid(uid)
+ self.gid = self._procgid(gid)
+ self.walk = walk.lower()
+ self.fmode = self._procmode(fmode)
+ self.fuid = self._procuid(fuid)
+ self.fgid = self._procgid(fgid)
+
+ def _setlink(self, path, link):
+ self.path = os.path.normpath(path)
+ self.link = link
+
+ def _procmode(self, mode):
+ if not mode or (mode and mode == "-"):
+ return None
+ else:
+ return int(mode,8)
-def npm_split_package_dirs(pkgdir):
+ # Note uid/gid -1 has special significance in os.lchown
+ def _procuid(self, uid):
+ if uid is None or uid == "-":
+ return -1
+ elif uid.isdigit():
+ return int(uid)
+ else:
+ return pwd.getpwnam(uid).pw_uid
+
+ def _procgid(self, gid):
+ if gid is None or gid == "-":
+ return -1
+ elif gid.isdigit():
+ return int(gid)
+ else:
+ return grp.getgrnam(gid).gr_gid
+
+ # Use for debugging the entries
+ def __str__(self):
+ if self.link:
+ return "%s link %s" % (self.path, self.link)
+ else:
+ mode = "-"
+ if self.mode:
+ mode = "0%o" % self.mode
+ fmode = "-"
+ if self.fmode:
+ fmode = "0%o" % self.fmode
+ uid = self._mapugid(self.uid)
+ gid = self._mapugid(self.gid)
+ fuid = self._mapugid(self.fuid)
+ fgid = self._mapugid(self.fgid)
+ return "%s %s %s %s %s %s %s %s" % (self.path, mode, uid, gid, self.walk, fmode, fuid, fgid)
+
+ def _mapugid(self, id):
+ if id is None or id == -1:
+ return "-"
+ else:
+ return "%d" % id
+
+ # Fix the permission, owner and group of path
+ def fix_perms(path, mode, uid, gid, dir):
+ if mode and not os.path.islink(path):
+ #bb.note("Fixup Perms: chmod 0%o %s" % (mode, dir))
+ os.chmod(path, mode)
+ # -1 is a special value that means don't change the uid/gid
+ # if they are BOTH -1, don't bother to lchown
+ if not (uid == -1 and gid == -1):
+ #bb.note("Fixup Perms: lchown %d:%d %s" % (uid, gid, dir))
+ os.lchown(path, uid, gid)
+
+ # Return a list of configuration files based on either the default
+ # files/fs-perms.txt or the contents of FILESYSTEM_PERMS_TABLES
+ # paths are resolved via BBPATH
+ def get_fs_perms_list(d):
+ str = ""
+ bbpath = d.getVar('BBPATH')
+ fs_perms_tables = d.getVar('FILESYSTEM_PERMS_TABLES') or ""
+ for conf_file in fs_perms_tables.split():
+ confpath = bb.utils.which(bbpath, conf_file)
+ if confpath:
+ str += " %s" % bb.utils.which(bbpath, conf_file)
+ else:
+ bb.warn("cannot find %s specified in FILESYSTEM_PERMS_TABLES" % conf_file)
+ return str
+
+ fs_perms_table = {}
+ fs_link_table = {}
+
+ # By default all of the standard directories specified in
+ # bitbake.conf will get 0755 root:root.
+ target_path_vars = [ 'base_prefix',
+ 'prefix',
+ 'exec_prefix',
+ 'base_bindir',
+ 'base_sbindir',
+ 'base_libdir',
+ 'datadir',
+ 'sysconfdir',
+ 'servicedir',
+ 'sharedstatedir',
+ 'localstatedir',
+ 'infodir',
+ 'mandir',
+ 'docdir',
+ 'bindir',
+ 'sbindir',
+ 'libexecdir',
+ 'libdir',
+ 'includedir',
+ 'oldincludedir' ]
+
+ for path in target_path_vars:
+ dir = d.getVar(path) or ""
+ if dir == "":
+ continue
+ fs_perms_table[dir] = fs_perms_entry(d.expand("%s 0755 root root false - - -" % (dir)))
+
+ # Now we actually load from the configuration files
+ for conf in get_fs_perms_list(d).split():
+ if not os.path.exists(conf):
+ continue
+ with open(conf) as f:
+ for line in f:
+ if line.startswith('#'):
+ continue
+ lsplit = line.split()
+ if len(lsplit) == 0:
+ continue
+ if len(lsplit) != 8 and not (len(lsplit) == 3 and lsplit[1].lower() == "link"):
+ msg = "Fixup perms: %s invalid line: %s" % (conf, line)
+ oe.qa.handle_error("perm-line", msg, d)
+ continue
+ entry = fs_perms_entry(d.expand(line))
+ if entry and entry.path:
+ if entry.link:
+ fs_link_table[entry.path] = entry
+ if entry.path in fs_perms_table:
+ fs_perms_table.pop(entry.path)
+ else:
+ fs_perms_table[entry.path] = entry
+ if entry.path in fs_link_table:
+ fs_link_table.pop(entry.path)
+
+ # Debug -- list out in-memory table
+ #for dir in fs_perms_table:
+ # bb.note("Fixup Perms: %s: %s" % (dir, str(fs_perms_table[dir])))
+ #for link in fs_link_table:
+ # bb.note("Fixup Perms: %s: %s" % (link, str(fs_link_table[link])))
+
+ # We process links first, so we can go back and fixup directory ownership
+ # for any newly created directories
+ # Process in sorted order so /run gets created before /run/lock, etc.
+ for entry in sorted(fs_link_table.values(), key=lambda x: x.link):
+ link = entry.link
+ dir = entry.path
+ origin = dvar + dir
+ if not (cpath.exists(origin) and cpath.isdir(origin) and not cpath.islink(origin)):
+ continue
+
+ if link[0] == "/":
+ target = dvar + link
+ ptarget = link
+ else:
+ target = os.path.join(os.path.dirname(origin), link)
+ ptarget = os.path.join(os.path.dirname(dir), link)
+ if os.path.exists(target):
+ msg = "Fixup Perms: Unable to correct directory link, target already exists: %s -> %s" % (dir, ptarget)
+ oe.qa.handle_error("perm-link", msg, d)
+ continue
+
+ # Create path to move directory to, move it, and then setup the symlink
+ bb.utils.mkdirhier(os.path.dirname(target))
+ #bb.note("Fixup Perms: Rename %s -> %s" % (dir, ptarget))
+ bb.utils.rename(origin, target)
+ #bb.note("Fixup Perms: Link %s -> %s" % (dir, link))
+ os.symlink(link, origin)
+
+ for dir in fs_perms_table:
+ origin = dvar + dir
+ if not (cpath.exists(origin) and cpath.isdir(origin)):
+ continue
+
+ fix_perms(origin, fs_perms_table[dir].mode, fs_perms_table[dir].uid, fs_perms_table[dir].gid, dir)
+
+ if fs_perms_table[dir].walk == 'true':
+ for root, dirs, files in os.walk(origin):
+ for dr in dirs:
+ each_dir = os.path.join(root, dr)
+ fix_perms(each_dir, fs_perms_table[dir].mode, fs_perms_table[dir].uid, fs_perms_table[dir].gid, dir)
+ for f in files:
+ each_file = os.path.join(root, f)
+ fix_perms(each_file, fs_perms_table[dir].fmode, fs_perms_table[dir].fuid, fs_perms_table[dir].fgid, dir)
+
+# Get a list of files from file vars by searching files under current working directory
+# The list contains symlinks, directories and normal files.
+def files_from_filevars(filevars):
+ cpath = oe.cachedpath.CachedPath()
+ files = []
+ for f in filevars:
+ if os.path.isabs(f):
+ f = '.' + f
+ if not f.startswith("./"):
+ f = './' + f
+ globbed = glob.glob(f)
+ if globbed:
+ if [ f ] != globbed:
+ files += globbed
+ continue
+ files.append(f)
+
+ symlink_paths = []
+ for ind, f in enumerate(files):
+ # Handle directory symlinks. Truncate path to the lowest level symlink
+ parent = ''
+ for dirname in f.split('/')[:-1]:
+ parent = os.path.join(parent, dirname)
+ if dirname == '.':
+ continue
+ if cpath.islink(parent):
+ bb.warn("FILES contains file '%s' which resides under a "
+ "directory symlink. Please fix the recipe and use the "
+ "real path for the file." % f[1:])
+ symlink_paths.append(f)
+ files[ind] = parent
+ f = parent
+ break
+
+ if not cpath.islink(f):
+ if cpath.isdir(f):
+ newfiles = [ os.path.join(f,x) for x in os.listdir(f) ]
+ if newfiles:
+ files += newfiles
+
+ return files, symlink_paths
+
+# Called in package_<rpm,ipk,deb>.bbclass to get the correct list of configuration files
+def get_conffiles(pkg, d):
+ pkgdest = d.getVar('PKGDEST')
+ root = os.path.join(pkgdest, pkg)
+ cwd = os.getcwd()
+ os.chdir(root)
+
+ conffiles = d.getVar('CONFFILES:%s' % pkg);
+ if conffiles == None:
+ conffiles = d.getVar('CONFFILES')
+ if conffiles == None:
+ conffiles = ""
+ conffiles = conffiles.split()
+ conf_orig_list = files_from_filevars(conffiles)[0]
+
+ # Remove links and directories from conf_orig_list to get conf_list which only contains normal files
+ conf_list = []
+ for f in conf_orig_list:
+ if os.path.isdir(f):
+ continue
+ if os.path.islink(f):
+ continue
+ if not os.path.exists(f):
+ continue
+ conf_list.append(f)
+
+ # Remove the leading './'
+ for i in range(0, len(conf_list)):
+ conf_list[i] = conf_list[i][1:]
+
+ os.chdir(cwd)
+ return conf_list
+
+def legitimize_package_name(s):
"""
- Work out the packages fetched and unpacked by BitBake's npm fetcher
- Returns a dict of packagename -> (relpath, package.json) ordered
- such that it is suitable for use in PACKAGES and FILES
+ Make sure package names are legitimate strings
"""
- from collections import OrderedDict
- import json
- packages = {}
- for root, dirs, files in os.walk(pkgdir):
- if os.path.basename(root) == 'node_modules':
- for dn in dirs:
- relpth = os.path.relpath(os.path.join(root, dn), pkgdir)
- pkgitems = ['${PN}']
- for pathitem in relpth.split('/'):
- if pathitem == 'node_modules':
+
+ def fixutf(m):
+ cp = m.group(1)
+ if cp:
+ return ('\\u%s' % cp).encode('latin-1').decode('unicode_escape')
+
+ # Handle unicode codepoints encoded as <U0123>, as in glibc locale files.
+ s = re.sub(r'<U([0-9A-Fa-f]{1,4})>', fixutf, s)
+
+ # Remaining package name validity fixes
+ return s.lower().replace('_', '-').replace('@', '+').replace(',', '+').replace('/', '-')
+
+def split_locales(d):
+ cpath = oe.cachedpath.CachedPath()
+ if (d.getVar('PACKAGE_NO_LOCALE') == '1'):
+ bb.debug(1, "package requested not splitting locales")
+ return
+
+ packages = (d.getVar('PACKAGES') or "").split()
+
+ datadir = d.getVar('datadir')
+ if not datadir:
+ bb.note("datadir not defined")
+ return
+
+ dvar = d.getVar('PKGD')
+ pn = d.getVar('LOCALEBASEPN')
+
+ if pn + '-locale' in packages:
+ packages.remove(pn + '-locale')
+
+ localedir = os.path.join(dvar + datadir, 'locale')
+
+ if not cpath.isdir(localedir):
+ bb.debug(1, "No locale files in this package")
+ return
+
+ locales = os.listdir(localedir)
+
+ summary = d.getVar('SUMMARY') or pn
+ description = d.getVar('DESCRIPTION') or ""
+ locale_section = d.getVar('LOCALE_SECTION')
+ mlprefix = d.getVar('MLPREFIX') or ""
+ for l in sorted(locales):
+ ln = legitimize_package_name(l)
+ pkg = pn + '-locale-' + ln
+ packages.append(pkg)
+ d.setVar('FILES:' + pkg, os.path.join(datadir, 'locale', l))
+ d.setVar('RRECOMMENDS:' + pkg, '%svirtual-locale-%s' % (mlprefix, ln))
+ d.setVar('RPROVIDES:' + pkg, '%s-locale %s%s-translation' % (pn, mlprefix, ln))
+ d.setVar('SUMMARY:' + pkg, '%s - %s translations' % (summary, l))
+ d.setVar('DESCRIPTION:' + pkg, '%s This package contains language translation files for the %s locale.' % (description, l))
+ if locale_section:
+ d.setVar('SECTION:' + pkg, locale_section)
+
+ d.setVar('PACKAGES', ' '.join(packages))
+
+ # Disabled by RP 18/06/07
+ # Wildcards aren't supported in debian
+ # They break with ipkg since glibc-locale* will mean that
+ # glibc-localedata-translit* won't install as a dependency
+ # for some other package which breaks meta-toolchain
+ # Probably breaks since virtual-locale- isn't provided anywhere
+ #rdep = (d.getVar('RDEPENDS:%s' % pn) or "").split()
+ #rdep.append('%s-locale*' % pn)
+ #d.setVar('RDEPENDS:%s' % pn, ' '.join(rdep))
+
+def package_debug_vars(d):
+ # We default to '.debug' style
+ if d.getVar('PACKAGE_DEBUG_SPLIT_STYLE') == 'debug-file-directory':
+ # Single debug-file-directory style debug info
+ debug_vars = {
+ "append": ".debug",
+ "staticappend": "",
+ "dir": "",
+ "staticdir": "",
+ "libdir": "/usr/lib/debug",
+ "staticlibdir": "/usr/lib/debug-static",
+ "srcdir": "/usr/src/debug",
+ }
+ elif d.getVar('PACKAGE_DEBUG_SPLIT_STYLE') == 'debug-without-src':
+ # Original OE-core, a.k.a. ".debug", style debug info, but without sources in /usr/src/debug
+ debug_vars = {
+ "append": "",
+ "staticappend": "",
+ "dir": "/.debug",
+ "staticdir": "/.debug-static",
+ "libdir": "",
+ "staticlibdir": "",
+ "srcdir": "",
+ }
+ elif d.getVar('PACKAGE_DEBUG_SPLIT_STYLE') == 'debug-with-srcpkg':
+ debug_vars = {
+ "append": "",
+ "staticappend": "",
+ "dir": "/.debug",
+ "staticdir": "/.debug-static",
+ "libdir": "",
+ "staticlibdir": "",
+ "srcdir": "/usr/src/debug",
+ }
+ else:
+ # Original OE-core, a.k.a. ".debug", style debug info
+ debug_vars = {
+ "append": "",
+ "staticappend": "",
+ "dir": "/.debug",
+ "staticdir": "/.debug-static",
+ "libdir": "",
+ "staticlibdir": "",
+ "srcdir": "/usr/src/debug",
+ }
+
+ return debug_vars
+
+
+def parse_debugsources_from_dwarfsrcfiles_output(dwarfsrcfiles_output):
+ debugfiles = {}
+
+ for line in dwarfsrcfiles_output.splitlines():
+ if line.startswith("\t"):
+ debugfiles[os.path.normpath(line.split()[0])] = ""
+
+ return debugfiles.keys()
+
+def source_info(file, d, fatal=True):
+ cmd = ["dwarfsrcfiles", file]
+ try:
+ output = subprocess.check_output(cmd, universal_newlines=True, stderr=subprocess.STDOUT)
+ retval = 0
+ except subprocess.CalledProcessError as exc:
+ output = exc.output
+ retval = exc.returncode
+
+ # 255 means a specific file wasn't fully parsed to get the debug file list, which is not a fatal failure
+ if retval != 0 and retval != 255:
+ msg = "dwarfsrcfiles failed with exit code %s (cmd was %s)%s" % (retval, cmd, ":\n%s" % output if output else "")
+ if fatal:
+ bb.fatal(msg)
+ bb.note(msg)
+
+ debugsources = parse_debugsources_from_dwarfsrcfiles_output(output)
+
+ return list(debugsources)
+
+def splitdebuginfo(file, dvar, dv, d):
+ # Function to split a single file into two components, one is the stripped
+ # target system binary, the other contains any debugging information. The
+ # two files are linked to reference each other.
+ #
+ # return a mapping of files:debugsources
+
+ src = file[len(dvar):]
+ dest = dv["libdir"] + os.path.dirname(src) + dv["dir"] + "/" + os.path.basename(src) + dv["append"]
+ debugfile = dvar + dest
+ sources = []
+
+ if file.endswith(".ko") and file.find("/lib/modules/") != -1:
+ if oe.package.is_kernel_module_signed(file):
+ bb.debug(1, "Skip strip on signed module %s" % file)
+ return (file, sources)
+
+ # Split the file...
+ bb.utils.mkdirhier(os.path.dirname(debugfile))
+ #bb.note("Split %s -> %s" % (file, debugfile))
+ # Only store off the hard link reference if we successfully split!
+
+ dvar = d.getVar('PKGD')
+ objcopy = d.getVar("OBJCOPY")
+
+ newmode = None
+ if not os.access(file, os.W_OK) or os.access(file, os.R_OK):
+ origmode = os.stat(file)[stat.ST_MODE]
+ newmode = origmode | stat.S_IWRITE | stat.S_IREAD
+ os.chmod(file, newmode)
+
+ # We need to extract the debug src information here...
+ if dv["srcdir"]:
+ sources = source_info(file, d)
+
+ bb.utils.mkdirhier(os.path.dirname(debugfile))
+
+ subprocess.check_output([objcopy, '--only-keep-debug', file, debugfile], stderr=subprocess.STDOUT)
+
+ # Set the debuglink to have the view of the file path on the target
+ subprocess.check_output([objcopy, '--add-gnu-debuglink', debugfile, file], stderr=subprocess.STDOUT)
+
+ if newmode:
+ os.chmod(file, origmode)
+
+ return (file, sources)
+
+def splitstaticdebuginfo(file, dvar, dv, d):
+ # Unlike the function above, there is no way to split a static library
+ # two components. So to get similar results we will copy the unmodified
+ # static library (containing the debug symbols) into a new directory.
+ # We will then strip (preserving symbols) the static library in the
+ # typical location.
+ #
+ # return a mapping of files:debugsources
+
+ src = file[len(dvar):]
+ dest = dv["staticlibdir"] + os.path.dirname(src) + dv["staticdir"] + "/" + os.path.basename(src) + dv["staticappend"]
+ debugfile = dvar + dest
+ sources = []
+
+ # Copy the file...
+ bb.utils.mkdirhier(os.path.dirname(debugfile))
+ #bb.note("Copy %s -> %s" % (file, debugfile))
+
+ dvar = d.getVar('PKGD')
+
+ newmode = None
+ if not os.access(file, os.W_OK) or os.access(file, os.R_OK):
+ origmode = os.stat(file)[stat.ST_MODE]
+ newmode = origmode | stat.S_IWRITE | stat.S_IREAD
+ os.chmod(file, newmode)
+
+ # We need to extract the debug src information here...
+ if dv["srcdir"]:
+ sources = source_info(file, d)
+
+ bb.utils.mkdirhier(os.path.dirname(debugfile))
+
+ # Copy the unmodified item to the debug directory
+ shutil.copy2(file, debugfile)
+
+ if newmode:
+ os.chmod(file, origmode)
+
+ return (file, sources)
+
+def inject_minidebuginfo(file, dvar, dv, d):
+ # Extract just the symbols from debuginfo into minidebuginfo,
+ # compress it with xz and inject it back into the binary in a .gnu_debugdata section.
+ # https://sourceware.org/gdb/onlinedocs/gdb/MiniDebugInfo.html
+
+ readelf = d.getVar('READELF')
+ nm = d.getVar('NM')
+ objcopy = d.getVar('OBJCOPY')
+
+ minidebuginfodir = d.expand('${WORKDIR}/minidebuginfo')
+
+ src = file[len(dvar):]
+ dest = dv["libdir"] + os.path.dirname(src) + dv["dir"] + "/" + os.path.basename(src) + dv["append"]
+ debugfile = dvar + dest
+ minidebugfile = minidebuginfodir + src + '.minidebug'
+ bb.utils.mkdirhier(os.path.dirname(minidebugfile))
+
+ # If we didn't produce debuginfo for any reason, we can't produce minidebuginfo either
+ # so skip it.
+ if not os.path.exists(debugfile):
+ bb.debug(1, 'ELF file {} has no debuginfo, skipping minidebuginfo injection'.format(file))
+ return
+
+ # minidebuginfo does not make sense to apply to ELF objects other than
+ # executables and shared libraries, skip applying the minidebuginfo
+ # generation for objects like kernel modules.
+ for line in subprocess.check_output([readelf, '-h', debugfile], universal_newlines=True).splitlines():
+ if not line.strip().startswith("Type:"):
+ continue
+ elftype = line.split(":")[1].strip()
+ if not any(elftype.startswith(i) for i in ["EXEC", "DYN"]):
+ bb.debug(1, 'ELF file {} is not executable/shared, skipping minidebuginfo injection'.format(file))
+ return
+ break
+
+ # Find non-allocated PROGBITS, NOTE, and NOBITS sections in the debuginfo.
+ # We will exclude all of these from minidebuginfo to save space.
+ remove_section_names = []
+ for line in subprocess.check_output([readelf, '-W', '-S', debugfile], universal_newlines=True).splitlines():
+ # strip the leading " [ 1]" section index to allow splitting on space
+ if ']' not in line:
+ continue
+ fields = line[line.index(']') + 1:].split()
+ if len(fields) < 7:
+ continue
+ name = fields[0]
+ type = fields[1]
+ flags = fields[6]
+ # .debug_ sections will be removed by objcopy -S so no need to explicitly remove them
+ if name.startswith('.debug_'):
+ continue
+ if 'A' not in flags and type in ['PROGBITS', 'NOTE', 'NOBITS']:
+ remove_section_names.append(name)
+
+ # List dynamic symbols in the binary. We can exclude these from minidebuginfo
+ # because they are always present in the binary.
+ dynsyms = set()
+ for line in subprocess.check_output([nm, '-D', file, '--format=posix', '--defined-only'], universal_newlines=True).splitlines():
+ dynsyms.add(line.split()[0])
+
+ # Find all function symbols from debuginfo which aren't in the dynamic symbols table.
+ # These are the ones we want to keep in minidebuginfo.
+ keep_symbols_file = minidebugfile + '.symlist'
+ found_any_symbols = False
+ with open(keep_symbols_file, 'w') as f:
+ for line in subprocess.check_output([nm, debugfile, '--format=sysv', '--defined-only'], universal_newlines=True).splitlines():
+ fields = line.split('|')
+ if len(fields) < 7:
+ continue
+ name = fields[0].strip()
+ type = fields[3].strip()
+ if type == 'FUNC' and name not in dynsyms:
+ f.write('{}\n'.format(name))
+ found_any_symbols = True
+
+ if not found_any_symbols:
+ bb.debug(1, 'ELF file {} contains no symbols, skipping minidebuginfo injection'.format(file))
+ return
+
+ bb.utils.remove(minidebugfile)
+ bb.utils.remove(minidebugfile + '.xz')
+
+ subprocess.check_call([objcopy, '-S'] +
+ ['--remove-section={}'.format(s) for s in remove_section_names] +
+ ['--keep-symbols={}'.format(keep_symbols_file), debugfile, minidebugfile])
+
+ subprocess.check_call(['xz', '--keep', minidebugfile])
+
+ subprocess.check_call([objcopy, '--add-section', '.gnu_debugdata={}.xz'.format(minidebugfile), file])
+
+def copydebugsources(debugsrcdir, sources, d):
+ # The debug src information written out to sourcefile is further processed
+ # and copied to the destination here.
+
+ cpath = oe.cachedpath.CachedPath()
+
+ if debugsrcdir and sources:
+ sourcefile = d.expand("${WORKDIR}/debugsources.list")
+ bb.utils.remove(sourcefile)
+
+ # filenames are null-separated - this is an artefact of the previous use
+ # of rpm's debugedit, which was writing them out that way, and the code elsewhere
+ # is still assuming that.
+ debuglistoutput = '\0'.join(sources) + '\0'
+ with open(sourcefile, 'a') as sf:
+ sf.write(debuglistoutput)
+
+ dvar = d.getVar('PKGD')
+ strip = d.getVar("STRIP")
+ objcopy = d.getVar("OBJCOPY")
+ workdir = d.getVar("WORKDIR")
+ sdir = d.getVar("S")
+ cflags = d.expand("${CFLAGS}")
+
+ prefixmap = {}
+ for flag in cflags.split():
+ if not flag.startswith("-fdebug-prefix-map"):
+ continue
+ if "recipe-sysroot" in flag:
+ continue
+ flag = flag.split("=")
+ prefixmap[flag[1]] = flag[2]
+
+ nosuchdir = []
+ basepath = dvar
+ for p in debugsrcdir.split("/"):
+ basepath = basepath + "/" + p
+ if not cpath.exists(basepath):
+ nosuchdir.append(basepath)
+ bb.utils.mkdirhier(basepath)
+ cpath.updatecache(basepath)
+
+ for pmap in prefixmap:
+ # Ignore files from the recipe sysroots (target and native)
+ cmd = "LC_ALL=C ; sort -z -u '%s' | egrep -v -z '((<internal>|<built-in>)$|/.*recipe-sysroot.*/)' | " % sourcefile
+ # We need to ignore files that are not actually ours
+ # we do this by only paying attention to items from this package
+ cmd += "fgrep -zw '%s' | " % prefixmap[pmap]
+ # Remove prefix in the source paths
+ cmd += "sed 's#%s/##g' | " % (prefixmap[pmap])
+ cmd += "(cd '%s' ; cpio -pd0mlL --no-preserve-owner '%s%s' 2>/dev/null)" % (pmap, dvar, prefixmap[pmap])
+
+ try:
+ subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT)
+ except subprocess.CalledProcessError:
+ # Can "fail" if internal headers/transient sources are attempted
+ pass
+ # cpio seems to have a bug with -lL together and symbolic links are just copied, not dereferenced.
+ # Work around this by manually finding and copying any symbolic links that made it through.
+ cmd = "find %s%s -type l -print0 -delete | sed s#%s%s/##g | (cd '%s' ; cpio -pd0mL --no-preserve-owner '%s%s')" % \
+ (dvar, prefixmap[pmap], dvar, prefixmap[pmap], pmap, dvar, prefixmap[pmap])
+ subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT)
+
+ # debugsources.list may be polluted from the host if we used externalsrc,
+ # cpio uses copy-pass and may have just created a directory structure
+ # matching the one from the host, if thats the case move those files to
+ # debugsrcdir to avoid host contamination.
+ # Empty dir structure will be deleted in the next step.
+
+ # Same check as above for externalsrc
+ if workdir not in sdir:
+ if os.path.exists(dvar + debugsrcdir + sdir):
+ cmd = "mv %s%s%s/* %s%s" % (dvar, debugsrcdir, sdir, dvar,debugsrcdir)
+ subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT)
+
+ # The copy by cpio may have resulted in some empty directories! Remove these
+ cmd = "find %s%s -empty -type d -delete" % (dvar, debugsrcdir)
+ subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT)
+
+ # Also remove debugsrcdir if its empty
+ for p in nosuchdir[::-1]:
+ if os.path.exists(p) and not os.listdir(p):
+ os.rmdir(p)
+
+
+def process_split_and_strip_files(d):
+ cpath = oe.cachedpath.CachedPath()
+
+ dvar = d.getVar('PKGD')
+ pn = d.getVar('PN')
+ hostos = d.getVar('HOST_OS')
+
+ oldcwd = os.getcwd()
+ os.chdir(dvar)
+
+ dv = package_debug_vars(d)
+
+ #
+ # First lets figure out all of the files we may have to process ... do this only once!
+ #
+ elffiles = {}
+ symlinks = {}
+ staticlibs = []
+ inodes = {}
+ libdir = os.path.abspath(dvar + os.sep + d.getVar("libdir"))
+ baselibdir = os.path.abspath(dvar + os.sep + d.getVar("base_libdir"))
+ skipfiles = (d.getVar("INHIBIT_PACKAGE_STRIP_FILES") or "").split()
+ if (d.getVar('INHIBIT_PACKAGE_STRIP') != '1' or \
+ d.getVar('INHIBIT_PACKAGE_DEBUG_SPLIT') != '1'):
+ checkelf = {}
+ checkelflinks = {}
+ for root, dirs, files in cpath.walk(dvar):
+ for f in files:
+ file = os.path.join(root, f)
+
+ # Skip debug files
+ if dv["append"] and file.endswith(dv["append"]):
+ continue
+ if dv["dir"] and dv["dir"] in os.path.dirname(file[len(dvar):]):
+ continue
+
+ if file in skipfiles:
+ continue
+
+ if oe.package.is_static_lib(file):
+ staticlibs.append(file)
+ continue
+
+ try:
+ ltarget = cpath.realpath(file, dvar, False)
+ s = cpath.lstat(ltarget)
+ except OSError as e:
+ (err, strerror) = e.args
+ if err != errno.ENOENT:
+ raise
+ # Skip broken symlinks
+ continue
+ if not s:
+ continue
+ # Check its an executable
+ if (s[stat.ST_MODE] & stat.S_IXUSR) or (s[stat.ST_MODE] & stat.S_IXGRP) \
+ or (s[stat.ST_MODE] & stat.S_IXOTH) \
+ or ((file.startswith(libdir) or file.startswith(baselibdir)) \
+ and (".so" in f or ".node" in f)) \
+ or (f.startswith('vmlinux') or ".ko" in f):
+
+ if cpath.islink(file):
+ checkelflinks[file] = ltarget
continue
- pkgitems.append(pathitem)
- pkgname = '-'.join(pkgitems).replace('_', '-')
- pkgfile = os.path.join(root, dn, 'package.json')
- data = None
- if os.path.exists(pkgfile):
- with open(pkgfile, 'r') as f:
- data = json.loads(f.read())
- packages[pkgname] = (relpth, data)
- # We want the main package for a module sorted *after* its subpackages
- # (so that it doesn't otherwise steal the files for the subpackage), so
- # this is a cheap way to do that whilst still having an otherwise
- # alphabetical sort
- return OrderedDict((key, packages[key]) for key in sorted(packages, key=lambda pkg: pkg + '~'))
+ # Use a reference of device ID and inode number to identify files
+ file_reference = "%d_%d" % (s.st_dev, s.st_ino)
+ checkelf[file] = (file, file_reference)
+
+ results = oe.utils.multiprocess_launch(oe.package.is_elf, checkelflinks.values(), d)
+ results_map = {}
+ for (ltarget, elf_file) in results:
+ results_map[ltarget] = elf_file
+ for file in checkelflinks:
+ ltarget = checkelflinks[file]
+ # If it's a symlink, and points to an ELF file, we capture the readlink target
+ if results_map[ltarget]:
+ target = os.readlink(file)
+ #bb.note("Sym: %s (%d)" % (ltarget, results_map[ltarget]))
+ symlinks[file] = target
+
+ results = oe.utils.multiprocess_launch(oe.package.is_elf, checkelf.keys(), d)
+
+ # Sort results by file path. This ensures that the files are always
+ # processed in the same order, which is important to make sure builds
+ # are reproducible when dealing with hardlinks
+ results.sort(key=lambda x: x[0])
+
+ for (file, elf_file) in results:
+ # It's a file (or hardlink), not a link
+ # ...but is it ELF, and is it already stripped?
+ if elf_file & 1:
+ if elf_file & 2:
+ if 'already-stripped' in (d.getVar('INSANE_SKIP:' + pn) or "").split():
+ bb.note("Skipping file %s from %s for already-stripped QA test" % (file[len(dvar):], pn))
+ else:
+ msg = "File '%s' from %s was already stripped, this will prevent future debugging!" % (file[len(dvar):], pn)
+ oe.qa.handle_error("already-stripped", msg, d)
+ continue
+
+ # At this point we have an unstripped elf file. We need to:
+ # a) Make sure any file we strip is not hardlinked to anything else outside this tree
+ # b) Only strip any hardlinked file once (no races)
+ # c) Track any hardlinks between files so that we can reconstruct matching debug file hardlinks
+
+ # Use a reference of device ID and inode number to identify files
+ file_reference = checkelf[file][1]
+ if file_reference in inodes:
+ os.unlink(file)
+ os.link(inodes[file_reference][0], file)
+ inodes[file_reference].append(file)
+ else:
+ inodes[file_reference] = [file]
+ # break hardlink
+ bb.utils.break_hardlinks(file)
+ elffiles[file] = elf_file
+ # Modified the file so clear the cache
+ cpath.updatecache(file)
+
+ def strip_pkgd_prefix(f):
+ nonlocal dvar
+
+ if f.startswith(dvar):
+ return f[len(dvar):]
+
+ return f
+
+ #
+ # First lets process debug splitting
+ #
+ if (d.getVar('INHIBIT_PACKAGE_DEBUG_SPLIT') != '1'):
+ results = oe.utils.multiprocess_launch(splitdebuginfo, list(elffiles), d, extraargs=(dvar, dv, d))
+
+ if dv["srcdir"] and not hostos.startswith("mingw"):
+ if (d.getVar('PACKAGE_DEBUG_STATIC_SPLIT') == '1'):
+ results = oe.utils.multiprocess_launch(splitstaticdebuginfo, staticlibs, d, extraargs=(dvar, dv, d))
+ else:
+ for file in staticlibs:
+ results.append( (file,source_info(file, d)) )
+
+ d.setVar("PKGDEBUGSOURCES", {strip_pkgd_prefix(f): sorted(s) for f, s in results})
+
+ sources = set()
+ for r in results:
+ sources.update(r[1])
+
+ # Hardlink our debug symbols to the other hardlink copies
+ for ref in inodes:
+ if len(inodes[ref]) == 1:
+ continue
+
+ target = inodes[ref][0][len(dvar):]
+ for file in inodes[ref][1:]:
+ src = file[len(dvar):]
+ dest = dv["libdir"] + os.path.dirname(src) + dv["dir"] + "/" + os.path.basename(target) + dv["append"]
+ fpath = dvar + dest
+ ftarget = dvar + dv["libdir"] + os.path.dirname(target) + dv["dir"] + "/" + os.path.basename(target) + dv["append"]
+ bb.utils.mkdirhier(os.path.dirname(fpath))
+ # Only one hardlink of separated debug info file in each directory
+ if not os.access(fpath, os.R_OK):
+ #bb.note("Link %s -> %s" % (fpath, ftarget))
+ os.link(ftarget, fpath)
+
+ # Create symlinks for all cases we were able to split symbols
+ for file in symlinks:
+ src = file[len(dvar):]
+ dest = dv["libdir"] + os.path.dirname(src) + dv["dir"] + "/" + os.path.basename(src) + dv["append"]
+ fpath = dvar + dest
+ # Skip it if the target doesn't exist
+ try:
+ s = os.stat(fpath)
+ except OSError as e:
+ (err, strerror) = e.args
+ if err != errno.ENOENT:
+ raise
+ continue
+
+ ltarget = symlinks[file]
+ lpath = os.path.dirname(ltarget)
+ lbase = os.path.basename(ltarget)
+ ftarget = ""
+ if lpath and lpath != ".":
+ ftarget += lpath + dv["dir"] + "/"
+ ftarget += lbase + dv["append"]
+ if lpath.startswith(".."):
+ ftarget = os.path.join("..", ftarget)
+ bb.utils.mkdirhier(os.path.dirname(fpath))
+ #bb.note("Symlink %s -> %s" % (fpath, ftarget))
+ os.symlink(ftarget, fpath)
+
+ # Process the dv["srcdir"] if requested...
+ # This copies and places the referenced sources for later debugging...
+ copydebugsources(dv["srcdir"], sources, d)
+ #
+ # End of debug splitting
+ #
+
+ #
+ # Now lets go back over things and strip them
+ #
+ if (d.getVar('INHIBIT_PACKAGE_STRIP') != '1'):
+ strip = d.getVar("STRIP")
+ sfiles = []
+ for file in elffiles:
+ elf_file = int(elffiles[file])
+ #bb.note("Strip %s" % file)
+ sfiles.append((file, elf_file, strip))
+ if (d.getVar('PACKAGE_STRIP_STATIC') == '1' or d.getVar('PACKAGE_DEBUG_STATIC_SPLIT') == '1'):
+ for f in staticlibs:
+ sfiles.append((f, 16, strip))
+
+ oe.utils.multiprocess_launch(oe.package.runstrip, sfiles, d)
+
+ # Build "minidebuginfo" and reinject it back into the stripped binaries
+ if d.getVar('PACKAGE_MINIDEBUGINFO') == '1':
+ oe.utils.multiprocess_launch(inject_minidebuginfo, list(elffiles), d,
+ extraargs=(dvar, dv, d))
+
+ #
+ # End of strip
+ #
+ os.chdir(oldcwd)
+
+
+def populate_packages(d):
+ cpath = oe.cachedpath.CachedPath()
+
+ workdir = d.getVar('WORKDIR')
+ outdir = d.getVar('DEPLOY_DIR')
+ dvar = d.getVar('PKGD')
+ packages = d.getVar('PACKAGES').split()
+ pn = d.getVar('PN')
+
+ bb.utils.mkdirhier(outdir)
+ os.chdir(dvar)
+
+ autodebug = not (d.getVar("NOAUTOPACKAGEDEBUG") or False)
+
+ split_source_package = (d.getVar('PACKAGE_DEBUG_SPLIT_STYLE') == 'debug-with-srcpkg')
+
+ # If debug-with-srcpkg mode is enabled then add the source package if it
+ # doesn't exist and add the source file contents to the source package.
+ if split_source_package:
+ src_package_name = ('%s-src' % d.getVar('PN'))
+ if not src_package_name in packages:
+ packages.append(src_package_name)
+ d.setVar('FILES:%s' % src_package_name, '/usr/src/debug')
+
+ # Sanity check PACKAGES for duplicates
+ # Sanity should be moved to sanity.bbclass once we have the infrastructure
+ package_dict = {}
+
+ for i, pkg in enumerate(packages):
+ if pkg in package_dict:
+ msg = "%s is listed in PACKAGES multiple times, this leads to packaging errors." % pkg
+ oe.qa.handle_error("packages-list", msg, d)
+ # Ensure the source package gets the chance to pick up the source files
+ # before the debug package by ordering it first in PACKAGES. Whether it
+ # actually picks up any source files is controlled by
+ # PACKAGE_DEBUG_SPLIT_STYLE.
+ elif pkg.endswith("-src"):
+ package_dict[pkg] = (10, i)
+ elif autodebug and pkg.endswith("-dbg"):
+ package_dict[pkg] = (30, i)
+ else:
+ package_dict[pkg] = (50, i)
+ packages = sorted(package_dict.keys(), key=package_dict.get)
+ d.setVar('PACKAGES', ' '.join(packages))
+ pkgdest = d.getVar('PKGDEST')
+
+ seen = []
+
+ # os.mkdir masks the permissions with umask so we have to unset it first
+ oldumask = os.umask(0)
+
+ debug = []
+ for root, dirs, files in cpath.walk(dvar):
+ dir = root[len(dvar):]
+ if not dir:
+ dir = os.sep
+ for f in (files + dirs):
+ path = "." + os.path.join(dir, f)
+ if "/.debug/" in path or "/.debug-static/" in path or path.endswith("/.debug"):
+ debug.append(path)
+
+ for pkg in packages:
+ root = os.path.join(pkgdest, pkg)
+ bb.utils.mkdirhier(root)
+
+ filesvar = d.getVar('FILES:%s' % pkg) or ""
+ if "//" in filesvar:
+ msg = "FILES variable for package %s contains '//' which is invalid. Attempting to fix this but you should correct the metadata.\n" % pkg
+ oe.qa.handle_error("files-invalid", msg, d)
+ filesvar.replace("//", "/")
+
+ origfiles = filesvar.split()
+ files, symlink_paths = oe.package.files_from_filevars(origfiles)
+
+ if autodebug and pkg.endswith("-dbg"):
+ files.extend(debug)
+
+ for file in files:
+ if (not cpath.islink(file)) and (not cpath.exists(file)):
+ continue
+ if file in seen:
+ continue
+ seen.append(file)
+
+ def mkdir(src, dest, p):
+ src = os.path.join(src, p)
+ dest = os.path.join(dest, p)
+ fstat = cpath.stat(src)
+ os.mkdir(dest)
+ os.chmod(dest, fstat.st_mode)
+ os.chown(dest, fstat.st_uid, fstat.st_gid)
+ if p not in seen:
+ seen.append(p)
+ cpath.updatecache(dest)
+
+ def mkdir_recurse(src, dest, paths):
+ if cpath.exists(dest + '/' + paths):
+ return
+ while paths.startswith("./"):
+ paths = paths[2:]
+ p = "."
+ for c in paths.split("/"):
+ p = os.path.join(p, c)
+ if not cpath.exists(os.path.join(dest, p)):
+ mkdir(src, dest, p)
+
+ if cpath.isdir(file) and not cpath.islink(file):
+ mkdir_recurse(dvar, root, file)
+ continue
+
+ mkdir_recurse(dvar, root, os.path.dirname(file))
+ fpath = os.path.join(root,file)
+ if not cpath.islink(file):
+ os.link(file, fpath)
+ continue
+ ret = bb.utils.copyfile(file, fpath)
+ if ret is False or ret == 0:
+ bb.fatal("File population failed")
+
+ # Check if symlink paths exist
+ for file in symlink_paths:
+ if not os.path.exists(os.path.join(root,file)):
+ bb.fatal("File '%s' cannot be packaged into '%s' because its "
+ "parent directory structure does not exist. One of "
+ "its parent directories is a symlink whose target "
+ "directory is not included in the package." %
+ (file, pkg))
+
+ os.umask(oldumask)
+ os.chdir(workdir)
+
+ # Handle excluding packages with incompatible licenses
+ package_list = []
+ for pkg in packages:
+ licenses = d.getVar('_exclude_incompatible-' + pkg)
+ if licenses:
+ msg = "Excluding %s from packaging as it has incompatible license(s): %s" % (pkg, licenses)
+ oe.qa.handle_error("incompatible-license", msg, d)
+ else:
+ package_list.append(pkg)
+ d.setVar('PACKAGES', ' '.join(package_list))
+
+ unshipped = []
+ for root, dirs, files in cpath.walk(dvar):
+ dir = root[len(dvar):]
+ if not dir:
+ dir = os.sep
+ for f in (files + dirs):
+ path = os.path.join(dir, f)
+ if ('.' + path) not in seen:
+ unshipped.append(path)
+
+ if unshipped != []:
+ msg = pn + ": Files/directories were installed but not shipped in any package:"
+ if "installed-vs-shipped" in (d.getVar('INSANE_SKIP:' + pn) or "").split():
+ bb.note("Package %s skipping QA tests: installed-vs-shipped" % pn)
+ else:
+ for f in unshipped:
+ msg = msg + "\n " + f
+ msg = msg + "\nPlease set FILES such that these items are packaged. Alternatively if they are unneeded, avoid installing them or delete them within do_install.\n"
+ msg = msg + "%s: %d installed and not shipped files." % (pn, len(unshipped))
+ oe.qa.handle_error("installed-vs-shipped", msg, d)
+
+def process_fixsymlinks(pkgfiles, d):
+ cpath = oe.cachedpath.CachedPath()
+ pkgdest = d.getVar('PKGDEST')
+ packages = d.getVar("PACKAGES", False).split()
+
+ dangling_links = {}
+ pkg_files = {}
+ for pkg in packages:
+ dangling_links[pkg] = []
+ pkg_files[pkg] = []
+ inst_root = os.path.join(pkgdest, pkg)
+ for path in pkgfiles[pkg]:
+ rpath = path[len(inst_root):]
+ pkg_files[pkg].append(rpath)
+ rtarget = cpath.realpath(path, inst_root, True, assume_dir = True)
+ if not cpath.lexists(rtarget):
+ dangling_links[pkg].append(os.path.normpath(rtarget[len(inst_root):]))
+
+ newrdepends = {}
+ for pkg in dangling_links:
+ for l in dangling_links[pkg]:
+ found = False
+ bb.debug(1, "%s contains dangling link %s" % (pkg, l))
+ for p in packages:
+ if l in pkg_files[p]:
+ found = True
+ bb.debug(1, "target found in %s" % p)
+ if p == pkg:
+ break
+ if pkg not in newrdepends:
+ newrdepends[pkg] = []
+ newrdepends[pkg].append(p)
+ break
+ if found == False:
+ bb.note("%s contains dangling symlink to %s" % (pkg, l))
+
+ for pkg in newrdepends:
+ rdepends = bb.utils.explode_dep_versions2(d.getVar('RDEPENDS:' + pkg) or "")
+ for p in newrdepends[pkg]:
+ if p not in rdepends:
+ rdepends[p] = []
+ d.setVar('RDEPENDS:' + pkg, bb.utils.join_deps(rdepends, commasep=False))
+
+def process_filedeps(pkgfiles, d):
+ """
+ Collect perfile run-time dependency metadata
+ Output:
+ FILERPROVIDESFLIST:pkg - list of all files w/ deps
+ FILERPROVIDES:filepath:pkg - per file dep
+
+ FILERDEPENDSFLIST:pkg - list of all files w/ deps
+ FILERDEPENDS:filepath:pkg - per file dep
+ """
+ if d.getVar('SKIP_FILEDEPS') == '1':
+ return
+
+ pkgdest = d.getVar('PKGDEST')
+ packages = d.getVar('PACKAGES')
+ rpmdeps = d.getVar('RPMDEPS')
+
+ def chunks(files, n):
+ return [files[i:i+n] for i in range(0, len(files), n)]
+
+ pkglist = []
+ for pkg in packages.split():
+ if d.getVar('SKIP_FILEDEPS:' + pkg) == '1':
+ continue
+ if pkg.endswith('-dbg') or pkg.endswith('-doc') or pkg.find('-locale-') != -1 or pkg.find('-localedata-') != -1 or pkg.find('-gconv-') != -1 or pkg.find('-charmap-') != -1 or pkg.startswith('kernel-module-') or pkg.endswith('-src'):
+ continue
+ for files in chunks(pkgfiles[pkg], 100):
+ pkglist.append((pkg, files, rpmdeps, pkgdest))
+
+ processed = oe.utils.multiprocess_launch(oe.package.filedeprunner, pkglist, d)
+
+ provides_files = {}
+ requires_files = {}
+
+ for result in processed:
+ (pkg, provides, requires) = result
+
+ if pkg not in provides_files:
+ provides_files[pkg] = []
+ if pkg not in requires_files:
+ requires_files[pkg] = []
+
+ for file in sorted(provides):
+ provides_files[pkg].append(file)
+ key = "FILERPROVIDES:" + file + ":" + pkg
+ d.appendVar(key, " " + " ".join(provides[file]))
+
+ for file in sorted(requires):
+ requires_files[pkg].append(file)
+ key = "FILERDEPENDS:" + file + ":" + pkg
+ d.appendVar(key, " " + " ".join(requires[file]))
+
+ for pkg in requires_files:
+ d.setVar("FILERDEPENDSFLIST:" + pkg, " ".join(sorted(requires_files[pkg])))
+ for pkg in provides_files:
+ d.setVar("FILERPROVIDESFLIST:" + pkg, " ".join(sorted(provides_files[pkg])))
+
+def process_shlibs(pkgfiles, d):
+ cpath = oe.cachedpath.CachedPath()
+
+ exclude_shlibs = d.getVar('EXCLUDE_FROM_SHLIBS', False)
+ if exclude_shlibs:
+ bb.note("not generating shlibs")
+ return
+
+ lib_re = re.compile(r"^.*\.so")
+ libdir_re = re.compile(r".*/%s$" % d.getVar('baselib'))
+
+ packages = d.getVar('PACKAGES')
+
+ shlib_pkgs = []
+ exclusion_list = d.getVar("EXCLUDE_PACKAGES_FROM_SHLIBS")
+ if exclusion_list:
+ for pkg in packages.split():
+ if pkg not in exclusion_list.split():
+ shlib_pkgs.append(pkg)
+ else:
+ bb.note("not generating shlibs for %s" % pkg)
+ else:
+ shlib_pkgs = packages.split()
+
+ hostos = d.getVar('HOST_OS')
+
+ workdir = d.getVar('WORKDIR')
+
+ ver = d.getVar('PKGV')
+ if not ver:
+ msg = "PKGV not defined"
+ oe.qa.handle_error("pkgv-undefined", msg, d)
+ return
+
+ pkgdest = d.getVar('PKGDEST')
+
+ shlibswork_dir = d.getVar('SHLIBSWORKDIR')
+
+ def linux_so(file, pkg, pkgver, d):
+ needs_ldconfig = False
+ needed = set()
+ sonames = set()
+ renames = []
+ ldir = os.path.dirname(file).replace(pkgdest + "/" + pkg, '')
+ cmd = d.getVar('OBJDUMP') + " -p " + pipes.quote(file) + " 2>/dev/null"
+ fd = os.popen(cmd)
+ lines = fd.readlines()
+ fd.close()
+ rpath = tuple()
+ for l in lines:
+ m = re.match(r"\s+RPATH\s+([^\s]*)", l)
+ if m:
+ rpaths = m.group(1).replace("$ORIGIN", ldir).split(":")
+ rpath = tuple(map(os.path.normpath, rpaths))
+ for l in lines:
+ m = re.match(r"\s+NEEDED\s+([^\s]*)", l)
+ if m:
+ dep = m.group(1)
+ if dep not in needed:
+ needed.add((dep, file, rpath))
+ m = re.match(r"\s+SONAME\s+([^\s]*)", l)
+ if m:
+ this_soname = m.group(1)
+ prov = (this_soname, ldir, pkgver)
+ if not prov in sonames:
+ # if library is private (only used by package) then do not build shlib for it
+ if not private_libs or len([i for i in private_libs if fnmatch.fnmatch(this_soname, i)]) == 0:
+ sonames.add(prov)
+ if libdir_re.match(os.path.dirname(file)):
+ needs_ldconfig = True
+ if needs_ldconfig and snap_symlinks and (os.path.basename(file) != this_soname):
+ renames.append((file, os.path.join(os.path.dirname(file), this_soname)))
+ return (needs_ldconfig, needed, sonames, renames)
+
+ def darwin_so(file, needed, sonames, renames, pkgver):
+ if not os.path.exists(file):
+ return
+ ldir = os.path.dirname(file).replace(pkgdest + "/" + pkg, '')
+
+ def get_combinations(base):
+ #
+ # Given a base library name, find all combinations of this split by "." and "-"
+ #
+ combos = []
+ options = base.split(".")
+ for i in range(1, len(options) + 1):
+ combos.append(".".join(options[0:i]))
+ options = base.split("-")
+ for i in range(1, len(options) + 1):
+ combos.append("-".join(options[0:i]))
+ return combos
+
+ if (file.endswith('.dylib') or file.endswith('.so')) and not pkg.endswith('-dev') and not pkg.endswith('-dbg') and not pkg.endswith('-src'):
+ # Drop suffix
+ name = os.path.basename(file).rsplit(".",1)[0]
+ # Find all combinations
+ combos = get_combinations(name)
+ for combo in combos:
+ if not combo in sonames:
+ prov = (combo, ldir, pkgver)
+ sonames.add(prov)
+ if file.endswith('.dylib') or file.endswith('.so'):
+ rpath = []
+ p = subprocess.Popen([d.expand("${HOST_PREFIX}otool"), '-l', file], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ out, err = p.communicate()
+ # If returned successfully, process stdout for results
+ if p.returncode == 0:
+ for l in out.split("\n"):
+ l = l.strip()
+ if l.startswith('path '):
+ rpath.append(l.split()[1])
+
+ p = subprocess.Popen([d.expand("${HOST_PREFIX}otool"), '-L', file], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ out, err = p.communicate()
+ # If returned successfully, process stdout for results
+ if p.returncode == 0:
+ for l in out.split("\n"):
+ l = l.strip()
+ if not l or l.endswith(":"):
+ continue
+ if "is not an object file" in l:
+ continue
+ name = os.path.basename(l.split()[0]).rsplit(".", 1)[0]
+ if name and name not in needed[pkg]:
+ needed[pkg].add((name, file, tuple()))
+
+ def mingw_dll(file, needed, sonames, renames, pkgver):
+ if not os.path.exists(file):
+ return
+
+ if file.endswith(".dll"):
+ # assume all dlls are shared objects provided by the package
+ sonames.add((os.path.basename(file), os.path.dirname(file).replace(pkgdest + "/" + pkg, ''), pkgver))
+
+ if (file.endswith(".dll") or file.endswith(".exe")):
+ # use objdump to search for "DLL Name: .*\.dll"
+ p = subprocess.Popen([d.expand("${HOST_PREFIX}objdump"), "-p", file], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ out, err = p.communicate()
+ # process the output, grabbing all .dll names
+ if p.returncode == 0:
+ for m in re.finditer(r"DLL Name: (.*?\.dll)$", out.decode(), re.MULTILINE | re.IGNORECASE):
+ dllname = m.group(1)
+ if dllname:
+ needed[pkg].add((dllname, file, tuple()))
+
+ if d.getVar('PACKAGE_SNAP_LIB_SYMLINKS') == "1":
+ snap_symlinks = True
+ else:
+ snap_symlinks = False
+
+ needed = {}
+
+ shlib_provider = oe.package.read_shlib_providers(d)
+
+ for pkg in shlib_pkgs:
+ private_libs = d.getVar('PRIVATE_LIBS:' + pkg) or d.getVar('PRIVATE_LIBS') or ""
+ private_libs = private_libs.split()
+ needs_ldconfig = False
+ bb.debug(2, "calculating shlib provides for %s" % pkg)
+
+ pkgver = d.getVar('PKGV:' + pkg)
+ if not pkgver:
+ pkgver = d.getVar('PV_' + pkg)
+ if not pkgver:
+ pkgver = ver
+
+ needed[pkg] = set()
+ sonames = set()
+ renames = []
+ linuxlist = []
+ for file in pkgfiles[pkg]:
+ soname = None
+ if cpath.islink(file):
+ continue
+ if hostos == "darwin" or hostos == "darwin8":
+ darwin_so(file, needed, sonames, renames, pkgver)
+ elif hostos.startswith("mingw"):
+ mingw_dll(file, needed, sonames, renames, pkgver)
+ elif os.access(file, os.X_OK) or lib_re.match(file):
+ linuxlist.append(file)
+
+ if linuxlist:
+ results = oe.utils.multiprocess_launch(linux_so, linuxlist, d, extraargs=(pkg, pkgver, d))
+ for r in results:
+ ldconfig = r[0]
+ needed[pkg] |= r[1]
+ sonames |= r[2]
+ renames.extend(r[3])
+ needs_ldconfig = needs_ldconfig or ldconfig
+
+ for (old, new) in renames:
+ bb.note("Renaming %s to %s" % (old, new))
+ bb.utils.rename(old, new)
+ pkgfiles[pkg].remove(old)
+
+ shlibs_file = os.path.join(shlibswork_dir, pkg + ".list")
+ if len(sonames):
+ with open(shlibs_file, 'w') as fd:
+ for s in sorted(sonames):
+ if s[0] in shlib_provider and s[1] in shlib_provider[s[0]]:
+ (old_pkg, old_pkgver) = shlib_provider[s[0]][s[1]]
+ if old_pkg != pkg:
+ bb.warn('%s-%s was registered as shlib provider for %s, changing it to %s-%s because it was built later' % (old_pkg, old_pkgver, s[0], pkg, pkgver))
+ bb.debug(1, 'registering %s-%s as shlib provider for %s' % (pkg, pkgver, s[0]))
+ fd.write(s[0] + ':' + s[1] + ':' + s[2] + '\n')
+ if s[0] not in shlib_provider:
+ shlib_provider[s[0]] = {}
+ shlib_provider[s[0]][s[1]] = (pkg, pkgver)
+ if needs_ldconfig:
+ bb.debug(1, 'adding ldconfig call to postinst for %s' % pkg)
+ postinst = d.getVar('pkg_postinst:%s' % pkg)
+ if not postinst:
+ postinst = '#!/bin/sh\n'
+ postinst += d.getVar('ldconfig_postinst_fragment')
+ d.setVar('pkg_postinst:%s' % pkg, postinst)
+ bb.debug(1, 'LIBNAMES: pkg %s sonames %s' % (pkg, sonames))
+
+ assumed_libs = d.getVar('ASSUME_SHLIBS')
+ if assumed_libs:
+ libdir = d.getVar("libdir")
+ for e in assumed_libs.split():
+ l, dep_pkg = e.split(":")
+ lib_ver = None
+ dep_pkg = dep_pkg.rsplit("_", 1)
+ if len(dep_pkg) == 2:
+ lib_ver = dep_pkg[1]
+ dep_pkg = dep_pkg[0]
+ if l not in shlib_provider:
+ shlib_provider[l] = {}
+ shlib_provider[l][libdir] = (dep_pkg, lib_ver)
+
+ libsearchpath = [d.getVar('libdir'), d.getVar('base_libdir')]
+
+ for pkg in shlib_pkgs:
+ bb.debug(2, "calculating shlib requirements for %s" % pkg)
+
+ private_libs = d.getVar('PRIVATE_LIBS:' + pkg) or d.getVar('PRIVATE_LIBS') or ""
+ private_libs = private_libs.split()
+
+ deps = list()
+ for n in needed[pkg]:
+ # if n is in private libraries, don't try to search provider for it
+ # this could cause problem in case some abc.bb provides private
+ # /opt/abc/lib/libfoo.so.1 and contains /usr/bin/abc depending on system library libfoo.so.1
+ # but skipping it is still better alternative than providing own
+ # version and then adding runtime dependency for the same system library
+ if private_libs and len([i for i in private_libs if fnmatch.fnmatch(n[0], i)]) > 0:
+ bb.debug(2, '%s: Dependency %s covered by PRIVATE_LIBS' % (pkg, n[0]))
+ continue
+ if n[0] in shlib_provider.keys():
+ shlib_provider_map = shlib_provider[n[0]]
+ matches = set()
+ for p in itertools.chain(list(n[2]), sorted(shlib_provider_map.keys()), libsearchpath):
+ if p in shlib_provider_map:
+ matches.add(p)
+ if len(matches) > 1:
+ matchpkgs = ', '.join([shlib_provider_map[match][0] for match in matches])
+ bb.error("%s: Multiple shlib providers for %s: %s (used by files: %s)" % (pkg, n[0], matchpkgs, n[1]))
+ elif len(matches) == 1:
+ (dep_pkg, ver_needed) = shlib_provider_map[matches.pop()]
+
+ bb.debug(2, '%s: Dependency %s requires package %s (used by files: %s)' % (pkg, n[0], dep_pkg, n[1]))
+
+ if dep_pkg == pkg:
+ continue
+
+ if ver_needed:
+ dep = "%s (>= %s)" % (dep_pkg, ver_needed)
+ else:
+ dep = dep_pkg
+ if not dep in deps:
+ deps.append(dep)
+ continue
+ bb.note("Couldn't find shared library provider for %s, used by files: %s" % (n[0], n[1]))
+
+ deps_file = os.path.join(pkgdest, pkg + ".shlibdeps")
+ if os.path.exists(deps_file):
+ os.remove(deps_file)
+ if deps:
+ with open(deps_file, 'w') as fd:
+ for dep in sorted(deps):
+ fd.write(dep + '\n')
+
+def process_pkgconfig(pkgfiles, d):
+ packages = d.getVar('PACKAGES')
+ workdir = d.getVar('WORKDIR')
+ pkgdest = d.getVar('PKGDEST')
+
+ shlibs_dirs = d.getVar('SHLIBSDIRS').split()
+ shlibswork_dir = d.getVar('SHLIBSWORKDIR')
+
+ pc_re = re.compile(r'(.*)\.pc$')
+ var_re = re.compile(r'(.*)=(.*)')
+ field_re = re.compile(r'(.*): (.*)')
+
+ pkgconfig_provided = {}
+ pkgconfig_needed = {}
+ for pkg in packages.split():
+ pkgconfig_provided[pkg] = []
+ pkgconfig_needed[pkg] = []
+ for file in sorted(pkgfiles[pkg]):
+ m = pc_re.match(file)
+ if m:
+ pd = bb.data.init()
+ name = m.group(1)
+ pkgconfig_provided[pkg].append(os.path.basename(name))
+ if not os.access(file, os.R_OK):
+ continue
+ with open(file, 'r') as f:
+ lines = f.readlines()
+ for l in lines:
+ m = var_re.match(l)
+ if m:
+ name = m.group(1)
+ val = m.group(2)
+ pd.setVar(name, pd.expand(val))
+ continue
+ m = field_re.match(l)
+ if m:
+ hdr = m.group(1)
+ exp = pd.expand(m.group(2))
+ if hdr == 'Requires':
+ pkgconfig_needed[pkg] += exp.replace(',', ' ').split()
+
+ for pkg in packages.split():
+ pkgs_file = os.path.join(shlibswork_dir, pkg + ".pclist")
+ if pkgconfig_provided[pkg] != []:
+ with open(pkgs_file, 'w') as f:
+ for p in sorted(pkgconfig_provided[pkg]):
+ f.write('%s\n' % p)
+
+ # Go from least to most specific since the last one found wins
+ for dir in reversed(shlibs_dirs):
+ if not os.path.exists(dir):
+ continue
+ for file in sorted(os.listdir(dir)):
+ m = re.match(r'^(.*)\.pclist$', file)
+ if m:
+ pkg = m.group(1)
+ with open(os.path.join(dir, file)) as fd:
+ lines = fd.readlines()
+ pkgconfig_provided[pkg] = []
+ for l in lines:
+ pkgconfig_provided[pkg].append(l.rstrip())
+
+ for pkg in packages.split():
+ deps = []
+ for n in pkgconfig_needed[pkg]:
+ found = False
+ for k in pkgconfig_provided.keys():
+ if n in pkgconfig_provided[k]:
+ if k != pkg and not (k in deps):
+ deps.append(k)
+ found = True
+ if found == False:
+ bb.note("couldn't find pkgconfig module '%s' in any package" % n)
+ deps_file = os.path.join(pkgdest, pkg + ".pcdeps")
+ if len(deps):
+ with open(deps_file, 'w') as fd:
+ for dep in deps:
+ fd.write(dep + '\n')
+
+def read_libdep_files(d):
+ pkglibdeps = {}
+ packages = d.getVar('PACKAGES').split()
+ for pkg in packages:
+ pkglibdeps[pkg] = {}
+ for extension in ".shlibdeps", ".pcdeps", ".clilibdeps":
+ depsfile = d.expand("${PKGDEST}/" + pkg + extension)
+ if os.access(depsfile, os.R_OK):
+ with open(depsfile) as fd:
+ lines = fd.readlines()
+ for l in lines:
+ l.rstrip()
+ deps = bb.utils.explode_dep_versions2(l)
+ for dep in deps:
+ if not dep in pkglibdeps[pkg]:
+ pkglibdeps[pkg][dep] = deps[dep]
+ return pkglibdeps
+
+def process_depchains(pkgfiles, d):
+ """
+ For a given set of prefix and postfix modifiers, make those packages
+ RRECOMMENDS on the corresponding packages for its RDEPENDS.
+
+ Example: If package A depends upon package B, and A's .bb emits an
+ A-dev package, this would make A-dev Recommends: B-dev.
+
+ If only one of a given suffix is specified, it will take the RRECOMMENDS
+ based on the RDEPENDS of *all* other packages. If more than one of a given
+ suffix is specified, its will only use the RDEPENDS of the single parent
+ package.
+ """
+
+ packages = d.getVar('PACKAGES')
+ postfixes = (d.getVar('DEPCHAIN_POST') or '').split()
+ prefixes = (d.getVar('DEPCHAIN_PRE') or '').split()
+
+ def pkg_adddeprrecs(pkg, base, suffix, getname, depends, d):
+
+ #bb.note('depends for %s is %s' % (base, depends))
+ rreclist = bb.utils.explode_dep_versions2(d.getVar('RRECOMMENDS:' + pkg) or "")
+
+ for depend in sorted(depends):
+ if depend.find('-native') != -1 or depend.find('-cross') != -1 or depend.startswith('virtual/'):
+ #bb.note("Skipping %s" % depend)
+ continue
+ if depend.endswith('-dev'):
+ depend = depend[:-4]
+ if depend.endswith('-dbg'):
+ depend = depend[:-4]
+ pkgname = getname(depend, suffix)
+ #bb.note("Adding %s for %s" % (pkgname, depend))
+ if pkgname not in rreclist and pkgname != pkg:
+ rreclist[pkgname] = []
+
+ #bb.note('setting: RRECOMMENDS:%s=%s' % (pkg, ' '.join(rreclist)))
+ d.setVar('RRECOMMENDS:%s' % pkg, bb.utils.join_deps(rreclist, commasep=False))
+
+ def pkg_addrrecs(pkg, base, suffix, getname, rdepends, d):
+
+ #bb.note('rdepends for %s is %s' % (base, rdepends))
+ rreclist = bb.utils.explode_dep_versions2(d.getVar('RRECOMMENDS:' + pkg) or "")
+
+ for depend in sorted(rdepends):
+ if depend.find('virtual-locale-') != -1:
+ #bb.note("Skipping %s" % depend)
+ continue
+ if depend.endswith('-dev'):
+ depend = depend[:-4]
+ if depend.endswith('-dbg'):
+ depend = depend[:-4]
+ pkgname = getname(depend, suffix)
+ #bb.note("Adding %s for %s" % (pkgname, depend))
+ if pkgname not in rreclist and pkgname != pkg:
+ rreclist[pkgname] = []
+
+ #bb.note('setting: RRECOMMENDS:%s=%s' % (pkg, ' '.join(rreclist)))
+ d.setVar('RRECOMMENDS:%s' % pkg, bb.utils.join_deps(rreclist, commasep=False))
+
+ def add_dep(list, dep):
+ if dep not in list:
+ list.append(dep)
+
+ depends = []
+ for dep in bb.utils.explode_deps(d.getVar('DEPENDS') or ""):
+ add_dep(depends, dep)
+
+ rdepends = []
+ for pkg in packages.split():
+ for dep in bb.utils.explode_deps(d.getVar('RDEPENDS:' + pkg) or ""):
+ add_dep(rdepends, dep)
+
+ #bb.note('rdepends is %s' % rdepends)
+
+ def post_getname(name, suffix):
+ return '%s%s' % (name, suffix)
+ def pre_getname(name, suffix):
+ return '%s%s' % (suffix, name)
+
+ pkgs = {}
+ for pkg in packages.split():
+ for postfix in postfixes:
+ if pkg.endswith(postfix):
+ if not postfix in pkgs:
+ pkgs[postfix] = {}
+ pkgs[postfix][pkg] = (pkg[:-len(postfix)], post_getname)
+
+ for prefix in prefixes:
+ if pkg.startswith(prefix):
+ if not prefix in pkgs:
+ pkgs[prefix] = {}
+ pkgs[prefix][pkg] = (pkg[:-len(prefix)], pre_getname)
+
+ if "-dbg" in pkgs:
+ pkglibdeps = read_libdep_files(d)
+ pkglibdeplist = []
+ for pkg in pkglibdeps:
+ for k in pkglibdeps[pkg]:
+ add_dep(pkglibdeplist, k)
+ dbgdefaultdeps = ((d.getVar('DEPCHAIN_DBGDEFAULTDEPS') == '1') or (bb.data.inherits_class('packagegroup', d)))
+
+ for suffix in pkgs:
+ for pkg in pkgs[suffix]:
+ if d.getVarFlag('RRECOMMENDS:' + pkg, 'nodeprrecs'):
+ continue
+ (base, func) = pkgs[suffix][pkg]
+ if suffix == "-dev":
+ pkg_adddeprrecs(pkg, base, suffix, func, depends, d)
+ elif suffix == "-dbg":
+ if not dbgdefaultdeps:
+ pkg_addrrecs(pkg, base, suffix, func, pkglibdeplist, d)
+ continue
+ if len(pkgs[suffix]) == 1:
+ pkg_addrrecs(pkg, base, suffix, func, rdepends, d)
+ else:
+ rdeps = []
+ for dep in bb.utils.explode_deps(d.getVar('RDEPENDS:' + base) or ""):
+ add_dep(rdeps, dep)
+ pkg_addrrecs(pkg, base, suffix, func, rdeps, d)
+
diff --git a/meta/lib/oe/package_manager.py b/meta/lib/oe/package_manager.py
deleted file mode 100644
index 47f6831f98..0000000000
--- a/meta/lib/oe/package_manager.py
+++ /dev/null
@@ -1,2276 +0,0 @@
-from abc import ABCMeta, abstractmethod
-import os
-import glob
-import subprocess
-import shutil
-import multiprocessing
-import re
-import collections
-import bb
-import tempfile
-import oe.utils
-import string
-from oe.gpg_sign import get_signer
-
-# this can be used by all PM backends to create the index files in parallel
-def create_index(arg):
- index_cmd = arg
-
- try:
- bb.note("Executing '%s' ..." % index_cmd)
- result = subprocess.check_output(index_cmd, stderr=subprocess.STDOUT, shell=True).decode("utf-8")
- except subprocess.CalledProcessError as e:
- return("Index creation command '%s' failed with return code %d:\n%s" %
- (e.cmd, e.returncode, e.output.decode("utf-8")))
-
- if result:
- bb.note(result)
-
- return None
-
-"""
-This method parse the output from the package managerand return
-a dictionary with the information of the packages. This is used
-when the packages are in deb or ipk format.
-"""
-def opkg_query(cmd_output):
- verregex = re.compile(' \([=<>]* [^ )]*\)')
- output = dict()
- pkg = ""
- arch = ""
- ver = ""
- filename = ""
- dep = []
- pkgarch = ""
- for line in cmd_output.splitlines():
- line = line.rstrip()
- if ':' in line:
- if line.startswith("Package: "):
- pkg = line.split(": ")[1]
- elif line.startswith("Architecture: "):
- arch = line.split(": ")[1]
- elif line.startswith("Version: "):
- ver = line.split(": ")[1]
- elif line.startswith("File: ") or line.startswith("Filename:"):
- filename = line.split(": ")[1]
- if "/" in filename:
- filename = os.path.basename(filename)
- elif line.startswith("Depends: "):
- depends = verregex.sub('', line.split(": ")[1])
- for depend in depends.split(", "):
- dep.append(depend)
- elif line.startswith("Recommends: "):
- recommends = verregex.sub('', line.split(": ")[1])
- for recommend in recommends.split(", "):
- dep.append("%s [REC]" % recommend)
- elif line.startswith("PackageArch: "):
- pkgarch = line.split(": ")[1]
-
- # When there is a blank line save the package information
- elif not line:
- # IPK doesn't include the filename
- if not filename:
- filename = "%s_%s_%s.ipk" % (pkg, ver, arch)
- if pkg:
- output[pkg] = {"arch":arch, "ver":ver,
- "filename":filename, "deps": dep, "pkgarch":pkgarch }
- pkg = ""
- arch = ""
- ver = ""
- filename = ""
- dep = []
- pkgarch = ""
-
- if pkg:
- if not filename:
- filename = "%s_%s_%s.ipk" % (pkg, ver, arch)
- output[pkg] = {"arch":arch, "ver":ver,
- "filename":filename, "deps": dep }
-
- return output
-
-
-class Indexer(object, metaclass=ABCMeta):
- def __init__(self, d, deploy_dir):
- self.d = d
- self.deploy_dir = deploy_dir
-
- @abstractmethod
- def write_index(self):
- pass
-
-
-class RpmIndexer(Indexer):
- def get_ml_prefix_and_os_list(self, arch_var=None, os_var=None):
- package_archs = collections.OrderedDict()
- target_os = collections.OrderedDict()
-
- if arch_var is not None and os_var is not None:
- package_archs['default'] = self.d.getVar(arch_var, True).split()
- package_archs['default'].reverse()
- target_os['default'] = self.d.getVar(os_var, True).strip()
- else:
- package_archs['default'] = self.d.getVar("PACKAGE_ARCHS", True).split()
- # arch order is reversed. This ensures the -best- match is
- # listed first!
- package_archs['default'].reverse()
- target_os['default'] = self.d.getVar("TARGET_OS", True).strip()
- multilibs = self.d.getVar('MULTILIBS', True) or ""
- for ext in multilibs.split():
- eext = ext.split(':')
- if len(eext) > 1 and eext[0] == 'multilib':
- localdata = bb.data.createCopy(self.d)
- default_tune_key = "DEFAULTTUNE_virtclass-multilib-" + eext[1]
- default_tune = localdata.getVar(default_tune_key, False)
- if default_tune is None:
- default_tune_key = "DEFAULTTUNE_ML_" + eext[1]
- default_tune = localdata.getVar(default_tune_key, False)
- if default_tune:
- localdata.setVar("DEFAULTTUNE", default_tune)
- bb.data.update_data(localdata)
- package_archs[eext[1]] = localdata.getVar('PACKAGE_ARCHS',
- True).split()
- package_archs[eext[1]].reverse()
- target_os[eext[1]] = localdata.getVar("TARGET_OS",
- True).strip()
-
- ml_prefix_list = collections.OrderedDict()
- for mlib in package_archs:
- if mlib == 'default':
- ml_prefix_list[mlib] = package_archs[mlib]
- else:
- ml_prefix_list[mlib] = list()
- for arch in package_archs[mlib]:
- if arch in ['all', 'noarch', 'any']:
- ml_prefix_list[mlib].append(arch)
- else:
- ml_prefix_list[mlib].append(mlib + "_" + arch)
-
- return (ml_prefix_list, target_os)
-
- def write_index(self):
- sdk_pkg_archs = (self.d.getVar('SDK_PACKAGE_ARCHS', True) or "").replace('-', '_').split()
- all_mlb_pkg_archs = (self.d.getVar('ALL_MULTILIB_PACKAGE_ARCHS', True) or "").replace('-', '_').split()
-
- mlb_prefix_list = self.get_ml_prefix_and_os_list()[0]
-
- archs = set()
- for item in mlb_prefix_list:
- archs = archs.union(set(i.replace('-', '_') for i in mlb_prefix_list[item]))
-
- if len(archs) == 0:
- archs = archs.union(set(all_mlb_pkg_archs))
-
- archs = archs.union(set(sdk_pkg_archs))
-
- rpm_createrepo = bb.utils.which(os.getenv('PATH'), "createrepo")
- if self.d.getVar('PACKAGE_FEED_SIGN', True) == '1':
- signer = get_signer(self.d, self.d.getVar('PACKAGE_FEED_GPG_BACKEND', True))
- else:
- signer = None
- index_cmds = []
- repomd_files = []
- rpm_dirs_found = False
- for arch in archs:
- dbpath = os.path.join(self.d.getVar('WORKDIR', True), 'rpmdb', arch)
- if os.path.exists(dbpath):
- bb.utils.remove(dbpath, True)
- arch_dir = os.path.join(self.deploy_dir, arch)
- if not os.path.isdir(arch_dir):
- continue
-
- index_cmds.append("%s --dbpath %s --update -q %s" % \
- (rpm_createrepo, dbpath, arch_dir))
- repomd_files.append(os.path.join(arch_dir, 'repodata', 'repomd.xml'))
-
- rpm_dirs_found = True
-
- if not rpm_dirs_found:
- bb.note("There are no packages in %s" % self.deploy_dir)
- return
-
- # Create repodata
- result = oe.utils.multiprocess_exec(index_cmds, create_index)
- if result:
- bb.fatal('%s' % ('\n'.join(result)))
- # Sign repomd
- if signer:
- for repomd in repomd_files:
- feed_sig_type = self.d.getVar('PACKAGE_FEED_GPG_SIGNATURE_TYPE', True)
- is_ascii_sig = (feed_sig_type.upper() != "BIN")
- signer.detach_sign(repomd,
- self.d.getVar('PACKAGE_FEED_GPG_NAME', True),
- self.d.getVar('PACKAGE_FEED_GPG_PASSPHRASE_FILE', True),
- armor=is_ascii_sig)
-
-
-class OpkgIndexer(Indexer):
- def write_index(self):
- arch_vars = ["ALL_MULTILIB_PACKAGE_ARCHS",
- "SDK_PACKAGE_ARCHS",
- "MULTILIB_ARCHS"]
-
- opkg_index_cmd = bb.utils.which(os.getenv('PATH'), "opkg-make-index")
- if self.d.getVar('PACKAGE_FEED_SIGN', True) == '1':
- signer = get_signer(self.d, self.d.getVar('PACKAGE_FEED_GPG_BACKEND', True))
- else:
- signer = None
-
- if not os.path.exists(os.path.join(self.deploy_dir, "Packages")):
- open(os.path.join(self.deploy_dir, "Packages"), "w").close()
-
- index_cmds = set()
- index_sign_files = set()
- for arch_var in arch_vars:
- archs = self.d.getVar(arch_var, True)
- if archs is None:
- continue
-
- for arch in archs.split():
- pkgs_dir = os.path.join(self.deploy_dir, arch)
- pkgs_file = os.path.join(pkgs_dir, "Packages")
-
- if not os.path.isdir(pkgs_dir):
- continue
-
- if not os.path.exists(pkgs_file):
- open(pkgs_file, "w").close()
-
- index_cmds.add('%s -r %s -p %s -m %s' %
- (opkg_index_cmd, pkgs_file, pkgs_file, pkgs_dir))
-
- index_sign_files.add(pkgs_file)
-
- if len(index_cmds) == 0:
- bb.note("There are no packages in %s!" % self.deploy_dir)
- return
-
- result = oe.utils.multiprocess_exec(index_cmds, create_index)
- if result:
- bb.fatal('%s' % ('\n'.join(result)))
-
- if signer:
- feed_sig_type = self.d.getVar('PACKAGE_FEED_GPG_SIGNATURE_TYPE', True)
- is_ascii_sig = (feed_sig_type.upper() != "BIN")
- for f in index_sign_files:
- signer.detach_sign(f,
- self.d.getVar('PACKAGE_FEED_GPG_NAME', True),
- self.d.getVar('PACKAGE_FEED_GPG_PASSPHRASE_FILE', True),
- armor=is_ascii_sig)
-
-
-class DpkgIndexer(Indexer):
- def _create_configs(self):
- bb.utils.mkdirhier(self.apt_conf_dir)
- bb.utils.mkdirhier(os.path.join(self.apt_conf_dir, "lists", "partial"))
- bb.utils.mkdirhier(os.path.join(self.apt_conf_dir, "apt.conf.d"))
- bb.utils.mkdirhier(os.path.join(self.apt_conf_dir, "preferences.d"))
-
- with open(os.path.join(self.apt_conf_dir, "preferences"),
- "w") as prefs_file:
- pass
- with open(os.path.join(self.apt_conf_dir, "sources.list"),
- "w+") as sources_file:
- pass
-
- with open(self.apt_conf_file, "w") as apt_conf:
- with open(os.path.join(self.d.expand("${STAGING_ETCDIR_NATIVE}"),
- "apt", "apt.conf.sample")) as apt_conf_sample:
- for line in apt_conf_sample.read().split("\n"):
- line = re.sub("#ROOTFS#", "/dev/null", line)
- line = re.sub("#APTCONF#", self.apt_conf_dir, line)
- apt_conf.write(line + "\n")
-
- def write_index(self):
- self.apt_conf_dir = os.path.join(self.d.expand("${APTCONF_TARGET}"),
- "apt-ftparchive")
- self.apt_conf_file = os.path.join(self.apt_conf_dir, "apt.conf")
- self._create_configs()
-
- os.environ['APT_CONFIG'] = self.apt_conf_file
-
- pkg_archs = self.d.getVar('PACKAGE_ARCHS', True)
- if pkg_archs is not None:
- arch_list = pkg_archs.split()
- sdk_pkg_archs = self.d.getVar('SDK_PACKAGE_ARCHS', True)
- if sdk_pkg_archs is not None:
- for a in sdk_pkg_archs.split():
- if a not in pkg_archs:
- arch_list.append(a)
-
- all_mlb_pkg_arch_list = (self.d.getVar('ALL_MULTILIB_PACKAGE_ARCHS', True) or "").split()
- arch_list.extend(arch for arch in all_mlb_pkg_arch_list if arch not in arch_list)
-
- apt_ftparchive = bb.utils.which(os.getenv('PATH'), "apt-ftparchive")
- gzip = bb.utils.which(os.getenv('PATH'), "gzip")
-
- index_cmds = []
- deb_dirs_found = False
- for arch in arch_list:
- arch_dir = os.path.join(self.deploy_dir, arch)
- if not os.path.isdir(arch_dir):
- continue
-
- cmd = "cd %s; PSEUDO_UNLOAD=1 %s packages . > Packages;" % (arch_dir, apt_ftparchive)
-
- cmd += "%s -fc Packages > Packages.gz;" % gzip
-
- with open(os.path.join(arch_dir, "Release"), "w+") as release:
- release.write("Label: %s\n" % arch)
-
- cmd += "PSEUDO_UNLOAD=1 %s release . >> Release" % apt_ftparchive
-
- index_cmds.append(cmd)
-
- deb_dirs_found = True
-
- if not deb_dirs_found:
- bb.note("There are no packages in %s" % self.deploy_dir)
- return
-
- result = oe.utils.multiprocess_exec(index_cmds, create_index)
- if result:
- bb.fatal('%s' % ('\n'.join(result)))
- if self.d.getVar('PACKAGE_FEED_SIGN', True) == '1':
- raise NotImplementedError('Package feed signing not implementd for dpkg')
-
-
-
-class PkgsList(object, metaclass=ABCMeta):
- def __init__(self, d, rootfs_dir):
- self.d = d
- self.rootfs_dir = rootfs_dir
-
- @abstractmethod
- def list_pkgs(self):
- pass
-
-
-class RpmPkgsList(PkgsList):
- def __init__(self, d, rootfs_dir, arch_var=None, os_var=None):
- super(RpmPkgsList, self).__init__(d, rootfs_dir)
-
- self.rpm_cmd = bb.utils.which(os.getenv('PATH'), "rpm")
- self.image_rpmlib = os.path.join(self.rootfs_dir, 'var/lib/rpm')
-
- self.ml_prefix_list, self.ml_os_list = \
- RpmIndexer(d, rootfs_dir).get_ml_prefix_and_os_list(arch_var, os_var)
-
- # Determine rpm version
- cmd = "%s --version" % self.rpm_cmd
- try:
- output = subprocess.check_output(cmd, stderr=subprocess.STDOUT, shell=True).decode("utf-8")
- except subprocess.CalledProcessError as e:
- bb.fatal("Getting rpm version failed. Command '%s' "
- "returned %d:\n%s" % (cmd, e.returncode, e.output.decode("utf-8")))
-
- '''
- Translate the RPM/Smart format names to the OE multilib format names
- '''
- def _pkg_translate_smart_to_oe(self, pkg, arch):
- new_pkg = pkg
- new_arch = arch
- fixed_arch = arch.replace('_', '-')
- found = 0
- for mlib in self.ml_prefix_list:
- for cmp_arch in self.ml_prefix_list[mlib]:
- fixed_cmp_arch = cmp_arch.replace('_', '-')
- if fixed_arch == fixed_cmp_arch:
- if mlib == 'default':
- new_pkg = pkg
- new_arch = cmp_arch
- else:
- new_pkg = mlib + '-' + pkg
- # We need to strip off the ${mlib}_ prefix on the arch
- new_arch = cmp_arch.replace(mlib + '_', '')
-
- # Workaround for bug 3565. Simply look to see if we
- # know of a package with that name, if not try again!
- filename = os.path.join(self.d.getVar('PKGDATA_DIR', True),
- 'runtime-reverse',
- new_pkg)
- if os.path.exists(filename):
- found = 1
- break
-
- if found == 1 and fixed_arch == fixed_cmp_arch:
- break
- #bb.note('%s, %s -> %s, %s' % (pkg, arch, new_pkg, new_arch))
- return new_pkg, new_arch
-
- def _list_pkg_deps(self):
- cmd = [bb.utils.which(os.getenv('PATH'), "rpmresolve"),
- "-t", self.image_rpmlib]
-
- try:
- output = subprocess.check_output(cmd, stderr=subprocess.STDOUT).strip().decode("utf-8")
- except subprocess.CalledProcessError as e:
- bb.fatal("Cannot get the package dependencies. Command '%s' "
- "returned %d:\n%s" % (' '.join(cmd), e.returncode, e.output.decode("utf-8")))
-
- return output
-
- def list_pkgs(self):
- cmd = self.rpm_cmd + ' --root ' + self.rootfs_dir
- cmd += ' -D "_dbpath /var/lib/rpm" -qa'
- cmd += " --qf '[%{NAME} %{ARCH} %{VERSION} %{PACKAGEORIGIN}\n]'"
-
- try:
- # bb.note(cmd)
- tmp_output = subprocess.check_output(cmd, stderr=subprocess.STDOUT, shell=True).strip().decode("utf-8")
- except subprocess.CalledProcessError as e:
- bb.fatal("Cannot get the installed packages list. Command '%s' "
- "returned %d:\n%s" % (cmd, e.returncode, e.output.decode("utf-8")))
-
- output = dict()
- deps = dict()
- dependencies = self._list_pkg_deps()
-
- # Populate deps dictionary for better manipulation
- for line in dependencies.splitlines():
- try:
- pkg, dep = line.split("|")
- if not pkg in deps:
- deps[pkg] = list()
- if not dep in deps[pkg]:
- deps[pkg].append(dep)
- except:
- # Ignore any other lines they're debug or errors
- pass
-
- for line in tmp_output.split('\n'):
- if len(line.strip()) == 0:
- continue
- pkg = line.split()[0]
- arch = line.split()[1]
- ver = line.split()[2]
- dep = deps.get(pkg, [])
-
- # Skip GPG keys
- if pkg == 'gpg-pubkey':
- continue
-
- pkgorigin = line.split()[3]
- new_pkg, new_arch = self._pkg_translate_smart_to_oe(pkg, arch)
-
- output[new_pkg] = {"arch":new_arch, "ver":ver,
- "filename":pkgorigin, "deps":dep}
-
- return output
-
-
-class OpkgPkgsList(PkgsList):
- def __init__(self, d, rootfs_dir, config_file):
- super(OpkgPkgsList, self).__init__(d, rootfs_dir)
-
- self.opkg_cmd = bb.utils.which(os.getenv('PATH'), "opkg")
- self.opkg_args = "-f %s -o %s " % (config_file, rootfs_dir)
- self.opkg_args += self.d.getVar("OPKG_ARGS", True)
-
- def list_pkgs(self, format=None):
- cmd = "%s %s status" % (self.opkg_cmd, self.opkg_args)
-
- # opkg returns success even when it printed some
- # "Collected errors:" report to stderr. Mixing stderr into
- # stdout then leads to random failures later on when
- # parsing the output. To avoid this we need to collect both
- # output streams separately and check for empty stderr.
- p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
- cmd_output, cmd_stderr = p.communicate()
- cmd_output = cmd_output.decode("utf-8")
- cmd_stderr = cmd_stderr.decode("utf-8")
- if p.returncode or cmd_stderr:
- bb.fatal("Cannot get the installed packages list. Command '%s' "
- "returned %d and stderr:\n%s" % (cmd, p.returncode, cmd_stderr))
-
- return opkg_query(cmd_output)
-
-
-class DpkgPkgsList(PkgsList):
-
- def list_pkgs(self):
- cmd = [bb.utils.which(os.getenv('PATH'), "dpkg-query"),
- "--admindir=%s/var/lib/dpkg" % self.rootfs_dir,
- "-W"]
-
- cmd.append("-f=Package: ${Package}\nArchitecture: ${PackageArch}\nVersion: ${Version}\nFile: ${Package}_${Version}_${Architecture}.deb\nDepends: ${Depends}\nRecommends: ${Recommends}\n\n")
-
- try:
- cmd_output = subprocess.check_output(cmd, stderr=subprocess.STDOUT).strip().decode("utf-8")
- except subprocess.CalledProcessError as e:
- bb.fatal("Cannot get the installed packages list. Command '%s' "
- "returned %d:\n%s" % (' '.join(cmd), e.returncode, e.output.decode("utf-8")))
-
- return opkg_query(cmd_output)
-
-
-class PackageManager(object, metaclass=ABCMeta):
- """
- This is an abstract class. Do not instantiate this directly.
- """
-
- def __init__(self, d):
- self.d = d
- self.deploy_dir = None
- self.deploy_lock = None
- self.feed_uris = self.d.getVar('PACKAGE_FEED_URIS', True) or ""
- self.feed_base_paths = self.d.getVar('PACKAGE_FEED_BASE_PATHS', True) or ""
- self.feed_archs = self.d.getVar('PACKAGE_FEED_ARCHS', True)
-
- """
- Update the package manager package database.
- """
- @abstractmethod
- def update(self):
- pass
-
- """
- Install a list of packages. 'pkgs' is a list object. If 'attempt_only' is
- True, installation failures are ignored.
- """
- @abstractmethod
- def install(self, pkgs, attempt_only=False):
- pass
-
- """
- Remove a list of packages. 'pkgs' is a list object. If 'with_dependencies'
- is False, the any dependencies are left in place.
- """
- @abstractmethod
- def remove(self, pkgs, with_dependencies=True):
- pass
-
- """
- This function creates the index files
- """
- @abstractmethod
- def write_index(self):
- pass
-
- @abstractmethod
- def remove_packaging_data(self):
- pass
-
- @abstractmethod
- def list_installed(self):
- pass
-
- @abstractmethod
- def insert_feeds_uris(self):
- pass
-
- """
- Install complementary packages based upon the list of currently installed
- packages e.g. locales, *-dev, *-dbg, etc. This will only attempt to install
- these packages, if they don't exist then no error will occur. Note: every
- backend needs to call this function explicitly after the normal package
- installation
- """
- def install_complementary(self, globs=None):
- # we need to write the list of installed packages to a file because the
- # oe-pkgdata-util reads it from a file
- installed_pkgs_file = os.path.join(self.d.getVar('WORKDIR', True),
- "installed_pkgs.txt")
- with open(installed_pkgs_file, "w+") as installed_pkgs:
- pkgs = self.list_installed()
- output = oe.utils.format_pkg_list(pkgs, "arch")
- installed_pkgs.write(output)
-
- if globs is None:
- globs = self.d.getVar('IMAGE_INSTALL_COMPLEMENTARY', True)
- split_linguas = set()
-
- for translation in self.d.getVar('IMAGE_LINGUAS', True).split():
- split_linguas.add(translation)
- split_linguas.add(translation.split('-')[0])
-
- split_linguas = sorted(split_linguas)
-
- for lang in split_linguas:
- globs += " *-locale-%s" % lang
-
- if globs is None:
- return
-
- cmd = [bb.utils.which(os.getenv('PATH'), "oe-pkgdata-util"),
- "-p", self.d.getVar('PKGDATA_DIR', True), "glob", installed_pkgs_file,
- globs]
- exclude = self.d.getVar('PACKAGE_EXCLUDE_COMPLEMENTARY', True)
- if exclude:
- cmd.extend(['-x', exclude])
- try:
- bb.note("Installing complementary packages ...")
- bb.note('Running %s' % cmd)
- complementary_pkgs = subprocess.check_output(cmd, stderr=subprocess.STDOUT).decode("utf-8")
- except subprocess.CalledProcessError as e:
- bb.fatal("Could not compute complementary packages list. Command "
- "'%s' returned %d:\n%s" %
- (' '.join(cmd), e.returncode, e.output.decode("utf-8")))
- self.install(complementary_pkgs.split(), attempt_only=True)
- os.remove(installed_pkgs_file)
-
- def deploy_dir_lock(self):
- if self.deploy_dir is None:
- raise RuntimeError("deploy_dir is not set!")
-
- lock_file_name = os.path.join(self.deploy_dir, "deploy.lock")
-
- self.deploy_lock = bb.utils.lockfile(lock_file_name)
-
- def deploy_dir_unlock(self):
- if self.deploy_lock is None:
- return
-
- bb.utils.unlockfile(self.deploy_lock)
-
- self.deploy_lock = None
-
- """
- Construct URIs based on the following pattern: uri/base_path where 'uri'
- and 'base_path' correspond to each element of the corresponding array
- argument leading to len(uris) x len(base_paths) elements on the returned
- array
- """
- def construct_uris(self, uris, base_paths):
- def _append(arr1, arr2, sep='/'):
- res = []
- narr1 = [a.rstrip(sep) for a in arr1]
- narr2 = [a.rstrip(sep).lstrip(sep) for a in arr2]
- for a1 in narr1:
- if arr2:
- for a2 in narr2:
- res.append("%s%s%s" % (a1, sep, a2))
- else:
- res.append(a1)
- return res
- return _append(uris, base_paths)
-
-class RpmPM(PackageManager):
- def __init__(self,
- d,
- target_rootfs,
- target_vendor,
- task_name='target',
- providename=None,
- arch_var=None,
- os_var=None):
- super(RpmPM, self).__init__(d)
- self.target_rootfs = target_rootfs
- self.target_vendor = target_vendor
- self.task_name = task_name
- self.providename = providename
- self.fullpkglist = list()
- self.deploy_dir = self.d.getVar('DEPLOY_DIR_RPM', True)
- self.etcrpm_dir = os.path.join(self.target_rootfs, "etc/rpm")
- self.install_dir_name = "oe_install"
- self.install_dir_path = os.path.join(self.target_rootfs, self.install_dir_name)
- self.rpm_cmd = bb.utils.which(os.getenv('PATH'), "rpm")
- self.smart_cmd = bb.utils.which(os.getenv('PATH'), "smart")
- # 0 = default, only warnings
- # 1 = --log-level=info (includes information about executing scriptlets and their output)
- # 2 = --log-level=debug
- # 3 = --log-level=debug plus dumps of scriplet content and command invocation
- self.debug_level = int(d.getVar('ROOTFS_RPM_DEBUG', True) or "0")
- self.smart_opt = "--log-level=%s --data-dir=%s" % \
- ("warning" if self.debug_level == 0 else
- "info" if self.debug_level == 1 else
- "debug",
- os.path.join(target_rootfs, 'var/lib/smart'))
- self.scriptlet_wrapper = self.d.expand('${WORKDIR}/scriptlet_wrapper')
- self.solution_manifest = self.d.expand('${T}/saved/%s_solution' %
- self.task_name)
- self.saved_rpmlib = self.d.expand('${T}/saved/%s' % self.task_name)
- self.image_rpmlib = os.path.join(self.target_rootfs, 'var/lib/rpm')
-
- if not os.path.exists(self.d.expand('${T}/saved')):
- bb.utils.mkdirhier(self.d.expand('${T}/saved'))
-
- self.indexer = RpmIndexer(self.d, self.deploy_dir)
- self.pkgs_list = RpmPkgsList(self.d, self.target_rootfs, arch_var, os_var)
-
- self.ml_prefix_list, self.ml_os_list = self.indexer.get_ml_prefix_and_os_list(arch_var, os_var)
-
- def insert_feeds_uris(self):
- if self.feed_uris == "":
- return
-
- arch_list = []
- if self.feed_archs is not None:
- # User define feed architectures
- arch_list = self.feed_archs.split()
- else:
- # List must be prefered to least preferred order
- default_platform_extra = list()
- platform_extra = list()
- bbextendvariant = self.d.getVar('BBEXTENDVARIANT', True) or ""
- for mlib in self.ml_os_list:
- for arch in self.ml_prefix_list[mlib]:
- plt = arch.replace('-', '_') + '-.*-' + self.ml_os_list[mlib]
- if mlib == bbextendvariant:
- if plt not in default_platform_extra:
- default_platform_extra.append(plt)
- else:
- if plt not in platform_extra:
- platform_extra.append(plt)
- platform_extra = default_platform_extra + platform_extra
-
- for canonical_arch in platform_extra:
- arch = canonical_arch.split('-')[0]
- if not os.path.exists(os.path.join(self.deploy_dir, arch)):
- continue
- arch_list.append(arch)
-
- feed_uris = self.construct_uris(self.feed_uris.split(), self.feed_base_paths.split())
-
- uri_iterator = 0
- channel_priority = 10 + 5 * len(feed_uris) * (len(arch_list) if arch_list else 1)
-
- for uri in feed_uris:
- if arch_list:
- for arch in arch_list:
- bb.note('Adding Smart channel url%d%s (%s)' %
- (uri_iterator, arch, channel_priority))
- self._invoke_smart('channel --add url%d-%s type=rpm-md baseurl=%s/%s -y'
- % (uri_iterator, arch, uri, arch))
- self._invoke_smart('channel --set url%d-%s priority=%d' %
- (uri_iterator, arch, channel_priority))
- channel_priority -= 5
- else:
- bb.note('Adding Smart channel url%d (%s)' %
- (uri_iterator, channel_priority))
- self._invoke_smart('channel --add url%d type=rpm-md baseurl=%s -y'
- % (uri_iterator, uri))
- self._invoke_smart('channel --set url%d priority=%d' %
- (uri_iterator, channel_priority))
- channel_priority -= 5
-
- uri_iterator += 1
-
- '''
- Create configs for rpm and smart, and multilib is supported
- '''
- def create_configs(self):
- target_arch = self.d.getVar('TARGET_ARCH', True)
- platform = '%s%s-%s' % (target_arch.replace('-', '_'),
- self.target_vendor,
- self.ml_os_list['default'])
-
- # List must be prefered to least preferred order
- default_platform_extra = list()
- platform_extra = list()
- bbextendvariant = self.d.getVar('BBEXTENDVARIANT', True) or ""
- for mlib in self.ml_os_list:
- for arch in self.ml_prefix_list[mlib]:
- plt = arch.replace('-', '_') + '-.*-' + self.ml_os_list[mlib]
- if mlib == bbextendvariant:
- if plt not in default_platform_extra:
- default_platform_extra.append(plt)
- else:
- if plt not in platform_extra:
- platform_extra.append(plt)
- platform_extra = default_platform_extra + platform_extra
-
- self._create_configs(platform, platform_extra)
-
- def _invoke_smart(self, args):
- cmd = "%s %s %s" % (self.smart_cmd, self.smart_opt, args)
- # bb.note(cmd)
- try:
- complementary_pkgs = subprocess.check_output(cmd,
- stderr=subprocess.STDOUT,
- shell=True).decode("utf-8")
- # bb.note(complementary_pkgs)
- return complementary_pkgs
- except subprocess.CalledProcessError as e:
- bb.fatal("Could not invoke smart. Command "
- "'%s' returned %d:\n%s" % (cmd, e.returncode, e.output.decode("utf-8")))
-
- def _search_pkg_name_in_feeds(self, pkg, feed_archs):
- for arch in feed_archs:
- arch = arch.replace('-', '_')
- regex_match = re.compile(r"^%s-[^-]*-[^-]*@%s$" % \
- (re.escape(pkg), re.escape(arch)))
- for p in self.fullpkglist:
- if regex_match.match(p) is not None:
- # First found is best match
- # bb.note('%s -> %s' % (pkg, pkg + '@' + arch))
- return pkg + '@' + arch
-
- # Search provides if not found by pkgname.
- bb.note('Not found %s by name, searching provides ...' % pkg)
- cmd = "%s %s query --provides %s --show-format='$name-$version'" % \
- (self.smart_cmd, self.smart_opt, pkg)
- cmd += " | sed -ne 's/ *Provides://p'"
- bb.note('cmd: %s' % cmd)
- output = subprocess.check_output(cmd, stderr=subprocess.STDOUT, shell=True).decode("utf-8")
- # Found a provider
- if output:
- bb.note('Found providers for %s: %s' % (pkg, output))
- for p in output.split():
- for arch in feed_archs:
- arch = arch.replace('-', '_')
- if p.rstrip().endswith('@' + arch):
- return p
-
- return ""
-
- '''
- Translate the OE multilib format names to the RPM/Smart format names
- It searched the RPM/Smart format names in probable multilib feeds first,
- and then searched the default base feed.
- '''
- def _pkg_translate_oe_to_smart(self, pkgs, attempt_only=False):
- new_pkgs = list()
-
- for pkg in pkgs:
- new_pkg = pkg
- # Search new_pkg in probable multilibs first
- for mlib in self.ml_prefix_list:
- # Jump the default archs
- if mlib == 'default':
- continue
-
- subst = pkg.replace(mlib + '-', '')
- # if the pkg in this multilib feed
- if subst != pkg:
- feed_archs = self.ml_prefix_list[mlib]
- new_pkg = self._search_pkg_name_in_feeds(subst, feed_archs)
- if not new_pkg:
- # Failed to translate, package not found!
- err_msg = '%s not found in the %s feeds (%s).\n' % \
- (pkg, mlib, " ".join(feed_archs))
- if not attempt_only:
- err_msg += " ".join(self.fullpkglist)
- bb.fatal(err_msg)
- bb.warn(err_msg)
- else:
- new_pkgs.append(new_pkg)
-
- break
-
- # Apparently not a multilib package...
- if pkg == new_pkg:
- # Search new_pkg in default archs
- default_archs = self.ml_prefix_list['default']
- new_pkg = self._search_pkg_name_in_feeds(pkg, default_archs)
- if not new_pkg:
- err_msg = '%s not found in the base feeds (%s).\n' % \
- (pkg, ' '.join(default_archs))
- if not attempt_only:
- err_msg += " ".join(self.fullpkglist)
- bb.fatal(err_msg)
- bb.warn(err_msg)
- else:
- new_pkgs.append(new_pkg)
-
- return new_pkgs
-
- def _create_configs(self, platform, platform_extra):
- # Setup base system configuration
- bb.note("configuring RPM platform settings")
-
- # Configure internal RPM environment when using Smart
- os.environ['RPM_ETCRPM'] = self.etcrpm_dir
- bb.utils.mkdirhier(self.etcrpm_dir)
-
- # Setup temporary directory -- install...
- if os.path.exists(self.install_dir_path):
- bb.utils.remove(self.install_dir_path, True)
- bb.utils.mkdirhier(os.path.join(self.install_dir_path, 'tmp'))
-
- channel_priority = 5
- platform_dir = os.path.join(self.etcrpm_dir, "platform")
- sdkos = self.d.getVar("SDK_OS", True)
- with open(platform_dir, "w+") as platform_fd:
- platform_fd.write(platform + '\n')
- for pt in platform_extra:
- channel_priority += 5
- if sdkos:
- tmp = re.sub("-%s$" % sdkos, "-%s\n" % sdkos, pt)
- tmp = re.sub("-linux.*$", "-linux.*\n", tmp)
- platform_fd.write(tmp)
-
- # Tell RPM that the "/" directory exist and is available
- bb.note("configuring RPM system provides")
- sysinfo_dir = os.path.join(self.etcrpm_dir, "sysinfo")
- bb.utils.mkdirhier(sysinfo_dir)
- with open(os.path.join(sysinfo_dir, "Dirnames"), "w+") as dirnames:
- dirnames.write("/\n")
-
- if self.providename:
- providename_dir = os.path.join(sysinfo_dir, "Providename")
- if not os.path.exists(providename_dir):
- providename_content = '\n'.join(self.providename)
- providename_content += '\n'
- open(providename_dir, "w+").write(providename_content)
-
- # Configure RPM... we enforce these settings!
- bb.note("configuring RPM DB settings")
- # After change the __db.* cache size, log file will not be
- # generated automatically, that will raise some warnings,
- # so touch a bare log for rpm write into it.
- rpmlib_log = os.path.join(self.image_rpmlib, 'log', 'log.0000000001')
- if not os.path.exists(rpmlib_log):
- bb.utils.mkdirhier(os.path.join(self.image_rpmlib, 'log'))
- open(rpmlib_log, 'w+').close()
-
- DB_CONFIG_CONTENT = "# ================ Environment\n" \
- "set_data_dir .\n" \
- "set_create_dir .\n" \
- "set_lg_dir ./log\n" \
- "set_tmp_dir ./tmp\n" \
- "set_flags db_log_autoremove on\n" \
- "\n" \
- "# -- thread_count must be >= 8\n" \
- "set_thread_count 64\n" \
- "\n" \
- "# ================ Logging\n" \
- "\n" \
- "# ================ Memory Pool\n" \
- "set_cachesize 0 1048576 0\n" \
- "set_mp_mmapsize 268435456\n" \
- "\n" \
- "# ================ Locking\n" \
- "set_lk_max_locks 16384\n" \
- "set_lk_max_lockers 16384\n" \
- "set_lk_max_objects 16384\n" \
- "mutex_set_max 163840\n" \
- "\n" \
- "# ================ Replication\n"
-
- db_config_dir = os.path.join(self.image_rpmlib, 'DB_CONFIG')
- if not os.path.exists(db_config_dir):
- open(db_config_dir, 'w+').write(DB_CONFIG_CONTENT)
-
- # Create database so that smart doesn't complain (lazy init)
- opt = "-qa"
- cmd = "%s --root %s --dbpath /var/lib/rpm %s > /dev/null" % (
- self.rpm_cmd, self.target_rootfs, opt)
- try:
- subprocess.check_output(cmd, stderr=subprocess.STDOUT, shell=True)
- except subprocess.CalledProcessError as e:
- bb.fatal("Create rpm database failed. Command '%s' "
- "returned %d:\n%s" % (cmd, e.returncode, e.output.decode("utf-8")))
- # Import GPG key to RPM database of the target system
- if self.d.getVar('RPM_SIGN_PACKAGES', True) == '1':
- pubkey_path = self.d.getVar('RPM_GPG_PUBKEY', True)
- cmd = "%s --root %s --dbpath /var/lib/rpm --import %s > /dev/null" % (
- self.rpm_cmd, self.target_rootfs, pubkey_path)
- subprocess.check_output(cmd, stderr=subprocess.STDOUT, shell=True)
-
- # Configure smart
- bb.note("configuring Smart settings")
- bb.utils.remove(os.path.join(self.target_rootfs, 'var/lib/smart'),
- True)
- self._invoke_smart('config --set rpm-root=%s' % self.target_rootfs)
- self._invoke_smart('config --set rpm-dbpath=/var/lib/rpm')
- self._invoke_smart('config --set rpm-extra-macros._var=%s' %
- self.d.getVar('localstatedir', True))
- cmd = "config --set rpm-extra-macros._tmppath=/%s/tmp" % (self.install_dir_name)
-
- prefer_color = self.d.getVar('RPM_PREFER_ELF_ARCH', True)
- if prefer_color:
- if prefer_color not in ['0', '1', '2', '4']:
- bb.fatal("Invalid RPM_PREFER_ELF_ARCH: %s, it should be one of:\n"
- "\t1: ELF32 wins\n"
- "\t2: ELF64 wins\n"
- "\t4: ELF64 N32 wins (mips64 or mips64el only)" %
- prefer_color)
- if prefer_color == "4" and self.d.getVar("TUNE_ARCH", True) not in \
- ['mips64', 'mips64el']:
- bb.fatal("RPM_PREFER_ELF_ARCH = \"4\" is for mips64 or mips64el "
- "only.")
- self._invoke_smart('config --set rpm-extra-macros._prefer_color=%s'
- % prefer_color)
-
- self._invoke_smart(cmd)
- self._invoke_smart('config --set rpm-ignoresize=1')
-
- # Write common configuration for host and target usage
- self._invoke_smart('config --set rpm-nolinktos=1')
- self._invoke_smart('config --set rpm-noparentdirs=1')
- check_signature = self.d.getVar('RPM_CHECK_SIGNATURES', True)
- if check_signature and check_signature.strip() == "0":
- self._invoke_smart('config --set rpm-check-signatures=false')
- for i in self.d.getVar('BAD_RECOMMENDATIONS', True).split():
- self._invoke_smart('flag --set ignore-recommends %s' % i)
-
- # Do the following configurations here, to avoid them being
- # saved for field upgrade
- if self.d.getVar('NO_RECOMMENDATIONS', True).strip() == "1":
- self._invoke_smart('config --set ignore-all-recommends=1')
- pkg_exclude = self.d.getVar('PACKAGE_EXCLUDE', True) or ""
- for i in pkg_exclude.split():
- self._invoke_smart('flag --set exclude-packages %s' % i)
-
- # Optional debugging
- # self._invoke_smart('config --set rpm-log-level=debug')
- # cmd = 'config --set rpm-log-file=/tmp/smart-debug-logfile'
- # self._invoke_smart(cmd)
- ch_already_added = []
- for canonical_arch in platform_extra:
- arch = canonical_arch.split('-')[0]
- arch_channel = os.path.join(self.deploy_dir, arch)
- if os.path.exists(arch_channel) and not arch in ch_already_added:
- bb.note('Adding Smart channel %s (%s)' %
- (arch, channel_priority))
- self._invoke_smart('channel --add %s type=rpm-md baseurl=%s -y'
- % (arch, arch_channel))
- self._invoke_smart('channel --set %s priority=%d' %
- (arch, channel_priority))
- channel_priority -= 5
-
- ch_already_added.append(arch)
-
- bb.note('adding Smart RPM DB channel')
- self._invoke_smart('channel --add rpmsys type=rpm-sys -y')
-
- # Construct install scriptlet wrapper.
- # Scripts need to be ordered when executed, this ensures numeric order.
- # If we ever run into needing more the 899 scripts, we'll have to.
- # change num to start with 1000.
- #
- scriptletcmd = "$2 $1/$3 $4\n"
- scriptpath = "$1/$3"
-
- # When self.debug_level >= 3, also dump the content of the
- # executed scriptlets and how they get invoked. We have to
- # replace "exit 1" and "ERR" because printing those as-is
- # would trigger a log analysis failure.
- if self.debug_level >= 3:
- dump_invocation = 'echo "Executing ${name} ${kind} with: ' + scriptletcmd + '"\n'
- dump_script = 'cat ' + scriptpath + '| sed -e "s/exit 1/exxxit 1/g" -e "s/ERR/IRR/g"; echo\n'
- else:
- dump_invocation = 'echo "Executing ${name} ${kind}"\n'
- dump_script = ''
-
- SCRIPTLET_FORMAT = "#!/bin/bash\n" \
- "\n" \
- "export PATH=%s\n" \
- "export D=%s\n" \
- 'export OFFLINE_ROOT="$D"\n' \
- 'export IPKG_OFFLINE_ROOT="$D"\n' \
- 'export OPKG_OFFLINE_ROOT="$D"\n' \
- "export INTERCEPT_DIR=%s\n" \
- "export NATIVE_ROOT=%s\n" \
- "\n" \
- "name=`head -1 " + scriptpath + " | cut -d\' \' -f 2`\n" \
- "kind=`head -1 " + scriptpath + " | cut -d\' \' -f 4`\n" \
- + dump_invocation \
- + dump_script \
- + scriptletcmd + \
- "ret=$?\n" \
- "echo Result of ${name} ${kind}: ${ret}\n" \
- "if [ ${ret} -ne 0 ]; then\n" \
- " if [ $4 -eq 1 ]; then\n" \
- " mkdir -p $1/etc/rpm-postinsts\n" \
- " num=100\n" \
- " while [ -e $1/etc/rpm-postinsts/${num}-* ]; do num=$((num + 1)); done\n" \
- ' echo "#!$2" > $1/etc/rpm-postinsts/${num}-${name}\n' \
- ' echo "# Arg: $4" >> $1/etc/rpm-postinsts/${num}-${name}\n' \
- " cat " + scriptpath + " >> $1/etc/rpm-postinsts/${num}-${name}\n" \
- " chmod +x $1/etc/rpm-postinsts/${num}-${name}\n" \
- ' echo "Info: deferring ${name} ${kind} install scriptlet to first boot"\n' \
- " else\n" \
- ' echo "Error: ${name} ${kind} remove scriptlet failed"\n' \
- " fi\n" \
- "fi\n"
-
- intercept_dir = self.d.expand('${WORKDIR}/intercept_scripts')
- native_root = self.d.getVar('STAGING_DIR_NATIVE', True)
- scriptlet_content = SCRIPTLET_FORMAT % (os.environ['PATH'],
- self.target_rootfs,
- intercept_dir,
- native_root)
- open(self.scriptlet_wrapper, 'w+').write(scriptlet_content)
-
- bb.note("configuring RPM cross-install scriptlet_wrapper")
- os.chmod(self.scriptlet_wrapper, 0o755)
- cmd = 'config --set rpm-extra-macros._cross_scriptlet_wrapper=%s' % \
- self.scriptlet_wrapper
- self._invoke_smart(cmd)
-
- # Debug to show smart config info
- # bb.note(self._invoke_smart('config --show'))
-
- def update(self):
- self._invoke_smart('update rpmsys')
-
- def get_rdepends_recursively(self, pkgs):
- # pkgs will be changed during the loop, so use [:] to make a copy.
- for pkg in pkgs[:]:
- sub_data = oe.packagedata.read_subpkgdata(pkg, self.d)
- sub_rdep = sub_data.get("RDEPENDS_" + pkg)
- if not sub_rdep:
- continue
- done = list(bb.utils.explode_dep_versions2(sub_rdep).keys())
- next = done
- # Find all the rdepends on dependency chain
- while next:
- new = []
- for sub_pkg in next:
- sub_data = oe.packagedata.read_subpkgdata(sub_pkg, self.d)
- sub_pkg_rdep = sub_data.get("RDEPENDS_" + sub_pkg)
- if not sub_pkg_rdep:
- continue
- for p in bb.utils.explode_dep_versions2(sub_pkg_rdep):
- # Already handled, skip it.
- if p in done or p in pkgs:
- continue
- # It's a new dep
- if oe.packagedata.has_subpkgdata(p, self.d):
- done.append(p)
- new.append(p)
- next = new
- pkgs.extend(done)
- return pkgs
-
- '''
- Install pkgs with smart, the pkg name is oe format
- '''
- def install(self, pkgs, attempt_only=False):
-
- if not pkgs:
- bb.note("There are no packages to install")
- return
- bb.note("Installing the following packages: %s" % ' '.join(pkgs))
- if not attempt_only:
- # Pull in multilib requires since rpm may not pull in them
- # correctly, for example,
- # lib32-packagegroup-core-standalone-sdk-target requires
- # lib32-libc6, but rpm may pull in libc6 rather than lib32-libc6
- # since it doesn't know mlprefix (lib32-), bitbake knows it and
- # can handle it well, find out the RDEPENDS on the chain will
- # fix the problem. Both do_rootfs and do_populate_sdk have this
- # issue.
- # The attempt_only packages don't need this since they are
- # based on the installed ones.
- #
- # Separate pkgs into two lists, one is multilib, the other one
- # is non-multilib.
- ml_pkgs = []
- non_ml_pkgs = pkgs[:]
- for pkg in pkgs:
- for mlib in (self.d.getVar("MULTILIB_VARIANTS", True) or "").split():
- if pkg.startswith(mlib + '-'):
- ml_pkgs.append(pkg)
- non_ml_pkgs.remove(pkg)
-
- if len(ml_pkgs) > 0 and len(non_ml_pkgs) > 0:
- # Found both foo and lib-foo
- ml_pkgs = self.get_rdepends_recursively(ml_pkgs)
- non_ml_pkgs = self.get_rdepends_recursively(non_ml_pkgs)
- # Longer list makes smart slower, so only keep the pkgs
- # which have the same BPN, and smart can handle others
- # correctly.
- pkgs_new = []
- for pkg in non_ml_pkgs:
- for mlib in (self.d.getVar("MULTILIB_VARIANTS", True) or "").split():
- mlib_pkg = mlib + "-" + pkg
- if mlib_pkg in ml_pkgs:
- pkgs_new.append(pkg)
- pkgs_new.append(mlib_pkg)
- for pkg in pkgs:
- if pkg not in pkgs_new:
- pkgs_new.append(pkg)
- pkgs = pkgs_new
- new_depends = {}
- deps = bb.utils.explode_dep_versions2(" ".join(pkgs))
- for depend in deps:
- data = oe.packagedata.read_subpkgdata(depend, self.d)
- key = "PKG_%s" % depend
- if key in data:
- new_depend = data[key]
- else:
- new_depend = depend
- new_depends[new_depend] = deps[depend]
- pkgs = bb.utils.join_deps(new_depends, commasep=True).split(', ')
- pkgs = self._pkg_translate_oe_to_smart(pkgs, attempt_only)
- if not pkgs:
- bb.note("There are no packages to install")
- return
- if not attempt_only:
- bb.note('to be installed: %s' % ' '.join(pkgs))
- cmd = "%s %s install -y %s" % \
- (self.smart_cmd, self.smart_opt, ' '.join(pkgs))
- bb.note(cmd)
- else:
- bb.note('installing attempt only packages...')
- bb.note('Attempting %s' % ' '.join(pkgs))
- cmd = "%s %s install --attempt -y %s" % \
- (self.smart_cmd, self.smart_opt, ' '.join(pkgs))
- try:
- output = subprocess.check_output(cmd.split(), stderr=subprocess.STDOUT).decode("utf-8")
- bb.note(output)
- except subprocess.CalledProcessError as e:
- bb.fatal("Unable to install packages. Command '%s' "
- "returned %d:\n%s" % (cmd, e.returncode, e.output.decode("utf-8")))
-
- '''
- Remove pkgs with smart, the pkg name is smart/rpm format
- '''
- def remove(self, pkgs, with_dependencies=True):
- bb.note('to be removed: ' + ' '.join(pkgs))
-
- if not with_dependencies:
- cmd = "%s -e --nodeps " % self.rpm_cmd
- cmd += "--root=%s " % self.target_rootfs
- cmd += "--dbpath=/var/lib/rpm "
- cmd += "--define='_cross_scriptlet_wrapper %s' " % \
- self.scriptlet_wrapper
- cmd += "--define='_tmppath /%s/tmp' %s" % (self.install_dir_name, ' '.join(pkgs))
- else:
- # for pkg in pkgs:
- # bb.note('Debug: What required: %s' % pkg)
- # bb.note(self._invoke_smart('query %s --show-requiredby' % pkg))
-
- cmd = "%s %s remove -y %s" % (self.smart_cmd,
- self.smart_opt,
- ' '.join(pkgs))
-
- try:
- bb.note(cmd)
- output = subprocess.check_output(cmd, stderr=subprocess.STDOUT, shell=True).decode("utf-8")
- bb.note(output)
- except subprocess.CalledProcessError as e:
- bb.note("Unable to remove packages. Command '%s' "
- "returned %d:\n%s" % (cmd, e.returncode, e.output.decode("utf-8")))
-
- def upgrade(self):
- bb.note('smart upgrade')
- self._invoke_smart('upgrade')
-
- def write_index(self):
- result = self.indexer.write_index()
-
- if result is not None:
- bb.fatal(result)
-
- def remove_packaging_data(self):
- bb.utils.remove(self.image_rpmlib, True)
- bb.utils.remove(os.path.join(self.target_rootfs, 'var/lib/smart'),
- True)
- bb.utils.remove(os.path.join(self.target_rootfs, 'var/lib/opkg'), True)
-
- # remove temp directory
- bb.utils.remove(self.install_dir_path, True)
-
- def backup_packaging_data(self):
- # Save the rpmlib for increment rpm image generation
- if os.path.exists(self.saved_rpmlib):
- bb.utils.remove(self.saved_rpmlib, True)
- shutil.copytree(self.image_rpmlib,
- self.saved_rpmlib,
- symlinks=True)
-
- def recovery_packaging_data(self):
- # Move the rpmlib back
- if os.path.exists(self.saved_rpmlib):
- if os.path.exists(self.image_rpmlib):
- bb.utils.remove(self.image_rpmlib, True)
-
- bb.note('Recovery packaging data')
- shutil.copytree(self.saved_rpmlib,
- self.image_rpmlib,
- symlinks=True)
-
- def list_installed(self):
- return self.pkgs_list.list_pkgs()
-
- '''
- If incremental install, we need to determine what we've got,
- what we need to add, and what to remove...
- The dump_install_solution will dump and save the new install
- solution.
- '''
- def dump_install_solution(self, pkgs):
- bb.note('creating new install solution for incremental install')
- if len(pkgs) == 0:
- return
-
- pkgs = self._pkg_translate_oe_to_smart(pkgs, False)
- install_pkgs = list()
-
- cmd = "%s %s install -y --dump %s 2>%s" % \
- (self.smart_cmd,
- self.smart_opt,
- ' '.join(pkgs),
- self.solution_manifest)
- try:
- # Disable rpmsys channel for the fake install
- self._invoke_smart('channel --disable rpmsys')
-
- subprocess.check_output(cmd, stderr=subprocess.STDOUT, shell=True)
- with open(self.solution_manifest, 'r') as manifest:
- for pkg in manifest.read().split('\n'):
- if '@' in pkg:
- install_pkgs.append(pkg)
- except subprocess.CalledProcessError as e:
- bb.note("Unable to dump install packages. Command '%s' "
- "returned %d:\n%s" % (cmd, e.returncode, e.output.decode("utf-8")))
- # Recovery rpmsys channel
- self._invoke_smart('channel --enable rpmsys')
- return install_pkgs
-
- '''
- If incremental install, we need to determine what we've got,
- what we need to add, and what to remove...
- The load_old_install_solution will load the previous install
- solution
- '''
- def load_old_install_solution(self):
- bb.note('load old install solution for incremental install')
- installed_pkgs = list()
- if not os.path.exists(self.solution_manifest):
- bb.note('old install solution not exist')
- return installed_pkgs
-
- with open(self.solution_manifest, 'r') as manifest:
- for pkg in manifest.read().split('\n'):
- if '@' in pkg:
- installed_pkgs.append(pkg.strip())
-
- return installed_pkgs
-
- '''
- Dump all available packages in feeds, it should be invoked after the
- newest rpm index was created
- '''
- def dump_all_available_pkgs(self):
- available_manifest = self.d.expand('${T}/saved/available_pkgs.txt')
- available_pkgs = list()
- cmd = "%s %s query --output %s" % \
- (self.smart_cmd, self.smart_opt, available_manifest)
- try:
- subprocess.check_output(cmd, stderr=subprocess.STDOUT, shell=True)
- with open(available_manifest, 'r') as manifest:
- for pkg in manifest.read().split('\n'):
- if '@' in pkg:
- available_pkgs.append(pkg.strip())
- except subprocess.CalledProcessError as e:
- bb.note("Unable to list all available packages. Command '%s' "
- "returned %d:\n%s" % (cmd, e.returncode, e.output.decode("utf-8")))
-
- self.fullpkglist = available_pkgs
-
- return
-
- def save_rpmpostinst(self, pkg):
- mlibs = (self.d.getVar('MULTILIB_GLOBAL_VARIANTS', False) or "").split()
-
- new_pkg = pkg
- # Remove any multilib prefix from the package name
- for mlib in mlibs:
- if mlib in pkg:
- new_pkg = pkg.replace(mlib + '-', '')
- break
-
- bb.note(' * postponing %s' % new_pkg)
- saved_dir = self.target_rootfs + self.d.expand('${sysconfdir}/rpm-postinsts/') + new_pkg
-
- cmd = self.rpm_cmd + ' -q --scripts --root ' + self.target_rootfs
- cmd += ' --dbpath=/var/lib/rpm ' + new_pkg
- cmd += ' | sed -n -e "/^postinstall scriptlet (using .*):$/,/^.* scriptlet (using .*):$/ {/.*/p}"'
- cmd += ' | sed -e "/postinstall scriptlet (using \(.*\)):$/d"'
- cmd += ' -e "/^.* scriptlet (using .*):$/d" > %s' % saved_dir
-
- try:
- bb.note(cmd)
- output = subprocess.check_output(cmd, stderr=subprocess.STDOUT, shell=True).strip().decode("utf-8")
- bb.note(output)
- os.chmod(saved_dir, 0o755)
- except subprocess.CalledProcessError as e:
- bb.fatal("Invoke save_rpmpostinst failed. Command '%s' "
- "returned %d:\n%s" % (cmd, e.returncode, e.output.decode("utf-8")))
-
- '''Write common configuration for target usage'''
- def rpm_setup_smart_target_config(self):
- bb.utils.remove(os.path.join(self.target_rootfs, 'var/lib/smart'),
- True)
-
- self._invoke_smart('config --set rpm-nolinktos=1')
- self._invoke_smart('config --set rpm-noparentdirs=1')
- for i in self.d.getVar('BAD_RECOMMENDATIONS', True).split():
- self._invoke_smart('flag --set ignore-recommends %s' % i)
- self._invoke_smart('channel --add rpmsys type=rpm-sys -y')
-
- '''
- The rpm db lock files were produced after invoking rpm to query on
- build system, and they caused the rpm on target didn't work, so we
- need to unlock the rpm db by removing the lock files.
- '''
- def unlock_rpm_db(self):
- # Remove rpm db lock files
- rpm_db_locks = glob.glob('%s/var/lib/rpm/__db.*' % self.target_rootfs)
- for f in rpm_db_locks:
- bb.utils.remove(f, True)
-
- """
- Returns a dictionary with the package info.
- """
- def package_info(self, pkg):
- cmd = "%s %s info --urls %s" % (self.smart_cmd, self.smart_opt, pkg)
- try:
- output = subprocess.check_output(cmd, stderr=subprocess.STDOUT, shell=True).decode("utf-8")
- except subprocess.CalledProcessError as e:
- bb.fatal("Unable to list available packages. Command '%s' "
- "returned %d:\n%s" % (cmd, e.returncode, e.output.decode("utf-8")))
-
- # Set default values to avoid UnboundLocalError
- arch = ""
- ver = ""
- filename = ""
-
- #Parse output
- for line in output.splitlines():
- line = line.rstrip()
- if line.startswith("Name:"):
- pkg = line.split(": ")[1]
- elif line.startswith("Version:"):
- tmp_str = line.split(": ")[1]
- ver, arch = tmp_str.split("@")
- break
-
- # Get filename
- index = re.search("^URLs", output, re.MULTILINE)
- tmp_str = output[index.end():]
- for line in tmp_str.splitlines():
- if "/" in line:
- line = line.lstrip()
- filename = line.split(" ")[0]
- break
-
- # To have the same data type than other package_info methods
- filepath = os.path.join(self.deploy_dir, arch, filename)
- pkg_dict = {}
- pkg_dict[pkg] = {"arch":arch, "ver":ver, "filename":filename,
- "filepath": filepath}
-
- return pkg_dict
-
- """
- Returns the path to a tmpdir where resides the contents of a package.
-
- Deleting the tmpdir is responsability of the caller.
-
- """
- def extract(self, pkg):
- pkg_info = self.package_info(pkg)
- if not pkg_info:
- bb.fatal("Unable to get information for package '%s' while "
- "trying to extract the package." % pkg)
-
- pkg_path = pkg_info[pkg]["filepath"]
-
- cpio_cmd = bb.utils.which(os.getenv("PATH"), "cpio")
- rpm2cpio_cmd = bb.utils.which(os.getenv("PATH"), "rpm2cpio")
-
- if not os.path.isfile(pkg_path):
- bb.fatal("Unable to extract package for '%s'."
- "File %s doesn't exists" % (pkg, pkg_path))
-
- tmp_dir = tempfile.mkdtemp()
- current_dir = os.getcwd()
- os.chdir(tmp_dir)
-
- try:
- cmd = "%s %s | %s -idmv" % (rpm2cpio_cmd, pkg_path, cpio_cmd)
- output = subprocess.check_output(cmd, stderr=subprocess.STDOUT, shell=True)
- except subprocess.CalledProcessError as e:
- bb.utils.remove(tmp_dir, recurse=True)
- bb.fatal("Unable to extract %s package. Command '%s' "
- "returned %d:\n%s" % (pkg_path, cmd, e.returncode, e.output.decode("utf-8")))
- except OSError as e:
- bb.utils.remove(tmp_dir, recurse=True)
- bb.fatal("Unable to extract %s package. Command '%s' "
- "returned %d:\n%s at %s" % (pkg_path, cmd, e.errno, e.strerror, e.filename))
-
- bb.note("Extracted %s to %s" % (pkg_path, tmp_dir))
- os.chdir(current_dir)
-
- return tmp_dir
-
-
-class OpkgDpkgPM(PackageManager):
- """
- This is an abstract class. Do not instantiate this directly.
- """
- def __init__(self, d):
- super(OpkgDpkgPM, self).__init__(d)
-
- """
- Returns a dictionary with the package info.
-
- This method extracts the common parts for Opkg and Dpkg
- """
- def package_info(self, pkg, cmd):
-
- try:
- output = subprocess.check_output(cmd, stderr=subprocess.STDOUT, shell=True).decode("utf-8")
- except subprocess.CalledProcessError as e:
- bb.fatal("Unable to list available packages. Command '%s' "
- "returned %d:\n%s" % (cmd, e.returncode, e.output.decode("utf-8")))
- return opkg_query(output)
-
- """
- Returns the path to a tmpdir where resides the contents of a package.
-
- Deleting the tmpdir is responsability of the caller.
-
- This method extracts the common parts for Opkg and Dpkg
- """
- def extract(self, pkg, pkg_info):
-
- ar_cmd = bb.utils.which(os.getenv("PATH"), "ar")
- tar_cmd = bb.utils.which(os.getenv("PATH"), "tar")
- pkg_path = pkg_info[pkg]["filepath"]
-
- if not os.path.isfile(pkg_path):
- bb.fatal("Unable to extract package for '%s'."
- "File %s doesn't exists" % (pkg, pkg_path))
-
- tmp_dir = tempfile.mkdtemp()
- current_dir = os.getcwd()
- os.chdir(tmp_dir)
-
- try:
- cmd = "%s x %s" % (ar_cmd, pkg_path)
- output = subprocess.check_output(cmd, stderr=subprocess.STDOUT, shell=True)
- cmd = "%s xf data.tar.*" % tar_cmd
- output = subprocess.check_output(cmd, stderr=subprocess.STDOUT, shell=True)
- except subprocess.CalledProcessError as e:
- bb.utils.remove(tmp_dir, recurse=True)
- bb.fatal("Unable to extract %s package. Command '%s' "
- "returned %d:\n%s" % (pkg_path, cmd, e.returncode, e.output.decode("utf-8")))
- except OSError as e:
- bb.utils.remove(tmp_dir, recurse=True)
- bb.fatal("Unable to extract %s package. Command '%s' "
- "returned %d:\n%s at %s" % (pkg_path, cmd, e.errno, e.strerror, e.filename))
-
- bb.note("Extracted %s to %s" % (pkg_path, tmp_dir))
- bb.utils.remove(os.path.join(tmp_dir, "debian-binary"))
- bb.utils.remove(os.path.join(tmp_dir, "control.tar.gz"))
- os.chdir(current_dir)
-
- return tmp_dir
-
-
-class OpkgPM(OpkgDpkgPM):
- def __init__(self, d, target_rootfs, config_file, archs, task_name='target'):
- super(OpkgPM, self).__init__(d)
-
- self.target_rootfs = target_rootfs
- self.config_file = config_file
- self.pkg_archs = archs
- self.task_name = task_name
-
- self.deploy_dir = self.d.getVar("DEPLOY_DIR_IPK", True)
- self.deploy_lock_file = os.path.join(self.deploy_dir, "deploy.lock")
- self.opkg_cmd = bb.utils.which(os.getenv('PATH'), "opkg")
- self.opkg_args = "--volatile-cache -f %s -t %s -o %s " % (self.config_file, self.d.expand('${T}/ipktemp/') ,target_rootfs)
- self.opkg_args += self.d.getVar("OPKG_ARGS", True)
-
- opkg_lib_dir = self.d.getVar('OPKGLIBDIR', True)
- if opkg_lib_dir[0] == "/":
- opkg_lib_dir = opkg_lib_dir[1:]
-
- self.opkg_dir = os.path.join(target_rootfs, opkg_lib_dir, "opkg")
-
- bb.utils.mkdirhier(self.opkg_dir)
-
- self.saved_opkg_dir = self.d.expand('${T}/saved/%s' % self.task_name)
- if not os.path.exists(self.d.expand('${T}/saved')):
- bb.utils.mkdirhier(self.d.expand('${T}/saved'))
-
- self.from_feeds = (self.d.getVar('BUILD_IMAGES_FROM_FEEDS', True) or "") == "1"
- if self.from_feeds:
- self._create_custom_config()
- else:
- self._create_config()
-
- self.indexer = OpkgIndexer(self.d, self.deploy_dir)
-
- """
- This function will change a package's status in /var/lib/opkg/status file.
- If 'packages' is None then the new_status will be applied to all
- packages
- """
- def mark_packages(self, status_tag, packages=None):
- status_file = os.path.join(self.opkg_dir, "status")
-
- with open(status_file, "r") as sf:
- with open(status_file + ".tmp", "w+") as tmp_sf:
- if packages is None:
- tmp_sf.write(re.sub(r"Package: (.*?)\n((?:[^\n]+\n)*?)Status: (.*)(?:unpacked|installed)",
- r"Package: \1\n\2Status: \3%s" % status_tag,
- sf.read()))
- else:
- if type(packages).__name__ != "list":
- raise TypeError("'packages' should be a list object")
-
- status = sf.read()
- for pkg in packages:
- status = re.sub(r"Package: %s\n((?:[^\n]+\n)*?)Status: (.*)(?:unpacked|installed)" % pkg,
- r"Package: %s\n\1Status: \2%s" % (pkg, status_tag),
- status)
-
- tmp_sf.write(status)
-
- os.rename(status_file + ".tmp", status_file)
-
- def _create_custom_config(self):
- bb.note("Building from feeds activated!")
-
- with open(self.config_file, "w+") as config_file:
- priority = 1
- for arch in self.pkg_archs.split():
- config_file.write("arch %s %d\n" % (arch, priority))
- priority += 5
-
- for line in (self.d.getVar('IPK_FEED_URIS', True) or "").split():
- feed_match = re.match("^[ \t]*(.*)##([^ \t]*)[ \t]*$", line)
-
- if feed_match is not None:
- feed_name = feed_match.group(1)
- feed_uri = feed_match.group(2)
-
- bb.note("Add %s feed with URL %s" % (feed_name, feed_uri))
-
- config_file.write("src/gz %s %s\n" % (feed_name, feed_uri))
-
- """
- Allow to use package deploy directory contents as quick devel-testing
- feed. This creates individual feed configs for each arch subdir of those
- specified as compatible for the current machine.
- NOTE: Development-helper feature, NOT a full-fledged feed.
- """
- if (self.d.getVar('FEED_DEPLOYDIR_BASE_URI', True) or "") != "":
- for arch in self.pkg_archs.split():
- cfg_file_name = os.path.join(self.target_rootfs,
- self.d.getVar("sysconfdir", True),
- "opkg",
- "local-%s-feed.conf" % arch)
-
- with open(cfg_file_name, "w+") as cfg_file:
- cfg_file.write("src/gz local-%s %s/%s" %
- (arch,
- self.d.getVar('FEED_DEPLOYDIR_BASE_URI', True),
- arch))
-
- if self.opkg_dir != '/var/lib/opkg':
- # There is no command line option for this anymore, we need to add
- # info_dir and status_file to config file, if OPKGLIBDIR doesn't have
- # the default value of "/var/lib" as defined in opkg:
- # libopkg/opkg_conf.h:#define OPKG_CONF_DEFAULT_INFO_DIR "/var/lib/opkg/info"
- # libopkg/opkg_conf.h:#define OPKG_CONF_DEFAULT_STATUS_FILE "/var/lib/opkg/status"
- cfg_file.write("option info_dir %s\n" % os.path.join(self.d.getVar('OPKGLIBDIR', True), 'opkg', 'info'))
- cfg_file.write("option status_file %s\n" % os.path.join(self.d.getVar('OPKGLIBDIR', True), 'opkg', 'status'))
-
-
- def _create_config(self):
- with open(self.config_file, "w+") as config_file:
- priority = 1
- for arch in self.pkg_archs.split():
- config_file.write("arch %s %d\n" % (arch, priority))
- priority += 5
-
- config_file.write("src oe file:%s\n" % self.deploy_dir)
-
- for arch in self.pkg_archs.split():
- pkgs_dir = os.path.join(self.deploy_dir, arch)
- if os.path.isdir(pkgs_dir):
- config_file.write("src oe-%s file:%s\n" %
- (arch, pkgs_dir))
-
- if self.opkg_dir != '/var/lib/opkg':
- # There is no command line option for this anymore, we need to add
- # info_dir and status_file to config file, if OPKGLIBDIR doesn't have
- # the default value of "/var/lib" as defined in opkg:
- # libopkg/opkg_conf.h:#define OPKG_CONF_DEFAULT_INFO_DIR "/var/lib/opkg/info"
- # libopkg/opkg_conf.h:#define OPKG_CONF_DEFAULT_STATUS_FILE "/var/lib/opkg/status"
- config_file.write("option info_dir %s\n" % os.path.join(self.d.getVar('OPKGLIBDIR', True), 'opkg', 'info'))
- config_file.write("option status_file %s\n" % os.path.join(self.d.getVar('OPKGLIBDIR', True), 'opkg', 'status'))
-
- def insert_feeds_uris(self):
- if self.feed_uris == "":
- return
-
- rootfs_config = os.path.join('%s/etc/opkg/base-feeds.conf'
- % self.target_rootfs)
-
- feed_uris = self.construct_uris(self.feed_uris.split(), self.feed_base_paths.split())
- archs = self.pkg_archs.split() if self.feed_archs is None else self.feed_archs.split()
-
- with open(rootfs_config, "w+") as config_file:
- uri_iterator = 0
- for uri in feed_uris:
- if archs:
- for arch in archs:
- if (self.feed_archs is None) and (not os.path.exists(os.path.join(self.deploy_dir, arch))):
- continue
- bb.note('Adding opkg feed url-%s-%d (%s)' %
- (arch, uri_iterator, uri))
- config_file.write("src/gz uri-%s-%d %s/%s\n" %
- (arch, uri_iterator, uri, arch))
- else:
- bb.note('Adding opkg feed url-%d (%s)' %
- (uri_iterator, uri))
- config_file.write("src/gz uri-%d %s\n" %
- (uri_iterator, uri))
-
- uri_iterator += 1
-
- def update(self):
- self.deploy_dir_lock()
-
- cmd = "%s %s update" % (self.opkg_cmd, self.opkg_args)
-
- try:
- subprocess.check_output(cmd.split(), stderr=subprocess.STDOUT)
- except subprocess.CalledProcessError as e:
- self.deploy_dir_unlock()
- bb.fatal("Unable to update the package index files. Command '%s' "
- "returned %d:\n%s" % (cmd, e.returncode, e.output.decode("utf-8")))
-
- self.deploy_dir_unlock()
-
- def install(self, pkgs, attempt_only=False):
- if not pkgs:
- return
-
- cmd = "%s %s install %s" % (self.opkg_cmd, self.opkg_args, ' '.join(pkgs))
-
- os.environ['D'] = self.target_rootfs
- os.environ['OFFLINE_ROOT'] = self.target_rootfs
- os.environ['IPKG_OFFLINE_ROOT'] = self.target_rootfs
- os.environ['OPKG_OFFLINE_ROOT'] = self.target_rootfs
- os.environ['INTERCEPT_DIR'] = os.path.join(self.d.getVar('WORKDIR', True),
- "intercept_scripts")
- os.environ['NATIVE_ROOT'] = self.d.getVar('STAGING_DIR_NATIVE', True)
-
- try:
- bb.note("Installing the following packages: %s" % ' '.join(pkgs))
- bb.note(cmd)
- output = subprocess.check_output(cmd.split(), stderr=subprocess.STDOUT).decode("utf-8")
- bb.note(output)
- except subprocess.CalledProcessError as e:
- (bb.fatal, bb.note)[attempt_only]("Unable to install packages. "
- "Command '%s' returned %d:\n%s" %
- (cmd, e.returncode, e.output.decode("utf-8")))
-
- def remove(self, pkgs, with_dependencies=True):
- if with_dependencies:
- cmd = "%s %s --force-depends --force-remove --force-removal-of-dependent-packages remove %s" % \
- (self.opkg_cmd, self.opkg_args, ' '.join(pkgs))
- else:
- cmd = "%s %s --force-depends remove %s" % \
- (self.opkg_cmd, self.opkg_args, ' '.join(pkgs))
-
- try:
- bb.note(cmd)
- output = subprocess.check_output(cmd.split(), stderr=subprocess.STDOUT).decode("utf-8")
- bb.note(output)
- except subprocess.CalledProcessError as e:
- bb.fatal("Unable to remove packages. Command '%s' "
- "returned %d:\n%s" % (e.cmd, e.returncode, e.output.decode("utf-8")))
-
- def write_index(self):
- self.deploy_dir_lock()
-
- result = self.indexer.write_index()
-
- self.deploy_dir_unlock()
-
- if result is not None:
- bb.fatal(result)
-
- def remove_packaging_data(self):
- bb.utils.remove(self.opkg_dir, True)
- # create the directory back, it's needed by PM lock
- bb.utils.mkdirhier(self.opkg_dir)
-
- def remove_lists(self):
- if not self.from_feeds:
- bb.utils.remove(os.path.join(self.opkg_dir, "lists"), True)
-
- def list_installed(self):
- return OpkgPkgsList(self.d, self.target_rootfs, self.config_file).list_pkgs()
-
- def handle_bad_recommendations(self):
- bad_recommendations = self.d.getVar("BAD_RECOMMENDATIONS", True) or ""
- if bad_recommendations.strip() == "":
- return
-
- status_file = os.path.join(self.opkg_dir, "status")
-
- # If status file existed, it means the bad recommendations has already
- # been handled
- if os.path.exists(status_file):
- return
-
- cmd = "%s %s info " % (self.opkg_cmd, self.opkg_args)
-
- with open(status_file, "w+") as status:
- for pkg in bad_recommendations.split():
- pkg_info = cmd + pkg
-
- try:
- output = subprocess.check_output(pkg_info.split(), stderr=subprocess.STDOUT).strip().decode("utf-8")
- except subprocess.CalledProcessError as e:
- bb.fatal("Cannot get package info. Command '%s' "
- "returned %d:\n%s" % (pkg_info, e.returncode, e.output.decode("utf-8")))
-
- if output == "":
- bb.note("Ignored bad recommendation: '%s' is "
- "not a package" % pkg)
- continue
-
- for line in output.split('\n'):
- if line.startswith("Status:"):
- status.write("Status: deinstall hold not-installed\n")
- else:
- status.write(line + "\n")
-
- # Append a blank line after each package entry to ensure that it
- # is separated from the following entry
- status.write("\n")
-
- '''
- The following function dummy installs pkgs and returns the log of output.
- '''
- def dummy_install(self, pkgs):
- if len(pkgs) == 0:
- return
-
- # Create an temp dir as opkg root for dummy installation
- temp_rootfs = self.d.expand('${T}/opkg')
- temp_opkg_dir = os.path.join(temp_rootfs, 'var/lib/opkg')
- bb.utils.mkdirhier(temp_opkg_dir)
-
- opkg_args = "-f %s -o %s " % (self.config_file, temp_rootfs)
- opkg_args += self.d.getVar("OPKG_ARGS", True)
-
- cmd = "%s %s update" % (self.opkg_cmd, opkg_args)
- try:
- subprocess.check_output(cmd, stderr=subprocess.STDOUT, shell=True)
- except subprocess.CalledProcessError as e:
- bb.fatal("Unable to update. Command '%s' "
- "returned %d:\n%s" % (cmd, e.returncode, e.output.decode("utf-8")))
-
- # Dummy installation
- cmd = "%s %s --noaction install %s " % (self.opkg_cmd,
- opkg_args,
- ' '.join(pkgs))
- try:
- output = subprocess.check_output(cmd, stderr=subprocess.STDOUT, shell=True)
- except subprocess.CalledProcessError as e:
- bb.fatal("Unable to dummy install packages. Command '%s' "
- "returned %d:\n%s" % (cmd, e.returncode, e.output.decode("utf-8")))
-
- bb.utils.remove(temp_rootfs, True)
-
- return output
-
- def backup_packaging_data(self):
- # Save the opkglib for increment ipk image generation
- if os.path.exists(self.saved_opkg_dir):
- bb.utils.remove(self.saved_opkg_dir, True)
- shutil.copytree(self.opkg_dir,
- self.saved_opkg_dir,
- symlinks=True)
-
- def recover_packaging_data(self):
- # Move the opkglib back
- if os.path.exists(self.saved_opkg_dir):
- if os.path.exists(self.opkg_dir):
- bb.utils.remove(self.opkg_dir, True)
-
- bb.note('Recover packaging data')
- shutil.copytree(self.saved_opkg_dir,
- self.opkg_dir,
- symlinks=True)
-
- """
- Returns a dictionary with the package info.
- """
- def package_info(self, pkg):
- cmd = "%s %s info %s" % (self.opkg_cmd, self.opkg_args, pkg)
- pkg_info = super(OpkgPM, self).package_info(pkg, cmd)
-
- pkg_arch = pkg_info[pkg]["arch"]
- pkg_filename = pkg_info[pkg]["filename"]
- pkg_info[pkg]["filepath"] = \
- os.path.join(self.deploy_dir, pkg_arch, pkg_filename)
-
- return pkg_info
-
- """
- Returns the path to a tmpdir where resides the contents of a package.
-
- Deleting the tmpdir is responsability of the caller.
- """
- def extract(self, pkg):
- pkg_info = self.package_info(pkg)
- if not pkg_info:
- bb.fatal("Unable to get information for package '%s' while "
- "trying to extract the package." % pkg)
-
- tmp_dir = super(OpkgPM, self).extract(pkg, pkg_info)
- bb.utils.remove(os.path.join(tmp_dir, "data.tar.gz"))
-
- return tmp_dir
-
-class DpkgPM(OpkgDpkgPM):
- def __init__(self, d, target_rootfs, archs, base_archs, apt_conf_dir=None):
- super(DpkgPM, self).__init__(d)
- self.target_rootfs = target_rootfs
- self.deploy_dir = self.d.getVar('DEPLOY_DIR_DEB', True)
- if apt_conf_dir is None:
- self.apt_conf_dir = self.d.expand("${APTCONF_TARGET}/apt")
- else:
- self.apt_conf_dir = apt_conf_dir
- self.apt_conf_file = os.path.join(self.apt_conf_dir, "apt.conf")
- self.apt_get_cmd = bb.utils.which(os.getenv('PATH'), "apt-get")
- self.apt_cache_cmd = bb.utils.which(os.getenv('PATH'), "apt-cache")
-
- self.apt_args = d.getVar("APT_ARGS", True)
-
- self.all_arch_list = archs.split()
- all_mlb_pkg_arch_list = (self.d.getVar('ALL_MULTILIB_PACKAGE_ARCHS', True) or "").split()
- self.all_arch_list.extend(arch for arch in all_mlb_pkg_arch_list if arch not in self.all_arch_list)
-
- self._create_configs(archs, base_archs)
-
- self.indexer = DpkgIndexer(self.d, self.deploy_dir)
-
- """
- This function will change a package's status in /var/lib/dpkg/status file.
- If 'packages' is None then the new_status will be applied to all
- packages
- """
- def mark_packages(self, status_tag, packages=None):
- status_file = self.target_rootfs + "/var/lib/dpkg/status"
-
- with open(status_file, "r") as sf:
- with open(status_file + ".tmp", "w+") as tmp_sf:
- if packages is None:
- tmp_sf.write(re.sub(r"Package: (.*?)\n((?:[^\n]+\n)*?)Status: (.*)(?:unpacked|installed)",
- r"Package: \1\n\2Status: \3%s" % status_tag,
- sf.read()))
- else:
- if type(packages).__name__ != "list":
- raise TypeError("'packages' should be a list object")
-
- status = sf.read()
- for pkg in packages:
- status = re.sub(r"Package: %s\n((?:[^\n]+\n)*?)Status: (.*)(?:unpacked|installed)" % pkg,
- r"Package: %s\n\1Status: \2%s" % (pkg, status_tag),
- status)
-
- tmp_sf.write(status)
-
- os.rename(status_file + ".tmp", status_file)
-
- """
- Run the pre/post installs for package "package_name". If package_name is
- None, then run all pre/post install scriptlets.
- """
- def run_pre_post_installs(self, package_name=None):
- info_dir = self.target_rootfs + "/var/lib/dpkg/info"
- suffixes = [(".preinst", "Preinstall"), (".postinst", "Postinstall")]
- status_file = self.target_rootfs + "/var/lib/dpkg/status"
- installed_pkgs = []
-
- with open(status_file, "r") as status:
- for line in status.read().split('\n'):
- m = re.match("^Package: (.*)", line)
- if m is not None:
- installed_pkgs.append(m.group(1))
-
- if package_name is not None and not package_name in installed_pkgs:
- return
-
- os.environ['D'] = self.target_rootfs
- os.environ['OFFLINE_ROOT'] = self.target_rootfs
- os.environ['IPKG_OFFLINE_ROOT'] = self.target_rootfs
- os.environ['OPKG_OFFLINE_ROOT'] = self.target_rootfs
- os.environ['INTERCEPT_DIR'] = os.path.join(self.d.getVar('WORKDIR', True),
- "intercept_scripts")
- os.environ['NATIVE_ROOT'] = self.d.getVar('STAGING_DIR_NATIVE', True)
-
- failed_pkgs = []
- for pkg_name in installed_pkgs:
- for suffix in suffixes:
- p_full = os.path.join(info_dir, pkg_name + suffix[0])
- if os.path.exists(p_full):
- try:
- bb.note("Executing %s for package: %s ..." %
- (suffix[1].lower(), pkg_name))
- subprocess.check_output(p_full, stderr=subprocess.STDOUT)
- except subprocess.CalledProcessError as e:
- bb.note("%s for package %s failed with %d:\n%s" %
- (suffix[1], pkg_name, e.returncode, e.output.decode("utf-8")))
- failed_pkgs.append(pkg_name)
- break
-
- if len(failed_pkgs):
- self.mark_packages("unpacked", failed_pkgs)
-
- def update(self):
- os.environ['APT_CONFIG'] = self.apt_conf_file
-
- self.deploy_dir_lock()
-
- cmd = "%s update" % self.apt_get_cmd
-
- try:
- subprocess.check_output(cmd.split(), stderr=subprocess.STDOUT)
- except subprocess.CalledProcessError as e:
- bb.fatal("Unable to update the package index files. Command '%s' "
- "returned %d:\n%s" % (e.cmd, e.returncode, e.output.decode("utf-8")))
-
- self.deploy_dir_unlock()
-
- def install(self, pkgs, attempt_only=False):
- if attempt_only and len(pkgs) == 0:
- return
-
- os.environ['APT_CONFIG'] = self.apt_conf_file
-
- cmd = "%s %s install --force-yes --allow-unauthenticated %s" % \
- (self.apt_get_cmd, self.apt_args, ' '.join(pkgs))
-
- try:
- bb.note("Installing the following packages: %s" % ' '.join(pkgs))
- subprocess.check_output(cmd.split(), stderr=subprocess.STDOUT)
- except subprocess.CalledProcessError as e:
- (bb.fatal, bb.note)[attempt_only]("Unable to install packages. "
- "Command '%s' returned %d:\n%s" %
- (cmd, e.returncode, e.output.decode("utf-8")))
-
- # rename *.dpkg-new files/dirs
- for root, dirs, files in os.walk(self.target_rootfs):
- for dir in dirs:
- new_dir = re.sub("\.dpkg-new", "", dir)
- if dir != new_dir:
- os.rename(os.path.join(root, dir),
- os.path.join(root, new_dir))
-
- for file in files:
- new_file = re.sub("\.dpkg-new", "", file)
- if file != new_file:
- os.rename(os.path.join(root, file),
- os.path.join(root, new_file))
-
-
- def remove(self, pkgs, with_dependencies=True):
- if with_dependencies:
- os.environ['APT_CONFIG'] = self.apt_conf_file
- cmd = "%s purge %s" % (self.apt_get_cmd, ' '.join(pkgs))
- else:
- cmd = "%s --admindir=%s/var/lib/dpkg --instdir=%s" \
- " -P --force-depends %s" % \
- (bb.utils.which(os.getenv('PATH'), "dpkg"),
- self.target_rootfs, self.target_rootfs, ' '.join(pkgs))
-
- try:
- subprocess.check_output(cmd.split(), stderr=subprocess.STDOUT)
- except subprocess.CalledProcessError as e:
- bb.fatal("Unable to remove packages. Command '%s' "
- "returned %d:\n%s" % (e.cmd, e.returncode, e.output.decode("utf-8")))
-
- def write_index(self):
- self.deploy_dir_lock()
-
- result = self.indexer.write_index()
-
- self.deploy_dir_unlock()
-
- if result is not None:
- bb.fatal(result)
-
- def insert_feeds_uris(self):
- if self.feed_uris == "":
- return
-
- sources_conf = os.path.join("%s/etc/apt/sources.list"
- % self.target_rootfs)
- arch_list = []
-
- if self.feed_archs is None:
- for arch in self.all_arch_list:
- if not os.path.exists(os.path.join(self.deploy_dir, arch)):
- continue
- arch_list.append(arch)
- else:
- arch_list = self.feed_archs.split()
-
- feed_uris = self.construct_uris(self.feed_uris.split(), self.feed_base_paths.split())
-
- with open(sources_conf, "w+") as sources_file:
- for uri in feed_uris:
- if arch_list:
- for arch in arch_list:
- bb.note('Adding dpkg channel at (%s)' % uri)
- sources_file.write("deb %s/%s ./\n" %
- (uri, arch))
- else:
- bb.note('Adding dpkg channel at (%s)' % uri)
- sources_file.write("deb %s ./\n" % uri)
-
- def _create_configs(self, archs, base_archs):
- base_archs = re.sub("_", "-", base_archs)
-
- if os.path.exists(self.apt_conf_dir):
- bb.utils.remove(self.apt_conf_dir, True)
-
- bb.utils.mkdirhier(self.apt_conf_dir)
- bb.utils.mkdirhier(self.apt_conf_dir + "/lists/partial/")
- bb.utils.mkdirhier(self.apt_conf_dir + "/apt.conf.d/")
- bb.utils.mkdirhier(self.apt_conf_dir + "/preferences.d/")
-
- arch_list = []
- for arch in self.all_arch_list:
- if not os.path.exists(os.path.join(self.deploy_dir, arch)):
- continue
- arch_list.append(arch)
-
- with open(os.path.join(self.apt_conf_dir, "preferences"), "w+") as prefs_file:
- priority = 801
- for arch in arch_list:
- prefs_file.write(
- "Package: *\n"
- "Pin: release l=%s\n"
- "Pin-Priority: %d\n\n" % (arch, priority))
-
- priority += 5
-
- pkg_exclude = self.d.getVar('PACKAGE_EXCLUDE', True) or ""
- for pkg in pkg_exclude.split():
- prefs_file.write(
- "Package: %s\n"
- "Pin: release *\n"
- "Pin-Priority: -1\n\n" % pkg)
-
- arch_list.reverse()
-
- with open(os.path.join(self.apt_conf_dir, "sources.list"), "w+") as sources_file:
- for arch in arch_list:
- sources_file.write("deb file:%s/ ./\n" %
- os.path.join(self.deploy_dir, arch))
-
- base_arch_list = base_archs.split()
- multilib_variants = self.d.getVar("MULTILIB_VARIANTS", True);
- for variant in multilib_variants.split():
- localdata = bb.data.createCopy(self.d)
- variant_tune = localdata.getVar("DEFAULTTUNE_virtclass-multilib-" + variant, False)
- orig_arch = localdata.getVar("DPKG_ARCH", True)
- localdata.setVar("DEFAULTTUNE", variant_tune)
- bb.data.update_data(localdata)
- variant_arch = localdata.getVar("DPKG_ARCH", True)
- if variant_arch not in base_arch_list:
- base_arch_list.append(variant_arch)
-
- with open(self.apt_conf_file, "w+") as apt_conf:
- with open(self.d.expand("${STAGING_ETCDIR_NATIVE}/apt/apt.conf.sample")) as apt_conf_sample:
- for line in apt_conf_sample.read().split("\n"):
- match_arch = re.match(" Architecture \".*\";$", line)
- architectures = ""
- if match_arch:
- for base_arch in base_arch_list:
- architectures += "\"%s\";" % base_arch
- apt_conf.write(" Architectures {%s};\n" % architectures);
- apt_conf.write(" Architecture \"%s\";\n" % base_archs)
- else:
- line = re.sub("#ROOTFS#", self.target_rootfs, line)
- line = re.sub("#APTCONF#", self.apt_conf_dir, line)
- apt_conf.write(line + "\n")
-
- target_dpkg_dir = "%s/var/lib/dpkg" % self.target_rootfs
- bb.utils.mkdirhier(os.path.join(target_dpkg_dir, "info"))
-
- bb.utils.mkdirhier(os.path.join(target_dpkg_dir, "updates"))
-
- if not os.path.exists(os.path.join(target_dpkg_dir, "status")):
- open(os.path.join(target_dpkg_dir, "status"), "w+").close()
- if not os.path.exists(os.path.join(target_dpkg_dir, "available")):
- open(os.path.join(target_dpkg_dir, "available"), "w+").close()
-
- def remove_packaging_data(self):
- bb.utils.remove(os.path.join(self.target_rootfs,
- self.d.getVar('opkglibdir', True)), True)
- bb.utils.remove(self.target_rootfs + "/var/lib/dpkg/", True)
-
- def fix_broken_dependencies(self):
- os.environ['APT_CONFIG'] = self.apt_conf_file
-
- cmd = "%s %s -f install" % (self.apt_get_cmd, self.apt_args)
-
- try:
- subprocess.check_output(cmd.split(), stderr=subprocess.STDOUT)
- except subprocess.CalledProcessError as e:
- bb.fatal("Cannot fix broken dependencies. Command '%s' "
- "returned %d:\n%s" % (cmd, e.returncode, e.output.decode("utf-8")))
-
- def list_installed(self):
- return DpkgPkgsList(self.d, self.target_rootfs).list_pkgs()
-
- """
- Returns a dictionary with the package info.
- """
- def package_info(self, pkg):
- cmd = "%s show %s" % (self.apt_cache_cmd, pkg)
- pkg_info = super(DpkgPM, self).package_info(pkg, cmd)
-
- pkg_arch = pkg_info[pkg]["pkgarch"]
- pkg_filename = pkg_info[pkg]["filename"]
- pkg_info[pkg]["filepath"] = \
- os.path.join(self.deploy_dir, pkg_arch, pkg_filename)
-
- return pkg_info
-
- """
- Returns the path to a tmpdir where resides the contents of a package.
-
- Deleting the tmpdir is responsability of the caller.
- """
- def extract(self, pkg):
- pkg_info = self.package_info(pkg)
- if not pkg_info:
- bb.fatal("Unable to get information for package '%s' while "
- "trying to extract the package." % pkg)
-
- tmp_dir = super(DpkgPM, self).extract(pkg, pkg_info)
- bb.utils.remove(os.path.join(tmp_dir, "data.tar.xz"))
-
- return tmp_dir
-
-def generate_index_files(d):
- classes = d.getVar('PACKAGE_CLASSES', True).replace("package_", "").split()
-
- indexer_map = {
- "rpm": (RpmIndexer, d.getVar('DEPLOY_DIR_RPM', True)),
- "ipk": (OpkgIndexer, d.getVar('DEPLOY_DIR_IPK', True)),
- "deb": (DpkgIndexer, d.getVar('DEPLOY_DIR_DEB', True))
- }
-
- result = None
-
- for pkg_class in classes:
- if not pkg_class in indexer_map:
- continue
-
- if os.path.exists(indexer_map[pkg_class][1]):
- result = indexer_map[pkg_class][0](d, indexer_map[pkg_class][1]).write_index()
-
- if result is not None:
- bb.fatal(result)
-
-if __name__ == "__main__":
- """
- We should be able to run this as a standalone script, from outside bitbake
- environment.
- """
- """
- TBD
- """
diff --git a/meta/lib/oe/package_manager/__init__.py b/meta/lib/oe/package_manager/__init__.py
new file mode 100644
index 0000000000..a6bf2fe219
--- /dev/null
+++ b/meta/lib/oe/package_manager/__init__.py
@@ -0,0 +1,558 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: GPL-2.0-only
+#
+
+from abc import ABCMeta, abstractmethod
+import os
+import glob
+import subprocess
+import shutil
+import re
+import collections
+import bb
+import tempfile
+import oe.utils
+import oe.path
+import string
+from oe.gpg_sign import get_signer
+import hashlib
+import fnmatch
+
+# this can be used by all PM backends to create the index files in parallel
+def create_index(arg):
+ index_cmd = arg
+
+ bb.note("Executing '%s' ..." % index_cmd)
+ result = subprocess.check_output(index_cmd, stderr=subprocess.STDOUT, shell=True).decode("utf-8")
+ if result:
+ bb.note(result)
+
+def opkg_query(cmd_output):
+ """
+ This method parse the output from the package managerand return
+ a dictionary with the information of the packages. This is used
+ when the packages are in deb or ipk format.
+ """
+ verregex = re.compile(r' \([=<>]* [^ )]*\)')
+ output = dict()
+ pkg = ""
+ arch = ""
+ ver = ""
+ filename = ""
+ dep = []
+ prov = []
+ pkgarch = ""
+ for line in cmd_output.splitlines()+['']:
+ line = line.rstrip()
+ if ':' in line:
+ if line.startswith("Package: "):
+ pkg = line.split(": ")[1]
+ elif line.startswith("Architecture: "):
+ arch = line.split(": ")[1]
+ elif line.startswith("Version: "):
+ ver = line.split(": ")[1]
+ elif line.startswith("File: ") or line.startswith("Filename:"):
+ filename = line.split(": ")[1]
+ if "/" in filename:
+ filename = os.path.basename(filename)
+ elif line.startswith("Depends: "):
+ depends = verregex.sub('', line.split(": ")[1])
+ for depend in depends.split(", "):
+ dep.append(depend)
+ elif line.startswith("Recommends: "):
+ recommends = verregex.sub('', line.split(": ")[1])
+ for recommend in recommends.split(", "):
+ dep.append("%s [REC]" % recommend)
+ elif line.startswith("PackageArch: "):
+ pkgarch = line.split(": ")[1]
+ elif line.startswith("Provides: "):
+ provides = verregex.sub('', line.split(": ")[1])
+ for provide in provides.split(", "):
+ prov.append(provide)
+
+ # When there is a blank line save the package information
+ elif not line:
+ # IPK doesn't include the filename
+ if not filename:
+ filename = "%s_%s_%s.ipk" % (pkg, ver, arch)
+ if pkg:
+ output[pkg] = {"arch":arch, "ver":ver,
+ "filename":filename, "deps": dep, "pkgarch":pkgarch, "provs": prov}
+ pkg = ""
+ arch = ""
+ ver = ""
+ filename = ""
+ dep = []
+ prov = []
+ pkgarch = ""
+
+ return output
+
+def failed_postinsts_abort(pkgs, log_path):
+ bb.fatal("""Postinstall scriptlets of %s have failed. If the intention is to defer them to first boot,
+then please place them into pkg_postinst_ontarget:${PN} ().
+Deferring to first boot via 'exit 1' is no longer supported.
+Details of the failure are in %s.""" %(pkgs, log_path))
+
+def generate_locale_archive(d, rootfs, target_arch, localedir):
+ # Pretty sure we don't need this for locale archive generation but
+ # keeping it to be safe...
+ locale_arch_options = { \
+ "arc": ["--uint32-align=4", "--little-endian"],
+ "arceb": ["--uint32-align=4", "--big-endian"],
+ "arm": ["--uint32-align=4", "--little-endian"],
+ "armeb": ["--uint32-align=4", "--big-endian"],
+ "aarch64": ["--uint32-align=4", "--little-endian"],
+ "aarch64_be": ["--uint32-align=4", "--big-endian"],
+ "sh4": ["--uint32-align=4", "--big-endian"],
+ "powerpc": ["--uint32-align=4", "--big-endian"],
+ "powerpc64": ["--uint32-align=4", "--big-endian"],
+ "powerpc64le": ["--uint32-align=4", "--little-endian"],
+ "mips": ["--uint32-align=4", "--big-endian"],
+ "mipsisa32r6": ["--uint32-align=4", "--big-endian"],
+ "mips64": ["--uint32-align=4", "--big-endian"],
+ "mipsisa64r6": ["--uint32-align=4", "--big-endian"],
+ "mipsel": ["--uint32-align=4", "--little-endian"],
+ "mipsisa32r6el": ["--uint32-align=4", "--little-endian"],
+ "mips64el": ["--uint32-align=4", "--little-endian"],
+ "mipsisa64r6el": ["--uint32-align=4", "--little-endian"],
+ "riscv64": ["--uint32-align=4", "--little-endian"],
+ "riscv32": ["--uint32-align=4", "--little-endian"],
+ "i586": ["--uint32-align=4", "--little-endian"],
+ "i686": ["--uint32-align=4", "--little-endian"],
+ "x86_64": ["--uint32-align=4", "--little-endian"]
+ }
+ if target_arch in locale_arch_options:
+ arch_options = locale_arch_options[target_arch]
+ else:
+ bb.error("locale_arch_options not found for target_arch=" + target_arch)
+ bb.fatal("unknown arch:" + target_arch + " for locale_arch_options")
+
+ # Need to set this so cross-localedef knows where the archive is
+ env = dict(os.environ)
+ env["LOCALEARCHIVE"] = oe.path.join(localedir, "locale-archive")
+
+ for name in sorted(os.listdir(localedir)):
+ path = os.path.join(localedir, name)
+ if os.path.isdir(path):
+ cmd = ["cross-localedef", "--verbose"]
+ cmd += arch_options
+ cmd += ["--add-to-archive", path]
+ subprocess.check_output(cmd, env=env, stderr=subprocess.STDOUT)
+
+class Indexer(object, metaclass=ABCMeta):
+ def __init__(self, d, deploy_dir):
+ self.d = d
+ self.deploy_dir = deploy_dir
+
+ @abstractmethod
+ def write_index(self):
+ pass
+
+class PkgsList(object, metaclass=ABCMeta):
+ def __init__(self, d, rootfs_dir):
+ self.d = d
+ self.rootfs_dir = rootfs_dir
+
+ @abstractmethod
+ def list_pkgs(self):
+ pass
+
+class PackageManager(object, metaclass=ABCMeta):
+ """
+ This is an abstract class. Do not instantiate this directly.
+ """
+
+ def __init__(self, d, target_rootfs):
+ self.d = d
+ self.target_rootfs = target_rootfs
+ self.deploy_dir = None
+ self.deploy_lock = None
+ self._initialize_intercepts()
+
+ def _initialize_intercepts(self):
+ bb.note("Initializing intercept dir for %s" % self.target_rootfs)
+ # As there might be more than one instance of PackageManager operating at the same time
+ # we need to isolate the intercept_scripts directories from each other,
+ # hence the ugly hash digest in dir name.
+ self.intercepts_dir = os.path.join(self.d.getVar('WORKDIR'), "intercept_scripts-%s" %
+ (hashlib.sha256(self.target_rootfs.encode()).hexdigest()))
+
+ postinst_intercepts = (self.d.getVar("POSTINST_INTERCEPTS") or "").split()
+ if not postinst_intercepts:
+ postinst_intercepts_path = self.d.getVar("POSTINST_INTERCEPTS_PATH")
+ if not postinst_intercepts_path:
+ postinst_intercepts_path = self.d.getVar("POSTINST_INTERCEPTS_DIR") or self.d.expand("${COREBASE}/scripts/postinst-intercepts")
+ postinst_intercepts = oe.path.which_wild('*', postinst_intercepts_path)
+
+ bb.debug(1, 'Collected intercepts:\n%s' % ''.join(' %s\n' % i for i in postinst_intercepts))
+ bb.utils.remove(self.intercepts_dir, True)
+ bb.utils.mkdirhier(self.intercepts_dir)
+ for intercept in postinst_intercepts:
+ shutil.copy(intercept, os.path.join(self.intercepts_dir, os.path.basename(intercept)))
+
+ @abstractmethod
+ def _handle_intercept_failure(self, failed_script):
+ pass
+
+ def _postpone_to_first_boot(self, postinst_intercept_hook):
+ with open(postinst_intercept_hook) as intercept:
+ registered_pkgs = None
+ for line in intercept.read().split("\n"):
+ m = re.match(r"^##PKGS:(.*)", line)
+ if m is not None:
+ registered_pkgs = m.group(1).strip()
+ break
+
+ if registered_pkgs is not None:
+ bb.note("If an image is being built, the postinstalls for the following packages "
+ "will be postponed for first boot: %s" %
+ registered_pkgs)
+
+ # call the backend dependent handler
+ self._handle_intercept_failure(registered_pkgs)
+
+
+ def run_intercepts(self, populate_sdk=None):
+ intercepts_dir = self.intercepts_dir
+
+ bb.note("Running intercept scripts:")
+ os.environ['D'] = self.target_rootfs
+ os.environ['STAGING_DIR_NATIVE'] = self.d.getVar('STAGING_DIR_NATIVE')
+ for script in os.listdir(intercepts_dir):
+ script_full = os.path.join(intercepts_dir, script)
+
+ if script == "postinst_intercept" or not os.access(script_full, os.X_OK):
+ continue
+
+ # we do not want to run any multilib variant of this
+ if script.startswith("delay_to_first_boot"):
+ self._postpone_to_first_boot(script_full)
+ continue
+
+ if populate_sdk == 'host' and self.d.getVar('SDK_OS') == 'mingw32':
+ bb.note("The postinstall intercept hook '%s' could not be executed due to missing wine support, details in %s/log.do_%s"
+ % (script, self.d.getVar('T'), self.d.getVar('BB_CURRENTTASK')))
+ continue
+
+ bb.note("> Executing %s intercept ..." % script)
+
+ try:
+ output = subprocess.check_output(script_full, stderr=subprocess.STDOUT)
+ if output: bb.note(output.decode("utf-8"))
+ except subprocess.CalledProcessError as e:
+ bb.note("Exit code %d. Output:\n%s" % (e.returncode, e.output.decode("utf-8")))
+ if populate_sdk == 'host':
+ bb.fatal("The postinstall intercept hook '%s' failed, details in %s/log.do_%s" % (script, self.d.getVar('T'), self.d.getVar('BB_CURRENTTASK')))
+ elif populate_sdk == 'target':
+ if "qemuwrapper: qemu usermode is not supported" in e.output.decode("utf-8"):
+ bb.note("The postinstall intercept hook '%s' could not be executed due to missing qemu usermode support, details in %s/log.do_%s"
+ % (script, self.d.getVar('T'), self.d.getVar('BB_CURRENTTASK')))
+ else:
+ bb.fatal("The postinstall intercept hook '%s' failed, details in %s/log.do_%s" % (script, self.d.getVar('T'), self.d.getVar('BB_CURRENTTASK')))
+ else:
+ if "qemuwrapper: qemu usermode is not supported" in e.output.decode("utf-8"):
+ bb.note("The postinstall intercept hook '%s' could not be executed due to missing qemu usermode support, details in %s/log.do_%s"
+ % (script, self.d.getVar('T'), self.d.getVar('BB_CURRENTTASK')))
+ self._postpone_to_first_boot(script_full)
+ else:
+ bb.fatal("The postinstall intercept hook '%s' failed, details in %s/log.do_%s" % (script, self.d.getVar('T'), self.d.getVar('BB_CURRENTTASK')))
+
+ @abstractmethod
+ def update(self):
+ """
+ Update the package manager package database.
+ """
+ pass
+
+ @abstractmethod
+ def install(self, pkgs, attempt_only=False, hard_depends_only=False):
+ """
+ Install a list of packages. 'pkgs' is a list object. If 'attempt_only' is
+ True, installation failures are ignored.
+ """
+ pass
+
+ @abstractmethod
+ def remove(self, pkgs, with_dependencies=True):
+ """
+ Remove a list of packages. 'pkgs' is a list object. If 'with_dependencies'
+ is False, then any dependencies are left in place.
+ """
+ pass
+
+ @abstractmethod
+ def write_index(self):
+ """
+ This function creates the index files
+ """
+ pass
+
+ @abstractmethod
+ def remove_packaging_data(self):
+ pass
+
+ @abstractmethod
+ def list_installed(self):
+ pass
+
+ @abstractmethod
+ def extract(self, pkg):
+ """
+ Returns the path to a tmpdir where resides the contents of a package.
+ Deleting the tmpdir is responsability of the caller.
+ """
+ pass
+
+ @abstractmethod
+ def insert_feeds_uris(self, feed_uris, feed_base_paths, feed_archs):
+ """
+ Add remote package feeds into repository manager configuration. The parameters
+ for the feeds are set by feed_uris, feed_base_paths and feed_archs.
+ See http://www.yoctoproject.org/docs/current/ref-manual/ref-manual.html#var-PACKAGE_FEED_URIS
+ for their description.
+ """
+ pass
+
+ def install_glob(self, globs, sdk=False):
+ """
+ Install all packages that match a glob.
+ """
+ # TODO don't have sdk here but have a property on the superclass
+ # (and respect in install_complementary)
+ if sdk:
+ pkgdatadir = self.d.getVar("PKGDATA_DIR_SDK")
+ else:
+ pkgdatadir = self.d.getVar("PKGDATA_DIR")
+
+ try:
+ bb.note("Installing globbed packages...")
+ cmd = ["oe-pkgdata-util", "-p", pkgdatadir, "list-pkgs", globs]
+ bb.note('Running %s' % cmd)
+ proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ stdout, stderr = proc.communicate()
+ if stderr: bb.note(stderr.decode("utf-8"))
+ pkgs = stdout.decode("utf-8")
+ self.install(pkgs.split(), attempt_only=True)
+ except subprocess.CalledProcessError as e:
+ # Return code 1 means no packages matched
+ if e.returncode != 1:
+ bb.fatal("Could not compute globbed packages list. Command "
+ "'%s' returned %d:\n%s" %
+ (' '.join(cmd), e.returncode, e.output.decode("utf-8")))
+
+ def install_complementary(self, globs=None):
+ """
+ Install complementary packages based upon the list of currently installed
+ packages e.g. locales, *-dev, *-dbg, etc. Note: every backend needs to
+ call this function explicitly after the normal package installation.
+ """
+ if globs is None:
+ globs = self.d.getVar('IMAGE_INSTALL_COMPLEMENTARY')
+ split_linguas = set()
+
+ for translation in self.d.getVar('IMAGE_LINGUAS').split():
+ split_linguas.add(translation)
+ split_linguas.add(translation.split('-')[0])
+
+ split_linguas = sorted(split_linguas)
+
+ for lang in split_linguas:
+ globs += " *-locale-%s" % lang
+ for complementary_linguas in (self.d.getVar('IMAGE_LINGUAS_COMPLEMENTARY') or "").split():
+ globs += (" " + complementary_linguas) % lang
+
+ if globs is None:
+ return
+
+ # we need to write the list of installed packages to a file because the
+ # oe-pkgdata-util reads it from a file
+ with tempfile.NamedTemporaryFile(mode="w+", prefix="installed-pkgs") as installed_pkgs:
+ pkgs = self.list_installed()
+
+ provided_pkgs = set()
+ for pkg in pkgs.values():
+ provided_pkgs |= set(pkg.get('provs', []))
+
+ output = oe.utils.format_pkg_list(pkgs, "arch")
+ installed_pkgs.write(output)
+ installed_pkgs.flush()
+
+ cmd = ["oe-pkgdata-util",
+ "-p", self.d.getVar('PKGDATA_DIR'), "glob", installed_pkgs.name,
+ globs]
+ exclude = self.d.getVar('PACKAGE_EXCLUDE_COMPLEMENTARY')
+ if exclude:
+ cmd.extend(['--exclude=' + '|'.join(exclude.split())])
+ try:
+ bb.note('Running %s' % cmd)
+ proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ stdout, stderr = proc.communicate()
+ if stderr: bb.note(stderr.decode("utf-8"))
+ complementary_pkgs = stdout.decode("utf-8")
+ complementary_pkgs = set(complementary_pkgs.split())
+ skip_pkgs = sorted(complementary_pkgs & provided_pkgs)
+ install_pkgs = sorted(complementary_pkgs - provided_pkgs)
+ bb.note("Installing complementary packages ... %s (skipped already provided packages %s)" % (
+ ' '.join(install_pkgs),
+ ' '.join(skip_pkgs)))
+ self.install(install_pkgs, hard_depends_only=True)
+ except subprocess.CalledProcessError as e:
+ bb.fatal("Could not compute complementary packages list. Command "
+ "'%s' returned %d:\n%s" %
+ (' '.join(cmd), e.returncode, e.output.decode("utf-8")))
+
+ if self.d.getVar('IMAGE_LOCALES_ARCHIVE') == '1':
+ target_arch = self.d.getVar('TARGET_ARCH')
+ localedir = oe.path.join(self.target_rootfs, self.d.getVar("libdir"), "locale")
+ if os.path.exists(localedir) and os.listdir(localedir):
+ generate_locale_archive(self.d, self.target_rootfs, target_arch, localedir)
+ # And now delete the binary locales
+ self.remove(fnmatch.filter(self.list_installed(), "glibc-binary-localedata-*"), False)
+
+ def deploy_dir_lock(self):
+ if self.deploy_dir is None:
+ raise RuntimeError("deploy_dir is not set!")
+
+ lock_file_name = os.path.join(self.deploy_dir, "deploy.lock")
+
+ self.deploy_lock = bb.utils.lockfile(lock_file_name)
+
+ def deploy_dir_unlock(self):
+ if self.deploy_lock is None:
+ return
+
+ bb.utils.unlockfile(self.deploy_lock)
+
+ self.deploy_lock = None
+
+ def construct_uris(self, uris, base_paths):
+ """
+ Construct URIs based on the following pattern: uri/base_path where 'uri'
+ and 'base_path' correspond to each element of the corresponding array
+ argument leading to len(uris) x len(base_paths) elements on the returned
+ array
+ """
+ def _append(arr1, arr2, sep='/'):
+ res = []
+ narr1 = [a.rstrip(sep) for a in arr1]
+ narr2 = [a.rstrip(sep).lstrip(sep) for a in arr2]
+ for a1 in narr1:
+ if arr2:
+ for a2 in narr2:
+ res.append("%s%s%s" % (a1, sep, a2))
+ else:
+ res.append(a1)
+ return res
+ return _append(uris, base_paths)
+
+def create_packages_dir(d, subrepo_dir, deploydir, taskname, filterbydependencies):
+ """
+ Go through our do_package_write_X dependencies and hardlink the packages we depend
+ upon into the repo directory. This prevents us seeing other packages that may
+ have been built that we don't depend upon and also packages for architectures we don't
+ support.
+ """
+ import errno
+
+ taskdepdata = d.getVar("BB_TASKDEPDATA", False)
+ mytaskname = d.getVar("BB_RUNTASK")
+ pn = d.getVar("PN")
+ seendirs = set()
+ multilibs = {}
+
+ bb.utils.remove(subrepo_dir, recurse=True)
+ bb.utils.mkdirhier(subrepo_dir)
+
+ # Detect bitbake -b usage
+ nodeps = d.getVar("BB_LIMITEDDEPS") or False
+ if nodeps or not filterbydependencies:
+ oe.path.symlink(deploydir, subrepo_dir, True)
+ return
+
+ start = None
+ for dep in taskdepdata:
+ data = taskdepdata[dep]
+ if data[1] == mytaskname and data[0] == pn:
+ start = dep
+ break
+ if start is None:
+ bb.fatal("Couldn't find ourself in BB_TASKDEPDATA?")
+ pkgdeps = set()
+ start = [start]
+ seen = set(start)
+ # Support direct dependencies (do_rootfs -> do_package_write_X)
+ # or indirect dependencies within PN (do_populate_sdk_ext -> do_rootfs -> do_package_write_X)
+ while start:
+ next = []
+ for dep2 in start:
+ for dep in taskdepdata[dep2][3]:
+ if taskdepdata[dep][0] != pn:
+ if "do_" + taskname in dep:
+ pkgdeps.add(dep)
+ elif dep not in seen:
+ next.append(dep)
+ seen.add(dep)
+ start = next
+
+ for dep in pkgdeps:
+ c = taskdepdata[dep][0]
+ manifest, d2 = oe.sstatesig.find_sstate_manifest(c, taskdepdata[dep][2], taskname, d, multilibs)
+ if not manifest:
+ bb.fatal("No manifest generated from: %s in %s" % (c, taskdepdata[dep][2]))
+ if not os.path.exists(manifest):
+ continue
+ with open(manifest, "r") as f:
+ for l in f:
+ l = l.strip()
+ deploydir = os.path.normpath(deploydir)
+ if bb.data.inherits_class('packagefeed-stability', d):
+ dest = l.replace(deploydir + "-prediff", "")
+ else:
+ dest = l.replace(deploydir, "")
+ dest = subrepo_dir + dest
+ if l.endswith("/"):
+ if dest not in seendirs:
+ bb.utils.mkdirhier(dest)
+ seendirs.add(dest)
+ continue
+ # Try to hardlink the file, copy if that fails
+ destdir = os.path.dirname(dest)
+ if destdir not in seendirs:
+ bb.utils.mkdirhier(destdir)
+ seendirs.add(destdir)
+ try:
+ os.link(l, dest)
+ except OSError as err:
+ if err.errno == errno.EXDEV:
+ bb.utils.copyfile(l, dest)
+ else:
+ raise
+
+
+def generate_index_files(d):
+ from oe.package_manager.rpm import RpmSubdirIndexer
+ from oe.package_manager.ipk import OpkgIndexer
+ from oe.package_manager.deb import DpkgIndexer
+
+ classes = d.getVar('PACKAGE_CLASSES').replace("package_", "").split()
+
+ indexer_map = {
+ "rpm": (RpmSubdirIndexer, d.getVar('DEPLOY_DIR_RPM')),
+ "ipk": (OpkgIndexer, d.getVar('DEPLOY_DIR_IPK')),
+ "deb": (DpkgIndexer, d.getVar('DEPLOY_DIR_DEB'))
+ }
+
+ result = None
+
+ for pkg_class in classes:
+ if not pkg_class in indexer_map:
+ continue
+
+ if os.path.exists(indexer_map[pkg_class][1]):
+ result = indexer_map[pkg_class][0](d, indexer_map[pkg_class][1]).write_index()
+
+ if result is not None:
+ bb.fatal(result)
diff --git a/meta/lib/oe/package_manager/deb/__init__.py b/meta/lib/oe/package_manager/deb/__init__.py
new file mode 100644
index 0000000000..0c23c884c1
--- /dev/null
+++ b/meta/lib/oe/package_manager/deb/__init__.py
@@ -0,0 +1,522 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: GPL-2.0-only
+#
+
+import re
+import subprocess
+from oe.package_manager import *
+
+class DpkgIndexer(Indexer):
+ def _create_configs(self):
+ bb.utils.mkdirhier(self.apt_conf_dir)
+ bb.utils.mkdirhier(os.path.join(self.apt_conf_dir, "lists", "partial"))
+ bb.utils.mkdirhier(os.path.join(self.apt_conf_dir, "apt.conf.d"))
+ bb.utils.mkdirhier(os.path.join(self.apt_conf_dir, "preferences.d"))
+
+ with open(os.path.join(self.apt_conf_dir, "preferences"),
+ "w") as prefs_file:
+ pass
+ with open(os.path.join(self.apt_conf_dir, "sources.list"),
+ "w+") as sources_file:
+ pass
+
+ with open(self.apt_conf_file, "w") as apt_conf:
+ with open(os.path.join(self.d.expand("${STAGING_ETCDIR_NATIVE}"),
+ "apt", "apt.conf.sample")) as apt_conf_sample:
+ for line in apt_conf_sample.read().split("\n"):
+ line = re.sub(r"#ROOTFS#", "/dev/null", line)
+ line = re.sub(r"#APTCONF#", self.apt_conf_dir, line)
+ apt_conf.write(line + "\n")
+
+ def write_index(self):
+ self.apt_conf_dir = os.path.join(self.d.expand("${APTCONF_TARGET}"),
+ "apt-ftparchive")
+ self.apt_conf_file = os.path.join(self.apt_conf_dir, "apt.conf")
+ self._create_configs()
+
+ os.environ['APT_CONFIG'] = self.apt_conf_file
+
+ pkg_archs = self.d.getVar('PACKAGE_ARCHS')
+ if pkg_archs is not None:
+ arch_list = pkg_archs.split()
+ sdk_pkg_archs = self.d.getVar('SDK_PACKAGE_ARCHS')
+ if sdk_pkg_archs is not None:
+ for a in sdk_pkg_archs.split():
+ if a not in pkg_archs:
+ arch_list.append(a)
+
+ all_mlb_pkg_arch_list = (self.d.getVar('ALL_MULTILIB_PACKAGE_ARCHS') or "").split()
+ arch_list.extend(arch for arch in all_mlb_pkg_arch_list if arch not in arch_list)
+
+ apt_ftparchive = bb.utils.which(os.getenv('PATH'), "apt-ftparchive")
+ gzip = bb.utils.which(os.getenv('PATH'), "gzip")
+
+ index_cmds = []
+ deb_dirs_found = False
+ index_sign_files = set()
+ for arch in arch_list:
+ arch_dir = os.path.join(self.deploy_dir, arch)
+ if not os.path.isdir(arch_dir):
+ continue
+
+ cmd = "cd %s; PSEUDO_UNLOAD=1 %s packages . > Packages;" % (arch_dir, apt_ftparchive)
+
+ cmd += "%s -fcn Packages > Packages.gz;" % gzip
+
+ release_file = os.path.join(arch_dir, "Release")
+ index_sign_files.add(release_file)
+
+ with open(release_file, "w+") as release:
+ release.write("Label: %s\n" % arch)
+
+ cmd += "PSEUDO_UNLOAD=1 %s release . >> Release" % apt_ftparchive
+
+ index_cmds.append(cmd)
+
+ deb_dirs_found = True
+
+ if not deb_dirs_found:
+ bb.note("There are no packages in %s" % self.deploy_dir)
+ return
+
+ oe.utils.multiprocess_launch(create_index, index_cmds, self.d)
+ if self.d.getVar('PACKAGE_FEED_SIGN') == '1':
+ signer = get_signer(self.d, self.d.getVar('PACKAGE_FEED_GPG_BACKEND'))
+ else:
+ signer = None
+ if signer:
+ for f in index_sign_files:
+ signer.detach_sign(f,
+ self.d.getVar('PACKAGE_FEED_GPG_NAME'),
+ self.d.getVar('PACKAGE_FEED_GPG_PASSPHRASE_FILE'),
+ output_suffix="gpg",
+ use_sha256=True)
+
+class PMPkgsList(PkgsList):
+
+ def list_pkgs(self):
+ cmd = [bb.utils.which(os.getenv('PATH'), "dpkg-query"),
+ "--admindir=%s/var/lib/dpkg" % self.rootfs_dir,
+ "-W"]
+
+ cmd.append("-f=Package: ${Package}\nArchitecture: ${PackageArch}\nVersion: ${Version}\nFile: ${Package}_${Version}_${Architecture}.deb\nDepends: ${Depends}\nRecommends: ${Recommends}\nProvides: ${Provides}\n\n")
+
+ try:
+ cmd_output = subprocess.check_output(cmd, stderr=subprocess.STDOUT).strip().decode("utf-8")
+ except subprocess.CalledProcessError as e:
+ bb.fatal("Cannot get the installed packages list. Command '%s' "
+ "returned %d:\n%s" % (' '.join(cmd), e.returncode, e.output.decode("utf-8")))
+
+ return opkg_query(cmd_output)
+
+class OpkgDpkgPM(PackageManager):
+ def __init__(self, d, target_rootfs):
+ """
+ This is an abstract class. Do not instantiate this directly.
+ """
+ super(OpkgDpkgPM, self).__init__(d, target_rootfs)
+
+ def package_info(self, pkg, cmd):
+ """
+ Returns a dictionary with the package info.
+
+ This method extracts the common parts for Opkg and Dpkg
+ """
+
+ try:
+ output = subprocess.check_output(cmd, stderr=subprocess.STDOUT, shell=True).decode("utf-8")
+ except subprocess.CalledProcessError as e:
+ bb.fatal("Unable to list available packages. Command '%s' "
+ "returned %d:\n%s" % (cmd, e.returncode, e.output.decode("utf-8")))
+ return opkg_query(output)
+
+ def extract(self, pkg, pkg_info):
+ """
+ Returns the path to a tmpdir where resides the contents of a package.
+
+ Deleting the tmpdir is responsability of the caller.
+
+ This method extracts the common parts for Opkg and Dpkg
+ """
+
+ ar_cmd = bb.utils.which(os.getenv("PATH"), "ar")
+ tar_cmd = bb.utils.which(os.getenv("PATH"), "tar")
+ pkg_path = pkg_info[pkg]["filepath"]
+
+ if not os.path.isfile(pkg_path):
+ bb.fatal("Unable to extract package for '%s'."
+ "File %s doesn't exists" % (pkg, pkg_path))
+
+ tmp_dir = tempfile.mkdtemp()
+ current_dir = os.getcwd()
+ os.chdir(tmp_dir)
+ data_tar = 'data.tar.xz'
+
+ try:
+ cmd = [ar_cmd, 'x', pkg_path]
+ output = subprocess.check_output(cmd, stderr=subprocess.STDOUT)
+ cmd = [tar_cmd, 'xf', data_tar]
+ output = subprocess.check_output(cmd, stderr=subprocess.STDOUT)
+ except subprocess.CalledProcessError as e:
+ bb.utils.remove(tmp_dir, recurse=True)
+ bb.fatal("Unable to extract %s package. Command '%s' "
+ "returned %d:\n%s" % (pkg_path, ' '.join(cmd), e.returncode, e.output.decode("utf-8")))
+ except OSError as e:
+ bb.utils.remove(tmp_dir, recurse=True)
+ bb.fatal("Unable to extract %s package. Command '%s' "
+ "returned %d:\n%s at %s" % (pkg_path, ' '.join(cmd), e.errno, e.strerror, e.filename))
+
+ bb.note("Extracted %s to %s" % (pkg_path, tmp_dir))
+ bb.utils.remove(os.path.join(tmp_dir, "debian-binary"))
+ bb.utils.remove(os.path.join(tmp_dir, "control.tar.gz"))
+ os.chdir(current_dir)
+
+ return tmp_dir
+
+ def _handle_intercept_failure(self, registered_pkgs):
+ self.mark_packages("unpacked", registered_pkgs.split())
+
+class DpkgPM(OpkgDpkgPM):
+ def __init__(self, d, target_rootfs, archs, base_archs, apt_conf_dir=None, deb_repo_workdir="oe-rootfs-repo", filterbydependencies=True):
+ super(DpkgPM, self).__init__(d, target_rootfs)
+ self.deploy_dir = oe.path.join(self.d.getVar('WORKDIR'), deb_repo_workdir)
+
+ create_packages_dir(self.d, self.deploy_dir, d.getVar("DEPLOY_DIR_DEB"), "package_write_deb", filterbydependencies)
+
+ if apt_conf_dir is None:
+ self.apt_conf_dir = self.d.expand("${APTCONF_TARGET}/apt")
+ else:
+ self.apt_conf_dir = apt_conf_dir
+ self.apt_conf_file = os.path.join(self.apt_conf_dir, "apt.conf")
+ self.apt_get_cmd = bb.utils.which(os.getenv('PATH'), "apt-get")
+ self.apt_cache_cmd = bb.utils.which(os.getenv('PATH'), "apt-cache")
+
+ self.apt_args = d.getVar("APT_ARGS")
+
+ self.all_arch_list = archs.split()
+ all_mlb_pkg_arch_list = (self.d.getVar('ALL_MULTILIB_PACKAGE_ARCHS') or "").split()
+ self.all_arch_list.extend(arch for arch in all_mlb_pkg_arch_list if arch not in self.all_arch_list)
+
+ self._create_configs(archs, base_archs)
+
+ self.indexer = DpkgIndexer(self.d, self.deploy_dir)
+
+ def mark_packages(self, status_tag, packages=None):
+ """
+ This function will change a package's status in /var/lib/dpkg/status file.
+ If 'packages' is None then the new_status will be applied to all
+ packages
+ """
+ status_file = self.target_rootfs + "/var/lib/dpkg/status"
+
+ with open(status_file, "r") as sf:
+ with open(status_file + ".tmp", "w+") as tmp_sf:
+ if packages is None:
+ tmp_sf.write(re.sub(r"Package: (.*?)\n((?:[^\n]+\n)*?)Status: (.*)(?:unpacked|installed)",
+ r"Package: \1\n\2Status: \3%s" % status_tag,
+ sf.read()))
+ else:
+ if type(packages).__name__ != "list":
+ raise TypeError("'packages' should be a list object")
+
+ status = sf.read()
+ for pkg in packages:
+ status = re.sub(r"Package: %s\n((?:[^\n]+\n)*?)Status: (.*)(?:unpacked|installed)" % pkg,
+ r"Package: %s\n\1Status: \2%s" % (pkg, status_tag),
+ status)
+
+ tmp_sf.write(status)
+
+ bb.utils.rename(status_file + ".tmp", status_file)
+
+ def run_pre_post_installs(self, package_name=None):
+ """
+ Run the pre/post installs for package "package_name". If package_name is
+ None, then run all pre/post install scriptlets.
+ """
+ info_dir = self.target_rootfs + "/var/lib/dpkg/info"
+ ControlScript = collections.namedtuple("ControlScript", ["suffix", "name", "argument"])
+ control_scripts = [
+ ControlScript(".preinst", "Preinstall", "install"),
+ ControlScript(".postinst", "Postinstall", "configure")]
+ status_file = self.target_rootfs + "/var/lib/dpkg/status"
+ installed_pkgs = []
+
+ with open(status_file, "r") as status:
+ for line in status.read().split('\n'):
+ m = re.match(r"^Package: (.*)", line)
+ if m is not None:
+ installed_pkgs.append(m.group(1))
+
+ if package_name is not None and not package_name in installed_pkgs:
+ return
+
+ os.environ['D'] = self.target_rootfs
+ os.environ['OFFLINE_ROOT'] = self.target_rootfs
+ os.environ['IPKG_OFFLINE_ROOT'] = self.target_rootfs
+ os.environ['OPKG_OFFLINE_ROOT'] = self.target_rootfs
+ os.environ['INTERCEPT_DIR'] = self.intercepts_dir
+ os.environ['NATIVE_ROOT'] = self.d.getVar('STAGING_DIR_NATIVE')
+
+ for pkg_name in installed_pkgs:
+ for control_script in control_scripts:
+ p_full = os.path.join(info_dir, pkg_name + control_script.suffix)
+ if os.path.exists(p_full):
+ try:
+ bb.note("Executing %s for package: %s ..." %
+ (control_script.name.lower(), pkg_name))
+ output = subprocess.check_output([p_full, control_script.argument],
+ stderr=subprocess.STDOUT).decode("utf-8")
+ bb.note(output)
+ except subprocess.CalledProcessError as e:
+ bb.warn("%s for package %s failed with %d:\n%s" %
+ (control_script.name, pkg_name, e.returncode,
+ e.output.decode("utf-8")))
+ failed_postinsts_abort([pkg_name], self.d.expand("${T}/log.do_${BB_CURRENTTASK}"))
+
+ def update(self):
+ os.environ['APT_CONFIG'] = self.apt_conf_file
+
+ self.deploy_dir_lock()
+
+ cmd = "%s update" % self.apt_get_cmd
+
+ try:
+ subprocess.check_output(cmd.split(), stderr=subprocess.STDOUT)
+ except subprocess.CalledProcessError as e:
+ bb.fatal("Unable to update the package index files. Command '%s' "
+ "returned %d:\n%s" % (e.cmd, e.returncode, e.output.decode("utf-8")))
+
+ self.deploy_dir_unlock()
+
+ def install(self, pkgs, attempt_only=False, hard_depends_only=False):
+ if attempt_only and len(pkgs) == 0:
+ return
+
+ os.environ['APT_CONFIG'] = self.apt_conf_file
+
+ extra_args = ""
+ if hard_depends_only:
+ extra_args = "--no-install-recommends"
+
+ cmd = "%s %s install --allow-downgrades --allow-remove-essential --allow-change-held-packages --allow-unauthenticated --no-remove %s %s" % \
+ (self.apt_get_cmd, self.apt_args, extra_args, ' '.join(pkgs))
+
+ try:
+ bb.note("Installing the following packages: %s" % ' '.join(pkgs))
+ output = subprocess.check_output(cmd.split(), stderr=subprocess.STDOUT)
+ bb.note(output.decode("utf-8"))
+ except subprocess.CalledProcessError as e:
+ (bb.fatal, bb.warn)[attempt_only]("Unable to install packages. "
+ "Command '%s' returned %d:\n%s" %
+ (cmd, e.returncode, e.output.decode("utf-8")))
+
+ # rename *.dpkg-new files/dirs
+ for root, dirs, files in os.walk(self.target_rootfs):
+ for dir in dirs:
+ new_dir = re.sub(r"\.dpkg-new", "", dir)
+ if dir != new_dir:
+ bb.utils.rename(os.path.join(root, dir),
+ os.path.join(root, new_dir))
+
+ for file in files:
+ new_file = re.sub(r"\.dpkg-new", "", file)
+ if file != new_file:
+ bb.utils.rename(os.path.join(root, file),
+ os.path.join(root, new_file))
+
+
+ def remove(self, pkgs, with_dependencies=True):
+ if not pkgs:
+ return
+
+ os.environ['D'] = self.target_rootfs
+ os.environ['OFFLINE_ROOT'] = self.target_rootfs
+ os.environ['IPKG_OFFLINE_ROOT'] = self.target_rootfs
+ os.environ['OPKG_OFFLINE_ROOT'] = self.target_rootfs
+ os.environ['INTERCEPT_DIR'] = self.intercepts_dir
+
+ if with_dependencies:
+ os.environ['APT_CONFIG'] = self.apt_conf_file
+ cmd = "%s purge %s" % (self.apt_get_cmd, ' '.join(pkgs))
+ else:
+ cmd = "%s --admindir=%s/var/lib/dpkg --instdir=%s" \
+ " -P --force-depends %s" % \
+ (bb.utils.which(os.getenv('PATH'), "dpkg"),
+ self.target_rootfs, self.target_rootfs, ' '.join(pkgs))
+
+ try:
+ subprocess.check_output(cmd.split(), stderr=subprocess.STDOUT)
+ except subprocess.CalledProcessError as e:
+ bb.fatal("Unable to remove packages. Command '%s' "
+ "returned %d:\n%s" % (e.cmd, e.returncode, e.output.decode("utf-8")))
+
+ def write_index(self):
+ self.deploy_dir_lock()
+
+ result = self.indexer.write_index()
+
+ self.deploy_dir_unlock()
+
+ if result is not None:
+ bb.fatal(result)
+
+ def insert_feeds_uris(self, feed_uris, feed_base_paths, feed_archs):
+ if feed_uris == "":
+ return
+
+
+ sources_conf = os.path.join("%s/etc/apt/sources.list"
+ % self.target_rootfs)
+ if not os.path.exists(os.path.dirname(sources_conf)):
+ return
+
+ arch_list = []
+
+ if feed_archs is None:
+ for arch in self.all_arch_list:
+ if not os.path.exists(os.path.join(self.deploy_dir, arch)):
+ continue
+ arch_list.append(arch)
+ else:
+ arch_list = feed_archs.split()
+
+ feed_uris = self.construct_uris(feed_uris.split(), feed_base_paths.split())
+
+ with open(sources_conf, "w+") as sources_file:
+ for uri in feed_uris:
+ if arch_list:
+ for arch in arch_list:
+ bb.note('Adding dpkg channel at (%s)' % uri)
+ sources_file.write("deb [trusted=yes] %s/%s ./\n" %
+ (uri, arch))
+ else:
+ bb.note('Adding dpkg channel at (%s)' % uri)
+ sources_file.write("deb [trusted=yes] %s ./\n" % uri)
+
+ def _create_configs(self, archs, base_archs):
+ base_archs = re.sub(r"_", r"-", base_archs)
+
+ if os.path.exists(self.apt_conf_dir):
+ bb.utils.remove(self.apt_conf_dir, True)
+
+ bb.utils.mkdirhier(self.apt_conf_dir)
+ bb.utils.mkdirhier(self.apt_conf_dir + "/lists/partial/")
+ bb.utils.mkdirhier(self.apt_conf_dir + "/apt.conf.d/")
+ bb.utils.mkdirhier(self.apt_conf_dir + "/preferences.d/")
+
+ arch_list = []
+ for arch in self.all_arch_list:
+ if not os.path.exists(os.path.join(self.deploy_dir, arch)):
+ continue
+ arch_list.append(arch)
+
+ with open(os.path.join(self.apt_conf_dir, "preferences"), "w+") as prefs_file:
+ priority = 801
+ for arch in arch_list:
+ prefs_file.write(
+ "Package: *\n"
+ "Pin: release l=%s\n"
+ "Pin-Priority: %d\n\n" % (arch, priority))
+
+ priority += 5
+
+ pkg_exclude = self.d.getVar('PACKAGE_EXCLUDE') or ""
+ for pkg in pkg_exclude.split():
+ prefs_file.write(
+ "Package: %s\n"
+ "Pin: release *\n"
+ "Pin-Priority: -1\n\n" % pkg)
+
+ arch_list.reverse()
+
+ with open(os.path.join(self.apt_conf_dir, "sources.list"), "w+") as sources_file:
+ for arch in arch_list:
+ sources_file.write("deb [trusted=yes] file:%s/ ./\n" %
+ os.path.join(self.deploy_dir, arch))
+
+ base_arch_list = base_archs.split()
+ multilib_variants = self.d.getVar("MULTILIB_VARIANTS");
+ for variant in multilib_variants.split():
+ localdata = bb.data.createCopy(self.d)
+ variant_tune = localdata.getVar("DEFAULTTUNE:virtclass-multilib-" + variant, False)
+ orig_arch = localdata.getVar("DPKG_ARCH")
+ localdata.setVar("DEFAULTTUNE", variant_tune)
+ variant_arch = localdata.getVar("DPKG_ARCH")
+ if variant_arch not in base_arch_list:
+ base_arch_list.append(variant_arch)
+
+ with open(self.apt_conf_file, "w+") as apt_conf:
+ with open(self.d.expand("${STAGING_ETCDIR_NATIVE}/apt/apt.conf.sample")) as apt_conf_sample:
+ for line in apt_conf_sample.read().split("\n"):
+ match_arch = re.match(r" Architecture \".*\";$", line)
+ architectures = ""
+ if match_arch:
+ for base_arch in base_arch_list:
+ architectures += "\"%s\";" % base_arch
+ apt_conf.write(" Architectures {%s};\n" % architectures);
+ apt_conf.write(" Architecture \"%s\";\n" % base_archs)
+ else:
+ line = re.sub(r"#ROOTFS#", self.target_rootfs, line)
+ line = re.sub(r"#APTCONF#", self.apt_conf_dir, line)
+ apt_conf.write(line + "\n")
+
+ target_dpkg_dir = "%s/var/lib/dpkg" % self.target_rootfs
+ bb.utils.mkdirhier(os.path.join(target_dpkg_dir, "info"))
+
+ bb.utils.mkdirhier(os.path.join(target_dpkg_dir, "updates"))
+
+ if not os.path.exists(os.path.join(target_dpkg_dir, "status")):
+ open(os.path.join(target_dpkg_dir, "status"), "w+").close()
+ if not os.path.exists(os.path.join(target_dpkg_dir, "available")):
+ open(os.path.join(target_dpkg_dir, "available"), "w+").close()
+
+ def remove_packaging_data(self):
+ bb.utils.remove(self.target_rootfs + self.d.getVar('opkglibdir'), True)
+ bb.utils.remove(self.target_rootfs + "/var/lib/dpkg/", True)
+
+ def fix_broken_dependencies(self):
+ os.environ['APT_CONFIG'] = self.apt_conf_file
+
+ cmd = "%s %s --allow-unauthenticated -f install" % (self.apt_get_cmd, self.apt_args)
+
+ try:
+ subprocess.check_output(cmd.split(), stderr=subprocess.STDOUT)
+ except subprocess.CalledProcessError as e:
+ bb.fatal("Cannot fix broken dependencies. Command '%s' "
+ "returned %d:\n%s" % (cmd, e.returncode, e.output.decode("utf-8")))
+
+ def list_installed(self):
+ return PMPkgsList(self.d, self.target_rootfs).list_pkgs()
+
+ def package_info(self, pkg):
+ """
+ Returns a dictionary with the package info.
+ """
+ cmd = "%s show %s" % (self.apt_cache_cmd, pkg)
+ pkg_info = super(DpkgPM, self).package_info(pkg, cmd)
+
+ pkg_arch = pkg_info[pkg]["pkgarch"]
+ pkg_filename = pkg_info[pkg]["filename"]
+ pkg_info[pkg]["filepath"] = \
+ os.path.join(self.deploy_dir, pkg_arch, pkg_filename)
+
+ return pkg_info
+
+ def extract(self, pkg):
+ """
+ Returns the path to a tmpdir where resides the contents of a package.
+
+ Deleting the tmpdir is responsability of the caller.
+ """
+ pkg_info = self.package_info(pkg)
+ if not pkg_info:
+ bb.fatal("Unable to get information for package '%s' while "
+ "trying to extract the package." % pkg)
+
+ tmp_dir = super(DpkgPM, self).extract(pkg, pkg_info)
+ bb.utils.remove(os.path.join(tmp_dir, "data.tar.xz"))
+
+ return tmp_dir
diff --git a/meta/lib/oe/package_manager/deb/manifest.py b/meta/lib/oe/package_manager/deb/manifest.py
new file mode 100644
index 0000000000..72983bae98
--- /dev/null
+++ b/meta/lib/oe/package_manager/deb/manifest.py
@@ -0,0 +1,28 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: GPL-2.0-only
+#
+
+from oe.manifest import Manifest
+
+class PkgManifest(Manifest):
+ def create_initial(self):
+ with open(self.initial_manifest, "w+") as manifest:
+ manifest.write(self.initial_manifest_file_header)
+
+ for var in self.var_maps[self.manifest_type]:
+ pkg_list = self.d.getVar(var)
+
+ if pkg_list is None:
+ continue
+
+ for pkg in pkg_list.split():
+ manifest.write("%s,%s\n" %
+ (self.var_maps[self.manifest_type][var], pkg))
+
+ def create_final(self):
+ pass
+
+ def create_full(self, pm):
+ pass
diff --git a/meta/lib/oe/package_manager/deb/rootfs.py b/meta/lib/oe/package_manager/deb/rootfs.py
new file mode 100644
index 0000000000..1e25b64ed9
--- /dev/null
+++ b/meta/lib/oe/package_manager/deb/rootfs.py
@@ -0,0 +1,212 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: GPL-2.0-only
+#
+
+import re
+import shutil
+from oe.rootfs import Rootfs
+from oe.manifest import Manifest
+from oe.utils import execute_pre_post_process
+from oe.package_manager.deb.manifest import PkgManifest
+from oe.package_manager.deb import DpkgPM
+
+class DpkgOpkgRootfs(Rootfs):
+ def __init__(self, d, progress_reporter=None, logcatcher=None):
+ super(DpkgOpkgRootfs, self).__init__(d, progress_reporter, logcatcher)
+
+ def _get_pkgs_postinsts(self, status_file):
+ def _get_pkg_depends_list(pkg_depends):
+ pkg_depends_list = []
+ # filter version requirements like libc (>= 1.1)
+ for dep in pkg_depends.split(', '):
+ m_dep = re.match(r"^(.*) \(.*\)$", dep)
+ if m_dep:
+ dep = m_dep.group(1)
+ pkg_depends_list.append(dep)
+
+ return pkg_depends_list
+
+ pkgs = {}
+ pkg_name = ""
+ pkg_status_match = False
+ pkg_depends = ""
+
+ with open(status_file) as status:
+ data = status.read()
+ status.close()
+ for line in data.split('\n'):
+ m_pkg = re.match(r"^Package: (.*)", line)
+ m_status = re.match(r"^Status:.*unpacked", line)
+ m_depends = re.match(r"^Depends: (.*)", line)
+
+ #Only one of m_pkg, m_status or m_depends is not None at time
+ #If m_pkg is not None, we started a new package
+ if m_pkg is not None:
+ #Get Package name
+ pkg_name = m_pkg.group(1)
+ #Make sure we reset other variables
+ pkg_status_match = False
+ pkg_depends = ""
+ elif m_status is not None:
+ #New status matched
+ pkg_status_match = True
+ elif m_depends is not None:
+ #New depends macthed
+ pkg_depends = m_depends.group(1)
+ else:
+ pass
+
+ #Now check if we can process package depends and postinst
+ if "" != pkg_name and pkg_status_match:
+ pkgs[pkg_name] = _get_pkg_depends_list(pkg_depends)
+ else:
+ #Not enough information
+ pass
+
+ # remove package dependencies not in postinsts
+ pkg_names = list(pkgs.keys())
+ for pkg_name in pkg_names:
+ deps = pkgs[pkg_name][:]
+
+ for d in deps:
+ if d not in pkg_names:
+ pkgs[pkg_name].remove(d)
+
+ return pkgs
+
+ def _get_delayed_postinsts_common(self, status_file):
+ def _dep_resolve(graph, node, resolved, seen):
+ seen.append(node)
+
+ for edge in graph[node]:
+ if edge not in resolved:
+ if edge in seen:
+ raise RuntimeError("Packages %s and %s have " \
+ "a circular dependency in postinsts scripts." \
+ % (node, edge))
+ _dep_resolve(graph, edge, resolved, seen)
+
+ resolved.append(node)
+
+ pkg_list = []
+
+ pkgs = None
+ if not self.d.getVar('PACKAGE_INSTALL').strip():
+ bb.note("Building empty image")
+ else:
+ pkgs = self._get_pkgs_postinsts(status_file)
+ if pkgs:
+ root = "__packagegroup_postinst__"
+ pkgs[root] = list(pkgs.keys())
+ _dep_resolve(pkgs, root, pkg_list, [])
+ pkg_list.remove(root)
+
+ if len(pkg_list) == 0:
+ return None
+
+ return pkg_list
+
+ def _save_postinsts_common(self, dst_postinst_dir, src_postinst_dir):
+ if bb.utils.contains("IMAGE_FEATURES", "package-management",
+ True, False, self.d):
+ return
+ num = 0
+ for p in self._get_delayed_postinsts():
+ bb.utils.mkdirhier(dst_postinst_dir)
+
+ if os.path.exists(os.path.join(src_postinst_dir, p + ".postinst")):
+ shutil.copy(os.path.join(src_postinst_dir, p + ".postinst"),
+ os.path.join(dst_postinst_dir, "%03d-%s" % (num, p)))
+
+ num += 1
+
+class PkgRootfs(DpkgOpkgRootfs):
+ def __init__(self, d, manifest_dir, progress_reporter=None, logcatcher=None):
+ super(PkgRootfs, self).__init__(d, progress_reporter, logcatcher)
+ self.log_check_regex = '^E:'
+ self.log_check_expected_regexes = \
+ [
+ "^E: Unmet dependencies."
+ ]
+
+ bb.utils.remove(self.image_rootfs, True)
+ bb.utils.remove(self.d.getVar('MULTILIB_TEMP_ROOTFS'), True)
+ self.manifest = PkgManifest(d, manifest_dir)
+ self.pm = DpkgPM(d, d.getVar('IMAGE_ROOTFS'),
+ d.getVar('PACKAGE_ARCHS'),
+ d.getVar('DPKG_ARCH'))
+
+
+ def _create(self):
+ pkgs_to_install = self.manifest.parse_initial_manifest()
+ deb_pre_process_cmds = self.d.getVar('DEB_PREPROCESS_COMMANDS')
+ deb_post_process_cmds = self.d.getVar('DEB_POSTPROCESS_COMMANDS')
+
+ alt_dir = self.d.expand("${IMAGE_ROOTFS}/var/lib/dpkg/alternatives")
+ bb.utils.mkdirhier(alt_dir)
+
+ # update PM index files
+ self.pm.write_index()
+
+ execute_pre_post_process(self.d, deb_pre_process_cmds)
+
+ if self.progress_reporter:
+ self.progress_reporter.next_stage()
+ # Don't support incremental, so skip that
+ self.progress_reporter.next_stage()
+
+ self.pm.update()
+
+ if self.progress_reporter:
+ self.progress_reporter.next_stage()
+
+ for pkg_type in self.install_order:
+ if pkg_type in pkgs_to_install:
+ self.pm.install(pkgs_to_install[pkg_type],
+ [False, True][pkg_type == Manifest.PKG_TYPE_ATTEMPT_ONLY])
+ self.pm.fix_broken_dependencies()
+
+ if self.progress_reporter:
+ # Don't support attemptonly, so skip that
+ self.progress_reporter.next_stage()
+ self.progress_reporter.next_stage()
+
+ self.pm.install_complementary()
+
+ if self.progress_reporter:
+ self.progress_reporter.next_stage()
+
+ self._setup_dbg_rootfs(['/var/lib/dpkg'])
+
+ self.pm.fix_broken_dependencies()
+
+ self.pm.mark_packages("installed")
+
+ self.pm.run_pre_post_installs()
+
+ execute_pre_post_process(self.d, deb_post_process_cmds)
+
+ if self.progress_reporter:
+ self.progress_reporter.next_stage()
+
+ @staticmethod
+ def _depends_list():
+ return ['DEPLOY_DIR_DEB', 'DEB_SDK_ARCH', 'APTCONF_TARGET', 'APT_ARGS', 'DPKG_ARCH', 'DEB_PREPROCESS_COMMANDS', 'DEB_POSTPROCESS_COMMANDS']
+
+ def _get_delayed_postinsts(self):
+ status_file = self.image_rootfs + "/var/lib/dpkg/status"
+ return self._get_delayed_postinsts_common(status_file)
+
+ def _save_postinsts(self):
+ dst_postinst_dir = self.d.expand("${IMAGE_ROOTFS}${sysconfdir}/deb-postinsts")
+ src_postinst_dir = self.d.expand("${IMAGE_ROOTFS}/var/lib/dpkg/info")
+ return self._save_postinsts_common(dst_postinst_dir, src_postinst_dir)
+
+ def _log_check(self):
+ self._log_check_warn()
+ self._log_check_error()
+
+ def _cleanup(self):
+ pass
diff --git a/meta/lib/oe/package_manager/deb/sdk.py b/meta/lib/oe/package_manager/deb/sdk.py
new file mode 100644
index 0000000000..653e42ab3c
--- /dev/null
+++ b/meta/lib/oe/package_manager/deb/sdk.py
@@ -0,0 +1,102 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: GPL-2.0-only
+#
+
+import glob
+import shutil
+from oe.utils import execute_pre_post_process
+from oe.sdk import Sdk
+from oe.manifest import Manifest
+from oe.package_manager.deb import DpkgPM
+from oe.package_manager.deb.manifest import PkgManifest
+
+class PkgSdk(Sdk):
+ def __init__(self, d, manifest_dir=None):
+ super(PkgSdk, self).__init__(d, manifest_dir)
+
+ self.target_conf_dir = os.path.join(self.d.getVar("APTCONF_TARGET"), "apt")
+ self.host_conf_dir = os.path.join(self.d.getVar("APTCONF_TARGET"), "apt-sdk")
+
+
+ self.target_manifest = PkgManifest(d, self.manifest_dir,
+ Manifest.MANIFEST_TYPE_SDK_TARGET)
+ self.host_manifest = PkgManifest(d, self.manifest_dir,
+ Manifest.MANIFEST_TYPE_SDK_HOST)
+
+ deb_repo_workdir = "oe-sdk-repo"
+ if "sdk_ext" in d.getVar("BB_RUNTASK"):
+ deb_repo_workdir = "oe-sdk-ext-repo"
+
+ self.target_pm = DpkgPM(d, self.sdk_target_sysroot,
+ self.d.getVar("PACKAGE_ARCHS"),
+ self.d.getVar("DPKG_ARCH"),
+ self.target_conf_dir,
+ deb_repo_workdir=deb_repo_workdir)
+
+ self.host_pm = DpkgPM(d, self.sdk_host_sysroot,
+ self.d.getVar("SDK_PACKAGE_ARCHS"),
+ self.d.getVar("DEB_SDK_ARCH"),
+ self.host_conf_dir,
+ deb_repo_workdir=deb_repo_workdir)
+
+ def _copy_apt_dir_to(self, dst_dir):
+ staging_etcdir_native = self.d.getVar("STAGING_ETCDIR_NATIVE")
+
+ self.remove(dst_dir, True)
+
+ shutil.copytree(os.path.join(staging_etcdir_native, "apt"), dst_dir)
+
+ def _populate_sysroot(self, pm, manifest):
+ pkgs_to_install = manifest.parse_initial_manifest()
+
+ pm.write_index()
+ pm.update()
+
+ for pkg_type in self.install_order:
+ if pkg_type in pkgs_to_install:
+ pm.install(pkgs_to_install[pkg_type],
+ [False, True][pkg_type == Manifest.PKG_TYPE_ATTEMPT_ONLY])
+
+ def _populate(self):
+ execute_pre_post_process(self.d, self.d.getVar("POPULATE_SDK_PRE_TARGET_COMMAND"))
+
+ bb.note("Installing TARGET packages")
+ self._populate_sysroot(self.target_pm, self.target_manifest)
+
+ self.target_pm.install_complementary(self.d.getVar('SDKIMAGE_INSTALL_COMPLEMENTARY'))
+
+ self.target_pm.run_pre_post_installs()
+
+ self.target_pm.run_intercepts(populate_sdk='target')
+
+ execute_pre_post_process(self.d, self.d.getVar("POPULATE_SDK_POST_TARGET_COMMAND"))
+
+ self._copy_apt_dir_to(os.path.join(self.sdk_target_sysroot, "etc", "apt"))
+
+ if not bb.utils.contains("SDKIMAGE_FEATURES", "package-management", True, False, self.d):
+ self.target_pm.remove_packaging_data()
+
+ bb.note("Installing NATIVESDK packages")
+ self._populate_sysroot(self.host_pm, self.host_manifest)
+ self.install_locales(self.host_pm)
+
+ self.host_pm.run_pre_post_installs()
+
+ self.host_pm.run_intercepts(populate_sdk='host')
+
+ execute_pre_post_process(self.d, self.d.getVar("POPULATE_SDK_POST_HOST_COMMAND"))
+
+ self._copy_apt_dir_to(os.path.join(self.sdk_output, self.sdk_native_path,
+ "etc", "apt"))
+
+ if not bb.utils.contains("SDKIMAGE_FEATURES", "package-management", True, False, self.d):
+ self.host_pm.remove_packaging_data()
+
+ native_dpkg_state_dir = os.path.join(self.sdk_output, self.sdk_native_path,
+ "var", "lib", "dpkg")
+ self.mkdirhier(native_dpkg_state_dir)
+ for f in glob.glob(os.path.join(self.sdk_output, "var", "lib", "dpkg", "*")):
+ self.movefile(f, native_dpkg_state_dir)
+ self.remove(os.path.join(self.sdk_output, "var"), True)
diff --git a/meta/lib/oe/package_manager/ipk/__init__.py b/meta/lib/oe/package_manager/ipk/__init__.py
new file mode 100644
index 0000000000..caca522fd6
--- /dev/null
+++ b/meta/lib/oe/package_manager/ipk/__init__.py
@@ -0,0 +1,510 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: GPL-2.0-only
+#
+
+import re
+import shutil
+import subprocess
+from oe.package_manager import *
+
+class OpkgIndexer(Indexer):
+ def write_index(self):
+ arch_vars = ["ALL_MULTILIB_PACKAGE_ARCHS",
+ "SDK_PACKAGE_ARCHS",
+ ]
+
+ opkg_index_cmd = bb.utils.which(os.getenv('PATH'), "opkg-make-index")
+ if self.d.getVar('PACKAGE_FEED_SIGN') == '1':
+ signer = get_signer(self.d, self.d.getVar('PACKAGE_FEED_GPG_BACKEND'))
+ else:
+ signer = None
+
+ if not os.path.exists(os.path.join(self.deploy_dir, "Packages")):
+ open(os.path.join(self.deploy_dir, "Packages"), "w").close()
+
+ index_cmds = set()
+ index_sign_files = set()
+ for arch_var in arch_vars:
+ archs = self.d.getVar(arch_var)
+ if archs is None:
+ continue
+
+ for arch in archs.split():
+ pkgs_dir = os.path.join(self.deploy_dir, arch)
+ pkgs_file = os.path.join(pkgs_dir, "Packages")
+
+ if not os.path.isdir(pkgs_dir):
+ continue
+
+ if not os.path.exists(pkgs_file):
+ open(pkgs_file, "w").close()
+
+ index_cmds.add('%s --checksum md5 --checksum sha256 -r %s -p %s -m %s' %
+ (opkg_index_cmd, pkgs_file, pkgs_file, pkgs_dir))
+
+ index_sign_files.add(pkgs_file)
+
+ if len(index_cmds) == 0:
+ bb.note("There are no packages in %s!" % self.deploy_dir)
+ return
+
+ oe.utils.multiprocess_launch(create_index, index_cmds, self.d)
+
+ if signer:
+ feed_sig_type = self.d.getVar('PACKAGE_FEED_GPG_SIGNATURE_TYPE')
+ is_ascii_sig = (feed_sig_type.upper() != "BIN")
+ for f in index_sign_files:
+ signer.detach_sign(f,
+ self.d.getVar('PACKAGE_FEED_GPG_NAME'),
+ self.d.getVar('PACKAGE_FEED_GPG_PASSPHRASE_FILE'),
+ armor=is_ascii_sig)
+
+class PMPkgsList(PkgsList):
+ def __init__(self, d, rootfs_dir):
+ super(PMPkgsList, self).__init__(d, rootfs_dir)
+ config_file = d.getVar("IPKGCONF_TARGET")
+
+ self.opkg_cmd = bb.utils.which(os.getenv('PATH'), "opkg")
+ self.opkg_args = "-f %s -o %s " % (config_file, rootfs_dir)
+ self.opkg_args += self.d.getVar("OPKG_ARGS")
+
+ def list_pkgs(self, format=None):
+ cmd = "%s %s status" % (self.opkg_cmd, self.opkg_args)
+
+ # opkg returns success even when it printed some
+ # "Collected errors:" report to stderr. Mixing stderr into
+ # stdout then leads to random failures later on when
+ # parsing the output. To avoid this we need to collect both
+ # output streams separately and check for empty stderr.
+ p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
+ cmd_output, cmd_stderr = p.communicate()
+ cmd_output = cmd_output.decode("utf-8")
+ cmd_stderr = cmd_stderr.decode("utf-8")
+ if p.returncode or cmd_stderr:
+ bb.fatal("Cannot get the installed packages list. Command '%s' "
+ "returned %d and stderr:\n%s" % (cmd, p.returncode, cmd_stderr))
+
+ return opkg_query(cmd_output)
+
+
+
+class OpkgDpkgPM(PackageManager):
+ def __init__(self, d, target_rootfs):
+ """
+ This is an abstract class. Do not instantiate this directly.
+ """
+ super(OpkgDpkgPM, self).__init__(d, target_rootfs)
+
+ def package_info(self, pkg, cmd):
+ """
+ Returns a dictionary with the package info.
+
+ This method extracts the common parts for Opkg and Dpkg
+ """
+
+ proc = subprocess.run(cmd, capture_output=True, encoding="utf-8", shell=True)
+ if proc.returncode:
+ bb.fatal("Unable to list available packages. Command '%s' "
+ "returned %d:\n%s" % (cmd, proc.returncode, proc.stderr))
+ elif proc.stderr:
+ bb.note("Command '%s' returned stderr: %s" % (cmd, proc.stderr))
+
+ return opkg_query(proc.stdout)
+
+ def extract(self, pkg, pkg_info):
+ """
+ Returns the path to a tmpdir where resides the contents of a package.
+
+ Deleting the tmpdir is responsability of the caller.
+
+ This method extracts the common parts for Opkg and Dpkg
+ """
+
+ ar_cmd = bb.utils.which(os.getenv("PATH"), "ar")
+ tar_cmd = bb.utils.which(os.getenv("PATH"), "tar")
+ pkg_path = pkg_info[pkg]["filepath"]
+
+ if not os.path.isfile(pkg_path):
+ bb.fatal("Unable to extract package for '%s'."
+ "File %s doesn't exists" % (pkg, pkg_path))
+
+ tmp_dir = tempfile.mkdtemp()
+ current_dir = os.getcwd()
+ os.chdir(tmp_dir)
+ data_tar = 'data.tar.xz'
+
+ try:
+ cmd = [ar_cmd, 'x', pkg_path]
+ output = subprocess.check_output(cmd, stderr=subprocess.STDOUT)
+ cmd = [tar_cmd, 'xf', data_tar]
+ output = subprocess.check_output(cmd, stderr=subprocess.STDOUT)
+ except subprocess.CalledProcessError as e:
+ bb.utils.remove(tmp_dir, recurse=True)
+ bb.fatal("Unable to extract %s package. Command '%s' "
+ "returned %d:\n%s" % (pkg_path, ' '.join(cmd), e.returncode, e.output.decode("utf-8")))
+ except OSError as e:
+ bb.utils.remove(tmp_dir, recurse=True)
+ bb.fatal("Unable to extract %s package. Command '%s' "
+ "returned %d:\n%s at %s" % (pkg_path, ' '.join(cmd), e.errno, e.strerror, e.filename))
+
+ bb.note("Extracted %s to %s" % (pkg_path, tmp_dir))
+ bb.utils.remove(os.path.join(tmp_dir, "debian-binary"))
+ bb.utils.remove(os.path.join(tmp_dir, "control.tar.gz"))
+ os.chdir(current_dir)
+
+ return tmp_dir
+
+ def _handle_intercept_failure(self, registered_pkgs):
+ self.mark_packages("unpacked", registered_pkgs.split())
+
+class OpkgPM(OpkgDpkgPM):
+ def __init__(self, d, target_rootfs, config_file, archs, task_name='target', ipk_repo_workdir="oe-rootfs-repo", filterbydependencies=True, prepare_index=True):
+ super(OpkgPM, self).__init__(d, target_rootfs)
+
+ self.config_file = config_file
+ self.pkg_archs = archs
+ self.task_name = task_name
+
+ self.deploy_dir = oe.path.join(self.d.getVar('WORKDIR'), ipk_repo_workdir)
+ self.deploy_lock_file = os.path.join(self.deploy_dir, "deploy.lock")
+ self.opkg_cmd = bb.utils.which(os.getenv('PATH'), "opkg")
+ self.opkg_args = "--volatile-cache -f %s -t %s -o %s " % (self.config_file, self.d.expand('${T}/ipktemp/') ,target_rootfs)
+ self.opkg_args += self.d.getVar("OPKG_ARGS")
+
+ if prepare_index:
+ create_packages_dir(self.d, self.deploy_dir, d.getVar("DEPLOY_DIR_IPK"), "package_write_ipk", filterbydependencies)
+
+ self.opkg_dir = oe.path.join(target_rootfs, self.d.getVar('OPKGLIBDIR'), "opkg")
+ bb.utils.mkdirhier(self.opkg_dir)
+
+ self.saved_opkg_dir = self.d.expand('${T}/saved/%s' % self.task_name)
+ if not os.path.exists(self.d.expand('${T}/saved')):
+ bb.utils.mkdirhier(self.d.expand('${T}/saved'))
+
+ self.from_feeds = (self.d.getVar('BUILD_IMAGES_FROM_FEEDS') or "") == "1"
+ if self.from_feeds:
+ self._create_custom_config()
+ else:
+ self._create_config()
+
+ self.indexer = OpkgIndexer(self.d, self.deploy_dir)
+
+ def mark_packages(self, status_tag, packages=None):
+ """
+ This function will change a package's status in /var/lib/opkg/status file.
+ If 'packages' is None then the new_status will be applied to all
+ packages
+ """
+ status_file = os.path.join(self.opkg_dir, "status")
+
+ with open(status_file, "r") as sf:
+ with open(status_file + ".tmp", "w+") as tmp_sf:
+ if packages is None:
+ tmp_sf.write(re.sub(r"Package: (.*?)\n((?:[^\n]+\n)*?)Status: (.*)(?:unpacked|installed)",
+ r"Package: \1\n\2Status: \3%s" % status_tag,
+ sf.read()))
+ else:
+ if type(packages).__name__ != "list":
+ raise TypeError("'packages' should be a list object")
+
+ status = sf.read()
+ for pkg in packages:
+ status = re.sub(r"Package: %s\n((?:[^\n]+\n)*?)Status: (.*)(?:unpacked|installed)" % pkg,
+ r"Package: %s\n\1Status: \2%s" % (pkg, status_tag),
+ status)
+
+ tmp_sf.write(status)
+
+ bb.utils.rename(status_file + ".tmp", status_file)
+
+ def _create_custom_config(self):
+ bb.note("Building from feeds activated!")
+
+ with open(self.config_file, "w+") as config_file:
+ priority = 1
+ for arch in self.pkg_archs.split():
+ config_file.write("arch %s %d\n" % (arch, priority))
+ priority += 5
+
+ for line in (self.d.getVar('IPK_FEED_URIS') or "").split():
+ feed_match = re.match(r"^[ \t]*(.*)##([^ \t]*)[ \t]*$", line)
+
+ if feed_match is not None:
+ feed_name = feed_match.group(1)
+ feed_uri = feed_match.group(2)
+
+ bb.note("Add %s feed with URL %s" % (feed_name, feed_uri))
+
+ config_file.write("src/gz %s %s\n" % (feed_name, feed_uri))
+
+ """
+ Allow to use package deploy directory contents as quick devel-testing
+ feed. This creates individual feed configs for each arch subdir of those
+ specified as compatible for the current machine.
+ NOTE: Development-helper feature, NOT a full-fledged feed.
+ """
+ if (self.d.getVar('FEED_DEPLOYDIR_BASE_URI') or "") != "":
+ for arch in self.pkg_archs.split():
+ cfg_file_name = os.path.join(self.target_rootfs,
+ self.d.getVar("sysconfdir"),
+ "opkg",
+ "local-%s-feed.conf" % arch)
+
+ with open(cfg_file_name, "w+") as cfg_file:
+ cfg_file.write("src/gz local-%s %s/%s" %
+ (arch,
+ self.d.getVar('FEED_DEPLOYDIR_BASE_URI'),
+ arch))
+
+ if self.d.getVar('OPKGLIBDIR') != '/var/lib':
+ # There is no command line option for this anymore, we need to add
+ # info_dir and status_file to config file, if OPKGLIBDIR doesn't have
+ # the default value of "/var/lib" as defined in opkg:
+ # libopkg/opkg_conf.h:#define OPKG_CONF_DEFAULT_LISTS_DIR VARDIR "/lib/opkg/lists"
+ # libopkg/opkg_conf.h:#define OPKG_CONF_DEFAULT_INFO_DIR VARDIR "/lib/opkg/info"
+ # libopkg/opkg_conf.h:#define OPKG_CONF_DEFAULT_STATUS_FILE VARDIR "/lib/opkg/status"
+ cfg_file.write("option info_dir %s\n" % os.path.join(self.d.getVar('OPKGLIBDIR'), 'opkg', 'info'))
+ cfg_file.write("option lists_dir %s\n" % os.path.join(self.d.getVar('OPKGLIBDIR'), 'opkg', 'lists'))
+ cfg_file.write("option status_file %s\n" % os.path.join(self.d.getVar('OPKGLIBDIR'), 'opkg', 'status'))
+
+
+ def _create_config(self):
+ with open(self.config_file, "w+") as config_file:
+ priority = 1
+ for arch in self.pkg_archs.split():
+ config_file.write("arch %s %d\n" % (arch, priority))
+ priority += 5
+
+ config_file.write("src oe file:%s\n" % self.deploy_dir)
+
+ for arch in self.pkg_archs.split():
+ pkgs_dir = os.path.join(self.deploy_dir, arch)
+ if os.path.isdir(pkgs_dir):
+ config_file.write("src oe-%s file:%s\n" %
+ (arch, pkgs_dir))
+
+ if self.d.getVar('OPKGLIBDIR') != '/var/lib':
+ # There is no command line option for this anymore, we need to add
+ # info_dir and status_file to config file, if OPKGLIBDIR doesn't have
+ # the default value of "/var/lib" as defined in opkg:
+ # libopkg/opkg_conf.h:#define OPKG_CONF_DEFAULT_LISTS_DIR VARDIR "/lib/opkg/lists"
+ # libopkg/opkg_conf.h:#define OPKG_CONF_DEFAULT_INFO_DIR VARDIR "/lib/opkg/info"
+ # libopkg/opkg_conf.h:#define OPKG_CONF_DEFAULT_STATUS_FILE VARDIR "/lib/opkg/status"
+ config_file.write("option info_dir %s\n" % os.path.join(self.d.getVar('OPKGLIBDIR'), 'opkg', 'info'))
+ config_file.write("option lists_dir %s\n" % os.path.join(self.d.getVar('OPKGLIBDIR'), 'opkg', 'lists'))
+ config_file.write("option status_file %s\n" % os.path.join(self.d.getVar('OPKGLIBDIR'), 'opkg', 'status'))
+
+ def insert_feeds_uris(self, feed_uris, feed_base_paths, feed_archs):
+ if feed_uris == "":
+ return
+
+ rootfs_config = os.path.join('%s/etc/opkg/base-feeds.conf'
+ % self.target_rootfs)
+
+ os.makedirs('%s/etc/opkg' % self.target_rootfs, exist_ok=True)
+
+ feed_uris = self.construct_uris(feed_uris.split(), feed_base_paths.split())
+ archs = self.pkg_archs.split() if feed_archs is None else feed_archs.split()
+
+ with open(rootfs_config, "w+") as config_file:
+ uri_iterator = 0
+ for uri in feed_uris:
+ if archs:
+ for arch in archs:
+ if (feed_archs is None) and (not os.path.exists(oe.path.join(self.deploy_dir, arch))):
+ continue
+ bb.note('Adding opkg feed url-%s-%d (%s)' %
+ (arch, uri_iterator, uri))
+ config_file.write("src/gz uri-%s-%d %s/%s\n" %
+ (arch, uri_iterator, uri, arch))
+ else:
+ bb.note('Adding opkg feed url-%d (%s)' %
+ (uri_iterator, uri))
+ config_file.write("src/gz uri-%d %s\n" %
+ (uri_iterator, uri))
+
+ uri_iterator += 1
+
+ def update(self):
+ self.deploy_dir_lock()
+
+ cmd = "%s %s update" % (self.opkg_cmd, self.opkg_args)
+
+ try:
+ subprocess.check_output(cmd.split(), stderr=subprocess.STDOUT)
+ except subprocess.CalledProcessError as e:
+ self.deploy_dir_unlock()
+ bb.fatal("Unable to update the package index files. Command '%s' "
+ "returned %d:\n%s" % (cmd, e.returncode, e.output.decode("utf-8")))
+
+ self.deploy_dir_unlock()
+
+ def install(self, pkgs, attempt_only=False, hard_depends_only=False):
+ if not pkgs:
+ return
+
+ cmd = "%s %s" % (self.opkg_cmd, self.opkg_args)
+ for exclude in (self.d.getVar("PACKAGE_EXCLUDE") or "").split():
+ cmd += " --add-exclude %s" % exclude
+ for bad_recommendation in (self.d.getVar("BAD_RECOMMENDATIONS") or "").split():
+ cmd += " --add-ignore-recommends %s" % bad_recommendation
+ if hard_depends_only:
+ cmd += " --no-install-recommends"
+ cmd += " install "
+ cmd += " ".join(pkgs)
+
+ os.environ['D'] = self.target_rootfs
+ os.environ['OFFLINE_ROOT'] = self.target_rootfs
+ os.environ['IPKG_OFFLINE_ROOT'] = self.target_rootfs
+ os.environ['OPKG_OFFLINE_ROOT'] = self.target_rootfs
+ os.environ['INTERCEPT_DIR'] = self.intercepts_dir
+ os.environ['NATIVE_ROOT'] = self.d.getVar('STAGING_DIR_NATIVE')
+
+ try:
+ bb.note("Installing the following packages: %s" % ' '.join(pkgs))
+ bb.note(cmd)
+ output = subprocess.check_output(cmd.split(), stderr=subprocess.STDOUT).decode("utf-8")
+ bb.note(output)
+ failed_pkgs = []
+ for line in output.split('\n'):
+ if line.endswith("configuration required on target."):
+ bb.warn(line)
+ failed_pkgs.append(line.split(".")[0])
+ if failed_pkgs:
+ failed_postinsts_abort(failed_pkgs, self.d.expand("${T}/log.do_${BB_CURRENTTASK}"))
+ except subprocess.CalledProcessError as e:
+ (bb.fatal, bb.warn)[attempt_only]("Unable to install packages. "
+ "Command '%s' returned %d:\n%s" %
+ (cmd, e.returncode, e.output.decode("utf-8")))
+
+ def remove(self, pkgs, with_dependencies=True):
+ if not pkgs:
+ return
+
+ if with_dependencies:
+ cmd = "%s %s --force-remove --force-removal-of-dependent-packages remove %s" % \
+ (self.opkg_cmd, self.opkg_args, ' '.join(pkgs))
+ else:
+ cmd = "%s %s --force-depends remove %s" % \
+ (self.opkg_cmd, self.opkg_args, ' '.join(pkgs))
+
+ try:
+ bb.note(cmd)
+ output = subprocess.check_output(cmd.split(), stderr=subprocess.STDOUT).decode("utf-8")
+ bb.note(output)
+ except subprocess.CalledProcessError as e:
+ bb.fatal("Unable to remove packages. Command '%s' "
+ "returned %d:\n%s" % (e.cmd, e.returncode, e.output.decode("utf-8")))
+
+ def write_index(self):
+ self.deploy_dir_lock()
+
+ result = self.indexer.write_index()
+
+ self.deploy_dir_unlock()
+
+ if result is not None:
+ bb.fatal(result)
+
+ def remove_packaging_data(self):
+ cachedir = oe.path.join(self.target_rootfs, self.d.getVar("localstatedir"), "cache", "opkg")
+ bb.utils.remove(self.opkg_dir, True)
+ bb.utils.remove(cachedir, True)
+
+ def remove_lists(self):
+ if not self.from_feeds:
+ bb.utils.remove(os.path.join(self.opkg_dir, "lists"), True)
+
+ def list_installed(self):
+ return PMPkgsList(self.d, self.target_rootfs).list_pkgs()
+
+ def dummy_install(self, pkgs):
+ """
+ The following function dummy installs pkgs and returns the log of output.
+ """
+ if len(pkgs) == 0:
+ return
+
+ # Create an temp dir as opkg root for dummy installation
+ temp_rootfs = self.d.expand('${T}/opkg')
+ opkg_lib_dir = self.d.getVar('OPKGLIBDIR')
+ if opkg_lib_dir[0] == "/":
+ opkg_lib_dir = opkg_lib_dir[1:]
+ temp_opkg_dir = os.path.join(temp_rootfs, opkg_lib_dir, 'opkg')
+ bb.utils.mkdirhier(temp_opkg_dir)
+
+ opkg_args = "-f %s -o %s " % (self.config_file, temp_rootfs)
+ opkg_args += self.d.getVar("OPKG_ARGS")
+
+ cmd = "%s %s update" % (self.opkg_cmd, opkg_args)
+ try:
+ subprocess.check_output(cmd, stderr=subprocess.STDOUT, shell=True)
+ except subprocess.CalledProcessError as e:
+ bb.fatal("Unable to update. Command '%s' "
+ "returned %d:\n%s" % (cmd, e.returncode, e.output.decode("utf-8")))
+
+ # Dummy installation
+ cmd = "%s %s --noaction install %s " % (self.opkg_cmd,
+ opkg_args,
+ ' '.join(pkgs))
+ proc = subprocess.run(cmd, capture_output=True, encoding="utf-8", shell=True)
+ if proc.returncode:
+ bb.fatal("Unable to dummy install packages. Command '%s' "
+ "returned %d:\n%s" % (cmd, proc.returncode, proc.stderr))
+ elif proc.stderr:
+ bb.note("Command '%s' returned stderr: %s" % (cmd, proc.stderr))
+
+ bb.utils.remove(temp_rootfs, True)
+
+ return proc.stdout
+
+ def backup_packaging_data(self):
+ # Save the opkglib for increment ipk image generation
+ if os.path.exists(self.saved_opkg_dir):
+ bb.utils.remove(self.saved_opkg_dir, True)
+ shutil.copytree(self.opkg_dir,
+ self.saved_opkg_dir,
+ symlinks=True)
+
+ def recover_packaging_data(self):
+ # Move the opkglib back
+ if os.path.exists(self.saved_opkg_dir):
+ if os.path.exists(self.opkg_dir):
+ bb.utils.remove(self.opkg_dir, True)
+
+ bb.note('Recover packaging data')
+ shutil.copytree(self.saved_opkg_dir,
+ self.opkg_dir,
+ symlinks=True)
+
+ def package_info(self, pkg):
+ """
+ Returns a dictionary with the package info.
+ """
+ cmd = "%s %s info %s" % (self.opkg_cmd, self.opkg_args, pkg)
+ pkg_info = super(OpkgPM, self).package_info(pkg, cmd)
+
+ pkg_arch = pkg_info[pkg]["arch"]
+ pkg_filename = pkg_info[pkg]["filename"]
+ pkg_info[pkg]["filepath"] = \
+ os.path.join(self.deploy_dir, pkg_arch, pkg_filename)
+
+ return pkg_info
+
+ def extract(self, pkg):
+ """
+ Returns the path to a tmpdir where resides the contents of a package.
+
+ Deleting the tmpdir is responsability of the caller.
+ """
+ pkg_info = self.package_info(pkg)
+ if not pkg_info:
+ bb.fatal("Unable to get information for package '%s' while "
+ "trying to extract the package." % pkg)
+
+ tmp_dir = super(OpkgPM, self).extract(pkg, pkg_info)
+ bb.utils.remove(os.path.join(tmp_dir, "data.tar.xz"))
+
+ return tmp_dir
diff --git a/meta/lib/oe/package_manager/ipk/manifest.py b/meta/lib/oe/package_manager/ipk/manifest.py
new file mode 100644
index 0000000000..469e14c3c6
--- /dev/null
+++ b/meta/lib/oe/package_manager/ipk/manifest.py
@@ -0,0 +1,76 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: GPL-2.0-only
+#
+
+from oe.manifest import Manifest
+import re
+
+class PkgManifest(Manifest):
+ """
+ Returns a dictionary object with mip and mlp packages.
+ """
+ def _split_multilib(self, pkg_list):
+ pkgs = dict()
+
+ for pkg in pkg_list.split():
+ pkg_type = self.PKG_TYPE_MUST_INSTALL
+
+ ml_variants = self.d.getVar('MULTILIB_VARIANTS').split()
+
+ for ml_variant in ml_variants:
+ if pkg.startswith(ml_variant + '-'):
+ pkg_type = self.PKG_TYPE_MULTILIB
+
+ if not pkg_type in pkgs:
+ pkgs[pkg_type] = pkg
+ else:
+ pkgs[pkg_type] += " " + pkg
+
+ return pkgs
+
+ def create_initial(self):
+ pkgs = dict()
+
+ with open(self.initial_manifest, "w+") as manifest:
+ manifest.write(self.initial_manifest_file_header)
+
+ for var in self.var_maps[self.manifest_type]:
+ if var in self.vars_to_split:
+ split_pkgs = self._split_multilib(self.d.getVar(var))
+ if split_pkgs is not None:
+ pkgs = dict(list(pkgs.items()) + list(split_pkgs.items()))
+ else:
+ pkg_list = self.d.getVar(var)
+ if pkg_list is not None:
+ pkgs[self.var_maps[self.manifest_type][var]] = self.d.getVar(var)
+
+ for pkg_type in sorted(pkgs):
+ for pkg in sorted(pkgs[pkg_type].split()):
+ manifest.write("%s,%s\n" % (pkg_type, pkg))
+
+ def create_final(self):
+ pass
+
+ def create_full(self, pm):
+ if not os.path.exists(self.initial_manifest):
+ self.create_initial()
+
+ initial_manifest = self.parse_initial_manifest()
+ pkgs_to_install = list()
+ for pkg_type in initial_manifest:
+ pkgs_to_install += initial_manifest[pkg_type]
+ if len(pkgs_to_install) == 0:
+ return
+
+ output = pm.dummy_install(pkgs_to_install).decode('utf-8')
+
+ with open(self.full_manifest, 'w+') as manifest:
+ pkg_re = re.compile('^Installing ([^ ]+) [^ ].*')
+ for line in set(output.split('\n')):
+ m = pkg_re.match(line)
+ if m:
+ manifest.write(m.group(1) + '\n')
+
+ return
diff --git a/meta/lib/oe/package_manager/ipk/rootfs.py b/meta/lib/oe/package_manager/ipk/rootfs.py
new file mode 100644
index 0000000000..1f74f7e39a
--- /dev/null
+++ b/meta/lib/oe/package_manager/ipk/rootfs.py
@@ -0,0 +1,352 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: GPL-2.0-only
+#
+
+import re
+import filecmp
+import shutil
+from oe.rootfs import Rootfs
+from oe.manifest import Manifest
+from oe.utils import execute_pre_post_process
+from oe.package_manager.ipk.manifest import PkgManifest
+from oe.package_manager.ipk import OpkgPM
+
+class DpkgOpkgRootfs(Rootfs):
+ def __init__(self, d, progress_reporter=None, logcatcher=None):
+ super(DpkgOpkgRootfs, self).__init__(d, progress_reporter, logcatcher)
+
+ def _get_pkgs_postinsts(self, status_file):
+ def _get_pkg_depends_list(pkg_depends):
+ pkg_depends_list = []
+ # filter version requirements like libc (>= 1.1)
+ for dep in pkg_depends.split(', '):
+ m_dep = re.match(r"^(.*) \(.*\)$", dep)
+ if m_dep:
+ dep = m_dep.group(1)
+ pkg_depends_list.append(dep)
+
+ return pkg_depends_list
+
+ pkgs = {}
+ pkg_name = ""
+ pkg_status_match = False
+ pkg_depends = ""
+
+ with open(status_file) as status:
+ data = status.read()
+ status.close()
+ for line in data.split('\n'):
+ m_pkg = re.match(r"^Package: (.*)", line)
+ m_status = re.match(r"^Status:.*unpacked", line)
+ m_depends = re.match(r"^Depends: (.*)", line)
+
+ #Only one of m_pkg, m_status or m_depends is not None at time
+ #If m_pkg is not None, we started a new package
+ if m_pkg is not None:
+ #Get Package name
+ pkg_name = m_pkg.group(1)
+ #Make sure we reset other variables
+ pkg_status_match = False
+ pkg_depends = ""
+ elif m_status is not None:
+ #New status matched
+ pkg_status_match = True
+ elif m_depends is not None:
+ #New depends macthed
+ pkg_depends = m_depends.group(1)
+ else:
+ pass
+
+ #Now check if we can process package depends and postinst
+ if "" != pkg_name and pkg_status_match:
+ pkgs[pkg_name] = _get_pkg_depends_list(pkg_depends)
+ else:
+ #Not enough information
+ pass
+
+ # remove package dependencies not in postinsts
+ pkg_names = list(pkgs.keys())
+ for pkg_name in pkg_names:
+ deps = pkgs[pkg_name][:]
+
+ for d in deps:
+ if d not in pkg_names:
+ pkgs[pkg_name].remove(d)
+
+ return pkgs
+
+ def _get_delayed_postinsts_common(self, status_file):
+ def _dep_resolve(graph, node, resolved, seen):
+ seen.append(node)
+
+ for edge in graph[node]:
+ if edge not in resolved:
+ if edge in seen:
+ raise RuntimeError("Packages %s and %s have " \
+ "a circular dependency in postinsts scripts." \
+ % (node, edge))
+ _dep_resolve(graph, edge, resolved, seen)
+
+ resolved.append(node)
+
+ pkg_list = []
+
+ pkgs = None
+ if not self.d.getVar('PACKAGE_INSTALL').strip():
+ bb.note("Building empty image")
+ else:
+ pkgs = self._get_pkgs_postinsts(status_file)
+ if pkgs:
+ root = "__packagegroup_postinst__"
+ pkgs[root] = list(pkgs.keys())
+ _dep_resolve(pkgs, root, pkg_list, [])
+ pkg_list.remove(root)
+
+ if len(pkg_list) == 0:
+ return None
+
+ return pkg_list
+
+ def _save_postinsts_common(self, dst_postinst_dir, src_postinst_dir):
+ if bb.utils.contains("IMAGE_FEATURES", "package-management",
+ True, False, self.d):
+ return
+ num = 0
+ for p in self._get_delayed_postinsts():
+ bb.utils.mkdirhier(dst_postinst_dir)
+
+ if os.path.exists(os.path.join(src_postinst_dir, p + ".postinst")):
+ shutil.copy(os.path.join(src_postinst_dir, p + ".postinst"),
+ os.path.join(dst_postinst_dir, "%03d-%s" % (num, p)))
+
+ num += 1
+
+class PkgRootfs(DpkgOpkgRootfs):
+ def __init__(self, d, manifest_dir, progress_reporter=None, logcatcher=None):
+ super(PkgRootfs, self).__init__(d, progress_reporter, logcatcher)
+ self.log_check_regex = '(exit 1|Collected errors)'
+
+ self.manifest = PkgManifest(d, manifest_dir)
+ self.opkg_conf = self.d.getVar("IPKGCONF_TARGET")
+ self.pkg_archs = self.d.getVar("ALL_MULTILIB_PACKAGE_ARCHS")
+
+ self.inc_opkg_image_gen = self.d.getVar('INC_IPK_IMAGE_GEN') or ""
+ if self._remove_old_rootfs():
+ bb.utils.remove(self.image_rootfs, True)
+ self.pm = OpkgPM(d,
+ self.image_rootfs,
+ self.opkg_conf,
+ self.pkg_archs)
+ else:
+ self.pm = OpkgPM(d,
+ self.image_rootfs,
+ self.opkg_conf,
+ self.pkg_archs)
+ self.pm.recover_packaging_data()
+
+ bb.utils.remove(self.d.getVar('MULTILIB_TEMP_ROOTFS'), True)
+ '''
+ Compare two files with the same key twice to see if they are equal.
+ If they are not equal, it means they are duplicated and come from
+ different packages.
+ '''
+ def _file_equal(self, key, f1, f2):
+ if filecmp.cmp(f1, f2):
+ return True
+ # Not equal
+ return False
+
+ """
+ This function was reused from the old implementation.
+ See commit: "image.bbclass: Added variables for multilib support." by
+ Lianhao Lu.
+ """
+ def _multilib_sanity_test(self, dirs):
+
+ allow_replace = self.d.getVar("MULTILIBRE_ALLOW_REP")
+ if allow_replace is None:
+ allow_replace = ""
+
+ allow_rep = re.compile(re.sub(r"\|$", r"", allow_replace))
+ error_prompt = "Multilib check error:"
+
+ files = {}
+ for dir in dirs:
+ for root, subfolders, subfiles in os.walk(dir):
+ for file in subfiles:
+ item = os.path.join(root, file)
+ key = str(os.path.join("/", os.path.relpath(item, dir)))
+
+ valid = True
+ if key in files:
+ #check whether the file is allow to replace
+ if allow_rep.match(key):
+ valid = True
+ else:
+ if os.path.exists(files[key]) and \
+ os.path.exists(item) and \
+ not self._file_equal(key, files[key], item):
+ valid = False
+ bb.fatal("%s duplicate files %s %s is not the same\n" %
+ (error_prompt, item, files[key]))
+
+ #pass the check, add to list
+ if valid:
+ files[key] = item
+
+ def _multilib_test_install(self, pkgs):
+ ml_temp = self.d.getVar("MULTILIB_TEMP_ROOTFS")
+ bb.utils.mkdirhier(ml_temp)
+
+ dirs = [self.image_rootfs]
+
+ for variant in self.d.getVar("MULTILIB_VARIANTS").split():
+ ml_target_rootfs = os.path.join(ml_temp, variant)
+
+ bb.utils.remove(ml_target_rootfs, True)
+
+ ml_opkg_conf = os.path.join(ml_temp,
+ variant + "-" + os.path.basename(self.opkg_conf))
+
+ ml_pm = OpkgPM(self.d, ml_target_rootfs, ml_opkg_conf, self.pkg_archs, prepare_index=False)
+
+ ml_pm.update()
+ ml_pm.install(pkgs)
+
+ dirs.append(ml_target_rootfs)
+
+ self._multilib_sanity_test(dirs)
+
+ '''
+ While ipk incremental image generation is enabled, it will remove the
+ unneeded pkgs by comparing the old full manifest in previous existing
+ image and the new full manifest in the current image.
+ '''
+ def _remove_extra_packages(self, pkgs_initial_install):
+ if self.inc_opkg_image_gen == "1":
+ # Parse full manifest in previous existing image creation session
+ old_full_manifest = self.manifest.parse_full_manifest()
+
+ # Create full manifest for the current image session, the old one
+ # will be replaced by the new one.
+ self.manifest.create_full(self.pm)
+
+ # Parse full manifest in current image creation session
+ new_full_manifest = self.manifest.parse_full_manifest()
+
+ pkg_to_remove = list()
+ for pkg in old_full_manifest:
+ if pkg not in new_full_manifest:
+ pkg_to_remove.append(pkg)
+
+ if pkg_to_remove != []:
+ bb.note('decremental removed: %s' % ' '.join(pkg_to_remove))
+ self.pm.remove(pkg_to_remove)
+
+ '''
+ Compare with previous existing image creation, if some conditions
+ triggered, the previous old image should be removed.
+ The conditions include any of 'PACKAGE_EXCLUDE, NO_RECOMMENDATIONS
+ and BAD_RECOMMENDATIONS' has been changed.
+ '''
+ def _remove_old_rootfs(self):
+ if self.inc_opkg_image_gen != "1":
+ return True
+
+ vars_list_file = self.d.expand('${T}/vars_list')
+
+ old_vars_list = ""
+ if os.path.exists(vars_list_file):
+ old_vars_list = open(vars_list_file, 'r+').read()
+
+ new_vars_list = '%s:%s:%s\n' % \
+ ((self.d.getVar('BAD_RECOMMENDATIONS') or '').strip(),
+ (self.d.getVar('NO_RECOMMENDATIONS') or '').strip(),
+ (self.d.getVar('PACKAGE_EXCLUDE') or '').strip())
+ open(vars_list_file, 'w+').write(new_vars_list)
+
+ if old_vars_list != new_vars_list:
+ return True
+
+ return False
+
+ def _create(self):
+ pkgs_to_install = self.manifest.parse_initial_manifest()
+ opkg_pre_process_cmds = self.d.getVar('OPKG_PREPROCESS_COMMANDS')
+ opkg_post_process_cmds = self.d.getVar('OPKG_POSTPROCESS_COMMANDS')
+
+ # update PM index files
+ self.pm.write_index()
+
+ execute_pre_post_process(self.d, opkg_pre_process_cmds)
+
+ if self.progress_reporter:
+ self.progress_reporter.next_stage()
+ # Steps are a bit different in order, skip next
+ self.progress_reporter.next_stage()
+
+ self.pm.update()
+
+ if self.progress_reporter:
+ self.progress_reporter.next_stage()
+
+ if self.inc_opkg_image_gen == "1":
+ self._remove_extra_packages(pkgs_to_install)
+
+ if self.progress_reporter:
+ self.progress_reporter.next_stage()
+
+ for pkg_type in self.install_order:
+ if pkg_type in pkgs_to_install:
+ # For multilib, we perform a sanity test before final install
+ # If sanity test fails, it will automatically do a bb.fatal()
+ # and the installation will stop
+ if pkg_type == Manifest.PKG_TYPE_MULTILIB:
+ self._multilib_test_install(pkgs_to_install[pkg_type])
+
+ self.pm.install(pkgs_to_install[pkg_type],
+ [False, True][pkg_type == Manifest.PKG_TYPE_ATTEMPT_ONLY])
+
+ if self.progress_reporter:
+ self.progress_reporter.next_stage()
+
+ self.pm.install_complementary()
+
+ if self.progress_reporter:
+ self.progress_reporter.next_stage()
+
+ opkg_lib_dir = self.d.getVar('OPKGLIBDIR')
+ opkg_dir = os.path.join(opkg_lib_dir, 'opkg')
+ self._setup_dbg_rootfs([opkg_dir])
+
+ execute_pre_post_process(self.d, opkg_post_process_cmds)
+
+ if self.inc_opkg_image_gen == "1":
+ self.pm.backup_packaging_data()
+
+ if self.progress_reporter:
+ self.progress_reporter.next_stage()
+
+ @staticmethod
+ def _depends_list():
+ return ['IPKGCONF_SDK', 'IPK_FEED_URIS', 'DEPLOY_DIR_IPK', 'IPKGCONF_TARGET', 'INC_IPK_IMAGE_GEN', 'OPKG_ARGS', 'OPKGLIBDIR', 'OPKG_PREPROCESS_COMMANDS', 'OPKG_POSTPROCESS_COMMANDS', 'OPKGLIBDIR']
+
+ def _get_delayed_postinsts(self):
+ status_file = os.path.join(self.image_rootfs,
+ self.d.getVar('OPKGLIBDIR').strip('/'),
+ "opkg", "status")
+ return self._get_delayed_postinsts_common(status_file)
+
+ def _save_postinsts(self):
+ dst_postinst_dir = self.d.expand("${IMAGE_ROOTFS}${sysconfdir}/ipk-postinsts")
+ src_postinst_dir = self.d.expand("${IMAGE_ROOTFS}${OPKGLIBDIR}/opkg/info")
+ return self._save_postinsts_common(dst_postinst_dir, src_postinst_dir)
+
+ def _log_check(self):
+ self._log_check_warn()
+ self._log_check_error()
+
+ def _cleanup(self):
+ self.pm.remove_lists()
diff --git a/meta/lib/oe/package_manager/ipk/sdk.py b/meta/lib/oe/package_manager/ipk/sdk.py
new file mode 100644
index 0000000000..6a1f167fb7
--- /dev/null
+++ b/meta/lib/oe/package_manager/ipk/sdk.py
@@ -0,0 +1,104 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: GPL-2.0-only
+#
+
+import glob
+import shutil
+from oe.utils import execute_pre_post_process
+from oe.sdk import Sdk
+from oe.package_manager.ipk.manifest import PkgManifest
+from oe.manifest import Manifest
+from oe.package_manager.ipk import OpkgPM
+
+class PkgSdk(Sdk):
+ def __init__(self, d, manifest_dir=None):
+ super(PkgSdk, self).__init__(d, manifest_dir)
+
+ # In sdk_list_installed_packages the call to opkg is hardcoded to
+ # always use IPKGCONF_TARGET and there's no exposed API to change this
+ # so simply override IPKGCONF_TARGET to use this separated config file.
+ ipkgconf_sdk_target = d.getVar("IPKGCONF_SDK_TARGET")
+ d.setVar("IPKGCONF_TARGET", ipkgconf_sdk_target)
+
+ self.target_conf = self.d.getVar("IPKGCONF_TARGET")
+ self.host_conf = self.d.getVar("IPKGCONF_SDK")
+
+ self.target_manifest = PkgManifest(d, self.manifest_dir,
+ Manifest.MANIFEST_TYPE_SDK_TARGET)
+ self.host_manifest = PkgManifest(d, self.manifest_dir,
+ Manifest.MANIFEST_TYPE_SDK_HOST)
+
+ ipk_repo_workdir = "oe-sdk-repo"
+ if "sdk_ext" in d.getVar("BB_RUNTASK"):
+ ipk_repo_workdir = "oe-sdk-ext-repo"
+
+ self.target_pm = OpkgPM(d, self.sdk_target_sysroot, self.target_conf,
+ self.d.getVar("ALL_MULTILIB_PACKAGE_ARCHS"),
+ ipk_repo_workdir=ipk_repo_workdir)
+
+ self.host_pm = OpkgPM(d, self.sdk_host_sysroot, self.host_conf,
+ self.d.getVar("SDK_PACKAGE_ARCHS"),
+ ipk_repo_workdir=ipk_repo_workdir)
+
+ def _populate_sysroot(self, pm, manifest):
+ pkgs_to_install = manifest.parse_initial_manifest()
+
+ if (self.d.getVar('BUILD_IMAGES_FROM_FEEDS') or "") != "1":
+ pm.write_index()
+
+ pm.update()
+
+ for pkg_type in self.install_order:
+ if pkg_type in pkgs_to_install:
+ pm.install(pkgs_to_install[pkg_type],
+ [False, True][pkg_type == Manifest.PKG_TYPE_ATTEMPT_ONLY])
+
+ def _populate(self):
+ execute_pre_post_process(self.d, self.d.getVar("POPULATE_SDK_PRE_TARGET_COMMAND"))
+
+ bb.note("Installing TARGET packages")
+ self._populate_sysroot(self.target_pm, self.target_manifest)
+
+ self.target_pm.install_complementary(self.d.getVar('SDKIMAGE_INSTALL_COMPLEMENTARY'))
+
+ self.target_pm.run_intercepts(populate_sdk='target')
+
+ execute_pre_post_process(self.d, self.d.getVar("POPULATE_SDK_POST_TARGET_COMMAND"))
+
+ if not bb.utils.contains("SDKIMAGE_FEATURES", "package-management", True, False, self.d):
+ self.target_pm.remove_packaging_data()
+
+ bb.note("Installing NATIVESDK packages")
+ self._populate_sysroot(self.host_pm, self.host_manifest)
+ self.install_locales(self.host_pm)
+
+ self.host_pm.run_intercepts(populate_sdk='host')
+
+ execute_pre_post_process(self.d, self.d.getVar("POPULATE_SDK_POST_HOST_COMMAND"))
+
+ if not bb.utils.contains("SDKIMAGE_FEATURES", "package-management", True, False, self.d):
+ self.host_pm.remove_packaging_data()
+
+ target_sysconfdir = os.path.join(self.sdk_target_sysroot, self.sysconfdir)
+ host_sysconfdir = os.path.join(self.sdk_host_sysroot, self.sysconfdir)
+
+ self.mkdirhier(target_sysconfdir)
+ shutil.copy(self.target_conf, target_sysconfdir)
+ os.chmod(os.path.join(target_sysconfdir,
+ os.path.basename(self.target_conf)), 0o644)
+
+ self.mkdirhier(host_sysconfdir)
+ shutil.copy(self.host_conf, host_sysconfdir)
+ os.chmod(os.path.join(host_sysconfdir,
+ os.path.basename(self.host_conf)), 0o644)
+
+ native_opkg_state_dir = os.path.join(self.sdk_output, self.sdk_native_path,
+ self.d.getVar('localstatedir_nativesdk').strip('/'),
+ "lib", "opkg")
+ self.mkdirhier(native_opkg_state_dir)
+ for f in glob.glob(os.path.join(self.sdk_output, "var", "lib", "opkg", "*")):
+ self.movefile(f, native_opkg_state_dir)
+
+ self.remove(os.path.join(self.sdk_output, "var"), True)
diff --git a/meta/lib/oe/package_manager/rpm/__init__.py b/meta/lib/oe/package_manager/rpm/__init__.py
new file mode 100644
index 0000000000..fa218485f5
--- /dev/null
+++ b/meta/lib/oe/package_manager/rpm/__init__.py
@@ -0,0 +1,421 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: GPL-2.0-only
+#
+
+import shutil
+import subprocess
+from oe.package_manager import *
+
+class RpmIndexer(Indexer):
+ def write_index(self):
+ self.do_write_index(self.deploy_dir)
+
+ def do_write_index(self, deploy_dir):
+ if self.d.getVar('PACKAGE_FEED_SIGN') == '1':
+ signer = get_signer(self.d, self.d.getVar('PACKAGE_FEED_GPG_BACKEND'))
+ else:
+ signer = None
+
+ createrepo_c = bb.utils.which(os.environ['PATH'], "createrepo_c")
+ result = create_index("%s --update -q %s" % (createrepo_c, deploy_dir))
+ if result:
+ bb.fatal(result)
+
+ # Sign repomd
+ if signer:
+ sig_type = self.d.getVar('PACKAGE_FEED_GPG_SIGNATURE_TYPE')
+ is_ascii_sig = (sig_type.upper() != "BIN")
+ signer.detach_sign(os.path.join(deploy_dir, 'repodata', 'repomd.xml'),
+ self.d.getVar('PACKAGE_FEED_GPG_NAME'),
+ self.d.getVar('PACKAGE_FEED_GPG_PASSPHRASE_FILE'),
+ armor=is_ascii_sig)
+
+class RpmSubdirIndexer(RpmIndexer):
+ def write_index(self):
+ bb.note("Generating package index for %s" %(self.deploy_dir))
+ # Remove the existing repodata to ensure that we re-generate it no matter what
+ bb.utils.remove(os.path.join(self.deploy_dir, "repodata"), recurse=True)
+
+ self.do_write_index(self.deploy_dir)
+ for entry in os.walk(self.deploy_dir):
+ if os.path.samefile(self.deploy_dir, entry[0]):
+ for dir in entry[1]:
+ if dir != 'repodata':
+ dir_path = oe.path.join(self.deploy_dir, dir)
+ bb.note("Generating package index for %s" %(dir_path))
+ self.do_write_index(dir_path)
+
+
+class PMPkgsList(PkgsList):
+ def list_pkgs(self):
+ return RpmPM(self.d, self.rootfs_dir, self.d.getVar('TARGET_VENDOR'), needfeed=False).list_installed()
+
+class RpmPM(PackageManager):
+ def __init__(self,
+ d,
+ target_rootfs,
+ target_vendor,
+ task_name='target',
+ arch_var=None,
+ os_var=None,
+ rpm_repo_workdir="oe-rootfs-repo",
+ filterbydependencies=True,
+ needfeed=True):
+ super(RpmPM, self).__init__(d, target_rootfs)
+ self.target_vendor = target_vendor
+ self.task_name = task_name
+ if arch_var == None:
+ self.archs = self.d.getVar('ALL_MULTILIB_PACKAGE_ARCHS').replace("-","_")
+ else:
+ self.archs = self.d.getVar(arch_var).replace("-","_")
+ if task_name == "host":
+ self.primary_arch = self.d.getVar('SDK_ARCH')
+ else:
+ self.primary_arch = self.d.getVar('MACHINE_ARCH')
+
+ if needfeed:
+ self.rpm_repo_dir = oe.path.join(self.d.getVar('WORKDIR'), rpm_repo_workdir)
+ create_packages_dir(self.d, oe.path.join(self.rpm_repo_dir, "rpm"), d.getVar("DEPLOY_DIR_RPM"), "package_write_rpm", filterbydependencies)
+
+ self.saved_packaging_data = self.d.expand('${T}/saved_packaging_data/%s' % self.task_name)
+ if not os.path.exists(self.d.expand('${T}/saved_packaging_data')):
+ bb.utils.mkdirhier(self.d.expand('${T}/saved_packaging_data'))
+ self.packaging_data_dirs = ['etc/rpm', 'etc/rpmrc', 'etc/dnf', 'var/lib/rpm', 'var/lib/dnf', 'var/cache/dnf']
+ self.solution_manifest = self.d.expand('${T}/saved/%s_solution' %
+ self.task_name)
+ if not os.path.exists(self.d.expand('${T}/saved')):
+ bb.utils.mkdirhier(self.d.expand('${T}/saved'))
+
+ def _configure_dnf(self):
+ # libsolv handles 'noarch' internally, we don't need to specify it explicitly
+ archs = [i for i in reversed(self.archs.split()) if i not in ["any", "all", "noarch"]]
+ # This prevents accidental matching against libsolv's built-in policies
+ if len(archs) <= 1:
+ archs = archs + ["bogusarch"]
+ # This architecture needs to be upfront so that packages using it are properly prioritized
+ archs = ["sdk_provides_dummy_target"] + archs
+ confdir = "%s/%s" %(self.target_rootfs, "etc/dnf/vars/")
+ bb.utils.mkdirhier(confdir)
+ with open(confdir + "arch", 'w') as f:
+ f.write(":".join(archs))
+
+ distro_codename = self.d.getVar('DISTRO_CODENAME')
+ with open(confdir + "releasever", 'w') as f:
+ f.write(distro_codename if distro_codename is not None else '')
+
+ with open(oe.path.join(self.target_rootfs, "etc/dnf/dnf.conf"), 'w') as f:
+ f.write("")
+
+
+ def _configure_rpm(self):
+ # We need to configure rpm to use our primary package architecture as the installation architecture,
+ # and to make it compatible with other package architectures that we use.
+ # Otherwise it will refuse to proceed with packages installation.
+ platformconfdir = "%s/%s" %(self.target_rootfs, "etc/rpm/")
+ rpmrcconfdir = "%s/%s" %(self.target_rootfs, "etc/")
+ bb.utils.mkdirhier(platformconfdir)
+ with open(platformconfdir + "platform", 'w') as f:
+ f.write("%s-pc-linux" % self.primary_arch)
+ with open(rpmrcconfdir + "rpmrc", 'w') as f:
+ f.write("arch_compat: %s: %s\n" % (self.primary_arch, self.archs if len(self.archs) > 0 else self.primary_arch))
+ f.write("buildarch_compat: %s: noarch\n" % self.primary_arch)
+
+ with open(platformconfdir + "macros", 'w') as f:
+ f.write("%_transaction_color 7\n")
+ if self.d.getVar('RPM_PREFER_ELF_ARCH'):
+ with open(platformconfdir + "macros", 'a') as f:
+ f.write("%%_prefer_color %s" % (self.d.getVar('RPM_PREFER_ELF_ARCH')))
+
+ if self.d.getVar('RPM_SIGN_PACKAGES') == '1':
+ signer = get_signer(self.d, self.d.getVar('RPM_GPG_BACKEND'))
+ pubkey_path = oe.path.join(self.d.getVar('B'), 'rpm-key')
+ signer.export_pubkey(pubkey_path, self.d.getVar('RPM_GPG_NAME'))
+ rpm_bin = bb.utils.which(os.getenv('PATH'), "rpmkeys")
+ cmd = [rpm_bin, '--root=%s' % self.target_rootfs, '--import', pubkey_path]
+ try:
+ subprocess.check_output(cmd, stderr=subprocess.STDOUT)
+ except subprocess.CalledProcessError as e:
+ bb.fatal("Importing GPG key failed. Command '%s' "
+ "returned %d:\n%s" % (' '.join(cmd), e.returncode, e.output.decode("utf-8")))
+
+ def create_configs(self):
+ self._configure_dnf()
+ self._configure_rpm()
+
+ def write_index(self):
+ lockfilename = self.d.getVar('DEPLOY_DIR_RPM') + "/rpm.lock"
+ lf = bb.utils.lockfile(lockfilename, False)
+ RpmIndexer(self.d, self.rpm_repo_dir).write_index()
+ bb.utils.unlockfile(lf)
+
+ def insert_feeds_uris(self, feed_uris, feed_base_paths, feed_archs):
+ from urllib.parse import urlparse
+
+ if feed_uris == "":
+ return
+
+ gpg_opts = ''
+ if self.d.getVar('PACKAGE_FEED_SIGN') == '1':
+ gpg_opts += 'repo_gpgcheck=1\n'
+ gpg_opts += 'gpgkey=file://%s/pki/packagefeed-gpg/PACKAGEFEED-GPG-KEY-%s-%s\n' % (self.d.getVar('sysconfdir'), self.d.getVar('DISTRO'), self.d.getVar('DISTRO_CODENAME'))
+
+ if self.d.getVar('RPM_SIGN_PACKAGES') != '1':
+ gpg_opts += 'gpgcheck=0\n'
+
+ bb.utils.mkdirhier(oe.path.join(self.target_rootfs, "etc", "yum.repos.d"))
+ remote_uris = self.construct_uris(feed_uris.split(), feed_base_paths.split())
+ for uri in remote_uris:
+ repo_base = "oe-remote-repo" + "-".join(urlparse(uri).path.split("/"))
+ if feed_archs is not None:
+ for arch in feed_archs.split():
+ repo_uri = uri + "/" + arch
+ repo_id = "oe-remote-repo" + "-".join(urlparse(repo_uri).path.split("/"))
+ repo_name = "OE Remote Repo:" + " ".join(urlparse(repo_uri).path.split("/"))
+ with open(oe.path.join(self.target_rootfs, "etc", "yum.repos.d", repo_base + ".repo"), 'a') as f:
+ f.write("[%s]\nname=%s\nbaseurl=%s\n%s\n" % (repo_id, repo_name, repo_uri, gpg_opts))
+ else:
+ repo_name = "OE Remote Repo:" + " ".join(urlparse(uri).path.split("/"))
+ repo_uri = uri
+ with open(oe.path.join(self.target_rootfs, "etc", "yum.repos.d", repo_base + ".repo"), 'w') as f:
+ f.write("[%s]\nname=%s\nbaseurl=%s\n%s" % (repo_base, repo_name, repo_uri, gpg_opts))
+
+ def _prepare_pkg_transaction(self):
+ os.environ['D'] = self.target_rootfs
+ os.environ['OFFLINE_ROOT'] = self.target_rootfs
+ os.environ['IPKG_OFFLINE_ROOT'] = self.target_rootfs
+ os.environ['OPKG_OFFLINE_ROOT'] = self.target_rootfs
+ os.environ['INTERCEPT_DIR'] = self.intercepts_dir
+ os.environ['NATIVE_ROOT'] = self.d.getVar('STAGING_DIR_NATIVE')
+
+
+ def install(self, pkgs, attempt_only=False, hard_depends_only=False):
+ if len(pkgs) == 0:
+ return
+ self._prepare_pkg_transaction()
+
+ bad_recommendations = self.d.getVar('BAD_RECOMMENDATIONS')
+ package_exclude = self.d.getVar('PACKAGE_EXCLUDE')
+ exclude_pkgs = (bad_recommendations.split() if bad_recommendations else []) + (package_exclude.split() if package_exclude else [])
+
+ output = self._invoke_dnf((["--skip-broken"] if attempt_only else []) +
+ (["-x", ",".join(exclude_pkgs)] if len(exclude_pkgs) > 0 else []) +
+ (["--setopt=install_weak_deps=False"] if (hard_depends_only or self.d.getVar('NO_RECOMMENDATIONS') == "1") else []) +
+ (["--nogpgcheck"] if self.d.getVar('RPM_SIGN_PACKAGES') != '1' else ["--setopt=gpgcheck=True"]) +
+ ["install"] +
+ pkgs)
+
+ failed_scriptlets_pkgnames = collections.OrderedDict()
+ for line in output.splitlines():
+ if line.startswith("Error: Systemctl"):
+ bb.error(line)
+
+ if line.startswith("Error in POSTIN scriptlet in rpm package"):
+ failed_scriptlets_pkgnames[line.split()[-1]] = True
+
+ if len(failed_scriptlets_pkgnames) > 0:
+ failed_postinsts_abort(list(failed_scriptlets_pkgnames.keys()), self.d.expand("${T}/log.do_${BB_CURRENTTASK}"))
+
+ def remove(self, pkgs, with_dependencies = True):
+ if not pkgs:
+ return
+
+ self._prepare_pkg_transaction()
+
+ if with_dependencies:
+ self._invoke_dnf(["remove"] + pkgs)
+ else:
+ cmd = bb.utils.which(os.getenv('PATH'), "rpm")
+ args = ["-e", "-v", "--nodeps", "--root=%s" %self.target_rootfs]
+
+ try:
+ bb.note("Running %s" % ' '.join([cmd] + args + pkgs))
+ output = subprocess.check_output([cmd] + args + pkgs, stderr=subprocess.STDOUT).decode("utf-8")
+ bb.note(output)
+ except subprocess.CalledProcessError as e:
+ bb.fatal("Could not invoke rpm. Command "
+ "'%s' returned %d:\n%s" % (' '.join([cmd] + args + pkgs), e.returncode, e.output.decode("utf-8")))
+
+ def upgrade(self):
+ self._prepare_pkg_transaction()
+ self._invoke_dnf(["upgrade"])
+
+ def autoremove(self):
+ self._prepare_pkg_transaction()
+ self._invoke_dnf(["autoremove"])
+
+ def remove_packaging_data(self):
+ self._invoke_dnf(["clean", "all"])
+ for dir in self.packaging_data_dirs:
+ bb.utils.remove(oe.path.join(self.target_rootfs, dir), True)
+
+ def backup_packaging_data(self):
+ # Save the packaging dirs for increment rpm image generation
+ if os.path.exists(self.saved_packaging_data):
+ bb.utils.remove(self.saved_packaging_data, True)
+ for i in self.packaging_data_dirs:
+ source_dir = oe.path.join(self.target_rootfs, i)
+ target_dir = oe.path.join(self.saved_packaging_data, i)
+ if os.path.isdir(source_dir):
+ shutil.copytree(source_dir, target_dir, symlinks=True)
+ elif os.path.isfile(source_dir):
+ shutil.copy2(source_dir, target_dir)
+
+ def recovery_packaging_data(self):
+ # Move the rpmlib back
+ if os.path.exists(self.saved_packaging_data):
+ for i in self.packaging_data_dirs:
+ target_dir = oe.path.join(self.target_rootfs, i)
+ if os.path.exists(target_dir):
+ bb.utils.remove(target_dir, True)
+ source_dir = oe.path.join(self.saved_packaging_data, i)
+ if os.path.isdir(source_dir):
+ shutil.copytree(source_dir, target_dir, symlinks=True)
+ elif os.path.isfile(source_dir):
+ shutil.copy2(source_dir, target_dir)
+
+ def list_installed(self):
+ output = self._invoke_dnf(["repoquery", "--installed", "--queryformat", "Package: %{name} %{arch} %{version} %{name}-%{version}-%{release}.%{arch}.rpm\nDependencies:\n%{requires}\nRecommendations:\n%{recommends}\nDependenciesEndHere:\n"],
+ print_output = False)
+ packages = {}
+ current_package = None
+ current_deps = None
+ current_state = "initial"
+ for line in output.splitlines():
+ if line.startswith("Package:"):
+ package_info = line.split(" ")[1:]
+ current_package = package_info[0]
+ package_arch = package_info[1]
+ package_version = package_info[2]
+ package_rpm = package_info[3]
+ packages[current_package] = {"arch":package_arch, "ver":package_version, "filename":package_rpm}
+ current_deps = []
+ elif line.startswith("Dependencies:"):
+ current_state = "dependencies"
+ elif line.startswith("Recommendations"):
+ current_state = "recommendations"
+ elif line.startswith("DependenciesEndHere:"):
+ current_state = "initial"
+ packages[current_package]["deps"] = current_deps
+ elif len(line) > 0:
+ if current_state == "dependencies":
+ current_deps.append(line)
+ elif current_state == "recommendations":
+ current_deps.append("%s [REC]" % line)
+
+ return packages
+
+ def update(self):
+ self._invoke_dnf(["makecache", "--refresh"])
+
+ def _invoke_dnf(self, dnf_args, fatal = True, print_output = True ):
+ os.environ['RPM_ETCCONFIGDIR'] = self.target_rootfs
+
+ dnf_cmd = bb.utils.which(os.getenv('PATH'), "dnf")
+ standard_dnf_args = ["-v", "--rpmverbosity=info", "-y",
+ "-c", oe.path.join(self.target_rootfs, "etc/dnf/dnf.conf"),
+ "--setopt=reposdir=%s" %(oe.path.join(self.target_rootfs, "etc/yum.repos.d")),
+ "--installroot=%s" % (self.target_rootfs),
+ "--setopt=logdir=%s" % (self.d.getVar('T'))
+ ]
+ if hasattr(self, "rpm_repo_dir"):
+ standard_dnf_args.append("--repofrompath=oe-repo,%s" % (self.rpm_repo_dir))
+ cmd = [dnf_cmd] + standard_dnf_args + dnf_args
+ bb.note('Running %s' % ' '.join(cmd))
+ try:
+ output = subprocess.check_output(cmd,stderr=subprocess.STDOUT).decode("utf-8")
+ if print_output:
+ bb.debug(1, output)
+ return output
+ except subprocess.CalledProcessError as e:
+ if print_output:
+ (bb.note, bb.fatal)[fatal]("Could not invoke dnf. Command "
+ "'%s' returned %d:\n%s" % (' '.join(cmd), e.returncode, e.output.decode("utf-8")))
+ else:
+ (bb.note, bb.fatal)[fatal]("Could not invoke dnf. Command "
+ "'%s' returned %d:" % (' '.join(cmd), e.returncode))
+ return e.output.decode("utf-8")
+
+ def dump_install_solution(self, pkgs):
+ with open(self.solution_manifest, 'w') as f:
+ f.write(" ".join(pkgs))
+ return pkgs
+
+ def load_old_install_solution(self):
+ if not os.path.exists(self.solution_manifest):
+ return []
+ with open(self.solution_manifest, 'r') as fd:
+ return fd.read().split()
+
+ def _script_num_prefix(self, path):
+ files = os.listdir(path)
+ numbers = set()
+ numbers.add(99)
+ for f in files:
+ numbers.add(int(f.split("-")[0]))
+ return max(numbers) + 1
+
+ def save_rpmpostinst(self, pkg):
+ bb.note("Saving postinstall script of %s" % (pkg))
+ cmd = bb.utils.which(os.getenv('PATH'), "rpm")
+ args = ["-q", "--root=%s" % self.target_rootfs, "--queryformat", "%{postin}", pkg]
+
+ try:
+ output = subprocess.check_output([cmd] + args,stderr=subprocess.STDOUT).decode("utf-8")
+ except subprocess.CalledProcessError as e:
+ bb.fatal("Could not invoke rpm. Command "
+ "'%s' returned %d:\n%s" % (' '.join([cmd] + args), e.returncode, e.output.decode("utf-8")))
+
+ # may need to prepend #!/bin/sh to output
+
+ target_path = oe.path.join(self.target_rootfs, self.d.expand('${sysconfdir}/rpm-postinsts/'))
+ bb.utils.mkdirhier(target_path)
+ num = self._script_num_prefix(target_path)
+ saved_script_name = oe.path.join(target_path, "%d-%s" % (num, pkg))
+ with open(saved_script_name, 'w') as f:
+ f.write(output)
+ os.chmod(saved_script_name, 0o755)
+
+ def _handle_intercept_failure(self, registered_pkgs):
+ rpm_postinsts_dir = self.target_rootfs + self.d.expand('${sysconfdir}/rpm-postinsts/')
+ bb.utils.mkdirhier(rpm_postinsts_dir)
+
+ # Save the package postinstalls in /etc/rpm-postinsts
+ for pkg in registered_pkgs.split():
+ self.save_rpmpostinst(pkg)
+
+ def extract(self, pkg):
+ output = self._invoke_dnf(["repoquery", "--queryformat", "%{location}", pkg])
+ pkg_name = output.splitlines()[-1]
+ if not pkg_name.endswith(".rpm"):
+ bb.fatal("dnf could not find package %s in repository: %s" %(pkg, output))
+ pkg_path = oe.path.join(self.rpm_repo_dir, pkg_name)
+
+ cpio_cmd = bb.utils.which(os.getenv("PATH"), "cpio")
+ rpm2cpio_cmd = bb.utils.which(os.getenv("PATH"), "rpm2cpio")
+
+ if not os.path.isfile(pkg_path):
+ bb.fatal("Unable to extract package for '%s'."
+ "File %s doesn't exists" % (pkg, pkg_path))
+
+ tmp_dir = tempfile.mkdtemp()
+ current_dir = os.getcwd()
+ os.chdir(tmp_dir)
+
+ try:
+ cmd = "%s %s | %s -idmv" % (rpm2cpio_cmd, pkg_path, cpio_cmd)
+ output = subprocess.check_output(cmd, stderr=subprocess.STDOUT, shell=True)
+ except subprocess.CalledProcessError as e:
+ bb.utils.remove(tmp_dir, recurse=True)
+ bb.fatal("Unable to extract %s package. Command '%s' "
+ "returned %d:\n%s" % (pkg_path, cmd, e.returncode, e.output.decode("utf-8")))
+ except OSError as e:
+ bb.utils.remove(tmp_dir, recurse=True)
+ bb.fatal("Unable to extract %s package. Command '%s' "
+ "returned %d:\n%s at %s" % (pkg_path, cmd, e.errno, e.strerror, e.filename))
+
+ bb.note("Extracted %s to %s" % (pkg_path, tmp_dir))
+ os.chdir(current_dir)
+
+ return tmp_dir
diff --git a/meta/lib/oe/package_manager/rpm/manifest.py b/meta/lib/oe/package_manager/rpm/manifest.py
new file mode 100644
index 0000000000..6ee7c329f0
--- /dev/null
+++ b/meta/lib/oe/package_manager/rpm/manifest.py
@@ -0,0 +1,56 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: GPL-2.0-only
+#
+
+from oe.manifest import Manifest
+
+class PkgManifest(Manifest):
+ """
+ Returns a dictionary object with mip and mlp packages.
+ """
+ def _split_multilib(self, pkg_list):
+ pkgs = dict()
+
+ for pkg in pkg_list.split():
+ pkg_type = self.PKG_TYPE_MUST_INSTALL
+
+ ml_variants = self.d.getVar('MULTILIB_VARIANTS').split()
+
+ for ml_variant in ml_variants:
+ if pkg.startswith(ml_variant + '-'):
+ pkg_type = self.PKG_TYPE_MULTILIB
+
+ if not pkg_type in pkgs:
+ pkgs[pkg_type] = pkg
+ else:
+ pkgs[pkg_type] += " " + pkg
+
+ return pkgs
+
+ def create_initial(self):
+ pkgs = dict()
+
+ with open(self.initial_manifest, "w+") as manifest:
+ manifest.write(self.initial_manifest_file_header)
+
+ for var in self.var_maps[self.manifest_type]:
+ if var in self.vars_to_split:
+ split_pkgs = self._split_multilib(self.d.getVar(var))
+ if split_pkgs is not None:
+ pkgs = dict(list(pkgs.items()) + list(split_pkgs.items()))
+ else:
+ pkg_list = self.d.getVar(var)
+ if pkg_list is not None:
+ pkgs[self.var_maps[self.manifest_type][var]] = self.d.getVar(var)
+
+ for pkg_type in pkgs:
+ for pkg in pkgs[pkg_type].split():
+ manifest.write("%s,%s\n" % (pkg_type, pkg))
+
+ def create_final(self):
+ pass
+
+ def create_full(self, pm):
+ pass
diff --git a/meta/lib/oe/package_manager/rpm/rootfs.py b/meta/lib/oe/package_manager/rpm/rootfs.py
new file mode 100644
index 0000000000..d4c415f68c
--- /dev/null
+++ b/meta/lib/oe/package_manager/rpm/rootfs.py
@@ -0,0 +1,150 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: GPL-2.0-only
+#
+
+from oe.rootfs import Rootfs
+from oe.manifest import Manifest
+from oe.utils import execute_pre_post_process
+from oe.package_manager.rpm.manifest import PkgManifest
+from oe.package_manager.rpm import RpmPM
+
+class PkgRootfs(Rootfs):
+ def __init__(self, d, manifest_dir, progress_reporter=None, logcatcher=None):
+ super(PkgRootfs, self).__init__(d, progress_reporter, logcatcher)
+ self.log_check_regex = r'(unpacking of archive failed|Cannot find package'\
+ r'|exit 1|ERROR: |Error: |Error |ERROR '\
+ r'|Failed |Failed: |Failed$|Failed\(\d+\):)'
+
+ self.manifest = PkgManifest(d, manifest_dir)
+
+ self.pm = RpmPM(d,
+ d.getVar('IMAGE_ROOTFS'),
+ self.d.getVar('TARGET_VENDOR')
+ )
+
+ self.inc_rpm_image_gen = self.d.getVar('INC_RPM_IMAGE_GEN')
+ if self.inc_rpm_image_gen != "1":
+ bb.utils.remove(self.image_rootfs, True)
+ else:
+ self.pm.recovery_packaging_data()
+ bb.utils.remove(self.d.getVar('MULTILIB_TEMP_ROOTFS'), True)
+
+ self.pm.create_configs()
+
+ '''
+ While rpm incremental image generation is enabled, it will remove the
+ unneeded pkgs by comparing the new install solution manifest and the
+ old installed manifest.
+ '''
+ def _create_incremental(self, pkgs_initial_install):
+ if self.inc_rpm_image_gen == "1":
+
+ pkgs_to_install = list()
+ for pkg_type in pkgs_initial_install:
+ pkgs_to_install += pkgs_initial_install[pkg_type]
+
+ installed_manifest = self.pm.load_old_install_solution()
+ solution_manifest = self.pm.dump_install_solution(pkgs_to_install)
+
+ pkg_to_remove = list()
+ for pkg in installed_manifest:
+ if pkg not in solution_manifest:
+ pkg_to_remove.append(pkg)
+
+ self.pm.update()
+
+ bb.note('incremental update -- upgrade packages in place ')
+ self.pm.upgrade()
+ if pkg_to_remove != []:
+ bb.note('incremental removed: %s' % ' '.join(pkg_to_remove))
+ self.pm.remove(pkg_to_remove)
+
+ self.pm.autoremove()
+
+ def _create(self):
+ pkgs_to_install = self.manifest.parse_initial_manifest()
+ rpm_pre_process_cmds = self.d.getVar('RPM_PREPROCESS_COMMANDS')
+ rpm_post_process_cmds = self.d.getVar('RPM_POSTPROCESS_COMMANDS')
+
+ # update PM index files
+ self.pm.write_index()
+
+ execute_pre_post_process(self.d, rpm_pre_process_cmds)
+
+ if self.progress_reporter:
+ self.progress_reporter.next_stage()
+
+ if self.inc_rpm_image_gen == "1":
+ self._create_incremental(pkgs_to_install)
+
+ if self.progress_reporter:
+ self.progress_reporter.next_stage()
+
+ self.pm.update()
+
+ pkgs = []
+ pkgs_attempt = []
+ for pkg_type in pkgs_to_install:
+ if pkg_type == Manifest.PKG_TYPE_ATTEMPT_ONLY:
+ pkgs_attempt += pkgs_to_install[pkg_type]
+ else:
+ pkgs += pkgs_to_install[pkg_type]
+
+ if self.progress_reporter:
+ self.progress_reporter.next_stage()
+
+ self.pm.install(pkgs)
+
+ if self.progress_reporter:
+ self.progress_reporter.next_stage()
+
+ self.pm.install(pkgs_attempt, True)
+
+ if self.progress_reporter:
+ self.progress_reporter.next_stage()
+
+ self.pm.install_complementary()
+
+ if self.progress_reporter:
+ self.progress_reporter.next_stage()
+
+ self._setup_dbg_rootfs(['/etc', '/var/lib/rpm', '/var/cache/dnf', '/var/lib/dnf'])
+
+ execute_pre_post_process(self.d, rpm_post_process_cmds)
+
+ if self.inc_rpm_image_gen == "1":
+ self.pm.backup_packaging_data()
+
+ if self.progress_reporter:
+ self.progress_reporter.next_stage()
+
+
+ @staticmethod
+ def _depends_list():
+ return ['DEPLOY_DIR_RPM', 'INC_RPM_IMAGE_GEN', 'RPM_PREPROCESS_COMMANDS',
+ 'RPM_POSTPROCESS_COMMANDS', 'RPM_PREFER_ELF_ARCH']
+
+ def _get_delayed_postinsts(self):
+ postinst_dir = self.d.expand("${IMAGE_ROOTFS}${sysconfdir}/rpm-postinsts")
+ if os.path.isdir(postinst_dir):
+ files = os.listdir(postinst_dir)
+ for f in files:
+ bb.note('Delayed package scriptlet: %s' % f)
+ return files
+
+ return None
+
+ def _save_postinsts(self):
+ # this is just a stub. For RPM, the failed postinstalls are
+ # already saved in /etc/rpm-postinsts
+ pass
+
+ def _log_check(self):
+ self._log_check_warn()
+ self._log_check_error()
+
+ def _cleanup(self):
+ if bb.utils.contains("IMAGE_FEATURES", "package-management", True, False, self.d):
+ self.pm._invoke_dnf(["clean", "all"])
diff --git a/meta/lib/oe/package_manager/rpm/sdk.py b/meta/lib/oe/package_manager/rpm/sdk.py
new file mode 100644
index 0000000000..0726a18b91
--- /dev/null
+++ b/meta/lib/oe/package_manager/rpm/sdk.py
@@ -0,0 +1,116 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: GPL-2.0-only
+#
+
+import glob
+from oe.utils import execute_pre_post_process
+from oe.sdk import Sdk
+from oe.manifest import Manifest
+from oe.package_manager.rpm.manifest import PkgManifest
+from oe.package_manager.rpm import RpmPM
+
+class PkgSdk(Sdk):
+ def __init__(self, d, manifest_dir=None, rpm_workdir="oe-sdk-repo"):
+ super(PkgSdk, self).__init__(d, manifest_dir)
+
+ self.target_manifest = PkgManifest(d, self.manifest_dir,
+ Manifest.MANIFEST_TYPE_SDK_TARGET)
+ self.host_manifest = PkgManifest(d, self.manifest_dir,
+ Manifest.MANIFEST_TYPE_SDK_HOST)
+
+ rpm_repo_workdir = "oe-sdk-repo"
+ if "sdk_ext" in d.getVar("BB_RUNTASK"):
+ rpm_repo_workdir = "oe-sdk-ext-repo"
+
+ self.target_pm = RpmPM(d,
+ self.sdk_target_sysroot,
+ self.d.getVar('TARGET_VENDOR'),
+ 'target',
+ rpm_repo_workdir=rpm_repo_workdir
+ )
+
+ self.host_pm = RpmPM(d,
+ self.sdk_host_sysroot,
+ self.d.getVar('SDK_VENDOR'),
+ 'host',
+ "SDK_PACKAGE_ARCHS",
+ "SDK_OS",
+ rpm_repo_workdir=rpm_repo_workdir
+ )
+
+ def _populate_sysroot(self, pm, manifest):
+ pkgs_to_install = manifest.parse_initial_manifest()
+
+ pm.create_configs()
+ pm.write_index()
+ pm.update()
+
+ pkgs = []
+ pkgs_attempt = []
+ for pkg_type in pkgs_to_install:
+ if pkg_type == Manifest.PKG_TYPE_ATTEMPT_ONLY:
+ pkgs_attempt += pkgs_to_install[pkg_type]
+ else:
+ pkgs += pkgs_to_install[pkg_type]
+
+ pm.install(pkgs)
+
+ pm.install(pkgs_attempt, True)
+
+ def _populate(self):
+ execute_pre_post_process(self.d, self.d.getVar("POPULATE_SDK_PRE_TARGET_COMMAND"))
+
+ bb.note("Installing TARGET packages")
+ self._populate_sysroot(self.target_pm, self.target_manifest)
+
+ self.target_pm.install_complementary(self.d.getVar('SDKIMAGE_INSTALL_COMPLEMENTARY'))
+
+ self.target_pm.run_intercepts(populate_sdk='target')
+
+ execute_pre_post_process(self.d, self.d.getVar("POPULATE_SDK_POST_TARGET_COMMAND"))
+
+ if not bb.utils.contains("SDKIMAGE_FEATURES", "package-management", True, False, self.d):
+ self.target_pm.remove_packaging_data()
+
+ bb.note("Installing NATIVESDK packages")
+ self._populate_sysroot(self.host_pm, self.host_manifest)
+ self.install_locales(self.host_pm)
+
+ self.host_pm.run_intercepts(populate_sdk='host')
+
+ execute_pre_post_process(self.d, self.d.getVar("POPULATE_SDK_POST_HOST_COMMAND"))
+
+ if not bb.utils.contains("SDKIMAGE_FEATURES", "package-management", True, False, self.d):
+ self.host_pm.remove_packaging_data()
+
+ # Move host RPM library data
+ native_rpm_state_dir = os.path.join(self.sdk_output,
+ self.sdk_native_path,
+ self.d.getVar('localstatedir_nativesdk').strip('/'),
+ "lib",
+ "rpm"
+ )
+ self.mkdirhier(native_rpm_state_dir)
+ for f in glob.glob(os.path.join(self.sdk_output,
+ "var",
+ "lib",
+ "rpm",
+ "*")):
+ self.movefile(f, native_rpm_state_dir)
+
+ self.remove(os.path.join(self.sdk_output, "var"), True)
+
+ # Move host sysconfig data
+ native_sysconf_dir = os.path.join(self.sdk_output,
+ self.sdk_native_path,
+ self.d.getVar('sysconfdir',
+ True).strip('/'),
+ )
+ self.mkdirhier(native_sysconf_dir)
+ for f in glob.glob(os.path.join(self.sdk_output, "etc", "rpm*")):
+ self.movefile(f, native_sysconf_dir)
+ for f in glob.glob(os.path.join(self.sdk_output, "etc", "dnf", "*")):
+ self.movefile(f, native_sysconf_dir)
+ self.remove(os.path.join(self.sdk_output, "etc"), True)
diff --git a/meta/lib/oe/packagedata.py b/meta/lib/oe/packagedata.py
index 21d4de914f..162ff60d72 100644
--- a/meta/lib/oe/packagedata.py
+++ b/meta/lib/oe/packagedata.py
@@ -1,5 +1,16 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: GPL-2.0-only
+#
+
import codecs
import os
+import json
+import bb.compress.zstd
+import oe.path
+
+from glob import glob
def packaged(pkg, d):
return os.access(get_subpkgedata_fn(pkg, d) + '.packaged', os.R_OK)
@@ -13,10 +24,9 @@ def read_pkgdatafile(fn):
if os.access(fn, os.R_OK):
import re
- f = open(fn, 'r')
- lines = f.readlines()
- f.close()
- r = re.compile("([^:]+):\s*(.*)")
+ with open(fn, 'r') as f:
+ lines = f.readlines()
+ r = re.compile(r"(^.+?):\s+(.*)")
for l in lines:
m = r.match(l)
if m:
@@ -42,22 +52,34 @@ def read_pkgdata(pn, d):
return read_pkgdatafile(fn)
#
-# Collapse FOO_pkg variables into FOO
+# Collapse FOO:pkg variables into FOO
#
def read_subpkgdata_dict(pkg, d):
ret = {}
subd = read_pkgdatafile(get_subpkgedata_fn(pkg, d))
for var in subd:
- newvar = var.replace("_" + pkg, "")
- if newvar == var and var + "_" + pkg in subd:
+ newvar = var.replace(":" + pkg, "")
+ if newvar == var and var + ":" + pkg in subd:
continue
ret[newvar] = subd[var]
return ret
+def read_subpkgdata_extended(pkg, d):
+ import json
+ import bb.compress.zstd
+
+ fn = d.expand("${PKGDATA_DIR}/extended/%s.json.zstd" % pkg)
+ try:
+ num_threads = int(d.getVar("BB_NUMBER_THREADS"))
+ with bb.compress.zstd.open(fn, "rt", encoding="utf-8", num_threads=num_threads) as f:
+ return json.load(f)
+ except FileNotFoundError:
+ return None
+
def _pkgmap(d):
"""Return a dictionary mapping package to recipe name."""
- pkgdatadir = d.getVar("PKGDATA_DIR", True)
+ pkgdatadir = d.getVar("PKGDATA_DIR")
pkgmap = {}
try:
@@ -93,3 +115,237 @@ def recipename(pkg, d):
"""Return the recipe name for the given binary package name."""
return pkgmap(d).get(pkg)
+
+def get_package_mapping(pkg, basepkg, d, depversions=None):
+ import oe.packagedata
+
+ data = oe.packagedata.read_subpkgdata(pkg, d)
+ key = "PKG:%s" % pkg
+
+ if key in data:
+ if bb.data.inherits_class('allarch', d) and bb.data.inherits_class('packagegroup', d) and pkg != data[key]:
+ bb.error("An allarch packagegroup shouldn't depend on packages which are dynamically renamed (%s to %s)" % (pkg, data[key]))
+ # Have to avoid undoing the write_extra_pkgs(global_variants...)
+ if bb.data.inherits_class('allarch', d) and not d.getVar('MULTILIB_VARIANTS') \
+ and data[key] == basepkg:
+ return pkg
+ if depversions == []:
+ # Avoid returning a mapping if the renamed package rprovides its original name
+ rprovkey = "RPROVIDES:%s" % pkg
+ if rprovkey in data:
+ if pkg in bb.utils.explode_dep_versions2(data[rprovkey]):
+ bb.note("%s rprovides %s, not replacing the latter" % (data[key], pkg))
+ return pkg
+ # Do map to rewritten package name
+ return data[key]
+
+ return pkg
+
+def get_package_additional_metadata(pkg_type, d):
+ base_key = "PACKAGE_ADD_METADATA"
+ for key in ("%s_%s" % (base_key, pkg_type.upper()), base_key):
+ if d.getVar(key, False) is None:
+ continue
+ d.setVarFlag(key, "type", "list")
+ if d.getVarFlag(key, "separator") is None:
+ d.setVarFlag(key, "separator", "\\n")
+ metadata_fields = [field.strip() for field in oe.data.typed_value(key, d)]
+ return "\n".join(metadata_fields).strip()
+
+def runtime_mapping_rename(varname, pkg, d):
+ #bb.note("%s before: %s" % (varname, d.getVar(varname)))
+
+ new_depends = {}
+ deps = bb.utils.explode_dep_versions2(d.getVar(varname) or "")
+ for depend, depversions in deps.items():
+ new_depend = get_package_mapping(depend, pkg, d, depversions)
+ if depend != new_depend:
+ bb.note("package name mapping done: %s -> %s" % (depend, new_depend))
+ new_depends[new_depend] = deps[depend]
+
+ d.setVar(varname, bb.utils.join_deps(new_depends, commasep=False))
+
+ #bb.note("%s after: %s" % (varname, d.getVar(varname)))
+
+def emit_pkgdata(pkgfiles, d):
+ def process_postinst_on_target(pkg, mlprefix):
+ pkgval = d.getVar('PKG:%s' % pkg)
+ if pkgval is None:
+ pkgval = pkg
+
+ defer_fragment = """
+if [ -n "$D" ]; then
+ $INTERCEPT_DIR/postinst_intercept delay_to_first_boot %s mlprefix=%s
+ exit 0
+fi
+""" % (pkgval, mlprefix)
+
+ postinst = d.getVar('pkg_postinst:%s' % pkg)
+ postinst_ontarget = d.getVar('pkg_postinst_ontarget:%s' % pkg)
+
+ if postinst_ontarget:
+ bb.debug(1, 'adding deferred pkg_postinst_ontarget() to pkg_postinst() for %s' % pkg)
+ if not postinst:
+ postinst = '#!/bin/sh\n'
+ postinst += defer_fragment
+ postinst += postinst_ontarget
+ d.setVar('pkg_postinst:%s' % pkg, postinst)
+
+ def add_set_e_to_scriptlets(pkg):
+ for scriptlet_name in ('pkg_preinst', 'pkg_postinst', 'pkg_prerm', 'pkg_postrm'):
+ scriptlet = d.getVar('%s:%s' % (scriptlet_name, pkg))
+ if scriptlet:
+ scriptlet_split = scriptlet.split('\n')
+ if scriptlet_split[0].startswith("#!"):
+ scriptlet = scriptlet_split[0] + "\nset -e\n" + "\n".join(scriptlet_split[1:])
+ else:
+ scriptlet = "set -e\n" + "\n".join(scriptlet_split[0:])
+ d.setVar('%s:%s' % (scriptlet_name, pkg), scriptlet)
+
+ def write_if_exists(f, pkg, var):
+ def encode(str):
+ import codecs
+ c = codecs.getencoder("unicode_escape")
+ return c(str)[0].decode("latin1")
+
+ val = d.getVar('%s:%s' % (var, pkg))
+ if val:
+ f.write('%s:%s: %s\n' % (var, pkg, encode(val)))
+ return val
+ val = d.getVar('%s' % (var))
+ if val:
+ f.write('%s: %s\n' % (var, encode(val)))
+ return val
+
+ def write_extra_pkgs(variants, pn, packages, pkgdatadir):
+ for variant in variants:
+ with open("%s/%s-%s" % (pkgdatadir, variant, pn), 'w') as fd:
+ fd.write("PACKAGES: %s\n" % ' '.join(
+ map(lambda pkg: '%s-%s' % (variant, pkg), packages.split())))
+
+ def write_extra_runtime_pkgs(variants, packages, pkgdatadir):
+ for variant in variants:
+ for pkg in packages.split():
+ ml_pkg = "%s-%s" % (variant, pkg)
+ subdata_file = "%s/runtime/%s" % (pkgdatadir, ml_pkg)
+ with open(subdata_file, 'w') as fd:
+ fd.write("PKG:%s: %s" % (ml_pkg, pkg))
+
+ packages = d.getVar('PACKAGES')
+ pkgdest = d.getVar('PKGDEST')
+ pkgdatadir = d.getVar('PKGDESTWORK')
+
+ data_file = pkgdatadir + d.expand("/${PN}")
+ with open(data_file, 'w') as fd:
+ fd.write("PACKAGES: %s\n" % packages)
+
+ pkgdebugsource = d.getVar("PKGDEBUGSOURCES") or []
+
+ pn = d.getVar('PN')
+ global_variants = (d.getVar('MULTILIB_GLOBAL_VARIANTS') or "").split()
+ variants = (d.getVar('MULTILIB_VARIANTS') or "").split()
+
+ if bb.data.inherits_class('kernel', d) or bb.data.inherits_class('module-base', d):
+ write_extra_pkgs(variants, pn, packages, pkgdatadir)
+
+ if bb.data.inherits_class('allarch', d) and not variants \
+ and not bb.data.inherits_class('packagegroup', d):
+ write_extra_pkgs(global_variants, pn, packages, pkgdatadir)
+
+ workdir = d.getVar('WORKDIR')
+
+ for pkg in packages.split():
+ pkgval = d.getVar('PKG:%s' % pkg)
+ if pkgval is None:
+ pkgval = pkg
+ d.setVar('PKG:%s' % pkg, pkg)
+
+ extended_data = {
+ "files_info": {}
+ }
+
+ pkgdestpkg = os.path.join(pkgdest, pkg)
+ files = {}
+ files_extra = {}
+ total_size = 0
+ seen = set()
+ for f in pkgfiles[pkg]:
+ fpath = os.sep + os.path.relpath(f, pkgdestpkg)
+
+ fstat = os.lstat(f)
+ files[fpath] = fstat.st_size
+
+ extended_data["files_info"].setdefault(fpath, {})
+ extended_data["files_info"][fpath]['size'] = fstat.st_size
+
+ if fstat.st_ino not in seen:
+ seen.add(fstat.st_ino)
+ total_size += fstat.st_size
+
+ if fpath in pkgdebugsource:
+ extended_data["files_info"][fpath]['debugsrc'] = pkgdebugsource[fpath]
+ del pkgdebugsource[fpath]
+
+ d.setVar('FILES_INFO:' + pkg , json.dumps(files, sort_keys=True))
+
+ process_postinst_on_target(pkg, d.getVar("MLPREFIX"))
+ add_set_e_to_scriptlets(pkg)
+
+ subdata_file = pkgdatadir + "/runtime/%s" % pkg
+ with open(subdata_file, 'w') as sf:
+ for var in (d.getVar('PKGDATA_VARS') or "").split():
+ val = write_if_exists(sf, pkg, var)
+
+ write_if_exists(sf, pkg, 'FILERPROVIDESFLIST')
+ for dfile in sorted((d.getVar('FILERPROVIDESFLIST:' + pkg) or "").split()):
+ write_if_exists(sf, pkg, 'FILERPROVIDES:' + dfile)
+
+ write_if_exists(sf, pkg, 'FILERDEPENDSFLIST')
+ for dfile in sorted((d.getVar('FILERDEPENDSFLIST:' + pkg) or "").split()):
+ write_if_exists(sf, pkg, 'FILERDEPENDS:' + dfile)
+
+ sf.write('%s:%s: %d\n' % ('PKGSIZE', pkg, total_size))
+
+ subdata_extended_file = pkgdatadir + "/extended/%s.json.zstd" % pkg
+ num_threads = int(d.getVar("BB_NUMBER_THREADS"))
+ with bb.compress.zstd.open(subdata_extended_file, "wt", encoding="utf-8", num_threads=num_threads) as f:
+ json.dump(extended_data, f, sort_keys=True, separators=(",", ":"))
+
+ # Symlinks needed for rprovides lookup
+ rprov = d.getVar('RPROVIDES:%s' % pkg) or d.getVar('RPROVIDES')
+ if rprov:
+ for p in bb.utils.explode_deps(rprov):
+ subdata_sym = pkgdatadir + "/runtime-rprovides/%s/%s" % (p, pkg)
+ bb.utils.mkdirhier(os.path.dirname(subdata_sym))
+ oe.path.symlink("../../runtime/%s" % pkg, subdata_sym, True)
+
+ allow_empty = d.getVar('ALLOW_EMPTY:%s' % pkg)
+ if not allow_empty:
+ allow_empty = d.getVar('ALLOW_EMPTY')
+ root = "%s/%s" % (pkgdest, pkg)
+ os.chdir(root)
+ g = glob('*')
+ if g or allow_empty == "1":
+ # Symlinks needed for reverse lookups (from the final package name)
+ subdata_sym = pkgdatadir + "/runtime-reverse/%s" % pkgval
+ oe.path.symlink("../runtime/%s" % pkg, subdata_sym, True)
+
+ packagedfile = pkgdatadir + '/runtime/%s.packaged' % pkg
+ open(packagedfile, 'w').close()
+
+ if bb.data.inherits_class('kernel', d) or bb.data.inherits_class('module-base', d):
+ write_extra_runtime_pkgs(variants, packages, pkgdatadir)
+
+ if bb.data.inherits_class('allarch', d) and not variants \
+ and not bb.data.inherits_class('packagegroup', d):
+ write_extra_runtime_pkgs(global_variants, packages, pkgdatadir)
+
+def mapping_rename_hook(d):
+ """
+ Rewrite variables to account for package renaming in things
+ like debian.bbclass or manual PKG variable name changes
+ """
+ pkg = d.getVar("PKG")
+ oe.packagedata.runtime_mapping_rename("RDEPENDS", pkg, d)
+ oe.packagedata.runtime_mapping_rename("RRECOMMENDS", pkg, d)
+ oe.packagedata.runtime_mapping_rename("RSUGGESTS", pkg, d)
diff --git a/meta/lib/oe/packagegroup.py b/meta/lib/oe/packagegroup.py
index 97819279b7..7b7594751a 100644
--- a/meta/lib/oe/packagegroup.py
+++ b/meta/lib/oe/packagegroup.py
@@ -1,17 +1,17 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: GPL-2.0-only
+#
+
import itertools
def is_optional(feature, d):
- packages = d.getVar("FEATURE_PACKAGES_%s" % feature, True)
- if packages:
- return bool(d.getVarFlag("FEATURE_PACKAGES_%s" % feature, "optional", True))
- else:
- return bool(d.getVarFlag("PACKAGE_GROUP_%s" % feature, "optional", True))
+ return bool(d.getVarFlag("FEATURE_PACKAGES_%s" % feature, "optional"))
def packages(features, d):
for feature in features:
- packages = d.getVar("FEATURE_PACKAGES_%s" % feature, True)
- if not packages:
- packages = d.getVar("PACKAGE_GROUP_%s" % feature, True)
+ packages = d.getVar("FEATURE_PACKAGES_%s" % feature)
for pkg in (packages or "").split():
yield pkg
diff --git a/meta/lib/oe/patch.py b/meta/lib/oe/patch.py
index af3adec140..b2dc8d0a90 100644
--- a/meta/lib/oe/patch.py
+++ b/meta/lib/oe/patch.py
@@ -1,4 +1,12 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: GPL-2.0-only
+#
+
import oe.path
+import oe.types
+import subprocess
class NotFoundError(bb.BBHandledException):
def __init__(self, path):
@@ -32,15 +40,25 @@ def runcmd(args, dir = None):
args = [ pipes.quote(str(arg)) for arg in args ]
cmd = " ".join(args)
# print("cmd: %s" % cmd)
- (exitstatus, output) = oe.utils.getstatusoutput(cmd)
+ proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
+ stdout, stderr = proc.communicate()
+ stdout = stdout.decode('utf-8')
+ stderr = stderr.decode('utf-8')
+ exitstatus = proc.returncode
if exitstatus != 0:
- raise CmdError(cmd, exitstatus >> 8, output)
- return output
+ raise CmdError(cmd, exitstatus >> 8, "stdout: %s\nstderr: %s" % (stdout, stderr))
+ if " fuzz " in stdout and "Hunk " in stdout:
+ # Drop patch fuzz info with header and footer to log file so
+ # insane.bbclass can handle to throw error/warning
+ bb.note("--- Patch fuzz start ---\n%s\n--- Patch fuzz end ---" % format(stdout))
+
+ return stdout
finally:
if dir:
os.chdir(olddir)
+
class PatchError(Exception):
def __init__(self, msg):
self.msg = msg
@@ -81,7 +99,7 @@ class PatchSet(object):
patch[param] = PatchSet.defaults[param]
if patch.get("remote"):
- patch["file"] = bb.data.expand(bb.fetch2.localpath(patch["remote"], self.d), self.d)
+ patch["file"] = self.d.expand(bb.fetch2.localpath(patch["remote"], self.d))
patch["filemd5"] = bb.utils.md5_file(patch["file"])
@@ -211,7 +229,7 @@ class PatchTree(PatchSet):
self.patches.insert(i, patch)
def _applypatch(self, patch, force = False, reverse = False, run = True):
- shellcmd = ["cat", patch['file'], "|", "patch", "-p", patch['strippath']]
+ shellcmd = ["cat", patch['file'], "|", "patch", "--no-backup-if-mismatch", "-p", patch['strippath']]
if reverse:
shellcmd.append('-R')
@@ -281,6 +299,26 @@ class GitApplyTree(PatchTree):
def __init__(self, dir, d):
PatchTree.__init__(self, dir, d)
+ self.commituser = d.getVar('PATCH_GIT_USER_NAME')
+ self.commitemail = d.getVar('PATCH_GIT_USER_EMAIL')
+ if not self._isInitialized(d):
+ self._initRepo()
+
+ def _isInitialized(self, d):
+ cmd = "git rev-parse --show-toplevel"
+ try:
+ output = runcmd(cmd.split(), self.dir).strip()
+ except CmdError as err:
+ ## runcmd returned non-zero which most likely means 128
+ ## Not a git directory
+ return False
+ ## Make sure repo is in builddir to not break top-level git repos, or under workdir
+ return os.path.samefile(output, self.dir) or oe.path.is_path_parent(d.getVar('WORKDIR'), output)
+
+ def _initRepo(self):
+ runcmd("git init".split(), self.dir)
+ runcmd("git add .".split(), self.dir)
+ runcmd("git commit -a --allow-empty -m bitbake_patching_started".split(), self.dir)
@staticmethod
def extractPatchHeader(patchfile):
@@ -314,7 +352,8 @@ class GitApplyTree(PatchTree):
@staticmethod
def interpretPatchHeader(headerlines):
import re
- author_re = re.compile('[\S ]+ <\S+@\S+\.\S+>')
+ author_re = re.compile(r'[\S ]+ <\S+@\S+\.\S+>')
+ from_commit_re = re.compile(r'^From [a-z0-9]{40} .*')
outlines = []
author = None
date = None
@@ -344,11 +383,39 @@ class GitApplyTree(PatchTree):
# git is fussy about author formatting i.e. it must be Name <email@domain>
if author_re.match(authorval):
author = authorval
+ elif from_commit_re.match(line):
+ # We don't want the From <commit> line - if it's present it will break rebasing
+ continue
outlines.append(line)
+
+ if not subject:
+ firstline = None
+ for line in headerlines:
+ line = line.strip()
+ if firstline:
+ if line:
+ # Second line is not blank, the first line probably isn't usable
+ firstline = None
+ break
+ elif line:
+ firstline = line
+ if firstline and not firstline.startswith(('#', 'Index:', 'Upstream-Status:')) and len(firstline) < 100:
+ subject = firstline
+
return outlines, author, date, subject
@staticmethod
- def prepareCommit(patchfile):
+ def gitCommandUserOptions(cmd, commituser=None, commitemail=None, d=None):
+ if d:
+ commituser = d.getVar('PATCH_GIT_USER_NAME')
+ commitemail = d.getVar('PATCH_GIT_USER_EMAIL')
+ if commituser:
+ cmd += ['-c', 'user.name="%s"' % commituser]
+ if commitemail:
+ cmd += ['-c', 'user.email="%s"' % commitemail]
+
+ @staticmethod
+ def prepareCommit(patchfile, commituser=None, commitemail=None):
"""
Prepare a git commit command line based on the header from a patch file
(typically this is useful for patches that cannot be applied with "git am" due to formatting)
@@ -357,21 +424,24 @@ class GitApplyTree(PatchTree):
# Process patch header and extract useful information
lines = GitApplyTree.extractPatchHeader(patchfile)
outlines, author, date, subject = GitApplyTree.interpretPatchHeader(lines)
- if not author or not subject:
+ if not author or not subject or not date:
try:
- shellcmd = ["git", "log", "--format=email", "--diff-filter=A", "--", patchfile]
+ shellcmd = ["git", "log", "--format=email", "--follow", "--diff-filter=A", "--", patchfile]
out = runcmd(["sh", "-c", " ".join(shellcmd)], os.path.dirname(patchfile))
except CmdError:
out = None
if out:
_, newauthor, newdate, newsubject = GitApplyTree.interpretPatchHeader(out.splitlines())
- if not author or not date:
- # These really need to go together
+ if not author:
+ # If we're setting the author then the date should be set as well
author = newauthor
date = newdate
+ elif not date:
+ # If we don't do this we'll get the current date, at least this will be closer
+ date = newdate
if not subject:
subject = newsubject
- if subject:
+ if subject and not (outlines and outlines[0].strip() == subject):
outlines.insert(0, '%s\n\n' % subject.strip())
# Write out commit message to a file
@@ -380,7 +450,9 @@ class GitApplyTree(PatchTree):
for line in outlines:
tf.write(line)
# Prepare git command
- cmd = ["git", "commit", "-F", tmpfile]
+ cmd = ["git"]
+ GitApplyTree.gitCommandUserOptions(cmd, commituser, commitemail)
+ cmd += ["commit", "-F", tmpfile]
# git doesn't like plain email addresses as authors
if author and '<' in author:
cmd.append('--author="%s"' % author)
@@ -394,23 +466,31 @@ class GitApplyTree(PatchTree):
import shutil
tempdir = tempfile.mkdtemp(prefix='oepatch')
try:
- shellcmd = ["git", "format-patch", startcommit, "-o", tempdir]
+ shellcmd = ["git", "format-patch", "--no-signature", "--no-numbered", startcommit, "-o", tempdir]
if paths:
shellcmd.append('--')
shellcmd.extend(paths)
out = runcmd(["sh", "-c", " ".join(shellcmd)], tree)
if out:
for srcfile in out.split():
- patchlines = []
- outfile = None
- with open(srcfile, 'r') as f:
- for line in f:
- if line.startswith(GitApplyTree.patch_line_prefix):
- outfile = line.split()[-1].strip()
- continue
- if line.startswith(GitApplyTree.ignore_commit_prefix):
- continue
- patchlines.append(line)
+ for encoding in ['utf-8', 'latin-1']:
+ patchlines = []
+ outfile = None
+ try:
+ with open(srcfile, 'r', encoding=encoding) as f:
+ for line in f:
+ if line.startswith(GitApplyTree.patch_line_prefix):
+ outfile = line.split()[-1].strip()
+ continue
+ if line.startswith(GitApplyTree.ignore_commit_prefix):
+ continue
+ patchlines.append(line)
+ except UnicodeDecodeError:
+ continue
+ break
+ else:
+ raise PatchError('Unable to find a character encoding to decode %s' % srcfile)
+
if not outfile:
outfile = os.path.basename(srcfile)
with open(os.path.join(outdir, outfile), 'w') as of:
@@ -449,14 +529,15 @@ class GitApplyTree(PatchTree):
with open(commithook, 'w') as f:
# NOTE: the formatting here is significant; if you change it you'll also need to
# change other places which read it back
- f.write('echo >> $1\n')
- f.write('echo "%s: $PATCHFILE" >> $1\n' % GitApplyTree.patch_line_prefix)
+ f.write('echo "\n%s: $PATCHFILE" >> $1' % GitApplyTree.patch_line_prefix)
os.chmod(commithook, 0o755)
shutil.copy2(commithook, applyhook)
try:
patchfilevar = 'PATCHFILE="%s"' % os.path.basename(patch['file'])
try:
- shellcmd = [patchfilevar, "git", "--work-tree=%s" % reporoot, "am", "-3", "--keep-cr", "-p%s" % patch['strippath']]
+ shellcmd = [patchfilevar, "git", "--work-tree=%s" % reporoot]
+ self.gitCommandUserOptions(shellcmd, self.commituser, self.commitemail)
+ shellcmd += ["am", "-3", "--keep-cr", "--no-scissors", "-p%s" % patch['strippath']]
return _applypatchhelper(shellcmd, patch, force, reverse, run)
except CmdError:
# Need to abort the git am, or we'll still be within it at the end
@@ -486,7 +567,7 @@ class GitApplyTree(PatchTree):
shellcmd = ["git", "reset", "HEAD", self.patchdir]
output += runcmd(["sh", "-c", " ".join(shellcmd)], self.dir)
# Commit the result
- (tmpfile, shellcmd) = self.prepareCommit(patch['file'])
+ (tmpfile, shellcmd) = self.prepareCommit(patch['file'], self.commituser, self.commitemail)
try:
shellcmd.insert(0, patchfilevar)
output += runcmd(["sh", "-c", " ".join(shellcmd)], self.dir)
@@ -501,7 +582,7 @@ class GitApplyTree(PatchTree):
class QuiltTree(PatchSet):
def _runcmd(self, args, run = True):
- quiltrc = self.d.getVar('QUILTRCFILE', True)
+ quiltrc = self.d.getVar('QUILTRCFILE')
if not run:
return ["quilt"] + ["--quiltrc"] + [quiltrc] + args
runcmd(["quilt"] + ["--quiltrc"] + [quiltrc] + args, self.dir)
@@ -519,6 +600,8 @@ class QuiltTree(PatchSet):
def Clean(self):
try:
+ # make sure that patches/series file exists before quilt pop to keep quilt-0.67 happy
+ open(os.path.join(self.dir, "patches","series"), 'a').close()
self._runcmd(["pop", "-a", "-f"])
oe.path.remove(os.path.join(self.dir, "patches","series"))
except Exception:
@@ -677,7 +760,7 @@ class UserResolver(Resolver):
# Patch application failed
patchcmd = self.patchset.Push(True, False, False)
- t = self.patchset.d.getVar('T', True)
+ t = self.patchset.d.getVar('T')
if not t:
bb.msg.fatal("Build", "T not set")
bb.utils.mkdirhier(t)
@@ -719,3 +802,123 @@ class UserResolver(Resolver):
os.chdir(olddir)
raise
os.chdir(olddir)
+
+
+def patch_path(url, fetch, workdir, expand=True):
+ """Return the local path of a patch, or return nothing if this isn't a patch"""
+
+ local = fetch.localpath(url)
+ if os.path.isdir(local):
+ return
+ base, ext = os.path.splitext(os.path.basename(local))
+ if ext in ('.gz', '.bz2', '.xz', '.Z'):
+ if expand:
+ local = os.path.join(workdir, base)
+ ext = os.path.splitext(base)[1]
+
+ urldata = fetch.ud[url]
+ if "apply" in urldata.parm:
+ apply = oe.types.boolean(urldata.parm["apply"])
+ if not apply:
+ return
+ elif ext not in (".diff", ".patch"):
+ return
+
+ return local
+
+def src_patches(d, all=False, expand=True):
+ workdir = d.getVar('WORKDIR')
+ fetch = bb.fetch2.Fetch([], d)
+ patches = []
+ sources = []
+ for url in fetch.urls:
+ local = patch_path(url, fetch, workdir, expand)
+ if not local:
+ if all:
+ local = fetch.localpath(url)
+ sources.append(local)
+ continue
+
+ urldata = fetch.ud[url]
+ parm = urldata.parm
+ patchname = parm.get('pname') or os.path.basename(local)
+
+ apply, reason = should_apply(parm, d)
+ if not apply:
+ if reason:
+ bb.note("Patch %s %s" % (patchname, reason))
+ continue
+
+ patchparm = {'patchname': patchname}
+ if "striplevel" in parm:
+ striplevel = parm["striplevel"]
+ elif "pnum" in parm:
+ #bb.msg.warn(None, "Deprecated usage of 'pnum' url parameter in '%s', please use 'striplevel'" % url)
+ striplevel = parm["pnum"]
+ else:
+ striplevel = '1'
+ patchparm['striplevel'] = striplevel
+
+ patchdir = parm.get('patchdir')
+ if patchdir:
+ patchparm['patchdir'] = patchdir
+
+ localurl = bb.fetch.encodeurl(('file', '', local, '', '', patchparm))
+ patches.append(localurl)
+
+ if all:
+ return sources
+
+ return patches
+
+
+def should_apply(parm, d):
+ import bb.utils
+ if "mindate" in parm or "maxdate" in parm:
+ pn = d.getVar('PN')
+ srcdate = d.getVar('SRCDATE_%s' % pn)
+ if not srcdate:
+ srcdate = d.getVar('SRCDATE')
+
+ if srcdate == "now":
+ srcdate = d.getVar('DATE')
+
+ if "maxdate" in parm and parm["maxdate"] < srcdate:
+ return False, 'is outdated'
+
+ if "mindate" in parm and parm["mindate"] > srcdate:
+ return False, 'is predated'
+
+
+ if "minrev" in parm:
+ srcrev = d.getVar('SRCREV')
+ if srcrev and srcrev < parm["minrev"]:
+ return False, 'applies to later revisions'
+
+ if "maxrev" in parm:
+ srcrev = d.getVar('SRCREV')
+ if srcrev and srcrev > parm["maxrev"]:
+ return False, 'applies to earlier revisions'
+
+ if "rev" in parm:
+ srcrev = d.getVar('SRCREV')
+ if srcrev and parm["rev"] not in srcrev:
+ return False, "doesn't apply to revision"
+
+ if "notrev" in parm:
+ srcrev = d.getVar('SRCREV')
+ if srcrev and parm["notrev"] in srcrev:
+ return False, "doesn't apply to revision"
+
+ if "maxver" in parm:
+ pv = d.getVar('PV')
+ if bb.utils.vercmp_string_op(pv, parm["maxver"], ">"):
+ return False, "applies to earlier version"
+
+ if "minver" in parm:
+ pv = d.getVar('PV')
+ if bb.utils.vercmp_string_op(pv, parm["minver"], "<"):
+ return False, "applies to later version"
+
+ return True, None
+
diff --git a/meta/lib/oe/path.py b/meta/lib/oe/path.py
index 3c07df33d4..0dc8f172d5 100644
--- a/meta/lib/oe/path.py
+++ b/meta/lib/oe/path.py
@@ -1,3 +1,9 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: GPL-2.0-only
+#
+
import errno
import glob
import shutil
@@ -50,9 +56,30 @@ def make_relative_symlink(path):
os.remove(path)
os.symlink(base, path)
+def replace_absolute_symlinks(basedir, d):
+ """
+ Walk basedir looking for absolute symlinks and replacing them with relative ones.
+ The absolute links are assumed to be relative to basedir
+ (compared to make_relative_symlink above which tries to compute common ancestors
+ using pattern matching instead)
+ """
+ for walkroot, dirs, files in os.walk(basedir):
+ for file in files + dirs:
+ path = os.path.join(walkroot, file)
+ if not os.path.islink(path):
+ continue
+ link = os.readlink(path)
+ if not os.path.isabs(link):
+ continue
+ walkdir = os.path.dirname(path.rpartition(basedir)[2])
+ base = os.path.relpath(link, walkdir)
+ bb.debug(2, "Replacing absolute path %s with relative path %s" % (link, base))
+ os.remove(path)
+ os.symlink(base, path)
+
def format_display(path, metadata):
""" Prepare a path for display to the user. """
- rel = relative(metadata.getVar("TOPDIR", True), path)
+ rel = relative(metadata.getVar("TOPDIR"), path)
if len(rel) > len(path):
return path
else:
@@ -65,27 +92,66 @@ def copytree(src, dst):
# This way we also preserve hardlinks between files in the tree.
bb.utils.mkdirhier(dst)
- cmd = 'tar -cf - -C %s -p . | tar -xf - -C %s' % (src, dst)
+ cmd = "tar --xattrs --xattrs-include='*' -cf - -S -C %s -p . | tar --xattrs --xattrs-include='*' -xf - -C %s" % (src, dst)
subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT)
def copyhardlinktree(src, dst):
- """ Make the hard link when possible, otherwise copy. """
+ """Make a tree of hard links when possible, otherwise copy."""
bb.utils.mkdirhier(dst)
if os.path.isdir(src) and not len(os.listdir(src)):
return
- if (os.stat(src).st_dev == os.stat(dst).st_dev):
+ canhard = False
+ testfile = None
+ for root, dirs, files in os.walk(src):
+ if len(files):
+ testfile = os.path.join(root, files[0])
+ break
+
+ if testfile is not None:
+ try:
+ os.link(testfile, os.path.join(dst, 'testfile'))
+ os.unlink(os.path.join(dst, 'testfile'))
+ canhard = True
+ except Exception as e:
+ bb.debug(2, "Hardlink test failed with " + str(e))
+
+ if (canhard):
# Need to copy directories only with tar first since cp will error if two
# writers try and create a directory at the same time
- cmd = 'cd %s; find . -type d -print | tar -cf - -C %s -p --no-recursion --files-from - | tar -xf - -C %s' % (src, src, dst)
- subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT)
- cmd = 'cd %s; find . -print0 | cpio --null -pdlu %s' % (src, dst)
+ cmd = "cd %s; find . -type d -print | tar --xattrs --xattrs-include='*' -cf - -S -C %s -p --no-recursion --files-from - | tar --xattrs --xattrs-include='*' -xhf - -C %s" % (src, src, dst)
subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT)
+ source = ''
+ if os.path.isdir(src):
+ if len(glob.glob('%s/.??*' % src)) > 0:
+ source = './.??* '
+ source += './*'
+ s_dir = src
+ else:
+ source = src
+ s_dir = os.getcwd()
+ cmd = 'cp -afl --preserve=xattr %s %s' % (source, os.path.realpath(dst))
+ subprocess.check_output(cmd, shell=True, cwd=s_dir, stderr=subprocess.STDOUT)
else:
copytree(src, dst)
+def copyhardlink(src, dst):
+ """Make a hard link when possible, otherwise copy."""
+
+ try:
+ os.link(src, dst)
+ except OSError:
+ shutil.copy(src, dst)
+
def remove(path, recurse=True):
- """Equivalent to rm -f or rm -rf"""
+ """
+ Equivalent to rm -f or rm -rf
+ NOTE: be careful about passing paths that may contain filenames with
+ wildcards in them (as opposed to passing an actual wildcarded path) -
+ since we use glob.glob() to expand the path. Filenames containing
+ square brackets are particularly problematic since the they may not
+ actually expand to match the original filename.
+ """
for name in glob.glob(path):
try:
os.unlink(name)
@@ -200,3 +266,80 @@ def realpath(file, root, use_physdir = True, loop_cnt = 100, assume_dir = False)
raise
return file
+
+def is_path_parent(possible_parent, *paths):
+ """
+ Return True if a path is the parent of another, False otherwise.
+ Multiple paths to test can be specified in which case all
+ specified test paths must be under the parent in order to
+ return True.
+ """
+ def abs_path_trailing(pth):
+ pth_abs = os.path.abspath(pth)
+ if not pth_abs.endswith(os.sep):
+ pth_abs += os.sep
+ return pth_abs
+
+ possible_parent_abs = abs_path_trailing(possible_parent)
+ if not paths:
+ return False
+ for path in paths:
+ path_abs = abs_path_trailing(path)
+ if not path_abs.startswith(possible_parent_abs):
+ return False
+ return True
+
+def which_wild(pathname, path=None, mode=os.F_OK, *, reverse=False, candidates=False):
+ """Search a search path for pathname, supporting wildcards.
+
+ Return all paths in the specific search path matching the wildcard pattern
+ in pathname, returning only the first encountered for each file. If
+ candidates is True, information on all potential candidate paths are
+ included.
+ """
+ paths = (path or os.environ.get('PATH', os.defpath)).split(':')
+ if reverse:
+ paths.reverse()
+
+ seen, files = set(), []
+ for index, element in enumerate(paths):
+ if not os.path.isabs(element):
+ element = os.path.abspath(element)
+
+ candidate = os.path.join(element, pathname)
+ globbed = glob.glob(candidate)
+ if globbed:
+ for found_path in sorted(globbed):
+ if not os.access(found_path, mode):
+ continue
+ rel = os.path.relpath(found_path, element)
+ if rel not in seen:
+ seen.add(rel)
+ if candidates:
+ files.append((found_path, [os.path.join(p, rel) for p in paths[:index+1]]))
+ else:
+ files.append(found_path)
+
+ return files
+
+def canonicalize(paths, sep=','):
+ """Given a string with paths (separated by commas by default), expand
+ each path using os.path.realpath() and return the resulting paths as a
+ string (separated using the same separator a the original string).
+ """
+ # Ignore paths containing "$" as they are assumed to be unexpanded bitbake
+ # variables. Normally they would be ignored, e.g., when passing the paths
+ # through the shell they would expand to empty strings. However, when they
+ # are passed through os.path.realpath(), it will cause them to be prefixed
+ # with the absolute path to the current directory and thus not be empty
+ # anymore.
+ #
+ # Also maintain trailing slashes, as the paths may actually be used as
+ # prefixes in sting compares later on, where the slashes then are important.
+ canonical_paths = []
+ for path in (paths or '').split(sep):
+ if '$' not in path:
+ trailing_slash = path.endswith('/') and '/' or ''
+ canonical_paths.append(os.path.realpath(path) + trailing_slash)
+
+ return sep.join(canonical_paths)
diff --git a/meta/lib/oe/prservice.py b/meta/lib/oe/prservice.py
index 0054f954cc..2f2a0c128a 100644
--- a/meta/lib/oe/prservice.py
+++ b/meta/lib/oe/prservice.py
@@ -1,49 +1,51 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: GPL-2.0-only
+#
def prserv_make_conn(d, check = False):
import prserv.serv
- host_params = list([_f for _f in (d.getVar("PRSERV_HOST", True) or '').split(':') if _f])
+ host_params = list([_f for _f in (d.getVar("PRSERV_HOST") or '').split(':') if _f])
try:
conn = None
- conn = prserv.serv.PRServerConnection(host_params[0], int(host_params[1]))
+ conn = prserv.serv.connect(host_params[0], int(host_params[1]))
if check:
if not conn.ping():
raise Exception('service not available')
- d.setVar("__PRSERV_CONN",conn)
except Exception as exc:
bb.fatal("Connecting to PR service %s:%s failed: %s" % (host_params[0], host_params[1], str(exc)))
return conn
def prserv_dump_db(d):
- if not d.getVar('PRSERV_HOST', True):
+ if not d.getVar('PRSERV_HOST'):
bb.error("Not using network based PR service")
return None
- conn = d.getVar("__PRSERV_CONN", True)
+ conn = prserv_make_conn(d)
if conn is None:
- conn = prserv_make_conn(d)
- if conn is None:
- bb.error("Making connection failed to remote PR service")
- return None
+ bb.error("Making connection failed to remote PR service")
+ return None
#dump db
- opt_version = d.getVar('PRSERV_DUMPOPT_VERSION', True)
- opt_pkgarch = d.getVar('PRSERV_DUMPOPT_PKGARCH', True)
- opt_checksum = d.getVar('PRSERV_DUMPOPT_CHECKSUM', True)
- opt_col = ("1" == d.getVar('PRSERV_DUMPOPT_COL', True))
- return conn.export(opt_version, opt_pkgarch, opt_checksum, opt_col)
+ opt_version = d.getVar('PRSERV_DUMPOPT_VERSION')
+ opt_pkgarch = d.getVar('PRSERV_DUMPOPT_PKGARCH')
+ opt_checksum = d.getVar('PRSERV_DUMPOPT_CHECKSUM')
+ opt_col = ("1" == d.getVar('PRSERV_DUMPOPT_COL'))
+ d = conn.export(opt_version, opt_pkgarch, opt_checksum, opt_col)
+ conn.close()
+ return d
def prserv_import_db(d, filter_version=None, filter_pkgarch=None, filter_checksum=None):
- if not d.getVar('PRSERV_HOST', True):
+ if not d.getVar('PRSERV_HOST'):
bb.error("Not using network based PR service")
return None
- conn = d.getVar("__PRSERV_CONN", True)
+ conn = prserv_make_conn(d)
if conn is None:
- conn = prserv_make_conn(d)
- if conn is None:
- bb.error("Making connection failed to remote PR service")
- return None
+ bb.error("Making connection failed to remote PR service")
+ return None
#get the entry values
imported = []
prefix = "PRAUTO$"
@@ -58,7 +60,7 @@ def prserv_import_db(d, filter_version=None, filter_pkgarch=None, filter_checksu
(filter_checksum and filter_checksum != checksum):
continue
try:
- value = int(d.getVar(remain + '$' + version + '$' + pkgarch + '$' + checksum, True))
+ value = int(d.getVar(remain + '$' + version + '$' + pkgarch + '$' + checksum))
except BaseException as exc:
bb.debug("Not valid value of %s:%s" % (v,str(exc)))
continue
@@ -67,54 +69,54 @@ def prserv_import_db(d, filter_version=None, filter_pkgarch=None, filter_checksu
bb.error("importing(%s,%s,%s,%d) failed. DB may have larger value %d" % (version,pkgarch,checksum,value,ret))
else:
imported.append((version,pkgarch,checksum,value))
+ conn.close()
return imported
def prserv_export_tofile(d, metainfo, datainfo, lockdown, nomax=False):
import bb.utils
#initilize the output file
- bb.utils.mkdirhier(d.getVar('PRSERV_DUMPDIR', True))
- df = d.getVar('PRSERV_DUMPFILE', True)
+ bb.utils.mkdirhier(d.getVar('PRSERV_DUMPDIR'))
+ df = d.getVar('PRSERV_DUMPFILE')
#write data
lf = bb.utils.lockfile("%s.lock" % df)
- f = open(df, "a")
- if metainfo:
- #dump column info
- f.write("#PR_core_ver = \"%s\"\n\n" % metainfo['core_ver']);
- f.write("#Table: %s\n" % metainfo['tbl_name'])
- f.write("#Columns:\n")
- f.write("#name \t type \t notn \t dflt \t pk\n")
- f.write("#----------\t --------\t --------\t --------\t ----\n")
- for i in range(len(metainfo['col_info'])):
- f.write("#%10s\t %8s\t %8s\t %8s\t %4s\n" %
- (metainfo['col_info'][i]['name'],
- metainfo['col_info'][i]['type'],
- metainfo['col_info'][i]['notnull'],
- metainfo['col_info'][i]['dflt_value'],
- metainfo['col_info'][i]['pk']))
- f.write("\n")
+ with open(df, "a") as f:
+ if metainfo:
+ #dump column info
+ f.write("#PR_core_ver = \"%s\"\n\n" % metainfo['core_ver']);
+ f.write("#Table: %s\n" % metainfo['tbl_name'])
+ f.write("#Columns:\n")
+ f.write("#name \t type \t notn \t dflt \t pk\n")
+ f.write("#----------\t --------\t --------\t --------\t ----\n")
+ for i in range(len(metainfo['col_info'])):
+ f.write("#%10s\t %8s\t %8s\t %8s\t %4s\n" %
+ (metainfo['col_info'][i]['name'],
+ metainfo['col_info'][i]['type'],
+ metainfo['col_info'][i]['notnull'],
+ metainfo['col_info'][i]['dflt_value'],
+ metainfo['col_info'][i]['pk']))
+ f.write("\n")
- if lockdown:
- f.write("PRSERV_LOCKDOWN = \"1\"\n\n")
+ if lockdown:
+ f.write("PRSERV_LOCKDOWN = \"1\"\n\n")
- if datainfo:
- idx = {}
- for i in range(len(datainfo)):
- pkgarch = datainfo[i]['pkgarch']
- value = datainfo[i]['value']
- if pkgarch not in idx:
- idx[pkgarch] = i
- elif value > datainfo[idx[pkgarch]]['value']:
- idx[pkgarch] = i
- f.write("PRAUTO$%s$%s$%s = \"%s\"\n" %
- (str(datainfo[i]['version']), pkgarch, str(datainfo[i]['checksum']), str(value)))
- if not nomax:
- for i in idx:
- f.write("PRAUTO_%s_%s = \"%s\"\n" % (str(datainfo[idx[i]]['version']),str(datainfo[idx[i]]['pkgarch']),str(datainfo[idx[i]]['value'])))
- f.close()
+ if datainfo:
+ idx = {}
+ for i in range(len(datainfo)):
+ pkgarch = datainfo[i]['pkgarch']
+ value = datainfo[i]['value']
+ if pkgarch not in idx:
+ idx[pkgarch] = i
+ elif value > datainfo[idx[pkgarch]]['value']:
+ idx[pkgarch] = i
+ f.write("PRAUTO$%s$%s$%s = \"%s\"\n" %
+ (str(datainfo[i]['version']), pkgarch, str(datainfo[i]['checksum']), str(value)))
+ if not nomax:
+ for i in idx:
+ f.write("PRAUTO_%s_%s = \"%s\"\n" % (str(datainfo[idx[i]]['version']),str(datainfo[idx[i]]['pkgarch']),str(datainfo[idx[i]]['value'])))
bb.utils.unlockfile(lf)
def prserv_check_avail(d):
- host_params = list([_f for _f in (d.getVar("PRSERV_HOST", True) or '').split(':') if _f])
+ host_params = list([_f for _f in (d.getVar("PRSERV_HOST") or '').split(':') if _f])
try:
if len(host_params) != 2:
raise TypeError
@@ -123,4 +125,5 @@ def prserv_check_avail(d):
except TypeError:
bb.fatal('Undefined/incorrect PRSERV_HOST value. Format: "host:port"')
else:
- prserv_make_conn(d, True)
+ conn = prserv_make_conn(d, True)
+ conn.close()
diff --git a/meta/lib/oe/qa.py b/meta/lib/oe/qa.py
index 75e7df8546..b4cbc50045 100644
--- a/meta/lib/oe/qa.py
+++ b/meta/lib/oe/qa.py
@@ -1,4 +1,10 @@
-import os, struct
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: GPL-2.0-only
+#
+
+import os, struct, mmap
class NotELFFileError(Exception):
pass
@@ -23,9 +29,9 @@ class ELFFile:
EV_CURRENT = 1
# possible values for EI_DATA
- ELFDATANONE = 0
- ELFDATA2LSB = 1
- ELFDATA2MSB = 2
+ EI_DATA_NONE = 0
+ EI_DATA_LSB = 1
+ EI_DATA_MSB = 2
PT_INTERP = 3
@@ -34,51 +40,51 @@ class ELFFile:
#print "'%x','%x' %s" % (ord(expectation), ord(result), self.name)
raise NotELFFileError("%s is not an ELF" % self.name)
- def __init__(self, name, bits = 0):
+ def __init__(self, name):
self.name = name
- self.bits = bits
self.objdump_output = {}
+ self.data = None
- def open(self):
- if not os.path.isfile(self.name):
- raise NotELFFileError("%s is not a normal file" % self.name)
+ # Context Manager functions to close the mmap explicitly
+ def __enter__(self):
+ return self
+
+ def __exit__(self, exc_type, exc_value, traceback):
+ self.close()
+ def close(self):
+ if self.data:
+ self.data.close()
+
+ def open(self):
with open(self.name, "rb") as f:
- # Read 4k which should cover most of the headers we're after
- self.data = f.read(4096)
+ try:
+ self.data = mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ)
+ except ValueError:
+ # This means the file is empty
+ raise NotELFFileError("%s is empty" % self.name)
+ # Check the file has the minimum number of ELF table entries
if len(self.data) < ELFFile.EI_NIDENT + 4:
raise NotELFFileError("%s is not an ELF" % self.name)
+ # ELF header
self.my_assert(self.data[0], 0x7f)
self.my_assert(self.data[1], ord('E'))
self.my_assert(self.data[2], ord('L'))
self.my_assert(self.data[3], ord('F'))
- if self.bits == 0:
- if self.data[ELFFile.EI_CLASS] == ELFFile.ELFCLASS32:
- self.bits = 32
- elif self.data[ELFFile.EI_CLASS] == ELFFile.ELFCLASS64:
- self.bits = 64
- else:
- # Not 32-bit or 64.. lets assert
- raise NotELFFileError("ELF but not 32 or 64 bit.")
- elif self.bits == 32:
- self.my_assert(self.data[ELFFile.EI_CLASS], ELFFile.ELFCLASS32)
- elif self.bits == 64:
- self.my_assert(self.data[ELFFile.EI_CLASS], ELFFile.ELFCLASS64)
+ if self.data[ELFFile.EI_CLASS] == ELFFile.ELFCLASS32:
+ self.bits = 32
+ elif self.data[ELFFile.EI_CLASS] == ELFFile.ELFCLASS64:
+ self.bits = 64
else:
- raise NotELFFileError("Must specify unknown, 32 or 64 bit size.")
+ # Not 32-bit or 64.. lets assert
+ raise NotELFFileError("ELF but not 32 or 64 bit.")
self.my_assert(self.data[ELFFile.EI_VERSION], ELFFile.EV_CURRENT)
- self.sex = self.data[ELFFile.EI_DATA]
- if self.sex == ELFFile.ELFDATANONE:
- raise NotELFFileError("self.sex == ELFDATANONE")
- elif self.sex == ELFFile.ELFDATA2LSB:
- self.sex = "<"
- elif self.sex == ELFFile.ELFDATA2MSB:
- self.sex = ">"
- else:
- raise NotELFFileError("Unknown self.sex")
+ self.endian = self.data[ELFFile.EI_DATA]
+ if self.endian not in (ELFFile.EI_DATA_LSB, ELFFile.EI_DATA_MSB):
+ raise NotELFFileError("Unexpected EI_DATA %x" % self.endian)
def osAbi(self):
return self.data[ELFFile.EI_OSABI]
@@ -90,16 +96,20 @@ class ELFFile:
return self.bits
def isLittleEndian(self):
- return self.sex == "<"
+ return self.endian == ELFFile.EI_DATA_LSB
def isBigEndian(self):
- return self.sex == ">"
+ return self.endian == ELFFile.EI_DATA_MSB
+
+ def getStructEndian(self):
+ return {ELFFile.EI_DATA_LSB: "<",
+ ELFFile.EI_DATA_MSB: ">"}[self.endian]
def getShort(self, offset):
- return struct.unpack_from(self.sex+"H", self.data, offset)[0]
+ return struct.unpack_from(self.getStructEndian() + "H", self.data, offset)[0]
def getWord(self, offset):
- return struct.unpack_from(self.sex+"i", self.data, offset)[0]
+ return struct.unpack_from(self.getStructEndian() + "i", self.data, offset)[0]
def isDynamic(self):
"""
@@ -118,11 +128,14 @@ class ELFFile:
def machine(self):
"""
- We know the sex stored in self.sex and we
+ We know the endian stored in self.endian and we
know the position
"""
return self.getShort(ELFFile.E_MACHINE)
+ def set_objdump(self, cmd, output):
+ self.objdump_output[cmd] = output
+
def run_objdump(self, cmd, d):
import bb.process
import sys
@@ -130,11 +143,11 @@ class ELFFile:
if cmd in self.objdump_output:
return self.objdump_output[cmd]
- objdump = d.getVar('OBJDUMP', True)
+ objdump = d.getVar('OBJDUMP')
env = os.environ.copy()
env["LC_ALL"] = "C"
- env["PATH"] = d.getVar('PATH', True)
+ env["PATH"] = d.getVar('PATH')
try:
bb.note("%s %s %s" % (objdump, cmd, self.name))
@@ -144,8 +157,65 @@ class ELFFile:
bb.note("%s %s %s failed: %s" % (objdump, cmd, self.name, e))
return ""
+def elf_machine_to_string(machine):
+ """
+ Return the name of a given ELF e_machine field or the hex value as a string
+ if it isn't recognised.
+ """
+ try:
+ return {
+ 0x00: "Unset",
+ 0x02: "SPARC",
+ 0x03: "x86",
+ 0x08: "MIPS",
+ 0x14: "PowerPC",
+ 0x28: "ARM",
+ 0x2A: "SuperH",
+ 0x32: "IA-64",
+ 0x3E: "x86-64",
+ 0xB7: "AArch64",
+ 0xF7: "BPF"
+ }[machine]
+ except:
+ return "Unknown (%s)" % repr(machine)
+
+def write_error(type, error, d):
+ logfile = d.getVar('QA_LOGFILE')
+ if logfile:
+ p = d.getVar('P')
+ with open(logfile, "a+") as f:
+ f.write("%s: %s [%s]\n" % (p, error, type))
+
+def handle_error(error_class, error_msg, d):
+ if error_class in (d.getVar("ERROR_QA") or "").split():
+ write_error(error_class, error_msg, d)
+ bb.error("QA Issue: %s [%s]" % (error_msg, error_class))
+ d.setVar("QA_ERRORS_FOUND", "True")
+ return False
+ elif error_class in (d.getVar("WARN_QA") or "").split():
+ write_error(error_class, error_msg, d)
+ bb.warn("QA Issue: %s [%s]" % (error_msg, error_class))
+ else:
+ bb.note("QA Issue: %s [%s]" % (error_msg, error_class))
+ return True
+
+def add_message(messages, section, new_msg):
+ if section not in messages:
+ messages[section] = new_msg
+ else:
+ messages[section] = messages[section] + "\n" + new_msg
+
+def exit_with_message_if_errors(message, d):
+ qa_fatal_errors = bb.utils.to_boolean(d.getVar("QA_ERRORS_FOUND"), False)
+ if qa_fatal_errors:
+ bb.fatal(message)
+
+def exit_if_errors(d):
+ exit_with_message_if_errors("Fatal QA errors were found, failing task.", d)
+
if __name__ == "__main__":
import sys
- elf = ELFFile(sys.argv[1])
- elf.open()
- print(elf.isDynamic())
+
+ with ELFFile(sys.argv[1]) as elf:
+ elf.open()
+ print(elf.isDynamic())
diff --git a/meta/lib/oe/recipeutils.py b/meta/lib/oe/recipeutils.py
index c77664f135..b04992c66d 100644
--- a/meta/lib/oe/recipeutils.py
+++ b/meta/lib/oe/recipeutils.py
@@ -2,7 +2,9 @@
#
# Some code borrowed from the OE layer index
#
-# Copyright (C) 2013-2016 Intel Corporation
+# Copyright (C) 2013-2017 Intel Corporation
+#
+# SPDX-License-Identifier: GPL-2.0-only
#
import sys
@@ -16,70 +18,40 @@ import shutil
import re
import fnmatch
import glob
-from collections import OrderedDict, defaultdict
+import bb.tinfoil
+from collections import OrderedDict, defaultdict
+from bb.utils import vercmp_string
# Help us to find places to insert values
-recipe_progression = ['SUMMARY', 'DESCRIPTION', 'HOMEPAGE', 'BUGTRACKER', 'SECTION', 'LICENSE', 'LICENSE_FLAGS', 'LIC_FILES_CHKSUM', 'PROVIDES', 'DEPENDS', 'PR', 'PV', 'SRCREV', 'SRCPV', 'SRC_URI', 'S', 'do_fetch()', 'do_unpack()', 'do_patch()', 'EXTRA_OECONF', 'EXTRA_OECMAKE', 'EXTRA_OESCONS', 'do_configure()', 'EXTRA_OEMAKE', 'do_compile()', 'do_install()', 'do_populate_sysroot()', 'INITSCRIPT', 'USERADD', 'GROUPADD', 'PACKAGES', 'FILES', 'RDEPENDS', 'RRECOMMENDS', 'RSUGGESTS', 'RPROVIDES', 'RREPLACES', 'RCONFLICTS', 'ALLOW_EMPTY', 'populate_packages()', 'do_package()', 'do_deploy()']
+recipe_progression = ['SUMMARY', 'DESCRIPTION', 'AUTHOR', 'HOMEPAGE', 'BUGTRACKER', 'SECTION', 'LICENSE', 'LICENSE_FLAGS', 'LIC_FILES_CHKSUM', 'PROVIDES', 'DEPENDS', 'PR', 'PV', 'SRCREV', 'SRCPV', 'SRC_URI', 'S', 'do_fetch()', 'do_unpack()', 'do_patch()', 'EXTRA_OECONF', 'EXTRA_OECMAKE', 'EXTRA_OESCONS', 'do_configure()', 'EXTRA_OEMAKE', 'do_compile()', 'do_install()', 'do_populate_sysroot()', 'INITSCRIPT', 'USERADD', 'GROUPADD', 'PACKAGES', 'FILES', 'RDEPENDS', 'RRECOMMENDS', 'RSUGGESTS', 'RPROVIDES', 'RREPLACES', 'RCONFLICTS', 'ALLOW_EMPTY', 'populate_packages()', 'do_package()', 'do_deploy()', 'BBCLASSEXTEND']
# Variables that sometimes are a bit long but shouldn't be wrapped
-nowrap_vars = ['SUMMARY', 'HOMEPAGE', 'BUGTRACKER', 'SRC_URI[md5sum]', 'SRC_URI[sha256sum]']
+nowrap_vars = ['SUMMARY', 'HOMEPAGE', 'BUGTRACKER', r'SRC_URI\[(.+\.)?md5sum\]', r'SRC_URI\[(.+\.)?sha256sum\]']
list_vars = ['SRC_URI', 'LIC_FILES_CHKSUM']
meta_vars = ['SUMMARY', 'DESCRIPTION', 'HOMEPAGE', 'BUGTRACKER', 'SECTION']
-def pn_to_recipe(cooker, pn):
- """Convert a recipe name (PN) to the path to the recipe file"""
- import bb.providers
-
- if pn in cooker.recipecache.pkg_pn:
- best = bb.providers.findBestProvider(pn, cooker.data, cooker.recipecache, cooker.recipecache.pkg_pn)
- return best[3]
- elif pn in cooker.recipecache.providers:
- filenames = cooker.recipecache.providers[pn]
- eligible, foundUnique = bb.providers.filterProviders(filenames, pn, cooker.expanded_data, cooker.recipecache)
- filename = eligible[0]
- return filename
- else:
- return None
-
-
-def get_unavailable_reasons(cooker, pn):
- """If a recipe could not be found, find out why if possible"""
- import bb.taskdata
- taskdata = bb.taskdata.TaskData(None, skiplist=cooker.skiplist)
- return taskdata.get_reasons(pn)
-
-
-def parse_recipe(fn, appendfiles, d):
+def simplify_history(history, d):
"""
- Parse an individual recipe file, optionally with a list of
- bbappend files.
+ Eliminate any irrelevant events from a variable history
"""
- import bb.cache
- envdata = bb.cache.Cache.loadDataFull(fn, appendfiles, d)
- return envdata
-
-
-def parse_recipe_simple(cooker, pn, d, appends=True):
- """
- Parse a recipe and optionally all bbappends that apply to it
- in the current configuration.
- """
- import bb.providers
-
- recipefile = pn_to_recipe(cooker, pn)
- if not recipefile:
- skipreasons = get_unavailable_reasons(cooker, pn)
- # We may as well re-use bb.providers.NoProvider here
- if skipreasons:
- raise bb.providers.NoProvider(skipreasons)
- else:
- raise bb.providers.NoProvider('Unable to find any recipe file matching %s' % pn)
- if appends:
- appendfiles = cooker.collection.get_file_appends(recipefile)
- else:
- appendfiles = None
- return parse_recipe(recipefile, appendfiles, d)
+ ret_history = []
+ has_set = False
+ # Go backwards through the history and remove any immediate operations
+ # before the most recent set
+ for event in reversed(history):
+ if 'flag' in event or not 'file' in event:
+ continue
+ if event['op'] == 'set':
+ if has_set:
+ continue
+ has_set = True
+ elif event['op'] in ('append', 'prepend', 'postdot', 'predot'):
+ # Reminder: "append" and "prepend" mean += and =+ respectively, NOT :append / :prepend
+ if has_set:
+ continue
+ ret_history.insert(0, event)
+ return ret_history
def get_var_files(fn, varlist, d):
@@ -88,11 +60,19 @@ def get_var_files(fn, varlist, d):
"""
varfiles = {}
for v in varlist:
- history = d.varhistory.variable(v)
files = []
- for event in history:
- if 'file' in event and not 'flag' in event:
- files.append(event['file'])
+ if '[' in v:
+ varsplit = v.split('[')
+ varflag = varsplit[1].split(']')[0]
+ history = d.varhistory.variable(varsplit[0])
+ for event in history:
+ if 'file' in event and event.get('flag', '') == varflag:
+ files.append(event['file'])
+ else:
+ history = d.varhistory.variable(v)
+ for event in history:
+ if 'file' in event and not 'flag' in event:
+ files.append(event['file'])
if files:
actualfile = files[-1]
else:
@@ -172,6 +152,10 @@ def patch_recipe_lines(fromlines, values, trailing_newline=True):
else:
newline = ''
+ nowrap_vars_res = []
+ for item in nowrap_vars:
+ nowrap_vars_res.append(re.compile('^%s$' % item))
+
recipe_progression_res = []
recipe_progression_restrs = []
for item in recipe_progression:
@@ -179,7 +163,7 @@ def patch_recipe_lines(fromlines, values, trailing_newline=True):
key = item[:-2]
else:
key = item
- restr = '%s(_[a-zA-Z0-9-_$(){}]+|\[[^\]]*\])?' % key
+ restr = r'%s(_[a-zA-Z0-9-_$(){}]+|\[[^\]]*\])?' % key
if item.endswith('()'):
recipe_progression_restrs.append(restr + '()')
else:
@@ -202,15 +186,27 @@ def patch_recipe_lines(fromlines, values, trailing_newline=True):
def outputvalue(name, lines, rewindcomments=False):
if values[name] is None:
return
- rawtext = '%s = "%s"%s' % (name, values[name], newline)
+ if isinstance(values[name], tuple):
+ op, value = values[name]
+ if op == '+=' and value.strip() == '':
+ return
+ else:
+ value = values[name]
+ op = '='
+ rawtext = '%s %s "%s"%s' % (name, op, value, newline)
addlines = []
- if name in nowrap_vars:
+ nowrap = False
+ for nowrap_re in nowrap_vars_res:
+ if nowrap_re.match(name):
+ nowrap = True
+ break
+ if nowrap:
addlines.append(rawtext)
elif name in list_vars:
- splitvalue = split_var_value(values[name], assignment=False)
+ splitvalue = split_var_value(value, assignment=False)
if len(splitvalue) > 1:
linesplit = ' \\\n' + (' ' * (len(name) + 4))
- addlines.append('%s = "%s%s"%s' % (name, linesplit.join(splitvalue), linesplit, newline))
+ addlines.append('%s %s "%s%s"%s' % (name, op, linesplit.join(splitvalue), linesplit, newline))
else:
addlines.append(rawtext)
else:
@@ -218,6 +214,11 @@ def patch_recipe_lines(fromlines, values, trailing_newline=True):
for wrapline in wrapped[:-1]:
addlines.append('%s \\%s' % (wrapline, newline))
addlines.append('%s%s' % (wrapped[-1], newline))
+
+ # Split on newlines - this isn't strictly necessary if you are only
+ # going to write the output to disk, but if you want to compare it
+ # (as patch_recipe_file() will do if patch=True) then it's important.
+ addlines = [line for l in addlines for line in l.splitlines(True)]
if rewindcomments:
# Ensure we insert the lines before any leading comments
# (that we'd want to ensure remain leading the next value)
@@ -267,7 +268,7 @@ def patch_recipe_lines(fromlines, values, trailing_newline=True):
return changed, tolines
-def patch_recipe_file(fn, values, patch=False, relpath=''):
+def patch_recipe_file(fn, values, patch=False, relpath='', redirect_output=None):
"""Update or insert variable values into a recipe file (assuming you
have already identified the exact file you want to update.)
Note that some manual inspection/intervention may be required
@@ -279,7 +280,11 @@ def patch_recipe_file(fn, values, patch=False, relpath=''):
_, tolines = patch_recipe_lines(fromlines, values)
- if patch:
+ if redirect_output:
+ with open(os.path.join(redirect_output, os.path.basename(fn)), 'w') as f:
+ f.writelines(tolines)
+ return None
+ elif patch:
relfn = os.path.relpath(fn, relpath)
diff = difflib.unified_diff(fromlines, tolines, 'a/%s' % relfn, 'b/%s' % relfn)
return diff
@@ -329,17 +334,52 @@ def localise_file_vars(fn, varfiles, varlist):
return filevars
-def patch_recipe(d, fn, varvalues, patch=False, relpath=''):
+def patch_recipe(d, fn, varvalues, patch=False, relpath='', redirect_output=None):
"""Modify a list of variable values in the specified recipe. Handles inc files if
used by the recipe.
"""
+ overrides = d.getVar('OVERRIDES').split(':')
+ def override_applicable(hevent):
+ op = hevent['op']
+ if '[' in op:
+ opoverrides = op.split('[')[1].split(']')[0].split(':')
+ for opoverride in opoverrides:
+ if not opoverride in overrides:
+ return False
+ return True
+
varlist = varvalues.keys()
+ fn = os.path.abspath(fn)
varfiles = get_var_files(fn, varlist, d)
locs = localise_file_vars(fn, varfiles, varlist)
patches = []
for f,v in locs.items():
vals = {k: varvalues[k] for k in v}
- patchdata = patch_recipe_file(f, vals, patch, relpath)
+ f = os.path.abspath(f)
+ if f == fn:
+ extravals = {}
+ for var, value in vals.items():
+ if var in list_vars:
+ history = simplify_history(d.varhistory.variable(var), d)
+ recipe_set = False
+ for event in history:
+ if os.path.abspath(event['file']) == fn:
+ if event['op'] == 'set':
+ recipe_set = True
+ if not recipe_set:
+ for event in history:
+ if event['op'].startswith(':remove'):
+ continue
+ if not override_applicable(event):
+ continue
+ newvalue = value.replace(event['detail'], '')
+ if newvalue == value and os.path.abspath(event['file']) == fn and event['op'].startswith(':'):
+ op = event['op'].replace('[', ':').replace(']', '')
+ extravals[var + op] = None
+ value = newvalue
+ vals[var] = ('+=', value)
+ vals.update(extravals)
+ patchdata = patch_recipe_file(f, vals, patch, relpath, redirect_output)
if patch:
patches.append(patchdata)
@@ -350,7 +390,7 @@ def patch_recipe(d, fn, varvalues, patch=False, relpath=''):
-def copy_recipe_files(d, tgt_dir, whole_dir=False, download=True):
+def copy_recipe_files(d, tgt_dir, whole_dir=False, download=True, all_variants=False):
"""Copy (local) recipe files, including both files included via include/require,
and files referred to in the SRC_URI variable."""
import bb.fetch2
@@ -358,18 +398,43 @@ def copy_recipe_files(d, tgt_dir, whole_dir=False, download=True):
# FIXME need a warning if the unexpanded SRC_URI value contains variable references
- uris = (d.getVar('SRC_URI', True) or "").split()
- fetch = bb.fetch2.Fetch(uris, d)
- if download:
- fetch.download()
+ uri_values = []
+ localpaths = []
+ def fetch_urls(rdata):
+ # Collect the local paths from SRC_URI
+ srcuri = rdata.getVar('SRC_URI') or ""
+ if srcuri not in uri_values:
+ fetch = bb.fetch2.Fetch(srcuri.split(), rdata)
+ if download:
+ fetch.download()
+ for pth in fetch.localpaths():
+ if pth not in localpaths:
+ localpaths.append(os.path.abspath(pth))
+ uri_values.append(srcuri)
+
+ fetch_urls(d)
+ if all_variants:
+ # Get files for other variants e.g. in the case of a SRC_URI:append
+ localdata = bb.data.createCopy(d)
+ variants = (localdata.getVar('BBCLASSEXTEND') or '').split()
+ if variants:
+ # Ensure we handle class-target if we're dealing with one of the variants
+ variants.append('target')
+ for variant in variants:
+ if variant.startswith("devupstream"):
+ localdata.setVar('SRCPV', 'git')
+ localdata.setVar('CLASSOVERRIDE', 'class-%s' % variant)
+ fetch_urls(localdata)
# Copy local files to target directory and gather any remote files
- bb_dir = os.path.dirname(d.getVar('FILE', True)) + os.sep
+ bb_dir = os.path.abspath(os.path.dirname(d.getVar('FILE'))) + os.sep
remotes = []
copied = []
- includes = [path for path in d.getVar('BBINCLUDED', True).split() if
- path.startswith(bb_dir) and os.path.exists(path)]
- for path in fetch.localpaths() + includes:
+ # Need to do this in two steps since we want to check against the absolute path
+ includes = [os.path.abspath(path) for path in d.getVar('BBINCLUDED').split() if os.path.exists(path)]
+ # We also check this below, but we don't want any items in this list being considered remotes
+ includes = [path for path in includes if path.startswith(bb_dir)]
+ for path in localpaths + includes:
# Only import files that are under the meta directory
if path.startswith(bb_dir):
if not whole_dir:
@@ -388,28 +453,55 @@ def copy_recipe_files(d, tgt_dir, whole_dir=False, download=True):
return copied, remotes
-def get_recipe_local_files(d, patches=False):
+def get_recipe_local_files(d, patches=False, archives=False):
"""Get a list of local files in SRC_URI within a recipe."""
- uris = (d.getVar('SRC_URI', True) or "").split()
+ import oe.patch
+ uris = (d.getVar('SRC_URI') or "").split()
fetch = bb.fetch2.Fetch(uris, d)
+ # FIXME this list should be factored out somewhere else (such as the
+ # fetcher) though note that this only encompasses actual container formats
+ # i.e. that can contain multiple files as opposed to those that only
+ # contain a compressed stream (i.e. .tar.gz as opposed to just .gz)
+ archive_exts = ['.tar', '.tgz', '.tar.gz', '.tar.Z', '.tbz', '.tbz2', '.tar.bz2', '.txz', '.tar.xz', '.tar.lz', '.zip', '.jar', '.rpm', '.srpm', '.deb', '.ipk', '.tar.7z', '.7z']
ret = {}
for uri in uris:
if fetch.ud[uri].type == 'file':
if (not patches and
- bb.utils.exec_flat_python_func('patch_path', uri, fetch, '')):
+ oe.patch.patch_path(uri, fetch, '', expand=False)):
continue
# Skip files that are referenced by absolute path
- if not os.path.isabs(fetch.ud[uri].basepath):
- ret[fetch.ud[uri].basepath] = fetch.localpath(uri)
+ fname = fetch.ud[uri].basepath
+ if os.path.isabs(fname):
+ continue
+ # Handle subdir=
+ subdir = fetch.ud[uri].parm.get('subdir', '')
+ if subdir:
+ if os.path.isabs(subdir):
+ continue
+ fname = os.path.join(subdir, fname)
+ localpath = fetch.localpath(uri)
+ if not archives:
+ # Ignore archives that will be unpacked
+ if localpath.endswith(tuple(archive_exts)):
+ unpack = fetch.ud[uri].parm.get('unpack', True)
+ if unpack:
+ continue
+ if os.path.isdir(localpath):
+ for root, dirs, files in os.walk(localpath):
+ for fname in files:
+ fileabspath = os.path.join(root,fname)
+ srcdir = os.path.dirname(localpath)
+ ret[os.path.relpath(fileabspath,srcdir)] = fileabspath
+ else:
+ ret[fname] = localpath
return ret
def get_recipe_patches(d):
"""Get a list of the patches included in SRC_URI within a recipe."""
+ import oe.patch
+ patches = oe.patch.src_patches(d, expand=False)
patchfiles = []
- # Execute src_patches() defined in patch.bbclass - this works since that class
- # is inherited globally
- patches = bb.utils.exec_flat_python_func('src_patches', d)
for patch in patches:
_, _, local, _, _, parm = bb.fetch.decodeurl(patch)
patchfiles.append(local)
@@ -426,22 +518,20 @@ def get_recipe_patched_files(d):
change mode ('A' for add, 'D' for delete or 'M' for modify)
"""
import oe.patch
- # Execute src_patches() defined in patch.bbclass - this works since that class
- # is inherited globally
- patches = bb.utils.exec_flat_python_func('src_patches', d)
+ patches = oe.patch.src_patches(d, expand=False)
patchedfiles = {}
for patch in patches:
_, _, patchfile, _, _, parm = bb.fetch.decodeurl(patch)
striplevel = int(parm['striplevel'])
- patchedfiles[patchfile] = oe.patch.PatchSet.getPatchedFiles(patchfile, striplevel, os.path.join(d.getVar('S', True), parm.get('patchdir', '')))
+ patchedfiles[patchfile] = oe.patch.PatchSet.getPatchedFiles(patchfile, striplevel, os.path.join(d.getVar('S'), parm.get('patchdir', '')))
return patchedfiles
def validate_pn(pn):
"""Perform validation on a recipe name (PN) for a new recipe."""
reserved_names = ['forcevariable', 'append', 'prepend', 'remove']
- if not re.match('[0-9a-z-.]+', pn):
- return 'Recipe name "%s" is invalid: only characters 0-9, a-z, - and . are allowed' % pn
+ if not re.match('^[0-9a-z-.+]+$', pn):
+ return 'Recipe name "%s" is invalid: only characters 0-9, a-z, -, + and . are allowed' % pn
elif pn in reserved_names:
return 'Recipe name "%s" is invalid: is a reserved keyword' % pn
elif pn.startswith('pn-'):
@@ -471,9 +561,26 @@ def get_bbfile_path(d, destdir, extrapathhint=None):
confdata.setVar('LAYERDIR', destlayerdir)
destlayerconf = os.path.join(destlayerdir, "conf", "layer.conf")
confdata = bb.cookerdata.parse_config_file(destlayerconf, confdata)
- pn = d.getVar('PN', True)
-
- bbfilespecs = (confdata.getVar('BBFILES', True) or '').split()
+ pn = d.getVar('PN')
+
+ # Parse BBFILES_DYNAMIC and append to BBFILES
+ bbfiles_dynamic = (confdata.getVar('BBFILES_DYNAMIC') or "").split()
+ collections = (confdata.getVar('BBFILE_COLLECTIONS') or "").split()
+ invalid = []
+ for entry in bbfiles_dynamic:
+ parts = entry.split(":", 1)
+ if len(parts) != 2:
+ invalid.append(entry)
+ continue
+ l, f = parts
+ invert = l[0] == "!"
+ if invert:
+ l = l[1:]
+ if (l in collections and not invert) or (l not in collections and invert):
+ confdata.appendVar("BBFILES", " " + f)
+ if invalid:
+ return None
+ bbfilespecs = (confdata.getVar('BBFILES') or '').split()
if destdir == destlayerdir:
for bbfilespec in bbfilespecs:
if not bbfilespec.endswith('.bbappend'):
@@ -486,8 +593,8 @@ def get_bbfile_path(d, destdir, extrapathhint=None):
# Try to make up a path that matches BBFILES
# this is a little crude, but better than nothing
- bpn = d.getVar('BPN', True)
- recipefn = os.path.basename(d.getVar('FILE', True))
+ bpn = d.getVar('BPN')
+ recipefn = os.path.basename(d.getVar('FILE'))
pathoptions = [destdir]
if extrapathhint:
pathoptions.append(os.path.join(destdir, extrapathhint))
@@ -511,7 +618,7 @@ def get_bbappend_path(d, destlayerdir, wildcardver=False):
import bb.cookerdata
destlayerdir = os.path.abspath(destlayerdir)
- recipefile = d.getVar('FILE', True)
+ recipefile = d.getVar('FILE')
recipefn = os.path.splitext(os.path.basename(recipefile))[0]
if wildcardver and '_' in recipefn:
recipefn = recipefn.split('_', 1)[0] + '_%'
@@ -531,7 +638,7 @@ def get_bbappend_path(d, destlayerdir, wildcardver=False):
appendpath = os.path.join(destlayerdir, os.path.relpath(os.path.dirname(recipefile), origlayerdir), appendfn)
closepath = ''
pathok = True
- for bbfilespec in confdata.getVar('BBFILES', True).split():
+ for bbfilespec in confdata.getVar('BBFILES').split():
if fnmatch.fnmatchcase(appendpath, bbfilespec):
# Our append path works, we're done
break
@@ -559,7 +666,7 @@ def get_bbappend_path(d, destlayerdir, wildcardver=False):
return (appendpath, pathok)
-def bbappend_recipe(rd, destlayerdir, srcfiles, install=None, wildcardver=False, machine=None, extralines=None, removevalues=None):
+def bbappend_recipe(rd, destlayerdir, srcfiles, install=None, wildcardver=False, machine=None, extralines=None, removevalues=None, redirect_output=None, params=None):
"""
Writes a bbappend file for a recipe
Parameters:
@@ -586,6 +693,12 @@ def bbappend_recipe(rd, destlayerdir, srcfiles, install=None, wildcardver=False,
value pairs, or simply a list of the lines.
removevalues:
Variable values to remove - a dict of names/values.
+ redirect_output:
+ If specified, redirects writing the output file to the
+ specified directory (for dry-run purposes)
+ params:
+ Parameters to use when adding entries to SRC_URI. If specified,
+ should be a list of dicts with the same length as srcfiles.
"""
if not removevalues:
@@ -600,11 +713,12 @@ def bbappend_recipe(rd, destlayerdir, srcfiles, install=None, wildcardver=False,
bb.warn('Unable to determine correct subdirectory path for bbappend file - check that what %s adds to BBFILES also matches .bbappend files. Using %s for now, but until you fix this the bbappend will not be applied.' % (os.path.join(destlayerdir, 'conf', 'layer.conf'), os.path.dirname(appendpath)))
appenddir = os.path.dirname(appendpath)
- bb.utils.mkdirhier(appenddir)
+ if not redirect_output:
+ bb.utils.mkdirhier(appenddir)
# FIXME check if the bbappend doesn't get overridden by a higher priority layer?
- layerdirs = [os.path.abspath(layerdir) for layerdir in rd.getVar('BBLAYERS', True).split()]
+ layerdirs = [os.path.abspath(layerdir) for layerdir in rd.getVar('BBLAYERS').split()]
if not os.path.abspath(destlayerdir) in layerdirs:
bb.warn('Specified layer is not currently enabled in bblayers.conf, you will need to add it before this bbappend will be active')
@@ -640,28 +754,30 @@ def bbappend_recipe(rd, destlayerdir, srcfiles, install=None, wildcardver=False,
else:
bbappendlines.append((varname, op, value))
- destsubdir = rd.getVar('PN', True)
+ destsubdir = rd.getVar('PN')
if srcfiles:
- bbappendlines.append(('FILESEXTRAPATHS_prepend', ':=', '${THISDIR}/${PN}:'))
+ bbappendlines.append(('FILESEXTRAPATHS:prepend', ':=', '${THISDIR}/${PN}:'))
appendoverride = ''
if machine:
bbappendlines.append(('PACKAGE_ARCH', '=', '${MACHINE_ARCH}'))
- appendoverride = '_%s' % machine
+ appendoverride = ':%s' % machine
copyfiles = {}
if srcfiles:
instfunclines = []
- for newfile, origsrcfile in srcfiles.items():
+ for i, (newfile, origsrcfile) in enumerate(srcfiles.items()):
srcfile = origsrcfile
srcurientry = None
if not srcfile:
srcfile = os.path.basename(newfile)
srcurientry = 'file://%s' % srcfile
+ if params and params[i]:
+ srcurientry = '%s;%s' % (srcurientry, ';'.join('%s=%s' % (k,v) for k,v in params[i].items()))
# Double-check it's not there already
# FIXME do we care if the entry is added by another bbappend that might go away?
- if not srcurientry in rd.getVar('SRC_URI', True).split():
+ if not srcurientry in rd.getVar('SRC_URI').split():
if machine:
- appendline('SRC_URI_append%s' % appendoverride, '=', ' ' + srcurientry)
+ appendline('SRC_URI:append%s' % appendoverride, '=', ' ' + srcurientry)
else:
appendline('SRC_URI', '+=', srcurientry)
copyfiles[newfile] = srcfile
@@ -675,24 +791,33 @@ def bbappend_recipe(rd, destlayerdir, srcfiles, install=None, wildcardver=False,
instfunclines.append(instdirline)
instfunclines.append('install -m %s ${WORKDIR}/%s ${D}%s' % (perms, os.path.basename(srcfile), instdestpath))
if instfunclines:
- bbappendlines.append(('do_install_append%s()' % appendoverride, '', instfunclines))
-
- bb.note('Writing append file %s' % appendpath)
+ bbappendlines.append(('do_install:append%s()' % appendoverride, '', instfunclines))
+
+ if redirect_output:
+ bb.note('Writing append file %s (dry-run)' % appendpath)
+ outfile = os.path.join(redirect_output, os.path.basename(appendpath))
+ # Only take a copy if the file isn't already there (this function may be called
+ # multiple times per operation when we're handling overrides)
+ if os.path.exists(appendpath) and not os.path.exists(outfile):
+ shutil.copy2(appendpath, outfile)
+ else:
+ bb.note('Writing append file %s' % appendpath)
+ outfile = appendpath
- if os.path.exists(appendpath):
+ if os.path.exists(outfile):
# Work around lack of nonlocal in python 2
extvars = {'destsubdir': destsubdir}
def appendfile_varfunc(varname, origvalue, op, newlines):
- if varname == 'FILESEXTRAPATHS_prepend':
+ if varname == 'FILESEXTRAPATHS:prepend':
if origvalue.startswith('${THISDIR}/'):
- popline('FILESEXTRAPATHS_prepend')
+ popline('FILESEXTRAPATHS:prepend')
extvars['destsubdir'] = rd.expand(origvalue.split('${THISDIR}/', 1)[1].rstrip(':'))
elif varname == 'PACKAGE_ARCH':
if machine:
popline('PACKAGE_ARCH')
return (machine, None, 4, False)
- elif varname.startswith('do_install_append'):
+ elif varname.startswith('do_install:append'):
func = popline(varname)
if func:
instfunclines = [line.strip() for line in origvalue.strip('\n').splitlines()]
@@ -704,7 +829,7 @@ def bbappend_recipe(rd, destlayerdir, srcfiles, install=None, wildcardver=False,
splitval = split_var_value(origvalue, assignment=False)
changed = False
removevar = varname
- if varname in ['SRC_URI', 'SRC_URI_append%s' % appendoverride]:
+ if varname in ['SRC_URI', 'SRC_URI:append%s' % appendoverride]:
removevar = 'SRC_URI'
line = popline(varname)
if line:
@@ -733,11 +858,11 @@ def bbappend_recipe(rd, destlayerdir, srcfiles, install=None, wildcardver=False,
newvalue = splitval
if len(newvalue) == 1:
# Ensure it's written out as one line
- if '_append' in varname:
+ if ':append' in varname:
newvalue = ' ' + newvalue[0]
else:
newvalue = newvalue[0]
- if not newvalue and (op in ['+=', '.='] or '_append' in varname):
+ if not newvalue and (op in ['+=', '.='] or ':append' in varname):
# There's no point appending nothing
newvalue = None
if varname.endswith('()'):
@@ -751,7 +876,7 @@ def bbappend_recipe(rd, destlayerdir, srcfiles, install=None, wildcardver=False,
if removevalues:
varnames.extend(list(removevalues.keys()))
- with open(appendpath, 'r') as f:
+ with open(outfile, 'r') as f:
(updated, newlines) = bb.utils.edit_metadata(f, varnames, appendfile_varfunc)
destsubdir = extvars['destsubdir']
@@ -768,16 +893,27 @@ def bbappend_recipe(rd, destlayerdir, srcfiles, install=None, wildcardver=False,
updated = True
if updated:
- with open(appendpath, 'w') as f:
+ with open(outfile, 'w') as f:
f.writelines(newlines)
if copyfiles:
if machine:
destsubdir = os.path.join(destsubdir, machine)
+ if redirect_output:
+ outdir = redirect_output
+ else:
+ outdir = appenddir
for newfile, srcfile in copyfiles.items():
- filedest = os.path.join(appenddir, destsubdir, os.path.basename(srcfile))
+ filedest = os.path.join(outdir, destsubdir, os.path.basename(srcfile))
if os.path.abspath(newfile) != os.path.abspath(filedest):
- bb.note('Copying %s to %s' % (newfile, filedest))
+ if newfile.startswith(tempfile.gettempdir()):
+ newfiledisp = os.path.basename(newfile)
+ else:
+ newfiledisp = newfile
+ if redirect_output:
+ bb.note('Copying %s to %s (dry-run)' % (newfiledisp, os.path.join(appenddir, destsubdir, os.path.basename(srcfile))))
+ else:
+ bb.note('Copying %s to %s' % (newfiledisp, filedest))
bb.utils.mkdirhier(os.path.dirname(filedest))
shutil.copyfile(newfile, filedest)
@@ -786,7 +922,7 @@ def bbappend_recipe(rd, destlayerdir, srcfiles, install=None, wildcardver=False,
def find_layerdir(fn):
""" Figure out the path to the base of the layer containing a file (e.g. a recipe)"""
- pth = fn
+ pth = os.path.abspath(fn)
layerdir = ''
while pth:
if os.path.exists(os.path.join(pth, 'conf', 'layer.conf')):
@@ -804,7 +940,7 @@ def replace_dir_vars(path, d):
# Sort by length so we get the variables we're interested in first
for var in sorted(list(d.keys()), key=len):
if var.endswith('dir') and var.lower() == var:
- value = d.getVar(var, True)
+ value = d.getVar(var)
if value.startswith('/') and not '\n' in value and value not in dirvars:
dirvars[value] = var
for dirpath in sorted(list(dirvars.keys()), reverse=True):
@@ -822,7 +958,7 @@ def get_recipe_pv_without_srcpv(pv, uri_type):
sfx = ''
if uri_type == 'git':
- git_regex = re.compile("(?P<pfx>v?)(?P<ver>[^\+]*)((?P<sfx>\+(git)?r?(AUTOINC\+))(?P<rev>.*))?")
+ git_regex = re.compile(r"(?P<pfx>v?)(?P<ver>.*?)(?P<sfx>\+[^\+]*(git)?r?(AUTOINC\+))(?P<rev>.*)")
m = git_regex.match(pv)
if m:
@@ -830,7 +966,7 @@ def get_recipe_pv_without_srcpv(pv, uri_type):
pfx = m.group('pfx')
sfx = m.group('sfx')
else:
- regex = re.compile("(?P<pfx>(v|r)?)(?P<ver>.*)")
+ regex = re.compile(r"(?P<pfx>(v|r)?)(?P<ver>.*)")
m = regex.match(pv)
if m:
pv = m.group('ver')
@@ -847,25 +983,25 @@ def get_recipe_upstream_version(rd):
FetchError when don't have network access or upstream site don't response.
NoMethodError when uri latest_versionstring method isn't implemented.
- Returns a dictonary with version, type and datetime.
+ Returns a dictonary with version, repository revision, current_version, type and datetime.
Type can be A for Automatic, M for Manual and U for Unknown.
"""
from bb.fetch2 import decodeurl
from datetime import datetime
ru = {}
+ ru['current_version'] = rd.getVar('PV')
ru['version'] = ''
ru['type'] = 'U'
ru['datetime'] = ''
-
- pv = rd.getVar('PV', True)
+ ru['revision'] = ''
# XXX: If don't have SRC_URI means that don't have upstream sources so
# returns the current recipe version, so that upstream version check
# declares a match.
- src_uris = rd.getVar('SRC_URI', True)
+ src_uris = rd.getVar('SRC_URI')
if not src_uris:
- ru['version'] = pv
+ ru['version'] = ru['current_version']
ru['type'] = 'M'
ru['datetime'] = datetime.now()
return ru
@@ -874,13 +1010,16 @@ def get_recipe_upstream_version(rd):
src_uri = src_uris.split()[0]
uri_type, _, _, _, _, _ = decodeurl(src_uri)
- manual_upstream_version = rd.getVar("RECIPE_UPSTREAM_VERSION", True)
+ (pv, pfx, sfx) = get_recipe_pv_without_srcpv(rd.getVar('PV'), uri_type)
+ ru['current_version'] = pv
+
+ manual_upstream_version = rd.getVar("RECIPE_UPSTREAM_VERSION")
if manual_upstream_version:
# manual tracking of upstream version.
ru['version'] = manual_upstream_version
ru['type'] = 'M'
- manual_upstream_date = rd.getVar("CHECK_DATE", True)
+ manual_upstream_date = rd.getVar("CHECK_DATE")
if manual_upstream_date:
date = datetime.strptime(manual_upstream_date, "%b %d, %Y")
else:
@@ -894,33 +1033,118 @@ def get_recipe_upstream_version(rd):
ru['datetime'] = datetime.now()
else:
ud = bb.fetch2.FetchData(src_uri, rd)
- pupver = ud.method.latest_versionstring(ud, rd)
- (upversion, revision) = pupver
+ if rd.getVar("UPSTREAM_CHECK_COMMITS") == "1":
+ bb.fetch2.get_srcrev(rd)
+ revision = ud.method.latest_revision(ud, rd, 'default')
+ upversion = pv
+ if revision != rd.getVar("SRCREV"):
+ upversion = upversion + "-new-commits-available"
+ else:
+ pupver = ud.method.latest_versionstring(ud, rd)
+ (upversion, revision) = pupver
+
+ if upversion:
+ ru['version'] = upversion
+ ru['type'] = 'A'
+
+ if revision:
+ ru['revision'] = revision
+
+ ru['datetime'] = datetime.now()
- # format git version version+gitAUTOINC+HASH
- if uri_type == 'git':
- (pv, pfx, sfx) = get_recipe_pv_without_srcpv(pv, uri_type)
+ return ru
- # if contains revision but not upversion use current pv
- if upversion == '' and revision:
- upversion = pv
+def _get_recipe_upgrade_status(data):
+ uv = get_recipe_upstream_version(data)
- if upversion:
- tmp = upversion
- upversion = ''
+ pn = data.getVar('PN')
+ cur_ver = uv['current_version']
- if pfx:
- upversion = pfx + tmp
+ upstream_version_unknown = data.getVar('UPSTREAM_VERSION_UNKNOWN')
+ if not uv['version']:
+ status = "UNKNOWN" if upstream_version_unknown else "UNKNOWN_BROKEN"
+ else:
+ cmp = vercmp_string(uv['current_version'], uv['version'])
+ if cmp == -1:
+ status = "UPDATE" if not upstream_version_unknown else "KNOWN_BROKEN"
+ elif cmp == 0:
+ status = "MATCH" if not upstream_version_unknown else "KNOWN_BROKEN"
+ else:
+ status = "UNKNOWN" if upstream_version_unknown else "UNKNOWN_BROKEN"
+
+ next_ver = uv['version'] if uv['version'] else "N/A"
+ revision = uv['revision'] if uv['revision'] else "N/A"
+ maintainer = data.getVar('RECIPE_MAINTAINER')
+ no_upgrade_reason = data.getVar('RECIPE_NO_UPDATE_REASON')
+
+ return (pn, status, cur_ver, next_ver, maintainer, revision, no_upgrade_reason)
+
+def get_recipe_upgrade_status(recipes=None):
+ pkgs_list = []
+ data_copy_list = []
+ copy_vars = ('SRC_URI',
+ 'PV',
+ 'DL_DIR',
+ 'PN',
+ 'CACHE',
+ 'PERSISTENT_DIR',
+ 'BB_URI_HEADREVS',
+ 'UPSTREAM_CHECK_COMMITS',
+ 'UPSTREAM_CHECK_GITTAGREGEX',
+ 'UPSTREAM_CHECK_REGEX',
+ 'UPSTREAM_CHECK_URI',
+ 'UPSTREAM_VERSION_UNKNOWN',
+ 'RECIPE_MAINTAINER',
+ 'RECIPE_NO_UPDATE_REASON',
+ 'RECIPE_UPSTREAM_VERSION',
+ 'RECIPE_UPSTREAM_DATE',
+ 'CHECK_DATE',
+ 'FETCHCMD_bzr',
+ 'FETCHCMD_ccrc',
+ 'FETCHCMD_cvs',
+ 'FETCHCMD_git',
+ 'FETCHCMD_hg',
+ 'FETCHCMD_npm',
+ 'FETCHCMD_osc',
+ 'FETCHCMD_p4',
+ 'FETCHCMD_repo',
+ 'FETCHCMD_s3',
+ 'FETCHCMD_svn',
+ 'FETCHCMD_wget',
+ )
+
+ with bb.tinfoil.Tinfoil() as tinfoil:
+ tinfoil.prepare(config_only=False)
+
+ if not recipes:
+ recipes = tinfoil.all_recipe_files(variants=False)
+
+ for fn in recipes:
+ try:
+ if fn.startswith("/"):
+ data = tinfoil.parse_recipe_file(fn)
else:
- upversion = tmp
+ data = tinfoil.parse_recipe(fn)
+ except bb.providers.NoProvider:
+ bb.note(" No provider for %s" % fn)
+ continue
- if sfx:
- upversion = upversion + sfx + revision[:10]
+ unreliable = data.getVar('UPSTREAM_CHECK_UNRELIABLE')
+ if unreliable == "1":
+ bb.note(" Skip package %s as upstream check unreliable" % pn)
+ continue
- if upversion:
- ru['version'] = upversion
- ru['type'] = 'A'
+ data_copy = bb.data.init()
+ for var in copy_vars:
+ data_copy.setVar(var, data.getVar(var))
+ for k in data:
+ if k.startswith('SRCREV'):
+ data_copy.setVar(k, data.getVar(k))
- ru['datetime'] = datetime.now()
+ data_copy_list.append(data_copy)
- return ru
+ from concurrent.futures import ProcessPoolExecutor
+ with ProcessPoolExecutor(max_workers=utils.cpu_count()) as executor:
+ pkgs_list = executor.map(_get_recipe_upgrade_status, data_copy_list)
+
+ return pkgs_list
diff --git a/meta/lib/oe/reproducible.py b/meta/lib/oe/reproducible.py
new file mode 100644
index 0000000000..9ac75c02e3
--- /dev/null
+++ b/meta/lib/oe/reproducible.py
@@ -0,0 +1,194 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: GPL-2.0-only
+#
+import os
+import subprocess
+import bb
+
+# For reproducible builds, this code sets the default SOURCE_DATE_EPOCH in each
+# component's build environment. The format is number of seconds since the
+# system epoch.
+#
+# Upstream components (generally) respect this environment variable,
+# using it in place of the "current" date and time.
+# See https://reproducible-builds.org/specs/source-date-epoch/
+#
+# The default value of SOURCE_DATE_EPOCH comes from the function
+# get_source_date_epoch_value which reads from the SDE_FILE, or if the file
+# is not available will use the fallback of SOURCE_DATE_EPOCH_FALLBACK.
+#
+# The SDE_FILE is normally constructed from the function
+# create_source_date_epoch_stamp which is typically added as a postfuncs to
+# the do_unpack task. If a recipe does NOT have do_unpack, it should be added
+# to a task that runs after the source is available and before the
+# do_deploy_source_date_epoch task is executed.
+#
+# If a recipe wishes to override the default behavior it should set it's own
+# SOURCE_DATE_EPOCH or override the do_deploy_source_date_epoch_stamp task
+# with recipe-specific functionality to write the appropriate
+# SOURCE_DATE_EPOCH into the SDE_FILE.
+#
+# SOURCE_DATE_EPOCH is intended to be a reproducible value. This value should
+# be reproducible for anyone who builds the same revision from the same
+# sources.
+#
+# There are 4 ways the create_source_date_epoch_stamp function determines what
+# becomes SOURCE_DATE_EPOCH:
+#
+# 1. Use the value from __source_date_epoch.txt file if this file exists.
+# This file was most likely created in the previous build by one of the
+# following methods 2,3,4.
+# Alternatively, it can be provided by a recipe via SRC_URI.
+#
+# If the file does not exist:
+#
+# 2. If there is a git checkout, use the last git commit timestamp.
+# Git does not preserve file timestamps on checkout.
+#
+# 3. Use the mtime of "known" files such as NEWS, CHANGLELOG, ...
+# This works for well-kept repositories distributed via tarball.
+#
+# 4. Use the modification time of the youngest file in the source tree, if
+# there is one.
+# This will be the newest file from the distribution tarball, if any.
+#
+# 5. Fall back to a fixed timestamp (SOURCE_DATE_EPOCH_FALLBACK).
+#
+# Once the value is determined, it is stored in the recipe's SDE_FILE.
+
+def get_source_date_epoch_from_known_files(d, sourcedir):
+ source_date_epoch = None
+ newest_file = None
+ known_files = set(["NEWS", "ChangeLog", "Changelog", "CHANGES"])
+ for file in known_files:
+ filepath = os.path.join(sourcedir, file)
+ if os.path.isfile(filepath):
+ mtime = int(os.lstat(filepath).st_mtime)
+ # There may be more than one "known_file" present, if so, use the youngest one
+ if not source_date_epoch or mtime > source_date_epoch:
+ source_date_epoch = mtime
+ newest_file = filepath
+ if newest_file:
+ bb.debug(1, "SOURCE_DATE_EPOCH taken from: %s" % newest_file)
+ return source_date_epoch
+
+def find_git_folder(d, sourcedir):
+ # First guess: WORKDIR/git
+ # This is the default git fetcher unpack path
+ workdir = d.getVar('WORKDIR')
+ gitpath = os.path.join(workdir, "git/.git")
+ if os.path.isdir(gitpath):
+ return gitpath
+
+ # Second guess: ${S}
+ gitpath = os.path.join(sourcedir, ".git")
+ if os.path.isdir(gitpath):
+ return gitpath
+
+ # Perhaps there was a subpath or destsuffix specified.
+ # Go looking in the WORKDIR
+ exclude = set(["build", "image", "license-destdir", "patches", "pseudo",
+ "recipe-sysroot", "recipe-sysroot-native", "sysroot-destdir", "temp"])
+ for root, dirs, files in os.walk(workdir, topdown=True):
+ dirs[:] = [d for d in dirs if d not in exclude]
+ if '.git' in dirs:
+ return os.path.join(root, ".git")
+
+ bb.warn("Failed to find a git repository in WORKDIR: %s" % workdir)
+ return None
+
+def get_source_date_epoch_from_git(d, sourcedir):
+ if not "git://" in d.getVar('SRC_URI') and not "gitsm://" in d.getVar('SRC_URI'):
+ return None
+
+ gitpath = find_git_folder(d, sourcedir)
+ if not gitpath:
+ return None
+
+ # Check that the repository has a valid HEAD; it may not if subdir is used
+ # in SRC_URI
+ p = subprocess.run(['git', '--git-dir', gitpath, 'rev-parse', 'HEAD'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+ if p.returncode != 0:
+ bb.debug(1, "%s does not have a valid HEAD: %s" % (gitpath, p.stdout.decode('utf-8')))
+ return None
+
+ bb.debug(1, "git repository: %s" % gitpath)
+ p = subprocess.run(['git', '-c', 'log.showSignature=false', '--git-dir', gitpath, 'log', '-1', '--pretty=%ct'],
+ check=True, stdout=subprocess.PIPE)
+ return int(p.stdout.decode('utf-8'))
+
+def get_source_date_epoch_from_youngest_file(d, sourcedir):
+ if sourcedir == d.getVar('WORKDIR'):
+ # These sources are almost certainly not from a tarball
+ return None
+
+ # Do it the hard way: check all files and find the youngest one...
+ source_date_epoch = None
+ newest_file = None
+ for root, dirs, files in os.walk(sourcedir, topdown=True):
+ files = [f for f in files if not f[0] == '.']
+
+ for fname in files:
+ filename = os.path.join(root, fname)
+ try:
+ mtime = int(os.lstat(filename).st_mtime)
+ except ValueError:
+ mtime = 0
+ if not source_date_epoch or mtime > source_date_epoch:
+ source_date_epoch = mtime
+ newest_file = filename
+
+ if newest_file:
+ bb.debug(1, "Newest file found: %s" % newest_file)
+ return source_date_epoch
+
+def fixed_source_date_epoch(d):
+ bb.debug(1, "No tarball or git repo found to determine SOURCE_DATE_EPOCH")
+ source_date_epoch = d.getVar('SOURCE_DATE_EPOCH_FALLBACK')
+ if source_date_epoch:
+ bb.debug(1, "Using SOURCE_DATE_EPOCH_FALLBACK")
+ return int(source_date_epoch)
+ return 0
+
+def get_source_date_epoch(d, sourcedir):
+ return (
+ get_source_date_epoch_from_git(d, sourcedir) or
+ get_source_date_epoch_from_youngest_file(d, sourcedir) or
+ fixed_source_date_epoch(d) # Last resort
+ )
+
+def epochfile_read(epochfile, d):
+ cached, efile = d.getVar('__CACHED_SOURCE_DATE_EPOCH') or (None, None)
+ if cached and efile == epochfile:
+ return cached
+
+ if cached and epochfile != efile:
+ bb.debug(1, "Epoch file changed from %s to %s" % (efile, epochfile))
+
+ source_date_epoch = int(d.getVar('SOURCE_DATE_EPOCH_FALLBACK'))
+ try:
+ with open(epochfile, 'r') as f:
+ s = f.read()
+ try:
+ source_date_epoch = int(s)
+ except ValueError:
+ bb.warn("SOURCE_DATE_EPOCH value '%s' is invalid. Reverting to SOURCE_DATE_EPOCH_FALLBACK" % s)
+ source_date_epoch = int(d.getVar('SOURCE_DATE_EPOCH_FALLBACK'))
+ bb.debug(1, "SOURCE_DATE_EPOCH: %d" % source_date_epoch)
+ except FileNotFoundError:
+ bb.debug(1, "Cannot find %s. SOURCE_DATE_EPOCH will default to %d" % (epochfile, source_date_epoch))
+
+ d.setVar('__CACHED_SOURCE_DATE_EPOCH', (str(source_date_epoch), epochfile))
+ return str(source_date_epoch)
+
+def epochfile_write(source_date_epoch, epochfile, d):
+
+ bb.debug(1, "SOURCE_DATE_EPOCH: %d" % source_date_epoch)
+ bb.utils.mkdirhier(os.path.dirname(epochfile))
+
+ tmp_file = "%s.new" % epochfile
+ with open(tmp_file, 'w') as f:
+ f.write(str(source_date_epoch))
+ os.rename(tmp_file, epochfile)
diff --git a/meta/lib/oe/rootfs.py b/meta/lib/oe/rootfs.py
index ed0bab1fa4..f26b66ba7a 100644
--- a/meta/lib/oe/rootfs.py
+++ b/meta/lib/oe/rootfs.py
@@ -1,26 +1,30 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: GPL-2.0-only
+#
from abc import ABCMeta, abstractmethod
from oe.utils import execute_pre_post_process
from oe.package_manager import *
from oe.manifest import *
import oe.path
-import filecmp
import shutil
import os
import subprocess
import re
-
class Rootfs(object, metaclass=ABCMeta):
"""
This is an abstract class. Do not instantiate this directly.
"""
- def __init__(self, d, progress_reporter=None):
+ def __init__(self, d, progress_reporter=None, logcatcher=None):
self.d = d
self.pm = None
- self.image_rootfs = self.d.getVar('IMAGE_ROOTFS', True)
- self.deploy_dir_image = self.d.getVar('DEPLOY_DIR_IMAGE', True)
+ self.image_rootfs = self.d.getVar('IMAGE_ROOTFS')
+ self.deploydir = self.d.getVar('IMGDEPLOYDIR')
self.progress_reporter = progress_reporter
+ self.logcatcher = logcatcher
self.install_order = Manifest.INSTALL_ORDER
@@ -47,12 +51,16 @@ class Rootfs(object, metaclass=ABCMeta):
excludes = [ 'log_check', r'^\+' ]
if hasattr(self, 'log_check_expected_regexes'):
excludes.extend(self.log_check_expected_regexes)
+ # Insert custom log_check excludes
+ excludes += [x for x in (self.d.getVar("IMAGE_LOG_CHECK_EXCLUDES") or "").split(" ") if x]
excludes = [re.compile(x) for x in excludes]
r = re.compile(match)
log_path = self.d.expand("${T}/log.do_rootfs")
messages = []
with open(log_path, 'r') as log:
for line in log:
+ if self.logcatcher and self.logcatcher.contains(line.rstrip()):
+ continue
for ee in excludes:
m = ee.search(line)
if m:
@@ -69,7 +77,7 @@ class Rootfs(object, metaclass=ABCMeta):
else:
msg = '%d %s messages' % (len(messages), type)
msg = '[log_check] %s: found %s in the logfile:\n%s' % \
- (self.d.getVar('PN', True), msg, ''.join(messages))
+ (self.d.getVar('PN'), msg, ''.join(messages))
if type == 'error':
bb.fatal(msg)
else:
@@ -81,14 +89,37 @@ class Rootfs(object, metaclass=ABCMeta):
def _log_check_error(self):
self._log_check_common('error', self.log_check_regex)
+ def _get_feed_archs(self):
+ feed_archs = self.d.getVar('PACKAGE_FEED_ARCHS') or ''
+ if not feed_archs:
+ bb.note(" Figuring PACKAGE_FEED_ARCHS from ALL_MULTILIB_PACKAGE_ARCHS")
+ manager = self.d.getVar('ROOTFS_PKGMANAGE')
+ deploy_dir = ''
+ if 'rpm' in manager:
+ deploy_dir = self.d.getVar('DEPLOY_DIR_RPM')
+ elif 'opkg' in manager:
+ deploy_dir = self.d.getVar('DEPLOY_DIR_IPK')
+ elif 'dpkg' in manager:
+ deploy_dir = self.d.getVar('DEPLOY_DIR_DEB')
+ else:
+ bb.warn('Failed to figure out deploy_dir')
+ return ''
+
+ for arch in self.d.getVar('ALL_MULTILIB_PACKAGE_ARCHS').split():
+ if 'rpm' in manager:
+ arch = arch.replace("-", "_")
+ arch_path = os.path.join(deploy_dir, arch)
+ if os.path.exists(arch_path):
+ feed_archs += " %s" % arch
+ return feed_archs.strip()
+
def _insert_feed_uris(self):
if bb.utils.contains("IMAGE_FEATURES", "package-management",
True, False, self.d):
- self.pm.insert_feeds_uris()
+ self.pm.insert_feeds_uris(self.d.getVar('PACKAGE_FEED_URIS') or "",
+ self.d.getVar('PACKAGE_FEED_BASE_PATHS') or "",
+ self._get_feed_archs())
- @abstractmethod
- def _handle_intercept_failure(self, failed_script):
- pass
"""
The _cleanup() method should be used to clean-up stuff that we don't really
@@ -100,7 +131,7 @@ class Rootfs(object, metaclass=ABCMeta):
pass
def _setup_dbg_rootfs(self, dirs):
- gen_debugfs = self.d.getVar('IMAGE_GEN_DEBUGFS', True) or '0'
+ gen_debugfs = self.d.getVar('IMAGE_GEN_DEBUGFS') or '0'
if gen_debugfs != '1':
return
@@ -109,7 +140,7 @@ class Rootfs(object, metaclass=ABCMeta):
shutil.rmtree(self.image_rootfs + '-orig')
except:
pass
- os.rename(self.image_rootfs, self.image_rootfs + '-orig')
+ bb.utils.rename(self.image_rootfs, self.image_rootfs + '-orig')
bb.note(" Creating debug rootfs...")
bb.utils.mkdirhier(self.image_rootfs)
@@ -121,17 +152,16 @@ class Rootfs(object, metaclass=ABCMeta):
bb.utils.mkdirhier(self.image_rootfs + os.path.dirname(dir))
shutil.copytree(self.image_rootfs + '-orig' + dir, self.image_rootfs + dir, symlinks=True)
- cpath = oe.cachedpath.CachedPath()
# Copy files located in /usr/lib/debug or /usr/src/debug
for dir in ["/usr/lib/debug", "/usr/src/debug"]:
src = self.image_rootfs + '-orig' + dir
- if cpath.exists(src):
+ if os.path.exists(src):
dst = self.image_rootfs + dir
bb.utils.mkdirhier(os.path.dirname(dst))
shutil.copytree(src, dst)
# Copy files with suffix '.debug' or located in '.debug' dir.
- for root, dirs, files in cpath.walk(self.image_rootfs + '-orig'):
+ for root, dirs, files in os.walk(self.image_rootfs + '-orig'):
relative_dir = root[len(self.image_rootfs + '-orig'):]
for f in files:
if f.endswith('.debug') or '/.debug' in relative_dir:
@@ -142,25 +172,33 @@ class Rootfs(object, metaclass=ABCMeta):
bb.note(" Install complementary '*-dbg' packages...")
self.pm.install_complementary('*-dbg')
+ if self.d.getVar('PACKAGE_DEBUG_SPLIT_STYLE') == 'debug-with-srcpkg':
+ bb.note(" Install complementary '*-src' packages...")
+ self.pm.install_complementary('*-src')
+
+ """
+ Install additional debug packages. Possibility to install additional packages,
+ which are not automatically installed as complementary package of
+ standard one, e.g. debug package of static libraries.
+ """
+ extra_debug_pkgs = self.d.getVar('IMAGE_INSTALL_DEBUGFS')
+ if extra_debug_pkgs:
+ bb.note(" Install extra debug packages...")
+ self.pm.install(extra_debug_pkgs.split(), True)
+
bb.note(" Rename debug rootfs...")
try:
shutil.rmtree(self.image_rootfs + '-dbg')
except:
pass
- os.rename(self.image_rootfs, self.image_rootfs + '-dbg')
+ bb.utils.rename(self.image_rootfs, self.image_rootfs + '-dbg')
- bb.note(" Restoreing original rootfs...")
- os.rename(self.image_rootfs + '-orig', self.image_rootfs)
+ bb.note(" Restoring original rootfs...")
+ bb.utils.rename(self.image_rootfs + '-orig', self.image_rootfs)
def _exec_shell_cmd(self, cmd):
- fakerootcmd = self.d.getVar('FAKEROOT', True)
- if fakerootcmd is not None:
- exec_cmd = [fakerootcmd, cmd]
- else:
- exec_cmd = cmd
-
try:
- subprocess.check_output(exec_cmd, stderr=subprocess.STDOUT)
+ subprocess.check_output(cmd, stderr=subprocess.STDOUT)
except subprocess.CalledProcessError as e:
return("Command '%s' returned %d:\n%s" % (e.cmd, e.returncode, e.output))
@@ -168,27 +206,9 @@ class Rootfs(object, metaclass=ABCMeta):
def create(self):
bb.note("###### Generate rootfs #######")
- pre_process_cmds = self.d.getVar("ROOTFS_PREPROCESS_COMMAND", True)
- post_process_cmds = self.d.getVar("ROOTFS_POSTPROCESS_COMMAND", True)
- rootfs_post_install_cmds = self.d.getVar('ROOTFS_POSTINSTALL_COMMAND', True)
-
- postinst_intercepts_dir = self.d.getVar("POSTINST_INTERCEPTS_DIR", True)
- if not postinst_intercepts_dir:
- postinst_intercepts_dir = self.d.expand("${COREBASE}/scripts/postinst-intercepts")
- intercepts_dir = os.path.join(self.d.getVar('WORKDIR', True),
- "intercept_scripts")
-
- bb.utils.remove(intercepts_dir, True)
-
- bb.utils.mkdirhier(self.image_rootfs)
-
- bb.utils.mkdirhier(self.deploy_dir_image)
-
- shutil.copytree(postinst_intercepts_dir, intercepts_dir)
-
- shutil.copy(self.d.expand("${COREBASE}/meta/files/deploydir_readme.txt"),
- self.deploy_dir_image +
- "/README_-_DO_NOT_DELETE_FILES_IN_THIS_DIRECTORY.txt")
+ pre_process_cmds = self.d.getVar("ROOTFS_PREPROCESS_COMMAND")
+ post_process_cmds = self.d.getVar("ROOTFS_POSTPROCESS_COMMAND")
+ rootfs_post_install_cmds = self.d.getVar('ROOTFS_POSTINSTALL_COMMAND')
execute_pre_post_process(self.d, pre_process_cmds)
@@ -198,14 +218,14 @@ class Rootfs(object, metaclass=ABCMeta):
# call the package manager dependent create method
self._create()
- sysconfdir = self.image_rootfs + self.d.getVar('sysconfdir', True)
+ sysconfdir = self.image_rootfs + self.d.getVar('sysconfdir')
bb.utils.mkdirhier(sysconfdir)
with open(sysconfdir + "/version", "w+") as ver:
- ver.write(self.d.getVar('BUILDNAME', True) + "\n")
+ ver.write(self.d.getVar('BUILDNAME') + "\n")
execute_pre_post_process(self.d, rootfs_post_install_cmds)
- self._run_intercepts()
+ self.pm.run_intercepts()
execute_pre_post_process(self.d, post_process_cmds)
@@ -213,6 +233,9 @@ class Rootfs(object, metaclass=ABCMeta):
self.progress_reporter.next_stage()
if bb.utils.contains("IMAGE_FEATURES", "read-only-rootfs",
+ True, False, self.d) and \
+ not bb.utils.contains("IMAGE_FEATURES",
+ "read-only-rootfs-delayed-postinsts",
True, False, self.d):
delayed_postinsts = self._get_delayed_postinsts()
if delayed_postinsts is not None:
@@ -220,7 +243,7 @@ class Rootfs(object, metaclass=ABCMeta):
"offline and rootfs is read-only: %s" %
delayed_postinsts)
- if self.d.getVar('USE_DEVFS', True) != "1":
+ if self.d.getVar('USE_DEVFS') != "1":
self._create_devfs()
self._uninstall_unneeded()
@@ -232,7 +255,7 @@ class Rootfs(object, metaclass=ABCMeta):
self._run_ldconfig()
- if self.d.getVar('USE_DEPMOD', True) != "0":
+ if self.d.getVar('USE_DEPMOD') != "0":
self._generate_kernel_module_deps()
self._cleanup()
@@ -243,24 +266,36 @@ class Rootfs(object, metaclass=ABCMeta):
def _uninstall_unneeded(self):
- # Remove unneeded init script symlinks
+ # Remove the run-postinsts package if no delayed postinsts are found
delayed_postinsts = self._get_delayed_postinsts()
if delayed_postinsts is None:
- if os.path.exists(self.d.expand("${IMAGE_ROOTFS}${sysconfdir}/init.d/run-postinsts")):
- self._exec_shell_cmd(["update-rc.d", "-f", "-r",
- self.d.getVar('IMAGE_ROOTFS', True),
- "run-postinsts", "remove"])
+ if os.path.exists(self.d.expand("${IMAGE_ROOTFS}${sysconfdir}/init.d/run-postinsts")) or os.path.exists(self.d.expand("${IMAGE_ROOTFS}${systemd_system_unitdir}/run-postinsts.service")):
+ self.pm.remove(["run-postinsts"])
image_rorfs = bb.utils.contains("IMAGE_FEATURES", "read-only-rootfs",
True, False, self.d)
- if image_rorfs:
+ image_rorfs_force = self.d.getVar('FORCE_RO_REMOVE')
+
+ if image_rorfs or image_rorfs_force == "1":
# Remove components that we don't need if it's a read-only rootfs
- unneeded_pkgs = self.d.getVar("ROOTFS_RO_UNNEEDED", True).split()
+ unneeded_pkgs = self.d.getVar("ROOTFS_RO_UNNEEDED").split()
pkgs_installed = image_list_installed_packages(self.d)
- pkgs_to_remove = [pkg for pkg in pkgs_installed if pkg in unneeded_pkgs]
-
+ # Make sure update-alternatives is removed last. This is
+ # because its database has to available while uninstalling
+ # other packages, allowing alternative symlinks of packages
+ # to be uninstalled or to be managed correctly otherwise.
+ provider = self.d.getVar("VIRTUAL-RUNTIME_update-alternatives")
+ pkgs_to_remove = sorted([pkg for pkg in pkgs_installed if pkg in unneeded_pkgs], key=lambda x: x == provider)
+
+ # update-alternatives provider is removed in its own remove()
+ # call because all package managers do not guarantee the packages
+ # are removed in the order they given in the list (which is
+ # passed to the command line). The sorting done earlier is
+ # utilized to implement the 2-stage removal.
+ if len(pkgs_to_remove) > 1:
+ self.pm.remove(pkgs_to_remove[:-1], False)
if len(pkgs_to_remove) > 0:
- self.pm.remove(pkgs_to_remove, False)
+ self.pm.remove([pkgs_to_remove[-1]], False)
if delayed_postinsts:
self._save_postinsts()
@@ -268,7 +303,7 @@ class Rootfs(object, metaclass=ABCMeta):
bb.warn("There are post install scripts "
"in a read-only rootfs")
- post_uninstall_cmds = self.d.getVar("ROOTFS_POSTUNINSTALL_COMMAND", True)
+ post_uninstall_cmds = self.d.getVar("ROOTFS_POSTUNINSTALL_COMMAND")
execute_pre_post_process(self.d, post_uninstall_cmds)
runtime_pkgmanage = bb.utils.contains("IMAGE_FEATURES", "package-management",
@@ -277,53 +312,26 @@ class Rootfs(object, metaclass=ABCMeta):
# Remove the package manager data files
self.pm.remove_packaging_data()
- def _run_intercepts(self):
- intercepts_dir = os.path.join(self.d.getVar('WORKDIR', True),
- "intercept_scripts")
-
- bb.note("Running intercept scripts:")
- os.environ['D'] = self.image_rootfs
- os.environ['STAGING_DIR_NATIVE'] = self.d.getVar('STAGING_DIR_NATIVE', True)
- for script in os.listdir(intercepts_dir):
- script_full = os.path.join(intercepts_dir, script)
-
- if script == "postinst_intercept" or not os.access(script_full, os.X_OK):
- continue
-
- bb.note("> Executing %s intercept ..." % script)
-
- try:
- subprocess.check_call(script_full)
- except subprocess.CalledProcessError as e:
- bb.warn("The postinstall intercept hook '%s' failed (exit code: %d)! See log for details!" %
- (script, e.returncode))
-
- with open(script_full) as intercept:
- registered_pkgs = None
- for line in intercept.read().split("\n"):
- m = re.match("^##PKGS:(.*)", line)
- if m is not None:
- registered_pkgs = m.group(1).strip()
- break
-
- if registered_pkgs is not None:
- bb.warn("The postinstalls for the following packages "
- "will be postponed for first boot: %s" %
- registered_pkgs)
-
- # call the backend dependent handler
- self._handle_intercept_failure(registered_pkgs)
-
def _run_ldconfig(self):
- if self.d.getVar('LDCONFIGDEPEND', True):
- bb.note("Executing: ldconfig -r" + self.image_rootfs + "-c new -v")
+ if self.d.getVar('LDCONFIGDEPEND'):
+ bb.note("Executing: ldconfig -r " + self.image_rootfs + " -c new -v -X")
self._exec_shell_cmd(['ldconfig', '-r', self.image_rootfs, '-c',
- 'new', '-v'])
+ 'new', '-v', '-X'])
+
+ image_rorfs = bb.utils.contains("IMAGE_FEATURES", "read-only-rootfs",
+ True, False, self.d)
+ ldconfig_in_features = bb.utils.contains("DISTRO_FEATURES", "ldconfig",
+ True, False, self.d)
+ if image_rorfs or not ldconfig_in_features:
+ ldconfig_cache_dir = os.path.join(self.image_rootfs, "var/cache/ldconfig")
+ if os.path.exists(ldconfig_cache_dir):
+ bb.note("Removing ldconfig auxiliary cache...")
+ shutil.rmtree(ldconfig_cache_dir)
def _check_for_kernel_modules(self, modules_dir):
for root, dirs, files in os.walk(modules_dir, topdown=True):
for name in files:
- found_ko = name.endswith(".ko")
+ found_ko = name.endswith((".ko", ".ko.gz", ".ko.xz", ".ko.zst"))
if found_ko:
return found_ko
return False
@@ -335,17 +343,29 @@ class Rootfs(object, metaclass=ABCMeta):
bb.note("No Kernel Modules found, not running depmod")
return
- kernel_abi_ver_file = oe.path.join(self.d.getVar('PKGDATA_DIR', True), "kernel-depmod",
- 'kernel-abiversion')
- if not os.path.exists(kernel_abi_ver_file):
- bb.fatal("No kernel-abiversion file found (%s), cannot run depmod, aborting" % kernel_abi_ver_file)
+ pkgdatadir = self.d.getVar('PKGDATA_DIR')
- kernel_ver = open(kernel_abi_ver_file).read().strip(' \n')
- versioned_modules_dir = os.path.join(self.image_rootfs, modules_dir, kernel_ver)
+ # PKGDATA_DIR can include multiple kernels so we run depmod for each
+ # one of them.
+ for direntry in os.listdir(pkgdatadir):
+ match = re.match('(.*)-depmod', direntry)
+ if not match:
+ continue
+ kernel_package_name = match.group(1)
- bb.utils.mkdirhier(versioned_modules_dir)
+ kernel_abi_ver_file = oe.path.join(pkgdatadir, direntry, kernel_package_name + '-abiversion')
+ if not os.path.exists(kernel_abi_ver_file):
+ bb.fatal("No kernel-abiversion file found (%s), cannot run depmod, aborting" % kernel_abi_ver_file)
- self._exec_shell_cmd(['depmodwrapper', '-a', '-b', self.image_rootfs, kernel_ver])
+ with open(kernel_abi_ver_file) as f:
+ kernel_ver = f.read().strip(' \n')
+
+ versioned_modules_dir = os.path.join(self.image_rootfs, modules_dir, kernel_ver)
+
+ bb.utils.mkdirhier(versioned_modules_dir)
+
+ bb.note("Running depmodwrapper for %s ..." % versioned_modules_dir)
+ self._exec_shell_cmd(['depmodwrapper', '-a', '-b', self.image_rootfs, kernel_ver, kernel_package_name])
"""
Create devfs:
@@ -357,669 +377,55 @@ class Rootfs(object, metaclass=ABCMeta):
"""
def _create_devfs(self):
devtable_list = []
- devtable = self.d.getVar('IMAGE_DEVICE_TABLE', True)
+ devtable = self.d.getVar('IMAGE_DEVICE_TABLE')
if devtable is not None:
devtable_list.append(devtable)
else:
- devtables = self.d.getVar('IMAGE_DEVICE_TABLES', True)
+ devtables = self.d.getVar('IMAGE_DEVICE_TABLES')
if devtables is None:
devtables = 'files/device_table-minimal.txt'
for devtable in devtables.split():
- devtable_list.append("%s" % bb.utils.which(self.d.getVar('BBPATH', True), devtable))
+ devtable_list.append("%s" % bb.utils.which(self.d.getVar('BBPATH'), devtable))
for devtable in devtable_list:
self._exec_shell_cmd(["makedevs", "-r",
self.image_rootfs, "-D", devtable])
-class RpmRootfs(Rootfs):
- def __init__(self, d, manifest_dir, progress_reporter=None):
- super(RpmRootfs, self).__init__(d, progress_reporter)
- self.log_check_regex = '(unpacking of archive failed|Cannot find package'\
- '|exit 1|ERROR: |Error: |Error |ERROR '\
- '|Failed |Failed: |Failed$|Failed\(\d+\):)'
- self.manifest = RpmManifest(d, manifest_dir)
-
- self.pm = RpmPM(d,
- d.getVar('IMAGE_ROOTFS', True),
- self.d.getVar('TARGET_VENDOR', True)
- )
-
- self.inc_rpm_image_gen = self.d.getVar('INC_RPM_IMAGE_GEN', True)
- if self.inc_rpm_image_gen != "1":
- bb.utils.remove(self.image_rootfs, True)
- else:
- self.pm.recovery_packaging_data()
- bb.utils.remove(self.d.getVar('MULTILIB_TEMP_ROOTFS', True), True)
-
- self.pm.create_configs()
-
- '''
- While rpm incremental image generation is enabled, it will remove the
- unneeded pkgs by comparing the new install solution manifest and the
- old installed manifest.
- '''
- def _create_incremental(self, pkgs_initial_install):
- if self.inc_rpm_image_gen == "1":
-
- pkgs_to_install = list()
- for pkg_type in pkgs_initial_install:
- pkgs_to_install += pkgs_initial_install[pkg_type]
-
- installed_manifest = self.pm.load_old_install_solution()
- solution_manifest = self.pm.dump_install_solution(pkgs_to_install)
-
- pkg_to_remove = list()
- for pkg in installed_manifest:
- if pkg not in solution_manifest:
- pkg_to_remove.append(pkg)
-
- self.pm.update()
-
- bb.note('incremental update -- upgrade packages in place ')
- self.pm.upgrade()
- if pkg_to_remove != []:
- bb.note('incremental removed: %s' % ' '.join(pkg_to_remove))
- self.pm.remove(pkg_to_remove)
-
- def _create(self):
- pkgs_to_install = self.manifest.parse_initial_manifest()
- rpm_pre_process_cmds = self.d.getVar('RPM_PREPROCESS_COMMANDS', True)
- rpm_post_process_cmds = self.d.getVar('RPM_POSTPROCESS_COMMANDS', True)
-
- # update PM index files
- self.pm.write_index()
-
- execute_pre_post_process(self.d, rpm_pre_process_cmds)
-
- if self.progress_reporter:
- self.progress_reporter.next_stage()
-
- self.pm.dump_all_available_pkgs()
-
- if self.inc_rpm_image_gen == "1":
- self._create_incremental(pkgs_to_install)
-
- if self.progress_reporter:
- self.progress_reporter.next_stage()
-
- self.pm.update()
-
- pkgs = []
- pkgs_attempt = []
- for pkg_type in pkgs_to_install:
- if pkg_type == Manifest.PKG_TYPE_ATTEMPT_ONLY:
- pkgs_attempt += pkgs_to_install[pkg_type]
- else:
- pkgs += pkgs_to_install[pkg_type]
-
- if self.progress_reporter:
- self.progress_reporter.next_stage()
-
- self.pm.install(pkgs)
-
- if self.progress_reporter:
- self.progress_reporter.next_stage()
-
- self.pm.install(pkgs_attempt, True)
-
- if self.progress_reporter:
- self.progress_reporter.next_stage()
-
- self.pm.install_complementary()
-
- if self.progress_reporter:
- self.progress_reporter.next_stage()
-
- self._setup_dbg_rootfs(['/etc/rpm', '/var/lib/rpm', '/var/lib/smart'])
-
- execute_pre_post_process(self.d, rpm_post_process_cmds)
-
- self._log_check()
-
- if self.inc_rpm_image_gen == "1":
- self.pm.backup_packaging_data()
-
- self.pm.rpm_setup_smart_target_config()
-
- if self.progress_reporter:
- self.progress_reporter.next_stage()
-
-
- @staticmethod
- def _depends_list():
- return ['DEPLOY_DIR_RPM', 'INC_RPM_IMAGE_GEN', 'RPM_PREPROCESS_COMMANDS',
- 'RPM_POSTPROCESS_COMMANDS', 'RPM_PREFER_ELF_ARCH']
-
- def _get_delayed_postinsts(self):
- postinst_dir = self.d.expand("${IMAGE_ROOTFS}${sysconfdir}/rpm-postinsts")
- if os.path.isdir(postinst_dir):
- files = os.listdir(postinst_dir)
- for f in files:
- bb.note('Delayed package scriptlet: %s' % f)
- return files
-
- return None
-
- def _save_postinsts(self):
- # this is just a stub. For RPM, the failed postinstalls are
- # already saved in /etc/rpm-postinsts
- pass
-
- def _log_check(self):
- self._log_check_warn()
- self._log_check_error()
-
- def _handle_intercept_failure(self, registered_pkgs):
- rpm_postinsts_dir = self.image_rootfs + self.d.expand('${sysconfdir}/rpm-postinsts/')
- bb.utils.mkdirhier(rpm_postinsts_dir)
-
- # Save the package postinstalls in /etc/rpm-postinsts
- for pkg in registered_pkgs.split():
- self.pm.save_rpmpostinst(pkg)
-
- def _cleanup(self):
- # during the execution of postprocess commands, rpm is called several
- # times to get the files installed, dependencies, etc. This creates the
- # __db.00* (Berkeley DB files that hold locks, rpm specific environment
- # settings, etc.), that should not get into the final rootfs
- self.pm.unlock_rpm_db()
- if os.path.isdir(self.pm.install_dir_path + "/tmp") and not os.listdir(self.pm.install_dir_path + "/tmp"):
- bb.utils.remove(self.pm.install_dir_path + "/tmp", True)
- if os.path.isdir(self.pm.install_dir_path) and not os.listdir(self.pm.install_dir_path):
- bb.utils.remove(self.pm.install_dir_path, True)
-
-class DpkgOpkgRootfs(Rootfs):
- def __init__(self, d, progress_reporter=None):
- super(DpkgOpkgRootfs, self).__init__(d, progress_reporter)
-
- def _get_pkgs_postinsts(self, status_file):
- def _get_pkg_depends_list(pkg_depends):
- pkg_depends_list = []
- # filter version requirements like libc (>= 1.1)
- for dep in pkg_depends.split(', '):
- m_dep = re.match("^(.*) \(.*\)$", dep)
- if m_dep:
- dep = m_dep.group(1)
- pkg_depends_list.append(dep)
-
- return pkg_depends_list
-
- pkgs = {}
- pkg_name = ""
- pkg_status_match = False
- pkg_depends = ""
-
- with open(status_file) as status:
- data = status.read()
- status.close()
- for line in data.split('\n'):
- m_pkg = re.match("^Package: (.*)", line)
- m_status = re.match("^Status:.*unpacked", line)
- m_depends = re.match("^Depends: (.*)", line)
-
- if m_pkg is not None:
- if pkg_name and pkg_status_match:
- pkgs[pkg_name] = _get_pkg_depends_list(pkg_depends)
-
- pkg_name = m_pkg.group(1)
- pkg_status_match = False
- pkg_depends = ""
- elif m_status is not None:
- pkg_status_match = True
- elif m_depends is not None:
- pkg_depends = m_depends.group(1)
-
- # remove package dependencies not in postinsts
- pkg_names = list(pkgs.keys())
- for pkg_name in pkg_names:
- deps = pkgs[pkg_name][:]
-
- for d in deps:
- if d not in pkg_names:
- pkgs[pkg_name].remove(d)
-
- return pkgs
-
- def _get_delayed_postinsts_common(self, status_file):
- def _dep_resolve(graph, node, resolved, seen):
- seen.append(node)
-
- for edge in graph[node]:
- if edge not in resolved:
- if edge in seen:
- raise RuntimeError("Packages %s and %s have " \
- "a circular dependency in postinsts scripts." \
- % (node, edge))
- _dep_resolve(graph, edge, resolved, seen)
-
- resolved.append(node)
-
- pkg_list = []
-
- pkgs = None
- if not self.d.getVar('PACKAGE_INSTALL', True).strip():
- bb.note("Building empty image")
- else:
- pkgs = self._get_pkgs_postinsts(status_file)
- if pkgs:
- root = "__packagegroup_postinst__"
- pkgs[root] = list(pkgs.keys())
- _dep_resolve(pkgs, root, pkg_list, [])
- pkg_list.remove(root)
-
- if len(pkg_list) == 0:
- return None
-
- return pkg_list
-
- def _save_postinsts_common(self, dst_postinst_dir, src_postinst_dir):
- num = 0
- for p in self._get_delayed_postinsts():
- bb.utils.mkdirhier(dst_postinst_dir)
-
- if os.path.exists(os.path.join(src_postinst_dir, p + ".postinst")):
- shutil.copy(os.path.join(src_postinst_dir, p + ".postinst"),
- os.path.join(dst_postinst_dir, "%03d-%s" % (num, p)))
-
- num += 1
-
-class DpkgRootfs(DpkgOpkgRootfs):
- def __init__(self, d, manifest_dir, progress_reporter=None):
- super(DpkgRootfs, self).__init__(d, progress_reporter)
- self.log_check_regex = '^E:'
- self.log_check_expected_regexes = \
- [
- "^E: Unmet dependencies."
- ]
-
- bb.utils.remove(self.image_rootfs, True)
- bb.utils.remove(self.d.getVar('MULTILIB_TEMP_ROOTFS', True), True)
- self.manifest = DpkgManifest(d, manifest_dir)
- self.pm = DpkgPM(d, d.getVar('IMAGE_ROOTFS', True),
- d.getVar('PACKAGE_ARCHS', True),
- d.getVar('DPKG_ARCH', True))
-
-
- def _create(self):
- pkgs_to_install = self.manifest.parse_initial_manifest()
- deb_pre_process_cmds = self.d.getVar('DEB_PREPROCESS_COMMANDS', True)
- deb_post_process_cmds = self.d.getVar('DEB_POSTPROCESS_COMMANDS', True)
-
- alt_dir = self.d.expand("${IMAGE_ROOTFS}/var/lib/dpkg/alternatives")
- bb.utils.mkdirhier(alt_dir)
-
- # update PM index files
- self.pm.write_index()
-
- execute_pre_post_process(self.d, deb_pre_process_cmds)
-
- if self.progress_reporter:
- self.progress_reporter.next_stage()
- # Don't support incremental, so skip that
- self.progress_reporter.next_stage()
-
- self.pm.update()
-
- if self.progress_reporter:
- self.progress_reporter.next_stage()
-
- for pkg_type in self.install_order:
- if pkg_type in pkgs_to_install:
- self.pm.install(pkgs_to_install[pkg_type],
- [False, True][pkg_type == Manifest.PKG_TYPE_ATTEMPT_ONLY])
-
- if self.progress_reporter:
- # Don't support attemptonly, so skip that
- self.progress_reporter.next_stage()
- self.progress_reporter.next_stage()
-
- self.pm.install_complementary()
-
- if self.progress_reporter:
- self.progress_reporter.next_stage()
-
- self._setup_dbg_rootfs(['/var/lib/dpkg'])
-
- self.pm.fix_broken_dependencies()
-
- self.pm.mark_packages("installed")
-
- self.pm.run_pre_post_installs()
-
- execute_pre_post_process(self.d, deb_post_process_cmds)
-
- if self.progress_reporter:
- self.progress_reporter.next_stage()
-
- @staticmethod
- def _depends_list():
- return ['DEPLOY_DIR_DEB', 'DEB_SDK_ARCH', 'APTCONF_TARGET', 'APT_ARGS', 'DPKG_ARCH', 'DEB_PREPROCESS_COMMANDS', 'DEB_POSTPROCESS_COMMANDS']
-
- def _get_delayed_postinsts(self):
- status_file = self.image_rootfs + "/var/lib/dpkg/status"
- return self._get_delayed_postinsts_common(status_file)
-
- def _save_postinsts(self):
- dst_postinst_dir = self.d.expand("${IMAGE_ROOTFS}${sysconfdir}/deb-postinsts")
- src_postinst_dir = self.d.expand("${IMAGE_ROOTFS}/var/lib/dpkg/info")
- return self._save_postinsts_common(dst_postinst_dir, src_postinst_dir)
-
- def _handle_intercept_failure(self, registered_pkgs):
- self.pm.mark_packages("unpacked", registered_pkgs.split())
-
- def _log_check(self):
- self._log_check_warn()
- self._log_check_error()
-
- def _cleanup(self):
- pass
-
-
-class OpkgRootfs(DpkgOpkgRootfs):
- def __init__(self, d, manifest_dir, progress_reporter=None):
- super(OpkgRootfs, self).__init__(d, progress_reporter)
- self.log_check_regex = '(exit 1|Collected errors)'
-
- self.manifest = OpkgManifest(d, manifest_dir)
- self.opkg_conf = self.d.getVar("IPKGCONF_TARGET", True)
- self.pkg_archs = self.d.getVar("ALL_MULTILIB_PACKAGE_ARCHS", True)
-
- self.inc_opkg_image_gen = self.d.getVar('INC_IPK_IMAGE_GEN', True) or ""
- if self._remove_old_rootfs():
- bb.utils.remove(self.image_rootfs, True)
- self.pm = OpkgPM(d,
- self.image_rootfs,
- self.opkg_conf,
- self.pkg_archs)
- else:
- self.pm = OpkgPM(d,
- self.image_rootfs,
- self.opkg_conf,
- self.pkg_archs)
- self.pm.recover_packaging_data()
-
- bb.utils.remove(self.d.getVar('MULTILIB_TEMP_ROOTFS', True), True)
-
- def _prelink_file(self, root_dir, filename):
- bb.note('prelink %s in %s' % (filename, root_dir))
- prelink_cfg = oe.path.join(root_dir,
- self.d.expand('${sysconfdir}/prelink.conf'))
- if not os.path.exists(prelink_cfg):
- shutil.copy(self.d.expand('${STAGING_DIR_NATIVE}${sysconfdir_native}/prelink.conf'),
- prelink_cfg)
-
- cmd_prelink = self.d.expand('${STAGING_DIR_NATIVE}${sbindir_native}/prelink')
- self._exec_shell_cmd([cmd_prelink,
- '--root',
- root_dir,
- '-amR',
- '-N',
- '-c',
- self.d.expand('${sysconfdir}/prelink.conf')])
-
- '''
- Compare two files with the same key twice to see if they are equal.
- If they are not equal, it means they are duplicated and come from
- different packages.
- 1st: Comapre them directly;
- 2nd: While incremental image creation is enabled, one of the
- files could be probaly prelinked in the previous image
- creation and the file has been changed, so we need to
- prelink the other one and compare them.
- '''
- def _file_equal(self, key, f1, f2):
-
- # Both of them are not prelinked
- if filecmp.cmp(f1, f2):
- return True
-
- if self.image_rootfs not in f1:
- self._prelink_file(f1.replace(key, ''), f1)
-
- if self.image_rootfs not in f2:
- self._prelink_file(f2.replace(key, ''), f2)
-
- # Both of them are prelinked
- if filecmp.cmp(f1, f2):
- return True
-
- # Not equal
- return False
-
- """
- This function was reused from the old implementation.
- See commit: "image.bbclass: Added variables for multilib support." by
- Lianhao Lu.
- """
- def _multilib_sanity_test(self, dirs):
-
- allow_replace = self.d.getVar("MULTILIBRE_ALLOW_REP", True)
- if allow_replace is None:
- allow_replace = ""
-
- allow_rep = re.compile(re.sub("\|$", "", allow_replace))
- error_prompt = "Multilib check error:"
-
- files = {}
- for dir in dirs:
- for root, subfolders, subfiles in os.walk(dir):
- for file in subfiles:
- item = os.path.join(root, file)
- key = str(os.path.join("/", os.path.relpath(item, dir)))
-
- valid = True
- if key in files:
- #check whether the file is allow to replace
- if allow_rep.match(key):
- valid = True
- else:
- if os.path.exists(files[key]) and \
- os.path.exists(item) and \
- not self._file_equal(key, files[key], item):
- valid = False
- bb.fatal("%s duplicate files %s %s is not the same\n" %
- (error_prompt, item, files[key]))
-
- #pass the check, add to list
- if valid:
- files[key] = item
-
- def _multilib_test_install(self, pkgs):
- ml_temp = self.d.getVar("MULTILIB_TEMP_ROOTFS", True)
- bb.utils.mkdirhier(ml_temp)
-
- dirs = [self.image_rootfs]
-
- for variant in self.d.getVar("MULTILIB_VARIANTS", True).split():
- ml_target_rootfs = os.path.join(ml_temp, variant)
-
- bb.utils.remove(ml_target_rootfs, True)
-
- ml_opkg_conf = os.path.join(ml_temp,
- variant + "-" + os.path.basename(self.opkg_conf))
-
- ml_pm = OpkgPM(self.d, ml_target_rootfs, ml_opkg_conf, self.pkg_archs)
-
- ml_pm.update()
- ml_pm.install(pkgs)
-
- dirs.append(ml_target_rootfs)
-
- self._multilib_sanity_test(dirs)
-
- '''
- While ipk incremental image generation is enabled, it will remove the
- unneeded pkgs by comparing the old full manifest in previous existing
- image and the new full manifest in the current image.
- '''
- def _remove_extra_packages(self, pkgs_initial_install):
- if self.inc_opkg_image_gen == "1":
- # Parse full manifest in previous existing image creation session
- old_full_manifest = self.manifest.parse_full_manifest()
-
- # Create full manifest for the current image session, the old one
- # will be replaced by the new one.
- self.manifest.create_full(self.pm)
-
- # Parse full manifest in current image creation session
- new_full_manifest = self.manifest.parse_full_manifest()
-
- pkg_to_remove = list()
- for pkg in old_full_manifest:
- if pkg not in new_full_manifest:
- pkg_to_remove.append(pkg)
-
- if pkg_to_remove != []:
- bb.note('decremental removed: %s' % ' '.join(pkg_to_remove))
- self.pm.remove(pkg_to_remove)
-
- '''
- Compare with previous existing image creation, if some conditions
- triggered, the previous old image should be removed.
- The conditions include any of 'PACKAGE_EXCLUDE, NO_RECOMMENDATIONS
- and BAD_RECOMMENDATIONS' has been changed.
- '''
- def _remove_old_rootfs(self):
- if self.inc_opkg_image_gen != "1":
- return True
-
- vars_list_file = self.d.expand('${T}/vars_list')
-
- old_vars_list = ""
- if os.path.exists(vars_list_file):
- old_vars_list = open(vars_list_file, 'r+').read()
-
- new_vars_list = '%s:%s:%s\n' % \
- ((self.d.getVar('BAD_RECOMMENDATIONS', True) or '').strip(),
- (self.d.getVar('NO_RECOMMENDATIONS', True) or '').strip(),
- (self.d.getVar('PACKAGE_EXCLUDE', True) or '').strip())
- open(vars_list_file, 'w+').write(new_vars_list)
-
- if old_vars_list != new_vars_list:
- return True
-
- return False
-
- def _create(self):
- pkgs_to_install = self.manifest.parse_initial_manifest()
- opkg_pre_process_cmds = self.d.getVar('OPKG_PREPROCESS_COMMANDS', True)
- opkg_post_process_cmds = self.d.getVar('OPKG_POSTPROCESS_COMMANDS', True)
-
- # update PM index files, unless users provide their own feeds
- if (self.d.getVar('BUILD_IMAGES_FROM_FEEDS', True) or "") != "1":
- self.pm.write_index()
-
- execute_pre_post_process(self.d, opkg_pre_process_cmds)
-
- if self.progress_reporter:
- self.progress_reporter.next_stage()
- # Steps are a bit different in order, skip next
- self.progress_reporter.next_stage()
-
- self.pm.update()
-
- self.pm.handle_bad_recommendations()
-
- if self.progress_reporter:
- self.progress_reporter.next_stage()
-
- if self.inc_opkg_image_gen == "1":
- self._remove_extra_packages(pkgs_to_install)
-
- if self.progress_reporter:
- self.progress_reporter.next_stage()
-
- for pkg_type in self.install_order:
- if pkg_type in pkgs_to_install:
- # For multilib, we perform a sanity test before final install
- # If sanity test fails, it will automatically do a bb.fatal()
- # and the installation will stop
- if pkg_type == Manifest.PKG_TYPE_MULTILIB:
- self._multilib_test_install(pkgs_to_install[pkg_type])
-
- self.pm.install(pkgs_to_install[pkg_type],
- [False, True][pkg_type == Manifest.PKG_TYPE_ATTEMPT_ONLY])
-
- if self.progress_reporter:
- self.progress_reporter.next_stage()
-
- self.pm.install_complementary()
-
- if self.progress_reporter:
- self.progress_reporter.next_stage()
-
- self._setup_dbg_rootfs(['/etc', '/var/lib/opkg', '/usr/lib/ssl'])
-
- execute_pre_post_process(self.d, opkg_post_process_cmds)
-
- if self.inc_opkg_image_gen == "1":
- self.pm.backup_packaging_data()
-
- if self.progress_reporter:
- self.progress_reporter.next_stage()
-
- @staticmethod
- def _depends_list():
- return ['IPKGCONF_SDK', 'IPK_FEED_URIS', 'DEPLOY_DIR_IPK', 'IPKGCONF_TARGET', 'INC_IPK_IMAGE_GEN', 'OPKG_ARGS', 'OPKGLIBDIR', 'OPKG_PREPROCESS_COMMANDS', 'OPKG_POSTPROCESS_COMMANDS', 'OPKGLIBDIR']
-
- def _get_delayed_postinsts(self):
- status_file = os.path.join(self.image_rootfs,
- self.d.getVar('OPKGLIBDIR', True).strip('/'),
- "opkg", "status")
- return self._get_delayed_postinsts_common(status_file)
-
- def _save_postinsts(self):
- dst_postinst_dir = self.d.expand("${IMAGE_ROOTFS}${sysconfdir}/ipk-postinsts")
- src_postinst_dir = self.d.expand("${IMAGE_ROOTFS}${OPKGLIBDIR}/opkg/info")
- return self._save_postinsts_common(dst_postinst_dir, src_postinst_dir)
-
- def _handle_intercept_failure(self, registered_pkgs):
- self.pm.mark_packages("unpacked", registered_pkgs.split())
-
- def _log_check(self):
- self._log_check_warn()
- self._log_check_error()
-
- def _cleanup(self):
- self.pm.remove_lists()
-
def get_class_for_type(imgtype):
- return {"rpm": RpmRootfs,
- "ipk": OpkgRootfs,
- "deb": DpkgRootfs}[imgtype]
+ import importlib
+ mod = importlib.import_module('oe.package_manager.' + imgtype + '.rootfs')
+ return mod.PkgRootfs
def variable_depends(d, manifest_dir=None):
- img_type = d.getVar('IMAGE_PKGTYPE', True)
+ img_type = d.getVar('IMAGE_PKGTYPE')
cls = get_class_for_type(img_type)
return cls._depends_list()
-def create_rootfs(d, manifest_dir=None, progress_reporter=None):
+def create_rootfs(d, manifest_dir=None, progress_reporter=None, logcatcher=None):
env_bkp = os.environ.copy()
- img_type = d.getVar('IMAGE_PKGTYPE', True)
- if img_type == "rpm":
- RpmRootfs(d, manifest_dir, progress_reporter).create()
- elif img_type == "ipk":
- OpkgRootfs(d, manifest_dir, progress_reporter).create()
- elif img_type == "deb":
- DpkgRootfs(d, manifest_dir, progress_reporter).create()
+ img_type = d.getVar('IMAGE_PKGTYPE')
+ cls = get_class_for_type(img_type)
+ cls(d, manifest_dir, progress_reporter, logcatcher).create()
os.environ.clear()
os.environ.update(env_bkp)
def image_list_installed_packages(d, rootfs_dir=None):
+ # Theres no rootfs for baremetal images
+ if bb.data.inherits_class('baremetal-image', d):
+ return ""
+
if not rootfs_dir:
- rootfs_dir = d.getVar('IMAGE_ROOTFS', True)
-
- img_type = d.getVar('IMAGE_PKGTYPE', True)
- if img_type == "rpm":
- return RpmPkgsList(d, rootfs_dir).list_pkgs()
- elif img_type == "ipk":
- return OpkgPkgsList(d, rootfs_dir, d.getVar("IPKGCONF_TARGET", True)).list_pkgs()
- elif img_type == "deb":
- return DpkgPkgsList(d, rootfs_dir).list_pkgs()
+ rootfs_dir = d.getVar('IMAGE_ROOTFS')
+
+ img_type = d.getVar('IMAGE_PKGTYPE')
+
+ import importlib
+ cls = importlib.import_module('oe.package_manager.' + img_type)
+ return cls.PMPkgsList(d, rootfs_dir).list_pkgs()
if __name__ == "__main__":
"""
diff --git a/meta/lib/oe/rust.py b/meta/lib/oe/rust.py
new file mode 100644
index 0000000000..185553eeeb
--- /dev/null
+++ b/meta/lib/oe/rust.py
@@ -0,0 +1,13 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
+# Handle mismatches between `uname -m`-style output and Rust's arch names
+def arch_to_rust_arch(arch):
+ if arch == "ppc64le":
+ return "powerpc64le"
+ if arch in ('riscv32', 'riscv64'):
+ return arch + 'gc'
+ return arch
diff --git a/meta/lib/oe/sbom.py b/meta/lib/oe/sbom.py
new file mode 100644
index 0000000000..bbf466bbad
--- /dev/null
+++ b/meta/lib/oe/sbom.py
@@ -0,0 +1,80 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: GPL-2.0-only
+#
+
+import collections
+
+DepRecipe = collections.namedtuple("DepRecipe", ("doc", "doc_sha1", "recipe"))
+DepSource = collections.namedtuple("DepSource", ("doc", "doc_sha1", "recipe", "file"))
+
+
+def get_recipe_spdxid(d):
+ return "SPDXRef-%s-%s" % ("Recipe", d.getVar("PN"))
+
+
+def get_package_spdxid(pkg):
+ return "SPDXRef-Package-%s" % pkg
+
+
+def get_source_file_spdxid(d, idx):
+ return "SPDXRef-SourceFile-%s-%d" % (d.getVar("PN"), idx)
+
+
+def get_packaged_file_spdxid(pkg, idx):
+ return "SPDXRef-PackagedFile-%s-%d" % (pkg, idx)
+
+
+def get_image_spdxid(img):
+ return "SPDXRef-Image-%s" % img
+
+
+def get_sdk_spdxid(sdk):
+ return "SPDXRef-SDK-%s" % sdk
+
+
+def write_doc(d, spdx_doc, subdir, spdx_deploy=None, indent=None):
+ from pathlib import Path
+
+ if spdx_deploy is None:
+ spdx_deploy = Path(d.getVar("SPDXDEPLOY"))
+
+ dest = spdx_deploy / subdir / (spdx_doc.name + ".spdx.json")
+ dest.parent.mkdir(exist_ok=True, parents=True)
+ with dest.open("wb") as f:
+ doc_sha1 = spdx_doc.to_json(f, sort_keys=True, indent=indent)
+
+ l = spdx_deploy / "by-namespace" / spdx_doc.documentNamespace.replace("/", "_")
+ l.parent.mkdir(exist_ok=True, parents=True)
+ l.symlink_to(os.path.relpath(dest, l.parent))
+
+ return doc_sha1
+
+
+def read_doc(fn):
+ import hashlib
+ import oe.spdx
+ import io
+ import contextlib
+
+ @contextlib.contextmanager
+ def get_file():
+ if isinstance(fn, io.IOBase):
+ yield fn
+ else:
+ with fn.open("rb") as f:
+ yield f
+
+ with get_file() as f:
+ sha1 = hashlib.sha1()
+ while True:
+ chunk = f.read(4096)
+ if not chunk:
+ break
+ sha1.update(chunk)
+
+ f.seek(0)
+ doc = oe.spdx.SPDXDocument.from_json(f)
+
+ return (doc, sha1.hexdigest())
diff --git a/meta/lib/oe/sdk.py b/meta/lib/oe/sdk.py
index c74525f929..81fcf15371 100644
--- a/meta/lib/oe/sdk.py
+++ b/meta/lib/oe/sdk.py
@@ -1,26 +1,29 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: GPL-2.0-only
+#
+
from abc import ABCMeta, abstractmethod
from oe.utils import execute_pre_post_process
from oe.manifest import *
from oe.package_manager import *
import os
-import shutil
-import glob
import traceback
-
class Sdk(object, metaclass=ABCMeta):
def __init__(self, d, manifest_dir):
self.d = d
- self.sdk_output = self.d.getVar('SDK_OUTPUT', True)
- self.sdk_native_path = self.d.getVar('SDKPATHNATIVE', True).strip('/')
- self.target_path = self.d.getVar('SDKTARGETSYSROOT', True).strip('/')
- self.sysconfdir = self.d.getVar('sysconfdir', True).strip('/')
+ self.sdk_output = self.d.getVar('SDK_OUTPUT')
+ self.sdk_native_path = self.d.getVar('SDKPATHNATIVE').strip('/')
+ self.target_path = self.d.getVar('SDKTARGETSYSROOT').strip('/')
+ self.sysconfdir = self.d.getVar('sysconfdir').strip('/')
self.sdk_target_sysroot = os.path.join(self.sdk_output, self.target_path)
self.sdk_host_sysroot = self.sdk_output
if manifest_dir is None:
- self.manifest_dir = self.d.getVar("SDK_DIR", True)
+ self.manifest_dir = self.d.getVar("SDK_DIR")
else:
self.manifest_dir = manifest_dir
@@ -40,12 +43,12 @@ class Sdk(object, metaclass=ABCMeta):
# Don't ship any libGL in the SDK
self.remove(os.path.join(self.sdk_output, self.sdk_native_path,
- self.d.getVar('libdir_nativesdk', True).strip('/'),
+ self.d.getVar('libdir_nativesdk').strip('/'),
"libGL*"))
# Fix or remove broken .la files
self.remove(os.path.join(self.sdk_output, self.sdk_native_path,
- self.d.getVar('libdir_nativesdk', True).strip('/'),
+ self.d.getVar('libdir_nativesdk').strip('/'),
"*.la"))
# Link the ld.so.cache file into the hosts filesystem
@@ -54,7 +57,7 @@ class Sdk(object, metaclass=ABCMeta):
self.mkdirhier(os.path.dirname(link_name))
os.symlink("/etc/ld.so.cache", link_name)
- execute_pre_post_process(self.d, self.d.getVar('SDK_POSTPROCESS_COMMAND', True))
+ execute_pre_post_process(self.d, self.d.getVar('SDK_POSTPROCESS_COMMAND'))
def movefile(self, sourcefile, destdir):
try:
@@ -84,292 +87,74 @@ class Sdk(object, metaclass=ABCMeta):
bb.debug(1, "printing the stack trace\n %s" %traceback.format_exc())
bb.warn("cannot remove SDK dir: %s" % path)
-class RpmSdk(Sdk):
- def __init__(self, d, manifest_dir=None):
- super(RpmSdk, self).__init__(d, manifest_dir)
-
- self.target_manifest = RpmManifest(d, self.manifest_dir,
- Manifest.MANIFEST_TYPE_SDK_TARGET)
- self.host_manifest = RpmManifest(d, self.manifest_dir,
- Manifest.MANIFEST_TYPE_SDK_HOST)
-
- target_providename = ['/bin/sh',
- '/bin/bash',
- '/usr/bin/env',
- '/usr/bin/perl',
- 'pkgconfig'
- ]
-
- self.target_pm = RpmPM(d,
- self.sdk_target_sysroot,
- self.d.getVar('TARGET_VENDOR', True),
- 'target',
- target_providename
- )
-
- sdk_providename = ['/bin/sh',
- '/bin/bash',
- '/usr/bin/env',
- '/usr/bin/perl',
- 'pkgconfig',
- 'libGL.so()(64bit)',
- 'libGL.so'
- ]
-
- self.host_pm = RpmPM(d,
- self.sdk_host_sysroot,
- self.d.getVar('SDK_VENDOR', True),
- 'host',
- sdk_providename,
- "SDK_PACKAGE_ARCHS",
- "SDK_OS"
- )
-
- def _populate_sysroot(self, pm, manifest):
- pkgs_to_install = manifest.parse_initial_manifest()
-
- pm.create_configs()
- pm.write_index()
- pm.dump_all_available_pkgs()
- pm.update()
-
- pkgs = []
- pkgs_attempt = []
- for pkg_type in pkgs_to_install:
- if pkg_type == Manifest.PKG_TYPE_ATTEMPT_ONLY:
- pkgs_attempt += pkgs_to_install[pkg_type]
+ def install_locales(self, pm):
+ linguas = self.d.getVar("SDKIMAGE_LINGUAS")
+ if linguas:
+ import fnmatch
+ # Install the binary locales
+ if linguas == "all":
+ pm.install_glob("nativesdk-glibc-binary-localedata-*.utf-8", sdk=True)
else:
- pkgs += pkgs_to_install[pkg_type]
-
- pm.install(pkgs)
-
- pm.install(pkgs_attempt, True)
-
- def _populate(self):
- bb.note("Installing TARGET packages")
- self._populate_sysroot(self.target_pm, self.target_manifest)
-
- self.target_pm.install_complementary(self.d.getVar('SDKIMAGE_INSTALL_COMPLEMENTARY', True))
-
- execute_pre_post_process(self.d, self.d.getVar("POPULATE_SDK_POST_TARGET_COMMAND", True))
-
- if not bb.utils.contains("SDKIMAGE_FEATURES", "package-management", True, False, self.d):
- self.target_pm.remove_packaging_data()
-
- bb.note("Installing NATIVESDK packages")
- self._populate_sysroot(self.host_pm, self.host_manifest)
-
- execute_pre_post_process(self.d, self.d.getVar("POPULATE_SDK_POST_HOST_COMMAND", True))
-
- if not bb.utils.contains("SDKIMAGE_FEATURES", "package-management", True, False, self.d):
- self.host_pm.remove_packaging_data()
-
- # Move host RPM library data
- native_rpm_state_dir = os.path.join(self.sdk_output,
- self.sdk_native_path,
- self.d.getVar('localstatedir_nativesdk', True).strip('/'),
- "lib",
- "rpm"
- )
- self.mkdirhier(native_rpm_state_dir)
- for f in glob.glob(os.path.join(self.sdk_output,
- "var",
- "lib",
- "rpm",
- "*")):
- self.movefile(f, native_rpm_state_dir)
-
- self.remove(os.path.join(self.sdk_output, "var"), True)
-
- # Move host sysconfig data
- native_sysconf_dir = os.path.join(self.sdk_output,
- self.sdk_native_path,
- self.d.getVar('sysconfdir',
- True).strip('/'),
- )
- self.mkdirhier(native_sysconf_dir)
- for f in glob.glob(os.path.join(self.sdk_output, "etc", "*")):
- self.movefile(f, native_sysconf_dir)
- self.remove(os.path.join(self.sdk_output, "etc"), True)
-
-
-class OpkgSdk(Sdk):
- def __init__(self, d, manifest_dir=None):
- super(OpkgSdk, self).__init__(d, manifest_dir)
-
- self.target_conf = self.d.getVar("IPKGCONF_TARGET", True)
- self.host_conf = self.d.getVar("IPKGCONF_SDK", True)
-
- self.target_manifest = OpkgManifest(d, self.manifest_dir,
- Manifest.MANIFEST_TYPE_SDK_TARGET)
- self.host_manifest = OpkgManifest(d, self.manifest_dir,
- Manifest.MANIFEST_TYPE_SDK_HOST)
-
- self.target_pm = OpkgPM(d, self.sdk_target_sysroot, self.target_conf,
- self.d.getVar("ALL_MULTILIB_PACKAGE_ARCHS", True))
-
- self.host_pm = OpkgPM(d, self.sdk_host_sysroot, self.host_conf,
- self.d.getVar("SDK_PACKAGE_ARCHS", True))
-
- def _populate_sysroot(self, pm, manifest):
- pkgs_to_install = manifest.parse_initial_manifest()
-
- if (self.d.getVar('BUILD_IMAGES_FROM_FEEDS', True) or "") != "1":
- pm.write_index()
-
- pm.update()
-
- for pkg_type in self.install_order:
- if pkg_type in pkgs_to_install:
- pm.install(pkgs_to_install[pkg_type],
- [False, True][pkg_type == Manifest.PKG_TYPE_ATTEMPT_ONLY])
-
- def _populate(self):
- bb.note("Installing TARGET packages")
- self._populate_sysroot(self.target_pm, self.target_manifest)
-
- self.target_pm.install_complementary(self.d.getVar('SDKIMAGE_INSTALL_COMPLEMENTARY', True))
-
- execute_pre_post_process(self.d, self.d.getVar("POPULATE_SDK_POST_TARGET_COMMAND", True))
-
- if not bb.utils.contains("SDKIMAGE_FEATURES", "package-management", True, False, self.d):
- self.target_pm.remove_packaging_data()
-
- bb.note("Installing NATIVESDK packages")
- self._populate_sysroot(self.host_pm, self.host_manifest)
-
- execute_pre_post_process(self.d, self.d.getVar("POPULATE_SDK_POST_HOST_COMMAND", True))
-
- if not bb.utils.contains("SDKIMAGE_FEATURES", "package-management", True, False, self.d):
- self.host_pm.remove_packaging_data()
-
- target_sysconfdir = os.path.join(self.sdk_target_sysroot, self.sysconfdir)
- host_sysconfdir = os.path.join(self.sdk_host_sysroot, self.sysconfdir)
-
- self.mkdirhier(target_sysconfdir)
- shutil.copy(self.target_conf, target_sysconfdir)
- os.chmod(os.path.join(target_sysconfdir,
- os.path.basename(self.target_conf)), 0o644)
-
- self.mkdirhier(host_sysconfdir)
- shutil.copy(self.host_conf, host_sysconfdir)
- os.chmod(os.path.join(host_sysconfdir,
- os.path.basename(self.host_conf)), 0o644)
-
- native_opkg_state_dir = os.path.join(self.sdk_output, self.sdk_native_path,
- self.d.getVar('localstatedir_nativesdk', True).strip('/'),
- "lib", "opkg")
- self.mkdirhier(native_opkg_state_dir)
- for f in glob.glob(os.path.join(self.sdk_output, "var", "lib", "opkg", "*")):
- self.movefile(f, native_opkg_state_dir)
-
- self.remove(os.path.join(self.sdk_output, "var"), True)
-
-
-class DpkgSdk(Sdk):
- def __init__(self, d, manifest_dir=None):
- super(DpkgSdk, self).__init__(d, manifest_dir)
-
- self.target_conf_dir = os.path.join(self.d.getVar("APTCONF_TARGET", True), "apt")
- self.host_conf_dir = os.path.join(self.d.getVar("APTCONF_TARGET", True), "apt-sdk")
-
- self.target_manifest = DpkgManifest(d, self.manifest_dir,
- Manifest.MANIFEST_TYPE_SDK_TARGET)
- self.host_manifest = DpkgManifest(d, self.manifest_dir,
- Manifest.MANIFEST_TYPE_SDK_HOST)
-
- self.target_pm = DpkgPM(d, self.sdk_target_sysroot,
- self.d.getVar("PACKAGE_ARCHS", True),
- self.d.getVar("DPKG_ARCH", True),
- self.target_conf_dir)
-
- self.host_pm = DpkgPM(d, self.sdk_host_sysroot,
- self.d.getVar("SDK_PACKAGE_ARCHS", True),
- self.d.getVar("DEB_SDK_ARCH", True),
- self.host_conf_dir)
-
- def _copy_apt_dir_to(self, dst_dir):
- staging_etcdir_native = self.d.getVar("STAGING_ETCDIR_NATIVE", True)
-
- self.remove(dst_dir, True)
-
- shutil.copytree(os.path.join(staging_etcdir_native, "apt"), dst_dir)
-
- def _populate_sysroot(self, pm, manifest):
- pkgs_to_install = manifest.parse_initial_manifest()
-
- pm.write_index()
- pm.update()
-
- for pkg_type in self.install_order:
- if pkg_type in pkgs_to_install:
- pm.install(pkgs_to_install[pkg_type],
- [False, True][pkg_type == Manifest.PKG_TYPE_ATTEMPT_ONLY])
-
- def _populate(self):
- bb.note("Installing TARGET packages")
- self._populate_sysroot(self.target_pm, self.target_manifest)
-
- self.target_pm.install_complementary(self.d.getVar('SDKIMAGE_INSTALL_COMPLEMENTARY', True))
-
- execute_pre_post_process(self.d, self.d.getVar("POPULATE_SDK_POST_TARGET_COMMAND", True))
-
- self._copy_apt_dir_to(os.path.join(self.sdk_target_sysroot, "etc", "apt"))
-
- if not bb.utils.contains("SDKIMAGE_FEATURES", "package-management", True, False, self.d):
- self.target_pm.remove_packaging_data()
-
- bb.note("Installing NATIVESDK packages")
- self._populate_sysroot(self.host_pm, self.host_manifest)
-
- execute_pre_post_process(self.d, self.d.getVar("POPULATE_SDK_POST_HOST_COMMAND", True))
-
- self._copy_apt_dir_to(os.path.join(self.sdk_output, self.sdk_native_path,
- "etc", "apt"))
-
- if not bb.utils.contains("SDKIMAGE_FEATURES", "package-management", True, False, self.d):
- self.host_pm.remove_packaging_data()
-
- native_dpkg_state_dir = os.path.join(self.sdk_output, self.sdk_native_path,
- "var", "lib", "dpkg")
- self.mkdirhier(native_dpkg_state_dir)
- for f in glob.glob(os.path.join(self.sdk_output, "var", "lib", "dpkg", "*")):
- self.movefile(f, native_dpkg_state_dir)
- self.remove(os.path.join(self.sdk_output, "var"), True)
-
+ pm.install(["nativesdk-glibc-binary-localedata-%s.utf-8" % \
+ lang for lang in linguas.split()])
+ # Generate a locale archive of them
+ target_arch = self.d.getVar('SDK_ARCH')
+ rootfs = oe.path.join(self.sdk_host_sysroot, self.sdk_native_path)
+ localedir = oe.path.join(rootfs, self.d.getVar("libdir_nativesdk"), "locale")
+ generate_locale_archive(self.d, rootfs, target_arch, localedir)
+ # And now delete the binary locales
+ pkgs = fnmatch.filter(pm.list_installed(), "nativesdk-glibc-binary-localedata-*.utf-8")
+ pm.remove(pkgs)
+ else:
+ # No linguas so do nothing
+ pass
def sdk_list_installed_packages(d, target, rootfs_dir=None):
if rootfs_dir is None:
- sdk_output = d.getVar('SDK_OUTPUT', True)
- target_path = d.getVar('SDKTARGETSYSROOT', True).strip('/')
+ sdk_output = d.getVar('SDK_OUTPUT')
+ target_path = d.getVar('SDKTARGETSYSROOT').strip('/')
rootfs_dir = [sdk_output, os.path.join(sdk_output, target_path)][target is True]
- img_type = d.getVar('IMAGE_PKGTYPE', True)
- if img_type == "rpm":
- arch_var = ["SDK_PACKAGE_ARCHS", None][target is True]
- os_var = ["SDK_OS", None][target is True]
- return RpmPkgsList(d, rootfs_dir, arch_var, os_var).list_pkgs()
- elif img_type == "ipk":
- conf_file_var = ["IPKGCONF_SDK", "IPKGCONF_TARGET"][target is True]
- return OpkgPkgsList(d, rootfs_dir, d.getVar(conf_file_var, True)).list_pkgs()
- elif img_type == "deb":
- return DpkgPkgsList(d, rootfs_dir).list_pkgs()
+ if target is False:
+ ipkgconf_sdk_target = d.getVar("IPKGCONF_SDK")
+ d.setVar("IPKGCONF_TARGET", ipkgconf_sdk_target)
+
+ img_type = d.getVar('IMAGE_PKGTYPE')
+ import importlib
+ cls = importlib.import_module('oe.package_manager.' + img_type)
+ return cls.PMPkgsList(d, rootfs_dir).list_pkgs()
def populate_sdk(d, manifest_dir=None):
env_bkp = os.environ.copy()
- img_type = d.getVar('IMAGE_PKGTYPE', True)
- if img_type == "rpm":
- RpmSdk(d, manifest_dir).populate()
- elif img_type == "ipk":
- OpkgSdk(d, manifest_dir).populate()
- elif img_type == "deb":
- DpkgSdk(d, manifest_dir).populate()
+ img_type = d.getVar('IMAGE_PKGTYPE')
+ import importlib
+ cls = importlib.import_module('oe.package_manager.' + img_type + '.sdk')
+ cls.PkgSdk(d, manifest_dir).populate()
os.environ.clear()
os.environ.update(env_bkp)
+def get_extra_sdkinfo(sstate_dir):
+ """
+ This function is going to be used for generating the target and host manifest files packages of eSDK.
+ """
+ import math
+
+ extra_info = {}
+ extra_info['tasksizes'] = {}
+ extra_info['filesizes'] = {}
+ for root, _, files in os.walk(sstate_dir):
+ for fn in files:
+ if fn.endswith('.tgz'):
+ fsize = int(math.ceil(float(os.path.getsize(os.path.join(root, fn))) / 1024))
+ task = fn.rsplit(':',1)[1].split('_',1)[1].split(',')[0]
+ origtotal = extra_info['tasksizes'].get(task, 0)
+ extra_info['tasksizes'][task] = origtotal + fsize
+ extra_info['filesizes'][fn] = fsize
+ return extra_info
+
if __name__ == "__main__":
pass
diff --git a/meta/lib/oe/spdx.py b/meta/lib/oe/spdx.py
new file mode 100644
index 0000000000..c74ea68878
--- /dev/null
+++ b/meta/lib/oe/spdx.py
@@ -0,0 +1,344 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: GPL-2.0-only
+#
+
+#
+# This library is intended to capture the JSON SPDX specification in a type
+# safe manner. It is not intended to encode any particular OE specific
+# behaviors, see the sbom.py for that.
+#
+# The documented SPDX spec document doesn't cover the JSON syntax for
+# particular configuration, which can make it hard to determine what the JSON
+# syntax should be. I've found it is actually much simpler to read the official
+# SPDX JSON schema which can be found here: https://github.com/spdx/spdx-spec
+# in schemas/spdx-schema.json
+#
+
+import hashlib
+import itertools
+import json
+
+SPDX_VERSION = "2.2"
+
+
+#
+# The following are the support classes that are used to implement SPDX object
+#
+
+class _Property(object):
+ """
+ A generic SPDX object property. The different types will derive from this
+ class
+ """
+
+ def __init__(self, *, default=None):
+ self.default = default
+
+ def setdefault(self, dest, name):
+ if self.default is not None:
+ dest.setdefault(name, self.default)
+
+
+class _String(_Property):
+ """
+ A scalar string property for an SPDX object
+ """
+
+ def __init__(self, **kwargs):
+ super().__init__(**kwargs)
+
+ def set_property(self, attrs, name):
+ def get_helper(obj):
+ return obj._spdx[name]
+
+ def set_helper(obj, value):
+ obj._spdx[name] = value
+
+ def del_helper(obj):
+ del obj._spdx[name]
+
+ attrs[name] = property(get_helper, set_helper, del_helper)
+
+ def init(self, source):
+ return source
+
+
+class _Object(_Property):
+ """
+ A scalar SPDX object property of a SPDX object
+ """
+
+ def __init__(self, cls, **kwargs):
+ super().__init__(**kwargs)
+ self.cls = cls
+
+ def set_property(self, attrs, name):
+ def get_helper(obj):
+ if not name in obj._spdx:
+ obj._spdx[name] = self.cls()
+ return obj._spdx[name]
+
+ def set_helper(obj, value):
+ obj._spdx[name] = value
+
+ def del_helper(obj):
+ del obj._spdx[name]
+
+ attrs[name] = property(get_helper, set_helper)
+
+ def init(self, source):
+ return self.cls(**source)
+
+
+class _ListProperty(_Property):
+ """
+ A list of SPDX properties
+ """
+
+ def __init__(self, prop, **kwargs):
+ super().__init__(**kwargs)
+ self.prop = prop
+
+ def set_property(self, attrs, name):
+ def get_helper(obj):
+ if not name in obj._spdx:
+ obj._spdx[name] = []
+ return obj._spdx[name]
+
+ def set_helper(obj, value):
+ obj._spdx[name] = list(value)
+
+ def del_helper(obj):
+ del obj._spdx[name]
+
+ attrs[name] = property(get_helper, set_helper, del_helper)
+
+ def init(self, source):
+ return [self.prop.init(o) for o in source]
+
+
+class _StringList(_ListProperty):
+ """
+ A list of strings as a property for an SPDX object
+ """
+
+ def __init__(self, **kwargs):
+ super().__init__(_String(), **kwargs)
+
+
+class _ObjectList(_ListProperty):
+ """
+ A list of SPDX objects as a property for an SPDX object
+ """
+
+ def __init__(self, cls, **kwargs):
+ super().__init__(_Object(cls), **kwargs)
+
+
+class MetaSPDXObject(type):
+ """
+ A metaclass that allows properties (anything derived from a _Property
+ class) to be defined for a SPDX object
+ """
+ def __new__(mcls, name, bases, attrs):
+ attrs["_properties"] = {}
+
+ for key in attrs.keys():
+ if isinstance(attrs[key], _Property):
+ prop = attrs[key]
+ attrs["_properties"][key] = prop
+ prop.set_property(attrs, key)
+
+ return super().__new__(mcls, name, bases, attrs)
+
+
+class SPDXObject(metaclass=MetaSPDXObject):
+ """
+ The base SPDX object; all SPDX spec classes must derive from this class
+ """
+ def __init__(self, **d):
+ self._spdx = {}
+
+ for name, prop in self._properties.items():
+ prop.setdefault(self._spdx, name)
+ if name in d:
+ self._spdx[name] = prop.init(d[name])
+
+ def serializer(self):
+ return self._spdx
+
+ def __setattr__(self, name, value):
+ if name in self._properties or name == "_spdx":
+ super().__setattr__(name, value)
+ return
+ raise KeyError("%r is not a valid SPDX property" % name)
+
+#
+# These are the SPDX objects implemented from the spec. The *only* properties
+# that can be added to these objects are ones directly specified in the SPDX
+# spec, however you may add helper functions to make operations easier.
+#
+# Defaults should *only* be specified if the SPDX spec says there is a certain
+# required value for a field (e.g. dataLicense), or if the field is mandatory
+# and has some sane "this field is unknown" (e.g. "NOASSERTION")
+#
+
+class SPDXAnnotation(SPDXObject):
+ annotationDate = _String()
+ annotationType = _String()
+ annotator = _String()
+ comment = _String()
+
+class SPDXChecksum(SPDXObject):
+ algorithm = _String()
+ checksumValue = _String()
+
+
+class SPDXRelationship(SPDXObject):
+ spdxElementId = _String()
+ relatedSpdxElement = _String()
+ relationshipType = _String()
+ comment = _String()
+ annotations = _ObjectList(SPDXAnnotation)
+
+
+class SPDXExternalReference(SPDXObject):
+ referenceCategory = _String()
+ referenceType = _String()
+ referenceLocator = _String()
+
+
+class SPDXPackageVerificationCode(SPDXObject):
+ packageVerificationCodeValue = _String()
+ packageVerificationCodeExcludedFiles = _StringList()
+
+
+class SPDXPackage(SPDXObject):
+ name = _String()
+ SPDXID = _String()
+ versionInfo = _String()
+ downloadLocation = _String(default="NOASSERTION")
+ supplier = _String(default="NOASSERTION")
+ homepage = _String()
+ licenseConcluded = _String(default="NOASSERTION")
+ licenseDeclared = _String(default="NOASSERTION")
+ summary = _String()
+ description = _String()
+ sourceInfo = _String()
+ copyrightText = _String(default="NOASSERTION")
+ licenseInfoFromFiles = _StringList(default=["NOASSERTION"])
+ externalRefs = _ObjectList(SPDXExternalReference)
+ packageVerificationCode = _Object(SPDXPackageVerificationCode)
+ hasFiles = _StringList()
+ packageFileName = _String()
+ annotations = _ObjectList(SPDXAnnotation)
+
+
+class SPDXFile(SPDXObject):
+ SPDXID = _String()
+ fileName = _String()
+ licenseConcluded = _String(default="NOASSERTION")
+ copyrightText = _String(default="NOASSERTION")
+ licenseInfoInFiles = _StringList(default=["NOASSERTION"])
+ checksums = _ObjectList(SPDXChecksum)
+ fileTypes = _StringList()
+
+
+class SPDXCreationInfo(SPDXObject):
+ created = _String()
+ licenseListVersion = _String()
+ comment = _String()
+ creators = _StringList()
+
+
+class SPDXExternalDocumentRef(SPDXObject):
+ externalDocumentId = _String()
+ spdxDocument = _String()
+ checksum = _Object(SPDXChecksum)
+
+
+class SPDXExtractedLicensingInfo(SPDXObject):
+ name = _String()
+ comment = _String()
+ licenseId = _String()
+ extractedText = _String()
+
+
+class SPDXDocument(SPDXObject):
+ spdxVersion = _String(default="SPDX-" + SPDX_VERSION)
+ dataLicense = _String(default="CC0-1.0")
+ SPDXID = _String(default="SPDXRef-DOCUMENT")
+ name = _String()
+ documentNamespace = _String()
+ creationInfo = _Object(SPDXCreationInfo)
+ packages = _ObjectList(SPDXPackage)
+ files = _ObjectList(SPDXFile)
+ relationships = _ObjectList(SPDXRelationship)
+ externalDocumentRefs = _ObjectList(SPDXExternalDocumentRef)
+ hasExtractedLicensingInfos = _ObjectList(SPDXExtractedLicensingInfo)
+
+ def __init__(self, **d):
+ super().__init__(**d)
+
+ def to_json(self, f, *, sort_keys=False, indent=None, separators=None):
+ class Encoder(json.JSONEncoder):
+ def default(self, o):
+ if isinstance(o, SPDXObject):
+ return o.serializer()
+
+ return super().default(o)
+
+ sha1 = hashlib.sha1()
+ for chunk in Encoder(
+ sort_keys=sort_keys,
+ indent=indent,
+ separators=separators,
+ ).iterencode(self):
+ chunk = chunk.encode("utf-8")
+ f.write(chunk)
+ sha1.update(chunk)
+
+ return sha1.hexdigest()
+
+ @classmethod
+ def from_json(cls, f):
+ return cls(**json.load(f))
+
+ def add_relationship(self, _from, relationship, _to, *, comment=None, annotation=None):
+ if isinstance(_from, SPDXObject):
+ from_spdxid = _from.SPDXID
+ else:
+ from_spdxid = _from
+
+ if isinstance(_to, SPDXObject):
+ to_spdxid = _to.SPDXID
+ else:
+ to_spdxid = _to
+
+ r = SPDXRelationship(
+ spdxElementId=from_spdxid,
+ relatedSpdxElement=to_spdxid,
+ relationshipType=relationship,
+ )
+
+ if comment is not None:
+ r.comment = comment
+
+ if annotation is not None:
+ r.annotations.append(annotation)
+
+ self.relationships.append(r)
+
+ def find_by_spdxid(self, spdxid):
+ for o in itertools.chain(self.packages, self.files):
+ if o.SPDXID == spdxid:
+ return o
+ return None
+
+ def find_external_document_ref(self, namespace):
+ for r in self.externalDocumentRefs:
+ if r.spdxDocument == namespace:
+ return r
+ return None
diff --git a/meta/lib/oe/sstatesig.py b/meta/lib/oe/sstatesig.py
index 8224e3a12e..f0224454c9 100644
--- a/meta/lib/oe/sstatesig.py
+++ b/meta/lib/oe/sstatesig.py
@@ -1,6 +1,13 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: GPL-2.0-only
+#
import bb.siggen
+import bb.runqueue
+import oe
-def sstate_rundepfilter(siggen, fn, recipename, task, dep, depname, dataCache):
+def sstate_rundepfilter(siggen, fn, recipename, task, dep, depname, dataCaches):
# Return True if we should keep the dependency, False to drop it
def isNative(x):
return x.endswith("-native")
@@ -8,31 +15,52 @@ def sstate_rundepfilter(siggen, fn, recipename, task, dep, depname, dataCache):
return "-cross-" in x
def isNativeSDK(x):
return x.startswith("nativesdk-")
- def isKernel(fn):
- inherits = " ".join(dataCache.inherits[fn])
+ def isKernel(mc, fn):
+ inherits = " ".join(dataCaches[mc].inherits[fn])
return inherits.find("/module-base.bbclass") != -1 or inherits.find("/linux-kernel-base.bbclass") != -1
- def isPackageGroup(fn):
- inherits = " ".join(dataCache.inherits[fn])
+ def isPackageGroup(mc, fn):
+ inherits = " ".join(dataCaches[mc].inherits[fn])
return "/packagegroup.bbclass" in inherits
- def isAllArch(fn):
- inherits = " ".join(dataCache.inherits[fn])
+ def isAllArch(mc, fn):
+ inherits = " ".join(dataCaches[mc].inherits[fn])
return "/allarch.bbclass" in inherits
- def isImage(fn):
- return "/image.bbclass" in " ".join(dataCache.inherits[fn])
+ def isImage(mc, fn):
+ return "/image.bbclass" in " ".join(dataCaches[mc].inherits[fn])
+ def isSPDXTask(task):
+ return task in ("do_create_spdx", "do_create_runtime_spdx")
+
+ depmc, _, deptaskname, depmcfn = bb.runqueue.split_tid_mcfn(dep)
+ mc, _ = bb.runqueue.split_mc(fn)
+
+ # We can skip the rm_work task signature to avoid running the task
+ # when we remove some tasks from the dependencie chain
+ # i.e INHERIT:remove = "create-spdx" will trigger the do_rm_work
+ if task == "do_rm_work":
+ return False
- # Always include our own inter-task dependencies
- if recipename == depname:
+ # Keep all dependencies between SPDX tasks in the signature. SPDX documents
+ # are linked together by hashes, which means if a dependent document changes,
+ # all downstream documents must be re-written (even if they are "safe"
+ # dependencies).
+ if isSPDXTask(task) and isSPDXTask(deptaskname):
return True
- # Quilt (patch application) changing isn't likely to affect anything
- excludelist = ['quilt-native', 'subversion-native', 'git-native']
- if depname in excludelist and recipename != depname:
- return False
+ # (Almost) always include our own inter-task dependencies (unless it comes
+ # from a mcdepends). The exception is the special
+ # do_kernel_configme->do_unpack_and_patch dependency from archiver.bbclass.
+ if recipename == depname and depmc == mc:
+ if task == "do_kernel_configme" and deptaskname == "do_unpack_and_patch":
+ return False
+ return True
# Exclude well defined recipe->dependency
if "%s->%s" % (recipename, depname) in siggen.saferecipedeps:
return False
+ # Check for special wildcard
+ if "*->%s" % depname in siggen.saferecipedeps and recipename != depname:
+ return False
+
# Don't change native/cross/nativesdk recipe dependencies any further
if isNative(recipename) or isCross(recipename) or isNativeSDK(recipename):
return True
@@ -40,22 +68,21 @@ def sstate_rundepfilter(siggen, fn, recipename, task, dep, depname, dataCache):
# Only target packages beyond here
# allarch packagegroups are assumed to have well behaved names which don't change between architecures/tunes
- if isPackageGroup(fn) and isAllArch(fn) and not isNative(depname):
- return False
+ if isPackageGroup(mc, fn) and isAllArch(mc, fn) and not isNative(depname):
+ return False
# Exclude well defined machine specific configurations which don't change ABI
- if depname in siggen.abisaferecipes and not isImage(fn):
+ if depname in siggen.abisaferecipes and not isImage(mc, fn):
return False
# Kernel modules are well namespaced. We don't want to depend on the kernel's checksum
- # if we're just doing an RRECOMMENDS_xxx = "kernel-module-*", not least because the checksum
+ # if we're just doing an RRECOMMENDS:xxx = "kernel-module-*", not least because the checksum
# is machine specific.
# Therefore if we're not a kernel or a module recipe (inheriting the kernel classes)
# and we reccomend a kernel-module, we exclude the dependency.
- depfn = dep.rsplit(".", 1)[0]
- if dataCache and isKernel(depfn) and not isKernel(fn):
- for pkg in dataCache.runrecs[fn]:
- if " ".join(dataCache.runrecs[fn][pkg]).find("kernel-module-") != -1:
+ if dataCaches and isKernel(depmc, depmcfn) and not isKernel(mc, fn):
+ for pkg in dataCaches[mc].runrecs[fn]:
+ if " ".join(dataCaches[mc].runrecs[fn][pkg]).find("kernel-module-") != -1:
return False
# Default to keep dependencies
@@ -63,10 +90,10 @@ def sstate_rundepfilter(siggen, fn, recipename, task, dep, depname, dataCache):
def sstate_lockedsigs(d):
sigs = {}
- types = (d.getVar("SIGGEN_LOCKEDSIGS_TYPES", True) or "").split()
+ types = (d.getVar("SIGGEN_LOCKEDSIGS_TYPES") or "").split()
for t in types:
siggen_lockedsigs_var = "SIGGEN_LOCKEDSIGS_%s" % t
- lockedsigs = (d.getVar(siggen_lockedsigs_var, True) or "").split()
+ lockedsigs = (d.getVar(siggen_lockedsigs_var) or "").split()
for ls in lockedsigs:
pn, task, h = ls.split(":", 2)
if pn not in sigs:
@@ -74,29 +101,22 @@ def sstate_lockedsigs(d):
sigs[pn][task] = [h, siggen_lockedsigs_var]
return sigs
-class SignatureGeneratorOEBasic(bb.siggen.SignatureGeneratorBasic):
- name = "OEBasic"
- def init_rundepcheck(self, data):
- self.abisaferecipes = (data.getVar("SIGGEN_EXCLUDERECIPES_ABISAFE", True) or "").split()
- self.saferecipedeps = (data.getVar("SIGGEN_EXCLUDE_SAFE_RECIPE_DEPS", True) or "").split()
- pass
- def rundep_check(self, fn, recipename, task, dep, depname, dataCache = None):
- return sstate_rundepfilter(self, fn, recipename, task, dep, depname, dataCache)
+class SignatureGeneratorOEBasicHashMixIn(object):
+ supports_multiconfig_datacaches = True
-class SignatureGeneratorOEBasicHash(bb.siggen.SignatureGeneratorBasicHash):
- name = "OEBasicHash"
def init_rundepcheck(self, data):
- self.abisaferecipes = (data.getVar("SIGGEN_EXCLUDERECIPES_ABISAFE", True) or "").split()
- self.saferecipedeps = (data.getVar("SIGGEN_EXCLUDE_SAFE_RECIPE_DEPS", True) or "").split()
+ self.abisaferecipes = (data.getVar("SIGGEN_EXCLUDERECIPES_ABISAFE") or "").split()
+ self.saferecipedeps = (data.getVar("SIGGEN_EXCLUDE_SAFE_RECIPE_DEPS") or "").split()
self.lockedsigs = sstate_lockedsigs(data)
self.lockedhashes = {}
self.lockedpnmap = {}
self.lockedhashfn = {}
- self.machine = data.getVar("MACHINE", True)
+ self.machine = data.getVar("MACHINE")
self.mismatch_msgs = []
- self.unlockedrecipes = (data.getVar("SIGGEN_UNLOCKED_RECIPES", True) or
+ self.unlockedrecipes = (data.getVar("SIGGEN_UNLOCKED_RECIPES") or
"").split()
self.unlockedrecipes = { k: "" for k in self.unlockedrecipes }
+ self._internal = False
pass
def tasks_resolved(self, virtmap, virtpnmap, dataCache):
@@ -118,16 +138,15 @@ class SignatureGeneratorOEBasicHash(bb.siggen.SignatureGeneratorBasicHash):
newsafedeps.append(a1 + "->" + a2)
self.saferecipedeps = newsafedeps
- def rundep_check(self, fn, recipename, task, dep, depname, dataCache = None):
- return sstate_rundepfilter(self, fn, recipename, task, dep, depname, dataCache)
+ def rundep_check(self, fn, recipename, task, dep, depname, dataCaches = None):
+ return sstate_rundepfilter(self, fn, recipename, task, dep, depname, dataCaches)
def get_taskdata(self):
- data = super(bb.siggen.SignatureGeneratorBasicHash, self).get_taskdata()
- return (data, self.lockedpnmap, self.lockedhashfn)
+ return (self.lockedpnmap, self.lockedhashfn, self.lockedhashes) + super().get_taskdata()
def set_taskdata(self, data):
- coredata, self.lockedpnmap, self.lockedhashfn = data
- super(bb.siggen.SignatureGeneratorBasicHash, self).set_taskdata(coredata)
+ self.lockedpnmap, self.lockedhashfn, self.lockedhashes = data[:3]
+ super().set_taskdata(data[3:])
def dump_sigs(self, dataCache, options):
sigfile = os.getcwd() + "/locked-sigs.inc"
@@ -135,102 +154,143 @@ class SignatureGeneratorOEBasicHash(bb.siggen.SignatureGeneratorBasicHash):
self.dump_lockedsigs(sigfile)
return super(bb.siggen.SignatureGeneratorBasicHash, self).dump_sigs(dataCache, options)
- def get_taskhash(self, fn, task, deps, dataCache):
- h = super(bb.siggen.SignatureGeneratorBasicHash, self).get_taskhash(fn, task, deps, dataCache)
- recipename = dataCache.pkg_fn[fn]
+ def get_taskhash(self, tid, deps, dataCaches):
+ if tid in self.lockedhashes:
+ if self.lockedhashes[tid]:
+ return self.lockedhashes[tid]
+ else:
+ return super().get_taskhash(tid, deps, dataCaches)
+
+ h = super().get_taskhash(tid, deps, dataCaches)
+
+ (mc, _, task, fn) = bb.runqueue.split_tid_mcfn(tid)
+
+ recipename = dataCaches[mc].pkg_fn[fn]
self.lockedpnmap[fn] = recipename
- self.lockedhashfn[fn] = dataCache.hashfn[fn]
+ self.lockedhashfn[fn] = dataCaches[mc].hashfn[fn]
unlocked = False
if recipename in self.unlockedrecipes:
unlocked = True
else:
def recipename_from_dep(dep):
- # The dep entry will look something like
- # /path/path/recipename.bb.task, virtual:native:/p/foo.bb.task,
- # ...
- fn = dep.rsplit('.', 1)[0]
- return dataCache.pkg_fn[fn]
+ (depmc, _, _, depfn) = bb.runqueue.split_tid_mcfn(dep)
+ return dataCaches[depmc].pkg_fn[depfn]
# If any unlocked recipe is in the direct dependencies then the
# current recipe should be unlocked as well.
- depnames = [ recipename_from_dep(x) for x in deps ]
+ depnames = [ recipename_from_dep(x) for x in deps if mc == bb.runqueue.mc_from_tid(x)]
if any(x in y for y in depnames for x in self.unlockedrecipes):
self.unlockedrecipes[recipename] = ''
unlocked = True
if not unlocked and recipename in self.lockedsigs:
if task in self.lockedsigs[recipename]:
- k = fn + "." + task
h_locked = self.lockedsigs[recipename][task][0]
var = self.lockedsigs[recipename][task][1]
- self.lockedhashes[k] = h_locked
- self.taskhash[k] = h_locked
+ self.lockedhashes[tid] = h_locked
+ self._internal = True
+ unihash = self.get_unihash(tid)
+ self._internal = False
#bb.warn("Using %s %s %s" % (recipename, task, h))
- if h != h_locked:
+ if h != h_locked and h_locked != unihash:
self.mismatch_msgs.append('The %s:%s sig is computed to be %s, but the sig is locked to %s in %s'
% (recipename, task, h, h_locked, var))
return h_locked
+
+ self.lockedhashes[tid] = False
#bb.warn("%s %s %s" % (recipename, task, h))
return h
+ def get_stampfile_hash(self, tid):
+ if tid in self.lockedhashes and self.lockedhashes[tid]:
+ return self.lockedhashes[tid]
+ return super().get_stampfile_hash(tid)
+
+ def get_unihash(self, tid):
+ if tid in self.lockedhashes and self.lockedhashes[tid] and not self._internal:
+ return self.lockedhashes[tid]
+ return super().get_unihash(tid)
+
def dump_sigtask(self, fn, task, stampbase, runtime):
- k = fn + "." + task
- if k in self.lockedhashes:
+ tid = fn + ":" + task
+ if tid in self.lockedhashes and self.lockedhashes[tid]:
return
super(bb.siggen.SignatureGeneratorBasicHash, self).dump_sigtask(fn, task, stampbase, runtime)
def dump_lockedsigs(self, sigfile, taskfilter=None):
types = {}
- for k in self.runtaskdeps:
+ for tid in self.runtaskdeps:
if taskfilter:
- if not k in taskfilter:
+ if not tid in taskfilter:
continue
- fn = k.rsplit(".",1)[0]
+ fn = bb.runqueue.fn_from_tid(tid)
t = self.lockedhashfn[fn].split(" ")[1].split(":")[5]
t = 't-' + t.replace('_', '-')
if t not in types:
types[t] = []
- types[t].append(k)
+ types[t].append(tid)
with open(sigfile, "w") as f:
- for t in types:
+ l = sorted(types)
+ for t in l:
f.write('SIGGEN_LOCKEDSIGS_%s = "\\\n' % t)
types[t].sort()
- sortedk = sorted(types[t], key=lambda k: self.lockedpnmap[k.rsplit(".",1)[0]])
- for k in sortedk:
- fn = k.rsplit(".",1)[0]
- task = k.rsplit(".",1)[1]
- if k not in self.taskhash:
+ sortedtid = sorted(types[t], key=lambda tid: self.lockedpnmap[bb.runqueue.fn_from_tid(tid)])
+ for tid in sortedtid:
+ (_, _, task, fn) = bb.runqueue.split_tid_mcfn(tid)
+ if tid not in self.taskhash:
continue
- f.write(" " + self.lockedpnmap[fn] + ":" + task + ":" + self.taskhash[k] + " \\\n")
+ f.write(" " + self.lockedpnmap[fn] + ":" + task + ":" + self.get_unihash(tid) + " \\\n")
f.write(' "\n')
- f.write('SIGGEN_LOCKEDSIGS_TYPES_%s = "%s"' % (self.machine, " ".join(list(types.keys()))))
+ f.write('SIGGEN_LOCKEDSIGS_TYPES:%s = "%s"' % (self.machine, " ".join(l)))
- def checkhashes(self, missed, ret, sq_fn, sq_task, sq_hash, sq_hashfn, d):
+ def dump_siglist(self, sigfile, path_prefix_strip=None):
+ def strip_fn(fn):
+ nonlocal path_prefix_strip
+ if not path_prefix_strip:
+ return fn
+
+ fn_exp = fn.split(":")
+ if fn_exp[-1].startswith(path_prefix_strip):
+ fn_exp[-1] = fn_exp[-1][len(path_prefix_strip):]
+
+ return ":".join(fn_exp)
+
+ with open(sigfile, "w") as f:
+ tasks = []
+ for taskitem in self.taskhash:
+ (fn, task) = taskitem.rsplit(":", 1)
+ pn = self.lockedpnmap[fn]
+ tasks.append((pn, task, strip_fn(fn), self.taskhash[taskitem]))
+ for (pn, task, fn, taskhash) in sorted(tasks):
+ f.write('%s:%s %s %s\n' % (pn, task, fn, taskhash))
+
+ def checkhashes(self, sq_data, missed, found, d):
warn_msgs = []
error_msgs = []
sstate_missing_msgs = []
- for task in range(len(sq_fn)):
- if task not in ret:
+ for tid in sq_data['hash']:
+ if tid not in found:
for pn in self.lockedsigs:
- if sq_hash[task] in iter(self.lockedsigs[pn].values()):
- if sq_task[task] == 'do_shared_workdir':
+ taskname = bb.runqueue.taskname_from_tid(tid)
+ if sq_data['hash'][tid] in iter(self.lockedsigs[pn].values()):
+ if taskname == 'do_shared_workdir':
continue
sstate_missing_msgs.append("Locked sig is set for %s:%s (%s) yet not in sstate cache?"
- % (pn, sq_task[task], sq_hash[task]))
+ % (pn, taskname, sq_data['hash'][tid]))
- checklevel = d.getVar("SIGGEN_LOCKEDSIGS_TASKSIG_CHECK", True)
+ checklevel = d.getVar("SIGGEN_LOCKEDSIGS_TASKSIG_CHECK")
if checklevel == 'warn':
warn_msgs += self.mismatch_msgs
elif checklevel == 'error':
error_msgs += self.mismatch_msgs
- checklevel = d.getVar("SIGGEN_LOCKEDSIGS_SSTATE_EXISTS_CHECK", True)
+ checklevel = d.getVar("SIGGEN_LOCKEDSIGS_SSTATE_EXISTS_CHECK")
if checklevel == 'warn':
warn_msgs += sstate_missing_msgs
elif checklevel == 'error':
@@ -241,10 +301,24 @@ class SignatureGeneratorOEBasicHash(bb.siggen.SignatureGeneratorBasicHash):
if error_msgs:
bb.fatal("\n".join(error_msgs))
+class SignatureGeneratorOEBasicHash(SignatureGeneratorOEBasicHashMixIn, bb.siggen.SignatureGeneratorBasicHash):
+ name = "OEBasicHash"
+
+class SignatureGeneratorOEEquivHash(SignatureGeneratorOEBasicHashMixIn, bb.siggen.SignatureGeneratorUniHashMixIn, bb.siggen.SignatureGeneratorBasicHash):
+ name = "OEEquivHash"
+
+ def init_rundepcheck(self, data):
+ super().init_rundepcheck(data)
+ self.server = data.getVar('BB_HASHSERVE')
+ if not self.server:
+ bb.fatal("OEEquivHash requires BB_HASHSERVE to be set")
+ self.method = data.getVar('SSTATE_HASHEQUIV_METHOD')
+ if not self.method:
+ bb.fatal("OEEquivHash requires SSTATE_HASHEQUIV_METHOD to be set")
# Insert these classes into siggen's namespace so it can see and select them
-bb.siggen.SignatureGeneratorOEBasic = SignatureGeneratorOEBasic
bb.siggen.SignatureGeneratorOEBasicHash = SignatureGeneratorOEBasicHash
+bb.siggen.SignatureGeneratorOEEquivHash = SignatureGeneratorOEEquivHash
def find_siginfo(pn, taskname, taskhashlist, d):
@@ -253,20 +327,24 @@ def find_siginfo(pn, taskname, taskhashlist, d):
import fnmatch
import glob
- if taskhashlist:
- hashfiles = {}
-
if not taskname:
# We have to derive pn and taskname
key = pn
- splitit = key.split('.bb.')
+ splitit = key.split('.bb:')
taskname = splitit[1]
pn = os.path.basename(splitit[0]).split('_')[0]
if key.startswith('virtual:native:'):
pn = pn + '-native'
+ hashfiles = {}
filedates = {}
+ def get_hashval(siginfo):
+ if siginfo.endswith('.siginfo'):
+ return siginfo.rpartition(':')[2].partition('_')[0]
+ else:
+ return siginfo.rpartition('.')[2]
+
# First search in stamps dir
localdata = d.createCopy()
localdata.setVar('MULTIMACH_TARGET_SYS', '*')
@@ -274,7 +352,7 @@ def find_siginfo(pn, taskname, taskhashlist, d):
localdata.setVar('PV', '*')
localdata.setVar('PR', '*')
localdata.setVar('EXTENDPE', '')
- stamp = localdata.getVar('STAMP', True)
+ stamp = localdata.getVar('STAMP')
if pn.startswith("gcc-source"):
# gcc-source shared workdir is a special case :(
stamp = localdata.expand("${STAMPS_DIR}/work-shared/gcc-${PV}-${PR}")
@@ -296,10 +374,12 @@ def find_siginfo(pn, taskname, taskhashlist, d):
filedates[fullpath] = os.stat(fullpath).st_mtime
except OSError:
continue
+ hashval = get_hashval(fullpath)
+ hashfiles[hashval] = fullpath
if not taskhashlist or (len(filedates) < 2 and not foundall):
# That didn't work, look in sstate-cache
- hashes = taskhashlist or ['*']
+ hashes = taskhashlist or ['?' * 64]
localdata = bb.data.createCopy(d)
for hashval in hashes:
localdata.setVar('PACKAGE_ARCH', '*')
@@ -309,30 +389,25 @@ def find_siginfo(pn, taskname, taskhashlist, d):
localdata.setVar('PV', '*')
localdata.setVar('PR', '*')
localdata.setVar('BB_TASKHASH', hashval)
- swspec = localdata.getVar('SSTATE_SWSPEC', True)
+ localdata.setVar('SSTATE_CURRTASK', taskname[3:])
+ swspec = localdata.getVar('SSTATE_SWSPEC')
if taskname in ['do_fetch', 'do_unpack', 'do_patch', 'do_populate_lic', 'do_preconfigure'] and swspec:
localdata.setVar('SSTATE_PKGSPEC', '${SSTATE_SWSPEC}')
elif pn.endswith('-native') or "-cross-" in pn or "-crosssdk-" in pn:
localdata.setVar('SSTATE_EXTRAPATH', "${NATIVELSBSTRING}/")
- sstatename = taskname[3:]
- filespec = '%s_%s.*.siginfo' % (localdata.getVar('SSTATE_PKG', True), sstatename)
+ filespec = '%s.siginfo' % localdata.getVar('SSTATE_PKG')
- if hashval != '*':
- sstatedir = "%s/%s" % (d.getVar('SSTATE_DIR', True), hashval[:2])
- else:
- sstatedir = d.getVar('SSTATE_DIR', True)
-
- for root, dirs, files in os.walk(sstatedir):
- for fn in files:
- fullpath = os.path.join(root, fn)
- if fnmatch.fnmatch(fullpath, filespec):
- if taskhashlist:
- hashfiles[hashval] = fullpath
- else:
- try:
- filedates[fullpath] = os.stat(fullpath).st_mtime
- except:
- continue
+ matchedfiles = glob.glob(filespec)
+ for fullpath in matchedfiles:
+ actual_hashval = get_hashval(fullpath)
+ if actual_hashval in hashfiles:
+ continue
+ hashfiles[hashval] = fullpath
+ if not taskhashlist:
+ try:
+ filedates[fullpath] = os.stat(fullpath).st_mtime
+ except:
+ continue
if taskhashlist:
return hashfiles
@@ -348,7 +423,238 @@ def sstate_get_manifest_filename(task, d):
Also returns the datastore that can be used to query related variables.
"""
d2 = d.createCopy()
- extrainf = d.getVarFlag("do_" + task, 'stamp-extra-info', True)
+ extrainf = d.getVarFlag("do_" + task, 'stamp-extra-info')
if extrainf:
d2.setVar("SSTATE_MANMACH", extrainf)
return (d2.expand("${SSTATE_MANFILEPREFIX}.%s" % task), d2)
+
+def find_sstate_manifest(taskdata, taskdata2, taskname, d, multilibcache):
+ d2 = d
+ variant = ''
+ curr_variant = ''
+ if d.getVar("BBEXTENDCURR") == "multilib":
+ curr_variant = d.getVar("BBEXTENDVARIANT")
+ if "virtclass-multilib" not in d.getVar("OVERRIDES"):
+ curr_variant = "invalid"
+ if taskdata2.startswith("virtual:multilib"):
+ variant = taskdata2.split(":")[2]
+ if curr_variant != variant:
+ if variant not in multilibcache:
+ multilibcache[variant] = oe.utils.get_multilib_datastore(variant, d)
+ d2 = multilibcache[variant]
+
+ if taskdata.endswith("-native"):
+ pkgarchs = ["${BUILD_ARCH}", "${BUILD_ARCH}_${ORIGNATIVELSBSTRING}"]
+ elif taskdata.startswith("nativesdk-"):
+ pkgarchs = ["${SDK_ARCH}_${SDK_OS}", "allarch"]
+ elif "-cross-canadian" in taskdata:
+ pkgarchs = ["${SDK_ARCH}_${SDK_ARCH}-${SDKPKGSUFFIX}"]
+ elif "-cross-" in taskdata:
+ pkgarchs = ["${BUILD_ARCH}"]
+ elif "-crosssdk" in taskdata:
+ pkgarchs = ["${BUILD_ARCH}_${SDK_ARCH}_${SDK_OS}"]
+ else:
+ pkgarchs = ['${MACHINE_ARCH}']
+ pkgarchs = pkgarchs + list(reversed(d2.getVar("PACKAGE_EXTRA_ARCHS").split()))
+ pkgarchs.append('allarch')
+ pkgarchs.append('${SDK_ARCH}_${SDK_ARCH}-${SDKPKGSUFFIX}')
+
+ searched_manifests = []
+
+ for pkgarch in pkgarchs:
+ manifest = d2.expand("${SSTATE_MANIFESTS}/manifest-%s-%s.%s" % (pkgarch, taskdata, taskname))
+ if os.path.exists(manifest):
+ return manifest, d2
+ searched_manifests.append(manifest)
+ bb.fatal("The sstate manifest for task '%s:%s' (multilib variant '%s') could not be found.\nThe pkgarchs considered were: %s.\nBut none of these manifests exists:\n %s"
+ % (taskdata, taskname, variant, d2.expand(", ".join(pkgarchs)),"\n ".join(searched_manifests)))
+ return None, d2
+
+def OEOuthashBasic(path, sigfile, task, d):
+ """
+ Basic output hash function
+
+ Calculates the output hash of a task by hashing all output file metadata,
+ and file contents.
+ """
+ import hashlib
+ import stat
+ import pwd
+ import grp
+ import re
+ import fnmatch
+
+ def update_hash(s):
+ s = s.encode('utf-8')
+ h.update(s)
+ if sigfile:
+ sigfile.write(s)
+
+ h = hashlib.sha256()
+ prev_dir = os.getcwd()
+ corebase = d.getVar("COREBASE")
+ tmpdir = d.getVar("TMPDIR")
+ include_owners = os.environ.get('PSEUDO_DISABLED') == '0'
+ if "package_write_" in task or task == "package_qa":
+ include_owners = False
+ include_timestamps = False
+ include_root = True
+ if task == "package":
+ include_timestamps = True
+ include_root = False
+ hash_version = d.getVar('HASHEQUIV_HASH_VERSION')
+ extra_sigdata = d.getVar("HASHEQUIV_EXTRA_SIGDATA")
+
+ filemaps = {}
+ for m in (d.getVar('SSTATE_HASHEQUIV_FILEMAP') or '').split():
+ entry = m.split(":")
+ if len(entry) != 3 or entry[0] != task:
+ continue
+ filemaps.setdefault(entry[1], [])
+ filemaps[entry[1]].append(entry[2])
+
+ try:
+ os.chdir(path)
+ basepath = os.path.normpath(path)
+
+ update_hash("OEOuthashBasic\n")
+ if hash_version:
+ update_hash(hash_version + "\n")
+
+ if extra_sigdata:
+ update_hash(extra_sigdata + "\n")
+
+ # It is only currently useful to get equivalent hashes for things that
+ # can be restored from sstate. Since the sstate object is named using
+ # SSTATE_PKGSPEC and the task name, those should be included in the
+ # output hash calculation.
+ update_hash("SSTATE_PKGSPEC=%s\n" % d.getVar('SSTATE_PKGSPEC'))
+ update_hash("task=%s\n" % task)
+
+ for root, dirs, files in os.walk('.', topdown=True):
+ # Sort directories to ensure consistent ordering when recursing
+ dirs.sort()
+ files.sort()
+
+ def process(path):
+ s = os.lstat(path)
+
+ if stat.S_ISDIR(s.st_mode):
+ update_hash('d')
+ elif stat.S_ISCHR(s.st_mode):
+ update_hash('c')
+ elif stat.S_ISBLK(s.st_mode):
+ update_hash('b')
+ elif stat.S_ISSOCK(s.st_mode):
+ update_hash('s')
+ elif stat.S_ISLNK(s.st_mode):
+ update_hash('l')
+ elif stat.S_ISFIFO(s.st_mode):
+ update_hash('p')
+ else:
+ update_hash('-')
+
+ def add_perm(mask, on, off='-'):
+ if mask & s.st_mode:
+ update_hash(on)
+ else:
+ update_hash(off)
+
+ add_perm(stat.S_IRUSR, 'r')
+ add_perm(stat.S_IWUSR, 'w')
+ if stat.S_ISUID & s.st_mode:
+ add_perm(stat.S_IXUSR, 's', 'S')
+ else:
+ add_perm(stat.S_IXUSR, 'x')
+
+ if include_owners:
+ # Group/other permissions are only relevant in pseudo context
+ add_perm(stat.S_IRGRP, 'r')
+ add_perm(stat.S_IWGRP, 'w')
+ if stat.S_ISGID & s.st_mode:
+ add_perm(stat.S_IXGRP, 's', 'S')
+ else:
+ add_perm(stat.S_IXGRP, 'x')
+
+ add_perm(stat.S_IROTH, 'r')
+ add_perm(stat.S_IWOTH, 'w')
+ if stat.S_ISVTX & s.st_mode:
+ update_hash('t')
+ else:
+ add_perm(stat.S_IXOTH, 'x')
+
+ try:
+ update_hash(" %10s" % pwd.getpwuid(s.st_uid).pw_name)
+ update_hash(" %10s" % grp.getgrgid(s.st_gid).gr_name)
+ except KeyError as e:
+ bb.warn("KeyError in %s" % path)
+ msg = ("KeyError: %s\nPath %s is owned by uid %d, gid %d, which doesn't match "
+ "any user/group on target. This may be due to host contamination." % (e, path, s.st_uid, s.st_gid))
+ raise Exception(msg).with_traceback(e.__traceback__)
+
+ if include_timestamps:
+ update_hash(" %10d" % s.st_mtime)
+
+ update_hash(" ")
+ if stat.S_ISBLK(s.st_mode) or stat.S_ISCHR(s.st_mode):
+ update_hash("%9s" % ("%d.%d" % (os.major(s.st_rdev), os.minor(s.st_rdev))))
+ else:
+ update_hash(" " * 9)
+
+ filterfile = False
+ for entry in filemaps:
+ if fnmatch.fnmatch(path, entry):
+ filterfile = True
+
+ update_hash(" ")
+ if stat.S_ISREG(s.st_mode) and not filterfile:
+ update_hash("%10d" % s.st_size)
+ else:
+ update_hash(" " * 10)
+
+ update_hash(" ")
+ fh = hashlib.sha256()
+ if stat.S_ISREG(s.st_mode):
+ # Hash file contents
+ if filterfile:
+ # Need to ignore paths in crossscripts and postinst-useradd files.
+ with open(path, 'rb') as d:
+ chunk = d.read()
+ chunk = chunk.replace(bytes(basepath, encoding='utf8'), b'')
+ for entry in filemaps:
+ if not fnmatch.fnmatch(path, entry):
+ continue
+ for r in filemaps[entry]:
+ if r.startswith("regex-"):
+ chunk = re.sub(bytes(r[6:], encoding='utf8'), b'', chunk)
+ else:
+ chunk = chunk.replace(bytes(r, encoding='utf8'), b'')
+ fh.update(chunk)
+ else:
+ with open(path, 'rb') as d:
+ for chunk in iter(lambda: d.read(4096), b""):
+ fh.update(chunk)
+ update_hash(fh.hexdigest())
+ else:
+ update_hash(" " * len(fh.hexdigest()))
+
+ update_hash(" %s" % path)
+
+ if stat.S_ISLNK(s.st_mode):
+ update_hash(" -> %s" % os.readlink(path))
+
+ update_hash("\n")
+
+ # Process this directory and all its child files
+ if include_root or root != ".":
+ process(root)
+ for f in files:
+ if f == 'fixmepath':
+ continue
+ process(os.path.join(root, f))
+ finally:
+ os.chdir(prev_dir)
+
+ return h.hexdigest()
+
+
diff --git a/meta/lib/oe/terminal.py b/meta/lib/oe/terminal.py
index 6d6a29f983..71ffc87019 100644
--- a/meta/lib/oe/terminal.py
+++ b/meta/lib/oe/terminal.py
@@ -1,8 +1,12 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: GPL-2.0-only
+#
import logging
import oe.classutils
import shlex
from bb.process import Popen, ExecutionError
-from distutils.version import LooseVersion
logger = logging.getLogger('BitBake.OE.Terminal')
@@ -11,7 +15,8 @@ class UnsupportedTerminal(Exception):
pass
class NoSupportedTerminals(Exception):
- pass
+ def __init__(self, terms):
+ self.terms = terms
class Registry(oe.classutils.ClassRegistry):
@@ -27,9 +32,10 @@ class Registry(oe.classutils.ClassRegistry):
class Terminal(Popen, metaclass=Registry):
def __init__(self, sh_cmd, title=None, env=None, d=None):
+ from subprocess import STDOUT
fmt_sh_cmd = self.format_command(sh_cmd, title)
try:
- Popen.__init__(self, fmt_sh_cmd, env=env)
+ Popen.__init__(self, fmt_sh_cmd, env=env, stderr=STDOUT)
except OSError as exc:
import errno
if exc.errno == errno.ENOENT:
@@ -38,7 +44,7 @@ class Terminal(Popen, metaclass=Registry):
raise
def format_command(self, sh_cmd, title):
- fmt = {'title': title or 'Terminal', 'command': sh_cmd}
+ fmt = {'title': title or 'Terminal', 'command': sh_cmd, 'cwd': os.getcwd() }
if isinstance(self.command, str):
return shlex.split(self.command.format(**fmt))
else:
@@ -51,7 +57,7 @@ class XTerminal(Terminal):
raise UnsupportedTerminal(self.name)
class Gnome(XTerminal):
- command = 'gnome-terminal -t "{title}" -x {command}'
+ command = 'gnome-terminal -t "{title}" -- {command}'
priority = 2
def __init__(self, sh_cmd, title=None, env=None, d=None):
@@ -61,29 +67,10 @@ class Gnome(XTerminal):
# Once fixed on the gnome-terminal project, this should be removed.
if os.getenv('LC_ALL'): os.putenv('LC_ALL','')
- # We need to know when the command completes but gnome-terminal gives us no way
- # to do this. We therefore write the pid to a file using a "phonehome" wrapper
- # script, then monitor the pid until it exits. Thanks gnome!
- import tempfile
- pidfile = tempfile.NamedTemporaryFile(delete = False).name
- try:
- sh_cmd = "oe-gnome-terminal-phonehome " + pidfile + " " + sh_cmd
- XTerminal.__init__(self, sh_cmd, title, env, d)
- while os.stat(pidfile).st_size <= 0:
- continue
- with open(pidfile, "r") as f:
- pid = int(f.readline())
- finally:
- os.unlink(pidfile)
-
- while True:
- try:
- os.kill(pid, 0)
- except OSError:
- return
+ XTerminal.__init__(self, sh_cmd, title, env, d)
class Mate(XTerminal):
- command = 'mate-terminal -t "{title}" -x {command}'
+ command = 'mate-terminal --disable-factory -t "{title}" -x {command}'
priority = 2
class Xfce(XTerminal):
@@ -95,15 +82,18 @@ class Terminology(XTerminal):
priority = 2
class Konsole(XTerminal):
- command = 'konsole --nofork --workdir . -p tabtitle="{title}" -e {command}'
+ command = 'konsole --separate --workdir . -p tabtitle="{title}" -e {command}'
priority = 2
def __init__(self, sh_cmd, title=None, env=None, d=None):
# Check version
vernum = check_terminal_version("konsole")
- if vernum and LooseVersion(vernum) < '2.0.0':
+ if vernum and bb.utils.vercmp_string_op(vernum, "2.0.0", "<"):
# Konsole from KDE 3.x
self.command = 'konsole -T "{title}" -e {command}'
+ elif vernum and bb.utils.vercmp_string_op(vernum, "16.08.1", "<"):
+ # Konsole pre 16.08.01 Has nofork
+ self.command = 'konsole --nofork --workdir . -p tabtitle="{title}" -e {command}'
XTerminal.__init__(self, sh_cmd, title, env, d)
class XTerm(XTerminal):
@@ -127,12 +117,12 @@ class Screen(Terminal):
bb.event.fire(bb.event.LogExecTTY(msg, "screen -r %s" % s_id,
0.5, 10), d)
else:
- logger.warn(msg)
+ logger.warning(msg)
class TmuxRunning(Terminal):
"""Open a new pane in the current running tmux window"""
name = 'tmux-running'
- command = 'tmux split-window "{command}"'
+ command = 'tmux split-window -c "{cwd}" "{command}"'
priority = 2.75
def __init__(self, sh_cmd, title=None, env=None, d=None):
@@ -150,7 +140,7 @@ class TmuxRunning(Terminal):
class TmuxNewWindow(Terminal):
"""Open a new window in the current running tmux session"""
name = 'tmux-new-window'
- command = 'tmux new-window -n "{title}" "{command}"'
+ command = 'tmux new-window -c "{cwd}" -n "{title}" "{command}"'
priority = 2.70
def __init__(self, sh_cmd, title=None, env=None, d=None):
@@ -164,7 +154,7 @@ class TmuxNewWindow(Terminal):
class Tmux(Terminal):
"""Start a new tmux session and window"""
- command = 'tmux new -d -s devshell -n devshell "{command}"'
+ command = 'tmux new -c "{cwd}" -d -s devshell -n devshell "{command}"'
priority = 0.75
def __init__(self, sh_cmd, title=None, env=None, d=None):
@@ -175,7 +165,12 @@ class Tmux(Terminal):
# devshells, if it's already there, add a new window to it.
window_name = 'devshell-%i' % os.getpid()
- self.command = 'tmux new -d -s {0} -n {0} "{{command}}"'.format(window_name)
+ self.command = 'tmux new -c "{{cwd}}" -d -s {0} -n {0} "{{command}}"'
+ if not check_tmux_version('1.9'):
+ # `tmux new-session -c` was added in 1.9;
+ # older versions fail with that flag
+ self.command = 'tmux new -d -s {0} -n {0} "{{command}}"'
+ self.command = self.command.format(window_name)
Terminal.__init__(self, sh_cmd, title, env, d)
attach_cmd = 'tmux att -t {0}'.format(window_name)
@@ -183,27 +178,35 @@ class Tmux(Terminal):
if d:
bb.event.fire(bb.event.LogExecTTY(msg, attach_cmd, 0.5, 10), d)
else:
- logger.warn(msg)
+ logger.warning(msg)
class Custom(Terminal):
command = 'false' # This is a placeholder
priority = 3
def __init__(self, sh_cmd, title=None, env=None, d=None):
- self.command = d and d.getVar('OE_TERMINAL_CUSTOMCMD', True)
+ self.command = d and d.getVar('OE_TERMINAL_CUSTOMCMD')
if self.command:
if not '{command}' in self.command:
self.command += ' {command}'
Terminal.__init__(self, sh_cmd, title, env, d)
- logger.warn('Custom terminal was started.')
+ logger.warning('Custom terminal was started.')
else:
- logger.debug(1, 'No custom terminal (OE_TERMINAL_CUSTOMCMD) set')
+ logger.debug('No custom terminal (OE_TERMINAL_CUSTOMCMD) set')
raise UnsupportedTerminal('OE_TERMINAL_CUSTOMCMD not set')
def prioritized():
return Registry.prioritized()
+def get_cmd_list():
+ terms = Registry.prioritized()
+ cmds = []
+ for term in terms:
+ if term.command:
+ cmds.append(term.command)
+ return cmds
+
def spawn_preferred(sh_cmd, title=None, env=None, d=None):
"""Spawn the first supported terminal, by priority"""
for terminal in prioritized():
@@ -211,30 +214,64 @@ def spawn_preferred(sh_cmd, title=None, env=None, d=None):
spawn(terminal.name, sh_cmd, title, env, d)
break
except UnsupportedTerminal:
- continue
+ pass
+ except:
+ bb.warn("Terminal %s is supported but did not start" % (terminal.name))
+ # when we've run out of options
else:
- raise NoSupportedTerminals()
+ raise NoSupportedTerminals(get_cmd_list())
def spawn(name, sh_cmd, title=None, env=None, d=None):
"""Spawn the specified terminal, by name"""
- logger.debug(1, 'Attempting to spawn terminal "%s"', name)
+ logger.debug('Attempting to spawn terminal "%s"', name)
try:
terminal = Registry.registry[name]
except KeyError:
raise UnsupportedTerminal(name)
- pipe = terminal(sh_cmd, title, env, d)
- output = pipe.communicate()[0]
- if pipe.returncode != 0:
- raise ExecutionError(sh_cmd, pipe.returncode, output)
+ # We need to know when the command completes but some terminals (at least
+ # gnome and tmux) gives us no way to do this. We therefore write the pid
+ # to a file using a "phonehome" wrapper script, then monitor the pid
+ # until it exits.
+ import tempfile
+ import time
+ pidfile = tempfile.NamedTemporaryFile(delete = False).name
+ try:
+ sh_cmd = bb.utils.which(os.getenv('PATH'), "oe-gnome-terminal-phonehome") + " " + pidfile + " " + sh_cmd
+ pipe = terminal(sh_cmd, title, env, d)
+ output = pipe.communicate()[0]
+ if output:
+ output = output.decode("utf-8")
+ if pipe.returncode != 0:
+ raise ExecutionError(sh_cmd, pipe.returncode, output)
+
+ while os.stat(pidfile).st_size <= 0:
+ time.sleep(0.01)
+ continue
+ with open(pidfile, "r") as f:
+ pid = int(f.readline())
+ finally:
+ os.unlink(pidfile)
+
+ while True:
+ try:
+ os.kill(pid, 0)
+ time.sleep(0.1)
+ except OSError:
+ return
+
+def check_tmux_version(desired):
+ vernum = check_terminal_version("tmux")
+ if vernum and bb.utils.vercmp_string_op(vernum, desired, "<"):
+ return False
+ return vernum
def check_tmux_pane_size(tmux):
import subprocess as sub
# On older tmux versions (<1.9), return false. The reason
# is that there is no easy way to get the height of the active panel
# on current window without nested formats (available from version 1.9)
- vernum = check_terminal_version("tmux")
- if vernum and LooseVersion(vernum) < '1.9':
+ if not check_tmux_version('1.9'):
return False
try:
p = sub.Popen('%s list-panes -F "#{?pane_active,#{pane_height},}"' % tmux,
@@ -273,8 +310,12 @@ def check_terminal_version(terminalName):
vernum = ver.split(' ')[-1]
if ver.startswith('GNOME Terminal'):
vernum = ver.split(' ')[-1]
+ if ver.startswith('MATE Terminal'):
+ vernum = ver.split(' ')[-1]
if ver.startswith('tmux'):
vernum = ver.split()[-1]
+ if ver.startswith('tmux next-'):
+ vernum = ver.split()[-1][5:]
return vernum
def distro_name():
diff --git a/meta/lib/oe/tests/test_license.py b/meta/lib/oe/tests/test_license.py
deleted file mode 100644
index c388886184..0000000000
--- a/meta/lib/oe/tests/test_license.py
+++ /dev/null
@@ -1,68 +0,0 @@
-import unittest
-import oe.license
-
-class SeenVisitor(oe.license.LicenseVisitor):
- def __init__(self):
- self.seen = []
- oe.license.LicenseVisitor.__init__(self)
-
- def visit_Str(self, node):
- self.seen.append(node.s)
-
-class TestSingleLicense(unittest.TestCase):
- licenses = [
- "GPLv2",
- "LGPL-2.0",
- "Artistic",
- "MIT",
- "GPLv3+",
- "FOO_BAR",
- ]
- invalid_licenses = ["GPL/BSD"]
-
- @staticmethod
- def parse(licensestr):
- visitor = SeenVisitor()
- visitor.visit_string(licensestr)
- return visitor.seen
-
- def test_single_licenses(self):
- for license in self.licenses:
- licenses = self.parse(license)
- self.assertListEqual(licenses, [license])
-
- def test_invalid_licenses(self):
- for license in self.invalid_licenses:
- with self.assertRaises(oe.license.InvalidLicense) as cm:
- self.parse(license)
- self.assertEqual(cm.exception.license, license)
-
-class TestSimpleCombinations(unittest.TestCase):
- tests = {
- "FOO&BAR": ["FOO", "BAR"],
- "BAZ & MOO": ["BAZ", "MOO"],
- "ALPHA|BETA": ["ALPHA"],
- "BAZ&MOO|FOO": ["FOO"],
- "FOO&BAR|BAZ": ["FOO", "BAR"],
- }
- preferred = ["ALPHA", "FOO", "BAR"]
-
- def test_tests(self):
- def choose(a, b):
- if all(lic in self.preferred for lic in b):
- return b
- else:
- return a
-
- for license, expected in self.tests.items():
- licenses = oe.license.flattened_licenses(license, choose)
- self.assertListEqual(licenses, expected)
-
-class TestComplexCombinations(TestSimpleCombinations):
- tests = {
- "FOO & (BAR | BAZ)&MOO": ["FOO", "BAR", "MOO"],
- "(ALPHA|(BETA&THETA)|OMEGA)&DELTA": ["OMEGA", "DELTA"],
- "((ALPHA|BETA)&FOO)|BAZ": ["BETA", "FOO"],
- "(GPL-2.0|Proprietary)&BSD-4-clause&MIT": ["GPL-2.0", "BSD-4-clause", "MIT"],
- }
- preferred = ["BAR", "OMEGA", "BETA", "GPL-2.0"]
diff --git a/meta/lib/oe/tests/test_utils.py b/meta/lib/oe/tests/test_utils.py
deleted file mode 100644
index 5d9ac52e7d..0000000000
--- a/meta/lib/oe/tests/test_utils.py
+++ /dev/null
@@ -1,51 +0,0 @@
-import unittest
-from oe.utils import packages_filter_out_system
-
-class TestPackagesFilterOutSystem(unittest.TestCase):
- def test_filter(self):
- """
- Test that oe.utils.packages_filter_out_system works.
- """
- try:
- import bb
- except ImportError:
- self.skipTest("Cannot import bb")
-
- d = bb.data_smart.DataSmart()
- d.setVar("PN", "foo")
-
- d.setVar("PACKAGES", "foo foo-doc foo-dev")
- pkgs = packages_filter_out_system(d)
- self.assertEqual(pkgs, [])
-
- d.setVar("PACKAGES", "foo foo-doc foo-data foo-dev")
- pkgs = packages_filter_out_system(d)
- self.assertEqual(pkgs, ["foo-data"])
-
- d.setVar("PACKAGES", "foo foo-locale-en-gb")
- pkgs = packages_filter_out_system(d)
- self.assertEqual(pkgs, [])
-
- d.setVar("PACKAGES", "foo foo-data foo-locale-en-gb")
- pkgs = packages_filter_out_system(d)
- self.assertEqual(pkgs, ["foo-data"])
-
-
-class TestTrimVersion(unittest.TestCase):
- def test_version_exception(self):
- with self.assertRaises(TypeError):
- trim_version(None, 2)
- with self.assertRaises(TypeError):
- trim_version((1, 2, 3), 2)
-
- def test_num_exception(self):
- with self.assertRaises(ValueError):
- trim_version("1.2.3", 0)
- with self.assertRaises(ValueError):
- trim_version("1.2.3", -1)
-
- def test_valid(self):
- self.assertEqual(trim_version("1.2.3", 1), "1")
- self.assertEqual(trim_version("1.2.3", 2), "1.2")
- self.assertEqual(trim_version("1.2.3", 3), "1.2.3")
- self.assertEqual(trim_version("1.2.3", 4), "1.2.3")
diff --git a/meta/lib/oe/types.py b/meta/lib/oe/types.py
index 4ae58acfac..b929afb1f3 100644
--- a/meta/lib/oe/types.py
+++ b/meta/lib/oe/types.py
@@ -1,3 +1,9 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: GPL-2.0-only
+#
+
import errno
import re
import os
@@ -103,8 +109,13 @@ def boolean(value):
"""OpenEmbedded 'boolean' type
Valid values for true: 'yes', 'y', 'true', 't', '1'
- Valid values for false: 'no', 'n', 'false', 'f', '0'
+ Valid values for false: 'no', 'n', 'false', 'f', '0', None
"""
+ if value is None:
+ return False
+
+ if isinstance(value, bool):
+ return value
if not isinstance(value, str):
raise TypeError("boolean accepts a string, not '%s'" % type(value))
@@ -145,9 +156,33 @@ def path(value, relativeto='', normalize='true', mustexist='false'):
if boolean(mustexist):
try:
- open(value, 'r')
+ with open(value, 'r'):
+ pass
except IOError as exc:
if exc.errno == errno.ENOENT:
raise ValueError("{0}: {1}".format(value, os.strerror(errno.ENOENT)))
return value
+
+def is_x86(arch):
+ """
+ Check whether arch is x86 or x86_64
+ """
+ if arch.startswith('x86_') or re.match('i.*86', arch):
+ return True
+ else:
+ return False
+
+def qemu_use_kvm(kvm, target_arch):
+ """
+ Enable kvm if target_arch == build_arch or both of them are x86 archs.
+ """
+
+ use_kvm = False
+ if kvm and boolean(kvm):
+ build_arch = os.uname()[4]
+ if is_x86(build_arch) and is_x86(target_arch):
+ use_kvm = True
+ elif build_arch == target_arch:
+ use_kvm = True
+ return use_kvm
diff --git a/meta/lib/oe/useradd.py b/meta/lib/oe/useradd.py
new file mode 100644
index 0000000000..54aa86feb5
--- /dev/null
+++ b/meta/lib/oe/useradd.py
@@ -0,0 +1,71 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: GPL-2.0-only
+#
+import argparse
+import re
+
+class myArgumentParser(argparse.ArgumentParser):
+ def _print_message(self, message, file=None):
+ bb.warn("%s - %s: %s" % (d.getVar('PN'), pkg, message))
+
+ # This should never be called...
+ def exit(self, status=0, message=None):
+ message = message or ("%s - %s: useradd.bbclass: Argument parsing exited" % (d.getVar('PN'), pkg))
+ error(message)
+
+ def error(self, message):
+ bb.fatal(message)
+
+def split_commands(params):
+ params = re.split('''[ \t]*;[ \t]*(?=(?:[^'"]|'[^']*'|"[^"]*")*$)''', params.strip())
+ # Remove any empty items
+ return [x for x in params if x]
+
+def split_args(params):
+ params = re.split('''[ \t]+(?=(?:[^'"]|'[^']*'|"[^"]*")*$)''', params.strip())
+ # Remove any empty items
+ return [x for x in params if x]
+
+def build_useradd_parser():
+ # The following comes from --help on useradd from shadow
+ parser = myArgumentParser(prog='useradd')
+ parser.add_argument("-b", "--base-dir", metavar="BASE_DIR", help="base directory for the home directory of the new account")
+ parser.add_argument("-c", "--comment", metavar="COMMENT", help="GECOS field of the new account")
+ parser.add_argument("-d", "--home-dir", metavar="HOME_DIR", help="home directory of the new account")
+ parser.add_argument("-D", "--defaults", help="print or change default useradd configuration", action="store_true")
+ parser.add_argument("-e", "--expiredate", metavar="EXPIRE_DATE", help="expiration date of the new account")
+ parser.add_argument("-f", "--inactive", metavar="INACTIVE", help="password inactivity period of the new account")
+ parser.add_argument("-g", "--gid", metavar="GROUP", help="name or ID of the primary group of the new account")
+ parser.add_argument("-G", "--groups", metavar="GROUPS", help="list of supplementary groups of the new account")
+ parser.add_argument("-k", "--skel", metavar="SKEL_DIR", help="use this alternative skeleton directory")
+ parser.add_argument("-K", "--key", metavar="KEY=VALUE", help="override /etc/login.defs defaults")
+ parser.add_argument("-l", "--no-log-init", help="do not add the user to the lastlog and faillog databases", action="store_true")
+ parser.add_argument("-m", "--create-home", help="create the user's home directory", action="store_const", const=True)
+ parser.add_argument("-M", "--no-create-home", dest="create_home", help="do not create the user's home directory", action="store_const", const=False)
+ parser.add_argument("-N", "--no-user-group", dest="user_group", help="do not create a group with the same name as the user", action="store_const", const=False)
+ parser.add_argument("-o", "--non-unique", help="allow to create users with duplicate (non-unique UID)", action="store_true")
+ parser.add_argument("-p", "--password", metavar="PASSWORD", help="encrypted password of the new account")
+ parser.add_argument("-R", "--root", metavar="CHROOT_DIR", help="directory to chroot into")
+ parser.add_argument("-r", "--system", help="create a system account", action="store_true")
+ parser.add_argument("-s", "--shell", metavar="SHELL", help="login shell of the new account")
+ parser.add_argument("-u", "--uid", metavar="UID", help="user ID of the new account")
+ parser.add_argument("-U", "--user-group", help="create a group with the same name as the user", action="store_const", const=True)
+ parser.add_argument("LOGIN", help="Login name of the new user")
+
+ return parser
+
+def build_groupadd_parser():
+ # The following comes from --help on groupadd from shadow
+ parser = myArgumentParser(prog='groupadd')
+ parser.add_argument("-f", "--force", help="exit successfully if the group already exists, and cancel -g if the GID is already used", action="store_true")
+ parser.add_argument("-g", "--gid", metavar="GID", help="use GID for the new group")
+ parser.add_argument("-K", "--key", metavar="KEY=VALUE", help="override /etc/login.defs defaults")
+ parser.add_argument("-o", "--non-unique", help="allow to create groups with duplicate (non-unique) GID", action="store_true")
+ parser.add_argument("-p", "--password", metavar="PASSWORD", help="use this encrypted password for the new group")
+ parser.add_argument("-R", "--root", metavar="CHROOT_DIR", help="directory to chroot into")
+ parser.add_argument("-r", "--system", help="create a system account", action="store_true")
+ parser.add_argument("GROUP", help="Group name of the new group")
+
+ return parser
diff --git a/meta/lib/oe/utils.py b/meta/lib/oe/utils.py
index 19db540779..69ca8987f3 100644
--- a/meta/lib/oe/utils.py
+++ b/meta/lib/oe/utils.py
@@ -1,9 +1,12 @@
-try:
- # Python 2
- import commands as cmdstatus
-except ImportError:
- # Python 3
- import subprocess as cmdstatus
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: GPL-2.0-only
+#
+
+import subprocess
+import multiprocessing
+import traceback
def read_file(filename):
try:
@@ -23,27 +26,34 @@ def ifelse(condition, iftrue = True, iffalse = False):
return iffalse
def conditional(variable, checkvalue, truevalue, falsevalue, d):
- if d.getVar(variable,1) == checkvalue:
+ if d.getVar(variable) == checkvalue:
return truevalue
else:
return falsevalue
+def vartrue(var, iftrue, iffalse, d):
+ import oe.types
+ if oe.types.boolean(d.getVar(var)):
+ return iftrue
+ else:
+ return iffalse
+
def less_or_equal(variable, checkvalue, truevalue, falsevalue, d):
- if float(d.getVar(variable,1)) <= float(checkvalue):
+ if float(d.getVar(variable)) <= float(checkvalue):
return truevalue
else:
return falsevalue
def version_less_or_equal(variable, checkvalue, truevalue, falsevalue, d):
- result = bb.utils.vercmp_string(d.getVar(variable,True), checkvalue)
+ result = bb.utils.vercmp_string(d.getVar(variable), checkvalue)
if result <= 0:
return truevalue
else:
return falsevalue
def both_contain(variable1, variable2, checkvalue, d):
- val1 = d.getVar(variable1, True)
- val2 = d.getVar(variable2, True)
+ val1 = d.getVar(variable1)
+ val2 = d.getVar(variable2)
val1 = set(val1.split())
val2 = set(val2.split())
if isinstance(checkvalue, str):
@@ -66,20 +76,20 @@ def set_intersect(variable1, variable2, d):
s3 = set_intersect(s1, s2)
=> s3 = "b c"
"""
- val1 = set(d.getVar(variable1, True).split())
- val2 = set(d.getVar(variable2, True).split())
+ val1 = set(d.getVar(variable1).split())
+ val2 = set(d.getVar(variable2).split())
return " ".join(val1 & val2)
def prune_suffix(var, suffixes, d):
# See if var ends with any of the suffixes listed and
# remove it if found
for suffix in suffixes:
- if var.endswith(suffix):
- var = var.replace(suffix, "")
+ if suffix and var.endswith(suffix):
+ var = var[:-len(suffix)]
- prefix = d.getVar("MLPREFIX", True)
+ prefix = d.getVar("MLPREFIX")
if prefix and var.startswith(prefix):
- var = var.replace(prefix, "")
+ var = var[len(prefix):]
return var
@@ -91,16 +101,9 @@ def str_filter_out(f, str, d):
from re import match
return " ".join([x for x in str.split() if not match(f, x, 0)])
-def param_bool(cfg, field, dflt = None):
- """Lookup <field> in <cfg> map and convert it to a boolean; take
- <dflt> when this <field> does not exist"""
- value = cfg.get(field, dflt)
- strvalue = str(value).lower()
- if strvalue in ('yes', 'y', 'true', 't', '1'):
- return True
- elif strvalue in ('no', 'n', 'false', 'f', '0'):
- return False
- raise ValueError("invalid value for boolean parameter '%s': '%s'" % (field, value))
+def build_depends_string(depends, task):
+ """Append a taskname to a string of dependencies as used by the [depends] flag"""
+ return " ".join(dep + ":" + task for dep in depends.split())
def inherits(d, *classes):
"""Return True if the metadata inherits any of the specified classes"""
@@ -115,9 +118,9 @@ def features_backfill(var,d):
# disturbing distributions that have already set DISTRO_FEATURES.
# Distributions wanting to elide a value in DISTRO_FEATURES_BACKFILL should
# add the feature to DISTRO_FEATURES_BACKFILL_CONSIDERED
- features = (d.getVar(var, True) or "").split()
- backfill = (d.getVar(var+"_BACKFILL", True) or "").split()
- considered = (d.getVar(var+"_BACKFILL_CONSIDERED", True) or "").split()
+ features = (d.getVar(var) or "").split()
+ backfill = (d.getVar(var+"_BACKFILL") or "").split()
+ considered = (d.getVar(var+"_BACKFILL_CONSIDERED") or "").split()
addfeatures = []
for feature in backfill:
@@ -127,24 +130,110 @@ def features_backfill(var,d):
if addfeatures:
d.appendVar(var, " " + " ".join(addfeatures))
+def all_distro_features(d, features, truevalue="1", falsevalue=""):
+ """
+ Returns truevalue if *all* given features are set in DISTRO_FEATURES,
+ else falsevalue. The features can be given as single string or anything
+ that can be turned into a set.
+
+ This is a shorter, more flexible version of
+ bb.utils.contains("DISTRO_FEATURES", features, truevalue, falsevalue, d).
+
+ Without explicit true/false values it can be used directly where
+ Python expects a boolean:
+ if oe.utils.all_distro_features(d, "foo bar"):
+ bb.fatal("foo and bar are mutually exclusive DISTRO_FEATURES")
+
+ With just a truevalue, it can be used to include files that are meant to be
+ used only when requested via DISTRO_FEATURES:
+ require ${@ oe.utils.all_distro_features(d, "foo bar", "foo-and-bar.inc")
+ """
+ return bb.utils.contains("DISTRO_FEATURES", features, truevalue, falsevalue, d)
+
+def any_distro_features(d, features, truevalue="1", falsevalue=""):
+ """
+ Returns truevalue if at least *one* of the given features is set in DISTRO_FEATURES,
+ else falsevalue. The features can be given as single string or anything
+ that can be turned into a set.
+
+ This is a shorter, more flexible version of
+ bb.utils.contains_any("DISTRO_FEATURES", features, truevalue, falsevalue, d).
+
+ Without explicit true/false values it can be used directly where
+ Python expects a boolean:
+ if not oe.utils.any_distro_features(d, "foo bar"):
+ bb.fatal("foo, bar or both must be set in DISTRO_FEATURES")
+
+ With just a truevalue, it can be used to include files that are meant to be
+ used only when requested via DISTRO_FEATURES:
+ require ${@ oe.utils.any_distro_features(d, "foo bar", "foo-or-bar.inc")
+
+ """
+ return bb.utils.contains_any("DISTRO_FEATURES", features, truevalue, falsevalue, d)
+
+def parallel_make(d, makeinst=False):
+ """
+ Return the integer value for the number of parallel threads to use when
+ building, scraped out of PARALLEL_MAKE. If no parallelization option is
+ found, returns None
+
+ e.g. if PARALLEL_MAKE = "-j 10", this will return 10 as an integer.
+ """
+ if makeinst:
+ pm = (d.getVar('PARALLEL_MAKEINST') or '').split()
+ else:
+ pm = (d.getVar('PARALLEL_MAKE') or '').split()
+ # look for '-j' and throw other options (e.g. '-l') away
+ while pm:
+ opt = pm.pop(0)
+ if opt == '-j':
+ v = pm.pop(0)
+ elif opt.startswith('-j'):
+ v = opt[2:].strip()
+ else:
+ continue
+
+ return int(v)
+
+ return ''
+
+def parallel_make_argument(d, fmt, limit=None, makeinst=False):
+ """
+ Helper utility to construct a parallel make argument from the number of
+ parallel threads specified in PARALLEL_MAKE.
+
+ Returns the input format string `fmt` where a single '%d' will be expanded
+ with the number of parallel threads to use. If `limit` is specified, the
+ number of parallel threads will be no larger than it. If no parallelization
+ option is found in PARALLEL_MAKE, returns an empty string
+
+ e.g. if PARALLEL_MAKE = "-j 10", parallel_make_argument(d, "-n %d") will return
+ "-n 10"
+ """
+ v = parallel_make(d, makeinst)
+ if v:
+ if limit:
+ v = min(limit, v)
+ return fmt % v
+ return ''
def packages_filter_out_system(d):
"""
Return a list of packages from PACKAGES with the "system" packages such as
PN-dbg PN-doc PN-locale-eb-gb removed.
"""
- pn = d.getVar('PN', True)
- blacklist = [pn + suffix for suffix in ('', '-dbg', '-dev', '-doc', '-locale', '-staticdev')]
+ pn = d.getVar('PN')
+ pkgfilter = [pn + suffix for suffix in ('', '-dbg', '-dev', '-doc', '-locale', '-staticdev', '-src')]
localepkg = pn + "-locale-"
pkgs = []
- for pkg in d.getVar('PACKAGES', True).split():
- if pkg not in blacklist and localepkg not in pkg:
+ for pkg in d.getVar('PACKAGES').split():
+ if pkg not in pkgfilter and localepkg not in pkg:
pkgs.append(pkg)
return pkgs
def getstatusoutput(cmd):
- return cmdstatus.getstatusoutput(cmd)
+ return subprocess.getstatusoutput(cmd)
def trim_version(version, num_parts=2):
@@ -161,9 +250,9 @@ def trim_version(version, num_parts=2):
trimmed = ".".join(parts[:num_parts])
return trimmed
-def cpu_count():
- import multiprocessing
- return multiprocessing.cpu_count()
+def cpu_count(at_least=1, at_most=64):
+ cpus = len(os.sched_getaffinity(0))
+ return max(min(cpus, at_most), at_least)
def execute_pre_post_process(d, cmds):
if cmds is None:
@@ -175,40 +264,111 @@ def execute_pre_post_process(d, cmds):
bb.note("Executing %s ..." % cmd)
bb.build.exec_func(cmd, d)
-def multiprocess_exec(commands, function):
- import signal
- import multiprocessing
-
- if not commands:
- return []
-
- def init_worker():
- signal.signal(signal.SIGINT, signal.SIG_IGN)
+# For each item in items, call the function 'target' with item as the first
+# argument, extraargs as the other arguments and handle any exceptions in the
+# parent thread
+def multiprocess_launch(target, items, d, extraargs=None):
- nproc = min(multiprocessing.cpu_count(), len(commands))
- pool = bb.utils.multiprocessingpool(nproc, init_worker)
- imap = pool.imap(function, commands)
+ class ProcessLaunch(multiprocessing.Process):
+ def __init__(self, *args, **kwargs):
+ multiprocessing.Process.__init__(self, *args, **kwargs)
+ self._pconn, self._cconn = multiprocessing.Pipe()
+ self._exception = None
+ self._result = None
- try:
- res = list(imap)
- pool.close()
- pool.join()
- results = []
- for result in res:
- if result is not None:
- results.append(result)
- return results
-
- except KeyboardInterrupt:
- pool.terminate()
- pool.join()
- raise
+ def run(self):
+ try:
+ ret = self._target(*self._args, **self._kwargs)
+ self._cconn.send((None, ret))
+ except Exception as e:
+ tb = traceback.format_exc()
+ self._cconn.send((e, tb))
+
+ def update(self):
+ if self._pconn.poll():
+ (e, tb) = self._pconn.recv()
+ if e is not None:
+ self._exception = (e, tb)
+ else:
+ self._result = tb
+
+ @property
+ def exception(self):
+ self.update()
+ return self._exception
+
+ @property
+ def result(self):
+ self.update()
+ return self._result
+
+ max_process = int(d.getVar("BB_NUMBER_THREADS") or os.cpu_count() or 1)
+ launched = []
+ errors = []
+ results = []
+ items = list(items)
+ while (items and not errors) or launched:
+ if not errors and items and len(launched) < max_process:
+ args = (items.pop(),)
+ if extraargs is not None:
+ args = args + extraargs
+ p = ProcessLaunch(target=target, args=args)
+ p.start()
+ launched.append(p)
+ for q in launched:
+ # Have to manually call update() to avoid deadlocks. The pipe can be full and
+ # transfer stalled until we try and read the results object but the subprocess won't exit
+ # as it still has data to write (https://bugs.python.org/issue8426)
+ q.update()
+ # The finished processes are joined when calling is_alive()
+ if not q.is_alive():
+ if q.exception:
+ errors.append(q.exception)
+ if q.result:
+ results.append(q.result)
+ launched.remove(q)
+ # Paranoia doesn't hurt
+ for p in launched:
+ p.join()
+ if errors:
+ msg = ""
+ for (e, tb) in errors:
+ if isinstance(e, subprocess.CalledProcessError) and e.output:
+ msg = msg + str(e) + "\n"
+ msg = msg + "Subprocess output:"
+ msg = msg + e.output.decode("utf-8", errors="ignore")
+ else:
+ msg = msg + str(e) + ": " + str(tb) + "\n"
+ bb.fatal("Fatal errors occurred in subprocesses:\n%s" % msg)
+ return results
def squashspaces(string):
import re
- return re.sub("\s+", " ", string).strip()
-
-def format_pkg_list(pkg_dict, ret_format=None):
+ return re.sub(r"\s+", " ", string).strip()
+
+def rprovides_map(pkgdata_dir, pkg_dict):
+ # Map file -> pkg provider
+ rprov_map = {}
+
+ for pkg in pkg_dict:
+ path_to_pkgfile = os.path.join(pkgdata_dir, 'runtime-reverse', pkg)
+ if not os.path.isfile(path_to_pkgfile):
+ continue
+ with open(path_to_pkgfile) as f:
+ for line in f:
+ if line.startswith('RPROVIDES') or line.startswith('FILERPROVIDES'):
+ # List all components provided by pkg.
+ # Exclude version strings, i.e. those starting with (
+ provides = [x for x in line.split()[1:] if not x.startswith('(')]
+ for prov in provides:
+ if prov in rprov_map:
+ rprov_map[prov].append(pkg)
+ else:
+ rprov_map[prov] = [pkg]
+
+ return rprov_map
+
+def format_pkg_list(pkg_dict, ret_format=None, pkgdata_dir=None):
output = []
if ret_format == "arch":
@@ -221,91 +381,101 @@ def format_pkg_list(pkg_dict, ret_format=None):
for pkg in sorted(pkg_dict):
output.append("%s %s %s" % (pkg, pkg_dict[pkg]["arch"], pkg_dict[pkg]["ver"]))
elif ret_format == "deps":
+ rprov_map = rprovides_map(pkgdata_dir, pkg_dict)
for pkg in sorted(pkg_dict):
for dep in pkg_dict[pkg]["deps"]:
- output.append("%s|%s" % (pkg, dep))
+ if dep in rprov_map:
+ # There could be multiple providers within the image
+ for pkg_provider in rprov_map[dep]:
+ output.append("%s|%s * %s [RPROVIDES]" % (pkg, pkg_provider, dep))
+ else:
+ output.append("%s|%s" % (pkg, dep))
else:
for pkg in sorted(pkg_dict):
output.append(pkg)
- return '\n'.join(output)
+ output_str = '\n'.join(output)
-#
-# Python 2.7 doesn't have threaded pools (just multiprocessing)
-# so implement a version here
-#
+ if output_str:
+ # make sure last line is newline terminated
+ output_str += '\n'
-from queue import Queue
-from threading import Thread
+ return output_str
-class ThreadedWorker(Thread):
- """Thread executing tasks from a given tasks queue"""
- def __init__(self, tasks, worker_init, worker_end):
- Thread.__init__(self)
- self.tasks = tasks
- self.daemon = True
- self.worker_init = worker_init
- self.worker_end = worker_end
+# Helper function to get the host compiler version
+# Do not assume the compiler is gcc
+def get_host_compiler_version(d, taskcontextonly=False):
+ import re, subprocess
- def run(self):
- from queue import Empty
+ if taskcontextonly and d.getVar('BB_WORKERCONTEXT') != '1':
+ return
- if self.worker_init is not None:
- self.worker_init(self)
+ compiler = d.getVar("BUILD_CC")
+ # Get rid of ccache since it is not present when parsing.
+ if compiler.startswith('ccache '):
+ compiler = compiler[7:]
+ try:
+ env = os.environ.copy()
+ # datastore PATH does not contain session PATH as set by environment-setup-...
+ # this breaks the install-buildtools use-case
+ # env["PATH"] = d.getVar("PATH")
+ output = subprocess.check_output("%s --version" % compiler, \
+ shell=True, env=env, stderr=subprocess.STDOUT).decode("utf-8")
+ except subprocess.CalledProcessError as e:
+ bb.fatal("Error running %s --version: %s" % (compiler, e.output.decode("utf-8")))
- while True:
- try:
- func, args, kargs = self.tasks.get(block=False)
- except Empty:
- if self.worker_end is not None:
- self.worker_end(self)
- break
+ match = re.match(r".* (\d+\.\d+)\.\d+.*", output.split('\n')[0])
+ if not match:
+ bb.fatal("Can't get compiler version from %s --version output" % compiler)
- try:
- func(self, *args, **kargs)
- except Exception as e:
- print(e)
- finally:
- self.tasks.task_done()
-
-class ThreadedPool:
- """Pool of threads consuming tasks from a queue"""
- def __init__(self, num_workers, num_tasks, worker_init=None,
- worker_end=None):
- self.tasks = Queue(num_tasks)
- self.workers = []
-
- for _ in range(num_workers):
- worker = ThreadedWorker(self.tasks, worker_init, worker_end)
- self.workers.append(worker)
-
- def start(self):
- for worker in self.workers:
- worker.start()
-
- def add_task(self, func, *args, **kargs):
- """Add a task to the queue"""
- self.tasks.put((func, args, kargs))
-
- def wait_completion(self):
- """Wait for completion of all the tasks in the queue"""
- self.tasks.join()
- for worker in self.workers:
- worker.join()
-
-def write_ld_so_conf(d):
- # Some utils like prelink may not have the correct target library paths
- # so write an ld.so.conf to help them
- ldsoconf = d.expand("${STAGING_DIR_TARGET}${sysconfdir}/ld.so.conf")
- if os.path.exists(ldsoconf):
- bb.utils.remove(ldsoconf)
- bb.utils.mkdirhier(os.path.dirname(ldsoconf))
- with open(ldsoconf, "w") as f:
- f.write(d.getVar("base_libdir", True) + '\n')
- f.write(d.getVar("libdir", True) + '\n')
-
-class ImageQAFailed(bb.build.FuncFailed):
+ version = match.group(1)
+ return compiler, version
+
+
+def host_gcc_version(d, taskcontextonly=False):
+ import re, subprocess
+
+ if taskcontextonly and d.getVar('BB_WORKERCONTEXT') != '1':
+ return
+
+ compiler = d.getVar("BUILD_CC")
+ # Get rid of ccache since it is not present when parsing.
+ if compiler.startswith('ccache '):
+ compiler = compiler[7:]
+ try:
+ env = os.environ.copy()
+ env["PATH"] = d.getVar("PATH")
+ output = subprocess.check_output("%s --version" % compiler, \
+ shell=True, env=env, stderr=subprocess.STDOUT).decode("utf-8")
+ except subprocess.CalledProcessError as e:
+ bb.fatal("Error running %s --version: %s" % (compiler, e.output.decode("utf-8")))
+
+ match = re.match(r".* (\d+\.\d+)\.\d+.*", output.split('\n')[0])
+ if not match:
+ bb.fatal("Can't get compiler version from %s --version output" % compiler)
+
+ version = match.group(1)
+ return "-%s" % version if version in ("4.8", "4.9") else ""
+
+
+def get_multilib_datastore(variant, d):
+ localdata = bb.data.createCopy(d)
+ if variant:
+ overrides = localdata.getVar("OVERRIDES", False) + ":virtclass-multilib-" + variant
+ localdata.setVar("OVERRIDES", overrides)
+ localdata.setVar("MLPREFIX", variant + "-")
+ else:
+ origdefault = localdata.getVar("DEFAULTTUNE_MULTILIB_ORIGINAL")
+ if origdefault:
+ localdata.setVar("DEFAULTTUNE", origdefault)
+ overrides = localdata.getVar("OVERRIDES", False).split(":")
+ overrides = ":".join([x for x in overrides if not x.startswith("virtclass-multilib-")])
+ localdata.setVar("OVERRIDES", overrides)
+ localdata.setVar("MLPREFIX", "")
+ return localdata
+
+class ImageQAFailed(Exception):
def __init__(self, description, name=None, logfile=None):
self.description = description
self.name = name
@@ -317,3 +487,38 @@ class ImageQAFailed(bb.build.FuncFailed):
msg = msg + ' (%s)' % self.description
return msg
+
+def sh_quote(string):
+ import shlex
+ return shlex.quote(string)
+
+def directory_size(root, blocksize=4096):
+ """
+ Calculate the size of the directory, taking into account hard links,
+ rounding up every size to multiples of the blocksize.
+ """
+ def roundup(size):
+ """
+ Round the size up to the nearest multiple of the block size.
+ """
+ import math
+ return math.ceil(size / blocksize) * blocksize
+
+ def getsize(filename):
+ """
+ Get the size of the filename, not following symlinks, taking into
+ account hard links.
+ """
+ stat = os.lstat(filename)
+ if stat.st_ino not in inodes:
+ inodes.add(stat.st_ino)
+ return stat.st_size
+ else:
+ return 0
+
+ inodes = set()
+ total = 0
+ for root, dirs, files in os.walk(root):
+ total += sum(roundup(getsize(os.path.join(root, name))) for name in files)
+ total += roundup(getsize(root))
+ return total
diff --git a/meta/lib/oeqa/buildperf/__init__.py b/meta/lib/oeqa/buildperf/__init__.py
index ad5b37c543..b7ebd036ae 100644
--- a/meta/lib/oeqa/buildperf/__init__.py
+++ b/meta/lib/oeqa/buildperf/__init__.py
@@ -1,15 +1,13 @@
# Copyright (c) 2016, Intel Corporation.
#
-# This program is free software; you can redistribute it and/or modify it
-# under the terms and conditions of the GNU General Public License,
-# version 2, as published by the Free Software Foundation.
#
-# This program is distributed in the hope 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.
+# SPDX-License-Identifier: GPL-2.0-only
#
"""Build performance tests"""
-from .base import (perf_test_case, BuildPerfTest, BuildPerfTestRunner,
- KernelDropCaches)
-from .basic_tests import *
+from .base import (BuildPerfTestCase,
+ BuildPerfTestLoader,
+ BuildPerfTestResult,
+ BuildPerfTestRunner,
+ KernelDropCaches,
+ runCmd2)
+from .test_basic import *
diff --git a/meta/lib/oeqa/buildperf/base.py b/meta/lib/oeqa/buildperf/base.py
index 527563bb0b..5d656c781a 100644
--- a/meta/lib/oeqa/buildperf/base.py
+++ b/meta/lib/oeqa/buildperf/base.py
@@ -1,32 +1,36 @@
# Copyright (c) 2016, Intel Corporation.
#
-# This program is free software; you can redistribute it and/or modify it
-# under the terms and conditions of the GNU General Public License,
-# version 2, as published by the Free Software Foundation.
-#
-# This program is distributed in the hope 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.
+# SPDX-License-Identifier: GPL-2.0-only
#
"""Build performance test base classes and functionality"""
-import glob
+import json
import logging
import os
import re
-import shutil
+import resource
import socket
-import tempfile
+import shutil
import time
-import traceback
+import unittest
+import xml.etree.ElementTree as ET
+from collections import OrderedDict
from datetime import datetime, timedelta
+from functools import partial
+from multiprocessing import Process
+from multiprocessing import SimpleQueue
+from xml.dom import minidom
-from oeqa.utils.commands import runCmd, get_bb_vars
+import oe.path
+from oeqa.utils.commands import CommandError, runCmd, get_bb_vars
from oeqa.utils.git import GitError, GitRepo
# Get logger for this module
log = logging.getLogger('build-perf')
+# Our own version of runCmd which does not raise AssertErrors which would cause
+# errors to interpreted as failures
+runCmd2 = partial(runCmd, assert_error=False, limit_exc_output=40)
+
class KernelDropCaches(object):
"""Container of the functions for dropping kernel caches"""
@@ -38,7 +42,7 @@ class KernelDropCaches(object):
from getpass import getpass
from locale import getdefaultlocale
cmd = ['sudo', '-k', '-n', 'tee', '/proc/sys/vm/drop_caches']
- ret = runCmd(cmd, ignore_status=True, data=b'0')
+ ret = runCmd2(cmd, ignore_status=True, data=b'0')
if ret.output.startswith('sudo:'):
pass_str = getpass(
"\nThe script requires sudo access to drop caches between "
@@ -58,273 +62,443 @@ class KernelDropCaches(object):
input_data = b''
cmd += ['tee', '/proc/sys/vm/drop_caches']
input_data += b'3'
- runCmd(cmd, data=input_data)
+ runCmd2(cmd, data=input_data)
+
+def str_to_fn(string):
+ """Convert string to a sanitized filename"""
+ return re.sub(r'(\W+)', '-', string, flags=re.LOCALE)
-def time_cmd(cmd, **kwargs):
- """TIme a command"""
- with tempfile.NamedTemporaryFile(mode='w+') as tmpf:
- timecmd = ['/usr/bin/time', '-v', '-o', tmpf.name]
- if isinstance(cmd, str):
- timecmd = ' '.join(timecmd) + ' '
- timecmd += cmd
- # TODO: 'ignore_status' could/should be removed when globalres.log is
- # deprecated. The function would just raise an exception, instead
- ret = runCmd(timecmd, ignore_status=True, **kwargs)
- timedata = tmpf.file.read()
- return ret, timedata
+class ResultsJsonEncoder(json.JSONEncoder):
+ """Extended encoder for build perf test results"""
+ unix_epoch = datetime.utcfromtimestamp(0)
-class BuildPerfTestRunner(object):
+ def default(self, obj):
+ """Encoder for our types"""
+ if isinstance(obj, datetime):
+ # NOTE: we assume that all timestamps are in UTC time
+ return (obj - self.unix_epoch).total_seconds()
+ if isinstance(obj, timedelta):
+ return obj.total_seconds()
+ return json.JSONEncoder.default(self, obj)
+
+
+class BuildPerfTestResult(unittest.TextTestResult):
"""Runner class for executing the individual tests"""
# List of test cases to run
test_run_queue = []
- def __init__(self, out_dir):
- self.results = {}
- self.out_dir = os.path.abspath(out_dir)
- if not os.path.exists(self.out_dir):
- os.makedirs(self.out_dir)
+ def __init__(self, out_dir, *args, **kwargs):
+ super(BuildPerfTestResult, self).__init__(*args, **kwargs)
- # Get Git parameters
- try:
- self.repo = GitRepo('.')
- except GitError:
- self.repo = None
- self.git_rev, self.git_branch = self.get_git_revision()
- log.info("Using Git branch:revision %s:%s", self.git_branch,
- self.git_rev)
-
- def get_git_revision(self):
- """Get git branch and revision under testing"""
- rev = os.getenv('OE_BUILDPERFTEST_GIT_REVISION')
- branch = os.getenv('OE_BUILDPERFTEST_GIT_BRANCH')
- if not self.repo and (not rev or not branch):
- log.info("The current working directory doesn't seem to be a Git "
- "repository clone. You can specify branch and revision "
- "used in test results with OE_BUILDPERFTEST_GIT_REVISION "
- "and OE_BUILDPERFTEST_GIT_BRANCH environment variables")
- else:
- if not rev:
- rev = self.repo.run_cmd(['rev-parse', 'HEAD'])
- if not branch:
- try:
- # Strip 11 chars, i.e. 'refs/heads' from the beginning
- branch = self.repo.run_cmd(['symbolic-ref', 'HEAD'])[11:]
- except GitError:
- log.debug('Currently on detached HEAD')
- branch = None
- return str(rev), str(branch)
-
- def run_tests(self):
- """Method that actually runs the tests"""
- self.results['schema_version'] = 1
- self.results['git_revision'] = self.git_rev
- self.results['git_branch'] = self.git_branch
- self.results['tester_host'] = socket.gethostname()
- start_time = datetime.utcnow()
- self.results['start_time'] = start_time
- self.results['tests'] = {}
-
- self.archive_build_conf()
- for test_class in self.test_run_queue:
- log.info("Executing test %s: %s", test_class.name,
- test_class.description)
-
- test = test_class(self.out_dir)
- try:
- test.run()
- except Exception:
- # Catch all exceptions. This way e.g buggy tests won't scrap
- # the whole test run
- sep = '-' * 5 + ' TRACEBACK ' + '-' * 60 + '\n'
- tb_msg = sep + traceback.format_exc() + sep
- log.error("Test execution failed with:\n" + tb_msg)
- self.results['tests'][test.name] = test.results
-
- self.results['elapsed_time'] = datetime.utcnow() - start_time
- return 0
-
- def archive_build_conf(self):
- """Archive build/conf to test results"""
- src_dir = os.path.join(os.environ['BUILDDIR'], 'conf')
- tgt_dir = os.path.join(self.out_dir, 'build', 'conf')
- os.makedirs(os.path.dirname(tgt_dir))
- shutil.copytree(src_dir, tgt_dir)
-
- def update_globalres_file(self, filename):
- """Write results to globalres csv file"""
- if self.repo:
- git_tag_rev = self.repo.run_cmd(['describe', self.git_rev])
- else:
- git_tag_rev = self.git_rev
- times = []
- sizes = []
- for test in self.results['tests'].values():
- for measurement in test['measurements']:
- res_type = measurement['type']
- values = measurement['values']
- if res_type == BuildPerfTest.SYSRES:
- e_sec = values['elapsed_time'].total_seconds()
- times.append('{:d}:{:02d}:{:.2f}'.format(
- int(e_sec / 3600),
- int((e_sec % 3600) / 60),
- e_sec % 60))
- elif res_type == BuildPerfTest.DISKUSAGE:
- sizes.append(str(values['size']))
+ self.out_dir = out_dir
+ self.hostname = socket.gethostname()
+ self.product = os.getenv('OE_BUILDPERFTEST_PRODUCT', 'oe-core')
+ self.start_time = self.elapsed_time = None
+ self.successes = []
+
+ def addSuccess(self, test):
+ """Record results from successful tests"""
+ super(BuildPerfTestResult, self).addSuccess(test)
+ self.successes.append(test)
+
+ def addError(self, test, err):
+ """Record results from crashed test"""
+ test.err = err
+ super(BuildPerfTestResult, self).addError(test, err)
+
+ def addFailure(self, test, err):
+ """Record results from failed test"""
+ test.err = err
+ super(BuildPerfTestResult, self).addFailure(test, err)
+
+ def addExpectedFailure(self, test, err):
+ """Record results from expectedly failed test"""
+ test.err = err
+ super(BuildPerfTestResult, self).addExpectedFailure(test, err)
+
+ def startTest(self, test):
+ """Pre-test hook"""
+ test.base_dir = self.out_dir
+ log.info("Executing test %s: %s", test.name, test.shortDescription())
+ self.stream.write(datetime.now().strftime("[%Y-%m-%d %H:%M:%S] "))
+ super(BuildPerfTestResult, self).startTest(test)
+
+ def startTestRun(self):
+ """Pre-run hook"""
+ self.start_time = datetime.utcnow()
+
+ def stopTestRun(self):
+ """Pre-run hook"""
+ self.elapsed_time = datetime.utcnow() - self.start_time
+
+ def all_results(self):
+ compound = [('SUCCESS', t, None) for t in self.successes] + \
+ [('FAILURE', t, m) for t, m in self.failures] + \
+ [('ERROR', t, m) for t, m in self.errors] + \
+ [('EXPECTED_FAILURE', t, m) for t, m in self.expectedFailures] + \
+ [('UNEXPECTED_SUCCESS', t, None) for t in self.unexpectedSuccesses] + \
+ [('SKIPPED', t, m) for t, m in self.skipped]
+ return sorted(compound, key=lambda info: info[1].start_time)
+
+
+ def write_buildstats_json(self):
+ """Write buildstats file"""
+ buildstats = OrderedDict()
+ for _, test, _ in self.all_results():
+ for key, val in test.buildstats.items():
+ buildstats[test.name + '.' + key] = val
+ with open(os.path.join(self.out_dir, 'buildstats.json'), 'w') as fobj:
+ json.dump(buildstats, fobj, cls=ResultsJsonEncoder)
+
+
+ def write_results_json(self):
+ """Write test results into a json-formatted file"""
+ results = OrderedDict([('tester_host', self.hostname),
+ ('start_time', self.start_time),
+ ('elapsed_time', self.elapsed_time),
+ ('tests', OrderedDict())])
+
+ for status, test, reason in self.all_results():
+ test_result = OrderedDict([('name', test.name),
+ ('description', test.shortDescription()),
+ ('status', status),
+ ('start_time', test.start_time),
+ ('elapsed_time', test.elapsed_time),
+ ('measurements', test.measurements)])
+ if status in ('ERROR', 'FAILURE', 'EXPECTED_FAILURE'):
+ test_result['message'] = str(test.err[1])
+ test_result['err_type'] = test.err[0].__name__
+ test_result['err_output'] = reason
+ elif reason:
+ test_result['message'] = reason
+
+ results['tests'][test.name] = test_result
+
+ with open(os.path.join(self.out_dir, 'results.json'), 'w') as fobj:
+ json.dump(results, fobj, indent=4,
+ cls=ResultsJsonEncoder)
+
+ def write_results_xml(self):
+ """Write test results into a JUnit XML file"""
+ top = ET.Element('testsuites')
+ suite = ET.SubElement(top, 'testsuite')
+ suite.set('name', 'oeqa.buildperf')
+ suite.set('timestamp', self.start_time.isoformat())
+ suite.set('time', str(self.elapsed_time.total_seconds()))
+ suite.set('hostname', self.hostname)
+ suite.set('failures', str(len(self.failures) + len(self.expectedFailures)))
+ suite.set('errors', str(len(self.errors)))
+ suite.set('skipped', str(len(self.skipped)))
+
+ test_cnt = 0
+ for status, test, reason in self.all_results():
+ test_cnt += 1
+ testcase = ET.SubElement(suite, 'testcase')
+ testcase.set('classname', test.__module__ + '.' + test.__class__.__name__)
+ testcase.set('name', test.name)
+ testcase.set('description', test.shortDescription())
+ testcase.set('timestamp', test.start_time.isoformat())
+ testcase.set('time', str(test.elapsed_time.total_seconds()))
+ if status in ('ERROR', 'FAILURE', 'EXP_FAILURE'):
+ if status in ('FAILURE', 'EXP_FAILURE'):
+ result = ET.SubElement(testcase, 'failure')
else:
- log.warning("Unable to handle '%s' values in "
- "globalres.log", res_type)
-
- log.debug("Writing globalres log to %s", filename)
- with open(filename, 'a') as fobj:
- fobj.write('{},{}:{},{},'.format(self.results['tester_host'],
- self.results['git_branch'],
- self.results['git_revision'],
- git_tag_rev))
- fobj.write(','.join(times + sizes) + '\n')
+ result = ET.SubElement(testcase, 'error')
+ result.set('message', str(test.err[1]))
+ result.set('type', test.err[0].__name__)
+ result.text = reason
+ elif status == 'SKIPPED':
+ result = ET.SubElement(testcase, 'skipped')
+ result.text = reason
+ elif status not in ('SUCCESS', 'UNEXPECTED_SUCCESS'):
+ raise TypeError("BUG: invalid test status '%s'" % status)
+
+ for data in test.measurements.values():
+ measurement = ET.SubElement(testcase, data['type'])
+ measurement.set('name', data['name'])
+ measurement.set('legend', data['legend'])
+ vals = data['values']
+ if data['type'] == BuildPerfTestCase.SYSRES:
+ ET.SubElement(measurement, 'time',
+ timestamp=vals['start_time'].isoformat()).text = \
+ str(vals['elapsed_time'].total_seconds())
+ attrib = dict((k, str(v)) for k, v in vals['iostat'].items())
+ ET.SubElement(measurement, 'iostat', attrib=attrib)
+ attrib = dict((k, str(v)) for k, v in vals['rusage'].items())
+ ET.SubElement(measurement, 'rusage', attrib=attrib)
+ elif data['type'] == BuildPerfTestCase.DISKUSAGE:
+ ET.SubElement(measurement, 'size').text = str(vals['size'])
+ else:
+ raise TypeError('BUG: unsupported measurement type')
+ suite.set('tests', str(test_cnt))
-def perf_test_case(obj):
- """Decorator for adding test classes"""
- BuildPerfTestRunner.test_run_queue.append(obj)
- return obj
+ # Use minidom for pretty-printing
+ dom_doc = minidom.parseString(ET.tostring(top, 'utf-8'))
+ with open(os.path.join(self.out_dir, 'results.xml'), 'w') as fobj:
+ dom_doc.writexml(fobj, addindent=' ', newl='\n', encoding='utf-8')
-class BuildPerfTest(object):
+class BuildPerfTestCase(unittest.TestCase):
"""Base class for build performance tests"""
SYSRES = 'sysres'
DISKUSAGE = 'diskusage'
-
- name = None
- description = None
-
- def __init__(self, out_dir):
- self.out_dir = out_dir
- self.results = {'name':self.name,
- 'description': self.description,
- 'status': 'NOTRUN',
- 'start_time': None,
- 'elapsed_time': None,
- 'measurements': []}
- if not os.path.exists(self.out_dir):
- os.makedirs(self.out_dir)
- if not self.name:
- self.name = self.__class__.__name__
+ build_target = None
+
+ def __init__(self, *args, **kwargs):
+ super(BuildPerfTestCase, self).__init__(*args, **kwargs)
+ self.name = self._testMethodName
+ self.base_dir = None
+ self.start_time = None
+ self.elapsed_time = None
+ self.measurements = OrderedDict()
+ self.buildstats = OrderedDict()
+ # self.err is supposed to be a tuple from sys.exc_info()
+ self.err = None
self.bb_vars = get_bb_vars()
- # TODO: remove the _failed flag when globalres.log is ditched as all
- # failures should raise an exception
- self._failed = False
- self.cmd_log = os.path.join(self.out_dir, 'commands.log')
-
- def run(self):
+ # TODO: remove 'times' and 'sizes' arrays when globalres support is
+ # removed
+ self.times = []
+ self.sizes = []
+
+ @property
+ def tmp_dir(self):
+ return os.path.join(self.base_dir, self.name + '.tmp')
+
+ def shortDescription(self):
+ return super(BuildPerfTestCase, self).shortDescription() or ""
+
+ def setUp(self):
+ """Set-up fixture for each test"""
+ if not os.path.isdir(self.tmp_dir):
+ os.mkdir(self.tmp_dir)
+ if self.build_target:
+ self.run_cmd(['bitbake', self.build_target, '--runall=fetch'])
+
+ def tearDown(self):
+ """Tear-down fixture for each test"""
+ if os.path.isdir(self.tmp_dir):
+ shutil.rmtree(self.tmp_dir)
+
+ def run(self, *args, **kwargs):
"""Run test"""
- self.results['status'] = 'FAILED'
- self.results['start_time'] = datetime.now()
- self._run()
- self.results['elapsed_time'] = (datetime.now() -
- self.results['start_time'])
- # Test is regarded as completed if it doesn't raise an exception
- if not self._failed:
- self.results['status'] = 'COMPLETED'
-
- def _run(self):
- """Actual test payload"""
- raise NotImplementedError
-
- def log_cmd_output(self, cmd):
- """Run a command and log it's output"""
- with open(self.cmd_log, 'a') as fobj:
- runCmd(cmd, stdout=fobj)
-
- def measure_cmd_resources(self, cmd, name, legend):
+ self.start_time = datetime.now()
+ super(BuildPerfTestCase, self).run(*args, **kwargs)
+ self.elapsed_time = datetime.now() - self.start_time
+
+ def run_cmd(self, cmd):
+ """Convenience method for running a command"""
+ cmd_str = cmd if isinstance(cmd, str) else ' '.join(cmd)
+ log.info("Logging command: %s", cmd_str)
+ try:
+ runCmd2(cmd)
+ except CommandError as err:
+ log.error("Command failed: %s", err.retcode)
+ raise
+
+ def _append_measurement(self, measurement):
+ """Simple helper for adding measurements results"""
+ if measurement['name'] in self.measurements:
+ raise ValueError('BUG: two measurements with the same name in {}'.format(
+ self.__class__.__name__))
+ self.measurements[measurement['name']] = measurement
+
+ def measure_cmd_resources(self, cmd, name, legend, save_bs=False):
"""Measure system resource usage of a command"""
- def str_time_to_timedelta(strtime):
- """Convert time strig from the time utility to timedelta"""
- split = strtime.split(':')
- hours = int(split[0]) if len(split) > 2 else 0
- mins = int(split[-2])
- secs, frac = split[-1].split('.')
- secs = int(secs)
- microsecs = int(float('0.' + frac) * pow(10, 6))
- return timedelta(0, hours*3600 + mins*60 + secs, microsecs)
+ def _worker(data_q, cmd, **kwargs):
+ """Worker process for measuring resources"""
+ try:
+ start_time = datetime.now()
+ ret = runCmd2(cmd, **kwargs)
+ etime = datetime.now() - start_time
+ rusage_struct = resource.getrusage(resource.RUSAGE_CHILDREN)
+ iostat = OrderedDict()
+ with open('/proc/{}/io'.format(os.getpid())) as fobj:
+ for line in fobj.readlines():
+ key, val = line.split(':')
+ iostat[key] = int(val)
+ rusage = OrderedDict()
+ # Skip unused fields, (i.e. 'ru_ixrss', 'ru_idrss', 'ru_isrss',
+ # 'ru_nswap', 'ru_msgsnd', 'ru_msgrcv' and 'ru_nsignals')
+ for key in ['ru_utime', 'ru_stime', 'ru_maxrss', 'ru_minflt',
+ 'ru_majflt', 'ru_inblock', 'ru_oublock',
+ 'ru_nvcsw', 'ru_nivcsw']:
+ rusage[key] = getattr(rusage_struct, key)
+ data_q.put({'ret': ret,
+ 'start_time': start_time,
+ 'elapsed_time': etime,
+ 'rusage': rusage,
+ 'iostat': iostat})
+ except Exception as err:
+ data_q.put(err)
cmd_str = cmd if isinstance(cmd, str) else ' '.join(cmd)
log.info("Timing command: %s", cmd_str)
- with open(self.cmd_log, 'a') as fobj:
- ret, timedata = time_cmd(cmd, stdout=fobj)
- if ret.status:
- log.error("Time will be reported as 0. Command failed: %s",
- ret.status)
- etime = timedelta(0)
- self._failed = True
- else:
- match = re.search(r'.*wall clock.*: (?P<etime>.*)\n', timedata)
- etime = str_time_to_timedelta(match.group('etime'))
-
- measurement = {'type': self.SYSRES,
- 'name': name,
- 'legend': legend}
- measurement['values'] = {'elapsed_time': etime}
- self.results['measurements'].append(measurement)
- nlogs = len(glob.glob(self.out_dir + '/results.log*'))
- results_log = os.path.join(self.out_dir,
- 'results.log.{}'.format(nlogs + 1))
- with open(results_log, 'w') as fobj:
- fobj.write(timedata)
-
- def measure_disk_usage(self, path, name, legend):
+ data_q = SimpleQueue()
+ try:
+ proc = Process(target=_worker, args=(data_q, cmd,))
+ proc.start()
+ data = data_q.get()
+ proc.join()
+ if isinstance(data, Exception):
+ raise data
+ except CommandError:
+ log.error("Command '%s' failed", cmd_str)
+ raise
+ etime = data['elapsed_time']
+
+ measurement = OrderedDict([('type', self.SYSRES),
+ ('name', name),
+ ('legend', legend)])
+ measurement['values'] = OrderedDict([('start_time', data['start_time']),
+ ('elapsed_time', etime),
+ ('rusage', data['rusage']),
+ ('iostat', data['iostat'])])
+ if save_bs:
+ self.save_buildstats(name)
+
+ self._append_measurement(measurement)
+
+ # Append to 'times' array for globalres log
+ e_sec = etime.total_seconds()
+ self.times.append('{:d}:{:02d}:{:05.2f}'.format(int(e_sec / 3600),
+ int((e_sec % 3600) / 60),
+ e_sec % 60))
+
+ def measure_disk_usage(self, path, name, legend, apparent_size=False):
"""Estimate disk usage of a file or directory"""
- # TODO: 'ignore_status' could/should be removed when globalres.log is
- # deprecated. The function would just raise an exception, instead
- ret = runCmd(['du', '-s', path], ignore_status=True)
- if ret.status:
- log.error("du failed, disk usage will be reported as 0")
- size = 0
- self._failed = True
- else:
- size = int(ret.output.split()[0])
- log.debug("Size of %s path is %s", path, size)
- measurement = {'type': self.DISKUSAGE,
- 'name': name,
- 'legend': legend}
- measurement['values'] = {'size': size}
- self.results['measurements'].append(measurement)
-
- def save_buildstats(self):
+ cmd = ['du', '-s', '--block-size', '1024']
+ if apparent_size:
+ cmd.append('--apparent-size')
+ cmd.append(path)
+
+ ret = runCmd2(cmd)
+ size = int(ret.output.split()[0])
+ log.debug("Size of %s path is %s", path, size)
+ measurement = OrderedDict([('type', self.DISKUSAGE),
+ ('name', name),
+ ('legend', legend)])
+ measurement['values'] = OrderedDict([('size', size)])
+ self._append_measurement(measurement)
+ # Append to 'sizes' array for globalres log
+ self.sizes.append(str(size))
+
+ def save_buildstats(self, measurement_name):
"""Save buildstats"""
- shutil.move(self.bb_vars['BUILDSTATS_BASE'],
- os.path.join(self.out_dir, 'buildstats-' + self.name))
-
- @staticmethod
- def force_rm(path):
- """Equivalent of 'rm -rf'"""
- if os.path.isfile(path) or os.path.islink(path):
- os.unlink(path)
- elif os.path.isdir(path):
- shutil.rmtree(path)
+ def split_nevr(nevr):
+ """Split name and version information from recipe "nevr" string"""
+ n_e_v, revision = nevr.rsplit('-', 1)
+ match = re.match(r'^(?P<name>\S+)-((?P<epoch>[0-9]{1,5})_)?(?P<version>[0-9]\S*)$',
+ n_e_v)
+ if not match:
+ # If we're not able to parse a version starting with a number, just
+ # take the part after last dash
+ match = re.match(r'^(?P<name>\S+)-((?P<epoch>[0-9]{1,5})_)?(?P<version>[^-]+)$',
+ n_e_v)
+ name = match.group('name')
+ version = match.group('version')
+ epoch = match.group('epoch')
+ return name, epoch, version, revision
+
+ def bs_to_json(filename):
+ """Convert (task) buildstats file into json format"""
+ bs_json = OrderedDict()
+ iostat = OrderedDict()
+ rusage = OrderedDict()
+ with open(filename) as fobj:
+ for line in fobj.readlines():
+ key, val = line.split(':', 1)
+ val = val.strip()
+ if key == 'Started':
+ start_time = datetime.utcfromtimestamp(float(val))
+ bs_json['start_time'] = start_time
+ elif key == 'Ended':
+ end_time = datetime.utcfromtimestamp(float(val))
+ elif key.startswith('IO '):
+ split = key.split()
+ iostat[split[1]] = int(val)
+ elif key.find('rusage') >= 0:
+ split = key.split()
+ ru_key = split[-1]
+ if ru_key in ('ru_stime', 'ru_utime'):
+ val = float(val)
+ else:
+ val = int(val)
+ rusage[ru_key] = rusage.get(ru_key, 0) + val
+ elif key == 'Status':
+ bs_json['status'] = val
+ bs_json['elapsed_time'] = end_time - start_time
+ bs_json['rusage'] = rusage
+ bs_json['iostat'] = iostat
+ return bs_json
+
+ log.info('Saving buildstats in JSON format')
+ bs_dirs = sorted(os.listdir(self.bb_vars['BUILDSTATS_BASE']))
+ if len(bs_dirs) > 1:
+ log.warning("Multiple buildstats found for test %s, only "
+ "archiving the last one", self.name)
+ bs_dir = os.path.join(self.bb_vars['BUILDSTATS_BASE'], bs_dirs[-1])
+
+ buildstats = []
+ for fname in os.listdir(bs_dir):
+ recipe_dir = os.path.join(bs_dir, fname)
+ if not os.path.isdir(recipe_dir) or fname == "reduced_proc_pressure":
+ continue
+ name, epoch, version, revision = split_nevr(fname)
+ recipe_bs = OrderedDict((('name', name),
+ ('epoch', epoch),
+ ('version', version),
+ ('revision', revision),
+ ('tasks', OrderedDict())))
+ for task in os.listdir(recipe_dir):
+ recipe_bs['tasks'][task] = bs_to_json(os.path.join(recipe_dir,
+ task))
+ buildstats.append(recipe_bs)
+
+ self.buildstats[measurement_name] = buildstats
def rm_tmp(self):
"""Cleanup temporary/intermediate files and directories"""
log.debug("Removing temporary and cache files")
- for name in ['bitbake.lock', 'conf/sanity_info',
+ for name in ['bitbake.lock', 'cache/sanity_info',
self.bb_vars['TMPDIR']]:
- self.force_rm(name)
+ oe.path.remove(name, recurse=True)
def rm_sstate(self):
"""Remove sstate directory"""
log.debug("Removing sstate-cache")
- self.force_rm(self.bb_vars['SSTATE_DIR'])
+ oe.path.remove(self.bb_vars['SSTATE_DIR'], recurse=True)
def rm_cache(self):
"""Drop bitbake caches"""
- self.force_rm(self.bb_vars['PERSISTENT_DIR'])
+ oe.path.remove(self.bb_vars['PERSISTENT_DIR'], recurse=True)
@staticmethod
def sync():
"""Sync and drop kernel caches"""
+ runCmd2('bitbake -m', ignore_status=True)
log.debug("Syncing and dropping kernel caches""")
KernelDropCaches.drop()
os.sync()
# Wait a bit for all the dirty blocks to be written onto disk
time.sleep(3)
+
+
+class BuildPerfTestLoader(unittest.TestLoader):
+ """Test loader for build performance tests"""
+ sortTestMethodsUsing = None
+
+
+class BuildPerfTestRunner(unittest.TextTestRunner):
+ """Test loader for build performance tests"""
+ sortTestMethodsUsing = None
+
+ def __init__(self, out_dir, *args, **kwargs):
+ super(BuildPerfTestRunner, self).__init__(*args, **kwargs)
+ self.out_dir = out_dir
+
+ def _makeResult(self):
+ return BuildPerfTestResult(self.out_dir, self.stream, self.descriptions,
+ self.verbosity)
diff --git a/meta/lib/oeqa/buildperf/basic_tests.py b/meta/lib/oeqa/buildperf/basic_tests.py
deleted file mode 100644
index ada5aba053..0000000000
--- a/meta/lib/oeqa/buildperf/basic_tests.py
+++ /dev/null
@@ -1,133 +0,0 @@
-# Copyright (c) 2016, Intel Corporation.
-#
-# This program is free software; you can redistribute it and/or modify it
-# under the terms and conditions of the GNU General Public License,
-# version 2, as published by the Free Software Foundation.
-#
-# This program is distributed in the hope 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.
-#
-"""Basic set of build performance tests"""
-import os
-import shutil
-
-from . import BuildPerfTest, perf_test_case
-from oeqa.utils.commands import get_bb_vars
-
-
-@perf_test_case
-class Test1P1(BuildPerfTest):
- name = "test1"
- build_target = 'core-image-sato'
- description = "Measure wall clock of bitbake {} and size of tmp dir".format(build_target)
-
- def _run(self):
- self.log_cmd_output("bitbake {} -c fetchall".format(self.build_target))
- self.rm_tmp()
- self.rm_sstate()
- self.rm_cache()
- self.sync()
- self.measure_cmd_resources(['bitbake', self.build_target], 'build',
- 'bitbake ' + self.build_target)
- self.measure_disk_usage(self.bb_vars['TMPDIR'], 'tmpdir', 'tmpdir')
- self.save_buildstats()
-
-
-@perf_test_case
-class Test1P2(BuildPerfTest):
- name = "test12"
- build_target = 'virtual/kernel'
- description = "Measure bitbake {}".format(build_target)
-
- def _run(self):
- self.log_cmd_output("bitbake {} -c cleansstate".format(
- self.build_target))
- self.sync()
- self.measure_cmd_resources(['bitbake', self.build_target], 'build',
- 'bitbake ' + self.build_target)
-
-
-@perf_test_case
-class Test1P3(BuildPerfTest):
- name = "test13"
- build_target = 'core-image-sato'
- description = "Build {} with rm_work enabled".format(build_target)
-
- def _run(self):
- postfile = os.path.join(self.out_dir, 'postfile.conf')
- with open(postfile, 'w') as fobj:
- fobj.write('INHERIT += "rm_work"\n')
- try:
- self.rm_tmp()
- self.rm_sstate()
- self.rm_cache()
- self.sync()
- cmd = ['bitbake', '-R', postfile, self.build_target]
- self.measure_cmd_resources(cmd, 'build',
- 'bitbake' + self.build_target)
- self.measure_disk_usage(self.bb_vars['TMPDIR'], 'tmpdir', 'tmpdir')
- finally:
- os.unlink(postfile)
- self.save_buildstats()
-
-
-@perf_test_case
-class Test2(BuildPerfTest):
- name = "test2"
- build_target = 'core-image-sato'
- description = "Measure bitbake {} -c rootfs with sstate".format(build_target)
-
- def _run(self):
- self.rm_tmp()
- self.rm_cache()
- self.sync()
- cmd = ['bitbake', self.build_target, '-c', 'rootfs']
- self.measure_cmd_resources(cmd, 'do_rootfs', 'bitbake do_rootfs')
-
-
-@perf_test_case
-class Test3(BuildPerfTest):
- name = "test3"
- description = "Parsing time metrics (bitbake -p)"
-
- def _run(self):
- # Drop all caches and parse
- self.rm_cache()
- self.force_rm(os.path.join(self.bb_vars['TMPDIR'], 'cache'))
- self.measure_cmd_resources(['bitbake', '-p'], 'parse_1',
- 'bitbake -p (no caches)')
- # Drop tmp/cache
- self.force_rm(os.path.join(self.bb_vars['TMPDIR'], 'cache'))
- self.measure_cmd_resources(['bitbake', '-p'], 'parse_2',
- 'bitbake -p (no tmp/cache)')
- # Parse with fully cached data
- self.measure_cmd_resources(['bitbake', '-p'], 'parse_3',
- 'bitbake -p (cached)')
-
-
-@perf_test_case
-class Test4(BuildPerfTest):
- name = "test4"
- build_target = 'core-image-sato'
- description = "eSDK metrics"
-
- def _run(self):
- self.log_cmd_output("bitbake {} -c do_populate_sdk_ext".format(
- self.build_target))
- self.bb_vars = get_bb_vars(None, self.build_target)
- tmp_dir = self.bb_vars['TMPDIR']
- installer = os.path.join(
- self.bb_vars['SDK_DEPLOY'],
- self.bb_vars['TOOLCHAINEXT_OUTPUTNAME'] + '.sh')
- # Measure installer size
- self.measure_disk_usage(installer, 'installer_bin', 'eSDK installer')
- # Measure deployment time and deployed size
- deploy_dir = os.path.join(tmp_dir, 'esdk-deploy')
- if os.path.exists(deploy_dir):
- shutil.rmtree(deploy_dir)
- self.sync()
- self.measure_cmd_resources([installer, '-y', '-d', deploy_dir],
- 'deploy', 'eSDK deploy')
- self.measure_disk_usage(deploy_dir, 'deploy_dir', 'deploy dir')
diff --git a/meta/lib/oeqa/buildperf/test_basic.py b/meta/lib/oeqa/buildperf/test_basic.py
new file mode 100644
index 0000000000..2104617ba3
--- /dev/null
+++ b/meta/lib/oeqa/buildperf/test_basic.py
@@ -0,0 +1,120 @@
+# Copyright (c) 2016, Intel Corporation.
+#
+# SPDX-License-Identifier: GPL-2.0-only
+#
+"""Basic set of build performance tests"""
+import os
+import shutil
+
+import oe.path
+from oeqa.buildperf import BuildPerfTestCase
+from oeqa.utils.commands import get_bb_var, get_bb_vars
+
+class Test1P1(BuildPerfTestCase):
+ build_target = 'core-image-sato'
+
+ def test1(self):
+ """Build core-image-sato"""
+ self.rm_tmp()
+ self.rm_sstate()
+ self.rm_cache()
+ self.sync()
+ self.measure_cmd_resources(['bitbake', self.build_target], 'build',
+ 'bitbake ' + self.build_target, save_bs=True)
+ self.measure_disk_usage(self.bb_vars['TMPDIR'], 'tmpdir', 'tmpdir')
+ self.measure_disk_usage(get_bb_var("IMAGE_ROOTFS", self.build_target), 'rootfs', 'rootfs', True)
+
+
+class Test1P2(BuildPerfTestCase):
+ build_target = 'virtual/kernel'
+
+ def test12(self):
+ """Build virtual/kernel"""
+ # Build and cleans state in order to get all dependencies pre-built
+ self.run_cmd(['bitbake', self.build_target])
+ self.run_cmd(['bitbake', self.build_target, '-c', 'cleansstate'])
+
+ self.sync()
+ self.measure_cmd_resources(['bitbake', self.build_target], 'build',
+ 'bitbake ' + self.build_target)
+
+
+class Test1P3(BuildPerfTestCase):
+ build_target = 'core-image-sato'
+
+ def test13(self):
+ """Build core-image-sato with rm_work enabled"""
+ postfile = os.path.join(self.tmp_dir, 'postfile.conf')
+ with open(postfile, 'w') as fobj:
+ fobj.write('INHERIT += "rm_work"\n')
+
+ self.rm_tmp()
+ self.rm_sstate()
+ self.rm_cache()
+ self.sync()
+ cmd = ['bitbake', '-R', postfile, self.build_target]
+ self.measure_cmd_resources(cmd, 'build',
+ 'bitbake' + self.build_target,
+ save_bs=True)
+ self.measure_disk_usage(self.bb_vars['TMPDIR'], 'tmpdir', 'tmpdir')
+
+
+class Test2(BuildPerfTestCase):
+ build_target = 'core-image-sato'
+
+ def test2(self):
+ """Run core-image-sato do_rootfs with sstate"""
+ # Build once in order to populate sstate cache
+ self.run_cmd(['bitbake', self.build_target])
+
+ self.rm_tmp()
+ self.rm_cache()
+ self.sync()
+ cmd = ['bitbake', self.build_target, '-c', 'rootfs']
+ self.measure_cmd_resources(cmd, 'do_rootfs', 'bitbake do_rootfs')
+
+
+class Test3(BuildPerfTestCase):
+
+ def test3(self):
+ """Bitbake parsing (bitbake -p)"""
+ # Drop all caches and parse
+ self.rm_cache()
+ oe.path.remove(os.path.join(self.bb_vars['TMPDIR'], 'cache'), True)
+ self.measure_cmd_resources(['bitbake', '-p'], 'parse_1',
+ 'bitbake -p (no caches)')
+ # Drop tmp/cache
+ oe.path.remove(os.path.join(self.bb_vars['TMPDIR'], 'cache'), True)
+ self.measure_cmd_resources(['bitbake', '-p'], 'parse_2',
+ 'bitbake -p (no tmp/cache)')
+ # Parse with fully cached data
+ self.measure_cmd_resources(['bitbake', '-p'], 'parse_3',
+ 'bitbake -p (cached)')
+
+
+class Test4(BuildPerfTestCase):
+ build_target = 'core-image-sato'
+
+ def test4(self):
+ """eSDK metrics"""
+ self.run_cmd(['bitbake', '-c', 'do_populate_sdk_ext',
+ self.build_target])
+ self.bb_vars = get_bb_vars(None, self.build_target)
+ tmp_dir = self.bb_vars['TMPDIR']
+ installer = os.path.join(
+ self.bb_vars['SDK_DEPLOY'],
+ self.bb_vars['TOOLCHAINEXT_OUTPUTNAME'] + '.sh')
+ # Measure installer size
+ self.measure_disk_usage(installer, 'installer_bin', 'eSDK installer',
+ apparent_size=True)
+ # Measure deployment time and deployed size
+ deploy_dir = os.path.join(tmp_dir, 'esdk-deploy')
+ if os.path.exists(deploy_dir):
+ shutil.rmtree(deploy_dir)
+ self.sync()
+ self.measure_cmd_resources([installer, '-y', '-d', deploy_dir],
+ 'deploy', 'eSDK deploy')
+ #make sure bitbake is unloaded
+ self.sync()
+ self.measure_disk_usage(deploy_dir, 'deploy_dir', 'deploy dir',
+ apparent_size=True)
diff --git a/meta/lib/oeqa/controllers/__init__.py b/meta/lib/oeqa/controllers/__init__.py
index 8eda92763c..0fc905be9a 100644
--- a/meta/lib/oeqa/controllers/__init__.py
+++ b/meta/lib/oeqa/controllers/__init__.py
@@ -1,3 +1,8 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: GPL-2.0-only
+#
# Enable other layers to have modules in the same named directory
from pkgutil import extend_path
__path__ = extend_path(__path__, __name__)
diff --git a/meta/lib/oeqa/controllers/masterimage.py b/meta/lib/oeqa/controllers/controllerimage.py
index 9ce3bf803d..78a4aaff87 100644
--- a/meta/lib/oeqa/controllers/masterimage.py
+++ b/meta/lib/oeqa/controllers/controllerimage.py
@@ -1,15 +1,15 @@
# Copyright (C) 2014 Intel Corporation
#
-# Released under the MIT license (see COPYING.MIT)
-
+# SPDX-License-Identifier: MIT
+#
# This module adds support to testimage.bbclass to deploy images and run
-# tests using a "master image" - this is a "known good" image that is
+# tests using a "controller image" - this is a "known good" image that is
# installed onto the device as part of initial setup and will be booted into
# with no interaction; we can then use it to deploy the image to be tested
# to a second partition before running the tests.
#
-# For an example master image, see core-image-testmaster
-# (meta/recipes-extended/images/core-image-testmaster.bb)
+# For an example controller image, see core-image-testcontroller
+# (meta/recipes-extended/images/core-image-testcontroller.bb)
import os
import bb
@@ -24,22 +24,22 @@ from oeqa.utils import CommandError
from abc import ABCMeta, abstractmethod
-class MasterImageHardwareTarget(oeqa.targetcontrol.BaseTarget, metaclass=ABCMeta):
+class ControllerImageHardwareTarget(oeqa.targetcontrol.BaseTarget, metaclass=ABCMeta):
supported_image_fstypes = ['tar.gz', 'tar.bz2']
def __init__(self, d):
- super(MasterImageHardwareTarget, self).__init__(d)
+ super(ControllerImageHardwareTarget, self).__init__(d)
# target ip
- addr = d.getVar("TEST_TARGET_IP", True) or bb.fatal('Please set TEST_TARGET_IP with the IP address of the machine you want to run the tests on.')
+ addr = d.getVar("TEST_TARGET_IP") or bb.fatal('Please set TEST_TARGET_IP with the IP address of the machine you want to run the tests on.')
self.ip = addr.split(":")[0]
try:
self.port = addr.split(":")[1]
except IndexError:
self.port = None
bb.note("Target IP: %s" % self.ip)
- self.server_ip = d.getVar("TEST_SERVER_IP", True)
+ self.server_ip = d.getVar("TEST_SERVER_IP")
if not self.server_ip:
try:
self.server_ip = subprocess.check_output(['ip', 'route', 'get', self.ip ]).split("\n")[0].split()[-1]
@@ -49,8 +49,8 @@ class MasterImageHardwareTarget(oeqa.targetcontrol.BaseTarget, metaclass=ABCMeta
# test rootfs + kernel
self.image_fstype = self.get_image_fstype(d)
- self.rootfs = os.path.join(d.getVar("DEPLOY_DIR_IMAGE", True), d.getVar("IMAGE_LINK_NAME", True) + '.' + self.image_fstype)
- self.kernel = os.path.join(d.getVar("DEPLOY_DIR_IMAGE", True), d.getVar("KERNEL_IMAGETYPE", False) + '-' + d.getVar('MACHINE', False) + '.bin')
+ self.rootfs = os.path.join(d.getVar("DEPLOY_DIR_IMAGE"), d.getVar("IMAGE_LINK_NAME") + '.' + self.image_fstype)
+ self.kernel = os.path.join(d.getVar("DEPLOY_DIR_IMAGE"), d.getVar("KERNEL_IMAGETYPE", False) + '-' + d.getVar('MACHINE', False) + '.bin')
if not os.path.isfile(self.rootfs):
# we could've checked that IMAGE_FSTYPES contains tar.gz but the config for running testimage might not be
# the same as the config with which the image was build, ie
@@ -61,19 +61,19 @@ class MasterImageHardwareTarget(oeqa.targetcontrol.BaseTarget, metaclass=ABCMeta
if not os.path.isfile(self.kernel):
bb.fatal("No kernel found. Expected path: %s" % self.kernel)
- # master ssh connection
- self.master = None
+ # controller ssh connection
+ self.controller = None
# if the user knows what they are doing, then by all means...
- self.user_cmds = d.getVar("TEST_DEPLOY_CMDS", True)
+ self.user_cmds = d.getVar("TEST_DEPLOY_CMDS")
self.deploy_cmds = None
# this is the name of the command that controls the power for a board
# e.g: TEST_POWERCONTROL_CMD = "/home/user/myscripts/powercontrol.py ${MACHINE} what-ever-other-args-the-script-wants"
# the command should take as the last argument "off" and "on" and "cycle" (off, on)
- self.powercontrol_cmd = d.getVar("TEST_POWERCONTROL_CMD", True) or None
+ self.powercontrol_cmd = d.getVar("TEST_POWERCONTROL_CMD") or None
self.powercontrol_args = d.getVar("TEST_POWERCONTROL_EXTRA_ARGS", False) or ""
- self.serialcontrol_cmd = d.getVar("TEST_SERIALCONTROL_CMD", True) or None
+ self.serialcontrol_cmd = d.getVar("TEST_SERIALCONTROL_CMD") or None
self.serialcontrol_args = d.getVar("TEST_SERIALCONTROL_EXTRA_ARGS", False) or ""
self.origenv = os.environ
@@ -82,7 +82,7 @@ class MasterImageHardwareTarget(oeqa.targetcontrol.BaseTarget, metaclass=ABCMeta
# ssh + keys means we need the original user env
bborigenv = d.getVar("BB_ORIGENV", False) or {}
for key in bborigenv:
- val = bborigenv.getVar(key, True)
+ val = bborigenv.getVar(key)
if val is not None:
self.origenv[key] = str(val)
@@ -97,7 +97,7 @@ class MasterImageHardwareTarget(oeqa.targetcontrol.BaseTarget, metaclass=ABCMeta
if self.powercontrol_cmd:
cmd = "%s %s" % (self.powercontrol_cmd, msg)
try:
- commands.runCmd(cmd, assert_error=False, preexec_fn=os.setsid, env=self.origenv)
+ commands.runCmd(cmd, assert_error=False, start_new_session=True, env=self.origenv)
except CommandError as e:
bb.fatal(str(e))
@@ -108,7 +108,7 @@ class MasterImageHardwareTarget(oeqa.targetcontrol.BaseTarget, metaclass=ABCMeta
time.sleep(10)
self.power_ctl("cycle")
else:
- status, output = conn.run("reboot")
+ status, output = conn.run("sync; { sleep 1; reboot; } > /dev/null &")
if status != 0:
bb.error("Failed rebooting target and no power control command defined. You need to manually reset the device.\n%s" % output)
@@ -119,19 +119,19 @@ class MasterImageHardwareTarget(oeqa.targetcontrol.BaseTarget, metaclass=ABCMeta
def deploy(self):
# base class just sets the ssh log file for us
- super(MasterImageHardwareTarget, self).deploy()
- self.master = sshcontrol.SSHControl(ip=self.ip, logfile=self.sshlog, timeout=600, port=self.port)
- status, output = self.master.run("cat /etc/masterimage")
+ super(ControllerImageHardwareTarget, self).deploy()
+ self.controller = sshcontrol.SSHControl(ip=self.ip, logfile=self.sshlog, timeout=600, port=self.port)
+ status, output = self.controller.run("cat /etc/controllerimage")
if status != 0:
- # We're not booted into the master image, so try rebooting
- bb.plain("%s - booting into the master image" % self.pn)
+ # We're not booted into the controller image, so try rebooting
+ bb.plain("%s - booting into the controller image" % self.pn)
self.power_ctl("cycle")
self._wait_until_booted()
bb.plain("%s - deploying image on target" % self.pn)
- status, output = self.master.run("cat /etc/masterimage")
+ status, output = self.controller.run("cat /etc/controllerimage")
if status != 0:
- bb.fatal("No ssh connectivity or target isn't running a master image.\n%s" % output)
+ bb.fatal("No ssh connectivity or target isn't running a controller image.\n%s" % output)
if self.user_cmds:
self.deploy_cmds = self.user_cmds.split("\n")
try:
@@ -143,7 +143,7 @@ class MasterImageHardwareTarget(oeqa.targetcontrol.BaseTarget, metaclass=ABCMeta
def _deploy(self):
pass
- def start(self, params=None):
+ def start(self, extra_bootparams=None):
bb.plain("%s - boot test image on target" % self.pn)
self._start()
# set the ssh object for the target/test image
@@ -156,50 +156,10 @@ class MasterImageHardwareTarget(oeqa.targetcontrol.BaseTarget, metaclass=ABCMeta
def stop(self):
bb.plain("%s - reboot/powercycle target" % self.pn)
- self.power_cycle(self.connection)
-
-
-class GummibootTarget(MasterImageHardwareTarget):
-
- def __init__(self, d):
- super(GummibootTarget, self).__init__(d)
- # this the value we need to set in the LoaderEntryOneShot EFI variable
- # so the system boots the 'test' bootloader label and not the default
- # The first four bytes are EFI bits, and the rest is an utf-16le string
- # (EFI vars values need to be utf-16)
- # $ echo -en "test\0" | iconv -f ascii -t utf-16le | hexdump -C
- # 00000000 74 00 65 00 73 00 74 00 00 00 |t.e.s.t...|
- self.efivarvalue = r'\x07\x00\x00\x00\x74\x00\x65\x00\x73\x00\x74\x00\x00\x00'
- self.deploy_cmds = [
- 'mount -L boot /boot',
- 'mkdir -p /mnt/testrootfs',
- 'mount -L testrootfs /mnt/testrootfs',
- 'modprobe efivarfs',
- 'mount -t efivarfs efivarfs /sys/firmware/efi/efivars',
- 'cp ~/test-kernel /boot',
- 'rm -rf /mnt/testrootfs/*',
- 'tar xvf ~/test-rootfs.%s -C /mnt/testrootfs' % self.image_fstype,
- 'printf "%s" > /sys/firmware/efi/efivars/LoaderEntryOneShot-4a67b082-0a4c-41cf-b6c7-440b29bb8c4f' % self.efivarvalue
- ]
-
- def _deploy(self):
- # make sure these aren't mounted
- self.master.run("umount /boot; umount /mnt/testrootfs; umount /sys/firmware/efi/efivars;")
- # from now on, every deploy cmd should return 0
- # else an exception will be thrown by sshcontrol
- self.master.ignore_status = False
- self.master.copy_to(self.rootfs, "~/test-rootfs." + self.image_fstype)
- self.master.copy_to(self.kernel, "~/test-kernel")
- for cmd in self.deploy_cmds:
- self.master.run(cmd)
-
- def _start(self, params=None):
- self.power_cycle(self.master)
- # there are better ways than a timeout but this should work for now
- time.sleep(120)
+ self.power_cycle(self.controller)
-class SystemdbootTarget(MasterImageHardwareTarget):
+class SystemdbootTarget(ControllerImageHardwareTarget):
def __init__(self, d):
super(SystemdbootTarget, self).__init__(d)
@@ -224,16 +184,16 @@ class SystemdbootTarget(MasterImageHardwareTarget):
def _deploy(self):
# make sure these aren't mounted
- self.master.run("umount /boot; umount /mnt/testrootfs; umount /sys/firmware/efi/efivars;")
+ self.controller.run("umount /boot; umount /mnt/testrootfs; umount /sys/firmware/efi/efivars;")
# from now on, every deploy cmd should return 0
# else an exception will be thrown by sshcontrol
- self.master.ignore_status = False
- self.master.copy_to(self.rootfs, "~/test-rootfs." + self.image_fstype)
- self.master.copy_to(self.kernel, "~/test-kernel")
+ self.controller.ignore_status = False
+ self.controller.copy_to(self.rootfs, "~/test-rootfs." + self.image_fstype)
+ self.controller.copy_to(self.kernel, "~/test-kernel")
for cmd in self.deploy_cmds:
- self.master.run(cmd)
+ self.controller.run(cmd)
def _start(self, params=None):
- self.power_cycle(self.master)
+ self.power_cycle(self.controller)
# there are better ways than a timeout but this should work for now
time.sleep(120)
diff --git a/meta/lib/oeqa/controllers/testtargetloader.py b/meta/lib/oeqa/controllers/testtargetloader.py
index a1b7b1d92b..209ff7061a 100644
--- a/meta/lib/oeqa/controllers/testtargetloader.py
+++ b/meta/lib/oeqa/controllers/testtargetloader.py
@@ -1,3 +1,9 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: GPL-2.0-only
+#
+
import types
import bb
import os
@@ -61,8 +67,6 @@ class TestTargetLoader:
obj = getattr(module, target)
if obj:
from oeqa.targetcontrol import BaseTarget
- if (not isinstance(obj, (type, types.ClassType))):
- bb.warn("Target {0} found, but not of type Class".format(target))
if( not issubclass(obj, BaseTarget)):
bb.warn("Target {0} found, but subclass is not BaseTarget".format(target))
except:
diff --git a/meta/lib/oeqa/core/README b/meta/lib/oeqa/core/README
new file mode 100644
index 0000000000..d4fcda41f2
--- /dev/null
+++ b/meta/lib/oeqa/core/README
@@ -0,0 +1,76 @@
+= OEQA (v2) Framework =
+
+== Introduction ==
+
+This is version 2 of the OEQA framework. Base clases are located in the
+'oeqa/core' directory and subsequent components must extend from these.
+
+The main design consideration was to implement the needed functionality on
+top of the Python unittest framework. To achieve this goal, the following
+modules are used:
+
+ * oeqa/core/runner.py: Provides OETestResult and OETestRunner base
+ classes extending the unittest class. These classes support exporting
+ results to different formats; currently RAW and XML support exist.
+
+ * oeqa/core/loader.py: Provides OETestLoader extending the unittest class.
+ It also features a unified implementation of decorator support and
+ filtering test cases.
+
+ * oeqa/core/case.py: Provides OETestCase base class extending
+ unittest.TestCase and provides access to the Test data (td), Test context
+ and Logger functionality.
+
+ * oeqa/core/decorator: Provides OETestDecorator, a new class to implement
+ decorators for Test cases.
+
+ * oeqa/core/context: Provides OETestContext, a high-level API for
+ loadTests and runTests of certain Test component and
+ OETestContextExecutor a base class to enable oe-test to discover/use
+ the Test component.
+
+Also, a new 'oe-test' runner is located under 'scripts', allowing scans for components
+that supports OETestContextExecutor (see below).
+
+== Terminology ==
+
+ * Test component: The area of testing in the Project, for example: runtime, SDK, eSDK, selftest.
+
+ * Test data: Data associated with the Test component. Currently we use bitbake datastore as
+ a Test data input.
+
+ * Test context: A context of what tests needs to be run and how to do it; this additionally
+ provides access to the Test data and could have custom methods and/or attrs.
+
+== oe-test ==
+
+The new tool, oe-test, has the ability to scan the code base for test components and provide
+a unified way to run test cases. Internally it scans folders inside oeqa module in order to find
+specific classes that implement a test component.
+
+== Usage ==
+
+Executing the example test component
+
+ $ source oe-init-build-env
+ $ oe-test core
+
+Getting help
+
+ $ oe-test -h
+
+== Creating new Test Component ==
+
+Adding a new test component the developer needs to extend OETestContext/OETestContextExecutor
+(from context.py) and OETestCase (from case.py)
+
+== Selftesting the framework ==
+
+Run all tests:
+
+ $ PATH=$PATH:../../ python3 -m unittest discover -s tests
+
+Run some test:
+
+ $ cd tests/
+ $ ./test_data.py
diff --git a/meta/lib/oe/tests/__init__.py b/meta/lib/oeqa/core/__init__.py
index e69de29bb2..e69de29bb2 100644
--- a/meta/lib/oe/tests/__init__.py
+++ b/meta/lib/oeqa/core/__init__.py
diff --git a/meta/lib/oeqa/core/case.py b/meta/lib/oeqa/core/case.py
new file mode 100644
index 0000000000..bc4446a938
--- /dev/null
+++ b/meta/lib/oeqa/core/case.py
@@ -0,0 +1,105 @@
+#
+# Copyright (C) 2016 Intel Corporation
+#
+# SPDX-License-Identifier: MIT
+#
+
+import base64
+import zlib
+import unittest
+
+from oeqa.core.exception import OEQAMissingVariable
+
+def _validate_td_vars(td, td_vars, type_msg):
+ if td_vars:
+ for v in td_vars:
+ if not v in td:
+ raise OEQAMissingVariable("Test %s need %s variable but"\
+ " isn't into td" % (type_msg, v))
+
+class OETestCase(unittest.TestCase):
+ # TestContext and Logger instance set by OETestLoader.
+ tc = None
+ logger = None
+
+ # td has all the variables needed by the test cases
+ # is the same across all the test cases.
+ td = None
+
+ # td_vars has the variables needed by a test class
+ # or test case instance, if some var isn't into td a
+ # OEQAMissingVariable exception is raised
+ td_vars = None
+
+ @classmethod
+ def _oeSetUpClass(clss):
+ _validate_td_vars(clss.td, clss.td_vars, "class")
+ if hasattr(clss, 'setUpHooker') and callable(getattr(clss, 'setUpHooker')):
+ clss.setUpHooker()
+ clss.setUpClassMethod()
+
+ @classmethod
+ def _oeTearDownClass(clss):
+ clss.tearDownClassMethod()
+
+ def _oeSetUp(self):
+ try:
+ for d in self.decorators:
+ d.setUpDecorator()
+ except:
+ for d in self.decorators:
+ d.tearDownDecorator()
+ raise
+ self.setUpMethod()
+
+ def _oeTearDown(self):
+ for d in self.decorators:
+ d.tearDownDecorator()
+ self.tearDownMethod()
+
+class OEPTestResultTestCase:
+ """
+ Mix-in class to provide functions to make interacting with extraresults for
+ the purposes of storing ptestresult data.
+ """
+ @staticmethod
+ def _compress_log(log):
+ logdata = log.encode("utf-8") if isinstance(log, str) else log
+ logdata = zlib.compress(logdata)
+ logdata = base64.b64encode(logdata).decode("utf-8")
+ return {"compressed" : logdata}
+
+ def ptest_rawlog(self, log):
+ if not hasattr(self, "extraresults"):
+ self.extraresults = {"ptestresult.sections" : {}}
+ self.extraresults["ptestresult.rawlogs"] = {"log" : self._compress_log(log)}
+
+ def ptest_section(self, section, duration = None, log = None, logfile = None, exitcode = None):
+ if not hasattr(self, "extraresults"):
+ self.extraresults = {"ptestresult.sections" : {}}
+
+ sections = self.extraresults.get("ptestresult.sections")
+ if section not in sections:
+ sections[section] = {}
+
+ if log is not None:
+ sections[section]["log"] = self._compress_log(log)
+ elif logfile is not None:
+ with open(logfile, "rb") as f:
+ sections[section]["log"] = self._compress_log(f.read())
+
+ if duration is not None:
+ sections[section]["duration"] = duration
+ if exitcode is not None:
+ sections[section]["exitcode"] = exitcode
+
+ def ptest_result(self, section, test, result):
+ if not hasattr(self, "extraresults"):
+ self.extraresults = {"ptestresult.sections" : {}}
+
+ sections = self.extraresults.get("ptestresult.sections")
+ if section not in sections:
+ sections[section] = {}
+ resultname = "ptestresult.{}.{}".format(section, test)
+ self.extraresults[resultname] = {"status" : result}
+
diff --git a/meta/lib/oeqa/core/cases/__init__.py b/meta/lib/oeqa/core/cases/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/meta/lib/oeqa/core/cases/__init__.py
diff --git a/meta/lib/oeqa/core/cases/example/data.json b/meta/lib/oeqa/core/cases/example/data.json
new file mode 100644
index 0000000000..21d6b16d17
--- /dev/null
+++ b/meta/lib/oeqa/core/cases/example/data.json
@@ -0,0 +1 @@
+{"ARCH": "x86", "IMAGE": "core-image-minimal"} \ No newline at end of file
diff --git a/meta/lib/oeqa/core/cases/example/test_basic.py b/meta/lib/oeqa/core/cases/example/test_basic.py
new file mode 100644
index 0000000000..d77edcdcec
--- /dev/null
+++ b/meta/lib/oeqa/core/cases/example/test_basic.py
@@ -0,0 +1,22 @@
+# Copyright (C) 2016 Intel Corporation
+#
+# SPDX-License-Identifier: MIT
+#
+
+from oeqa.core.case import OETestCase
+from oeqa.core.decorator.depends import OETestDepends
+
+class OETestExample(OETestCase):
+ def test_example(self):
+ self.logger.info('IMAGE: %s' % self.td.get('IMAGE'))
+ self.assertEqual('core-image-minimal', self.td.get('IMAGE'))
+ self.logger.info('ARCH: %s' % self.td.get('ARCH'))
+ self.assertEqual('x86', self.td.get('ARCH'))
+
+class OETestExampleDepend(OETestCase):
+ @OETestDepends(['OETestExample.test_example'])
+ def test_example_depends(self):
+ pass
+
+ def test_example_no_depends(self):
+ pass
diff --git a/meta/lib/oeqa/core/context.py b/meta/lib/oeqa/core/context.py
new file mode 100644
index 0000000000..2abe353d27
--- /dev/null
+++ b/meta/lib/oeqa/core/context.py
@@ -0,0 +1,246 @@
+## Copyright (C) 2016 Intel Corporation
+#
+# SPDX-License-Identifier: MIT
+#
+
+import os
+import sys
+import json
+import time
+import logging
+import collections
+import unittest
+
+from oeqa.core.loader import OETestLoader
+from oeqa.core.runner import OETestRunner
+from oeqa.core.exception import OEQAMissingManifest, OEQATestNotFound
+
+class OETestContext(object):
+ loaderClass = OETestLoader
+ runnerClass = OETestRunner
+
+ files_dir = os.path.abspath(os.path.join(os.path.dirname(
+ os.path.abspath(__file__)), "../files"))
+
+ def __init__(self, td=None, logger=None):
+ if not type(td) is dict:
+ raise TypeError("td isn't dictionary type")
+
+ self.td = td
+ self.logger = logger
+ self._registry = {}
+ self._registry['cases'] = collections.OrderedDict()
+
+ self.results = unittest.TestResult()
+ unittest.registerResult(self.results)
+
+ def _read_modules_from_manifest(self, manifest):
+ if not os.path.exists(manifest):
+ raise OEQAMissingManifest("Manifest does not exist on %s" % manifest)
+
+ modules = []
+ for line in open(manifest).readlines():
+ line = line.strip()
+ if line and not line.startswith("#"):
+ modules.append(line)
+
+ return modules
+
+ def skipTests(self, skips):
+ if not skips:
+ return
+ def skipfuncgen(skipmsg):
+ def func():
+ raise unittest.SkipTest(skipmsg)
+ return func
+ class_ids = {}
+ for test in self.suites:
+ if test.__class__ not in class_ids:
+ class_ids[test.__class__] = '.'.join(test.id().split('.')[:-1])
+ for skip in skips:
+ if (test.id()+'.').startswith(skip+'.'):
+ setattr(test, 'setUp', skipfuncgen('Skip by the command line argument "%s"' % skip))
+ for tclass in class_ids:
+ cid = class_ids[tclass]
+ for skip in skips:
+ if (cid + '.').startswith(skip + '.'):
+ setattr(tclass, 'setUpHooker', skipfuncgen('Skip by the command line argument "%s"' % skip))
+
+ def loadTests(self, module_paths, modules=[], tests=[],
+ modules_manifest="", modules_required=[], **kwargs):
+ if modules_manifest:
+ modules = self._read_modules_from_manifest(modules_manifest)
+
+ self.loader = self.loaderClass(self, module_paths, modules, tests,
+ modules_required, **kwargs)
+ self.suites = self.loader.discover()
+
+ def prepareSuite(self, suites, processes):
+ return suites
+
+ def runTests(self, processes=None, skips=[]):
+ self.runner = self.runnerClass(self, descriptions=False, verbosity=2)
+
+ # Dinamically skip those tests specified though arguments
+ self.skipTests(skips)
+
+ self._run_start_time = time.time()
+ self._run_end_time = self._run_start_time
+ if not processes:
+ self.runner.buffer = True
+ result = self.runner.run(self.prepareSuite(self.suites, processes))
+ self._run_end_time = time.time()
+
+ return result
+
+ def listTests(self, display_type):
+ self.runner = self.runnerClass(self, verbosity=2)
+ return self.runner.list_tests(self.suites, display_type)
+
+class OETestContextExecutor(object):
+ _context_class = OETestContext
+ _script_executor = 'oe-test'
+
+ name = 'core'
+ help = 'core test component example'
+ description = 'executes core test suite example'
+ datetime = time.strftime("%Y%m%d%H%M%S")
+
+ default_cases = [os.path.join(os.path.abspath(os.path.dirname(__file__)),
+ 'cases/example')]
+ default_test_data = os.path.join(default_cases[0], 'data.json')
+ default_tests = None
+ default_json_result_dir = None
+
+ def register_commands(self, logger, subparsers):
+ self.parser = subparsers.add_parser(self.name, help=self.help,
+ description=self.description, group='components')
+
+ self.default_output_log = '%s-results-%s.log' % (self.name, self.datetime)
+ self.parser.add_argument('--output-log', action='store',
+ default=self.default_output_log,
+ help="results output log, default: %s" % self.default_output_log)
+
+ self.parser.add_argument('--json-result-dir', action='store',
+ default=self.default_json_result_dir,
+ help="json result output dir, default: %s" % self.default_json_result_dir)
+
+ group = self.parser.add_mutually_exclusive_group()
+ group.add_argument('--run-tests', action='store', nargs='+',
+ default=self.default_tests,
+ help="tests to run in <module>[.<class>[.<name>]]")
+ group.add_argument('--list-tests', action='store',
+ choices=('module', 'class', 'name'),
+ help="lists available tests")
+
+ if self.default_test_data:
+ self.parser.add_argument('--test-data-file', action='store',
+ default=self.default_test_data,
+ help="data file to load, default: %s" % self.default_test_data)
+ else:
+ self.parser.add_argument('--test-data-file', action='store',
+ help="data file to load")
+
+ if self.default_cases:
+ self.parser.add_argument('CASES_PATHS', action='store',
+ default=self.default_cases, nargs='*',
+ help="paths to directories with test cases, default: %s"\
+ % self.default_cases)
+ else:
+ self.parser.add_argument('CASES_PATHS', action='store',
+ nargs='+', help="paths to directories with test cases")
+
+ self.parser.set_defaults(func=self.run)
+
+ def _setup_logger(self, logger, args):
+ formatter = logging.Formatter('%(asctime)s - ' + self.name + \
+ ' - %(levelname)s - %(message)s')
+ sh = logger.handlers[0]
+ sh.setFormatter(formatter)
+ fh = logging.FileHandler(args.output_log)
+ fh.setFormatter(formatter)
+ logger.addHandler(fh)
+ if getattr(args, 'verbose', False):
+ logger.setLevel('DEBUG')
+
+ return logger
+
+ def _process_args(self, logger, args):
+ self.tc_kwargs = {}
+ self.tc_kwargs['init'] = {}
+ self.tc_kwargs['load'] = {}
+ self.tc_kwargs['list'] = {}
+ self.tc_kwargs['run'] = {}
+
+ self.tc_kwargs['init']['logger'] = self._setup_logger(logger, args)
+ if args.test_data_file:
+ self.tc_kwargs['init']['td'] = json.load(
+ open(args.test_data_file, "r"))
+ else:
+ self.tc_kwargs['init']['td'] = {}
+
+ if args.run_tests:
+ self.tc_kwargs['load']['modules'] = args.run_tests
+ self.tc_kwargs['load']['modules_required'] = args.run_tests
+ else:
+ self.tc_kwargs['load']['modules'] = []
+
+ self.tc_kwargs['run']['skips'] = []
+
+ self.module_paths = args.CASES_PATHS
+
+ def _get_json_result_dir(self, args):
+ return args.json_result_dir
+
+ def _get_configuration(self):
+ td = self.tc_kwargs['init']['td']
+ configuration = {'TEST_TYPE': self.name,
+ 'MACHINE': td.get("MACHINE"),
+ 'DISTRO': td.get("DISTRO"),
+ 'IMAGE_BASENAME': td.get("IMAGE_BASENAME"),
+ 'DATETIME': td.get("DATETIME")}
+ return configuration
+
+ def _get_result_id(self, configuration):
+ return '%s_%s_%s_%s' % (configuration['TEST_TYPE'], configuration['IMAGE_BASENAME'],
+ configuration['MACHINE'], self.datetime)
+
+ def _pre_run(self):
+ pass
+
+ def run(self, logger, args):
+ self._process_args(logger, args)
+
+ self.tc = self._context_class(**self.tc_kwargs['init'])
+ try:
+ self.tc.loadTests(self.module_paths, **self.tc_kwargs['load'])
+ except OEQATestNotFound as ex:
+ logger.error(ex)
+ sys.exit(1)
+
+ if args.list_tests:
+ rc = self.tc.listTests(args.list_tests, **self.tc_kwargs['list'])
+ else:
+ self._pre_run()
+ rc = self.tc.runTests(**self.tc_kwargs['run'])
+
+ json_result_dir = self._get_json_result_dir(args)
+ if json_result_dir:
+ configuration = self._get_configuration()
+ rc.logDetails(json_result_dir,
+ configuration,
+ self._get_result_id(configuration))
+ else:
+ rc.logDetails()
+
+ rc.logSummary(self.name)
+
+ output_link = os.path.join(os.path.dirname(args.output_log),
+ "%s-results.log" % self.name)
+ if os.path.exists(output_link):
+ os.remove(output_link)
+ os.symlink(args.output_log, output_link)
+
+ return rc
+
+_executor_class = OETestContextExecutor
diff --git a/meta/lib/oeqa/core/decorator/__init__.py b/meta/lib/oeqa/core/decorator/__init__.py
new file mode 100644
index 0000000000..93efd30e1d
--- /dev/null
+++ b/meta/lib/oeqa/core/decorator/__init__.py
@@ -0,0 +1,74 @@
+#
+# Copyright (C) 2016 Intel Corporation
+#
+# SPDX-License-Identifier: MIT
+#
+
+from functools import wraps
+from abc import ABCMeta
+
+decoratorClasses = set()
+
+def registerDecorator(cls):
+ decoratorClasses.add(cls)
+ return cls
+
+class OETestDecorator(object, metaclass=ABCMeta):
+ case = None # Reference of OETestCase decorated
+ attrs = None # Attributes to be loaded by decorator implementation
+
+ def __init__(self, *args, **kwargs):
+ if not self.attrs:
+ return
+
+ for idx, attr in enumerate(self.attrs):
+ if attr in kwargs:
+ value = kwargs[attr]
+ else:
+ value = args[idx]
+ setattr(self, attr, value)
+
+ def __call__(self, func):
+ @wraps(func)
+ def wrapped_f(*args, **kwargs):
+ self.attrs = self.attrs # XXX: Enables OETestLoader discover
+ return func(*args, **kwargs)
+ return wrapped_f
+
+ # OETestLoader call it when is loading test cases.
+ # XXX: Most methods would change the registry for later
+ # processing; be aware that filtrate method needs to
+ # run later than bind, so there could be data (in the
+ # registry) of a cases that were filtered.
+ def bind(self, registry, case):
+ self.case = case
+ self.logger = case.tc.logger
+ self.case.decorators.append(self)
+
+ # OETestRunner call this method when tries to run
+ # the test case.
+ def setUpDecorator(self):
+ pass
+
+ # OETestRunner call it after a test method has been
+ # called even if the method raised an exception.
+ def tearDownDecorator(self):
+ pass
+
+class OETestDiscover(OETestDecorator):
+
+ # OETestLoader call it after discover test cases
+ # needs to return the cases to be run.
+ @staticmethod
+ def discover(registry):
+ return registry['cases']
+
+def OETestTag(*tags):
+ def decorator(item):
+ if hasattr(item, "__oeqa_testtags"):
+ # do not append, create a new list (to handle classes with inheritance)
+ item.__oeqa_testtags = list(item.__oeqa_testtags) + list(tags)
+ else:
+ item.__oeqa_testtags = tags
+ return item
+ return decorator
diff --git a/meta/lib/oeqa/core/decorator/data.py b/meta/lib/oeqa/core/decorator/data.py
new file mode 100644
index 0000000000..de881e097a
--- /dev/null
+++ b/meta/lib/oeqa/core/decorator/data.py
@@ -0,0 +1,220 @@
+#
+# Copyright (C) 2016 Intel Corporation
+#
+# SPDX-License-Identifier: MIT
+#
+
+from oeqa.core.exception import OEQAMissingVariable
+
+from . import OETestDecorator, registerDecorator
+
+def has_feature(td, feature):
+ """
+ Checks for feature in DISTRO_FEATURES or IMAGE_FEATURES.
+ """
+
+ if (feature in td.get('DISTRO_FEATURES', '').split() or
+ feature in td.get('IMAGE_FEATURES', '').split()):
+ return True
+ return False
+
+def has_machine(td, machine):
+ """
+ Checks for MACHINE.
+ """
+
+ if (machine == td.get('MACHINE', '')):
+ return True
+ return False
+
+@registerDecorator
+class skipIfDataVar(OETestDecorator):
+ """
+ Skip test based on value of a data store's variable.
+
+ It will get the info of var from the data store and will
+ check it against value; if are equal it will skip the test
+ with msg as the reason.
+ """
+
+ attrs = ('var', 'value', 'msg')
+
+ def setUpDecorator(self):
+ msg = ('Checking if %r value is %r to skip test' %
+ (self.var, self.value))
+ self.logger.debug(msg)
+ if self.case.td.get(self.var) == self.value:
+ self.case.skipTest(self.msg)
+
+@registerDecorator
+class skipIfNotDataVar(OETestDecorator):
+ """
+ Skip test based on value of a data store's variable.
+
+ It will get the info of var from the data store and will
+ check it against value; if are not equal it will skip the
+ test with msg as the reason.
+ """
+
+ attrs = ('var', 'value', 'msg')
+
+ def setUpDecorator(self):
+ msg = ('Checking if %r value is not %r to skip test' %
+ (self.var, self.value))
+ self.logger.debug(msg)
+ if not self.case.td.get(self.var) == self.value:
+ self.case.skipTest(self.msg)
+
+@registerDecorator
+class skipIfInDataVar(OETestDecorator):
+ """
+ Skip test if value is in data store's variable.
+ """
+
+ attrs = ('var', 'value', 'msg')
+ def setUpDecorator(self):
+ msg = ('Checking if %r value contains %r to skip '
+ 'the test' % (self.var, self.value))
+ self.logger.debug(msg)
+ if self.value in (self.case.td.get(self.var)):
+ self.case.skipTest(self.msg)
+
+@registerDecorator
+class skipIfNotInDataVar(OETestDecorator):
+ """
+ Skip test if value is not in data store's variable.
+ """
+
+ attrs = ('var', 'value', 'msg')
+ def setUpDecorator(self):
+ msg = ('Checking if %r value contains %r to run '
+ 'the test' % (self.var, self.value))
+ self.logger.debug(msg)
+ if not self.value in (self.case.td.get(self.var) or ""):
+ self.case.skipTest(self.msg)
+
+@registerDecorator
+class OETestDataDepends(OETestDecorator):
+ attrs = ('td_depends',)
+
+ def setUpDecorator(self):
+ for v in self.td_depends:
+ try:
+ value = self.case.td[v]
+ except KeyError:
+ raise OEQAMissingVariable("Test case need %s variable but"\
+ " isn't into td" % v)
+
+@registerDecorator
+class skipIfNotFeature(OETestDecorator):
+ """
+ Skip test based on DISTRO_FEATURES.
+
+ value must be in distro features or it will skip the test
+ with msg as the reason.
+ """
+
+ attrs = ('value', 'msg')
+
+ def setUpDecorator(self):
+ msg = ('Checking if %s is in DISTRO_FEATURES '
+ 'or IMAGE_FEATURES' % (self.value))
+ self.logger.debug(msg)
+ if not has_feature(self.case.td, self.value):
+ self.case.skipTest(self.msg)
+
+@registerDecorator
+class skipIfFeature(OETestDecorator):
+ """
+ Skip test based on DISTRO_FEATURES.
+
+ value must not be in distro features or it will skip the test
+ with msg as the reason.
+ """
+
+ attrs = ('value', 'msg')
+
+ def setUpDecorator(self):
+ msg = ('Checking if %s is not in DISTRO_FEATURES '
+ 'or IMAGE_FEATURES' % (self.value))
+ self.logger.debug(msg)
+ if has_feature(self.case.td, self.value):
+ self.case.skipTest(self.msg)
+
+@registerDecorator
+class skipIfNotMachine(OETestDecorator):
+ """
+ Skip test based on MACHINE.
+
+ value must be match MACHINE or it will skip the test
+ with msg as the reason.
+ """
+
+ attrs = ('value', 'msg')
+
+ def setUpDecorator(self):
+ msg = ('Checking if %s is not this MACHINE' % self.value)
+ self.logger.debug(msg)
+ if not has_machine(self.case.td, self.value):
+ self.case.skipTest(self.msg)
+
+@registerDecorator
+class skipIfMachine(OETestDecorator):
+ """
+ Skip test based on Machine.
+
+ value must not be this machine or it will skip the test
+ with msg as the reason.
+ """
+
+ attrs = ('value', 'msg')
+
+ def setUpDecorator(self):
+ msg = ('Checking if %s is this MACHINE' % self.value)
+ self.logger.debug(msg)
+ if has_machine(self.case.td, self.value):
+ self.case.skipTest(self.msg)
+
+@registerDecorator
+class skipIfNotQemu(OETestDecorator):
+ """
+ Skip test if MACHINE is not qemu*
+ """
+ def setUpDecorator(self):
+ self.logger.debug("Checking if not qemu MACHINE")
+ if not self.case.td.get('MACHINE', '').startswith('qemu'):
+ self.case.skipTest('Test only runs on qemu machines')
+
+@registerDecorator
+class skipIfQemu(OETestDecorator):
+ """
+ Skip test if MACHINE is qemu*
+ """
+ def setUpDecorator(self):
+ self.logger.debug("Checking if qemu MACHINE")
+ if self.case.td.get('MACHINE', '').startswith('qemu'):
+ self.case.skipTest('Test only runs on real hardware')
+
+@registerDecorator
+class skipIfArch(OETestDecorator):
+ """
+ Skip test if HOST_ARCH is present in the tuple specified.
+ """
+
+ attrs = ('archs',)
+ def setUpDecorator(self):
+ arch = self.case.td['HOST_ARCH']
+ if arch in self.archs:
+ self.case.skipTest('Test skipped on %s' % arch)
+
+@registerDecorator
+class skipIfNotArch(OETestDecorator):
+ """
+ Skip test if HOST_ARCH is not present in the tuple specified.
+ """
+
+ attrs = ('archs',)
+ def setUpDecorator(self):
+ arch = self.case.td['HOST_ARCH']
+ if arch not in self.archs:
+ self.case.skipTest('Test skipped on %s' % arch)
diff --git a/meta/lib/oeqa/core/decorator/depends.py b/meta/lib/oeqa/core/decorator/depends.py
new file mode 100644
index 0000000000..33f0841cab
--- /dev/null
+++ b/meta/lib/oeqa/core/decorator/depends.py
@@ -0,0 +1,98 @@
+#
+# Copyright (C) 2016 Intel Corporation
+#
+# SPDX-License-Identifier: MIT
+#
+
+from unittest import SkipTest
+
+from oeqa.core.exception import OEQADependency
+
+from . import OETestDiscover, registerDecorator
+
+def _add_depends(registry, case, depends):
+ module_name = case.__module__
+ class_name = case.__class__.__name__
+
+ case_id = case.id()
+
+ for depend in depends:
+ dparts = depend.split('.')
+
+ if len(dparts) == 1:
+ depend_id = ".".join((module_name, class_name, dparts[0]))
+ elif len(dparts) == 2:
+ depend_id = ".".join((module_name, dparts[0], dparts[1]))
+ else:
+ depend_id = depend
+
+ if not case_id in registry:
+ registry[case_id] = []
+ if not depend_id in registry[case_id]:
+ registry[case_id].append(depend_id)
+
+def _validate_test_case_depends(cases, depends):
+ for case in depends:
+ if not case in cases:
+ continue
+ for dep in depends[case]:
+ if not dep in cases:
+ raise OEQADependency("TestCase %s depends on %s and isn't available"\
+ ", cases available %s." % (case, dep, str(cases.keys())))
+
+def _order_test_case_by_depends(cases, depends):
+ def _dep_resolve(graph, node, resolved, seen):
+ seen.append(node)
+ for edge in graph[node]:
+ if edge not in resolved:
+ if edge in seen:
+ raise OEQADependency("Test cases %s and %s have a circular" \
+ " dependency." % (node, edge))
+ _dep_resolve(graph, edge, resolved, seen)
+ resolved.append(node)
+
+ dep_graph = {}
+ dep_graph['__root__'] = cases.keys()
+ for case in cases:
+ if case in depends:
+ dep_graph[case] = depends[case]
+ else:
+ dep_graph[case] = []
+
+ cases_ordered = []
+ _dep_resolve(dep_graph, '__root__', cases_ordered, [])
+ cases_ordered.remove('__root__')
+
+ return [cases[case_id] for case_id in cases_ordered]
+
+def _skipTestDependency(case, depends):
+ for dep in depends:
+ found = False
+ for test, _ in case.tc.results.successes:
+ if test.id() == dep:
+ found = True
+ break
+ if not found:
+ raise SkipTest("Test case %s depends on %s but it didn't pass/run." \
+ % (case.id(), dep))
+
+@registerDecorator
+class OETestDepends(OETestDiscover):
+ attrs = ('depends',)
+
+ def bind(self, registry, case):
+ super(OETestDepends, self).bind(registry, case)
+ if not registry.get('depends'):
+ registry['depends'] = {}
+ _add_depends(registry['depends'], case, self.depends)
+
+ @staticmethod
+ def discover(registry):
+ if registry.get('depends'):
+ _validate_test_case_depends(registry['cases'], registry['depends'])
+ return _order_test_case_by_depends(registry['cases'], registry['depends'])
+ else:
+ return [registry['cases'][case_id] for case_id in registry['cases']]
+
+ def setUpDecorator(self):
+ _skipTestDependency(self.case, self.depends)
diff --git a/meta/lib/oeqa/core/decorator/oetimeout.py b/meta/lib/oeqa/core/decorator/oetimeout.py
new file mode 100644
index 0000000000..5e6873ad48
--- /dev/null
+++ b/meta/lib/oeqa/core/decorator/oetimeout.py
@@ -0,0 +1,29 @@
+#
+# Copyright (C) 2016 Intel Corporation
+#
+# SPDX-License-Identifier: MIT
+#
+
+import signal
+from . import OETestDecorator, registerDecorator
+from oeqa.core.exception import OEQATimeoutError
+
+@registerDecorator
+class OETimeout(OETestDecorator):
+ attrs = ('oetimeout',)
+
+ def setUpDecorator(self):
+ timeout = self.oetimeout
+ def _timeoutHandler(signum, frame):
+ raise OEQATimeoutError("Timed out after %s "
+ "seconds of execution" % timeout)
+
+ self.logger.debug("Setting up a %d second(s) timeout" % self.oetimeout)
+ self.alarmSignal = signal.signal(signal.SIGALRM, _timeoutHandler)
+ signal.alarm(self.oetimeout)
+
+ def tearDownDecorator(self):
+ signal.alarm(0)
+ if hasattr(self, 'alarmSignal'):
+ signal.signal(signal.SIGALRM, self.alarmSignal)
+ self.logger.debug("Removed SIGALRM handler")
diff --git a/meta/lib/oeqa/core/exception.py b/meta/lib/oeqa/core/exception.py
new file mode 100644
index 0000000000..05be0ed21f
--- /dev/null
+++ b/meta/lib/oeqa/core/exception.py
@@ -0,0 +1,26 @@
+#
+# Copyright (C) 2016 Intel Corporation
+#
+# SPDX-License-Identifier: MIT
+#
+
+class OEQAException(Exception):
+ pass
+
+class OEQATimeoutError(OEQAException):
+ pass
+
+class OEQAMissingVariable(OEQAException):
+ pass
+
+class OEQADependency(OEQAException):
+ pass
+
+class OEQAMissingManifest(OEQAException):
+ pass
+
+class OEQAPreRun(OEQAException):
+ pass
+
+class OEQATestNotFound(OEQAException):
+ pass
diff --git a/meta/lib/oeqa/core/loader.py b/meta/lib/oeqa/core/loader.py
new file mode 100644
index 0000000000..11978213b8
--- /dev/null
+++ b/meta/lib/oeqa/core/loader.py
@@ -0,0 +1,342 @@
+#
+# Copyright (C) 2016 Intel Corporation
+#
+# SPDX-License-Identifier: MIT
+#
+
+import os
+import re
+import sys
+import unittest
+import inspect
+
+from oeqa.core.utils.path import findFile
+from oeqa.core.utils.test import getSuiteModules, getCaseID
+
+from oeqa.core.exception import OEQATestNotFound
+from oeqa.core.case import OETestCase
+from oeqa.core.decorator import decoratorClasses, OETestDecorator, \
+ OETestDiscover
+
+# When loading tests, the unittest framework stores any exceptions and
+# displays them only when the run method is called.
+#
+# For our purposes, it is better to raise the exceptions in the loading
+# step rather than waiting to run the test suite.
+#
+# Generate the function definition because this differ across python versions
+# Python >= 3.4.4 uses tree parameters instead four but for example Python 3.5.3
+# ueses four parameters so isn't incremental.
+_failed_test_args = inspect.getfullargspec(unittest.loader._make_failed_test).args
+exec("""def _make_failed_test(%s): raise exception""" % ', '.join(_failed_test_args))
+unittest.loader._make_failed_test = _make_failed_test
+
+def _find_duplicated_modules(suite, directory):
+ for module in getSuiteModules(suite):
+ path = findFile('%s.py' % module, directory)
+ if path:
+ raise ImportError("Duplicated %s module found in %s" % (module, path))
+
+def _built_modules_dict(modules):
+ modules_dict = {}
+
+ if modules == None:
+ return modules_dict
+
+ for module in modules:
+ # Assumption: package and module names do not contain upper case
+ # characters, whereas class names do
+ m = re.match(r'^([0-9a-z_.]+)(?:\.(\w[^.]*)(?:\.([^.]+))?)?$', module, flags=re.ASCII)
+ if not m:
+ continue
+
+ module_name, class_name, test_name = m.groups()
+
+ if module_name and module_name not in modules_dict:
+ modules_dict[module_name] = {}
+ if class_name and class_name not in modules_dict[module_name]:
+ modules_dict[module_name][class_name] = []
+ if test_name and test_name not in modules_dict[module_name][class_name]:
+ modules_dict[module_name][class_name].append(test_name)
+
+ return modules_dict
+
+class OETestLoader(unittest.TestLoader):
+ caseClass = OETestCase
+
+ kwargs_names = ['testMethodPrefix', 'sortTestMethodUsing', 'suiteClass',
+ '_top_level_dir']
+
+ def __init__(self, tc, module_paths, modules, tests, modules_required,
+ *args, **kwargs):
+ self.tc = tc
+
+ self.modules = _built_modules_dict(modules)
+
+ self.tests = tests
+ self.modules_required = modules_required
+
+ self.tags_filter = kwargs.get("tags_filter", None)
+
+ if isinstance(module_paths, str):
+ module_paths = [module_paths]
+ elif not isinstance(module_paths, list):
+ raise TypeError('module_paths must be a str or a list of str')
+ self.module_paths = module_paths
+
+ for kwname in self.kwargs_names:
+ if kwname in kwargs:
+ setattr(self, kwname, kwargs[kwname])
+
+ self._patchCaseClass(self.caseClass)
+
+ super(OETestLoader, self).__init__()
+
+ def _patchCaseClass(self, testCaseClass):
+ # Adds custom attributes to the OETestCase class
+ setattr(testCaseClass, 'tc', self.tc)
+ setattr(testCaseClass, 'td', self.tc.td)
+ setattr(testCaseClass, 'logger', self.tc.logger)
+
+ def _registerTestCase(self, case):
+ case_id = case.id()
+ self.tc._registry['cases'][case_id] = case
+
+ def _handleTestCaseDecorators(self, case):
+ def _handle(obj):
+ if isinstance(obj, OETestDecorator):
+ if not obj.__class__ in decoratorClasses:
+ raise Exception("Decorator %s isn't registered" \
+ " in decoratorClasses." % obj.__name__)
+ obj.bind(self.tc._registry, case)
+
+ def _walk_closure(obj):
+ if hasattr(obj, '__closure__') and obj.__closure__:
+ for f in obj.__closure__:
+ obj = f.cell_contents
+ _handle(obj)
+ _walk_closure(obj)
+ method = getattr(case, case._testMethodName, None)
+ _walk_closure(method)
+
+ def _filterTest(self, case):
+ """
+ Returns True if test case must be filtered, False otherwise.
+ """
+ # XXX; If the module has more than one namespace only use
+ # the first to support run the whole module specifying the
+ # <module_name>.[test_class].[test_name]
+ module_name_small = case.__module__.split('.')[0]
+ module_name = case.__module__
+
+ class_name = case.__class__.__name__
+ test_name = case._testMethodName
+
+ # 'auto' is a reserved key word to run test cases automatically
+ # warn users if their test case belong to a module named 'auto'
+ if module_name_small == "auto":
+ bb.warn("'auto' is a reserved key word for TEST_SUITES. "
+ "But test case '%s' is detected to belong to auto module. "
+ "Please condier using a new name for your module." % str(case))
+
+ # check if case belongs to any specified module
+ # if 'auto' is specified, such check is skipped
+ if self.modules and not 'auto' in self.modules:
+ module = None
+ try:
+ module = self.modules[module_name_small]
+ except KeyError:
+ try:
+ module = self.modules[module_name]
+ except KeyError:
+ return True
+
+ if module:
+ if not class_name in module:
+ return True
+
+ if module[class_name]:
+ if test_name not in module[class_name]:
+ return True
+
+ # Decorator filters
+ if self.tags_filter is not None and callable(self.tags_filter):
+ alltags = set()
+ # pull tags from the case class
+ if hasattr(case, "__oeqa_testtags"):
+ for t in getattr(case, "__oeqa_testtags"):
+ alltags.add(t)
+ # pull tags from the method itself
+ if hasattr(case, test_name):
+ method = getattr(case, test_name)
+ if hasattr(method, "__oeqa_testtags"):
+ for t in getattr(method, "__oeqa_testtags"):
+ alltags.add(t)
+
+ if self.tags_filter(alltags):
+ return True
+
+ return False
+
+ def _getTestCase(self, testCaseClass, tcName):
+ if not hasattr(testCaseClass, '__oeqa_loader') and \
+ issubclass(testCaseClass, OETestCase):
+ # In order to support data_vars validation
+ # monkey patch the default setUp/tearDown{Class} to use
+ # the ones provided by OETestCase
+ setattr(testCaseClass, 'setUpClassMethod',
+ getattr(testCaseClass, 'setUpClass'))
+ setattr(testCaseClass, 'tearDownClassMethod',
+ getattr(testCaseClass, 'tearDownClass'))
+ setattr(testCaseClass, 'setUpClass',
+ testCaseClass._oeSetUpClass)
+ setattr(testCaseClass, 'tearDownClass',
+ testCaseClass._oeTearDownClass)
+
+ # In order to support decorators initialization
+ # monkey patch the default setUp/tearDown to use
+ # a setUpDecorators/tearDownDecorators that methods
+ # will call setUp/tearDown original methods.
+ setattr(testCaseClass, 'setUpMethod',
+ getattr(testCaseClass, 'setUp'))
+ setattr(testCaseClass, 'tearDownMethod',
+ getattr(testCaseClass, 'tearDown'))
+ setattr(testCaseClass, 'setUp', testCaseClass._oeSetUp)
+ setattr(testCaseClass, 'tearDown', testCaseClass._oeTearDown)
+
+ setattr(testCaseClass, '__oeqa_loader', True)
+
+ case = testCaseClass(tcName)
+ if isinstance(case, OETestCase):
+ setattr(case, 'decorators', [])
+
+ return case
+
+ def loadTestsFromTestCase(self, testCaseClass):
+ """
+ Returns a suite of all tests cases contained in testCaseClass.
+ """
+ if issubclass(testCaseClass, unittest.suite.TestSuite):
+ raise TypeError("Test cases should not be derived from TestSuite." \
+ " Maybe you meant to derive %s from TestCase?" \
+ % testCaseClass.__name__)
+ if not issubclass(testCaseClass, unittest.case.TestCase):
+ raise TypeError("Test %s is not derived from %s" % \
+ (testCaseClass.__name__, unittest.case.TestCase.__name__))
+
+ testCaseNames = self.getTestCaseNames(testCaseClass)
+ if not testCaseNames and hasattr(testCaseClass, 'runTest'):
+ testCaseNames = ['runTest']
+
+ suite = []
+ for tcName in testCaseNames:
+ case = self._getTestCase(testCaseClass, tcName)
+ # Filer by case id
+ if not (self.tests and not 'auto' in self.tests
+ and not getCaseID(case) in self.tests):
+ self._handleTestCaseDecorators(case)
+
+ # Filter by decorators
+ if not self._filterTest(case):
+ self._registerTestCase(case)
+ suite.append(case)
+
+ return self.suiteClass(suite)
+
+ def _required_modules_validation(self):
+ """
+ Search in Test context registry if a required
+ test is found, raise an exception when not found.
+ """
+
+ for module in self.modules_required:
+ found = False
+
+ # The module name is splitted to only compare the
+ # first part of a test case id.
+ comp_len = len(module.split('.'))
+ for case in self.tc._registry['cases']:
+ case_comp = '.'.join(case.split('.')[0:comp_len])
+ if module == case_comp:
+ found = True
+ break
+
+ if not found:
+ raise OEQATestNotFound("Not found %s in loaded test cases" % \
+ module)
+
+ def discover(self):
+ big_suite = self.suiteClass()
+ for path in self.module_paths:
+ _find_duplicated_modules(big_suite, path)
+ suite = super(OETestLoader, self).discover(path,
+ pattern='*.py', top_level_dir=path)
+ big_suite.addTests(suite)
+
+ cases = None
+ discover_classes = [clss for clss in decoratorClasses
+ if issubclass(clss, OETestDiscover)]
+ for clss in discover_classes:
+ cases = clss.discover(self.tc._registry)
+
+ if self.modules_required:
+ self._required_modules_validation()
+
+ return self.suiteClass(cases) if cases else big_suite
+
+ def _filterModule(self, module):
+ if module.__name__ in sys.builtin_module_names:
+ msg = 'Tried to import %s test module but is a built-in'
+ raise ImportError(msg % module.__name__)
+
+ # XXX; If the module has more than one namespace only use
+ # the first to support run the whole module specifying the
+ # <module_name>.[test_class].[test_name]
+ module_name_small = module.__name__.split('.')[0]
+ module_name = module.__name__
+
+ # Normal test modules are loaded if no modules were specified,
+ # if module is in the specified module list or if 'auto' is in
+ # module list.
+ # Underscore modules are loaded only if specified in module list.
+ load_module = True if not module_name.startswith('_') \
+ and (not self.modules \
+ or module_name in self.modules \
+ or module_name_small in self.modules \
+ or 'auto' in self.modules) \
+ else False
+
+ load_underscore = True if module_name.startswith('_') \
+ and (module_name in self.modules or \
+ module_name_small in self.modules) \
+ else False
+
+ return (load_module, load_underscore)
+
+
+ # XXX After Python 3.5, remove backward compatibility hacks for
+ # use_load_tests deprecation via *args and **kws. See issue 16662.
+ if sys.version_info >= (3,5):
+ def loadTestsFromModule(self, module, *args, pattern=None, **kws):
+ """
+ Returns a suite of all tests cases contained in module.
+ """
+ load_module, load_underscore = self._filterModule(module)
+
+ if load_module or load_underscore:
+ return super(OETestLoader, self).loadTestsFromModule(
+ module, *args, pattern=pattern, **kws)
+ else:
+ return self.suiteClass()
+ else:
+ def loadTestsFromModule(self, module, use_load_tests=True):
+ """
+ Returns a suite of all tests cases contained in module.
+ """
+ load_module, load_underscore = self._filterModule(module)
+
+ if load_module or load_underscore:
+ return super(OETestLoader, self).loadTestsFromModule(
+ module, use_load_tests)
+ else:
+ return self.suiteClass()
diff --git a/meta/lib/oeqa/core/runner.py b/meta/lib/oeqa/core/runner.py
new file mode 100644
index 0000000000..d50690ab37
--- /dev/null
+++ b/meta/lib/oeqa/core/runner.py
@@ -0,0 +1,353 @@
+#
+# Copyright (C) 2016 Intel Corporation
+#
+# SPDX-License-Identifier: MIT
+#
+
+import os
+import time
+import unittest
+import logging
+import re
+import json
+import sys
+
+from unittest import TextTestResult as _TestResult
+from unittest import TextTestRunner as _TestRunner
+
+class OEStreamLogger(object):
+ def __init__(self, logger):
+ self.logger = logger
+ self.buffer = ""
+
+ def write(self, msg):
+ if len(msg) > 1 and msg[0] != '\n':
+ if '...' in msg:
+ self.buffer += msg
+ elif self.buffer:
+ self.buffer += msg
+ self.logger.log(logging.INFO, self.buffer)
+ self.buffer = ""
+ else:
+ self.logger.log(logging.INFO, msg)
+
+ def flush(self):
+ for handler in self.logger.handlers:
+ handler.flush()
+
+class OETestResult(_TestResult):
+ def __init__(self, tc, *args, **kwargs):
+ super(OETestResult, self).__init__(*args, **kwargs)
+
+ self.successes = []
+ self.starttime = {}
+ self.endtime = {}
+ self.progressinfo = {}
+ self.extraresults = {}
+
+ # Inject into tc so that TestDepends decorator can see results
+ tc.results = self
+
+ self.tc = tc
+
+ # stdout and stderr for each test case
+ self.logged_output = {}
+
+ def startTest(self, test):
+ # May have been set by concurrencytest
+ if test.id() not in self.starttime:
+ self.starttime[test.id()] = time.time()
+ super(OETestResult, self).startTest(test)
+
+ def stopTest(self, test):
+ self.endtime[test.id()] = time.time()
+ if self.buffer:
+ self.logged_output[test.id()] = (
+ sys.stdout.getvalue(), sys.stderr.getvalue())
+ super(OETestResult, self).stopTest(test)
+ if test.id() in self.progressinfo:
+ self.tc.logger.info(self.progressinfo[test.id()])
+
+ # Print the errors/failures early to aid/speed debugging, its a pain
+ # to wait until selftest finishes to see them.
+ for t in ['failures', 'errors', 'skipped', 'expectedFailures']:
+ for (scase, msg) in getattr(self, t):
+ if test.id() == scase.id():
+ self.tc.logger.info(str(msg))
+ break
+
+ def logSummary(self, component, context_msg=''):
+ elapsed_time = self.tc._run_end_time - self.tc._run_start_time
+ self.tc.logger.info("SUMMARY:")
+ self.tc.logger.info("%s (%s) - Ran %d test%s in %.3fs" % (component,
+ context_msg, self.testsRun, self.testsRun != 1 and "s" or "",
+ elapsed_time))
+
+ if self.wasSuccessful():
+ msg = "%s - OK - All required tests passed" % component
+ else:
+ msg = "%s - FAIL - Required tests failed" % component
+ msg += " (successes=%d, skipped=%d, failures=%d, errors=%d)" % (len(self.successes), len(self.skipped), len(self.failures), len(self.errors))
+ self.tc.logger.info(msg)
+
+ def _getTestResultDetails(self, case):
+ result_types = {'failures': 'FAILED', 'errors': 'ERROR', 'skipped': 'SKIPPED',
+ 'expectedFailures': 'EXPECTEDFAIL', 'successes': 'PASSED',
+ 'unexpectedSuccesses' : 'PASSED'}
+
+ for rtype in result_types:
+ found = False
+ for resultclass in getattr(self, rtype):
+ # unexpectedSuccesses are just lists, not lists of tuples
+ if isinstance(resultclass, tuple):
+ scase, msg = resultclass
+ else:
+ scase, msg = resultclass, None
+ if case.id() == scase.id():
+ found = True
+ break
+ scase_str = str(scase.id())
+
+ # When fails at module or class level the class name is passed as string
+ # so figure out to see if match
+ m = re.search(r"^setUpModule \((?P<module_name>.*)\).*$", scase_str)
+ if m:
+ if case.__class__.__module__ == m.group('module_name'):
+ found = True
+ break
+
+ m = re.search(r"^setUpClass \((?P<class_name>.*)\).*$", scase_str)
+ if m:
+ class_name = "%s.%s" % (case.__class__.__module__,
+ case.__class__.__name__)
+
+ if class_name == m.group('class_name'):
+ found = True
+ break
+
+ if found:
+ return result_types[rtype], msg
+
+ return 'UNKNOWN', None
+
+ def extractExtraResults(self, test, details = None):
+ extraresults = None
+ if details is not None and "extraresults" in details:
+ extraresults = details.get("extraresults", {})
+ elif hasattr(test, "extraresults"):
+ extraresults = test.extraresults
+
+ if extraresults is not None:
+ for k, v in extraresults.items():
+ # handle updating already existing entries (e.g. ptestresults.sections)
+ if k in self.extraresults:
+ self.extraresults[k].update(v)
+ else:
+ self.extraresults[k] = v
+
+ def addError(self, test, *args, details = None):
+ self.extractExtraResults(test, details = details)
+ return super(OETestResult, self).addError(test, *args)
+
+ def addFailure(self, test, *args, details = None):
+ self.extractExtraResults(test, details = details)
+ return super(OETestResult, self).addFailure(test, *args)
+
+ def addSuccess(self, test, details = None):
+ #Added so we can keep track of successes too
+ self.successes.append((test, None))
+ self.extractExtraResults(test, details = details)
+ return super(OETestResult, self).addSuccess(test)
+
+ def addExpectedFailure(self, test, *args, details = None):
+ self.extractExtraResults(test, details = details)
+ return super(OETestResult, self).addExpectedFailure(test, *args)
+
+ def addUnexpectedSuccess(self, test, details = None):
+ self.extractExtraResults(test, details = details)
+ return super(OETestResult, self).addUnexpectedSuccess(test)
+
+ def logDetails(self, json_file_dir=None, configuration=None, result_id=None,
+ dump_streams=False):
+ self.tc.logger.info("RESULTS:")
+
+ result = self.extraresults
+ logs = {}
+ if hasattr(self.tc, "extraresults"):
+ result.update(self.tc.extraresults)
+
+ for case_name in self.tc._registry['cases']:
+ case = self.tc._registry['cases'][case_name]
+
+ (status, log) = self._getTestResultDetails(case)
+
+ t = ""
+ duration = 0
+ if case.id() in self.starttime and case.id() in self.endtime:
+ duration = self.endtime[case.id()] - self.starttime[case.id()]
+ t = " (" + "{0:.2f}".format(duration) + "s)"
+
+ if status not in logs:
+ logs[status] = []
+ logs[status].append("RESULTS - %s: %s%s" % (case.id(), status, t))
+ report = {'status': status}
+ if log:
+ report['log'] = log
+ if duration:
+ report['duration'] = duration
+
+ alltags = []
+ # pull tags from the case class
+ if hasattr(case, "__oeqa_testtags"):
+ alltags.extend(getattr(case, "__oeqa_testtags"))
+ # pull tags from the method itself
+ test_name = case._testMethodName
+ if hasattr(case, test_name):
+ method = getattr(case, test_name)
+ if hasattr(method, "__oeqa_testtags"):
+ alltags.extend(getattr(method, "__oeqa_testtags"))
+ if alltags:
+ report['oetags'] = alltags
+
+ if dump_streams and case.id() in self.logged_output:
+ (stdout, stderr) = self.logged_output[case.id()]
+ report['stdout'] = stdout
+ report['stderr'] = stderr
+ result[case.id()] = report
+
+ for i in ['PASSED', 'SKIPPED', 'EXPECTEDFAIL', 'ERROR', 'FAILED', 'UNKNOWN']:
+ if i not in logs:
+ continue
+ for l in logs[i]:
+ self.tc.logger.info(l)
+
+ if json_file_dir:
+ tresultjsonhelper = OETestResultJSONHelper()
+ tresultjsonhelper.dump_testresult_file(json_file_dir, configuration, result_id, result)
+
+ def wasSuccessful(self):
+ # Override as we unexpected successes aren't failures for us
+ return (len(self.failures) == len(self.errors) == 0)
+
+class OEListTestsResult(object):
+ def wasSuccessful(self):
+ return True
+
+class OETestRunner(_TestRunner):
+ streamLoggerClass = OEStreamLogger
+
+ def __init__(self, tc, *args, **kwargs):
+ kwargs['stream'] = self.streamLoggerClass(tc.logger)
+ super(OETestRunner, self).__init__(*args, **kwargs)
+ self.tc = tc
+ self.resultclass = OETestResult
+
+ def _makeResult(self):
+ return self.resultclass(self.tc, self.stream, self.descriptions,
+ self.verbosity)
+
+ def _walk_suite(self, suite, func):
+ for obj in suite:
+ if isinstance(obj, unittest.suite.TestSuite):
+ if len(obj._tests):
+ self._walk_suite(obj, func)
+ elif isinstance(obj, unittest.case.TestCase):
+ func(self.tc.logger, obj)
+ self._walked_cases = self._walked_cases + 1
+
+ def _list_tests_name(self, suite):
+ self._walked_cases = 0
+
+ def _list_cases(logger, case):
+ oetags = []
+ if hasattr(case, '__oeqa_testtags'):
+ oetags = getattr(case, '__oeqa_testtags')
+ if oetags:
+ logger.info("%s (%s)" % (case.id(), ",".join(oetags)))
+ else:
+ logger.info("%s" % (case.id()))
+
+ self.tc.logger.info("Listing all available tests:")
+ self._walked_cases = 0
+ self.tc.logger.info("test (tags)")
+ self.tc.logger.info("-" * 80)
+ self._walk_suite(suite, _list_cases)
+ self.tc.logger.info("-" * 80)
+ self.tc.logger.info("Total found:\t%s" % self._walked_cases)
+
+ def _list_tests_class(self, suite):
+ self._walked_cases = 0
+
+ curr = {}
+ def _list_classes(logger, case):
+ if not 'module' in curr or curr['module'] != case.__module__:
+ curr['module'] = case.__module__
+ logger.info(curr['module'])
+
+ if not 'class' in curr or curr['class'] != \
+ case.__class__.__name__:
+ curr['class'] = case.__class__.__name__
+ logger.info(" -- %s" % curr['class'])
+
+ logger.info(" -- -- %s" % case._testMethodName)
+
+ self.tc.logger.info("Listing all available test classes:")
+ self._walk_suite(suite, _list_classes)
+
+ def _list_tests_module(self, suite):
+ self._walked_cases = 0
+
+ listed = []
+ def _list_modules(logger, case):
+ if not case.__module__ in listed:
+ if case.__module__.startswith('_'):
+ logger.info("%s (hidden)" % case.__module__)
+ else:
+ logger.info(case.__module__)
+ listed.append(case.__module__)
+
+ self.tc.logger.info("Listing all available test modules:")
+ self._walk_suite(suite, _list_modules)
+
+ def list_tests(self, suite, display_type):
+ if display_type == 'name':
+ self._list_tests_name(suite)
+ elif display_type == 'class':
+ self._list_tests_class(suite)
+ elif display_type == 'module':
+ self._list_tests_module(suite)
+
+ return OEListTestsResult()
+
+class OETestResultJSONHelper(object):
+
+ testresult_filename = 'testresults.json'
+
+ def _get_existing_testresults_if_available(self, write_dir):
+ testresults = {}
+ file = os.path.join(write_dir, self.testresult_filename)
+ if os.path.exists(file):
+ with open(file, "r") as f:
+ testresults = json.load(f)
+ return testresults
+
+ def _write_file(self, write_dir, file_name, file_content):
+ file_path = os.path.join(write_dir, file_name)
+ with open(file_path, 'w') as the_file:
+ the_file.write(file_content)
+
+ def dump_testresult_file(self, write_dir, configuration, result_id, test_result):
+ try:
+ import bb
+ has_bb = True
+ bb.utils.mkdirhier(write_dir)
+ lf = bb.utils.lockfile(os.path.join(write_dir, 'jsontestresult.lock'))
+ except ImportError:
+ has_bb = False
+ os.makedirs(write_dir, exist_ok=True)
+ test_results = self._get_existing_testresults_if_available(write_dir)
+ test_results[result_id] = {'configuration': configuration, 'result': test_result}
+ json_testresults = json.dumps(test_results, sort_keys=True, indent=4)
+ self._write_file(write_dir, self.testresult_filename, json_testresults)
+ if has_bb:
+ bb.utils.unlockfile(lf)
diff --git a/meta/lib/oeqa/core/target/__init__.py b/meta/lib/oeqa/core/target/__init__.py
new file mode 100644
index 0000000000..1382aa9b52
--- /dev/null
+++ b/meta/lib/oeqa/core/target/__init__.py
@@ -0,0 +1,36 @@
+#
+# Copyright (C) 2016 Intel Corporation
+#
+# SPDX-License-Identifier: MIT
+#
+
+from abc import abstractmethod
+
+class OETarget(object):
+
+ def __init__(self, logger, *args, **kwargs):
+ self.logger = logger
+
+ @abstractmethod
+ def start(self):
+ pass
+
+ @abstractmethod
+ def stop(self):
+ pass
+
+ @abstractmethod
+ def run(self, cmd, timeout=None):
+ pass
+
+ @abstractmethod
+ def copyTo(self, localSrc, remoteDst):
+ pass
+
+ @abstractmethod
+ def copyFrom(self, remoteSrc, localDst):
+ pass
+
+ @abstractmethod
+ def copyDirTo(self, localSrc, remoteDst):
+ pass
diff --git a/meta/lib/oeqa/core/target/qemu.py b/meta/lib/oeqa/core/target/qemu.py
new file mode 100644
index 0000000000..79fd724f7d
--- /dev/null
+++ b/meta/lib/oeqa/core/target/qemu.py
@@ -0,0 +1,105 @@
+#
+# Copyright (C) 2016 Intel Corporation
+#
+# SPDX-License-Identifier: MIT
+#
+
+import os
+import sys
+import signal
+import time
+import glob
+import subprocess
+from collections import defaultdict
+
+from .ssh import OESSHTarget
+from oeqa.utils.qemurunner import QemuRunner
+from oeqa.utils.dump import MonitorDumper
+from oeqa.utils.dump import TargetDumper
+
+supported_fstypes = ['ext3', 'ext4', 'cpio.gz', 'wic']
+
+class OEQemuTarget(OESSHTarget):
+ def __init__(self, logger, server_ip, timeout=300, user='root',
+ port=None, machine='', rootfs='', kernel='', kvm=False, slirp=False,
+ dump_dir='', dump_host_cmds='', display='', bootlog='',
+ tmpdir='', dir_image='', boottime=60, serial_ports=2,
+ boot_patterns = defaultdict(str), ovmf=False, tmpfsdir=None, **kwargs):
+
+ super(OEQemuTarget, self).__init__(logger, None, server_ip, timeout,
+ user, port)
+
+ self.server_ip = server_ip
+ self.server_port = 0
+ self.machine = machine
+ self.rootfs = rootfs
+ self.kernel = kernel
+ self.kvm = kvm
+ self.ovmf = ovmf
+ self.use_slirp = slirp
+ self.boot_patterns = boot_patterns
+ self.dump_dir = dump_dir
+ self.bootlog = bootlog
+
+ self.runner = QemuRunner(machine=machine, rootfs=rootfs, tmpdir=tmpdir,
+ deploy_dir_image=dir_image, display=display,
+ logfile=bootlog, boottime=boottime,
+ use_kvm=kvm, use_slirp=slirp, dump_dir=dump_dir,
+ dump_host_cmds=dump_host_cmds, logger=logger,
+ serial_ports=serial_ports, boot_patterns = boot_patterns,
+ use_ovmf=ovmf, tmpfsdir=tmpfsdir)
+ dump_monitor_cmds = kwargs.get("testimage_dump_monitor")
+ self.monitor_dumper = MonitorDumper(dump_monitor_cmds, dump_dir, self.runner)
+ if self.monitor_dumper:
+ self.monitor_dumper.create_dir("qmp")
+
+ dump_target_cmds = kwargs.get("testimage_dump_target")
+ self.target_dumper = TargetDumper(dump_target_cmds, dump_dir, self.runner)
+ self.target_dumper.create_dir("qemu")
+
+ def start(self, params=None, extra_bootparams=None, runqemuparams=''):
+ if self.use_slirp and not self.server_ip:
+ self.logger.error("Could not start qemu with slirp without server ip - provide 'TEST_SERVER_IP'")
+ raise RuntimeError("FAILED to start qemu - check the task log and the boot log")
+ if self.runner.start(params, extra_bootparams=extra_bootparams, runqemuparams=runqemuparams):
+ self.ip = self.runner.ip
+ if self.use_slirp:
+ target_ip_port = self.runner.ip.split(':')
+ if len(target_ip_port) == 2:
+ target_ip = target_ip_port[0]
+ port = target_ip_port[1]
+ self.ip = target_ip
+ self.ssh = self.ssh + ['-p', port]
+ self.scp = self.scp + ['-P', port]
+ else:
+ self.logger.error("Could not get host machine port to connect qemu with slirp, ssh will not be "
+ "able to connect to qemu with slirp")
+ if self.runner.server_ip:
+ self.server_ip = self.runner.server_ip
+ else:
+ self.stop()
+ # Display the first 20 lines of top and
+ # last 20 lines of the bootlog when the
+ # target is not being booted up.
+ topfile = glob.glob(self.dump_dir + "/*_qemu/host_*_top")
+ msg = "\n\n===== start: snippet =====\n\n"
+ for f in topfile:
+ msg += "file: %s\n\n" % f
+ with open(f) as tf:
+ for x in range(20):
+ msg += next(tf)
+ msg += "\n\n===== end: snippet =====\n\n"
+ blcmd = ["tail", "-20", self.bootlog]
+ msg += "===== start: snippet =====\n\n"
+ try:
+ out = subprocess.check_output(blcmd, stderr=subprocess.STDOUT, timeout=1).decode('utf-8')
+ msg += "file: %s\n\n" % self.bootlog
+ msg += out
+ except (subprocess.CalledProcessError, subprocess.TimeoutExpired, FileNotFoundError) as err:
+ msg += "Error running command: %s\n%s\n" % (blcmd, err)
+ msg += "\n\n===== end: snippet =====\n"
+
+ raise RuntimeError("FAILED to start qemu - check the task log and the boot log %s" % (msg))
+
+ def stop(self):
+ self.runner.stop()
diff --git a/meta/lib/oeqa/core/target/ssh.py b/meta/lib/oeqa/core/target/ssh.py
new file mode 100644
index 0000000000..2597256c91
--- /dev/null
+++ b/meta/lib/oeqa/core/target/ssh.py
@@ -0,0 +1,295 @@
+#
+# Copyright (C) 2016 Intel Corporation
+#
+# SPDX-License-Identifier: MIT
+#
+
+import os
+import time
+import select
+import logging
+import subprocess
+import codecs
+
+from . import OETarget
+
+class OESSHTarget(OETarget):
+ def __init__(self, logger, ip, server_ip, timeout=300, user='root',
+ port=None, server_port=0, **kwargs):
+ if not logger:
+ logger = logging.getLogger('target')
+ logger.setLevel(logging.INFO)
+ filePath = os.path.join(os.getcwd(), 'remoteTarget.log')
+ fileHandler = logging.FileHandler(filePath, 'w', 'utf-8')
+ formatter = logging.Formatter(
+ '%(asctime)s.%(msecs)03d %(levelname)s: %(message)s',
+ '%H:%M:%S')
+ fileHandler.setFormatter(formatter)
+ logger.addHandler(fileHandler)
+
+ super(OESSHTarget, self).__init__(logger)
+ self.ip = ip
+ self.server_ip = server_ip
+ self.server_port = server_port
+ self.timeout = timeout
+ self.user = user
+ ssh_options = [
+ '-o', 'ServerAliveCountMax=2',
+ '-o', 'ServerAliveInterval=30',
+ '-o', 'UserKnownHostsFile=/dev/null',
+ '-o', 'StrictHostKeyChecking=no',
+ '-o', 'LogLevel=ERROR'
+ ]
+ self.ssh = ['ssh', '-l', self.user ] + ssh_options
+ self.scp = ['scp'] + ssh_options
+ if port:
+ self.ssh = self.ssh + [ '-p', port ]
+ self.scp = self.scp + [ '-P', port ]
+ self._monitor_dumper = None
+ self.target_dumper = None
+
+ def start(self, **kwargs):
+ pass
+
+ def stop(self, **kwargs):
+ pass
+
+ @property
+ def monitor_dumper(self):
+ return self._monitor_dumper
+
+ @monitor_dumper.setter
+ def monitor_dumper(self, dumper):
+ self._monitor_dumper = dumper
+ self.monitor_dumper.dump_monitor()
+
+ def _run(self, command, timeout=None, ignore_status=True):
+ """
+ Runs command in target using SSHProcess.
+ """
+ self.logger.debug("[Running]$ %s" % " ".join(command))
+
+ starttime = time.time()
+ status, output = SSHCall(command, self.logger, timeout)
+ self.logger.debug("[Command returned '%d' after %.2f seconds]"
+ "" % (status, time.time() - starttime))
+
+ if status and not ignore_status:
+ raise AssertionError("Command '%s' returned non-zero exit "
+ "status %d:\n%s" % (command, status, output))
+
+ return (status, output)
+
+ def run(self, command, timeout=None, ignore_status=True):
+ """
+ Runs command in target.
+
+ command: Command to run on target.
+ timeout: <value>: Kill command after <val> seconds.
+ None: Kill command default value seconds.
+ 0: No timeout, runs until return.
+ """
+ targetCmd = 'export PATH=/usr/sbin:/sbin:/usr/bin:/bin; %s' % command
+ sshCmd = self.ssh + [self.ip, targetCmd]
+
+ if timeout:
+ processTimeout = timeout
+ elif timeout==0:
+ processTimeout = None
+ else:
+ processTimeout = self.timeout
+
+ status, output = self._run(sshCmd, processTimeout, ignore_status)
+ self.logger.debug('Command: %s\nStatus: %d Output: %s\n' % (command, status, output))
+ if (status == 255) and (('No route to host') in output):
+ if self.monitor_dumper:
+ self.monitor_dumper.dump_monitor()
+ if status == 255:
+ if self.target_dumper:
+ self.target_dumper.dump_target()
+ if self.monitor_dumper:
+ self.monitor_dumper.dump_monitor()
+ return (status, output)
+
+ def copyTo(self, localSrc, remoteDst):
+ """
+ Copy file to target.
+
+ If local file is symlink, recreate symlink in target.
+ """
+ if os.path.islink(localSrc):
+ link = os.readlink(localSrc)
+ dstDir, dstBase = os.path.split(remoteDst)
+ sshCmd = 'cd %s; ln -s %s %s' % (dstDir, link, dstBase)
+ return self.run(sshCmd)
+
+ else:
+ remotePath = '%s@%s:%s' % (self.user, self.ip, remoteDst)
+ scpCmd = self.scp + [localSrc, remotePath]
+ return self._run(scpCmd, ignore_status=False)
+
+ def copyFrom(self, remoteSrc, localDst, warn_on_failure=False):
+ """
+ Copy file from target.
+ """
+ remotePath = '%s@%s:%s' % (self.user, self.ip, remoteSrc)
+ scpCmd = self.scp + [remotePath, localDst]
+ (status, output) = self._run(scpCmd, ignore_status=warn_on_failure)
+ if warn_on_failure and status:
+ self.logger.warning("Copy returned non-zero exit status %d:\n%s" % (status, output))
+ return (status, output)
+
+ def copyDirTo(self, localSrc, remoteDst):
+ """
+ Copy recursively localSrc directory to remoteDst in target.
+ """
+
+ for root, dirs, files in os.walk(localSrc):
+ # Create directories in the target as needed
+ for d in dirs:
+ tmpDir = os.path.join(root, d).replace(localSrc, "")
+ newDir = os.path.join(remoteDst, tmpDir.lstrip("/"))
+ cmd = "mkdir -p %s" % newDir
+ self.run(cmd)
+
+ # Copy files into the target
+ for f in files:
+ tmpFile = os.path.join(root, f).replace(localSrc, "")
+ dstFile = os.path.join(remoteDst, tmpFile.lstrip("/"))
+ srcFile = os.path.join(root, f)
+ self.copyTo(srcFile, dstFile)
+
+ def deleteFiles(self, remotePath, files):
+ """
+ Deletes files in target's remotePath.
+ """
+
+ cmd = "rm"
+ if not isinstance(files, list):
+ files = [files]
+
+ for f in files:
+ cmd = "%s %s" % (cmd, os.path.join(remotePath, f))
+
+ self.run(cmd)
+
+
+ def deleteDir(self, remotePath):
+ """
+ Deletes target's remotePath directory.
+ """
+
+ cmd = "rmdir %s" % remotePath
+ self.run(cmd)
+
+
+ def deleteDirStructure(self, localPath, remotePath):
+ """
+ Delete recursively localPath structure directory in target's remotePath.
+
+ This function is very usefult to delete a package that is installed in
+ the DUT and the host running the test has such package extracted in tmp
+ directory.
+
+ Example:
+ pwd: /home/user/tmp
+ tree: .
+ └── work
+ ├── dir1
+ │   └── file1
+ └── dir2
+
+ localpath = "/home/user/tmp" and remotepath = "/home/user"
+
+ With the above variables this function will try to delete the
+ directory in the DUT in this order:
+ /home/user/work/dir1/file1
+ /home/user/work/dir1 (if dir is empty)
+ /home/user/work/dir2 (if dir is empty)
+ /home/user/work (if dir is empty)
+ """
+
+ for root, dirs, files in os.walk(localPath, topdown=False):
+ # Delete files first
+ tmpDir = os.path.join(root).replace(localPath, "")
+ remoteDir = os.path.join(remotePath, tmpDir.lstrip("/"))
+ self.deleteFiles(remoteDir, files)
+
+ # Remove dirs if empty
+ for d in dirs:
+ tmpDir = os.path.join(root, d).replace(localPath, "")
+ remoteDir = os.path.join(remotePath, tmpDir.lstrip("/"))
+ self.deleteDir(remoteDir)
+
+def SSHCall(command, logger, timeout=None, **opts):
+
+ def run():
+ nonlocal output
+ nonlocal process
+ starttime = time.time()
+ process = subprocess.Popen(command, **options)
+ if timeout:
+ endtime = starttime + timeout
+ eof = False
+ while time.time() < endtime and not eof:
+ logger.debug('time: %s, endtime: %s' % (time.time(), endtime))
+ try:
+ if select.select([process.stdout], [], [], 5)[0] != []:
+ reader = codecs.getreader('utf-8')(process.stdout, 'ignore')
+ data = reader.read(1024, 4096)
+ if not data:
+ process.stdout.close()
+ eof = True
+ else:
+ output += data
+ logger.debug('Partial data from SSH call:\n%s' % data)
+ endtime = time.time() + timeout
+ except InterruptedError:
+ continue
+
+ # process hasn't returned yet
+ if not eof:
+ process.terminate()
+ time.sleep(5)
+ try:
+ process.kill()
+ except OSError:
+ pass
+ endtime = time.time() - starttime
+ lastline = ("\nProcess killed - no output for %d seconds. Total"
+ " running time: %d seconds." % (timeout, endtime))
+ logger.debug('Received data from SSH call:\n%s ' % lastline)
+ output += lastline
+
+ else:
+ output = process.communicate()[0].decode('utf-8', errors='ignore')
+ logger.debug('Data from SSH call:\n%s' % output.rstrip())
+
+ options = {
+ "stdout": subprocess.PIPE,
+ "stderr": subprocess.STDOUT,
+ "stdin": None,
+ "shell": False,
+ "bufsize": -1,
+ "start_new_session": True,
+ }
+ options.update(opts)
+ output = ''
+ process = None
+
+ # Unset DISPLAY which means we won't trigger SSH_ASKPASS
+ env = os.environ.copy()
+ if "DISPLAY" in env:
+ del env['DISPLAY']
+ options['env'] = env
+
+ try:
+ run()
+ except:
+ # Need to guard against a SystemExit or other exception ocurring
+ # whilst running and ensure we don't leave a process behind.
+ if process.poll() is None:
+ process.kill()
+ logger.debug('Something went wrong, killing SSH process')
+ raise
+ return (process.wait(), output.rstrip())
diff --git a/meta/lib/oeqa/core/tests/__init__.py b/meta/lib/oeqa/core/tests/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/meta/lib/oeqa/core/tests/__init__.py
diff --git a/meta/lib/oeqa/core/tests/cases/data.py b/meta/lib/oeqa/core/tests/cases/data.py
new file mode 100644
index 0000000000..61f88547f7
--- /dev/null
+++ b/meta/lib/oeqa/core/tests/cases/data.py
@@ -0,0 +1,23 @@
+#
+# Copyright (C) 2016 Intel Corporation
+#
+# SPDX-License-Identifier: MIT
+#
+
+from oeqa.core.case import OETestCase
+from oeqa.core.decorator import OETestTag
+from oeqa.core.decorator.data import OETestDataDepends
+
+class DataTest(OETestCase):
+ data_vars = ['IMAGE', 'ARCH']
+
+ @OETestDataDepends(['MACHINE',])
+ @OETestTag('dataTestOk')
+ def testDataOk(self):
+ self.assertEqual(self.td.get('IMAGE'), 'core-image-minimal')
+ self.assertEqual(self.td.get('ARCH'), 'x86')
+ self.assertEqual(self.td.get('MACHINE'), 'qemuarm')
+
+ @OETestTag('dataTestFail')
+ def testDataFail(self):
+ pass
diff --git a/meta/lib/oeqa/core/tests/cases/depends.py b/meta/lib/oeqa/core/tests/cases/depends.py
new file mode 100644
index 0000000000..46e7db900d
--- /dev/null
+++ b/meta/lib/oeqa/core/tests/cases/depends.py
@@ -0,0 +1,41 @@
+#
+# Copyright (C) 2016 Intel Corporation
+#
+# SPDX-License-Identifier: MIT
+#
+
+from oeqa.core.case import OETestCase
+from oeqa.core.decorator.depends import OETestDepends
+
+class DependsTest(OETestCase):
+
+ def testDependsFirst(self):
+ self.assertTrue(True, msg='How is this possible?')
+
+ @OETestDepends(['testDependsFirst'])
+ def testDependsSecond(self):
+ self.assertTrue(True, msg='How is this possible?')
+
+ @OETestDepends(['testDependsSecond'])
+ def testDependsThird(self):
+ self.assertTrue(True, msg='How is this possible?')
+
+ @OETestDepends(['testDependsSecond'])
+ def testDependsFourth(self):
+ self.assertTrue(True, msg='How is this possible?')
+
+ @OETestDepends(['testDependsThird', 'testDependsFourth'])
+ def testDependsFifth(self):
+ self.assertTrue(True, msg='How is this possible?')
+
+ @OETestDepends(['testDependsCircular3'])
+ def testDependsCircular1(self):
+ self.assertTrue(True, msg='How is this possible?')
+
+ @OETestDepends(['testDependsCircular1'])
+ def testDependsCircular2(self):
+ self.assertTrue(True, msg='How is this possible?')
+
+ @OETestDepends(['testDependsCircular2'])
+ def testDependsCircular3(self):
+ self.assertTrue(True, msg='How is this possible?')
diff --git a/meta/lib/oeqa/core/tests/cases/loader/valid/another.py b/meta/lib/oeqa/core/tests/cases/loader/valid/another.py
new file mode 100644
index 0000000000..bedc20c8a6
--- /dev/null
+++ b/meta/lib/oeqa/core/tests/cases/loader/valid/another.py
@@ -0,0 +1,12 @@
+#
+# Copyright (C) 2016 Intel Corporation
+#
+# SPDX-License-Identifier: MIT
+#
+
+from oeqa.core.case import OETestCase
+
+class AnotherTest(OETestCase):
+
+ def testAnother(self):
+ self.assertTrue(True, msg='How is this possible?')
diff --git a/meta/lib/oeqa/core/tests/cases/oetag.py b/meta/lib/oeqa/core/tests/cases/oetag.py
new file mode 100644
index 0000000000..52f97dfda6
--- /dev/null
+++ b/meta/lib/oeqa/core/tests/cases/oetag.py
@@ -0,0 +1,38 @@
+#
+# Copyright (C) 2016 Intel Corporation
+#
+# SPDX-License-Identifier: MIT
+#
+
+from oeqa.core.case import OETestCase
+from oeqa.core.decorator import OETestTag
+
+class TagTest(OETestCase):
+ @OETestTag('goodTag')
+ def testTagGood(self):
+ self.assertTrue(True, msg='How is this possible?')
+
+ @OETestTag('otherTag')
+ def testTagOther(self):
+ self.assertTrue(True, msg='How is this possible?')
+
+ @OETestTag('otherTag', 'multiTag')
+ def testTagOtherMulti(self):
+ self.assertTrue(True, msg='How is this possible?')
+
+ def testTagNone(self):
+ self.assertTrue(True, msg='How is this possible?')
+
+@OETestTag('classTag')
+class TagClassTest(OETestCase):
+ @OETestTag('otherTag')
+ def testTagOther(self):
+ self.assertTrue(True, msg='How is this possible?')
+
+ @OETestTag('otherTag', 'multiTag')
+ def testTagOtherMulti(self):
+ self.assertTrue(True, msg='How is this possible?')
+
+ def testTagNone(self):
+ self.assertTrue(True, msg='How is this possible?')
+
diff --git a/meta/lib/oeqa/core/tests/cases/timeout.py b/meta/lib/oeqa/core/tests/cases/timeout.py
new file mode 100644
index 0000000000..69cf969a67
--- /dev/null
+++ b/meta/lib/oeqa/core/tests/cases/timeout.py
@@ -0,0 +1,34 @@
+#
+# Copyright (C) 2016 Intel Corporation
+#
+# SPDX-License-Identifier: MIT
+#
+
+from time import sleep
+
+from oeqa.core.case import OETestCase
+from oeqa.core.decorator.oetimeout import OETimeout
+from oeqa.core.decorator.depends import OETestDepends
+
+class TimeoutTest(OETestCase):
+
+ @OETimeout(1)
+ def testTimeoutPass(self):
+ self.assertTrue(True, msg='How is this possible?')
+
+ @OETimeout(1)
+ def testTimeoutFail(self):
+ sleep(2)
+ self.assertTrue(True, msg='How is this possible?')
+
+
+ def testTimeoutSkip(self):
+ self.skipTest("This test needs to be skipped, so that testTimeoutDepends()'s OETestDepends kicks in")
+
+ @OETestDepends(["timeout.TimeoutTest.testTimeoutSkip"])
+ @OETimeout(3)
+ def testTimeoutDepends(self):
+ self.assertTrue(False, msg='How is this possible?')
+
+ def testTimeoutUnrelated(self):
+ sleep(6)
diff --git a/meta/lib/oeqa/core/tests/common.py b/meta/lib/oeqa/core/tests/common.py
new file mode 100644
index 0000000000..88cc758ad3
--- /dev/null
+++ b/meta/lib/oeqa/core/tests/common.py
@@ -0,0 +1,38 @@
+#
+# Copyright (C) 2016 Intel Corporation
+#
+# SPDX-License-Identifier: MIT
+#
+
+import sys
+import os
+
+import unittest
+import logging
+import os
+
+logger = logging.getLogger("oeqa")
+logger.setLevel(logging.INFO)
+consoleHandler = logging.StreamHandler()
+formatter = logging.Formatter('OEQATest: %(message)s')
+consoleHandler.setFormatter(formatter)
+logger.addHandler(consoleHandler)
+
+def setup_sys_path():
+ directory = os.path.dirname(os.path.abspath(__file__))
+ oeqa_lib = os.path.realpath(os.path.join(directory, '../../../'))
+ if not oeqa_lib in sys.path:
+ sys.path.insert(0, oeqa_lib)
+
+class TestBase(unittest.TestCase):
+ def setUp(self):
+ self.logger = logger
+ directory = os.path.dirname(os.path.abspath(__file__))
+ self.cases_path = os.path.join(directory, 'cases')
+
+ def _testLoader(self, d={}, modules=[], tests=[], **kwargs):
+ from oeqa.core.context import OETestContext
+ tc = OETestContext(d, self.logger)
+ tc.loadTests(self.cases_path, modules=modules, tests=tests,
+ **kwargs)
+ return tc
diff --git a/meta/lib/oeqa/core/tests/test_data.py b/meta/lib/oeqa/core/tests/test_data.py
new file mode 100755
index 0000000000..acd726f3a0
--- /dev/null
+++ b/meta/lib/oeqa/core/tests/test_data.py
@@ -0,0 +1,55 @@
+#!/usr/bin/env python3
+
+# Copyright (C) 2016 Intel Corporation
+#
+# SPDX-License-Identifier: MIT
+#
+
+import unittest
+import logging
+import os
+
+from common import setup_sys_path, TestBase
+setup_sys_path()
+
+from oeqa.core.exception import OEQAMissingVariable
+from oeqa.core.utils.test import getCaseMethod, getSuiteCasesNames
+
+class TestData(TestBase):
+ modules = ['data']
+
+ def test_data_fail_missing_variable(self):
+ expectedException = "oeqa.core.exception.OEQAMissingVariable"
+
+ tc = self._testLoader(modules=self.modules)
+ results = tc.runTests()
+ self.assertFalse(results.wasSuccessful())
+ for test, data in results.errors:
+ expect = False
+ if expectedException in data:
+ expect = True
+
+ self.assertTrue(expect)
+
+ def test_data_fail_wrong_variable(self):
+ expectedError = 'AssertionError'
+ d = {'IMAGE' : 'core-image-weston', 'ARCH' : 'arm'}
+
+ tc = self._testLoader(d=d, modules=self.modules)
+ results = tc.runTests()
+ self.assertFalse(results.wasSuccessful())
+ for test, data in results.failures:
+ expect = False
+ if expectedError in data:
+ expect = True
+
+ self.assertTrue(expect)
+
+ def test_data_ok(self):
+ d = {'IMAGE' : 'core-image-minimal', 'ARCH' : 'x86', 'MACHINE' : 'qemuarm'}
+
+ tc = self._testLoader(d=d, modules=self.modules)
+ self.assertEqual(True, tc.runTests().wasSuccessful())
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/meta/lib/oeqa/core/tests/test_decorators.py b/meta/lib/oeqa/core/tests/test_decorators.py
new file mode 100755
index 0000000000..5095f39948
--- /dev/null
+++ b/meta/lib/oeqa/core/tests/test_decorators.py
@@ -0,0 +1,143 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2016 Intel Corporation
+#
+# SPDX-License-Identifier: MIT
+#
+
+import signal
+import unittest
+
+from common import setup_sys_path, TestBase
+setup_sys_path()
+
+from oeqa.core.exception import OEQADependency
+from oeqa.core.utils.test import getCaseMethod, getSuiteCasesNames, getSuiteCasesIDs
+
+class TestTagDecorator(TestBase):
+ def _runTest(self, modules, filterfn, expect):
+ tc = self._testLoader(modules = modules, tags_filter = filterfn)
+ test_loaded = set(getSuiteCasesIDs(tc.suites))
+ self.assertEqual(expect, test_loaded)
+
+ def test_oetag(self):
+ # get all cases without any filtering
+ self._runTest(['oetag'], None, {
+ 'oetag.TagTest.testTagGood',
+ 'oetag.TagTest.testTagOther',
+ 'oetag.TagTest.testTagOtherMulti',
+ 'oetag.TagTest.testTagNone',
+ 'oetag.TagClassTest.testTagOther',
+ 'oetag.TagClassTest.testTagOtherMulti',
+ 'oetag.TagClassTest.testTagNone',
+ })
+
+ # exclude any case with tags
+ self._runTest(['oetag'], lambda tags: tags, {
+ 'oetag.TagTest.testTagNone',
+ })
+
+ # exclude any case with otherTag
+ self._runTest(['oetag'], lambda tags: "otherTag" in tags, {
+ 'oetag.TagTest.testTagGood',
+ 'oetag.TagTest.testTagNone',
+ 'oetag.TagClassTest.testTagNone',
+ })
+
+ # exclude any case with classTag
+ self._runTest(['oetag'], lambda tags: "classTag" in tags, {
+ 'oetag.TagTest.testTagGood',
+ 'oetag.TagTest.testTagOther',
+ 'oetag.TagTest.testTagOtherMulti',
+ 'oetag.TagTest.testTagNone',
+ })
+
+ # include any case with classTag
+ self._runTest(['oetag'], lambda tags: "classTag" not in tags, {
+ 'oetag.TagClassTest.testTagOther',
+ 'oetag.TagClassTest.testTagOtherMulti',
+ 'oetag.TagClassTest.testTagNone',
+ })
+
+ # include any case with classTag or no tags
+ self._runTest(['oetag'], lambda tags: tags and "classTag" not in tags, {
+ 'oetag.TagTest.testTagNone',
+ 'oetag.TagClassTest.testTagOther',
+ 'oetag.TagClassTest.testTagOtherMulti',
+ 'oetag.TagClassTest.testTagNone',
+ })
+
+class TestDependsDecorator(TestBase):
+ modules = ['depends']
+
+ def test_depends_order(self):
+ tests = ['depends.DependsTest.testDependsFirst',
+ 'depends.DependsTest.testDependsSecond',
+ 'depends.DependsTest.testDependsThird',
+ 'depends.DependsTest.testDependsFourth',
+ 'depends.DependsTest.testDependsFifth']
+ tests2 = list(tests)
+ tests2[2], tests2[3] = tests[3], tests[2]
+ tc = self._testLoader(modules=self.modules, tests=tests)
+ test_loaded = getSuiteCasesIDs(tc.suites)
+ result = True if test_loaded == tests or test_loaded == tests2 else False
+ msg = 'Failed to order tests using OETestDepends decorator.\nTest order:'\
+ ' %s.\nExpected: %s\nOr: %s' % (test_loaded, tests, tests2)
+ self.assertTrue(result, msg=msg)
+
+ def test_depends_fail_missing_dependency(self):
+ expect = "TestCase depends.DependsTest.testDependsSecond depends on "\
+ "depends.DependsTest.testDependsFirst and isn't available"
+ tests = ['depends.DependsTest.testDependsSecond']
+ try:
+ # Must throw OEQADependency because missing 'testDependsFirst'
+ tc = self._testLoader(modules=self.modules, tests=tests)
+ self.fail('Expected OEQADependency exception')
+ except OEQADependency as e:
+ result = True if expect in str(e) else False
+ msg = 'Expected OEQADependency exception missing testDependsFirst test'
+ self.assertTrue(result, msg=msg)
+
+ def test_depends_fail_circular_dependency(self):
+ expect = 'have a circular dependency'
+ tests = ['depends.DependsTest.testDependsCircular1',
+ 'depends.DependsTest.testDependsCircular2',
+ 'depends.DependsTest.testDependsCircular3']
+ try:
+ # Must throw OEQADependency because circular dependency
+ tc = self._testLoader(modules=self.modules, tests=tests)
+ self.fail('Expected OEQADependency exception')
+ except OEQADependency as e:
+ result = True if expect in str(e) else False
+ msg = 'Expected OEQADependency exception having a circular dependency'
+ self.assertTrue(result, msg=msg)
+
+class TestTimeoutDecorator(TestBase):
+ modules = ['timeout']
+
+ def test_timeout(self):
+ tests = ['timeout.TimeoutTest.testTimeoutPass']
+ msg = 'Failed to run test using OETestTimeout'
+ alarm_signal = signal.getsignal(signal.SIGALRM)
+ tc = self._testLoader(modules=self.modules, tests=tests)
+ self.assertTrue(tc.runTests().wasSuccessful(), msg=msg)
+ msg = "OETestTimeout didn't restore SIGALRM"
+ self.assertIs(alarm_signal, signal.getsignal(signal.SIGALRM), msg=msg)
+
+ def test_timeout_fail(self):
+ tests = ['timeout.TimeoutTest.testTimeoutFail']
+ msg = "OETestTimeout test didn't timeout as expected"
+ alarm_signal = signal.getsignal(signal.SIGALRM)
+ tc = self._testLoader(modules=self.modules, tests=tests)
+ self.assertFalse(tc.runTests().wasSuccessful(), msg=msg)
+ msg = "OETestTimeout didn't restore SIGALRM"
+ self.assertIs(alarm_signal, signal.getsignal(signal.SIGALRM), msg=msg)
+
+ def test_timeout_cancel(self):
+ tests = ['timeout.TimeoutTest.testTimeoutSkip', 'timeout.TimeoutTest.testTimeoutDepends', 'timeout.TimeoutTest.testTimeoutUnrelated']
+ msg = 'Unrelated test failed to complete'
+ tc = self._testLoader(modules=self.modules, tests=tests)
+ self.assertTrue(tc.runTests().wasSuccessful(), msg=msg)
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/meta/lib/oeqa/core/tests/test_loader.py b/meta/lib/oeqa/core/tests/test_loader.py
new file mode 100755
index 0000000000..cb38ac845e
--- /dev/null
+++ b/meta/lib/oeqa/core/tests/test_loader.py
@@ -0,0 +1,63 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2016 Intel Corporation
+#
+# SPDX-License-Identifier: MIT
+#
+
+import os
+import unittest
+
+from common import setup_sys_path, TestBase
+setup_sys_path()
+
+from oeqa.core.exception import OEQADependency
+from oeqa.core.utils.test import getSuiteModules, getSuiteCasesIDs
+
+class TestLoader(TestBase):
+ @unittest.skip("invalid directory is missing oetag.py")
+ def test_fail_duplicated_module(self):
+ cases_path = self.cases_path
+ invalid_path = os.path.join(cases_path, 'loader', 'invalid')
+ self.cases_path = [self.cases_path, invalid_path]
+ expect = 'Duplicated oetag module found in'
+ msg = 'Expected ImportError exception for having duplicated module'
+ try:
+ # Must throw ImportEror because duplicated module
+ tc = self._testLoader()
+ self.fail(msg)
+ except ImportError as e:
+ result = True if expect in str(e) else False
+ self.assertTrue(result, msg=msg)
+ finally:
+ self.cases_path = cases_path
+
+ def test_filter_modules(self):
+ expected_modules = {'oetag'}
+ tc = self._testLoader(modules=expected_modules)
+ modules = getSuiteModules(tc.suites)
+ msg = 'Expected just %s modules' % ', '.join(expected_modules)
+ self.assertEqual(modules, expected_modules, msg=msg)
+
+ def test_filter_cases(self):
+ modules = ['oetag', 'data']
+ expected_cases = {'data.DataTest.testDataOk',
+ 'oetag.TagTest.testTagGood'}
+ tc = self._testLoader(modules=modules, tests=expected_cases)
+ cases = set(getSuiteCasesIDs(tc.suites))
+ msg = 'Expected just %s cases' % ', '.join(expected_cases)
+ self.assertEqual(cases, expected_cases, msg=msg)
+
+ def test_import_from_paths(self):
+ cases_path = self.cases_path
+ cases2_path = os.path.join(cases_path, 'loader', 'valid')
+ expected_modules = {'another'}
+ self.cases_path = [self.cases_path, cases2_path]
+ tc = self._testLoader(modules=expected_modules)
+ modules = getSuiteModules(tc.suites)
+ self.cases_path = cases_path
+ msg = 'Expected modules from two different paths'
+ self.assertEqual(modules, expected_modules, msg=msg)
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/meta/lib/oeqa/core/tests/test_runner.py b/meta/lib/oeqa/core/tests/test_runner.py
new file mode 100755
index 0000000000..205464cfae
--- /dev/null
+++ b/meta/lib/oeqa/core/tests/test_runner.py
@@ -0,0 +1,40 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2016 Intel Corporation
+#
+# SPDX-License-Identifier: MIT
+#
+
+import unittest
+import logging
+import tempfile
+
+from common import setup_sys_path, TestBase
+setup_sys_path()
+
+from oeqa.core.runner import OEStreamLogger
+
+class TestRunner(TestBase):
+ def test_stream_logger(self):
+ fp = tempfile.TemporaryFile(mode='w+')
+
+ logging.basicConfig(format='%(message)s', stream=fp)
+ logger = logging.getLogger()
+ logger.setLevel(logging.INFO)
+
+ oeSL = OEStreamLogger(logger)
+
+ lines = ['init', 'bigline_' * 65535, 'morebigline_' * 65535 * 4, 'end']
+ for line in lines:
+ oeSL.write(line)
+
+ fp.seek(0)
+ fp_lines = fp.readlines()
+ for i, fp_line in enumerate(fp_lines):
+ fp_line = fp_line.strip()
+ self.assertEqual(lines[i], fp_line)
+
+ fp.close()
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/meta/lib/oeqa/core/utils/__init__.py b/meta/lib/oeqa/core/utils/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/meta/lib/oeqa/core/utils/__init__.py
diff --git a/meta/lib/oeqa/core/utils/concurrencytest.py b/meta/lib/oeqa/core/utils/concurrencytest.py
new file mode 100644
index 0000000000..4f77589b00
--- /dev/null
+++ b/meta/lib/oeqa/core/utils/concurrencytest.py
@@ -0,0 +1,335 @@
+#!/usr/bin/env python3
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+#
+# Modified for use in OE by Richard Purdie, 2018
+#
+# Modified by: Corey Goldberg, 2013
+# License: GPLv2+
+#
+# Original code from:
+# Bazaar (bzrlib.tests.__init__.py, v2.6, copied Jun 01 2013)
+# Copyright (C) 2005-2011 Canonical Ltd
+# License: GPLv2+
+
+import os
+import sys
+import traceback
+import unittest
+import subprocess
+import testtools
+import threading
+import time
+import io
+import json
+import subunit
+
+from queue import Queue
+from itertools import cycle
+from subunit import ProtocolTestCase, TestProtocolClient
+from subunit.test_results import AutoTimingTestResultDecorator
+from testtools import ThreadsafeForwardingResult, iterate_tests
+from testtools.content import Content
+from testtools.content_type import ContentType
+from oeqa.utils.commands import get_test_layer
+
+import bb.utils
+import oe.path
+
+_all__ = [
+ 'ConcurrentTestSuite',
+ 'fork_for_tests',
+ 'partition_tests',
+]
+
+#
+# Patch the version from testtools to allow access to _test_start and allow
+# computation of timing information and threading progress
+#
+class BBThreadsafeForwardingResult(ThreadsafeForwardingResult):
+
+ def __init__(self, target, semaphore, threadnum, totalinprocess, totaltests, output, finalresult):
+ super(BBThreadsafeForwardingResult, self).__init__(target, semaphore)
+ self.threadnum = threadnum
+ self.totalinprocess = totalinprocess
+ self.totaltests = totaltests
+ self.buffer = True
+ self.outputbuf = output
+ self.finalresult = finalresult
+ self.finalresult.buffer = True
+ self.target = target
+
+ def _add_result_with_semaphore(self, method, test, *args, **kwargs):
+ self.semaphore.acquire()
+ try:
+ if self._test_start:
+ self.result.starttime[test.id()] = self._test_start.timestamp()
+ self.result.threadprogress[self.threadnum].append(test.id())
+ totalprogress = sum(len(x) for x in self.result.threadprogress.values())
+ self.result.progressinfo[test.id()] = "%s: %s/%s %s/%s (%ss) (%s failed) (%s)" % (
+ self.threadnum,
+ len(self.result.threadprogress[self.threadnum]),
+ self.totalinprocess,
+ totalprogress,
+ self.totaltests,
+ "{0:.2f}".format(time.time()-self._test_start.timestamp()),
+ self.target.failed_tests,
+ test.id())
+ finally:
+ self.semaphore.release()
+ self.finalresult._stderr_buffer = io.StringIO(initial_value=self.outputbuf.getvalue().decode("utf-8"))
+ self.finalresult._stdout_buffer = io.StringIO()
+ super(BBThreadsafeForwardingResult, self)._add_result_with_semaphore(method, test, *args, **kwargs)
+
+class ProxyTestResult:
+ # a very basic TestResult proxy, in order to modify add* calls
+ def __init__(self, target):
+ self.result = target
+ self.failed_tests = 0
+
+ def _addResult(self, method, test, *args, exception = False, **kwargs):
+ return method(test, *args, **kwargs)
+
+ def addError(self, test, err = None, **kwargs):
+ self.failed_tests += 1
+ self._addResult(self.result.addError, test, err, exception = True, **kwargs)
+
+ def addFailure(self, test, err = None, **kwargs):
+ self.failed_tests += 1
+ self._addResult(self.result.addFailure, test, err, exception = True, **kwargs)
+
+ def addSuccess(self, test, **kwargs):
+ self._addResult(self.result.addSuccess, test, **kwargs)
+
+ def addExpectedFailure(self, test, err = None, **kwargs):
+ self._addResult(self.result.addExpectedFailure, test, err, exception = True, **kwargs)
+
+ def addUnexpectedSuccess(self, test, **kwargs):
+ self._addResult(self.result.addUnexpectedSuccess, test, **kwargs)
+
+ def wasSuccessful(self):
+ return self.failed_tests == 0
+
+ def __getattr__(self, attr):
+ return getattr(self.result, attr)
+
+class ExtraResultsDecoderTestResult(ProxyTestResult):
+ def _addResult(self, method, test, *args, exception = False, **kwargs):
+ if "details" in kwargs and "extraresults" in kwargs["details"]:
+ if isinstance(kwargs["details"]["extraresults"], Content):
+ kwargs = kwargs.copy()
+ kwargs["details"] = kwargs["details"].copy()
+ extraresults = kwargs["details"]["extraresults"]
+ data = bytearray()
+ for b in extraresults.iter_bytes():
+ data += b
+ extraresults = json.loads(data.decode())
+ kwargs["details"]["extraresults"] = extraresults
+ return method(test, *args, **kwargs)
+
+class ExtraResultsEncoderTestResult(ProxyTestResult):
+ def _addResult(self, method, test, *args, exception = False, **kwargs):
+ if hasattr(test, "extraresults"):
+ extras = lambda : [json.dumps(test.extraresults).encode()]
+ kwargs = kwargs.copy()
+ if "details" not in kwargs:
+ kwargs["details"] = {}
+ else:
+ kwargs["details"] = kwargs["details"].copy()
+ kwargs["details"]["extraresults"] = Content(ContentType("application", "json", {'charset': 'utf8'}), extras)
+ # if using details, need to encode any exceptions into the details obj,
+ # testtools does not handle "err" and "details" together.
+ if "details" in kwargs and exception and (len(args) >= 1 and args[0] is not None):
+ kwargs["details"]["traceback"] = testtools.content.TracebackContent(args[0], test)
+ args = []
+ return method(test, *args, **kwargs)
+
+#
+# We have to patch subunit since it doesn't understand how to handle addError
+# outside of a running test case. This can happen if classSetUp() fails
+# for a class of tests. This unfortunately has horrible internal knowledge.
+#
+def outSideTestaddError(self, offset, line):
+ """An 'error:' directive has been read."""
+ test_name = line[offset:-1].decode('utf8')
+ self.parser._current_test = subunit.RemotedTestCase(test_name)
+ self.parser.current_test_description = test_name
+ self.parser._state = self.parser._reading_error_details
+ self.parser._reading_error_details.set_simple()
+ self.parser.subunitLineReceived(line)
+
+subunit._OutSideTest.addError = outSideTestaddError
+
+# Like outSideTestaddError above, we need an equivalent for skips
+# happening at the setUpClass() level, otherwise we will see "UNKNOWN"
+# as a result for concurrent tests
+#
+def outSideTestaddSkip(self, offset, line):
+ """A 'skip:' directive has been read."""
+ test_name = line[offset:-1].decode('utf8')
+ self.parser._current_test = subunit.RemotedTestCase(test_name)
+ self.parser.current_test_description = test_name
+ self.parser._state = self.parser._reading_skip_details
+ self.parser._reading_skip_details.set_simple()
+ self.parser.subunitLineReceived(line)
+
+subunit._OutSideTest.addSkip = outSideTestaddSkip
+
+#
+# A dummy structure to add to io.StringIO so that the .buffer object
+# is available and accepts writes. This allows unittest with buffer=True
+# to interact ok with subunit which wants to access sys.stdout.buffer.
+#
+class dummybuf(object):
+ def __init__(self, parent):
+ self.p = parent
+ def write(self, data):
+ self.p.write(data.decode("utf-8"))
+
+#
+# Taken from testtools.ConncurrencyTestSuite but modified for OE use
+#
+class ConcurrentTestSuite(unittest.TestSuite):
+
+ def __init__(self, suite, processes, setupfunc, removefunc):
+ super(ConcurrentTestSuite, self).__init__([suite])
+ self.processes = processes
+ self.setupfunc = setupfunc
+ self.removefunc = removefunc
+
+ def run(self, result):
+ testservers, totaltests = fork_for_tests(self.processes, self)
+ try:
+ threads = {}
+ queue = Queue()
+ semaphore = threading.Semaphore(1)
+ result.threadprogress = {}
+ for i, (testserver, testnum, output) in enumerate(testservers):
+ result.threadprogress[i] = []
+ process_result = BBThreadsafeForwardingResult(
+ ExtraResultsDecoderTestResult(result),
+ semaphore, i, testnum, totaltests, output, result)
+ reader_thread = threading.Thread(
+ target=self._run_test, args=(testserver, process_result, queue))
+ threads[testserver] = reader_thread, process_result
+ reader_thread.start()
+ while threads:
+ finished_test = queue.get()
+ threads[finished_test][0].join()
+ del threads[finished_test]
+ except:
+ for thread, process_result in threads.values():
+ process_result.stop()
+ raise
+ finally:
+ for testserver in testservers:
+ testserver[0]._stream.close()
+
+ def _run_test(self, testserver, process_result, queue):
+ try:
+ try:
+ testserver.run(process_result)
+ except Exception:
+ # The run logic itself failed
+ case = testtools.ErrorHolder(
+ "broken-runner",
+ error=sys.exc_info())
+ case.run(process_result)
+ finally:
+ queue.put(testserver)
+
+def fork_for_tests(concurrency_num, suite):
+ testservers = []
+ if 'BUILDDIR' in os.environ:
+ selftestdir = get_test_layer()
+
+ test_blocks = partition_tests(suite, concurrency_num)
+ # Clear the tests from the original suite so it doesn't keep them alive
+ suite._tests[:] = []
+ totaltests = sum(len(x) for x in test_blocks)
+ for process_tests in test_blocks:
+ numtests = len(process_tests)
+ process_suite = unittest.TestSuite(process_tests)
+ # Also clear each split list so new suite has only reference
+ process_tests[:] = []
+ c2pread, c2pwrite = os.pipe()
+ # Clear buffers before fork to avoid duplicate output
+ sys.stdout.flush()
+ sys.stderr.flush()
+ pid = os.fork()
+ if pid == 0:
+ ourpid = os.getpid()
+ try:
+ newbuilddir = None
+ stream = os.fdopen(c2pwrite, 'wb', 1)
+ os.close(c2pread)
+
+ (builddir, newbuilddir) = suite.setupfunc("-st-" + str(ourpid), selftestdir, process_suite)
+
+ # Leave stderr and stdout open so we can see test noise
+ # Close stdin so that the child goes away if it decides to
+ # read from stdin (otherwise its a roulette to see what
+ # child actually gets keystrokes for pdb etc).
+ newsi = os.open(os.devnull, os.O_RDWR)
+ os.dup2(newsi, sys.stdin.fileno())
+
+ # Send stdout/stderr over the stream
+ os.dup2(c2pwrite, sys.stdout.fileno())
+ os.dup2(c2pwrite, sys.stderr.fileno())
+
+ subunit_client = TestProtocolClient(stream)
+ subunit_result = AutoTimingTestResultDecorator(subunit_client)
+ unittest_result = process_suite.run(ExtraResultsEncoderTestResult(subunit_result))
+ if ourpid != os.getpid():
+ os._exit(0)
+ if newbuilddir and unittest_result.wasSuccessful():
+ suite.removefunc(newbuilddir)
+ except:
+ # Don't do anything with process children
+ if ourpid != os.getpid():
+ os._exit(1)
+ # Try and report traceback on stream, but exit with error
+ # even if stream couldn't be created or something else
+ # goes wrong. The traceback is formatted to a string and
+ # written in one go to avoid interleaving lines from
+ # multiple failing children.
+ try:
+ stream.write(traceback.format_exc().encode('utf-8'))
+ except:
+ sys.stderr.write(traceback.format_exc())
+ finally:
+ if newbuilddir:
+ suite.removefunc(newbuilddir)
+ stream.flush()
+ os._exit(1)
+ stream.flush()
+ os._exit(0)
+ else:
+ os.close(c2pwrite)
+ stream = os.fdopen(c2pread, 'rb', 1)
+ # Collect stdout/stderr into an io buffer
+ output = io.BytesIO()
+ testserver = ProtocolTestCase(stream, passthrough=output)
+ testservers.append((testserver, numtests, output))
+ return testservers, totaltests
+
+def partition_tests(suite, count):
+ # Keep tests from the same class together but allow tests from modules
+ # to go to different processes to aid parallelisation.
+ modules = {}
+ for test in iterate_tests(suite):
+ m = test.__module__ + "." + test.__class__.__name__
+ if m not in modules:
+ modules[m] = []
+ modules[m].append(test)
+
+ # Simply divide the test blocks between the available processes
+ partitions = [list() for _ in range(count)]
+ for partition, m in zip(cycle(partitions), modules):
+ partition.extend(modules[m])
+
+ # No point in empty threads so drop them
+ return [p for p in partitions if p]
+
diff --git a/meta/lib/oeqa/core/utils/path.py b/meta/lib/oeqa/core/utils/path.py
new file mode 100644
index 0000000000..c086dcb0b0
--- /dev/null
+++ b/meta/lib/oeqa/core/utils/path.py
@@ -0,0 +1,22 @@
+#
+# Copyright (C) 2016 Intel Corporation
+#
+# SPDX-License-Identifier: MIT
+#
+
+import os
+import sys
+
+def findFile(file_name, directory):
+ """
+ Search for a file in directory and returns its complete path.
+ """
+ for r, d, f in os.walk(directory):
+ if file_name in f:
+ return os.path.join(r, file_name)
+ return None
+
+def remove_safe(path):
+ if os.path.exists(path):
+ os.remove(path)
+
diff --git a/meta/lib/oeqa/core/utils/test.py b/meta/lib/oeqa/core/utils/test.py
new file mode 100644
index 0000000000..d38cab8a51
--- /dev/null
+++ b/meta/lib/oeqa/core/utils/test.py
@@ -0,0 +1,89 @@
+#
+# Copyright (C) 2016 Intel Corporation
+#
+# SPDX-License-Identifier: MIT
+#
+
+import os
+import inspect
+import unittest
+
+def getSuiteCases(suite):
+ """
+ Returns individual test from a test suite.
+ """
+ tests = []
+
+ if isinstance(suite, unittest.TestCase):
+ tests.append(suite)
+ elif isinstance(suite, unittest.suite.TestSuite):
+ for item in suite:
+ tests.extend(getSuiteCases(item))
+
+ return tests
+
+def getSuiteModules(suite):
+ """
+ Returns modules in a test suite.
+ """
+ modules = set()
+ for test in getSuiteCases(suite):
+ modules.add(getCaseModule(test))
+ return modules
+
+def getSuiteCasesInfo(suite, func):
+ """
+ Returns test case info from suite. Info is fetched from func.
+ """
+ tests = []
+ for test in getSuiteCases(suite):
+ tests.append(func(test))
+ return tests
+
+def getSuiteCasesNames(suite):
+ """
+ Returns test case names from suite.
+ """
+ return getSuiteCasesInfo(suite, getCaseMethod)
+
+def getSuiteCasesIDs(suite):
+ """
+ Returns test case ids from suite.
+ """
+ return getSuiteCasesInfo(suite, getCaseID)
+
+def getSuiteCasesFiles(suite):
+ """
+ Returns test case files paths from suite.
+ """
+ return getSuiteCasesInfo(suite, getCaseFile)
+
+def getCaseModule(test_case):
+ """
+ Returns test case module name.
+ """
+ return test_case.__module__
+
+def getCaseClass(test_case):
+ """
+ Returns test case class name.
+ """
+ return test_case.__class__.__name__
+
+def getCaseID(test_case):
+ """
+ Returns test case complete id.
+ """
+ return test_case.id()
+
+def getCaseFile(test_case):
+ """
+ Returns test case file path.
+ """
+ return inspect.getsourcefile(test_case.__class__)
+
+def getCaseMethod(test_case):
+ """
+ Returns test case method name.
+ """
+ return getCaseID(test_case).split('.')[-1]
diff --git a/meta/lib/oeqa/files/buildhistory_filelist1.txt b/meta/lib/oeqa/files/buildhistory_filelist1.txt
new file mode 100644
index 0000000000..8d882895ad
--- /dev/null
+++ b/meta/lib/oeqa/files/buildhistory_filelist1.txt
@@ -0,0 +1,9214 @@
+drwxr-xr-x root root 4096 ./bin
+lrwxrwxrwx root root 19 ./bin/ash -> /bin/busybox.nosuid
+lrwxrwxrwx root root 25 ./bin/base64 -> /usr/bin/base64.coreutils
+-rwxr-xr-x root root 1190872 ./bin/bash.bash
+lrwxrwxrwx root root 14 ./bin/bash -> /bin/bash.bash
+lrwxrwxrwx root root 14 ./bin/busybox -> busybox.nosuid
+-rwxr-xr-x root root 613008 ./bin/busybox.nosuid
+-rwsr-xr-x root root 59440 ./bin/busybox.suid
+lrwxrwxrwx root root 18 ./bin/cat -> /bin/cat.coreutils
+-rwxr-xr-x root root 47336 ./bin/cat.coreutils
+lrwxrwxrwx root root 21 ./bin/chattr -> /bin/chattr.e2fsprogs
+-rwxr-xr-x root root 14312 ./bin/chattr.e2fsprogs
+lrwxrwxrwx root root 20 ./bin/chgrp -> /bin/chgrp.coreutils
+-rwxr-xr-x root root 75944 ./bin/chgrp.coreutils
+lrwxrwxrwx root root 20 ./bin/chmod -> /bin/chmod.coreutils
+-rwxr-xr-x root root 71880 ./bin/chmod.coreutils
+lrwxrwxrwx root root 20 ./bin/chown -> /bin/chown.coreutils
+-rwxr-xr-x root root 80040 ./bin/chown.coreutils
+lrwxrwxrwx root root 17 ./bin/cp -> /bin/cp.coreutils
+-rwxr-xr-x root root 137416 ./bin/cp.coreutils
+lrwxrwxrwx root root 19 ./bin/cpio -> /bin/busybox.nosuid
+lrwxrwxrwx root root 19 ./bin/date -> /bin/date.coreutils
+-rwxr-xr-x root root 121032 ./bin/date.coreutils
+lrwxrwxrwx root root 17 ./bin/dd -> /bin/dd.coreutils
+-rwxr-xr-x root root 88272 ./bin/dd.coreutils
+lrwxrwxrwx root root 21 ./bin/df -> /usr/bin/df.coreutils
+lrwxrwxrwx root root 21 ./bin/dmesg -> /bin/dmesg.util-linux
+-rwxr-xr-x root root 84256 ./bin/dmesg.util-linux
+lrwxrwxrwx root root 19 ./bin/dnsdomainname -> /bin/busybox.nosuid
+lrwxrwxrwx root root 19 ./bin/dumpkmap -> /bin/busybox.nosuid
+lrwxrwxrwx root root 19 ./bin/echo -> /bin/echo.coreutils
+-rwxr-xr-x root root 39064 ./bin/echo.coreutils
+lrwxrwxrwx root root 15 ./bin/egrep -> /bin/egrep.grep
+-rwxr-xr-x root root 28 ./bin/egrep.grep
+lrwxrwxrwx root root 20 ./bin/false -> /bin/false.coreutils
+-rwxr-xr-x root root 39064 ./bin/false.coreutils
+lrwxrwxrwx root root 15 ./bin/fgrep -> /bin/fgrep.grep
+-rwxr-xr-x root root 28 ./bin/fgrep.grep
+lrwxrwxrwx root root 22 ./bin/getopt -> /bin/getopt.util-linux
+-rwxr-xr-x root root 22576 ./bin/getopt.util-linux
+lrwxrwxrwx root root 14 ./bin/grep -> /bin/grep.grep
+-rwxr-xr-x root root 244016 ./bin/grep.grep
+lrwxrwxrwx root root 19 ./bin/gunzip -> /bin/busybox.nosuid
+lrwxrwxrwx root root 19 ./bin/gzip -> /bin/busybox.nosuid
+lrwxrwxrwx root root 23 ./bin/hostname -> /bin/hostname.coreutils
+-rwxr-xr-x root root 43176 ./bin/hostname.coreutils
+lrwxrwxrwx root root 16 ./bin/kill -> /bin/kill.procps
+-rwxr-xr-x root root 47712 ./bin/kill.coreutils
+-rwxr-xr-x root root 30760 ./bin/kill.procps
+-rwxr-xr-x root root 38960 ./bin/kill.util-linux
+-rwxr-xr-x root root 141456 ./bin/kmod
+lrwxrwxrwx root root 17 ./bin/ln -> /bin/ln.coreutils
+-rwxr-xr-x root root 75984 ./bin/ln.coreutils
+lrwxrwxrwx root root 17 ./bin/login -> /bin/login.shadow
+-rwxr-xr-x root root 73120 ./bin/login.shadow
+lrwxrwxrwx root root 17 ./bin/ls -> /bin/ls.coreutils
+-rwxr-xr-x root root 162448 ./bin/ls.coreutils
+lrwxrwxrwx root root 15 ./bin/lsmod -> /bin/lsmod.kmod
+lrwxrwxrwx root root 4 ./bin/lsmod.kmod -> kmod
+lrwxrwxrwx root root 20 ./bin/mkdir -> /bin/mkdir.coreutils
+-rwxr-xr-x root root 67752 ./bin/mkdir.coreutils
+lrwxrwxrwx root root 20 ./bin/mknod -> /bin/mknod.coreutils
+-rwxr-xr-x root root 47272 ./bin/mknod.coreutils
+lrwxrwxrwx root root 25 ./bin/mktemp -> /usr/bin/mktemp.coreutils
+lrwxrwxrwx root root 20 ./bin/more -> /bin/more.util-linux
+-rwxr-xr-x root root 42976 ./bin/more.util-linux
+lrwxrwxrwx root root 21 ./bin/mount -> /bin/mount.util-linux
+lrwxrwxrwx root root 26 ./bin/mountpoint -> /bin/mountpoint.util-linux
+-rwxr-xr-x root root 14304 ./bin/mountpoint.sysvinit
+-rwxr-xr-x root root 18480 ./bin/mountpoint.util-linux
+-rwsr-xr-x root root 55344 ./bin/mount.util-linux
+lrwxrwxrwx root root 17 ./bin/mv -> /bin/mv.coreutils
+-rwxr-xr-x root root 145616 ./bin/mv.coreutils
+lrwxrwxrwx root root 19 ./bin/netstat -> /bin/busybox.nosuid
+lrwxrwxrwx root root 23 ./bin/nice -> /usr/bin/nice.coreutils
+lrwxrwxrwx root root 19 ./bin/pidof -> /bin/pidof.sysvinit
+-rwxr-xr-x root root 22568 ./bin/pidof.procps
+lrwxrwxrwx root root 14 ./bin/pidof.sysvinit -> /sbin/killall5
+lrwxrwxrwx root root 17 ./bin/ping6 -> /bin/busybox.suid
+lrwxrwxrwx root root 17 ./bin/ping -> /bin/busybox.suid
+lrwxrwxrwx root root 27 ./bin/printenv -> /usr/bin/printenv.coreutils
+lrwxrwxrwx root root 14 ./bin/ps -> /bin/ps.procps
+-rwxr-xr-x root root 137496 ./bin/ps.procps
+lrwxrwxrwx root root 18 ./bin/pwd -> /bin/pwd.coreutils
+-rwxr-xr-x root root 47272 ./bin/pwd.coreutils
+lrwxrwxrwx root root 17 ./bin/rm -> /bin/rm.coreutils
+-rwxr-xr-x root root 75976 ./bin/rm.coreutils
+lrwxrwxrwx root root 20 ./bin/rmdir -> /bin/rmdir.coreutils
+-rwxr-xr-x root root 55464 ./bin/rmdir.coreutils
+lrwxrwxrwx root root 19 ./bin/run-parts -> /bin/busybox.nosuid
+lrwxrwxrwx root root 12 ./bin/sed -> /bin/sed.sed
+-rwxr-xr-x root root 190896 ./bin/sed.sed
+lrwxrwxrwx root root 14 ./bin/sh -> /bin/bash.bash
+lrwxrwxrwx root root 20 ./bin/sleep -> /bin/sleep.coreutils
+-rwxr-xr-x root root 43176 ./bin/sleep.coreutils
+-rwxr-xr-x root root 1736 ./bin/start_getty
+lrwxrwxrwx root root 19 ./bin/stat -> /bin/stat.coreutils
+-rwxr-xr-x root root 96456 ./bin/stat.coreutils
+lrwxrwxrwx root root 19 ./bin/stty -> /bin/stty.coreutils
+-rwxr-xr-x root root 92360 ./bin/stty.coreutils
+lrwxrwxrwx root root 14 ./bin/su -> /bin/su.shadow
+-rwsr-xr-x root root 60992 ./bin/su.shadow
+lrwxrwxrwx root root 19 ./bin/sync -> /bin/sync.coreutils
+-rwxr-xr-x root root 43176 ./bin/sync.coreutils
+lrwxrwxrwx root root 19 ./bin/tar -> /bin/busybox.nosuid
+lrwxrwxrwx root root 20 ./bin/touch -> /bin/touch.coreutils
+-rwxr-xr-x root root 108744 ./bin/touch.coreutils
+lrwxrwxrwx root root 19 ./bin/true -> /bin/true.coreutils
+-rwxr-xr-x root root 39064 ./bin/true.coreutils
+lrwxrwxrwx root root 22 ./bin/umount -> /bin/umount.util-linux
+-rwsr-xr-x root root 34864 ./bin/umount.util-linux
+lrwxrwxrwx root root 20 ./bin/uname -> /bin/uname.coreutils
+-rwxr-xr-x root root 43208 ./bin/uname.coreutils
+lrwxrwxrwx root root 19 ./bin/usleep -> /bin/busybox.nosuid
+lrwxrwxrwx root root 19 ./bin/vi -> /bin/busybox.nosuid
+lrwxrwxrwx root root 17 ./bin/watch -> /bin/watch.procps
+-rwxr-xr-x root root 27016 ./bin/watch.procps
+lrwxrwxrwx root root 19 ./bin/zcat -> /bin/busybox.nosuid
+drwxr-xr-x root root 4096 ./boot
+drwxr-xr-x root root 4096 ./dev
+drwxr-xr-x root root 4096 ./etc
+-rw-r--r-- root root 45 ./etc/bash_completion
+drwxr-xr-x root root 4096 ./etc/bash_completion.d
+-rw-r--r-- root root 447 ./etc/bindresvport.blacklist
+-rw-r--r-- root root 506 ./etc/build
+-rw-r--r-- root root 2370 ./etc/busybox.links.nosuid
+-rw-r--r-- root root 91 ./etc/busybox.links.suid
+drwxr-xr-x root root 4096 ./etc/ca-certificates
+-rw-r--r-- root root 5340 ./etc/ca-certificates.conf
+drwxr-xr-x root root 4096 ./etc/ca-certificates/update.d
+drwxr-xr-x root root 4096 ./etc/dbus-1
+-rw-r--r-- root root 838 ./etc/dbus-1/session.conf
+-rw-r--r-- root root 833 ./etc/dbus-1/system.conf
+drwxr-xr-x root root 4096 ./etc/default
+-rwxr-xr-x root root 93 ./etc/default/devpts
+-rw-r--r-- root root 36 ./etc/default/mountall
+-rw-r--r-- root root 52 ./etc/default/postinst
+-rw-r--r-- root root 1040 ./etc/default/rcS
+-rw-r--r-- root root 117 ./etc/default/useradd
+drwxr-xr-x root root 4096 ./etc/default/volatiles
+-rw-r--r-- root root 1637 ./etc/default/volatiles/00_core
+-rw-r--r-- root root 36 ./etc/default/volatiles/01_bootlogd
+-rw-r--r-- root root 48 ./etc/default/volatiles/99_dbus
+drwxr-xr-x root root 4096 ./etc/depmod.d
+-rw-r--r-- root root 685 ./etc/e2scrub.conf
+drwxr-xr-x root root 4096 ./etc/fonts
+drwxr-xr-x root root 4096 ./etc/fonts/conf.d
+lrwxrwxrwx root root 63 ./etc/fonts/conf.d/10-hinting-slight.conf -> ../../../usr/share/fontconfig/conf.avail/10-hinting-slight.conf
+lrwxrwxrwx root root 67 ./etc/fonts/conf.d/10-scale-bitmap-fonts.conf -> ../../../usr/share/fontconfig/conf.avail/10-scale-bitmap-fonts.conf
+lrwxrwxrwx root root 66 ./etc/fonts/conf.d/20-unhint-small-vera.conf -> ../../../usr/share/fontconfig/conf.avail/20-unhint-small-vera.conf
+lrwxrwxrwx root root 63 ./etc/fonts/conf.d/30-metric-aliases.conf -> ../../../usr/share/fontconfig/conf.avail/30-metric-aliases.conf
+lrwxrwxrwx root root 57 ./etc/fonts/conf.d/40-nonlatin.conf -> ../../../usr/share/fontconfig/conf.avail/40-nonlatin.conf
+lrwxrwxrwx root root 56 ./etc/fonts/conf.d/45-generic.conf -> ../../../usr/share/fontconfig/conf.avail/45-generic.conf
+lrwxrwxrwx root root 54 ./etc/fonts/conf.d/45-latin.conf -> ../../../usr/share/fontconfig/conf.avail/45-latin.conf
+lrwxrwxrwx root root 58 ./etc/fonts/conf.d/49-sansserif.conf -> ../../../usr/share/fontconfig/conf.avail/49-sansserif.conf
+lrwxrwxrwx root root 53 ./etc/fonts/conf.d/50-user.conf -> ../../../usr/share/fontconfig/conf.avail/50-user.conf
+lrwxrwxrwx root root 54 ./etc/fonts/conf.d/51-local.conf -> ../../../usr/share/fontconfig/conf.avail/51-local.conf
+lrwxrwxrwx root root 56 ./etc/fonts/conf.d/60-generic.conf -> ../../../usr/share/fontconfig/conf.avail/60-generic.conf
+lrwxrwxrwx root root 54 ./etc/fonts/conf.d/60-latin.conf -> ../../../usr/share/fontconfig/conf.avail/60-latin.conf
+lrwxrwxrwx root root 62 ./etc/fonts/conf.d/65-fonts-persian.conf -> ../../../usr/share/fontconfig/conf.avail/65-fonts-persian.conf
+lrwxrwxrwx root root 57 ./etc/fonts/conf.d/65-nonlatin.conf -> ../../../usr/share/fontconfig/conf.avail/65-nonlatin.conf
+lrwxrwxrwx root root 56 ./etc/fonts/conf.d/69-unifont.conf -> ../../../usr/share/fontconfig/conf.avail/69-unifont.conf
+lrwxrwxrwx root root 58 ./etc/fonts/conf.d/80-delicious.conf -> ../../../usr/share/fontconfig/conf.avail/80-delicious.conf
+lrwxrwxrwx root root 58 ./etc/fonts/conf.d/90-synthetic.conf -> ../../../usr/share/fontconfig/conf.avail/90-synthetic.conf
+-rw-r--r-- root root 978 ./etc/fonts/conf.d/README
+-rw-r--r-- root root 2532 ./etc/fonts/fonts.conf
+-rw-r--r-- root root 650 ./etc/fstab
+-rw-r--r-- root root 501 ./etc/group
+-r-------- root root 420 ./etc/gshadow
+-rw-r--r-- root root 26 ./etc/host.conf
+-rw-r--r-- root root 11 ./etc/hostname
+-rw-r--r-- root root 258 ./etc/hosts
+drwxr-xr-x root root 4096 ./etc/init.d
+-rwxr-xr-x root root 492 ./etc/init.d/banner.sh
+-rwxr-xr-x root root 1997 ./etc/init.d/bootlogd
+-rwxr-xr-x root root 2017 ./etc/init.d/bootmisc.sh
+-rwxr-xr-x root root 3591 ./etc/init.d/checkroot.sh
+-rwxr-xr-x root root 2893 ./etc/init.d/dbus-1
+-rwxr-xr-x root root 526 ./etc/init.d/devpts.sh
+-rwxr-xr-x root root 352 ./etc/init.d/dmesg.sh
+-rw-r--r-- root root 2141 ./etc/init.d/functions
+-rwxr-xr-x root root 510 ./etc/init.d/halt
+-rwxr-xr-x root root 580 ./etc/init.d/hostname.sh
+-rwxr-xr-x root root 2541 ./etc/init.d/hwclock.sh
+-rwxr-xr-x root root 1773 ./etc/init.d/mdmonitor
+-rwxr-xr-x root root 1223 ./etc/init.d/modutils.sh
+-rwxr-xr-x root root 869 ./etc/init.d/mountall.sh
+-rwxr-xr-x root root 1589 ./etc/init.d/mountnfs.sh
+-rwxr-xr-x root root 1956 ./etc/init.d/networking
+-rwxr-xr-x root root 7823 ./etc/init.d/populate-volatile.sh
+-rwxr-xr-x root root 4457 ./etc/init.d/rc
+-rwxr-xr-x root root 525 ./etc/init.d/rcS
+-rwxr-xr-x root root 1273 ./etc/init.d/read-only-rootfs-hook.sh
+-rwxr-xr-x root root 289 ./etc/init.d/reboot
+-rwxr-xr-x root root 585 ./etc/init.d/rmnologin.sh
+-rwxr-xr-x root root 25 ./etc/init.d/run-postinsts
+-rwxr-xr-x root root 429 ./etc/init.d/save-rtc.sh
+-rwxr-xr-x root root 438 ./etc/init.d/sendsigs
+-rwxr-xr-x root root 578 ./etc/init.d/single
+lrwxrwxrwx root root 8 ./etc/init.d/stop-bootlogd -> bootlogd
+-rwxr-xr-x root root 1046 ./etc/init.d/sysfs.sh
+-rwxr-xr-x root root 2066 ./etc/init.d/syslog
+-rwxr-xr-x root root 2779 ./etc/init.d/udev
+-rwxr-xr-x root root 540 ./etc/init.d/umountfs
+-rwxr-xr-x root root 711 ./etc/init.d/umountnfs.sh
+-rwxr-xr-x root root 1473 ./etc/init.d/urandom
+-rw-r--r-- root root 1140 ./etc/inittab
+-rw-r--r-- root root 1633 ./etc/inputrc
+drwxr-xr-x root root 4096 ./etc/iproute2
+-rw-r--r-- root root 85 ./etc/iproute2/bpf_pinning
+-rw-r--r-- root root 81 ./etc/iproute2/ematch_map
+-rw-r--r-- root root 31 ./etc/iproute2/group
+-rw-r--r-- root root 262 ./etc/iproute2/nl_protos
+-rw-r--r-- root root 331 ./etc/iproute2/rt_dsfield
+-rw-r--r-- root root 201 ./etc/iproute2/rt_protos
+-rw-r--r-- root root 112 ./etc/iproute2/rt_realms
+-rw-r--r-- root root 92 ./etc/iproute2/rt_scopes
+-rw-r--r-- root root 87 ./etc/iproute2/rt_tables
+drwxr-xr-x root root 4096 ./etc/iptables
+-rw-r--r-- root root 0 ./etc/iptables/ip6tables.rules
+-rw-r--r-- root root 0 ./etc/iptables/iptables.rules
+-rw-r--r-- root root 58 ./etc/issue
+-rw-r--r-- root root 55 ./etc/issue.net
+-rw-r--r-- root root 18635 ./etc/ld.so.cache
+-rw-r--r-- root root 33 ./etc/ld.so.conf
+-rw-r--r-- root root 827 ./etc/limits
+-rw-r--r-- root root 2006 ./etc/login.access
+-rw-r--r-- root root 12001 ./etc/login.defs
+-rw-r--r-- root root 121 ./etc/logrotate-dmesg.conf
+-rw-r--r-- root root 2687 ./etc/mdadm.conf
+-rw-r--r-- root root 812 ./etc/mke2fs.conf
+drwxr-xr-x root root 4096 ./etc/modprobe.d
+-rw-r--r-- root root 0 ./etc/motd
+lrwxrwxrwx root root 12 ./etc/mtab -> /proc/mounts
+-rw-r--r-- root root 767 ./etc/netconfig
+drwxr-xr-x root root 4096 ./etc/network
+drwxr-xr-x root root 4096 ./etc/network/if-down.d
+drwxr-xr-x root root 4096 ./etc/network/if-post-down.d
+drwxr-xr-x root root 4096 ./etc/network/if-pre-up.d
+-rwxr-xr-x root root 809 ./etc/network/if-pre-up.d/nfsroot
+drwxr-xr-x root root 4096 ./etc/network/if-up.d
+-rw-r--r-- root root 132 ./etc/network/interfaces
+-rw-r--r-- root root 0 ./etc/network/nm-disabled-eth0
+-rw-r--r-- root root 465 ./etc/nsswitch.conf
+-rw-r--r-- root root 767 ./etc/passwd
+-rw-r--r-- root root 984 ./etc/profile
+drwxr-xr-x root root 4096 ./etc/profile.d
+-rw-r--r-- root root 729 ./etc/profile.d/bash_completion.sh
+-rw-r--r-- root root 1107 ./etc/profile.d/gawk.csh
+-rw-r--r-- root root 757 ./etc/profile.d/gawk.sh
+-rw-r--r-- root root 2932 ./etc/protocols
+drwxr-xr-x root root 4096 ./etc/rc0.d
+lrwxrwxrwx root root 16 ./etc/rc0.d/K20dbus-1 -> ../init.d/dbus-1
+lrwxrwxrwx root root 20 ./etc/rc0.d/K20hwclock.sh -> ../init.d/hwclock.sh
+lrwxrwxrwx root root 16 ./etc/rc0.d/K20syslog -> ../init.d/syslog
+lrwxrwxrwx root root 20 ./etc/rc0.d/K80networking -> ../init.d/networking
+lrwxrwxrwx root root 18 ./etc/rc0.d/S20sendsigs -> ../init.d/sendsigs
+lrwxrwxrwx root root 21 ./etc/rc0.d/S25save-rtc.sh -> ../init.d/save-rtc.sh
+lrwxrwxrwx root root 22 ./etc/rc0.d/S31umountnfs.sh -> ../init.d/umountnfs.sh
+lrwxrwxrwx root root 17 ./etc/rc0.d/S38urandom -> ../init.d/urandom
+lrwxrwxrwx root root 18 ./etc/rc0.d/S40umountfs -> ../init.d/umountfs
+lrwxrwxrwx root root 14 ./etc/rc0.d/S90halt -> ../init.d/halt
+drwxr-xr-x root root 4096 ./etc/rc1.d
+lrwxrwxrwx root root 16 ./etc/rc1.d/K20dbus-1 -> ../init.d/dbus-1
+lrwxrwxrwx root root 20 ./etc/rc1.d/K20hwclock.sh -> ../init.d/hwclock.sh
+lrwxrwxrwx root root 16 ./etc/rc1.d/K20syslog -> ../init.d/syslog
+lrwxrwxrwx root root 20 ./etc/rc1.d/K80networking -> ../init.d/networking
+lrwxrwxrwx root root 22 ./etc/rc1.d/S31umountnfs.sh -> ../init.d/umountnfs.sh
+drwxr-xr-x root root 4096 ./etc/rc2.d
+lrwxrwxrwx root root 20 ./etc/rc2.d/S01networking -> ../init.d/networking
+lrwxrwxrwx root root 16 ./etc/rc2.d/S02dbus-1 -> ../init.d/dbus-1
+lrwxrwxrwx root root 21 ./etc/rc2.d/S15mountnfs.sh -> ../init.d/mountnfs.sh
+lrwxrwxrwx root root 20 ./etc/rc2.d/S20hwclock.sh -> ../init.d/hwclock.sh
+lrwxrwxrwx root root 16 ./etc/rc2.d/S20syslog -> ../init.d/syslog
+lrwxrwxrwx root root 22 ./etc/rc2.d/S99rmnologin.sh -> ../init.d/rmnologin.sh
+lrwxrwxrwx root root 23 ./etc/rc2.d/S99stop-bootlogd -> ../init.d/stop-bootlogd
+drwxr-xr-x root root 4096 ./etc/rc3.d
+lrwxrwxrwx root root 20 ./etc/rc3.d/S01networking -> ../init.d/networking
+lrwxrwxrwx root root 16 ./etc/rc3.d/S02dbus-1 -> ../init.d/dbus-1
+lrwxrwxrwx root root 21 ./etc/rc3.d/S15mountnfs.sh -> ../init.d/mountnfs.sh
+lrwxrwxrwx root root 20 ./etc/rc3.d/S20hwclock.sh -> ../init.d/hwclock.sh
+lrwxrwxrwx root root 16 ./etc/rc3.d/S20syslog -> ../init.d/syslog
+lrwxrwxrwx root root 22 ./etc/rc3.d/S99rmnologin.sh -> ../init.d/rmnologin.sh
+lrwxrwxrwx root root 23 ./etc/rc3.d/S99stop-bootlogd -> ../init.d/stop-bootlogd
+drwxr-xr-x root root 4096 ./etc/rc4.d
+lrwxrwxrwx root root 20 ./etc/rc4.d/S01networking -> ../init.d/networking
+lrwxrwxrwx root root 21 ./etc/rc4.d/S15mountnfs.sh -> ../init.d/mountnfs.sh
+lrwxrwxrwx root root 20 ./etc/rc4.d/S20hwclock.sh -> ../init.d/hwclock.sh
+lrwxrwxrwx root root 16 ./etc/rc4.d/S20syslog -> ../init.d/syslog
+lrwxrwxrwx root root 22 ./etc/rc4.d/S99rmnologin.sh -> ../init.d/rmnologin.sh
+lrwxrwxrwx root root 23 ./etc/rc4.d/S99stop-bootlogd -> ../init.d/stop-bootlogd
+drwxr-xr-x root root 4096 ./etc/rc5.d
+lrwxrwxrwx root root 20 ./etc/rc5.d/S01networking -> ../init.d/networking
+lrwxrwxrwx root root 16 ./etc/rc5.d/S02dbus-1 -> ../init.d/dbus-1
+lrwxrwxrwx root root 21 ./etc/rc5.d/S15mountnfs.sh -> ../init.d/mountnfs.sh
+lrwxrwxrwx root root 20 ./etc/rc5.d/S20hwclock.sh -> ../init.d/hwclock.sh
+lrwxrwxrwx root root 16 ./etc/rc5.d/S20syslog -> ../init.d/syslog
+lrwxrwxrwx root root 22 ./etc/rc5.d/S99rmnologin.sh -> ../init.d/rmnologin.sh
+lrwxrwxrwx root root 23 ./etc/rc5.d/S99stop-bootlogd -> ../init.d/stop-bootlogd
+drwxr-xr-x root root 4096 ./etc/rc6.d
+lrwxrwxrwx root root 16 ./etc/rc6.d/K20dbus-1 -> ../init.d/dbus-1
+lrwxrwxrwx root root 20 ./etc/rc6.d/K20hwclock.sh -> ../init.d/hwclock.sh
+lrwxrwxrwx root root 16 ./etc/rc6.d/K20syslog -> ../init.d/syslog
+lrwxrwxrwx root root 20 ./etc/rc6.d/K80networking -> ../init.d/networking
+lrwxrwxrwx root root 18 ./etc/rc6.d/S20sendsigs -> ../init.d/sendsigs
+lrwxrwxrwx root root 21 ./etc/rc6.d/S25save-rtc.sh -> ../init.d/save-rtc.sh
+lrwxrwxrwx root root 22 ./etc/rc6.d/S31umountnfs.sh -> ../init.d/umountnfs.sh
+lrwxrwxrwx root root 17 ./etc/rc6.d/S38urandom -> ../init.d/urandom
+lrwxrwxrwx root root 18 ./etc/rc6.d/S40umountfs -> ../init.d/umountfs
+lrwxrwxrwx root root 16 ./etc/rc6.d/S90reboot -> ../init.d/reboot
+drwxr-xr-x root root 4096 ./etc/rcS.d
+lrwxrwxrwx root root 19 ./etc/rcS.d/S02banner.sh -> ../init.d/banner.sh
+lrwxrwxrwx root root 18 ./etc/rcS.d/S02sysfs.sh -> ../init.d/sysfs.sh
+lrwxrwxrwx root root 21 ./etc/rcS.d/S03mountall.sh -> ../init.d/mountall.sh
+lrwxrwxrwx root root 14 ./etc/rcS.d/S04udev -> ../init.d/udev
+lrwxrwxrwx root root 21 ./etc/rcS.d/S05modutils.sh -> ../init.d/modutils.sh
+lrwxrwxrwx root root 22 ./etc/rcS.d/S06checkroot.sh -> ../init.d/checkroot.sh
+lrwxrwxrwx root root 19 ./etc/rcS.d/S06devpts.sh -> ../init.d/devpts.sh
+lrwxrwxrwx root root 18 ./etc/rcS.d/S07bootlogd -> ../init.d/bootlogd
+lrwxrwxrwx root root 34 ./etc/rcS.d/S29read-only-rootfs-hook.sh -> ../init.d/read-only-rootfs-hook.sh
+lrwxrwxrwx root root 21 ./etc/rcS.d/S36bootmisc.sh -> ../init.d/bootmisc.sh
+lrwxrwxrwx root root 30 ./etc/rcS.d/S37populate-volatile.sh -> ../init.d/populate-volatile.sh
+lrwxrwxrwx root root 18 ./etc/rcS.d/S38dmesg.sh -> ../init.d/dmesg.sh
+lrwxrwxrwx root root 17 ./etc/rcS.d/S38urandom -> ../init.d/urandom
+lrwxrwxrwx root root 21 ./etc/rcS.d/S39hostname.sh -> ../init.d/hostname.sh
+-rw-r--r-- root root 887 ./etc/rpc
+-r-------- root root 1848 ./etc/securetty
+-rw-r--r-- root root 14464 ./etc/services
+-r-------- root root 404 ./etc/shadow
+-rw-r--r-- root root 52 ./etc/shells
+drwxr-xr-x root root 4096 ./etc/skel
+-rwxr-xr-x root root 410 ./etc/skel/.bashrc
+-rwxr-xr-x root root 241 ./etc/skel/.profile
+drwxr-xr-x root root 4096 ./etc/ssl
+drwxr-xr-x root root 16384 ./etc/ssl/certs
+lrwxrwxrwx root root 45 ./etc/ssl/certs/02265526.0 -> Entrust_Root_Certification_Authority_-_G2.pem
+lrwxrwxrwx root root 36 ./etc/ssl/certs/03179a64.0 -> Staat_der_Nederlanden_EV_Root_CA.pem
+lrwxrwxrwx root root 27 ./etc/ssl/certs/062cdee6.0 -> GlobalSign_Root_CA_-_R3.pem
+lrwxrwxrwx root root 25 ./etc/ssl/certs/064e0aa9.0 -> QuoVadis_Root_CA_2_G3.pem
+lrwxrwxrwx root root 50 ./etc/ssl/certs/06dc52d5.0 -> SSL.com_EV_Root_Certification_Authority_RSA_R2.pem
+lrwxrwxrwx root root 20 ./etc/ssl/certs/080911ac.0 -> QuoVadis_Root_CA.pem
+lrwxrwxrwx root root 54 ./etc/ssl/certs/09789157.0 -> Starfield_Services_Root_Certificate_Authority_-_G2.pem
+lrwxrwxrwx root root 16 ./etc/ssl/certs/0b1b94ef.0 -> CFCA_EV_ROOT.pem
+lrwxrwxrwx root root 44 ./etc/ssl/certs/0bf05006.0 -> SSL.com_Root_Certification_Authority_ECC.pem
+lrwxrwxrwx root root 34 ./etc/ssl/certs/0c4c9b6c.0 -> Global_Chambersign_Root_-_2008.pem
+lrwxrwxrwx root root 26 ./etc/ssl/certs/0f6fa695.0 -> GDCA_TrustAUTH_R5_ROOT.pem
+lrwxrwxrwx root root 46 ./etc/ssl/certs/106f3e4d.0 -> Entrust_Root_Certification_Authority_-_EC1.pem
+lrwxrwxrwx root root 49 ./etc/ssl/certs/116bf586.0 -> GeoTrust_Primary_Certification_Authority_-_G2.pem
+lrwxrwxrwx root root 35 ./etc/ssl/certs/128805a3.0 -> EE_Certification_Centre_Root_CA.pem
+lrwxrwxrwx root root 26 ./etc/ssl/certs/157753a5.0 -> AddTrust_External_Root.pem
+lrwxrwxrwx root root 59 ./etc/ssl/certs/1636090b.0 -> Hellenic_Academic_and_Research_Institutions_RootCA_2011.pem
+lrwxrwxrwx root root 23 ./etc/ssl/certs/18856ac4.0 -> SecureSign_RootCA11.pem
+lrwxrwxrwx root root 31 ./etc/ssl/certs/1d3472b9.0 -> GlobalSign_ECC_Root_CA_-_R5.pem
+lrwxrwxrwx root root 37 ./etc/ssl/certs/1e08bfd1.0 -> IdenTrust_Public_Sector_Root_CA_1.pem
+lrwxrwxrwx root root 32 ./etc/ssl/certs/1e09d511.0 -> T-TeleSec_GlobalRoot_Class_2.pem
+lrwxrwxrwx root root 38 ./etc/ssl/certs/244b5494.0 -> DigiCert_High_Assurance_EV_Root_CA.pem
+lrwxrwxrwx root root 20 ./etc/ssl/certs/2ae6433e.0 -> CA_Disig_Root_R2.pem
+lrwxrwxrwx root root 26 ./etc/ssl/certs/2b349938.0 -> AffirmTrust_Commercial.pem
+lrwxrwxrwx root root 22 ./etc/ssl/certs/2c543cd1.0 -> GeoTrust_Global_CA.pem
+lrwxrwxrwx root root 26 ./etc/ssl/certs/2e4eed3c.0 -> thawte_Primary_Root_CA.pem
+lrwxrwxrwx root root 18 ./etc/ssl/certs/2e5ac55d.0 -> DST_Root_CA_X3.pem
+lrwxrwxrwx root root 59 ./etc/ssl/certs/32888f65.0 -> Hellenic_Academic_and_Research_Institutions_RootCA_2015.pem
+lrwxrwxrwx root root 10 ./etc/ssl/certs/349f2832.0 -> EC-ACC.pem
+lrwxrwxrwx root root 27 ./etc/ssl/certs/3513523f.0 -> DigiCert_Global_Root_CA.pem
+lrwxrwxrwx root root 61 ./etc/ssl/certs/3bde41ac.0 -> Autoridad_de_Certificacion_Firmaprofesional_CIF_A62634068.pem
+lrwxrwxrwx root root 26 ./etc/ssl/certs/3e44d2f7.0 -> TrustCor_RootCert_CA-2.pem
+lrwxrwxrwx root root 27 ./etc/ssl/certs/3e45d192.0 -> Hongkong_Post_Root_CA_1.pem
+lrwxrwxrwx root root 31 ./etc/ssl/certs/40193066.0 -> Certum_Trusted_Network_CA_2.pem
+lrwxrwxrwx root root 16 ./etc/ssl/certs/4042bcee.0 -> ISRG_Root_X1.pem
+lrwxrwxrwx root root 34 ./etc/ssl/certs/40547a79.0 -> COMODO_Certification_Authority.pem
+lrwxrwxrwx root root 43 ./etc/ssl/certs/4304c5e5.0 -> Network_Solutions_Certificate_Authority.pem
+lrwxrwxrwx root root 44 ./etc/ssl/certs/480720ec.0 -> GeoTrust_Primary_Certification_Authority.pem
+lrwxrwxrwx root root 29 ./etc/ssl/certs/48bec511.0 -> Certum_Trusted_Network_CA.pem
+lrwxrwxrwx root root 27 ./etc/ssl/certs/4a6481c9.0 -> GlobalSign_Root_CA_-_R2.pem
+lrwxrwxrwx root root 45 ./etc/ssl/certs/4bfab552.0 -> Starfield_Root_Certificate_Authority_-_G2.pem
+lrwxrwxrwx root root 26 ./etc/ssl/certs/4f316efb.0 -> SwissSign_Gold_CA_-_G2.pem
+lrwxrwxrwx root root 35 ./etc/ssl/certs/5273a94c.0 -> E-Tugra_Certification_Authority.pem
+lrwxrwxrwx root root 32 ./etc/ssl/certs/5443e9e3.0 -> T-TeleSec_GlobalRoot_Class_3.pem
+lrwxrwxrwx root root 27 ./etc/ssl/certs/54657681.0 -> Buypass_Class_2_Root_CA.pem
+lrwxrwxrwx root root 28 ./etc/ssl/certs/57bcb2da.0 -> SwissSign_Silver_CA_-_G2.pem
+lrwxrwxrwx root root 38 ./etc/ssl/certs/5a4d6896.0 -> Staat_der_Nederlanden_Root_CA_-_G3.pem
+lrwxrwxrwx root root 22 ./etc/ssl/certs/5ad8a5d6.0 -> GlobalSign_Root_CA.pem
+lrwxrwxrwx root root 38 ./etc/ssl/certs/5c44d531.0 -> Staat_der_Nederlanden_Root_CA_-_G2.pem
+lrwxrwxrwx root root 26 ./etc/ssl/certs/5cd81ad7.0 -> TeliaSonera_Root_CA_v1.pem
+lrwxrwxrwx root root 26 ./etc/ssl/certs/5d3033c5.0 -> TrustCor_RootCert_CA-1.pem
+lrwxrwxrwx root root 23 ./etc/ssl/certs/5f15c80c.0 -> TWCA_Global_Root_CA.pem
+lrwxrwxrwx root root 27 ./etc/ssl/certs/607986c7.0 -> DigiCert_Global_Root_G2.pem
+lrwxrwxrwx root root 15 ./etc/ssl/certs/6410666e.0 -> Taiwan_GRCA.pem
+lrwxrwxrwx root root 29 ./etc/ssl/certs/653b494a.0 -> Baltimore_CyberTrust_Root.pem
+lrwxrwxrwx root root 40 ./etc/ssl/certs/6b99d060.0 -> Entrust_Root_Certification_Authority.pem
+lrwxrwxrwx root root 20 ./etc/ssl/certs/6d41d539.0 -> Amazon_Root_CA_2.pem
+lrwxrwxrwx root root 44 ./etc/ssl/certs/6fa5da56.0 -> SSL.com_Root_Certification_Authority_RSA.pem
+lrwxrwxrwx root root 24 ./etc/ssl/certs/706f604c.0 -> XRamp_Global_CA_Root.pem
+lrwxrwxrwx root root 25 ./etc/ssl/certs/749e9e03.0 -> QuoVadis_Root_CA_1_G3.pem
+lrwxrwxrwx root root 28 ./etc/ssl/certs/75d1b2ed.0 -> DigiCert_Trusted_Root_G4.pem
+lrwxrwxrwx root root 26 ./etc/ssl/certs/76cb8f92.0 -> Cybertrust_Global_Root.pem
+lrwxrwxrwx root root 22 ./etc/ssl/certs/76faf6c0.0 -> QuoVadis_Root_CA_3.pem
+lrwxrwxrwx root root 63 ./etc/ssl/certs/7719f463.0 -> Hellenic_Academic_and_Research_Institutions_ECC_RootCA_2015.pem
+lrwxrwxrwx root root 35 ./etc/ssl/certs/773e07ad.0 -> OISTE_WISeKey_Global_Root_GC_CA.pem
+lrwxrwxrwx root root 18 ./etc/ssl/certs/7aaf71c0.0 -> TrustCor_ECA-1.pem
+lrwxrwxrwx root root 64 ./etc/ssl/certs/7d0b38bd.0 -> VeriSign_Class_3_Public_Primary_Certification_Authority_-_G4.pem
+lrwxrwxrwx root root 31 ./etc/ssl/certs/7f3d5d1d.0 -> DigiCert_Assured_ID_Root_G3.pem
+lrwxrwxrwx root root 30 ./etc/ssl/certs/812e17de.0 -> Deutsche_Telekom_Root_CA_2.pem
+lrwxrwxrwx root root 34 ./etc/ssl/certs/8160b96c.0 -> Microsec_e-Szigno_Root_CA_2009.pem
+lrwxrwxrwx root root 27 ./etc/ssl/certs/8867006a.0 -> GeoTrust_Universal_CA_2.pem
+lrwxrwxrwx root root 20 ./etc/ssl/certs/8cb5ee0f.0 -> Amazon_Root_CA_3.pem
+lrwxrwxrwx root root 20 ./etc/ssl/certs/8d86cdd1.0 -> certSIGN_ROOT_CA.pem
+lrwxrwxrwx root root 34 ./etc/ssl/certs/930ac5d2.0 -> Actalis_Authentication_Root_CA.pem
+lrwxrwxrwx root root 26 ./etc/ssl/certs/93bc0acc.0 -> AffirmTrust_Networking.pem
+lrwxrwxrwx root root 48 ./etc/ssl/certs/988a38cb.0 -> NetLock_Arany_=Class_Gold=_Főtanúsítvány.pem
+lrwxrwxrwx root root 26 ./etc/ssl/certs/9c2e7d30.0 -> Sonera_Class_2_Root_CA.pem
+lrwxrwxrwx root root 27 ./etc/ssl/certs/9c8dfbd4.0 -> AffirmTrust_Premium_ECC.pem
+lrwxrwxrwx root root 31 ./etc/ssl/certs/9d04f354.0 -> DigiCert_Assured_ID_Root_G2.pem
+lrwxrwxrwx root root 24 ./etc/ssl/certs/9f0f5fd6.0 -> Certinomis_-_Root_CA.pem
+lrwxrwxrwx root root 13 ./etc/ssl/certs/a94d09e5.0 -> ACCVRAIZ1.pem
+lrwxrwxrwx root root 56 ./etc/ssl/certs/ACCVRAIZ1.pem -> ../../../usr/share/ca-certificates/mozilla/ACCVRAIZ1.crt
+lrwxrwxrwx root root 63 ./etc/ssl/certs/AC_RAIZ_FNMT-RCM.pem -> ../../../usr/share/ca-certificates/mozilla/AC_RAIZ_FNMT-RCM.crt
+lrwxrwxrwx root root 77 ./etc/ssl/certs/Actalis_Authentication_Root_CA.pem -> ../../../usr/share/ca-certificates/mozilla/Actalis_Authentication_Root_CA.crt
+lrwxrwxrwx root root 25 ./etc/ssl/certs/ad088e1d.0 -> GeoTrust_Universal_CA.pem
+lrwxrwxrwx root root 69 ./etc/ssl/certs/AddTrust_External_Root.pem -> ../../../usr/share/ca-certificates/mozilla/AddTrust_External_Root.crt
+lrwxrwxrwx root root 45 ./etc/ssl/certs/aee5f10d.0 -> Entrust.net_Premium_2048_Secure_Server_CA.pem
+lrwxrwxrwx root root 69 ./etc/ssl/certs/AffirmTrust_Commercial.pem -> ../../../usr/share/ca-certificates/mozilla/AffirmTrust_Commercial.crt
+lrwxrwxrwx root root 69 ./etc/ssl/certs/AffirmTrust_Networking.pem -> ../../../usr/share/ca-certificates/mozilla/AffirmTrust_Networking.crt
+lrwxrwxrwx root root 70 ./etc/ssl/certs/AffirmTrust_Premium_ECC.pem -> ../../../usr/share/ca-certificates/mozilla/AffirmTrust_Premium_ECC.crt
+lrwxrwxrwx root root 66 ./etc/ssl/certs/AffirmTrust_Premium.pem -> ../../../usr/share/ca-certificates/mozilla/AffirmTrust_Premium.crt
+lrwxrwxrwx root root 63 ./etc/ssl/certs/Amazon_Root_CA_1.pem -> ../../../usr/share/ca-certificates/mozilla/Amazon_Root_CA_1.crt
+lrwxrwxrwx root root 63 ./etc/ssl/certs/Amazon_Root_CA_2.pem -> ../../../usr/share/ca-certificates/mozilla/Amazon_Root_CA_2.crt
+lrwxrwxrwx root root 63 ./etc/ssl/certs/Amazon_Root_CA_3.pem -> ../../../usr/share/ca-certificates/mozilla/Amazon_Root_CA_3.crt
+lrwxrwxrwx root root 63 ./etc/ssl/certs/Amazon_Root_CA_4.pem -> ../../../usr/share/ca-certificates/mozilla/Amazon_Root_CA_4.crt
+lrwxrwxrwx root root 68 ./etc/ssl/certs/Atos_TrustedRoot_2011.pem -> ../../../usr/share/ca-certificates/mozilla/Atos_TrustedRoot_2011.crt
+lrwxrwxrwx root root 104 ./etc/ssl/certs/Autoridad_de_Certificacion_Firmaprofesional_CIF_A62634068.pem -> ../../../usr/share/ca-certificates/mozilla/Autoridad_de_Certificacion_Firmaprofesional_CIF_A62634068.crt
+lrwxrwxrwx root root 31 ./etc/ssl/certs/b0e59380.0 -> GlobalSign_ECC_Root_CA_-_R4.pem
+lrwxrwxrwx root root 31 ./etc/ssl/certs/b1159c4c.0 -> DigiCert_Assured_ID_Root_CA.pem
+lrwxrwxrwx root root 35 ./etc/ssl/certs/b1b8a7f3.0 -> OISTE_WISeKey_Global_Root_GA_CA.pem
+lrwxrwxrwx root root 64 ./etc/ssl/certs/b204d74a.0 -> VeriSign_Class_3_Public_Primary_Certification_Authority_-_G5.pem
+lrwxrwxrwx root root 20 ./etc/ssl/certs/b66938e9.0 -> Secure_Global_CA.pem
+lrwxrwxrwx root root 23 ./etc/ssl/certs/b727005e.0 -> AffirmTrust_Premium.pem
+lrwxrwxrwx root root 37 ./etc/ssl/certs/b7a5b843.0 -> TWCA_Root_Certification_Authority.pem
+lrwxrwxrwx root root 31 ./etc/ssl/certs/ba89ed3b.0 -> thawte_Primary_Root_CA_-_G3.pem
+lrwxrwxrwx root root 72 ./etc/ssl/certs/Baltimore_CyberTrust_Root.pem -> ../../../usr/share/ca-certificates/mozilla/Baltimore_CyberTrust_Root.crt
+lrwxrwxrwx root root 70 ./etc/ssl/certs/Buypass_Class_2_Root_CA.pem -> ../../../usr/share/ca-certificates/mozilla/Buypass_Class_2_Root_CA.crt
+lrwxrwxrwx root root 70 ./etc/ssl/certs/Buypass_Class_3_Root_CA.pem -> ../../../usr/share/ca-certificates/mozilla/Buypass_Class_3_Root_CA.crt
+lrwxrwxrwx root root 51 ./etc/ssl/certs/c01cdfa2.0 -> VeriSign_Universal_Root_Certification_Authority.pem
+lrwxrwxrwx root root 31 ./etc/ssl/certs/c089bbbd.0 -> thawte_Primary_Root_CA_-_G2.pem
+lrwxrwxrwx root root 64 ./etc/ssl/certs/c0ff1f52.0 -> Verisign_Class_3_Public_Primary_Certification_Authority_-_G3.pem
+lrwxrwxrwx root root 34 ./etc/ssl/certs/c28a8a30.0 -> D-TRUST_Root_Class_3_CA_2_2009.pem
+lrwxrwxrwx root root 36 ./etc/ssl/certs/c47d9980.0 -> Chambers_of_Commerce_Root_-_2008.pem
+lrwxrwxrwx root root 37 ./etc/ssl/certs/ca6e4ad9.0 -> ePKI_Root_Certification_Authority.pem
+-rw-r--r-- root root 200061 ./etc/ssl/certs/ca-certificates.crt
+lrwxrwxrwx root root 63 ./etc/ssl/certs/CA_Disig_Root_R2.pem -> ../../../usr/share/ca-certificates/mozilla/CA_Disig_Root_R2.crt
+lrwxrwxrwx root root 44 ./etc/ssl/certs/cbf06781.0 -> Go_Daddy_Root_Certificate_Authority_-_G2.pem
+lrwxrwxrwx root root 14 ./etc/ssl/certs/cc450945.0 -> Izenpe.com.pem
+lrwxrwxrwx root root 34 ./etc/ssl/certs/cd58d51e.0 -> Security_Communication_RootCA2.pem
+lrwxrwxrwx root root 20 ./etc/ssl/certs/cd8c0d63.0 -> AC_RAIZ_FNMT-RCM.pem
+lrwxrwxrwx root root 20 ./etc/ssl/certs/ce5e74ef.0 -> Amazon_Root_CA_1.pem
+lrwxrwxrwx root root 55 ./etc/ssl/certs/Certigna.pem -> ../../../usr/share/ca-certificates/mozilla/Certigna.crt
+lrwxrwxrwx root root 67 ./etc/ssl/certs/Certinomis_-_Root_CA.pem -> ../../../usr/share/ca-certificates/mozilla/Certinomis_-_Root_CA.crt
+lrwxrwxrwx root root 74 ./etc/ssl/certs/Certplus_Class_2_Primary_CA.pem -> ../../../usr/share/ca-certificates/mozilla/Certplus_Class_2_Primary_CA.crt
+lrwxrwxrwx root root 63 ./etc/ssl/certs/certSIGN_ROOT_CA.pem -> ../../../usr/share/ca-certificates/mozilla/certSIGN_ROOT_CA.crt
+lrwxrwxrwx root root 74 ./etc/ssl/certs/Certum_Trusted_Network_CA_2.pem -> ../../../usr/share/ca-certificates/mozilla/Certum_Trusted_Network_CA_2.crt
+lrwxrwxrwx root root 72 ./etc/ssl/certs/Certum_Trusted_Network_CA.pem -> ../../../usr/share/ca-certificates/mozilla/Certum_Trusted_Network_CA.crt
+lrwxrwxrwx root root 59 ./etc/ssl/certs/CFCA_EV_ROOT.pem -> ../../../usr/share/ca-certificates/mozilla/CFCA_EV_ROOT.crt
+lrwxrwxrwx root root 79 ./etc/ssl/certs/Chambers_of_Commerce_Root_-_2008.pem -> ../../../usr/share/ca-certificates/mozilla/Chambers_of_Commerce_Root_-_2008.crt
+lrwxrwxrwx root root 71 ./etc/ssl/certs/Comodo_AAA_Services_root.pem -> ../../../usr/share/ca-certificates/mozilla/Comodo_AAA_Services_root.crt
+lrwxrwxrwx root root 77 ./etc/ssl/certs/COMODO_Certification_Authority.pem -> ../../../usr/share/ca-certificates/mozilla/COMODO_Certification_Authority.crt
+lrwxrwxrwx root root 81 ./etc/ssl/certs/COMODO_ECC_Certification_Authority.pem -> ../../../usr/share/ca-certificates/mozilla/COMODO_ECC_Certification_Authority.crt
+lrwxrwxrwx root root 81 ./etc/ssl/certs/COMODO_RSA_Certification_Authority.pem -> ../../../usr/share/ca-certificates/mozilla/COMODO_RSA_Certification_Authority.crt
+lrwxrwxrwx root root 69 ./etc/ssl/certs/Cybertrust_Global_Root.pem -> ../../../usr/share/ca-certificates/mozilla/Cybertrust_Global_Root.crt
+lrwxrwxrwx root root 37 ./etc/ssl/certs/d4dae3dd.0 -> D-TRUST_Root_Class_3_CA_2_EV_2009.pem
+lrwxrwxrwx root root 38 ./etc/ssl/certs/d6325660.0 -> COMODO_RSA_Certification_Authority.pem
+lrwxrwxrwx root root 22 ./etc/ssl/certs/d7e8dc79.0 -> QuoVadis_Root_CA_2.pem
+lrwxrwxrwx root root 23 ./etc/ssl/certs/d853d49e.0 -> Trustis_FPS_Root_CA.pem
+lrwxrwxrwx root root 27 ./etc/ssl/certs/dc4d6a89.0 -> GlobalSign_Root_CA_-_R6.pem
+lrwxrwxrwx root root 27 ./etc/ssl/certs/dd8e9d41.0 -> DigiCert_Global_Root_G3.pem
+lrwxrwxrwx root root 20 ./etc/ssl/certs/de6d66f3.0 -> Amazon_Root_CA_4.pem
+lrwxrwxrwx root root 26 ./etc/ssl/certs/def36a68.0 -> LuxTrust_Global_Root_2.pem
+lrwxrwxrwx root root 73 ./etc/ssl/certs/Deutsche_Telekom_Root_CA_2.pem -> ../../../usr/share/ca-certificates/mozilla/Deutsche_Telekom_Root_CA_2.crt
+lrwxrwxrwx root root 74 ./etc/ssl/certs/DigiCert_Assured_ID_Root_CA.pem -> ../../../usr/share/ca-certificates/mozilla/DigiCert_Assured_ID_Root_CA.crt
+lrwxrwxrwx root root 74 ./etc/ssl/certs/DigiCert_Assured_ID_Root_G2.pem -> ../../../usr/share/ca-certificates/mozilla/DigiCert_Assured_ID_Root_G2.crt
+lrwxrwxrwx root root 74 ./etc/ssl/certs/DigiCert_Assured_ID_Root_G3.pem -> ../../../usr/share/ca-certificates/mozilla/DigiCert_Assured_ID_Root_G3.crt
+lrwxrwxrwx root root 70 ./etc/ssl/certs/DigiCert_Global_Root_CA.pem -> ../../../usr/share/ca-certificates/mozilla/DigiCert_Global_Root_CA.crt
+lrwxrwxrwx root root 70 ./etc/ssl/certs/DigiCert_Global_Root_G2.pem -> ../../../usr/share/ca-certificates/mozilla/DigiCert_Global_Root_G2.crt
+lrwxrwxrwx root root 70 ./etc/ssl/certs/DigiCert_Global_Root_G3.pem -> ../../../usr/share/ca-certificates/mozilla/DigiCert_Global_Root_G3.crt
+lrwxrwxrwx root root 81 ./etc/ssl/certs/DigiCert_High_Assurance_EV_Root_CA.pem -> ../../../usr/share/ca-certificates/mozilla/DigiCert_High_Assurance_EV_Root_CA.crt
+lrwxrwxrwx root root 71 ./etc/ssl/certs/DigiCert_Trusted_Root_G4.pem -> ../../../usr/share/ca-certificates/mozilla/DigiCert_Trusted_Root_G4.crt
+lrwxrwxrwx root root 61 ./etc/ssl/certs/DST_Root_CA_X3.pem -> ../../../usr/share/ca-certificates/mozilla/DST_Root_CA_X3.crt
+lrwxrwxrwx root root 77 ./etc/ssl/certs/D-TRUST_Root_Class_3_CA_2_2009.pem -> ../../../usr/share/ca-certificates/mozilla/D-TRUST_Root_Class_3_CA_2_2009.crt
+lrwxrwxrwx root root 80 ./etc/ssl/certs/D-TRUST_Root_Class_3_CA_2_EV_2009.pem -> ../../../usr/share/ca-certificates/mozilla/D-TRUST_Root_Class_3_CA_2_EV_2009.crt
+lrwxrwxrwx root root 12 ./etc/ssl/certs/e113c810.0 -> Certigna.pem
+lrwxrwxrwx root root 25 ./etc/ssl/certs/e18bfb83.0 -> QuoVadis_Root_CA_3_G3.pem
+lrwxrwxrwx root root 49 ./etc/ssl/certs/e2799e36.0 -> GeoTrust_Primary_Certification_Authority_-_G3.pem
+lrwxrwxrwx root root 25 ./etc/ssl/certs/e36a6752.0 -> Atos_TrustedRoot_2011.pem
+lrwxrwxrwx root root 35 ./etc/ssl/certs/e73d606e.0 -> OISTE_WISeKey_Global_Root_GB_CA.pem
+lrwxrwxrwx root root 27 ./etc/ssl/certs/e8de2f56.0 -> Buypass_Class_3_Root_CA.pem
+lrwxrwxrwx root root 53 ./etc/ssl/certs/EC-ACC.pem -> ../../../usr/share/ca-certificates/mozilla/EC-ACC.crt
+lrwxrwxrwx root root 28 ./etc/ssl/certs/ee64a828.0 -> Comodo_AAA_Services_root.pem
+lrwxrwxrwx root root 78 ./etc/ssl/certs/EE_Certification_Centre_Root_CA.pem -> ../../../usr/share/ca-certificates/mozilla/EE_Certification_Centre_Root_CA.crt
+lrwxrwxrwx root root 38 ./etc/ssl/certs/eed8c118.0 -> COMODO_ECC_Certification_Authority.pem
+lrwxrwxrwx root root 34 ./etc/ssl/certs/ef954a4e.0 -> IdenTrust_Commercial_Root_CA_1.pem
+lrwxrwxrwx root root 88 ./etc/ssl/certs/Entrust.net_Premium_2048_Secure_Server_CA.pem -> ../../../usr/share/ca-certificates/mozilla/Entrust.net_Premium_2048_Secure_Server_CA.crt
+lrwxrwxrwx root root 89 ./etc/ssl/certs/Entrust_Root_Certification_Authority_-_EC1.pem -> ../../../usr/share/ca-certificates/mozilla/Entrust_Root_Certification_Authority_-_EC1.crt
+lrwxrwxrwx root root 88 ./etc/ssl/certs/Entrust_Root_Certification_Authority_-_G2.pem -> ../../../usr/share/ca-certificates/mozilla/Entrust_Root_Certification_Authority_-_G2.crt
+lrwxrwxrwx root root 83 ./etc/ssl/certs/Entrust_Root_Certification_Authority.pem -> ../../../usr/share/ca-certificates/mozilla/Entrust_Root_Certification_Authority.crt
+lrwxrwxrwx root root 80 ./etc/ssl/certs/ePKI_Root_Certification_Authority.pem -> ../../../usr/share/ca-certificates/mozilla/ePKI_Root_Certification_Authority.crt
+lrwxrwxrwx root root 78 ./etc/ssl/certs/E-Tugra_Certification_Authority.pem -> ../../../usr/share/ca-certificates/mozilla/E-Tugra_Certification_Authority.crt
+lrwxrwxrwx root root 31 ./etc/ssl/certs/f060240e.0 -> Certplus_Class_2_Primary_CA.pem
+lrwxrwxrwx root root 23 ./etc/ssl/certs/f081611a.0 -> Go_Daddy_Class_2_CA.pem
+lrwxrwxrwx root root 47 ./etc/ssl/certs/f0c70a8d.0 -> SSL.com_EV_Root_Certification_Authority_ECC.pem
+lrwxrwxrwx root root 41 ./etc/ssl/certs/f30dd6ad.0 -> USERTrust_ECC_Certification_Authority.pem
+lrwxrwxrwx root root 34 ./etc/ssl/certs/f3377b1b.0 -> Security_Communication_Root_CA.pem
+lrwxrwxrwx root root 24 ./etc/ssl/certs/f387163d.0 -> Starfield_Class_2_CA.pem
+lrwxrwxrwx root root 18 ./etc/ssl/certs/f39fc864.0 -> SecureTrust_CA.pem
+lrwxrwxrwx root root 41 ./etc/ssl/certs/fc5a8f99.0 -> USERTrust_RSA_Certification_Authority.pem
+lrwxrwxrwx root root 19 ./etc/ssl/certs/fe8a2cd8.0 -> SZAFIR_ROOT_CA2.pem
+lrwxrwxrwx root root 49 ./etc/ssl/certs/ff34af3f.0 -> TUBITAK_Kamu_SM_SSL_Kok_Sertifikasi_-_Surum_1.pem
+lrwxrwxrwx root root 69 ./etc/ssl/certs/GDCA_TrustAUTH_R5_ROOT.pem -> ../../../usr/share/ca-certificates/mozilla/GDCA_TrustAUTH_R5_ROOT.crt
+lrwxrwxrwx root root 65 ./etc/ssl/certs/GeoTrust_Global_CA.pem -> ../../../usr/share/ca-certificates/mozilla/GeoTrust_Global_CA.crt
+lrwxrwxrwx root root 92 ./etc/ssl/certs/GeoTrust_Primary_Certification_Authority_-_G2.pem -> ../../../usr/share/ca-certificates/mozilla/GeoTrust_Primary_Certification_Authority_-_G2.crt
+lrwxrwxrwx root root 92 ./etc/ssl/certs/GeoTrust_Primary_Certification_Authority_-_G3.pem -> ../../../usr/share/ca-certificates/mozilla/GeoTrust_Primary_Certification_Authority_-_G3.crt
+lrwxrwxrwx root root 87 ./etc/ssl/certs/GeoTrust_Primary_Certification_Authority.pem -> ../../../usr/share/ca-certificates/mozilla/GeoTrust_Primary_Certification_Authority.crt
+lrwxrwxrwx root root 70 ./etc/ssl/certs/GeoTrust_Universal_CA_2.pem -> ../../../usr/share/ca-certificates/mozilla/GeoTrust_Universal_CA_2.crt
+lrwxrwxrwx root root 68 ./etc/ssl/certs/GeoTrust_Universal_CA.pem -> ../../../usr/share/ca-certificates/mozilla/GeoTrust_Universal_CA.crt
+lrwxrwxrwx root root 77 ./etc/ssl/certs/Global_Chambersign_Root_-_2008.pem -> ../../../usr/share/ca-certificates/mozilla/Global_Chambersign_Root_-_2008.crt
+lrwxrwxrwx root root 74 ./etc/ssl/certs/GlobalSign_ECC_Root_CA_-_R4.pem -> ../../../usr/share/ca-certificates/mozilla/GlobalSign_ECC_Root_CA_-_R4.crt
+lrwxrwxrwx root root 74 ./etc/ssl/certs/GlobalSign_ECC_Root_CA_-_R5.pem -> ../../../usr/share/ca-certificates/mozilla/GlobalSign_ECC_Root_CA_-_R5.crt
+lrwxrwxrwx root root 65 ./etc/ssl/certs/GlobalSign_Root_CA.pem -> ../../../usr/share/ca-certificates/mozilla/GlobalSign_Root_CA.crt
+lrwxrwxrwx root root 70 ./etc/ssl/certs/GlobalSign_Root_CA_-_R2.pem -> ../../../usr/share/ca-certificates/mozilla/GlobalSign_Root_CA_-_R2.crt
+lrwxrwxrwx root root 70 ./etc/ssl/certs/GlobalSign_Root_CA_-_R3.pem -> ../../../usr/share/ca-certificates/mozilla/GlobalSign_Root_CA_-_R3.crt
+lrwxrwxrwx root root 70 ./etc/ssl/certs/GlobalSign_Root_CA_-_R6.pem -> ../../../usr/share/ca-certificates/mozilla/GlobalSign_Root_CA_-_R6.crt
+lrwxrwxrwx root root 66 ./etc/ssl/certs/Go_Daddy_Class_2_CA.pem -> ../../../usr/share/ca-certificates/mozilla/Go_Daddy_Class_2_CA.crt
+lrwxrwxrwx root root 87 ./etc/ssl/certs/Go_Daddy_Root_Certificate_Authority_-_G2.pem -> ../../../usr/share/ca-certificates/mozilla/Go_Daddy_Root_Certificate_Authority_-_G2.crt
+lrwxrwxrwx root root 106 ./etc/ssl/certs/Hellenic_Academic_and_Research_Institutions_ECC_RootCA_2015.pem -> ../../../usr/share/ca-certificates/mozilla/Hellenic_Academic_and_Research_Institutions_ECC_RootCA_2015.crt
+lrwxrwxrwx root root 102 ./etc/ssl/certs/Hellenic_Academic_and_Research_Institutions_RootCA_2011.pem -> ../../../usr/share/ca-certificates/mozilla/Hellenic_Academic_and_Research_Institutions_RootCA_2011.crt
+lrwxrwxrwx root root 102 ./etc/ssl/certs/Hellenic_Academic_and_Research_Institutions_RootCA_2015.pem -> ../../../usr/share/ca-certificates/mozilla/Hellenic_Academic_and_Research_Institutions_RootCA_2015.crt
+lrwxrwxrwx root root 70 ./etc/ssl/certs/Hongkong_Post_Root_CA_1.pem -> ../../../usr/share/ca-certificates/mozilla/Hongkong_Post_Root_CA_1.crt
+lrwxrwxrwx root root 77 ./etc/ssl/certs/IdenTrust_Commercial_Root_CA_1.pem -> ../../../usr/share/ca-certificates/mozilla/IdenTrust_Commercial_Root_CA_1.crt
+lrwxrwxrwx root root 80 ./etc/ssl/certs/IdenTrust_Public_Sector_Root_CA_1.pem -> ../../../usr/share/ca-certificates/mozilla/IdenTrust_Public_Sector_Root_CA_1.crt
+lrwxrwxrwx root root 59 ./etc/ssl/certs/ISRG_Root_X1.pem -> ../../../usr/share/ca-certificates/mozilla/ISRG_Root_X1.crt
+lrwxrwxrwx root root 57 ./etc/ssl/certs/Izenpe.com.pem -> ../../../usr/share/ca-certificates/mozilla/Izenpe.com.crt
+lrwxrwxrwx root root 69 ./etc/ssl/certs/LuxTrust_Global_Root_2.pem -> ../../../usr/share/ca-certificates/mozilla/LuxTrust_Global_Root_2.crt
+lrwxrwxrwx root root 77 ./etc/ssl/certs/Microsec_e-Szigno_Root_CA_2009.pem -> ../../../usr/share/ca-certificates/mozilla/Microsec_e-Szigno_Root_CA_2009.crt
+lrwxrwxrwx root root 91 ./etc/ssl/certs/NetLock_Arany_=Class_Gold=_Főtanúsítvány.pem -> ../../../usr/share/ca-certificates/mozilla/NetLock_Arany_=Class_Gold=_Főtanúsítvány.crt
+lrwxrwxrwx root root 86 ./etc/ssl/certs/Network_Solutions_Certificate_Authority.pem -> ../../../usr/share/ca-certificates/mozilla/Network_Solutions_Certificate_Authority.crt
+lrwxrwxrwx root root 78 ./etc/ssl/certs/OISTE_WISeKey_Global_Root_GA_CA.pem -> ../../../usr/share/ca-certificates/mozilla/OISTE_WISeKey_Global_Root_GA_CA.crt
+lrwxrwxrwx root root 78 ./etc/ssl/certs/OISTE_WISeKey_Global_Root_GB_CA.pem -> ../../../usr/share/ca-certificates/mozilla/OISTE_WISeKey_Global_Root_GB_CA.crt
+lrwxrwxrwx root root 78 ./etc/ssl/certs/OISTE_WISeKey_Global_Root_GC_CA.pem -> ../../../usr/share/ca-certificates/mozilla/OISTE_WISeKey_Global_Root_GC_CA.crt
+lrwxrwxrwx root root 68 ./etc/ssl/certs/QuoVadis_Root_CA_1_G3.pem -> ../../../usr/share/ca-certificates/mozilla/QuoVadis_Root_CA_1_G3.crt
+lrwxrwxrwx root root 68 ./etc/ssl/certs/QuoVadis_Root_CA_2_G3.pem -> ../../../usr/share/ca-certificates/mozilla/QuoVadis_Root_CA_2_G3.crt
+lrwxrwxrwx root root 65 ./etc/ssl/certs/QuoVadis_Root_CA_2.pem -> ../../../usr/share/ca-certificates/mozilla/QuoVadis_Root_CA_2.crt
+lrwxrwxrwx root root 68 ./etc/ssl/certs/QuoVadis_Root_CA_3_G3.pem -> ../../../usr/share/ca-certificates/mozilla/QuoVadis_Root_CA_3_G3.crt
+lrwxrwxrwx root root 65 ./etc/ssl/certs/QuoVadis_Root_CA_3.pem -> ../../../usr/share/ca-certificates/mozilla/QuoVadis_Root_CA_3.crt
+lrwxrwxrwx root root 63 ./etc/ssl/certs/QuoVadis_Root_CA.pem -> ../../../usr/share/ca-certificates/mozilla/QuoVadis_Root_CA.crt
+lrwxrwxrwx root root 63 ./etc/ssl/certs/Secure_Global_CA.pem -> ../../../usr/share/ca-certificates/mozilla/Secure_Global_CA.crt
+lrwxrwxrwx root root 66 ./etc/ssl/certs/SecureSign_RootCA11.pem -> ../../../usr/share/ca-certificates/mozilla/SecureSign_RootCA11.crt
+lrwxrwxrwx root root 61 ./etc/ssl/certs/SecureTrust_CA.pem -> ../../../usr/share/ca-certificates/mozilla/SecureTrust_CA.crt
+lrwxrwxrwx root root 77 ./etc/ssl/certs/Security_Communication_RootCA2.pem -> ../../../usr/share/ca-certificates/mozilla/Security_Communication_RootCA2.crt
+lrwxrwxrwx root root 77 ./etc/ssl/certs/Security_Communication_Root_CA.pem -> ../../../usr/share/ca-certificates/mozilla/Security_Communication_Root_CA.crt
+lrwxrwxrwx root root 69 ./etc/ssl/certs/Sonera_Class_2_Root_CA.pem -> ../../../usr/share/ca-certificates/mozilla/Sonera_Class_2_Root_CA.crt
+lrwxrwxrwx root root 90 ./etc/ssl/certs/SSL.com_EV_Root_Certification_Authority_ECC.pem -> ../../../usr/share/ca-certificates/mozilla/SSL.com_EV_Root_Certification_Authority_ECC.crt
+lrwxrwxrwx root root 93 ./etc/ssl/certs/SSL.com_EV_Root_Certification_Authority_RSA_R2.pem -> ../../../usr/share/ca-certificates/mozilla/SSL.com_EV_Root_Certification_Authority_RSA_R2.crt
+lrwxrwxrwx root root 87 ./etc/ssl/certs/SSL.com_Root_Certification_Authority_ECC.pem -> ../../../usr/share/ca-certificates/mozilla/SSL.com_Root_Certification_Authority_ECC.crt
+lrwxrwxrwx root root 87 ./etc/ssl/certs/SSL.com_Root_Certification_Authority_RSA.pem -> ../../../usr/share/ca-certificates/mozilla/SSL.com_Root_Certification_Authority_RSA.crt
+lrwxrwxrwx root root 79 ./etc/ssl/certs/Staat_der_Nederlanden_EV_Root_CA.pem -> ../../../usr/share/ca-certificates/mozilla/Staat_der_Nederlanden_EV_Root_CA.crt
+lrwxrwxrwx root root 81 ./etc/ssl/certs/Staat_der_Nederlanden_Root_CA_-_G2.pem -> ../../../usr/share/ca-certificates/mozilla/Staat_der_Nederlanden_Root_CA_-_G2.crt
+lrwxrwxrwx root root 81 ./etc/ssl/certs/Staat_der_Nederlanden_Root_CA_-_G3.pem -> ../../../usr/share/ca-certificates/mozilla/Staat_der_Nederlanden_Root_CA_-_G3.crt
+lrwxrwxrwx root root 67 ./etc/ssl/certs/Starfield_Class_2_CA.pem -> ../../../usr/share/ca-certificates/mozilla/Starfield_Class_2_CA.crt
+lrwxrwxrwx root root 88 ./etc/ssl/certs/Starfield_Root_Certificate_Authority_-_G2.pem -> ../../../usr/share/ca-certificates/mozilla/Starfield_Root_Certificate_Authority_-_G2.crt
+lrwxrwxrwx root root 97 ./etc/ssl/certs/Starfield_Services_Root_Certificate_Authority_-_G2.pem -> ../../../usr/share/ca-certificates/mozilla/Starfield_Services_Root_Certificate_Authority_-_G2.crt
+lrwxrwxrwx root root 69 ./etc/ssl/certs/SwissSign_Gold_CA_-_G2.pem -> ../../../usr/share/ca-certificates/mozilla/SwissSign_Gold_CA_-_G2.crt
+lrwxrwxrwx root root 71 ./etc/ssl/certs/SwissSign_Silver_CA_-_G2.pem -> ../../../usr/share/ca-certificates/mozilla/SwissSign_Silver_CA_-_G2.crt
+lrwxrwxrwx root root 62 ./etc/ssl/certs/SZAFIR_ROOT_CA2.pem -> ../../../usr/share/ca-certificates/mozilla/SZAFIR_ROOT_CA2.crt
+lrwxrwxrwx root root 58 ./etc/ssl/certs/Taiwan_GRCA.pem -> ../../../usr/share/ca-certificates/mozilla/Taiwan_GRCA.crt
+lrwxrwxrwx root root 69 ./etc/ssl/certs/TeliaSonera_Root_CA_v1.pem -> ../../../usr/share/ca-certificates/mozilla/TeliaSonera_Root_CA_v1.crt
+lrwxrwxrwx root root 74 ./etc/ssl/certs/thawte_Primary_Root_CA_-_G2.pem -> ../../../usr/share/ca-certificates/mozilla/thawte_Primary_Root_CA_-_G2.crt
+lrwxrwxrwx root root 74 ./etc/ssl/certs/thawte_Primary_Root_CA_-_G3.pem -> ../../../usr/share/ca-certificates/mozilla/thawte_Primary_Root_CA_-_G3.crt
+lrwxrwxrwx root root 69 ./etc/ssl/certs/thawte_Primary_Root_CA.pem -> ../../../usr/share/ca-certificates/mozilla/thawte_Primary_Root_CA.crt
+lrwxrwxrwx root root 61 ./etc/ssl/certs/TrustCor_ECA-1.pem -> ../../../usr/share/ca-certificates/mozilla/TrustCor_ECA-1.crt
+lrwxrwxrwx root root 69 ./etc/ssl/certs/TrustCor_RootCert_CA-1.pem -> ../../../usr/share/ca-certificates/mozilla/TrustCor_RootCert_CA-1.crt
+lrwxrwxrwx root root 69 ./etc/ssl/certs/TrustCor_RootCert_CA-2.pem -> ../../../usr/share/ca-certificates/mozilla/TrustCor_RootCert_CA-2.crt
+lrwxrwxrwx root root 66 ./etc/ssl/certs/Trustis_FPS_Root_CA.pem -> ../../../usr/share/ca-certificates/mozilla/Trustis_FPS_Root_CA.crt
+lrwxrwxrwx root root 75 ./etc/ssl/certs/T-TeleSec_GlobalRoot_Class_2.pem -> ../../../usr/share/ca-certificates/mozilla/T-TeleSec_GlobalRoot_Class_2.crt
+lrwxrwxrwx root root 75 ./etc/ssl/certs/T-TeleSec_GlobalRoot_Class_3.pem -> ../../../usr/share/ca-certificates/mozilla/T-TeleSec_GlobalRoot_Class_3.crt
+lrwxrwxrwx root root 92 ./etc/ssl/certs/TUBITAK_Kamu_SM_SSL_Kok_Sertifikasi_-_Surum_1.pem -> ../../../usr/share/ca-certificates/mozilla/TUBITAK_Kamu_SM_SSL_Kok_Sertifikasi_-_Surum_1.crt
+lrwxrwxrwx root root 66 ./etc/ssl/certs/TWCA_Global_Root_CA.pem -> ../../../usr/share/ca-certificates/mozilla/TWCA_Global_Root_CA.crt
+lrwxrwxrwx root root 80 ./etc/ssl/certs/TWCA_Root_Certification_Authority.pem -> ../../../usr/share/ca-certificates/mozilla/TWCA_Root_Certification_Authority.crt
+lrwxrwxrwx root root 84 ./etc/ssl/certs/USERTrust_ECC_Certification_Authority.pem -> ../../../usr/share/ca-certificates/mozilla/USERTrust_ECC_Certification_Authority.crt
+lrwxrwxrwx root root 84 ./etc/ssl/certs/USERTrust_RSA_Certification_Authority.pem -> ../../../usr/share/ca-certificates/mozilla/USERTrust_RSA_Certification_Authority.crt
+lrwxrwxrwx root root 107 ./etc/ssl/certs/Verisign_Class_3_Public_Primary_Certification_Authority_-_G3.pem -> ../../../usr/share/ca-certificates/mozilla/Verisign_Class_3_Public_Primary_Certification_Authority_-_G3.crt
+lrwxrwxrwx root root 107 ./etc/ssl/certs/VeriSign_Class_3_Public_Primary_Certification_Authority_-_G4.pem -> ../../../usr/share/ca-certificates/mozilla/VeriSign_Class_3_Public_Primary_Certification_Authority_-_G4.crt
+lrwxrwxrwx root root 107 ./etc/ssl/certs/VeriSign_Class_3_Public_Primary_Certification_Authority_-_G5.pem -> ../../../usr/share/ca-certificates/mozilla/VeriSign_Class_3_Public_Primary_Certification_Authority_-_G5.crt
+lrwxrwxrwx root root 94 ./etc/ssl/certs/VeriSign_Universal_Root_Certification_Authority.pem -> ../../../usr/share/ca-certificates/mozilla/VeriSign_Universal_Root_Certification_Authority.crt
+lrwxrwxrwx root root 67 ./etc/ssl/certs/XRamp_Global_CA_Root.pem -> ../../../usr/share/ca-certificates/mozilla/XRamp_Global_CA_Root.crt
+-rw-r--r-- root root 10909 ./etc/ssl/openssl.cnf
+drwxr-xr-x root root 4096 ./etc/ssl/private
+-rw-r--r-- root root 2128 ./etc/sysctl.conf
+-rw-r--r-- root root 69 ./etc/syslog.conf
+-rw-r--r-- root root 651 ./etc/syslog-startup.conf
+drwxr-xr-x root root 4096 ./etc/terminfo
+drwxr-xr-x root root 4096 ./etc/terminfo/a
+-rw-r--r-- root root 1481 ./etc/terminfo/a/ansi
+drwxr-xr-x root root 4096 ./etc/terminfo/d
+-rw-r--r-- root root 308 ./etc/terminfo/d/dumb
+drwxr-xr-x root root 4096 ./etc/terminfo/l
+-rw-r--r-- root root 1730 ./etc/terminfo/l/linux
+drwxr-xr-x root root 4096 ./etc/terminfo/r
+-rw-r--r-- root root 2222 ./etc/terminfo/r/rxvt
+drwxr-xr-x root root 4096 ./etc/terminfo/s
+-rw-r--r-- root root 1573 ./etc/terminfo/s/screen
+-rw-r--r-- root root 1687 ./etc/terminfo/s/screen-256color
+-rw-r--r-- root root 1004 ./etc/terminfo/s/sun
+drwxr-xr-x root root 4096 ./etc/terminfo/v
+-rw-r--r-- root root 1190 ./etc/terminfo/v/vt100
+-rw-r--r-- root root 1184 ./etc/terminfo/v/vt102
+-rw-r--r-- root root 1377 ./etc/terminfo/v/vt200
+-rw-r--r-- root root 1377 ./etc/terminfo/v/vt220
+-rw-r--r-- root root 470 ./etc/terminfo/v/vt52
+drwxr-xr-x root root 4096 ./etc/terminfo/x
+-rw-r--r-- root root 3780 ./etc/terminfo/x/xterm-256color
+-rw-r--r-- root root 1551 ./etc/terminfo/x/xterm-color
+-rw-r--r-- root root 2240 ./etc/terminfo/x/xterm-xfree86
+lrwxrwxrwx root root 11 ./etc/terminfo/x/xterm -> xterm-color
+-rw-r--r-- root root 15 ./etc/timestamp
+drwxr-xr-x root root 4096 ./etc/udev
+drwxr-xr-x root root 4096 ./etc/udev/rules.d
+-rw-r--r-- root root 0 ./etc/udev/rules.d/80-net-name-slot.rules
+-rw-r--r-- root root 885 ./etc/udev/rules.d/local.rules
+-rw-r--r-- root root 49 ./etc/udev/udev.conf
+drwxr-xr-x root root 4096 ./etc/udhcpc.d
+-rwxr-xr-x root root 2652 ./etc/udhcpc.d/50default
+-rw-r--r-- root root 15 ./etc/version
+-rw-r--r-- root root 642 ./etc/xattr.conf
+drwxr-xr-x root root 4096 ./home
+drwx------ root root 4096 ./home/root
+drwxr-xr-x root root 4096 ./lib
+drwxr-xr-x root root 4096 ./lib/depmod.d
+-rw-r--r-- root root 71 ./lib/depmod.d/search.conf
+-rwxr-xr-x root root 177712 ./lib/ld-2.31.so
+lrwxrwxrwx root root 10 ./lib/ld-linux-x86-64.so.2 -> ld-2.31.so
+-rwxr-xr-x root root 18696 ./lib/libanl-2.31.so
+lrwxrwxrwx root root 14 ./lib/libanl.so.1 -> libanl-2.31.so
+-rwxr-xr-x root root 326600 ./lib/libblkid.so.1.1.0
+lrwxrwxrwx root root 17 ./lib/libblkid.so.1 -> libblkid.so.1.1.0
+-rwxr-xr-x root root 14296 ./lib/libBrokenLocale-2.31.so
+lrwxrwxrwx root root 23 ./lib/libBrokenLocale.so.1 -> libBrokenLocale-2.31.so
+-rwxr-xr-x root root 1806504 ./lib/libc-2.31.so
+-rwxr-xr-x root root 26512 ./lib/libcap-ng.so.0.0.0
+lrwxrwxrwx root root 18 ./lib/libcap-ng.so.0 -> libcap-ng.so.0.0.0
+-rw-r--r-- root root 39152 ./lib/libcap.so.2.33
+lrwxrwxrwx root root 14 ./lib/libcap.so.2 -> libcap.so.2.33
+lrwxrwxrwx root root 11 ./lib/libcap.so -> libcap.so.2
+-rwxr-xr-x root root 18320 ./lib/libcom_err.so.2.1
+lrwxrwxrwx root root 17 ./lib/libcom_err.so.2 -> libcom_err.so.2.1
+lrwxrwxrwx root root 15 ./lib/libcom_err.so -> libcom_err.so.2
+lrwxrwxrwx root root 12 ./lib/libc.so.6 -> libc-2.31.so
+-rwxr-xr-x root root 14360 ./lib/libdl-2.31.so
+lrwxrwxrwx root root 13 ./lib/libdl.so.2 -> libdl-2.31.so
+-rwxr-xr-x root root 44616 ./lib/libe2p.so.2.3
+lrwxrwxrwx root root 13 ./lib/libe2p.so.2 -> libe2p.so.2.3
+lrwxrwxrwx root root 11 ./lib/libe2p.so -> libe2p.so.2
+-rwxr-xr-x root root 426264 ./lib/libext2fs.so.2.4
+lrwxrwxrwx root root 16 ./lib/libext2fs.so.2 -> libext2fs.so.2.4
+lrwxrwxrwx root root 14 ./lib/libext2fs.so -> libext2fs.so.2
+-rwxr-xr-x root root 440104 ./lib/libfdisk.so.1.1.0
+lrwxrwxrwx root root 17 ./lib/libfdisk.so.1 -> libfdisk.so.1.1.0
+-rw-r--r-- root root 132 ./lib/libgcc_s.so
+-rw-r--r-- root root 100248 ./lib/libgcc_s.so.1
+-rwxr-xr-x root root 1312800 ./lib/libm-2.31.so
+-rwxr-xr-x root root 379432 ./lib/libmount.so.1.1.0
+lrwxrwxrwx root root 17 ./lib/libmount.so.1 -> libmount.so.1.1.0
+lrwxrwxrwx root root 12 ./lib/libm.so.6 -> libm-2.31.so
+-rwxr-xr-x root root 174104 ./lib/libmvec-2.31.so
+lrwxrwxrwx root root 15 ./lib/libmvec.so.1 -> libmvec-2.31.so
+-rwxr-xr-x root root 157512 ./lib/libncurses.so.5.9
+lrwxrwxrwx root root 17 ./lib/libncurses.so.5 -> libncurses.so.5.9
+-rwxr-xr-x root root 210760 ./lib/libncursesw.so.5.9
+lrwxrwxrwx root root 18 ./lib/libncursesw.so.5 -> libncursesw.so.5.9
+-rwxr-xr-x root root 92184 ./lib/libnsl-2.31.so
+lrwxrwxrwx root root 14 ./lib/libnsl.so.1 -> libnsl-2.31.so
+-rwxr-xr-x root root 35288 ./lib/libnss_compat-2.31.so
+lrwxrwxrwx root root 21 ./lib/libnss_compat.so.2 -> libnss_compat-2.31.so
+-rwxr-xr-x root root 30752 ./lib/libnss_db-2.31.so
+lrwxrwxrwx root root 17 ./lib/libnss_db.so.2 -> libnss_db-2.31.so
+-rwxr-xr-x root root 22560 ./lib/libnss_dns-2.31.so
+lrwxrwxrwx root root 18 ./lib/libnss_dns.so.2 -> libnss_dns-2.31.so
+-rwxr-xr-x root root 51232 ./lib/libnss_files-2.31.so
+lrwxrwxrwx root root 20 ./lib/libnss_files.so.2 -> libnss_files-2.31.so
+-rwxr-xr-x root root 22560 ./lib/libnss_hesiod-2.31.so
+lrwxrwxrwx root root 21 ./lib/libnss_hesiod.so.2 -> libnss_hesiod-2.31.so
+-rwxr-xr-x root root 113296 ./lib/libpthread-2.31.so
+lrwxrwxrwx root root 18 ./lib/libpthread.so.0 -> libpthread-2.31.so
+-rwxr-xr-x root root 88320 ./lib/libresolv-2.31.so
+lrwxrwxrwx root root 17 ./lib/libresolv.so.2 -> libresolv-2.31.so
+-rwxr-xr-x root root 39328 ./lib/librt-2.31.so
+lrwxrwxrwx root root 13 ./lib/librt.so.1 -> librt-2.31.so
+-rwxr-xr-x root root 227432 ./lib/libsmartcols.so.1.1.0
+lrwxrwxrwx root root 21 ./lib/libsmartcols.so.1 -> libsmartcols.so.1.1.0
+-rwxr-xr-x root root 34704 ./lib/libss.so.2.0
+lrwxrwxrwx root root 12 ./lib/libss.so.2 -> libss.so.2.0
+lrwxrwxrwx root root 10 ./lib/libss.so -> libss.so.2
+-rwxr-xr-x root root 35416 ./lib/libthread_db-1.0.so
+lrwxrwxrwx root root 19 ./lib/libthread_db.so.1 -> libthread_db-1.0.so
+-rwxr-xr-x root root 175208 ./lib/libtinfo.so.5.9
+lrwxrwxrwx root root 15 ./lib/libtinfo.so.5 -> libtinfo.so.5.9
+-rwxr-xr-x root root 157912 ./lib/libudev.so.1.6.3
+lrwxrwxrwx root root 16 ./lib/libudev.so.1 -> libudev.so.1.6.3
+-rwxr-xr-x root root 14360 ./lib/libutil-2.31.so
+lrwxrwxrwx root root 15 ./lib/libutil.so.1 -> libutil-2.31.so
+-rwxr-xr-x root root 30752 ./lib/libuuid.so.1.3.0
+lrwxrwxrwx root root 16 ./lib/libuuid.so.1 -> libuuid.so.1.3.0
+-rwxr-xr-x root root 39816 ./lib/libwrap.so.0.7.6
+lrwxrwxrwx root root 16 ./lib/libwrap.so.0 -> libwrap.so.0.7.6
+-rwxr-xr-x root root 100312 ./lib/libz.so.1.2.11
+lrwxrwxrwx root root 14 ./lib/libz.so.1 -> libz.so.1.2.11
+drwxr-xr-x root root 4096 ./lib/modprobe.d
+drwxr-xr-x root root 4096 ./lib/modules
+drwxr-xr-x root root 4096 ./lib/modules/5.4.40-yocto-standard
+drwxr-xr-x root root 4096 ./lib/modules/5.4.40-yocto-standard/kernel
+drwxr-xr-x root root 4096 ./lib/modules/5.4.40-yocto-standard/kernel/drivers
+drwxr-xr-x root root 4096 ./lib/modules/5.4.40-yocto-standard/kernel/drivers/video
+drwxr-xr-x root root 4096 ./lib/modules/5.4.40-yocto-standard/kernel/drivers/video/fbdev
+-rw-r--r-- root root 46440 ./lib/modules/5.4.40-yocto-standard/kernel/drivers/video/fbdev/uvesafb.ko
+drwxr-xr-x root root 4096 ./lib/modules/5.4.40-yocto-standard/kernel/net
+drwxr-xr-x root root 4096 ./lib/modules/5.4.40-yocto-standard/kernel/net/ipv4
+drwxr-xr-x root root 4096 ./lib/modules/5.4.40-yocto-standard/kernel/net/ipv4/netfilter
+-rw-r--r-- root root 6912 ./lib/modules/5.4.40-yocto-standard/kernel/net/ipv4/netfilter/iptable_filter.ko
+-rw-r--r-- root root 6272 ./lib/modules/5.4.40-yocto-standard/kernel/net/ipv4/netfilter/iptable_nat.ko
+-rw-r--r-- root root 32144 ./lib/modules/5.4.40-yocto-standard/kernel/net/ipv4/netfilter/ip_tables.ko
+-rw-r--r-- root root 6160 ./lib/modules/5.4.40-yocto-standard/kernel/net/ipv4/netfilter/nf_defrag_ipv4.ko
+drwxr-xr-x root root 4096 ./lib/modules/5.4.40-yocto-standard/kernel/net/ipv6
+drwxr-xr-x root root 4096 ./lib/modules/5.4.40-yocto-standard/kernel/net/ipv6/netfilter
+-rw-r--r-- root root 6928 ./lib/modules/5.4.40-yocto-standard/kernel/net/ipv6/netfilter/ip6table_filter.ko
+-rw-r--r-- root root 32640 ./lib/modules/5.4.40-yocto-standard/kernel/net/ipv6/netfilter/ip6_tables.ko
+-rw-r--r-- root root 16472 ./lib/modules/5.4.40-yocto-standard/kernel/net/ipv6/netfilter/nf_defrag_ipv6.ko
+drwxr-xr-x root root 4096 ./lib/modules/5.4.40-yocto-standard/kernel/net/netfilter
+-rw-r--r-- root root 164400 ./lib/modules/5.4.40-yocto-standard/kernel/net/netfilter/nf_conntrack.ko
+-rw-r--r-- root root 45776 ./lib/modules/5.4.40-yocto-standard/kernel/net/netfilter/nf_nat.ko
+-rw-r--r-- root root 49480 ./lib/modules/5.4.40-yocto-standard/kernel/net/netfilter/x_tables.ko
+-rw-r--r-- root root 199 ./lib/modules/5.4.40-yocto-standard/modules.alias
+-rw-r--r-- root root 443 ./lib/modules/5.4.40-yocto-standard/modules.alias.bin
+-rw-r--r-- root root 9285 ./lib/modules/5.4.40-yocto-standard/modules.builtin
+-rw-r--r-- root root 10874 ./lib/modules/5.4.40-yocto-standard/modules.builtin.bin
+-rw-r--r-- root root 68434 ./lib/modules/5.4.40-yocto-standard/modules.builtin.modinfo
+-rw-r--r-- root root 1099 ./lib/modules/5.4.40-yocto-standard/modules.dep
+-rw-r--r-- root root 1794 ./lib/modules/5.4.40-yocto-standard/modules.dep.bin
+-rw-r--r-- root root 0 ./lib/modules/5.4.40-yocto-standard/modules.devname
+-rw-r--r-- root root 17785 ./lib/modules/5.4.40-yocto-standard/modules.order
+-rw-r--r-- root root 55 ./lib/modules/5.4.40-yocto-standard/modules.softdep
+-rw-r--r-- root root 7817 ./lib/modules/5.4.40-yocto-standard/modules.symbols
+-rw-r--r-- root root 9233 ./lib/modules/5.4.40-yocto-standard/modules.symbols.bin
+drwxr-xr-x root root 4096 ./lib/udev
+-rwxr-xr-x root root 104640 ./lib/udev/ata_id
+-rwxr-xr-x root root 116936 ./lib/udev/cdrom_id
+-rwxr-xr-x root root 100552 ./lib/udev/collect
+-rwxr-xr-x root root 14296 ./lib/udev/mtd_probe
+drwxr-xr-x root root 4096 ./lib/udev/rules.d
+-rw-r--r-- root root 321 ./lib/udev/rules.d/01-md-raid-creating.rules
+-rw-r--r-- root root 121 ./lib/udev/rules.d/50-firmware.rules
+-rw-r--r-- root root 3677 ./lib/udev/rules.d/50-udev-default.rules
+-rw-r--r-- root root 620 ./lib/udev/rules.d/60-block.rules
+-rw-r--r-- root root 1071 ./lib/udev/rules.d/60-cdrom_id.rules
+-rw-r--r-- root root 413 ./lib/udev/rules.d/60-drm.rules
+-rw-r--r-- root root 974 ./lib/udev/rules.d/60-evdev.rules
+-rw-r--r-- root root 282 ./lib/udev/rules.d/60-input-id.rules
+-rw-r--r-- root root 616 ./lib/udev/rules.d/60-persistent-alsa.rules
+-rw-r--r-- root root 2710 ./lib/udev/rules.d/60-persistent-input.rules
+-rw-r--r-- root root 6521 ./lib/udev/rules.d/60-persistent-storage.rules
+-rw-r--r-- root root 1509 ./lib/udev/rules.d/60-persistent-storage-tape.rules
+-rw-r--r-- root root 769 ./lib/udev/rules.d/60-persistent-v4l.rules
+-rw-r--r-- root root 727 ./lib/udev/rules.d/60-sensor.rules
+-rw-r--r-- root root 1190 ./lib/udev/rules.d/60-serial.rules
+-rw-r--r-- root root 2134 ./lib/udev/rules.d/63-md-raid-arrays.rules
+-rw-r--r-- root root 387 ./lib/udev/rules.d/64-btrfs-dm.rules
+-rw-r--r-- root root 574 ./lib/udev/rules.d/64-btrfs.rules
+-rw-r--r-- root root 1444 ./lib/udev/rules.d/64-md-raid-assembly.rules
+-rw-r--r-- root root 846 ./lib/udev/rules.d/69-md-clustered-confirm-device.rules
+-rw-r--r-- root root 432 ./lib/udev/rules.d/70-joystick.rules
+-rw-r--r-- root root 734 ./lib/udev/rules.d/70-mouse.rules
+-rw-r--r-- root root 473 ./lib/udev/rules.d/70-touchpad.rules
+-rw-r--r-- root root 452 ./lib/udev/rules.d/75-net-description.rules
+-rw-r--r-- root root 174 ./lib/udev/rules.d/75-probe_mtd.rules
+-rw-r--r-- root root 4816 ./lib/udev/rules.d/78-sound-card.rules
+-rw-r--r-- root root 615 ./lib/udev/rules.d/80-drivers.rules
+-rw-r--r-- root root 491 ./lib/udev/rules.d/80-net-name-slot.rules
+-rwxr-xr-x root root 109304 ./lib/udev/scsi_id
+-rwxr-xr-x root root 67776 ./lib/udev/v4l_id
+drwxr-xr-x root root 4096 ./media
+drwxr-xr-x root root 4096 ./mnt
+dr-xr-xr-x root root 4096 ./proc
+drwxr-xr-x root root 4096 ./run
+drwxr-xr-x root root 4096 ./sbin
+-rwxr-xr-x root root 64736 ./sbin/agetty
+-rwxr-xr-x root root 34792 ./sbin/badblocks
+lrwxrwxrwx root root 22 ./sbin/blkid -> /sbin/blkid.util-linux
+-rwxr-xr-x root root 120912 ./sbin/blkid.util-linux
+lrwxrwxrwx root root 25 ./sbin/blockdev -> /sbin/blockdev.util-linux
+-rwxr-xr-x root root 63536 ./sbin/blockdev.util-linux
+-rwxr-xr-x root root 22736 ./sbin/bootlogd
+-rwxr-xr-x root root 104568 ./sbin/bridge
+-rwxr-xr-x root root 96664 ./sbin/cfdisk
+-rwxr-xr-x root root 38952 ./sbin/ctrlaltdel
+-rwxr-xr-x root root 239064 ./sbin/debugfs
+lrwxrwxrwx root root 11 ./sbin/depmod.kmod -> ../bin/kmod
+lrwxrwxrwx root root 17 ./sbin/depmod -> /sbin/depmod.kmod
+-rwxr-xr-x root root 30768 ./sbin/dumpe2fs
+-rwxr-xr-x root root 14376 ./sbin/e2freefrag
+-rwxr-xr-x root root 330808 ./sbin/e2fsck
+-rwxr-xr-x root root 38952 ./sbin/e2image
+-rwxr-xr-x root root 30768 ./sbin/e2mmpstatus
+-rwxr-xr-x root root 22560 ./sbin/e2undo
+-rwxr-xr-x root root 26656 ./sbin/e4crypt
+-rwxr-xr-x root root 34776 ./sbin/e4defrag
+lrwxrwxrwx root root 22 ./sbin/fdisk -> /sbin/fdisk.util-linux
+-rwxr-xr-x root root 149600 ./sbin/fdisk.util-linux
+-rwxr-xr-x root root 18416 ./sbin/filefrag
+-rwxr-xr-x root root 330808 ./sbin/fsck.ext2
+-rwxr-xr-x root root 330808 ./sbin/fsck.ext3
+-rwxr-xr-x root root 330808 ./sbin/fsck.ext4
+lrwxrwxrwx root root 21 ./sbin/fsck -> /sbin/fsck.util-linux
+-rwxr-xr-x root root 55392 ./sbin/fsck.util-linux
+-rwxr-xr-x root root 14296 ./sbin/fstab-decode
+lrwxrwxrwx root root 23 ./sbin/fstrim -> /sbin/fstrim.util-linux
+-rwxr-xr-x root root 71728 ./sbin/fstrim.util-linux
+lrwxrwxrwx root root 12 ./sbin/getty -> /sbin/agetty
+lrwxrwxrwx root root 19 ./sbin/halt -> /sbin/halt.sysvinit
+-rwsr-xr-- root shutdown 22512 ./sbin/halt.sysvinit
+lrwxrwxrwx root root 24 ./sbin/hwclock -> /sbin/hwclock.util-linux
+-rwxr-xr-x root root 80048 ./sbin/hwclock.util-linux
+-rwxr-xr-x root root 3109 ./sbin/ifcfg
+lrwxrwxrwx root root 19 ./sbin/ifconfig -> /bin/busybox.nosuid
+lrwxrwxrwx root root 19 ./sbin/ifdown -> /bin/busybox.nosuid
+lrwxrwxrwx root root 19 ./sbin/ifup -> /bin/busybox.nosuid
+lrwxrwxrwx root root 19 ./sbin/init -> /sbin/init.sysvinit
+-rwxr-xr-x root root 47944 ./sbin/init.sysvinit
+lrwxrwxrwx root root 11 ./sbin/insmod.kmod -> ../bin/kmod
+lrwxrwxrwx root root 17 ./sbin/insmod -> /sbin/insmod.kmod
+-rwxr-xr-x root root 619960 ./sbin/ip.iproute2
+lrwxrwxrwx root root 17 ./sbin/ip -> /sbin/ip.iproute2
+-rwxr-xr-x root root 26664 ./sbin/killall5
+lrwxrwxrwx root root 19 ./sbin/klogd -> /bin/busybox.nosuid
+-rwxr-xr-x root root 887640 ./sbin/ldconfig
+lrwxrwxrwx root root 19 ./sbin/loadkmap -> /bin/busybox.nosuid
+lrwxrwxrwx root root 19 ./sbin/logread -> /bin/busybox.nosuid
+-rwxr-xr-x root root 14296 ./sbin/logsave
+lrwxrwxrwx root root 24 ./sbin/losetup -> /sbin/losetup.util-linux
+-rwxr-xr-x root root 112808 ./sbin/losetup.util-linux
+lrwxrwxrwx root root 15 ./sbin/lsmod -> /bin/lsmod.kmod
+-rwxr-xr-x root root 595280 ./sbin/mdadm
+-rwxr-xr-x root root 328880 ./sbin/mdmon
+-rwxr-xr-x root root 137512 ./sbin/mke2fs.e2fsprogs
+lrwxrwxrwx root root 22 ./sbin/mke2fs -> /sbin/mke2fs.e2fsprogs
+-rwxr-xr-x root root 137512 ./sbin/mkfs.ext2.e2fsprogs
+lrwxrwxrwx root root 25 ./sbin/mkfs.ext2 -> /sbin/mkfs.ext2.e2fsprogs
+-rwxr-xr-x root root 137512 ./sbin/mkfs.ext3
+-rwxr-xr-x root root 137512 ./sbin/mkfs.ext4
+-rwxr-xr-x root root 14296 ./sbin/mklost+found
+lrwxrwxrwx root root 23 ./sbin/mkswap -> /sbin/mkswap.util-linux
+-rwxr-xr-x root root 104504 ./sbin/mkswap.util-linux
+lrwxrwxrwx root root 11 ./sbin/modinfo.kmod -> ../bin/kmod
+lrwxrwxrwx root root 18 ./sbin/modinfo -> /sbin/modinfo.kmod
+lrwxrwxrwx root root 11 ./sbin/modprobe.kmod -> ../bin/kmod
+lrwxrwxrwx root root 19 ./sbin/modprobe -> /sbin/modprobe.kmod
+lrwxrwxrwx root root 20 ./sbin/nologin -> /sbin/nologin.shadow
+-rwxr-xr-x root root 14296 ./sbin/nologin.shadow
+-rwxr-xr-x root root 14384 ./sbin/nologin.util-linux
+lrwxrwxrwx root root 27 ./sbin/pivot_root -> /sbin/pivot_root.util-linux
+-rwxr-xr-x root root 14384 ./sbin/pivot_root.util-linux
+-rwxr-xr-x root root 2460 ./sbin/populate-extfs.sh
+lrwxrwxrwx root root 23 ./sbin/poweroff -> /sbin/poweroff.sysvinit
+lrwxrwxrwx root root 13 ./sbin/poweroff.sysvinit -> halt.sysvinit
+lrwxrwxrwx root root 21 ./sbin/reboot -> /sbin/reboot.sysvinit
+lrwxrwxrwx root root 13 ./sbin/reboot.sysvinit -> halt.sysvinit
+lrwxrwxrwx root root 11 ./sbin/rmmod.kmod -> ../bin/kmod
+lrwxrwxrwx root root 16 ./sbin/rmmod -> /sbin/rmmod.kmod
+lrwxrwxrwx root root 19 ./sbin/route -> /bin/busybox.nosuid
+-rwxr-xr-x root root 208 ./sbin/routef
+-rwxr-xr-x root root 1656 ./sbin/routel
+-rwxr-xr-x root root 75832 ./sbin/rtmon
+-rwxr-xr-x root root 70 ./sbin/rtpr
+lrwxrwxrwx root root 23 ./sbin/runlevel -> /sbin/runlevel.sysvinit
+-rwxr-xr-x root root 14304 ./sbin/runlevel.sysvinit
+lrwxrwxrwx root root 19 ./sbin/setconsole -> /bin/busybox.nosuid
+lrwxrwxrwx root root 23 ./sbin/shutdown -> /sbin/shutdown.sysvinit
+-rwsr-xr-- root shutdown 30744 ./sbin/shutdown.sysvinit
+lrwxrwxrwx root root 19 ./sbin/start-stop-daemon -> /bin/busybox.nosuid
+lrwxrwxrwx root root 24 ./sbin/sulogin -> /sbin/sulogin.util-linux
+-rwxr-xr-x root root 47152 ./sbin/sulogin.util-linux
+lrwxrwxrwx root root 24 ./sbin/swapoff -> /sbin/swapoff.util-linux
+-rwxr-xr-x root root 22576 ./sbin/swapoff.util-linux
+lrwxrwxrwx root root 23 ./sbin/swapon -> /sbin/swapon.util-linux
+-rwxr-xr-x root root 51248 ./sbin/swapon.util-linux
+lrwxrwxrwx root root 28 ./sbin/switch_root -> /sbin/switch_root.util-linux
+-rwxr-xr-x root root 14384 ./sbin/switch_root.util-linux
+-rwxr-xr-x root root 30768 ./sbin/sysctl.procps
+lrwxrwxrwx root root 19 ./sbin/sysctl -> /sbin/sysctl.procps
+lrwxrwxrwx root root 19 ./sbin/syslogd -> /bin/busybox.nosuid
+lrwxrwxrwx root root 4 ./sbin/telinit -> init
+lrwxrwxrwx root root 16 ./sbin/udevadm -> /usr/bin/udevadm
+-rwxr-xr-x root root 334168 ./sbin/udevd
+lrwxrwxrwx root root 19 ./sbin/udhcpc -> /bin/busybox.nosuid
+-rwxr-xr-x root root 133264 ./sbin/v86d
+lrwxrwxrwx root root 17 ./sbin/vigr -> /sbin/vigr.shadow
+lrwxrwxrwx root root 11 ./sbin/vigr.shadow -> vipw.shadow
+lrwxrwxrwx root root 17 ./sbin/vipw -> /sbin/vipw.shadow
+-rwxr-xr-x root root 61496 ./sbin/vipw.shadow
+dr-xr-xr-x root root 4096 ./sys
+drwxrwxrwt root root 4096 ./tmp
+drwxr-xr-x root root 4096 ./usr
+drwxr-xr-x root root 20480 ./usr/bin
+lrwxrwxrwx root root 36 ./usr/bin/addr2line -> /usr/bin/x86_64-poky-linux-addr2line
+-rwxr-xr-x root root 43208 ./usr/bin/arch.coreutils
+lrwxrwxrwx root root 23 ./usr/bin/arch -> /usr/bin/arch.coreutils
+lrwxrwxrwx root root 29 ./usr/bin/ar -> /usr/bin/x86_64-poky-linux-ar
+lrwxrwxrwx root root 29 ./usr/bin/as -> /usr/bin/x86_64-poky-linux-as
+-rwxr-xr-x root root 14288 ./usr/bin/attr
+lrwxrwxrwx root root 13 ./usr/bin/awk -> /usr/bin/gawk
+-rwxr-xr-x root root 63680 ./usr/bin/b2sum
+-rwxr-xr-x root root 47264 ./usr/bin/base32
+-rwxr-xr-x root root 47272 ./usr/bin/base64.coreutils
+-rwxr-xr-x root root 43176 ./usr/bin/basename.coreutils
+lrwxrwxrwx root root 27 ./usr/bin/basename -> /usr/bin/basename.coreutils
+-rwxr-xr-x root root 59552 ./usr/bin/basenc
+-rwxr-xr-x root root 96928 ./usr/bin/bc.bc
+lrwxrwxrwx root root 14 ./usr/bin/bc -> /usr/bin/bc.bc
+lrwxrwxrwx root root 19 ./usr/bin/[[ -> /bin/busybox.nosuid
+-rwxr-xr-x root root 455224 ./usr/bin/bison
+-rwxr-xr-x root root 933632 ./usr/bin/btrfs
+lrwxrwxrwx root root 5 ./usr/bin/btrfsck -> btrfs
+-rwxr-xr-x root root 527560 ./usr/bin/btrfs-convert
+-rwxr-xr-x root root 490760 ./usr/bin/btrfs-find-root
+-rwxr-xr-x root root 519360 ./usr/bin/btrfs-image
+-rwxr-xr-x root root 498888 ./usr/bin/btrfs-map-logical
+-rwxr-xr-x root root 494792 ./usr/bin/btrfs-select-super
+-rwxr-xr-x root root 494784 ./usr/bin/btrfstune
+lrwxrwxrwx root root 11 ./usr/bin/bunzip2.bzip2 -> bzip2.bzip2
+lrwxrwxrwx root root 22 ./usr/bin/bunzip2 -> /usr/bin/bunzip2.bzip2
+lrwxrwxrwx root root 11 ./usr/bin/bzcat.bzip2 -> bzip2.bzip2
+lrwxrwxrwx root root 20 ./usr/bin/bzcat -> /usr/bin/bzcat.bzip2
+lrwxrwxrwx root root 6 ./usr/bin/bzcmp -> bzdiff
+-rwxr-xr-x root root 2140 ./usr/bin/bzdiff
+lrwxrwxrwx root root 6 ./usr/bin/bzegrep -> bzgrep
+lrwxrwxrwx root root 6 ./usr/bin/bzfgrep -> bzgrep
+-rwxr-xr-x root root 2054 ./usr/bin/bzgrep
+-rwxr-xr-x root root 38952 ./usr/bin/bzip2.bzip2
+-rwxr-xr-x root root 14296 ./usr/bin/bzip2recover
+lrwxrwxrwx root root 20 ./usr/bin/bzip2 -> /usr/bin/bzip2.bzip2
+lrwxrwxrwx root root 6 ./usr/bin/bzless -> bzmore
+-rwxr-xr-x root root 1259 ./usr/bin/bzmore
+lrwxrwxrwx root root 23 ./usr/bin/cal -> /usr/bin/cal.util-linux
+-rwxr-xr-x root root 67936 ./usr/bin/cal.util-linux
+lrwxrwxrwx root root 34 ./usr/bin/c++filt -> /usr/bin/x86_64-poky-linux-c++filt
+-rwxr-xr-x root root 14288 ./usr/bin/chacl
+-rwsr-xr-x root root 71776 ./usr/bin/chage
+-rwxr-xr-x root root 71848 ./usr/bin/chcon.coreutils
+lrwxrwxrwx root root 24 ./usr/bin/chcon -> /usr/bin/chcon.coreutils
+-rwsr-xr-x root root 54032 ./usr/bin/chfn.shadow
+lrwxrwxrwx root root 20 ./usr/bin/chfn -> /usr/bin/chfn.shadow
+-rwxr-xr-x root root 63528 ./usr/bin/chmem
+-rwxr-xr-x root root 51240 ./usr/bin/choom
+lrwxrwxrwx root root 24 ./usr/bin/chrt -> /usr/bin/chrt.util-linux
+-rwxr-xr-x root root 34864 ./usr/bin/chrt.util-linux
+-rwsr-xr-x root root 53904 ./usr/bin/chsh.shadow
+lrwxrwxrwx root root 20 ./usr/bin/chsh -> /usr/bin/chsh.shadow
+lrwxrwxrwx root root 19 ./usr/bin/chvt -> /bin/busybox.nosuid
+-rwxr-xr-x root root 43176 ./usr/bin/cksum.coreutils
+lrwxrwxrwx root root 24 ./usr/bin/cksum -> /usr/bin/cksum.coreutils
+lrwxrwxrwx root root 19 ./usr/bin/clear -> /bin/busybox.nosuid
+-rwxr-xr-x root root 47176 ./usr/bin/cmp.diffutils
+lrwxrwxrwx root root 22 ./usr/bin/cmp -> /usr/bin/cmp.diffutils
+-rwxr-xr-x root root 34848 ./usr/bin/col
+-rwxr-xr-x root root 14368 ./usr/bin/colcrt
+-rwxr-xr-x root root 30760 ./usr/bin/colrm
+-rwxr-xr-x root root 51240 ./usr/bin/column
+-rwxr-xr-x root root 51400 ./usr/bin/comm.coreutils
+lrwxrwxrwx root root 23 ./usr/bin/comm -> /usr/bin/comm.coreutils
+-rwxr-xr-x root root 1342 ./usr/bin/compile_et
+-rwxr-xr-x root root 6214 ./usr/bin/c_rehash
+-rwxr-xr-x root root 125128 ./usr/bin/csplit.coreutils
+lrwxrwxrwx root root 25 ./usr/bin/csplit -> /usr/bin/csplit.coreutils
+-rwxr-xr-x root root 55496 ./usr/bin/cut.coreutils
+lrwxrwxrwx root root 22 ./usr/bin/cut -> /usr/bin/cut.coreutils
+-rwxr-xr-x root root 14304 ./usr/bin/dbus-cleanup-sockets
+-rwxr-xr-x root root 223688 ./usr/bin/dbus-daemon
+-rwxr-xr-x root root 30680 ./usr/bin/dbus-launch
+-rwxr-xr-x root root 30688 ./usr/bin/dbus-monitor
+-rwxr-xr-x root root 14304 ./usr/bin/dbus-run-session
+-rwxr-xr-x root root 30680 ./usr/bin/dbus-send
+-rwxr-xr-x root root 26672 ./usr/bin/dbus-test-tool
+-rwxr-xr-x root root 14320 ./usr/bin/dbus-update-activation-environment
+-rwxr-xr-x root root 14296 ./usr/bin/dbus-uuidgen
+-rwxr-xr-x root root 55352 ./usr/bin/dc.bc
+lrwxrwxrwx root root 14 ./usr/bin/dc -> /usr/bin/dc.bc
+lrwxrwxrwx root root 19 ./usr/bin/deallocvt -> /bin/busybox.nosuid
+-rwxr-xr-x root root 105232 ./usr/bin/df.coreutils
+-rwxr-xr-x root root 67760 ./usr/bin/diff3
+-rwxr-xr-x root root 223544 ./usr/bin/diff.diffutils
+lrwxrwxrwx root root 23 ./usr/bin/diff -> /usr/bin/diff.diffutils
+-rwxr-xr-x root root 71864 ./usr/bin/dircolors.coreutils
+lrwxrwxrwx root root 28 ./usr/bin/dircolors -> /usr/bin/dircolors.coreutils
+-rwxr-xr-x root root 162448 ./usr/bin/dir.coreutils
+-rwxr-xr-x root root 43176 ./usr/bin/dirname.coreutils
+lrwxrwxrwx root root 26 ./usr/bin/dirname -> /usr/bin/dirname.coreutils
+lrwxrwxrwx root root 22 ./usr/bin/dir -> /usr/bin/dir.coreutils
+-rwxr-xr-x root root 194760 ./usr/bin/du.coreutils
+lrwxrwxrwx root root 19 ./usr/bin/dumpleases -> /bin/busybox.nosuid
+lrwxrwxrwx root root 21 ./usr/bin/du -> /usr/bin/du.coreutils
+lrwxrwxrwx root root 30 ./usr/bin/dwp -> /usr/bin/x86_64-poky-linux-dwp
+lrwxrwxrwx root root 25 ./usr/bin/eject -> /usr/bin/eject.util-linux
+-rwxr-xr-x root root 79920 ./usr/bin/eject.util-linux
+lrwxrwxrwx root root 34 ./usr/bin/elfedit -> /usr/bin/x86_64-poky-linux-elfedit
+-rwxr-xr-x root root 55904 ./usr/bin/env.coreutils
+lrwxrwxrwx root root 22 ./usr/bin/env -> /usr/bin/env.coreutils
+-rwxr-xr-x root root 39016 ./usr/bin/eu-ar
+-rwxr-xr-x root root 28656 ./usr/bin/eu-elfclassify
+-rwxr-xr-x root root 350840 ./usr/bin/eu-elfcmp
+-rwxr-xr-x root root 31160 ./usr/bin/eu-elfcompress
+-rwxr-xr-x root root 432760 ./usr/bin/eu-elflint
+-rwxr-xr-x root root 22672 ./usr/bin/eu-findtextrel
+-rwxr-xr-x root root 2911 ./usr/bin/eu-make-debug-archive
+-rwxr-xr-x root root 355056 ./usr/bin/eu-objdump
+-rwxr-xr-x root root 22568 ./usr/bin/eu-ranlib
+-rwxr-xr-x root root 27600 ./usr/bin/eu-stack
+-rwxr-xr-x root root 26736 ./usr/bin/eu-strings
+-rwxr-xr-x root root 51240 ./usr/bin/eu-unstrip
+-rwxr-xr-x root root 47304 ./usr/bin/expand.coreutils
+lrwxrwxrwx root root 25 ./usr/bin/expand -> /usr/bin/expand.coreutils
+-rwsr-xr-x root root 36336 ./usr/bin/expiry
+-rwxr-xr-x root root 125096 ./usr/bin/expr.coreutils
+lrwxrwxrwx root root 23 ./usr/bin/expr -> /usr/bin/expr.coreutils
+-rwxr-xr-x root root 84168 ./usr/bin/factor.coreutils
+lrwxrwxrwx root root 25 ./usr/bin/factor -> /usr/bin/factor.coreutils
+-rwxr-xr-x root root 22784 ./usr/bin/faillog
+lrwxrwxrwx root root 29 ./usr/bin/fallocate -> /usr/bin/fallocate.util-linux
+-rwxr-xr-x root root 30776 ./usr/bin/fallocate.util-linux
+-rwxr-xr-x root root 92656 ./usr/bin/filan
+-rwxr-xr-x root root 34904 ./usr/bin/fincore
+-rwxr-xr-x root root 324064 ./usr/bin/find.findutils
+-rwxr-xr-x root root 68840 ./usr/bin/findmnt
+lrwxrwxrwx root root 23 ./usr/bin/find -> /usr/bin/find.findutils
+-rwxr-xr-x root root 443016 ./usr/bin/flex
+lrwxrwxrwx root root 4 ./usr/bin/flex++ -> flex
+lrwxrwxrwx root root 25 ./usr/bin/flock -> /usr/bin/flock.util-linux
+-rwxr-xr-x root root 34944 ./usr/bin/flock.util-linux
+-rwxr-xr-x root root 55464 ./usr/bin/fmt.coreutils
+lrwxrwxrwx root root 22 ./usr/bin/fmt -> /usr/bin/fmt.coreutils
+-rwxr-xr-x root root 47272 ./usr/bin/fold.coreutils
+lrwxrwxrwx root root 23 ./usr/bin/fold -> /usr/bin/fold.coreutils
+-rwxr-xr-x root root 26672 ./usr/bin/free.procps
+lrwxrwxrwx root root 20 ./usr/bin/free -> /usr/bin/free.procps
+-rwxr-xr-x root root 1185 ./usr/bin/fsck.btrfs
+-rwxr-xr-x root root 26576 ./usr/bin/funzip
+lrwxrwxrwx root root 19 ./usr/bin/fuser -> /bin/busybox.nosuid
+-rwxr-xr-x root root 653560 ./usr/bin/gawk
+-rwxr-xr-x root root 653560 ./usr/bin/gawk-5.0.1
+-rwxr-xr-x root root 26808 ./usr/bin/gencat
+-rwxr-xr-x root root 34912 ./usr/bin/getconf
+-rwxr-xr-x root root 35280 ./usr/bin/getent
+-rwxr-xr-x root root 31312 ./usr/bin/getfacl
+-rwxr-xr-x root root 23032 ./usr/bin/getfattr
+lrwxrwxrwx root root 28 ./usr/bin/ginsttest-runner -> gnome-desktop-testing-runner
+-rwxr-xr-x root root 4049 ./usr/bin/g-ir-annotation-tool
+-rwxr-xr-x root root 187384 ./usr/bin/g-ir-compiler
+-rwxr-xr-x root root 42968 ./usr/bin/g-ir-generate
+-rwxr-xr-x root root 14296 ./usr/bin/g-ir-inspect
+-rwxr-xr-x root root 4040 ./usr/bin/g-ir-scanner
+-rwxr-xr-x root root 35384 ./usr/bin/gnome-desktop-testing-runner
+-rwsr-xr-x root root 71624 ./usr/bin/gpasswd
+lrwxrwxrwx root root 32 ./usr/bin/gprof -> /usr/bin/x86_64-poky-linux-gprof
+-rwxr-xr-x root root 43176 ./usr/bin/groups.coreutils
+-rwxr-xr-x root root 14296 ./usr/bin/groups.shadow
+lrwxrwxrwx root root 22 ./usr/bin/groups -> /usr/bin/groups.shadow
+-rwxr-xr-x root root 22568 ./usr/bin/hardlink
+-rwxr-xr-x root root 55496 ./usr/bin/head.coreutils
+lrwxrwxrwx root root 23 ./usr/bin/head -> /usr/bin/head.coreutils
+lrwxrwxrwx root root 27 ./usr/bin/hexdump -> /usr/bin/hexdump.util-linux
+-rwxr-xr-x root root 55352 ./usr/bin/hexdump.util-linux
+-rwxr-xr-x root root 43176 ./usr/bin/hostid.coreutils
+lrwxrwxrwx root root 25 ./usr/bin/hostid -> /usr/bin/hostid.coreutils
+lrwxrwxrwx root root 7 ./usr/bin/i386 -> setarch
+-rwxr-xr-x root root 59608 ./usr/bin/iconv
+-rwxr-xr-x root root 55496 ./usr/bin/id.coreutils
+lrwxrwxrwx root root 21 ./usr/bin/id -> /usr/bin/id.coreutils
+-rwxr-xr-x root root 141560 ./usr/bin/install.coreutils
+lrwxrwxrwx root root 26 ./usr/bin/install -> /usr/bin/install.coreutils
+lrwxrwxrwx root root 26 ./usr/bin/ionice -> /usr/bin/ionice.util-linux
+-rwxr-xr-x root root 30768 ./usr/bin/ionice.util-linux
+-rwxr-xr-x root root 30824 ./usr/bin/ipcmk
+-rwxr-xr-x root root 34856 ./usr/bin/ipcrm
+-rwxr-xr-x root root 71720 ./usr/bin/ipcs
+lrwxrwxrwx root root 30 ./usr/bin/iptables-xml -> /usr/sbin/xtables-legacy-multi
+-rwxr-xr-x root root 30760 ./usr/bin/isosize
+-rwxr-xr-x root root 59592 ./usr/bin/join.coreutils
+lrwxrwxrwx root root 23 ./usr/bin/join -> /usr/bin/join.coreutils
+lrwxrwxrwx root root 19 ./usr/bin/killall -> /bin/busybox.nosuid
+lrwxrwxrwx root root 13 ./usr/bin/lastb.sysvinit -> last.sysvinit
+lrwxrwxrwx root root 23 ./usr/bin/lastb -> /usr/bin/lastb.sysvinit
+lrwxrwxrwx root root 15 ./usr/bin/lastb.util-linux -> last.util-linux
+-rwxr-xr-x root root 32032 ./usr/bin/lastlog
+-rwxr-xr-x root root 22512 ./usr/bin/last.sysvinit
+lrwxrwxrwx root root 22 ./usr/bin/last -> /usr/bin/last.sysvinit
+-rwxr-xr-x root root 47152 ./usr/bin/last.util-linux
+-rwxr-xr-x root root 63648 ./usr/bin/lbracket.coreutils
+lrwxrwxrwx root root 33 ./usr/bin/ld.bfd -> /usr/bin/x86_64-poky-linux-ld.bfd
+lrwxrwxrwx root root 34 ./usr/bin/ld.gold -> /usr/bin/x86_64-poky-linux-ld.gold
+lrwxrwxrwx root root 29 ./usr/bin/ld -> /usr/bin/x86_64-poky-linux-ld
+lrwxrwxrwx root root 19 ./usr/bin/less -> /bin/busybox.nosuid
+-rwxr-xr-x root root 173 ./usr/bin/libpng16-config
+lrwxrwxrwx root root 15 ./usr/bin/libpng-config -> libpng16-config
+-rwxr-xr-x root root 43176 ./usr/bin/link.coreutils
+lrwxrwxrwx root root 23 ./usr/bin/link -> /usr/bin/link.coreutils
+lrwxrwxrwx root root 7 ./usr/bin/linux32 -> setarch
+lrwxrwxrwx root root 7 ./usr/bin/linux64 -> setarch
+-rwxr-xr-x root root 54648 ./usr/bin/locale
+-rwxr-xr-x root root 170408 ./usr/bin/locate
+lrwxrwxrwx root root 26 ./usr/bin/logger -> /usr/bin/logger.util-linux
+-rwxr-xr-x root root 47760 ./usr/bin/logger.util-linux
+-rwxr-xr-x root root 43176 ./usr/bin/logname.coreutils
+lrwxrwxrwx root root 26 ./usr/bin/logname -> /usr/bin/logname.coreutils
+-rwxr-xr-x root root 14368 ./usr/bin/look
+-rwxr-xr-x root root 14296 ./usr/bin/lsattr
+-rwxr-xr-x root root 145448 ./usr/bin/lsblk
+-rwxr-xr-x root root 100392 ./usr/bin/lscpu
+-rwxr-xr-x root root 92200 ./usr/bin/lsipc
+-rwxr-xr-x root root 39288 ./usr/bin/lslocks
+-rwxr-xr-x root root 67624 ./usr/bin/lslogins
+-rwxr-xr-x root root 67624 ./usr/bin/lsmem
+-rwxr-xr-x root root 51240 ./usr/bin/lsns
+lrwxrwxrwx root root 17 ./usr/bin/lzcat -> /usr/bin/lzcat.xz
+lrwxrwxrwx root root 5 ./usr/bin/lzcat.xz -> xz.xz
+lrwxrwxrwx root root 6 ./usr/bin/lzcmp -> xzdiff
+lrwxrwxrwx root root 6 ./usr/bin/lzdiff -> xzdiff
+lrwxrwxrwx root root 6 ./usr/bin/lzegrep -> xzgrep
+lrwxrwxrwx root root 6 ./usr/bin/lzfgrep -> xzgrep
+lrwxrwxrwx root root 6 ./usr/bin/lzgrep -> xzgrep
+lrwxrwxrwx root root 6 ./usr/bin/lzless -> xzless
+-rwxr-xr-x root root 14376 ./usr/bin/lzmadec
+-rwxr-xr-x root root 14376 ./usr/bin/lzmainfo
+lrwxrwxrwx root root 16 ./usr/bin/lzma -> /usr/bin/lzma.xz
+lrwxrwxrwx root root 5 ./usr/bin/lzma.xz -> xz.xz
+lrwxrwxrwx root root 6 ./usr/bin/lzmore -> xzmore
+-rwxr-xr-x root root 243992 ./usr/bin/m4
+-rwxr-xr-x root root 243208 ./usr/bin/make
+-rwxr-xr-x root root 22712 ./usr/bin/makedb
+-rwxr-xr-x root root 34920 ./usr/bin/mcookie
+-rwxr-xr-x root root 55496 ./usr/bin/md5sum.coreutils
+lrwxrwxrwx root root 25 ./usr/bin/md5sum -> /usr/bin/md5sum.coreutils
+-rwxr-xr-x root root 14304 ./usr/bin/mesg.sysvinit
+lrwxrwxrwx root root 22 ./usr/bin/mesg -> /usr/bin/mesg.sysvinit
+-rwxr-xr-x root root 14376 ./usr/bin/mesg.util-linux
+lrwxrwxrwx root root 19 ./usr/bin/microcom -> /bin/busybox.nosuid
+-rwxr-xr-x root root 1102 ./usr/bin/mk_cmds
+-rwxr-xr-x root root 47272 ./usr/bin/mkfifo.coreutils
+lrwxrwxrwx root root 25 ./usr/bin/mkfifo -> /usr/bin/mkfifo.coreutils
+-rwxr-xr-x root root 519360 ./usr/bin/mkfs.btrfs
+-rwxr-xr-x root root 55464 ./usr/bin/mktemp.coreutils
+-rwxr-xr-x root root 34856 ./usr/bin/namei
+lrwxrwxrwx root root 19 ./usr/bin/nc -> /bin/busybox.nosuid
+-rwxr-xr-x root root 173 ./usr/bin/ncurses5-config
+-rwxr-xr-x root root 173 ./usr/bin/ncurses6-config
+-rwxr-xr-x root root 175 ./usr/bin/ncursesw5-config
+-rwxr-xr-x root root 175 ./usr/bin/ncursesw6-config
+-rwsr-xr-x root root 41136 ./usr/bin/newgidmap
+-rwsr-xr-x root root 40312 ./usr/bin/newgrp.shadow
+lrwxrwxrwx root root 22 ./usr/bin/newgrp -> /usr/bin/newgrp.shadow
+-rwsr-xr-x root root 37040 ./usr/bin/newuidmap
+-rwxr-xr-x root root 47272 ./usr/bin/nice.coreutils
+-rwxr-xr-x root root 117000 ./usr/bin/nl.coreutils
+lrwxrwxrwx root root 21 ./usr/bin/nl -> /usr/bin/nl.coreutils
+lrwxrwxrwx root root 29 ./usr/bin/nm -> /usr/bin/x86_64-poky-linux-nm
+-rwxr-xr-x root root 47272 ./usr/bin/nohup.coreutils
+lrwxrwxrwx root root 24 ./usr/bin/nohup -> /usr/bin/nohup.coreutils
+-rwxr-xr-x root root 47272 ./usr/bin/nproc.coreutils
+lrwxrwxrwx root root 24 ./usr/bin/nproc -> /usr/bin/nproc.coreutils
+lrwxrwxrwx root root 27 ./usr/bin/nsenter -> /usr/bin/nsenter.util-linux
+-rwxr-xr-x root root 35072 ./usr/bin/nsenter.util-linux
+lrwxrwxrwx root root 19 ./usr/bin/nslookup -> /bin/busybox.nosuid
+-rwxr-xr-x root root 71904 ./usr/bin/numfmt
+lrwxrwxrwx root root 34 ./usr/bin/objcopy -> /usr/bin/x86_64-poky-linux-objcopy
+lrwxrwxrwx root root 34 ./usr/bin/objdump -> /usr/bin/x86_64-poky-linux-objdump
+-rwxr-xr-x root root 80072 ./usr/bin/od.coreutils
+lrwxrwxrwx root root 21 ./usr/bin/od -> /usr/bin/od.coreutils
+-rwxr-xr-x root root 736944 ./usr/bin/openssl
+lrwxrwxrwx root root 19 ./usr/bin/openvt -> /bin/busybox.nosuid
+-rwsr-xr-x root root 67760 ./usr/bin/passwd.shadow
+lrwxrwxrwx root root 22 ./usr/bin/passwd -> /usr/bin/passwd.shadow
+-rwxr-xr-x root root 47304 ./usr/bin/paste.coreutils
+lrwxrwxrwx root root 24 ./usr/bin/paste -> /usr/bin/paste.coreutils
+lrwxrwxrwx root root 19 ./usr/bin/patch -> /bin/busybox.nosuid
+-rwxr-xr-x root root 43176 ./usr/bin/pathchk.coreutils
+lrwxrwxrwx root root 26 ./usr/bin/pathchk -> /usr/bin/pathchk.coreutils
+-rwxr-xr-x root root 14520 ./usr/bin/pcprofiledump
+-rwxr-xr-x root root 165 ./usr/bin/pcre-config
+-rwxr-xr-x root root 14288 ./usr/bin/perl
+-rwxr-xr-x root root 30776 ./usr/bin/pgrep.procps
+lrwxrwxrwx root root 21 ./usr/bin/pgrep -> /usr/bin/pgrep.procps
+-rwxr-xr-x root root 47304 ./usr/bin/pinky.coreutils
+lrwxrwxrwx root root 24 ./usr/bin/pinky -> /usr/bin/pinky.coreutils
+-rwxr-xr-x root root 30776 ./usr/bin/pkill.procps
+lrwxrwxrwx root root 21 ./usr/bin/pkill -> /usr/bin/pkill.procps
+-rwxr-xr-x root root 22712 ./usr/bin/pldd
+-rwxr-xr-x root root 34872 ./usr/bin/pmap.procps
+lrwxrwxrwx root root 20 ./usr/bin/pmap -> /usr/bin/pmap.procps
+-rwxr-xr-x root root 84232 ./usr/bin/pr.coreutils
+-rwxr-xr-x root root 43176 ./usr/bin/printenv.coreutils
+-rwxr-xr-x root root 63648 ./usr/bin/printf.coreutils
+lrwxrwxrwx root root 25 ./usr/bin/printf -> /usr/bin/printf.coreutils
+-rwxr-xr-x root root 39480 ./usr/bin/prlimit
+-rwxr-xr-x root root 80288 ./usr/bin/procan
+lrwxrwxrwx root root 21 ./usr/bin/pr -> /usr/bin/pr.coreutils
+-rwxr-xr-x root root 145640 ./usr/bin/ptx.coreutils
+lrwxrwxrwx root root 22 ./usr/bin/ptx -> /usr/bin/ptx.coreutils
+-rwxr-xr-x root root 14376 ./usr/bin/pwdx.procps
+lrwxrwxrwx root root 20 ./usr/bin/pwdx -> /usr/bin/pwdx.procps
+-rwxr-xr-x root root 14296 ./usr/bin/python3.8
+-rwxr-xr-x root root 2114 ./usr/bin/python3.8-config-lib
+lrwxrwxrwx root root 29 ./usr/bin/python3.8-config -> /usr/bin/python3.8-config-lib
+lrwxrwxrwx root root 16 ./usr/bin/python3-config -> python3.8-config
+lrwxrwxrwx root root 9 ./usr/bin/python3 -> python3.8
+lrwxrwxrwx root root 33 ./usr/bin/ranlib -> /usr/bin/x86_64-poky-linux-ranlib
+-rwxr-xr-x root root 14296 ./usr/bin/readbootlog
+lrwxrwxrwx root root 34 ./usr/bin/readelf -> /usr/bin/x86_64-poky-linux-readelf
+-rwxr-xr-x root root 55464 ./usr/bin/readlink.coreutils
+lrwxrwxrwx root root 27 ./usr/bin/readlink -> /usr/bin/readlink.coreutils
+-rwxr-xr-x root root 55496 ./usr/bin/realpath.coreutils
+lrwxrwxrwx root root 27 ./usr/bin/realpath -> /usr/bin/realpath.coreutils
+-rwxr-xr-x root root 22560 ./usr/bin/rename
+lrwxrwxrwx root root 26 ./usr/bin/renice -> /usr/bin/renice.util-linux
+-rwxr-xr-x root root 14384 ./usr/bin/renice.util-linux
+lrwxrwxrwx root root 19 ./usr/bin/reset -> /bin/busybox.nosuid
+lrwxrwxrwx root root 19 ./usr/bin/resize -> /bin/busybox.nosuid
+lrwxrwxrwx root root 23 ./usr/bin/rev -> /usr/bin/rev.util-linux
+-rwxr-xr-x root root 14376 ./usr/bin/rev.util-linux
+-rwxr-xr-x root root 43176 ./usr/bin/runcon.coreutils
+lrwxrwxrwx root root 25 ./usr/bin/runcon -> /usr/bin/runcon.coreutils
+-rwxr-xr-x root root 67624 ./usr/bin/script
+-rwxr-xr-x root root 55336 ./usr/bin/scriptlive
+-rwxr-xr-x root root 43056 ./usr/bin/scriptreplay
+-rwxr-xr-x root root 51264 ./usr/bin/sdiff
+-rwxr-xr-x root root 63656 ./usr/bin/seq.coreutils
+lrwxrwxrwx root root 22 ./usr/bin/seq -> /usr/bin/seq.coreutils
+-rwxr-xr-x root root 26936 ./usr/bin/setarch
+-rwxr-xr-x root root 39568 ./usr/bin/setfacl
+-rwxr-xr-x root root 18696 ./usr/bin/setfattr.attr
+lrwxrwxrwx root root 22 ./usr/bin/setfattr -> /usr/bin/setfattr.attr
+lrwxrwxrwx root root 27 ./usr/bin/setpriv -> /usr/bin/setpriv.util-linux
+-rwxr-xr-x root root 47160 ./usr/bin/setpriv.util-linux
+lrwxrwxrwx root root 26 ./usr/bin/setsid -> /usr/bin/setsid.util-linux
+-rwxr-xr-x root root 14384 ./usr/bin/setsid.util-linux
+-rwxr-xr-x root root 47144 ./usr/bin/setterm
+lrwxrwxrwx root root 13 ./usr/bin/sg -> newgrp.shadow
+-rwxr-xr-x root root 59592 ./usr/bin/sha1sum.coreutils
+lrwxrwxrwx root root 26 ./usr/bin/sha1sum -> /usr/bin/sha1sum.coreutils
+-rwxr-xr-x root root 67784 ./usr/bin/sha224sum.coreutils
+lrwxrwxrwx root root 28 ./usr/bin/sha224sum -> /usr/bin/sha224sum.coreutils
+-rwxr-xr-x root root 67784 ./usr/bin/sha256sum.coreutils
+lrwxrwxrwx root root 28 ./usr/bin/sha256sum -> /usr/bin/sha256sum.coreutils
+-rwxr-xr-x root root 71880 ./usr/bin/sha384sum.coreutils
+lrwxrwxrwx root root 28 ./usr/bin/sha384sum -> /usr/bin/sha384sum.coreutils
+-rwxr-xr-x root root 71880 ./usr/bin/sha512sum.coreutils
+lrwxrwxrwx root root 28 ./usr/bin/sha512sum -> /usr/bin/sha512sum.coreutils
+-rwxr-xr-x root root 67784 ./usr/bin/shred.coreutils
+lrwxrwxrwx root root 24 ./usr/bin/shred -> /usr/bin/shred.coreutils
+-rwxr-xr-x root root 63656 ./usr/bin/shuf.coreutils
+lrwxrwxrwx root root 23 ./usr/bin/shuf -> /usr/bin/shuf.coreutils
+lrwxrwxrwx root root 31 ./usr/bin/size -> /usr/bin/x86_64-poky-linux-size
+-rwxr-xr-x root root 30768 ./usr/bin/skill.procps
+lrwxrwxrwx root root 21 ./usr/bin/skill -> /usr/bin/skill.procps
+-rwxr-xr-x root root 22568 ./usr/bin/slabtop
+-rwxr-xr-x root root 30768 ./usr/bin/snice.procps
+lrwxrwxrwx root root 21 ./usr/bin/snice -> /usr/bin/snice.procps
+-rwxr-xr-x root root 380104 ./usr/bin/socat
+-rwxr-xr-x root root 117200 ./usr/bin/sort.coreutils
+lrwxrwxrwx root root 23 ./usr/bin/sort -> /usr/bin/sort.coreutils
+-rwxr-xr-x root root 64128 ./usr/bin/split.coreutils
+lrwxrwxrwx root root 24 ./usr/bin/split -> /usr/bin/split.coreutils
+-rwxr-xr-x root root 30896 ./usr/bin/sprof
+-rwxr-xr-x root root 63648 ./usr/bin/stdbuf
+lrwxrwxrwx root root 34 ./usr/bin/strings -> /usr/bin/x86_64-poky-linux-strings
+lrwxrwxrwx root root 32 ./usr/bin/strip -> /usr/bin/x86_64-poky-linux-strip
+-rwxr-xr-x root root 51376 ./usr/bin/sum.coreutils
+lrwxrwxrwx root root 22 ./usr/bin/sum -> /usr/bin/sum.coreutils
+-rwxr-xr-x root root 112808 ./usr/bin/tac.coreutils
+lrwxrwxrwx root root 22 ./usr/bin/tac -> /usr/bin/tac.coreutils
+-rwxr-xr-x root root 80104 ./usr/bin/tail.coreutils
+lrwxrwxrwx root root 23 ./usr/bin/tail -> /usr/bin/tail.coreutils
+lrwxrwxrwx root root 27 ./usr/bin/taskset -> /usr/bin/taskset.util-linux
+-rwxr-xr-x root root 34864 ./usr/bin/taskset.util-linux
+-rwxr-xr-x root root 47304 ./usr/bin/tee.coreutils
+lrwxrwxrwx root root 22 ./usr/bin/tee -> /usr/bin/tee.coreutils
+lrwxrwxrwx root root 19 ./usr/bin/telnet -> /bin/busybox.nosuid
+-rwxr-xr-x root root 59544 ./usr/bin/test.coreutils
+lrwxrwxrwx root root 23 ./usr/bin/test -> /usr/bin/test.coreutils
+lrwxrwxrwx root root 19 ./usr/bin/tftp -> /bin/busybox.nosuid
+lrwxrwxrwx root root 19 ./usr/bin/time -> /bin/busybox.nosuid
+-rwxr-xr-x root root 51840 ./usr/bin/timeout.coreutils
+lrwxrwxrwx root root 26 ./usr/bin/timeout -> /usr/bin/timeout.coreutils
+-rwxr-xr-x root root 22576 ./usr/bin/tload
+-rwxr-xr-x root root 124784 ./usr/bin/top.procps
+lrwxrwxrwx root root 19 ./usr/bin/top -> /usr/bin/top.procps
+-rwxr-xr-x root root 22512 ./usr/bin/tput
+lrwxrwxrwx root root 17 ./usr/bin/traceroute -> /bin/busybox.suid
+-rwxr-xr-x root root 55464 ./usr/bin/tr.coreutils
+-rwxr-xr-x root root 47272 ./usr/bin/truncate.coreutils
+lrwxrwxrwx root root 27 ./usr/bin/truncate -> /usr/bin/truncate.coreutils
+lrwxrwxrwx root root 21 ./usr/bin/tr -> /usr/bin/tr.coreutils
+lrwxrwxrwx root root 19 ./usr/bin/ts -> /bin/busybox.nosuid
+-rwxr-xr-x root root 30680 ./usr/bin/tset
+-rwxr-xr-x root root 59560 ./usr/bin/tsort.coreutils
+lrwxrwxrwx root root 24 ./usr/bin/tsort -> /usr/bin/tsort.coreutils
+-rwxr-xr-x root root 43176 ./usr/bin/tty.coreutils
+lrwxrwxrwx root root 22 ./usr/bin/tty -> /usr/bin/tty.coreutils
+-rwxr-xr-x root root 354584 ./usr/bin/udevadm
+-rwxr-xr-x root root 22560 ./usr/bin/ul
+lrwxrwxrwx root root 7 ./usr/bin/uname26 -> setarch
+-rwxr-xr-x root root 47304 ./usr/bin/unexpand.coreutils
+lrwxrwxrwx root root 27 ./usr/bin/unexpand -> /usr/bin/unexpand.coreutils
+-rwxr-xr-x root root 55496 ./usr/bin/uniq.coreutils
+lrwxrwxrwx root root 23 ./usr/bin/uniq -> /usr/bin/uniq.coreutils
+-rwxr-xr-x root root 43176 ./usr/bin/unlink.coreutils
+lrwxrwxrwx root root 25 ./usr/bin/unlink -> /usr/bin/unlink.coreutils
+lrwxrwxrwx root root 18 ./usr/bin/unlzma -> /usr/bin/unlzma.xz
+lrwxrwxrwx root root 5 ./usr/bin/unlzma.xz -> xz.xz
+lrwxrwxrwx root root 27 ./usr/bin/unshare -> /usr/bin/unshare.util-linux
+-rwxr-xr-x root root 39176 ./usr/bin/unshare.util-linux
+lrwxrwxrwx root root 16 ./usr/bin/unxz -> /usr/bin/unxz.xz
+lrwxrwxrwx root root 5 ./usr/bin/unxz.xz -> xz.xz
+-rwxr-xr-x root root 88152 ./usr/bin/unzipsfx
+-rwxr-xr-x root root 186472 ./usr/bin/unzip.unzip
+lrwxrwxrwx root root 20 ./usr/bin/unzip -> /usr/bin/unzip.unzip
+-rwxr-xr-x root root 4678 ./usr/bin/update-alternatives
+-rwxr-xr-x root root 9076 ./usr/bin/updatedb
+-rwxr-xr-x root root 59584 ./usr/bin/update-mime-database
+-rwxr-xr-x root root 59560 ./usr/bin/uptime.coreutils
+-rwxr-xr-x root root 14376 ./usr/bin/uptime.procps
+lrwxrwxrwx root root 22 ./usr/bin/uptime -> /usr/bin/uptime.procps
+-rwxr-xr-x root root 43176 ./usr/bin/users.coreutils
+lrwxrwxrwx root root 24 ./usr/bin/users -> /usr/bin/users.coreutils
+lrwxrwxrwx root root 27 ./usr/bin/[ -> /usr/bin/lbracket.coreutils
+-rwxr-xr-x root root 18400 ./usr/bin/utmpdump.sysvinit
+lrwxrwxrwx root root 26 ./usr/bin/utmpdump -> /usr/bin/utmpdump.sysvinit
+-rwxr-xr-x root root 30768 ./usr/bin/utmpdump.util-linux
+-rwxr-xr-x root root 14368 ./usr/bin/uuidgen
+-rwxr-xr-x root root 38952 ./usr/bin/uuidparse
+-rwxr-xr-x root root 162448 ./usr/bin/vdir.coreutils
+lrwxrwxrwx root root 23 ./usr/bin/vdir -> /usr/bin/vdir.coreutils
+lrwxrwxrwx root root 17 ./usr/bin/vlock -> /bin/busybox.suid
+-rwxr-xr-x root root 38968 ./usr/bin/vmstat
+-rwxr-xr-x root root 18392 ./usr/bin/wall.sysvinit
+lrwxrwxrwx root root 22 ./usr/bin/wall -> /usr/bin/wall.sysvinit
+-rwxr-xr-x root root 34864 ./usr/bin/wall.util-linux
+-rwxr-xr-x root root 51248 ./usr/bin/wayland-scanner
+-rwxr-xr-x root root 55472 ./usr/bin/wc.coreutils
+lrwxrwxrwx root root 21 ./usr/bin/wc -> /usr/bin/wc.coreutils
+-rwxr-xr-x root root 63552 ./usr/bin/wdctl
+lrwxrwxrwx root root 19 ./usr/bin/wget -> /bin/busybox.nosuid
+-rwxr-xr-x root root 31176 ./usr/bin/whereis
+lrwxrwxrwx root root 20 ./usr/bin/which -> /usr/bin/which.which
+-rwxr-xr-x root root 31280 ./usr/bin/which.which
+-rwxr-xr-x root root 43176 ./usr/bin/whoami.coreutils
+lrwxrwxrwx root root 25 ./usr/bin/whoami -> /usr/bin/whoami.coreutils
+-rwxr-xr-x root root 63688 ./usr/bin/who.coreutils
+lrwxrwxrwx root root 22 ./usr/bin/who -> /usr/bin/who.coreutils
+-rwxr-xr-x root root 22568 ./usr/bin/w.procps
+-rwxr-xr-x root root 22560 ./usr/bin/write
+lrwxrwxrwx root root 17 ./usr/bin/w -> /usr/bin/w.procps
+-rwxr-xr-x root root 31304 ./usr/bin/x86_64-poky-linux-addr2line
+-rwxr-xr-x root root 63784 ./usr/bin/x86_64-poky-linux-ar
+-rwxr-xr-x root root 737584 ./usr/bin/x86_64-poky-linux-as
+-rwxr-xr-x root root 30776 ./usr/bin/x86_64-poky-linux-c++filt
+-rwxr-xr-x root root 2058648 ./usr/bin/x86_64-poky-linux-dwp
+-rwxr-xr-x root root 39320 ./usr/bin/x86_64-poky-linux-elfedit
+-rwxr-xr-x root root 102056 ./usr/bin/x86_64-poky-linux-gprof
+-rwxr-xr-x root root 1711488 ./usr/bin/x86_64-poky-linux-ld
+-rwxr-xr-x root root 1711488 ./usr/bin/x86_64-poky-linux-ld.bfd
+-rwxr-xr-x root root 2316464 ./usr/bin/x86_64-poky-linux-ld.gold
+-rwxr-xr-x root root 48344 ./usr/bin/x86_64-poky-linux-nm
+-rwxr-xr-x root root 190736 ./usr/bin/x86_64-poky-linux-objcopy
+-rwxr-xr-x root root 512664 ./usr/bin/x86_64-poky-linux-objdump
+-rwxr-xr-x root root 63824 ./usr/bin/x86_64-poky-linux-ranlib
+-rwxr-xr-x root root 670432 ./usr/bin/x86_64-poky-linux-readelf
+-rwxr-xr-x root root 35136 ./usr/bin/x86_64-poky-linux-size
+-rwxr-xr-x root root 31176 ./usr/bin/x86_64-poky-linux-strings
+-rwxr-xr-x root root 190736 ./usr/bin/x86_64-poky-linux-strip
+lrwxrwxrwx root root 7 ./usr/bin/x86_64 -> setarch
+-rwxr-xr-x root root 75976 ./usr/bin/xargs.findutils
+lrwxrwxrwx root root 24 ./usr/bin/xargs -> /usr/bin/xargs.findutils
+-rwxr-xr-x root root 16982 ./usr/bin/xkeystone
+-rwxr-xr-x root root 165 ./usr/bin/xml2-config
+-rwxr-xr-x root root 63544 ./usr/bin/xrandr
+lrwxrwxrwx root root 17 ./usr/bin/xzcat -> /usr/bin/xzcat.xz
+lrwxrwxrwx root root 5 ./usr/bin/xzcat.xz -> xz.xz
+lrwxrwxrwx root root 6 ./usr/bin/xzcmp -> xzdiff
+-rwxr-xr-x root root 14376 ./usr/bin/xzdec
+-rwxr-xr-x root root 6633 ./usr/bin/xzdiff
+lrwxrwxrwx root root 6 ./usr/bin/xzegrep -> xzgrep
+lrwxrwxrwx root root 6 ./usr/bin/xzfgrep -> xzgrep
+-rwxr-xr-x root root 5630 ./usr/bin/xzgrep
+-rwxr-xr-x root root 1799 ./usr/bin/xzless
+-rwxr-xr-x root root 2162 ./usr/bin/xzmore
+lrwxrwxrwx root root 14 ./usr/bin/xz -> /usr/bin/xz.xz
+-rwxr-xr-x root root 80184 ./usr/bin/xz.xz
+-rwxr-xr-x root root 4184 ./usr/bin/yacc
+-rwxr-xr-x root root 43176 ./usr/bin/yes.coreutils
+lrwxrwxrwx root root 22 ./usr/bin/yes -> /usr/bin/yes.coreutils
+-rwxr-xr-x root root 212088 ./usr/bin/zip
+-rwxr-xr-x root root 97872 ./usr/bin/zipcloak
+-rwxr-xr-x root root 2953 ./usr/bin/zipgrep
+-rwxr-xr-x root root 186472 ./usr/bin/zipinfo
+-rwxr-xr-x root root 89448 ./usr/bin/zipnote
+-rwxr-xr-x root root 89456 ./usr/bin/zipsplit
+drwxr-xr-x root root 4096 ./usr/games
+drwxr-xr-x root root 12288 ./usr/include
+drwxr-xr-x root root 4096 ./usr/include/acl
+-rw-r--r-- root root 2611 ./usr/include/acl/libacl.h
+-rw-r--r-- root root 7457 ./usr/include/aio.h
+-rw-r--r-- root root 2032 ./usr/include/aliases.h
+-rw-r--r-- root root 1204 ./usr/include/alloca.h
+-rw-r--r-- root root 14130 ./usr/include/ansidecl.h
+-rw-r--r-- root root 4351 ./usr/include/a.out.h
+-rw-r--r-- root root 25473 ./usr/include/argp.h
+-rw-r--r-- root root 6051 ./usr/include/argz.h
+-rw-r--r-- root root 1731 ./usr/include/ar.h
+drwxr-xr-x root root 4096 ./usr/include/arpa
+-rw-r--r-- root root 3432 ./usr/include/arpa/ftp.h
+-rw-r--r-- root root 4277 ./usr/include/arpa/inet.h
+-rw-r--r-- root root 7041 ./usr/include/arpa/nameser_compat.h
+-rw-r--r-- root root 14195 ./usr/include/arpa/nameser.h
+-rw-r--r-- root root 10263 ./usr/include/arpa/telnet.h
+-rw-r--r-- root root 3051 ./usr/include/arpa/tftp.h
+drwxr-xr-x root root 4096 ./usr/include/asm
+-rw-r--r-- root root 756 ./usr/include/asm/a.out.h
+-rw-r--r-- root root 546 ./usr/include/asm/auxvec.h
+-rw-r--r-- root root 321 ./usr/include/asm/bitsperlong.h
+-rw-r--r-- root root 323 ./usr/include/asm/boot.h
+-rw-r--r-- root root 7757 ./usr/include/asm/bootparam.h
+-rw-r--r-- root root 40 ./usr/include/asm/bpf_perf_event.h
+-rw-r--r-- root root 200 ./usr/include/asm/byteorder.h
+-rw-r--r-- root root 3285 ./usr/include/asm/debugreg.h
+-rw-r--r-- root root 2579 ./usr/include/asm/e820.h
+-rw-r--r-- root root 31 ./usr/include/asm/errno.h
+-rw-r--r-- root root 31 ./usr/include/asm/fcntl.h
+drwxr-xr-x root root 4096 ./usr/include/asm-generic
+-rw-r--r-- root root 218 ./usr/include/asm-generic/auxvec.h
+-rw-r--r-- root root 564 ./usr/include/asm-generic/bitsperlong.h
+-rw-r--r-- root root 238 ./usr/include/asm-generic/bpf_perf_event.h
+-rw-r--r-- root root 1612 ./usr/include/asm-generic/errno-base.h
+-rw-r--r-- root root 5648 ./usr/include/asm-generic/errno.h
+-rw-r--r-- root root 5423 ./usr/include/asm-generic/fcntl.h
+-rw-r--r-- root root 1740 ./usr/include/asm-generic/hugetlb_encode.h
+-rw-r--r-- root root 718 ./usr/include/asm-generic/int-l64.h
+-rw-r--r-- root root 864 ./usr/include/asm-generic/int-ll64.h
+-rw-r--r-- root root 3478 ./usr/include/asm-generic/ioctl.h
+-rw-r--r-- root root 3987 ./usr/include/asm-generic/ioctls.h
+-rw-r--r-- root root 1003 ./usr/include/asm-generic/ipcbuf.h
+-rw-r--r-- root root 96 ./usr/include/asm-generic/kvm_para.h
+-rw-r--r-- root root 3417 ./usr/include/asm-generic/mman-common.h
+-rw-r--r-- root root 740 ./usr/include/asm-generic/mman.h
+-rw-r--r-- root root 1618 ./usr/include/asm-generic/msgbuf.h
+-rw-r--r-- root root 353 ./usr/include/asm-generic/param.h
+-rw-r--r-- root root 878 ./usr/include/asm-generic/poll.h
+-rw-r--r-- root root 2331 ./usr/include/asm-generic/posix_types.h
+-rw-r--r-- root root 1872 ./usr/include/asm-generic/resource.h
+-rw-r--r-- root root 1550 ./usr/include/asm-generic/sembuf.h
+-rw-r--r-- root root 190 ./usr/include/asm-generic/setup.h
+-rw-r--r-- root root 1837 ./usr/include/asm-generic/shmbuf.h
+-rw-r--r-- root root 9969 ./usr/include/asm-generic/siginfo.h
+-rw-r--r-- root root 800 ./usr/include/asm-generic/signal-defs.h
+-rw-r--r-- root root 2709 ./usr/include/asm-generic/signal.h
+-rw-r--r-- root root 3538 ./usr/include/asm-generic/socket.h
+-rw-r--r-- root root 447 ./usr/include/asm-generic/sockios.h
+-rw-r--r-- root root 1839 ./usr/include/asm-generic/statfs.h
+-rw-r--r-- root root 2633 ./usr/include/asm-generic/stat.h
+-rw-r--r-- root root 502 ./usr/include/asm-generic/swab.h
+-rw-r--r-- root root 4716 ./usr/include/asm-generic/termbits.h
+-rw-r--r-- root root 1377 ./usr/include/asm-generic/termios.h
+-rw-r--r-- root root 233 ./usr/include/asm-generic/types.h
+-rw-r--r-- root root 357 ./usr/include/asm-generic/ucontext.h
+-rw-r--r-- root root 30377 ./usr/include/asm-generic/unistd.h
+-rw-r--r-- root root 69 ./usr/include/asm/hw_breakpoint.h
+-rw-r--r-- root root 198 ./usr/include/asm/hwcap2.h
+-rw-r--r-- root root 31 ./usr/include/asm/ioctl.h
+-rw-r--r-- root root 32 ./usr/include/asm/ioctls.h
+-rw-r--r-- root root 32 ./usr/include/asm/ipcbuf.h
+-rw-r--r-- root root 854 ./usr/include/asm/ist.h
+-rw-r--r-- root root 9244 ./usr/include/asm/kvm.h
+-rw-r--r-- root root 3341 ./usr/include/asm/kvm_para.h
+-rw-r--r-- root root 388 ./usr/include/asm/kvm_perf.h
+-rw-r--r-- root root 1306 ./usr/include/asm/ldt.h
+-rw-r--r-- root root 1688 ./usr/include/asm/mce.h
+-rw-r--r-- root root 1002 ./usr/include/asm/mman.h
+-rw-r--r-- root root 1053 ./usr/include/asm/msgbuf.h
+-rw-r--r-- root root 346 ./usr/include/asm/msr.h
+-rw-r--r-- root root 4225 ./usr/include/asm/mtrr.h
+-rw-r--r-- root root 31 ./usr/include/asm/param.h
+-rw-r--r-- root root 1403 ./usr/include/asm/perf_regs.h
+-rw-r--r-- root root 30 ./usr/include/asm/poll.h
+-rw-r--r-- root root 765 ./usr/include/asm/posix_types_32.h
+-rw-r--r-- root root 609 ./usr/include/asm/posix_types_64.h
+-rw-r--r-- root root 224 ./usr/include/asm/posix_types.h
+-rw-r--r-- root root 581 ./usr/include/asm/posix_types_x32.h
+-rw-r--r-- root root 418 ./usr/include/asm/prctl.h
+-rw-r--r-- root root 6623 ./usr/include/asm/processor-flags.h
+-rw-r--r-- root root 2037 ./usr/include/asm/ptrace-abi.h
+-rw-r--r-- root root 1495 ./usr/include/asm/ptrace.h
+-rw-r--r-- root root 34 ./usr/include/asm/resource.h
+-rw-r--r-- root root 1045 ./usr/include/asm/sembuf.h
+-rw-r--r-- root root 6 ./usr/include/asm/setup.h
+-rw-r--r-- root root 1258 ./usr/include/asm/shmbuf.h
+-rw-r--r-- root root 271 ./usr/include/asm/sigcontext32.h
+-rw-r--r-- root root 9724 ./usr/include/asm/sigcontext.h
+-rw-r--r-- root root 422 ./usr/include/asm/siginfo.h
+-rw-r--r-- root root 2901 ./usr/include/asm/signal.h
+-rw-r--r-- root root 32 ./usr/include/asm/socket.h
+-rw-r--r-- root root 33 ./usr/include/asm/sockios.h
+-rw-r--r-- root root 416 ./usr/include/asm/statfs.h
+-rw-r--r-- root root 3131 ./usr/include/asm/stat.h
+-rw-r--r-- root root 7068 ./usr/include/asm/svm.h
+-rw-r--r-- root root 724 ./usr/include/asm/swab.h
+-rw-r--r-- root root 34 ./usr/include/asm/termbits.h
+-rw-r--r-- root root 33 ./usr/include/asm/termios.h
+-rw-r--r-- root root 31 ./usr/include/asm/types.h
+-rw-r--r-- root root 2117 ./usr/include/asm/ucontext.h
+-rw-r--r-- root root 11475 ./usr/include/asm/unistd_32.h
+-rw-r--r-- root root 9286 ./usr/include/asm/unistd_64.h
+-rw-r--r-- root root 361 ./usr/include/asm/unistd.h
+-rw-r--r-- root root 16367 ./usr/include/asm/unistd_x32.h
+-rw-r--r-- root root 3118 ./usr/include/asm/vm86.h
+-rw-r--r-- root root 7032 ./usr/include/asm/vmx.h
+-rw-r--r-- root root 263 ./usr/include/asm/vsyscall.h
+-rw-r--r-- root root 4562 ./usr/include/assert.h
+drwxr-xr-x root root 4096 ./usr/include/attr
+-rw-r--r-- root root 8010 ./usr/include/attr/attributes.h
+-rw-r--r-- root root 1569 ./usr/include/attr/error_context.h
+-rw-r--r-- root root 1411 ./usr/include/attr/libattr.h
+drwxr-xr-x root root 4096 ./usr/include/bash
+-rw-r--r-- root root 2225 ./usr/include/bash/alias.h
+-rw-r--r-- root root 3561 ./usr/include/bash/arrayfunc.h
+-rw-r--r-- root root 4172 ./usr/include/bash/array.h
+-rw-r--r-- root root 2302 ./usr/include/bash/assoc.h
+-rw-r--r-- root root 1262 ./usr/include/bash/bashansi.h
+-rw-r--r-- root root 1462 ./usr/include/bash/bashintl.h
+-rw-r--r-- root root 1646 ./usr/include/bash/bashjmp.h
+-rw-r--r-- root root 1086 ./usr/include/bash/bashtypes.h
+drwxr-xr-x root root 4096 ./usr/include/bash/builtins
+-rw-r--r-- root root 1263 ./usr/include/bash/builtins/bashgetopt.h
+-rw-r--r-- root root 6715 ./usr/include/bash/builtins/builtext.h
+-rw-r--r-- root root 8372 ./usr/include/bash/builtins/common.h
+-rw-r--r-- root root 2582 ./usr/include/bash/builtins/getopt.h
+-rw-r--r-- root root 2373 ./usr/include/bash/builtins.h
+-rw-r--r-- root root 15490 ./usr/include/bash/command.h
+-rw-r--r-- root root 6514 ./usr/include/bash/config-bot.h
+-rw-r--r-- root root 32166 ./usr/include/bash/config.h
+-rw-r--r-- root root 7436 ./usr/include/bash/config-top.h
+-rw-r--r-- root root 1709 ./usr/include/bash/conftypes.h
+-rw-r--r-- root root 1397 ./usr/include/bash/dispose_cmd.h
+-rw-r--r-- root root 3053 ./usr/include/bash/error.h
+-rw-r--r-- root root 18999 ./usr/include/bash/externs.h
+-rw-r--r-- root root 11828 ./usr/include/bash/general.h
+-rw-r--r-- root root 3036 ./usr/include/bash/hashlib.h
+drwxr-xr-x root root 4096 ./usr/include/bash/include
+-rw-r--r-- root root 1437 ./usr/include/bash/include/ansi_stdlib.h
+-rw-r--r-- root root 4125 ./usr/include/bash/include/chartypes.h
+-rw-r--r-- root root 1581 ./usr/include/bash/include/filecntl.h
+-rw-r--r-- root root 3014 ./usr/include/bash/include/gettext.h
+-rw-r--r-- root root 2113 ./usr/include/bash/include/maxpath.h
+-rw-r--r-- root root 1994 ./usr/include/bash/include/memalloc.h
+-rw-r--r-- root root 3669 ./usr/include/bash/include/ocache.h
+-rw-r--r-- root root 2305 ./usr/include/bash/include/posixdir.h
+-rw-r--r-- root root 1407 ./usr/include/bash/include/posixjmp.h
+-rw-r--r-- root root 4318 ./usr/include/bash/include/posixstat.h
+-rw-r--r-- root root 1509 ./usr/include/bash/include/posixtime.h
+-rw-r--r-- root root 3068 ./usr/include/bash/include/posixwait.h
+-rw-r--r-- root root 4319 ./usr/include/bash/include/shmbchar.h
+-rw-r--r-- root root 13847 ./usr/include/bash/include/shmbutil.h
+-rw-r--r-- root root 3636 ./usr/include/bash/include/shtty.h
+-rw-r--r-- root root 6088 ./usr/include/bash/include/stat-time.h
+-rw-r--r-- root root 2652 ./usr/include/bash/include/stdc.h
+-rw-r--r-- root root 1778 ./usr/include/bash/include/systimes.h
+-rw-r--r-- root root 2890 ./usr/include/bash/include/typemax.h
+-rw-r--r-- root root 2973 ./usr/include/bash/include/unionwait.h
+-rw-r--r-- root root 9640 ./usr/include/bash/jobs.h
+-rw-r--r-- root root 2960 ./usr/include/bash/make_cmd.h
+-rw-r--r-- root root 1208 ./usr/include/bash/pathnames.h
+-rw-r--r-- root root 2541 ./usr/include/bash/quit.h
+-rw-r--r-- root root 5957 ./usr/include/bash/shell.h
+-rw-r--r-- root root 4485 ./usr/include/bash/sig.h
+-rw-r--r-- root root 1544 ./usr/include/bash/siglist.h
+-rw-r--r-- root root 247 ./usr/include/bash/signames.h
+-rw-r--r-- root root 15184 ./usr/include/bash/subst.h
+-rw-r--r-- root root 3544 ./usr/include/bash/syntax.h
+-rw-r--r-- root root 2003 ./usr/include/bash/unwind_prot.h
+-rw-r--r-- root root 17643 ./usr/include/bash/variables.h
+-rw-r--r-- root root 579 ./usr/include/bash/version.h
+-rw-r--r-- root root 1759 ./usr/include/bash/xmalloc.h
+-rw-r--r-- root root 255175 ./usr/include/bfd-64.h
+-rw-r--r-- root root 500 ./usr/include/bfd.h
+-rw-r--r-- root root 35620 ./usr/include/bfdlink.h
+-rw-r--r-- root root 848 ./usr/include/bfd_stdint.h
+drwxr-xr-x root root 4096 ./usr/include/bits
+-rw-r--r-- root root 268 ./usr/include/bits/a.out.h
+-rw-r--r-- root root 1010 ./usr/include/bits/argp-ldbl.h
+-rw-r--r-- root root 2450 ./usr/include/bits/byteswap.h
+-rw-r--r-- root root 4139 ./usr/include/bits/cmathcalls.h
+-rw-r--r-- root root 23709 ./usr/include/bits/confname.h
+-rw-r--r-- root root 4516 ./usr/include/bits/cpu-set.h
+-rw-r--r-- root root 1275 ./usr/include/bits/dirent_ext.h
+-rw-r--r-- root root 1771 ./usr/include/bits/dirent.h
+-rw-r--r-- root root 2521 ./usr/include/bits/dlfcn.h
+-rw-r--r-- root root 426 ./usr/include/bits/elfclass.h
+-rw-r--r-- root root 1905 ./usr/include/bits/endian.h
+-rw-r--r-- root root 273 ./usr/include/bits/endianness-64.h
+-rw-r--r-- root root 548 ./usr/include/bits/endianness.h
+-rw-r--r-- root root 3791 ./usr/include/bits/environments.h
+-rw-r--r-- root root 1071 ./usr/include/bits/epoll.h
+-rw-r--r-- root root 1148 ./usr/include/bits/err-ldbl.h
+-rw-r--r-- root root 1426 ./usr/include/bits/errno.h
+-rw-r--r-- root root 2684 ./usr/include/bits/error.h
+-rw-r--r-- root root 1012 ./usr/include/bits/error-ldbl.h
+-rw-r--r-- root root 1129 ./usr/include/bits/eventfd.h
+-rw-r--r-- root root 5575 ./usr/include/bits/fcntl2.h
+-rw-r--r-- root root 2246 ./usr/include/bits/fcntl.h
+-rw-r--r-- root root 13995 ./usr/include/bits/fcntl-linux.h
+-rw-r--r-- root root 4611 ./usr/include/bits/fenv.h
+-rw-r--r-- root root 190 ./usr/include/bits/fenvinline.h
+-rw-r--r-- root root 4373 ./usr/include/bits/floatn-64.h
+-rw-r--r-- root root 9765 ./usr/include/bits/floatn-common.h
+-rw-r--r-- root root 532 ./usr/include/bits/floatn.h
+-rw-r--r-- root root 1215 ./usr/include/bits/flt-eval-method.h
+-rw-r--r-- root root 1216 ./usr/include/bits/fp-fast.h
+-rw-r--r-- root root 1012 ./usr/include/bits/fp-logb.h
+-rw-r--r-- root root 3667 ./usr/include/bits/getopt_core.h
+-rw-r--r-- root root 3038 ./usr/include/bits/getopt_ext.h
+-rw-r--r-- root root 1810 ./usr/include/bits/getopt_posix.h
+-rw-r--r-- root root 972 ./usr/include/bits/hwcap.h
+-rw-r--r-- root root 1591 ./usr/include/bits/indirect-return.h
+-rw-r--r-- root root 9534 ./usr/include/bits/in.h
+-rw-r--r-- root root 25 ./usr/include/bits/initspin.h
+-rw-r--r-- root root 1080 ./usr/include/bits/inotify.h
+-rw-r--r-- root root 4478 ./usr/include/bits/ioctls.h
+-rw-r--r-- root root 2456 ./usr/include/bits/ioctl-types.h
+-rw-r--r-- root root 1523 ./usr/include/bits/ipc.h
+-rw-r--r-- root root 1745 ./usr/include/bits/ipc-perm.h
+-rw-r--r-- root root 1176 ./usr/include/bits/ipctypes.h
+-rw-r--r-- root root 2479 ./usr/include/bits/iscanonical.h
+-rw-r--r-- root root 3288 ./usr/include/bits/libc-header-start.h
+-rw-r--r-- root root 3004 ./usr/include/bits/libm-simd-decl-stubs.h
+-rw-r--r-- root root 4286 ./usr/include/bits/link.h
+-rw-r--r-- root root 1368 ./usr/include/bits/locale.h
+-rw-r--r-- root root 3185 ./usr/include/bits/local_lim.h
+-rw-r--r-- root root 962 ./usr/include/bits/long-double-64.h
+-rw-r--r-- root root 552 ./usr/include/bits/long-double.h
+-rw-r--r-- root root 13210 ./usr/include/bits/mathcalls.h
+-rw-r--r-- root root 1765 ./usr/include/bits/mathcalls-helper-functions.h
+-rw-r--r-- root root 1312 ./usr/include/bits/mathcalls-narrow.h
+-rw-r--r-- root root 891 ./usr/include/bits/mathdef.h
+-rw-r--r-- root root 337 ./usr/include/bits/mathinline.h
+-rw-r--r-- root root 2308 ./usr/include/bits/math-vector.h
+-rw-r--r-- root root 1309 ./usr/include/bits/mman.h
+-rw-r--r-- root root 4911 ./usr/include/bits/mman-linux.h
+-rw-r--r-- root root 1997 ./usr/include/bits/mman-map-flags-generic.h
+-rw-r--r-- root root 2813 ./usr/include/bits/mman-shared.h
+-rw-r--r-- root root 1047 ./usr/include/bits/monetary-ldbl.h
+-rw-r--r-- root root 2151 ./usr/include/bits/mqueue2.h
+-rw-r--r-- root root 1246 ./usr/include/bits/mqueue.h
+-rw-r--r-- root root 2818 ./usr/include/bits/msq.h
+-rw-r--r-- root root 1283 ./usr/include/bits/msq-pad.h
+-rw-r--r-- root root 1264 ./usr/include/bits/netdb.h
+-rw-r--r-- root root 1433 ./usr/include/bits/param.h
+-rw-r--r-- root root 2937 ./usr/include/bits/poll2.h
+-rw-r--r-- root root 2076 ./usr/include/bits/poll.h
+-rw-r--r-- root root 5189 ./usr/include/bits/posix1_lim.h
+-rw-r--r-- root root 2867 ./usr/include/bits/posix2_lim.h
+-rw-r--r-- root root 5913 ./usr/include/bits/posix_opt.h
+-rw-r--r-- root root 992 ./usr/include/bits/printf-ldbl.h
+-rw-r--r-- root root 963 ./usr/include/bits/procfs-extra.h
+-rw-r--r-- root root 2025 ./usr/include/bits/procfs.h
+-rw-r--r-- root root 1148 ./usr/include/bits/procfs-id.h
+-rw-r--r-- root root 1050 ./usr/include/bits/procfs-prregset.h
+-rw-r--r-- root root 1838 ./usr/include/bits/pthreadtypes-arch.h
+-rw-r--r-- root root 3072 ./usr/include/bits/pthreadtypes.h
+-rw-r--r-- root root 4091 ./usr/include/bits/ptrace-shared.h
+-rw-r--r-- root root 6299 ./usr/include/bits/resource.h
+-rw-r--r-- root root 3947 ./usr/include/bits/sched.h
+-rw-r--r-- root root 1438 ./usr/include/bits/select2.h
+-rw-r--r-- root root 2106 ./usr/include/bits/select.h
+-rw-r--r-- root root 1238 ./usr/include/bits/semaphore.h
+-rw-r--r-- root root 2905 ./usr/include/bits/sem.h
+-rw-r--r-- root root 1019 ./usr/include/bits/sem-pad.h
+-rw-r--r-- root root 1705 ./usr/include/bits/setjmp2.h
+-rw-r--r-- root root 1287 ./usr/include/bits/setjmp.h
+-rw-r--r-- root root 3872 ./usr/include/bits/shm.h
+-rw-r--r-- root root 1106 ./usr/include/bits/shmlba.h
+-rw-r--r-- root root 1668 ./usr/include/bits/shm-pad.h
+-rw-r--r-- root root 2935 ./usr/include/bits/sigaction.h
+-rw-r--r-- root root 4266 ./usr/include/bits/sigcontext.h
+-rw-r--r-- root root 1471 ./usr/include/bits/sigevent-consts.h
+-rw-r--r-- root root 729 ./usr/include/bits/siginfo-arch.h
+-rw-r--r-- root root 204 ./usr/include/bits/siginfo-consts-arch.h
+-rw-r--r-- root root 6855 ./usr/include/bits/siginfo-consts.h
+-rw-r--r-- root root 1285 ./usr/include/bits/signal_ext.h
+-rw-r--r-- root root 1067 ./usr/include/bits/signalfd.h
+-rw-r--r-- root root 4341 ./usr/include/bits/signum-generic.h
+-rw-r--r-- root root 1634 ./usr/include/bits/signum.h
+-rw-r--r-- root root 1168 ./usr/include/bits/sigstack.h
+-rw-r--r-- root root 1692 ./usr/include/bits/sigthread.h
+-rw-r--r-- root root 1514 ./usr/include/bits/sockaddr.h
+-rw-r--r-- root root 3026 ./usr/include/bits/socket2.h
+-rw-r--r-- root root 1318 ./usr/include/bits/socket-constants.h
+-rw-r--r-- root root 12261 ./usr/include/bits/socket.h
+-rw-r--r-- root root 2216 ./usr/include/bits/socket_type.h
+-rw-r--r-- root root 1188 ./usr/include/bits/ss_flags.h
+-rw-r--r-- root root 9040 ./usr/include/bits/stab.def
+-rw-r--r-- root root 1917 ./usr/include/bits/statfs.h
+-rw-r--r-- root root 7620 ./usr/include/bits/stat.h
+-rw-r--r-- root root 3423 ./usr/include/bits/statvfs.h
+-rw-r--r-- root root 2050 ./usr/include/bits/statx-generic.h
+-rw-r--r-- root root 1400 ./usr/include/bits/statx.h
+-rw-r--r-- root root 1037 ./usr/include/bits/stdint-intn.h
+-rw-r--r-- root root 1049 ./usr/include/bits/stdint-uintn.h
+-rw-r--r-- root root 12679 ./usr/include/bits/stdio2.h
+-rw-r--r-- root root 5584 ./usr/include/bits/stdio.h
+-rw-r--r-- root root 2843 ./usr/include/bits/stdio-ldbl.h
+-rw-r--r-- root root 1213 ./usr/include/bits/stdio_lim.h
+-rw-r--r-- root root 1378 ./usr/include/bits/stdlib-bsearch.h
+-rw-r--r-- root root 1115 ./usr/include/bits/stdlib-float.h
+-rw-r--r-- root root 5659 ./usr/include/bits/stdlib.h
+-rw-r--r-- root root 1377 ./usr/include/bits/stdlib-ldbl.h
+-rw-r--r-- root root 4314 ./usr/include/bits/string_fortified.h
+-rw-r--r-- root root 1209 ./usr/include/bits/strings_fortified.h
+-rw-r--r-- root root 1810 ./usr/include/bits/struct_mutex.h
+-rw-r--r-- root root 2027 ./usr/include/bits/struct_rwlock-64.h
+-rw-r--r-- root root 560 ./usr/include/bits/struct_rwlock.h
+-rw-r--r-- root root 44103 ./usr/include/bits/syscall-64.h
+-rw-r--r-- root root 536 ./usr/include/bits/syscall.h
+-rw-r--r-- root root 899 ./usr/include/bits/sysctl.h
+-rw-r--r-- root root 1216 ./usr/include/bits/sys_errlist.h
+-rw-r--r-- root root 1685 ./usr/include/bits/syslog.h
+-rw-r--r-- root root 1206 ./usr/include/bits/syslog-ldbl.h
+-rw-r--r-- root root 1061 ./usr/include/bits/syslog-path.h
+-rw-r--r-- root root 2953 ./usr/include/bits/sysmacros.h
+-rw-r--r-- root root 1824 ./usr/include/bits/termios-baud.h
+-rw-r--r-- root root 1279 ./usr/include/bits/termios-c_cc.h
+-rw-r--r-- root root 1230 ./usr/include/bits/termios-c_cflag.h
+-rw-r--r-- root root 1936 ./usr/include/bits/termios-c_iflag.h
+-rw-r--r-- root root 2594 ./usr/include/bits/termios-c_lflag.h
+-rw-r--r-- root root 2822 ./usr/include/bits/termios-c_oflag.h
+-rw-r--r-- root root 2168 ./usr/include/bits/termios.h
+-rw-r--r-- root root 969 ./usr/include/bits/termios-misc.h
+-rw-r--r-- root root 1433 ./usr/include/bits/termios-struct.h
+-rw-r--r-- root root 1062 ./usr/include/bits/termios-tcflow.h
+-rw-r--r-- root root 3982 ./usr/include/bits/thread-shared-types.h
+-rw-r--r-- root root 1340 ./usr/include/bits/time64.h
+-rw-r--r-- root root 2999 ./usr/include/bits/time.h
+-rw-r--r-- root root 1103 ./usr/include/bits/timerfd.h
+-rw-r--r-- root root 1081 ./usr/include/bits/timesize.h
+-rw-r--r-- root root 4596 ./usr/include/bits/timex.h
+drwxr-xr-x root root 4096 ./usr/include/bits/types
+-rw-r--r-- root root 174 ./usr/include/bits/types/clockid_t.h
+-rw-r--r-- root root 143 ./usr/include/bits/types/clock_t.h
+-rw-r--r-- root root 2725 ./usr/include/bits/types/cookie_io_functions_t.h
+-rw-r--r-- root root 894 ./usr/include/bits/types/error_t.h
+-rw-r--r-- root root 110 ./usr/include/bits/types/__FILE.h
+-rw-r--r-- root root 180 ./usr/include/bits/types/FILE.h
+-rw-r--r-- root root 410 ./usr/include/bits/types/__fpos64_t.h
+-rw-r--r-- root root 381 ./usr/include/bits/types/__fpos_t.h
+-rw-r--r-- root root 8757 ./usr/include/bits/types.h
+-rw-r--r-- root root 3546 ./usr/include/bits/typesizes.h
+-rw-r--r-- root root 1722 ./usr/include/bits/types/__locale_t.h
+-rw-r--r-- root root 983 ./usr/include/bits/types/locale_t.h
+-rw-r--r-- root root 564 ./usr/include/bits/types/__mbstate_t.h
+-rw-r--r-- root root 135 ./usr/include/bits/types/mbstate_t.h
+-rw-r--r-- root root 2009 ./usr/include/bits/types/res_state.h
+-rw-r--r-- root root 272 ./usr/include/bits/types/sig_atomic_t.h
+-rw-r--r-- root root 1204 ./usr/include/bits/types/sigevent_t.h
+-rw-r--r-- root root 3892 ./usr/include/bits/types/siginfo_t.h
+-rw-r--r-- root root 206 ./usr/include/bits/types/__sigset_t.h
+-rw-r--r-- root root 195 ./usr/include/bits/types/sigset_t.h
+-rw-r--r-- root root 1148 ./usr/include/bits/types/__sigval_t.h
+-rw-r--r-- root root 599 ./usr/include/bits/types/sigval_t.h
+-rw-r--r-- root root 1062 ./usr/include/bits/types/stack_t.h
+-rw-r--r-- root root 4104 ./usr/include/bits/types/struct_FILE.h
+-rw-r--r-- root root 1066 ./usr/include/bits/types/struct_iovec.h
+-rw-r--r-- root root 288 ./usr/include/bits/types/struct_itimerspec.h
+-rw-r--r-- root root 274 ./usr/include/bits/types/struct_osockaddr.h
+-rw-r--r-- root root 4121 ./usr/include/bits/types/struct_rusage.h
+-rw-r--r-- root root 1073 ./usr/include/bits/types/struct_sched_param.h
+-rw-r--r-- root root 1073 ./usr/include/bits/types/struct_sigstack.h
+-rw-r--r-- root root 1897 ./usr/include/bits/types/struct_statx.h
+-rw-r--r-- root root 1202 ./usr/include/bits/types/struct_statx_timestamp.h
+-rw-r--r-- root root 728 ./usr/include/bits/types/struct_timespec.h
+-rw-r--r-- root root 287 ./usr/include/bits/types/struct_timeval.h
+-rw-r--r-- root root 760 ./usr/include/bits/types/struct_tm.h
+-rw-r--r-- root root 159 ./usr/include/bits/types/timer_t.h
+-rw-r--r-- root root 138 ./usr/include/bits/types/time_t.h
+-rw-r--r-- root root 796 ./usr/include/bits/types/wint_t.h
+-rw-r--r-- root root 1542 ./usr/include/bits/uintn-identity.h
+-rw-r--r-- root root 1923 ./usr/include/bits/uio-ext.h
+-rw-r--r-- root root 1385 ./usr/include/bits/uio_lim.h
+-rw-r--r-- root root 1613 ./usr/include/bits/unistd_ext.h
+-rw-r--r-- root root 13316 ./usr/include/bits/unistd.h
+-rw-r--r-- root root 4067 ./usr/include/bits/utmp.h
+-rw-r--r-- root root 3578 ./usr/include/bits/utmpx.h
+-rw-r--r-- root root 1213 ./usr/include/bits/utsname.h
+-rw-r--r-- root root 1697 ./usr/include/bits/waitflags.h
+-rw-r--r-- root root 2287 ./usr/include/bits/waitstatus.h
+-rw-r--r-- root root 20506 ./usr/include/bits/wchar2.h
+-rw-r--r-- root root 1906 ./usr/include/bits/wchar.h
+-rw-r--r-- root root 2251 ./usr/include/bits/wchar-ldbl.h
+-rw-r--r-- root root 6307 ./usr/include/bits/wctype-wchar.h
+-rw-r--r-- root root 442 ./usr/include/bits/wordsize.h
+-rw-r--r-- root root 3858 ./usr/include/bits/xopen_lim.h
+drwxr-xr-x root root 4096 ./usr/include/blkid
+-rw-r--r-- root root 15478 ./usr/include/blkid/blkid.h
+drwxr-xr-x root root 4096 ./usr/include/btrfs
+-rw-r--r-- root root 5045 ./usr/include/btrfs/btrfsck.h
+-rw-r--r-- root root 4670 ./usr/include/btrfs/btrfs-list.h
+-rw-r--r-- root root 1095 ./usr/include/btrfs/crc32c.h
+-rw-r--r-- root root 93730 ./usr/include/btrfs/ctree.h
+-rw-r--r-- root root 3524 ./usr/include/btrfs/extent-cache.h
+-rw-r--r-- root root 6507 ./usr/include/btrfs/extent_io.h
+-rw-r--r-- root root 29359 ./usr/include/btrfs/ioctl.h
+-rw-r--r-- root root 10965 ./usr/include/btrfs/kerncompat.h
+-rw-r--r-- root root 14636 ./usr/include/btrfs/list.h
+-rw-r--r-- root root 3343 ./usr/include/btrfs/radix-tree.h
+-rw-r--r-- root root 2024 ./usr/include/btrfs/raid56.h
+-rw-r--r-- root root 3902 ./usr/include/btrfs/rbtree.h
+-rw-r--r-- root root 3090 ./usr/include/btrfs/send.h
+-rw-r--r-- root root 2803 ./usr/include/btrfs/send-stream.h
+-rw-r--r-- root root 3388 ./usr/include/btrfs/send-utils.h
+-rw-r--r-- root root 1223 ./usr/include/btrfs/sizes.h
+-rw-r--r-- root root 22942 ./usr/include/btrfsutil.h
+-rw-r--r-- root root 363 ./usr/include/btrfs/version.h
+-rw-r--r-- root root 1405 ./usr/include/byteswap.h
+-rw-r--r-- root root 6240 ./usr/include/bzlib.h
+drwxr-xr-x root root 4096 ./usr/include/c++
+drwxr-xr-x root root 4096 ./usr/include/c++/10.1.0
+-rw-r--r-- root root 3045 ./usr/include/c++/10.1.0/algorithm
+-rw-r--r-- root root 18236 ./usr/include/c++/10.1.0/any
+-rw-r--r-- root root 13700 ./usr/include/c++/10.1.0/array
+-rw-r--r-- root root 45341 ./usr/include/c++/10.1.0/atomic
+drwxr-xr-x root root 4096 ./usr/include/c++/10.1.0/backward
+-rw-r--r-- root root 10804 ./usr/include/c++/10.1.0/backward/auto_ptr.h
+-rw-r--r-- root root 2491 ./usr/include/c++/10.1.0/backward/backward_warning.h
+-rw-r--r-- root root 7167 ./usr/include/c++/10.1.0/backward/binders.h
+-rw-r--r-- root root 4248 ./usr/include/c++/10.1.0/backward/hash_fun.h
+-rw-r--r-- root root 17822 ./usr/include/c++/10.1.0/backward/hash_map
+-rw-r--r-- root root 17323 ./usr/include/c++/10.1.0/backward/hash_set
+-rw-r--r-- root root 33883 ./usr/include/c++/10.1.0/backward/hashtable.h
+-rw-r--r-- root root 7454 ./usr/include/c++/10.1.0/backward/strstream
+-rw-r--r-- root root 11044 ./usr/include/c++/10.1.0/bit
+drwxr-xr-x root root 4096 ./usr/include/c++/10.1.0/bits
+-rw-r--r-- root root 24547 ./usr/include/c++/10.1.0/bits/algorithmfwd.h
+-rw-r--r-- root root 3293 ./usr/include/c++/10.1.0/bits/allocated_ptr.h
+-rw-r--r-- root root 8984 ./usr/include/c++/10.1.0/bits/allocator.h
+-rw-r--r-- root root 24105 ./usr/include/c++/10.1.0/bits/alloc_traits.h
+-rw-r--r-- root root 51344 ./usr/include/c++/10.1.0/bits/atomic_base.h
+-rw-r--r-- root root 9499 ./usr/include/c++/10.1.0/bits/atomic_futex.h
+-rw-r--r-- root root 2352 ./usr/include/c++/10.1.0/bits/atomic_lockfree_defines.h
+-rw-r--r-- root root 16074 ./usr/include/c++/10.1.0/bits/basic_ios.h
+-rw-r--r-- root root 6083 ./usr/include/c++/10.1.0/bits/basic_ios.tcc
+-rw-r--r-- root root 249154 ./usr/include/c++/10.1.0/bits/basic_string.h
+-rw-r--r-- root root 54513 ./usr/include/c++/10.1.0/bits/basic_string.tcc
+-rw-r--r-- root root 27182 ./usr/include/c++/10.1.0/bits/boost_concept_check.h
+-rw-r--r-- root root 1474 ./usr/include/c++/10.1.0/bits/c++0x_warning.h
+-rw-r--r-- root root 3435 ./usr/include/c++/10.1.0/bits/charconv.h
+-rw-r--r-- root root 28509 ./usr/include/c++/10.1.0/bits/char_traits.h
+-rw-r--r-- root root 25429 ./usr/include/c++/10.1.0/bits/codecvt.h
+-rw-r--r-- root root 3423 ./usr/include/c++/10.1.0/bits/concept_check.h
+-rw-r--r-- root root 12011 ./usr/include/c++/10.1.0/bits/cpp_type_traits.h
+-rw-r--r-- root root 1811 ./usr/include/c++/10.1.0/bits/cxxabi_forced.h
+-rw-r--r-- root root 2220 ./usr/include/c++/10.1.0/bits/cxxabi_init_exception.h
+-rw-r--r-- root root 37325 ./usr/include/c++/10.1.0/bits/deque.tcc
+-rw-r--r-- root root 12387 ./usr/include/c++/10.1.0/bits/enable_special_members.h
+-rw-r--r-- root root 2037 ./usr/include/c++/10.1.0/bits/erase_if.h
+-rw-r--r-- root root 45979 ./usr/include/c++/10.1.0/bitset
+-rw-r--r-- root root 1645 ./usr/include/c++/10.1.0/bits/exception_defines.h
+-rw-r--r-- root root 2483 ./usr/include/c++/10.1.0/bits/exception.h
+-rw-r--r-- root root 6072 ./usr/include/c++/10.1.0/bits/exception_ptr.h
+-rw-r--r-- root root 50386 ./usr/include/c++/10.1.0/bits/forward_list.h
+-rw-r--r-- root root 13871 ./usr/include/c++/10.1.0/bits/forward_list.tcc
+-rw-r--r-- root root 16405 ./usr/include/c++/10.1.0/bits/fs_dir.h
+-rw-r--r-- root root 10267 ./usr/include/c++/10.1.0/bits/fs_fwd.h
+-rw-r--r-- root root 9729 ./usr/include/c++/10.1.0/bits/fs_ops.h
+-rw-r--r-- root root 38775 ./usr/include/c++/10.1.0/bits/fs_path.h
+-rw-r--r-- root root 33663 ./usr/include/c++/10.1.0/bits/fstream.tcc
+-rw-r--r-- root root 3433 ./usr/include/c++/10.1.0/bits/functexcept.h
+-rw-r--r-- root root 8567 ./usr/include/c++/10.1.0/bits/functional_hash.h
+-rw-r--r-- root root 7851 ./usr/include/c++/10.1.0/bits/gslice_array.h
+-rw-r--r-- root root 5518 ./usr/include/c++/10.1.0/bits/gslice.h
+-rw-r--r-- root root 2146 ./usr/include/c++/10.1.0/bits/hash_bytes.h
+-rw-r--r-- root root 74752 ./usr/include/c++/10.1.0/bits/hashtable.h
+-rw-r--r-- root root 67673 ./usr/include/c++/10.1.0/bits/hashtable_policy.h
+-rw-r--r-- root root 7861 ./usr/include/c++/10.1.0/bits/indirect_array.h
+-rw-r--r-- root root 2877 ./usr/include/c++/10.1.0/bits/int_limits.h
+-rw-r--r-- root root 6025 ./usr/include/c++/10.1.0/bits/invoke.h
+-rw-r--r-- root root 31179 ./usr/include/c++/10.1.0/bits/ios_base.h
+-rw-r--r-- root root 31093 ./usr/include/c++/10.1.0/bits/istream.tcc
+-rw-r--r-- root root 30948 ./usr/include/c++/10.1.0/bits/iterator_concepts.h
+-rw-r--r-- root root 16968 ./usr/include/c++/10.1.0/bits/list.tcc
+-rw-r--r-- root root 24950 ./usr/include/c++/10.1.0/bits/locale_classes.h
+-rw-r--r-- root root 8375 ./usr/include/c++/10.1.0/bits/locale_classes.tcc
+-rw-r--r-- root root 18801 ./usr/include/c++/10.1.0/bits/locale_conv.h
+-rw-r--r-- root root 92321 ./usr/include/c++/10.1.0/bits/locale_facets.h
+-rw-r--r-- root root 68980 ./usr/include/c++/10.1.0/bits/locale_facets_nonio.h
+-rw-r--r-- root root 45280 ./usr/include/c++/10.1.0/bits/locale_facets_nonio.tcc
+-rw-r--r-- root root 39548 ./usr/include/c++/10.1.0/bits/locale_facets.tcc
+-rw-r--r-- root root 5941 ./usr/include/c++/10.1.0/bits/localefwd.h
+-rw-r--r-- root root 7675 ./usr/include/c++/10.1.0/bits/mask_array.h
+-rw-r--r-- root root 2487 ./usr/include/c++/10.1.0/bits/memoryfwd.h
+-rw-r--r-- root root 6613 ./usr/include/c++/10.1.0/bits/move.h
+-rw-r--r-- root root 4886 ./usr/include/c++/10.1.0/bits/nested_exception.h
+-rw-r--r-- root root 8216 ./usr/include/c++/10.1.0/bits/node_handle.h
+-rw-r--r-- root root 4002 ./usr/include/c++/10.1.0/bits/ostream_insert.h
+-rw-r--r-- root root 12315 ./usr/include/c++/10.1.0/bits/ostream.tcc
+-rw-r--r-- root root 7943 ./usr/include/c++/10.1.0/bits/parse_numbers.h
+-rw-r--r-- root root 8465 ./usr/include/c++/10.1.0/bits/postypes.h
+-rw-r--r-- root root 10153 ./usr/include/c++/10.1.0/bits/predefined_ops.h
+-rw-r--r-- root root 6728 ./usr/include/c++/10.1.0/bits/ptr_traits.h
+-rw-r--r-- root root 5053 ./usr/include/c++/10.1.0/bits/quoted_string.h
+-rw-r--r-- root root 178118 ./usr/include/c++/10.1.0/bits/random.h
+-rw-r--r-- root root 103405 ./usr/include/c++/10.1.0/bits/random.tcc
+-rw-r--r-- root root 32001 ./usr/include/c++/10.1.0/bits/range_access.h
+-rw-r--r-- root root 6516 ./usr/include/c++/10.1.0/bits/range_cmp.h
+-rw-r--r-- root root 18319 ./usr/include/c++/10.1.0/bits/ranges_algobase.h
+-rw-r--r-- root root 121079 ./usr/include/c++/10.1.0/bits/ranges_algo.h
+-rw-r--r-- root root 18023 ./usr/include/c++/10.1.0/bits/ranges_uninitialized.h
+-rw-r--r-- root root 13207 ./usr/include/c++/10.1.0/bits/refwrap.h
+-rw-r--r-- root root 10738 ./usr/include/c++/10.1.0/bits/regex_automaton.h
+-rw-r--r-- root root 7722 ./usr/include/c++/10.1.0/bits/regex_automaton.tcc
+-rw-r--r-- root root 16481 ./usr/include/c++/10.1.0/bits/regex_compiler.h
+-rw-r--r-- root root 18929 ./usr/include/c++/10.1.0/bits/regex_compiler.tcc
+-rw-r--r-- root root 14729 ./usr/include/c++/10.1.0/bits/regex_constants.h
+-rw-r--r-- root root 4904 ./usr/include/c++/10.1.0/bits/regex_error.h
+-rw-r--r-- root root 7488 ./usr/include/c++/10.1.0/bits/regex_executor.h
+-rw-r--r-- root root 18841 ./usr/include/c++/10.1.0/bits/regex_executor.tcc
+-rw-r--r-- root root 102775 ./usr/include/c++/10.1.0/bits/regex.h
+-rw-r--r-- root root 7088 ./usr/include/c++/10.1.0/bits/regex_scanner.h
+-rw-r--r-- root root 15009 ./usr/include/c++/10.1.0/bits/regex_scanner.tcc
+-rw-r--r-- root root 16524 ./usr/include/c++/10.1.0/bits/regex.tcc
+-rw-r--r-- root root 9867 ./usr/include/c++/10.1.0/bits/shared_ptr_atomic.h
+-rw-r--r-- root root 55312 ./usr/include/c++/10.1.0/bits/shared_ptr_base.h
+-rw-r--r-- root root 30837 ./usr/include/c++/10.1.0/bits/shared_ptr.h
+-rw-r--r-- root root 9578 ./usr/include/c++/10.1.0/bits/slice_array.h
+-rw-r--r-- root root 47238 ./usr/include/c++/10.1.0/bits/specfun.h
+-rw-r--r-- root root 10142 ./usr/include/c++/10.1.0/bits/sstream.tcc
+-rw-r--r-- root root 3360 ./usr/include/c++/10.1.0/bits/std_abs.h
+-rw-r--r-- root root 21612 ./usr/include/c++/10.1.0/bits/std_function.h
+-rw-r--r-- root root 4767 ./usr/include/c++/10.1.0/bits/std_mutex.h
+-rw-r--r-- root root 71744 ./usr/include/c++/10.1.0/bits/stl_algobase.h
+-rw-r--r-- root root 214835 ./usr/include/c++/10.1.0/bits/stl_algo.h
+-rw-r--r-- root root 34767 ./usr/include/c++/10.1.0/bits/stl_bvector.h
+-rw-r--r-- root root 8521 ./usr/include/c++/10.1.0/bits/stl_construct.h
+-rw-r--r-- root root 76807 ./usr/include/c++/10.1.0/bits/stl_deque.h
+-rw-r--r-- root root 42293 ./usr/include/c++/10.1.0/bits/stl_function.h
+-rw-r--r-- root root 20756 ./usr/include/c++/10.1.0/bits/stl_heap.h
+-rw-r--r-- root root 8178 ./usr/include/c++/10.1.0/bits/stl_iterator_base_funcs.h
+-rw-r--r-- root root 9660 ./usr/include/c++/10.1.0/bits/stl_iterator_base_types.h
+-rw-r--r-- root root 69682 ./usr/include/c++/10.1.0/bits/stl_iterator.h
+-rw-r--r-- root root 68748 ./usr/include/c++/10.1.0/bits/stl_list.h
+-rw-r--r-- root root 54669 ./usr/include/c++/10.1.0/bits/stl_map.h
+-rw-r--r-- root root 43510 ./usr/include/c++/10.1.0/bits/stl_multimap.h
+-rw-r--r-- root root 37662 ./usr/include/c++/10.1.0/bits/stl_multiset.h
+-rw-r--r-- root root 14600 ./usr/include/c++/10.1.0/bits/stl_numeric.h
+-rw-r--r-- root root 20163 ./usr/include/c++/10.1.0/bits/stl_pair.h
+-rw-r--r-- root root 25036 ./usr/include/c++/10.1.0/bits/stl_queue.h
+-rw-r--r-- root root 3830 ./usr/include/c++/10.1.0/bits/stl_raw_storage_iter.h
+-rw-r--r-- root root 4594 ./usr/include/c++/10.1.0/bits/stl_relops.h
+-rw-r--r-- root root 37922 ./usr/include/c++/10.1.0/bits/stl_set.h
+-rw-r--r-- root root 12684 ./usr/include/c++/10.1.0/bits/stl_stack.h
+-rw-r--r-- root root 8623 ./usr/include/c++/10.1.0/bits/stl_tempbuf.h
+-rw-r--r-- root root 74660 ./usr/include/c++/10.1.0/bits/stl_tree.h
+-rw-r--r-- root root 33161 ./usr/include/c++/10.1.0/bits/stl_uninitialized.h
+-rw-r--r-- root root 65919 ./usr/include/c++/10.1.0/bits/stl_vector.h
+-rw-r--r-- root root 15462 ./usr/include/c++/10.1.0/bits/streambuf_iterator.h
+-rw-r--r-- root root 4929 ./usr/include/c++/10.1.0/bits/streambuf.tcc
+-rw-r--r-- root root 7694 ./usr/include/c++/10.1.0/bits/stream_iterator.h
+-rw-r--r-- root root 2690 ./usr/include/c++/10.1.0/bits/stringfwd.h
+-rw-r--r-- root root 6698 ./usr/include/c++/10.1.0/bits/string_view.tcc
+-rw-r--r-- root root 10730 ./usr/include/c++/10.1.0/bits/uniform_int_dist.h
+-rw-r--r-- root root 6090 ./usr/include/c++/10.1.0/bits/unique_lock.h
+-rw-r--r-- root root 31291 ./usr/include/c++/10.1.0/bits/unique_ptr.h
+-rw-r--r-- root root 76744 ./usr/include/c++/10.1.0/bits/unordered_map.h
+-rw-r--r-- root root 60612 ./usr/include/c++/10.1.0/bits/unordered_set.h
+-rw-r--r-- root root 6870 ./usr/include/c++/10.1.0/bits/uses_allocator.h
+-rw-r--r-- root root 22839 ./usr/include/c++/10.1.0/bits/valarray_after.h
+-rw-r--r-- root root 21295 ./usr/include/c++/10.1.0/bits/valarray_array.h
+-rw-r--r-- root root 7254 ./usr/include/c++/10.1.0/bits/valarray_array.tcc
+-rw-r--r-- root root 19142 ./usr/include/c++/10.1.0/bits/valarray_before.h
+-rw-r--r-- root root 30870 ./usr/include/c++/10.1.0/bits/vector.tcc
+-rw-r--r-- root root 1648 ./usr/include/c++/10.1.0/cassert
+-rw-r--r-- root root 1335 ./usr/include/c++/10.1.0/ccomplex
+-rw-r--r-- root root 2409 ./usr/include/c++/10.1.0/cctype
+-rw-r--r-- root root 1770 ./usr/include/c++/10.1.0/cerrno
+-rw-r--r-- root root 2051 ./usr/include/c++/10.1.0/cfenv
+-rw-r--r-- root root 1889 ./usr/include/c++/10.1.0/cfloat
+-rw-r--r-- root root 17991 ./usr/include/c++/10.1.0/charconv
+-rw-r--r-- root root 38834 ./usr/include/c++/10.1.0/chrono
+-rw-r--r-- root root 2157 ./usr/include/c++/10.1.0/cinttypes
+-rw-r--r-- root root 1464 ./usr/include/c++/10.1.0/ciso646
+-rw-r--r-- root root 1913 ./usr/include/c++/10.1.0/climits
+-rw-r--r-- root root 1905 ./usr/include/c++/10.1.0/clocale
+-rw-r--r-- root root 49130 ./usr/include/c++/10.1.0/cmath
+-rw-r--r-- root root 5275 ./usr/include/c++/10.1.0/codecvt
+-rw-r--r-- root root 27896 ./usr/include/c++/10.1.0/compare
+-rw-r--r-- root root 56646 ./usr/include/c++/10.1.0/complex
+-rw-r--r-- root root 1596 ./usr/include/c++/10.1.0/complex.h
+-rw-r--r-- root root 12267 ./usr/include/c++/10.1.0/concepts
+-rw-r--r-- root root 12993 ./usr/include/c++/10.1.0/condition_variable
+-rw-r--r-- root root 7898 ./usr/include/c++/10.1.0/coroutine
+-rw-r--r-- root root 1949 ./usr/include/c++/10.1.0/csetjmp
+-rw-r--r-- root root 1855 ./usr/include/c++/10.1.0/csignal
+-rw-r--r-- root root 1407 ./usr/include/c++/10.1.0/cstdalign
+-rw-r--r-- root root 1868 ./usr/include/c++/10.1.0/cstdarg
+-rw-r--r-- root root 1401 ./usr/include/c++/10.1.0/cstdbool
+-rw-r--r-- root root 6274 ./usr/include/c++/10.1.0/cstddef
+-rw-r--r-- root root 2335 ./usr/include/c++/10.1.0/cstdint
+-rw-r--r-- root root 4439 ./usr/include/c++/10.1.0/cstdio
+-rw-r--r-- root root 6325 ./usr/include/c++/10.1.0/cstdlib
+-rw-r--r-- root root 3156 ./usr/include/c++/10.1.0/cstring
+-rw-r--r-- root root 1360 ./usr/include/c++/10.1.0/ctgmath
+-rw-r--r-- root root 2298 ./usr/include/c++/10.1.0/ctime
+-rw-r--r-- root root 2210 ./usr/include/c++/10.1.0/cuchar
+-rw-r--r-- root root 6542 ./usr/include/c++/10.1.0/cwchar
+-rw-r--r-- root root 2793 ./usr/include/c++/10.1.0/cwctype
+-rw-r--r-- root root 22011 ./usr/include/c++/10.1.0/cxxabi.h
+drwxr-xr-x root root 4096 ./usr/include/c++/10.1.0/debug
+-rw-r--r-- root root 12476 ./usr/include/c++/10.1.0/debug/array
+-rw-r--r-- root root 2411 ./usr/include/c++/10.1.0/debug/assertions.h
+-rw-r--r-- root root 11903 ./usr/include/c++/10.1.0/debug/bitset
+-rw-r--r-- root root 5881 ./usr/include/c++/10.1.0/debug/debug.h
+-rw-r--r-- root root 17979 ./usr/include/c++/10.1.0/debug/deque
+-rw-r--r-- root root 16991 ./usr/include/c++/10.1.0/debug/formatter.h
+-rw-r--r-- root root 27420 ./usr/include/c++/10.1.0/debug/forward_list
+-rw-r--r-- root root 15612 ./usr/include/c++/10.1.0/debug/functions.h
+-rw-r--r-- root root 9985 ./usr/include/c++/10.1.0/debug/helper_functions.h
+-rw-r--r-- root root 25327 ./usr/include/c++/10.1.0/debug/list
+-rw-r--r-- root root 20915 ./usr/include/c++/10.1.0/debug/macros.h
+-rw-r--r-- root root 1656 ./usr/include/c++/10.1.0/debug/map
+-rw-r--r-- root root 23035 ./usr/include/c++/10.1.0/debug/map.h
+-rw-r--r-- root root 20301 ./usr/include/c++/10.1.0/debug/multimap.h
+-rw-r--r-- root root 19200 ./usr/include/c++/10.1.0/debug/multiset.h
+-rw-r--r-- root root 9279 ./usr/include/c++/10.1.0/debug/safe_base.h
+-rw-r--r-- root root 3413 ./usr/include/c++/10.1.0/debug/safe_container.h
+-rw-r--r-- root root 30112 ./usr/include/c++/10.1.0/debug/safe_iterator.h
+-rw-r--r-- root root 16171 ./usr/include/c++/10.1.0/debug/safe_iterator.tcc
+-rw-r--r-- root root 13739 ./usr/include/c++/10.1.0/debug/safe_local_iterator.h
+-rw-r--r-- root root 2905 ./usr/include/c++/10.1.0/debug/safe_local_iterator.tcc
+-rw-r--r-- root root 5096 ./usr/include/c++/10.1.0/debug/safe_sequence.h
+-rw-r--r-- root root 5040 ./usr/include/c++/10.1.0/debug/safe_sequence.tcc
+-rw-r--r-- root root 6895 ./usr/include/c++/10.1.0/debug/safe_unordered_base.h
+-rw-r--r-- root root 3866 ./usr/include/c++/10.1.0/debug/safe_unordered_container.h
+-rw-r--r-- root root 3263 ./usr/include/c++/10.1.0/debug/safe_unordered_container.tcc
+-rw-r--r-- root root 1620 ./usr/include/c++/10.1.0/debug/set
+-rw-r--r-- root root 19199 ./usr/include/c++/10.1.0/debug/set.h
+-rw-r--r-- root root 4542 ./usr/include/c++/10.1.0/debug/stl_iterator.h
+-rw-r--r-- root root 36471 ./usr/include/c++/10.1.0/debug/string
+-rw-r--r-- root root 41394 ./usr/include/c++/10.1.0/debug/unordered_map
+-rw-r--r-- root root 35429 ./usr/include/c++/10.1.0/debug/unordered_set
+-rw-r--r-- root root 23523 ./usr/include/c++/10.1.0/debug/vector
+drwxr-xr-x root root 4096 ./usr/include/c++/10.1.0/decimal
+-rw-r--r-- root root 17636 ./usr/include/c++/10.1.0/decimal/decimal
+-rw-r--r-- root root 16999 ./usr/include/c++/10.1.0/decimal/decimal.h
+-rw-r--r-- root root 3973 ./usr/include/c++/10.1.0/deque
+-rw-r--r-- root root 4848 ./usr/include/c++/10.1.0/exception
+-rw-r--r-- root root 1803 ./usr/include/c++/10.1.0/execution
+drwxr-xr-x root root 4096 ./usr/include/c++/10.1.0/experimental
+-rw-r--r-- root root 3688 ./usr/include/c++/10.1.0/experimental/algorithm
+-rw-r--r-- root root 16010 ./usr/include/c++/10.1.0/experimental/any
+-rw-r--r-- root root 3371 ./usr/include/c++/10.1.0/experimental/array
+drwxr-xr-x root root 4096 ./usr/include/c++/10.1.0/experimental/bits
+-rw-r--r-- root root 10799 ./usr/include/c++/10.1.0/experimental/bits/fs_dir.h
+-rw-r--r-- root root 8524 ./usr/include/c++/10.1.0/experimental/bits/fs_fwd.h
+-rw-r--r-- root root 9340 ./usr/include/c++/10.1.0/experimental/bits/fs_ops.h
+-rw-r--r-- root root 36768 ./usr/include/c++/10.1.0/experimental/bits/fs_path.h
+-rw-r--r-- root root 2227 ./usr/include/c++/10.1.0/experimental/bits/lfts_config.h
+-rw-r--r-- root root 4814 ./usr/include/c++/10.1.0/experimental/bits/net.h
+-rw-r--r-- root root 20205 ./usr/include/c++/10.1.0/experimental/bits/shared_ptr.h
+-rw-r--r-- root root 6816 ./usr/include/c++/10.1.0/experimental/bits/string_view.tcc
+-rw-r--r-- root root 28719 ./usr/include/c++/10.1.0/experimental/buffer
+-rw-r--r-- root root 1960 ./usr/include/c++/10.1.0/experimental/chrono
+-rw-r--r-- root root 2296 ./usr/include/c++/10.1.0/experimental/deque
+-rw-r--r-- root root 55081 ./usr/include/c++/10.1.0/experimental/executor
+-rw-r--r-- root root 1589 ./usr/include/c++/10.1.0/experimental/filesystem
+-rw-r--r-- root root 2367 ./usr/include/c++/10.1.0/experimental/forward_list
+-rw-r--r-- root root 12311 ./usr/include/c++/10.1.0/experimental/functional
+-rw-r--r-- root root 65288 ./usr/include/c++/10.1.0/experimental/internet
+-rw-r--r-- root root 21331 ./usr/include/c++/10.1.0/experimental/io_context
+-rw-r--r-- root root 3534 ./usr/include/c++/10.1.0/experimental/iterator
+-rw-r--r-- root root 2265 ./usr/include/c++/10.1.0/experimental/list
+-rw-r--r-- root root 2594 ./usr/include/c++/10.1.0/experimental/map
+-rw-r--r-- root root 6056 ./usr/include/c++/10.1.0/experimental/memory
+-rw-r--r-- root root 17388 ./usr/include/c++/10.1.0/experimental/memory_resource
+-rw-r--r-- root root 1542 ./usr/include/c++/10.1.0/experimental/net
+-rw-r--r-- root root 3744 ./usr/include/c++/10.1.0/experimental/netfwd
+-rw-r--r-- root root 2858 ./usr/include/c++/10.1.0/experimental/numeric
+-rw-r--r-- root root 26832 ./usr/include/c++/10.1.0/experimental/optional
+-rw-r--r-- root root 15335 ./usr/include/c++/10.1.0/experimental/propagate_const
+-rw-r--r-- root root 2499 ./usr/include/c++/10.1.0/experimental/random
+-rw-r--r-- root root 2438 ./usr/include/c++/10.1.0/experimental/ratio
+-rw-r--r-- root root 2121 ./usr/include/c++/10.1.0/experimental/regex
+-rw-r--r-- root root 2471 ./usr/include/c++/10.1.0/experimental/set
+-rw-r--r-- root root 76228 ./usr/include/c++/10.1.0/experimental/socket
+-rw-r--r-- root root 2699 ./usr/include/c++/10.1.0/experimental/source_location
+-rw-r--r-- root root 2920 ./usr/include/c++/10.1.0/experimental/string
+-rw-r--r-- root root 22662 ./usr/include/c++/10.1.0/experimental/string_view
+-rw-r--r-- root root 2045 ./usr/include/c++/10.1.0/experimental/system_error
+-rw-r--r-- root root 5794 ./usr/include/c++/10.1.0/experimental/timer
+-rw-r--r-- root root 2472 ./usr/include/c++/10.1.0/experimental/tuple
+-rw-r--r-- root root 11221 ./usr/include/c++/10.1.0/experimental/type_traits
+-rw-r--r-- root root 2845 ./usr/include/c++/10.1.0/experimental/unordered_map
+-rw-r--r-- root root 2728 ./usr/include/c++/10.1.0/experimental/unordered_set
+-rw-r--r-- root root 1657 ./usr/include/c++/10.1.0/experimental/utility
+-rw-r--r-- root root 2355 ./usr/include/c++/10.1.0/experimental/vector
+drwxr-xr-x root root 4096 ./usr/include/c++/10.1.0/ext
+-rw-r--r-- root root 19255 ./usr/include/c++/10.1.0/ext/algorithm
+-rw-r--r-- root root 3972 ./usr/include/c++/10.1.0/ext/aligned_buffer.h
+-rw-r--r-- root root 6139 ./usr/include/c++/10.1.0/ext/alloc_traits.h
+-rw-r--r-- root root 3477 ./usr/include/c++/10.1.0/ext/atomicity.h
+-rw-r--r-- root root 32193 ./usr/include/c++/10.1.0/ext/bitmap_allocator.h
+-rw-r--r-- root root 4447 ./usr/include/c++/10.1.0/ext/cast.h
+-rw-r--r-- root root 6570 ./usr/include/c++/10.1.0/ext/cmath
+-rw-r--r-- root root 16353 ./usr/include/c++/10.1.0/ext/codecvt_specializations.h
+-rw-r--r-- root root 7542 ./usr/include/c++/10.1.0/ext/concurrence.h
+-rw-r--r-- root root 5881 ./usr/include/c++/10.1.0/ext/debug_allocator.h
+-rw-r--r-- root root 2247 ./usr/include/c++/10.1.0/ext/enc_filebuf.h
+-rw-r--r-- root root 6277 ./usr/include/c++/10.1.0/ext/extptr_allocator.h
+-rw-r--r-- root root 14172 ./usr/include/c++/10.1.0/ext/functional
+-rw-r--r-- root root 17822 ./usr/include/c++/10.1.0/ext/hash_map
+-rw-r--r-- root root 17323 ./usr/include/c++/10.1.0/ext/hash_set
+-rw-r--r-- root root 4031 ./usr/include/c++/10.1.0/ext/iterator
+-rw-r--r-- root root 5696 ./usr/include/c++/10.1.0/ext/malloc_allocator.h
+-rw-r--r-- root root 7173 ./usr/include/c++/10.1.0/ext/memory
+-rw-r--r-- root root 23628 ./usr/include/c++/10.1.0/ext/mt_allocator.h
+-rw-r--r-- root root 5587 ./usr/include/c++/10.1.0/ext/new_allocator.h
+-rw-r--r-- root root 4739 ./usr/include/c++/10.1.0/ext/numeric
+-rw-r--r-- root root 4570 ./usr/include/c++/10.1.0/ext/numeric_traits.h
+drwxr-xr-x root root 4096 ./usr/include/c++/10.1.0/ext/pb_ds
+-rw-r--r-- root root 30110 ./usr/include/c++/10.1.0/ext/pb_ds/assoc_container.hpp
+drwxr-xr-x root root 4096 ./usr/include/c++/10.1.0/ext/pb_ds/detail
+drwxr-xr-x root root 4096 ./usr/include/c++/10.1.0/ext/pb_ds/detail/binary_heap_
+-rw-r--r-- root root 9027 ./usr/include/c++/10.1.0/ext/pb_ds/detail/binary_heap_/binary_heap_.hpp
+-rw-r--r-- root root 4338 ./usr/include/c++/10.1.0/ext/pb_ds/detail/binary_heap_/const_iterator.hpp
+-rw-r--r-- root root 4222 ./usr/include/c++/10.1.0/ext/pb_ds/detail/binary_heap_/constructors_destructor_fn_imps.hpp
+-rw-r--r-- root root 2574 ./usr/include/c++/10.1.0/ext/pb_ds/detail/binary_heap_/debug_fn_imps.hpp
+-rw-r--r-- root root 2802 ./usr/include/c++/10.1.0/ext/pb_ds/detail/binary_heap_/entry_cmp.hpp
+-rw-r--r-- root root 2767 ./usr/include/c++/10.1.0/ext/pb_ds/detail/binary_heap_/entry_pred.hpp
+-rw-r--r-- root root 5537 ./usr/include/c++/10.1.0/ext/pb_ds/detail/binary_heap_/erase_fn_imps.hpp
+-rw-r--r-- root root 2630 ./usr/include/c++/10.1.0/ext/pb_ds/detail/binary_heap_/find_fn_imps.hpp
+-rw-r--r-- root root 2114 ./usr/include/c++/10.1.0/ext/pb_ds/detail/binary_heap_/info_fn_imps.hpp
+-rw-r--r-- root root 5011 ./usr/include/c++/10.1.0/ext/pb_ds/detail/binary_heap_/insert_fn_imps.hpp
+-rw-r--r-- root root 2303 ./usr/include/c++/10.1.0/ext/pb_ds/detail/binary_heap_/iterators_fn_imps.hpp
+-rw-r--r-- root root 4363 ./usr/include/c++/10.1.0/ext/pb_ds/detail/binary_heap_/point_const_iterator.hpp
+-rw-r--r-- root root 1935 ./usr/include/c++/10.1.0/ext/pb_ds/detail/binary_heap_/policy_access_fn_imps.hpp
+-rw-r--r-- root root 6133 ./usr/include/c++/10.1.0/ext/pb_ds/detail/binary_heap_/resize_policy.hpp
+-rw-r--r-- root root 4956 ./usr/include/c++/10.1.0/ext/pb_ds/detail/binary_heap_/split_join_fn_imps.hpp
+-rw-r--r-- root root 2480 ./usr/include/c++/10.1.0/ext/pb_ds/detail/binary_heap_/trace_fn_imps.hpp
+drwxr-xr-x root root 4096 ./usr/include/c++/10.1.0/ext/pb_ds/detail/binomial_heap_
+drwxr-xr-x root root 4096 ./usr/include/c++/10.1.0/ext/pb_ds/detail/binomial_heap_base_
+-rw-r--r-- root root 6185 ./usr/include/c++/10.1.0/ext/pb_ds/detail/binomial_heap_base_/binomial_heap_base_.hpp
+-rw-r--r-- root root 2721 ./usr/include/c++/10.1.0/ext/pb_ds/detail/binomial_heap_base_/constructors_destructor_fn_imps.hpp
+-rw-r--r-- root root 3501 ./usr/include/c++/10.1.0/ext/pb_ds/detail/binomial_heap_base_/debug_fn_imps.hpp
+-rw-r--r-- root root 4515 ./usr/include/c++/10.1.0/ext/pb_ds/detail/binomial_heap_base_/erase_fn_imps.hpp
+-rw-r--r-- root root 2378 ./usr/include/c++/10.1.0/ext/pb_ds/detail/binomial_heap_base_/find_fn_imps.hpp
+-rw-r--r-- root root 5304 ./usr/include/c++/10.1.0/ext/pb_ds/detail/binomial_heap_base_/insert_fn_imps.hpp
+-rw-r--r-- root root 5398 ./usr/include/c++/10.1.0/ext/pb_ds/detail/binomial_heap_base_/split_join_fn_imps.hpp
+-rw-r--r-- root root 3922 ./usr/include/c++/10.1.0/ext/pb_ds/detail/binomial_heap_/binomial_heap_.hpp
+-rw-r--r-- root root 2184 ./usr/include/c++/10.1.0/ext/pb_ds/detail/binomial_heap_/constructors_destructor_fn_imps.hpp
+-rw-r--r-- root root 1930 ./usr/include/c++/10.1.0/ext/pb_ds/detail/binomial_heap_/debug_fn_imps.hpp
+drwxr-xr-x root root 4096 ./usr/include/c++/10.1.0/ext/pb_ds/detail/bin_search_tree_
+-rw-r--r-- root root 12468 ./usr/include/c++/10.1.0/ext/pb_ds/detail/bin_search_tree_/bin_search_tree_.hpp
+-rw-r--r-- root root 5539 ./usr/include/c++/10.1.0/ext/pb_ds/detail/bin_search_tree_/constructors_destructor_fn_imps.hpp
+-rw-r--r-- root root 8104 ./usr/include/c++/10.1.0/ext/pb_ds/detail/bin_search_tree_/debug_fn_imps.hpp
+-rw-r--r-- root root 2952 ./usr/include/c++/10.1.0/ext/pb_ds/detail/bin_search_tree_/erase_fn_imps.hpp
+-rw-r--r-- root root 4712 ./usr/include/c++/10.1.0/ext/pb_ds/detail/bin_search_tree_/find_fn_imps.hpp
+-rw-r--r-- root root 2132 ./usr/include/c++/10.1.0/ext/pb_ds/detail/bin_search_tree_/info_fn_imps.hpp
+-rw-r--r-- root root 5514 ./usr/include/c++/10.1.0/ext/pb_ds/detail/bin_search_tree_/insert_fn_imps.hpp
+-rw-r--r-- root root 3548 ./usr/include/c++/10.1.0/ext/pb_ds/detail/bin_search_tree_/iterators_fn_imps.hpp
+-rw-r--r-- root root 5921 ./usr/include/c++/10.1.0/ext/pb_ds/detail/bin_search_tree_/node_iterators.hpp
+-rw-r--r-- root root 8961 ./usr/include/c++/10.1.0/ext/pb_ds/detail/bin_search_tree_/point_iterators.hpp
+-rw-r--r-- root root 1938 ./usr/include/c++/10.1.0/ext/pb_ds/detail/bin_search_tree_/policy_access_fn_imps.hpp
+-rw-r--r-- root root 2942 ./usr/include/c++/10.1.0/ext/pb_ds/detail/bin_search_tree_/r_erase_fn_imps.hpp
+-rw-r--r-- root root 4223 ./usr/include/c++/10.1.0/ext/pb_ds/detail/bin_search_tree_/rotate_fn_imps.hpp
+-rw-r--r-- root root 4040 ./usr/include/c++/10.1.0/ext/pb_ds/detail/bin_search_tree_/split_join_fn_imps.hpp
+-rw-r--r-- root root 6374 ./usr/include/c++/10.1.0/ext/pb_ds/detail/bin_search_tree_/traits.hpp
+drwxr-xr-x root root 4096 ./usr/include/c++/10.1.0/ext/pb_ds/detail/branch_policy
+-rw-r--r-- root root 4020 ./usr/include/c++/10.1.0/ext/pb_ds/detail/branch_policy/branch_policy.hpp
+-rw-r--r-- root root 2379 ./usr/include/c++/10.1.0/ext/pb_ds/detail/branch_policy/null_node_metadata.hpp
+-rw-r--r-- root root 3254 ./usr/include/c++/10.1.0/ext/pb_ds/detail/branch_policy/traits.hpp
+drwxr-xr-x root root 4096 ./usr/include/c++/10.1.0/ext/pb_ds/detail/cc_hash_table_map_
+-rw-r--r-- root root 20071 ./usr/include/c++/10.1.0/ext/pb_ds/detail/cc_hash_table_map_/cc_ht_map_.hpp
+-rw-r--r-- root root 2798 ./usr/include/c++/10.1.0/ext/pb_ds/detail/cc_hash_table_map_/cmp_fn_imps.hpp
+-rw-r--r-- root root 2874 ./usr/include/c++/10.1.0/ext/pb_ds/detail/cc_hash_table_map_/cond_key_dtor_entry_dealtor.hpp
+-rw-r--r-- root root 5824 ./usr/include/c++/10.1.0/ext/pb_ds/detail/cc_hash_table_map_/constructor_destructor_fn_imps.hpp
+-rw-r--r-- root root 2259 ./usr/include/c++/10.1.0/ext/pb_ds/detail/cc_hash_table_map_/constructor_destructor_no_store_hash_fn_imps.hpp
+-rw-r--r-- root root 2339 ./usr/include/c++/10.1.0/ext/pb_ds/detail/cc_hash_table_map_/constructor_destructor_store_hash_fn_imps.hpp
+-rw-r--r-- root root 2726 ./usr/include/c++/10.1.0/ext/pb_ds/detail/cc_hash_table_map_/debug_fn_imps.hpp
+-rw-r--r-- root root 2033 ./usr/include/c++/10.1.0/ext/pb_ds/detail/cc_hash_table_map_/debug_no_store_hash_fn_imps.hpp
+-rw-r--r-- root root 2181 ./usr/include/c++/10.1.0/ext/pb_ds/detail/cc_hash_table_map_/debug_store_hash_fn_imps.hpp
+-rw-r--r-- root root 2987 ./usr/include/c++/10.1.0/ext/pb_ds/detail/cc_hash_table_map_/entry_list_fn_imps.hpp
+-rw-r--r-- root root 3278 ./usr/include/c++/10.1.0/ext/pb_ds/detail/cc_hash_table_map_/erase_fn_imps.hpp
+-rw-r--r-- root root 3297 ./usr/include/c++/10.1.0/ext/pb_ds/detail/cc_hash_table_map_/erase_no_store_hash_fn_imps.hpp
+-rw-r--r-- root root 3258 ./usr/include/c++/10.1.0/ext/pb_ds/detail/cc_hash_table_map_/erase_store_hash_fn_imps.hpp
+-rw-r--r-- root root 2518 ./usr/include/c++/10.1.0/ext/pb_ds/detail/cc_hash_table_map_/find_fn_imps.hpp
+-rw-r--r-- root root 1779 ./usr/include/c++/10.1.0/ext/pb_ds/detail/cc_hash_table_map_/find_store_hash_fn_imps.hpp
+-rw-r--r-- root root 3163 ./usr/include/c++/10.1.0/ext/pb_ds/detail/cc_hash_table_map_/info_fn_imps.hpp
+-rw-r--r-- root root 1896 ./usr/include/c++/10.1.0/ext/pb_ds/detail/cc_hash_table_map_/insert_fn_imps.hpp
+-rw-r--r-- root root 2651 ./usr/include/c++/10.1.0/ext/pb_ds/detail/cc_hash_table_map_/insert_no_store_hash_fn_imps.hpp
+-rw-r--r-- root root 2707 ./usr/include/c++/10.1.0/ext/pb_ds/detail/cc_hash_table_map_/insert_store_hash_fn_imps.hpp
+-rw-r--r-- root root 2697 ./usr/include/c++/10.1.0/ext/pb_ds/detail/cc_hash_table_map_/iterators_fn_imps.hpp
+-rw-r--r-- root root 2514 ./usr/include/c++/10.1.0/ext/pb_ds/detail/cc_hash_table_map_/policy_access_fn_imps.hpp
+-rw-r--r-- root root 4095 ./usr/include/c++/10.1.0/ext/pb_ds/detail/cc_hash_table_map_/resize_fn_imps.hpp
+-rw-r--r-- root root 2275 ./usr/include/c++/10.1.0/ext/pb_ds/detail/cc_hash_table_map_/resize_no_store_hash_fn_imps.hpp
+-rw-r--r-- root root 2307 ./usr/include/c++/10.1.0/ext/pb_ds/detail/cc_hash_table_map_/resize_store_hash_fn_imps.hpp
+-rw-r--r-- root root 2161 ./usr/include/c++/10.1.0/ext/pb_ds/detail/cc_hash_table_map_/size_fn_imps.hpp
+-rw-r--r-- root root 2396 ./usr/include/c++/10.1.0/ext/pb_ds/detail/cc_hash_table_map_/trace_fn_imps.hpp
+-rw-r--r-- root root 2772 ./usr/include/c++/10.1.0/ext/pb_ds/detail/cond_dealtor.hpp
+-rw-r--r-- root root 13120 ./usr/include/c++/10.1.0/ext/pb_ds/detail/container_base_dispatch.hpp
+-rw-r--r-- root root 8697 ./usr/include/c++/10.1.0/ext/pb_ds/detail/debug_map_base.hpp
+drwxr-xr-x root root 4096 ./usr/include/c++/10.1.0/ext/pb_ds/detail/eq_fn
+-rw-r--r-- root root 2330 ./usr/include/c++/10.1.0/ext/pb_ds/detail/eq_fn/eq_by_less.hpp
+-rw-r--r-- root root 3739 ./usr/include/c++/10.1.0/ext/pb_ds/detail/eq_fn/hash_eq_fn.hpp
+drwxr-xr-x root root 4096 ./usr/include/c++/10.1.0/ext/pb_ds/detail/gp_hash_table_map_
+-rw-r--r-- root root 6639 ./usr/include/c++/10.1.0/ext/pb_ds/detail/gp_hash_table_map_/constructor_destructor_fn_imps.hpp
+-rw-r--r-- root root 2235 ./usr/include/c++/10.1.0/ext/pb_ds/detail/gp_hash_table_map_/constructor_destructor_no_store_hash_fn_imps.hpp
+-rw-r--r-- root root 2302 ./usr/include/c++/10.1.0/ext/pb_ds/detail/gp_hash_table_map_/constructor_destructor_store_hash_fn_imps.hpp
+-rw-r--r-- root root 2207 ./usr/include/c++/10.1.0/ext/pb_ds/detail/gp_hash_table_map_/debug_fn_imps.hpp
+-rw-r--r-- root root 2538 ./usr/include/c++/10.1.0/ext/pb_ds/detail/gp_hash_table_map_/debug_no_store_hash_fn_imps.hpp
+-rw-r--r-- root root 2678 ./usr/include/c++/10.1.0/ext/pb_ds/detail/gp_hash_table_map_/debug_store_hash_fn_imps.hpp
+-rw-r--r-- root root 3237 ./usr/include/c++/10.1.0/ext/pb_ds/detail/gp_hash_table_map_/erase_fn_imps.hpp
+-rw-r--r-- root root 2918 ./usr/include/c++/10.1.0/ext/pb_ds/detail/gp_hash_table_map_/erase_no_store_hash_fn_imps.hpp
+-rw-r--r-- root root 2952 ./usr/include/c++/10.1.0/ext/pb_ds/detail/gp_hash_table_map_/erase_store_hash_fn_imps.hpp
+-rw-r--r-- root root 2511 ./usr/include/c++/10.1.0/ext/pb_ds/detail/gp_hash_table_map_/find_fn_imps.hpp
+-rw-r--r-- root root 1950 ./usr/include/c++/10.1.0/ext/pb_ds/detail/gp_hash_table_map_/find_no_store_hash_fn_imps.hpp
+-rw-r--r-- root root 1780 ./usr/include/c++/10.1.0/ext/pb_ds/detail/gp_hash_table_map_/find_store_hash_fn_imps.hpp
+-rw-r--r-- root root 20441 ./usr/include/c++/10.1.0/ext/pb_ds/detail/gp_hash_table_map_/gp_ht_map_.hpp
+-rw-r--r-- root root 2160 ./usr/include/c++/10.1.0/ext/pb_ds/detail/gp_hash_table_map_/info_fn_imps.hpp
+-rw-r--r-- root root 1896 ./usr/include/c++/10.1.0/ext/pb_ds/detail/gp_hash_table_map_/insert_fn_imps.hpp
+-rw-r--r-- root root 3810 ./usr/include/c++/10.1.0/ext/pb_ds/detail/gp_hash_table_map_/insert_no_store_hash_fn_imps.hpp
+-rw-r--r-- root root 4118 ./usr/include/c++/10.1.0/ext/pb_ds/detail/gp_hash_table_map_/insert_store_hash_fn_imps.hpp
+-rw-r--r-- root root 2652 ./usr/include/c++/10.1.0/ext/pb_ds/detail/gp_hash_table_map_/iterator_fn_imps.hpp
+-rw-r--r-- root root 2693 ./usr/include/c++/10.1.0/ext/pb_ds/detail/gp_hash_table_map_/policy_access_fn_imps.hpp
+-rw-r--r-- root root 4190 ./usr/include/c++/10.1.0/ext/pb_ds/detail/gp_hash_table_map_/resize_fn_imps.hpp
+-rw-r--r-- root root 2651 ./usr/include/c++/10.1.0/ext/pb_ds/detail/gp_hash_table_map_/resize_no_store_hash_fn_imps.hpp
+-rw-r--r-- root root 2684 ./usr/include/c++/10.1.0/ext/pb_ds/detail/gp_hash_table_map_/resize_store_hash_fn_imps.hpp
+-rw-r--r-- root root 2457 ./usr/include/c++/10.1.0/ext/pb_ds/detail/gp_hash_table_map_/trace_fn_imps.hpp
+drwxr-xr-x root root 4096 ./usr/include/c++/10.1.0/ext/pb_ds/detail/hash_fn
+-rw-r--r-- root root 2137 ./usr/include/c++/10.1.0/ext/pb_ds/detail/hash_fn/direct_mask_range_hashing_imp.hpp
+-rw-r--r-- root root 2127 ./usr/include/c++/10.1.0/ext/pb_ds/detail/hash_fn/direct_mod_range_hashing_imp.hpp
+-rw-r--r-- root root 1946 ./usr/include/c++/10.1.0/ext/pb_ds/detail/hash_fn/linear_probe_fn_imp.hpp
+-rw-r--r-- root root 3290 ./usr/include/c++/10.1.0/ext/pb_ds/detail/hash_fn/mask_based_range_hashing.hpp
+-rw-r--r-- root root 2391 ./usr/include/c++/10.1.0/ext/pb_ds/detail/hash_fn/mod_based_range_hashing.hpp
+-rw-r--r-- root root 2009 ./usr/include/c++/10.1.0/ext/pb_ds/detail/hash_fn/probe_fn_base.hpp
+-rw-r--r-- root root 1953 ./usr/include/c++/10.1.0/ext/pb_ds/detail/hash_fn/quadratic_probe_fn_imp.hpp
+-rw-r--r-- root root 10543 ./usr/include/c++/10.1.0/ext/pb_ds/detail/hash_fn/ranged_hash_fn.hpp
+-rw-r--r-- root root 10256 ./usr/include/c++/10.1.0/ext/pb_ds/detail/hash_fn/ranged_probe_fn.hpp
+-rw-r--r-- root root 2291 ./usr/include/c++/10.1.0/ext/pb_ds/detail/hash_fn/sample_probe_fn.hpp
+-rw-r--r-- root root 2469 ./usr/include/c++/10.1.0/ext/pb_ds/detail/hash_fn/sample_ranged_hash_fn.hpp
+-rw-r--r-- root root 2598 ./usr/include/c++/10.1.0/ext/pb_ds/detail/hash_fn/sample_ranged_probe_fn.hpp
+-rw-r--r-- root root 2487 ./usr/include/c++/10.1.0/ext/pb_ds/detail/hash_fn/sample_range_hashing.hpp
+drwxr-xr-x root root 4096 ./usr/include/c++/10.1.0/ext/pb_ds/detail/left_child_next_sibling_heap_
+-rw-r--r-- root root 4924 ./usr/include/c++/10.1.0/ext/pb_ds/detail/left_child_next_sibling_heap_/const_iterator.hpp
+-rw-r--r-- root root 4088 ./usr/include/c++/10.1.0/ext/pb_ds/detail/left_child_next_sibling_heap_/constructors_destructor_fn_imps.hpp
+-rw-r--r-- root root 4108 ./usr/include/c++/10.1.0/ext/pb_ds/detail/left_child_next_sibling_heap_/debug_fn_imps.hpp
+-rw-r--r-- root root 3992 ./usr/include/c++/10.1.0/ext/pb_ds/detail/left_child_next_sibling_heap_/erase_fn_imps.hpp
+-rw-r--r-- root root 2158 ./usr/include/c++/10.1.0/ext/pb_ds/detail/left_child_next_sibling_heap_/info_fn_imps.hpp
+-rw-r--r-- root root 5234 ./usr/include/c++/10.1.0/ext/pb_ds/detail/left_child_next_sibling_heap_/insert_fn_imps.hpp
+-rw-r--r-- root root 2588 ./usr/include/c++/10.1.0/ext/pb_ds/detail/left_child_next_sibling_heap_/iterators_fn_imps.hpp
+-rw-r--r-- root root 8182 ./usr/include/c++/10.1.0/ext/pb_ds/detail/left_child_next_sibling_heap_/left_child_next_sibling_heap_.hpp
+-rw-r--r-- root root 3240 ./usr/include/c++/10.1.0/ext/pb_ds/detail/left_child_next_sibling_heap_/node.hpp
+-rw-r--r-- root root 4397 ./usr/include/c++/10.1.0/ext/pb_ds/detail/left_child_next_sibling_heap_/point_const_iterator.hpp
+-rw-r--r-- root root 1960 ./usr/include/c++/10.1.0/ext/pb_ds/detail/left_child_next_sibling_heap_/policy_access_fn_imps.hpp
+-rw-r--r-- root root 2848 ./usr/include/c++/10.1.0/ext/pb_ds/detail/left_child_next_sibling_heap_/trace_fn_imps.hpp
+drwxr-xr-x root root 4096 ./usr/include/c++/10.1.0/ext/pb_ds/detail/list_update_map_
+-rw-r--r-- root root 3617 ./usr/include/c++/10.1.0/ext/pb_ds/detail/list_update_map_/constructor_destructor_fn_imps.hpp
+-rw-r--r-- root root 2128 ./usr/include/c++/10.1.0/ext/pb_ds/detail/list_update_map_/debug_fn_imps.hpp
+-rw-r--r-- root root 2117 ./usr/include/c++/10.1.0/ext/pb_ds/detail/list_update_map_/entry_metadata_base.hpp
+-rw-r--r-- root root 3515 ./usr/include/c++/10.1.0/ext/pb_ds/detail/list_update_map_/erase_fn_imps.hpp
+-rw-r--r-- root root 2894 ./usr/include/c++/10.1.0/ext/pb_ds/detail/list_update_map_/find_fn_imps.hpp
+-rw-r--r-- root root 2126 ./usr/include/c++/10.1.0/ext/pb_ds/detail/list_update_map_/info_fn_imps.hpp
+-rw-r--r-- root root 3543 ./usr/include/c++/10.1.0/ext/pb_ds/detail/list_update_map_/insert_fn_imps.hpp
+-rw-r--r-- root root 2547 ./usr/include/c++/10.1.0/ext/pb_ds/detail/list_update_map_/iterators_fn_imps.hpp
+-rw-r--r-- root root 10551 ./usr/include/c++/10.1.0/ext/pb_ds/detail/list_update_map_/lu_map_.hpp
+-rw-r--r-- root root 2061 ./usr/include/c++/10.1.0/ext/pb_ds/detail/list_update_map_/trace_fn_imps.hpp
+drwxr-xr-x root root 4096 ./usr/include/c++/10.1.0/ext/pb_ds/detail/list_update_policy
+-rw-r--r-- root root 2850 ./usr/include/c++/10.1.0/ext/pb_ds/detail/list_update_policy/lu_counter_metadata.hpp
+-rw-r--r-- root root 2672 ./usr/include/c++/10.1.0/ext/pb_ds/detail/list_update_policy/sample_update_policy.hpp
+drwxr-xr-x root root 4096 ./usr/include/c++/10.1.0/ext/pb_ds/detail/ov_tree_map_
+-rw-r--r-- root root 6916 ./usr/include/c++/10.1.0/ext/pb_ds/detail/ov_tree_map_/constructors_destructor_fn_imps.hpp
+-rw-r--r-- root root 2851 ./usr/include/c++/10.1.0/ext/pb_ds/detail/ov_tree_map_/debug_fn_imps.hpp
+-rw-r--r-- root root 5014 ./usr/include/c++/10.1.0/ext/pb_ds/detail/ov_tree_map_/erase_fn_imps.hpp
+-rw-r--r-- root root 2136 ./usr/include/c++/10.1.0/ext/pb_ds/detail/ov_tree_map_/info_fn_imps.hpp
+-rw-r--r-- root root 2306 ./usr/include/c++/10.1.0/ext/pb_ds/detail/ov_tree_map_/insert_fn_imps.hpp
+-rw-r--r-- root root 3394 ./usr/include/c++/10.1.0/ext/pb_ds/detail/ov_tree_map_/iterators_fn_imps.hpp
+-rw-r--r-- root root 8638 ./usr/include/c++/10.1.0/ext/pb_ds/detail/ov_tree_map_/node_iterators.hpp
+-rw-r--r-- root root 15509 ./usr/include/c++/10.1.0/ext/pb_ds/detail/ov_tree_map_/ov_tree_map_.hpp
+-rw-r--r-- root root 1920 ./usr/include/c++/10.1.0/ext/pb_ds/detail/ov_tree_map_/policy_access_fn_imps.hpp
+-rw-r--r-- root root 3807 ./usr/include/c++/10.1.0/ext/pb_ds/detail/ov_tree_map_/split_join_fn_imps.hpp
+-rw-r--r-- root root 4562 ./usr/include/c++/10.1.0/ext/pb_ds/detail/ov_tree_map_/traits.hpp
+drwxr-xr-x root root 4096 ./usr/include/c++/10.1.0/ext/pb_ds/detail/pairing_heap_
+-rw-r--r-- root root 2539 ./usr/include/c++/10.1.0/ext/pb_ds/detail/pairing_heap_/constructors_destructor_fn_imps.hpp
+-rw-r--r-- root root 2029 ./usr/include/c++/10.1.0/ext/pb_ds/detail/pairing_heap_/debug_fn_imps.hpp
+-rw-r--r-- root root 7224 ./usr/include/c++/10.1.0/ext/pb_ds/detail/pairing_heap_/erase_fn_imps.hpp
+-rw-r--r-- root root 1970 ./usr/include/c++/10.1.0/ext/pb_ds/detail/pairing_heap_/find_fn_imps.hpp
+-rw-r--r-- root root 2980 ./usr/include/c++/10.1.0/ext/pb_ds/detail/pairing_heap_/insert_fn_imps.hpp
+-rw-r--r-- root root 5500 ./usr/include/c++/10.1.0/ext/pb_ds/detail/pairing_heap_/pairing_heap_.hpp
+-rw-r--r-- root root 3739 ./usr/include/c++/10.1.0/ext/pb_ds/detail/pairing_heap_/split_join_fn_imps.hpp
+drwxr-xr-x root root 4096 ./usr/include/c++/10.1.0/ext/pb_ds/detail/pat_trie_
+-rw-r--r-- root root 5745 ./usr/include/c++/10.1.0/ext/pb_ds/detail/pat_trie_/constructors_destructor_fn_imps.hpp
+-rw-r--r-- root root 3824 ./usr/include/c++/10.1.0/ext/pb_ds/detail/pat_trie_/debug_fn_imps.hpp
+-rw-r--r-- root root 7978 ./usr/include/c++/10.1.0/ext/pb_ds/detail/pat_trie_/erase_fn_imps.hpp
+-rw-r--r-- root root 7908 ./usr/include/c++/10.1.0/ext/pb_ds/detail/pat_trie_/find_fn_imps.hpp
+-rw-r--r-- root root 2108 ./usr/include/c++/10.1.0/ext/pb_ds/detail/pat_trie_/info_fn_imps.hpp
+-rw-r--r-- root root 14508 ./usr/include/c++/10.1.0/ext/pb_ds/detail/pat_trie_/insert_join_fn_imps.hpp
+-rw-r--r-- root root 3513 ./usr/include/c++/10.1.0/ext/pb_ds/detail/pat_trie_/iterators_fn_imps.hpp
+-rw-r--r-- root root 36857 ./usr/include/c++/10.1.0/ext/pb_ds/detail/pat_trie_/pat_trie_base.hpp
+-rw-r--r-- root root 16777 ./usr/include/c++/10.1.0/ext/pb_ds/detail/pat_trie_/pat_trie_.hpp
+-rw-r--r-- root root 2248 ./usr/include/c++/10.1.0/ext/pb_ds/detail/pat_trie_/policy_access_fn_imps.hpp
+-rw-r--r-- root root 2953 ./usr/include/c++/10.1.0/ext/pb_ds/detail/pat_trie_/r_erase_fn_imps.hpp
+-rw-r--r-- root root 4363 ./usr/include/c++/10.1.0/ext/pb_ds/detail/pat_trie_/rotate_fn_imps.hpp
+-rw-r--r-- root root 7758 ./usr/include/c++/10.1.0/ext/pb_ds/detail/pat_trie_/split_fn_imps.hpp
+-rw-r--r-- root root 6718 ./usr/include/c++/10.1.0/ext/pb_ds/detail/pat_trie_/synth_access_traits.hpp
+-rw-r--r-- root root 3434 ./usr/include/c++/10.1.0/ext/pb_ds/detail/pat_trie_/trace_fn_imps.hpp
+-rw-r--r-- root root 6305 ./usr/include/c++/10.1.0/ext/pb_ds/detail/pat_trie_/traits.hpp
+-rw-r--r-- root root 2075 ./usr/include/c++/10.1.0/ext/pb_ds/detail/pat_trie_/update_fn_imps.hpp
+-rw-r--r-- root root 4140 ./usr/include/c++/10.1.0/ext/pb_ds/detail/priority_queue_base_dispatch.hpp
+drwxr-xr-x root root 4096 ./usr/include/c++/10.1.0/ext/pb_ds/detail/rb_tree_map_
+-rw-r--r-- root root 2816 ./usr/include/c++/10.1.0/ext/pb_ds/detail/rb_tree_map_/constructors_destructor_fn_imps.hpp
+-rw-r--r-- root root 2794 ./usr/include/c++/10.1.0/ext/pb_ds/detail/rb_tree_map_/debug_fn_imps.hpp
+-rw-r--r-- root root 7084 ./usr/include/c++/10.1.0/ext/pb_ds/detail/rb_tree_map_/erase_fn_imps.hpp
+-rw-r--r-- root root 1703 ./usr/include/c++/10.1.0/ext/pb_ds/detail/rb_tree_map_/find_fn_imps.hpp
+-rw-r--r-- root root 1874 ./usr/include/c++/10.1.0/ext/pb_ds/detail/rb_tree_map_/info_fn_imps.hpp
+-rw-r--r-- root root 3900 ./usr/include/c++/10.1.0/ext/pb_ds/detail/rb_tree_map_/insert_fn_imps.hpp
+-rw-r--r-- root root 3671 ./usr/include/c++/10.1.0/ext/pb_ds/detail/rb_tree_map_/node.hpp
+-rw-r--r-- root root 7962 ./usr/include/c++/10.1.0/ext/pb_ds/detail/rb_tree_map_/rb_tree_.hpp
+-rw-r--r-- root root 7894 ./usr/include/c++/10.1.0/ext/pb_ds/detail/rb_tree_map_/split_join_fn_imps.hpp
+-rw-r--r-- root root 3283 ./usr/include/c++/10.1.0/ext/pb_ds/detail/rb_tree_map_/traits.hpp
+drwxr-xr-x root root 4096 ./usr/include/c++/10.1.0/ext/pb_ds/detail/rc_binomial_heap_
+-rw-r--r-- root root 2500 ./usr/include/c++/10.1.0/ext/pb_ds/detail/rc_binomial_heap_/constructors_destructor_fn_imps.hpp
+-rw-r--r-- root root 3571 ./usr/include/c++/10.1.0/ext/pb_ds/detail/rc_binomial_heap_/debug_fn_imps.hpp
+-rw-r--r-- root root 2922 ./usr/include/c++/10.1.0/ext/pb_ds/detail/rc_binomial_heap_/erase_fn_imps.hpp
+-rw-r--r-- root root 4270 ./usr/include/c++/10.1.0/ext/pb_ds/detail/rc_binomial_heap_/insert_fn_imps.hpp
+-rw-r--r-- root root 5303 ./usr/include/c++/10.1.0/ext/pb_ds/detail/rc_binomial_heap_/rc_binomial_heap_.hpp
+-rw-r--r-- root root 6199 ./usr/include/c++/10.1.0/ext/pb_ds/detail/rc_binomial_heap_/rc.hpp
+-rw-r--r-- root root 2451 ./usr/include/c++/10.1.0/ext/pb_ds/detail/rc_binomial_heap_/split_join_fn_imps.hpp
+-rw-r--r-- root root 1937 ./usr/include/c++/10.1.0/ext/pb_ds/detail/rc_binomial_heap_/trace_fn_imps.hpp
+drwxr-xr-x root root 4096 ./usr/include/c++/10.1.0/ext/pb_ds/detail/resize_policy
+-rw-r--r-- root root 4932 ./usr/include/c++/10.1.0/ext/pb_ds/detail/resize_policy/cc_hash_max_collision_check_resize_trigger_imp.hpp
+-rw-r--r-- root root 2805 ./usr/include/c++/10.1.0/ext/pb_ds/detail/resize_policy/hash_exponential_size_policy_imp.hpp
+-rw-r--r-- root root 7785 ./usr/include/c++/10.1.0/ext/pb_ds/detail/resize_policy/hash_load_check_resize_trigger_imp.hpp
+-rw-r--r-- root root 2970 ./usr/include/c++/10.1.0/ext/pb_ds/detail/resize_policy/hash_load_check_resize_trigger_size_base.hpp
+-rw-r--r-- root root 6172 ./usr/include/c++/10.1.0/ext/pb_ds/detail/resize_policy/hash_prime_size_policy_imp.hpp
+-rw-r--r-- root root 6316 ./usr/include/c++/10.1.0/ext/pb_ds/detail/resize_policy/hash_standard_resize_policy_imp.hpp
+-rw-r--r-- root root 3578 ./usr/include/c++/10.1.0/ext/pb_ds/detail/resize_policy/sample_resize_policy.hpp
+-rw-r--r-- root root 3914 ./usr/include/c++/10.1.0/ext/pb_ds/detail/resize_policy/sample_resize_trigger.hpp
+-rw-r--r-- root root 2427 ./usr/include/c++/10.1.0/ext/pb_ds/detail/resize_policy/sample_size_policy.hpp
+drwxr-xr-x root root 4096 ./usr/include/c++/10.1.0/ext/pb_ds/detail/splay_tree_
+-rw-r--r-- root root 2880 ./usr/include/c++/10.1.0/ext/pb_ds/detail/splay_tree_/constructors_destructor_fn_imps.hpp
+-rw-r--r-- root root 2496 ./usr/include/c++/10.1.0/ext/pb_ds/detail/splay_tree_/debug_fn_imps.hpp
+-rw-r--r-- root root 4302 ./usr/include/c++/10.1.0/ext/pb_ds/detail/splay_tree_/erase_fn_imps.hpp
+-rw-r--r-- root root 3352 ./usr/include/c++/10.1.0/ext/pb_ds/detail/splay_tree_/find_fn_imps.hpp
+-rw-r--r-- root root 1689 ./usr/include/c++/10.1.0/ext/pb_ds/detail/splay_tree_/info_fn_imps.hpp
+-rw-r--r-- root root 3386 ./usr/include/c++/10.1.0/ext/pb_ds/detail/splay_tree_/insert_fn_imps.hpp
+-rw-r--r-- root root 3587 ./usr/include/c++/10.1.0/ext/pb_ds/detail/splay_tree_/node.hpp
+-rw-r--r-- root root 8082 ./usr/include/c++/10.1.0/ext/pb_ds/detail/splay_tree_/splay_fn_imps.hpp
+-rw-r--r-- root root 9307 ./usr/include/c++/10.1.0/ext/pb_ds/detail/splay_tree_/splay_tree_.hpp
+-rw-r--r-- root root 3667 ./usr/include/c++/10.1.0/ext/pb_ds/detail/splay_tree_/split_join_fn_imps.hpp
+-rw-r--r-- root root 3351 ./usr/include/c++/10.1.0/ext/pb_ds/detail/splay_tree_/traits.hpp
+-rw-r--r-- root root 5031 ./usr/include/c++/10.1.0/ext/pb_ds/detail/standard_policies.hpp
+drwxr-xr-x root root 4096 ./usr/include/c++/10.1.0/ext/pb_ds/detail/thin_heap_
+-rw-r--r-- root root 2979 ./usr/include/c++/10.1.0/ext/pb_ds/detail/thin_heap_/constructors_destructor_fn_imps.hpp
+-rw-r--r-- root root 3899 ./usr/include/c++/10.1.0/ext/pb_ds/detail/thin_heap_/debug_fn_imps.hpp
+-rw-r--r-- root root 6088 ./usr/include/c++/10.1.0/ext/pb_ds/detail/thin_heap_/erase_fn_imps.hpp
+-rw-r--r-- root root 1985 ./usr/include/c++/10.1.0/ext/pb_ds/detail/thin_heap_/find_fn_imps.hpp
+-rw-r--r-- root root 7516 ./usr/include/c++/10.1.0/ext/pb_ds/detail/thin_heap_/insert_fn_imps.hpp
+-rw-r--r-- root root 3188 ./usr/include/c++/10.1.0/ext/pb_ds/detail/thin_heap_/split_join_fn_imps.hpp
+-rw-r--r-- root root 8389 ./usr/include/c++/10.1.0/ext/pb_ds/detail/thin_heap_/thin_heap_.hpp
+-rw-r--r-- root root 1995 ./usr/include/c++/10.1.0/ext/pb_ds/detail/thin_heap_/trace_fn_imps.hpp
+drwxr-xr-x root root 4096 ./usr/include/c++/10.1.0/ext/pb_ds/detail/tree_policy
+-rw-r--r-- root root 3338 ./usr/include/c++/10.1.0/ext/pb_ds/detail/tree_policy/node_metadata_selector.hpp
+-rw-r--r-- root root 3756 ./usr/include/c++/10.1.0/ext/pb_ds/detail/tree_policy/order_statistics_imp.hpp
+-rw-r--r-- root root 2346 ./usr/include/c++/10.1.0/ext/pb_ds/detail/tree_policy/sample_tree_node_update.hpp
+-rw-r--r-- root root 5153 ./usr/include/c++/10.1.0/ext/pb_ds/detail/tree_trace_base.hpp
+drwxr-xr-x root root 4096 ./usr/include/c++/10.1.0/ext/pb_ds/detail/trie_policy
+-rw-r--r-- root root 3338 ./usr/include/c++/10.1.0/ext/pb_ds/detail/trie_policy/node_metadata_selector.hpp
+-rw-r--r-- root root 4734 ./usr/include/c++/10.1.0/ext/pb_ds/detail/trie_policy/order_statistics_imp.hpp
+-rw-r--r-- root root 4544 ./usr/include/c++/10.1.0/ext/pb_ds/detail/trie_policy/prefix_search_node_update_imp.hpp
+-rw-r--r-- root root 2666 ./usr/include/c++/10.1.0/ext/pb_ds/detail/trie_policy/sample_trie_access_traits.hpp
+-rw-r--r-- root root 2348 ./usr/include/c++/10.1.0/ext/pb_ds/detail/trie_policy/sample_trie_node_update.hpp
+-rw-r--r-- root root 5847 ./usr/include/c++/10.1.0/ext/pb_ds/detail/trie_policy/trie_policy_base.hpp
+-rw-r--r-- root root 3084 ./usr/include/c++/10.1.0/ext/pb_ds/detail/trie_policy/trie_string_access_traits_imp.hpp
+-rw-r--r-- root root 6450 ./usr/include/c++/10.1.0/ext/pb_ds/detail/types_traits.hpp
+-rw-r--r-- root root 4318 ./usr/include/c++/10.1.0/ext/pb_ds/detail/type_utils.hpp
+drwxr-xr-x root root 4096 ./usr/include/c++/10.1.0/ext/pb_ds/detail/unordered_iterator
+-rw-r--r-- root root 3517 ./usr/include/c++/10.1.0/ext/pb_ds/detail/unordered_iterator/const_iterator.hpp
+-rw-r--r-- root root 3966 ./usr/include/c++/10.1.0/ext/pb_ds/detail/unordered_iterator/iterator.hpp
+-rw-r--r-- root root 3975 ./usr/include/c++/10.1.0/ext/pb_ds/detail/unordered_iterator/point_const_iterator.hpp
+-rw-r--r-- root root 3742 ./usr/include/c++/10.1.0/ext/pb_ds/detail/unordered_iterator/point_iterator.hpp
+-rw-r--r-- root root 2988 ./usr/include/c++/10.1.0/ext/pb_ds/exception.hpp
+-rw-r--r-- root root 16815 ./usr/include/c++/10.1.0/ext/pb_ds/hash_policy.hpp
+-rw-r--r-- root root 4318 ./usr/include/c++/10.1.0/ext/pb_ds/list_update_policy.hpp
+-rw-r--r-- root root 5444 ./usr/include/c++/10.1.0/ext/pb_ds/priority_queue.hpp
+-rw-r--r-- root root 12268 ./usr/include/c++/10.1.0/ext/pb_ds/tag_and_trait.hpp
+-rw-r--r-- root root 5569 ./usr/include/c++/10.1.0/ext/pb_ds/tree_policy.hpp
+-rw-r--r-- root root 12201 ./usr/include/c++/10.1.0/ext/pb_ds/trie_policy.hpp
+-rw-r--r-- root root 5556 ./usr/include/c++/10.1.0/ext/pod_char_traits.h
+-rw-r--r-- root root 20480 ./usr/include/c++/10.1.0/ext/pointer.h
+-rw-r--r-- root root 8965 ./usr/include/c++/10.1.0/ext/pool_allocator.h
+-rw-r--r-- root root 113176 ./usr/include/c++/10.1.0/ext/random
+-rw-r--r-- root root 60330 ./usr/include/c++/10.1.0/ext/random.tcc
+-rw-r--r-- root root 3278 ./usr/include/c++/10.1.0/ext/rb_tree
+-rw-r--r-- root root 23794 ./usr/include/c++/10.1.0/ext/rc_string_base.h
+-rw-r--r-- root root 88598 ./usr/include/c++/10.1.0/ext/rope
+-rw-r--r-- root root 48860 ./usr/include/c++/10.1.0/ext/ropeimpl.h
+-rw-r--r-- root root 29900 ./usr/include/c++/10.1.0/ext/slist
+-rw-r--r-- root root 16393 ./usr/include/c++/10.1.0/ext/sso_string_base.h
+-rw-r--r-- root root 5670 ./usr/include/c++/10.1.0/ext/stdio_filebuf.h
+-rw-r--r-- root root 8782 ./usr/include/c++/10.1.0/ext/stdio_sync_filebuf.h
+-rw-r--r-- root root 3597 ./usr/include/c++/10.1.0/ext/string_conversions.h
+-rw-r--r-- root root 25222 ./usr/include/c++/10.1.0/ext/throw_allocator.h
+-rw-r--r-- root root 16480 ./usr/include/c++/10.1.0/ext/typelist.h
+-rw-r--r-- root root 5914 ./usr/include/c++/10.1.0/ext/type_traits.h
+-rw-r--r-- root root 3178 ./usr/include/c++/10.1.0/ext/vstring_fwd.h
+-rw-r--r-- root root 110624 ./usr/include/c++/10.1.0/ext/vstring.h
+-rw-r--r-- root root 23614 ./usr/include/c++/10.1.0/ext/vstring.tcc
+-rw-r--r-- root root 5885 ./usr/include/c++/10.1.0/ext/vstring_util.h
+-rw-r--r-- root root 2020 ./usr/include/c++/10.1.0/fenv.h
+-rw-r--r-- root root 1645 ./usr/include/c++/10.1.0/filesystem
+-rw-r--r-- root root 2690 ./usr/include/c++/10.1.0/forward_list
+-rw-r--r-- root root 40559 ./usr/include/c++/10.1.0/fstream
+-rw-r--r-- root root 40189 ./usr/include/c++/10.1.0/functional
+-rw-r--r-- root root 50826 ./usr/include/c++/10.1.0/future
+-rw-r--r-- root root 3038 ./usr/include/c++/10.1.0/initializer_list
+-rw-r--r-- root root 16547 ./usr/include/c++/10.1.0/iomanip
+-rw-r--r-- root root 1601 ./usr/include/c++/10.1.0/ios
+-rw-r--r-- root root 6918 ./usr/include/c++/10.1.0/iosfwd
+-rw-r--r-- root root 2695 ./usr/include/c++/10.1.0/iostream
+-rw-r--r-- root root 32843 ./usr/include/c++/10.1.0/istream
+-rw-r--r-- root root 2751 ./usr/include/c++/10.1.0/iterator
+-rw-r--r-- root root 71808 ./usr/include/c++/10.1.0/limits
+-rw-r--r-- root root 3657 ./usr/include/c++/10.1.0/list
+-rw-r--r-- root root 1488 ./usr/include/c++/10.1.0/locale
+-rw-r--r-- root root 3929 ./usr/include/c++/10.1.0/map
+-rw-r--r-- root root 4573 ./usr/include/c++/10.1.0/math.h
+-rw-r--r-- root root 13663 ./usr/include/c++/10.1.0/memory
+-rw-r--r-- root root 20624 ./usr/include/c++/10.1.0/memory_resource
+-rw-r--r-- root root 19755 ./usr/include/c++/10.1.0/mutex
+-rw-r--r-- root root 8199 ./usr/include/c++/10.1.0/new
+-rw-r--r-- root root 6220 ./usr/include/c++/10.1.0/numbers
+-rw-r--r-- root root 25090 ./usr/include/c++/10.1.0/numeric
+-rw-r--r-- root root 38703 ./usr/include/c++/10.1.0/optional
+-rw-r--r-- root root 24826 ./usr/include/c++/10.1.0/ostream
+drwxr-xr-x root root 4096 ./usr/include/c++/10.1.0/parallel
+-rw-r--r-- root root 18259 ./usr/include/c++/10.1.0/parallel/algobase.h
+-rw-r--r-- root root 80136 ./usr/include/c++/10.1.0/parallel/algo.h
+-rw-r--r-- root root 1381 ./usr/include/c++/10.1.0/parallel/algorithm
+-rw-r--r-- root root 32306 ./usr/include/c++/10.1.0/parallel/algorithmfwd.h
+-rw-r--r-- root root 16952 ./usr/include/c++/10.1.0/parallel/balanced_quicksort.h
+-rw-r--r-- root root 12373 ./usr/include/c++/10.1.0/parallel/base.h
+-rw-r--r-- root root 1586 ./usr/include/c++/10.1.0/parallel/basic_iterator.h
+-rw-r--r-- root root 2235 ./usr/include/c++/10.1.0/parallel/checkers.h
+-rw-r--r-- root root 3790 ./usr/include/c++/10.1.0/parallel/compatibility.h
+-rw-r--r-- root root 2871 ./usr/include/c++/10.1.0/parallel/compiletime_settings.h
+-rw-r--r-- root root 3356 ./usr/include/c++/10.1.0/parallel/equally_split.h
+-rw-r--r-- root root 3543 ./usr/include/c++/10.1.0/parallel/features.h
+-rw-r--r-- root root 13591 ./usr/include/c++/10.1.0/parallel/find.h
+-rw-r--r-- root root 6992 ./usr/include/c++/10.1.0/parallel/find_selectors.h
+-rw-r--r-- root root 3947 ./usr/include/c++/10.1.0/parallel/for_each.h
+-rw-r--r-- root root 10565 ./usr/include/c++/10.1.0/parallel/for_each_selectors.h
+-rw-r--r-- root root 5678 ./usr/include/c++/10.1.0/parallel/iterator.h
+-rw-r--r-- root root 6542 ./usr/include/c++/10.1.0/parallel/list_partition.h
+-rw-r--r-- root root 28592 ./usr/include/c++/10.1.0/parallel/losertree.h
+-rw-r--r-- root root 9578 ./usr/include/c++/10.1.0/parallel/merge.h
+-rw-r--r-- root root 22073 ./usr/include/c++/10.1.0/parallel/multiseq_selection.h
+-rw-r--r-- root root 70545 ./usr/include/c++/10.1.0/parallel/multiway_merge.h
+-rw-r--r-- root root 15281 ./usr/include/c++/10.1.0/parallel/multiway_mergesort.h
+-rw-r--r-- root root 20717 ./usr/include/c++/10.1.0/parallel/numeric
+-rw-r--r-- root root 7506 ./usr/include/c++/10.1.0/parallel/numericfwd.h
+-rw-r--r-- root root 4031 ./usr/include/c++/10.1.0/parallel/omp_loop.h
+-rw-r--r-- root root 4104 ./usr/include/c++/10.1.0/parallel/omp_loop_static.h
+-rw-r--r-- root root 1576 ./usr/include/c++/10.1.0/parallel/parallel.h
+-rw-r--r-- root root 4552 ./usr/include/c++/10.1.0/parallel/par_loop.h
+-rw-r--r-- root root 7474 ./usr/include/c++/10.1.0/parallel/partial_sum.h
+-rw-r--r-- root root 14961 ./usr/include/c++/10.1.0/parallel/partition.h
+-rw-r--r-- root root 5542 ./usr/include/c++/10.1.0/parallel/queue.h
+-rw-r--r-- root root 6126 ./usr/include/c++/10.1.0/parallel/quicksort.h
+-rw-r--r-- root root 4227 ./usr/include/c++/10.1.0/parallel/random_number.h
+-rw-r--r-- root root 18675 ./usr/include/c++/10.1.0/parallel/random_shuffle.h
+-rw-r--r-- root root 5391 ./usr/include/c++/10.1.0/parallel/search.h
+-rw-r--r-- root root 14590 ./usr/include/c++/10.1.0/parallel/set_operations.h
+-rw-r--r-- root root 12462 ./usr/include/c++/10.1.0/parallel/settings.h
+-rw-r--r-- root root 7709 ./usr/include/c++/10.1.0/parallel/sort.h
+-rw-r--r-- root root 5982 ./usr/include/c++/10.1.0/parallel/tags.h
+-rw-r--r-- root root 3716 ./usr/include/c++/10.1.0/parallel/types.h
+-rw-r--r-- root root 6165 ./usr/include/c++/10.1.0/parallel/unique_copy.h
+-rw-r--r-- root root 9610 ./usr/include/c++/10.1.0/parallel/workstealing.h
+drwxr-xr-x root root 4096 ./usr/include/c++/10.1.0/pstl
+-rw-r--r-- root root 68340 ./usr/include/c++/10.1.0/pstl/algorithm_fwd.h
+-rw-r--r-- root root 172216 ./usr/include/c++/10.1.0/pstl/algorithm_impl.h
+-rw-r--r-- root root 3694 ./usr/include/c++/10.1.0/pstl/execution_defs.h
+-rw-r--r-- root root 4834 ./usr/include/c++/10.1.0/pstl/execution_impl.h
+-rw-r--r-- root root 32278 ./usr/include/c++/10.1.0/pstl/glue_algorithm_defs.h
+-rw-r--r-- root root 64874 ./usr/include/c++/10.1.0/pstl/glue_algorithm_impl.h
+-rw-r--r-- root root 1549 ./usr/include/c++/10.1.0/pstl/glue_execution_defs.h
+-rw-r--r-- root root 3865 ./usr/include/c++/10.1.0/pstl/glue_memory_defs.h
+-rw-r--r-- root root 19574 ./usr/include/c++/10.1.0/pstl/glue_memory_impl.h
+-rw-r--r-- root root 6620 ./usr/include/c++/10.1.0/pstl/glue_numeric_defs.h
+-rw-r--r-- root root 11628 ./usr/include/c++/10.1.0/pstl/glue_numeric_impl.h
+-rw-r--r-- root root 1997 ./usr/include/c++/10.1.0/pstl/memory_impl.h
+-rw-r--r-- root root 7929 ./usr/include/c++/10.1.0/pstl/numeric_fwd.h
+-rw-r--r-- root root 18748 ./usr/include/c++/10.1.0/pstl/numeric_impl.h
+-rw-r--r-- root root 718 ./usr/include/c++/10.1.0/pstl/parallel_backend.h
+-rw-r--r-- root root 4084 ./usr/include/c++/10.1.0/pstl/parallel_backend_serial.h
+-rw-r--r-- root root 26379 ./usr/include/c++/10.1.0/pstl/parallel_backend_tbb.h
+-rw-r--r-- root root 5602 ./usr/include/c++/10.1.0/pstl/parallel_backend_utils.h
+-rw-r--r-- root root 4110 ./usr/include/c++/10.1.0/pstl/parallel_impl.h
+-rw-r--r-- root root 6990 ./usr/include/c++/10.1.0/pstl/pstl_config.h
+-rw-r--r-- root root 29256 ./usr/include/c++/10.1.0/pstl/unseq_backend_simd.h
+-rw-r--r-- root root 4606 ./usr/include/c++/10.1.0/pstl/utils.h
+-rw-r--r-- root root 2467 ./usr/include/c++/10.1.0/queue
+-rw-r--r-- root root 1692 ./usr/include/c++/10.1.0/random
+-rw-r--r-- root root 97030 ./usr/include/c++/10.1.0/ranges
+-rw-r--r-- root root 20107 ./usr/include/c++/10.1.0/ratio
+-rw-r--r-- root root 2648 ./usr/include/c++/10.1.0/regex
+-rw-r--r-- root root 17459 ./usr/include/c++/10.1.0/scoped_allocator
+-rw-r--r-- root root 3799 ./usr/include/c++/10.1.0/set
+-rw-r--r-- root root 24417 ./usr/include/c++/10.1.0/shared_mutex
+-rw-r--r-- root root 13251 ./usr/include/c++/10.1.0/span
+-rw-r--r-- root root 28524 ./usr/include/c++/10.1.0/sstream
+-rw-r--r-- root root 2391 ./usr/include/c++/10.1.0/stack
+-rw-r--r-- root root 9877 ./usr/include/c++/10.1.0/stdexcept
+-rw-r--r-- root root 2248 ./usr/include/c++/10.1.0/stdlib.h
+-rw-r--r-- root root 16254 ./usr/include/c++/10.1.0/stop_token
+-rw-r--r-- root root 30017 ./usr/include/c++/10.1.0/streambuf
+-rw-r--r-- root root 4645 ./usr/include/c++/10.1.0/string
+-rw-r--r-- root root 24878 ./usr/include/c++/10.1.0/string_view
+-rw-r--r-- root root 14871 ./usr/include/c++/10.1.0/system_error
+-rw-r--r-- root root 1360 ./usr/include/c++/10.1.0/tgmath.h
+-rw-r--r-- root root 13968 ./usr/include/c++/10.1.0/thread
+drwxr-xr-x root root 4096 ./usr/include/c++/10.1.0/tr1
+-rw-r--r-- root root 6983 ./usr/include/c++/10.1.0/tr1/array
+-rw-r--r-- root root 22937 ./usr/include/c++/10.1.0/tr1/bessel_function.tcc
+-rw-r--r-- root root 5995 ./usr/include/c++/10.1.0/tr1/beta_function.tcc
+-rw-r--r-- root root 1255 ./usr/include/c++/10.1.0/tr1/ccomplex
+-rw-r--r-- root root 1478 ./usr/include/c++/10.1.0/tr1/cctype
+-rw-r--r-- root root 2070 ./usr/include/c++/10.1.0/tr1/cfenv
+-rw-r--r-- root root 1380 ./usr/include/c++/10.1.0/tr1/cfloat
+-rw-r--r-- root root 2322 ./usr/include/c++/10.1.0/tr1/cinttypes
+-rw-r--r-- root root 1454 ./usr/include/c++/10.1.0/tr1/climits
+-rw-r--r-- root root 43874 ./usr/include/c++/10.1.0/tr1/cmath
+-rw-r--r-- root root 12384 ./usr/include/c++/10.1.0/tr1/complex
+-rw-r--r-- root root 1261 ./usr/include/c++/10.1.0/tr1/complex.h
+-rw-r--r-- root root 1246 ./usr/include/c++/10.1.0/tr1/cstdarg
+-rw-r--r-- root root 1344 ./usr/include/c++/10.1.0/tr1/cstdbool
+-rw-r--r-- root root 2687 ./usr/include/c++/10.1.0/tr1/cstdint
+-rw-r--r-- root root 1548 ./usr/include/c++/10.1.0/tr1/cstdio
+-rw-r--r-- root root 1862 ./usr/include/c++/10.1.0/tr1/cstdlib
+-rw-r--r-- root root 1248 ./usr/include/c++/10.1.0/tr1/ctgmath
+-rw-r--r-- root root 1234 ./usr/include/c++/10.1.0/tr1/ctime
+-rw-r--r-- root root 1209 ./usr/include/c++/10.1.0/tr1/ctype.h
+-rw-r--r-- root root 1784 ./usr/include/c++/10.1.0/tr1/cwchar
+-rw-r--r-- root root 1525 ./usr/include/c++/10.1.0/tr1/cwctype
+-rw-r--r-- root root 27644 ./usr/include/c++/10.1.0/tr1/ell_integral.tcc
+-rw-r--r-- root root 16013 ./usr/include/c++/10.1.0/tr1/exp_integral.tcc
+-rw-r--r-- root root 1204 ./usr/include/c++/10.1.0/tr1/fenv.h
+-rw-r--r-- root root 1209 ./usr/include/c++/10.1.0/tr1/float.h
+-rw-r--r-- root root 70545 ./usr/include/c++/10.1.0/tr1/functional
+-rw-r--r-- root root 6043 ./usr/include/c++/10.1.0/tr1/functional_hash.h
+-rw-r--r-- root root 14682 ./usr/include/c++/10.1.0/tr1/gamma.tcc
+-rw-r--r-- root root 41995 ./usr/include/c++/10.1.0/tr1/hashtable.h
+-rw-r--r-- root root 25086 ./usr/include/c++/10.1.0/tr1/hashtable_policy.h
+-rw-r--r-- root root 28066 ./usr/include/c++/10.1.0/tr1/hypergeometric.tcc
+-rw-r--r-- root root 1267 ./usr/include/c++/10.1.0/tr1/inttypes.h
+-rw-r--r-- root root 10652 ./usr/include/c++/10.1.0/tr1/legendre_function.tcc
+-rw-r--r-- root root 1214 ./usr/include/c++/10.1.0/tr1/limits.h
+-rw-r--r-- root root 4553 ./usr/include/c++/10.1.0/tr1/math.h
+-rw-r--r-- root root 1791 ./usr/include/c++/10.1.0/tr1/memory
+-rw-r--r-- root root 16324 ./usr/include/c++/10.1.0/tr1/modified_bessel_func.tcc
+-rw-r--r-- root root 3925 ./usr/include/c++/10.1.0/tr1/poly_hermite.tcc
+-rw-r--r-- root root 11676 ./usr/include/c++/10.1.0/tr1/poly_laguerre.tcc
+-rw-r--r-- root root 1589 ./usr/include/c++/10.1.0/tr1/random
+-rw-r--r-- root root 73123 ./usr/include/c++/10.1.0/tr1/random.h
+-rw-r--r-- root root 53927 ./usr/include/c++/10.1.0/tr1/random.tcc
+-rw-r--r-- root root 92899 ./usr/include/c++/10.1.0/tr1/regex
+-rw-r--r-- root root 14067 ./usr/include/c++/10.1.0/tr1/riemann_zeta.tcc
+-rw-r--r-- root root 32608 ./usr/include/c++/10.1.0/tr1/shared_ptr.h
+-rw-r--r-- root root 5055 ./usr/include/c++/10.1.0/tr1/special_function_util.h
+-rw-r--r-- root root 1214 ./usr/include/c++/10.1.0/tr1/stdarg.h
+-rw-r--r-- root root 1219 ./usr/include/c++/10.1.0/tr1/stdbool.h
+-rw-r--r-- root root 1214 ./usr/include/c++/10.1.0/tr1/stdint.h
+-rw-r--r-- root root 1209 ./usr/include/c++/10.1.0/tr1/stdio.h
+-rw-r--r-- root root 1487 ./usr/include/c++/10.1.0/tr1/stdlib.h
+-rw-r--r-- root root 1255 ./usr/include/c++/10.1.0/tr1/tgmath.h
+-rw-r--r-- root root 12119 ./usr/include/c++/10.1.0/tr1/tuple
+-rw-r--r-- root root 19019 ./usr/include/c++/10.1.0/tr1/type_traits
+-rw-r--r-- root root 1574 ./usr/include/c++/10.1.0/tr1/unordered_map
+-rw-r--r-- root root 10216 ./usr/include/c++/10.1.0/tr1/unordered_map.h
+-rw-r--r-- root root 1574 ./usr/include/c++/10.1.0/tr1/unordered_set
+-rw-r--r-- root root 9540 ./usr/include/c++/10.1.0/tr1/unordered_set.h
+-rw-r--r-- root root 3225 ./usr/include/c++/10.1.0/tr1/utility
+-rw-r--r-- root root 1249 ./usr/include/c++/10.1.0/tr1/wchar.h
+-rw-r--r-- root root 1255 ./usr/include/c++/10.1.0/tr1/wctype.h
+drwxr-xr-x root root 4096 ./usr/include/c++/10.1.0/tr2
+-rw-r--r-- root root 7370 ./usr/include/c++/10.1.0/tr2/bool_set
+-rw-r--r-- root root 8319 ./usr/include/c++/10.1.0/tr2/bool_set.tcc
+-rw-r--r-- root root 34336 ./usr/include/c++/10.1.0/tr2/dynamic_bitset
+-rw-r--r-- root root 8925 ./usr/include/c++/10.1.0/tr2/dynamic_bitset.tcc
+-rw-r--r-- root root 2130 ./usr/include/c++/10.1.0/tr2/ratio
+-rw-r--r-- root root 2699 ./usr/include/c++/10.1.0/tr2/type_traits
+-rw-r--r-- root root 60078 ./usr/include/c++/10.1.0/tuple
+-rw-r--r-- root root 3512 ./usr/include/c++/10.1.0/typeindex
+-rw-r--r-- root root 7746 ./usr/include/c++/10.1.0/typeinfo
+-rw-r--r-- root root 103356 ./usr/include/c++/10.1.0/type_traits
+-rw-r--r-- root root 3467 ./usr/include/c++/10.1.0/unordered_map
+-rw-r--r-- root root 3340 ./usr/include/c++/10.1.0/unordered_set
+-rw-r--r-- root root 14820 ./usr/include/c++/10.1.0/utility
+-rw-r--r-- root root 40362 ./usr/include/c++/10.1.0/valarray
+-rw-r--r-- root root 60701 ./usr/include/c++/10.1.0/variant
+-rw-r--r-- root root 4275 ./usr/include/c++/10.1.0/vector
+-rw-r--r-- root root 7706 ./usr/include/c++/10.1.0/version
+drwxr-xr-x root root 4096 ./usr/include/c++/10.1.0/x86_64-poky-linux
+drwxr-xr-x root root 4096 ./usr/include/c++/10.1.0/x86_64-poky-linux/bits
+-rw-r--r-- root root 1518 ./usr/include/c++/10.1.0/x86_64-poky-linux/bits/atomic_word.h
+-rw-r--r-- root root 3575 ./usr/include/c++/10.1.0/x86_64-poky-linux/bits/basic_file.h
+-rw-r--r-- root root 1979 ./usr/include/c++/10.1.0/x86_64-poky-linux/bits/c++allocator.h
+-rw-r--r-- root root 61947 ./usr/include/c++/10.1.0/x86_64-poky-linux/bits/c++config.h
+-rw-r--r-- root root 1608 ./usr/include/c++/10.1.0/x86_64-poky-linux/bits/c++io.h
+-rw-r--r-- root root 3307 ./usr/include/c++/10.1.0/x86_64-poky-linux/bits/c++locale.h
+-rw-r--r-- root root 1333 ./usr/include/c++/10.1.0/x86_64-poky-linux/bits/cpu_defines.h
+-rw-r--r-- root root 2316 ./usr/include/c++/10.1.0/x86_64-poky-linux/bits/ctype_base.h
+-rw-r--r-- root root 2284 ./usr/include/c++/10.1.0/x86_64-poky-linux/bits/ctype_inline.h
+-rw-r--r-- root root 2096 ./usr/include/c++/10.1.0/x86_64-poky-linux/bits/cxxabi_tweaks.h
+-rw-r--r-- root root 5175 ./usr/include/c++/10.1.0/x86_64-poky-linux/bits/error_constants.h
+-rw-r--r-- root root 2628 ./usr/include/c++/10.1.0/x86_64-poky-linux/bits/extc++.h
+-rw-r--r-- root root 24260 ./usr/include/c++/10.1.0/x86_64-poky-linux/bits/gthr-default.h
+-rw-r--r-- root root 5608 ./usr/include/c++/10.1.0/x86_64-poky-linux/bits/gthr.h
+-rw-r--r-- root root 24260 ./usr/include/c++/10.1.0/x86_64-poky-linux/bits/gthr-posix.h
+-rw-r--r-- root root 6808 ./usr/include/c++/10.1.0/x86_64-poky-linux/bits/gthr-single.h
+-rw-r--r-- root root 4516 ./usr/include/c++/10.1.0/x86_64-poky-linux/bits/messages_members.h
+-rw-r--r-- root root 6194 ./usr/include/c++/10.1.0/x86_64-poky-linux/bits/opt_random.h
+-rw-r--r-- root root 2007 ./usr/include/c++/10.1.0/x86_64-poky-linux/bits/os_defines.h
+-rw-r--r-- root root 3286 ./usr/include/c++/10.1.0/x86_64-poky-linux/bits/stdc++.h
+-rw-r--r-- root root 1741 ./usr/include/c++/10.1.0/x86_64-poky-linux/bits/stdtr1c++.h
+-rw-r--r-- root root 2924 ./usr/include/c++/10.1.0/x86_64-poky-linux/bits/time_members.h
+drwxr-xr-x root root 4096 ./usr/include/c++/10.1.0/x86_64-poky-linux/ext
+-rw-r--r-- root root 4756 ./usr/include/c++/10.1.0/x86_64-poky-linux/ext/opt_random.h
+drwxr-xr-x root root 4096 ./usr/include/cairo
+-rw-r--r-- root root 8698 ./usr/include/cairo/cairo-deprecated.h
+-rw-r--r-- root root 1460 ./usr/include/cairo/cairo-features.h
+-rw-r--r-- root root 3721 ./usr/include/cairo/cairo-ft.h
+-rw-r--r-- root root 5117 ./usr/include/cairo/cairo-gl.h
+-rw-r--r-- root root 6452 ./usr/include/cairo/cairo-gobject.h
+-rw-r--r-- root root 110955 ./usr/include/cairo/cairo.h
+-rw-r--r-- root root 5617 ./usr/include/cairo/cairo-pdf.h
+-rw-r--r-- root root 3632 ./usr/include/cairo/cairo-ps.h
+-rw-r--r-- root root 3072 ./usr/include/cairo/cairo-script.h
+-rw-r--r-- root root 4059 ./usr/include/cairo/cairo-script-interpreter.h
+-rw-r--r-- root root 4504 ./usr/include/cairo/cairo-svg.h
+-rw-r--r-- root root 2173 ./usr/include/cairo/cairo-tee.h
+-rw-r--r-- root root 148 ./usr/include/cairo/cairo-version.h
+-rw-r--r-- root root 3775 ./usr/include/cairo/cairo-xcb.h
+-rw-r--r-- root root 3577 ./usr/include/cairo/cairo-xlib.h
+-rw-r--r-- root root 2436 ./usr/include/cairo/cairo-xlib-xrender.h
+-rw-r--r-- root root 3198 ./usr/include/cap-ng.h
+-rw-r--r-- root root 2118 ./usr/include/com_err.h
+-rw-r--r-- root root 7164 ./usr/include/complex.h
+-rw-r--r-- root root 2268 ./usr/include/cpio.h
+-rw-r--r-- root root 11160 ./usr/include/crypt.h
+-rw-r--r-- root root 19025 ./usr/include/ctf-api.h
+-rw-r--r-- root root 25153 ./usr/include/ctf.h
+-rw-r--r-- root root 10969 ./usr/include/ctype.h
+-rw-r--r-- root root 100249 ./usr/include/curses-64.h
+-rw-r--r-- root root 6878 ./usr/include/cursesapp.h
+-rw-r--r-- root root 28021 ./usr/include/cursesf.h
+-rw-r--r-- root root 512 ./usr/include/curses.h
+-rw-r--r-- root root 19874 ./usr/include/cursesm.h
+-rw-r--r-- root root 8722 ./usr/include/cursesp.h
+-rw-r--r-- root root 49871 ./usr/include/cursesw.h
+-rw-r--r-- root root 7407 ./usr/include/cursslk.h
+drwxr-xr-x root root 4096 ./usr/include/db51
+-rw-r--r-- root root 49057 ./usr/include/db51/db_cxx.h
+-rw-r--r-- root root 123105 ./usr/include/db51/db.h
+lrwxrwxrwx root root 13 ./usr/include/db_cxx.h -> db51/db_cxx.h
+lrwxrwxrwx root root 9 ./usr/include/db.h -> db51/db.h
+-rw-r--r-- root root 1414 ./usr/include/dbm.h
+drwxr-xr-x root root 4096 ./usr/include/dbus-1.0
+drwxr-xr-x root root 4096 ./usr/include/dbus-1.0/dbus
+-rw-r--r-- root root 2812 ./usr/include/dbus-1.0/dbus/dbus-address.h
+-rw-r--r-- root root 3472 ./usr/include/dbus-1.0/dbus/dbus-bus.h
+-rw-r--r-- root root 27020 ./usr/include/dbus-1.0/dbus/dbus-connection.h
+-rw-r--r-- root root 2911 ./usr/include/dbus-1.0/dbus/dbus-errors.h
+-rw-r--r-- root root 3963 ./usr/include/dbus-1.0/dbus/dbus.h
+-rw-r--r-- root root 6757 ./usr/include/dbus-1.0/dbus/dbus-macros.h
+-rw-r--r-- root root 1963 ./usr/include/dbus-1.0/dbus/dbus-memory.h
+-rw-r--r-- root root 15005 ./usr/include/dbus-1.0/dbus/dbus-message.h
+-rw-r--r-- root root 1813 ./usr/include/dbus-1.0/dbus/dbus-misc.h
+-rw-r--r-- root root 3811 ./usr/include/dbus-1.0/dbus/dbus-pending-call.h
+-rw-r--r-- root root 23642 ./usr/include/dbus-1.0/dbus/dbus-protocol.h
+-rw-r--r-- root root 4045 ./usr/include/dbus-1.0/dbus/dbus-python.h
+-rw-r--r-- root root 5414 ./usr/include/dbus-1.0/dbus/dbus-server.h
+-rw-r--r-- root root 5394 ./usr/include/dbus-1.0/dbus/dbus-shared.h
+-rw-r--r-- root root 3049 ./usr/include/dbus-1.0/dbus/dbus-signature.h
+-rw-r--r-- root root 2359 ./usr/include/dbus-1.0/dbus/dbus-syntax.h
+-rw-r--r-- root root 8507 ./usr/include/dbus-1.0/dbus/dbus-threads.h
+-rw-r--r-- root root 4145 ./usr/include/dbus-1.0/dbus/dbus-types.h
+-rw-r--r-- root root 3332 ./usr/include/diagnostics.h
+-rw-r--r-- root root 12515 ./usr/include/dirent.h
+-rw-r--r-- root root 16687 ./usr/include/dis-asm.h
+-rw-r--r-- root root 7479 ./usr/include/dlfcn.h
+drwxr-xr-x root root 4096 ./usr/include/drm
+-rw-r--r-- root root 31894 ./usr/include/drm/amdgpu_drm.h
+-rw-r--r-- root root 1212 ./usr/include/drm/armada_drm.h
+-rw-r--r-- root root 32817 ./usr/include/drm/drm_fourcc.h
+-rw-r--r-- root root 32129 ./usr/include/drm/drm.h
+-rw-r--r-- root root 28604 ./usr/include/drm/drm_mode.h
+-rw-r--r-- root root 2782 ./usr/include/drm/drm_sarea.h
+-rw-r--r-- root root 11822 ./usr/include/drm/etnaviv_drm.h
+-rw-r--r-- root root 11132 ./usr/include/drm/exynos_drm.h
+-rw-r--r-- root root 10061 ./usr/include/drm/i810_drm.h
+-rw-r--r-- root root 70507 ./usr/include/drm/i915_drm.h
+-rw-r--r-- root root 4817 ./usr/include/drm/lima_drm.h
+-rw-r--r-- root root 13010 ./usr/include/drm/mga_drm.h
+-rw-r--r-- root root 13230 ./usr/include/drm/msm_drm.h
+-rw-r--r-- root root 6560 ./usr/include/drm/nouveau_drm.h
+-rw-r--r-- root root 4141 ./usr/include/drm/omap_drm.h
+-rw-r--r-- root root 7346 ./usr/include/drm/panfrost_drm.h
+-rw-r--r-- root root 4131 ./usr/include/drm/qxl_drm.h
+-rw-r--r-- root root 10000 ./usr/include/drm/r128_drm.h
+-rw-r--r-- root root 38236 ./usr/include/drm/radeon_drm.h
+-rw-r--r-- root root 7170 ./usr/include/drm/savage_drm.h
+-rw-r--r-- root root 2637 ./usr/include/drm/sis_drm.h
+-rw-r--r-- root root 14877 ./usr/include/drm/tegra_drm.h
+-rw-r--r-- root root 8671 ./usr/include/drm/v3d_drm.h
+-rw-r--r-- root root 14457 ./usr/include/drm/vc4_drm.h
+-rw-r--r-- root root 1971 ./usr/include/drm/vgem_drm.h
+-rw-r--r-- root root 8345 ./usr/include/drm/via_drm.h
+-rw-r--r-- root root 5010 ./usr/include/drm/virtgpu_drm.h
+-rw-r--r-- root root 35392 ./usr/include/drm/vmwgfx_drm.h
+-rw-r--r-- root root 31014 ./usr/include/dwarf.h
+drwxr-xr-x root root 4096 ./usr/include/e2p
+-rw-r--r-- root root 3252 ./usr/include/e2p/e2p.h
+-rw-r--r-- root root 180099 ./usr/include/elf.h
+drwxr-xr-x root root 4096 ./usr/include/elfutils
+-rw-r--r-- root root 3947 ./usr/include/elfutils/elf-knowledge.h
+-rw-r--r-- root root 41860 ./usr/include/elfutils/known-dwarf.h
+-rw-r--r-- root root 7098 ./usr/include/elfutils/libasm.h
+-rw-r--r-- root root 6452 ./usr/include/elfutils/libdwelf.h
+-rw-r--r-- root root 37558 ./usr/include/elfutils/libdwfl.h
+-rw-r--r-- root root 44920 ./usr/include/elfutils/libdw.h
+-rw-r--r-- root root 1274 ./usr/include/elfutils/version.h
+-rw-r--r-- root root 2299 ./usr/include/endian.h
+-rw-r--r-- root root 2867 ./usr/include/envz.h
+-rw-r--r-- root root 2267 ./usr/include/err.h
+-rw-r--r-- root root 1679 ./usr/include/errno.h
+-rw-r--r-- root root 2282 ./usr/include/error.h
+drwxr-xr-x root root 4096 ./usr/include/et
+-rw-r--r-- root root 2118 ./usr/include/et/com_err.h
+-rw-r--r-- root root 2969 ./usr/include/eti.h
+-rw-r--r-- root root 9775 ./usr/include/etip.h
+-rw-r--r-- root root 1523 ./usr/include/execinfo.h
+-rw-r--r-- root root 3830 ./usr/include/expat_config.h
+-rw-r--r-- root root 5528 ./usr/include/expat_external.h
+-rw-r--r-- root root 41473 ./usr/include/expat.h
+drwxr-xr-x root root 4096 ./usr/include/ext2fs
+-rw-r--r-- root root 22148 ./usr/include/ext2fs/bitops.h
+-rw-r--r-- root root 11847 ./usr/include/ext2fs/ext2_err.h
+-rw-r--r-- root root 2644 ./usr/include/ext2fs/ext2_ext_attr.h
+-rw-r--r-- root root 42075 ./usr/include/ext2fs/ext2_fs.h
+-rw-r--r-- root root 72208 ./usr/include/ext2fs/ext2fs.h
+-rw-r--r-- root root 5391 ./usr/include/ext2fs/ext2_io.h
+-rw-r--r-- root root 4212 ./usr/include/ext2fs/ext2_types-64.h
+-rw-r--r-- root root 556 ./usr/include/ext2fs/ext2_types.h
+-rw-r--r-- root root 4558 ./usr/include/ext2fs/ext3_extents.h
+-rw-r--r-- root root 1179 ./usr/include/ext2fs/hashmap.h
+-rw-r--r-- root root 2588 ./usr/include/ext2fs/qcow2.h
+-rw-r--r-- root root 8871 ./usr/include/ext2fs/tdb.h
+-rw-r--r-- root root 11026 ./usr/include/fcntl.h
+-rw-r--r-- root root 17235 ./usr/include/features.h
+-rw-r--r-- root root 5874 ./usr/include/fenv.h
+-rw-r--r-- root root 13934 ./usr/include/ffi-64.h
+-rw-r--r-- root root 500 ./usr/include/ffi.h
+-rw-r--r-- root root 4343 ./usr/include/ffitarget.h
+drwxr-xr-x root root 4096 ./usr/include/finclude
+-rw-r--r-- root root 2384 ./usr/include/finclude/math-vector-fortran.h
+-rw-r--r-- root root 6893 ./usr/include/FlexLexer.h
+-rw-r--r-- root root 3240 ./usr/include/fmtmsg.h
+-rw-r--r-- root root 2296 ./usr/include/fnmatch.h
+drwxr-xr-x root root 4096 ./usr/include/fontconfig
+-rw-r--r-- root root 1958 ./usr/include/fontconfig/fcfreetype.h
+-rw-r--r-- root root 4489 ./usr/include/fontconfig/fcprivate.h
+-rw-r--r-- root root 28461 ./usr/include/fontconfig/fontconfig.h
+-rw-r--r-- root root 18811 ./usr/include/form.h
+-rw-r--r-- root root 3584 ./usr/include/fpu_control.h
+drwxr-xr-x root root 4096 ./usr/include/freedreno
+-rw-r--r-- root root 4992 ./usr/include/freedreno/freedreno_drmif.h
+-rw-r--r-- root root 4963 ./usr/include/freedreno/freedreno_ringbuffer.h
+drwxr-xr-x root root 4096 ./usr/include/freetype2
+drwxr-xr-x root root 4096 ./usr/include/freetype2/freetype
+drwxr-xr-x root root 4096 ./usr/include/freetype2/freetype/config
+-rw-r--r-- root root 19859 ./usr/include/freetype2/freetype/config/ftconfig-64.h
+-rw-r--r-- root root 624 ./usr/include/freetype2/freetype/config/ftconfig.h
+-rw-r--r-- root root 23228 ./usr/include/freetype2/freetype/config/ftheader.h
+-rw-r--r-- root root 1056 ./usr/include/freetype2/freetype/config/ftmodule.h
+-rw-r--r-- root root 39330 ./usr/include/freetype2/freetype/config/ftoption.h
+-rw-r--r-- root root 4307 ./usr/include/freetype2/freetype/config/ftstdlib.h
+-rw-r--r-- root root 165664 ./usr/include/freetype2/freetype/freetype.h
+-rw-r--r-- root root 5479 ./usr/include/freetype2/freetype/ftadvanc.h
+-rw-r--r-- root root 2652 ./usr/include/freetype2/freetype/ftbbox.h
+-rw-r--r-- root root 5336 ./usr/include/freetype2/freetype/ftbdf.h
+-rw-r--r-- root root 9055 ./usr/include/freetype2/freetype/ftbitmap.h
+-rw-r--r-- root root 2745 ./usr/include/freetype2/freetype/ftbzip2.h
+-rw-r--r-- root root 33870 ./usr/include/freetype2/freetype/ftcache.h
+-rw-r--r-- root root 2510 ./usr/include/freetype2/freetype/ftchapters.h
+-rw-r--r-- root root 4036 ./usr/include/freetype2/freetype/ftcid.h
+-rw-r--r-- root root 8927 ./usr/include/freetype2/freetype/ftcolor.h
+-rw-r--r-- root root 47451 ./usr/include/freetype2/freetype/ftdriver.h
+-rw-r--r-- root root 12336 ./usr/include/freetype2/freetype/fterrdef.h
+-rw-r--r-- root root 8904 ./usr/include/freetype2/freetype/fterrors.h
+-rw-r--r-- root root 2227 ./usr/include/freetype2/freetype/ftfntfmt.h
+-rw-r--r-- root root 4152 ./usr/include/freetype2/freetype/ftgasp.h
+-rw-r--r-- root root 18505 ./usr/include/freetype2/freetype/ftglyph.h
+-rw-r--r-- root root 10639 ./usr/include/freetype2/freetype/ftgxval.h
+-rw-r--r-- root root 4170 ./usr/include/freetype2/freetype/ftgzip.h
+-rw-r--r-- root root 39169 ./usr/include/freetype2/freetype/ftimage.h
+-rw-r--r-- root root 10322 ./usr/include/freetype2/freetype/ftincrem.h
+-rw-r--r-- root root 11969 ./usr/include/freetype2/freetype/ftlcdfil.h
+-rw-r--r-- root root 7114 ./usr/include/freetype2/freetype/ftlist.h
+-rw-r--r-- root root 2726 ./usr/include/freetype2/freetype/ftlzw.h
+-rw-r--r-- root root 7793 ./usr/include/freetype2/freetype/ftmac.h
+-rw-r--r-- root root 21811 ./usr/include/freetype2/freetype/ftmm.h
+-rw-r--r-- root root 21820 ./usr/include/freetype2/freetype/ftmodapi.h
+-rw-r--r-- root root 6598 ./usr/include/freetype2/freetype/ftmoderr.h
+-rw-r--r-- root root 5360 ./usr/include/freetype2/freetype/ftotval.h
+-rw-r--r-- root root 17476 ./usr/include/freetype2/freetype/ftoutln.h
+-rw-r--r-- root root 5606 ./usr/include/freetype2/freetype/ftparams.h
+-rw-r--r-- root root 4924 ./usr/include/freetype2/freetype/ftpfr.h
+-rw-r--r-- root root 6627 ./usr/include/freetype2/freetype/ftrender.h
+-rw-r--r-- root root 4302 ./usr/include/freetype2/freetype/ftsizes.h
+-rw-r--r-- root root 7742 ./usr/include/freetype2/freetype/ftsnames.h
+-rw-r--r-- root root 21778 ./usr/include/freetype2/freetype/ftstroke.h
+-rw-r--r-- root root 3376 ./usr/include/freetype2/freetype/ftsynth.h
+-rw-r--r-- root root 8540 ./usr/include/freetype2/freetype/ftsystem.h
+-rw-r--r-- root root 7403 ./usr/include/freetype2/freetype/fttrigon.h
+-rw-r--r-- root root 14467 ./usr/include/freetype2/freetype/fttypes.h
+-rw-r--r-- root root 7980 ./usr/include/freetype2/freetype/ftwinfnt.h
+-rw-r--r-- root root 22843 ./usr/include/freetype2/freetype/t1tables.h
+-rw-r--r-- root root 58791 ./usr/include/freetype2/freetype/ttnameid.h
+-rw-r--r-- root root 25245 ./usr/include/freetype2/freetype/tttables.h
+-rw-r--r-- root root 5106 ./usr/include/freetype2/freetype/tttags.h
+-rw-r--r-- root root 1111 ./usr/include/freetype2/ft2build.h
+-rw-r--r-- root root 3111 ./usr/include/fstab.h
+-rw-r--r-- root root 8373 ./usr/include/fts.h
+-rw-r--r-- root root 5252 ./usr/include/ftw.h
+-rw-r--r-- root root 40486 ./usr/include/gawkapi.h
+-rw-r--r-- root root 4211 ./usr/include/gconv.h
+drwxr-xr-x root root 4096 ./usr/include/gdbm
+lrwxrwxrwx root root 9 ./usr/include/gdbm/gdbm.h -> ../gdbm.h
+-rw-r--r-- root root 10345 ./usr/include/gdbm.h
+lrwxrwxrwx root root 9 ./usr/include/gdbm/ndbm.h -> ../ndbm.h
+-rw-r--r-- root root 11312 ./usr/include/gelf.h
+-rw-r--r-- root root 1469 ./usr/include/getopt.h
+drwxr-xr-x root root 4096 ./usr/include/gio-unix-2.0
+drwxr-xr-x root root 4096 ./usr/include/gio-unix-2.0/gio
+-rw-r--r-- root root 8679 ./usr/include/gio-unix-2.0/gio/gdesktopappinfo.h
+-rw-r--r-- root root 2218 ./usr/include/gio-unix-2.0/gio/gfiledescriptorbased.h
+-rw-r--r-- root root 5761 ./usr/include/gio-unix-2.0/gio/gunixconnection.h
+-rw-r--r-- root root 3197 ./usr/include/gio-unix-2.0/gio/gunixcredentialsmessage.h
+-rw-r--r-- root root 4245 ./usr/include/gio-unix-2.0/gio/gunixfdlist.h
+-rw-r--r-- root root 3767 ./usr/include/gio-unix-2.0/gio/gunixfdmessage.h
+-rw-r--r-- root root 3018 ./usr/include/gio-unix-2.0/gio/gunixinputstream.h
+-rw-r--r-- root root 7349 ./usr/include/gio-unix-2.0/gio/gunixmounts.h
+-rw-r--r-- root root 3050 ./usr/include/gio-unix-2.0/gio/gunixoutputstream.h
+-rw-r--r-- root root 3424 ./usr/include/gio-unix-2.0/gio/gunixsocketaddress.h
+drwxr-xr-x root root 4096 ./usr/include/GL
+-rw-r--r-- root root 421419 ./usr/include/GL/glcorearb.h
+-rw-r--r-- root root 848217 ./usr/include/GL/glext.h
+-rw-r--r-- root root 80393 ./usr/include/GL/gl.h
+-rw-r--r-- root root 48752 ./usr/include/GL/glxext.h
+-rw-r--r-- root root 14578 ./usr/include/GL/glx.h
+-rw-r--r-- root root 4695 ./usr/include/GL/glxint.h
+-rw-r--r-- root root 2085 ./usr/include/GL/glxmd.h
+-rw-r--r-- root root 78531 ./usr/include/GL/glxproto.h
+-rw-r--r-- root root 11429 ./usr/include/GL/glxtokens.h
+drwxr-xr-x root root 4096 ./usr/include/glib-2.0
+drwxr-xr-x root root 4096 ./usr/include/glib-2.0/gio
+-rw-r--r-- root root 1768 ./usr/include/glib-2.0/gio/gactiongroupexporter.h
+-rw-r--r-- root root 9167 ./usr/include/glib-2.0/gio/gactiongroup.h
+-rw-r--r-- root root 4610 ./usr/include/glib-2.0/gio/gaction.h
+-rw-r--r-- root root 3996 ./usr/include/glib-2.0/gio/gactionmap.h
+-rw-r--r-- root root 19095 ./usr/include/glib-2.0/gio/gappinfo.h
+-rw-r--r-- root root 6168 ./usr/include/glib-2.0/gio/gapplicationcommandline.h
+-rw-r--r-- root root 14551 ./usr/include/glib-2.0/gio/gapplication.h
+-rw-r--r-- root root 4423 ./usr/include/glib-2.0/gio/gasyncinitable.h
+-rw-r--r-- root root 2818 ./usr/include/glib-2.0/gio/gasyncresult.h
+-rw-r--r-- root root 5229 ./usr/include/glib-2.0/gio/gbufferedinputstream.h
+-rw-r--r-- root root 3334 ./usr/include/glib-2.0/gio/gbufferedoutputstream.h
+-rw-r--r-- root root 1652 ./usr/include/glib-2.0/gio/gbytesicon.h
+-rw-r--r-- root root 4058 ./usr/include/glib-2.0/gio/gcancellable.h
+-rw-r--r-- root root 2518 ./usr/include/glib-2.0/gio/gcharsetconverter.h
+-rw-r--r-- root root 2971 ./usr/include/glib-2.0/gio/gcontenttype.h
+-rw-r--r-- root root 2885 ./usr/include/glib-2.0/gio/gconverter.h
+-rw-r--r-- root root 3015 ./usr/include/glib-2.0/gio/gconverterinputstream.h
+-rw-r--r-- root root 3054 ./usr/include/glib-2.0/gio/gconverteroutputstream.h
+-rw-r--r-- root root 3408 ./usr/include/glib-2.0/gio/gcredentials.h
+-rw-r--r-- root root 6661 ./usr/include/glib-2.0/gio/gdatagrambased.h
+-rw-r--r-- root root 11140 ./usr/include/glib-2.0/gio/gdatainputstream.h
+-rw-r--r-- root root 4923 ./usr/include/glib-2.0/gio/gdataoutputstream.h
+-rw-r--r-- root root 2739 ./usr/include/glib-2.0/gio/gdbusactiongroup.h
+-rw-r--r-- root root 2670 ./usr/include/glib-2.0/gio/gdbusaddress.h
+-rw-r--r-- root root 2130 ./usr/include/glib-2.0/gio/gdbusauthobserver.h
+-rw-r--r-- root root 38873 ./usr/include/glib-2.0/gio/gdbusconnection.h
+-rw-r--r-- root root 4306 ./usr/include/glib-2.0/gio/gdbuserror.h
+-rw-r--r-- root root 3069 ./usr/include/glib-2.0/gio/gdbusinterface.h
+-rw-r--r-- root root 6055 ./usr/include/glib-2.0/gio/gdbusinterfaceskeleton.h
+-rw-r--r-- root root 12393 ./usr/include/glib-2.0/gio/gdbusintrospection.h
+-rw-r--r-- root root 1730 ./usr/include/glib-2.0/gio/gdbusmenumodel.h
+-rw-r--r-- root root 11383 ./usr/include/glib-2.0/gio/gdbusmessage.h
+-rw-r--r-- root root 5801 ./usr/include/glib-2.0/gio/gdbusmethodinvocation.h
+-rw-r--r-- root root 4877 ./usr/include/glib-2.0/gio/gdbusnameowning.h
+-rw-r--r-- root root 4521 ./usr/include/glib-2.0/gio/gdbusnamewatching.h
+-rw-r--r-- root root 2941 ./usr/include/glib-2.0/gio/gdbusobject.h
+-rw-r--r-- root root 9800 ./usr/include/glib-2.0/gio/gdbusobjectmanagerclient.h
+-rw-r--r-- root root 4474 ./usr/include/glib-2.0/gio/gdbusobjectmanager.h
+-rw-r--r-- root root 4120 ./usr/include/glib-2.0/gio/gdbusobjectmanagerserver.h
+-rw-r--r-- root root 2635 ./usr/include/glib-2.0/gio/gdbusobjectproxy.h
+-rw-r--r-- root root 3957 ./usr/include/glib-2.0/gio/gdbusobjectskeleton.h
+-rw-r--r-- root root 12082 ./usr/include/glib-2.0/gio/gdbusproxy.h
+-rw-r--r-- root root 2534 ./usr/include/glib-2.0/gio/gdbusserver.h
+-rw-r--r-- root root 1779 ./usr/include/glib-2.0/gio/gdbusutils.h
+-rw-r--r-- root root 14503 ./usr/include/glib-2.0/gio/gdrive.h
+-rw-r--r-- root root 3197 ./usr/include/glib-2.0/gio/gdtlsclientconnection.h
+-rw-r--r-- root root 11430 ./usr/include/glib-2.0/gio/gdtlsconnection.h
+-rw-r--r-- root root 2446 ./usr/include/glib-2.0/gio/gdtlsserverconnection.h
+-rw-r--r-- root root 2788 ./usr/include/glib-2.0/gio/gemblemedicon.h
+-rw-r--r-- root root 2155 ./usr/include/glib-2.0/gio/gemblem.h
+-rw-r--r-- root root 2801 ./usr/include/glib-2.0/gio/gfileattribute.h
+-rw-r--r-- root root 6393 ./usr/include/glib-2.0/gio/gfileenumerator.h
+-rw-r--r-- root root 79870 ./usr/include/glib-2.0/gio/gfile.h
+-rw-r--r-- root root 1959 ./usr/include/glib-2.0/gio/gfileicon.h
+-rw-r--r-- root root 44335 ./usr/include/glib-2.0/gio/gfileinfo.h
+-rw-r--r-- root root 4656 ./usr/include/glib-2.0/gio/gfileinputstream.h
+-rw-r--r-- root root 5041 ./usr/include/glib-2.0/gio/gfileiostream.h
+-rw-r--r-- root root 3280 ./usr/include/glib-2.0/gio/gfilemonitor.h
+-rw-r--r-- root root 3090 ./usr/include/glib-2.0/gio/gfilenamecompleter.h
+-rw-r--r-- root root 5338 ./usr/include/glib-2.0/gio/gfileoutputstream.h
+-rw-r--r-- root root 2832 ./usr/include/glib-2.0/gio/gfilterinputstream.h
+-rw-r--r-- root root 2875 ./usr/include/glib-2.0/gio/gfilteroutputstream.h
+-rw-r--r-- root root 3435 ./usr/include/glib-2.0/gio/gicon.h
+-rw-r--r-- root root 4529 ./usr/include/glib-2.0/gio/ginetaddress.h
+-rw-r--r-- root root 3119 ./usr/include/glib-2.0/gio/ginetaddressmask.h
+-rw-r--r-- root root 3111 ./usr/include/glib-2.0/gio/ginetsocketaddress.h
+-rw-r--r-- root root 2976 ./usr/include/glib-2.0/gio/ginitable.h
+-rw-r--r-- root root 9188 ./usr/include/glib-2.0/gio/ginputstream.h
+-rw-r--r-- root root 9066 ./usr/include/glib-2.0/gio/gio-autocleanups.h
+-rw-r--r-- root root 76503 ./usr/include/glib-2.0/gio/gioenums.h
+-rw-r--r-- root root 12517 ./usr/include/glib-2.0/gio/gioenumtypes.h
+-rw-r--r-- root root 1558 ./usr/include/glib-2.0/gio/gioerror.h
+-rw-r--r-- root root 5646 ./usr/include/glib-2.0/gio/gio.h
+-rw-r--r-- root root 8064 ./usr/include/glib-2.0/gio/giomodule.h
+-rw-r--r-- root root 1999 ./usr/include/glib-2.0/gio/gioscheduler.h
+-rw-r--r-- root root 4862 ./usr/include/glib-2.0/gio/giostream.h
+-rw-r--r-- root root 24681 ./usr/include/glib-2.0/gio/giotypes.h
+-rw-r--r-- root root 2576 ./usr/include/glib-2.0/gio/glistmodel.h
+-rw-r--r-- root root 4178 ./usr/include/glib-2.0/gio/gliststore.h
+-rw-r--r-- root root 3671 ./usr/include/glib-2.0/gio/gloadableicon.h
+-rw-r--r-- root root 3434 ./usr/include/glib-2.0/gio/gmemoryinputstream.h
+-rw-r--r-- root root 2140 ./usr/include/glib-2.0/gio/gmemorymonitor.h
+-rw-r--r-- root root 3933 ./usr/include/glib-2.0/gio/gmemoryoutputstream.h
+-rw-r--r-- root root 1611 ./usr/include/glib-2.0/gio/gmenuexporter.h
+-rw-r--r-- root root 8940 ./usr/include/glib-2.0/gio/gmenu.h
+-rw-r--r-- root root 14334 ./usr/include/glib-2.0/gio/gmenumodel.h
+-rw-r--r-- root root 15791 ./usr/include/glib-2.0/gio/gmount.h
+-rw-r--r-- root root 6765 ./usr/include/glib-2.0/gio/gmountoperation.h
+-rw-r--r-- root root 2536 ./usr/include/glib-2.0/gio/gnativesocketaddress.h
+-rw-r--r-- root root 2270 ./usr/include/glib-2.0/gio/gnativevolumemonitor.h
+-rw-r--r-- root root 2956 ./usr/include/glib-2.0/gio/gnetworkaddress.h
+-rw-r--r-- root root 1994 ./usr/include/glib-2.0/gio/gnetworking.h
+-rw-r--r-- root root 4239 ./usr/include/glib-2.0/gio/gnetworkmonitor.h
+-rw-r--r-- root root 2756 ./usr/include/glib-2.0/gio/gnetworkservice.h
+-rw-r--r-- root root 4898 ./usr/include/glib-2.0/gio/gnotification.h
+-rw-r--r-- root root 15760 ./usr/include/glib-2.0/gio/goutputstream.h
+-rw-r--r-- root root 5862 ./usr/include/glib-2.0/gio/gpermission.h
+-rw-r--r-- root root 3829 ./usr/include/glib-2.0/gio/gpollableinputstream.h
+-rw-r--r-- root root 4919 ./usr/include/glib-2.0/gio/gpollableoutputstream.h
+-rw-r--r-- root root 2134 ./usr/include/glib-2.0/gio/gpollableutils.h
+-rw-r--r-- root root 1994 ./usr/include/glib-2.0/gio/gpropertyaction.h
+-rw-r--r-- root root 2939 ./usr/include/glib-2.0/gio/gproxyaddressenumerator.h
+-rw-r--r-- root root 3166 ./usr/include/glib-2.0/gio/gproxyaddress.h
+-rw-r--r-- root root 4067 ./usr/include/glib-2.0/gio/gproxy.h
+-rw-r--r-- root root 3393 ./usr/include/glib-2.0/gio/gproxyresolver.h
+-rw-r--r-- root root 3635 ./usr/include/glib-2.0/gio/gremoteactiongroup.h
+-rw-r--r-- root root 16852 ./usr/include/glib-2.0/gio/gresolver.h
+-rw-r--r-- root root 4651 ./usr/include/glib-2.0/gio/gresource.h
+-rw-r--r-- root root 3280 ./usr/include/glib-2.0/gio/gseekable.h
+-rw-r--r-- root root 8508 ./usr/include/glib-2.0/gio/gsettingsbackend.h
+-rw-r--r-- root root 21148 ./usr/include/glib-2.0/gio/gsettings.h
+-rw-r--r-- root root 5933 ./usr/include/glib-2.0/gio/gsettingsschema.h
+-rw-r--r-- root root 4355 ./usr/include/glib-2.0/gio/gsimpleactiongroup.h
+-rw-r--r-- root root 2915 ./usr/include/glib-2.0/gio/gsimpleaction.h
+-rw-r--r-- root root 7809 ./usr/include/glib-2.0/gio/gsimpleasyncresult.h
+-rw-r--r-- root root 1722 ./usr/include/glib-2.0/gio/gsimpleiostream.h
+-rw-r--r-- root root 1686 ./usr/include/glib-2.0/gio/gsimplepermission.h
+-rw-r--r-- root root 3531 ./usr/include/glib-2.0/gio/gsimpleproxyresolver.h
+-rw-r--r-- root root 3897 ./usr/include/glib-2.0/gio/gsocketaddressenumerator.h
+-rw-r--r-- root root 3086 ./usr/include/glib-2.0/gio/gsocketaddress.h
+-rw-r--r-- root root 11211 ./usr/include/glib-2.0/gio/gsocketclient.h
+-rw-r--r-- root root 2886 ./usr/include/glib-2.0/gio/gsocketconnectable.h
+-rw-r--r-- root root 5056 ./usr/include/glib-2.0/gio/gsocketconnection.h
+-rw-r--r-- root root 4886 ./usr/include/glib-2.0/gio/gsocketcontrolmessage.h
+-rw-r--r-- root root 16181 ./usr/include/glib-2.0/gio/gsocket.h
+-rw-r--r-- root root 7680 ./usr/include/glib-2.0/gio/gsocketlistener.h
+-rw-r--r-- root root 3620 ./usr/include/glib-2.0/gio/gsocketservice.h
+-rw-r--r-- root root 1936 ./usr/include/glib-2.0/gio/gsrvtarget.h
+-rw-r--r-- root root 8606 ./usr/include/glib-2.0/gio/gsubprocess.h
+-rw-r--r-- root root 6399 ./usr/include/glib-2.0/gio/gsubprocesslauncher.h
+-rw-r--r-- root root 8278 ./usr/include/glib-2.0/gio/gtask.h
+-rw-r--r-- root root 2957 ./usr/include/glib-2.0/gio/gtcpconnection.h
+-rw-r--r-- root root 2973 ./usr/include/glib-2.0/gio/gtcpwrapperconnection.h
+-rw-r--r-- root root 2303 ./usr/include/glib-2.0/gio/gtestdbus.h
+-rw-r--r-- root root 2643 ./usr/include/glib-2.0/gio/gthemedicon.h
+-rw-r--r-- root root 3665 ./usr/include/glib-2.0/gio/gthreadedsocketservice.h
+-rw-r--r-- root root 4587 ./usr/include/glib-2.0/gio/gtlsbackend.h
+-rw-r--r-- root root 3505 ./usr/include/glib-2.0/gio/gtlscertificate.h
+-rw-r--r-- root root 3683 ./usr/include/glib-2.0/gio/gtlsclientconnection.h
+-rw-r--r-- root root 6575 ./usr/include/glib-2.0/gio/gtlsconnection.h
+-rw-r--r-- root root 17271 ./usr/include/glib-2.0/gio/gtlsdatabase.h
+-rw-r--r-- root root 1909 ./usr/include/glib-2.0/gio/gtlsfiledatabase.h
+-rw-r--r-- root root 8333 ./usr/include/glib-2.0/gio/gtlsinteraction.h
+-rw-r--r-- root root 4818 ./usr/include/glib-2.0/gio/gtlspassword.h
+-rw-r--r-- root root 2348 ./usr/include/glib-2.0/gio/gtlsserverconnection.h
+-rw-r--r-- root root 6616 ./usr/include/glib-2.0/gio/gvfs.h
+-rw-r--r-- root root 11736 ./usr/include/glib-2.0/gio/gvolume.h
+-rw-r--r-- root root 5998 ./usr/include/glib-2.0/gio/gvolumemonitor.h
+-rw-r--r-- root root 2350 ./usr/include/glib-2.0/gio/gzlibcompressor.h
+-rw-r--r-- root root 2212 ./usr/include/glib-2.0/gio/gzlibdecompressor.h
+drwxr-xr-x root root 4096 ./usr/include/glib-2.0/glib
+drwxr-xr-x root root 4096 ./usr/include/glib-2.0/glib/deprecated
+-rw-r--r-- root root 3256 ./usr/include/glib-2.0/glib/deprecated/gallocator.h
+-rw-r--r-- root root 2987 ./usr/include/glib-2.0/glib/deprecated/gcache.h
+-rw-r--r-- root root 2922 ./usr/include/glib-2.0/glib/deprecated/gcompletion.h
+-rw-r--r-- root root 4392 ./usr/include/glib-2.0/glib/deprecated/gmain.h
+-rw-r--r-- root root 3682 ./usr/include/glib-2.0/glib/deprecated/grel.h
+-rw-r--r-- root root 10938 ./usr/include/glib-2.0/glib/deprecated/gthread.h
+-rw-r--r-- root root 3912 ./usr/include/glib-2.0/glib/galloca.h
+-rw-r--r-- root root 11385 ./usr/include/glib-2.0/glib/garray.h
+-rw-r--r-- root root 5726 ./usr/include/glib-2.0/glib/gasyncqueue.h
+-rw-r--r-- root root 23740 ./usr/include/glib-2.0/glib/gatomic.h
+-rw-r--r-- root root 2727 ./usr/include/glib-2.0/glib/gbacktrace.h
+-rw-r--r-- root root 2323 ./usr/include/glib-2.0/glib/gbase64.h
+-rw-r--r-- root root 2902 ./usr/include/glib-2.0/glib/gbitlock.h
+-rw-r--r-- root root 9596 ./usr/include/glib-2.0/glib/gbookmarkfile.h
+-rw-r--r-- root root 3334 ./usr/include/glib-2.0/glib/gbytes.h
+-rw-r--r-- root root 1578 ./usr/include/glib-2.0/glib/gcharset.h
+-rw-r--r-- root root 3864 ./usr/include/glib-2.0/glib/gchecksum.h
+-rw-r--r-- root root 5923 ./usr/include/glib-2.0/glib/gconvert.h
+-rw-r--r-- root root 6245 ./usr/include/glib-2.0/glib/gdataset.h
+-rw-r--r-- root root 12420 ./usr/include/glib-2.0/glib/gdate.h
+-rw-r--r-- root root 12738 ./usr/include/glib-2.0/glib/gdatetime.h
+-rw-r--r-- root root 1641 ./usr/include/glib-2.0/glib/gdir.h
+-rw-r--r-- root root 2364 ./usr/include/glib-2.0/glib/genviron.h
+-rw-r--r-- root root 3943 ./usr/include/glib-2.0/glib/gerror.h
+-rw-r--r-- root root 5813 ./usr/include/glib-2.0/glib/gfileutils.h
+-rw-r--r-- root root 2424 ./usr/include/glib-2.0/glib/ggettext.h
+-rw-r--r-- root root 7886 ./usr/include/glib-2.0/glib/ghash.h
+-rw-r--r-- root root 3469 ./usr/include/glib-2.0/glib/ghmac.h
+-rw-r--r-- root root 6358 ./usr/include/glib-2.0/glib/ghook.h
+-rw-r--r-- root root 1456 ./usr/include/glib-2.0/glib/ghostutils.h
+-rw-r--r-- root root 1167 ./usr/include/glib-2.0/glib/gi18n.h
+-rw-r--r-- root root 1370 ./usr/include/glib-2.0/glib/gi18n-lib.h
+-rw-r--r-- root root 13954 ./usr/include/glib-2.0/glib/giochannel.h
+-rw-r--r-- root root 14913 ./usr/include/glib-2.0/glib/gkeyfile.h
+-rw-r--r-- root root 4789 ./usr/include/glib-2.0/glib/glib-autocleanups.h
+-rw-r--r-- root root 6930 ./usr/include/glib-2.0/glib/glist.h
+-rw-r--r-- root root 42372 ./usr/include/glib-2.0/glib/gmacros.h
+-rw-r--r-- root root 28138 ./usr/include/glib-2.0/glib/gmain.h
+-rw-r--r-- root root 1986 ./usr/include/glib-2.0/glib/gmappedfile.h
+-rw-r--r-- root root 10876 ./usr/include/glib-2.0/glib/gmarkup.h
+-rw-r--r-- root root 14684 ./usr/include/glib-2.0/glib/gmem.h
+-rw-r--r-- root root 26913 ./usr/include/glib-2.0/glib/gmessages.h
+-rw-r--r-- root root 8700 ./usr/include/glib-2.0/glib/gnode.h
+-rw-r--r-- root root 16099 ./usr/include/glib-2.0/glib/goption.h
+-rw-r--r-- root root 1782 ./usr/include/glib-2.0/glib/gpattern.h
+-rw-r--r-- root root 4125 ./usr/include/glib-2.0/glib/gpoll.h
+-rw-r--r-- root root 1694 ./usr/include/glib-2.0/glib/gprimes.h
+-rw-r--r-- root root 1984 ./usr/include/glib-2.0/glib/gprintf.h
+-rw-r--r-- root root 1499 ./usr/include/glib-2.0/glib/gqsort.h
+-rw-r--r-- root root 2688 ./usr/include/glib-2.0/glib/gquark.h
+-rw-r--r-- root root 7750 ./usr/include/glib-2.0/glib/gqueue.h
+-rw-r--r-- root root 3182 ./usr/include/glib-2.0/glib/grand.h
+-rw-r--r-- root root 3764 ./usr/include/glib-2.0/glib/grcbox.h
+-rw-r--r-- root root 3988 ./usr/include/glib-2.0/glib/grefcount.h
+-rw-r--r-- root root 1868 ./usr/include/glib-2.0/glib/grefstring.h
+-rw-r--r-- root root 28095 ./usr/include/glib-2.0/glib/gregex.h
+-rw-r--r-- root root 8861 ./usr/include/glib-2.0/glib/gscanner.h
+-rw-r--r-- root root 8811 ./usr/include/glib-2.0/glib/gsequence.h
+-rw-r--r-- root root 1752 ./usr/include/glib-2.0/glib/gshell.h
+-rw-r--r-- root root 3892 ./usr/include/glib-2.0/glib/gslice.h
+-rw-r--r-- root root 6551 ./usr/include/glib-2.0/glib/gslist.h
+-rw-r--r-- root root 11874 ./usr/include/glib-2.0/glib/gspawn.h
+-rw-r--r-- root root 5109 ./usr/include/glib-2.0/glib/gstdio.h
+-rw-r--r-- root root 13232 ./usr/include/glib-2.0/glib/gstrfuncs.h
+-rw-r--r-- root root 2130 ./usr/include/glib-2.0/glib/gstringchunk.h
+-rw-r--r-- root root 8045 ./usr/include/glib-2.0/glib/gstring.h
+-rw-r--r-- root root 31435 ./usr/include/glib-2.0/glib/gtestutils.h
+-rw-r--r-- root root 17496 ./usr/include/glib-2.0/glib/gthread.h
+-rw-r--r-- root root 3824 ./usr/include/glib-2.0/glib/gthreadpool.h
+-rw-r--r-- root root 2576 ./usr/include/glib-2.0/glib/gtimer.h
+-rw-r--r-- root root 3723 ./usr/include/glib-2.0/glib/gtimezone.h
+-rw-r--r-- root root 1906 ./usr/include/glib-2.0/glib/gtrashstack.h
+-rw-r--r-- root root 4194 ./usr/include/glib-2.0/glib/gtree.h
+-rw-r--r-- root root 20493 ./usr/include/glib-2.0/glib/gtypes.h
+-rw-r--r-- root root 40690 ./usr/include/glib-2.0/glib/gunicode.h
+-rw-r--r-- root root 2716 ./usr/include/glib-2.0/glib/gurifuncs.h
+-rw-r--r-- root root 14564 ./usr/include/glib-2.0/glib/gutils.h
+-rw-r--r-- root root 1291 ./usr/include/glib-2.0/glib/guuid.h
+-rw-r--r-- root root 29560 ./usr/include/glib-2.0/glib/gvariant.h
+-rw-r--r-- root root 13244 ./usr/include/glib-2.0/glib/gvarianttype.h
+-rw-r--r-- root root 1981 ./usr/include/glib-2.0/glib/gversion.h
+-rw-r--r-- root root 40799 ./usr/include/glib-2.0/glib/gversionmacros.h
+-rw-r--r-- root root 4667 ./usr/include/glib-2.0/glib/gwin32.h
+-rw-r--r-- root root 3381 ./usr/include/glib-2.0/glib.h
+-rw-r--r-- root root 1462 ./usr/include/glib-2.0/glib-object.h
+-rw-r--r-- root root 4461 ./usr/include/glib-2.0/glib-unix.h
+-rw-r--r-- root root 4318 ./usr/include/glib-2.0/gmodule.h
+drwxr-xr-x root root 4096 ./usr/include/glib-2.0/gobject
+-rw-r--r-- root root 6342 ./usr/include/glib-2.0/gobject/gbinding.h
+-rw-r--r-- root root 3965 ./usr/include/glib-2.0/gobject/gboxed.h
+-rw-r--r-- root root 11053 ./usr/include/glib-2.0/gobject/gclosure.h
+-rw-r--r-- root root 8041 ./usr/include/glib-2.0/gobject/genums.h
+-rw-r--r-- root root 1026 ./usr/include/glib-2.0/gobject/glib-enumtypes.h
+-rw-r--r-- root root 8656 ./usr/include/glib-2.0/gobject/glib-types.h
+-rw-r--r-- root root 21841 ./usr/include/glib-2.0/gobject/gmarshal.h
+-rw-r--r-- root root 1382 ./usr/include/glib-2.0/gobject/gobject-autocleanups.h
+-rw-r--r-- root root 34088 ./usr/include/glib-2.0/gobject/gobject.h
+-rw-r--r-- root root 5516 ./usr/include/glib-2.0/gobject/gobjectnotifyqueue.c
+-rw-r--r-- root root 16431 ./usr/include/glib-2.0/gobject/gparam.h
+-rw-r--r-- root root 34850 ./usr/include/glib-2.0/gobject/gparamspecs.h
+-rw-r--r-- root root 24872 ./usr/include/glib-2.0/gobject/gsignal.h
+-rw-r--r-- root root 1275 ./usr/include/glib-2.0/gobject/gsourceclosure.h
+-rw-r--r-- root root 92450 ./usr/include/glib-2.0/gobject/gtype.h
+-rw-r--r-- root root 10837 ./usr/include/glib-2.0/gobject/gtypemodule.h
+-rw-r--r-- root root 4965 ./usr/include/glib-2.0/gobject/gtypeplugin.h
+-rw-r--r-- root root 3218 ./usr/include/glib-2.0/gobject/gvaluearray.h
+-rw-r--r-- root root 9817 ./usr/include/glib-2.0/gobject/gvaluecollector.h
+-rw-r--r-- root root 5656 ./usr/include/glib-2.0/gobject/gvalue.h
+-rw-r--r-- root root 9653 ./usr/include/glib-2.0/gobject/gvaluetypes.h
+drwxr-xr-x root root 4096 ./usr/include/GL/internal
+-rw-r--r-- root root 78637 ./usr/include/GL/internal/dri_interface.h
+-rw-r--r-- root root 6315 ./usr/include/GL/internal/glcore.h
+-rw-r--r-- root root 6617 ./usr/include/glob.h
+-rw-r--r-- root root 84177 ./usr/include/gmp-64.h
+-rw-r--r-- root root 500 ./usr/include/gmp.h
+-rw-r--r-- root root 129113 ./usr/include/gmpxx.h
+drwxr-xr-x root root 4096 ./usr/include/gnu
+-rw-r--r-- root root 1264 ./usr/include/gnu/libc-version.h
+-rw-r--r-- root root 1665 ./usr/include/gnu/lib-names-64.h
+-rw-r--r-- root root 467 ./usr/include/gnu/lib-names.h
+-rw-r--r-- root root 2912 ./usr/include/gnumake.h
+-rw-r--r-- root root 523 ./usr/include/gnu/stubs-64.h
+-rw-r--r-- root root 384 ./usr/include/gnu/stubs.h
+-rw-r--r-- root root 2343 ./usr/include/gnu-versions.h
+drwxr-xr-x root root 4096 ./usr/include/gobject-introspection-1.0
+-rw-r--r-- root root 2622 ./usr/include/gobject-introspection-1.0/giarginfo.h
+-rw-r--r-- root root 3275 ./usr/include/gobject-introspection-1.0/gibaseinfo.h
+-rw-r--r-- root root 4523 ./usr/include/gobject-introspection-1.0/gicallableinfo.h
+-rw-r--r-- root root 1769 ./usr/include/gobject-introspection-1.0/giconstantinfo.h
+-rw-r--r-- root root 2348 ./usr/include/gobject-introspection-1.0/gienuminfo.h
+-rw-r--r-- root root 2129 ./usr/include/gobject-introspection-1.0/gifieldinfo.h
+-rw-r--r-- root root 2877 ./usr/include/gobject-introspection-1.0/gifunctioninfo.h
+-rw-r--r-- root root 3418 ./usr/include/gobject-introspection-1.0/giinterfaceinfo.h
+-rw-r--r-- root root 6060 ./usr/include/gobject-introspection-1.0/giobjectinfo.h
+-rw-r--r-- root root 1685 ./usr/include/gobject-introspection-1.0/gipropertyinfo.h
+-rw-r--r-- root root 2363 ./usr/include/gobject-introspection-1.0/giregisteredtypeinfo.h
+-rw-r--r-- root root 8052 ./usr/include/gobject-introspection-1.0/girepository.h
+-rw-r--r-- root root 3468 ./usr/include/gobject-introspection-1.0/girffi.h
+-rw-r--r-- root root 1696 ./usr/include/gobject-introspection-1.0/gisignalinfo.h
+-rw-r--r-- root root 2403 ./usr/include/gobject-introspection-1.0/gistructinfo.h
+-rw-r--r-- root root 2556 ./usr/include/gobject-introspection-1.0/gitypeinfo.h
+-rw-r--r-- root root 2327 ./usr/include/gobject-introspection-1.0/gitypelib.h
+-rw-r--r-- root root 14019 ./usr/include/gobject-introspection-1.0/gitypes.h
+-rw-r--r-- root root 2558 ./usr/include/gobject-introspection-1.0/giunioninfo.h
+-rw-r--r-- root root 1578 ./usr/include/gobject-introspection-1.0/giversion.h
+-rw-r--r-- root root 5730 ./usr/include/gobject-introspection-1.0/giversionmacros.h
+-rw-r--r-- root root 2572 ./usr/include/gobject-introspection-1.0/givfuncinfo.h
+-rw-r--r-- root root 6687 ./usr/include/grp.h
+-rw-r--r-- root root 4529 ./usr/include/gshadow.h
+-rw-r--r-- root root 1858 ./usr/include/iconv.h
+-rw-r--r-- root root 4916 ./usr/include/ieee754.h
+-rw-r--r-- root root 2841 ./usr/include/ifaddrs.h
+-rw-r--r-- root root 2446 ./usr/include/initreq.h
+-rw-r--r-- root root 11893 ./usr/include/inttypes.h
+drwxr-xr-x root root 4096 ./usr/include/iproute2
+-rw-r--r-- root root 1271 ./usr/include/iproute2/bpf_elf.h
+-rw-r--r-- root root 17849 ./usr/include/langinfo.h
+-rw-r--r-- root root 126 ./usr/include/lastlog.h
+drwxr-xr-x root root 4096 ./usr/include/libdrm
+-rw-r--r-- root root 31894 ./usr/include/libdrm/amdgpu_drm.h
+-rw-r--r-- root root 55079 ./usr/include/libdrm/amdgpu.h
+-rw-r--r-- root root 32818 ./usr/include/libdrm/drm_fourcc.h
+-rw-r--r-- root root 32306 ./usr/include/libdrm/drm.h
+-rw-r--r-- root root 24920 ./usr/include/libdrm/drm_mode.h
+-rw-r--r-- root root 2782 ./usr/include/libdrm/drm_sarea.h
+-rw-r--r-- root root 6977 ./usr/include/libdrm/etnaviv_drmif.h
+-rw-r--r-- root root 62951 ./usr/include/libdrm/i915_drm.h
+-rw-r--r-- root root 5933 ./usr/include/libdrm/intel_aub.h
+-rw-r--r-- root root 12892 ./usr/include/libdrm/intel_bufmgr.h
+-rw-r--r-- root root 1585 ./usr/include/libdrm/intel_debug.h
+-rw-r--r-- root root 7895 ./usr/include/libdrm/mach64_drm.h
+-rw-r--r-- root root 13010 ./usr/include/libdrm/mga_drm.h
+-rw-r--r-- root root 12105 ./usr/include/libdrm/msm_drm.h
+drwxr-xr-x root root 4096 ./usr/include/libdrm/nouveau
+-rw-r--r-- root root 5699 ./usr/include/libdrm/nouveau_drm.h
+-rw-r--r-- root root 7766 ./usr/include/libdrm/nouveau/nouveau.h
+drwxr-xr-x root root 4096 ./usr/include/libdrm/nouveau/nvif
+-rw-r--r-- root root 1785 ./usr/include/libdrm/nouveau/nvif/cl0080.h
+-rw-r--r-- root root 2062 ./usr/include/libdrm/nouveau/nvif/cl9097.h
+-rw-r--r-- root root 8789 ./usr/include/libdrm/nouveau/nvif/class.h
+-rw-r--r-- root root 769 ./usr/include/libdrm/nouveau/nvif/if0002.h
+-rw-r--r-- root root 645 ./usr/include/libdrm/nouveau/nvif/if0003.h
+-rw-r--r-- root root 3174 ./usr/include/libdrm/nouveau/nvif/ioctl.h
+-rw-r--r-- root root 1551 ./usr/include/libdrm/nouveau/nvif/unpack.h
+-rw-r--r-- root root 2555 ./usr/include/libdrm/omap_drmif.h
+-rw-r--r-- root root 4131 ./usr/include/libdrm/qxl_drm.h
+-rw-r--r-- root root 10000 ./usr/include/libdrm/r128_drm.h
+-rw-r--r-- root root 16388 ./usr/include/libdrm/r600_pci_ids.h
+-rw-r--r-- root root 1991 ./usr/include/libdrm/radeon_bo_gem.h
+-rw-r--r-- root root 2839 ./usr/include/libdrm/radeon_bo.h
+-rw-r--r-- root root 1678 ./usr/include/libdrm/radeon_bo_int.h
+-rw-r--r-- root root 1601 ./usr/include/libdrm/radeon_cs_gem.h
+-rw-r--r-- root root 5121 ./usr/include/libdrm/radeon_cs.h
+-rw-r--r-- root root 2179 ./usr/include/libdrm/radeon_cs_int.h
+-rw-r--r-- root root 38317 ./usr/include/libdrm/radeon_drm.h
+-rw-r--r-- root root 5968 ./usr/include/libdrm/radeon_surface.h
+-rw-r--r-- root root 7170 ./usr/include/libdrm/savage_drm.h
+-rw-r--r-- root root 2633 ./usr/include/libdrm/sis_drm.h
+-rw-r--r-- root root 14877 ./usr/include/libdrm/tegra_drm.h
+-rw-r--r-- root root 14457 ./usr/include/libdrm/vc4_drm.h
+-rw-r--r-- root root 16906 ./usr/include/libdrm/vc4_packet.h
+-rw-r--r-- root root 8244 ./usr/include/libdrm/vc4_qpu_defines.h
+-rw-r--r-- root root 8372 ./usr/include/libdrm/via_drm.h
+-rw-r--r-- root root 5010 ./usr/include/libdrm/virtgpu_drm.h
+-rw-r--r-- root root 32085 ./usr/include/libdrm/vmwgfx_drm.h
+-rw-r--r-- root root 19573 ./usr/include/libelf.h
+drwxr-xr-x root root 4096 ./usr/include/libfdisk
+-rw-r--r-- root root 29857 ./usr/include/libfdisk/libfdisk.h
+-rw-r--r-- root root 1386 ./usr/include/libgen.h
+drwxr-xr-x root root 4096 ./usr/include/libiberty
+-rw-r--r-- root root 14130 ./usr/include/libiberty/ansidecl.h
+-rw-r--r-- root root 27301 ./usr/include/libiberty/demangle.h
+-rw-r--r-- root root 2706 ./usr/include/libiberty/dyn-string.h
+-rw-r--r-- root root 2937 ./usr/include/libiberty/fibheap.h
+-rw-r--r-- root root 5890 ./usr/include/libiberty/floatformat.h
+-rw-r--r-- root root 27820 ./usr/include/libiberty.h
+-rw-r--r-- root root 7270 ./usr/include/libiberty/hashtab.h
+-rw-r--r-- root root 27820 ./usr/include/libiberty/libiberty.h
+-rw-r--r-- root root 3976 ./usr/include/libiberty/objalloc.h
+-rw-r--r-- root root 2824 ./usr/include/libiberty/partition.h
+-rw-r--r-- root root 5642 ./usr/include/libiberty/safe-ctype.h
+-rw-r--r-- root root 1209 ./usr/include/libiberty/sort.h
+-rw-r--r-- root root 6238 ./usr/include/libiberty/splay-tree.h
+-rw-r--r-- root root 1296 ./usr/include/libiberty/timeval-utils.h
+-rw-r--r-- root root 4580 ./usr/include/libintl.h
+drwxr-xr-x root root 4096 ./usr/include/libiptc
+-rw-r--r-- root root 360 ./usr/include/libiptc/ipt_kernel_headers.h
+-rw-r--r-- root root 5375 ./usr/include/libiptc/libip6tc.h
+-rw-r--r-- root root 5447 ./usr/include/libiptc/libiptc.h
+-rw-r--r-- root root 724 ./usr/include/libiptc/libxtc.h
+-rw-r--r-- root root 867 ./usr/include/libiptc/xtcshared.h
+-rw-r--r-- root root 9433 ./usr/include/libkmod.h
+drwxr-xr-x root root 4096 ./usr/include/libkms
+-rw-r--r-- root root 2571 ./usr/include/libkms/libkms.h
+drwxr-xr-x root root 4096 ./usr/include/libmnl
+-rw-r--r-- root root 8002 ./usr/include/libmnl/libmnl.h
+drwxr-xr-x root root 4096 ./usr/include/libmount
+-rw-r--r-- root root 36308 ./usr/include/libmount/libmount.h
+drwxr-xr-x root root 4096 ./usr/include/libpng16
+-rw-r--r-- root root 22846 ./usr/include/libpng16/pngconf.h
+-rw-r--r-- root root 142860 ./usr/include/libpng16/png.h
+-rw-r--r-- root root 7629 ./usr/include/libpng16/pnglibconf.h
+drwxr-xr-x root root 4096 ./usr/include/libsmartcols
+-rw-r--r-- root root 15473 ./usr/include/libsmartcols/libsmartcols.h
+-rw-r--r-- root root 3466 ./usr/include/libsync.h
+-rw-r--r-- root root 10327 ./usr/include/libudev.h
+drwxr-xr-x root root 4096 ./usr/include/libxml2
+drwxr-xr-x root root 4096 ./usr/include/libxml2/libxml
+-rw-r--r-- root root 3115 ./usr/include/libxml2/libxml/c14n.h
+-rw-r--r-- root root 4906 ./usr/include/libxml2/libxml/catalog.h
+-rw-r--r-- root root 5159 ./usr/include/libxml2/libxml/chvalid.h
+-rw-r--r-- root root 5152 ./usr/include/libxml2/libxml/debugXML.h
+-rw-r--r-- root root 1814 ./usr/include/libxml2/libxml/dict.h
+-rw-r--r-- root root 3157 ./usr/include/libxml2/libxml/DOCBparser.h
+-rw-r--r-- root root 8507 ./usr/include/libxml2/libxml/encoding.h
+-rw-r--r-- root root 4712 ./usr/include/libxml2/libxml/entities.h
+-rw-r--r-- root root 14670 ./usr/include/libxml2/libxml/globals.h
+-rw-r--r-- root root 6601 ./usr/include/libxml2/libxml/hash.h
+-rw-r--r-- root root 9410 ./usr/include/libxml2/libxml/HTMLparser.h
+-rw-r--r-- root root 3646 ./usr/include/libxml2/libxml/HTMLtree.h
+-rw-r--r-- root root 3348 ./usr/include/libxml2/libxml/list.h
+-rw-r--r-- root root 3758 ./usr/include/libxml2/libxml/nanoftp.h
+-rw-r--r-- root root 2005 ./usr/include/libxml2/libxml/nanohttp.h
+-rw-r--r-- root root 39718 ./usr/include/libxml2/libxml/parser.h
+-rw-r--r-- root root 17419 ./usr/include/libxml2/libxml/parserInternals.h
+-rw-r--r-- root root 2586 ./usr/include/libxml2/libxml/pattern.h
+-rw-r--r-- root root 5996 ./usr/include/libxml2/libxml/relaxng.h
+-rw-r--r-- root root 4949 ./usr/include/libxml2/libxml/SAX2.h
+-rw-r--r-- root root 4341 ./usr/include/libxml2/libxml/SAX.h
+-rw-r--r-- root root 26224 ./usr/include/libxml2/libxml/schemasInternals.h
+-rw-r--r-- root root 4371 ./usr/include/libxml2/libxml/schematron.h
+-rw-r--r-- root root 1958 ./usr/include/libxml2/libxml/threads.h
+-rw-r--r-- root root 38108 ./usr/include/libxml2/libxml/tree.h
+-rw-r--r-- root root 2664 ./usr/include/libxml2/libxml/uri.h
+-rw-r--r-- root root 13622 ./usr/include/libxml2/libxml/valid.h
+-rw-r--r-- root root 2967 ./usr/include/libxml2/libxml/xinclude.h
+-rw-r--r-- root root 5042 ./usr/include/libxml2/libxml/xlink.h
+-rw-r--r-- root root 3956 ./usr/include/libxml2/libxml/xmlautomata.h
+-rw-r--r-- root root 36809 ./usr/include/libxml2/libxml/xmlerror.h
+-rw-r--r-- root root 3759 ./usr/include/libxml2/libxml/xmlexports.h
+-rw-r--r-- root root 10605 ./usr/include/libxml2/libxml/xmlIO.h
+-rw-r--r-- root root 5945 ./usr/include/libxml2/libxml/xmlmemory.h
+-rw-r--r-- root root 1170 ./usr/include/libxml2/libxml/xmlmodule.h
+-rw-r--r-- root root 12607 ./usr/include/libxml2/libxml/xmlreader.h
+-rw-r--r-- root root 5458 ./usr/include/libxml2/libxml/xmlregexp.h
+-rw-r--r-- root root 2337 ./usr/include/libxml2/libxml/xmlsave.h
+-rw-r--r-- root root 7069 ./usr/include/libxml2/libxml/xmlschemas.h
+-rw-r--r-- root root 4841 ./usr/include/libxml2/libxml/xmlschemastypes.h
+-rw-r--r-- root root 5511 ./usr/include/libxml2/libxml/xmlstring.h
+-rw-r--r-- root root 9993 ./usr/include/libxml2/libxml/xmlunicode.h
+-rw-r--r-- root root 8035 ./usr/include/libxml2/libxml/xmlversion.h
+-rw-r--r-- root root 21265 ./usr/include/libxml2/libxml/xmlwriter.h
+-rw-r--r-- root root 16602 ./usr/include/libxml2/libxml/xpath.h
+-rw-r--r-- root root 19353 ./usr/include/libxml2/libxml/xpathInternals.h
+-rw-r--r-- root root 3359 ./usr/include/libxml2/libxml/xpointer.h
+-rw-r--r-- root root 5417 ./usr/include/limits.h
+-rw-r--r-- root root 7207 ./usr/include/link.h
+drwxr-xr-x root root 20480 ./usr/include/linux
+-rw-r--r-- root root 3733 ./usr/include/linux/acct.h
+-rw-r--r-- root root 1140 ./usr/include/linux/adb.h
+-rw-r--r-- root root 993 ./usr/include/linux/adfs_fs.h
+-rw-r--r-- root root 1544 ./usr/include/linux/affs_hardblocks.h
+-rw-r--r-- root root 3940 ./usr/include/linux/agpgart.h
+-rw-r--r-- root root 3398 ./usr/include/linux/aio_abi.h
+-rw-r--r-- root root 3681 ./usr/include/linux/am437x-vpfe.h
+drwxr-xr-x root root 4096 ./usr/include/linux/android
+-rw-r--r-- root root 789 ./usr/include/linux/android/binderfs.h
+-rw-r--r-- root root 14535 ./usr/include/linux/android/binder.h
+-rw-r--r-- root root 6892 ./usr/include/linux/a.out.h
+-rw-r--r-- root root 3683 ./usr/include/linux/apm_bios.h
+-rw-r--r-- root root 213 ./usr/include/linux/arcfb.h
+-rw-r--r-- root root 2751 ./usr/include/linux/arm_sdei.h
+-rw-r--r-- root root 1780 ./usr/include/linux/aspeed-lpc-ctrl.h
+-rw-r--r-- root root 1906 ./usr/include/linux/aspeed-p2a-ctrl.h
+-rw-r--r-- root root 1023 ./usr/include/linux/atalk.h
+-rw-r--r-- root root 952 ./usr/include/linux/atmapi.h
+-rw-r--r-- root root 1296 ./usr/include/linux/atmarp.h
+-rw-r--r-- root root 3271 ./usr/include/linux/atmbr2684.h
+-rw-r--r-- root root 576 ./usr/include/linux/atmclip.h
+-rw-r--r-- root root 7677 ./usr/include/linux/atmdev.h
+-rw-r--r-- root root 648 ./usr/include/linux/atm_eni.h
+-rw-r--r-- root root 7888 ./usr/include/linux/atm.h
+-rw-r--r-- root root 406 ./usr/include/linux/atm_he.h
+-rw-r--r-- root root 955 ./usr/include/linux/atm_idt77105.h
+-rw-r--r-- root root 1646 ./usr/include/linux/atmioc.h
+-rw-r--r-- root root 2381 ./usr/include/linux/atmlec.h
+-rw-r--r-- root root 4226 ./usr/include/linux/atmmpc.h
+-rw-r--r-- root root 1278 ./usr/include/linux/atm_nicstar.h
+-rw-r--r-- root root 639 ./usr/include/linux/atmppp.h
+-rw-r--r-- root root 4970 ./usr/include/linux/atmsap.h
+-rw-r--r-- root root 1853 ./usr/include/linux/atmsvc.h
+-rw-r--r-- root root 1622 ./usr/include/linux/atm_tcp.h
+-rw-r--r-- root root 1540 ./usr/include/linux/atm_zatm.h
+-rw-r--r-- root root 20759 ./usr/include/linux/audit.h
+-rw-r--r-- root root 4986 ./usr/include/linux/auto_dev-ioctl.h
+-rw-r--r-- root root 451 ./usr/include/linux/auto_fs4.h
+-rw-r--r-- root root 6428 ./usr/include/linux/auto_fs.h
+-rw-r--r-- root root 1496 ./usr/include/linux/auxvec.h
+-rw-r--r-- root root 2824 ./usr/include/linux/ax25.h
+-rw-r--r-- root root 1717 ./usr/include/linux/b1lli.h
+-rw-r--r-- root root 20373 ./usr/include/linux/batadv_packet.h
+-rw-r--r-- root root 16306 ./usr/include/linux/batman_adv.h
+-rw-r--r-- root root 883 ./usr/include/linux/baycom.h
+-rw-r--r-- root root 8425 ./usr/include/linux/bcache.h
+-rw-r--r-- root root 419 ./usr/include/linux/bcm933xx_hcs.h
+-rw-r--r-- root root 1905 ./usr/include/linux/bfs_fs.h
+-rw-r--r-- root root 628 ./usr/include/linux/binfmts.h
+-rw-r--r-- root root 1634 ./usr/include/linux/blkpg.h
+-rw-r--r-- root root 4701 ./usr/include/linux/blktrace_api.h
+-rw-r--r-- root root 5368 ./usr/include/linux/blkzoned.h
+-rw-r--r-- root root 1367 ./usr/include/linux/bpf_common.h
+-rw-r--r-- root root 138331 ./usr/include/linux/bpf.h
+-rw-r--r-- root root 465 ./usr/include/linux/bpfilter.h
+-rw-r--r-- root root 529 ./usr/include/linux/bpf_perf_event.h
+-rw-r--r-- root root 981 ./usr/include/linux/bpqether.h
+-rw-r--r-- root root 2494 ./usr/include/linux/bsg.h
+-rw-r--r-- root root 572 ./usr/include/linux/bt-bmc.h
+-rw-r--r-- root root 4624 ./usr/include/linux/btf.h
+-rw-r--r-- root root 29142 ./usr/include/linux/btrfs.h
+-rw-r--r-- root root 25245 ./usr/include/linux/btrfs_tree.h
+drwxr-xr-x root root 4096 ./usr/include/linux/byteorder
+-rw-r--r-- root root 3542 ./usr/include/linux/byteorder/big_endian.h
+-rw-r--r-- root root 3611 ./usr/include/linux/byteorder/little_endian.h
+drwxr-xr-x root root 4096 ./usr/include/linux/caif
+-rw-r--r-- root root 5832 ./usr/include/linux/caif/caif_socket.h
+-rw-r--r-- root root 1041 ./usr/include/linux/caif/if_caif.h
+drwxr-xr-x root root 4096 ./usr/include/linux/can
+-rw-r--r-- root root 4116 ./usr/include/linux/can/bcm.h
+-rw-r--r-- root root 6610 ./usr/include/linux/can/error.h
+-rw-r--r-- root root 8031 ./usr/include/linux/can/gw.h
+-rw-r--r-- root root 8213 ./usr/include/linux/can.h
+-rw-r--r-- root root 2207 ./usr/include/linux/can/j1939.h
+-rw-r--r-- root root 3993 ./usr/include/linux/can/netlink.h
+-rw-r--r-- root root 2858 ./usr/include/linux/can/raw.h
+-rw-r--r-- root root 232 ./usr/include/linux/can/vxcan.h
+-rw-r--r-- root root 11780 ./usr/include/linux/capability.h
+-rw-r--r-- root root 3124 ./usr/include/linux/capi.h
+-rw-r--r-- root root 3281 ./usr/include/linux/cciss_defs.h
+-rw-r--r-- root root 2761 ./usr/include/linux/cciss_ioctl.h
+-rw-r--r-- root root 28859 ./usr/include/linux/cdrom.h
+-rw-r--r-- root root 53535 ./usr/include/linux/cec-funcs.h
+-rw-r--r-- root root 36389 ./usr/include/linux/cec.h
+-rw-r--r-- root root 2219 ./usr/include/linux/cgroupstats.h
+-rw-r--r-- root root 5344 ./usr/include/linux/chio.h
+drwxr-xr-x root root 4096 ./usr/include/linux/cifs
+-rw-r--r-- root root 1225 ./usr/include/linux/cifs/cifs_mount.h
+-rw-r--r-- root root 1806 ./usr/include/linux/cm4000_cs.h
+-rw-r--r-- root root 3456 ./usr/include/linux/cn_proc.h
+-rw-r--r-- root root 18216 ./usr/include/linux/coda.h
+-rw-r--r-- root root 12549 ./usr/include/linux/coff.h
+-rw-r--r-- root root 2253 ./usr/include/linux/connector.h
+-rw-r--r-- root root 788 ./usr/include/linux/const.h
+-rw-r--r-- root root 674 ./usr/include/linux/coresight-stm.h
+-rw-r--r-- root root 3555 ./usr/include/linux/cramfs_fs.h
+-rw-r--r-- root root 5321 ./usr/include/linux/cryptouser.h
+-rw-r--r-- root root 905 ./usr/include/linux/cuda.h
+-rw-r--r-- root root 17108 ./usr/include/linux/cyclades.h
+-rw-r--r-- root root 2990 ./usr/include/linux/cycx_cfm.h
+-rw-r--r-- root root 25291 ./usr/include/linux/dcbnl.h
+-rw-r--r-- root root 6436 ./usr/include/linux/dccp.h
+-rw-r--r-- root root 14860 ./usr/include/linux/devlink.h
+-rw-r--r-- root root 5080 ./usr/include/linux/dlmconstants.h
+-rw-r--r-- root root 2543 ./usr/include/linux/dlm_device.h
+-rw-r--r-- root root 2553 ./usr/include/linux/dlm.h
+-rw-r--r-- root root 1159 ./usr/include/linux/dlm_netlink.h
+-rw-r--r-- root root 894 ./usr/include/linux/dlm_plock.h
+-rw-r--r-- root root 1448 ./usr/include/linux/dma-buf.h
+-rw-r--r-- root root 10988 ./usr/include/linux/dm-ioctl.h
+-rw-r--r-- root root 15191 ./usr/include/linux/dm-log-userspace.h
+-rw-r--r-- root root 4642 ./usr/include/linux/dn.h
+-rw-r--r-- root root 3949 ./usr/include/linux/dns_resolver.h
+-rw-r--r-- root root 8999 ./usr/include/linux/dqblk_xfs.h
+drwxr-xr-x root root 4096 ./usr/include/linux/dvb
+-rw-r--r-- root root 3550 ./usr/include/linux/dvb/audio.h
+-rw-r--r-- root root 4247 ./usr/include/linux/dvb/ca.h
+-rw-r--r-- root root 10177 ./usr/include/linux/dvb/dmx.h
+-rw-r--r-- root root 29244 ./usr/include/linux/dvb/frontend.h
+-rw-r--r-- root root 2127 ./usr/include/linux/dvb/net.h
+-rw-r--r-- root root 5937 ./usr/include/linux/dvb/osd.h
+-rw-r--r-- root root 1082 ./usr/include/linux/dvb/version.h
+-rw-r--r-- root root 7106 ./usr/include/linux/dvb/video.h
+-rw-r--r-- root root 5604 ./usr/include/linux/edd.h
+-rw-r--r-- root root 2227 ./usr/include/linux/efs_fs_sb.h
+-rw-r--r-- root root 2995 ./usr/include/linux/elfcore.h
+-rw-r--r-- root root 2586 ./usr/include/linux/elf-em.h
+-rw-r--r-- root root 1124 ./usr/include/linux/elf-fdpic.h
+-rw-r--r-- root root 13642 ./usr/include/linux/elf.h
+-rw-r--r-- root root 23 ./usr/include/linux/errno.h
+-rw-r--r-- root root 1572 ./usr/include/linux/errqueue.h
+-rw-r--r-- root root 1059 ./usr/include/linux/erspan.h
+-rw-r--r-- root root 74781 ./usr/include/linux/ethtool.h
+-rw-r--r-- root root 2743 ./usr/include/linux/eventpoll.h
+-rw-r--r-- root root 842 ./usr/include/linux/fadvise.h
+-rw-r--r-- root root 3584 ./usr/include/linux/falloc.h
+-rw-r--r-- root root 5369 ./usr/include/linux/fanotify.h
+-rw-r--r-- root root 16412 ./usr/include/linux/fb.h
+-rw-r--r-- root root 3438 ./usr/include/linux/fcntl.h
+-rw-r--r-- root root 11672 ./usr/include/linux/fd.h
+-rw-r--r-- root root 5420 ./usr/include/linux/fdreg.h
+-rw-r--r-- root root 2036 ./usr/include/linux/fib_rules.h
+-rw-r--r-- root root 2775 ./usr/include/linux/fiemap.h
+-rw-r--r-- root root 2216 ./usr/include/linux/filter.h
+-rw-r--r-- root root 44242 ./usr/include/linux/firewire-cdev.h
+-rw-r--r-- root root 3231 ./usr/include/linux/firewire-constants.h
+-rw-r--r-- root root 894 ./usr/include/linux/fou.h
+-rw-r--r-- root root 6103 ./usr/include/linux/fpga-dfl.h
+-rw-r--r-- root root 6104 ./usr/include/linux/fscrypt.h
+-rw-r--r-- root root 12205 ./usr/include/linux/fs.h
+-rw-r--r-- root root 2255 ./usr/include/linux/fsi.h
+-rw-r--r-- root root 7301 ./usr/include/linux/fsl_hypervisor.h
+-rw-r--r-- root root 4393 ./usr/include/linux/fsmap.h
+-rw-r--r-- root root 931 ./usr/include/linux/fsverity.h
+-rw-r--r-- root root 20407 ./usr/include/linux/fuse.h
+-rw-r--r-- root root 4993 ./usr/include/linux/futex.h
+-rw-r--r-- root root 897 ./usr/include/linux/gameport.h
+-rw-r--r-- root root 1923 ./usr/include/linux/genetlink.h
+-rw-r--r-- root root 1599 ./usr/include/linux/gen_stats.h
+drwxr-xr-x root root 4096 ./usr/include/linux/genwqe
+-rw-r--r-- root root 17802 ./usr/include/linux/genwqe/genwqe_card.h
+-rw-r--r-- root root 14651 ./usr/include/linux/gfs2_ondisk.h
+-rw-r--r-- root root 1442 ./usr/include/linux/gigaset_dev.h
+-rw-r--r-- root root 5753 ./usr/include/linux/gpio.h
+-rw-r--r-- root root 1144 ./usr/include/linux/gsmmux.h
+-rw-r--r-- root root 681 ./usr/include/linux/gtp.h
+-rw-r--r-- root root 971 ./usr/include/linux/hash_info.h
+drwxr-xr-x root root 4096 ./usr/include/linux/hdlc
+-rw-r--r-- root root 2908 ./usr/include/linux/hdlcdrv.h
+-rw-r--r-- root root 637 ./usr/include/linux/hdlc.h
+-rw-r--r-- root root 2657 ./usr/include/linux/hdlc/ioctl.h
+-rw-r--r-- root root 22703 ./usr/include/linux/hdreg.h
+-rw-r--r-- root root 6345 ./usr/include/linux/hiddev.h
+-rw-r--r-- root root 1901 ./usr/include/linux/hid.h
+-rw-r--r-- root root 1511 ./usr/include/linux/hidraw.h
+-rw-r--r-- root root 743 ./usr/include/linux/hpet.h
+drwxr-xr-x root root 4096 ./usr/include/linux/hsi
+-rw-r--r-- root root 3656 ./usr/include/linux/hsi/cs-protocol.h
+-rw-r--r-- root root 1895 ./usr/include/linux/hsi/hsi_char.h
+-rw-r--r-- root root 1081 ./usr/include/linux/hsr_netlink.h
+-rw-r--r-- root root 742 ./usr/include/linux/hw_breakpoint.h
+-rw-r--r-- root root 10569 ./usr/include/linux/hyperv.h
+-rw-r--r-- root root 1382 ./usr/include/linux/hysdn_if.h
+-rw-r--r-- root root 2612 ./usr/include/linux/i2c-dev.h
+-rw-r--r-- root root 7132 ./usr/include/linux/i2c.h
+-rw-r--r-- root root 11555 ./usr/include/linux/i2o-dev.h
+-rw-r--r-- root root 1528 ./usr/include/linux/i8k.h
+-rw-r--r-- root root 2975 ./usr/include/linux/icmp.h
+-rw-r--r-- root root 4083 ./usr/include/linux/icmpv6.h
+-rw-r--r-- root root 1886 ./usr/include/linux/if_addr.h
+-rw-r--r-- root root 721 ./usr/include/linux/if_addrlabel.h
+-rw-r--r-- root root 946 ./usr/include/linux/if_alg.h
+-rw-r--r-- root root 3717 ./usr/include/linux/if_arcnet.h
+-rw-r--r-- root root 6565 ./usr/include/linux/if_arp.h
+-rw-r--r-- root root 4839 ./usr/include/linux/if_bonding.h
+-rw-r--r-- root root 7266 ./usr/include/linux/if_bridge.h
+-rw-r--r-- root root 986 ./usr/include/linux/if_cablemodem.h
+-rw-r--r-- root root 351 ./usr/include/linux/ife.h
+-rw-r--r-- root root 1349 ./usr/include/linux/if_eql.h
+-rw-r--r-- root root 8227 ./usr/include/linux/if_ether.h
+-rw-r--r-- root root 1738 ./usr/include/linux/if_fc.h
+-rw-r--r-- root root 4372 ./usr/include/linux/if_fddi.h
+-rw-r--r-- root root 3019 ./usr/include/linux/if_frad.h
+-rw-r--r-- root root 10813 ./usr/include/linux/if.h
+-rw-r--r-- root root 4235 ./usr/include/linux/if_hippi.h
+-rw-r--r-- root root 1245 ./usr/include/linux/if_infiniband.h
+-rw-r--r-- root root 23649 ./usr/include/linux/if_link.h
+-rw-r--r-- root root 210 ./usr/include/linux/if_ltalk.h
+-rw-r--r-- root root 5832 ./usr/include/linux/if_macsec.h
+-rw-r--r-- root root 7955 ./usr/include/linux/if_packet.h
+-rw-r--r-- root root 424 ./usr/include/linux/if_phonet.h
+-rw-r--r-- root root 660 ./usr/include/linux/if_plip.h
+-rw-r--r-- root root 29 ./usr/include/linux/if_ppp.h
+-rw-r--r-- root root 3292 ./usr/include/linux/if_pppol2tp.h
+-rw-r--r-- root root 4879 ./usr/include/linux/if_pppox.h
+-rw-r--r-- root root 872 ./usr/include/linux/if_slip.h
+-rw-r--r-- root root 2600 ./usr/include/linux/if_team.h
+-rw-r--r-- root root 4098 ./usr/include/linux/if_tun.h
+-rw-r--r-- root root 4512 ./usr/include/linux/if_tunnel.h
+-rw-r--r-- root root 1831 ./usr/include/linux/if_vlan.h
+-rw-r--r-- root root 881 ./usr/include/linux/if_x25.h
+-rw-r--r-- root root 2819 ./usr/include/linux/if_xdp.h
+-rw-r--r-- root root 3064 ./usr/include/linux/igmp.h
+drwxr-xr-x root root 4096 ./usr/include/linux/iio
+-rw-r--r-- root root 1390 ./usr/include/linux/iio/events.h
+-rw-r--r-- root root 2114 ./usr/include/linux/iio/types.h
+-rw-r--r-- root root 1246 ./usr/include/linux/ila.h
+-rw-r--r-- root root 7505 ./usr/include/linux/in6.h
+-rw-r--r-- root root 4540 ./usr/include/linux/inet_diag.h
+-rw-r--r-- root root 9881 ./usr/include/linux/in.h
+-rw-r--r-- root root 3292 ./usr/include/linux/inotify.h
+-rw-r--r-- root root 25218 ./usr/include/linux/input-event-codes.h
+-rw-r--r-- root root 15964 ./usr/include/linux/input.h
+-rw-r--r-- root root 936 ./usr/include/linux/in_route.h
+-rw-r--r-- root root 163 ./usr/include/linux/ioctl.h
+-rw-r--r-- root root 4578 ./usr/include/linux/iommu.h
+-rw-r--r-- root root 3478 ./usr/include/linux/io_uring.h
+-rw-r--r-- root root 1953 ./usr/include/linux/ip6_tunnel.h
+-rw-r--r-- root root 2101 ./usr/include/linux/ipc.h
+-rw-r--r-- root root 4728 ./usr/include/linux/ip.h
+-rw-r--r-- root root 488 ./usr/include/linux/ipmi_bmc.h
+-rw-r--r-- root root 15049 ./usr/include/linux/ipmi.h
+-rw-r--r-- root root 3350 ./usr/include/linux/ipmi_msgdefs.h
+-rw-r--r-- root root 947 ./usr/include/linux/ipsec.h
+-rw-r--r-- root root 3967 ./usr/include/linux/ipv6.h
+-rw-r--r-- root root 1908 ./usr/include/linux/ipv6_route.h
+-rw-r--r-- root root 14135 ./usr/include/linux/ip_vs.h
+-rw-r--r-- root root 2347 ./usr/include/linux/ipx.h
+-rw-r--r-- root root 104 ./usr/include/linux/irqnr.h
+drwxr-xr-x root root 4096 ./usr/include/linux/isdn
+-rw-r--r-- root root 4783 ./usr/include/linux/isdn/capicmd.h
+-rw-r--r-- root root 6485 ./usr/include/linux/iso_fs.h
+-rw-r--r-- root root 5408 ./usr/include/linux/isst_if.h
+-rw-r--r-- root root 1207 ./usr/include/linux/ivtvfb.h
+-rw-r--r-- root root 3022 ./usr/include/linux/ivtv.h
+-rw-r--r-- root root 6815 ./usr/include/linux/jffs2.h
+-rw-r--r-- root root 3434 ./usr/include/linux/joystick.h
+-rw-r--r-- root root 822 ./usr/include/linux/kcm.h
+-rw-r--r-- root root 522 ./usr/include/linux/kcmp.h
+-rw-r--r-- root root 1099 ./usr/include/linux/kcov.h
+-rw-r--r-- root root 383 ./usr/include/linux/kdev_t.h
+-rw-r--r-- root root 6253 ./usr/include/linux/kd.h
+-rw-r--r-- root root 1019 ./usr/include/linux/kernelcapi.h
+-rw-r--r-- root root 438 ./usr/include/linux/kernel.h
+-rw-r--r-- root root 900 ./usr/include/linux/kernel-page-flags.h
+-rw-r--r-- root root 1873 ./usr/include/linux/kexec.h
+-rw-r--r-- root root 13459 ./usr/include/linux/keyboard.h
+-rw-r--r-- root root 5837 ./usr/include/linux/keyctl.h
+-rw-r--r-- root root 16263 ./usr/include/linux/kfd_ioctl.h
+-rw-r--r-- root root 46258 ./usr/include/linux/kvm.h
+-rw-r--r-- root root 968 ./usr/include/linux/kvm_para.h
+-rw-r--r-- root root 5672 ./usr/include/linux/l2tp.h
+-rw-r--r-- root root 8289 ./usr/include/linux/libc-compat.h
+-rw-r--r-- root root 5042 ./usr/include/linux/lightnvm.h
+-rw-r--r-- root root 937 ./usr/include/linux/limits.h
+-rw-r--r-- root root 8102 ./usr/include/linux/lirc.h
+-rw-r--r-- root root 3164 ./usr/include/linux/llc.h
+-rw-r--r-- root root 2520 ./usr/include/linux/loop.h
+-rw-r--r-- root root 4190 ./usr/include/linux/lp.h
+-rw-r--r-- root root 1273 ./usr/include/linux/lwtunnel.h
+-rw-r--r-- root root 3604 ./usr/include/linux/magic.h
+-rw-r--r-- root root 4713 ./usr/include/linux/major.h
+-rw-r--r-- root root 7251 ./usr/include/linux/map_to_7segment.h
+-rw-r--r-- root root 1464 ./usr/include/linux/matroxfb.h
+-rw-r--r-- root root 1035 ./usr/include/linux/max2175.h
+-rw-r--r-- root root 15645 ./usr/include/linux/mdio.h
+-rw-r--r-- root root 6540 ./usr/include/linux/media-bus-format.h
+-rw-r--r-- root root 12641 ./usr/include/linux/media.h
+-rw-r--r-- root root 1993 ./usr/include/linux/mei.h
+-rw-r--r-- root root 7899 ./usr/include/linux/membarrier.h
+-rw-r--r-- root root 1324 ./usr/include/linux/memfd.h
+-rw-r--r-- root root 2154 ./usr/include/linux/mempolicy.h
+-rw-r--r-- root root 2529 ./usr/include/linux/meye.h
+-rw-r--r-- root root 6519 ./usr/include/linux/mic_common.h
+-rw-r--r-- root root 2252 ./usr/include/linux/mic_ioctl.h
+-rw-r--r-- root root 8281 ./usr/include/linux/mii.h
+-rw-r--r-- root root 2122 ./usr/include/linux/minix_fs.h
+-rw-r--r-- root root 1508 ./usr/include/linux/mman.h
+drwxr-xr-x root root 4096 ./usr/include/linux/mmc
+-rw-r--r-- root root 2331 ./usr/include/linux/mmc/ioctl.h
+-rw-r--r-- root root 2117 ./usr/include/linux/mmtimer.h
+-rw-r--r-- root root 255 ./usr/include/linux/module.h
+-rw-r--r-- root root 4546 ./usr/include/linux/mount.h
+-rw-r--r-- root root 2302 ./usr/include/linux/mpls.h
+-rw-r--r-- root root 761 ./usr/include/linux/mpls_iptunnel.h
+-rw-r--r-- root root 2201 ./usr/include/linux/mqueue.h
+-rw-r--r-- root root 4931 ./usr/include/linux/mroute6.h
+-rw-r--r-- root root 5881 ./usr/include/linux/mroute.h
+-rw-r--r-- root root 6731 ./usr/include/linux/msdos_fs.h
+-rw-r--r-- root root 3374 ./usr/include/linux/msg.h
+-rw-r--r-- root root 8175 ./usr/include/linux/mtio.h
+-rw-r--r-- root root 3024 ./usr/include/linux/nbd.h
+-rw-r--r-- root root 2378 ./usr/include/linux/nbd-netlink.h
+-rw-r--r-- root root 4828 ./usr/include/linux/ncsi.h
+-rw-r--r-- root root 6770 ./usr/include/linux/ndctl.h
+-rw-r--r-- root root 4406 ./usr/include/linux/neighbour.h
+-rw-r--r-- root root 614 ./usr/include/linux/netconf.h
+-rw-r--r-- root root 2253 ./usr/include/linux/netdevice.h
+-rw-r--r-- root root 2839 ./usr/include/linux/net_dropmon.h
+drwxr-xr-x root root 4096 ./usr/include/linux/netfilter
+drwxr-xr-x root root 4096 ./usr/include/linux/netfilter_arp
+-rw-r--r-- root root 5999 ./usr/include/linux/netfilter_arp/arp_tables.h
+-rw-r--r-- root root 606 ./usr/include/linux/netfilter_arp/arpt_mangle.h
+-rw-r--r-- root root 445 ./usr/include/linux/netfilter_arp.h
+drwxr-xr-x root root 4096 ./usr/include/linux/netfilter_bridge
+-rw-r--r-- root root 1274 ./usr/include/linux/netfilter_bridge/ebt_802_3.h
+-rw-r--r-- root root 9308 ./usr/include/linux/netfilter_bridge/ebtables.h
+-rw-r--r-- root root 2043 ./usr/include/linux/netfilter_bridge/ebt_among.h
+-rw-r--r-- root root 900 ./usr/include/linux/netfilter_bridge/ebt_arp.h
+-rw-r--r-- root root 289 ./usr/include/linux/netfilter_bridge/ebt_arpreply.h
+-rw-r--r-- root root 1056 ./usr/include/linux/netfilter_bridge/ebt_ip6.h
+-rw-r--r-- root root 1094 ./usr/include/linux/netfilter_bridge/ebt_ip.h
+-rw-r--r-- root root 616 ./usr/include/linux/netfilter_bridge/ebt_limit.h
+-rw-r--r-- root root 538 ./usr/include/linux/netfilter_bridge/ebt_log.h
+-rw-r--r-- root root 388 ./usr/include/linux/netfilter_bridge/ebt_mark_m.h
+-rw-r--r-- root root 831 ./usr/include/linux/netfilter_bridge/ebt_mark_t.h
+-rw-r--r-- root root 387 ./usr/include/linux/netfilter_bridge/ebt_nat.h
+-rw-r--r-- root root 510 ./usr/include/linux/netfilter_bridge/ebt_nflog.h
+-rw-r--r-- root root 267 ./usr/include/linux/netfilter_bridge/ebt_pkttype.h
+-rw-r--r-- root root 286 ./usr/include/linux/netfilter_bridge/ebt_redirect.h
+-rw-r--r-- root root 1110 ./usr/include/linux/netfilter_bridge/ebt_stp.h
+-rw-r--r-- root root 719 ./usr/include/linux/netfilter_bridge/ebt_vlan.h
+-rw-r--r-- root root 1168 ./usr/include/linux/netfilter_bridge.h
+-rw-r--r-- root root 1758 ./usr/include/linux/netfilter_decnet.h
+-rw-r--r-- root root 1674 ./usr/include/linux/netfilter.h
+drwxr-xr-x root root 4096 ./usr/include/linux/netfilter/ipset
+-rw-r--r-- root root 428 ./usr/include/linux/netfilter/ipset/ip_set_bitmap.h
+-rw-r--r-- root root 9108 ./usr/include/linux/netfilter/ipset/ip_set.h
+-rw-r--r-- root root 578 ./usr/include/linux/netfilter/ipset/ip_set_hash.h
+-rw-r--r-- root root 609 ./usr/include/linux/netfilter/ipset/ip_set_list.h
+drwxr-xr-x root root 4096 ./usr/include/linux/netfilter_ipv4
+-rw-r--r-- root root 1488 ./usr/include/linux/netfilter_ipv4.h
+-rw-r--r-- root root 6647 ./usr/include/linux/netfilter_ipv4/ip_tables.h
+-rw-r--r-- root root 425 ./usr/include/linux/netfilter_ipv4/ipt_ah.h
+-rw-r--r-- root root 821 ./usr/include/linux/netfilter_ipv4/ipt_CLUSTERIP.h
+-rw-r--r-- root root 431 ./usr/include/linux/netfilter_ipv4/ipt_ecn.h
+-rw-r--r-- root root 901 ./usr/include/linux/netfilter_ipv4/ipt_ECN.h
+-rw-r--r-- root root 654 ./usr/include/linux/netfilter_ipv4/ipt_LOG.h
+-rw-r--r-- root root 468 ./usr/include/linux/netfilter_ipv4/ipt_REJECT.h
+-rw-r--r-- root root 431 ./usr/include/linux/netfilter_ipv4/ipt_ttl.h
+-rw-r--r-- root root 375 ./usr/include/linux/netfilter_ipv4/ipt_TTL.h
+drwxr-xr-x root root 4096 ./usr/include/linux/netfilter_ipv6
+-rw-r--r-- root root 1383 ./usr/include/linux/netfilter_ipv6.h
+-rw-r--r-- root root 8011 ./usr/include/linux/netfilter_ipv6/ip6_tables.h
+-rw-r--r-- root root 657 ./usr/include/linux/netfilter_ipv6/ip6t_ah.h
+-rw-r--r-- root root 744 ./usr/include/linux/netfilter_ipv6/ip6t_frag.h
+-rw-r--r-- root root 458 ./usr/include/linux/netfilter_ipv6/ip6t_hl.h
+-rw-r--r-- root root 408 ./usr/include/linux/netfilter_ipv6/ip6t_HL.h
+-rw-r--r-- root root 645 ./usr/include/linux/netfilter_ipv6/ip6t_ipv6header.h
+-rw-r--r-- root root 662 ./usr/include/linux/netfilter_ipv6/ip6t_LOG.h
+-rw-r--r-- root root 439 ./usr/include/linux/netfilter_ipv6/ip6t_mh.h
+-rw-r--r-- root root 400 ./usr/include/linux/netfilter_ipv6/ip6t_NPT.h
+-rw-r--r-- root root 649 ./usr/include/linux/netfilter_ipv6/ip6t_opts.h
+-rw-r--r-- root root 470 ./usr/include/linux/netfilter_ipv6/ip6t_REJECT.h
+-rw-r--r-- root root 985 ./usr/include/linux/netfilter_ipv6/ip6t_rt.h
+-rw-r--r-- root root 3305 ./usr/include/linux/netfilter_ipv6/ip6t_srh.h
+-rw-r--r-- root root 4421 ./usr/include/linux/netfilter/nf_conntrack_common.h
+-rw-r--r-- root root 438 ./usr/include/linux/netfilter/nf_conntrack_ftp.h
+-rw-r--r-- root root 576 ./usr/include/linux/netfilter/nf_conntrack_sctp.h
+-rw-r--r-- root root 1415 ./usr/include/linux/netfilter/nf_conntrack_tcp.h
+-rw-r--r-- root root 896 ./usr/include/linux/netfilter/nf_conntrack_tuple_common.h
+-rw-r--r-- root root 538 ./usr/include/linux/netfilter/nf_log.h
+-rw-r--r-- root root 1522 ./usr/include/linux/netfilter/nf_nat.h
+-rw-r--r-- root root 900 ./usr/include/linux/netfilter/nfnetlink_acct.h
+-rw-r--r-- root root 2444 ./usr/include/linux/netfilter/nfnetlink_compat.h
+-rw-r--r-- root root 5924 ./usr/include/linux/netfilter/nfnetlink_conntrack.h
+-rw-r--r-- root root 1202 ./usr/include/linux/netfilter/nfnetlink_cthelper.h
+-rw-r--r-- root root 2930 ./usr/include/linux/netfilter/nfnetlink_cttimeout.h
+-rw-r--r-- root root 2428 ./usr/include/linux/netfilter/nfnetlink.h
+-rw-r--r-- root root 3106 ./usr/include/linux/netfilter/nfnetlink_log.h
+-rw-r--r-- root root 2665 ./usr/include/linux/netfilter/nfnetlink_osf.h
+-rw-r--r-- root root 3499 ./usr/include/linux/netfilter/nfnetlink_queue.h
+-rw-r--r-- root root 576 ./usr/include/linux/netfilter/nf_synproxy.h
+-rw-r--r-- root root 731 ./usr/include/linux/netfilter/nf_tables_compat.h
+-rw-r--r-- root root 51835 ./usr/include/linux/netfilter/nf_tables.h
+-rw-r--r-- root root 4467 ./usr/include/linux/netfilter/x_tables.h
+-rw-r--r-- root root 1084 ./usr/include/linux/netfilter/xt_addrtype.h
+-rw-r--r-- root root 718 ./usr/include/linux/netfilter/xt_AUDIT.h
+-rw-r--r-- root root 935 ./usr/include/linux/netfilter/xt_bpf.h
+-rw-r--r-- root root 740 ./usr/include/linux/netfilter/xt_cgroup.h
+-rw-r--r-- root root 563 ./usr/include/linux/netfilter/xt_CHECKSUM.h
+-rw-r--r-- root root 217 ./usr/include/linux/netfilter/xt_CLASSIFY.h
+-rw-r--r-- root root 374 ./usr/include/linux/netfilter/xt_cluster.h
+-rw-r--r-- root root 230 ./usr/include/linux/netfilter/xt_comment.h
+-rw-r--r-- root root 577 ./usr/include/linux/netfilter/xt_connbytes.h
+-rw-r--r-- root root 360 ./usr/include/linux/netfilter/xt_connlabel.h
+-rw-r--r-- root root 575 ./usr/include/linux/netfilter/xt_connlimit.h
+-rw-r--r-- root root 900 ./usr/include/linux/netfilter/xt_connmark.h
+-rw-r--r-- root root 199 ./usr/include/linux/netfilter/xt_CONNMARK.h
+-rw-r--r-- root root 301 ./usr/include/linux/netfilter/xt_CONNSECMARK.h
+-rw-r--r-- root root 2557 ./usr/include/linux/netfilter/xt_conntrack.h
+-rw-r--r-- root root 199 ./usr/include/linux/netfilter/xt_cpu.h
+-rw-r--r-- root root 853 ./usr/include/linux/netfilter/xt_CT.h
+-rw-r--r-- root root 483 ./usr/include/linux/netfilter/xt_dccp.h
+-rw-r--r-- root root 429 ./usr/include/linux/netfilter/xt_devgroup.h
+-rw-r--r-- root root 701 ./usr/include/linux/netfilter/xt_dscp.h
+-rw-r--r-- root root 697 ./usr/include/linux/netfilter/xt_DSCP.h
+-rw-r--r-- root root 736 ./usr/include/linux/netfilter/xt_ecn.h
+-rw-r--r-- root root 418 ./usr/include/linux/netfilter/xt_esp.h
+-rw-r--r-- root root 3256 ./usr/include/linux/netfilter/xt_hashlimit.h
+-rw-r--r-- root root 188 ./usr/include/linux/netfilter/xt_helper.h
+-rw-r--r-- root root 933 ./usr/include/linux/netfilter/xt_HMARK.h
+-rw-r--r-- root root 1393 ./usr/include/linux/netfilter/xt_IDLETIMER.h
+-rw-r--r-- root root 485 ./usr/include/linux/netfilter/xt_ipcomp.h
+-rw-r--r-- root root 581 ./usr/include/linux/netfilter/xt_iprange.h
+-rw-r--r-- root root 680 ./usr/include/linux/netfilter/xt_ipvs.h
+-rw-r--r-- root root 739 ./usr/include/linux/netfilter/xt_l2tp.h
+-rw-r--r-- root root 470 ./usr/include/linux/netfilter/xt_LED.h
+-rw-r--r-- root root 221 ./usr/include/linux/netfilter/xt_length.h
+-rw-r--r-- root root 673 ./usr/include/linux/netfilter/xt_limit.h
+-rw-r--r-- root root 642 ./usr/include/linux/netfilter/xt_LOG.h
+-rw-r--r-- root root 227 ./usr/include/linux/netfilter/xt_mac.h
+-rw-r--r-- root root 260 ./usr/include/linux/netfilter/xt_mark.h
+-rw-r--r-- root root 184 ./usr/include/linux/netfilter/xt_MARK.h
+-rw-r--r-- root root 721 ./usr/include/linux/netfilter/xt_multiport.h
+-rw-r--r-- root root 421 ./usr/include/linux/netfilter/xt_nfacct.h
+-rw-r--r-- root root 556 ./usr/include/linux/netfilter/xt_NFLOG.h
+-rw-r--r-- root root 779 ./usr/include/linux/netfilter/xt_NFQUEUE.h
+-rw-r--r-- root root 1703 ./usr/include/linux/netfilter/xt_osf.h
+-rw-r--r-- root root 535 ./usr/include/linux/netfilter/xt_owner.h
+-rw-r--r-- root root 553 ./usr/include/linux/netfilter/xt_physdev.h
+-rw-r--r-- root root 188 ./usr/include/linux/netfilter/xt_pkttype.h
+-rw-r--r-- root root 1051 ./usr/include/linux/netfilter/xt_policy.h
+-rw-r--r-- root root 400 ./usr/include/linux/netfilter/xt_quota.h
+-rw-r--r-- root root 859 ./usr/include/linux/netfilter/xt_rateest.h
+-rw-r--r-- root root 390 ./usr/include/linux/netfilter/xt_RATEEST.h
+-rw-r--r-- root root 220 ./usr/include/linux/netfilter/xt_realm.h
+-rw-r--r-- root root 1058 ./usr/include/linux/netfilter/xt_recent.h
+-rw-r--r-- root root 320 ./usr/include/linux/netfilter/xt_rpfilter.h
+-rw-r--r-- root root 2326 ./usr/include/linux/netfilter/xt_sctp.h
+-rw-r--r-- root root 549 ./usr/include/linux/netfilter/xt_SECMARK.h
+-rw-r--r-- root root 1827 ./usr/include/linux/netfilter/xt_set.h
+-rw-r--r-- root root 640 ./usr/include/linux/netfilter/xt_socket.h
+-rw-r--r-- root root 331 ./usr/include/linux/netfilter/xt_state.h
+-rw-r--r-- root root 716 ./usr/include/linux/netfilter/xt_statistic.h
+-rw-r--r-- root root 664 ./usr/include/linux/netfilter/xt_string.h
+-rw-r--r-- root root 498 ./usr/include/linux/netfilter/xt_SYNPROXY.h
+-rw-r--r-- root root 253 ./usr/include/linux/netfilter/xt_tcpmss.h
+-rw-r--r-- root root 235 ./usr/include/linux/netfilter/xt_TCPMSS.h
+-rw-r--r-- root root 407 ./usr/include/linux/netfilter/xt_TCPOPTSTRIP.h
+-rw-r--r-- root root 1250 ./usr/include/linux/netfilter/xt_tcpudp.h
+-rw-r--r-- root root 333 ./usr/include/linux/netfilter/xt_TEE.h
+-rw-r--r-- root root 730 ./usr/include/linux/netfilter/xt_time.h
+-rw-r--r-- root root 575 ./usr/include/linux/netfilter/xt_TPROXY.h
+-rw-r--r-- root root 752 ./usr/include/linux/netfilter/xt_u32.h
+-rw-r--r-- root root 2085 ./usr/include/linux/net.h
+-rw-r--r-- root root 1524 ./usr/include/linux/netlink_diag.h
+-rw-r--r-- root root 7825 ./usr/include/linux/netlink.h
+-rw-r--r-- root root 715 ./usr/include/linux/net_namespace.h
+-rw-r--r-- root root 807 ./usr/include/linux/netrom.h
+-rw-r--r-- root root 4914 ./usr/include/linux/net_tstamp.h
+-rw-r--r-- root root 1534 ./usr/include/linux/nexthop.h
+-rw-r--r-- root root 11209 ./usr/include/linux/nfc.h
+-rw-r--r-- root root 1468 ./usr/include/linux/nfs2.h
+-rw-r--r-- root root 2359 ./usr/include/linux/nfs3.h
+-rw-r--r-- root root 6338 ./usr/include/linux/nfs4.h
+-rw-r--r-- root root 1932 ./usr/include/linux/nfs4_mount.h
+-rw-r--r-- root root 668 ./usr/include/linux/nfsacl.h
+drwxr-xr-x root root 4096 ./usr/include/linux/nfsd
+-rw-r--r-- root root 3122 ./usr/include/linux/nfsd/cld.h
+-rw-r--r-- root root 736 ./usr/include/linux/nfsd/debug.h
+-rw-r--r-- root root 2113 ./usr/include/linux/nfsd/export.h
+-rw-r--r-- root root 3517 ./usr/include/linux/nfsd/nfsfh.h
+-rw-r--r-- root root 421 ./usr/include/linux/nfsd/stats.h
+-rw-r--r-- root root 1608 ./usr/include/linux/nfs_fs.h
+-rw-r--r-- root root 4500 ./usr/include/linux/nfs.h
+-rw-r--r-- root root 2243 ./usr/include/linux/nfs_idmap.h
+-rw-r--r-- root root 2142 ./usr/include/linux/nfs_mount.h
+-rw-r--r-- root root 7589 ./usr/include/linux/nilfs2_api.h
+-rw-r--r-- root root 18085 ./usr/include/linux/nilfs2_ondisk.h
+-rw-r--r-- root root 280715 ./usr/include/linux/nl80211.h
+-rw-r--r-- root root 2410 ./usr/include/linux/n_r3964.h
+-rw-r--r-- root root 639 ./usr/include/linux/nsfs.h
+-rw-r--r-- root root 8191 ./usr/include/linux/nubus.h
+-rw-r--r-- root root 1661 ./usr/include/linux/nvme_ioctl.h
+-rw-r--r-- root root 532 ./usr/include/linux/nvram.h
+-rw-r--r-- root root 20853 ./usr/include/linux/omap3isp.h
+-rw-r--r-- root root 5918 ./usr/include/linux/omapfb.h
+-rw-r--r-- root root 511 ./usr/include/linux/oom.h
+-rw-r--r-- root root 37676 ./usr/include/linux/openvswitch.h
+-rw-r--r-- root root 1672 ./usr/include/linux/packet_diag.h
+-rw-r--r-- root root 141 ./usr/include/linux/param.h
+-rw-r--r-- root root 3644 ./usr/include/linux/parport.h
+-rw-r--r-- root root 892 ./usr/include/linux/patchkey.h
+-rw-r--r-- root root 1380 ./usr/include/linux/pci.h
+-rw-r--r-- root root 56733 ./usr/include/linux/pci_regs.h
+-rw-r--r-- root root 711 ./usr/include/linux/pcitest.h
+-rw-r--r-- root root 34228 ./usr/include/linux/perf_event.h
+-rw-r--r-- root root 2097 ./usr/include/linux/personality.h
+-rw-r--r-- root root 10569 ./usr/include/linux/pfkeyv2.h
+-rw-r--r-- root root 2394 ./usr/include/linux/pg.h
+-rw-r--r-- root root 1654 ./usr/include/linux/phantom.h
+-rw-r--r-- root root 4677 ./usr/include/linux/phonet.h
+-rw-r--r-- root root 2687 ./usr/include/linux/pktcdvd.h
+-rw-r--r-- root root 15441 ./usr/include/linux/pkt_cls.h
+-rw-r--r-- root root 27648 ./usr/include/linux/pkt_sched.h
+-rw-r--r-- root root 5444 ./usr/include/linux/pmu.h
+-rw-r--r-- root root 22 ./usr/include/linux/poll.h
+-rw-r--r-- root root 1254 ./usr/include/linux/posix_acl.h
+-rw-r--r-- root root 1115 ./usr/include/linux/posix_acl_xattr.h
+-rw-r--r-- root root 1098 ./usr/include/linux/posix_types.h
+-rw-r--r-- root root 3285 ./usr/include/linux/ppdev.h
+-rw-r--r-- root root 2527 ./usr/include/linux/ppp-comp.h
+-rw-r--r-- root root 5107 ./usr/include/linux/ppp_defs.h
+-rw-r--r-- root root 5438 ./usr/include/linux/ppp-ioctl.h
+-rw-r--r-- root root 4734 ./usr/include/linux/pps.h
+-rw-r--r-- root root 8073 ./usr/include/linux/prctl.h
+-rw-r--r-- root root 1073 ./usr/include/linux/pr.h
+-rw-r--r-- root root 798 ./usr/include/linux/psample.h
+-rw-r--r-- root root 4328 ./usr/include/linux/psci.h
+-rw-r--r-- root root 4036 ./usr/include/linux/psp-sev.h
+-rw-r--r-- root root 6731 ./usr/include/linux/ptp_clock.h
+-rw-r--r-- root root 4265 ./usr/include/linux/ptrace.h
+-rw-r--r-- root root 2469 ./usr/include/linux/qemu_fw_cfg.h
+-rw-r--r-- root root 2328 ./usr/include/linux/qnx4_fs.h
+-rw-r--r-- root root 624 ./usr/include/linux/qnxtypes.h
+-rw-r--r-- root root 893 ./usr/include/linux/qrtr.h
+-rw-r--r-- root root 6291 ./usr/include/linux/quota.h
+-rw-r--r-- root root 360 ./usr/include/linux/radeonfb.h
+drwxr-xr-x root root 4096 ./usr/include/linux/raid
+-rw-r--r-- root root 16161 ./usr/include/linux/raid/md_p.h
+-rw-r--r-- root root 4484 ./usr/include/linux/raid/md_u.h
+-rw-r--r-- root root 1370 ./usr/include/linux/random.h
+-rw-r--r-- root root 365 ./usr/include/linux/raw.h
+-rw-r--r-- root root 11081 ./usr/include/linux/rds.h
+-rw-r--r-- root root 1343 ./usr/include/linux/reboot.h
+-rw-r--r-- root root 775 ./usr/include/linux/reiserfs_fs.h
+-rw-r--r-- root root 533 ./usr/include/linux/reiserfs_xattr.h
+-rw-r--r-- root root 2347 ./usr/include/linux/resource.h
+-rw-r--r-- root root 3682 ./usr/include/linux/rfkill.h
+-rw-r--r-- root root 3248 ./usr/include/linux/rio_cm_cdev.h
+-rw-r--r-- root root 9330 ./usr/include/linux/rio_mport_cdev.h
+-rw-r--r-- root root 1238 ./usr/include/linux/romfs_fs.h
+-rw-r--r-- root root 2232 ./usr/include/linux/rose.h
+-rw-r--r-- root root 2332 ./usr/include/linux/route.h
+-rw-r--r-- root root 544 ./usr/include/linux/rpmsg.h
+-rw-r--r-- root root 4904 ./usr/include/linux/rseq.h
+-rw-r--r-- root root 4009 ./usr/include/linux/rtc.h
+-rw-r--r-- root root 19055 ./usr/include/linux/rtnetlink.h
+-rw-r--r-- root root 4897 ./usr/include/linux/rxrpc.h
+-rw-r--r-- root root 4597 ./usr/include/linux/scc.h
+drwxr-xr-x root root 4096 ./usr/include/linux/sched
+-rw-r--r-- root root 4647 ./usr/include/linux/sched.h
+-rw-r--r-- root root 4480 ./usr/include/linux/sched/types.h
+-rw-r--r-- root root 6382 ./usr/include/linux/scif_ioctl.h
+-rw-r--r-- root root 2479 ./usr/include/linux/screen_info.h
+-rw-r--r-- root root 34783 ./usr/include/linux/sctp.h
+-rw-r--r-- root root 2839 ./usr/include/linux/sdla.h
+-rw-r--r-- root root 3235 ./usr/include/linux/seccomp.h
+-rw-r--r-- root root 2704 ./usr/include/linux/securebits.h
+-rw-r--r-- root root 3297 ./usr/include/linux/sed-opal.h
+-rw-r--r-- root root 589 ./usr/include/linux/seg6_genl.h
+-rw-r--r-- root root 1170 ./usr/include/linux/seg6.h
+-rw-r--r-- root root 423 ./usr/include/linux/seg6_hmac.h
+-rw-r--r-- root root 927 ./usr/include/linux/seg6_iptunnel.h
+-rw-r--r-- root root 2060 ./usr/include/linux/seg6_local.h
+-rw-r--r-- root root 1195 ./usr/include/linux/selinux_netlink.h
+-rw-r--r-- root root 3043 ./usr/include/linux/sem.h
+-rw-r--r-- root root 6436 ./usr/include/linux/serial_core.h
+-rw-r--r-- root root 3866 ./usr/include/linux/serial.h
+-rw-r--r-- root root 15496 ./usr/include/linux/serial_reg.h
+-rw-r--r-- root root 2063 ./usr/include/linux/serio.h
+-rw-r--r-- root root 3785 ./usr/include/linux/shm.h
+-rw-r--r-- root root 1233 ./usr/include/linux/signalfd.h
+-rw-r--r-- root root 388 ./usr/include/linux/signal.h
+-rw-r--r-- root root 2835 ./usr/include/linux/smc_diag.h
+-rw-r--r-- root root 780 ./usr/include/linux/smc.h
+-rw-r--r-- root root 1058 ./usr/include/linux/smiapp.h
+-rw-r--r-- root root 13014 ./usr/include/linux/snmp.h
+-rw-r--r-- root root 727 ./usr/include/linux/sock_diag.h
+-rw-r--r-- root root 819 ./usr/include/linux/socket.h
+-rw-r--r-- root root 6846 ./usr/include/linux/sockios.h
+-rw-r--r-- root root 2290 ./usr/include/linux/sonet.h
+-rw-r--r-- root root 5309 ./usr/include/linux/sonypi.h
+-rw-r--r-- root root 46038 ./usr/include/linux/soundcard.h
+-rw-r--r-- root root 1237 ./usr/include/linux/sound.h
+drwxr-xr-x root root 4096 ./usr/include/linux/spi
+-rw-r--r-- root root 5286 ./usr/include/linux/spi/spidev.h
+-rw-r--r-- root root 6100 ./usr/include/linux/stat.h
+-rw-r--r-- root root 131 ./usr/include/linux/stddef.h
+-rw-r--r-- root root 1275 ./usr/include/linux/stm.h
+-rw-r--r-- root root 238 ./usr/include/linux/string.h
+drwxr-xr-x root root 4096 ./usr/include/linux/sunrpc
+-rw-r--r-- root root 1144 ./usr/include/linux/sunrpc/debug.h
+-rw-r--r-- root root 1431 ./usr/include/linux/suspend_ioctls.h
+-rw-r--r-- root root 6711 ./usr/include/linux/swab.h
+-rw-r--r-- root root 4768 ./usr/include/linux/switchtec_ioctl.h
+-rw-r--r-- root root 2883 ./usr/include/linux/sync_file.h
+-rw-r--r-- root root 8985 ./usr/include/linux/synclink.h
+-rw-r--r-- root root 25880 ./usr/include/linux/sysctl.h
+-rw-r--r-- root root 1049 ./usr/include/linux/sysinfo.h
+-rw-r--r-- root root 3899 ./usr/include/linux/target_core_user.h
+-rw-r--r-- root root 7152 ./usr/include/linux/taskstats.h
+drwxr-xr-x root root 4096 ./usr/include/linux/tc_act
+-rw-r--r-- root root 764 ./usr/include/linux/tc_act/tc_bpf.h
+-rw-r--r-- root root 390 ./usr/include/linux/tc_act/tc_connmark.h
+-rw-r--r-- root root 644 ./usr/include/linux/tc_act/tc_csum.h
+-rw-r--r-- root root 934 ./usr/include/linux/tc_act/tc_ct.h
+-rw-r--r-- root root 556 ./usr/include/linux/tc_act/tc_ctinfo.h
+-rw-r--r-- root root 322 ./usr/include/linux/tc_act/tc_defact.h
+-rw-r--r-- root root 626 ./usr/include/linux/tc_act/tc_gact.h
+-rw-r--r-- root root 600 ./usr/include/linux/tc_act/tc_ife.h
+-rw-r--r-- root root 415 ./usr/include/linux/tc_act/tc_ipt.h
+-rw-r--r-- root root 728 ./usr/include/linux/tc_act/tc_mirred.h
+-rw-r--r-- root root 992 ./usr/include/linux/tc_act/tc_mpls.h
+-rw-r--r-- root root 424 ./usr/include/linux/tc_act/tc_nat.h
+-rw-r--r-- root root 1527 ./usr/include/linux/tc_act/tc_pedit.h
+-rw-r--r-- root root 456 ./usr/include/linux/tc_act/tc_sample.h
+-rw-r--r-- root root 1443 ./usr/include/linux/tc_act/tc_skbedit.h
+-rw-r--r-- root root 815 ./usr/include/linux/tc_act/tc_skbmod.h
+-rw-r--r-- root root 1898 ./usr/include/linux/tc_act/tc_tunnel_key.h
+-rw-r--r-- root root 816 ./usr/include/linux/tc_act/tc_vlan.h
+drwxr-xr-x root root 4096 ./usr/include/linux/tc_ematch
+-rw-r--r-- root root 414 ./usr/include/linux/tc_ematch/tc_em_cmp.h
+-rw-r--r-- root root 391 ./usr/include/linux/tc_ematch/tc_em_ipt.h
+-rw-r--r-- root root 2116 ./usr/include/linux/tc_ematch/tc_em_meta.h
+-rw-r--r-- root root 255 ./usr/include/linux/tc_ematch/tc_em_nbyte.h
+-rw-r--r-- root root 384 ./usr/include/linux/tc_ematch/tc_em_text.h
+-rw-r--r-- root root 10857 ./usr/include/linux/tcp.h
+-rw-r--r-- root root 1549 ./usr/include/linux/tcp_metrics.h
+-rw-r--r-- root root 12581 ./usr/include/linux/tee.h
+-rw-r--r-- root root 506 ./usr/include/linux/termios.h
+-rw-r--r-- root root 924 ./usr/include/linux/thermal.h
+-rw-r--r-- root root 1748 ./usr/include/linux/time.h
+-rw-r--r-- root root 936 ./usr/include/linux/timerfd.h
+-rw-r--r-- root root 278 ./usr/include/linux/times.h
+-rw-r--r-- root root 996 ./usr/include/linux/time_types.h
+-rw-r--r-- root root 7817 ./usr/include/linux/timex.h
+-rw-r--r-- root root 1729 ./usr/include/linux/tiocl.h
+-rw-r--r-- root root 14848 ./usr/include/linux/tipc_config.h
+-rw-r--r-- root root 8272 ./usr/include/linux/tipc.h
+-rw-r--r-- root root 9156 ./usr/include/linux/tipc_netlink.h
+-rw-r--r-- root root 468 ./usr/include/linux/tipc_sockets_diag.h
+-rw-r--r-- root root 4288 ./usr/include/linux/tls.h
+-rw-r--r-- root root 1930 ./usr/include/linux/toshiba.h
+-rw-r--r-- root root 4527 ./usr/include/linux/tty_flags.h
+-rw-r--r-- root root 1585 ./usr/include/linux/tty.h
+-rw-r--r-- root root 1476 ./usr/include/linux/types.h
+-rw-r--r-- root root 697 ./usr/include/linux/udf_fs_i.h
+-rw-r--r-- root root 643 ./usr/include/linux/udmabuf.h
+-rw-r--r-- root root 1613 ./usr/include/linux/udp.h
+-rw-r--r-- root root 4648 ./usr/include/linux/uhid.h
+-rw-r--r-- root root 9261 ./usr/include/linux/uinput.h
+-rw-r--r-- root root 732 ./usr/include/linux/uio.h
+-rw-r--r-- root root 798 ./usr/include/linux/uleds.h
+-rw-r--r-- root root 4562 ./usr/include/linux/ultrasound.h
+-rw-r--r-- root root 384 ./usr/include/linux/un.h
+-rw-r--r-- root root 220 ./usr/include/linux/unistd.h
+-rw-r--r-- root root 1328 ./usr/include/linux/unix_diag.h
+drwxr-xr-x root root 4096 ./usr/include/linux/usb
+-rw-r--r-- root root 19490 ./usr/include/linux/usb/audio.h
+-rw-r--r-- root root 12962 ./usr/include/linux/usb/cdc.h
+-rw-r--r-- root root 739 ./usr/include/linux/usb/cdc-wdm.h
+-rw-r--r-- root root 9149 ./usr/include/linux/usb/ch11.h
+-rw-r--r-- root root 38850 ./usr/include/linux/usb/ch9.h
+-rw-r--r-- root root 566 ./usr/include/linux/usb/charger.h
+-rw-r--r-- root root 8317 ./usr/include/linux/usbdevice_fs.h
+-rw-r--r-- root root 10370 ./usr/include/linux/usb/functionfs.h
+-rw-r--r-- root root 2818 ./usr/include/linux/usb/gadgetfs.h
+-rw-r--r-- root root 1385 ./usr/include/linux/usb/g_printer.h
+-rw-r--r-- root root 1097 ./usr/include/linux/usb/g_uvc.h
+-rw-r--r-- root root 640 ./usr/include/linux/usbip.h
+-rw-r--r-- root root 3434 ./usr/include/linux/usb/midi.h
+-rw-r--r-- root root 4713 ./usr/include/linux/usb/tmc.h
+-rw-r--r-- root root 16360 ./usr/include/linux/usb/video.h
+-rw-r--r-- root root 6811 ./usr/include/linux/userfaultfd.h
+-rw-r--r-- root root 1516 ./usr/include/linux/userio.h
+-rw-r--r-- root root 215 ./usr/include/linux/utime.h
+-rw-r--r-- root root 669 ./usr/include/linux/utsname.h
+-rw-r--r-- root root 1356 ./usr/include/linux/uuid.h
+-rw-r--r-- root root 2590 ./usr/include/linux/uvcvideo.h
+-rw-r--r-- root root 4177 ./usr/include/linux/v4l2-common.h
+-rw-r--r-- root root 52061 ./usr/include/linux/v4l2-controls.h
+-rw-r--r-- root root 31562 ./usr/include/linux/v4l2-dv-timings.h
+-rw-r--r-- root root 5101 ./usr/include/linux/v4l2-mediabus.h
+-rw-r--r-- root root 6339 ./usr/include/linux/v4l2-subdev.h
+-rw-r--r-- root root 7257 ./usr/include/linux/vbox_err.h
+-rw-r--r-- root root 8755 ./usr/include/linux/vboxguest.h
+-rw-r--r-- root root 11509 ./usr/include/linux/vbox_vmmdev_types.h
+-rw-r--r-- root root 97 ./usr/include/linux/version.h
+-rw-r--r-- root root 224 ./usr/include/linux/veth.h
+-rw-r--r-- root root 836 ./usr/include/linux/vfio_ccw.h
+-rw-r--r-- root root 33767 ./usr/include/linux/vfio.h
+-rw-r--r-- root root 5069 ./usr/include/linux/vhost.h
+-rw-r--r-- root root 3164 ./usr/include/linux/vhost_types.h
+-rw-r--r-- root root 91377 ./usr/include/linux/videodev2.h
+-rw-r--r-- root root 2041 ./usr/include/linux/virtio_9p.h
+-rw-r--r-- root root 5036 ./usr/include/linux/virtio_balloon.h
+-rw-r--r-- root root 6797 ./usr/include/linux/virtio_blk.h
+-rw-r--r-- root root 3836 ./usr/include/linux/virtio_config.h
+-rw-r--r-- root root 3136 ./usr/include/linux/virtio_console.h
+-rw-r--r-- root root 13874 ./usr/include/linux/virtio_crypto.h
+-rw-r--r-- root root 490 ./usr/include/linux/virtio_fs.h
+-rw-r--r-- root root 8540 ./usr/include/linux/virtio_gpu.h
+-rw-r--r-- root root 2592 ./usr/include/linux/virtio_ids.h
+-rw-r--r-- root root 2506 ./usr/include/linux/virtio_input.h
+-rw-r--r-- root root 3783 ./usr/include/linux/virtio_iommu.h
+-rw-r--r-- root root 4586 ./usr/include/linux/virtio_mmio.h
+-rw-r--r-- root root 10549 ./usr/include/linux/virtio_net.h
+-rw-r--r-- root root 7079 ./usr/include/linux/virtio_pci.h
+-rw-r--r-- root root 639 ./usr/include/linux/virtio_pmem.h
+-rw-r--r-- root root 7430 ./usr/include/linux/virtio_ring.h
+-rw-r--r-- root root 265 ./usr/include/linux/virtio_rng.h
+-rw-r--r-- root root 6035 ./usr/include/linux/virtio_scsi.h
+-rw-r--r-- root root 2153 ./usr/include/linux/virtio_types.h
+-rw-r--r-- root root 3086 ./usr/include/linux/virtio_vsock.h
+-rw-r--r-- root root 455 ./usr/include/linux/vmcore.h
+-rw-r--r-- root root 963 ./usr/include/linux/vm_sockets_diag.h
+-rw-r--r-- root root 5314 ./usr/include/linux/vm_sockets.h
+-rw-r--r-- root root 1885 ./usr/include/linux/vsockmon.h
+-rw-r--r-- root root 3059 ./usr/include/linux/vt.h
+-rw-r--r-- root root 1719 ./usr/include/linux/vtpm_proxy.h
+-rw-r--r-- root root 682 ./usr/include/linux/wait.h
+-rw-r--r-- root root 2335 ./usr/include/linux/watchdog.h
+drwxr-xr-x root root 4096 ./usr/include/linux/wimax
+-rw-r--r-- root root 8371 ./usr/include/linux/wimax.h
+-rw-r--r-- root root 15930 ./usr/include/linux/wimax/i2400m.h
+-rw-r--r-- root root 42713 ./usr/include/linux/wireless.h
+-rw-r--r-- root root 1761 ./usr/include/linux/wmi.h
+-rw-r--r-- root root 3562 ./usr/include/linux/x25.h
+-rw-r--r-- root root 2860 ./usr/include/linux/xattr.h
+-rw-r--r-- root root 1259 ./usr/include/linux/xdp_diag.h
+-rw-r--r-- root root 11737 ./usr/include/linux/xfrm.h
+-rw-r--r-- root root 2976 ./usr/include/linux/xilinx-v4l2-controls.h
+-rw-r--r-- root root 3296 ./usr/include/linux/zorro.h
+-rw-r--r-- root root 29963 ./usr/include/linux/zorro_ids.h
+-rw-r--r-- root root 7675 ./usr/include/locale.h
+drwxr-xr-x root root 4096 ./usr/include/lzma
+-rw-r--r-- root root 24858 ./usr/include/lzma/base.h
+-rw-r--r-- root root 2630 ./usr/include/lzma/bcj.h
+-rw-r--r-- root root 22107 ./usr/include/lzma/block.h
+-rw-r--r-- root root 4255 ./usr/include/lzma/check.h
+-rw-r--r-- root root 24844 ./usr/include/lzma/container.h
+-rw-r--r-- root root 1865 ./usr/include/lzma/delta.h
+-rw-r--r-- root root 16520 ./usr/include/lzma/filter.h
+-rw-r--r-- root root 9866 ./usr/include/lzma.h
+-rw-r--r-- root root 2604 ./usr/include/lzma/hardware.h
+-rw-r--r-- root root 23491 ./usr/include/lzma/index.h
+-rw-r--r-- root root 3914 ./usr/include/lzma/index_hash.h
+-rw-r--r-- root root 14744 ./usr/include/lzma/lzma12.h
+-rw-r--r-- root root 8253 ./usr/include/lzma/stream_flags.h
+-rw-r--r-- root root 3497 ./usr/include/lzma/version.h
+-rw-r--r-- root root 6546 ./usr/include/lzma/vli.h
+drwxr-xr-x root root 4096 ./usr/include/lzo
+-rw-r--r-- root root 2638 ./usr/include/lzo/lzo1a.h
+-rw-r--r-- root root 5387 ./usr/include/lzo/lzo1b.h
+-rw-r--r-- root root 5384 ./usr/include/lzo/lzo1c.h
+-rw-r--r-- root root 3073 ./usr/include/lzo/lzo1f.h
+-rw-r--r-- root root 2634 ./usr/include/lzo/lzo1.h
+-rw-r--r-- root root 5873 ./usr/include/lzo/lzo1x.h
+-rw-r--r-- root root 4641 ./usr/include/lzo/lzo1y.h
+-rw-r--r-- root root 3771 ./usr/include/lzo/lzo1z.h
+-rw-r--r-- root root 2525 ./usr/include/lzo/lzo2a.h
+-rw-r--r-- root root 5566 ./usr/include/lzo/lzo_asm.h
+-rw-r--r-- root root 16006 ./usr/include/lzo/lzoconf.h
+-rw-r--r-- root root 127289 ./usr/include/lzo/lzodefs.h
+-rw-r--r-- root root 1823 ./usr/include/lzo/lzoutil.h
+-rw-r--r-- root root 6186 ./usr/include/malloc.h
+-rw-r--r-- root root 46404 ./usr/include/math.h
+-rw-r--r-- root root 2435 ./usr/include/mcheck.h
+-rw-r--r-- root root 956 ./usr/include/memory.h
+-rw-r--r-- root root 12275 ./usr/include/menu.h
+drwxr-xr-x root root 4096 ./usr/include/misc
+-rw-r--r-- root root 3936 ./usr/include/misc/cxl.h
+-rw-r--r-- root root 953 ./usr/include/misc/fastrpc.h
+-rw-r--r-- root root 19004 ./usr/include/misc/habanalabs.h
+-rw-r--r-- root root 1947 ./usr/include/misc/ocxl.h
+-rw-r--r-- root root 12341 ./usr/include/misc/xilinx_sdfec.h
+-rw-r--r-- root root 3359 ./usr/include/mntent.h
+-rw-r--r-- root root 1804 ./usr/include/monetary.h
+-rw-r--r-- root root 3760 ./usr/include/mqueue.h
+drwxr-xr-x root root 4096 ./usr/include/mtd
+-rw-r--r-- root root 1644 ./usr/include/mtd/inftl-user.h
+-rw-r--r-- root root 9732 ./usr/include/mtd/mtd-abi.h
+-rw-r--r-- root root 1242 ./usr/include/mtd/mtd-user.h
+-rw-r--r-- root root 2116 ./usr/include/mtd/nftl-user.h
+-rw-r--r-- root root 18220 ./usr/include/mtd/ubi-user.h
+-rw-r--r-- root root 4240 ./usr/include/nc_tparm.h
+-rw-r--r-- root root 4522 ./usr/include/ncurses_dll.h
+lrwxrwxrwx root root 8 ./usr/include/ncurses.h -> curses.h
+-rw-r--r-- root root 2454 ./usr/include/ndbm.h
+drwxr-xr-x root root 4096 ./usr/include/net
+drwxr-xr-x root root 4096 ./usr/include/netash
+-rw-r--r-- root root 1363 ./usr/include/netash/ash.h
+drwxr-xr-x root root 4096 ./usr/include/netatalk
+-rw-r--r-- root root 1029 ./usr/include/netatalk/at.h
+drwxr-xr-x root root 4096 ./usr/include/netax25
+-rw-r--r-- root root 4810 ./usr/include/netax25/ax25.h
+-rw-r--r-- root root 28100 ./usr/include/netdb.h
+drwxr-xr-x root root 4096 ./usr/include/neteconet
+-rw-r--r-- root root 1668 ./usr/include/neteconet/ec.h
+-rw-r--r-- root root 3136 ./usr/include/net/ethernet.h
+-rw-r--r-- root root 7132 ./usr/include/net/if_arp.h
+-rw-r--r-- root root 6982 ./usr/include/net/if.h
+-rw-r--r-- root root 1262 ./usr/include/net/if_packet.h
+-rw-r--r-- root root 6714 ./usr/include/net/if_ppp.h
+-rw-r--r-- root root 1625 ./usr/include/net/if_shaper.h
+-rw-r--r-- root root 933 ./usr/include/net/if_slip.h
+drwxr-xr-x root root 4096 ./usr/include/netinet
+-rw-r--r-- root root 1985 ./usr/include/netinet/ether.h
+-rw-r--r-- root root 11515 ./usr/include/netinet/icmp6.h
+-rw-r--r-- root root 3976 ./usr/include/netinet/if_ether.h
+-rw-r--r-- root root 1186 ./usr/include/netinet/if_fddi.h
+-rw-r--r-- root root 3692 ./usr/include/netinet/if_tr.h
+-rw-r--r-- root root 4663 ./usr/include/netinet/igmp.h
+-rw-r--r-- root root 21702 ./usr/include/netinet/in.h
+-rw-r--r-- root root 1494 ./usr/include/netinet/in_systm.h
+-rw-r--r-- root root 5394 ./usr/include/netinet/ip6.h
+-rw-r--r-- root root 9436 ./usr/include/netinet/ip.h
+-rw-r--r-- root root 10131 ./usr/include/netinet/ip_icmp.h
+-rw-r--r-- root root 10490 ./usr/include/netinet/tcp.h
+-rw-r--r-- root root 3774 ./usr/include/netinet/udp.h
+drwxr-xr-x root root 4096 ./usr/include/netipx
+-rw-r--r-- root root 2900 ./usr/include/netipx/ipx.h
+drwxr-xr-x root root 4096 ./usr/include/netiucv
+-rw-r--r-- root root 1594 ./usr/include/netiucv/iucv.h
+drwxr-xr-x root root 4096 ./usr/include/netpacket
+-rw-r--r-- root root 2438 ./usr/include/netpacket/packet.h
+-rw-r--r-- root root 28 ./usr/include/net/ppp-comp.h
+-rw-r--r-- root root 162 ./usr/include/net/ppp_defs.h
+drwxr-xr-x root root 4096 ./usr/include/netrom
+-rw-r--r-- root root 2226 ./usr/include/netrom/netrom.h
+drwxr-xr-x root root 4096 ./usr/include/netrose
+-rw-r--r-- root root 3184 ./usr/include/netrose/rose.h
+-rw-r--r-- root root 4704 ./usr/include/net/route.h
+drwxr-xr-x root root 4096 ./usr/include/nfs
+-rw-r--r-- root root 23 ./usr/include/nfs/nfs.h
+-rw-r--r-- root root 1601 ./usr/include/nlist.h
+-rw-r--r-- root root 1753 ./usr/include/nl_types.h
+-rw-r--r-- root root 1879 ./usr/include/nss.h
+-rw-r--r-- root root 21307 ./usr/include/obstack.h
+drwxr-xr-x root root 4096 ./usr/include/omap
+-rw-r--r-- root root 4843 ./usr/include/omap/omap_drm.h
+drwxr-xr-x root root 4096 ./usr/include/openssl
+-rw-r--r-- root root 3349 ./usr/include/openssl/aes.h
+-rw-r--r-- root root 14599 ./usr/include/openssl/asn1err.h
+-rw-r--r-- root root 33627 ./usr/include/openssl/asn1.h
+-rw-r--r-- root root 395 ./usr/include/openssl/asn1_mac.h
+-rw-r--r-- root root 32940 ./usr/include/openssl/asn1t.h
+-rw-r--r-- root root 1326 ./usr/include/openssl/asyncerr.h
+-rw-r--r-- root root 2398 ./usr/include/openssl/async.h
+-rw-r--r-- root root 6400 ./usr/include/openssl/bioerr.h
+-rw-r--r-- root root 34907 ./usr/include/openssl/bio.h
+-rw-r--r-- root root 1847 ./usr/include/openssl/blowfish.h
+-rw-r--r-- root root 4907 ./usr/include/openssl/bnerr.h
+-rw-r--r-- root root 22135 ./usr/include/openssl/bn.h
+-rw-r--r-- root root 820 ./usr/include/openssl/buffererr.h
+-rw-r--r-- root root 1600 ./usr/include/openssl/buffer.h
+-rw-r--r-- root root 3179 ./usr/include/openssl/camellia.h
+-rw-r--r-- root root 1674 ./usr/include/openssl/cast.h
+-rw-r--r-- root root 1064 ./usr/include/openssl/cmac.h
+-rw-r--r-- root root 11160 ./usr/include/openssl/cmserr.h
+-rw-r--r-- root root 16379 ./usr/include/openssl/cms.h
+-rw-r--r-- root root 1212 ./usr/include/openssl/comperr.h
+-rw-r--r-- root root 1328 ./usr/include/openssl/comp.h
+-rw-r--r-- root root 1300 ./usr/include/openssl/conf_api.h
+-rw-r--r-- root root 3429 ./usr/include/openssl/conferr.h
+-rw-r--r-- root root 5601 ./usr/include/openssl/conf.h
+-rw-r--r-- root root 2261 ./usr/include/openssl/cryptoerr.h
+-rw-r--r-- root root 17239 ./usr/include/openssl/crypto.h
+-rw-r--r-- root root 3470 ./usr/include/openssl/cterr.h
+-rw-r--r-- root root 15872 ./usr/include/openssl/ct.h
+-rw-r--r-- root root 7627 ./usr/include/openssl/des.h
+-rw-r--r-- root root 3974 ./usr/include/openssl/dherr.h
+-rw-r--r-- root root 13403 ./usr/include/openssl/dh.h
+-rw-r--r-- root root 2972 ./usr/include/openssl/dsaerr.h
+-rw-r--r-- root root 10051 ./usr/include/openssl/dsa.h
+-rw-r--r-- root root 1578 ./usr/include/openssl/dtls1.h
+-rw-r--r-- root root 924 ./usr/include/openssl/ebcdic.h
+-rw-r--r-- root root 358 ./usr/include/openssl/ecdh.h
+-rw-r--r-- root root 358 ./usr/include/openssl/ecdsa.h
+-rw-r--r-- root root 15758 ./usr/include/openssl/ecerr.h
+-rw-r--r-- root root 63596 ./usr/include/openssl/ec.h
+-rw-r--r-- root root 5447 ./usr/include/openssl/engineerr.h
+-rw-r--r-- root root 34661 ./usr/include/openssl/engine.h
+-rw-r--r-- root root 8888 ./usr/include/openssl/e_os2.h
+-rw-r--r-- root root 11269 ./usr/include/openssl/err.h
+-rw-r--r-- root root 11427 ./usr/include/openssl/evperr.h
+-rw-r--r-- root root 76828 ./usr/include/openssl/evp.h
+-rw-r--r-- root root 1591 ./usr/include/openssl/hmac.h
+-rw-r--r-- root root 2099 ./usr/include/openssl/idea.h
+-rw-r--r-- root root 2122 ./usr/include/openssl/kdferr.h
+-rw-r--r-- root root 4326 ./usr/include/openssl/kdf.h
+-rw-r--r-- root root 9271 ./usr/include/openssl/lhash.h
+-rw-r--r-- root root 1054 ./usr/include/openssl/md2.h
+-rw-r--r-- root root 1322 ./usr/include/openssl/md4.h
+-rw-r--r-- root root 1320 ./usr/include/openssl/md5.h
+-rw-r--r-- root root 1053 ./usr/include/openssl/mdc2.h
+-rw-r--r-- root root 10478 ./usr/include/openssl/modes.h
+-rw-r--r-- root root 1316 ./usr/include/openssl/objectserr.h
+-rw-r--r-- root root 6633 ./usr/include/openssl/objects.h
+-rw-r--r-- root root 217522 ./usr/include/openssl/obj_mac.h
+-rw-r--r-- root root 3356 ./usr/include/openssl/ocsperr.h
+-rw-r--r-- root root 15305 ./usr/include/openssl/ocsp.h
+-rw-r--r-- root root 4520 ./usr/include/openssl/opensslconf-64.h
+-rw-r--r-- root root 564 ./usr/include/openssl/opensslconf.h
+-rw-r--r-- root root 4102 ./usr/include/openssl/opensslv.h
+-rw-r--r-- root root 6266 ./usr/include/openssl/ossl_typ.h
+-rw-r--r-- root root 415 ./usr/include/openssl/pem2.h
+-rw-r--r-- root root 5098 ./usr/include/openssl/pemerr.h
+-rw-r--r-- root root 15468 ./usr/include/openssl/pem.h
+-rw-r--r-- root root 3749 ./usr/include/openssl/pkcs12err.h
+-rw-r--r-- root root 9871 ./usr/include/openssl/pkcs12.h
+-rw-r--r-- root root 5110 ./usr/include/openssl/pkcs7err.h
+-rw-r--r-- root root 11590 ./usr/include/openssl/pkcs7.h
+-rw-r--r-- root root 4763 ./usr/include/openssl/rand_drbg.h
+-rw-r--r-- root root 4633 ./usr/include/openssl/randerr.h
+-rw-r--r-- root root 2213 ./usr/include/openssl/rand.h
+-rw-r--r-- root root 1534 ./usr/include/openssl/rc2.h
+-rw-r--r-- root root 825 ./usr/include/openssl/rc4.h
+-rw-r--r-- root root 1988 ./usr/include/openssl/rc5.h
+-rw-r--r-- root root 1243 ./usr/include/openssl/ripemd.h
+-rw-r--r-- root root 9075 ./usr/include/openssl/rsaerr.h
+-rw-r--r-- root root 22202 ./usr/include/openssl/rsa.h
+-rw-r--r-- root root 8139 ./usr/include/openssl/safestack.h
+-rw-r--r-- root root 3479 ./usr/include/openssl/seed.h
+-rw-r--r-- root root 3831 ./usr/include/openssl/sha.h
+-rw-r--r-- root root 3827 ./usr/include/openssl/srp.h
+-rw-r--r-- root root 1316 ./usr/include/openssl/srtp.h
+-rw-r--r-- root root 542 ./usr/include/openssl/ssl2.h
+-rw-r--r-- root root 14576 ./usr/include/openssl/ssl3.h
+-rw-r--r-- root root 46676 ./usr/include/openssl/sslerr.h
+-rw-r--r-- root root 111253 ./usr/include/openssl/ssl.h
+-rw-r--r-- root root 3095 ./usr/include/openssl/stack.h
+-rw-r--r-- root root 4399 ./usr/include/openssl/storeerr.h
+-rw-r--r-- root root 11199 ./usr/include/openssl/store.h
+-rw-r--r-- root root 1311 ./usr/include/openssl/symhacks.h
+-rw-r--r-- root root 72490 ./usr/include/openssl/tls1.h
+-rw-r--r-- root root 6746 ./usr/include/openssl/tserr.h
+-rw-r--r-- root root 22429 ./usr/include/openssl/ts.h
+-rw-r--r-- root root 1666 ./usr/include/openssl/txt_db.h
+-rw-r--r-- root root 2737 ./usr/include/openssl/uierr.h
+-rw-r--r-- root root 16052 ./usr/include/openssl/ui.h
+-rw-r--r-- root root 1377 ./usr/include/openssl/whrlpool.h
+-rw-r--r-- root root 6777 ./usr/include/openssl/x509err.h
+-rw-r--r-- root root 43123 ./usr/include/openssl/x509.h
+-rw-r--r-- root root 8777 ./usr/include/openssl/x509v3err.h
+-rw-r--r-- root root 33377 ./usr/include/openssl/x509v3.h
+-rw-r--r-- root root 32179 ./usr/include/openssl/x509_vfy.h
+-rw-r--r-- root root 4201 ./usr/include/panel.h
+-rw-r--r-- root root 2977 ./usr/include/paths.h
+-rw-r--r-- root root 15456 ./usr/include/pciaccess.h
+-rw-r--r-- root root 6783 ./usr/include/pcrecpparg.h
+-rw-r--r-- root root 26529 ./usr/include/pcrecpp.h
+-rw-r--r-- root root 31718 ./usr/include/pcre.h
+-rw-r--r-- root root 5631 ./usr/include/pcreposix.h
+-rw-r--r-- root root 6600 ./usr/include/pcre_scanner.h
+-rw-r--r-- root root 6312 ./usr/include/pcre_stringpiece.h
+drwxr-xr-x root root 4096 ./usr/include/pixman-1
+-rw-r--r-- root root 45455 ./usr/include/pixman-1/pixman.h
+-rw-r--r-- root root 1739 ./usr/include/pixman-1/pixman-version.h
+-rw-r--r-- root root 15029 ./usr/include/plugin-api.h
+lrwxrwxrwx root root 18 ./usr/include/pngconf.h -> libpng16/pngconf.h
+lrwxrwxrwx root root 14 ./usr/include/png.h -> libpng16/png.h
+lrwxrwxrwx root root 21 ./usr/include/pnglibconf.h -> libpng16/pnglibconf.h
+-rw-r--r-- root root 22 ./usr/include/poll.h
+-rw-r--r-- root root 6801 ./usr/include/printf.h
+drwxr-xr-x root root 4096 ./usr/include/proc
+-rw-r--r-- root root 509 ./usr/include/proc/alloc.h
+-rw-r--r-- root root 457 ./usr/include/proc/devname.h
+-rw-r--r-- root root 913 ./usr/include/proc/escape.h
+-rw-r--r-- root root 1068 ./usr/include/proc/numa.h
+-rw-r--r-- root root 2936 ./usr/include/proc/procps.h
+-rw-r--r-- root root 305 ./usr/include/proc/pwcache.h
+-rw-r--r-- root root 15204 ./usr/include/proc/readproc.h
+-rw-r--r-- root root 3477 ./usr/include/proc_service.h
+-rw-r--r-- root root 1000 ./usr/include/proc/sig.h
+-rw-r--r-- root root 1797 ./usr/include/proc/slab.h
+-rw-r--r-- root root 4820 ./usr/include/proc/sysinfo.h
+-rw-r--r-- root root 1480 ./usr/include/proc/version.h
+-rw-r--r-- root root 160 ./usr/include/proc/wchan.h
+-rw-r--r-- root root 202 ./usr/include/proc/whattime.h
+drwxr-xr-x root root 4096 ./usr/include/protocols
+-rw-r--r-- root root 3844 ./usr/include/protocols/routed.h
+-rw-r--r-- root root 2567 ./usr/include/protocols/rwhod.h
+-rw-r--r-- root root 4826 ./usr/include/protocols/talkd.h
+-rw-r--r-- root root 3881 ./usr/include/protocols/timed.h
+-rw-r--r-- root root 41701 ./usr/include/pthread.h
+-rw-r--r-- root root 1570 ./usr/include/pty.h
+-rw-r--r-- root root 6159 ./usr/include/pwd.h
+drwxr-xr-x root root 4096 ./usr/include/pycairo
+-rw-r--r-- root root 9152 ./usr/include/pycairo/py3cairo.h
+drwxr-xr-x root root 4096 ./usr/include/pygobject-3.0
+-rw-r--r-- root root 24983 ./usr/include/pygobject-3.0/pygobject.h
+drwxr-xr-x root root 4096 ./usr/include/python3.8
+-rw-r--r-- root root 30286 ./usr/include/python3.8/abstract.h
+-rw-r--r-- root root 1229 ./usr/include/python3.8/asdl.h
+-rw-r--r-- root root 948 ./usr/include/python3.8/ast.h
+-rw-r--r-- root root 468 ./usr/include/python3.8/bitset.h
+-rw-r--r-- root root 264 ./usr/include/python3.8/bltinmodule.h
+-rw-r--r-- root root 886 ./usr/include/python3.8/boolobject.h
+-rw-r--r-- root root 2114 ./usr/include/python3.8/bytearrayobject.h
+-rw-r--r-- root root 3301 ./usr/include/python3.8/bytes_methods.h
+-rw-r--r-- root root 8493 ./usr/include/python3.8/bytesobject.h
+-rw-r--r-- root root 713 ./usr/include/python3.8/cellobject.h
+-rw-r--r-- root root 8366 ./usr/include/python3.8/ceval.h
+-rw-r--r-- root root 1710 ./usr/include/python3.8/classobject.h
+-rw-r--r-- root root 6793 ./usr/include/python3.8/codecs.h
+-rw-r--r-- root root 6982 ./usr/include/python3.8/code.h
+-rw-r--r-- root root 3256 ./usr/include/python3.8/compile.h
+-rw-r--r-- root root 1807 ./usr/include/python3.8/complexobject.h
+-rw-r--r-- root root 2014 ./usr/include/python3.8/context.h
+drwxr-xr-x root root 4096 ./usr/include/python3.8/cpython
+-rw-r--r-- root root 12295 ./usr/include/python3.8/cpython/abstract.h
+-rw-r--r-- root root 3845 ./usr/include/python3.8/cpython/dictobject.h
+-rw-r--r-- root root 951 ./usr/include/python3.8/cpython/fileobject.h
+-rw-r--r-- root root 16028 ./usr/include/python3.8/cpython/initconfig.h
+-rw-r--r-- root root 456 ./usr/include/python3.8/cpython/interpreteridobject.h
+-rw-r--r-- root root 15691 ./usr/include/python3.8/cpython/object.h
+-rw-r--r-- root root 3600 ./usr/include/python3.8/cpython/objimpl.h
+-rw-r--r-- root root 4607 ./usr/include/python3.8/cpython/pyerrors.h
+-rw-r--r-- root root 2263 ./usr/include/python3.8/cpython/pylifecycle.h
+-rw-r--r-- root root 3511 ./usr/include/python3.8/cpython/pymem.h
+-rw-r--r-- root root 9743 ./usr/include/python3.8/cpython/pystate.h
+-rw-r--r-- root root 547 ./usr/include/python3.8/cpython/sysmodule.h
+-rw-r--r-- root root 473 ./usr/include/python3.8/cpython/traceback.h
+-rw-r--r-- root root 1036 ./usr/include/python3.8/cpython/tupleobject.h
+-rw-r--r-- root root 46299 ./usr/include/python3.8/cpython/unicodeobject.h
+-rw-r--r-- root root 9260 ./usr/include/python3.8/datetime.h
+-rw-r--r-- root root 3019 ./usr/include/python3.8/descrobject.h
+-rw-r--r-- root root 3716 ./usr/include/python3.8/dictobject.h
+-rw-r--r-- root root 458 ./usr/include/python3.8/dtoa.h
+-rw-r--r-- root root 22469 ./usr/include/python3.8/dynamic_annotations.h
+-rw-r--r-- root root 253 ./usr/include/python3.8/enumobject.h
+-rw-r--r-- root root 1695 ./usr/include/python3.8/errcode.h
+-rw-r--r-- root root 1209 ./usr/include/python3.8/eval.h
+-rw-r--r-- root root 1342 ./usr/include/python3.8/fileobject.h
+-rw-r--r-- root root 4352 ./usr/include/python3.8/fileutils.h
+-rw-r--r-- root root 4794 ./usr/include/python3.8/floatobject.h
+-rw-r--r-- root root 3317 ./usr/include/python3.8/frameobject.h
+-rw-r--r-- root root 4200 ./usr/include/python3.8/funcobject.h
+-rw-r--r-- root root 3720 ./usr/include/python3.8/genobject.h
+-rw-r--r-- root root 2118 ./usr/include/python3.8/graminit.h
+-rw-r--r-- root root 1821 ./usr/include/python3.8/grammar.h
+-rw-r--r-- root root 4926 ./usr/include/python3.8/import.h
+drwxr-xr-x root root 4096 ./usr/include/python3.8/internal
+-rw-r--r-- root root 1126 ./usr/include/python3.8/internal/pycore_accu.h
+-rw-r--r-- root root 16944 ./usr/include/python3.8/internal/pycore_atomic.h
+-rw-r--r-- root root 966 ./usr/include/python3.8/internal/pycore_ceval.h
+-rw-r--r-- root root 542 ./usr/include/python3.8/internal/pycore_code.h
+-rw-r--r-- root root 2809 ./usr/include/python3.8/internal/pycore_condvar.h
+-rw-r--r-- root root 779 ./usr/include/python3.8/internal/pycore_context.h
+-rw-r--r-- root root 1254 ./usr/include/python3.8/internal/pycore_fileutils.h
+-rw-r--r-- root root 490 ./usr/include/python3.8/internal/pycore_getopt.h
+-rw-r--r-- root root 1520 ./usr/include/python3.8/internal/pycore_gil.h
+-rw-r--r-- root root 3128 ./usr/include/python3.8/internal/pycore_hamt.h
+-rw-r--r-- root root 5168 ./usr/include/python3.8/internal/pycore_initconfig.h
+-rw-r--r-- root root 2896 ./usr/include/python3.8/internal/pycore_object.h
+-rw-r--r-- root root 2037 ./usr/include/python3.8/internal/pycore_pathconfig.h
+-rw-r--r-- root root 1329 ./usr/include/python3.8/internal/pycore_pyerrors.h
+-rw-r--r-- root root 206 ./usr/include/python3.8/internal/pycore_pyhash.h
+-rw-r--r-- root root 3758 ./usr/include/python3.8/internal/pycore_pylifecycle.h
+-rw-r--r-- root root 8217 ./usr/include/python3.8/internal/pycore_pymem.h
+-rw-r--r-- root root 9494 ./usr/include/python3.8/internal/pycore_pystate.h
+-rw-r--r-- root root 3076 ./usr/include/python3.8/internal/pycore_traceback.h
+-rw-r--r-- root root 418 ./usr/include/python3.8/internal/pycore_tupleobject.h
+-rw-r--r-- root root 591 ./usr/include/python3.8/internal/pycore_warnings.h
+-rw-r--r-- root root 334 ./usr/include/python3.8/interpreteridobject.h
+-rw-r--r-- root root 861 ./usr/include/python3.8/intrcheck.h
+-rw-r--r-- root root 567 ./usr/include/python3.8/iterobject.h
+-rw-r--r-- root root 2927 ./usr/include/python3.8/listobject.h
+-rw-r--r-- root root 3799 ./usr/include/python3.8/longintrepr.h
+-rw-r--r-- root root 9520 ./usr/include/python3.8/longobject.h
+-rw-r--r-- root root 803 ./usr/include/python3.8/marshal.h
+-rw-r--r-- root root 2765 ./usr/include/python3.8/memoryobject.h
+-rw-r--r-- root root 4406 ./usr/include/python3.8/methodobject.h
+-rw-r--r-- root root 9591 ./usr/include/python3.8/modsupport.h
+-rw-r--r-- root root 2362 ./usr/include/python3.8/moduleobject.h
+-rw-r--r-- root root 349 ./usr/include/python3.8/namespaceobject.h
+-rw-r--r-- root root 1328 ./usr/include/python3.8/node.h
+-rw-r--r-- root root 29600 ./usr/include/python3.8/object.h
+-rw-r--r-- root root 10537 ./usr/include/python3.8/objimpl.h
+-rw-r--r-- root root 1300 ./usr/include/python3.8/odictobject.h
+-rw-r--r-- root root 5164 ./usr/include/python3.8/opcode.h
+-rw-r--r-- root root 737 ./usr/include/python3.8/osdefs.h
+-rw-r--r-- root root 291 ./usr/include/python3.8/osmodule.h
+-rw-r--r-- root root 2958 ./usr/include/python3.8/parsetok.h
+-rw-r--r-- root root 1297 ./usr/include/python3.8/patchlevel.h
+-rw-r--r-- root root 847 ./usr/include/python3.8/picklebufobject.h
+-rw-r--r-- root root 2744 ./usr/include/python3.8/pyarena.h
+-rw-r--r-- root root 1726 ./usr/include/python3.8/pycapsule.h
+-rw-r--r-- root root 47363 ./usr/include/python3.8/pyconfig-64.h
+-rw-r--r-- root root 560 ./usr/include/python3.8/pyconfig.h
+-rw-r--r-- root root 1320 ./usr/include/python3.8/pyctype.h
+-rw-r--r-- root root 2477 ./usr/include/python3.8/py_curses.h
+-rw-r--r-- root root 1214 ./usr/include/python3.8/pydebug.h
+-rw-r--r-- root root 2413 ./usr/include/python3.8/pydtrace.h
+-rw-r--r-- root root 12786 ./usr/include/python3.8/pyerrors.h
+-rw-r--r-- root root 2450 ./usr/include/python3.8/pyexpat.h
+-rw-r--r-- root root 341 ./usr/include/python3.8/pyfpe.h
+-rw-r--r-- root root 4140 ./usr/include/python3.8/pyhash.h
+-rw-r--r-- root root 2081 ./usr/include/python3.8/pylifecycle.h
+-rw-r--r-- root root 2989 ./usr/include/python3.8/pymacconfig.h
+-rw-r--r-- root root 3778 ./usr/include/python3.8/pymacro.h
+-rw-r--r-- root root 8312 ./usr/include/python3.8/pymath.h
+-rw-r--r-- root root 5406 ./usr/include/python3.8/pymem.h
+-rw-r--r-- root root 30221 ./usr/include/python3.8/pyport.h
+-rw-r--r-- root root 4686 ./usr/include/python3.8/pystate.h
+-rw-r--r-- root root 436 ./usr/include/python3.8/pystrcmp.h
+-rw-r--r-- root root 849 ./usr/include/python3.8/pystrhex.h
+-rw-r--r-- root root 1483 ./usr/include/python3.8/pystrtod.h
+-rw-r--r-- root root 26491 ./usr/include/python3.8/Python-ast.h
+-rw-r--r-- root root 3615 ./usr/include/python3.8/Python.h
+-rw-r--r-- root root 7688 ./usr/include/python3.8/pythonrun.h
+-rw-r--r-- root root 5660 ./usr/include/python3.8/pythread.h
+-rw-r--r-- root root 8926 ./usr/include/python3.8/pytime.h
+-rw-r--r-- root root 629 ./usr/include/python3.8/rangeobject.h
+-rw-r--r-- root root 3362 ./usr/include/python3.8/setobject.h
+-rw-r--r-- root root 2517 ./usr/include/python3.8/sliceobject.h
+-rw-r--r-- root root 2030 ./usr/include/python3.8/structmember.h
+-rw-r--r-- root root 1377 ./usr/include/python3.8/structseq.h
+-rw-r--r-- root root 5308 ./usr/include/python3.8/symtable.h
+-rw-r--r-- root root 1242 ./usr/include/python3.8/sysmodule.h
+-rw-r--r-- root root 2429 ./usr/include/python3.8/token.h
+-rw-r--r-- root root 601 ./usr/include/python3.8/traceback.h
+-rw-r--r-- root root 1114 ./usr/include/python3.8/tracemalloc.h
+-rw-r--r-- root root 1661 ./usr/include/python3.8/tupleobject.h
+-rw-r--r-- root root 2253 ./usr/include/python3.8/typeslots.h
+-rw-r--r-- root root 1056 ./usr/include/python3.8/ucnhash.h
+-rw-r--r-- root root 35732 ./usr/include/python3.8/unicodeobject.h
+-rw-r--r-- root root 1776 ./usr/include/python3.8/warnings.h
+-rw-r--r-- root root 2866 ./usr/include/python3.8/weakrefobject.h
+drwxr-xr-x root root 4096 ./usr/include/rdma
+-rw-r--r-- root root 3291 ./usr/include/rdma/bnxt_re-abi.h
+-rw-r--r-- root root 2468 ./usr/include/rdma/cxgb3-abi.h
+-rw-r--r-- root root 3122 ./usr/include/rdma/cxgb4-abi.h
+-rw-r--r-- root root 2141 ./usr/include/rdma/efa-abi.h
+drwxr-xr-x root root 4096 ./usr/include/rdma/hfi
+-rw-r--r-- root root 6618 ./usr/include/rdma/hfi/hfi1_ioctl.h
+-rw-r--r-- root root 9225 ./usr/include/rdma/hfi/hfi1_user.h
+-rw-r--r-- root root 2388 ./usr/include/rdma/hns-abi.h
+-rw-r--r-- root root 3030 ./usr/include/rdma/i40iw-abi.h
+-rw-r--r-- root root 6046 ./usr/include/rdma/ib_user_ioctl_cmds.h
+-rw-r--r-- root root 5655 ./usr/include/rdma/ib_user_ioctl_verbs.h
+-rw-r--r-- root root 8531 ./usr/include/rdma/ib_user_mad.h
+-rw-r--r-- root root 2305 ./usr/include/rdma/ib_user_sa.h
+-rw-r--r-- root root 26750 ./usr/include/rdma/ib_user_verbs.h
+-rw-r--r-- root root 5117 ./usr/include/rdma/mlx4-abi.h
+-rw-r--r-- root root 12968 ./usr/include/rdma/mlx5-abi.h
+-rw-r--r-- root root 7368 ./usr/include/rdma/mlx5_user_ioctl_cmds.h
+-rw-r--r-- root root 2624 ./usr/include/rdma/mlx5_user_ioctl_verbs.h
+-rw-r--r-- root root 3055 ./usr/include/rdma/mthca-abi.h
+-rw-r--r-- root root 3487 ./usr/include/rdma/nes-abi.h
+-rw-r--r-- root root 4116 ./usr/include/rdma/ocrdma-abi.h
+-rw-r--r-- root root 3160 ./usr/include/rdma/qedr-abi.h
+-rw-r--r-- root root 14231 ./usr/include/rdma/rdma_netlink.h
+-rw-r--r-- root root 6903 ./usr/include/rdma/rdma_user_cm.h
+-rw-r--r-- root root 3008 ./usr/include/rdma/rdma_user_ioctl_cmds.h
+-rw-r--r-- root root 3749 ./usr/include/rdma/rdma_user_ioctl.h
+-rw-r--r-- root root 3839 ./usr/include/rdma/rdma_user_rxe.h
+-rw-r--r-- root root 1771 ./usr/include/rdma/rvt-abi.h
+-rw-r--r-- root root 3430 ./usr/include/rdma/siw-abi.h
+-rw-r--r-- root root 7807 ./usr/include/rdma/vmw_pvrdma-abi.h
+drwxr-xr-x root root 4096 ./usr/include/readline
+-rw-r--r-- root root 4697 ./usr/include/readline/chardefs.h
+-rw-r--r-- root root 10779 ./usr/include/readline/history.h
+-rw-r--r-- root root 3260 ./usr/include/readline/keymaps.h
+-rw-r--r-- root root 39338 ./usr/include/readline/readline.h
+-rw-r--r-- root root 2829 ./usr/include/readline/rlconf.h
+-rw-r--r-- root root 1835 ./usr/include/readline/rlstdc.h
+-rw-r--r-- root root 3193 ./usr/include/readline/rltypedefs.h
+-rw-r--r-- root root 3046 ./usr/include/readline/tilde.h
+-rw-r--r-- root root 963 ./usr/include/re_comp.h
+-rw-r--r-- root root 24715 ./usr/include/regex.h
+-rw-r--r-- root root 1448 ./usr/include/regexp.h
+-rw-r--r-- root root 11873 ./usr/include/resolv.h
+drwxr-xr-x root root 4096 ./usr/include/rpc
+-rw-r--r-- root root 2897 ./usr/include/rpc/netdb.h
+drwxr-xr-x root root 4096 ./usr/include/rpcsvc
+-rw-r--r-- root root 2675 ./usr/include/rpcsvc/nis_callback.h
+-rw-r--r-- root root 2178 ./usr/include/rpcsvc/nis_callback.x
+-rw-r--r-- root root 15879 ./usr/include/rpcsvc/nis.h
+-rw-r--r-- root root 12340 ./usr/include/rpcsvc/nislib.h
+-rw-r--r-- root root 13090 ./usr/include/rpcsvc/nis_object.x
+-rw-r--r-- root root 5370 ./usr/include/rpcsvc/nis_tags.h
+-rw-r--r-- root root 16802 ./usr/include/rpcsvc/nis.x
+-rw-r--r-- root root 3481 ./usr/include/rpcsvc/ypclnt.h
+-rw-r--r-- root root 7964 ./usr/include/rpcsvc/yp.h
+-rw-r--r-- root root 913 ./usr/include/rpcsvc/yppasswd.h
+-rw-r--r-- root root 2286 ./usr/include/rpcsvc/yppasswd.x
+-rw-r--r-- root root 14920 ./usr/include/rpcsvc/yp_prot.h
+-rw-r--r-- root root 3027 ./usr/include/rpcsvc/ypupd.h
+-rw-r--r-- root root 6981 ./usr/include/rpcsvc/yp.x
+-rw-r--r-- root root 4733 ./usr/include/sched.h
+drwxr-xr-x root root 4096 ./usr/include/scsi
+-rw-r--r-- root root 10168 ./usr/include/scsi/cxlflash_ioctl.h
+drwxr-xr-x root root 4096 ./usr/include/scsi/fc
+-rw-r--r-- root root 26902 ./usr/include/scsi/fc/fc_els.h
+-rw-r--r-- root root 11703 ./usr/include/scsi/fc/fc_fs.h
+-rw-r--r-- root root 2231 ./usr/include/scsi/fc/fc_gs.h
+-rw-r--r-- root root 4317 ./usr/include/scsi/fc/fc_ns.h
+-rw-r--r-- root root 8027 ./usr/include/scsi/scsi_bsg_fc.h
+-rw-r--r-- root root 2795 ./usr/include/scsi/scsi_bsg_ufs.h
+-rw-r--r-- root root 6970 ./usr/include/scsi/scsi.h
+-rw-r--r-- root root 1316 ./usr/include/scsi/scsi_ioctl.h
+-rw-r--r-- root root 1264 ./usr/include/scsi/scsi_netlink_fc.h
+-rw-r--r-- root root 2906 ./usr/include/scsi/scsi_netlink.h
+-rw-r--r-- root root 11662 ./usr/include/scsi/sg.h
+-rw-r--r-- root root 5450 ./usr/include/search.h
+-rw-r--r-- root root 2735 ./usr/include/semaphore.h
+-rw-r--r-- root root 3670 ./usr/include/setjmp.h
+-rw-r--r-- root root 1344 ./usr/include/sgtty.h
+-rw-r--r-- root root 5472 ./usr/include/shadow.h
+-rw-r--r-- root root 12309 ./usr/include/signal.h
+drwxr-xr-x root root 4096 ./usr/include/sound
+-rw-r--r-- root root 21847 ./usr/include/sound/asequencer.h
+-rw-r--r-- root root 22222 ./usr/include/sound/asoc.h
+-rw-r--r-- root root 4377 ./usr/include/sound/asound_fm.h
+-rw-r--r-- root root 46564 ./usr/include/sound/asound.h
+-rw-r--r-- root root 6743 ./usr/include/sound/compress_offload.h
+-rw-r--r-- root root 16992 ./usr/include/sound/compress_params.h
+-rw-r--r-- root root 17240 ./usr/include/sound/emu10k1.h
+-rw-r--r-- root root 3245 ./usr/include/sound/firewire.h
+-rw-r--r-- root root 3140 ./usr/include/sound/hdsp.h
+-rw-r--r-- root root 5486 ./usr/include/sound/hdspm.h
+-rw-r--r-- root root 4304 ./usr/include/sound/sb16_csp.h
+-rw-r--r-- root root 7494 ./usr/include/sound/sfnt_info.h
+-rw-r--r-- root root 5195 ./usr/include/sound/skl-tplg-interface.h
+-rw-r--r-- root root 12191 ./usr/include/sound/snd_sst_tokens.h
+drwxr-xr-x root root 4096 ./usr/include/sound/sof
+-rw-r--r-- root root 2036 ./usr/include/sound/sof/abi.h
+-rw-r--r-- root root 2267 ./usr/include/sound/sof/fw.h
+-rw-r--r-- root root 922 ./usr/include/sound/sof/header.h
+-rw-r--r-- root root 3267 ./usr/include/sound/sof/tokens.h
+-rw-r--r-- root root 4601 ./usr/include/sound/tlv.h
+-rw-r--r-- root root 1939 ./usr/include/sound/usb_stream.h
+-rw-r--r-- root root 7758 ./usr/include/spawn.h
+-rw-r--r-- root root 34802 ./usr/include/sqlite3ext.h
+-rw-r--r-- root root 576161 ./usr/include/sqlite3.h
+drwxr-xr-x root root 4096 ./usr/include/ss
+-rw-r--r-- root root 1193 ./usr/include/ss/ss_err.h
+-rw-r--r-- root root 3166 ./usr/include/ss/ss.h
+-rw-r--r-- root root 264 ./usr/include/stab.h
+-rw-r--r-- root root 2290 ./usr/include/stdc-predef.h
+-rw-r--r-- root root 8474 ./usr/include/stdint.h
+-rw-r--r-- root root 2800 ./usr/include/stdio_ext.h
+-rw-r--r-- root root 29950 ./usr/include/stdio.h
+-rw-r--r-- root root 35835 ./usr/include/stdlib.h
+-rw-r--r-- root root 17660 ./usr/include/string.h
+-rw-r--r-- root root 4753 ./usr/include/strings.h
+-rw-r--r-- root root 2191 ./usr/include/symcat.h
+drwxr-xr-x root root 4096 ./usr/include/sys
+-rw-r--r-- root root 3302 ./usr/include/sys/acct.h
+-rw-r--r-- root root 3700 ./usr/include/sys/acl.h
+-rw-r--r-- root root 1260 ./usr/include/sys/auxv.h
+-rw-r--r-- root root 86 ./usr/include/sys/bitypes.h
+-rw-r--r-- root root 25 ./usr/include/syscall.h
+-rw-r--r-- root root 6996 ./usr/include/sys/capability.h
+-rw-r--r-- root root 18308 ./usr/include/sys/cdefs.h
+-rw-r--r-- root root 3576 ./usr/include/sys/debugreg.h
+-rw-r--r-- root root 922 ./usr/include/sys/dir.h
+-rw-r--r-- root root 1024 ./usr/include/sys/elf.h
+-rw-r--r-- root root 4411 ./usr/include/sys/epoll.h
+-rw-r--r-- root root 19 ./usr/include/sys/errno.h
+-rw-r--r-- root root 1400 ./usr/include/sys/eventfd.h
+-rw-r--r-- root root 5232 ./usr/include/sysexits.h
+-rw-r--r-- root root 1292 ./usr/include/sys/fanotify.h
+-rw-r--r-- root root 19 ./usr/include/sys/fcntl.h
+-rw-r--r-- root root 1675 ./usr/include/sys/file.h
+-rw-r--r-- root root 1188 ./usr/include/sys/fsuid.h
+-rw-r--r-- root root 6210 ./usr/include/sys/gmon.h
+-rw-r--r-- root root 2636 ./usr/include/sys/gmon_out.h
+-rw-r--r-- root root 3901 ./usr/include/sys/inotify.h
+-rw-r--r-- root root 1740 ./usr/include/sys/ioctl.h
+-rw-r--r-- root root 5086 ./usr/include/sys/io.h
+-rw-r--r-- root root 1462 ./usr/include/sys/ipc.h
+-rw-r--r-- root root 1112 ./usr/include/sys/kd.h
+-rw-r--r-- root root 1204 ./usr/include/sys/klog.h
+-rw-r--r-- root root 24 ./usr/include/syslog.h
+-rw-r--r-- root root 5552 ./usr/include/sys/mman.h
+-rw-r--r-- root root 5612 ./usr/include/sys/mount.h
+-rw-r--r-- root root 2366 ./usr/include/sys/msg.h
+-rw-r--r-- root root 11163 ./usr/include/sys/mtio.h
+-rw-r--r-- root root 3149 ./usr/include/sys/param.h
+-rw-r--r-- root root 923 ./usr/include/sys/pci.h
+-rw-r--r-- root root 1127 ./usr/include/sys/perm.h
+-rw-r--r-- root root 2723 ./usr/include/sys/personality.h
+-rw-r--r-- root root 2550 ./usr/include/sys/poll.h
+-rw-r--r-- root root 1059 ./usr/include/sys/prctl.h
+-rw-r--r-- root root 4338 ./usr/include/sys/procfs.h
+-rw-r--r-- root root 1959 ./usr/include/sys/profil.h
+-rw-r--r-- root root 4680 ./usr/include/sys/psx_syscall.h
+-rw-r--r-- root root 6126 ./usr/include/sys/ptrace.h
+-rw-r--r-- root root 19539 ./usr/include/sys/queue.h
+-rw-r--r-- root root 5173 ./usr/include/sys/quota.h
+-rw-r--r-- root root 1444 ./usr/include/sys/random.h
+-rw-r--r-- root root 1182 ./usr/include/sys/raw.h
+-rw-r--r-- root root 1633 ./usr/include/sys/reboot.h
+-rw-r--r-- root root 1827 ./usr/include/sys/reg.h
+-rw-r--r-- root root 3646 ./usr/include/sys/resource.h
+-rw-r--r-- root root 4141 ./usr/include/sys/select.h
+-rw-r--r-- root root 2037 ./usr/include/sys/sem.h
+-rw-r--r-- root root 1806 ./usr/include/sys/sendfile.h
+-rw-r--r-- root root 1874 ./usr/include/sys/shm.h
+-rw-r--r-- root root 1714 ./usr/include/sys/signalfd.h
+-rw-r--r-- root root 20 ./usr/include/sys/signal.h
+-rw-r--r-- root root 10205 ./usr/include/sys/socket.h
+-rw-r--r-- root root 141 ./usr/include/sys/socketvar.h
+-rw-r--r-- root root 29 ./usr/include/sys/soundcard.h
+-rw-r--r-- root root 2094 ./usr/include/sys/statfs.h
+-rw-r--r-- root root 16237 ./usr/include/sys/stat.h
+-rw-r--r-- root root 2820 ./usr/include/sys/statvfs.h
+-rw-r--r-- root root 1593 ./usr/include/sys/swap.h
+-rw-r--r-- root root 1256 ./usr/include/sys/syscall.h
+-rw-r--r-- root root 2105 ./usr/include/sys/sysctl.h
+-rw-r--r-- root root 1518 ./usr/include/sys/sysinfo.h
+-rw-r--r-- root root 7702 ./usr/include/sys/syslog.h
+-rw-r--r-- root root 2103 ./usr/include/sys/sysmacros.h
+-rw-r--r-- root root 74 ./usr/include/sys/termios.h
+-rw-r--r-- root root 1420 ./usr/include/sys/timeb.h
+-rw-r--r-- root root 6754 ./usr/include/sys/time.h
+-rw-r--r-- root root 1874 ./usr/include/sys/timerfd.h
+-rw-r--r-- root root 1597 ./usr/include/sys/times.h
+-rw-r--r-- root root 2206 ./usr/include/sys/timex.h
+-rw-r--r-- root root 2499 ./usr/include/sys/ttychars.h
+-rw-r--r-- root root 3568 ./usr/include/sys/ttydefaults.h
+-rw-r--r-- root root 5713 ./usr/include/sys/types.h
+-rw-r--r-- root root 5842 ./usr/include/sys/ucontext.h
+-rw-r--r-- root root 6280 ./usr/include/sys/uio.h
+-rw-r--r-- root root 1453 ./usr/include/sys/un.h
+-rw-r--r-- root root 20 ./usr/include/sys/unistd.h
+-rw-r--r-- root root 5208 ./usr/include/sys/user.h
+-rw-r--r-- root root 2481 ./usr/include/sys/utsname.h
+-rw-r--r-- root root 161 ./usr/include/sys/vfs.h
+-rw-r--r-- root root 1880 ./usr/include/sys/vlimit.h
+-rw-r--r-- root root 1199 ./usr/include/sys/vm86.h
+-rw-r--r-- root root 22 ./usr/include/sys/vt.h
+-rw-r--r-- root root 2463 ./usr/include/sys/vtimes.h
+-rw-r--r-- root root 5605 ./usr/include/sys/wait.h
+-rw-r--r-- root root 4275 ./usr/include/sys/xattr.h
+-rw-r--r-- root root 3786 ./usr/include/tar.h
+-rw-r--r-- root root 9130 ./usr/include/tcpd.h
+-rw-r--r-- root root 3471 ./usr/include/termcap.h
+-rw-r--r-- root root 9096 ./usr/include/term_entry.h
+-rw-r--r-- root root 40447 ./usr/include/term.h
+-rw-r--r-- root root 214 ./usr/include/termio.h
+-rw-r--r-- root root 3599 ./usr/include/termios.h
+-rw-r--r-- root root 37419 ./usr/include/tgmath.h
+-rw-r--r-- root root 16024 ./usr/include/thread_db.h
+-rw-r--r-- root root 6661 ./usr/include/threads.h
+-rw-r--r-- root root 14830 ./usr/include/tic.h
+-rw-r--r-- root root 10276 ./usr/include/time.h
+drwxr-xr-x root root 4096 ./usr/include/tirpc
+-rw-r--r-- root root 2195 ./usr/include/tirpc/netconfig.h
+drwxr-xr-x root root 4096 ./usr/include/tirpc/rpc
+-rw-r--r-- root root 4143 ./usr/include/tirpc/rpc/auth_des.h
+-rw-r--r-- root root 11085 ./usr/include/tirpc/rpc/auth.h
+-rw-r--r-- root root 3009 ./usr/include/tirpc/rpc/auth_unix.h
+-rw-r--r-- root root 17067 ./usr/include/tirpc/rpc/clnt.h
+-rw-r--r-- root root 3904 ./usr/include/tirpc/rpc/clnt_soc.h
+-rw-r--r-- root root 2202 ./usr/include/tirpc/rpc/clnt_stat.h
+-rw-r--r-- root root 3706 ./usr/include/tirpc/rpc/des_crypt.h
+-rw-r--r-- root root 3045 ./usr/include/tirpc/rpc/des.h
+-rw-r--r-- root root 8021 ./usr/include/tirpc/rpc/key_prot.h
+-rw-r--r-- root root 2431 ./usr/include/tirpc/rpc/nettype.h
+-rw-r--r-- root root 3582 ./usr/include/tirpc/rpc/pmap_clnt.h
+-rw-r--r-- root root 4064 ./usr/include/tirpc/rpc/pmap_prot.h
+-rw-r--r-- root root 2450 ./usr/include/tirpc/rpc/pmap_rmt.h
+-rw-r--r-- root root 2117 ./usr/include/tirpc/rpc/raw.h
+-rw-r--r-- root root 3496 ./usr/include/tirpc/rpc/rpcb_clnt.h
+-rw-r--r-- root root 25776 ./usr/include/tirpc/rpc/rpcb_prot.h
+-rw-r--r-- root root 14673 ./usr/include/tirpc/rpc/rpcb_prot.x
+-rw-r--r-- root root 3102 ./usr/include/tirpc/rpc/rpc_com.h
+-rw-r--r-- root root 2712 ./usr/include/tirpc/rpc/rpcent.h
+-rw-r--r-- root root 4130 ./usr/include/tirpc/rpc/rpc.h
+-rw-r--r-- root root 5340 ./usr/include/tirpc/rpc/rpc_msg.h
+drwxr-xr-x root root 4096 ./usr/include/tirpc/rpcsvc
+-rw-r--r-- root root 3041 ./usr/include/tirpc/rpc/svc_auth.h
+-rw-r--r-- root root 2414 ./usr/include/tirpc/rpcsvc/crypt.h
+-rw-r--r-- root root 3929 ./usr/include/tirpc/rpcsvc/crypt.x
+-rw-r--r-- root root 2462 ./usr/include/tirpc/rpc/svc_dg.h
+-rw-r--r-- root root 14589 ./usr/include/tirpc/rpc/svc.h
+-rw-r--r-- root root 1912 ./usr/include/tirpc/rpc/svc_mt.h
+-rw-r--r-- root root 3749 ./usr/include/tirpc/rpc/svc_soc.h
+-rw-r--r-- root root 3756 ./usr/include/tirpc/rpc/types.h
+-rw-r--r-- root root 13372 ./usr/include/tirpc/rpc/xdr.h
+-rw-r--r-- root root 2494 ./usr/include/ttyent.h
+-rw-r--r-- root root 2002 ./usr/include/uchar.h
+-rw-r--r-- root root 2037 ./usr/include/ucontext.h
+-rw-r--r-- root root 8998 ./usr/include/udev.h
+-rw-r--r-- root root 1584 ./usr/include/ulimit.h
+-rw-r--r-- root root 3177 ./usr/include/unctrl.h
+-rw-r--r-- root root 42804 ./usr/include/unistd.h
+-rw-r--r-- root root 1502 ./usr/include/utime.h
+-rw-r--r-- root root 3223 ./usr/include/utmp.h
+-rw-r--r-- root root 4100 ./usr/include/utmpx.h
+drwxr-xr-x root root 4096 ./usr/include/uuid
+-rw-r--r-- root root 3910 ./usr/include/uuid/uuid.h
+-rw-r--r-- root root 1956 ./usr/include/values.h
+drwxr-xr-x root root 4096 ./usr/include/video
+-rw-r--r-- root root 213 ./usr/include/video/edid.h
+-rw-r--r-- root root 7643 ./usr/include/video/sisfb.h
+-rw-r--r-- root root 1078 ./usr/include/video/uvesafb.h
+-rw-r--r-- root root 22 ./usr/include/wait.h
+-rw-r--r-- root root 8755 ./usr/include/wayland-client-core.h
+-rw-r--r-- root root 1573 ./usr/include/wayland-client.h
+-rw-r--r-- root root 184232 ./usr/include/wayland-client-protocol.h
+-rw-r--r-- root root 2260 ./usr/include/wayland-cursor.h
+-rw-r--r-- root root 1848 ./usr/include/wayland-egl-backend.h
+-rw-r--r-- root root 1788 ./usr/include/wayland-egl-core.h
+-rw-r--r-- root root 1313 ./usr/include/wayland-egl.h
+-rw-r--r-- root root 19021 ./usr/include/wayland-server-core.h
+-rw-r--r-- root root 3237 ./usr/include/wayland-server.h
+-rw-r--r-- root root 144281 ./usr/include/wayland-server-protocol.h
+-rw-r--r-- root root 24118 ./usr/include/wayland-util.h
+-rw-r--r-- root root 1354 ./usr/include/wayland-version.h
+-rw-r--r-- root root 31111 ./usr/include/wchar.h
+-rw-r--r-- root root 5549 ./usr/include/wctype.h
+-rw-r--r-- root root 2502 ./usr/include/wordexp.h
+drwxr-xr-x root root 4096 ./usr/include/X11
+-rw-r--r-- root root 2293 ./usr/include/X11/ap_keysym.h
+-rw-r--r-- root root 3118 ./usr/include/X11/cursorfont.h
+-rw-r--r-- root root 2815 ./usr/include/X11/DECkeysym.h
+drwxr-xr-x root root 4096 ./usr/include/X11/dri
+-rw-r--r-- root root 2445 ./usr/include/X11/dri/xf86dri.h
+-rw-r--r-- root root 9669 ./usr/include/X11/dri/xf86driproto.h
+-rw-r--r-- root root 174 ./usr/include/X11/dri/xf86dristr.h
+drwxr-xr-x root root 4096 ./usr/include/X11/extensions
+-rw-r--r-- root root 1705 ./usr/include/X11/extensions/ag.h
+-rw-r--r-- root root 5005 ./usr/include/X11/extensions/agproto.h
+-rw-r--r-- root root 2900 ./usr/include/X11/extensions/applewmconst.h
+-rw-r--r-- root root 8098 ./usr/include/X11/extensions/applewmproto.h
+-rw-r--r-- root root 1909 ./usr/include/X11/extensions/bigreqsproto.h
+-rw-r--r-- root root 187 ./usr/include/X11/extensions/bigreqstr.h
+-rw-r--r-- root root 3130 ./usr/include/X11/extensions/composite.h
+-rw-r--r-- root root 5462 ./usr/include/X11/extensions/compositeproto.h
+-rw-r--r-- root root 1353 ./usr/include/X11/extensions/cup.h
+-rw-r--r-- root root 3065 ./usr/include/X11/extensions/cupproto.h
+-rw-r--r-- root root 3615 ./usr/include/X11/extensions/damageproto.h
+-rw-r--r-- root root 1893 ./usr/include/X11/extensions/damagewire.h
+-rw-r--r-- root root 2159 ./usr/include/X11/extensions/dbe.h
+-rw-r--r-- root root 7343 ./usr/include/X11/extensions/dbeproto.h
+-rw-r--r-- root root 2373 ./usr/include/X11/extensions/dmx.h
+-rw-r--r-- root root 13343 ./usr/include/X11/extensions/dmxproto.h
+-rw-r--r-- root root 1778 ./usr/include/X11/extensions/dpmsconst.h
+-rw-r--r-- root root 2161 ./usr/include/X11/extensions/dpms.h
+-rw-r--r-- root root 5288 ./usr/include/X11/extensions/dpmsproto.h
+-rw-r--r-- root root 8318 ./usr/include/X11/extensions/dri2proto.h
+-rw-r--r-- root root 2468 ./usr/include/X11/extensions/dri2tokens.h
+-rw-r--r-- root root 6129 ./usr/include/X11/extensions/dri3proto.h
+-rw-r--r-- root root 1563 ./usr/include/X11/extensions/EVI.h
+-rw-r--r-- root root 3006 ./usr/include/X11/extensions/EVIproto.h
+-rw-r--r-- root root 6096 ./usr/include/X11/extensions/extutil.h
+-rw-r--r-- root root 1782 ./usr/include/X11/extensions/ge.h
+-rw-r--r-- root root 2351 ./usr/include/X11/extensions/geproto.h
+-rw-r--r-- root root 2236 ./usr/include/X11/extensions/lbx.h
+-rw-r--r-- root root 24782 ./usr/include/X11/extensions/lbxproto.h
+-rw-r--r-- root root 1509 ./usr/include/X11/extensions/mitmiscconst.h
+-rw-r--r-- root root 1741 ./usr/include/X11/extensions/MITMisc.h
+-rw-r--r-- root root 2229 ./usr/include/X11/extensions/mitmiscproto.h
+-rw-r--r-- root root 2575 ./usr/include/X11/extensions/multibufconst.h
+-rw-r--r-- root root 5835 ./usr/include/X11/extensions/multibuf.h
+-rw-r--r-- root root 8600 ./usr/include/X11/extensions/multibufproto.h
+-rw-r--r-- root root 5473 ./usr/include/X11/extensions/panoramiXproto.h
+-rw-r--r-- root root 5409 ./usr/include/X11/extensions/presentproto.h
+-rw-r--r-- root root 3597 ./usr/include/X11/extensions/presenttokens.h
+-rw-r--r-- root root 6909 ./usr/include/X11/extensions/randr.h
+-rw-r--r-- root root 25751 ./usr/include/X11/extensions/randrproto.h
+-rw-r--r-- root root 2064 ./usr/include/X11/extensions/recordconst.h
+-rw-r--r-- root root 7634 ./usr/include/X11/extensions/recordproto.h
+-rw-r--r-- root root 258 ./usr/include/X11/extensions/recordstr.h
+-rw-r--r-- root root 6933 ./usr/include/X11/extensions/render.h
+-rw-r--r-- root root 13218 ./usr/include/X11/extensions/renderproto.h
+-rw-r--r-- root root 1900 ./usr/include/X11/extensions/saver.h
+-rw-r--r-- root root 5132 ./usr/include/X11/extensions/saverproto.h
+-rw-r--r-- root root 2141 ./usr/include/X11/extensions/secur.h
+-rw-r--r-- root root 2457 ./usr/include/X11/extensions/security.h
+-rw-r--r-- root root 3177 ./usr/include/X11/extensions/securproto.h
+-rw-r--r-- root root 1878 ./usr/include/X11/extensions/shapeconst.h
+-rw-r--r-- root root 4133 ./usr/include/X11/extensions/shape.h
+-rw-r--r-- root root 6730 ./usr/include/X11/extensions/shapeproto.h
+-rw-r--r-- root root 252 ./usr/include/X11/extensions/shapestr.h
+-rw-r--r-- root root 1645 ./usr/include/X11/extensions/shm.h
+-rw-r--r-- root root 6045 ./usr/include/X11/extensions/shmproto.h
+-rw-r--r-- root root 2123 ./usr/include/X11/extensions/shmstr.h
+-rw-r--r-- root root 6750 ./usr/include/X11/extensions/syncconst.h
+-rw-r--r-- root root 9676 ./usr/include/X11/extensions/sync.h
+-rw-r--r-- root root 11001 ./usr/include/X11/extensions/syncproto.h
+-rw-r--r-- root root 5606 ./usr/include/X11/extensions/syncstr.h
+-rw-r--r-- root root 2377 ./usr/include/X11/extensions/Xag.h
+-rw-r--r-- root root 3057 ./usr/include/X11/extensions/xcmiscproto.h
+-rw-r--r-- root root 185 ./usr/include/X11/extensions/xcmiscstr.h
+-rw-r--r-- root root 1710 ./usr/include/X11/extensions/Xcup.h
+-rw-r--r-- root root 2307 ./usr/include/X11/extensions/Xdamage.h
+-rw-r--r-- root root 4170 ./usr/include/X11/extensions/Xdbe.h
+-rw-r--r-- root root 2130 ./usr/include/X11/extensions/XEVI.h
+-rw-r--r-- root root 1655 ./usr/include/X11/extensions/Xext.h
+-rw-r--r-- root root 414 ./usr/include/X11/extensions/xf86bigfont.h
+-rw-r--r-- root root 2544 ./usr/include/X11/extensions/xf86bigfproto.h
+-rw-r--r-- root root 191 ./usr/include/X11/extensions/xf86bigfstr.h
+-rw-r--r-- root root 931 ./usr/include/X11/extensions/xf86dga1const.h
+-rw-r--r-- root root 4506 ./usr/include/X11/extensions/xf86dga1proto.h
+-rw-r--r-- root root 191 ./usr/include/X11/extensions/xf86dga1str.h
+-rw-r--r-- root root 2533 ./usr/include/X11/extensions/xf86dgaconst.h
+-rw-r--r-- root root 369 ./usr/include/X11/extensions/xf86dga.h
+-rw-r--r-- root root 7106 ./usr/include/X11/extensions/xf86dgaproto.h
+-rw-r--r-- root root 188 ./usr/include/X11/extensions/xf86dgastr.h
+-rw-r--r-- root root 2106 ./usr/include/X11/extensions/xf86vm.h
+-rw-r--r-- root root 7619 ./usr/include/X11/extensions/xf86vmode.h
+-rw-r--r-- root root 15700 ./usr/include/X11/extensions/xf86vmproto.h
+-rw-r--r-- root root 185 ./usr/include/X11/extensions/xf86vmstr.h
+-rw-r--r-- root root 7588 ./usr/include/X11/extensions/Xfixes.h
+-rw-r--r-- root root 12752 ./usr/include/X11/extensions/xfixesproto.h
+-rw-r--r-- root root 5396 ./usr/include/X11/extensions/xfixeswire.h
+-rw-r--r-- root root 1927 ./usr/include/X11/extensions/Xge.h
+-rw-r--r-- root root 10542 ./usr/include/X11/extensions/XI2.h
+-rw-r--r-- root root 37577 ./usr/include/X11/extensions/XI2proto.h
+-rw-r--r-- root root 9823 ./usr/include/X11/extensions/XI.h
+-rw-r--r-- root root 41010 ./usr/include/X11/extensions/XIproto.h
+-rw-r--r-- root root 15808 ./usr/include/X11/extensions/XKBgeom.h
+-rw-r--r-- root root 28211 ./usr/include/X11/extensions/XKB.h
+-rw-r--r-- root root 29105 ./usr/include/X11/extensions/XKBproto.h
+-rw-r--r-- root root 28018 ./usr/include/X11/extensions/XKBsrv.h
+-rw-r--r-- root root 19630 ./usr/include/X11/extensions/XKBstr.h
+-rw-r--r-- root root 1601 ./usr/include/X11/extensions/XLbx.h
+-rw-r--r-- root root 17120 ./usr/include/X11/extensions/Xrandr.h
+-rw-r--r-- root root 12805 ./usr/include/X11/extensions/Xrender.h
+-rw-r--r-- root root 5168 ./usr/include/X11/extensions/XResproto.h
+-rw-r--r-- root root 3735 ./usr/include/X11/extensions/XShm.h
+-rw-r--r-- root root 1392 ./usr/include/X11/extensions/xtestconst.h
+-rw-r--r-- root root 5439 ./usr/include/X11/extensions/xtestext1const.h
+-rw-r--r-- root root 3708 ./usr/include/X11/extensions/xtestext1.h
+-rw-r--r-- root root 7790 ./usr/include/X11/extensions/xtestext1proto.h
+-rw-r--r-- root root 3254 ./usr/include/X11/extensions/xtestproto.h
+-rw-r--r-- root root 3027 ./usr/include/X11/extensions/Xv.h
+-rw-r--r-- root root 3620 ./usr/include/X11/extensions/XvMC.h
+-rw-r--r-- root root 4484 ./usr/include/X11/extensions/XvMCproto.h
+-rw-r--r-- root root 12109 ./usr/include/X11/extensions/Xvproto.h
+drwxr-xr-x root root 4096 ./usr/include/X11/fonts
+-rw-r--r-- root root 4253 ./usr/include/X11/fonts/font.h
+-rw-r--r-- root root 3450 ./usr/include/X11/fonts/fontproto.h
+-rw-r--r-- root root 9401 ./usr/include/X11/fonts/fontstruct.h
+-rw-r--r-- root root 4075 ./usr/include/X11/fonts/FS.h
+-rw-r--r-- root root 3992 ./usr/include/X11/fonts/fsmasks.h
+-rw-r--r-- root root 19889 ./usr/include/X11/fonts/FSproto.h
+-rw-r--r-- root root 6046 ./usr/include/X11/HPkeysym.h
+drwxr-xr-x root root 4096 ./usr/include/X11/ICE
+-rw-r--r-- root root 7413 ./usr/include/X11/ICE/ICEconn.h
+-rw-r--r-- root root 2512 ./usr/include/X11/ICE/ICE.h
+-rw-r--r-- root root 9925 ./usr/include/X11/ICE/ICElib.h
+-rw-r--r-- root root 8206 ./usr/include/X11/ICE/ICEmsg.h
+-rw-r--r-- root root 4604 ./usr/include/X11/ICE/ICEproto.h
+-rw-r--r-- root root 3154 ./usr/include/X11/ICE/ICEutil.h
+-rw-r--r-- root root 459 ./usr/include/X11/ImUtil.h
+-rw-r--r-- root root 175248 ./usr/include/X11/keysymdef.h
+-rw-r--r-- root root 2769 ./usr/include/X11/keysym.h
+drwxr-xr-x root root 4096 ./usr/include/X11/SM
+-rw-r--r-- root root 2927 ./usr/include/X11/SM/SM.h
+-rw-r--r-- root root 11268 ./usr/include/X11/SM/SMlib.h
+-rw-r--r-- root root 4852 ./usr/include/X11/SM/SMproto.h
+-rw-r--r-- root root 4022 ./usr/include/X11/Sunkeysym.h
+-rw-r--r-- root root 4587 ./usr/include/X11/Xalloca.h
+-rw-r--r-- root root 2951 ./usr/include/X11/Xarch.h
+-rw-r--r-- root root 2518 ./usr/include/X11/Xatom.h
+-rw-r--r-- root root 3817 ./usr/include/X11/Xauth.h
+-rw-r--r-- root root 21346 ./usr/include/X11/Xcms.h
+-rw-r--r-- root root 2401 ./usr/include/X11/Xdefs.h
+-rw-r--r-- root root 6371 ./usr/include/X11/Xdmcp.h
+-rw-r--r-- root root 13612 ./usr/include/X11/XF86keysym.h
+-rw-r--r-- root root 7863 ./usr/include/X11/Xfuncproto.h
+-rw-r--r-- root root 2256 ./usr/include/X11/Xfuncs.h
+-rw-r--r-- root root 20137 ./usr/include/X11/X.h
+-rw-r--r-- root root 30995 ./usr/include/X11/XKBlib.h
+-rw-r--r-- root root 1567 ./usr/include/X11/XlibConf.h
+-rw-r--r-- root root 99532 ./usr/include/X11/Xlib.h
+-rw-r--r-- root root 40597 ./usr/include/X11/Xlibint.h
+-rw-r--r-- root root 506 ./usr/include/X11/Xlib-xcb.h
+-rw-r--r-- root root 1297 ./usr/include/X11/Xlocale.h
+-rw-r--r-- root root 5122 ./usr/include/X11/Xmd.h
+-rw-r--r-- root root 3115 ./usr/include/X11/Xosdefs.h
+-rw-r--r-- root root 4362 ./usr/include/X11/Xos.h
+-rw-r--r-- root root 33693 ./usr/include/X11/Xos_r.h
+-rw-r--r-- root root 7743 ./usr/include/X11/Xpoll.h
+-rw-r--r-- root root 52399 ./usr/include/X11/Xproto.h
+-rw-r--r-- root root 2743 ./usr/include/X11/Xprotostr.h
+-rw-r--r-- root root 5949 ./usr/include/X11/Xregion.h
+-rw-r--r-- root root 10628 ./usr/include/X11/Xresource.h
+-rw-r--r-- root root 1719 ./usr/include/X11/xshmfence.h
+-rw-r--r-- root root 12395 ./usr/include/X11/Xthreads.h
+drwxr-xr-x root root 4096 ./usr/include/X11/Xtrans
+-rw-r--r-- root root 2876 ./usr/include/X11/Xtrans/transport.c
+-rw-r--r-- root root 29462 ./usr/include/X11/Xtrans/Xtrans.c
+-rw-r--r-- root root 8785 ./usr/include/X11/Xtrans/Xtrans.h
+-rw-r--r-- root root 10158 ./usr/include/X11/Xtrans/Xtransint.h
+-rw-r--r-- root root 55410 ./usr/include/X11/Xtrans/Xtranslcl.c
+-rw-r--r-- root root 62655 ./usr/include/X11/Xtrans/Xtranssock.c
+-rw-r--r-- root root 14937 ./usr/include/X11/Xtrans/Xtransutil.c
+-rw-r--r-- root root 21353 ./usr/include/X11/Xutil.h
+-rw-r--r-- root root 1909 ./usr/include/X11/Xw32defs.h
+-rw-r--r-- root root 3872 ./usr/include/X11/XWDFile.h
+-rw-r--r-- root root 3283 ./usr/include/X11/Xwindows.h
+-rw-r--r-- root root 2261 ./usr/include/X11/Xwinsock.h
+drwxr-xr-x root root 4096 ./usr/include/xcb
+-rw-r--r-- root root 2407 ./usr/include/xcb/bigreq.h
+-rw-r--r-- root root 13867 ./usr/include/xcb/composite.h
+-rw-r--r-- root root 9285 ./usr/include/xcb/damage.h
+-rw-r--r-- root root 11924 ./usr/include/xcb/dpms.h
+-rw-r--r-- root root 35759 ./usr/include/xcb/dri2.h
+-rw-r--r-- root root 24241 ./usr/include/xcb/dri3.h
+-rw-r--r-- root root 2981 ./usr/include/xcb/ge.h
+-rw-r--r-- root root 252818 ./usr/include/xcb/glx.h
+-rw-r--r-- root root 19292 ./usr/include/xcb/present.h
+-rw-r--r-- root root 139534 ./usr/include/xcb/randr.h
+-rw-r--r-- root root 27912 ./usr/include/xcb/record.h
+-rw-r--r-- root root 103726 ./usr/include/xcb/render.h
+-rw-r--r-- root root 24483 ./usr/include/xcb/res.h
+-rw-r--r-- root root 16460 ./usr/include/xcb/screensaver.h
+-rw-r--r-- root root 20806 ./usr/include/xcb/shape.h
+-rw-r--r-- root root 17261 ./usr/include/xcb/shm.h
+-rw-r--r-- root root 43756 ./usr/include/xcb/sync.h
+-rw-r--r-- root root 13990 ./usr/include/xcb/xcbext.h
+-rw-r--r-- root root 22260 ./usr/include/xcb/xcb.h
+-rw-r--r-- root root 7137 ./usr/include/xcb/xc_misc.h
+-rw-r--r-- root root 11593 ./usr/include/xcb/xevie.h
+-rw-r--r-- root root 28034 ./usr/include/xcb/xf86dri.h
+-rw-r--r-- root root 58079 ./usr/include/xcb/xfixes.h
+-rw-r--r-- root root 14955 ./usr/include/xcb/xinerama.h
+-rw-r--r-- root root 305557 ./usr/include/xcb/xinput.h
+-rw-r--r-- root root 246448 ./usr/include/xcb/xkb.h
+-rw-r--r-- root root 57187 ./usr/include/xcb/xprint.h
+-rw-r--r-- root root 385800 ./usr/include/xcb/xproto.h
+-rw-r--r-- root root 56622 ./usr/include/xcb/xselinux.h
+-rw-r--r-- root root 7589 ./usr/include/xcb/xtest.h
+-rw-r--r-- root root 57788 ./usr/include/xcb/xv.h
+-rw-r--r-- root root 24530 ./usr/include/xcb/xvmc.h
+drwxr-xr-x root root 4096 ./usr/include/xen
+-rw-r--r-- root root 3553 ./usr/include/xen/evtchn.h
+-rw-r--r-- root root 2619 ./usr/include/xen/gntalloc.h
+-rw-r--r-- root root 10647 ./usr/include/xen/gntdev.h
+-rw-r--r-- root root 4206 ./usr/include/xen/privcmd.h
+-rw-r--r-- root root 35465 ./usr/include/xf86drm.h
+-rw-r--r-- root root 18016 ./usr/include/xf86drmMode.h
+-rw-r--r-- root root 19283 ./usr/include/xtables.h
+-rw-r--r-- root root 75 ./usr/include/xtables-version.h
+-rw-r--r-- root root 16262 ./usr/include/zconf.h
+-rw-r--r-- root root 96239 ./usr/include/zlib.h
+drwxr-xr-x root root 20480 ./usr/lib
+drwxr-xr-x root root 4096 ./usr/lib/cmake
+drwxr-xr-x root root 4096 ./usr/lib/cmake/DBus1
+-rw-r--r-- root root 2883 ./usr/lib/cmake/DBus1/DBus1Config.cmake
+-rw-r--r-- root root 367 ./usr/lib/cmake/DBus1/DBus1ConfigVersion.cmake
+drwxr-xr-x root root 4096 ./usr/lib/cmake/libxml2
+-rw-r--r-- root root 1642 ./usr/lib/cmake/libxml2/libxml2-config.cmake
+drwxr-xr-x root root 4096 ./usr/lib/coreutils
+-rwxr-xr-x root root 14144 ./usr/lib/coreutils/libstdbuf.so
+-rw-r--r-- root root 4280 ./usr/lib/crt1.o
+-rw-r--r-- root root 2808 ./usr/lib/crti.o
+-rw-r--r-- root root 2552 ./usr/lib/crtn.o
+drwxr-xr-x root root 4096 ./usr/lib/dbus-1.0
+drwxr-xr-x root root 4096 ./usr/lib/dbus-1.0/include
+drwxr-xr-x root root 4096 ./usr/lib/dbus-1.0/include/dbus
+-rw-r--r-- root root 2052 ./usr/lib/dbus-1.0/include/dbus/dbus-arch-deps.h
+drwxr-xr-x root root 4096 ./usr/lib/dri
+-rwxr-xr-x root root 12207608 ./usr/lib/dri/i915_dri.so
+-rwxr-xr-x root root 12207608 ./usr/lib/dri/i965_dri.so
+-rwxr-xr-x root root 9195384 ./usr/lib/dri/kms_swrast_dri.so
+-rwxr-xr-x root root 12207608 ./usr/lib/dri/nouveau_vieux_dri.so
+-rwxr-xr-x root root 12207608 ./usr/lib/dri/r200_dri.so
+-rwxr-xr-x root root 12207608 ./usr/lib/dri/radeon_dri.so
+-rwxr-xr-x root root 9195384 ./usr/lib/dri/swrast_dri.so
+-rwxr-xr-x root root 9195384 ./usr/lib/dri/virtio_gpu_dri.so
+-rwxr-xr-x root root 14376 ./usr/lib/e2initrd_helper
+drwxr-xr-x root root 4096 ./usr/libexec
+drwxr-xr-x root root 4096 ./usr/libexec/awk
+-rwxr-xr-x root root 14288 ./usr/libexec/awk/grcat
+-rwxr-xr-x root root 14288 ./usr/libexec/awk/pwcat
+-rwsr-xr-x root messagebus 63592 ./usr/libexec/dbus-daemon-launch-helper
+-rwxr-xr-x root root 43168 ./usr/libexec/frcode
+-rwxr-xr-x root root 14304 ./usr/libexec/gio-querymodules
+-rwxr-xr-x root root 354584 ./usr/libexec/udevadm
+drwxr-xr-x root root 4096 ./usr/lib/gawk
+-rwxr-xr-x root root 39016 ./usr/lib/gawk/filefuncs.so
+-rwxr-xr-x root root 14288 ./usr/lib/gawk/fnmatch.so
+-rwxr-xr-x root root 14304 ./usr/lib/gawk/fork.so
+-rwxr-xr-x root root 14288 ./usr/lib/gawk/inplace.so
+-rwxr-xr-x root root 14208 ./usr/lib/gawk/intdiv.so
+-rwxr-xr-x root root 14256 ./usr/lib/gawk/ordchr.so
+-rwxr-xr-x root root 14192 ./usr/lib/gawk/readdir.so
+-rwxr-xr-x root root 14256 ./usr/lib/gawk/readfile.so
+-rwxr-xr-x root root 14200 ./usr/lib/gawk/revoutput.so
+-rwxr-xr-x root root 14200 ./usr/lib/gawk/revtwoway.so
+-rwxr-xr-x root root 18352 ./usr/lib/gawk/rwarray.so
+-rwxr-xr-x root root 14256 ./usr/lib/gawk/time.so
+-rw-r--r-- root root 7064 ./usr/lib/gcrt1.o
+drwxr-xr-x root root 4096 ./usr/lib/gio
+drwxr-xr-x root root 4096 ./usr/lib/gio/modules
+drwxr-xr-x root root 4096 ./usr/lib/girepository-1.0
+-rw-r--r-- root root 14344 ./usr/lib/girepository-1.0/cairo-1.0.typelib
+-rw-r--r-- root root 712 ./usr/lib/girepository-1.0/DBus-1.0.typelib
+-rw-r--r-- root root 560 ./usr/lib/girepository-1.0/DBusGLib-1.0.typelib
+-rw-r--r-- root root 348 ./usr/lib/girepository-1.0/fontconfig-2.0.typelib
+-rw-r--r-- root root 420 ./usr/lib/girepository-1.0/freetype2-2.0.typelib
+-rw-r--r-- root root 353336 ./usr/lib/girepository-1.0/Gio-2.0.typelib
+-rw-r--r-- root root 27752 ./usr/lib/girepository-1.0/GIRepository-2.0.typelib
+-rw-r--r-- root root 948 ./usr/lib/girepository-1.0/GL-1.0.typelib
+-rw-r--r-- root root 191884 ./usr/lib/girepository-1.0/GLib-2.0.typelib
+-rw-r--r-- root root 1340 ./usr/lib/girepository-1.0/GModule-2.0.typelib
+-rw-r--r-- root root 58972 ./usr/lib/girepository-1.0/GObject-2.0.typelib
+-rw-r--r-- root root 668 ./usr/lib/girepository-1.0/libxml2-2.0.typelib
+-rw-r--r-- root root 59380 ./usr/lib/girepository-1.0/Vulkan-1.0.typelib
+-rw-r--r-- root root 176 ./usr/lib/girepository-1.0/win32-1.0.typelib
+-rw-r--r-- root root 240 ./usr/lib/girepository-1.0/xfixes-4.0.typelib
+-rw-r--r-- root root 464 ./usr/lib/girepository-1.0/xft-2.0.typelib
+-rw-r--r-- root root 836 ./usr/lib/girepository-1.0/xlib-2.0.typelib
+-rw-r--r-- root root 640 ./usr/lib/girepository-1.0/xrandr-1.3.typelib
+drwxr-xr-x root root 4096 ./usr/lib/glib-2.0
+drwxr-xr-x root root 4096 ./usr/lib/glib-2.0/include
+-rw-r--r-- root root 5649 ./usr/lib/glib-2.0/include/glibconfig.h
+drwxr-xr-x root root 4096 ./usr/lib/gobject-introspection
+drwxr-xr-x root root 4096 ./usr/lib/gobject-introspection/giscanner
+-rw-r--r-- root root 3526 ./usr/lib/gobject-introspection/giscanner/annotationmain.py
+-rw-r--r-- root root 101376 ./usr/lib/gobject-introspection/giscanner/annotationparser.py
+-rw-r--r-- root root 43411 ./usr/lib/gobject-introspection/giscanner/ast.py
+-rw-r--r-- root root 5852 ./usr/lib/gobject-introspection/giscanner/cachestore.py
+-rw-r--r-- root root 19524 ./usr/lib/gobject-introspection/giscanner/ccompiler.py
+-rw-r--r-- root root 6190 ./usr/lib/gobject-introspection/giscanner/codegen.py
+-rw-r--r-- root root 3268 ./usr/lib/gobject-introspection/giscanner/docmain.py
+drwxr-xr-x root root 4096 ./usr/lib/gobject-introspection/giscanner/doctemplates
+drwxr-xr-x root root 4096 ./usr/lib/gobject-introspection/giscanner/doctemplates/devdocs
+drwxr-xr-x root root 4096 ./usr/lib/gobject-introspection/giscanner/doctemplates/devdocs/Gjs
+-rw-r--r-- root root 567 ./usr/lib/gobject-introspection/giscanner/doctemplates/devdocs/Gjs/base.tmpl
+-rw-r--r-- root root 113 ./usr/lib/gobject-introspection/giscanner/doctemplates/devdocs/Gjs/callback.tmpl
+-rw-r--r-- root root 29 ./usr/lib/gobject-introspection/giscanner/doctemplates/devdocs/Gjs/class.tmpl
+-rw-r--r-- root root 847 ./usr/lib/gobject-introspection/giscanner/doctemplates/devdocs/Gjs/default.tmpl
+-rw-r--r-- root root 890 ./usr/lib/gobject-introspection/giscanner/doctemplates/devdocs/Gjs/_doc.tmpl
+-rw-r--r-- root root 313 ./usr/lib/gobject-introspection/giscanner/doctemplates/devdocs/Gjs/enum.tmpl
+-rw-r--r-- root root 113 ./usr/lib/gobject-introspection/giscanner/doctemplates/devdocs/Gjs/function.tmpl
+-rw-r--r-- root root 5189 ./usr/lib/gobject-introspection/giscanner/doctemplates/devdocs/Gjs/_index.tmpl
+-rw-r--r-- root root 29 ./usr/lib/gobject-introspection/giscanner/doctemplates/devdocs/Gjs/interface.tmpl
+-rw-r--r-- root root 120 ./usr/lib/gobject-introspection/giscanner/doctemplates/devdocs/Gjs/_methods.tmpl
+-rw-r--r-- root root 1899 ./usr/lib/gobject-introspection/giscanner/doctemplates/devdocs/Gjs/_method.tmpl
+-rw-r--r-- root root 32 ./usr/lib/gobject-introspection/giscanner/doctemplates/devdocs/Gjs/method.tmpl
+-rw-r--r-- root root 1278 ./usr/lib/gobject-introspection/giscanner/doctemplates/devdocs/Gjs/namespace.tmpl
+-rw-r--r-- root root 1123 ./usr/lib/gobject-introspection/giscanner/doctemplates/devdocs/Gjs/_properties.tmpl
+-rw-r--r-- root root 652 ./usr/lib/gobject-introspection/giscanner/doctemplates/devdocs/Gjs/_signals.tmpl
+-rw-r--r-- root root 176 ./usr/lib/gobject-introspection/giscanner/doctemplates/devdocs/Gjs/_staticmethods.tmpl
+-rw-r--r-- root root 183 ./usr/lib/gobject-introspection/giscanner/doctemplates/devdocs/Gjs/_vfuncs.tmpl
+drwxr-xr-x root root 4096 ./usr/lib/gobject-introspection/giscanner/doctemplates/mallard
+-rw-r--r-- root root 765 ./usr/lib/gobject-introspection/giscanner/doctemplates/mallard/base.tmpl
+drwxr-xr-x root root 4096 ./usr/lib/gobject-introspection/giscanner/doctemplates/mallard/C
+-rw-r--r-- root root 141 ./usr/lib/gobject-introspection/giscanner/doctemplates/mallard/C/callback.tmpl
+-rw-r--r-- root root 57 ./usr/lib/gobject-introspection/giscanner/doctemplates/mallard/C/class.tmpl
+-rw-r--r-- root root 35 ./usr/lib/gobject-introspection/giscanner/doctemplates/mallard/C/constructor.tmpl
+-rw-r--r-- root root 30 ./usr/lib/gobject-introspection/giscanner/doctemplates/mallard/C/default.tmpl
+-rw-r--r-- root root 56 ./usr/lib/gobject-introspection/giscanner/doctemplates/mallard/C/enum.tmpl
+-rw-r--r-- root root 30 ./usr/lib/gobject-introspection/giscanner/doctemplates/mallard/C/field.tmpl
+-rw-r--r-- root root 1654 ./usr/lib/gobject-introspection/giscanner/doctemplates/mallard/C/function.tmpl
+-rw-r--r-- root root 57 ./usr/lib/gobject-introspection/giscanner/doctemplates/mallard/C/interface.tmpl
+-rw-r--r-- root root 1982 ./usr/lib/gobject-introspection/giscanner/doctemplates/mallard/class.tmpl
+-rw-r--r-- root root 35 ./usr/lib/gobject-introspection/giscanner/doctemplates/mallard/C/method.tmpl
+-rw-r--r-- root root 35 ./usr/lib/gobject-introspection/giscanner/doctemplates/mallard/C/namespace.tmpl
+-rw-r--r-- root root 191 ./usr/lib/gobject-introspection/giscanner/doctemplates/mallard/C/property.tmpl
+-rw-r--r-- root root 30 ./usr/lib/gobject-introspection/giscanner/doctemplates/mallard/C/record.tmpl
+-rw-r--r-- root root 196 ./usr/lib/gobject-introspection/giscanner/doctemplates/mallard/C/signal.tmpl
+-rw-r--r-- root root 139 ./usr/lib/gobject-introspection/giscanner/doctemplates/mallard/C/vfunc.tmpl
+drwxr-xr-x root root 4096 ./usr/lib/gobject-introspection/giscanner/doctemplates/mallard/Gjs
+-rw-r--r-- root root 780 ./usr/lib/gobject-introspection/giscanner/doctemplates/mallard/Gjs/callback.tmpl
+-rw-r--r-- root root 863 ./usr/lib/gobject-introspection/giscanner/doctemplates/mallard/Gjs/class.tmpl
+-rw-r--r-- root root 35 ./usr/lib/gobject-introspection/giscanner/doctemplates/mallard/Gjs/constructor.tmpl
+-rw-r--r-- root root 30 ./usr/lib/gobject-introspection/giscanner/doctemplates/mallard/Gjs/default.tmpl
+-rw-r--r-- root root 511 ./usr/lib/gobject-introspection/giscanner/doctemplates/mallard/Gjs/enum.tmpl
+-rw-r--r-- root root 423 ./usr/lib/gobject-introspection/giscanner/doctemplates/mallard/Gjs/field.tmpl
+-rw-r--r-- root root 1469 ./usr/lib/gobject-introspection/giscanner/doctemplates/mallard/Gjs/function.tmpl
+-rw-r--r-- root root 558 ./usr/lib/gobject-introspection/giscanner/doctemplates/mallard/Gjs/interface.tmpl
+-rw-r--r-- root root 35 ./usr/lib/gobject-introspection/giscanner/doctemplates/mallard/Gjs/method.tmpl
+-rw-r--r-- root root 61 ./usr/lib/gobject-introspection/giscanner/doctemplates/mallard/Gjs/namespace.tmpl
+-rw-r--r-- root root 423 ./usr/lib/gobject-introspection/giscanner/doctemplates/mallard/Gjs/property.tmpl
+-rw-r--r-- root root 56 ./usr/lib/gobject-introspection/giscanner/doctemplates/mallard/Gjs/record.tmpl
+-rw-r--r-- root root 1185 ./usr/lib/gobject-introspection/giscanner/doctemplates/mallard/Gjs/signal.tmpl
+-rw-r--r-- root root 746 ./usr/lib/gobject-introspection/giscanner/doctemplates/mallard/Gjs/vfunc.tmpl
+-rw-r--r-- root root 551 ./usr/lib/gobject-introspection/giscanner/doctemplates/mallard/namespace.tmpl
+drwxr-xr-x root root 4096 ./usr/lib/gobject-introspection/giscanner/doctemplates/mallard/Python
+-rw-r--r-- root root 849 ./usr/lib/gobject-introspection/giscanner/doctemplates/mallard/Python/callback.tmpl
+-rw-r--r-- root root 593 ./usr/lib/gobject-introspection/giscanner/doctemplates/mallard/Python/class.tmpl
+-rw-r--r-- root root 35 ./usr/lib/gobject-introspection/giscanner/doctemplates/mallard/Python/constructor.tmpl
+-rw-r--r-- root root 30 ./usr/lib/gobject-introspection/giscanner/doctemplates/mallard/Python/default.tmpl
+-rw-r--r-- root root 264 ./usr/lib/gobject-introspection/giscanner/doctemplates/mallard/Python/enum.tmpl
+-rw-r--r-- root root 30 ./usr/lib/gobject-introspection/giscanner/doctemplates/mallard/Python/field.tmpl
+-rw-r--r-- root root 1572 ./usr/lib/gobject-introspection/giscanner/doctemplates/mallard/Python/function.tmpl
+-rw-r--r-- root root 535 ./usr/lib/gobject-introspection/giscanner/doctemplates/mallard/Python/interface.tmpl
+-rw-r--r-- root root 35 ./usr/lib/gobject-introspection/giscanner/doctemplates/mallard/Python/method.tmpl
+-rw-r--r-- root root 61 ./usr/lib/gobject-introspection/giscanner/doctemplates/mallard/Python/namespace.tmpl
+-rw-r--r-- root root 407 ./usr/lib/gobject-introspection/giscanner/doctemplates/mallard/Python/property.tmpl
+-rw-r--r-- root root 56 ./usr/lib/gobject-introspection/giscanner/doctemplates/mallard/Python/record.tmpl
+-rw-r--r-- root root 1235 ./usr/lib/gobject-introspection/giscanner/doctemplates/mallard/Python/signal.tmpl
+-rw-r--r-- root root 849 ./usr/lib/gobject-introspection/giscanner/doctemplates/mallard/Python/vfunc.tmpl
+-rw-r--r-- root root 50143 ./usr/lib/gobject-introspection/giscanner/docwriter.py
+-rw-r--r-- root root 10639 ./usr/lib/gobject-introspection/giscanner/dumper.py
+-rw-r--r-- root root 21322 ./usr/lib/gobject-introspection/giscanner/gdumpparser.py
+-rw-r--r-- root root 28229 ./usr/lib/gobject-introspection/giscanner/girparser.py
+-rw-r--r-- root root 28222 ./usr/lib/gobject-introspection/giscanner/girwriter.py
+-rwxr-xr-x root root 101672 ./usr/lib/gobject-introspection/giscanner/_giscanner.cpython-38-x86_64-linux-gnu.so
+-rw-r--r-- root root 1105 ./usr/lib/gobject-introspection/giscanner/__init__.py
+-rw-r--r-- root root 9398 ./usr/lib/gobject-introspection/giscanner/introspectablepass.py
+-rw-r--r-- root root 2554 ./usr/lib/gobject-introspection/giscanner/libtoolimporter.py
+-rw-r--r-- root root 65300 ./usr/lib/gobject-introspection/giscanner/maintransformer.py
+-rw-r--r-- root root 392 ./usr/lib/gobject-introspection/giscanner/mdextensions.py
+-rw-r--r-- root root 7612 ./usr/lib/gobject-introspection/giscanner/message.py
+-rw-r--r-- root root 3756 ./usr/lib/gobject-introspection/giscanner/msvccompiler.py
+-rw-r--r-- root root 2283 ./usr/lib/gobject-introspection/giscanner/pkgconfig.py
+-rw-r--r-- root root 27285 ./usr/lib/gobject-introspection/giscanner/scannermain.py
+-rw-r--r-- root root 4790 ./usr/lib/gobject-introspection/giscanner/sectionparser.py
+-rw-r--r-- root root 6259 ./usr/lib/gobject-introspection/giscanner/shlibs.py
+-rw-r--r-- root root 9628 ./usr/lib/gobject-introspection/giscanner/sourcescanner.py
+-rw-r--r-- root root 5699 ./usr/lib/gobject-introspection/giscanner/testcodegen.py
+-rw-r--r-- root root 44647 ./usr/lib/gobject-introspection/giscanner/transformer.py
+-rw-r--r-- root root 10521 ./usr/lib/gobject-introspection/giscanner/utils.py
+-rw-r--r-- root root 23 ./usr/lib/gobject-introspection/giscanner/_version.py
+-rw-r--r-- root root 5798 ./usr/lib/gobject-introspection/giscanner/xmlwriter.py
+-rwxr-xr-x root root 38904 ./usr/lib/libacl.so.1.1.2253
+lrwxrwxrwx root root 18 ./usr/lib/libacl.so.1 -> libacl.so.1.1.2253
+lrwxrwxrwx root root 18 ./usr/lib/libacl.so -> libacl.so.1.1.2253
+lrwxrwxrwx root root 21 ./usr/lib/libanl.so -> ../../lib/libanl.so.1
+-rwxr-xr-x root root 34856 ./usr/lib/libasm-0.179.so
+lrwxrwxrwx root root 15 ./usr/lib/libasm.so.1 -> libasm-0.179.so
+lrwxrwxrwx root root 11 ./usr/lib/libasm.so -> libasm.so.1
+-rwxr-xr-x root root 26512 ./usr/lib/libattr.so.1.1.2448
+lrwxrwxrwx root root 19 ./usr/lib/libattr.so.1 -> libattr.so.1.1.2448
+lrwxrwxrwx root root 19 ./usr/lib/libattr.so -> libattr.so.1.1.2448
+-rwxr-xr-x root root 1310600 ./usr/lib/libbfd-2.34.0.20200220.so
+lrwxrwxrwx root root 25 ./usr/lib/libbfd.so -> libbfd-2.34.0.20200220.so
+lrwxrwxrwx root root 27 ./usr/lib/libblkid.so -> ../../lib/libblkid.so.1.1.0
+lrwxrwxrwx root root 30 ./usr/lib/libBrokenLocale.so -> ../../lib/libBrokenLocale.so.1
+-rwxr-xr-x root root 383584 ./usr/lib/libbtrfs.so.0.1
+lrwxrwxrwx root root 15 ./usr/lib/libbtrfs.so.0 -> libbtrfs.so.0.1
+lrwxrwxrwx root root 15 ./usr/lib/libbtrfs.so -> libbtrfs.so.0.1
+-rwxr-xr-x root root 34704 ./usr/lib/libbtrfsutil.so.1.1.1
+lrwxrwxrwx root root 21 ./usr/lib/libbtrfsutil.so.1 -> libbtrfsutil.so.1.1.1
+lrwxrwxrwx root root 21 ./usr/lib/libbtrfsutil.so -> libbtrfsutil.so.1.1.1
+-rwxr-xr-x root root 74656 ./usr/lib/libbz2.so.1.0.6
+lrwxrwxrwx root root 15 ./usr/lib/libbz2.so.1 -> libbz2.so.1.0.6
+lrwxrwxrwx root root 15 ./usr/lib/libbz2.so -> libbz2.so.1.0.6
+-rwxr-xr-x root root 42752 ./usr/lib/libcairo-gobject.so.2.11600.0
+lrwxrwxrwx root root 29 ./usr/lib/libcairo-gobject.so.2 -> libcairo-gobject.so.2.11600.0
+lrwxrwxrwx root root 29 ./usr/lib/libcairo-gobject.so -> libcairo-gobject.so.2.11600.0
+-rwxr-xr-x root root 156384 ./usr/lib/libcairo-script-interpreter.so.2.11600.0
+lrwxrwxrwx root root 40 ./usr/lib/libcairo-script-interpreter.so.2 -> libcairo-script-interpreter.so.2.11600.0
+lrwxrwxrwx root root 40 ./usr/lib/libcairo-script-interpreter.so -> libcairo-script-interpreter.so.2.11600.0
+-rwxr-xr-x root root 1291312 ./usr/lib/libcairo.so.2.11600.0
+lrwxrwxrwx root root 21 ./usr/lib/libcairo.so.2 -> libcairo.so.2.11600.0
+lrwxrwxrwx root root 21 ./usr/lib/libcairo.so -> libcairo.so.2.11600.0
+lrwxrwxrwx root root 28 ./usr/lib/libcap-ng.so -> ../../lib/libcap-ng.so.0.0.0
+-rw-r--r-- root root 76674 ./usr/lib/libc_nonshared.a
+-rwxr-xr-x root root 2872136 ./usr/lib/libcrypto.so.1.1
+lrwxrwxrwx root root 16 ./usr/lib/libcrypto.so -> libcrypto.so.1.1
+-rwxr-xr-x root root 202648 ./usr/lib/libcrypt.so.2.0.0
+lrwxrwxrwx root root 17 ./usr/lib/libcrypt.so.2 -> libcrypt.so.2.0.0
+lrwxrwxrwx root root 17 ./usr/lib/libcrypt.so -> libcrypt.so.2.0.0
+-rw-r--r-- root root 247 ./usr/lib/libc.so
+-rwxr-xr-x root root 116736 ./usr/lib/libctf-nobfd.so.0.0.0
+lrwxrwxrwx root root 21 ./usr/lib/libctf-nobfd.so.0 -> libctf-nobfd.so.0.0.0
+lrwxrwxrwx root root 21 ./usr/lib/libctf-nobfd.so -> libctf-nobfd.so.0.0.0
+-rwxr-xr-x root root 116728 ./usr/lib/libctf.so.0.0.0
+lrwxrwxrwx root root 15 ./usr/lib/libctf.so.0 -> libctf.so.0.0.0
+lrwxrwxrwx root root 15 ./usr/lib/libctf.so -> libctf.so.0.0.0
+lrwxrwxrwx root root 13 ./usr/lib/libcurses.so -> libncurses.so
+-rwxr-xr-x root root 1267928 ./usr/lib/libdb-5.3.so
+lrwxrwxrwx root root 12 ./usr/lib/libdb-5.so -> libdb-5.3.so
+lrwxrwxrwx root root 12 ./usr/lib/libdb.so -> libdb-5.3.so
+-rwxr-xr-x root root 346240 ./usr/lib/libdbus-1.so.3.19.11
+lrwxrwxrwx root root 20 ./usr/lib/libdbus-1.so.3 -> libdbus-1.so.3.19.11
+lrwxrwxrwx root root 20 ./usr/lib/libdbus-1.so -> libdbus-1.so.3.19.11
+lrwxrwxrwx root root 20 ./usr/lib/libdl.so -> ../../lib/libdl.so.2
+-rwxr-xr-x root root 42824 ./usr/lib/libdrm_amdgpu.so.1.0.0
+lrwxrwxrwx root root 22 ./usr/lib/libdrm_amdgpu.so.1 -> libdrm_amdgpu.so.1.0.0
+lrwxrwxrwx root root 18 ./usr/lib/libdrm_amdgpu.so -> libdrm_amdgpu.so.1
+-rwxr-xr-x root root 30536 ./usr/lib/libdrm_etnaviv.so.1.0.0
+lrwxrwxrwx root root 23 ./usr/lib/libdrm_etnaviv.so.1 -> libdrm_etnaviv.so.1.0.0
+lrwxrwxrwx root root 19 ./usr/lib/libdrm_etnaviv.so -> libdrm_etnaviv.so.1
+-rwxr-xr-x root root 34712 ./usr/lib/libdrm_freedreno.so.1.0.0
+lrwxrwxrwx root root 25 ./usr/lib/libdrm_freedreno.so.1 -> libdrm_freedreno.so.1.0.0
+lrwxrwxrwx root root 21 ./usr/lib/libdrm_freedreno.so -> libdrm_freedreno.so.1
+-rwxr-xr-x root root 146920 ./usr/lib/libdrm_intel.so.1.0.0
+lrwxrwxrwx root root 21 ./usr/lib/libdrm_intel.so.1 -> libdrm_intel.so.1.0.0
+lrwxrwxrwx root root 17 ./usr/lib/libdrm_intel.so -> libdrm_intel.so.1
+-rwxr-xr-x root root 34632 ./usr/lib/libdrm_nouveau.so.2.0.0
+lrwxrwxrwx root root 23 ./usr/lib/libdrm_nouveau.so.2 -> libdrm_nouveau.so.2.0.0
+lrwxrwxrwx root root 19 ./usr/lib/libdrm_nouveau.so -> libdrm_nouveau.so.2
+-rwxr-xr-x root root 14080 ./usr/lib/libdrm_omap.so.1.0.0
+lrwxrwxrwx root root 20 ./usr/lib/libdrm_omap.so.1 -> libdrm_omap.so.1.0.0
+lrwxrwxrwx root root 16 ./usr/lib/libdrm_omap.so -> libdrm_omap.so.1
+-rwxr-xr-x root root 55184 ./usr/lib/libdrm_radeon.so.1.0.1
+lrwxrwxrwx root root 22 ./usr/lib/libdrm_radeon.so.1 -> libdrm_radeon.so.1.0.1
+lrwxrwxrwx root root 18 ./usr/lib/libdrm_radeon.so -> libdrm_radeon.so.1
+-rwxr-xr-x root root 79752 ./usr/lib/libdrm.so.2.4.0
+lrwxrwxrwx root root 15 ./usr/lib/libdrm.so.2 -> libdrm.so.2.4.0
+lrwxrwxrwx root root 11 ./usr/lib/libdrm.so -> libdrm.so.2
+-rwxr-xr-x root root 650160 ./usr/lib/libdw-0.179.so
+lrwxrwxrwx root root 14 ./usr/lib/libdw.so.1 -> libdw-0.179.so
+lrwxrwxrwx root root 10 ./usr/lib/libdw.so -> libdw.so.1
+-rwxr-xr-x root root 100384 ./usr/lib/libelf-0.179.so
+lrwxrwxrwx root root 15 ./usr/lib/libelf.so.1 -> libelf-0.179.so
+lrwxrwxrwx root root 11 ./usr/lib/libelf.so -> libelf.so.1
+-rwxr-xr-x root root 182160 ./usr/lib/libexpat.so.1.6.11
+lrwxrwxrwx root root 18 ./usr/lib/libexpat.so.1 -> libexpat.so.1.6.11
+lrwxrwxrwx root root 18 ./usr/lib/libexpat.so -> libexpat.so.1.6.11
+lrwxrwxrwx root root 27 ./usr/lib/libfdisk.so -> ../../lib/libfdisk.so.1.1.0
+-rwxr-xr-x root root 43032 ./usr/lib/libffi.so.7.1.0
+lrwxrwxrwx root root 15 ./usr/lib/libffi.so.7 -> libffi.so.7.1.0
+lrwxrwxrwx root root 15 ./usr/lib/libffi.so -> libffi.so.7.1.0
+-rwxr-xr-x root root 14072 ./usr/lib/libfl.so.2.0.0
+lrwxrwxrwx root root 14 ./usr/lib/libfl.so.2 -> libfl.so.2.0.0
+lrwxrwxrwx root root 14 ./usr/lib/libfl.so -> libfl.so.2.0.0
+-rwxr-xr-x root root 288664 ./usr/lib/libfontconfig.so.1.12.0
+lrwxrwxrwx root root 23 ./usr/lib/libfontconfig.so.1 -> libfontconfig.so.1.12.0
+lrwxrwxrwx root root 23 ./usr/lib/libfontconfig.so -> libfontconfig.so.1.12.0
+-rwxr-xr-x root root 68696 ./usr/lib/libform.so.5.9
+lrwxrwxrwx root root 14 ./usr/lib/libform.so.5 -> libform.so.5.9
+lrwxrwxrwx root root 12 ./usr/lib/libform.so -> libform.so.5
+-rwxr-xr-x root root 76952 ./usr/lib/libformw.so.5.9
+lrwxrwxrwx root root 15 ./usr/lib/libformw.so.5 -> libformw.so.5.9
+lrwxrwxrwx root root 13 ./usr/lib/libformw.so -> libformw.so.5
+-rwxr-xr-x root root 722832 ./usr/lib/libfreetype.so.6.17.2
+lrwxrwxrwx root root 21 ./usr/lib/libfreetype.so.6 -> libfreetype.so.6.17.2
+lrwxrwxrwx root root 21 ./usr/lib/libfreetype.so -> libfreetype.so.6.17.2
+-rwxr-xr-x root root 14080 ./usr/lib/libgdbm_compat.so.4.0.0
+lrwxrwxrwx root root 23 ./usr/lib/libgdbm_compat.so.4 -> libgdbm_compat.so.4.0.0
+lrwxrwxrwx root root 23 ./usr/lib/libgdbm_compat.so -> libgdbm_compat.so.4.0.0
+-rwxr-xr-x root root 59392 ./usr/lib/libgdbm.so.6.0.0
+lrwxrwxrwx root root 16 ./usr/lib/libgdbm.so.6 -> libgdbm.so.6.0.0
+lrwxrwxrwx root root 16 ./usr/lib/libgdbm.so -> libgdbm.so.6.0.0
+-rwxr-xr-x root root 1932600 ./usr/lib/libgio-2.0.so.0.6400.2
+lrwxrwxrwx root root 22 ./usr/lib/libgio-2.0.so.0 -> libgio-2.0.so.0.6400.2
+lrwxrwxrwx root root 15 ./usr/lib/libgio-2.0.so -> libgio-2.0.so.0
+-rwxr-xr-x root root 223248 ./usr/lib/libgirepository-1.0.so.1.0.0
+lrwxrwxrwx root root 28 ./usr/lib/libgirepository-1.0.so.1 -> libgirepository-1.0.so.1.0.0
+lrwxrwxrwx root root 24 ./usr/lib/libgirepository-1.0.so -> libgirepository-1.0.so.1
+-rwxr-xr-x root root 325664 ./usr/lib/libglapi.so.0.0.0
+lrwxrwxrwx root root 17 ./usr/lib/libglapi.so.0 -> libglapi.so.0.0.0
+lrwxrwxrwx root root 13 ./usr/lib/libglapi.so -> libglapi.so.0
+-rwxr-xr-x root root 1203480 ./usr/lib/libglib-2.0.so.0.6400.2
+lrwxrwxrwx root root 23 ./usr/lib/libglib-2.0.so.0 -> libglib-2.0.so.0.6400.2
+lrwxrwxrwx root root 16 ./usr/lib/libglib-2.0.so -> libglib-2.0.so.0
+-rwxr-xr-x root root 498608 ./usr/lib/libGL.so.1.2.0
+lrwxrwxrwx root root 14 ./usr/lib/libGL.so.1 -> libGL.so.1.2.0
+lrwxrwxrwx root root 10 ./usr/lib/libGL.so -> libGL.so.1
+-rwxr-xr-x root root 18304 ./usr/lib/libgmodule-2.0.so.0.6400.2
+lrwxrwxrwx root root 26 ./usr/lib/libgmodule-2.0.so.0 -> libgmodule-2.0.so.0.6400.2
+lrwxrwxrwx root root 19 ./usr/lib/libgmodule-2.0.so -> libgmodule-2.0.so.0
+-rwxr-xr-x root root 489440 ./usr/lib/libgmp.so.10.4.0
+lrwxrwxrwx root root 16 ./usr/lib/libgmp.so.10 -> libgmp.so.10.4.0
+lrwxrwxrwx root root 16 ./usr/lib/libgmp.so -> libgmp.so.10.4.0
+-rwxr-xr-x root root 30696 ./usr/lib/libgmpxx.so.4.6.0
+lrwxrwxrwx root root 17 ./usr/lib/libgmpxx.so.4 -> libgmpxx.so.4.6.0
+lrwxrwxrwx root root 17 ./usr/lib/libgmpxx.so -> libgmpxx.so.4.6.0
+-rwxr-xr-x root root 354344 ./usr/lib/libgobject-2.0.so.0.6400.2
+lrwxrwxrwx root root 26 ./usr/lib/libgobject-2.0.so.0 -> libgobject-2.0.so.0.6400.2
+lrwxrwxrwx root root 19 ./usr/lib/libgobject-2.0.so -> libgobject-2.0.so.0
+-rwxr-xr-x root root 14000 ./usr/lib/libgthread-2.0.so.0.6400.2
+lrwxrwxrwx root root 26 ./usr/lib/libgthread-2.0.so.0 -> libgthread-2.0.so.0.6400.2
+lrwxrwxrwx root root 19 ./usr/lib/libgthread-2.0.so -> libgthread-2.0.so.0
+-rwxr-xr-x root root 46944 ./usr/lib/libhistory.so.8.0
+lrwxrwxrwx root root 17 ./usr/lib/libhistory.so.8 -> libhistory.so.8.0
+lrwxrwxrwx root root 17 ./usr/lib/libhistory.so -> libhistory.so.8.0
+-rwxr-xr-x root root 101096 ./usr/lib/libICE.so.6.3.0
+lrwxrwxrwx root root 15 ./usr/lib/libICE.so.6 -> libICE.so.6.3.0
+lrwxrwxrwx root root 15 ./usr/lib/libICE.so -> libICE.so.6.3.0
+-rwxr-xr-x root root 35256 ./usr/lib/libip4tc.so.2.0.0
+lrwxrwxrwx root root 17 ./usr/lib/libip4tc.so.2 -> libip4tc.so.2.0.0
+lrwxrwxrwx root root 17 ./usr/lib/libip4tc.so -> libip4tc.so.2.0.0
+-rwxr-xr-x root root 35256 ./usr/lib/libip6tc.so.2.0.0
+lrwxrwxrwx root root 17 ./usr/lib/libip6tc.so.2 -> libip6tc.so.2.0.0
+lrwxrwxrwx root root 17 ./usr/lib/libip6tc.so -> libip6tc.so.2.0.0
+-rwxr-xr-x root root 83992 ./usr/lib/libkmod.so.2.3.4
+lrwxrwxrwx root root 16 ./usr/lib/libkmod.so.2 -> libkmod.so.2.3.4
+lrwxrwxrwx root root 16 ./usr/lib/libkmod.so -> libkmod.so.2.3.4
+-rwxr-xr-x root root 18240 ./usr/lib/libkms.so.1.0.0
+lrwxrwxrwx root root 15 ./usr/lib/libkms.so.1 -> libkms.so.1.0.0
+lrwxrwxrwx root root 11 ./usr/lib/libkms.so -> libkms.so.1
+-rwxr-xr-x root root 161760 ./usr/lib/liblzma.so.5.2.5
+lrwxrwxrwx root root 16 ./usr/lib/liblzma.so.5 -> liblzma.so.5.2.5
+lrwxrwxrwx root root 16 ./usr/lib/liblzma.so -> liblzma.so.5.2.5
+-rwxr-xr-x root root 141200 ./usr/lib/liblzo2.so.2.0.0
+lrwxrwxrwx root root 16 ./usr/lib/liblzo2.so.2 -> liblzo2.so.2.0.0
+lrwxrwxrwx root root 16 ./usr/lib/liblzo2.so -> liblzo2.so.2.0.0
+-rwxr-xr-x root root 34976 ./usr/lib/libmenu.so.5.9
+lrwxrwxrwx root root 14 ./usr/lib/libmenu.so.5 -> libmenu.so.5.9
+lrwxrwxrwx root root 12 ./usr/lib/libmenu.so -> libmenu.so.5
+-rwxr-xr-x root root 39072 ./usr/lib/libmenuw.so.5.9
+lrwxrwxrwx root root 15 ./usr/lib/libmenuw.so.5 -> libmenuw.so.5.9
+lrwxrwxrwx root root 13 ./usr/lib/libmenuw.so -> libmenuw.so.5
+-rwxr-xr-x root root 26584 ./usr/lib/libmnl.so.0.2.0
+lrwxrwxrwx root root 15 ./usr/lib/libmnl.so.0 -> libmnl.so.0.2.0
+lrwxrwxrwx root root 15 ./usr/lib/libmnl.so -> libmnl.so.0.2.0
+lrwxrwxrwx root root 27 ./usr/lib/libmount.so -> ../../lib/libmount.so.1.1.0
+-rw-r--r-- root root 106 ./usr/lib/libm.so
+lrwxrwxrwx root root 22 ./usr/lib/libmvec.so -> ../../lib/libmvec.so.1
+-rw-r--r-- root root 62 ./usr/lib/libncurses.so
+-rw-r--r-- root root 63 ./usr/lib/libncursesw.so
+-rwxr-xr-x root root 96288 ./usr/lib/libnsl.so.2.0.0
+lrwxrwxrwx root root 15 ./usr/lib/libnsl.so.2 -> libnsl.so.2.0.0
+lrwxrwxrwx root root 15 ./usr/lib/libnsl.so -> libnsl.so.2.0.0
+lrwxrwxrwx root root 28 ./usr/lib/libnss_compat.so -> ../../lib/libnss_compat.so.2
+lrwxrwxrwx root root 24 ./usr/lib/libnss_db.so -> ../../lib/libnss_db.so.2
+lrwxrwxrwx root root 25 ./usr/lib/libnss_dns.so -> ../../lib/libnss_dns.so.2
+lrwxrwxrwx root root 27 ./usr/lib/libnss_files.so -> ../../lib/libnss_files.so.2
+lrwxrwxrwx root root 28 ./usr/lib/libnss_hesiod.so -> ../../lib/libnss_hesiod.so.2
+-rwxr-xr-x root root 1426544 ./usr/lib/libopcodes-2.34.0.20200220.so
+lrwxrwxrwx root root 29 ./usr/lib/libopcodes.so -> libopcodes-2.34.0.20200220.so
+-rwxr-xr-x root root 18168 ./usr/lib/libpanel.so.5.9
+lrwxrwxrwx root root 15 ./usr/lib/libpanel.so.5 -> libpanel.so.5.9
+lrwxrwxrwx root root 13 ./usr/lib/libpanel.so -> libpanel.so.5
+-rwxr-xr-x root root 18168 ./usr/lib/libpanelw.so.5.9
+lrwxrwxrwx root root 16 ./usr/lib/libpanelw.so.5 -> libpanelw.so.5.9
+lrwxrwxrwx root root 14 ./usr/lib/libpanelw.so -> libpanelw.so.5
+-rwxr-xr-x root root 42896 ./usr/lib/libpciaccess.so.0.11.1
+lrwxrwxrwx root root 22 ./usr/lib/libpciaccess.so.0 -> libpciaccess.so.0.11.1
+lrwxrwxrwx root root 22 ./usr/lib/libpciaccess.so -> libpciaccess.so.0.11.1
+-rwxr-xr-x root root 42984 ./usr/lib/libpcrecpp.so.0.0.2
+lrwxrwxrwx root root 19 ./usr/lib/libpcrecpp.so.0 -> libpcrecpp.so.0.0.2
+lrwxrwxrwx root root 19 ./usr/lib/libpcrecpp.so -> libpcrecpp.so.0.0.2
+-rwxr-xr-x root root 14224 ./usr/lib/libpcreposix.so.0.0.7
+lrwxrwxrwx root root 21 ./usr/lib/libpcreposix.so.0 -> libpcreposix.so.0.0.7
+lrwxrwxrwx root root 21 ./usr/lib/libpcreposix.so -> libpcreposix.so.0.0.7
+-rwxr-xr-x root root 489400 ./usr/lib/libpcre.so.1.2.12
+lrwxrwxrwx root root 17 ./usr/lib/libpcre.so.1 -> libpcre.so.1.2.12
+lrwxrwxrwx root root 17 ./usr/lib/libpcre.so -> libpcre.so.1.2.12
+-r-xr-xr-x root root 3351136 ./usr/lib/libperl.so.5.30.0
+lrwxrwxrwx root root 17 ./usr/lib/libperl.so.5 -> libperl.so.5.30.0
+lrwxrwxrwx root root 17 ./usr/lib/libperl.so -> libperl.so.5.30.0
+-rwxr-xr-x root root 686072 ./usr/lib/libpixman-1.so.0.38.4
+lrwxrwxrwx root root 21 ./usr/lib/libpixman-1.so.0 -> libpixman-1.so.0.38.4
+lrwxrwxrwx root root 16 ./usr/lib/libpixman-1.so -> libpixman-1.so.0
+-rwxr-xr-x root root 219024 ./usr/lib/libpng16.so.16.37.0
+lrwxrwxrwx root root 19 ./usr/lib/libpng16.so.16 -> libpng16.so.16.37.0
+lrwxrwxrwx root root 19 ./usr/lib/libpng16.so -> libpng16.so.16.37.0
+lrwxrwxrwx root root 11 ./usr/lib/libpng.so -> libpng16.so
+-rwxr-xr-x root root 79888 ./usr/lib/libprocps.so.8.0.2
+lrwxrwxrwx root root 18 ./usr/lib/libprocps.so.8 -> libprocps.so.8.0.2
+lrwxrwxrwx root root 18 ./usr/lib/libprocps.so -> libprocps.so.8.0.2
+lrwxrwxrwx root root 25 ./usr/lib/libpthread.so -> ../../lib/libpthread.so.0
+-rwxr-xr-x root root 3267712 ./usr/lib/libpython3.8.so.1.0
+lrwxrwxrwx root root 19 ./usr/lib/libpython3.8.so -> libpython3.8.so.1.0
+-rwxr-xr-x root root 13920 ./usr/lib/libpython3.so
+-rwxr-xr-x root root 330696 ./usr/lib/libreadline.so.8.0
+lrwxrwxrwx root root 18 ./usr/lib/libreadline.so.8 -> libreadline.so.8.0
+lrwxrwxrwx root root 18 ./usr/lib/libreadline.so -> libreadline.so.8.0
+lrwxrwxrwx root root 24 ./usr/lib/libresolv.so -> ../../lib/libresolv.so.2
+lrwxrwxrwx root root 20 ./usr/lib/librt.so -> ../../lib/librt.so.1
+lrwxrwxrwx root root 31 ./usr/lib/libsmartcols.so -> ../../lib/libsmartcols.so.1.1.0
+-rwxr-xr-x root root 38736 ./usr/lib/libSM.so.6.0.1
+lrwxrwxrwx root root 14 ./usr/lib/libSM.so.6 -> libSM.so.6.0.1
+lrwxrwxrwx root root 14 ./usr/lib/libSM.so -> libSM.so.6.0.1
+-rwxr-xr-x root root 1244736 ./usr/lib/libsqlite3.so.0.8.6
+lrwxrwxrwx root root 19 ./usr/lib/libsqlite3.so.0 -> libsqlite3.so.0.8.6
+lrwxrwxrwx root root 19 ./usr/lib/libsqlite3.so -> libsqlite3.so.0.8.6
+-rwxr-xr-x root root 593728 ./usr/lib/libssl.so.1.1
+lrwxrwxrwx root root 13 ./usr/lib/libssl.so -> libssl.so.1.1
+-rwxr-xr-x root root 1866240 ./usr/lib/libstdc++.so.6.0.28
+lrwxrwxrwx root root 19 ./usr/lib/libstdc++.so.6 -> libstdc++.so.6.0.28
+lrwxrwxrwx root root 19 ./usr/lib/libstdc++.so -> libstdc++.so.6.0.28
+-rw-r--r-- root root 46 ./usr/lib/libtermcap.so
+lrwxrwxrwx root root 27 ./usr/lib/libthread_db.so -> ../../lib/libthread_db.so.1
+-rwxr-xr-x root root 67472 ./usr/lib/libtic.so.5.9
+lrwxrwxrwx root root 13 ./usr/lib/libtic.so.5 -> libtic.so.5.9
+lrwxrwxrwx root root 11 ./usr/lib/libtic.so -> libtic.so.5
+-rwxr-xr-x root root 67472 ./usr/lib/libticw.so.5.9
+lrwxrwxrwx root root 14 ./usr/lib/libticw.so.5 -> libticw.so.5.9
+lrwxrwxrwx root root 12 ./usr/lib/libticw.so -> libticw.so.5
+lrwxrwxrwx root root 23 ./usr/lib/libtinfo.so -> ../../lib/libtinfo.so.5
+-rwxr-xr-x root root 161888 ./usr/lib/libtirpc.so.3.0.0
+lrwxrwxrwx root root 17 ./usr/lib/libtirpc.so.3 -> libtirpc.so.3.0.0
+lrwxrwxrwx root root 17 ./usr/lib/libtirpc.so -> libtirpc.so.3.0.0
+lrwxrwxrwx root root 26 ./usr/lib/libudev.so -> ../../lib/libudev.so.1.6.3
+lrwxrwxrwx root root 22 ./usr/lib/libutil.so -> ../../lib/libutil.so.1
+lrwxrwxrwx root root 26 ./usr/lib/libuuid.so -> ../../lib/libuuid.so.1.3.0
+-rwxr-xr-x root root 68272 ./usr/lib/libwayland-client.so.0.3.0
+lrwxrwxrwx root root 26 ./usr/lib/libwayland-client.so.0 -> libwayland-client.so.0.3.0
+lrwxrwxrwx root root 22 ./usr/lib/libwayland-client.so -> libwayland-client.so.0
+-rwxr-xr-x root root 30720 ./usr/lib/libwayland-cursor.so.0.0.0
+lrwxrwxrwx root root 26 ./usr/lib/libwayland-cursor.so.0 -> libwayland-cursor.so.0.0.0
+lrwxrwxrwx root root 22 ./usr/lib/libwayland-cursor.so -> libwayland-cursor.so.0
+-rwxr-xr-x root root 14080 ./usr/lib/libwayland-egl.so.1.0.0
+lrwxrwxrwx root root 23 ./usr/lib/libwayland-egl.so.1 -> libwayland-egl.so.1.0.0
+lrwxrwxrwx root root 19 ./usr/lib/libwayland-egl.so -> libwayland-egl.so.1
+-rwxr-xr-x root root 88784 ./usr/lib/libwayland-server.so.0.1.0
+lrwxrwxrwx root root 26 ./usr/lib/libwayland-server.so.0 -> libwayland-server.so.0.1.0
+lrwxrwxrwx root root 22 ./usr/lib/libwayland-server.so -> libwayland-server.so.0
+lrwxrwxrwx root root 26 ./usr/lib/libwrap.so -> ../../lib/libwrap.so.0.7.6
+-rwxr-xr-x root root 1308960 ./usr/lib/libX11.so.6.3.0
+lrwxrwxrwx root root 15 ./usr/lib/libX11.so.6 -> libX11.so.6.3.0
+lrwxrwxrwx root root 15 ./usr/lib/libX11.so -> libX11.so.6.3.0
+-rwxr-xr-x root root 13848 ./usr/lib/libX11-xcb.so.1.0.0
+lrwxrwxrwx root root 19 ./usr/lib/libX11-xcb.so.1 -> libX11-xcb.so.1.0.0
+lrwxrwxrwx root root 19 ./usr/lib/libX11-xcb.so -> libX11-xcb.so.1.0.0
+-rwxr-xr-x root root 14144 ./usr/lib/libXau.so.6.0.0
+lrwxrwxrwx root root 15 ./usr/lib/libXau.so.6 -> libXau.so.6.0.0
+lrwxrwxrwx root root 15 ./usr/lib/libXau.so -> libXau.so.6.0.0
+-rwxr-xr-x root root 14256 ./usr/lib/libxcb-composite.so.0.0.0
+lrwxrwxrwx root root 25 ./usr/lib/libxcb-composite.so.0 -> libxcb-composite.so.0.0.0
+lrwxrwxrwx root root 25 ./usr/lib/libxcb-composite.so -> libxcb-composite.so.0.0.0
+-rwxr-xr-x root root 14248 ./usr/lib/libxcb-damage.so.0.0.0
+lrwxrwxrwx root root 22 ./usr/lib/libxcb-damage.so.0 -> libxcb-damage.so.0.0.0
+lrwxrwxrwx root root 22 ./usr/lib/libxcb-damage.so -> libxcb-damage.so.0.0.0
+-rwxr-xr-x root root 14248 ./usr/lib/libxcb-dpms.so.0.0.0
+lrwxrwxrwx root root 20 ./usr/lib/libxcb-dpms.so.0 -> libxcb-dpms.so.0.0.0
+lrwxrwxrwx root root 20 ./usr/lib/libxcb-dpms.so -> libxcb-dpms.so.0.0.0
+-rwxr-xr-x root root 22440 ./usr/lib/libxcb-dri2.so.0.0.0
+lrwxrwxrwx root root 20 ./usr/lib/libxcb-dri2.so.0 -> libxcb-dri2.so.0.0.0
+lrwxrwxrwx root root 20 ./usr/lib/libxcb-dri2.so -> libxcb-dri2.so.0.0.0
+-rwxr-xr-x root root 18344 ./usr/lib/libxcb-dri3.so.0.0.0
+lrwxrwxrwx root root 20 ./usr/lib/libxcb-dri3.so.0 -> libxcb-dri3.so.0.0.0
+lrwxrwxrwx root root 20 ./usr/lib/libxcb-dri3.so -> libxcb-dri3.so.0.0.0
+-rwxr-xr-x root root 116648 ./usr/lib/libxcb-glx.so.0.0.0
+lrwxrwxrwx root root 19 ./usr/lib/libxcb-glx.so.0 -> libxcb-glx.so.0.0.0
+lrwxrwxrwx root root 19 ./usr/lib/libxcb-glx.so -> libxcb-glx.so.0.0.0
+-rwxr-xr-x root root 14248 ./usr/lib/libxcb-present.so.0.0.0
+lrwxrwxrwx root root 23 ./usr/lib/libxcb-present.so.0 -> libxcb-present.so.0.0.0
+lrwxrwxrwx root root 23 ./usr/lib/libxcb-present.so -> libxcb-present.so.0.0.0
+-rwxr-xr-x root root 67496 ./usr/lib/libxcb-randr.so.0.1.0
+lrwxrwxrwx root root 21 ./usr/lib/libxcb-randr.so.0 -> libxcb-randr.so.0.1.0
+lrwxrwxrwx root root 21 ./usr/lib/libxcb-randr.so -> libxcb-randr.so.0.1.0
+-rwxr-xr-x root root 18344 ./usr/lib/libxcb-record.so.0.0.0
+lrwxrwxrwx root root 22 ./usr/lib/libxcb-record.so.0 -> libxcb-record.so.0.0.0
+lrwxrwxrwx root root 22 ./usr/lib/libxcb-record.so -> libxcb-record.so.0.0.0
+-rwxr-xr-x root root 59304 ./usr/lib/libxcb-render.so.0.0.0
+lrwxrwxrwx root root 22 ./usr/lib/libxcb-render.so.0 -> libxcb-render.so.0.0.0
+lrwxrwxrwx root root 22 ./usr/lib/libxcb-render.so -> libxcb-render.so.0.0.0
+-rwxr-xr-x root root 18344 ./usr/lib/libxcb-res.so.0.0.0
+lrwxrwxrwx root root 19 ./usr/lib/libxcb-res.so.0 -> libxcb-res.so.0.0.0
+lrwxrwxrwx root root 19 ./usr/lib/libxcb-res.so -> libxcb-res.so.0.0.0
+-rwxr-xr-x root root 14256 ./usr/lib/libxcb-screensaver.so.0.0.0
+lrwxrwxrwx root root 27 ./usr/lib/libxcb-screensaver.so.0 -> libxcb-screensaver.so.0.0.0
+lrwxrwxrwx root root 27 ./usr/lib/libxcb-screensaver.so -> libxcb-screensaver.so.0.0.0
+-rwxr-xr-x root root 14248 ./usr/lib/libxcb-shape.so.0.0.0
+lrwxrwxrwx root root 21 ./usr/lib/libxcb-shape.so.0 -> libxcb-shape.so.0.0.0
+lrwxrwxrwx root root 21 ./usr/lib/libxcb-shape.so -> libxcb-shape.so.0.0.0
+-rwxr-xr-x root root 14248 ./usr/lib/libxcb-shm.so.0.0.0
+lrwxrwxrwx root root 19 ./usr/lib/libxcb-shm.so.0 -> libxcb-shm.so.0.0.0
+lrwxrwxrwx root root 19 ./usr/lib/libxcb-shm.so -> libxcb-shm.so.0.0.0
+-rwxr-xr-x root root 169920 ./usr/lib/libxcb.so.1.1.0
+lrwxrwxrwx root root 15 ./usr/lib/libxcb.so.1 -> libxcb.so.1.1.0
+lrwxrwxrwx root root 15 ./usr/lib/libxcb.so -> libxcb.so.1.1.0
+-rwxr-xr-x root root 34728 ./usr/lib/libxcb-sync.so.1.0.0
+lrwxrwxrwx root root 20 ./usr/lib/libxcb-sync.so.1 -> libxcb-sync.so.1.0.0
+lrwxrwxrwx root root 20 ./usr/lib/libxcb-sync.so -> libxcb-sync.so.1.0.0
+-rwxr-xr-x root root 18344 ./usr/lib/libxcb-xf86dri.so.0.0.0
+lrwxrwxrwx root root 23 ./usr/lib/libxcb-xf86dri.so.0 -> libxcb-xf86dri.so.0.0.0
+lrwxrwxrwx root root 23 ./usr/lib/libxcb-xf86dri.so -> libxcb-xf86dri.so.0.0.0
+-rwxr-xr-x root root 34728 ./usr/lib/libxcb-xfixes.so.0.0.0
+lrwxrwxrwx root root 22 ./usr/lib/libxcb-xfixes.so.0 -> libxcb-xfixes.so.0.0.0
+lrwxrwxrwx root root 22 ./usr/lib/libxcb-xfixes.so -> libxcb-xfixes.so.0.0.0
+-rwxr-xr-x root root 14256 ./usr/lib/libxcb-xinerama.so.0.0.0
+lrwxrwxrwx root root 24 ./usr/lib/libxcb-xinerama.so.0 -> libxcb-xinerama.so.0.0.0
+lrwxrwxrwx root root 24 ./usr/lib/libxcb-xinerama.so -> libxcb-xinerama.so.0.0.0
+-rwxr-xr-x root root 149416 ./usr/lib/libxcb-xinput.so.0.1.0
+lrwxrwxrwx root root 22 ./usr/lib/libxcb-xinput.so.0 -> libxcb-xinput.so.0.1.0
+lrwxrwxrwx root root 22 ./usr/lib/libxcb-xinput.so -> libxcb-xinput.so.0.1.0
+-rwxr-xr-x root root 120744 ./usr/lib/libxcb-xkb.so.1.0.0
+lrwxrwxrwx root root 19 ./usr/lib/libxcb-xkb.so.1 -> libxcb-xkb.so.1.0.0
+lrwxrwxrwx root root 19 ./usr/lib/libxcb-xkb.so -> libxcb-xkb.so.1.0.0
+-rwxr-xr-x root root 14248 ./usr/lib/libxcb-xtest.so.0.0.0
+lrwxrwxrwx root root 21 ./usr/lib/libxcb-xtest.so.0 -> libxcb-xtest.so.0.0.0
+lrwxrwxrwx root root 21 ./usr/lib/libxcb-xtest.so -> libxcb-xtest.so.0.0.0
+-rwxr-xr-x root root 18344 ./usr/lib/libxcb-xvmc.so.0.0.0
+lrwxrwxrwx root root 20 ./usr/lib/libxcb-xvmc.so.0 -> libxcb-xvmc.so.0.0.0
+lrwxrwxrwx root root 20 ./usr/lib/libxcb-xvmc.so -> libxcb-xvmc.so.0.0.0
+-rwxr-xr-x root root 34728 ./usr/lib/libxcb-xv.so.0.0.0
+lrwxrwxrwx root root 18 ./usr/lib/libxcb-xv.so.0 -> libxcb-xv.so.0.0.0
+lrwxrwxrwx root root 18 ./usr/lib/libxcb-xv.so -> libxcb-xv.so.0.0.0
+-rwxr-xr-x root root 14144 ./usr/lib/libXdamage.so.1.1.0
+lrwxrwxrwx root root 19 ./usr/lib/libXdamage.so.1 -> libXdamage.so.1.1.0
+lrwxrwxrwx root root 19 ./usr/lib/libXdamage.so -> libXdamage.so.1.1.0
+-rwxr-xr-x root root 26432 ./usr/lib/libXdmcp.so.6.0.0
+lrwxrwxrwx root root 17 ./usr/lib/libXdmcp.so.6 -> libXdmcp.so.6.0.0
+lrwxrwxrwx root root 17 ./usr/lib/libXdmcp.so -> libXdmcp.so.6.0.0
+-rwxr-xr-x root root 80992 ./usr/lib/libXext.so.6.4.0
+lrwxrwxrwx root root 16 ./usr/lib/libXext.so.6 -> libXext.so.6.4.0
+lrwxrwxrwx root root 16 ./usr/lib/libXext.so -> libXext.so.6.4.0
+-rwxr-xr-x root root 30464 ./usr/lib/libXfixes.so.3.1.0
+lrwxrwxrwx root root 18 ./usr/lib/libXfixes.so.3 -> libXfixes.so.3.1.0
+lrwxrwxrwx root root 18 ./usr/lib/libXfixes.so -> libXfixes.so.3.1.0
+-rwxr-xr-x root root 1409880 ./usr/lib/libxml2.so.2.9.10
+lrwxrwxrwx root root 17 ./usr/lib/libxml2.so.2 -> libxml2.so.2.9.10
+lrwxrwxrwx root root 17 ./usr/lib/libxml2.so -> libxml2.so.2.9.10
+-rwxr-xr-x root root 47024 ./usr/lib/libXrandr.so.2.2.0
+lrwxrwxrwx root root 18 ./usr/lib/libXrandr.so.2 -> libXrandr.so.2.2.0
+lrwxrwxrwx root root 18 ./usr/lib/libXrandr.so -> libXrandr.so.2.2.0
+-rwxr-xr-x root root 47184 ./usr/lib/libXrender.so.1.3.0
+lrwxrwxrwx root root 19 ./usr/lib/libXrender.so.1 -> libXrender.so.1.3.0
+lrwxrwxrwx root root 19 ./usr/lib/libXrender.so -> libXrender.so.1.3.0
+-rwxr-xr-x root root 14152 ./usr/lib/libxshmfence.so.1.0.0
+lrwxrwxrwx root root 21 ./usr/lib/libxshmfence.so.1 -> libxshmfence.so.1.0.0
+lrwxrwxrwx root root 21 ./usr/lib/libxshmfence.so -> libxshmfence.so.1.0.0
+-rwxr-xr-x root root 63384 ./usr/lib/libxtables.so.12.2.0
+lrwxrwxrwx root root 20 ./usr/lib/libxtables.so.12 -> libxtables.so.12.2.0
+lrwxrwxrwx root root 20 ./usr/lib/libxtables.so -> libxtables.so.12.2.0
+-rwxr-xr-x root root 22456 ./usr/lib/libXxf86vm.so.1.0.0
+lrwxrwxrwx root root 19 ./usr/lib/libXxf86vm.so.1 -> libXxf86vm.so.1.0.0
+lrwxrwxrwx root root 19 ./usr/lib/libXxf86vm.so -> libXxf86vm.so.1.0.0
+lrwxrwxrwx root root 24 ./usr/lib/libz.so -> ../../lib/libz.so.1.2.11
+-rw-r--r-- root root 1368 ./usr/lib/Mcrt1.o
+drwxr-xr-x root root 4096 ./usr/lib/opkg
+drwxr-xr-x root root 12288 ./usr/lib/opkg/alternatives
+-rw-r--r-- root root 35 ./usr/lib/opkg/alternatives/[[
+-rw-r--r-- root root 42 ./usr/lib/opkg/alternatives/addgroup
+-rw-r--r-- root root 60 ./usr/lib/opkg/alternatives/addr2line
+-rw-r--r-- root root 41 ./usr/lib/opkg/alternatives/adduser
+-rw-r--r-- root root 46 ./usr/lib/opkg/alternatives/ar
+-rw-r--r-- root root 42 ./usr/lib/opkg/alternatives/arch
+-rw-r--r-- root root 46 ./usr/lib/opkg/alternatives/as
+-rw-r--r-- root root 32 ./usr/lib/opkg/alternatives/ash
+-rw-r--r-- root root 54 ./usr/lib/opkg/alternatives/awk
+-rw-r--r-- root root 42 ./usr/lib/opkg/alternatives/base64
+-rw-r--r-- root root 73 ./usr/lib/opkg/alternatives/basename
+-rw-r--r-- root root 29 ./usr/lib/opkg/alternatives/bash
+-rw-r--r-- root root 31 ./usr/lib/opkg/alternatives/bc
+-rw-r--r-- root root 30 ./usr/lib/opkg/alternatives/bin-lsmod
+-rw-r--r-- root root 61 ./usr/lib/opkg/alternatives/blkid
+-rw-r--r-- root root 44 ./usr/lib/opkg/alternatives/blockdev
+-rw-r--r-- root root 67 ./usr/lib/opkg/alternatives/bunzip2
+-rw-r--r-- root root 63 ./usr/lib/opkg/alternatives/bzcat
+-rw-r--r-- root root 63 ./usr/lib/opkg/alternatives/bzip2
+-rw-r--r-- root root 40 ./usr/lib/opkg/alternatives/cal
+-rw-r--r-- root root 55 ./usr/lib/opkg/alternatives/cat
+-rw-r--r-- root root 56 ./usr/lib/opkg/alternatives/c++filt
+-rw-r--r-- root root 61 ./usr/lib/opkg/alternatives/chattr
+-rw-r--r-- root root 44 ./usr/lib/opkg/alternatives/chcon
+-rw-r--r-- root root 39 ./usr/lib/opkg/alternatives/chfn
+-rw-r--r-- root root 59 ./usr/lib/opkg/alternatives/chgrp
+-rw-r--r-- root root 59 ./usr/lib/opkg/alternatives/chmod
+-rw-r--r-- root root 59 ./usr/lib/opkg/alternatives/chown
+-rw-r--r-- root root 49 ./usr/lib/opkg/alternatives/chpasswd
+-rw-r--r-- root root 71 ./usr/lib/opkg/alternatives/chroot
+-rw-r--r-- root root 42 ./usr/lib/opkg/alternatives/chrt
+-rw-r--r-- root root 39 ./usr/lib/opkg/alternatives/chsh
+-rw-r--r-- root root 37 ./usr/lib/opkg/alternatives/chvt
+-rw-r--r-- root root 44 ./usr/lib/opkg/alternatives/cksum
+-rw-r--r-- root root 38 ./usr/lib/opkg/alternatives/clear
+-rw-r--r-- root root 63 ./usr/lib/opkg/alternatives/cmp
+-rw-r--r-- root root 42 ./usr/lib/opkg/alternatives/comm
+-rw-r--r-- root root 53 ./usr/lib/opkg/alternatives/cp
+-rw-r--r-- root root 33 ./usr/lib/opkg/alternatives/cpio
+-rw-r--r-- root root 46 ./usr/lib/opkg/alternatives/csplit
+-rw-r--r-- root root 63 ./usr/lib/opkg/alternatives/cut
+-rw-r--r-- root root 57 ./usr/lib/opkg/alternatives/date
+-rw-r--r-- root root 54 ./usr/lib/opkg/alternatives/dc
+-rw-r--r-- root root 53 ./usr/lib/opkg/alternatives/dd
+-rw-r--r-- root root 42 ./usr/lib/opkg/alternatives/deallocvt
+-rw-r--r-- root root 42 ./usr/lib/opkg/alternatives/delgroup
+-rw-r--r-- root root 41 ./usr/lib/opkg/alternatives/deluser
+-rw-r--r-- root root 57 ./usr/lib/opkg/alternatives/depmod
+-rw-r--r-- root root 57 ./usr/lib/opkg/alternatives/df
+-rw-r--r-- root root 65 ./usr/lib/opkg/alternatives/diff
+-rw-r--r-- root root 40 ./usr/lib/opkg/alternatives/dir
+-rw-r--r-- root root 52 ./usr/lib/opkg/alternatives/dircolors
+-rw-r--r-- root root 71 ./usr/lib/opkg/alternatives/dirname
+-rw-r--r-- root root 59 ./usr/lib/opkg/alternatives/dmesg
+-rw-r--r-- root root 42 ./usr/lib/opkg/alternatives/dnsdomainname
+-rw-r--r-- root root 61 ./usr/lib/opkg/alternatives/du
+-rw-r--r-- root root 37 ./usr/lib/opkg/alternatives/dumpkmap
+-rw-r--r-- root root 43 ./usr/lib/opkg/alternatives/dumpleases
+-rw-r--r-- root root 48 ./usr/lib/opkg/alternatives/dwp
+-rw-r--r-- root root 57 ./usr/lib/opkg/alternatives/echo
+-rw-r--r-- root root 54 ./usr/lib/opkg/alternatives/egrep
+-rw-r--r-- root root 44 ./usr/lib/opkg/alternatives/eject
+-rw-r--r-- root root 56 ./usr/lib/opkg/alternatives/elfedit
+-rw-r--r-- root root 63 ./usr/lib/opkg/alternatives/env
+-rw-r--r-- root root 46 ./usr/lib/opkg/alternatives/expand
+-rw-r--r-- root root 65 ./usr/lib/opkg/alternatives/expr
+-rw-r--r-- root root 46 ./usr/lib/opkg/alternatives/factor
+-rw-r--r-- root root 52 ./usr/lib/opkg/alternatives/fallocate
+-rw-r--r-- root root 59 ./usr/lib/opkg/alternatives/false
+-rw-r--r-- root root 39 ./usr/lib/opkg/alternatives/fbset
+-rw-r--r-- root root 61 ./usr/lib/opkg/alternatives/fdisk
+-rw-r--r-- root root 54 ./usr/lib/opkg/alternatives/fgrep
+-rw-r--r-- root root 65 ./usr/lib/opkg/alternatives/find
+-rw-r--r-- root root 67 ./usr/lib/opkg/alternatives/flock
+-rw-r--r-- root root 40 ./usr/lib/opkg/alternatives/fmt
+-rw-r--r-- root root 42 ./usr/lib/opkg/alternatives/fold
+-rw-r--r-- root root 62 ./usr/lib/opkg/alternatives/free
+-rw-r--r-- root root 59 ./usr/lib/opkg/alternatives/fsck
+-rw-r--r-- root root 52 ./usr/lib/opkg/alternatives/fsfreeze
+-rw-r--r-- root root 63 ./usr/lib/opkg/alternatives/fstrim
+-rw-r--r-- root root 38 ./usr/lib/opkg/alternatives/fuser
+-rw-r--r-- root root 61 ./usr/lib/opkg/alternatives/getopt
+-rw-r--r-- root root 51 ./usr/lib/opkg/alternatives/getty
+-rw-r--r-- root root 52 ./usr/lib/opkg/alternatives/gprof
+-rw-r--r-- root root 52 ./usr/lib/opkg/alternatives/grep
+-rw-r--r-- root root 96 ./usr/lib/opkg/alternatives/groups
+-rw-r--r-- root root 35 ./usr/lib/opkg/alternatives/gunzip
+-rw-r--r-- root root 33 ./usr/lib/opkg/alternatives/gzip
+-rw-r--r-- root root 35 ./usr/lib/opkg/alternatives/halt
+-rw-r--r-- root root 65 ./usr/lib/opkg/alternatives/head
+-rw-r--r-- root root 71 ./usr/lib/opkg/alternatives/hexdump
+-rw-r--r-- root root 46 ./usr/lib/opkg/alternatives/hostid
+-rw-r--r-- root root 64 ./usr/lib/opkg/alternatives/hostname
+-rw-r--r-- root root 65 ./usr/lib/opkg/alternatives/hwclock
+-rw-r--r-- root root 61 ./usr/lib/opkg/alternatives/id
+-rw-r--r-- root root 38 ./usr/lib/opkg/alternatives/ifconfig
+-rw-r--r-- root root 36 ./usr/lib/opkg/alternatives/ifdown
+-rw-r--r-- root root 34 ./usr/lib/opkg/alternatives/ifup
+-rw-r--r-- root root 34 ./usr/lib/opkg/alternatives/init
+-rw-r--r-- root root 57 ./usr/lib/opkg/alternatives/insmod
+-rw-r--r-- root root 48 ./usr/lib/opkg/alternatives/install
+-rw-r--r-- root root 46 ./usr/lib/opkg/alternatives/ionice
+-rw-r--r-- root root 54 ./usr/lib/opkg/alternatives/ip
+-rw-r--r-- root root 42 ./usr/lib/opkg/alternatives/join
+-rw-r--r-- root root 102 ./usr/lib/opkg/alternatives/kill
+-rw-r--r-- root root 40 ./usr/lib/opkg/alternatives/killall
+-rw-r--r-- root root 35 ./usr/lib/opkg/alternatives/klogd
+-rw-r--r-- root root 69 ./usr/lib/opkg/alternatives/last
+-rw-r--r-- root root 72 ./usr/lib/opkg/alternatives/lastb
+-rw-r--r-- root root 66 ./usr/lib/opkg/alternatives/lbracket
+-rw-r--r-- root root 46 ./usr/lib/opkg/alternatives/ld
+-rw-r--r-- root root 54 ./usr/lib/opkg/alternatives/ld.bfd
+-rw-r--r-- root root 56 ./usr/lib/opkg/alternatives/ld.gold
+-rw-r--r-- root root 37 ./usr/lib/opkg/alternatives/less
+-rw-r--r-- root root 42 ./usr/lib/opkg/alternatives/link
+-rw-r--r-- root root 53 ./usr/lib/opkg/alternatives/ln
+-rw-r--r-- root root 42 ./usr/lib/opkg/alternatives/loadfont
+-rw-r--r-- root root 38 ./usr/lib/opkg/alternatives/loadkmap
+-rw-r--r-- root root 69 ./usr/lib/opkg/alternatives/logger
+-rw-r--r-- root root 54 ./usr/lib/opkg/alternatives/login
+-rw-r--r-- root root 71 ./usr/lib/opkg/alternatives/logname
+-rw-r--r-- root root 37 ./usr/lib/opkg/alternatives/logread
+-rw-r--r-- root root 65 ./usr/lib/opkg/alternatives/losetup
+-rw-r--r-- root root 53 ./usr/lib/opkg/alternatives/ls
+-rw-r--r-- root root 54 ./usr/lib/opkg/alternatives/lsmod
+-rw-r--r-- root root 60 ./usr/lib/opkg/alternatives/lzcat
+-rw-r--r-- root root 35 ./usr/lib/opkg/alternatives/lzma
+-rw-r--r-- root root 69 ./usr/lib/opkg/alternatives/md5sum
+-rw-r--r-- root root 92 ./usr/lib/opkg/alternatives/mesg
+-rw-r--r-- root root 41 ./usr/lib/opkg/alternatives/microcom
+-rw-r--r-- root root 59 ./usr/lib/opkg/alternatives/mkdir
+-rw-r--r-- root root 40 ./usr/lib/opkg/alternatives/mke2fs
+-rw-r--r-- root root 69 ./usr/lib/opkg/alternatives/mkfifo
+-rw-r--r-- root root 46 ./usr/lib/opkg/alternatives/mkfs.ext2
+-rw-r--r-- root root 59 ./usr/lib/opkg/alternatives/mknod
+-rw-r--r-- root root 63 ./usr/lib/opkg/alternatives/mkswap
+-rw-r--r-- root root 65 ./usr/lib/opkg/alternatives/mktemp
+-rw-r--r-- root root 36 ./usr/lib/opkg/alternatives/modinfo
+-rw-r--r-- root root 61 ./usr/lib/opkg/alternatives/modprobe
+-rw-r--r-- root root 57 ./usr/lib/opkg/alternatives/more
+-rw-r--r-- root root 59 ./usr/lib/opkg/alternatives/mount
+-rw-r--r-- root root 97 ./usr/lib/opkg/alternatives/mountpoint
+-rw-r--r-- root root 53 ./usr/lib/opkg/alternatives/mv
+-rw-r--r-- root root 35 ./usr/lib/opkg/alternatives/nc
+-rw-r--r-- root root 36 ./usr/lib/opkg/alternatives/netstat
+-rw-r--r-- root root 43 ./usr/lib/opkg/alternatives/newgrp
+-rw-r--r-- root root 38 ./usr/lib/opkg/alternatives/nice
+-rw-r--r-- root root 38 ./usr/lib/opkg/alternatives/nl
+-rw-r--r-- root root 46 ./usr/lib/opkg/alternatives/nm
+-rw-r--r-- root root 67 ./usr/lib/opkg/alternatives/nohup
+-rw-r--r-- root root 67 ./usr/lib/opkg/alternatives/nologin
+-rw-r--r-- root root 67 ./usr/lib/opkg/alternatives/nproc
+-rw-r--r-- root root 48 ./usr/lib/opkg/alternatives/nsenter
+-rw-r--r-- root root 41 ./usr/lib/opkg/alternatives/nslookup
+-rw-r--r-- root root 56 ./usr/lib/opkg/alternatives/objcopy
+-rw-r--r-- root root 56 ./usr/lib/opkg/alternatives/objdump
+-rw-r--r-- root root 61 ./usr/lib/opkg/alternatives/od
+-rw-r--r-- root root 39 ./usr/lib/opkg/alternatives/openvt
+-rw-r--r-- root root 64 ./usr/lib/opkg/alternatives/passwd
+-rw-r--r-- root root 44 ./usr/lib/opkg/alternatives/paste
+-rw-r--r-- root root 38 ./usr/lib/opkg/alternatives/patch
+-rw-r--r-- root root 48 ./usr/lib/opkg/alternatives/pathchk
+-rw-r--r-- root root 41 ./usr/lib/opkg/alternatives/pgrep
+-rw-r--r-- root root 80 ./usr/lib/opkg/alternatives/pidof
+-rw-r--r-- root root 31 ./usr/lib/opkg/alternatives/ping
+-rw-r--r-- root root 32 ./usr/lib/opkg/alternatives/ping6
+-rw-r--r-- root root 44 ./usr/lib/opkg/alternatives/pinky
+-rw-r--r-- root root 71 ./usr/lib/opkg/alternatives/pivot_root
+-rw-r--r-- root root 41 ./usr/lib/opkg/alternatives/pkill
+-rw-r--r-- root root 39 ./usr/lib/opkg/alternatives/pmap
+-rw-r--r-- root root 43 ./usr/lib/opkg/alternatives/poweroff
+-rw-r--r-- root root 38 ./usr/lib/opkg/alternatives/pr
+-rw-r--r-- root root 46 ./usr/lib/opkg/alternatives/printenv
+-rw-r--r-- root root 69 ./usr/lib/opkg/alternatives/printf
+-rw-r--r-- root root 50 ./usr/lib/opkg/alternatives/ps
+-rw-r--r-- root root 40 ./usr/lib/opkg/alternatives/ptx
+-rw-r--r-- root root 55 ./usr/lib/opkg/alternatives/pwd
+-rw-r--r-- root root 39 ./usr/lib/opkg/alternatives/pwdx
+-rw-r--r-- root root 59 ./usr/lib/opkg/alternatives/python3-config
+-rw-r--r-- root root 54 ./usr/lib/opkg/alternatives/ranlib
+-rw-r--r-- root root 39 ./usr/lib/opkg/alternatives/rdate
+-rw-r--r-- root root 56 ./usr/lib/opkg/alternatives/readelf
+-rw-r--r-- root root 73 ./usr/lib/opkg/alternatives/readlink
+-rw-r--r-- root root 58 ./usr/lib/opkg/alternatives/readprofile
+-rw-r--r-- root root 73 ./usr/lib/opkg/alternatives/realpath
+-rw-r--r-- root root 62 ./usr/lib/opkg/alternatives/reboot
+-rw-r--r-- root root 69 ./usr/lib/opkg/alternatives/renice
+-rw-r--r-- root root 38 ./usr/lib/opkg/alternatives/reset
+-rw-r--r-- root root 39 ./usr/lib/opkg/alternatives/resize
+-rw-r--r-- root root 40 ./usr/lib/opkg/alternatives/rev
+-rw-r--r-- root root 71 ./usr/lib/opkg/alternatives/rfkill
+-rw-r--r-- root root 53 ./usr/lib/opkg/alternatives/rm
+-rw-r--r-- root root 59 ./usr/lib/opkg/alternatives/rmdir
+-rw-r--r-- root root 55 ./usr/lib/opkg/alternatives/rmmod
+-rw-r--r-- root root 35 ./usr/lib/opkg/alternatives/route
+-rw-r--r-- root root 46 ./usr/lib/opkg/alternatives/runcon
+-rw-r--r-- root root 43 ./usr/lib/opkg/alternatives/runlevel
+-rw-r--r-- root root 38 ./usr/lib/opkg/alternatives/run-parts
+-rw-r--r-- root root 49 ./usr/lib/opkg/alternatives/sed
+-rw-r--r-- root root 63 ./usr/lib/opkg/alternatives/seq
+-rw-r--r-- root root 40 ./usr/lib/opkg/alternatives/setconsole
+-rw-r--r-- root root 45 ./usr/lib/opkg/alternatives/setfattr
+-rw-r--r-- root root 48 ./usr/lib/opkg/alternatives/setpriv
+-rw-r--r-- root root 69 ./usr/lib/opkg/alternatives/setsid
+-rw-r--r-- root root 50 ./usr/lib/opkg/alternatives/sh
+-rw-r--r-- root root 71 ./usr/lib/opkg/alternatives/sha1sum
+-rw-r--r-- root root 52 ./usr/lib/opkg/alternatives/sha224sum
+-rw-r--r-- root root 75 ./usr/lib/opkg/alternatives/sha256sum
+-rw-r--r-- root root 52 ./usr/lib/opkg/alternatives/sha384sum
+-rw-r--r-- root root 52 ./usr/lib/opkg/alternatives/sha512sum
+-rw-r--r-- root root 44 ./usr/lib/opkg/alternatives/shred
+-rw-r--r-- root root 65 ./usr/lib/opkg/alternatives/shuf
+-rw-r--r-- root root 43 ./usr/lib/opkg/alternatives/shutdown
+-rw-r--r-- root root 50 ./usr/lib/opkg/alternatives/size
+-rw-r--r-- root root 41 ./usr/lib/opkg/alternatives/skill
+-rw-r--r-- root root 59 ./usr/lib/opkg/alternatives/sleep
+-rw-r--r-- root root 41 ./usr/lib/opkg/alternatives/snice
+-rw-r--r-- root root 65 ./usr/lib/opkg/alternatives/sort
+-rw-r--r-- root root 44 ./usr/lib/opkg/alternatives/split
+-rw-r--r-- root root 47 ./usr/lib/opkg/alternatives/start-stop-daemon
+-rw-r--r-- root root 57 ./usr/lib/opkg/alternatives/stat
+-rw-r--r-- root root 79 ./usr/lib/opkg/alternatives/strings
+-rw-r--r-- root root 52 ./usr/lib/opkg/alternatives/strip
+-rw-r--r-- root root 57 ./usr/lib/opkg/alternatives/stty
+-rw-r--r-- root root 48 ./usr/lib/opkg/alternatives/su
+-rw-r--r-- root root 65 ./usr/lib/opkg/alternatives/sulogin
+-rw-r--r-- root root 40 ./usr/lib/opkg/alternatives/sum
+-rw-r--r-- root root 65 ./usr/lib/opkg/alternatives/swapoff
+-rw-r--r-- root root 63 ./usr/lib/opkg/alternatives/swapon
+-rw-r--r-- root root 73 ./usr/lib/opkg/alternatives/switch_root
+-rw-r--r-- root root 57 ./usr/lib/opkg/alternatives/sync
+-rw-r--r-- root root 60 ./usr/lib/opkg/alternatives/sysctl
+-rw-r--r-- root root 37 ./usr/lib/opkg/alternatives/syslogd
+-rw-r--r-- root root 40 ./usr/lib/opkg/alternatives/tac
+-rw-r--r-- root root 65 ./usr/lib/opkg/alternatives/tail
+-rw-r--r-- root root 32 ./usr/lib/opkg/alternatives/tar
+-rw-r--r-- root root 48 ./usr/lib/opkg/alternatives/taskset
+-rw-r--r-- root root 63 ./usr/lib/opkg/alternatives/tee
+-rw-r--r-- root root 39 ./usr/lib/opkg/alternatives/telnet
+-rw-r--r-- root root 65 ./usr/lib/opkg/alternatives/test
+-rw-r--r-- root root 37 ./usr/lib/opkg/alternatives/tftp
+-rw-r--r-- root root 37 ./usr/lib/opkg/alternatives/time
+-rw-r--r-- root root 48 ./usr/lib/opkg/alternatives/timeout
+-rw-r--r-- root root 60 ./usr/lib/opkg/alternatives/top
+-rw-r--r-- root root 59 ./usr/lib/opkg/alternatives/touch
+-rw-r--r-- root root 61 ./usr/lib/opkg/alternatives/tr
+-rw-r--r-- root root 41 ./usr/lib/opkg/alternatives/traceroute
+-rw-r--r-- root root 57 ./usr/lib/opkg/alternatives/true
+-rw-r--r-- root root 50 ./usr/lib/opkg/alternatives/truncate
+-rw-r--r-- root root 35 ./usr/lib/opkg/alternatives/ts
+-rw-r--r-- root root 44 ./usr/lib/opkg/alternatives/tsort
+-rw-r--r-- root root 63 ./usr/lib/opkg/alternatives/tty
+-rw-r--r-- root root 36 ./usr/lib/opkg/alternatives/udhcpc
+-rw-r--r-- root root 40 ./usr/lib/opkg/alternatives/udhcpd
+-rw-r--r-- root root 61 ./usr/lib/opkg/alternatives/umount
+-rw-r--r-- root root 59 ./usr/lib/opkg/alternatives/uname
+-rw-r--r-- root root 50 ./usr/lib/opkg/alternatives/unexpand
+-rw-r--r-- root root 65 ./usr/lib/opkg/alternatives/uniq
+-rw-r--r-- root root 69 ./usr/lib/opkg/alternatives/unlink
+-rw-r--r-- root root 39 ./usr/lib/opkg/alternatives/unlzma
+-rw-r--r-- root root 48 ./usr/lib/opkg/alternatives/unshare
+-rw-r--r-- root root 35 ./usr/lib/opkg/alternatives/unxz
+-rw-r--r-- root root 63 ./usr/lib/opkg/alternatives/unzip
+-rw-r--r-- root root 96 ./usr/lib/opkg/alternatives/uptime
+-rw-r--r-- root root 67 ./usr/lib/opkg/alternatives/users
+-rw-r--r-- root root 35 ./usr/lib/opkg/alternatives/usleep
+-rw-r--r-- root root 81 ./usr/lib/opkg/alternatives/utmpdump
+-rw-r--r-- root root 42 ./usr/lib/opkg/alternatives/vdir
+-rw-r--r-- root root 31 ./usr/lib/opkg/alternatives/vi
+-rw-r--r-- root root 33 ./usr/lib/opkg/alternatives/vigr
+-rw-r--r-- root root 33 ./usr/lib/opkg/alternatives/vipw
+-rw-r--r-- root root 36 ./usr/lib/opkg/alternatives/vlock
+-rw-r--r-- root root 33 ./usr/lib/opkg/alternatives/w
+-rw-r--r-- root root 69 ./usr/lib/opkg/alternatives/wall
+-rw-r--r-- root root 56 ./usr/lib/opkg/alternatives/watch
+-rw-r--r-- root root 61 ./usr/lib/opkg/alternatives/wc
+-rw-r--r-- root root 37 ./usr/lib/opkg/alternatives/wget
+-rw-r--r-- root root 63 ./usr/lib/opkg/alternatives/which
+-rw-r--r-- root root 63 ./usr/lib/opkg/alternatives/who
+-rw-r--r-- root root 69 ./usr/lib/opkg/alternatives/whoami
+-rw-r--r-- root root 67 ./usr/lib/opkg/alternatives/xargs
+-rw-r--r-- root root 31 ./usr/lib/opkg/alternatives/xz
+-rw-r--r-- root root 60 ./usr/lib/opkg/alternatives/xzcat
+-rw-r--r-- root root 63 ./usr/lib/opkg/alternatives/yes
+-rw-r--r-- root root 33 ./usr/lib/opkg/alternatives/zcat
+drwxr-xr-x root root 4096 ./usr/lib/perl5
+drwxr-xr-x root root 4096 ./usr/lib/perl5/5.30.2
+-rwxr-xr-x root root 3305 ./usr/lib/perl5/5.30.2/Config.pm
+drwxr-xr-x root root 4096 ./usr/lib/perl5/5.30.2/ExtUtils
+-r--r--r-- root root 1105 ./usr/lib/perl5/5.30.2/ExtUtils/MANIFEST.SKIP
+-rwxr-xr-x root root 11315 ./usr/lib/perl5/5.30.2/ExtUtils/typemap
+-r--r--r-- root root 5071 ./usr/lib/perl5/5.30.2/ExtUtils/xsubpp
+-r--r--r-- root root 4738 ./usr/lib/perl5/5.30.2/strict.pm
+-r--r--r-- root root 2458 ./usr/lib/perl5/5.30.2/vars.pm
+drwxr-xr-x root root 4096 ./usr/lib/perl5/5.30.2/warnings
+-r--r--r-- root root 49989 ./usr/lib/perl5/5.30.2/warnings.pm
+-r--r--r-- root root 759 ./usr/lib/perl5/5.30.2/warnings/register.pm
+drwxr-xr-x root root 4096 ./usr/lib/perl5/5.30.2/x86_64-linux
+-r--r--r-- root root 409 ./usr/lib/perl5/5.30.2/x86_64-linux/Config_git.pl
+-r--r--r-- root root 43123 ./usr/lib/perl5/5.30.2/x86_64-linux/Config_heavy.pl
+lrwxrwxrwx root root 15 ./usr/lib/perl5/5.30.2/x86_64-linux/Config_heavy-target.pl -> Config_heavy.pl
+-r--r--r-- root root 3305 ./usr/lib/perl5/5.30.2/x86_64-linux/Config.pm
+drwxr-xr-x root root 4096 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE
+-r--r--r-- root root 3294 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/av.h
+-r--r--r-- root root 850 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/bitcount.h
+-r--r--r-- root root 4114121 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/charclass_invlists.h
+-r--r--r-- root root 162839 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/config.h
+-r--r--r-- root root 40671 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/cop.h
+-r--r--r-- root root 12323 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/cv.h
+-r--r--r-- root root 5461 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/dosish.h
+-r--r--r-- root root 1861 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/dquote_inline.h
+-r--r--r-- root root 49548 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/ebcdic_tables.h
+-r--r--r-- root root 102635 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/embed.h
+-r--r--r-- root root 23467 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/embedvar.h
+-r--r--r-- root root 1652 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/EXTERN.h
+-r--r--r-- root root 3210 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/fakesdio.h
+-r--r--r-- root root 5046 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/feature.h
+-r--r--r-- root root 1463 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/form.h
+-r--r--r-- root root 357 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/git_version.h
+-r--r--r-- root root 10711 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/gv.h
+-r--r--r-- root root 126538 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/handy.h
+-r--r--r-- root root 10786 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/hv_func.h
+-r--r--r-- root root 25545 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/hv.h
+-r--r--r-- root root 2953 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/hv_macro.h
+-r--r--r-- root root 68866 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/inline.h
+-r--r--r-- root root 1309 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/INTERN.h
+-r--r--r-- root root 29425 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/intrpvar.h
+-r--r--r-- root root 2976 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/invlist_inline.h
+-r--r--r-- root root 48759 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/iperlsys.h
+-r--r--r-- root root 6587 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/keywords.h
+-r--r--r-- root root 126938 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/l1_char_class_tab.h
+lrwxrwxrwx root root 29 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/libperl.so -> ../../../../libperl.so.5.30.0
+-r--r--r-- root root 1524 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/malloc_ctl.h
+-r--r--r-- root root 952 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/metaconfig.h
+-r--r--r-- root root 5021 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/mg_data.h
+-r--r--r-- root root 3013 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/mg.h
+-r--r--r-- root root 4377 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/mg_raw.h
+-r--r--r-- root root 9562 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/mg_vtable.h
+-r--r--r-- root root 1693 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/mydtrace.h
+-r--r--r-- root root 3392 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/nostdio.h
+-r--r--r-- root root 93275 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/opcode.h
+-r--r--r-- root root 36350 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/op.h
+-r--r--r-- root root 8860 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/opnames.h
+-r--r--r-- root root 5911 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/op_reg_common.h
+-r--r--r-- root root 3276 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/overload.h
+-r--r--r-- root root 17220 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/pad.h
+-r--r--r-- root root 6993 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/parser.h
+-r--r--r-- root root 5321 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/patchlevel.h
+-r--r--r-- root root 10170 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/perlapi.h
+-r--r--r-- root root 270251 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/perl.h
+-r--r--r-- root root 6223 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/perl_inc_macro.h
+-r--r--r-- root root 9464 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/perlio.h
+-r--r--r-- root root 13761 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/perliol.h
+-r--r--r-- root root 2973 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/perl_langinfo.h
+-r--r--r-- root root 527 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/perlsdio.h
+-r--r--r-- root root 13314 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/perlvars.h
+-r--r--r-- root root 4434 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/perly.h
+-r--r--r-- root root 28969 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/pp.h
+-r--r--r-- root root 12131 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/pp_proto.h
+-r--r--r-- root root 258888 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/proto.h
+-r--r--r-- root root 78454 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/reentr.h
+-r--r--r-- root root 140155 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/regcharclass.h
+-r--r--r-- root root 48923 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/regcomp.h
+-r--r--r-- root root 36671 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/regexp.h
+-r--r--r-- root root 38053 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/regnodes.h
+-r--r--r-- root root 57294 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/sbox32_hash.h
+-r--r--r-- root root 11887 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/scope.h
+-r--r--r-- root root 10477 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/stadtx_hash.h
+-r--r--r-- root root 85432 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/sv.h
+-r--r--r-- root root 12095 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/thread.h
+-r--r--r-- root root 2048 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/time64_config.h
+-r--r--r-- root root 1588 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/time64.h
+-r--r--r-- root root 44 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/try.h
+-r--r--r-- root root 163425 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/uconfig.h
+-r--r--r-- root root 8027 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/unicode_constants.h
+-r--r--r-- root root 535594 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/uni_keywords.h
+-r--r--r-- root root 5193 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/unixish.h
+-r--r--r-- root root 47587 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/utf8.h
+-r--r--r-- root root 67051 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/utfebcdic.h
+-r--r--r-- root root 10011 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/util.h
+-r--r--r-- root root 904 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/uudmap.h
+-r--r--r-- root root 7993 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/vutil.h
+-r--r--r-- root root 8230 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/warnings.h
+-r--r--r-- root root 24399 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/XSUB.h
+-r--r--r-- root root 10541 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/zaphod32_hash.h
+-rwxr-xr-x root root 36089 ./usr/lib/perl5/config.sh
+drwxr-xr-x root root 4096 ./usr/lib/perl5/site_perl
+drwxr-xr-x root root 4096 ./usr/lib/perl5/site_perl/5.30.2
+drwxr-xr-x root root 4096 ./usr/lib/perl5/site_perl/5.30.2/x86_64-linux
+drwxr-xr-x root root 4096 ./usr/lib/pkgconfig
+-rw-r--r-- root root 155 ./usr/lib/pkgconfig/applewmproto.pc
+-rw-r--r-- root root 900 ./usr/lib/pkgconfig/bash.pc
+-rw-r--r-- root root 155 ./usr/lib/pkgconfig/bigreqsproto.pc
+-rw-r--r-- root root 191 ./usr/lib/pkgconfig/blkid.pc
+-rw-r--r-- root root 242 ./usr/lib/pkgconfig/cairo-fc.pc
+-rw-r--r-- root root 239 ./usr/lib/pkgconfig/cairo-ft.pc
+-rw-r--r-- root root 223 ./usr/lib/pkgconfig/cairo-gl.pc
+-rw-r--r-- root root 217 ./usr/lib/pkgconfig/cairo-glx.pc
+-rw-r--r-- root root 276 ./usr/lib/pkgconfig/cairo-gobject.pc
+-rw-r--r-- root root 446 ./usr/lib/pkgconfig/cairo.pc
+-rw-r--r-- root root 222 ./usr/lib/pkgconfig/cairo-pdf.pc
+-rw-r--r-- root root 219 ./usr/lib/pkgconfig/cairo-png.pc
+-rw-r--r-- root root 228 ./usr/lib/pkgconfig/cairo-ps.pc
+-rw-r--r-- root root 228 ./usr/lib/pkgconfig/cairo-script.pc
+-rw-r--r-- root root 219 ./usr/lib/pkgconfig/cairo-svg.pc
+-rw-r--r-- root root 219 ./usr/lib/pkgconfig/cairo-tee.pc
+-rw-r--r-- root root 247 ./usr/lib/pkgconfig/cairo-xcb.pc
+-rw-r--r-- root root 228 ./usr/lib/pkgconfig/cairo-xcb-shm.pc
+-rw-r--r-- root root 229 ./usr/lib/pkgconfig/cairo-xlib.pc
+-rw-r--r-- root root 256 ./usr/lib/pkgconfig/cairo-xlib-xrender.pc
+-rw-r--r-- root root 247 ./usr/lib/pkgconfig/com_err.pc
+-rw-r--r-- root root 159 ./usr/lib/pkgconfig/compositeproto.pc
+-rw-r--r-- root root 153 ./usr/lib/pkgconfig/damageproto.pc
+-rw-r--r-- root root 607 ./usr/lib/pkgconfig/dbus-1.pc
+-rw-r--r-- root root 275 ./usr/lib/pkgconfig/dbus-python.pc
+-rw-r--r-- root root 147 ./usr/lib/pkgconfig/dmxproto.pc
+-rw-r--r-- root root 147 ./usr/lib/pkgconfig/dpmsproto.pc
+-rw-r--r-- root root 147 ./usr/lib/pkgconfig/dri2proto.pc
+-rw-r--r-- root root 147 ./usr/lib/pkgconfig/dri3proto.pc
+-rw-r--r-- root root 226 ./usr/lib/pkgconfig/e2p.pc
+-rw-r--r-- root root 206 ./usr/lib/pkgconfig/expat.pc
+-rw-r--r-- root root 223 ./usr/lib/pkgconfig/ext2fs.pc
+-rw-r--r-- root root 213 ./usr/lib/pkgconfig/fdisk.pc
+-rw-r--r-- root root 149 ./usr/lib/pkgconfig/fixesproto.pc
+-rw-r--r-- root root 407 ./usr/lib/pkgconfig/fontconfig.pc
+-rw-r--r-- root root 151 ./usr/lib/pkgconfig/fontsproto.pc
+-rw-r--r-- root root 469 ./usr/lib/pkgconfig/form.pc
+-rw-r--r-- root root 454 ./usr/lib/pkgconfig/formw.pc
+-rw-r--r-- root root 310 ./usr/lib/pkgconfig/freetype2.pc
+-rw-r--r-- root root 631 ./usr/lib/pkgconfig/gio-2.0.pc
+-rw-r--r-- root root 232 ./usr/lib/pkgconfig/gio-unix-2.0.pc
+-rw-r--r-- root root 378 ./usr/lib/pkgconfig/glib-2.0.pc
+-rw-r--r-- root root 355 ./usr/lib/pkgconfig/gl.pc
+-rw-r--r-- root root 146 ./usr/lib/pkgconfig/glproto.pc
+-rw-r--r-- root root 254 ./usr/lib/pkgconfig/gmodule-2.0.pc
+-rw-r--r-- root root 254 ./usr/lib/pkgconfig/gmodule-export-2.0.pc
+-rw-r--r-- root root 273 ./usr/lib/pkgconfig/gmodule-no-export-2.0.pc
+-rw-r--r-- root root 225 ./usr/lib/pkgconfig/gmp.pc
+-rw-r--r-- root root 260 ./usr/lib/pkgconfig/gmpxx.pc
+-rw-r--r-- root root 287 ./usr/lib/pkgconfig/gobject-2.0.pc
+-rw-r--r-- root root 649 ./usr/lib/pkgconfig/gobject-introspection-1.0.pc
+-rw-r--r-- root root 612 ./usr/lib/pkgconfig/gobject-introspection-no-export-1.0.pc
+-rw-r--r-- root root 223 ./usr/lib/pkgconfig/gthread-2.0.pc
+-rw-r--r-- root root 206 ./usr/lib/pkgconfig/ice.pc
+-rw-r--r-- root root 151 ./usr/lib/pkgconfig/inputproto.pc
+-rw-r--r-- root root 145 ./usr/lib/pkgconfig/kbproto.pc
+-rw-r--r-- root root 204 ./usr/lib/pkgconfig/libacl.pc
+-rw-r--r-- root root 217 ./usr/lib/pkgconfig/libattr.pc
+-rw-r--r-- root root 208 ./usr/lib/pkgconfig/libcap-ng.pc
+-rw-r--r-- root root 209 ./usr/lib/pkgconfig/libcap.pc
+-rw-r--r-- root root 275 ./usr/lib/pkgconfig/libcrypto.pc
+lrwxrwxrwx root root 12 ./usr/lib/pkgconfig/libcrypt.pc -> libxcrypt.pc
+-rw-r--r-- root root 270 ./usr/lib/pkgconfig/libdrm_amdgpu.pc
+-rw-r--r-- root root 267 ./usr/lib/pkgconfig/libdrm_etnaviv.pc
+-rw-r--r-- root root 301 ./usr/lib/pkgconfig/libdrm_freedreno.pc
+-rw-r--r-- root root 255 ./usr/lib/pkgconfig/libdrm_intel.pc
+-rw-r--r-- root root 300 ./usr/lib/pkgconfig/libdrm_nouveau.pc
+-rw-r--r-- root root 277 ./usr/lib/pkgconfig/libdrm_omap.pc
+-rw-r--r-- root root 220 ./usr/lib/pkgconfig/libdrm.pc
+-rw-r--r-- root root 270 ./usr/lib/pkgconfig/libdrm_radeon.pc
+-rw-r--r-- root root 206 ./usr/lib/pkgconfig/libdrm_vc4.pc
+-rw-r--r-- root root 633 ./usr/lib/pkgconfig/libdw.pc
+-rw-r--r-- root root 262 ./usr/lib/pkgconfig/libelf.pc
+-rw-r--r-- root root 237 ./usr/lib/pkgconfig/libffi.pc
+-rw-r--r-- root root 213 ./usr/lib/pkgconfig/libip4tc.pc
+-rw-r--r-- root root 213 ./usr/lib/pkgconfig/libip6tc.pc
+-rw-r--r-- root root 190 ./usr/lib/pkgconfig/libiptc.pc
+-rw-r--r-- root root 213 ./usr/lib/pkgconfig/libkmod.pc
+-rw-r--r-- root root 259 ./usr/lib/pkgconfig/libkms.pc
+-rw-r--r-- root root 390 ./usr/lib/pkgconfig/liblzma.pc
+-rw-r--r-- root root 292 ./usr/lib/pkgconfig/libmnl.pc
+-rw-r--r-- root root 247 ./usr/lib/pkgconfig/libnsl.pc
+-rw-r--r-- root root 243 ./usr/lib/pkgconfig/libpcrecpp.pc
+-rw-r--r-- root root 305 ./usr/lib/pkgconfig/libpcre.pc
+-rw-r--r-- root root 285 ./usr/lib/pkgconfig/libpcreposix.pc
+-rw-r--r-- root root 239 ./usr/lib/pkgconfig/libpng16.pc
+lrwxrwxrwx root root 11 ./usr/lib/pkgconfig/libpng.pc -> libpng16.pc
+-rw-r--r-- root root 223 ./usr/lib/pkgconfig/libprocps.pc
+-rw-r--r-- root root 254 ./usr/lib/pkgconfig/libpsx.pc
+-rw-r--r-- root root 254 ./usr/lib/pkgconfig/libssl.pc
+-rw-r--r-- root root 235 ./usr/lib/pkgconfig/libtirpc.pc
+-rw-r--r-- root root 493 ./usr/lib/pkgconfig/libudev.pc
+-rw-r--r-- root root 367 ./usr/lib/pkgconfig/libxcrypt.pc
+-rw-r--r-- root root 243 ./usr/lib/pkgconfig/libxml-2.0.pc
+-rw-r--r-- root root 500 ./usr/lib/pkgconfig/lzo2.pc
+-rw-r--r-- root root 469 ./usr/lib/pkgconfig/menu.pc
+-rw-r--r-- root root 454 ./usr/lib/pkgconfig/menuw.pc
+-rw-r--r-- root root 627 ./usr/lib/pkgconfig/mount.pc
+-rw-r--r-- root root 469 ./usr/lib/pkgconfig/ncurses.pc
+-rw-r--r-- root root 498 ./usr/lib/pkgconfig/ncurses++.pc
+-rw-r--r-- root root 486 ./usr/lib/pkgconfig/ncurses++w.pc
+-rw-r--r-- root root 453 ./usr/lib/pkgconfig/ncursesw.pc
+-rw-r--r-- root root 208 ./usr/lib/pkgconfig/openssl.pc
+-rw-r--r-- root root 471 ./usr/lib/pkgconfig/panel.pc
+-rw-r--r-- root root 456 ./usr/lib/pkgconfig/panelw.pc
+-rw-r--r-- root root 228 ./usr/lib/pkgconfig/pciaccess.pc
+-rw-r--r-- root root 198 ./usr/lib/pkgconfig/pixman-1.pc
+-rw-r--r-- root root 153 ./usr/lib/pkgconfig/presentproto.pc
+-rw-r--r-- root root 224 ./usr/lib/pkgconfig/pthread-stubs.pc
+-rw-r--r-- root root 183 ./usr/lib/pkgconfig/py3cairo.pc
+-rw-r--r-- root root 706 ./usr/lib/pkgconfig/pygobject-3.0.pc
+-rw-r--r-- root root 297 ./usr/lib/pkgconfig/python-3.8-embed.pc
+-rw-r--r-- root root 271 ./usr/lib/pkgconfig/python-3.8.pc
+lrwxrwxrwx root root 19 ./usr/lib/pkgconfig/python3-embed.pc -> python-3.8-embed.pc
+lrwxrwxrwx root root 13 ./usr/lib/pkgconfig/python3.pc -> python-3.8.pc
+-rw-r--r-- root root 151 ./usr/lib/pkgconfig/randrproto.pc
+-rw-r--r-- root root 302 ./usr/lib/pkgconfig/readline.pc
+-rw-r--r-- root root 154 ./usr/lib/pkgconfig/recordproto.pc
+-rw-r--r-- root root 154 ./usr/lib/pkgconfig/renderproto.pc
+-rw-r--r-- root root 157 ./usr/lib/pkgconfig/resourceproto.pc
+-rw-r--r-- root root 159 ./usr/lib/pkgconfig/scrnsaverproto.pc
+-rw-r--r-- root root 204 ./usr/lib/pkgconfig/smartcols.pc
+-rw-r--r-- root root 222 ./usr/lib/pkgconfig/sm.pc
+-rw-r--r-- root root 256 ./usr/lib/pkgconfig/sqlite3.pc
+-rw-r--r-- root root 249 ./usr/lib/pkgconfig/ss.pc
+-rw-r--r-- root root 467 ./usr/lib/pkgconfig/tic.pc
+-rw-r--r-- root root 452 ./usr/lib/pkgconfig/ticw.pc
+-rw-r--r-- root root 458 ./usr/lib/pkgconfig/tinfo.pc
+-rw-r--r-- root root 204 ./usr/lib/pkgconfig/uuid.pc
+-rw-r--r-- root root 151 ./usr/lib/pkgconfig/videoproto.pc
+-rw-r--r-- root root 315 ./usr/lib/pkgconfig/wayland-client.pc
+-rw-r--r-- root root 235 ./usr/lib/pkgconfig/wayland-cursor.pc
+-rw-r--r-- root root 167 ./usr/lib/pkgconfig/wayland-egl-backend.pc
+-rw-r--r-- root root 220 ./usr/lib/pkgconfig/wayland-egl.pc
+-rw-r--r-- root root 270 ./usr/lib/pkgconfig/wayland-scanner.pc
+-rw-r--r-- root root 338 ./usr/lib/pkgconfig/wayland-server.pc
+-rw-r--r-- root root 270 ./usr/lib/pkgconfig/x11.pc
+-rw-r--r-- root root 206 ./usr/lib/pkgconfig/x11-xcb.pc
+-rw-r--r-- root root 212 ./usr/lib/pkgconfig/xau.pc
+-rw-r--r-- root root 232 ./usr/lib/pkgconfig/xcb-composite.pc
+-rw-r--r-- root root 223 ./usr/lib/pkgconfig/xcb-damage.pc
+-rw-r--r-- root root 206 ./usr/lib/pkgconfig/xcb-dpms.pc
+-rw-r--r-- root root 206 ./usr/lib/pkgconfig/xcb-dri2.pc
+-rw-r--r-- root root 206 ./usr/lib/pkgconfig/xcb-dri3.pc
+-rw-r--r-- root root 203 ./usr/lib/pkgconfig/xcb-glx.pc
+-rw-r--r-- root root 251 ./usr/lib/pkgconfig/xcb.pc
+-rw-r--r-- root root 245 ./usr/lib/pkgconfig/xcb-present.pc
+-rw-r--r-- root root 273 ./usr/lib/pkgconfig/xcb-proto.pc
+-rw-r--r-- root root 220 ./usr/lib/pkgconfig/xcb-randr.pc
+-rw-r--r-- root root 212 ./usr/lib/pkgconfig/xcb-record.pc
+-rw-r--r-- root root 212 ./usr/lib/pkgconfig/xcb-render.pc
+-rw-r--r-- root root 210 ./usr/lib/pkgconfig/xcb-res.pc
+-rw-r--r-- root root 227 ./usr/lib/pkgconfig/xcb-screensaver.pc
+-rw-r--r-- root root 209 ./usr/lib/pkgconfig/xcb-shape.pc
+-rw-r--r-- root root 203 ./usr/lib/pkgconfig/xcb-shm.pc
+-rw-r--r-- root root 206 ./usr/lib/pkgconfig/xcb-sync.pc
+-rw-r--r-- root root 223 ./usr/lib/pkgconfig/xcb-xf86dri.pc
+-rw-r--r-- root root 233 ./usr/lib/pkgconfig/xcb-xfixes.pc
+-rw-r--r-- root root 218 ./usr/lib/pkgconfig/xcb-xinerama.pc
+-rw-r--r-- root root 238 ./usr/lib/pkgconfig/xcb-xinput.pc
+-rw-r--r-- root root 223 ./usr/lib/pkgconfig/xcb-xkb.pc
+-rw-r--r-- root root 209 ./usr/lib/pkgconfig/xcb-xtest.pc
+-rw-r--r-- root root 213 ./usr/lib/pkgconfig/xcb-xvmc.pc
+-rw-r--r-- root root 208 ./usr/lib/pkgconfig/xcb-xv.pc
+-rw-r--r-- root root 153 ./usr/lib/pkgconfig/xcmiscproto.pc
+-rw-r--r-- root root 254 ./usr/lib/pkgconfig/xdamage.pc
+-rw-r--r-- root root 220 ./usr/lib/pkgconfig/xdmcp.pc
+-rw-r--r-- root root 225 ./usr/lib/pkgconfig/xext.pc
+-rw-r--r-- root root 149 ./usr/lib/pkgconfig/xextproto.pc
+-rw-r--r-- root root 163 ./usr/lib/pkgconfig/xf86bigfontproto.pc
+-rw-r--r-- root root 153 ./usr/lib/pkgconfig/xf86dgaproto.pc
+-rw-r--r-- root root 163 ./usr/lib/pkgconfig/xf86driproto.pc
+-rw-r--r-- root root 163 ./usr/lib/pkgconfig/xf86vidmodeproto.pc
+-rw-r--r-- root root 236 ./usr/lib/pkgconfig/xfixes.pc
+-rw-r--r-- root root 157 ./usr/lib/pkgconfig/xineramaproto.pc
+-rw-r--r-- root root 144 ./usr/lib/pkgconfig/xproto.pc
+-rw-r--r-- root root 248 ./usr/lib/pkgconfig/xrandr.pc
+-rw-r--r-- root root 244 ./usr/lib/pkgconfig/xrender.pc
+-rw-r--r-- root root 216 ./usr/lib/pkgconfig/xshmfence.pc
+-rw-r--r-- root root 261 ./usr/lib/pkgconfig/xtables.pc
+-rw-r--r-- root root 255 ./usr/lib/pkgconfig/xxf86vm.pc
+-rw-r--r-- root root 233 ./usr/lib/pkgconfig/zlib.pc
+drwxr-xr-x root root 4096 ./usr/lib/python3.8
+-rw-r--r-- root root 4489 ./usr/lib/python3.8/abc.py
+-rw-r--r-- root root 96015 ./usr/lib/python3.8/argparse.py
+-rw-r--r-- root root 18474 ./usr/lib/python3.8/ast.py
+-rwxr-xr-x root root 20382 ./usr/lib/python3.8/base64.py
+-rw-r--r-- root root 2214 ./usr/lib/python3.8/bisect.py
+-rw-r--r-- root root 1801 ./usr/lib/python3.8/_bootlocale.py
+-rw-r--r-- root root 12558 ./usr/lib/python3.8/bz2.py
+-rw-r--r-- root root 24832 ./usr/lib/python3.8/calendar.py
+-rw-r--r-- root root 14860 ./usr/lib/python3.8/cmd.py
+-rw-r--r-- root root 36590 ./usr/lib/python3.8/codecs.py
+-rw-r--r-- root root 6059 ./usr/lib/python3.8/codeop.py
+-rw-r--r-- root root 10622 ./usr/lib/python3.8/code.py
+drwxr-xr-x root root 4096 ./usr/lib/python3.8/collections
+-rw-r--r-- root root 26100 ./usr/lib/python3.8/_collections_abc.py
+-rw-r--r-- root root 68 ./usr/lib/python3.8/collections/abc.py
+-rw-r--r-- root root 47521 ./usr/lib/python3.8/collections/__init__.py
+drwxr-xr-x root root 4096 ./usr/lib/python3.8/collections/__pycache__
+-rw-r--r-- root root 179 ./usr/lib/python3.8/collections/__pycache__/abc.cpython-38.opt-1.pyc
+-rw-r--r-- root root 179 ./usr/lib/python3.8/collections/__pycache__/abc.cpython-38.opt-2.pyc
+-rw-r--r-- root root 179 ./usr/lib/python3.8/collections/__pycache__/abc.cpython-38.pyc
+-rw-r--r-- root root 46423 ./usr/lib/python3.8/collections/__pycache__/__init__.cpython-38.opt-1.pyc
+-rw-r--r-- root root 35834 ./usr/lib/python3.8/collections/__pycache__/__init__.cpython-38.opt-2.pyc
+-rw-r--r-- root root 46423 ./usr/lib/python3.8/collections/__pycache__/__init__.cpython-38.pyc
+-rw-r--r-- root root 8749 ./usr/lib/python3.8/_compat_pickle.py
+-rw-r--r-- root root 5340 ./usr/lib/python3.8/_compression.py
+drwxr-xr-x root root 4096 ./usr/lib/python3.8/config-3.8-x86_64-linux-gnu
+-rw-r--r-- root root 3303 ./usr/lib/python3.8/config-3.8-x86_64-linux-gnu/config.c
+-rw-r--r-- root root 1623 ./usr/lib/python3.8/config-3.8-x86_64-linux-gnu/config.c.in
+-rwxr-xr-x root root 15368 ./usr/lib/python3.8/config-3.8-x86_64-linux-gnu/install-sh
+-rw-r--r-- root root 78513 ./usr/lib/python3.8/config-3.8-x86_64-linux-gnu/Makefile
+-rwxr-xr-x root root 7848 ./usr/lib/python3.8/config-3.8-x86_64-linux-gnu/makesetup
+drwxr-xr-x root root 4096 ./usr/lib/python3.8/config-3.8-x86_64-linux-gnu/__pycache__
+-rw-r--r-- root root 1931 ./usr/lib/python3.8/config-3.8-x86_64-linux-gnu/__pycache__/python-config.cpython-38.opt-1.pyc
+-rw-r--r-- root root 1931 ./usr/lib/python3.8/config-3.8-x86_64-linux-gnu/__pycache__/python-config.cpython-38.opt-2.pyc
+-rw-r--r-- root root 1931 ./usr/lib/python3.8/config-3.8-x86_64-linux-gnu/__pycache__/python-config.cpython-38.pyc
+-rwxr-xr-x root root 2114 ./usr/lib/python3.8/config-3.8-x86_64-linux-gnu/python-config.py
+-rw-r--r-- root root 4488 ./usr/lib/python3.8/config-3.8-x86_64-linux-gnu/python.o
+-rw-r--r-- root root 14786 ./usr/lib/python3.8/config-3.8-x86_64-linux-gnu/Setup
+-rw-r--r-- root root 13 ./usr/lib/python3.8/config-3.8-x86_64-linux-gnu/Setup.local
+-rw-r--r-- root root 54374 ./usr/lib/python3.8/configparser.py
+-rw-r--r-- root root 24995 ./usr/lib/python3.8/contextlib.py
+-rw-r--r-- root root 8661 ./usr/lib/python3.8/copy.py
+-rw-r--r-- root root 7135 ./usr/lib/python3.8/copyreg.py
+-rw-r--r-- root root 3610 ./usr/lib/python3.8/crypt.py
+-rw-r--r-- root root 16144 ./usr/lib/python3.8/csv.py
+-rw-r--r-- root root 88074 ./usr/lib/python3.8/datetime.py
+-rw-r--r-- root root 20566 ./usr/lib/python3.8/dis.py
+drwxr-xr-x root root 4096 ./usr/lib/python3.8/distutils
+-rw-r--r-- root root 8572 ./usr/lib/python3.8/distutils/archive_util.py
+-rw-r--r-- root root 14935 ./usr/lib/python3.8/distutils/bcppcompiler.py
+-rw-r--r-- root root 47433 ./usr/lib/python3.8/distutils/ccompiler.py
+-rw-r--r-- root root 18079 ./usr/lib/python3.8/distutils/cmd.py
+drwxr-xr-x root root 4096 ./usr/lib/python3.8/distutils/command
+-rw-r--r-- root root 4913 ./usr/lib/python3.8/distutils/command/bdist_dumb.py
+-rw-r--r-- root root 35295 ./usr/lib/python3.8/distutils/command/bdist_msi.py
+-rw-r--r-- root root 5562 ./usr/lib/python3.8/distutils/command/bdist.py
+-rw-r--r-- root root 21577 ./usr/lib/python3.8/distutils/command/bdist_rpm.py
+-rw-r--r-- root root 16043 ./usr/lib/python3.8/distutils/command/bdist_wininst.py
+-rw-r--r-- root root 8022 ./usr/lib/python3.8/distutils/command/build_clib.py
+-rw-r--r-- root root 31568 ./usr/lib/python3.8/distutils/command/build_ext.py
+-rw-r--r-- root root 5767 ./usr/lib/python3.8/distutils/command/build.py
+-rw-r--r-- root root 17164 ./usr/lib/python3.8/distutils/command/build_py.py
+-rw-r--r-- root root 6232 ./usr/lib/python3.8/distutils/command/build_scripts.py
+-rw-r--r-- root root 5599 ./usr/lib/python3.8/distutils/command/check.py
+-rw-r--r-- root root 2776 ./usr/lib/python3.8/distutils/command/clean.py
+-rw-r--r-- root root 633 ./usr/lib/python3.8/distutils/command/command_template
+-rw-r--r-- root root 13117 ./usr/lib/python3.8/distutils/command/config.py
+-rw-r--r-- root root 799 ./usr/lib/python3.8/distutils/command/__init__.py
+-rw-r--r-- root root 2822 ./usr/lib/python3.8/distutils/command/install_data.py
+-rw-r--r-- root root 2603 ./usr/lib/python3.8/distutils/command/install_egg_info.py
+-rw-r--r-- root root 1298 ./usr/lib/python3.8/distutils/command/install_headers.py
+-rw-r--r-- root root 8397 ./usr/lib/python3.8/distutils/command/install_lib.py
+-rw-r--r-- root root 26774 ./usr/lib/python3.8/distutils/command/install.py
+-rw-r--r-- root root 2017 ./usr/lib/python3.8/distutils/command/install_scripts.py
+drwxr-xr-x root root 4096 ./usr/lib/python3.8/distutils/command/__pycache__
+-rw-r--r-- root root 3648 ./usr/lib/python3.8/distutils/command/__pycache__/bdist.cpython-38.opt-1.pyc
+-rw-r--r-- root root 3454 ./usr/lib/python3.8/distutils/command/__pycache__/bdist.cpython-38.opt-2.pyc
+-rw-r--r-- root root 3648 ./usr/lib/python3.8/distutils/command/__pycache__/bdist.cpython-38.pyc
+-rw-r--r-- root root 3574 ./usr/lib/python3.8/distutils/command/__pycache__/bdist_dumb.cpython-38.opt-1.pyc
+-rw-r--r-- root root 3374 ./usr/lib/python3.8/distutils/command/__pycache__/bdist_dumb.cpython-38.opt-2.pyc
+-rw-r--r-- root root 3574 ./usr/lib/python3.8/distutils/command/__pycache__/bdist_dumb.cpython-38.pyc
+-rw-r--r-- root root 19517 ./usr/lib/python3.8/distutils/command/__pycache__/bdist_msi.cpython-38.opt-1.pyc
+-rw-r--r-- root root 17976 ./usr/lib/python3.8/distutils/command/__pycache__/bdist_msi.cpython-38.opt-2.pyc
+-rw-r--r-- root root 19605 ./usr/lib/python3.8/distutils/command/__pycache__/bdist_msi.cpython-38.pyc
+-rw-r--r-- root root 12344 ./usr/lib/python3.8/distutils/command/__pycache__/bdist_rpm.cpython-38.opt-1.pyc
+-rw-r--r-- root root 12025 ./usr/lib/python3.8/distutils/command/__pycache__/bdist_rpm.cpython-38.opt-2.pyc
+-rw-r--r-- root root 12410 ./usr/lib/python3.8/distutils/command/__pycache__/bdist_rpm.cpython-38.pyc
+-rw-r--r-- root root 8405 ./usr/lib/python3.8/distutils/command/__pycache__/bdist_wininst.cpython-38.opt-1.pyc
+-rw-r--r-- root root 8266 ./usr/lib/python3.8/distutils/command/__pycache__/bdist_wininst.cpython-38.opt-2.pyc
+-rw-r--r-- root root 8471 ./usr/lib/python3.8/distutils/command/__pycache__/bdist_wininst.cpython-38.pyc
+-rw-r--r-- root root 4796 ./usr/lib/python3.8/distutils/command/__pycache__/build_clib.cpython-38.opt-1.pyc
+-rw-r--r-- root root 4242 ./usr/lib/python3.8/distutils/command/__pycache__/build_clib.cpython-38.opt-2.pyc
+-rw-r--r-- root root 4796 ./usr/lib/python3.8/distutils/command/__pycache__/build_clib.cpython-38.pyc
+-rw-r--r-- root root 3863 ./usr/lib/python3.8/distutils/command/__pycache__/build.cpython-38.opt-1.pyc
+-rw-r--r-- root root 3780 ./usr/lib/python3.8/distutils/command/__pycache__/build.cpython-38.opt-2.pyc
+-rw-r--r-- root root 3863 ./usr/lib/python3.8/distutils/command/__pycache__/build.cpython-38.pyc
+-rw-r--r-- root root 16119 ./usr/lib/python3.8/distutils/command/__pycache__/build_ext.cpython-38.opt-1.pyc
+-rw-r--r-- root root 14162 ./usr/lib/python3.8/distutils/command/__pycache__/build_ext.cpython-38.opt-2.pyc
+-rw-r--r-- root root 16119 ./usr/lib/python3.8/distutils/command/__pycache__/build_ext.cpython-38.pyc
+-rw-r--r-- root root 10387 ./usr/lib/python3.8/distutils/command/__pycache__/build_py.cpython-38.opt-1.pyc
+-rw-r--r-- root root 9180 ./usr/lib/python3.8/distutils/command/__pycache__/build_py.cpython-38.opt-2.pyc
+-rw-r--r-- root root 10444 ./usr/lib/python3.8/distutils/command/__pycache__/build_py.cpython-38.pyc
+-rw-r--r-- root root 4306 ./usr/lib/python3.8/distutils/command/__pycache__/build_scripts.cpython-38.opt-1.pyc
+-rw-r--r-- root root 3912 ./usr/lib/python3.8/distutils/command/__pycache__/build_scripts.cpython-38.opt-2.pyc
+-rw-r--r-- root root 4306 ./usr/lib/python3.8/distutils/command/__pycache__/build_scripts.cpython-38.pyc
+-rw-r--r-- root root 4867 ./usr/lib/python3.8/distutils/command/__pycache__/check.cpython-38.opt-1.pyc
+-rw-r--r-- root root 4299 ./usr/lib/python3.8/distutils/command/__pycache__/check.cpython-38.opt-2.pyc
+-rw-r--r-- root root 4867 ./usr/lib/python3.8/distutils/command/__pycache__/check.cpython-38.pyc
+-rw-r--r-- root root 2082 ./usr/lib/python3.8/distutils/command/__pycache__/clean.cpython-38.opt-1.pyc
+-rw-r--r-- root root 1999 ./usr/lib/python3.8/distutils/command/__pycache__/clean.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2082 ./usr/lib/python3.8/distutils/command/__pycache__/clean.cpython-38.pyc
+-rw-r--r-- root root 10209 ./usr/lib/python3.8/distutils/command/__pycache__/config.cpython-38.opt-1.pyc
+-rw-r--r-- root root 6873 ./usr/lib/python3.8/distutils/command/__pycache__/config.cpython-38.opt-2.pyc
+-rw-r--r-- root root 10209 ./usr/lib/python3.8/distutils/command/__pycache__/config.cpython-38.pyc
+-rw-r--r-- root root 525 ./usr/lib/python3.8/distutils/command/__pycache__/__init__.cpython-38.opt-1.pyc
+-rw-r--r-- root root 416 ./usr/lib/python3.8/distutils/command/__pycache__/__init__.cpython-38.opt-2.pyc
+-rw-r--r-- root root 525 ./usr/lib/python3.8/distutils/command/__pycache__/__init__.cpython-38.pyc
+-rw-r--r-- root root 13550 ./usr/lib/python3.8/distutils/command/__pycache__/install.cpython-38.opt-1.pyc
+-rw-r--r-- root root 12495 ./usr/lib/python3.8/distutils/command/__pycache__/install.cpython-38.opt-2.pyc
+-rw-r--r-- root root 13550 ./usr/lib/python3.8/distutils/command/__pycache__/install.cpython-38.pyc
+-rw-r--r-- root root 2271 ./usr/lib/python3.8/distutils/command/__pycache__/install_data.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2126 ./usr/lib/python3.8/distutils/command/__pycache__/install_data.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2271 ./usr/lib/python3.8/distutils/command/__pycache__/install_data.cpython-38.pyc
+-rw-r--r-- root root 2978 ./usr/lib/python3.8/distutils/command/__pycache__/install_egg_info.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2299 ./usr/lib/python3.8/distutils/command/__pycache__/install_egg_info.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2978 ./usr/lib/python3.8/distutils/command/__pycache__/install_egg_info.cpython-38.pyc
+-rw-r--r-- root root 1690 ./usr/lib/python3.8/distutils/command/__pycache__/install_headers.cpython-38.opt-1.pyc
+-rw-r--r-- root root 1524 ./usr/lib/python3.8/distutils/command/__pycache__/install_headers.cpython-38.opt-2.pyc
+-rw-r--r-- root root 1690 ./usr/lib/python3.8/distutils/command/__pycache__/install_headers.cpython-38.pyc
+-rw-r--r-- root root 5095 ./usr/lib/python3.8/distutils/command/__pycache__/install_lib.cpython-38.opt-1.pyc
+-rw-r--r-- root root 4514 ./usr/lib/python3.8/distutils/command/__pycache__/install_lib.cpython-38.opt-2.pyc
+-rw-r--r-- root root 5095 ./usr/lib/python3.8/distutils/command/__pycache__/install_lib.cpython-38.pyc
+-rw-r--r-- root root 2123 ./usr/lib/python3.8/distutils/command/__pycache__/install_scripts.cpython-38.opt-1.pyc
+-rw-r--r-- root root 1989 ./usr/lib/python3.8/distutils/command/__pycache__/install_scripts.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2123 ./usr/lib/python3.8/distutils/command/__pycache__/install_scripts.cpython-38.pyc
+-rw-r--r-- root root 8437 ./usr/lib/python3.8/distutils/command/__pycache__/register.cpython-38.opt-1.pyc
+-rw-r--r-- root root 7172 ./usr/lib/python3.8/distutils/command/__pycache__/register.cpython-38.opt-2.pyc
+-rw-r--r-- root root 8437 ./usr/lib/python3.8/distutils/command/__pycache__/register.cpython-38.pyc
+-rw-r--r-- root root 14498 ./usr/lib/python3.8/distutils/command/__pycache__/sdist.cpython-38.opt-1.pyc
+-rw-r--r-- root root 11139 ./usr/lib/python3.8/distutils/command/__pycache__/sdist.cpython-38.opt-2.pyc
+-rw-r--r-- root root 14498 ./usr/lib/python3.8/distutils/command/__pycache__/sdist.cpython-38.pyc
+-rw-r--r-- root root 4921 ./usr/lib/python3.8/distutils/command/__pycache__/upload.cpython-38.opt-1.pyc
+-rw-r--r-- root root 4795 ./usr/lib/python3.8/distutils/command/__pycache__/upload.cpython-38.opt-2.pyc
+-rw-r--r-- root root 4921 ./usr/lib/python3.8/distutils/command/__pycache__/upload.cpython-38.pyc
+-rw-r--r-- root root 11712 ./usr/lib/python3.8/distutils/command/register.py
+-rw-r--r-- root root 19005 ./usr/lib/python3.8/distutils/command/sdist.py
+-rw-r--r-- root root 7001 ./usr/lib/python3.8/distutils/command/upload.py
+-rw-r--r-- root root 222208 ./usr/lib/python3.8/distutils/command/wininst-10.0-amd64.exe
+-rw-r--r-- root root 190976 ./usr/lib/python3.8/distutils/command/wininst-10.0.exe
+-rw-r--r-- root root 587776 ./usr/lib/python3.8/distutils/command/wininst-14.0-amd64.exe
+-rw-r--r-- root root 458240 ./usr/lib/python3.8/distutils/command/wininst-14.0.exe
+-rw-r--r-- root root 61440 ./usr/lib/python3.8/distutils/command/wininst-6.0.exe
+-rw-r--r-- root root 65536 ./usr/lib/python3.8/distutils/command/wininst-7.1.exe
+-rw-r--r-- root root 61440 ./usr/lib/python3.8/distutils/command/wininst-8.0.exe
+-rw-r--r-- root root 224256 ./usr/lib/python3.8/distutils/command/wininst-9.0-amd64.exe
+-rw-r--r-- root root 196096 ./usr/lib/python3.8/distutils/command/wininst-9.0.exe
+-rw-r--r-- root root 4827 ./usr/lib/python3.8/distutils/config.py
+-rw-r--r-- root root 8876 ./usr/lib/python3.8/distutils/core.py
+-rw-r--r-- root root 16478 ./usr/lib/python3.8/distutils/cygwinccompiler.py
+-rw-r--r-- root root 139 ./usr/lib/python3.8/distutils/debug.py
+-rw-r--r-- root root 3491 ./usr/lib/python3.8/distutils/dep_util.py
+-rw-r--r-- root root 7778 ./usr/lib/python3.8/distutils/dir_util.py
+-rw-r--r-- root root 50385 ./usr/lib/python3.8/distutils/dist.py
+-rw-r--r-- root root 3577 ./usr/lib/python3.8/distutils/errors.py
+-rw-r--r-- root root 10515 ./usr/lib/python3.8/distutils/extension.py
+-rw-r--r-- root root 17784 ./usr/lib/python3.8/distutils/fancy_getopt.py
+-rw-r--r-- root root 12832 ./usr/lib/python3.8/distutils/filelist.py
+-rw-r--r-- root root 8148 ./usr/lib/python3.8/distutils/file_util.py
+-rw-r--r-- root root 236 ./usr/lib/python3.8/distutils/__init__.py
+-rw-r--r-- root root 1969 ./usr/lib/python3.8/distutils/log.py
+-rw-r--r-- root root 30511 ./usr/lib/python3.8/distutils/msvc9compiler.py
+-rw-r--r-- root root 21931 ./usr/lib/python3.8/distutils/_msvccompiler.py
+-rw-r--r-- root root 23564 ./usr/lib/python3.8/distutils/msvccompiler.py
+drwxr-xr-x root root 4096 ./usr/lib/python3.8/distutils/__pycache__
+-rw-r--r-- root root 6529 ./usr/lib/python3.8/distutils/__pycache__/archive_util.cpython-38.opt-1.pyc
+-rw-r--r-- root root 4487 ./usr/lib/python3.8/distutils/__pycache__/archive_util.cpython-38.opt-2.pyc
+-rw-r--r-- root root 6529 ./usr/lib/python3.8/distutils/__pycache__/archive_util.cpython-38.pyc
+-rw-r--r-- root root 6513 ./usr/lib/python3.8/distutils/__pycache__/bcppcompiler.cpython-38.opt-1.pyc
+-rw-r--r-- root root 6225 ./usr/lib/python3.8/distutils/__pycache__/bcppcompiler.cpython-38.opt-2.pyc
+-rw-r--r-- root root 6513 ./usr/lib/python3.8/distutils/__pycache__/bcppcompiler.cpython-38.pyc
+-rw-r--r-- root root 33160 ./usr/lib/python3.8/distutils/__pycache__/ccompiler.cpython-38.opt-1.pyc
+-rw-r--r-- root root 16854 ./usr/lib/python3.8/distutils/__pycache__/ccompiler.cpython-38.opt-2.pyc
+-rw-r--r-- root root 33287 ./usr/lib/python3.8/distutils/__pycache__/ccompiler.cpython-38.pyc
+-rw-r--r-- root root 13938 ./usr/lib/python3.8/distutils/__pycache__/cmd.cpython-38.opt-1.pyc
+-rw-r--r-- root root 8072 ./usr/lib/python3.8/distutils/__pycache__/cmd.cpython-38.opt-2.pyc
+-rw-r--r-- root root 13938 ./usr/lib/python3.8/distutils/__pycache__/cmd.cpython-38.pyc
+-rw-r--r-- root root 3499 ./usr/lib/python3.8/distutils/__pycache__/config.cpython-38.opt-1.pyc
+-rw-r--r-- root root 3108 ./usr/lib/python3.8/distutils/__pycache__/config.cpython-38.opt-2.pyc
+-rw-r--r-- root root 3499 ./usr/lib/python3.8/distutils/__pycache__/config.cpython-38.pyc
+-rw-r--r-- root root 6604 ./usr/lib/python3.8/distutils/__pycache__/core.cpython-38.opt-1.pyc
+-rw-r--r-- root root 3217 ./usr/lib/python3.8/distutils/__pycache__/core.cpython-38.opt-2.pyc
+-rw-r--r-- root root 6604 ./usr/lib/python3.8/distutils/__pycache__/core.cpython-38.pyc
+-rw-r--r-- root root 8602 ./usr/lib/python3.8/distutils/__pycache__/cygwinccompiler.cpython-38.opt-1.pyc
+-rw-r--r-- root root 6972 ./usr/lib/python3.8/distutils/__pycache__/cygwinccompiler.cpython-38.opt-2.pyc
+-rw-r--r-- root root 8602 ./usr/lib/python3.8/distutils/__pycache__/cygwinccompiler.cpython-38.pyc
+-rw-r--r-- root root 184 ./usr/lib/python3.8/distutils/__pycache__/debug.cpython-38.opt-1.pyc
+-rw-r--r-- root root 184 ./usr/lib/python3.8/distutils/__pycache__/debug.cpython-38.opt-2.pyc
+-rw-r--r-- root root 184 ./usr/lib/python3.8/distutils/__pycache__/debug.cpython-38.pyc
+-rw-r--r-- root root 2704 ./usr/lib/python3.8/distutils/__pycache__/dep_util.cpython-38.opt-1.pyc
+-rw-r--r-- root root 1260 ./usr/lib/python3.8/distutils/__pycache__/dep_util.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2704 ./usr/lib/python3.8/distutils/__pycache__/dep_util.cpython-38.pyc
+-rw-r--r-- root root 5813 ./usr/lib/python3.8/distutils/__pycache__/dir_util.cpython-38.opt-1.pyc
+-rw-r--r-- root root 3435 ./usr/lib/python3.8/distutils/__pycache__/dir_util.cpython-38.opt-2.pyc
+-rw-r--r-- root root 5813 ./usr/lib/python3.8/distutils/__pycache__/dir_util.cpython-38.pyc
+-rw-r--r-- root root 34482 ./usr/lib/python3.8/distutils/__pycache__/dist.cpython-38.opt-1.pyc
+-rw-r--r-- root root 25191 ./usr/lib/python3.8/distutils/__pycache__/dist.cpython-38.opt-2.pyc
+-rw-r--r-- root root 34482 ./usr/lib/python3.8/distutils/__pycache__/dist.cpython-38.pyc
+-rw-r--r-- root root 5240 ./usr/lib/python3.8/distutils/__pycache__/errors.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2692 ./usr/lib/python3.8/distutils/__pycache__/errors.cpython-38.opt-2.pyc
+-rw-r--r-- root root 5240 ./usr/lib/python3.8/distutils/__pycache__/errors.cpython-38.pyc
+-rw-r--r-- root root 6913 ./usr/lib/python3.8/distutils/__pycache__/extension.cpython-38.opt-1.pyc
+-rw-r--r-- root root 3423 ./usr/lib/python3.8/distutils/__pycache__/extension.cpython-38.opt-2.pyc
+-rw-r--r-- root root 6913 ./usr/lib/python3.8/distutils/__pycache__/extension.cpython-38.pyc
+-rw-r--r-- root root 10502 ./usr/lib/python3.8/distutils/__pycache__/fancy_getopt.cpython-38.opt-1.pyc
+-rw-r--r-- root root 7699 ./usr/lib/python3.8/distutils/__pycache__/fancy_getopt.cpython-38.opt-2.pyc
+-rw-r--r-- root root 10646 ./usr/lib/python3.8/distutils/__pycache__/fancy_getopt.cpython-38.pyc
+-rw-r--r-- root root 9767 ./usr/lib/python3.8/distutils/__pycache__/filelist.cpython-38.opt-1.pyc
+-rw-r--r-- root root 6896 ./usr/lib/python3.8/distutils/__pycache__/filelist.cpython-38.opt-2.pyc
+-rw-r--r-- root root 9857 ./usr/lib/python3.8/distutils/__pycache__/filelist.cpython-38.pyc
+-rw-r--r-- root root 5923 ./usr/lib/python3.8/distutils/__pycache__/file_util.cpython-38.opt-1.pyc
+-rw-r--r-- root root 3786 ./usr/lib/python3.8/distutils/__pycache__/file_util.cpython-38.opt-2.pyc
+-rw-r--r-- root root 5923 ./usr/lib/python3.8/distutils/__pycache__/file_util.cpython-38.pyc
+-rw-r--r-- root root 374 ./usr/lib/python3.8/distutils/__pycache__/__init__.cpython-38.opt-1.pyc
+-rw-r--r-- root root 192 ./usr/lib/python3.8/distutils/__pycache__/__init__.cpython-38.opt-2.pyc
+-rw-r--r-- root root 374 ./usr/lib/python3.8/distutils/__pycache__/__init__.cpython-38.pyc
+-rw-r--r-- root root 2305 ./usr/lib/python3.8/distutils/__pycache__/log.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2244 ./usr/lib/python3.8/distutils/__pycache__/log.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2305 ./usr/lib/python3.8/distutils/__pycache__/log.cpython-38.pyc
+-rw-r--r-- root root 17441 ./usr/lib/python3.8/distutils/__pycache__/msvc9compiler.cpython-38.opt-1.pyc
+-rw-r--r-- root root 15820 ./usr/lib/python3.8/distutils/__pycache__/msvc9compiler.cpython-38.opt-2.pyc
+-rw-r--r-- root root 17500 ./usr/lib/python3.8/distutils/__pycache__/msvc9compiler.cpython-38.pyc
+-rw-r--r-- root root 13907 ./usr/lib/python3.8/distutils/__pycache__/_msvccompiler.cpython-38.opt-1.pyc
+-rw-r--r-- root root 14713 ./usr/lib/python3.8/distutils/__pycache__/msvccompiler.cpython-38.opt-1.pyc
+-rw-r--r-- root root 12757 ./usr/lib/python3.8/distutils/__pycache__/_msvccompiler.cpython-38.opt-2.pyc
+-rw-r--r-- root root 13138 ./usr/lib/python3.8/distutils/__pycache__/msvccompiler.cpython-38.opt-2.pyc
+-rw-r--r-- root root 13970 ./usr/lib/python3.8/distutils/__pycache__/_msvccompiler.cpython-38.pyc
+-rw-r--r-- root root 14713 ./usr/lib/python3.8/distutils/__pycache__/msvccompiler.cpython-38.pyc
+-rw-r--r-- root root 5096 ./usr/lib/python3.8/distutils/__pycache__/spawn.cpython-38.opt-1.pyc
+-rw-r--r-- root root 3792 ./usr/lib/python3.8/distutils/__pycache__/spawn.cpython-38.opt-2.pyc
+-rw-r--r-- root root 5096 ./usr/lib/python3.8/distutils/__pycache__/spawn.cpython-38.pyc
+-rw-r--r-- root root 12091 ./usr/lib/python3.8/distutils/__pycache__/sysconfig.cpython-38.opt-1.pyc
+-rw-r--r-- root root 8606 ./usr/lib/python3.8/distutils/__pycache__/sysconfig.cpython-38.opt-2.pyc
+-rw-r--r-- root root 12091 ./usr/lib/python3.8/distutils/__pycache__/sysconfig.cpython-38.pyc
+-rw-r--r-- root root 8429 ./usr/lib/python3.8/distutils/__pycache__/text_file.cpython-38.opt-1.pyc
+-rw-r--r-- root root 3331 ./usr/lib/python3.8/distutils/__pycache__/text_file.cpython-38.opt-2.pyc
+-rw-r--r-- root root 8429 ./usr/lib/python3.8/distutils/__pycache__/text_file.cpython-38.pyc
+-rw-r--r-- root root 6608 ./usr/lib/python3.8/distutils/__pycache__/unixccompiler.cpython-38.opt-1.pyc
+-rw-r--r-- root root 6019 ./usr/lib/python3.8/distutils/__pycache__/unixccompiler.cpython-38.opt-2.pyc
+-rw-r--r-- root root 6608 ./usr/lib/python3.8/distutils/__pycache__/unixccompiler.cpython-38.pyc
+-rw-r--r-- root root 15536 ./usr/lib/python3.8/distutils/__pycache__/util.cpython-38.opt-1.pyc
+-rw-r--r-- root root 9652 ./usr/lib/python3.8/distutils/__pycache__/util.cpython-38.opt-2.pyc
+-rw-r--r-- root root 15536 ./usr/lib/python3.8/distutils/__pycache__/util.cpython-38.pyc
+-rw-r--r-- root root 7256 ./usr/lib/python3.8/distutils/__pycache__/version.cpython-38.opt-1.pyc
+-rw-r--r-- root root 3971 ./usr/lib/python3.8/distutils/__pycache__/version.cpython-38.opt-2.pyc
+-rw-r--r-- root root 7301 ./usr/lib/python3.8/distutils/__pycache__/version.cpython-38.pyc
+-rw-r--r-- root root 5125 ./usr/lib/python3.8/distutils/__pycache__/versionpredicate.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2645 ./usr/lib/python3.8/distutils/__pycache__/versionpredicate.cpython-38.opt-2.pyc
+-rw-r--r-- root root 5125 ./usr/lib/python3.8/distutils/__pycache__/versionpredicate.cpython-38.pyc
+-rw-r--r-- root root 242 ./usr/lib/python3.8/distutils/README
+-rw-r--r-- root root 7843 ./usr/lib/python3.8/distutils/spawn.py
+-rw-r--r-- root root 20390 ./usr/lib/python3.8/distutils/sysconfig.py
+-rw-r--r-- root root 12483 ./usr/lib/python3.8/distutils/text_file.py
+-rw-r--r-- root root 14696 ./usr/lib/python3.8/distutils/unixccompiler.py
+-rw-r--r-- root root 20892 ./usr/lib/python3.8/distutils/util.py
+-rw-r--r-- root root 5133 ./usr/lib/python3.8/distutils/versionpredicate.py
+-rw-r--r-- root root 12345 ./usr/lib/python3.8/distutils/version.py
+-rw-r--r-- root root 6027 ./usr/lib/python3.8/_dummy_thread.py
+drwxr-xr-x root root 4096 ./usr/lib/python3.8/email
+-rw-r--r-- root root 9561 ./usr/lib/python3.8/email/architecture.rst
+-rw-r--r-- root root 3558 ./usr/lib/python3.8/email/base64mime.py
+-rw-r--r-- root root 17128 ./usr/lib/python3.8/email/charset.py
+-rw-r--r-- root root 10672 ./usr/lib/python3.8/email/contentmanager.py
+-rw-r--r-- root root 8524 ./usr/lib/python3.8/email/_encoded_words.py
+-rw-r--r-- root root 1786 ./usr/lib/python3.8/email/encoders.py
+-rw-r--r-- root root 3647 ./usr/lib/python3.8/email/errors.py
+-rw-r--r-- root root 22780 ./usr/lib/python3.8/email/feedparser.py
+-rw-r--r-- root root 19975 ./usr/lib/python3.8/email/generator.py
+-rw-r--r-- root root 24102 ./usr/lib/python3.8/email/header.py
+-rw-r--r-- root root 20591 ./usr/lib/python3.8/email/headerregistry.py
+-rw-r--r-- root root 106460 ./usr/lib/python3.8/email/_header_value_parser.py
+-rw-r--r-- root root 1766 ./usr/lib/python3.8/email/__init__.py
+-rw-r--r-- root root 2135 ./usr/lib/python3.8/email/iterators.py
+-rw-r--r-- root root 47072 ./usr/lib/python3.8/email/message.py
+drwxr-xr-x root root 4096 ./usr/lib/python3.8/email/mime
+-rw-r--r-- root root 1321 ./usr/lib/python3.8/email/mime/application.py
+-rw-r--r-- root root 2739 ./usr/lib/python3.8/email/mime/audio.py
+-rw-r--r-- root root 916 ./usr/lib/python3.8/email/mime/base.py
+-rw-r--r-- root root 1829 ./usr/lib/python3.8/email/mime/image.py
+-rw-r--r-- root root 0 ./usr/lib/python3.8/email/mime/__init__.py
+-rw-r--r-- root root 1317 ./usr/lib/python3.8/email/mime/message.py
+-rw-r--r-- root root 1621 ./usr/lib/python3.8/email/mime/multipart.py
+-rw-r--r-- root root 691 ./usr/lib/python3.8/email/mime/nonmultipart.py
+drwxr-xr-x root root 4096 ./usr/lib/python3.8/email/mime/__pycache__
+-rw-r--r-- root root 1448 ./usr/lib/python3.8/email/mime/__pycache__/application.cpython-38.opt-1.pyc
+-rw-r--r-- root root 794 ./usr/lib/python3.8/email/mime/__pycache__/application.cpython-38.opt-2.pyc
+-rw-r--r-- root root 1448 ./usr/lib/python3.8/email/mime/__pycache__/application.cpython-38.pyc
+-rw-r--r-- root root 2613 ./usr/lib/python3.8/email/mime/__pycache__/audio.cpython-38.opt-1.pyc
+-rw-r--r-- root root 1173 ./usr/lib/python3.8/email/mime/__pycache__/audio.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2613 ./usr/lib/python3.8/email/mime/__pycache__/audio.cpython-38.pyc
+-rw-r--r-- root root 1030 ./usr/lib/python3.8/email/mime/__pycache__/base.cpython-38.opt-1.pyc
+-rw-r--r-- root root 706 ./usr/lib/python3.8/email/mime/__pycache__/base.cpython-38.opt-2.pyc
+-rw-r--r-- root root 1030 ./usr/lib/python3.8/email/mime/__pycache__/base.cpython-38.pyc
+-rw-r--r-- root root 1893 ./usr/lib/python3.8/email/mime/__pycache__/image.cpython-38.opt-1.pyc
+-rw-r--r-- root root 816 ./usr/lib/python3.8/email/mime/__pycache__/image.cpython-38.opt-2.pyc
+-rw-r--r-- root root 1893 ./usr/lib/python3.8/email/mime/__pycache__/image.cpython-38.pyc
+-rw-r--r-- root root 121 ./usr/lib/python3.8/email/mime/__pycache__/__init__.cpython-38.opt-1.pyc
+-rw-r--r-- root root 121 ./usr/lib/python3.8/email/mime/__pycache__/__init__.cpython-38.opt-2.pyc
+-rw-r--r-- root root 121 ./usr/lib/python3.8/email/mime/__pycache__/__init__.cpython-38.pyc
+-rw-r--r-- root root 1271 ./usr/lib/python3.8/email/mime/__pycache__/message.cpython-38.opt-1.pyc
+-rw-r--r-- root root 779 ./usr/lib/python3.8/email/mime/__pycache__/message.cpython-38.opt-2.pyc
+-rw-r--r-- root root 1271 ./usr/lib/python3.8/email/mime/__pycache__/message.cpython-38.pyc
+-rw-r--r-- root root 1491 ./usr/lib/python3.8/email/mime/__pycache__/multipart.cpython-38.opt-1.pyc
+-rw-r--r-- root root 695 ./usr/lib/python3.8/email/mime/__pycache__/multipart.cpython-38.opt-2.pyc
+-rw-r--r-- root root 1491 ./usr/lib/python3.8/email/mime/__pycache__/multipart.cpython-38.pyc
+-rw-r--r-- root root 753 ./usr/lib/python3.8/email/mime/__pycache__/nonmultipart.cpython-38.opt-1.pyc
+-rw-r--r-- root root 618 ./usr/lib/python3.8/email/mime/__pycache__/nonmultipart.cpython-38.opt-2.pyc
+-rw-r--r-- root root 753 ./usr/lib/python3.8/email/mime/__pycache__/nonmultipart.cpython-38.pyc
+-rw-r--r-- root root 1300 ./usr/lib/python3.8/email/mime/__pycache__/text.cpython-38.opt-1.pyc
+-rw-r--r-- root root 789 ./usr/lib/python3.8/email/mime/__pycache__/text.cpython-38.opt-2.pyc
+-rw-r--r-- root root 1300 ./usr/lib/python3.8/email/mime/__pycache__/text.cpython-38.pyc
+-rw-r--r-- root root 1437 ./usr/lib/python3.8/email/mime/text.py
+-rw-r--r-- root root 17604 ./usr/lib/python3.8/email/_parseaddr.py
+-rw-r--r-- root root 5041 ./usr/lib/python3.8/email/parser.py
+-rw-r--r-- root root 15073 ./usr/lib/python3.8/email/_policybase.py
+-rw-r--r-- root root 10383 ./usr/lib/python3.8/email/policy.py
+drwxr-xr-x root root 4096 ./usr/lib/python3.8/email/__pycache__
+-rw-r--r-- root root 3229 ./usr/lib/python3.8/email/__pycache__/base64mime.cpython-38.opt-1.pyc
+-rw-r--r-- root root 1452 ./usr/lib/python3.8/email/__pycache__/base64mime.cpython-38.opt-2.pyc
+-rw-r--r-- root root 3229 ./usr/lib/python3.8/email/__pycache__/base64mime.cpython-38.pyc
+-rw-r--r-- root root 11416 ./usr/lib/python3.8/email/__pycache__/charset.cpython-38.opt-1.pyc
+-rw-r--r-- root root 5087 ./usr/lib/python3.8/email/__pycache__/charset.cpython-38.opt-2.pyc
+-rw-r--r-- root root 11453 ./usr/lib/python3.8/email/__pycache__/charset.cpython-38.pyc
+-rw-r--r-- root root 7337 ./usr/lib/python3.8/email/__pycache__/contentmanager.cpython-38.opt-1.pyc
+-rw-r--r-- root root 7337 ./usr/lib/python3.8/email/__pycache__/contentmanager.cpython-38.opt-2.pyc
+-rw-r--r-- root root 7337 ./usr/lib/python3.8/email/__pycache__/contentmanager.cpython-38.pyc
+-rw-r--r-- root root 5680 ./usr/lib/python3.8/email/__pycache__/_encoded_words.cpython-38.opt-1.pyc
+-rw-r--r-- root root 3794 ./usr/lib/python3.8/email/__pycache__/_encoded_words.cpython-38.opt-2.pyc
+-rw-r--r-- root root 5680 ./usr/lib/python3.8/email/__pycache__/_encoded_words.cpython-38.pyc
+-rw-r--r-- root root 1606 ./usr/lib/python3.8/email/__pycache__/encoders.cpython-38.opt-1.pyc
+-rw-r--r-- root root 1255 ./usr/lib/python3.8/email/__pycache__/encoders.cpython-38.opt-2.pyc
+-rw-r--r-- root root 1606 ./usr/lib/python3.8/email/__pycache__/encoders.cpython-38.pyc
+-rw-r--r-- root root 5899 ./usr/lib/python3.8/email/__pycache__/errors.cpython-38.opt-1.pyc
+-rw-r--r-- root root 4467 ./usr/lib/python3.8/email/__pycache__/errors.cpython-38.opt-2.pyc
+-rw-r--r-- root root 5899 ./usr/lib/python3.8/email/__pycache__/errors.cpython-38.pyc
+-rw-r--r-- root root 10484 ./usr/lib/python3.8/email/__pycache__/feedparser.cpython-38.opt-1.pyc
+-rw-r--r-- root root 8821 ./usr/lib/python3.8/email/__pycache__/feedparser.cpython-38.opt-2.pyc
+-rw-r--r-- root root 10636 ./usr/lib/python3.8/email/__pycache__/feedparser.cpython-38.pyc
+-rw-r--r-- root root 12476 ./usr/lib/python3.8/email/__pycache__/generator.cpython-38.opt-1.pyc
+-rw-r--r-- root root 8777 ./usr/lib/python3.8/email/__pycache__/generator.cpython-38.opt-2.pyc
+-rw-r--r-- root root 12476 ./usr/lib/python3.8/email/__pycache__/generator.cpython-38.pyc
+-rw-r--r-- root root 16433 ./usr/lib/python3.8/email/__pycache__/header.cpython-38.opt-1.pyc
+-rw-r--r-- root root 10809 ./usr/lib/python3.8/email/__pycache__/header.cpython-38.opt-2.pyc
+-rw-r--r-- root root 16433 ./usr/lib/python3.8/email/__pycache__/header.cpython-38.pyc
+-rw-r--r-- root root 21842 ./usr/lib/python3.8/email/__pycache__/headerregistry.cpython-38.opt-1.pyc
+-rw-r--r-- root root 16079 ./usr/lib/python3.8/email/__pycache__/headerregistry.cpython-38.opt-2.pyc
+-rw-r--r-- root root 21894 ./usr/lib/python3.8/email/__pycache__/headerregistry.cpython-38.pyc
+-rw-r--r-- root root 79733 ./usr/lib/python3.8/email/__pycache__/_header_value_parser.cpython-38.opt-1.pyc
+-rw-r--r-- root root 62861 ./usr/lib/python3.8/email/__pycache__/_header_value_parser.cpython-38.opt-2.pyc
+-rw-r--r-- root root 79781 ./usr/lib/python3.8/email/__pycache__/_header_value_parser.cpython-38.pyc
+-rw-r--r-- root root 1685 ./usr/lib/python3.8/email/__pycache__/__init__.cpython-38.opt-1.pyc
+-rw-r--r-- root root 1060 ./usr/lib/python3.8/email/__pycache__/__init__.cpython-38.opt-2.pyc
+-rw-r--r-- root root 1685 ./usr/lib/python3.8/email/__pycache__/__init__.cpython-38.pyc
+-rw-r--r-- root root 1914 ./usr/lib/python3.8/email/__pycache__/iterators.cpython-38.opt-1.pyc
+-rw-r--r-- root root 1294 ./usr/lib/python3.8/email/__pycache__/iterators.cpython-38.opt-2.pyc
+-rw-r--r-- root root 1914 ./usr/lib/python3.8/email/__pycache__/iterators.cpython-38.pyc
+-rw-r--r-- root root 37872 ./usr/lib/python3.8/email/__pycache__/message.cpython-38.opt-1.pyc
+-rw-r--r-- root root 21310 ./usr/lib/python3.8/email/__pycache__/message.cpython-38.opt-2.pyc
+-rw-r--r-- root root 37872 ./usr/lib/python3.8/email/__pycache__/message.cpython-38.pyc
+-rw-r--r-- root root 12448 ./usr/lib/python3.8/email/__pycache__/_parseaddr.cpython-38.opt-1.pyc
+-rw-r--r-- root root 9488 ./usr/lib/python3.8/email/__pycache__/_parseaddr.cpython-38.opt-2.pyc
+-rw-r--r-- root root 12448 ./usr/lib/python3.8/email/__pycache__/_parseaddr.cpython-38.pyc
+-rw-r--r-- root root 5716 ./usr/lib/python3.8/email/__pycache__/parser.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2698 ./usr/lib/python3.8/email/__pycache__/parser.cpython-38.opt-2.pyc
+-rw-r--r-- root root 5716 ./usr/lib/python3.8/email/__pycache__/parser.cpython-38.pyc
+-rw-r--r-- root root 14804 ./usr/lib/python3.8/email/__pycache__/_policybase.cpython-38.opt-1.pyc
+-rw-r--r-- root root 5976 ./usr/lib/python3.8/email/__pycache__/_policybase.cpython-38.opt-2.pyc
+-rw-r--r-- root root 14804 ./usr/lib/python3.8/email/__pycache__/_policybase.cpython-38.pyc
+-rw-r--r-- root root 9652 ./usr/lib/python3.8/email/__pycache__/policy.cpython-38.opt-1.pyc
+-rw-r--r-- root root 3437 ./usr/lib/python3.8/email/__pycache__/policy.cpython-38.opt-2.pyc
+-rw-r--r-- root root 9652 ./usr/lib/python3.8/email/__pycache__/policy.cpython-38.pyc
+-rw-r--r-- root root 7672 ./usr/lib/python3.8/email/__pycache__/quoprimime.cpython-38.opt-1.pyc
+-rw-r--r-- root root 4199 ./usr/lib/python3.8/email/__pycache__/quoprimime.cpython-38.opt-2.pyc
+-rw-r--r-- root root 7672 ./usr/lib/python3.8/email/__pycache__/quoprimime.cpython-38.pyc
+-rw-r--r-- root root 9541 ./usr/lib/python3.8/email/__pycache__/utils.cpython-38.opt-1.pyc
+-rw-r--r-- root root 6212 ./usr/lib/python3.8/email/__pycache__/utils.cpython-38.opt-2.pyc
+-rw-r--r-- root root 9541 ./usr/lib/python3.8/email/__pycache__/utils.cpython-38.pyc
+-rw-r--r-- root root 9858 ./usr/lib/python3.8/email/quoprimime.py
+-rw-r--r-- root root 13488 ./usr/lib/python3.8/email/utils.py
+drwxr-xr-x root root 4096 ./usr/lib/python3.8/encodings
+-rw-r--r-- root root 15693 ./usr/lib/python3.8/encodings/aliases.py
+-rw-r--r-- root root 1248 ./usr/lib/python3.8/encodings/ascii.py
+-rw-r--r-- root root 1533 ./usr/lib/python3.8/encodings/base64_codec.py
+-rw-r--r-- root root 1039 ./usr/lib/python3.8/encodings/big5hkscs.py
+-rw-r--r-- root root 1019 ./usr/lib/python3.8/encodings/big5.py
+-rw-r--r-- root root 2249 ./usr/lib/python3.8/encodings/bz2_codec.py
+-rw-r--r-- root root 2084 ./usr/lib/python3.8/encodings/charmap.py
+-rw-r--r-- root root 13121 ./usr/lib/python3.8/encodings/cp037.py
+-rw-r--r-- root root 13568 ./usr/lib/python3.8/encodings/cp1006.py
+-rw-r--r-- root root 13113 ./usr/lib/python3.8/encodings/cp1026.py
+-rw-r--r-- root root 34597 ./usr/lib/python3.8/encodings/cp1125.py
+-rw-r--r-- root root 13105 ./usr/lib/python3.8/encodings/cp1140.py
+-rw-r--r-- root root 13686 ./usr/lib/python3.8/encodings/cp1250.py
+-rw-r--r-- root root 13361 ./usr/lib/python3.8/encodings/cp1251.py
+-rw-r--r-- root root 13511 ./usr/lib/python3.8/encodings/cp1252.py
+-rw-r--r-- root root 13094 ./usr/lib/python3.8/encodings/cp1253.py
+-rw-r--r-- root root 13502 ./usr/lib/python3.8/encodings/cp1254.py
+-rw-r--r-- root root 12466 ./usr/lib/python3.8/encodings/cp1255.py
+-rw-r--r-- root root 12814 ./usr/lib/python3.8/encodings/cp1256.py
+-rw-r--r-- root root 13374 ./usr/lib/python3.8/encodings/cp1257.py
+-rw-r--r-- root root 13364 ./usr/lib/python3.8/encodings/cp1258.py
+-rw-r--r-- root root 14132 ./usr/lib/python3.8/encodings/cp273.py
+-rw-r--r-- root root 12055 ./usr/lib/python3.8/encodings/cp424.py
+-rw-r--r-- root root 34564 ./usr/lib/python3.8/encodings/cp437.py
+-rw-r--r-- root root 13121 ./usr/lib/python3.8/encodings/cp500.py
+-rw-r--r-- root root 13686 ./usr/lib/python3.8/encodings/cp720.py
+-rw-r--r-- root root 34681 ./usr/lib/python3.8/encodings/cp737.py
+-rw-r--r-- root root 34476 ./usr/lib/python3.8/encodings/cp775.py
+-rw-r--r-- root root 34105 ./usr/lib/python3.8/encodings/cp850.py
+-rw-r--r-- root root 35002 ./usr/lib/python3.8/encodings/cp852.py
+-rw-r--r-- root root 33850 ./usr/lib/python3.8/encodings/cp855.py
+-rw-r--r-- root root 12423 ./usr/lib/python3.8/encodings/cp856.py
+-rw-r--r-- root root 33908 ./usr/lib/python3.8/encodings/cp857.py
+-rw-r--r-- root root 34015 ./usr/lib/python3.8/encodings/cp858.py
+-rw-r--r-- root root 34681 ./usr/lib/python3.8/encodings/cp860.py
+-rw-r--r-- root root 34633 ./usr/lib/python3.8/encodings/cp861.py
+-rw-r--r-- root root 33370 ./usr/lib/python3.8/encodings/cp862.py
+-rw-r--r-- root root 34252 ./usr/lib/python3.8/encodings/cp863.py
+-rw-r--r-- root root 33663 ./usr/lib/python3.8/encodings/cp864.py
+-rw-r--r-- root root 34618 ./usr/lib/python3.8/encodings/cp865.py
+-rw-r--r-- root root 34396 ./usr/lib/python3.8/encodings/cp866.py
+-rw-r--r-- root root 32965 ./usr/lib/python3.8/encodings/cp869.py
+-rw-r--r-- root root 12595 ./usr/lib/python3.8/encodings/cp874.py
+-rw-r--r-- root root 12854 ./usr/lib/python3.8/encodings/cp875.py
+-rw-r--r-- root root 1023 ./usr/lib/python3.8/encodings/cp932.py
+-rw-r--r-- root root 1023 ./usr/lib/python3.8/encodings/cp949.py
+-rw-r--r-- root root 1023 ./usr/lib/python3.8/encodings/cp950.py
+-rw-r--r-- root root 1051 ./usr/lib/python3.8/encodings/euc_jis_2004.py
+-rw-r--r-- root root 1051 ./usr/lib/python3.8/encodings/euc_jisx0213.py
+-rw-r--r-- root root 1027 ./usr/lib/python3.8/encodings/euc_jp.py
+-rw-r--r-- root root 1027 ./usr/lib/python3.8/encodings/euc_kr.py
+-rw-r--r-- root root 1031 ./usr/lib/python3.8/encodings/gb18030.py
+-rw-r--r-- root root 1027 ./usr/lib/python3.8/encodings/gb2312.py
+-rw-r--r-- root root 1015 ./usr/lib/python3.8/encodings/gbk.py
+-rw-r--r-- root root 1508 ./usr/lib/python3.8/encodings/hex_codec.py
+-rw-r--r-- root root 13475 ./usr/lib/python3.8/encodings/hp_roman8.py
+-rw-r--r-- root root 1011 ./usr/lib/python3.8/encodings/hz.py
+-rw-r--r-- root root 9170 ./usr/lib/python3.8/encodings/idna.py
+-rw-r--r-- root root 5588 ./usr/lib/python3.8/encodings/__init__.py
+-rw-r--r-- root root 1061 ./usr/lib/python3.8/encodings/iso2022_jp_1.py
+-rw-r--r-- root root 1073 ./usr/lib/python3.8/encodings/iso2022_jp_2004.py
+-rw-r--r-- root root 1061 ./usr/lib/python3.8/encodings/iso2022_jp_2.py
+-rw-r--r-- root root 1061 ./usr/lib/python3.8/encodings/iso2022_jp_3.py
+-rw-r--r-- root root 1069 ./usr/lib/python3.8/encodings/iso2022_jp_ext.py
+-rw-r--r-- root root 1053 ./usr/lib/python3.8/encodings/iso2022_jp.py
+-rw-r--r-- root root 1053 ./usr/lib/python3.8/encodings/iso2022_kr.py
+-rw-r--r-- root root 13589 ./usr/lib/python3.8/encodings/iso8859_10.py
+-rw-r--r-- root root 12335 ./usr/lib/python3.8/encodings/iso8859_11.py
+-rw-r--r-- root root 13271 ./usr/lib/python3.8/encodings/iso8859_13.py
+-rw-r--r-- root root 13652 ./usr/lib/python3.8/encodings/iso8859_14.py
+-rw-r--r-- root root 13212 ./usr/lib/python3.8/encodings/iso8859_15.py
+-rw-r--r-- root root 13557 ./usr/lib/python3.8/encodings/iso8859_16.py
+-rw-r--r-- root root 13176 ./usr/lib/python3.8/encodings/iso8859_1.py
+-rw-r--r-- root root 13404 ./usr/lib/python3.8/encodings/iso8859_2.py
+-rw-r--r-- root root 13089 ./usr/lib/python3.8/encodings/iso8859_3.py
+-rw-r--r-- root root 13376 ./usr/lib/python3.8/encodings/iso8859_4.py
+-rw-r--r-- root root 13015 ./usr/lib/python3.8/encodings/iso8859_5.py
+-rw-r--r-- root root 10833 ./usr/lib/python3.8/encodings/iso8859_6.py
+-rw-r--r-- root root 12844 ./usr/lib/python3.8/encodings/iso8859_7.py
+-rw-r--r-- root root 11036 ./usr/lib/python3.8/encodings/iso8859_8.py
+-rw-r--r-- root root 13156 ./usr/lib/python3.8/encodings/iso8859_9.py
+-rw-r--r-- root root 1023 ./usr/lib/python3.8/encodings/johab.py
+-rw-r--r-- root root 13779 ./usr/lib/python3.8/encodings/koi8_r.py
+-rw-r--r-- root root 13193 ./usr/lib/python3.8/encodings/koi8_t.py
+-rw-r--r-- root root 13762 ./usr/lib/python3.8/encodings/koi8_u.py
+-rw-r--r-- root root 13723 ./usr/lib/python3.8/encodings/kz1048.py
+-rw-r--r-- root root 1264 ./usr/lib/python3.8/encodings/latin_1.py
+-rw-r--r-- root root 36467 ./usr/lib/python3.8/encodings/mac_arabic.py
+-rw-r--r-- root root 14102 ./usr/lib/python3.8/encodings/mac_centeuro.py
+-rw-r--r-- root root 13633 ./usr/lib/python3.8/encodings/mac_croatian.py
+-rw-r--r-- root root 13454 ./usr/lib/python3.8/encodings/mac_cyrillic.py
+-rw-r--r-- root root 15170 ./usr/lib/python3.8/encodings/mac_farsi.py
+-rw-r--r-- root root 13721 ./usr/lib/python3.8/encodings/mac_greek.py
+-rw-r--r-- root root 13498 ./usr/lib/python3.8/encodings/mac_iceland.py
+-rw-r--r-- root root 14118 ./usr/lib/python3.8/encodings/mac_latin2.py
+-rw-r--r-- root root 13661 ./usr/lib/python3.8/encodings/mac_romanian.py
+-rw-r--r-- root root 13480 ./usr/lib/python3.8/encodings/mac_roman.py
+-rw-r--r-- root root 13513 ./usr/lib/python3.8/encodings/mac_turkish.py
+-rw-r--r-- root root 1211 ./usr/lib/python3.8/encodings/mbcs.py
+-rw-r--r-- root root 1019 ./usr/lib/python3.8/encodings/oem.py
+-rw-r--r-- root root 13519 ./usr/lib/python3.8/encodings/palmos.py
+-rw-r--r-- root root 14015 ./usr/lib/python3.8/encodings/ptcp154.py
+-rw-r--r-- root root 6881 ./usr/lib/python3.8/encodings/punycode.py
+drwxr-xr-x root root 24576 ./usr/lib/python3.8/encodings/__pycache__
+-rw-r--r-- root root 6320 ./usr/lib/python3.8/encodings/__pycache__/aliases.cpython-38.opt-1.pyc
+-rw-r--r-- root root 5728 ./usr/lib/python3.8/encodings/__pycache__/aliases.cpython-38.opt-2.pyc
+-rw-r--r-- root root 6320 ./usr/lib/python3.8/encodings/__pycache__/aliases.cpython-38.pyc
+-rw-r--r-- root root 1871 ./usr/lib/python3.8/encodings/__pycache__/ascii.cpython-38.opt-1.pyc
+-rw-r--r-- root root 1725 ./usr/lib/python3.8/encodings/__pycache__/ascii.cpython-38.opt-2.pyc
+-rw-r--r-- root root 1871 ./usr/lib/python3.8/encodings/__pycache__/ascii.cpython-38.pyc
+-rw-r--r-- root root 2285 ./usr/lib/python3.8/encodings/__pycache__/base64_codec.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2110 ./usr/lib/python3.8/encodings/__pycache__/base64_codec.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2389 ./usr/lib/python3.8/encodings/__pycache__/base64_codec.cpython-38.pyc
+-rw-r--r-- root root 1399 ./usr/lib/python3.8/encodings/__pycache__/big5.cpython-38.opt-1.pyc
+-rw-r--r-- root root 1399 ./usr/lib/python3.8/encodings/__pycache__/big5.cpython-38.opt-2.pyc
+-rw-r--r-- root root 1399 ./usr/lib/python3.8/encodings/__pycache__/big5.cpython-38.pyc
+-rw-r--r-- root root 1409 ./usr/lib/python3.8/encodings/__pycache__/big5hkscs.cpython-38.opt-1.pyc
+-rw-r--r-- root root 1409 ./usr/lib/python3.8/encodings/__pycache__/big5hkscs.cpython-38.opt-2.pyc
+-rw-r--r-- root root 1409 ./usr/lib/python3.8/encodings/__pycache__/big5hkscs.cpython-38.pyc
+-rw-r--r-- root root 3190 ./usr/lib/python3.8/encodings/__pycache__/bz2_codec.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2894 ./usr/lib/python3.8/encodings/__pycache__/bz2_codec.cpython-38.opt-2.pyc
+-rw-r--r-- root root 3280 ./usr/lib/python3.8/encodings/__pycache__/bz2_codec.cpython-38.pyc
+-rw-r--r-- root root 2881 ./usr/lib/python3.8/encodings/__pycache__/charmap.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2587 ./usr/lib/python3.8/encodings/__pycache__/charmap.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2881 ./usr/lib/python3.8/encodings/__pycache__/charmap.cpython-38.pyc
+-rw-r--r-- root root 2412 ./usr/lib/python3.8/encodings/__pycache__/cp037.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2280 ./usr/lib/python3.8/encodings/__pycache__/cp037.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2412 ./usr/lib/python3.8/encodings/__pycache__/cp037.cpython-38.pyc
+-rw-r--r-- root root 2488 ./usr/lib/python3.8/encodings/__pycache__/cp1006.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2363 ./usr/lib/python3.8/encodings/__pycache__/cp1006.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2488 ./usr/lib/python3.8/encodings/__pycache__/cp1006.cpython-38.pyc
+-rw-r--r-- root root 2416 ./usr/lib/python3.8/encodings/__pycache__/cp1026.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2282 ./usr/lib/python3.8/encodings/__pycache__/cp1026.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2416 ./usr/lib/python3.8/encodings/__pycache__/cp1026.cpython-38.pyc
+-rw-r--r-- root root 8119 ./usr/lib/python3.8/encodings/__pycache__/cp1125.cpython-38.opt-1.pyc
+-rw-r--r-- root root 8056 ./usr/lib/python3.8/encodings/__pycache__/cp1125.cpython-38.opt-2.pyc
+-rw-r--r-- root root 8119 ./usr/lib/python3.8/encodings/__pycache__/cp1125.cpython-38.pyc
+-rw-r--r-- root root 2402 ./usr/lib/python3.8/encodings/__pycache__/cp1140.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2283 ./usr/lib/python3.8/encodings/__pycache__/cp1140.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2402 ./usr/lib/python3.8/encodings/__pycache__/cp1140.cpython-38.pyc
+-rw-r--r-- root root 2439 ./usr/lib/python3.8/encodings/__pycache__/cp1250.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2304 ./usr/lib/python3.8/encodings/__pycache__/cp1250.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2439 ./usr/lib/python3.8/encodings/__pycache__/cp1250.cpython-38.pyc
+-rw-r--r-- root root 2436 ./usr/lib/python3.8/encodings/__pycache__/cp1251.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2301 ./usr/lib/python3.8/encodings/__pycache__/cp1251.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2436 ./usr/lib/python3.8/encodings/__pycache__/cp1251.cpython-38.pyc
+-rw-r--r-- root root 2439 ./usr/lib/python3.8/encodings/__pycache__/cp1252.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2304 ./usr/lib/python3.8/encodings/__pycache__/cp1252.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2439 ./usr/lib/python3.8/encodings/__pycache__/cp1252.cpython-38.pyc
+-rw-r--r-- root root 2452 ./usr/lib/python3.8/encodings/__pycache__/cp1253.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2317 ./usr/lib/python3.8/encodings/__pycache__/cp1253.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2452 ./usr/lib/python3.8/encodings/__pycache__/cp1253.cpython-38.pyc
+-rw-r--r-- root root 2441 ./usr/lib/python3.8/encodings/__pycache__/cp1254.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2306 ./usr/lib/python3.8/encodings/__pycache__/cp1254.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2441 ./usr/lib/python3.8/encodings/__pycache__/cp1254.cpython-38.pyc
+-rw-r--r-- root root 2460 ./usr/lib/python3.8/encodings/__pycache__/cp1255.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2325 ./usr/lib/python3.8/encodings/__pycache__/cp1255.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2460 ./usr/lib/python3.8/encodings/__pycache__/cp1255.cpython-38.pyc
+-rw-r--r-- root root 2438 ./usr/lib/python3.8/encodings/__pycache__/cp1256.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2303 ./usr/lib/python3.8/encodings/__pycache__/cp1256.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2438 ./usr/lib/python3.8/encodings/__pycache__/cp1256.cpython-38.pyc
+-rw-r--r-- root root 2446 ./usr/lib/python3.8/encodings/__pycache__/cp1257.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2311 ./usr/lib/python3.8/encodings/__pycache__/cp1257.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2446 ./usr/lib/python3.8/encodings/__pycache__/cp1257.cpython-38.pyc
+-rw-r--r-- root root 2444 ./usr/lib/python3.8/encodings/__pycache__/cp1258.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2309 ./usr/lib/python3.8/encodings/__pycache__/cp1258.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2444 ./usr/lib/python3.8/encodings/__pycache__/cp1258.cpython-38.pyc
+-rw-r--r-- root root 2398 ./usr/lib/python3.8/encodings/__pycache__/cp273.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2281 ./usr/lib/python3.8/encodings/__pycache__/cp273.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2398 ./usr/lib/python3.8/encodings/__pycache__/cp273.cpython-38.pyc
+-rw-r--r-- root root 2442 ./usr/lib/python3.8/encodings/__pycache__/cp424.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2319 ./usr/lib/python3.8/encodings/__pycache__/cp424.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2442 ./usr/lib/python3.8/encodings/__pycache__/cp424.cpython-38.pyc
+-rw-r--r-- root root 7836 ./usr/lib/python3.8/encodings/__pycache__/cp437.cpython-38.opt-1.pyc
+-rw-r--r-- root root 7715 ./usr/lib/python3.8/encodings/__pycache__/cp437.cpython-38.opt-2.pyc
+-rw-r--r-- root root 7836 ./usr/lib/python3.8/encodings/__pycache__/cp437.cpython-38.pyc
+-rw-r--r-- root root 2412 ./usr/lib/python3.8/encodings/__pycache__/cp500.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2280 ./usr/lib/python3.8/encodings/__pycache__/cp500.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2412 ./usr/lib/python3.8/encodings/__pycache__/cp500.cpython-38.pyc
+-rw-r--r-- root root 2509 ./usr/lib/python3.8/encodings/__pycache__/cp720.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2334 ./usr/lib/python3.8/encodings/__pycache__/cp720.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2509 ./usr/lib/python3.8/encodings/__pycache__/cp720.cpython-38.pyc
+-rw-r--r-- root root 8158 ./usr/lib/python3.8/encodings/__pycache__/cp737.cpython-38.opt-1.pyc
+-rw-r--r-- root root 8037 ./usr/lib/python3.8/encodings/__pycache__/cp737.cpython-38.opt-2.pyc
+-rw-r--r-- root root 8158 ./usr/lib/python3.8/encodings/__pycache__/cp737.cpython-38.pyc
+-rw-r--r-- root root 7866 ./usr/lib/python3.8/encodings/__pycache__/cp775.cpython-38.opt-1.pyc
+-rw-r--r-- root root 7745 ./usr/lib/python3.8/encodings/__pycache__/cp775.cpython-38.opt-2.pyc
+-rw-r--r-- root root 7866 ./usr/lib/python3.8/encodings/__pycache__/cp775.cpython-38.pyc
+-rw-r--r-- root root 7497 ./usr/lib/python3.8/encodings/__pycache__/cp850.cpython-38.opt-1.pyc
+-rw-r--r-- root root 7382 ./usr/lib/python3.8/encodings/__pycache__/cp850.cpython-38.opt-2.pyc
+-rw-r--r-- root root 7497 ./usr/lib/python3.8/encodings/__pycache__/cp850.cpython-38.pyc
+-rw-r--r-- root root 7874 ./usr/lib/python3.8/encodings/__pycache__/cp852.cpython-38.opt-1.pyc
+-rw-r--r-- root root 7759 ./usr/lib/python3.8/encodings/__pycache__/cp852.cpython-38.opt-2.pyc
+-rw-r--r-- root root 7874 ./usr/lib/python3.8/encodings/__pycache__/cp852.cpython-38.pyc
+-rw-r--r-- root root 8127 ./usr/lib/python3.8/encodings/__pycache__/cp855.cpython-38.opt-1.pyc
+-rw-r--r-- root root 8012 ./usr/lib/python3.8/encodings/__pycache__/cp855.cpython-38.opt-2.pyc
+-rw-r--r-- root root 8127 ./usr/lib/python3.8/encodings/__pycache__/cp855.cpython-38.pyc
+-rw-r--r-- root root 2474 ./usr/lib/python3.8/encodings/__pycache__/cp856.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2351 ./usr/lib/python3.8/encodings/__pycache__/cp856.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2474 ./usr/lib/python3.8/encodings/__pycache__/cp856.cpython-38.pyc
+-rw-r--r-- root root 7477 ./usr/lib/python3.8/encodings/__pycache__/cp857.cpython-38.opt-1.pyc
+-rw-r--r-- root root 7362 ./usr/lib/python3.8/encodings/__pycache__/cp857.cpython-38.opt-2.pyc
+-rw-r--r-- root root 7477 ./usr/lib/python3.8/encodings/__pycache__/cp857.cpython-38.pyc
+-rw-r--r-- root root 7467 ./usr/lib/python3.8/encodings/__pycache__/cp858.cpython-38.opt-1.pyc
+-rw-r--r-- root root 7383 ./usr/lib/python3.8/encodings/__pycache__/cp858.cpython-38.opt-2.pyc
+-rw-r--r-- root root 7467 ./usr/lib/python3.8/encodings/__pycache__/cp858.cpython-38.pyc
+-rw-r--r-- root root 7815 ./usr/lib/python3.8/encodings/__pycache__/cp860.cpython-38.opt-1.pyc
+-rw-r--r-- root root 7700 ./usr/lib/python3.8/encodings/__pycache__/cp860.cpython-38.opt-2.pyc
+-rw-r--r-- root root 7815 ./usr/lib/python3.8/encodings/__pycache__/cp860.cpython-38.pyc
+-rw-r--r-- root root 7830 ./usr/lib/python3.8/encodings/__pycache__/cp861.cpython-38.opt-1.pyc
+-rw-r--r-- root root 7715 ./usr/lib/python3.8/encodings/__pycache__/cp861.cpython-38.opt-2.pyc
+-rw-r--r-- root root 7830 ./usr/lib/python3.8/encodings/__pycache__/cp861.cpython-38.pyc
+-rw-r--r-- root root 8019 ./usr/lib/python3.8/encodings/__pycache__/cp862.cpython-38.opt-1.pyc
+-rw-r--r-- root root 7904 ./usr/lib/python3.8/encodings/__pycache__/cp862.cpython-38.opt-2.pyc
+-rw-r--r-- root root 8019 ./usr/lib/python3.8/encodings/__pycache__/cp862.cpython-38.pyc
+-rw-r--r-- root root 7830 ./usr/lib/python3.8/encodings/__pycache__/cp863.cpython-38.opt-1.pyc
+-rw-r--r-- root root 7715 ./usr/lib/python3.8/encodings/__pycache__/cp863.cpython-38.opt-2.pyc
+-rw-r--r-- root root 7830 ./usr/lib/python3.8/encodings/__pycache__/cp863.cpython-38.pyc
+-rw-r--r-- root root 7974 ./usr/lib/python3.8/encodings/__pycache__/cp864.cpython-38.opt-1.pyc
+-rw-r--r-- root root 7859 ./usr/lib/python3.8/encodings/__pycache__/cp864.cpython-38.opt-2.pyc
+-rw-r--r-- root root 7974 ./usr/lib/python3.8/encodings/__pycache__/cp864.cpython-38.pyc
+-rw-r--r-- root root 7830 ./usr/lib/python3.8/encodings/__pycache__/cp865.cpython-38.opt-1.pyc
+-rw-r--r-- root root 7715 ./usr/lib/python3.8/encodings/__pycache__/cp865.cpython-38.opt-2.pyc
+-rw-r--r-- root root 7830 ./usr/lib/python3.8/encodings/__pycache__/cp865.cpython-38.pyc
+-rw-r--r-- root root 8163 ./usr/lib/python3.8/encodings/__pycache__/cp866.cpython-38.opt-1.pyc
+-rw-r--r-- root root 8048 ./usr/lib/python3.8/encodings/__pycache__/cp866.cpython-38.opt-2.pyc
+-rw-r--r-- root root 8163 ./usr/lib/python3.8/encodings/__pycache__/cp866.cpython-38.pyc
+-rw-r--r-- root root 7854 ./usr/lib/python3.8/encodings/__pycache__/cp869.cpython-38.opt-1.pyc
+-rw-r--r-- root root 7739 ./usr/lib/python3.8/encodings/__pycache__/cp869.cpython-38.opt-2.pyc
+-rw-r--r-- root root 7854 ./usr/lib/python3.8/encodings/__pycache__/cp869.cpython-38.pyc
+-rw-r--r-- root root 2540 ./usr/lib/python3.8/encodings/__pycache__/cp874.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2407 ./usr/lib/python3.8/encodings/__pycache__/cp874.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2540 ./usr/lib/python3.8/encodings/__pycache__/cp874.cpython-38.pyc
+-rw-r--r-- root root 2409 ./usr/lib/python3.8/encodings/__pycache__/cp875.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2277 ./usr/lib/python3.8/encodings/__pycache__/cp875.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2409 ./usr/lib/python3.8/encodings/__pycache__/cp875.cpython-38.pyc
+-rw-r--r-- root root 1401 ./usr/lib/python3.8/encodings/__pycache__/cp932.cpython-38.opt-1.pyc
+-rw-r--r-- root root 1401 ./usr/lib/python3.8/encodings/__pycache__/cp932.cpython-38.opt-2.pyc
+-rw-r--r-- root root 1401 ./usr/lib/python3.8/encodings/__pycache__/cp932.cpython-38.pyc
+-rw-r--r-- root root 1401 ./usr/lib/python3.8/encodings/__pycache__/cp949.cpython-38.opt-1.pyc
+-rw-r--r-- root root 1401 ./usr/lib/python3.8/encodings/__pycache__/cp949.cpython-38.opt-2.pyc
+-rw-r--r-- root root 1401 ./usr/lib/python3.8/encodings/__pycache__/cp949.cpython-38.pyc
+-rw-r--r-- root root 1401 ./usr/lib/python3.8/encodings/__pycache__/cp950.cpython-38.opt-1.pyc
+-rw-r--r-- root root 1401 ./usr/lib/python3.8/encodings/__pycache__/cp950.cpython-38.opt-2.pyc
+-rw-r--r-- root root 1401 ./usr/lib/python3.8/encodings/__pycache__/cp950.cpython-38.pyc
+-rw-r--r-- root root 1415 ./usr/lib/python3.8/encodings/__pycache__/euc_jis_2004.cpython-38.opt-1.pyc
+-rw-r--r-- root root 1415 ./usr/lib/python3.8/encodings/__pycache__/euc_jis_2004.cpython-38.opt-2.pyc
+-rw-r--r-- root root 1415 ./usr/lib/python3.8/encodings/__pycache__/euc_jis_2004.cpython-38.pyc
+-rw-r--r-- root root 1415 ./usr/lib/python3.8/encodings/__pycache__/euc_jisx0213.cpython-38.opt-1.pyc
+-rw-r--r-- root root 1415 ./usr/lib/python3.8/encodings/__pycache__/euc_jisx0213.cpython-38.opt-2.pyc
+-rw-r--r-- root root 1415 ./usr/lib/python3.8/encodings/__pycache__/euc_jisx0213.cpython-38.pyc
+-rw-r--r-- root root 1403 ./usr/lib/python3.8/encodings/__pycache__/euc_jp.cpython-38.opt-1.pyc
+-rw-r--r-- root root 1403 ./usr/lib/python3.8/encodings/__pycache__/euc_jp.cpython-38.opt-2.pyc
+-rw-r--r-- root root 1403 ./usr/lib/python3.8/encodings/__pycache__/euc_jp.cpython-38.pyc
+-rw-r--r-- root root 1403 ./usr/lib/python3.8/encodings/__pycache__/euc_kr.cpython-38.opt-1.pyc
+-rw-r--r-- root root 1403 ./usr/lib/python3.8/encodings/__pycache__/euc_kr.cpython-38.opt-2.pyc
+-rw-r--r-- root root 1403 ./usr/lib/python3.8/encodings/__pycache__/euc_kr.cpython-38.pyc
+-rw-r--r-- root root 1405 ./usr/lib/python3.8/encodings/__pycache__/gb18030.cpython-38.opt-1.pyc
+-rw-r--r-- root root 1405 ./usr/lib/python3.8/encodings/__pycache__/gb18030.cpython-38.opt-2.pyc
+-rw-r--r-- root root 1405 ./usr/lib/python3.8/encodings/__pycache__/gb18030.cpython-38.pyc
+-rw-r--r-- root root 1403 ./usr/lib/python3.8/encodings/__pycache__/gb2312.cpython-38.opt-1.pyc
+-rw-r--r-- root root 1403 ./usr/lib/python3.8/encodings/__pycache__/gb2312.cpython-38.opt-2.pyc
+-rw-r--r-- root root 1403 ./usr/lib/python3.8/encodings/__pycache__/gb2312.cpython-38.pyc
+-rw-r--r-- root root 1397 ./usr/lib/python3.8/encodings/__pycache__/gbk.cpython-38.opt-1.pyc
+-rw-r--r-- root root 1397 ./usr/lib/python3.8/encodings/__pycache__/gbk.cpython-38.opt-2.pyc
+-rw-r--r-- root root 1397 ./usr/lib/python3.8/encodings/__pycache__/gbk.cpython-38.pyc
+-rw-r--r-- root root 2272 ./usr/lib/python3.8/encodings/__pycache__/hex_codec.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2095 ./usr/lib/python3.8/encodings/__pycache__/hex_codec.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2376 ./usr/lib/python3.8/encodings/__pycache__/hex_codec.cpython-38.pyc
+-rw-r--r-- root root 2613 ./usr/lib/python3.8/encodings/__pycache__/hp_roman8.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2292 ./usr/lib/python3.8/encodings/__pycache__/hp_roman8.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2613 ./usr/lib/python3.8/encodings/__pycache__/hp_roman8.cpython-38.pyc
+-rw-r--r-- root root 1395 ./usr/lib/python3.8/encodings/__pycache__/hz.cpython-38.opt-1.pyc
+-rw-r--r-- root root 1395 ./usr/lib/python3.8/encodings/__pycache__/hz.cpython-38.opt-2.pyc
+-rw-r--r-- root root 1395 ./usr/lib/python3.8/encodings/__pycache__/hz.cpython-38.pyc
+-rw-r--r-- root root 5607 ./usr/lib/python3.8/encodings/__pycache__/idna.cpython-38.opt-1.pyc
+-rw-r--r-- root root 5607 ./usr/lib/python3.8/encodings/__pycache__/idna.cpython-38.opt-2.pyc
+-rw-r--r-- root root 5607 ./usr/lib/python3.8/encodings/__pycache__/idna.cpython-38.pyc
+-rw-r--r-- root root 3893 ./usr/lib/python3.8/encodings/__pycache__/__init__.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2438 ./usr/lib/python3.8/encodings/__pycache__/__init__.cpython-38.opt-2.pyc
+-rw-r--r-- root root 3893 ./usr/lib/python3.8/encodings/__pycache__/__init__.cpython-38.pyc
+-rw-r--r-- root root 1420 ./usr/lib/python3.8/encodings/__pycache__/iso2022_jp_1.cpython-38.opt-1.pyc
+-rw-r--r-- root root 1420 ./usr/lib/python3.8/encodings/__pycache__/iso2022_jp_1.cpython-38.opt-2.pyc
+-rw-r--r-- root root 1420 ./usr/lib/python3.8/encodings/__pycache__/iso2022_jp_1.cpython-38.pyc
+-rw-r--r-- root root 1426 ./usr/lib/python3.8/encodings/__pycache__/iso2022_jp_2004.cpython-38.opt-1.pyc
+-rw-r--r-- root root 1426 ./usr/lib/python3.8/encodings/__pycache__/iso2022_jp_2004.cpython-38.opt-2.pyc
+-rw-r--r-- root root 1426 ./usr/lib/python3.8/encodings/__pycache__/iso2022_jp_2004.cpython-38.pyc
+-rw-r--r-- root root 1420 ./usr/lib/python3.8/encodings/__pycache__/iso2022_jp_2.cpython-38.opt-1.pyc
+-rw-r--r-- root root 1420 ./usr/lib/python3.8/encodings/__pycache__/iso2022_jp_2.cpython-38.opt-2.pyc
+-rw-r--r-- root root 1420 ./usr/lib/python3.8/encodings/__pycache__/iso2022_jp_2.cpython-38.pyc
+-rw-r--r-- root root 1420 ./usr/lib/python3.8/encodings/__pycache__/iso2022_jp_3.cpython-38.opt-1.pyc
+-rw-r--r-- root root 1420 ./usr/lib/python3.8/encodings/__pycache__/iso2022_jp_3.cpython-38.opt-2.pyc
+-rw-r--r-- root root 1420 ./usr/lib/python3.8/encodings/__pycache__/iso2022_jp_3.cpython-38.pyc
+-rw-r--r-- root root 1416 ./usr/lib/python3.8/encodings/__pycache__/iso2022_jp.cpython-38.opt-1.pyc
+-rw-r--r-- root root 1416 ./usr/lib/python3.8/encodings/__pycache__/iso2022_jp.cpython-38.opt-2.pyc
+-rw-r--r-- root root 1416 ./usr/lib/python3.8/encodings/__pycache__/iso2022_jp.cpython-38.pyc
+-rw-r--r-- root root 1424 ./usr/lib/python3.8/encodings/__pycache__/iso2022_jp_ext.cpython-38.opt-1.pyc
+-rw-r--r-- root root 1424 ./usr/lib/python3.8/encodings/__pycache__/iso2022_jp_ext.cpython-38.opt-2.pyc
+-rw-r--r-- root root 1424 ./usr/lib/python3.8/encodings/__pycache__/iso2022_jp_ext.cpython-38.pyc
+-rw-r--r-- root root 1416 ./usr/lib/python3.8/encodings/__pycache__/iso2022_kr.cpython-38.opt-1.pyc
+-rw-r--r-- root root 1416 ./usr/lib/python3.8/encodings/__pycache__/iso2022_kr.cpython-38.opt-2.pyc
+-rw-r--r-- root root 1416 ./usr/lib/python3.8/encodings/__pycache__/iso2022_kr.cpython-38.pyc
+-rw-r--r-- root root 2416 ./usr/lib/python3.8/encodings/__pycache__/iso8859_10.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2291 ./usr/lib/python3.8/encodings/__pycache__/iso8859_10.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2416 ./usr/lib/python3.8/encodings/__pycache__/iso8859_10.cpython-38.pyc
+-rw-r--r-- root root 2510 ./usr/lib/python3.8/encodings/__pycache__/iso8859_11.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2385 ./usr/lib/python3.8/encodings/__pycache__/iso8859_11.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2510 ./usr/lib/python3.8/encodings/__pycache__/iso8859_11.cpython-38.pyc
+-rw-r--r-- root root 2419 ./usr/lib/python3.8/encodings/__pycache__/iso8859_13.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2294 ./usr/lib/python3.8/encodings/__pycache__/iso8859_13.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2419 ./usr/lib/python3.8/encodings/__pycache__/iso8859_13.cpython-38.pyc
+-rw-r--r-- root root 2437 ./usr/lib/python3.8/encodings/__pycache__/iso8859_14.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2312 ./usr/lib/python3.8/encodings/__pycache__/iso8859_14.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2437 ./usr/lib/python3.8/encodings/__pycache__/iso8859_14.cpython-38.pyc
+-rw-r--r-- root root 2416 ./usr/lib/python3.8/encodings/__pycache__/iso8859_15.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2291 ./usr/lib/python3.8/encodings/__pycache__/iso8859_15.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2416 ./usr/lib/python3.8/encodings/__pycache__/iso8859_15.cpython-38.pyc
+-rw-r--r-- root root 2418 ./usr/lib/python3.8/encodings/__pycache__/iso8859_16.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2293 ./usr/lib/python3.8/encodings/__pycache__/iso8859_16.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2418 ./usr/lib/python3.8/encodings/__pycache__/iso8859_16.cpython-38.pyc
+-rw-r--r-- root root 2411 ./usr/lib/python3.8/encodings/__pycache__/iso8859_1.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2288 ./usr/lib/python3.8/encodings/__pycache__/iso8859_1.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2411 ./usr/lib/python3.8/encodings/__pycache__/iso8859_1.cpython-38.pyc
+-rw-r--r-- root root 2411 ./usr/lib/python3.8/encodings/__pycache__/iso8859_2.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2288 ./usr/lib/python3.8/encodings/__pycache__/iso8859_2.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2411 ./usr/lib/python3.8/encodings/__pycache__/iso8859_2.cpython-38.pyc
+-rw-r--r-- root root 2418 ./usr/lib/python3.8/encodings/__pycache__/iso8859_3.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2295 ./usr/lib/python3.8/encodings/__pycache__/iso8859_3.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2418 ./usr/lib/python3.8/encodings/__pycache__/iso8859_3.cpython-38.pyc
+-rw-r--r-- root root 2411 ./usr/lib/python3.8/encodings/__pycache__/iso8859_4.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2288 ./usr/lib/python3.8/encodings/__pycache__/iso8859_4.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2411 ./usr/lib/python3.8/encodings/__pycache__/iso8859_4.cpython-38.pyc
+-rw-r--r-- root root 2412 ./usr/lib/python3.8/encodings/__pycache__/iso8859_5.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2289 ./usr/lib/python3.8/encodings/__pycache__/iso8859_5.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2412 ./usr/lib/python3.8/encodings/__pycache__/iso8859_5.cpython-38.pyc
+-rw-r--r-- root root 2456 ./usr/lib/python3.8/encodings/__pycache__/iso8859_6.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2333 ./usr/lib/python3.8/encodings/__pycache__/iso8859_6.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2456 ./usr/lib/python3.8/encodings/__pycache__/iso8859_6.cpython-38.pyc
+-rw-r--r-- root root 2419 ./usr/lib/python3.8/encodings/__pycache__/iso8859_7.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2296 ./usr/lib/python3.8/encodings/__pycache__/iso8859_7.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2419 ./usr/lib/python3.8/encodings/__pycache__/iso8859_7.cpython-38.pyc
+-rw-r--r-- root root 2450 ./usr/lib/python3.8/encodings/__pycache__/iso8859_8.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2327 ./usr/lib/python3.8/encodings/__pycache__/iso8859_8.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2450 ./usr/lib/python3.8/encodings/__pycache__/iso8859_8.cpython-38.pyc
+-rw-r--r-- root root 2411 ./usr/lib/python3.8/encodings/__pycache__/iso8859_9.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2288 ./usr/lib/python3.8/encodings/__pycache__/iso8859_9.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2411 ./usr/lib/python3.8/encodings/__pycache__/iso8859_9.cpython-38.pyc
+-rw-r--r-- root root 1401 ./usr/lib/python3.8/encodings/__pycache__/johab.cpython-38.opt-1.pyc
+-rw-r--r-- root root 1401 ./usr/lib/python3.8/encodings/__pycache__/johab.cpython-38.opt-2.pyc
+-rw-r--r-- root root 1401 ./usr/lib/python3.8/encodings/__pycache__/johab.cpython-38.pyc
+-rw-r--r-- root root 2463 ./usr/lib/python3.8/encodings/__pycache__/koi8_r.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2338 ./usr/lib/python3.8/encodings/__pycache__/koi8_r.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2463 ./usr/lib/python3.8/encodings/__pycache__/koi8_r.cpython-38.pyc
+-rw-r--r-- root root 2374 ./usr/lib/python3.8/encodings/__pycache__/koi8_t.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2318 ./usr/lib/python3.8/encodings/__pycache__/koi8_t.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2374 ./usr/lib/python3.8/encodings/__pycache__/koi8_t.cpython-38.pyc
+-rw-r--r-- root root 2449 ./usr/lib/python3.8/encodings/__pycache__/koi8_u.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2330 ./usr/lib/python3.8/encodings/__pycache__/koi8_u.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2449 ./usr/lib/python3.8/encodings/__pycache__/koi8_u.cpython-38.pyc
+-rw-r--r-- root root 2426 ./usr/lib/python3.8/encodings/__pycache__/kz1048.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2301 ./usr/lib/python3.8/encodings/__pycache__/kz1048.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2426 ./usr/lib/python3.8/encodings/__pycache__/kz1048.cpython-38.pyc
+-rw-r--r-- root root 1883 ./usr/lib/python3.8/encodings/__pycache__/latin_1.cpython-38.opt-1.pyc
+-rw-r--r-- root root 1735 ./usr/lib/python3.8/encodings/__pycache__/latin_1.cpython-38.opt-2.pyc
+-rw-r--r-- root root 1883 ./usr/lib/python3.8/encodings/__pycache__/latin_1.cpython-38.pyc
+-rw-r--r-- root root 7730 ./usr/lib/python3.8/encodings/__pycache__/mac_arabic.cpython-38.opt-1.pyc
+-rw-r--r-- root root 7618 ./usr/lib/python3.8/encodings/__pycache__/mac_arabic.cpython-38.opt-2.pyc
+-rw-r--r-- root root 7730 ./usr/lib/python3.8/encodings/__pycache__/mac_arabic.cpython-38.pyc
+-rw-r--r-- root root 2450 ./usr/lib/python3.8/encodings/__pycache__/mac_centeuro.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2316 ./usr/lib/python3.8/encodings/__pycache__/mac_centeuro.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2450 ./usr/lib/python3.8/encodings/__pycache__/mac_centeuro.cpython-38.pyc
+-rw-r--r-- root root 2458 ./usr/lib/python3.8/encodings/__pycache__/mac_croatian.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2324 ./usr/lib/python3.8/encodings/__pycache__/mac_croatian.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2458 ./usr/lib/python3.8/encodings/__pycache__/mac_croatian.cpython-38.pyc
+-rw-r--r-- root root 2448 ./usr/lib/python3.8/encodings/__pycache__/mac_cyrillic.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2314 ./usr/lib/python3.8/encodings/__pycache__/mac_cyrillic.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2448 ./usr/lib/python3.8/encodings/__pycache__/mac_cyrillic.cpython-38.pyc
+-rw-r--r-- root root 2392 ./usr/lib/python3.8/encodings/__pycache__/mac_farsi.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2264 ./usr/lib/python3.8/encodings/__pycache__/mac_farsi.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2392 ./usr/lib/python3.8/encodings/__pycache__/mac_farsi.cpython-38.pyc
+-rw-r--r-- root root 2432 ./usr/lib/python3.8/encodings/__pycache__/mac_greek.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2304 ./usr/lib/python3.8/encodings/__pycache__/mac_greek.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2432 ./usr/lib/python3.8/encodings/__pycache__/mac_greek.cpython-38.pyc
+-rw-r--r-- root root 2451 ./usr/lib/python3.8/encodings/__pycache__/mac_iceland.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2319 ./usr/lib/python3.8/encodings/__pycache__/mac_iceland.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2451 ./usr/lib/python3.8/encodings/__pycache__/mac_iceland.cpython-38.pyc
+-rw-r--r-- root root 2592 ./usr/lib/python3.8/encodings/__pycache__/mac_latin2.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2312 ./usr/lib/python3.8/encodings/__pycache__/mac_latin2.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2592 ./usr/lib/python3.8/encodings/__pycache__/mac_latin2.cpython-38.pyc
+-rw-r--r-- root root 2449 ./usr/lib/python3.8/encodings/__pycache__/mac_roman.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2321 ./usr/lib/python3.8/encodings/__pycache__/mac_roman.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2449 ./usr/lib/python3.8/encodings/__pycache__/mac_roman.cpython-38.pyc
+-rw-r--r-- root root 2459 ./usr/lib/python3.8/encodings/__pycache__/mac_romanian.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2325 ./usr/lib/python3.8/encodings/__pycache__/mac_romanian.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2459 ./usr/lib/python3.8/encodings/__pycache__/mac_romanian.cpython-38.pyc
+-rw-r--r-- root root 2452 ./usr/lib/python3.8/encodings/__pycache__/mac_turkish.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2320 ./usr/lib/python3.8/encodings/__pycache__/mac_turkish.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2452 ./usr/lib/python3.8/encodings/__pycache__/mac_turkish.cpython-38.pyc
+-rw-r--r-- root root 1701 ./usr/lib/python3.8/encodings/__pycache__/mbcs.cpython-38.opt-1.pyc
+-rw-r--r-- root root 1468 ./usr/lib/python3.8/encodings/__pycache__/mbcs.cpython-38.opt-2.pyc
+-rw-r--r-- root root 1701 ./usr/lib/python3.8/encodings/__pycache__/mbcs.cpython-38.pyc
+-rw-r--r-- root root 1514 ./usr/lib/python3.8/encodings/__pycache__/oem.cpython-38.opt-1.pyc
+-rw-r--r-- root root 1464 ./usr/lib/python3.8/encodings/__pycache__/oem.cpython-38.opt-2.pyc
+-rw-r--r-- root root 1514 ./usr/lib/python3.8/encodings/__pycache__/oem.cpython-38.pyc
+-rw-r--r-- root root 2439 ./usr/lib/python3.8/encodings/__pycache__/palmos.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2302 ./usr/lib/python3.8/encodings/__pycache__/palmos.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2439 ./usr/lib/python3.8/encodings/__pycache__/palmos.cpython-38.pyc
+-rw-r--r-- root root 2533 ./usr/lib/python3.8/encodings/__pycache__/ptcp154.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2294 ./usr/lib/python3.8/encodings/__pycache__/ptcp154.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2533 ./usr/lib/python3.8/encodings/__pycache__/ptcp154.cpython-38.pyc
+-rw-r--r-- root root 6301 ./usr/lib/python3.8/encodings/__pycache__/punycode.cpython-38.opt-1.pyc
+-rw-r--r-- root root 5709 ./usr/lib/python3.8/encodings/__pycache__/punycode.cpython-38.opt-2.pyc
+-rw-r--r-- root root 6301 ./usr/lib/python3.8/encodings/__pycache__/punycode.cpython-38.pyc
+-rw-r--r-- root root 2348 ./usr/lib/python3.8/encodings/__pycache__/quopri_codec.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2250 ./usr/lib/python3.8/encodings/__pycache__/quopri_codec.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2405 ./usr/lib/python3.8/encodings/__pycache__/quopri_codec.cpython-38.pyc
+-rw-r--r-- root root 1752 ./usr/lib/python3.8/encodings/__pycache__/raw_unicode_escape.cpython-38.opt-1.pyc
+-rw-r--r-- root root 1593 ./usr/lib/python3.8/encodings/__pycache__/raw_unicode_escape.cpython-38.opt-2.pyc
+-rw-r--r-- root root 1752 ./usr/lib/python3.8/encodings/__pycache__/raw_unicode_escape.cpython-38.pyc
+-rw-r--r-- root root 2991 ./usr/lib/python3.8/encodings/__pycache__/rot_13.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2841 ./usr/lib/python3.8/encodings/__pycache__/rot_13.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2991 ./usr/lib/python3.8/encodings/__pycache__/rot_13.cpython-38.pyc
+-rw-r--r-- root root 1419 ./usr/lib/python3.8/encodings/__pycache__/shift_jis_2004.cpython-38.opt-1.pyc
+-rw-r--r-- root root 1419 ./usr/lib/python3.8/encodings/__pycache__/shift_jis_2004.cpython-38.opt-2.pyc
+-rw-r--r-- root root 1419 ./usr/lib/python3.8/encodings/__pycache__/shift_jis_2004.cpython-38.pyc
+-rw-r--r-- root root 1409 ./usr/lib/python3.8/encodings/__pycache__/shift_jis.cpython-38.opt-1.pyc
+-rw-r--r-- root root 1409 ./usr/lib/python3.8/encodings/__pycache__/shift_jis.cpython-38.opt-2.pyc
+-rw-r--r-- root root 1409 ./usr/lib/python3.8/encodings/__pycache__/shift_jis.cpython-38.pyc
+-rw-r--r-- root root 1419 ./usr/lib/python3.8/encodings/__pycache__/shift_jisx0213.cpython-38.opt-1.pyc
+-rw-r--r-- root root 1419 ./usr/lib/python3.8/encodings/__pycache__/shift_jisx0213.cpython-38.opt-2.pyc
+-rw-r--r-- root root 1419 ./usr/lib/python3.8/encodings/__pycache__/shift_jisx0213.cpython-38.pyc
+-rw-r--r-- root root 2501 ./usr/lib/python3.8/encodings/__pycache__/tis_620.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2380 ./usr/lib/python3.8/encodings/__pycache__/tis_620.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2501 ./usr/lib/python3.8/encodings/__pycache__/tis_620.cpython-38.pyc
+-rw-r--r-- root root 2085 ./usr/lib/python3.8/encodings/__pycache__/undefined.cpython-38.opt-1.pyc
+-rw-r--r-- root root 1756 ./usr/lib/python3.8/encodings/__pycache__/undefined.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2085 ./usr/lib/python3.8/encodings/__pycache__/undefined.cpython-38.pyc
+-rw-r--r-- root root 1732 ./usr/lib/python3.8/encodings/__pycache__/unicode_escape.cpython-38.opt-1.pyc
+-rw-r--r-- root root 1577 ./usr/lib/python3.8/encodings/__pycache__/unicode_escape.cpython-38.opt-2.pyc
+-rw-r--r-- root root 1732 ./usr/lib/python3.8/encodings/__pycache__/unicode_escape.cpython-38.pyc
+-rw-r--r-- root root 1640 ./usr/lib/python3.8/encodings/__pycache__/utf_16_be.cpython-38.opt-1.pyc
+-rw-r--r-- root root 1490 ./usr/lib/python3.8/encodings/__pycache__/utf_16_be.cpython-38.opt-2.pyc
+-rw-r--r-- root root 1640 ./usr/lib/python3.8/encodings/__pycache__/utf_16_be.cpython-38.pyc
+-rw-r--r-- root root 4862 ./usr/lib/python3.8/encodings/__pycache__/utf_16.cpython-38.opt-1.pyc
+-rw-r--r-- root root 4715 ./usr/lib/python3.8/encodings/__pycache__/utf_16.cpython-38.opt-2.pyc
+-rw-r--r-- root root 4862 ./usr/lib/python3.8/encodings/__pycache__/utf_16.cpython-38.pyc
+-rw-r--r-- root root 1640 ./usr/lib/python3.8/encodings/__pycache__/utf_16_le.cpython-38.opt-1.pyc
+-rw-r--r-- root root 1490 ./usr/lib/python3.8/encodings/__pycache__/utf_16_le.cpython-38.opt-2.pyc
+-rw-r--r-- root root 1640 ./usr/lib/python3.8/encodings/__pycache__/utf_16_le.cpython-38.pyc
+-rw-r--r-- root root 1533 ./usr/lib/python3.8/encodings/__pycache__/utf_32_be.cpython-38.opt-1.pyc
+-rw-r--r-- root root 1490 ./usr/lib/python3.8/encodings/__pycache__/utf_32_be.cpython-38.opt-2.pyc
+-rw-r--r-- root root 1533 ./usr/lib/python3.8/encodings/__pycache__/utf_32_be.cpython-38.pyc
+-rw-r--r-- root root 4755 ./usr/lib/python3.8/encodings/__pycache__/utf_32.cpython-38.opt-1.pyc
+-rw-r--r-- root root 4715 ./usr/lib/python3.8/encodings/__pycache__/utf_32.cpython-38.opt-2.pyc
+-rw-r--r-- root root 4755 ./usr/lib/python3.8/encodings/__pycache__/utf_32.cpython-38.pyc
+-rw-r--r-- root root 1533 ./usr/lib/python3.8/encodings/__pycache__/utf_32_le.cpython-38.opt-1.pyc
+-rw-r--r-- root root 1490 ./usr/lib/python3.8/encodings/__pycache__/utf_32_le.cpython-38.opt-2.pyc
+-rw-r--r-- root root 1533 ./usr/lib/python3.8/encodings/__pycache__/utf_32_le.cpython-38.pyc
+-rw-r--r-- root root 1561 ./usr/lib/python3.8/encodings/__pycache__/utf_7.cpython-38.opt-1.pyc
+-rw-r--r-- root root 1474 ./usr/lib/python3.8/encodings/__pycache__/utf_7.cpython-38.opt-2.pyc
+-rw-r--r-- root root 1561 ./usr/lib/python3.8/encodings/__pycache__/utf_7.cpython-38.pyc
+-rw-r--r-- root root 1620 ./usr/lib/python3.8/encodings/__pycache__/utf_8.cpython-38.opt-1.pyc
+-rw-r--r-- root root 1474 ./usr/lib/python3.8/encodings/__pycache__/utf_8.cpython-38.opt-2.pyc
+-rw-r--r-- root root 1620 ./usr/lib/python3.8/encodings/__pycache__/utf_8.cpython-38.pyc
+-rw-r--r-- root root 4536 ./usr/lib/python3.8/encodings/__pycache__/utf_8_sig.cpython-38.opt-1.pyc
+-rw-r--r-- root root 4234 ./usr/lib/python3.8/encodings/__pycache__/utf_8_sig.cpython-38.opt-2.pyc
+-rw-r--r-- root root 4536 ./usr/lib/python3.8/encodings/__pycache__/utf_8_sig.cpython-38.pyc
+-rw-r--r-- root root 3180 ./usr/lib/python3.8/encodings/__pycache__/uu_codec.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2887 ./usr/lib/python3.8/encodings/__pycache__/uu_codec.cpython-38.opt-2.pyc
+-rw-r--r-- root root 3239 ./usr/lib/python3.8/encodings/__pycache__/uu_codec.cpython-38.pyc
+-rw-r--r-- root root 3009 ./usr/lib/python3.8/encodings/__pycache__/zlib_codec.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2843 ./usr/lib/python3.8/encodings/__pycache__/zlib_codec.cpython-38.opt-2.pyc
+-rw-r--r-- root root 3099 ./usr/lib/python3.8/encodings/__pycache__/zlib_codec.cpython-38.pyc
+-rw-r--r-- root root 1525 ./usr/lib/python3.8/encodings/quopri_codec.py
+-rw-r--r-- root root 1208 ./usr/lib/python3.8/encodings/raw_unicode_escape.py
+-rwxr-xr-x root root 2448 ./usr/lib/python3.8/encodings/rot_13.py
+-rw-r--r-- root root 1059 ./usr/lib/python3.8/encodings/shift_jis_2004.py
+-rw-r--r-- root root 1039 ./usr/lib/python3.8/encodings/shift_jis.py
+-rw-r--r-- root root 1059 ./usr/lib/python3.8/encodings/shift_jisx0213.py
+-rw-r--r-- root root 12300 ./usr/lib/python3.8/encodings/tis_620.py
+-rw-r--r-- root root 1299 ./usr/lib/python3.8/encodings/undefined.py
+-rw-r--r-- root root 1184 ./usr/lib/python3.8/encodings/unicode_escape.py
+-rw-r--r-- root root 1037 ./usr/lib/python3.8/encodings/utf_16_be.py
+-rw-r--r-- root root 1037 ./usr/lib/python3.8/encodings/utf_16_le.py
+-rw-r--r-- root root 5236 ./usr/lib/python3.8/encodings/utf_16.py
+-rw-r--r-- root root 930 ./usr/lib/python3.8/encodings/utf_32_be.py
+-rw-r--r-- root root 930 ./usr/lib/python3.8/encodings/utf_32_le.py
+-rw-r--r-- root root 5129 ./usr/lib/python3.8/encodings/utf_32.py
+-rw-r--r-- root root 946 ./usr/lib/python3.8/encodings/utf_7.py
+-rw-r--r-- root root 1005 ./usr/lib/python3.8/encodings/utf_8.py
+-rw-r--r-- root root 4133 ./usr/lib/python3.8/encodings/utf_8_sig.py
+-rw-r--r-- root root 2851 ./usr/lib/python3.8/encodings/uu_codec.py
+-rw-r--r-- root root 2204 ./usr/lib/python3.8/encodings/zlib_codec.py
+-rw-r--r-- root root 34616 ./usr/lib/python3.8/enum.py
+-rw-r--r-- root root 4056 ./usr/lib/python3.8/fnmatch.py
+-rw-r--r-- root root 34768 ./usr/lib/python3.8/ftplib.py
+-rw-r--r-- root root 37376 ./usr/lib/python3.8/functools.py
+-rw-r--r-- root root 5101 ./usr/lib/python3.8/__future__.py
+-rw-r--r-- root root 4975 ./usr/lib/python3.8/genericpath.py
+-rw-r--r-- root root 7489 ./usr/lib/python3.8/getopt.py
+-rw-r--r-- root root 27138 ./usr/lib/python3.8/gettext.py
+-rw-r--r-- root root 5697 ./usr/lib/python3.8/glob.py
+-rw-r--r-- root root 21441 ./usr/lib/python3.8/gzip.py
+-rw-r--r-- root root 9730 ./usr/lib/python3.8/hashlib.py
+-rw-r--r-- root root 22877 ./usr/lib/python3.8/heapq.py
+-rw-r--r-- root root 6629 ./usr/lib/python3.8/hmac.py
+drwxr-xr-x root root 4096 ./usr/lib/python3.8/http
+-rw-r--r-- root root 54496 ./usr/lib/python3.8/http/client.py
+-rw-r--r-- root root 76835 ./usr/lib/python3.8/http/cookiejar.py
+-rw-r--r-- root root 20412 ./usr/lib/python3.8/http/cookies.py
+-rw-r--r-- root root 6378 ./usr/lib/python3.8/http/__init__.py
+drwxr-xr-x root root 4096 ./usr/lib/python3.8/http/__pycache__
+-rw-r--r-- root root 33915 ./usr/lib/python3.8/http/__pycache__/client.cpython-38.opt-1.pyc
+-rw-r--r-- root root 25008 ./usr/lib/python3.8/http/__pycache__/client.cpython-38.opt-2.pyc
+-rw-r--r-- root root 34014 ./usr/lib/python3.8/http/__pycache__/client.cpython-38.pyc
+-rw-r--r-- root root 53437 ./usr/lib/python3.8/http/__pycache__/cookiejar.cpython-38.opt-1.pyc
+-rw-r--r-- root root 37800 ./usr/lib/python3.8/http/__pycache__/cookiejar.cpython-38.opt-2.pyc
+-rw-r--r-- root root 53637 ./usr/lib/python3.8/http/__pycache__/cookiejar.cpython-38.pyc
+-rw-r--r-- root root 15215 ./usr/lib/python3.8/http/__pycache__/cookies.cpython-38.opt-1.pyc
+-rw-r--r-- root root 10818 ./usr/lib/python3.8/http/__pycache__/cookies.cpython-38.opt-2.pyc
+-rw-r--r-- root root 15263 ./usr/lib/python3.8/http/__pycache__/cookies.cpython-38.pyc
+-rw-r--r-- root root 6059 ./usr/lib/python3.8/http/__pycache__/__init__.cpython-38.opt-1.pyc
+-rw-r--r-- root root 5378 ./usr/lib/python3.8/http/__pycache__/__init__.cpython-38.opt-2.pyc
+-rw-r--r-- root root 6059 ./usr/lib/python3.8/http/__pycache__/__init__.cpython-38.pyc
+-rw-r--r-- root root 34387 ./usr/lib/python3.8/http/__pycache__/server.cpython-38.opt-1.pyc
+-rw-r--r-- root root 22451 ./usr/lib/python3.8/http/__pycache__/server.cpython-38.opt-2.pyc
+-rw-r--r-- root root 34387 ./usr/lib/python3.8/http/__pycache__/server.cpython-38.pyc
+-rw-r--r-- root root 47254 ./usr/lib/python3.8/http/server.py
+-rw-r--r-- root root 53606 ./usr/lib/python3.8/imaplib.py
+drwxr-xr-x root root 4096 ./usr/lib/python3.8/importlib
+-rw-r--r-- root root 12873 ./usr/lib/python3.8/importlib/abc.py
+-rw-r--r-- root root 62357 ./usr/lib/python3.8/importlib/_bootstrap_external.py
+-rw-r--r-- root root 39644 ./usr/lib/python3.8/importlib/_bootstrap.py
+-rw-r--r-- root root 6061 ./usr/lib/python3.8/importlib/__init__.py
+-rw-r--r-- root root 844 ./usr/lib/python3.8/importlib/machinery.py
+-rw-r--r-- root root 17607 ./usr/lib/python3.8/importlib/metadata.py
+drwxr-xr-x root root 4096 ./usr/lib/python3.8/importlib/__pycache__
+-rw-r--r-- root root 13563 ./usr/lib/python3.8/importlib/__pycache__/abc.cpython-38.opt-1.pyc
+-rw-r--r-- root root 6752 ./usr/lib/python3.8/importlib/__pycache__/abc.cpython-38.opt-2.pyc
+-rw-r--r-- root root 13563 ./usr/lib/python3.8/importlib/__pycache__/abc.cpython-38.pyc
+-rw-r--r-- root root 28563 ./usr/lib/python3.8/importlib/__pycache__/_bootstrap.cpython-38.opt-1.pyc
+-rw-r--r-- root root 21804 ./usr/lib/python3.8/importlib/__pycache__/_bootstrap.cpython-38.opt-2.pyc
+-rw-r--r-- root root 28595 ./usr/lib/python3.8/importlib/__pycache__/_bootstrap.cpython-38.pyc
+-rw-r--r-- root root 43396 ./usr/lib/python3.8/importlib/__pycache__/_bootstrap_external.cpython-38.opt-1.pyc
+-rw-r--r-- root root 32275 ./usr/lib/python3.8/importlib/__pycache__/_bootstrap_external.cpython-38.opt-2.pyc
+-rw-r--r-- root root 43700 ./usr/lib/python3.8/importlib/__pycache__/_bootstrap_external.cpython-38.pyc
+-rw-r--r-- root root 3748 ./usr/lib/python3.8/importlib/__pycache__/__init__.cpython-38.opt-1.pyc
+-rw-r--r-- root root 3069 ./usr/lib/python3.8/importlib/__pycache__/__init__.cpython-38.opt-2.pyc
+-rw-r--r-- root root 3748 ./usr/lib/python3.8/importlib/__pycache__/__init__.cpython-38.pyc
+-rw-r--r-- root root 952 ./usr/lib/python3.8/importlib/__pycache__/machinery.cpython-38.opt-1.pyc
+-rw-r--r-- root root 812 ./usr/lib/python3.8/importlib/__pycache__/machinery.cpython-38.opt-2.pyc
+-rw-r--r-- root root 952 ./usr/lib/python3.8/importlib/__pycache__/machinery.cpython-38.pyc
+-rw-r--r-- root root 20830 ./usr/lib/python3.8/importlib/__pycache__/metadata.cpython-38.opt-1.pyc
+-rw-r--r-- root root 15063 ./usr/lib/python3.8/importlib/__pycache__/metadata.cpython-38.opt-2.pyc
+-rw-r--r-- root root 20830 ./usr/lib/python3.8/importlib/__pycache__/metadata.cpython-38.pyc
+-rw-r--r-- root root 6470 ./usr/lib/python3.8/importlib/__pycache__/resources.cpython-38.opt-1.pyc
+-rw-r--r-- root root 5125 ./usr/lib/python3.8/importlib/__pycache__/resources.cpython-38.opt-2.pyc
+-rw-r--r-- root root 6470 ./usr/lib/python3.8/importlib/__pycache__/resources.cpython-38.pyc
+-rw-r--r-- root root 9282 ./usr/lib/python3.8/importlib/__pycache__/util.cpython-38.opt-1.pyc
+-rw-r--r-- root root 6413 ./usr/lib/python3.8/importlib/__pycache__/util.cpython-38.opt-2.pyc
+-rw-r--r-- root root 9282 ./usr/lib/python3.8/importlib/__pycache__/util.cpython-38.pyc
+-rw-r--r-- root root 9437 ./usr/lib/python3.8/importlib/resources.py
+-rw-r--r-- root root 11319 ./usr/lib/python3.8/importlib/util.py
+-rw-r--r-- root root 10536 ./usr/lib/python3.8/imp.py
+-rw-r--r-- root root 118039 ./usr/lib/python3.8/inspect.py
+-rw-r--r-- root root 3541 ./usr/lib/python3.8/io.py
+-rw-r--r-- root root 71160 ./usr/lib/python3.8/ipaddress.py
+-rw-r--r-- root root 945 ./usr/lib/python3.8/keyword.py
+drwxr-xr-x root root 4096 ./usr/lib/python3.8/lib-dynload
+-rwxr-xr-x root root 65816 ./usr/lib/python3.8/lib-dynload/array.cpython-38-x86_64-linux-gnu.so
+-rwxr-xr-x root root 31736 ./usr/lib/python3.8/lib-dynload/binascii.cpython-38-x86_64-linux-gnu.so
+-rwxr-xr-x root root 14760 ./usr/lib/python3.8/lib-dynload/_bisect.cpython-38-x86_64-linux-gnu.so
+-rwxr-xr-x root root 44664 ./usr/lib/python3.8/lib-dynload/_blake2.cpython-38-x86_64-linux-gnu.so
+-rwxr-xr-x root root 27896 ./usr/lib/python3.8/lib-dynload/_bz2.cpython-38-x86_64-linux-gnu.so
+-rwxr-xr-x root root 43896 ./usr/lib/python3.8/lib-dynload/cmath.cpython-38-x86_64-linux-gnu.so
+-rwxr-xr-x root root 14384 ./usr/lib/python3.8/lib-dynload/_crypt.cpython-38-x86_64-linux-gnu.so
+-rwxr-xr-x root root 37240 ./usr/lib/python3.8/lib-dynload/_csv.cpython-38-x86_64-linux-gnu.so
+-rwxr-xr-x root root 99712 ./usr/lib/python3.8/lib-dynload/_datetime.cpython-38-x86_64-linux-gnu.so
+-rwxr-xr-x root root 76160 ./usr/lib/python3.8/lib-dynload/_elementtree.cpython-38-x86_64-linux-gnu.so
+-rwxr-xr-x root root 18856 ./usr/lib/python3.8/lib-dynload/grp.cpython-38-x86_64-linux-gnu.so
+-rwxr-xr-x root root 36600 ./usr/lib/python3.8/lib-dynload/_hashlib.cpython-38-x86_64-linux-gnu.so
+-rwxr-xr-x root root 22640 ./usr/lib/python3.8/lib-dynload/_heapq.cpython-38-x86_64-linux-gnu.so
+-rwxr-xr-x root root 40920 ./usr/lib/python3.8/lib-dynload/_lzma.cpython-38-x86_64-linux-gnu.so
+-rwxr-xr-x root root 57208 ./usr/lib/python3.8/lib-dynload/math.cpython-38-x86_64-linux-gnu.so
+-rwxr-xr-x root root 19352 ./usr/lib/python3.8/lib-dynload/_md5.cpython-38-x86_64-linux-gnu.so
+-rwxr-xr-x root root 14520 ./usr/lib/python3.8/lib-dynload/_opcode.cpython-38-x86_64-linux-gnu.so
+-rwxr-xr-x root root 27856 ./usr/lib/python3.8/lib-dynload/parser.cpython-38-x86_64-linux-gnu.so
+-rwxr-xr-x root root 113208 ./usr/lib/python3.8/lib-dynload/_pickle.cpython-38-x86_64-linux-gnu.so
+-rwxr-xr-x root root 22680 ./usr/lib/python3.8/lib-dynload/_posixsubprocess.cpython-38-x86_64-linux-gnu.so
+-rwxr-xr-x root root 233072 ./usr/lib/python3.8/lib-dynload/pyexpat.cpython-38-x86_64-linux-gnu.so
+-rwxr-xr-x root root 19320 ./usr/lib/python3.8/lib-dynload/_queue.cpython-38-x86_64-linux-gnu.so
+-rwxr-xr-x root root 19024 ./usr/lib/python3.8/lib-dynload/_random.cpython-38-x86_64-linux-gnu.so
+-rwxr-xr-x root root 35672 ./usr/lib/python3.8/lib-dynload/readline.cpython-38-x86_64-linux-gnu.so
+-rwxr-xr-x root root 32632 ./usr/lib/python3.8/lib-dynload/select.cpython-38-x86_64-linux-gnu.so
+-rwxr-xr-x root root 15256 ./usr/lib/python3.8/lib-dynload/_sha1.cpython-38-x86_64-linux-gnu.so
+-rwxr-xr-x root root 24024 ./usr/lib/python3.8/lib-dynload/_sha256.cpython-38-x86_64-linux-gnu.so
+-rwxr-xr-x root root 82960 ./usr/lib/python3.8/lib-dynload/_sha3.cpython-38-x86_64-linux-gnu.so
+-rwxr-xr-x root root 28120 ./usr/lib/python3.8/lib-dynload/_sha512.cpython-38-x86_64-linux-gnu.so
+-rwxr-xr-x root root 99056 ./usr/lib/python3.8/lib-dynload/_socket.cpython-38-x86_64-linux-gnu.so
+-rwxr-xr-x root root 140280 ./usr/lib/python3.8/lib-dynload/_ssl.cpython-38-x86_64-linux-gnu.so
+-rwxr-xr-x root root 50392 ./usr/lib/python3.8/lib-dynload/_struct.cpython-38-x86_64-linux-gnu.so
+-rwxr-xr-x root root 30576 ./usr/lib/python3.8/lib-dynload/termios.cpython-38-x86_64-linux-gnu.so
+-rwxr-xr-x root root 1091200 ./usr/lib/python3.8/lib-dynload/unicodedata.cpython-38-x86_64-linux-gnu.so
+-rwxr-xr-x root root 14384 ./usr/lib/python3.8/lib-dynload/_uuid.cpython-38-x86_64-linux-gnu.so
+-rwxr-xr-x root root 40888 ./usr/lib/python3.8/lib-dynload/zlib.cpython-38-x86_64-linux-gnu.so
+-rw-r--r-- root root 5312 ./usr/lib/python3.8/linecache.py
+-rw-r--r-- root root 78191 ./usr/lib/python3.8/locale.py
+drwxr-xr-x root root 4096 ./usr/lib/python3.8/logging
+-rw-r--r-- root root 36357 ./usr/lib/python3.8/logging/config.py
+-rw-r--r-- root root 57885 ./usr/lib/python3.8/logging/handlers.py
+-rw-r--r-- root root 77642 ./usr/lib/python3.8/logging/__init__.py
+drwxr-xr-x root root 4096 ./usr/lib/python3.8/logging/__pycache__
+-rw-r--r-- root root 23170 ./usr/lib/python3.8/logging/__pycache__/config.cpython-38.opt-1.pyc
+-rw-r--r-- root root 19060 ./usr/lib/python3.8/logging/__pycache__/config.cpython-38.opt-2.pyc
+-rw-r--r-- root root 23216 ./usr/lib/python3.8/logging/__pycache__/config.cpython-38.pyc
+-rw-r--r-- root root 43148 ./usr/lib/python3.8/logging/__pycache__/handlers.cpython-38.opt-1.pyc
+-rw-r--r-- root root 24441 ./usr/lib/python3.8/logging/__pycache__/handlers.cpython-38.opt-2.pyc
+-rw-r--r-- root root 43148 ./usr/lib/python3.8/logging/__pycache__/handlers.cpython-38.pyc
+-rw-r--r-- root root 64831 ./usr/lib/python3.8/logging/__pycache__/__init__.cpython-38.opt-1.pyc
+-rw-r--r-- root root 36333 ./usr/lib/python3.8/logging/__pycache__/__init__.cpython-38.opt-2.pyc
+-rw-r--r-- root root 64863 ./usr/lib/python3.8/logging/__pycache__/__init__.cpython-38.pyc
+-rw-r--r-- root root 12983 ./usr/lib/python3.8/lzma.py
+-rw-r--r-- root root 14598 ./usr/lib/python3.8/_markupbase.py
+-rw-r--r-- root root 21604 ./usr/lib/python3.8/mimetypes.py
+-rw-r--r-- root root 43261 ./usr/lib/python3.8/nntplib.py
+-rw-r--r-- root root 27734 ./usr/lib/python3.8/ntpath.py
+-rw-r--r-- root root 5808 ./usr/lib/python3.8/opcode.py
+-rw-r--r-- root root 10711 ./usr/lib/python3.8/operator.py
+-rw-r--r-- root root 60369 ./usr/lib/python3.8/optparse.py
+-rw-r--r-- root root 38995 ./usr/lib/python3.8/os.py
+-rw-r--r-- root root 51531 ./usr/lib/python3.8/pathlib.py
+-rw-r--r-- root root 64395 ./usr/lib/python3.8/pickle.py
+-rw-r--r-- root root 93486 ./usr/lib/python3.8/pickletools.py
+-rw-r--r-- root root 8916 ./usr/lib/python3.8/pipes.py
+-rw-r--r-- root root 21461 ./usr/lib/python3.8/pkgutil.py
+-rwxr-xr-x root root 40306 ./usr/lib/python3.8/platform.py
+-rw-r--r-- root root 15077 ./usr/lib/python3.8/poplib.py
+-rw-r--r-- root root 15627 ./usr/lib/python3.8/posixpath.py
+drwxr-xr-x root root 20480 ./usr/lib/python3.8/__pycache__
+-rw-r--r-- root root 5334 ./usr/lib/python3.8/__pycache__/abc.cpython-38.opt-1.pyc
+-rw-r--r-- root root 3212 ./usr/lib/python3.8/__pycache__/abc.cpython-38.opt-2.pyc
+-rw-r--r-- root root 5334 ./usr/lib/python3.8/__pycache__/abc.cpython-38.pyc
+-rw-r--r-- root root 62128 ./usr/lib/python3.8/__pycache__/argparse.cpython-38.opt-1.pyc
+-rw-r--r-- root root 52887 ./usr/lib/python3.8/__pycache__/argparse.cpython-38.opt-2.pyc
+-rw-r--r-- root root 62277 ./usr/lib/python3.8/__pycache__/argparse.cpython-38.pyc
+-rw-r--r-- root root 16301 ./usr/lib/python3.8/__pycache__/ast.cpython-38.opt-1.pyc
+-rw-r--r-- root root 9889 ./usr/lib/python3.8/__pycache__/ast.cpython-38.opt-2.pyc
+-rw-r--r-- root root 16336 ./usr/lib/python3.8/__pycache__/ast.cpython-38.pyc
+-rw-r--r-- root root 16908 ./usr/lib/python3.8/__pycache__/base64.cpython-38.opt-1.pyc
+-rw-r--r-- root root 11324 ./usr/lib/python3.8/__pycache__/base64.cpython-38.opt-2.pyc
+-rw-r--r-- root root 17071 ./usr/lib/python3.8/__pycache__/base64.cpython-38.pyc
+-rw-r--r-- root root 2354 ./usr/lib/python3.8/__pycache__/bisect.cpython-38.opt-1.pyc
+-rw-r--r-- root root 1042 ./usr/lib/python3.8/__pycache__/bisect.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2354 ./usr/lib/python3.8/__pycache__/bisect.cpython-38.pyc
+-rw-r--r-- root root 1217 ./usr/lib/python3.8/__pycache__/_bootlocale.cpython-38.opt-1.pyc
+-rw-r--r-- root root 992 ./usr/lib/python3.8/__pycache__/_bootlocale.cpython-38.opt-2.pyc
+-rw-r--r-- root root 1243 ./usr/lib/python3.8/__pycache__/_bootlocale.cpython-38.pyc
+-rw-r--r-- root root 11445 ./usr/lib/python3.8/__pycache__/bz2.cpython-38.opt-1.pyc
+-rw-r--r-- root root 6387 ./usr/lib/python3.8/__pycache__/bz2.cpython-38.opt-2.pyc
+-rw-r--r-- root root 11445 ./usr/lib/python3.8/__pycache__/bz2.cpython-38.pyc
+-rw-r--r-- root root 27064 ./usr/lib/python3.8/__pycache__/calendar.cpython-38.opt-1.pyc
+-rw-r--r-- root root 22472 ./usr/lib/python3.8/__pycache__/calendar.cpython-38.opt-2.pyc
+-rw-r--r-- root root 27064 ./usr/lib/python3.8/__pycache__/calendar.cpython-38.pyc
+-rw-r--r-- root root 12626 ./usr/lib/python3.8/__pycache__/cmd.cpython-38.opt-1.pyc
+-rw-r--r-- root root 7201 ./usr/lib/python3.8/__pycache__/cmd.cpython-38.opt-2.pyc
+-rw-r--r-- root root 12626 ./usr/lib/python3.8/__pycache__/cmd.cpython-38.pyc
+-rw-r--r-- root root 9913 ./usr/lib/python3.8/__pycache__/code.cpython-38.opt-1.pyc
+-rw-r--r-- root root 4642 ./usr/lib/python3.8/__pycache__/code.cpython-38.opt-2.pyc
+-rw-r--r-- root root 9913 ./usr/lib/python3.8/__pycache__/code.cpython-38.pyc
+-rw-r--r-- root root 33913 ./usr/lib/python3.8/__pycache__/codecs.cpython-38.opt-1.pyc
+-rw-r--r-- root root 18347 ./usr/lib/python3.8/__pycache__/codecs.cpython-38.opt-2.pyc
+-rw-r--r-- root root 33913 ./usr/lib/python3.8/__pycache__/codecs.cpython-38.pyc
+-rw-r--r-- root root 6297 ./usr/lib/python3.8/__pycache__/codeop.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2259 ./usr/lib/python3.8/__pycache__/codeop.cpython-38.opt-2.pyc
+-rw-r--r-- root root 6297 ./usr/lib/python3.8/__pycache__/codeop.cpython-38.pyc
+-rw-r--r-- root root 28741 ./usr/lib/python3.8/__pycache__/_collections_abc.cpython-38.opt-1.pyc
+-rw-r--r-- root root 23682 ./usr/lib/python3.8/__pycache__/_collections_abc.cpython-38.opt-2.pyc
+-rw-r--r-- root root 28741 ./usr/lib/python3.8/__pycache__/_collections_abc.cpython-38.pyc
+-rw-r--r-- root root 5443 ./usr/lib/python3.8/__pycache__/_compat_pickle.cpython-38.opt-1.pyc
+-rw-r--r-- root root 5443 ./usr/lib/python3.8/__pycache__/_compat_pickle.cpython-38.opt-2.pyc
+-rw-r--r-- root root 5501 ./usr/lib/python3.8/__pycache__/_compat_pickle.cpython-38.pyc
+-rw-r--r-- root root 4146 ./usr/lib/python3.8/__pycache__/_compression.cpython-38.opt-1.pyc
+-rw-r--r-- root root 3932 ./usr/lib/python3.8/__pycache__/_compression.cpython-38.opt-2.pyc
+-rw-r--r-- root root 4146 ./usr/lib/python3.8/__pycache__/_compression.cpython-38.pyc
+-rw-r--r-- root root 45718 ./usr/lib/python3.8/__pycache__/configparser.cpython-38.opt-1.pyc
+-rw-r--r-- root root 30792 ./usr/lib/python3.8/__pycache__/configparser.cpython-38.opt-2.pyc
+-rw-r--r-- root root 45718 ./usr/lib/python3.8/__pycache__/configparser.cpython-38.pyc
+-rw-r--r-- root root 20176 ./usr/lib/python3.8/__pycache__/contextlib.cpython-38.opt-1.pyc
+-rw-r--r-- root root 14596 ./usr/lib/python3.8/__pycache__/contextlib.cpython-38.opt-2.pyc
+-rw-r--r-- root root 20229 ./usr/lib/python3.8/__pycache__/contextlib.cpython-38.pyc
+-rw-r--r-- root root 6987 ./usr/lib/python3.8/__pycache__/copy.cpython-38.opt-1.pyc
+-rw-r--r-- root root 4673 ./usr/lib/python3.8/__pycache__/copy.cpython-38.opt-2.pyc
+-rw-r--r-- root root 6987 ./usr/lib/python3.8/__pycache__/copy.cpython-38.pyc
+-rw-r--r-- root root 4283 ./usr/lib/python3.8/__pycache__/copyreg.cpython-38.opt-1.pyc
+-rw-r--r-- root root 3481 ./usr/lib/python3.8/__pycache__/copyreg.cpython-38.opt-2.pyc
+-rw-r--r-- root root 4318 ./usr/lib/python3.8/__pycache__/copyreg.cpython-38.pyc
+-rw-r--r-- root root 3387 ./usr/lib/python3.8/__pycache__/crypt.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2725 ./usr/lib/python3.8/__pycache__/crypt.cpython-38.opt-2.pyc
+-rw-r--r-- root root 3387 ./usr/lib/python3.8/__pycache__/crypt.cpython-38.pyc
+-rw-r--r-- root root 11910 ./usr/lib/python3.8/__pycache__/csv.cpython-38.opt-1.pyc
+-rw-r--r-- root root 9871 ./usr/lib/python3.8/__pycache__/csv.cpython-38.opt-2.pyc
+-rw-r--r-- root root 11910 ./usr/lib/python3.8/__pycache__/csv.cpython-38.pyc
+-rw-r--r-- root root 55741 ./usr/lib/python3.8/__pycache__/datetime.cpython-38.opt-1.pyc
+-rw-r--r-- root root 47501 ./usr/lib/python3.8/__pycache__/datetime.cpython-38.opt-2.pyc
+-rw-r--r-- root root 56978 ./usr/lib/python3.8/__pycache__/datetime.cpython-38.pyc
+-rw-r--r-- root root 15802 ./usr/lib/python3.8/__pycache__/dis.cpython-38.opt-1.pyc
+-rw-r--r-- root root 11995 ./usr/lib/python3.8/__pycache__/dis.cpython-38.opt-2.pyc
+-rw-r--r-- root root 15802 ./usr/lib/python3.8/__pycache__/dis.cpython-38.pyc
+-rw-r--r-- root root 6037 ./usr/lib/python3.8/__pycache__/_dummy_thread.cpython-38.opt-1.pyc
+-rw-r--r-- root root 3392 ./usr/lib/python3.8/__pycache__/_dummy_thread.cpython-38.opt-2.pyc
+-rw-r--r-- root root 6037 ./usr/lib/python3.8/__pycache__/_dummy_thread.cpython-38.pyc
+-rw-r--r-- root root 24399 ./usr/lib/python3.8/__pycache__/enum.cpython-38.opt-1.pyc
+-rw-r--r-- root root 20110 ./usr/lib/python3.8/__pycache__/enum.cpython-38.opt-2.pyc
+-rw-r--r-- root root 24399 ./usr/lib/python3.8/__pycache__/enum.cpython-38.pyc
+-rw-r--r-- root root 3332 ./usr/lib/python3.8/__pycache__/fnmatch.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2147 ./usr/lib/python3.8/__pycache__/fnmatch.cpython-38.opt-2.pyc
+-rw-r--r-- root root 3332 ./usr/lib/python3.8/__pycache__/fnmatch.cpython-38.pyc
+-rw-r--r-- root root 27849 ./usr/lib/python3.8/__pycache__/ftplib.cpython-38.opt-1.pyc
+-rw-r--r-- root root 18116 ./usr/lib/python3.8/__pycache__/ftplib.cpython-38.opt-2.pyc
+-rw-r--r-- root root 27849 ./usr/lib/python3.8/__pycache__/ftplib.cpython-38.pyc
+-rw-r--r-- root root 27897 ./usr/lib/python3.8/__pycache__/functools.cpython-38.opt-1.pyc
+-rw-r--r-- root root 21244 ./usr/lib/python3.8/__pycache__/functools.cpython-38.opt-2.pyc
+-rw-r--r-- root root 27897 ./usr/lib/python3.8/__pycache__/functools.cpython-38.pyc
+-rw-r--r-- root root 4131 ./usr/lib/python3.8/__pycache__/__future__.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2159 ./usr/lib/python3.8/__pycache__/__future__.cpython-38.opt-2.pyc
+-rw-r--r-- root root 4131 ./usr/lib/python3.8/__pycache__/__future__.cpython-38.pyc
+-rw-r--r-- root root 4001 ./usr/lib/python3.8/__pycache__/genericpath.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2865 ./usr/lib/python3.8/__pycache__/genericpath.cpython-38.opt-2.pyc
+-rw-r--r-- root root 4001 ./usr/lib/python3.8/__pycache__/genericpath.cpython-38.pyc
+-rw-r--r-- root root 6237 ./usr/lib/python3.8/__pycache__/getopt.cpython-38.opt-1.pyc
+-rw-r--r-- root root 3683 ./usr/lib/python3.8/__pycache__/getopt.cpython-38.opt-2.pyc
+-rw-r--r-- root root 6271 ./usr/lib/python3.8/__pycache__/getopt.cpython-38.pyc
+-rw-r--r-- root root 17883 ./usr/lib/python3.8/__pycache__/gettext.cpython-38.opt-1.pyc
+-rw-r--r-- root root 17192 ./usr/lib/python3.8/__pycache__/gettext.cpython-38.opt-2.pyc
+-rw-r--r-- root root 17883 ./usr/lib/python3.8/__pycache__/gettext.cpython-38.pyc
+-rw-r--r-- root root 4278 ./usr/lib/python3.8/__pycache__/glob.cpython-38.opt-1.pyc
+-rw-r--r-- root root 3418 ./usr/lib/python3.8/__pycache__/glob.cpython-38.opt-2.pyc
+-rw-r--r-- root root 4343 ./usr/lib/python3.8/__pycache__/glob.cpython-38.pyc
+-rw-r--r-- root root 18191 ./usr/lib/python3.8/__pycache__/gzip.cpython-38.opt-1.pyc
+-rw-r--r-- root root 14323 ./usr/lib/python3.8/__pycache__/gzip.cpython-38.opt-2.pyc
+-rw-r--r-- root root 18191 ./usr/lib/python3.8/__pycache__/gzip.cpython-38.pyc
+-rw-r--r-- root root 6727 ./usr/lib/python3.8/__pycache__/hashlib.cpython-38.opt-1.pyc
+-rw-r--r-- root root 6159 ./usr/lib/python3.8/__pycache__/hashlib.cpython-38.opt-2.pyc
+-rw-r--r-- root root 6727 ./usr/lib/python3.8/__pycache__/hashlib.cpython-38.pyc
+-rw-r--r-- root root 14070 ./usr/lib/python3.8/__pycache__/heapq.cpython-38.opt-1.pyc
+-rw-r--r-- root root 11054 ./usr/lib/python3.8/__pycache__/heapq.cpython-38.opt-2.pyc
+-rw-r--r-- root root 14070 ./usr/lib/python3.8/__pycache__/heapq.cpython-38.pyc
+-rw-r--r-- root root 6388 ./usr/lib/python3.8/__pycache__/hmac.cpython-38.opt-1.pyc
+-rw-r--r-- root root 3871 ./usr/lib/python3.8/__pycache__/hmac.cpython-38.opt-2.pyc
+-rw-r--r-- root root 6388 ./usr/lib/python3.8/__pycache__/hmac.cpython-38.pyc
+-rw-r--r-- root root 39159 ./usr/lib/python3.8/__pycache__/imaplib.cpython-38.opt-1.pyc
+-rw-r--r-- root root 27182 ./usr/lib/python3.8/__pycache__/imaplib.cpython-38.opt-2.pyc
+-rw-r--r-- root root 41342 ./usr/lib/python3.8/__pycache__/imaplib.cpython-38.pyc
+-rw-r--r-- root root 9809 ./usr/lib/python3.8/__pycache__/imp.cpython-38.opt-1.pyc
+-rw-r--r-- root root 7444 ./usr/lib/python3.8/__pycache__/imp.cpython-38.opt-2.pyc
+-rw-r--r-- root root 9809 ./usr/lib/python3.8/__pycache__/imp.cpython-38.pyc
+-rw-r--r-- root root 80098 ./usr/lib/python3.8/__pycache__/inspect.cpython-38.opt-1.pyc
+-rw-r--r-- root root 54985 ./usr/lib/python3.8/__pycache__/inspect.cpython-38.opt-2.pyc
+-rw-r--r-- root root 80383 ./usr/lib/python3.8/__pycache__/inspect.cpython-38.pyc
+-rw-r--r-- root root 3454 ./usr/lib/python3.8/__pycache__/io.cpython-38.opt-1.pyc
+-rw-r--r-- root root 1965 ./usr/lib/python3.8/__pycache__/io.cpython-38.opt-2.pyc
+-rw-r--r-- root root 3454 ./usr/lib/python3.8/__pycache__/io.cpython-38.pyc
+-rw-r--r-- root root 59559 ./usr/lib/python3.8/__pycache__/ipaddress.cpython-38.opt-1.pyc
+-rw-r--r-- root root 35711 ./usr/lib/python3.8/__pycache__/ipaddress.cpython-38.opt-2.pyc
+-rw-r--r-- root root 59559 ./usr/lib/python3.8/__pycache__/ipaddress.cpython-38.pyc
+-rw-r--r-- root root 998 ./usr/lib/python3.8/__pycache__/keyword.cpython-38.opt-1.pyc
+-rw-r--r-- root root 571 ./usr/lib/python3.8/__pycache__/keyword.cpython-38.opt-2.pyc
+-rw-r--r-- root root 998 ./usr/lib/python3.8/__pycache__/keyword.cpython-38.pyc
+-rw-r--r-- root root 3839 ./usr/lib/python3.8/__pycache__/linecache.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2734 ./usr/lib/python3.8/__pycache__/linecache.cpython-38.opt-2.pyc
+-rw-r--r-- root root 3839 ./usr/lib/python3.8/__pycache__/linecache.cpython-38.pyc
+-rw-r--r-- root root 34689 ./usr/lib/python3.8/__pycache__/locale.cpython-38.opt-1.pyc
+-rw-r--r-- root root 30074 ./usr/lib/python3.8/__pycache__/locale.cpython-38.opt-2.pyc
+-rw-r--r-- root root 34689 ./usr/lib/python3.8/__pycache__/locale.cpython-38.pyc
+-rw-r--r-- root root 12018 ./usr/lib/python3.8/__pycache__/lzma.cpython-38.opt-1.pyc
+-rw-r--r-- root root 5849 ./usr/lib/python3.8/__pycache__/lzma.cpython-38.opt-2.pyc
+-rw-r--r-- root root 12018 ./usr/lib/python3.8/__pycache__/lzma.cpython-38.pyc
+-rw-r--r-- root root 7618 ./usr/lib/python3.8/__pycache__/_markupbase.cpython-38.opt-1.pyc
+-rw-r--r-- root root 7240 ./usr/lib/python3.8/__pycache__/_markupbase.cpython-38.opt-2.pyc
+-rw-r--r-- root root 7790 ./usr/lib/python3.8/__pycache__/_markupbase.cpython-38.pyc
+-rw-r--r-- root root 15988 ./usr/lib/python3.8/__pycache__/mimetypes.cpython-38.opt-1.pyc
+-rw-r--r-- root root 9973 ./usr/lib/python3.8/__pycache__/mimetypes.cpython-38.opt-2.pyc
+-rw-r--r-- root root 15988 ./usr/lib/python3.8/__pycache__/mimetypes.cpython-38.pyc
+-rw-r--r-- root root 33974 ./usr/lib/python3.8/__pycache__/nntplib.cpython-38.opt-1.pyc
+-rw-r--r-- root root 21464 ./usr/lib/python3.8/__pycache__/nntplib.cpython-38.opt-2.pyc
+-rw-r--r-- root root 33974 ./usr/lib/python3.8/__pycache__/nntplib.cpython-38.pyc
+-rw-r--r-- root root 14657 ./usr/lib/python3.8/__pycache__/ntpath.cpython-38.opt-1.pyc
+-rw-r--r-- root root 12606 ./usr/lib/python3.8/__pycache__/ntpath.cpython-38.opt-2.pyc
+-rw-r--r-- root root 14657 ./usr/lib/python3.8/__pycache__/ntpath.cpython-38.pyc
+-rw-r--r-- root root 5420 ./usr/lib/python3.8/__pycache__/opcode.cpython-38.opt-1.pyc
+-rw-r--r-- root root 5280 ./usr/lib/python3.8/__pycache__/opcode.cpython-38.opt-2.pyc
+-rw-r--r-- root root 5420 ./usr/lib/python3.8/__pycache__/opcode.cpython-38.pyc
+-rw-r--r-- root root 13691 ./usr/lib/python3.8/__pycache__/operator.cpython-38.opt-1.pyc
+-rw-r--r-- root root 11322 ./usr/lib/python3.8/__pycache__/operator.cpython-38.opt-2.pyc
+-rw-r--r-- root root 13691 ./usr/lib/python3.8/__pycache__/operator.cpython-38.pyc
+-rw-r--r-- root root 47974 ./usr/lib/python3.8/__pycache__/optparse.cpython-38.opt-1.pyc
+-rw-r--r-- root root 35659 ./usr/lib/python3.8/__pycache__/optparse.cpython-38.opt-2.pyc
+-rw-r--r-- root root 48057 ./usr/lib/python3.8/__pycache__/optparse.cpython-38.pyc
+-rw-r--r-- root root 31365 ./usr/lib/python3.8/__pycache__/os.cpython-38.opt-1.pyc
+-rw-r--r-- root root 19174 ./usr/lib/python3.8/__pycache__/os.cpython-38.opt-2.pyc
+-rw-r--r-- root root 31397 ./usr/lib/python3.8/__pycache__/os.cpython-38.pyc
+-rw-r--r-- root root 43498 ./usr/lib/python3.8/__pycache__/pathlib.cpython-38.opt-1.pyc
+-rw-r--r-- root root 35441 ./usr/lib/python3.8/__pycache__/pathlib.cpython-38.opt-2.pyc
+-rw-r--r-- root root 43498 ./usr/lib/python3.8/__pycache__/pathlib.cpython-38.pyc
+-rw-r--r-- root root 46761 ./usr/lib/python3.8/__pycache__/pickle.cpython-38.opt-1.pyc
+-rw-r--r-- root root 40889 ./usr/lib/python3.8/__pycache__/pickle.cpython-38.opt-2.pyc
+-rw-r--r-- root root 46878 ./usr/lib/python3.8/__pycache__/pickle.cpython-38.pyc
+-rw-r--r-- root root 66314 ./usr/lib/python3.8/__pycache__/pickletools.cpython-38.opt-1.pyc
+-rw-r--r-- root root 57221 ./usr/lib/python3.8/__pycache__/pickletools.cpython-38.opt-2.pyc
+-rw-r--r-- root root 67204 ./usr/lib/python3.8/__pycache__/pickletools.cpython-38.pyc
+-rw-r--r-- root root 7795 ./usr/lib/python3.8/__pycache__/pipes.cpython-38.opt-1.pyc
+-rw-r--r-- root root 4928 ./usr/lib/python3.8/__pycache__/pipes.cpython-38.opt-2.pyc
+-rw-r--r-- root root 7795 ./usr/lib/python3.8/__pycache__/pipes.cpython-38.pyc
+-rw-r--r-- root root 16309 ./usr/lib/python3.8/__pycache__/pkgutil.cpython-38.opt-1.pyc
+-rw-r--r-- root root 11053 ./usr/lib/python3.8/__pycache__/pkgutil.cpython-38.opt-2.pyc
+-rw-r--r-- root root 16309 ./usr/lib/python3.8/__pycache__/pkgutil.cpython-38.pyc
+-rw-r--r-- root root 24221 ./usr/lib/python3.8/__pycache__/platform.cpython-38.opt-1.pyc
+-rw-r--r-- root root 16345 ./usr/lib/python3.8/__pycache__/platform.cpython-38.opt-2.pyc
+-rw-r--r-- root root 24221 ./usr/lib/python3.8/__pycache__/platform.cpython-38.pyc
+-rw-r--r-- root root 13459 ./usr/lib/python3.8/__pycache__/poplib.cpython-38.opt-1.pyc
+-rw-r--r-- root root 8528 ./usr/lib/python3.8/__pycache__/poplib.cpython-38.opt-2.pyc
+-rw-r--r-- root root 13459 ./usr/lib/python3.8/__pycache__/poplib.cpython-38.pyc
+-rw-r--r-- root root 10428 ./usr/lib/python3.8/__pycache__/posixpath.cpython-38.opt-1.pyc
+-rw-r--r-- root root 8713 ./usr/lib/python3.8/__pycache__/posixpath.cpython-38.opt-2.pyc
+-rw-r--r-- root root 10428 ./usr/lib/python3.8/__pycache__/posixpath.cpython-38.pyc
+-rw-r--r-- root root 74059 ./usr/lib/python3.8/__pycache__/_pyio.cpython-38.opt-1.pyc
+-rw-r--r-- root root 51166 ./usr/lib/python3.8/__pycache__/_pyio.cpython-38.opt-2.pyc
+-rw-r--r-- root root 74079 ./usr/lib/python3.8/__pycache__/_pyio.cpython-38.pyc
+-rw-r--r-- root root 10626 ./usr/lib/python3.8/__pycache__/queue.cpython-38.opt-1.pyc
+-rw-r--r-- root root 6289 ./usr/lib/python3.8/__pycache__/queue.cpython-38.opt-2.pyc
+-rw-r--r-- root root 10626 ./usr/lib/python3.8/__pycache__/queue.cpython-38.pyc
+-rw-r--r-- root root 5573 ./usr/lib/python3.8/__pycache__/quopri.cpython-38.opt-1.pyc
+-rw-r--r-- root root 4537 ./usr/lib/python3.8/__pycache__/quopri.cpython-38.opt-2.pyc
+-rw-r--r-- root root 5748 ./usr/lib/python3.8/__pycache__/quopri.cpython-38.pyc
+-rw-r--r-- root root 20108 ./usr/lib/python3.8/__pycache__/random.cpython-38.opt-1.pyc
+-rw-r--r-- root root 13132 ./usr/lib/python3.8/__pycache__/random.cpython-38.opt-2.pyc
+-rw-r--r-- root root 20108 ./usr/lib/python3.8/__pycache__/random.cpython-38.pyc
+-rw-r--r-- root root 14308 ./usr/lib/python3.8/__pycache__/re.cpython-38.opt-1.pyc
+-rw-r--r-- root root 6084 ./usr/lib/python3.8/__pycache__/re.cpython-38.opt-2.pyc
+-rw-r--r-- root root 14308 ./usr/lib/python3.8/__pycache__/re.cpython-38.pyc
+-rw-r--r-- root root 5303 ./usr/lib/python3.8/__pycache__/reprlib.cpython-38.opt-1.pyc
+-rw-r--r-- root root 5147 ./usr/lib/python3.8/__pycache__/reprlib.cpython-38.opt-2.pyc
+-rw-r--r-- root root 5303 ./usr/lib/python3.8/__pycache__/reprlib.cpython-38.pyc
+-rw-r--r-- root root 5755 ./usr/lib/python3.8/__pycache__/rlcompleter.cpython-38.opt-1.pyc
+-rw-r--r-- root root 3092 ./usr/lib/python3.8/__pycache__/rlcompleter.cpython-38.opt-2.pyc
+-rw-r--r-- root root 5755 ./usr/lib/python3.8/__pycache__/rlcompleter.cpython-38.pyc
+-rw-r--r-- root root 8104 ./usr/lib/python3.8/__pycache__/runpy.cpython-38.opt-1.pyc
+-rw-r--r-- root root 6538 ./usr/lib/python3.8/__pycache__/runpy.cpython-38.opt-2.pyc
+-rw-r--r-- root root 8104 ./usr/lib/python3.8/__pycache__/runpy.cpython-38.pyc
+-rw-r--r-- root root 16935 ./usr/lib/python3.8/__pycache__/selectors.cpython-38.opt-1.pyc
+-rw-r--r-- root root 12900 ./usr/lib/python3.8/__pycache__/selectors.cpython-38.opt-2.pyc
+-rw-r--r-- root root 16935 ./usr/lib/python3.8/__pycache__/selectors.cpython-38.pyc
+-rw-r--r-- root root 9490 ./usr/lib/python3.8/__pycache__/shelve.cpython-38.opt-1.pyc
+-rw-r--r-- root root 5339 ./usr/lib/python3.8/__pycache__/shelve.cpython-38.opt-2.pyc
+-rw-r--r-- root root 9490 ./usr/lib/python3.8/__pycache__/shelve.cpython-38.pyc
+-rw-r--r-- root root 7536 ./usr/lib/python3.8/__pycache__/shlex.cpython-38.opt-1.pyc
+-rw-r--r-- root root 6979 ./usr/lib/python3.8/__pycache__/shlex.cpython-38.opt-2.pyc
+-rw-r--r-- root root 7536 ./usr/lib/python3.8/__pycache__/shlex.cpython-38.pyc
+-rw-r--r-- root root 36569 ./usr/lib/python3.8/__pycache__/shutil.cpython-38.opt-1.pyc
+-rw-r--r-- root root 25114 ./usr/lib/python3.8/__pycache__/shutil.cpython-38.opt-2.pyc
+-rw-r--r-- root root 36569 ./usr/lib/python3.8/__pycache__/shutil.cpython-38.pyc
+-rw-r--r-- root root 2843 ./usr/lib/python3.8/__pycache__/signal.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2619 ./usr/lib/python3.8/__pycache__/signal.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2843 ./usr/lib/python3.8/__pycache__/signal.cpython-38.pyc
+-rw-r--r-- root root 3481 ./usr/lib/python3.8/__pycache__/_sitebuiltins.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2957 ./usr/lib/python3.8/__pycache__/_sitebuiltins.cpython-38.opt-2.pyc
+-rw-r--r-- root root 3481 ./usr/lib/python3.8/__pycache__/_sitebuiltins.cpython-38.pyc
+-rw-r--r-- root root 16700 ./usr/lib/python3.8/__pycache__/site.cpython-38.opt-1.pyc
+-rw-r--r-- root root 11164 ./usr/lib/python3.8/__pycache__/site.cpython-38.opt-2.pyc
+-rw-r--r-- root root 16700 ./usr/lib/python3.8/__pycache__/site.cpython-38.pyc
+-rw-r--r-- root root 35252 ./usr/lib/python3.8/__pycache__/smtplib.cpython-38.opt-1.pyc
+-rw-r--r-- root root 18892 ./usr/lib/python3.8/__pycache__/smtplib.cpython-38.opt-2.pyc
+-rw-r--r-- root root 35313 ./usr/lib/python3.8/__pycache__/smtplib.cpython-38.pyc
+-rw-r--r-- root root 27747 ./usr/lib/python3.8/__pycache__/socket.cpython-38.opt-1.pyc
+-rw-r--r-- root root 19424 ./usr/lib/python3.8/__pycache__/socket.cpython-38.opt-2.pyc
+-rw-r--r-- root root 27787 ./usr/lib/python3.8/__pycache__/socket.cpython-38.pyc
+-rw-r--r-- root root 14916 ./usr/lib/python3.8/__pycache__/sre_compile.cpython-38.opt-1.pyc
+-rw-r--r-- root root 14502 ./usr/lib/python3.8/__pycache__/sre_compile.cpython-38.opt-2.pyc
+-rw-r--r-- root root 15142 ./usr/lib/python3.8/__pycache__/sre_compile.cpython-38.pyc
+-rw-r--r-- root root 6359 ./usr/lib/python3.8/__pycache__/sre_constants.cpython-38.opt-1.pyc
+-rw-r--r-- root root 5934 ./usr/lib/python3.8/__pycache__/sre_constants.cpython-38.opt-2.pyc
+-rw-r--r-- root root 6359 ./usr/lib/python3.8/__pycache__/sre_constants.cpython-38.pyc
+-rw-r--r-- root root 21600 ./usr/lib/python3.8/__pycache__/sre_parse.cpython-38.opt-1.pyc
+-rw-r--r-- root root 21552 ./usr/lib/python3.8/__pycache__/sre_parse.cpython-38.opt-2.pyc
+-rw-r--r-- root root 21647 ./usr/lib/python3.8/__pycache__/sre_parse.cpython-38.pyc
+-rw-r--r-- root root 44596 ./usr/lib/python3.8/__pycache__/ssl.cpython-38.opt-1.pyc
+-rw-r--r-- root root 33618 ./usr/lib/python3.8/__pycache__/ssl.cpython-38.opt-2.pyc
+-rw-r--r-- root root 44596 ./usr/lib/python3.8/__pycache__/ssl.cpython-38.pyc
+-rw-r--r-- root root 4372 ./usr/lib/python3.8/__pycache__/stat.cpython-38.opt-1.pyc
+-rw-r--r-- root root 3589 ./usr/lib/python3.8/__pycache__/stat.cpython-38.opt-2.pyc
+-rw-r--r-- root root 4372 ./usr/lib/python3.8/__pycache__/stat.cpython-38.pyc
+-rw-r--r-- root root 7300 ./usr/lib/python3.8/__pycache__/string.cpython-38.opt-1.pyc
+-rw-r--r-- root root 6194 ./usr/lib/python3.8/__pycache__/string.cpython-38.opt-2.pyc
+-rw-r--r-- root root 7300 ./usr/lib/python3.8/__pycache__/string.cpython-38.pyc
+-rw-r--r-- root root 10959 ./usr/lib/python3.8/__pycache__/stringprep.cpython-38.opt-1.pyc
+-rw-r--r-- root root 10739 ./usr/lib/python3.8/__pycache__/stringprep.cpython-38.opt-2.pyc
+-rw-r--r-- root root 11017 ./usr/lib/python3.8/__pycache__/stringprep.cpython-38.pyc
+-rw-r--r-- root root 16044 ./usr/lib/python3.8/__pycache__/_strptime.cpython-38.opt-1.pyc
+-rw-r--r-- root root 12316 ./usr/lib/python3.8/__pycache__/_strptime.cpython-38.opt-2.pyc
+-rw-r--r-- root root 16044 ./usr/lib/python3.8/__pycache__/_strptime.cpython-38.pyc
+-rw-r--r-- root root 330 ./usr/lib/python3.8/__pycache__/struct.cpython-38.opt-1.pyc
+-rw-r--r-- root root 330 ./usr/lib/python3.8/__pycache__/struct.cpython-38.opt-2.pyc
+-rw-r--r-- root root 330 ./usr/lib/python3.8/__pycache__/struct.cpython-38.pyc
+-rw-r--r-- root root 41843 ./usr/lib/python3.8/__pycache__/subprocess.cpython-38.opt-1.pyc
+-rw-r--r-- root root 29913 ./usr/lib/python3.8/__pycache__/subprocess.cpython-38.opt-2.pyc
+-rw-r--r-- root root 41940 ./usr/lib/python3.8/__pycache__/subprocess.cpython-38.pyc
+-rw-r--r-- root root 2404 ./usr/lib/python3.8/__pycache__/symbol.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2328 ./usr/lib/python3.8/__pycache__/symbol.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2404 ./usr/lib/python3.8/__pycache__/symbol.cpython-38.pyc
+-rw-r--r-- root root 15462 ./usr/lib/python3.8/__pycache__/sysconfig.cpython-38.opt-1.pyc
+-rw-r--r-- root root 13084 ./usr/lib/python3.8/__pycache__/sysconfig.cpython-38.opt-2.pyc
+-rw-r--r-- root root 15462 ./usr/lib/python3.8/__pycache__/sysconfig.cpython-38.pyc
+-rw-r--r-- root root 62519 ./usr/lib/python3.8/__pycache__/tarfile.cpython-38.opt-1.pyc
+-rw-r--r-- root root 48629 ./usr/lib/python3.8/__pycache__/tarfile.cpython-38.opt-2.pyc
+-rw-r--r-- root root 62550 ./usr/lib/python3.8/__pycache__/tarfile.cpython-38.pyc
+-rw-r--r-- root root 18237 ./usr/lib/python3.8/__pycache__/telnetlib.cpython-38.opt-1.pyc
+-rw-r--r-- root root 10735 ./usr/lib/python3.8/__pycache__/telnetlib.cpython-38.opt-2.pyc
+-rw-r--r-- root root 18237 ./usr/lib/python3.8/__pycache__/telnetlib.cpython-38.pyc
+-rw-r--r-- root root 23459 ./usr/lib/python3.8/__pycache__/tempfile.cpython-38.opt-1.pyc
+-rw-r--r-- root root 16875 ./usr/lib/python3.8/__pycache__/tempfile.cpython-38.opt-2.pyc
+-rw-r--r-- root root 23459 ./usr/lib/python3.8/__pycache__/tempfile.cpython-38.pyc
+-rw-r--r-- root root 13445 ./usr/lib/python3.8/__pycache__/textwrap.cpython-38.opt-1.pyc
+-rw-r--r-- root root 6236 ./usr/lib/python3.8/__pycache__/textwrap.cpython-38.opt-2.pyc
+-rw-r--r-- root root 13519 ./usr/lib/python3.8/__pycache__/textwrap.cpython-38.pyc
+-rw-r--r-- root root 39378 ./usr/lib/python3.8/__pycache__/threading.cpython-38.opt-1.pyc
+-rw-r--r-- root root 22801 ./usr/lib/python3.8/__pycache__/threading.cpython-38.opt-2.pyc
+-rw-r--r-- root root 39929 ./usr/lib/python3.8/__pycache__/threading.cpython-38.pyc
+-rw-r--r-- root root 6446 ./usr/lib/python3.8/__pycache__/_threading_local.cpython-38.opt-1.pyc
+-rw-r--r-- root root 3126 ./usr/lib/python3.8/__pycache__/_threading_local.cpython-38.opt-2.pyc
+-rw-r--r-- root root 6446 ./usr/lib/python3.8/__pycache__/_threading_local.cpython-38.pyc
+-rw-r--r-- root root 2485 ./usr/lib/python3.8/__pycache__/token.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2452 ./usr/lib/python3.8/__pycache__/token.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2485 ./usr/lib/python3.8/__pycache__/token.cpython-38.pyc
+-rw-r--r-- root root 17116 ./usr/lib/python3.8/__pycache__/tokenize.cpython-38.opt-1.pyc
+-rw-r--r-- root root 13352 ./usr/lib/python3.8/__pycache__/tokenize.cpython-38.opt-2.pyc
+-rw-r--r-- root root 17160 ./usr/lib/python3.8/__pycache__/tokenize.cpython-38.pyc
+-rw-r--r-- root root 19890 ./usr/lib/python3.8/__pycache__/traceback.cpython-38.opt-1.pyc
+-rw-r--r-- root root 10986 ./usr/lib/python3.8/__pycache__/traceback.cpython-38.opt-2.pyc
+-rw-r--r-- root root 19890 ./usr/lib/python3.8/__pycache__/traceback.cpython-38.pyc
+-rw-r--r-- root root 9177 ./usr/lib/python3.8/__pycache__/types.cpython-38.opt-1.pyc
+-rw-r--r-- root root 7955 ./usr/lib/python3.8/__pycache__/types.cpython-38.opt-2.pyc
+-rw-r--r-- root root 9177 ./usr/lib/python3.8/__pycache__/types.cpython-38.pyc
+-rw-r--r-- root root 3605 ./usr/lib/python3.8/__pycache__/uu.cpython-38.opt-1.pyc
+-rw-r--r-- root root 3361 ./usr/lib/python3.8/__pycache__/uu.cpython-38.opt-2.pyc
+-rw-r--r-- root root 3605 ./usr/lib/python3.8/__pycache__/uu.cpython-38.pyc
+-rw-r--r-- root root 23532 ./usr/lib/python3.8/__pycache__/uuid.cpython-38.opt-1.pyc
+-rw-r--r-- root root 16376 ./usr/lib/python3.8/__pycache__/uuid.cpython-38.opt-2.pyc
+-rw-r--r-- root root 23666 ./usr/lib/python3.8/__pycache__/uuid.cpython-38.pyc
+-rw-r--r-- root root 13192 ./usr/lib/python3.8/__pycache__/warnings.cpython-38.opt-1.pyc
+-rw-r--r-- root root 10917 ./usr/lib/python3.8/__pycache__/warnings.cpython-38.opt-2.pyc
+-rw-r--r-- root root 13652 ./usr/lib/python3.8/__pycache__/warnings.cpython-38.pyc
+-rw-r--r-- root root 19488 ./usr/lib/python3.8/__pycache__/weakref.cpython-38.opt-1.pyc
+-rw-r--r-- root root 16204 ./usr/lib/python3.8/__pycache__/weakref.cpython-38.opt-2.pyc
+-rw-r--r-- root root 19518 ./usr/lib/python3.8/__pycache__/weakref.cpython-38.pyc
+-rw-r--r-- root root 7600 ./usr/lib/python3.8/__pycache__/_weakrefset.cpython-38.opt-1.pyc
+-rw-r--r-- root root 7600 ./usr/lib/python3.8/__pycache__/_weakrefset.cpython-38.opt-2.pyc
+-rw-r--r-- root root 7600 ./usr/lib/python3.8/__pycache__/_weakrefset.cpython-38.pyc
+-rw-r--r-- root root 58599 ./usr/lib/python3.8/__pycache__/zipfile.cpython-38.opt-1.pyc
+-rw-r--r-- root root 49927 ./usr/lib/python3.8/__pycache__/zipfile.cpython-38.opt-2.pyc
+-rw-r--r-- root root 58636 ./usr/lib/python3.8/__pycache__/zipfile.cpython-38.pyc
+-rw-r--r-- root root 93177 ./usr/lib/python3.8/_pyio.py
+-rw-r--r-- root root 11356 ./usr/lib/python3.8/queue.py
+-rwxr-xr-x root root 7254 ./usr/lib/python3.8/quopri.py
+-rw-r--r-- root root 28802 ./usr/lib/python3.8/random.py
+-rw-r--r-- root root 5267 ./usr/lib/python3.8/reprlib.py
+-rw-r--r-- root root 15747 ./usr/lib/python3.8/re.py
+-rw-r--r-- root root 7097 ./usr/lib/python3.8/rlcompleter.py
+-rw-r--r-- root root 11973 ./usr/lib/python3.8/runpy.py
+-rw-r--r-- root root 18561 ./usr/lib/python3.8/selectors.py
+-rw-r--r-- root root 8527 ./usr/lib/python3.8/shelve.py
+-rw-r--r-- root root 13325 ./usr/lib/python3.8/shlex.py
+-rw-r--r-- root root 50752 ./usr/lib/python3.8/shutil.py
+-rw-r--r-- root root 2273 ./usr/lib/python3.8/signal.py
+-rw-r--r-- root root 3115 ./usr/lib/python3.8/_sitebuiltins.py
+drwxr-xr-x root root 4096 ./usr/lib/python3.8/site-packages
+drwxr-xr-x root root 4096 ./usr/lib/python3.8/site-packages/btrfsutil-1.1.1-py3.8.egg-info
+-rw-r--r-- root root 1 ./usr/lib/python3.8/site-packages/btrfsutil-1.1.1-py3.8.egg-info/dependency_links.txt
+-rw-r--r-- root root 242 ./usr/lib/python3.8/site-packages/btrfsutil-1.1.1-py3.8.egg-info/PKG-INFO
+-rw-r--r-- root root 203 ./usr/lib/python3.8/site-packages/btrfsutil-1.1.1-py3.8.egg-info/SOURCES.txt
+-rw-r--r-- root root 10 ./usr/lib/python3.8/site-packages/btrfsutil-1.1.1-py3.8.egg-info/top_level.txt
+-rwxr-xr-x root root 45936 ./usr/lib/python3.8/site-packages/btrfsutil.cpython-38-x86_64-linux-gnu.so
+drwxr-xr-x root root 4096 ./usr/lib/python3.8/site-packages/cairo
+-rwxr-xr-x root root 220616 ./usr/lib/python3.8/site-packages/cairo/_cairo.cpython-38-x86_64-linux-gnu.so
+drwxr-xr-x root root 4096 ./usr/lib/python3.8/site-packages/cairo/include
+-rw-r--r-- root root 9152 ./usr/lib/python3.8/site-packages/cairo/include/py3cairo.h
+-rwxr-xr-x root root 660 ./usr/lib/python3.8/site-packages/cairo/__init__.py
+-rw-r--r-- root root 33334 ./usr/lib/python3.8/site-packages/cairo/__init__.pyi
+-rw-r--r-- root root 0 ./usr/lib/python3.8/site-packages/cairo/py.typed
+drwxr-xr-x root root 4096 ./usr/lib/python3.8/site-packages/dbus
+-rwxr-xr-x root root 167752 ./usr/lib/python3.8/site-packages/_dbus_bindings.so
+-rw-r--r-- root root 17960 ./usr/lib/python3.8/site-packages/dbus/bus.py
+-rw-r--r-- root root 148 ./usr/lib/python3.8/site-packages/dbus/_compat.py
+-rw-r--r-- root root 27806 ./usr/lib/python3.8/site-packages/dbus/connection.py
+-rw-r--r-- root root 8837 ./usr/lib/python3.8/site-packages/dbus/_dbus.py
+-rw-r--r-- root root 15240 ./usr/lib/python3.8/site-packages/dbus/decorators.py
+-rw-r--r-- root root 4707 ./usr/lib/python3.8/site-packages/dbus/exceptions.py
+-rw-r--r-- root root 3409 ./usr/lib/python3.8/site-packages/dbus/_expat_introspect_parser.py
+-rw-r--r-- root root 3517 ./usr/lib/python3.8/site-packages/dbus/gi_service.py
+-rwxr-xr-x root root 22736 ./usr/lib/python3.8/site-packages/_dbus_glib_bindings.so
+-rw-r--r-- root root 2130 ./usr/lib/python3.8/site-packages/dbus/glib.py
+-rw-r--r-- root root 3756 ./usr/lib/python3.8/site-packages/dbus/__init__.py
+-rw-r--r-- root root 1864 ./usr/lib/python3.8/site-packages/dbus/lowlevel.py
+drwxr-xr-x root root 4096 ./usr/lib/python3.8/site-packages/dbus/mainloop
+-rw-r--r-- root root 1806 ./usr/lib/python3.8/site-packages/dbus/mainloop/glib.py
+-rw-r--r-- root root 2369 ./usr/lib/python3.8/site-packages/dbus/mainloop/__init__.py
+drwxr-xr-x root root 4096 ./usr/lib/python3.8/site-packages/dbus/mainloop/__pycache__
+-rw-r--r-- root root 655 ./usr/lib/python3.8/site-packages/dbus/mainloop/__pycache__/glib.cpython-38.opt-1.pyc
+-rw-r--r-- root root 655 ./usr/lib/python3.8/site-packages/dbus/mainloop/__pycache__/glib.cpython-38.pyc
+-rw-r--r-- root root 435 ./usr/lib/python3.8/site-packages/dbus/mainloop/__pycache__/__init__.cpython-38.opt-1.pyc
+-rw-r--r-- root root 435 ./usr/lib/python3.8/site-packages/dbus/mainloop/__pycache__/__init__.cpython-38.pyc
+drwxr-xr-x root root 4096 ./usr/lib/python3.8/site-packages/dbusmock
+-rw-r--r-- root root 856 ./usr/lib/python3.8/site-packages/dbusmock/__init__.py
+-rw-r--r-- root root 4533 ./usr/lib/python3.8/site-packages/dbusmock/__main__.py
+-rw-r--r-- root root 28848 ./usr/lib/python3.8/site-packages/dbusmock/mockobject.py
+drwxr-xr-x root root 4096 ./usr/lib/python3.8/site-packages/dbusmock/__pycache__
+-rw-r--r-- root root 641 ./usr/lib/python3.8/site-packages/dbusmock/__pycache__/__init__.cpython-38.pyc
+-rw-r--r-- root root 3142 ./usr/lib/python3.8/site-packages/dbusmock/__pycache__/__main__.cpython-38.pyc
+-rw-r--r-- root root 22372 ./usr/lib/python3.8/site-packages/dbusmock/__pycache__/mockobject.cpython-38.pyc
+-rw-r--r-- root root 7903 ./usr/lib/python3.8/site-packages/dbusmock/__pycache__/testcase.cpython-38.pyc
+drwxr-xr-x root root 4096 ./usr/lib/python3.8/site-packages/dbusmock/templates
+-rw-r--r-- root root 16490 ./usr/lib/python3.8/site-packages/dbusmock/templates/bluez4.py
+-rw-r--r-- root root 10784 ./usr/lib/python3.8/site-packages/dbusmock/templates/bluez5-obex.py
+-rw-r--r-- root root 15264 ./usr/lib/python3.8/site-packages/dbusmock/templates/bluez5.py
+-rw-r--r-- root root 1250 ./usr/lib/python3.8/site-packages/dbusmock/templates/gnome_screensaver.py
+-rw-r--r-- root root 382 ./usr/lib/python3.8/site-packages/dbusmock/templates/__init__.py
+-rw-r--r-- root root 10765 ./usr/lib/python3.8/site-packages/dbusmock/templates/logind.py
+-rw-r--r-- root root 1139 ./usr/lib/python3.8/site-packages/dbusmock/templates/low_memory_monitor.py
+-rw-r--r-- root root 34680 ./usr/lib/python3.8/site-packages/dbusmock/templates/networkmanager.py
+-rw-r--r-- root root 1777 ./usr/lib/python3.8/site-packages/dbusmock/templates/notification_daemon.py
+-rw-r--r-- root root 18046 ./usr/lib/python3.8/site-packages/dbusmock/templates/ofono.py
+-rw-r--r-- root root 2089 ./usr/lib/python3.8/site-packages/dbusmock/templates/polkitd.py
+drwxr-xr-x root root 4096 ./usr/lib/python3.8/site-packages/dbusmock/templates/__pycache__
+-rw-r--r-- root root 10255 ./usr/lib/python3.8/site-packages/dbusmock/templates/__pycache__/bluez4.cpython-38.pyc
+-rw-r--r-- root root 9287 ./usr/lib/python3.8/site-packages/dbusmock/templates/__pycache__/bluez5.cpython-38.pyc
+-rw-r--r-- root root 7996 ./usr/lib/python3.8/site-packages/dbusmock/templates/__pycache__/bluez5-obex.cpython-38.pyc
+-rw-r--r-- root root 1052 ./usr/lib/python3.8/site-packages/dbusmock/templates/__pycache__/gnome_screensaver.cpython-38.pyc
+-rw-r--r-- root root 206 ./usr/lib/python3.8/site-packages/dbusmock/templates/__pycache__/__init__.cpython-38.pyc
+-rw-r--r-- root root 6563 ./usr/lib/python3.8/site-packages/dbusmock/templates/__pycache__/logind.cpython-38.pyc
+-rw-r--r-- root root 1111 ./usr/lib/python3.8/site-packages/dbusmock/templates/__pycache__/low_memory_monitor.cpython-38.pyc
+-rw-r--r-- root root 23374 ./usr/lib/python3.8/site-packages/dbusmock/templates/__pycache__/networkmanager.cpython-38.pyc
+-rw-r--r-- root root 1419 ./usr/lib/python3.8/site-packages/dbusmock/templates/__pycache__/notification_daemon.cpython-38.pyc
+-rw-r--r-- root root 9250 ./usr/lib/python3.8/site-packages/dbusmock/templates/__pycache__/ofono.cpython-38.pyc
+-rw-r--r-- root root 1890 ./usr/lib/python3.8/site-packages/dbusmock/templates/__pycache__/polkitd.cpython-38.pyc
+-rw-r--r-- root root 1342 ./usr/lib/python3.8/site-packages/dbusmock/templates/__pycache__/timedated.cpython-38.pyc
+-rw-r--r-- root root 6843 ./usr/lib/python3.8/site-packages/dbusmock/templates/__pycache__/upower.cpython-38.pyc
+-rw-r--r-- root root 2520 ./usr/lib/python3.8/site-packages/dbusmock/templates/__pycache__/urfkill.cpython-38.pyc
+-rw-r--r-- root root 1796 ./usr/lib/python3.8/site-packages/dbusmock/templates/timedated.py
+-rw-r--r-- root root 10801 ./usr/lib/python3.8/site-packages/dbusmock/templates/upower.py
+-rw-r--r-- root root 3709 ./usr/lib/python3.8/site-packages/dbusmock/templates/urfkill.py
+-rw-r--r-- root root 9445 ./usr/lib/python3.8/site-packages/dbusmock/testcase.py
+-rw-r--r-- root root 24821 ./usr/lib/python3.8/site-packages/dbus/proxies.py
+drwxr-xr-x root root 4096 ./usr/lib/python3.8/site-packages/dbus/__pycache__
+-rw-r--r-- root root 13609 ./usr/lib/python3.8/site-packages/dbus/__pycache__/bus.cpython-38.opt-1.pyc
+-rw-r--r-- root root 13609 ./usr/lib/python3.8/site-packages/dbus/__pycache__/bus.cpython-38.pyc
+-rw-r--r-- root root 218 ./usr/lib/python3.8/site-packages/dbus/__pycache__/_compat.cpython-38.opt-1.pyc
+-rw-r--r-- root root 218 ./usr/lib/python3.8/site-packages/dbus/__pycache__/_compat.cpython-38.pyc
+-rw-r--r-- root root 17806 ./usr/lib/python3.8/site-packages/dbus/__pycache__/connection.cpython-38.opt-1.pyc
+-rw-r--r-- root root 17806 ./usr/lib/python3.8/site-packages/dbus/__pycache__/connection.cpython-38.pyc
+-rw-r--r-- root root 7385 ./usr/lib/python3.8/site-packages/dbus/__pycache__/_dbus.cpython-38.opt-1.pyc
+-rw-r--r-- root root 7385 ./usr/lib/python3.8/site-packages/dbus/__pycache__/_dbus.cpython-38.pyc
+-rw-r--r-- root root 11569 ./usr/lib/python3.8/site-packages/dbus/__pycache__/decorators.cpython-38.opt-1.pyc
+-rw-r--r-- root root 11569 ./usr/lib/python3.8/site-packages/dbus/__pycache__/decorators.cpython-38.pyc
+-rw-r--r-- root root 3916 ./usr/lib/python3.8/site-packages/dbus/__pycache__/exceptions.cpython-38.opt-1.pyc
+-rw-r--r-- root root 3916 ./usr/lib/python3.8/site-packages/dbus/__pycache__/exceptions.cpython-38.pyc
+-rw-r--r-- root root 2206 ./usr/lib/python3.8/site-packages/dbus/__pycache__/_expat_introspect_parser.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2206 ./usr/lib/python3.8/site-packages/dbus/__pycache__/_expat_introspect_parser.cpython-38.pyc
+-rw-r--r-- root root 1954 ./usr/lib/python3.8/site-packages/dbus/__pycache__/gi_service.cpython-38.opt-1.pyc
+-rw-r--r-- root root 1954 ./usr/lib/python3.8/site-packages/dbus/__pycache__/gi_service.cpython-38.pyc
+-rw-r--r-- root root 1018 ./usr/lib/python3.8/site-packages/dbus/__pycache__/glib.cpython-38.opt-1.pyc
+-rw-r--r-- root root 1018 ./usr/lib/python3.8/site-packages/dbus/__pycache__/glib.cpython-38.pyc
+-rw-r--r-- root root 2185 ./usr/lib/python3.8/site-packages/dbus/__pycache__/__init__.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2185 ./usr/lib/python3.8/site-packages/dbus/__pycache__/__init__.cpython-38.pyc
+-rw-r--r-- root root 677 ./usr/lib/python3.8/site-packages/dbus/__pycache__/lowlevel.cpython-38.opt-1.pyc
+-rw-r--r-- root root 677 ./usr/lib/python3.8/site-packages/dbus/__pycache__/lowlevel.cpython-38.pyc
+-rw-r--r-- root root 17730 ./usr/lib/python3.8/site-packages/dbus/__pycache__/proxies.cpython-38.opt-1.pyc
+-rw-r--r-- root root 17730 ./usr/lib/python3.8/site-packages/dbus/__pycache__/proxies.cpython-38.pyc
+-rw-r--r-- root root 3462 ./usr/lib/python3.8/site-packages/dbus/__pycache__/server.cpython-38.opt-1.pyc
+-rw-r--r-- root root 3462 ./usr/lib/python3.8/site-packages/dbus/__pycache__/server.cpython-38.pyc
+-rw-r--r-- root root 22086 ./usr/lib/python3.8/site-packages/dbus/__pycache__/service.cpython-38.opt-1.pyc
+-rw-r--r-- root root 22086 ./usr/lib/python3.8/site-packages/dbus/__pycache__/service.cpython-38.pyc
+-rw-r--r-- root root 730 ./usr/lib/python3.8/site-packages/dbus/__pycache__/types.cpython-38.opt-1.pyc
+-rw-r--r-- root root 730 ./usr/lib/python3.8/site-packages/dbus/__pycache__/types.cpython-38.pyc
+-rw-r--r-- root root 4657 ./usr/lib/python3.8/site-packages/dbus/server.py
+-rw-r--r-- root root 35473 ./usr/lib/python3.8/site-packages/dbus/service.py
+-rw-r--r-- root root 561 ./usr/lib/python3.8/site-packages/dbus/types.py
+drwxr-xr-x root root 4096 ./usr/lib/python3.8/site-packages/gi
+-rw-r--r-- root root 1493 ./usr/lib/python3.8/site-packages/gi/_compat.py
+-rw-r--r-- root root 1969 ./usr/lib/python3.8/site-packages/gi/_constants.py
+-rw-r--r-- root root 6688 ./usr/lib/python3.8/site-packages/gi/docstring.py
+-rw-r--r-- root root 2082 ./usr/lib/python3.8/site-packages/gi/_error.py
+-rwxr-xr-x root root 22488 ./usr/lib/python3.8/site-packages/gi/_gi_cairo.cpython-38-x86_64-linux-gnu.so
+-rwxr-xr-x root root 344488 ./usr/lib/python3.8/site-packages/gi/_gi.cpython-38-x86_64-linux-gnu.so
+-rw-r--r-- root root 7835 ./usr/lib/python3.8/site-packages/gi/_gtktemplate.py
+-rw-r--r-- root root 5280 ./usr/lib/python3.8/site-packages/gi/importer.py
+-rw-r--r-- root root 5894 ./usr/lib/python3.8/site-packages/gi/__init__.py
+-rw-r--r-- root root 9705 ./usr/lib/python3.8/site-packages/gi/module.py
+-rw-r--r-- root root 13192 ./usr/lib/python3.8/site-packages/gi/_option.py
+-rw-r--r-- root root 8083 ./usr/lib/python3.8/site-packages/gi/_ossighelper.py
+drwxr-xr-x root root 4096 ./usr/lib/python3.8/site-packages/gi/overrides
+-rw-r--r-- root root 1724 ./usr/lib/python3.8/site-packages/gi/overrides/GdkPixbuf.py
+-rw-r--r-- root root 16239 ./usr/lib/python3.8/site-packages/gi/overrides/Gdk.py
+-rw-r--r-- root root 2242 ./usr/lib/python3.8/site-packages/gi/overrides/GIMarshallingTests.py
+-rw-r--r-- root root 19033 ./usr/lib/python3.8/site-packages/gi/overrides/Gio.py
+-rw-r--r-- root root 29897 ./usr/lib/python3.8/site-packages/gi/overrides/GLib.py
+-rw-r--r-- root root 24640 ./usr/lib/python3.8/site-packages/gi/overrides/GObject.py
+-rw-r--r-- root root 59083 ./usr/lib/python3.8/site-packages/gi/overrides/Gtk.py
+-rw-r--r-- root root 12590 ./usr/lib/python3.8/site-packages/gi/overrides/__init__.py
+-rw-r--r-- root root 1705 ./usr/lib/python3.8/site-packages/gi/overrides/keysyms.py
+-rw-r--r-- root root 1774 ./usr/lib/python3.8/site-packages/gi/overrides/Pango.py
+-rw-r--r-- root root 14331 ./usr/lib/python3.8/site-packages/gi/_propertyhelper.py
+-rw-r--r-- root root 766 ./usr/lib/python3.8/site-packages/gi/pygtkcompat.py
+drwxr-xr-x root root 4096 ./usr/lib/python3.8/site-packages/gi/repository
+-rw-r--r-- root root 1042 ./usr/lib/python3.8/site-packages/gi/repository/__init__.py
+-rw-r--r-- root root 9303 ./usr/lib/python3.8/site-packages/gi/_signalhelper.py
+-rw-r--r-- root root 14330 ./usr/lib/python3.8/site-packages/gi/types.py
+-rw-r--r-- root root 1024 ./usr/lib/python3.8/site-packages/pycairo-1.19.0.egg-info
+-rw-r--r-- root root 810 ./usr/lib/python3.8/site-packages/PyGObject-3.34.0.egg-info
+drwxr-xr-x root root 4096 ./usr/lib/python3.8/site-packages/pygtkcompat
+-rw-r--r-- root root 14200 ./usr/lib/python3.8/site-packages/pygtkcompat/generictreemodel.py
+-rw-r--r-- root root 547 ./usr/lib/python3.8/site-packages/pygtkcompat/__init__.py
+-rw-r--r-- root root 20890 ./usr/lib/python3.8/site-packages/pygtkcompat/pygtkcompat.py
+drwxr-xr-x root root 4096 ./usr/lib/python3.8/site-packages/python_dbusmock-0.19-py3.8.egg-info
+-rw-r--r-- root root 1 ./usr/lib/python3.8/site-packages/python_dbusmock-0.19-py3.8.egg-info/dependency_links.txt
+-rw-r--r-- root root 14631 ./usr/lib/python3.8/site-packages/python_dbusmock-0.19-py3.8.egg-info/PKG-INFO
+-rw-r--r-- root root 1137 ./usr/lib/python3.8/site-packages/python_dbusmock-0.19-py3.8.egg-info/SOURCES.txt
+-rw-r--r-- root root 9 ./usr/lib/python3.8/site-packages/python_dbusmock-0.19-py3.8.egg-info/top_level.txt
+-rw-r--r-- root root 21342 ./usr/lib/python3.8/site.py
+-rwxr-xr-x root root 44328 ./usr/lib/python3.8/smtplib.py
+-rw-r--r-- root root 35243 ./usr/lib/python3.8/socket.py
+-rw-r--r-- root root 26695 ./usr/lib/python3.8/sre_compile.py
+-rw-r--r-- root root 7154 ./usr/lib/python3.8/sre_constants.py
+-rw-r--r-- root root 40230 ./usr/lib/python3.8/sre_parse.py
+-rw-r--r-- root root 50760 ./usr/lib/python3.8/ssl.py
+-rw-r--r-- root root 5485 ./usr/lib/python3.8/stat.py
+-rw-r--r-- root root 12917 ./usr/lib/python3.8/stringprep.py
+-rw-r--r-- root root 10535 ./usr/lib/python3.8/string.py
+-rw-r--r-- root root 25268 ./usr/lib/python3.8/_strptime.py
+-rw-r--r-- root root 257 ./usr/lib/python3.8/struct.py
+-rw-r--r-- root root 77289 ./usr/lib/python3.8/subprocess.py
+-rw-r--r-- root root 2109 ./usr/lib/python3.8/symbol.py
+-rw-r--r-- root root 26663 ./usr/lib/python3.8/_sysconfigdata__linux_x86_64-linux-gnu.py
+-rw-r--r-- root root 24339 ./usr/lib/python3.8/sysconfig.py
+-rwxr-xr-x root root 93575 ./usr/lib/python3.8/tarfile.py
+-rw-r--r-- root root 23254 ./usr/lib/python3.8/telnetlib.py
+-rw-r--r-- root root 27588 ./usr/lib/python3.8/tempfile.py
+-rw-r--r-- root root 19407 ./usr/lib/python3.8/textwrap.py
+-rw-r--r-- root root 7220 ./usr/lib/python3.8/_threading_local.py
+-rw-r--r-- root root 50585 ./usr/lib/python3.8/threading.py
+-rw-r--r-- root root 25841 ./usr/lib/python3.8/tokenize.py
+-rw-r--r-- root root 2368 ./usr/lib/python3.8/token.py
+-rw-r--r-- root root 23479 ./usr/lib/python3.8/traceback.py
+-rw-r--r-- root root 9713 ./usr/lib/python3.8/types.py
+drwxr-xr-x root root 4096 ./usr/lib/python3.8/urllib
+-rw-r--r-- root root 2632 ./usr/lib/python3.8/urllib/error.py
+-rw-r--r-- root root 0 ./usr/lib/python3.8/urllib/__init__.py
+-rw-r--r-- root root 41583 ./usr/lib/python3.8/urllib/parse.py
+drwxr-xr-x root root 4096 ./usr/lib/python3.8/urllib/__pycache__
+-rw-r--r-- root root 2802 ./usr/lib/python3.8/urllib/__pycache__/error.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2127 ./usr/lib/python3.8/urllib/__pycache__/error.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2802 ./usr/lib/python3.8/urllib/__pycache__/error.cpython-38.pyc
+-rw-r--r-- root root 121 ./usr/lib/python3.8/urllib/__pycache__/__init__.cpython-38.opt-1.pyc
+-rw-r--r-- root root 121 ./usr/lib/python3.8/urllib/__pycache__/__init__.cpython-38.opt-2.pyc
+-rw-r--r-- root root 121 ./usr/lib/python3.8/urllib/__pycache__/__init__.cpython-38.pyc
+-rw-r--r-- root root 33925 ./usr/lib/python3.8/urllib/__pycache__/parse.cpython-38.opt-1.pyc
+-rw-r--r-- root root 24489 ./usr/lib/python3.8/urllib/__pycache__/parse.cpython-38.opt-2.pyc
+-rw-r--r-- root root 33925 ./usr/lib/python3.8/urllib/__pycache__/parse.cpython-38.pyc
+-rw-r--r-- root root 72410 ./usr/lib/python3.8/urllib/__pycache__/request.cpython-38.opt-1.pyc
+-rw-r--r-- root root 60117 ./usr/lib/python3.8/urllib/__pycache__/request.cpython-38.opt-2.pyc
+-rw-r--r-- root root 72524 ./usr/lib/python3.8/urllib/__pycache__/request.cpython-38.pyc
+-rw-r--r-- root root 3282 ./usr/lib/python3.8/urllib/__pycache__/response.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2703 ./usr/lib/python3.8/urllib/__pycache__/response.cpython-38.opt-2.pyc
+-rw-r--r-- root root 3282 ./usr/lib/python3.8/urllib/__pycache__/response.cpython-38.pyc
+-rw-r--r-- root root 7320 ./usr/lib/python3.8/urllib/__pycache__/robotparser.cpython-38.opt-1.pyc
+-rw-r--r-- root root 5952 ./usr/lib/python3.8/urllib/__pycache__/robotparser.cpython-38.opt-2.pyc
+-rw-r--r-- root root 7320 ./usr/lib/python3.8/urllib/__pycache__/robotparser.cpython-38.pyc
+-rw-r--r-- root root 101308 ./usr/lib/python3.8/urllib/request.py
+-rw-r--r-- root root 2299 ./usr/lib/python3.8/urllib/response.py
+-rw-r--r-- root root 9424 ./usr/lib/python3.8/urllib/robotparser.py
+-rw-r--r-- root root 30394 ./usr/lib/python3.8/uuid.py
+-rwxr-xr-x root root 6959 ./usr/lib/python3.8/uu.py
+-rw-r--r-- root root 19688 ./usr/lib/python3.8/warnings.py
+-rw-r--r-- root root 21387 ./usr/lib/python3.8/weakref.py
+-rw-r--r-- root root 5735 ./usr/lib/python3.8/_weakrefset.py
+drwxr-xr-x root root 4096 ./usr/lib/python3.8/xml
+drwxr-xr-x root root 4096 ./usr/lib/python3.8/xml/dom
+-rw-r--r-- root root 3451 ./usr/lib/python3.8/xml/dom/domreg.py
+-rw-r--r-- root root 35756 ./usr/lib/python3.8/xml/dom/expatbuilder.py
+-rw-r--r-- root root 4019 ./usr/lib/python3.8/xml/dom/__init__.py
+-rw-r--r-- root root 3367 ./usr/lib/python3.8/xml/dom/minicompat.py
+-rw-r--r-- root root 66857 ./usr/lib/python3.8/xml/dom/minidom.py
+-rw-r--r-- root root 936 ./usr/lib/python3.8/xml/dom/NodeFilter.py
+-rw-r--r-- root root 11997 ./usr/lib/python3.8/xml/dom/pulldom.py
+drwxr-xr-x root root 4096 ./usr/lib/python3.8/xml/dom/__pycache__
+-rw-r--r-- root root 2842 ./usr/lib/python3.8/xml/dom/__pycache__/domreg.cpython-38.opt-1.pyc
+-rw-r--r-- root root 1640 ./usr/lib/python3.8/xml/dom/__pycache__/domreg.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2842 ./usr/lib/python3.8/xml/dom/__pycache__/domreg.cpython-38.pyc
+-rw-r--r-- root root 26798 ./usr/lib/python3.8/xml/dom/__pycache__/expatbuilder.cpython-38.opt-1.pyc
+-rw-r--r-- root root 24193 ./usr/lib/python3.8/xml/dom/__pycache__/expatbuilder.cpython-38.opt-2.pyc
+-rw-r--r-- root root 27333 ./usr/lib/python3.8/xml/dom/__pycache__/expatbuilder.cpython-38.pyc
+-rw-r--r-- root root 5522 ./usr/lib/python3.8/xml/dom/__pycache__/__init__.cpython-38.opt-1.pyc
+-rw-r--r-- root root 4727 ./usr/lib/python3.8/xml/dom/__pycache__/__init__.cpython-38.opt-2.pyc
+-rw-r--r-- root root 5522 ./usr/lib/python3.8/xml/dom/__pycache__/__init__.cpython-38.pyc
+-rw-r--r-- root root 2642 ./usr/lib/python3.8/xml/dom/__pycache__/minicompat.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2464 ./usr/lib/python3.8/xml/dom/__pycache__/minicompat.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2734 ./usr/lib/python3.8/xml/dom/__pycache__/minicompat.cpython-38.pyc
+-rw-r--r-- root root 55264 ./usr/lib/python3.8/xml/dom/__pycache__/minidom.cpython-38.opt-1.pyc
+-rw-r--r-- root root 53693 ./usr/lib/python3.8/xml/dom/__pycache__/minidom.cpython-38.opt-2.pyc
+-rw-r--r-- root root 55366 ./usr/lib/python3.8/xml/dom/__pycache__/minidom.cpython-38.pyc
+-rw-r--r-- root root 959 ./usr/lib/python3.8/xml/dom/__pycache__/NodeFilter.cpython-38.opt-1.pyc
+-rw-r--r-- root root 866 ./usr/lib/python3.8/xml/dom/__pycache__/NodeFilter.cpython-38.opt-2.pyc
+-rw-r--r-- root root 959 ./usr/lib/python3.8/xml/dom/__pycache__/NodeFilter.cpython-38.pyc
+-rw-r--r-- root root 10683 ./usr/lib/python3.8/xml/dom/__pycache__/pulldom.cpython-38.opt-1.pyc
+-rw-r--r-- root root 10247 ./usr/lib/python3.8/xml/dom/__pycache__/pulldom.cpython-38.opt-2.pyc
+-rw-r--r-- root root 10683 ./usr/lib/python3.8/xml/dom/__pycache__/pulldom.cpython-38.pyc
+-rw-r--r-- root root 12456 ./usr/lib/python3.8/xml/dom/__pycache__/xmlbuilder.cpython-38.opt-1.pyc
+-rw-r--r-- root root 12027 ./usr/lib/python3.8/xml/dom/__pycache__/xmlbuilder.cpython-38.opt-2.pyc
+-rw-r--r-- root root 12486 ./usr/lib/python3.8/xml/dom/__pycache__/xmlbuilder.cpython-38.pyc
+-rw-r--r-- root root 12403 ./usr/lib/python3.8/xml/dom/xmlbuilder.py
+drwxr-xr-x root root 4096 ./usr/lib/python3.8/xml/etree
+-rw-r--r-- root root 82 ./usr/lib/python3.8/xml/etree/cElementTree.py
+-rw-r--r-- root root 5151 ./usr/lib/python3.8/xml/etree/ElementInclude.py
+-rw-r--r-- root root 13118 ./usr/lib/python3.8/xml/etree/ElementPath.py
+-rw-r--r-- root root 72728 ./usr/lib/python3.8/xml/etree/ElementTree.py
+-rw-r--r-- root root 1604 ./usr/lib/python3.8/xml/etree/__init__.py
+drwxr-xr-x root root 4096 ./usr/lib/python3.8/xml/etree/__pycache__
+-rw-r--r-- root root 163 ./usr/lib/python3.8/xml/etree/__pycache__/cElementTree.cpython-38.opt-1.pyc
+-rw-r--r-- root root 163 ./usr/lib/python3.8/xml/etree/__pycache__/cElementTree.cpython-38.opt-2.pyc
+-rw-r--r-- root root 163 ./usr/lib/python3.8/xml/etree/__pycache__/cElementTree.cpython-38.pyc
+-rw-r--r-- root root 1569 ./usr/lib/python3.8/xml/etree/__pycache__/ElementInclude.cpython-38.opt-1.pyc
+-rw-r--r-- root root 1569 ./usr/lib/python3.8/xml/etree/__pycache__/ElementInclude.cpython-38.opt-2.pyc
+-rw-r--r-- root root 1569 ./usr/lib/python3.8/xml/etree/__pycache__/ElementInclude.cpython-38.pyc
+-rw-r--r-- root root 8424 ./usr/lib/python3.8/xml/etree/__pycache__/ElementPath.cpython-38.opt-1.pyc
+-rw-r--r-- root root 8424 ./usr/lib/python3.8/xml/etree/__pycache__/ElementPath.cpython-38.opt-2.pyc
+-rw-r--r-- root root 8424 ./usr/lib/python3.8/xml/etree/__pycache__/ElementPath.cpython-38.pyc
+-rw-r--r-- root root 55288 ./usr/lib/python3.8/xml/etree/__pycache__/ElementTree.cpython-38.opt-1.pyc
+-rw-r--r-- root root 36891 ./usr/lib/python3.8/xml/etree/__pycache__/ElementTree.cpython-38.opt-2.pyc
+-rw-r--r-- root root 55602 ./usr/lib/python3.8/xml/etree/__pycache__/ElementTree.cpython-38.pyc
+-rw-r--r-- root root 121 ./usr/lib/python3.8/xml/etree/__pycache__/__init__.cpython-38.opt-1.pyc
+-rw-r--r-- root root 121 ./usr/lib/python3.8/xml/etree/__pycache__/__init__.cpython-38.opt-2.pyc
+-rw-r--r-- root root 121 ./usr/lib/python3.8/xml/etree/__pycache__/__init__.cpython-38.pyc
+-rw-r--r-- root root 557 ./usr/lib/python3.8/xml/__init__.py
+drwxr-xr-x root root 4096 ./usr/lib/python3.8/xml/parsers
+-rw-r--r-- root root 248 ./usr/lib/python3.8/xml/parsers/expat.py
+-rw-r--r-- root root 167 ./usr/lib/python3.8/xml/parsers/__init__.py
+drwxr-xr-x root root 4096 ./usr/lib/python3.8/xml/parsers/__pycache__
+-rw-r--r-- root root 322 ./usr/lib/python3.8/xml/parsers/__pycache__/expat.cpython-38.opt-1.pyc
+-rw-r--r-- root root 256 ./usr/lib/python3.8/xml/parsers/__pycache__/expat.cpython-38.opt-2.pyc
+-rw-r--r-- root root 322 ./usr/lib/python3.8/xml/parsers/__pycache__/expat.cpython-38.pyc
+-rw-r--r-- root root 293 ./usr/lib/python3.8/xml/parsers/__pycache__/__init__.cpython-38.opt-1.pyc
+-rw-r--r-- root root 121 ./usr/lib/python3.8/xml/parsers/__pycache__/__init__.cpython-38.opt-2.pyc
+-rw-r--r-- root root 293 ./usr/lib/python3.8/xml/parsers/__pycache__/__init__.cpython-38.pyc
+drwxr-xr-x root root 4096 ./usr/lib/python3.8/xml/__pycache__
+-rw-r--r-- root root 688 ./usr/lib/python3.8/xml/__pycache__/__init__.cpython-38.opt-1.pyc
+-rw-r--r-- root root 165 ./usr/lib/python3.8/xml/__pycache__/__init__.cpython-38.opt-2.pyc
+-rw-r--r-- root root 688 ./usr/lib/python3.8/xml/__pycache__/__init__.cpython-38.pyc
+drwxr-xr-x root root 4096 ./usr/lib/python3.8/xml/sax
+-rw-r--r-- root root 4785 ./usr/lib/python3.8/xml/sax/_exceptions.py
+-rw-r--r-- root root 15704 ./usr/lib/python3.8/xml/sax/expatreader.py
+-rw-r--r-- root root 13922 ./usr/lib/python3.8/xml/sax/handler.py
+-rw-r--r-- root root 3647 ./usr/lib/python3.8/xml/sax/__init__.py
+drwxr-xr-x root root 4096 ./usr/lib/python3.8/xml/sax/__pycache__
+-rw-r--r-- root root 5436 ./usr/lib/python3.8/xml/sax/__pycache__/_exceptions.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2833 ./usr/lib/python3.8/xml/sax/__pycache__/_exceptions.cpython-38.opt-2.pyc
+-rw-r--r-- root root 5436 ./usr/lib/python3.8/xml/sax/__pycache__/_exceptions.cpython-38.pyc
+-rw-r--r-- root root 12487 ./usr/lib/python3.8/xml/sax/__pycache__/expatreader.cpython-38.opt-1.pyc
+-rw-r--r-- root root 12076 ./usr/lib/python3.8/xml/sax/__pycache__/expatreader.cpython-38.opt-2.pyc
+-rw-r--r-- root root 12487 ./usr/lib/python3.8/xml/sax/__pycache__/expatreader.cpython-38.pyc
+-rw-r--r-- root root 12414 ./usr/lib/python3.8/xml/sax/__pycache__/handler.cpython-38.opt-1.pyc
+-rw-r--r-- root root 4643 ./usr/lib/python3.8/xml/sax/__pycache__/handler.cpython-38.opt-2.pyc
+-rw-r--r-- root root 12414 ./usr/lib/python3.8/xml/sax/__pycache__/handler.cpython-38.pyc
+-rw-r--r-- root root 3211 ./usr/lib/python3.8/xml/sax/__pycache__/__init__.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2148 ./usr/lib/python3.8/xml/sax/__pycache__/__init__.cpython-38.opt-2.pyc
+-rw-r--r-- root root 3211 ./usr/lib/python3.8/xml/sax/__pycache__/__init__.cpython-38.pyc
+-rw-r--r-- root root 12911 ./usr/lib/python3.8/xml/sax/__pycache__/saxutils.cpython-38.opt-1.pyc
+-rw-r--r-- root root 11256 ./usr/lib/python3.8/xml/sax/__pycache__/saxutils.cpython-38.opt-2.pyc
+-rw-r--r-- root root 12911 ./usr/lib/python3.8/xml/sax/__pycache__/saxutils.cpython-38.pyc
+-rw-r--r-- root root 16836 ./usr/lib/python3.8/xml/sax/__pycache__/xmlreader.cpython-38.opt-1.pyc
+-rw-r--r-- root root 10399 ./usr/lib/python3.8/xml/sax/__pycache__/xmlreader.cpython-38.opt-2.pyc
+-rw-r--r-- root root 16836 ./usr/lib/python3.8/xml/sax/__pycache__/xmlreader.cpython-38.pyc
+-rw-r--r-- root root 12255 ./usr/lib/python3.8/xml/sax/saxutils.py
+-rw-r--r-- root root 12684 ./usr/lib/python3.8/xml/sax/xmlreader.py
+-rw-r--r-- root root 88132 ./usr/lib/python3.8/zipfile.py
+-rw-r--r-- root root 3920 ./usr/lib/Scrt1.o
+drwxr-xr-x root root 4096 ./usr/lib/ssl-1.1
+lrwxrwxrwx root root 22 ./usr/lib/ssl-1.1/certs -> ../../../etc/ssl/certs
+-rw-r--r-- root root 412 ./usr/lib/ssl-1.1/ct_log_list.cnf
+-rw-r--r-- root root 412 ./usr/lib/ssl-1.1/ct_log_list.cnf.dist
+-rw-r--r-- root root 10909 ./usr/lib/ssl-1.1/openssl.cnf.dist
+lrwxrwxrwx root root 28 ./usr/lib/ssl-1.1/openssl.cnf -> ../../../etc/ssl/openssl.cnf
+lrwxrwxrwx root root 24 ./usr/lib/ssl-1.1/private -> ../../../etc/ssl/private
+drwxr-xr-x root root 4096 ./usr/lib/systemd
+drwxr-xr-x root root 4096 ./usr/lib/systemd/user
+-rw-r--r-- root root 360 ./usr/lib/systemd/user/dbus.service
+-rw-r--r-- root root 174 ./usr/lib/systemd/user/dbus.socket
+drwxr-xr-x root root 4096 ./usr/lib/systemd/user/sockets.target.wants
+lrwxrwxrwx root root 14 ./usr/lib/systemd/user/sockets.target.wants/dbus.socket -> ../dbus.socket
+drwxr-xr-x root root 4096 ./usr/lib/x86_64-poky-linux
+drwxr-xr-x root root 4096 ./usr/lib/x86_64-poky-linux/10.1.0
+-rw-r--r-- root root 2432 ./usr/lib/x86_64-poky-linux/10.1.0/crtbegin.o
+-rw-r--r-- root root 2752 ./usr/lib/x86_64-poky-linux/10.1.0/crtbeginS.o
+-rw-r--r-- root root 2944 ./usr/lib/x86_64-poky-linux/10.1.0/crtbeginT.o
+-rw-r--r-- root root 1200 ./usr/lib/x86_64-poky-linux/10.1.0/crtend.o
+-rw-r--r-- root root 1200 ./usr/lib/x86_64-poky-linux/10.1.0/crtendS.o
+-rw-r--r-- root root 3848 ./usr/lib/x86_64-poky-linux/10.1.0/crtfastmath.o
+-rw-r--r-- root root 3400 ./usr/lib/x86_64-poky-linux/10.1.0/crtprec32.o
+-rw-r--r-- root root 3416 ./usr/lib/x86_64-poky-linux/10.1.0/crtprec64.o
+-rw-r--r-- root root 3400 ./usr/lib/x86_64-poky-linux/10.1.0/crtprec80.o
+-rw-r--r-- root root 6179894 ./usr/lib/x86_64-poky-linux/10.1.0/libgcc.a
+-rw-r--r-- root root 405636 ./usr/lib/x86_64-poky-linux/10.1.0/libgcc_eh.a
+-rw-r--r-- root root 267062 ./usr/lib/x86_64-poky-linux/10.1.0/libgcov.a
+-rw-r--r-- root root 201 ./usr/lib/xml2Conf.sh
+drwxr-xr-x root root 4096 ./usr/lib/xtables
+-rwxr-xr-x root root 14432 ./usr/lib/xtables/libip6t_ah.so
+-rwxr-xr-x root root 14640 ./usr/lib/xtables/libip6t_DNAT.so
+-rwxr-xr-x root root 14440 ./usr/lib/xtables/libip6t_DNPT.so
+-rwxr-xr-x root root 14432 ./usr/lib/xtables/libip6t_dst.so
+-rwxr-xr-x root root 14208 ./usr/lib/xtables/libip6t_eui64.so
+-rwxr-xr-x root root 14432 ./usr/lib/xtables/libip6t_frag.so
+-rwxr-xr-x root root 14432 ./usr/lib/xtables/libip6t_hbh.so
+-rwxr-xr-x root root 14432 ./usr/lib/xtables/libip6t_hl.so
+-rwxr-xr-x root root 14440 ./usr/lib/xtables/libip6t_HL.so
+-rwxr-xr-x root root 14440 ./usr/lib/xtables/libip6t_icmp6.so
+-rwxr-xr-x root root 14440 ./usr/lib/xtables/libip6t_ipv6header.so
+-rwxr-xr-x root root 14440 ./usr/lib/xtables/libip6t_LOG.so
+-rwxr-xr-x root root 14448 ./usr/lib/xtables/libip6t_MASQUERADE.so
+-rwxr-xr-x root root 14432 ./usr/lib/xtables/libip6t_mh.so
+-rwxr-xr-x root root 14448 ./usr/lib/xtables/libip6t_NETMAP.so
+-rwxr-xr-x root root 14448 ./usr/lib/xtables/libip6t_REDIRECT.so
+-rwxr-xr-x root root 14448 ./usr/lib/xtables/libip6t_REJECT.so
+-rwxr-xr-x root root 14432 ./usr/lib/xtables/libip6t_rt.so
+-rwxr-xr-x root root 14440 ./usr/lib/xtables/libip6t_SNAT.so
+-rwxr-xr-x root root 14440 ./usr/lib/xtables/libip6t_SNPT.so
+-rwxr-xr-x root root 22816 ./usr/lib/xtables/libip6t_srh.so
+-rwxr-xr-x root root 14432 ./usr/lib/xtables/libipt_ah.so
+-rwxr-xr-x root root 14448 ./usr/lib/xtables/libipt_CLUSTERIP.so
+-rwxr-xr-x root root 18736 ./usr/lib/xtables/libipt_DNAT.so
+-rwxr-xr-x root root 14440 ./usr/lib/xtables/libipt_ECN.so
+-rwxr-xr-x root root 14432 ./usr/lib/xtables/libipt_icmp.so
+-rwxr-xr-x root root 14440 ./usr/lib/xtables/libipt_LOG.so
+-rwxr-xr-x root root 14448 ./usr/lib/xtables/libipt_MASQUERADE.so
+-rwxr-xr-x root root 14448 ./usr/lib/xtables/libipt_NETMAP.so
+-rwxr-xr-x root root 14432 ./usr/lib/xtables/libipt_realm.so
+-rwxr-xr-x root root 14448 ./usr/lib/xtables/libipt_REDIRECT.so
+-rwxr-xr-x root root 14448 ./usr/lib/xtables/libipt_REJECT.so
+-rwxr-xr-x root root 14440 ./usr/lib/xtables/libipt_SNAT.so
+-rwxr-xr-x root root 14432 ./usr/lib/xtables/libipt_ttl.so
+-rwxr-xr-x root root 14440 ./usr/lib/xtables/libipt_TTL.so
+-rwxr-xr-x root root 14440 ./usr/lib/xtables/libipt_ULOG.so
+-rwxr-xr-x root root 14632 ./usr/lib/xtables/libxt_addrtype.so
+-rwxr-xr-x root root 14440 ./usr/lib/xtables/libxt_AUDIT.so
+-rwxr-xr-x root root 14624 ./usr/lib/xtables/libxt_bpf.so
+-rwxr-xr-x root root 14816 ./usr/lib/xtables/libxt_cgroup.so
+-rwxr-xr-x root root 14448 ./usr/lib/xtables/libxt_CHECKSUM.so
+-rwxr-xr-x root root 14648 ./usr/lib/xtables/libxt_CLASSIFY.so
+-rwxr-xr-x root root 14440 ./usr/lib/xtables/libxt_cluster.so
+-rwxr-xr-x root root 14440 ./usr/lib/xtables/libxt_comment.so
+-rwxr-xr-x root root 14440 ./usr/lib/xtables/libxt_connbytes.so
+-rwxr-xr-x root root 15016 ./usr/lib/xtables/libxt_connlimit.so
+-rwxr-xr-x root root 14632 ./usr/lib/xtables/libxt_connmark.so
+-rwxr-xr-x root root 18944 ./usr/lib/xtables/libxt_CONNMARK.so
+-rwxr-xr-x root root 14448 ./usr/lib/xtables/libxt_CONNSECMARK.so
+-rwxr-xr-x root root 32744 ./usr/lib/xtables/libxt_conntrack.so
+-rwxr-xr-x root root 14432 ./usr/lib/xtables/libxt_cpu.so
+-rwxr-xr-x root root 19736 ./usr/lib/xtables/libxt_CT.so
+-rwxr-xr-x root root 14432 ./usr/lib/xtables/libxt_dccp.so
+-rwxr-xr-x root root 14440 ./usr/lib/xtables/libxt_devgroup.so
+-rwxr-xr-x root root 14624 ./usr/lib/xtables/libxt_dscp.so
+-rwxr-xr-x root root 14640 ./usr/lib/xtables/libxt_DSCP.so
+-rwxr-xr-x root root 14432 ./usr/lib/xtables/libxt_ecn.so
+-rwxr-xr-x root root 14432 ./usr/lib/xtables/libxt_esp.so
+-rwxr-xr-x root root 36136 ./usr/lib/xtables/libxt_hashlimit.so
+-rwxr-xr-x root root 14432 ./usr/lib/xtables/libxt_helper.so
+-rwxr-xr-x root root 14640 ./usr/lib/xtables/libxt_HMARK.so
+-rwxr-xr-x root root 14448 ./usr/lib/xtables/libxt_IDLETIMER.so
+-rwxr-xr-x root root 14432 ./usr/lib/xtables/libxt_ipcomp.so
+-rwxr-xr-x root root 14824 ./usr/lib/xtables/libxt_iprange.so
+-rwxr-xr-x root root 14624 ./usr/lib/xtables/libxt_ipvs.so
+-rwxr-xr-x root root 14440 ./usr/lib/xtables/libxt_LED.so
+-rwxr-xr-x root root 14432 ./usr/lib/xtables/libxt_length.so
+-rwxr-xr-x root root 14624 ./usr/lib/xtables/libxt_limit.so
+-rwxr-xr-x root root 14432 ./usr/lib/xtables/libxt_mac.so
+-rwxr-xr-x root root 14624 ./usr/lib/xtables/libxt_mark.so
+-rwxr-xr-x root root 15168 ./usr/lib/xtables/libxt_MARK.so
+-rwxr-xr-x root root 19112 ./usr/lib/xtables/libxt_multiport.so
+-rwxr-xr-x root root 14624 ./usr/lib/xtables/libxt_nfacct.so
+-rwxr-xr-x root root 14440 ./usr/lib/xtables/libxt_NFLOG.so
+-rwxr-xr-x root root 15048 ./usr/lib/xtables/libxt_NFQUEUE.so
+lrwxrwxrwx root root 11 ./usr/lib/xtables/libxt_NOTRACK.so -> libxt_CT.so
+-rwxr-xr-x root root 14432 ./usr/lib/xtables/libxt_osf.so
+-rwxr-xr-x root root 23008 ./usr/lib/xtables/libxt_owner.so
+-rwxr-xr-x root root 14440 ./usr/lib/xtables/libxt_physdev.so
+-rwxr-xr-x root root 14440 ./usr/lib/xtables/libxt_pkttype.so
+-rwxr-xr-x root root 14624 ./usr/lib/xtables/libxt_policy.so
+-rwxr-xr-x root root 14432 ./usr/lib/xtables/libxt_quota.so
+-rwxr-xr-x root root 14440 ./usr/lib/xtables/libxt_rateest.so
+-rwxr-xr-x root root 14448 ./usr/lib/xtables/libxt_RATEEST.so
+-rwxr-xr-x root root 18912 ./usr/lib/xtables/libxt_recent.so
+-rwxr-xr-x root root 14440 ./usr/lib/xtables/libxt_rpfilter.so
+-rwxr-xr-x root root 14432 ./usr/lib/xtables/libxt_sctp.so
+-rwxr-xr-x root root 14448 ./usr/lib/xtables/libxt_SECMARK.so
+-rwxr-xr-x root root 23392 ./usr/lib/xtables/libxt_set.so
+-rwxr-xr-x root root 23232 ./usr/lib/xtables/libxt_SET.so
+-rwxr-xr-x root root 15008 ./usr/lib/xtables/libxt_socket.so
+-rwxr-xr-x root root 14368 ./usr/lib/xtables/libxt_standard.so
+lrwxrwxrwx root root 18 ./usr/lib/xtables/libxt_state.so -> libxt_conntrack.so
+-rwxr-xr-x root root 14440 ./usr/lib/xtables/libxt_statistic.so
+-rwxr-xr-x root root 14624 ./usr/lib/xtables/libxt_string.so
+-rwxr-xr-x root root 14448 ./usr/lib/xtables/libxt_SYNPROXY.so
+-rwxr-xr-x root root 14432 ./usr/lib/xtables/libxt_tcpmss.so
+-rwxr-xr-x root root 14640 ./usr/lib/xtables/libxt_TCPMSS.so
+-rwxr-xr-x root root 14448 ./usr/lib/xtables/libxt_TCPOPTSTRIP.so
+-rwxr-xr-x root root 14432 ./usr/lib/xtables/libxt_tcp.so
+-rwxr-xr-x root root 14640 ./usr/lib/xtables/libxt_TEE.so
+-rwxr-xr-x root root 14432 ./usr/lib/xtables/libxt_time.so
+-rwxr-xr-x root root 14624 ./usr/lib/xtables/libxt_tos.so
+-rwxr-xr-x root root 14640 ./usr/lib/xtables/libxt_TOS.so
+-rwxr-xr-x root root 14840 ./usr/lib/xtables/libxt_TPROXY.so
+-rwxr-xr-x root root 14208 ./usr/lib/xtables/libxt_TRACE.so
+-rwxr-xr-x root root 14432 ./usr/lib/xtables/libxt_u32.so
+-rwxr-xr-x root root 14432 ./usr/lib/xtables/libxt_udp.so
+drwxr-xr-x root root 4096 ./usr/sbin
+lrwxrwxrwx root root 19 ./usr/sbin/addgroup -> /bin/busybox.nosuid
+-rwxr-xr-x root root 26664 ./usr/sbin/addpart
+lrwxrwxrwx root root 19 ./usr/sbin/adduser -> /bin/busybox.nosuid
+-rwxr-xr-x root root 30760 ./usr/sbin/blkdiscard
+-rwxr-xr-x root root 71720 ./usr/sbin/blkzone
+-rwxr-xr-x root root 47136 ./usr/sbin/chcpu
+-rwxr-xr-x root root 59152 ./usr/sbin/chgpasswd
+-rwxr-xr-x root root 55056 ./usr/sbin/chpasswd.shadow
+lrwxrwxrwx root root 25 ./usr/sbin/chpasswd -> /usr/sbin/chpasswd.shadow
+-rwxr-xr-x root root 55464 ./usr/sbin/chroot.coreutils
+lrwxrwxrwx root root 26 ./usr/sbin/chroot -> /usr/sbin/chroot.coreutils
+lrwxrwxrwx root root 19 ./usr/sbin/delgroup -> /bin/busybox.nosuid
+-rwxr-xr-x root root 26664 ./usr/sbin/delpart
+lrwxrwxrwx root root 19 ./usr/sbin/deluser -> /bin/busybox.nosuid
+lrwxrwxrwx root root 19 ./usr/sbin/fbset -> /bin/busybox.nosuid
+-rwxr-xr-x root root 34856 ./usr/sbin/fdformat
+-rwxr-xr-x root root 14368 ./usr/sbin/findfs
+-rwxr-xr-x root root 38984 ./usr/sbin/fsck.cramfs
+lrwxrwxrwx root root 29 ./usr/sbin/fsfreeze -> /usr/sbin/fsfreeze.util-linux
+-rwxr-xr-x root root 14384 ./usr/sbin/fsfreeze.util-linux
+-rwxr-xr-x root root 84336 ./usr/sbin/groupadd
+-rwxr-xr-x root root 75952 ./usr/sbin/groupdel
+-rwxr-xr-x root root 59160 ./usr/sbin/groupmems
+-rwxr-xr-x root root 84272 ./usr/sbin/groupmod
+-rwxr-xr-x root root 59120 ./usr/sbin/grpck
+-rwxr-xr-x root root 54896 ./usr/sbin/grpconv
+-rwxr-xr-x root root 54904 ./usr/sbin/grpunconv
+-rwxr-xr-x root root 30936 ./usr/sbin/iconvconfig
+lrwxrwxrwx root root 20 ./usr/sbin/ip6tables-legacy-restore -> xtables-legacy-multi
+lrwxrwxrwx root root 20 ./usr/sbin/ip6tables-legacy-save -> xtables-legacy-multi
+lrwxrwxrwx root root 20 ./usr/sbin/ip6tables-legacy -> xtables-legacy-multi
+lrwxrwxrwx root root 20 ./usr/sbin/ip6tables-restore -> xtables-legacy-multi
+lrwxrwxrwx root root 20 ./usr/sbin/ip6tables-save -> xtables-legacy-multi
+lrwxrwxrwx root root 20 ./usr/sbin/ip6tables -> xtables-legacy-multi
+lrwxrwxrwx root root 20 ./usr/sbin/iptables-legacy-restore -> xtables-legacy-multi
+lrwxrwxrwx root root 20 ./usr/sbin/iptables-legacy-save -> xtables-legacy-multi
+lrwxrwxrwx root root 20 ./usr/sbin/iptables-legacy -> xtables-legacy-multi
+lrwxrwxrwx root root 20 ./usr/sbin/iptables-restore -> xtables-legacy-multi
+lrwxrwxrwx root root 20 ./usr/sbin/iptables-save -> xtables-legacy-multi
+lrwxrwxrwx root root 20 ./usr/sbin/iptables -> xtables-legacy-multi
+-rwxr-xr-x root root 34856 ./usr/sbin/ldattach
+lrwxrwxrwx root root 19 ./usr/sbin/loadfont -> /bin/busybox.nosuid
+-rwxr-xr-x root root 14288 ./usr/sbin/logoutd
+-rwxr-xr-x root root 14368 ./usr/sbin/mkfs
+-rwxr-xr-x root root 38880 ./usr/sbin/mkfs.cramfs
+-rwxr-xr-x root root 96560 ./usr/sbin/newusers
+-rwxr-xr-x root root 116776 ./usr/sbin/partx
+-rwxr-xr-x root root 55016 ./usr/sbin/pwck
+-rwxr-xr-x root root 50792 ./usr/sbin/pwconv
+-rwxr-xr-x root root 50808 ./usr/sbin/pwunconv
+-rwxr-xr-x root root 14368 ./usr/sbin/raw
+lrwxrwxrwx root root 19 ./usr/sbin/rdate -> /bin/busybox.nosuid
+lrwxrwxrwx root root 32 ./usr/sbin/readprofile -> /usr/sbin/readprofile.util-linux
+-rwxr-xr-x root root 22616 ./usr/sbin/readprofile.util-linux
+-rwxr-xr-x root root 63528 ./usr/sbin/resizepart
+lrwxrwxrwx root root 27 ./usr/sbin/rfkill -> /usr/sbin/rfkill.util-linux
+-rwxr-xr-x root root 47152 ./usr/sbin/rfkill.util-linux
+-rwxr-xr-x root root 47144 ./usr/sbin/rtcwake
+-rwxr-xr-x root root 1986 ./usr/sbin/run-postinsts
+-rwxr-xr-x root root 141352 ./usr/sbin/sfdisk
+-rwxr-xr-x root root 18472 ./usr/sbin/swaplabel
+lrwxrwxrwx root root 19 ./usr/sbin/udhcpd -> /bin/busybox.nosuid
+-rwxr-xr-x root root 5990 ./usr/sbin/update-ca-certificates
+-rwxr-xr-x root root 6365 ./usr/sbin/update-rc.d
+-rwxr-xr-x root root 130136 ./usr/sbin/useradd
+-rwxr-xr-x root root 88328 ./usr/sbin/userdel
+-rwxr-xr-x root root 125880 ./usr/sbin/usermod
+-rwxr-xr-x root root 39032 ./usr/sbin/uuidd
+-rwxr-xr-x root root 47144 ./usr/sbin/wipefs
+-rwxr-xr-x root root 98960 ./usr/sbin/xtables-legacy-multi
+-rwxr-xr-x root root 112792 ./usr/sbin/zramctl
+drwxr-xr-x root root 4096 ./usr/share
+drwxr-xr-x root root 4096 ./usr/share/aclocal
+-rw-r--r-- root root 2221 ./usr/share/aclocal/bison-i18n.m4
+-rw-r--r-- root root 1184 ./usr/share/aclocal/cap-ng.m4
+-rw-r--r-- root root 6337 ./usr/share/aclocal/freetype2.m4
+-rw-r--r-- root root 8316 ./usr/share/aclocal/glib-2.0.m4
+-rw-r--r-- root root 15838 ./usr/share/aclocal/glib-gettext.m4
+-rw-r--r-- root root 3589 ./usr/share/aclocal/gsettings.m4
+-rw-r--r-- root root 5132 ./usr/share/aclocal/introspection.m4
+-rw-r--r-- root root 357 ./usr/share/aclocal/libxml.m4
+-rw-r--r-- root root 428 ./usr/share/aclocal/wayland-scanner.m4
+-rw-r--r-- root root 71315 ./usr/share/aclocal/xorg-macros.m4
+-rw-r--r-- root root 6537 ./usr/share/aclocal/xtrans.m4
+drwxr-xr-x root root 4096 ./usr/share/awk
+-rw-r--r-- root root 383 ./usr/share/awk/assert.awk
+-rw-r--r-- root root 334 ./usr/share/awk/bits2str.awk
+-rw-r--r-- root root 307 ./usr/share/awk/cliff_rand.awk
+-rw-r--r-- root root 234 ./usr/share/awk/ctime.awk
+-rw-r--r-- root root 315 ./usr/share/awk/ftrans.awk
+-rw-r--r-- root root 2202 ./usr/share/awk/getopt.awk
+-rw-r--r-- root root 2491 ./usr/share/awk/gettime.awk
+-rw-r--r-- root root 1765 ./usr/share/awk/group.awk
+-rw-r--r-- root root 221 ./usr/share/awk/have_mpfr.awk
+-rw-r--r-- root root 1992 ./usr/share/awk/inplace.awk
+-rw-r--r-- root root 462 ./usr/share/awk/intdiv0.awk
+-rw-r--r-- root root 378 ./usr/share/awk/join.awk
+-rw-r--r-- root root 238 ./usr/share/awk/libintl.awk
+-rw-r--r-- root root 422 ./usr/share/awk/noassign.awk
+-rw-r--r-- root root 1282 ./usr/share/awk/ns_passwd.awk
+-rw-r--r-- root root 937 ./usr/share/awk/ord.awk
+-rw-r--r-- root root 1199 ./usr/share/awk/passwd.awk
+-rw-r--r-- root root 355 ./usr/share/awk/processarray.awk
+-rw-r--r-- root root 1031 ./usr/share/awk/quicksort.awk
+-rw-r--r-- root root 489 ./usr/share/awk/readable.awk
+-rw-r--r-- root root 267 ./usr/share/awk/readfile.awk
+-rw-r--r-- root root 404 ./usr/share/awk/rewind.awk
+-rw-r--r-- root root 661 ./usr/share/awk/round.awk
+-rw-r--r-- root root 472 ./usr/share/awk/shellquote.awk
+-rw-r--r-- root root 1454 ./usr/share/awk/strtonum.awk
+-rw-r--r-- root root 214 ./usr/share/awk/walkarray.awk
+-rw-r--r-- root root 424 ./usr/share/awk/zerofile.awk
+drwxr-xr-x root root 4096 ./usr/share/bash-completion
+-rw-r--r-- root root 74302 ./usr/share/bash-completion/bash_completion
+drwxr-xr-x root root 4096 ./usr/share/bison
+-rw-r--r-- root root 1147 ./usr/share/bison/bison-default.css
+drwxr-xr-x root root 4096 ./usr/share/bison/m4sugar
+-rw-r--r-- root root 14755 ./usr/share/bison/m4sugar/foreach.m4
+-rw-r--r-- root root 122297 ./usr/share/bison/m4sugar/m4sugar.m4
+-rw-r--r-- root root 6832 ./usr/share/bison/README.md
+drwxr-xr-x root root 4096 ./usr/share/bison/skeletons
+-rw-r--r-- root root 39019 ./usr/share/bison/skeletons/bison.m4
+-rw-r--r-- root root 2404 ./usr/share/bison/skeletons/c-like.m4
+-rw-r--r-- root root 29832 ./usr/share/bison/skeletons/c.m4
+-rw-r--r-- root root 19123 ./usr/share/bison/skeletons/c++.m4
+-rw-r--r-- root root 1163 ./usr/share/bison/skeletons/c-skel.m4
+-rw-r--r-- root root 1169 ./usr/share/bison/skeletons/c++-skel.m4
+-rw-r--r-- root root 9790 ./usr/share/bison/skeletons/d.m4
+-rw-r--r-- root root 1135 ./usr/share/bison/skeletons/d-skel.m4
+-rw-r--r-- root root 87461 ./usr/share/bison/skeletons/glr.c
+-rw-r--r-- root root 11938 ./usr/share/bison/skeletons/glr.cc
+-rw-r--r-- root root 10796 ./usr/share/bison/skeletons/java.m4
+-rw-r--r-- root root 1166 ./usr/share/bison/skeletons/java-skel.m4
+-rw-r--r-- root root 46677 ./usr/share/bison/skeletons/lalr1.cc
+-rw-r--r-- root root 29428 ./usr/share/bison/skeletons/lalr1.d
+-rw-r--r-- root root 34757 ./usr/share/bison/skeletons/lalr1.java
+-rw-r--r-- root root 10331 ./usr/share/bison/skeletons/location.cc
+-rw-r--r-- root root 1898 ./usr/share/bison/skeletons/README-D.txt
+-rw-r--r-- root root 3854 ./usr/share/bison/skeletons/stack.hh
+-rw-r--r-- root root 12992 ./usr/share/bison/skeletons/variant.hh
+-rw-r--r-- root root 66135 ./usr/share/bison/skeletons/yacc.c
+drwxr-xr-x root root 4096 ./usr/share/bison/xslt
+-rw-r--r-- root root 3364 ./usr/share/bison/xslt/bison.xsl
+-rw-r--r-- root root 12820 ./usr/share/bison/xslt/xml2dot.xsl
+-rw-r--r-- root root 18554 ./usr/share/bison/xslt/xml2text.xsl
+-rw-r--r-- root root 22678 ./usr/share/bison/xslt/xml2xhtml.xsl
+drwxr-xr-x root root 4096 ./usr/share/ca-certificates
+drwxr-xr-x root root 12288 ./usr/share/ca-certificates/mozilla
+-rw-r--r-- root root 2772 ./usr/share/ca-certificates/mozilla/ACCVRAIZ1.crt
+-rw-r--r-- root root 1972 ./usr/share/ca-certificates/mozilla/AC_RAIZ_FNMT-RCM.crt
+-rw-r--r-- root root 2049 ./usr/share/ca-certificates/mozilla/Actalis_Authentication_Root_CA.crt
+-rw-r--r-- root root 1521 ./usr/share/ca-certificates/mozilla/AddTrust_External_Root.crt
+-rw-r--r-- root root 1204 ./usr/share/ca-certificates/mozilla/AffirmTrust_Commercial.crt
+-rw-r--r-- root root 1204 ./usr/share/ca-certificates/mozilla/AffirmTrust_Networking.crt
+-rw-r--r-- root root 1891 ./usr/share/ca-certificates/mozilla/AffirmTrust_Premium.crt
+-rw-r--r-- root root 753 ./usr/share/ca-certificates/mozilla/AffirmTrust_Premium_ECC.crt
+-rw-r--r-- root root 1188 ./usr/share/ca-certificates/mozilla/Amazon_Root_CA_1.crt
+-rw-r--r-- root root 1883 ./usr/share/ca-certificates/mozilla/Amazon_Root_CA_2.crt
+-rw-r--r-- root root 656 ./usr/share/ca-certificates/mozilla/Amazon_Root_CA_3.crt
+-rw-r--r-- root root 737 ./usr/share/ca-certificates/mozilla/Amazon_Root_CA_4.crt
+-rw-r--r-- root root 1261 ./usr/share/ca-certificates/mozilla/Atos_TrustedRoot_2011.crt
+-rw-r--r-- root root 2167 ./usr/share/ca-certificates/mozilla/Autoridad_de_Certificacion_Firmaprofesional_CIF_A62634068.crt
+-rw-r--r-- root root 1261 ./usr/share/ca-certificates/mozilla/Baltimore_CyberTrust_Root.crt
+-rw-r--r-- root root 1915 ./usr/share/ca-certificates/mozilla/Buypass_Class_2_Root_CA.crt
+-rw-r--r-- root root 1915 ./usr/share/ca-certificates/mozilla/Buypass_Class_3_Root_CA.crt
+-rw-r--r-- root root 1935 ./usr/share/ca-certificates/mozilla/CA_Disig_Root_R2.crt
+-rw-r--r-- root root 1330 ./usr/share/ca-certificates/mozilla/Certigna.crt
+-rw-r--r-- root root 1992 ./usr/share/ca-certificates/mozilla/Certinomis_-_Root_CA.crt
+-rw-r--r-- root root 1298 ./usr/share/ca-certificates/mozilla/Certplus_Class_2_Primary_CA.crt
+-rw-r--r-- root root 1176 ./usr/share/ca-certificates/mozilla/certSIGN_ROOT_CA.crt
+-rw-r--r-- root root 2078 ./usr/share/ca-certificates/mozilla/Certum_Trusted_Network_CA_2.crt
+-rw-r--r-- root root 1354 ./usr/share/ca-certificates/mozilla/Certum_Trusted_Network_CA.crt
+-rw-r--r-- root root 1984 ./usr/share/ca-certificates/mozilla/CFCA_EV_ROOT.crt
+-rw-r--r-- root root 2594 ./usr/share/ca-certificates/mozilla/Chambers_of_Commerce_Root_-_2008.crt
+-rw-r--r-- root root 1517 ./usr/share/ca-certificates/mozilla/Comodo_AAA_Services_root.crt
+-rw-r--r-- root root 1489 ./usr/share/ca-certificates/mozilla/COMODO_Certification_Authority.crt
+-rw-r--r-- root root 940 ./usr/share/ca-certificates/mozilla/COMODO_ECC_Certification_Authority.crt
+-rw-r--r-- root root 2086 ./usr/share/ca-certificates/mozilla/COMODO_RSA_Certification_Authority.crt
+-rw-r--r-- root root 1318 ./usr/share/ca-certificates/mozilla/Cybertrust_Global_Root.crt
+-rw-r--r-- root root 1318 ./usr/share/ca-certificates/mozilla/Deutsche_Telekom_Root_CA_2.crt
+-rw-r--r-- root root 1350 ./usr/share/ca-certificates/mozilla/DigiCert_Assured_ID_Root_CA.crt
+-rw-r--r-- root root 1306 ./usr/share/ca-certificates/mozilla/DigiCert_Assured_ID_Root_G2.crt
+-rw-r--r-- root root 851 ./usr/share/ca-certificates/mozilla/DigiCert_Assured_ID_Root_G3.crt
+-rw-r--r-- root root 1338 ./usr/share/ca-certificates/mozilla/DigiCert_Global_Root_CA.crt
+-rw-r--r-- root root 1294 ./usr/share/ca-certificates/mozilla/DigiCert_Global_Root_G2.crt
+-rw-r--r-- root root 839 ./usr/share/ca-certificates/mozilla/DigiCert_Global_Root_G3.crt
+-rw-r--r-- root root 1367 ./usr/share/ca-certificates/mozilla/DigiCert_High_Assurance_EV_Root_CA.crt
+-rw-r--r-- root root 1988 ./usr/share/ca-certificates/mozilla/DigiCert_Trusted_Root_G4.crt
+-rw-r--r-- root root 1200 ./usr/share/ca-certificates/mozilla/DST_Root_CA_X3.crt
+-rw-r--r-- root root 1517 ./usr/share/ca-certificates/mozilla/D-TRUST_Root_Class_3_CA_2_2009.crt
+-rw-r--r-- root root 1537 ./usr/share/ca-certificates/mozilla/D-TRUST_Root_Class_3_CA_2_EV_2009.crt
+-rw-r--r-- root root 1911 ./usr/share/ca-certificates/mozilla/EC-ACC.crt
+-rw-r--r-- root root 1452 ./usr/share/ca-certificates/mozilla/EE_Certification_Centre_Root_CA.crt
+-rw-r--r-- root root 1505 ./usr/share/ca-certificates/mozilla/Entrust.net_Premium_2048_Secure_Server_CA.crt
+-rw-r--r-- root root 1643 ./usr/share/ca-certificates/mozilla/Entrust_Root_Certification_Authority.crt
+-rw-r--r-- root root 1090 ./usr/share/ca-certificates/mozilla/Entrust_Root_Certification_Authority_-_EC1.crt
+-rw-r--r-- root root 1533 ./usr/share/ca-certificates/mozilla/Entrust_Root_Certification_Authority_-_G2.crt
+-rw-r--r-- root root 2033 ./usr/share/ca-certificates/mozilla/ePKI_Root_Certification_Authority.crt
+-rw-r--r-- root root 2244 ./usr/share/ca-certificates/mozilla/E-Tugra_Certification_Authority.crt
+-rw-r--r-- root root 1980 ./usr/share/ca-certificates/mozilla/GDCA_TrustAUTH_R5_ROOT.crt
+-rw-r--r-- root root 1216 ./usr/share/ca-certificates/mozilla/GeoTrust_Global_CA.crt
+-rw-r--r-- root root 1269 ./usr/share/ca-certificates/mozilla/GeoTrust_Primary_Certification_Authority.crt
+-rw-r--r-- root root 989 ./usr/share/ca-certificates/mozilla/GeoTrust_Primary_Certification_Authority_-_G2.crt
+-rw-r--r-- root root 1444 ./usr/share/ca-certificates/mozilla/GeoTrust_Primary_Certification_Authority_-_G3.crt
+-rw-r--r-- root root 1939 ./usr/share/ca-certificates/mozilla/GeoTrust_Universal_CA_2.crt
+-rw-r--r-- root root 1935 ./usr/share/ca-certificates/mozilla/GeoTrust_Universal_CA.crt
+-rw-r--r-- root root 2585 ./usr/share/ca-certificates/mozilla/Global_Chambersign_Root_-_2008.crt
+-rw-r--r-- root root 713 ./usr/share/ca-certificates/mozilla/GlobalSign_ECC_Root_CA_-_R4.crt
+-rw-r--r-- root root 794 ./usr/share/ca-certificates/mozilla/GlobalSign_ECC_Root_CA_-_R5.crt
+-rw-r--r-- root root 1261 ./usr/share/ca-certificates/mozilla/GlobalSign_Root_CA.crt
+-rw-r--r-- root root 1354 ./usr/share/ca-certificates/mozilla/GlobalSign_Root_CA_-_R2.crt
+-rw-r--r-- root root 1229 ./usr/share/ca-certificates/mozilla/GlobalSign_Root_CA_-_R3.crt
+-rw-r--r-- root root 1972 ./usr/share/ca-certificates/mozilla/GlobalSign_Root_CA_-_R6.crt
+-rw-r--r-- root root 1448 ./usr/share/ca-certificates/mozilla/Go_Daddy_Class_2_CA.crt
+-rw-r--r-- root root 1367 ./usr/share/ca-certificates/mozilla/Go_Daddy_Root_Certificate_Authority_-_G2.crt
+-rw-r--r-- root root 1017 ./usr/share/ca-certificates/mozilla/Hellenic_Academic_and_Research_Institutions_ECC_RootCA_2015.crt
+-rw-r--r-- root root 1513 ./usr/share/ca-certificates/mozilla/Hellenic_Academic_and_Research_Institutions_RootCA_2011.crt
+-rw-r--r-- root root 2155 ./usr/share/ca-certificates/mozilla/Hellenic_Academic_and_Research_Institutions_RootCA_2015.crt
+-rw-r--r-- root root 1168 ./usr/share/ca-certificates/mozilla/Hongkong_Post_Root_CA_1.crt
+-rw-r--r-- root root 1923 ./usr/share/ca-certificates/mozilla/IdenTrust_Commercial_Root_CA_1.crt
+-rw-r--r-- root root 1931 ./usr/share/ca-certificates/mozilla/IdenTrust_Public_Sector_Root_CA_1.crt
+-rw-r--r-- root root 1939 ./usr/share/ca-certificates/mozilla/ISRG_Root_X1.crt
+-rw-r--r-- root root 2122 ./usr/share/ca-certificates/mozilla/Izenpe.com.crt
+-rw-r--r-- root root 2057 ./usr/share/ca-certificates/mozilla/LuxTrust_Global_Root_2.crt
+-rw-r--r-- root root 1460 ./usr/share/ca-certificates/mozilla/Microsec_e-Szigno_Root_CA_2009.crt
+-rw-r--r-- root root 1476 ./usr/share/ca-certificates/mozilla/NetLock_Arany_=Class_Gold=_Főtanúsítvány.crt
+-rw-r--r-- root root 1411 ./usr/share/ca-certificates/mozilla/Network_Solutions_Certificate_Authority.crt
+-rw-r--r-- root root 1428 ./usr/share/ca-certificates/mozilla/OISTE_WISeKey_Global_Root_GA_CA.crt
+-rw-r--r-- root root 1346 ./usr/share/ca-certificates/mozilla/OISTE_WISeKey_Global_Root_GB_CA.crt
+-rw-r--r-- root root 895 ./usr/share/ca-certificates/mozilla/OISTE_WISeKey_Global_Root_GC_CA.crt
+-rw-r--r-- root root 1923 ./usr/share/ca-certificates/mozilla/QuoVadis_Root_CA_1_G3.crt
+-rw-r--r-- root root 2041 ./usr/share/ca-certificates/mozilla/QuoVadis_Root_CA_2.crt
+-rw-r--r-- root root 1923 ./usr/share/ca-certificates/mozilla/QuoVadis_Root_CA_2_G3.crt
+-rw-r--r-- root root 2354 ./usr/share/ca-certificates/mozilla/QuoVadis_Root_CA_3.crt
+-rw-r--r-- root root 1923 ./usr/share/ca-certificates/mozilla/QuoVadis_Root_CA_3_G3.crt
+-rw-r--r-- root root 2078 ./usr/share/ca-certificates/mozilla/QuoVadis_Root_CA.crt
+-rw-r--r-- root root 1354 ./usr/share/ca-certificates/mozilla/Secure_Global_CA.crt
+-rw-r--r-- root root 1249 ./usr/share/ca-certificates/mozilla/SecureSign_RootCA11.crt
+-rw-r--r-- root root 1350 ./usr/share/ca-certificates/mozilla/SecureTrust_CA.crt
+-rw-r--r-- root root 1261 ./usr/share/ca-certificates/mozilla/Security_Communication_RootCA2.crt
+-rw-r--r-- root root 1224 ./usr/share/ca-certificates/mozilla/Security_Communication_Root_CA.crt
+-rw-r--r-- root root 1143 ./usr/share/ca-certificates/mozilla/Sonera_Class_2_Root_CA.crt
+-rw-r--r-- root root 956 ./usr/share/ca-certificates/mozilla/SSL.com_EV_Root_Certification_Authority_ECC.crt
+-rw-r--r-- root root 2114 ./usr/share/ca-certificates/mozilla/SSL.com_EV_Root_Certification_Authority_RSA_R2.crt
+-rw-r--r-- root root 944 ./usr/share/ca-certificates/mozilla/SSL.com_Root_Certification_Authority_ECC.crt
+-rw-r--r-- root root 2094 ./usr/share/ca-certificates/mozilla/SSL.com_Root_Certification_Authority_RSA.crt
+-rw-r--r-- root root 1948 ./usr/share/ca-certificates/mozilla/Staat_der_Nederlanden_EV_Root_CA.crt
+-rw-r--r-- root root 2069 ./usr/share/ca-certificates/mozilla/Staat_der_Nederlanden_Root_CA_-_G2.crt
+-rw-r--r-- root root 1952 ./usr/share/ca-certificates/mozilla/Staat_der_Nederlanden_Root_CA_-_G3.crt
+-rw-r--r-- root root 1468 ./usr/share/ca-certificates/mozilla/Starfield_Class_2_CA.crt
+-rw-r--r-- root root 1399 ./usr/share/ca-certificates/mozilla/Starfield_Root_Certificate_Authority_-_G2.crt
+-rw-r--r-- root root 1424 ./usr/share/ca-certificates/mozilla/Starfield_Services_Root_Certificate_Authority_-_G2.crt
+-rw-r--r-- root root 2045 ./usr/share/ca-certificates/mozilla/SwissSign_Gold_CA_-_G2.crt
+-rw-r--r-- root root 2049 ./usr/share/ca-certificates/mozilla/SwissSign_Silver_CA_-_G2.crt
+-rw-r--r-- root root 1257 ./usr/share/ca-certificates/mozilla/SZAFIR_ROOT_CA2.crt
+-rw-r--r-- root root 1948 ./usr/share/ca-certificates/mozilla/Taiwan_GRCA.crt
+-rw-r--r-- root root 1870 ./usr/share/ca-certificates/mozilla/TeliaSonera_Root_CA_v1.crt
+-rw-r--r-- root root 1493 ./usr/share/ca-certificates/mozilla/thawte_Primary_Root_CA.crt
+-rw-r--r-- root root 940 ./usr/share/ca-certificates/mozilla/thawte_Primary_Root_CA_-_G2.crt
+-rw-r--r-- root root 1505 ./usr/share/ca-certificates/mozilla/thawte_Primary_Root_CA_-_G3.crt
+-rw-r--r-- root root 1493 ./usr/share/ca-certificates/mozilla/TrustCor_ECA-1.crt
+-rw-r--r-- root root 1513 ./usr/share/ca-certificates/mozilla/TrustCor_RootCert_CA-1.crt
+-rw-r--r-- root root 2204 ./usr/share/ca-certificates/mozilla/TrustCor_RootCert_CA-2.crt
+-rw-r--r-- root root 1241 ./usr/share/ca-certificates/mozilla/Trustis_FPS_Root_CA.crt
+-rw-r--r-- root root 1367 ./usr/share/ca-certificates/mozilla/T-TeleSec_GlobalRoot_Class_2.crt
+-rw-r--r-- root root 1367 ./usr/share/ca-certificates/mozilla/T-TeleSec_GlobalRoot_Class_3.crt
+-rw-r--r-- root root 1582 ./usr/share/ca-certificates/mozilla/TUBITAK_Kamu_SM_SSL_Kok_Sertifikasi_-_Surum_1.crt
+-rw-r--r-- root root 1883 ./usr/share/ca-certificates/mozilla/TWCA_Global_Root_CA.crt
+-rw-r--r-- root root 1269 ./usr/share/ca-certificates/mozilla/TWCA_Root_Certification_Authority.crt
+-rw-r--r-- root root 948 ./usr/share/ca-certificates/mozilla/USERTrust_ECC_Certification_Authority.crt
+-rw-r--r-- root root 2094 ./usr/share/ca-certificates/mozilla/USERTrust_RSA_Certification_Authority.crt
+-rw-r--r-- root root 1484 ./usr/share/ca-certificates/mozilla/Verisign_Class_3_Public_Primary_Certification_Authority_-_G3.crt
+-rw-r--r-- root root 1281 ./usr/share/ca-certificates/mozilla/VeriSign_Class_3_Public_Primary_Certification_Authority_-_G4.crt
+-rw-r--r-- root root 1732 ./usr/share/ca-certificates/mozilla/VeriSign_Class_3_Public_Primary_Certification_Authority_-_G5.crt
+-rw-r--r-- root root 1700 ./usr/share/ca-certificates/mozilla/VeriSign_Universal_Root_Certification_Authority.crt
+-rw-r--r-- root root 1513 ./usr/share/ca-certificates/mozilla/XRamp_Global_CA_Root.crt
+drwxr-xr-x root root 4096 ./usr/share/cmake
+drwxr-xr-x root root 4096 ./usr/share/cmake/bash-completion
+-rw-r--r-- root root 393 ./usr/share/cmake/bash-completion/bash-completion-config.cmake
+-rw-r--r-- root root 252 ./usr/share/cmake/bash-completion/bash-completion-config-version.cmake
+drwxr-xr-x root root 4096 ./usr/share/dbus-1
+drwxr-xr-x root root 4096 ./usr/share/dbus-1/services
+-rw-r--r-- root root 3561 ./usr/share/dbus-1/session.conf
+drwxr-xr-x root root 4096 ./usr/share/dbus-1/session.d
+-rw-r--r-- root root 5692 ./usr/share/dbus-1/system.conf
+drwxr-xr-x root root 4096 ./usr/share/dbus-1/system.d
+drwxr-xr-x root root 4096 ./usr/share/dbus-1/system-services
+drwxr-xr-x root root 4096 ./usr/share/dict
+drwxr-xr-x root root 4096 ./usr/share/drirc.d
+-rw-r--r-- root root 27422 ./usr/share/drirc.d/00-mesa-defaults.conf
+drwxr-xr-x root root 4096 ./usr/share/et
+-rw-r--r-- root root 6485 ./usr/share/et/et_c.awk
+-rw-r--r-- root root 4539 ./usr/share/et/et_h.awk
+drwxr-xr-x root root 4096 ./usr/share/fontconfig
+drwxr-xr-x root root 4096 ./usr/share/fontconfig/conf.avail
+-rw-r--r-- root root 706 ./usr/share/fontconfig/conf.avail/10-autohint.conf
+-rw-r--r-- root root 692 ./usr/share/fontconfig/conf.avail/10-hinting-full.conf
+-rw-r--r-- root root 696 ./usr/share/fontconfig/conf.avail/10-hinting-medium.conf
+-rw-r--r-- root root 692 ./usr/share/fontconfig/conf.avail/10-hinting-none.conf
+-rw-r--r-- root root 696 ./usr/share/fontconfig/conf.avail/10-hinting-slight.conf
+-rw-r--r-- root root 723 ./usr/share/fontconfig/conf.avail/10-no-sub-pixel.conf
+-rw-r--r-- root root 2228 ./usr/share/fontconfig/conf.avail/10-scale-bitmap-fonts.conf
+-rw-r--r-- root root 748 ./usr/share/fontconfig/conf.avail/10-sub-pixel-bgr.conf
+-rw-r--r-- root root 748 ./usr/share/fontconfig/conf.avail/10-sub-pixel-rgb.conf
+-rw-r--r-- root root 758 ./usr/share/fontconfig/conf.avail/10-sub-pixel-vbgr.conf
+-rw-r--r-- root root 758 ./usr/share/fontconfig/conf.avail/10-sub-pixel-vrgb.conf
+-rw-r--r-- root root 701 ./usr/share/fontconfig/conf.avail/10-unhinted.conf
+-rw-r--r-- root root 771 ./usr/share/fontconfig/conf.avail/11-lcdfilter-default.conf
+-rw-r--r-- root root 768 ./usr/share/fontconfig/conf.avail/11-lcdfilter-legacy.conf
+-rw-r--r-- root root 765 ./usr/share/fontconfig/conf.avail/11-lcdfilter-light.conf
+-rw-r--r-- root root 1537 ./usr/share/fontconfig/conf.avail/20-unhint-small-vera.conf
+-rw-r--r-- root root 3489 ./usr/share/fontconfig/conf.avail/25-unhint-nonlatin.conf
+-rw-r--r-- root root 13274 ./usr/share/fontconfig/conf.avail/30-metric-aliases.conf
+-rw-r--r-- root root 5424 ./usr/share/fontconfig/conf.avail/40-nonlatin.conf
+-rw-r--r-- root root 3543 ./usr/share/fontconfig/conf.avail/45-generic.conf
+-rw-r--r-- root root 6600 ./usr/share/fontconfig/conf.avail/45-latin.conf
+-rw-r--r-- root root 799 ./usr/share/fontconfig/conf.avail/49-sansserif.conf
+-rw-r--r-- root root 911 ./usr/share/fontconfig/conf.avail/50-user.conf
+-rw-r--r-- root root 423 ./usr/share/fontconfig/conf.avail/51-local.conf
+-rw-r--r-- root root 2041 ./usr/share/fontconfig/conf.avail/60-generic.conf
+-rw-r--r-- root root 2068 ./usr/share/fontconfig/conf.avail/60-latin.conf
+-rw-r--r-- root root 10293 ./usr/share/fontconfig/conf.avail/65-fonts-persian.conf
+-rw-r--r-- root root 464 ./usr/share/fontconfig/conf.avail/65-khmer.conf
+-rw-r--r-- root root 8170 ./usr/share/fontconfig/conf.avail/65-nonlatin.conf
+-rw-r--r-- root root 847 ./usr/share/fontconfig/conf.avail/69-unifont.conf
+-rw-r--r-- root root 487 ./usr/share/fontconfig/conf.avail/70-no-bitmaps.conf
+-rw-r--r-- root root 487 ./usr/share/fontconfig/conf.avail/70-yes-bitmaps.conf
+-rw-r--r-- root root 597 ./usr/share/fontconfig/conf.avail/80-delicious.conf
+-rw-r--r-- root root 1917 ./usr/share/fontconfig/conf.avail/90-synthetic.conf
+drwxr-xr-x root root 4096 ./usr/share/gettext
+drwxr-xr-x root root 4096 ./usr/share/gettext/its
+-rw-r--r-- root root 189 ./usr/share/gettext/its/fontconfig.its
+-rw-r--r-- root root 189 ./usr/share/gettext/its/fontconfig.loc
+-rw-r--r-- root root 1048 ./usr/share/gettext/its/gschema.its
+-rw-r--r-- root root 333 ./usr/share/gettext/its/gschema.loc
+drwxr-xr-x root root 4096 ./usr/share/gir-1.0
+-rw-r--r-- root root 23723 ./usr/share/gir-1.0/cairo-1.0.gir
+-rw-r--r-- root root 1185 ./usr/share/gir-1.0/DBus-1.0.gir
+-rw-r--r-- root root 797 ./usr/share/gir-1.0/DBusGLib-1.0.gir
+-rw-r--r-- root root 620 ./usr/share/gir-1.0/fontconfig-2.0.gir
+-rw-r--r-- root root 768 ./usr/share/gir-1.0/freetype2-2.0.gir
+-rw-r--r-- root root 6332887 ./usr/share/gir-1.0/Gio-2.0.gir
+-rw-r--r-- root root 29235 ./usr/share/gir-1.0/gir-1.2.rnc
+-rw-r--r-- root root 324506 ./usr/share/gir-1.0/GIRepository-2.0.gir
+-rw-r--r-- root root 1122 ./usr/share/gir-1.0/GL-1.0.gir
+-rw-r--r-- root root 3544680 ./usr/share/gir-1.0/GLib-2.0.gir
+-rw-r--r-- root root 19691 ./usr/share/gir-1.0/GModule-2.0.gir
+-rw-r--r-- root root 1247584 ./usr/share/gir-1.0/GObject-2.0.gir
+-rw-r--r-- root root 938 ./usr/share/gir-1.0/libxml2-2.0.gir
+-rw-r--r-- root root 65349 ./usr/share/gir-1.0/Vulkan-1.0.gir
+-rw-r--r-- root root 611 ./usr/share/gir-1.0/win32-1.0.gir
+-rw-r--r-- root root 361 ./usr/share/gir-1.0/xfixes-4.0.gir
+-rw-r--r-- root root 745 ./usr/share/gir-1.0/xft-2.0.gir
+-rw-r--r-- root root 2325 ./usr/share/gir-1.0/xlib-2.0.gir
+-rw-r--r-- root root 808 ./usr/share/gir-1.0/xrandr-1.3.gir
+drwxr-xr-x root root 4096 ./usr/share/glib-2.0
+drwxr-xr-x root root 4096 ./usr/share/glib-2.0/gettext
+drwxr-xr-x root root 4096 ./usr/share/glib-2.0/gettext/po
+-rw-r--r-- root root 8076 ./usr/share/glib-2.0/gettext/po/Makefile.in.in
+drwxr-xr-x root root 4096 ./usr/share/glib-2.0/schemas
+-rw-r--r-- root root 2916 ./usr/share/glib-2.0/schemas/gschema.dtd
+drwxr-xr-x root root 4096 ./usr/share/glib-2.0/valgrind
+-rw-r--r-- root root 15263 ./usr/share/glib-2.0/valgrind/glib.supp
+drwxr-xr-x root root 4096 ./usr/share/gobject-introspection-1.0
+-rw-r--r-- root root 15228 ./usr/share/gobject-introspection-1.0/gdump.c
+-rw-r--r-- root root 7177 ./usr/share/gobject-introspection-1.0/Makefile.introspection
+drwxr-xr-x root root 4096 ./usr/share/info
+drwxr-xr-x root root 4096 ./usr/share/libdrm
+-rw-r--r-- root root 7547 ./usr/share/libdrm/amdgpu.ids
+drwxr-xr-x root root 4096 ./usr/share/man
+drwxr-xr-x root root 4096 ./usr/share/mime
+-rw-r--r-- root root 10777 ./usr/share/mime/aliases
+drwxr-xr-x root root 20480 ./usr/share/mime/application
+-rw-r--r-- root root 2700 ./usr/share/mime/application/andrew-inset.xml
+-rw-r--r-- root root 3200 ./usr/share/mime/application/annodex.xml
+-rw-r--r-- root root 3123 ./usr/share/mime/application/atom+xml.xml
+-rw-r--r-- root root 3009 ./usr/share/mime/application/dicom.xml
+-rw-r--r-- root root 3299 ./usr/share/mime/application/ecmascript.xml
+-rw-r--r-- root root 3513 ./usr/share/mime/application/epub+zip.xml
+-rw-r--r-- root root 2263 ./usr/share/mime/application/geo+json.xml
+-rw-r--r-- root root 2304 ./usr/share/mime/application/gml+xml.xml
+-rw-r--r-- root root 3264 ./usr/share/mime/application/gnunet-directory.xml
+-rw-r--r-- root root 2354 ./usr/share/mime/application/gpx+xml.xml
+-rw-r--r-- root root 2813 ./usr/share/mime/application/gzip.xml
+-rw-r--r-- root root 3757 ./usr/share/mime/application/illustrator.xml
+-rw-r--r-- root root 3404 ./usr/share/mime/application/javascript.xml
+-rw-r--r-- root root 2140 ./usr/share/mime/application/jrd+json.xml
+-rw-r--r-- root root 1993 ./usr/share/mime/application/json-patch+json.xml
+-rw-r--r-- root root 2281 ./usr/share/mime/application/json.xml
+-rw-r--r-- root root 2255 ./usr/share/mime/application/ld+json.xml
+-rw-r--r-- root root 4240 ./usr/share/mime/application/mac-binhex40.xml
+-rw-r--r-- root root 1136 ./usr/share/mime/application/mathematica.xml
+-rw-r--r-- root root 3328 ./usr/share/mime/application/mathml+xml.xml
+-rw-r--r-- root root 3112 ./usr/share/mime/application/mbox.xml
+-rw-r--r-- root root 2759 ./usr/share/mime/application/metalink4+xml.xml
+-rw-r--r-- root root 2761 ./usr/share/mime/application/metalink+xml.xml
+-rw-r--r-- root root 2925 ./usr/share/mime/application/msword-template.xml
+-rw-r--r-- root root 3057 ./usr/share/mime/application/msword.xml
+-rw-r--r-- root root 2615 ./usr/share/mime/application/mxf.xml
+-rw-r--r-- root root 2687 ./usr/share/mime/application/octet-stream.xml
+-rw-r--r-- root root 3111 ./usr/share/mime/application/oda.xml
+-rw-r--r-- root root 3393 ./usr/share/mime/application/ogg.xml
+-rw-r--r-- root root 2057 ./usr/share/mime/application/owl+xml.xml
+-rw-r--r-- root root 3059 ./usr/share/mime/application/oxps.xml
+-rw-r--r-- root root 3131 ./usr/share/mime/application/pdf.xml
+-rw-r--r-- root root 4545 ./usr/share/mime/application/pgp-encrypted.xml
+-rw-r--r-- root root 3138 ./usr/share/mime/application/pgp-keys.xml
+-rw-r--r-- root root 3716 ./usr/share/mime/application/pgp-signature.xml
+-rw-r--r-- root root 3686 ./usr/share/mime/application/pkcs10.xml
+-rw-r--r-- root root 3703 ./usr/share/mime/application/pkcs12.xml
+-rw-r--r-- root root 1090 ./usr/share/mime/application/pkcs7-mime.xml
+-rw-r--r-- root root 3684 ./usr/share/mime/application/pkcs7-signature.xml
+-rw-r--r-- root root 2231 ./usr/share/mime/application/pkcs8-encrypted.xml
+-rw-r--r-- root root 2936 ./usr/share/mime/application/pkcs8.xml
+-rw-r--r-- root root 2674 ./usr/share/mime/application/pkix-cert.xml
+-rw-r--r-- root root 1120 ./usr/share/mime/application/pkix-crl.xml
+-rw-r--r-- root root 3306 ./usr/share/mime/application/pkix-pkipath.xml
+-rw-r--r-- root root 1110 ./usr/share/mime/application/postscript.xml
+-rw-r--r-- root root 3011 ./usr/share/mime/application/prs.plucker.xml
+-rw-r--r-- root root 1992 ./usr/share/mime/application/raml+yaml.xml
+-rw-r--r-- root root 1115 ./usr/share/mime/application/ram.xml
+-rw-r--r-- root root 2800 ./usr/share/mime/application/rdf+xml.xml
+-rw-r--r-- root root 2940 ./usr/share/mime/application/relax-ng-compact-syntax.xml
+-rw-r--r-- root root 2927 ./usr/share/mime/application/rss+xml.xml
+-rw-r--r-- root root 2954 ./usr/share/mime/application/rtf.xml
+-rw-r--r-- root root 3857 ./usr/share/mime/application/sdp.xml
+-rw-r--r-- root root 3701 ./usr/share/mime/application/sieve.xml
+-rw-r--r-- root root 3131 ./usr/share/mime/application/smil+xml.xml
+-rw-r--r-- root root 2733 ./usr/share/mime/application/sql.xml
+-rw-r--r-- root root 2434 ./usr/share/mime/application/trig.xml
+-rw-r--r-- root root 3433 ./usr/share/mime/application/vnd.adobe.flash.movie.xml
+-rw-r--r-- root root 432 ./usr/share/mime/application/vnd.amazon.mobi8-ebook.xml
+-rw-r--r-- root root 2605 ./usr/share/mime/application/vnd.android.package-archive.xml
+-rw-r--r-- root root 2358 ./usr/share/mime/application/vnd.appimage.xml
+-rw-r--r-- root root 3597 ./usr/share/mime/application/vnd.apple.mpegurl.xml
+-rw-r--r-- root root 3598 ./usr/share/mime/application/vnd.chess-pgn.xml
+-rw-r--r-- root root 2381 ./usr/share/mime/application/vnd.coffeescript.xml
+-rw-r--r-- root root 3230 ./usr/share/mime/application/vnd.comicbook-rar.xml
+-rw-r--r-- root root 3226 ./usr/share/mime/application/vnd.comicbook+zip.xml
+-rw-r--r-- root root 3655 ./usr/share/mime/application/vnd.corel-draw.xml
+-rw-r--r-- root root 3205 ./usr/share/mime/application/vnd.debian.binary-package.xml
+-rw-r--r-- root root 3403 ./usr/share/mime/application/vnd.emusic-emusic_package.xml
+-rw-r--r-- root root 2211 ./usr/share/mime/application/vnd.flatpak.ref.xml
+-rw-r--r-- root root 2273 ./usr/share/mime/application/vnd.flatpak.repo.xml
+-rw-r--r-- root root 2279 ./usr/share/mime/application/vnd.flatpak.xml
+-rw-r--r-- root root 3675 ./usr/share/mime/application/vnd.framemaker.xml
+-rw-r--r-- root root 3051 ./usr/share/mime/application/vnd.google-earth.kml+xml.xml
+-rw-r--r-- root root 3579 ./usr/share/mime/application/vnd.google-earth.kmz.xml
+-rw-r--r-- root root 2820 ./usr/share/mime/application/vnd.hp-hpgl.xml
+-rw-r--r-- root root 2769 ./usr/share/mime/application/vnd.hp-pcl.xml
+-rw-r--r-- root root 2536 ./usr/share/mime/application/vnd.iccprofile.xml
+-rw-r--r-- root root 3991 ./usr/share/mime/application/vnd.lotus-1-2-3.xml
+-rw-r--r-- root root 1142 ./usr/share/mime/application/vnd.lotus-wordpro.xml
+-rw-r--r-- root root 3540 ./usr/share/mime/application/vnd.mozilla.xul+xml.xml
+-rw-r--r-- root root 3419 ./usr/share/mime/application/vnd.ms-access.xml
+-rw-r--r-- root root 2921 ./usr/share/mime/application/vnd.ms-asf.xml
+-rw-r--r-- root root 3299 ./usr/share/mime/application/vnd.ms-cab-compressed.xml
+-rw-r--r-- root root 2619 ./usr/share/mime/application/vnd.ms-excel.addin.macroenabled.12.xml
+-rw-r--r-- root root 3407 ./usr/share/mime/application/vnd.ms-excel.sheet.binary.macroenabled.12.xml
+-rw-r--r-- root root 3330 ./usr/share/mime/application/vnd.ms-excel.sheet.macroenabled.12.xml
+-rw-r--r-- root root 2685 ./usr/share/mime/application/vnd.ms-excel.template.macroenabled.12.xml
+-rw-r--r-- root root 3525 ./usr/share/mime/application/vnd.ms-excel.xml
+-rw-r--r-- root root 3011 ./usr/share/mime/application/vnd.ms-htmlhelp.xml
+-rw-r--r-- root root 2734 ./usr/share/mime/application/vnd.ms-powerpoint.addin.macroenabled.12.xml
+-rw-r--r-- root root 3491 ./usr/share/mime/application/vnd.ms-powerpoint.presentation.macroenabled.12.xml
+-rw-r--r-- root root 2420 ./usr/share/mime/application/vnd.ms-powerpoint.slide.macroenabled.12.xml
+-rw-r--r-- root root 3485 ./usr/share/mime/application/vnd.ms-powerpoint.slideshow.macroenabled.12.xml
+-rw-r--r-- root root 2906 ./usr/share/mime/application/vnd.ms-powerpoint.template.macroenabled.12.xml
+-rw-r--r-- root root 3569 ./usr/share/mime/application/vnd.ms-powerpoint.xml
+-rw-r--r-- root root 2757 ./usr/share/mime/application/vnd.ms-publisher.xml
+-rw-r--r-- root root 2977 ./usr/share/mime/application/vnd.ms-tnef.xml
+-rw-r--r-- root root 1161 ./usr/share/mime/application/vnd.ms-visio.drawing.macroenabled.main+xml.xml
+-rw-r--r-- root root 1148 ./usr/share/mime/application/vnd.ms-visio.drawing.main+xml.xml
+-rw-r--r-- root root 1163 ./usr/share/mime/application/vnd.ms-visio.stencil.macroenabled.main+xml.xml
+-rw-r--r-- root root 1150 ./usr/share/mime/application/vnd.ms-visio.stencil.main+xml.xml
+-rw-r--r-- root root 1226 ./usr/share/mime/application/vnd.ms-visio.template.macroenabled.main+xml.xml
+-rw-r--r-- root root 1213 ./usr/share/mime/application/vnd.ms-visio.template.main+xml.xml
+-rw-r--r-- root root 3004 ./usr/share/mime/application/vnd.ms-word.document.macroenabled.12.xml
+-rw-r--r-- root root 2541 ./usr/share/mime/application/vnd.ms-word.template.macroenabled.12.xml
+-rw-r--r-- root root 3639 ./usr/share/mime/application/vnd.ms-works.xml
+-rw-r--r-- root root 3039 ./usr/share/mime/application/vnd.ms-wpl.xml
+-rw-r--r-- root root 2927 ./usr/share/mime/application/vnd.nintendo.snes.rom.xml
+-rw-r--r-- root root 2760 ./usr/share/mime/application/vnd.oasis.opendocument.chart-template.xml
+-rw-r--r-- root root 2879 ./usr/share/mime/application/vnd.oasis.opendocument.chart.xml
+-rw-r--r-- root root 3262 ./usr/share/mime/application/vnd.oasis.opendocument.database.xml
+-rw-r--r-- root root 2776 ./usr/share/mime/application/vnd.oasis.opendocument.formula-template.xml
+-rw-r--r-- root root 2954 ./usr/share/mime/application/vnd.oasis.opendocument.formula.xml
+-rw-r--r-- root root 3235 ./usr/share/mime/application/vnd.oasis.opendocument.graphics-flat-xml.xml
+-rw-r--r-- root root 2958 ./usr/share/mime/application/vnd.oasis.opendocument.graphics-template.xml
+-rw-r--r-- root root 2918 ./usr/share/mime/application/vnd.oasis.opendocument.graphics.xml
+-rw-r--r-- root root 2956 ./usr/share/mime/application/vnd.oasis.opendocument.image.xml
+-rw-r--r-- root root 3480 ./usr/share/mime/application/vnd.oasis.opendocument.presentation-flat-xml.xml
+-rw-r--r-- root root 2974 ./usr/share/mime/application/vnd.oasis.opendocument.presentation-template.xml
+-rw-r--r-- root root 3204 ./usr/share/mime/application/vnd.oasis.opendocument.presentation.xml
+-rw-r--r-- root root 3506 ./usr/share/mime/application/vnd.oasis.opendocument.spreadsheet-flat-xml.xml
+-rw-r--r-- root root 2970 ./usr/share/mime/application/vnd.oasis.opendocument.spreadsheet-template.xml
+-rw-r--r-- root root 3226 ./usr/share/mime/application/vnd.oasis.opendocument.spreadsheet.xml
+-rw-r--r-- root root 3352 ./usr/share/mime/application/vnd.oasis.opendocument.text-flat-xml.xml
+-rw-r--r-- root root 3033 ./usr/share/mime/application/vnd.oasis.opendocument.text-master.xml
+-rw-r--r-- root root 2956 ./usr/share/mime/application/vnd.oasis.opendocument.text-template.xml
+-rw-r--r-- root root 2925 ./usr/share/mime/application/vnd.oasis.opendocument.text-web.xml
+-rw-r--r-- root root 3024 ./usr/share/mime/application/vnd.oasis.opendocument.text.xml
+-rw-r--r-- root root 3524 ./usr/share/mime/application/vnd.openofficeorg.extension.xml
+-rw-r--r-- root root 3394 ./usr/share/mime/application/vnd.openxmlformats-officedocument.presentationml.presentation.xml
+-rw-r--r-- root root 3257 ./usr/share/mime/application/vnd.openxmlformats-officedocument.presentationml.slideshow.xml
+-rw-r--r-- root root 2932 ./usr/share/mime/application/vnd.openxmlformats-officedocument.presentationml.slide.xml
+-rw-r--r-- root root 3563 ./usr/share/mime/application/vnd.openxmlformats-officedocument.presentationml.template.xml
+-rw-r--r-- root root 3250 ./usr/share/mime/application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.xml
+-rw-r--r-- root root 3378 ./usr/share/mime/application/vnd.openxmlformats-officedocument.spreadsheetml.template.xml
+-rw-r--r-- root root 2957 ./usr/share/mime/application/vnd.openxmlformats-officedocument.wordprocessingml.document.xml
+-rw-r--r-- root root 3210 ./usr/share/mime/application/vnd.openxmlformats-officedocument.wordprocessingml.template.xml
+-rw-r--r-- root root 3457 ./usr/share/mime/application/vnd.palm.xml
+-rw-r--r-- root root 2983 ./usr/share/mime/application/vnd.rar.xml
+-rw-r--r-- root root 3320 ./usr/share/mime/application/vnd.rn-realmedia.xml
+-rw-r--r-- root root 1759 ./usr/share/mime/application/vnd.snap.xml
+-rw-r--r-- root root 3196 ./usr/share/mime/application/vnd.sqlite3.xml
+-rw-r--r-- root root 1139 ./usr/share/mime/application/vnd.squashfs.xml
+-rw-r--r-- root root 3467 ./usr/share/mime/application/vnd.stardivision.calc.xml
+-rw-r--r-- root root 3228 ./usr/share/mime/application/vnd.stardivision.chart.xml
+-rw-r--r-- root root 3156 ./usr/share/mime/application/vnd.stardivision.draw.xml
+-rw-r--r-- root root 3619 ./usr/share/mime/application/vnd.stardivision.impress.xml
+-rw-r--r-- root root 3181 ./usr/share/mime/application/vnd.stardivision.mail.xml
+-rw-r--r-- root root 3090 ./usr/share/mime/application/vnd.stardivision.math.xml
+-rw-r--r-- root root 3489 ./usr/share/mime/application/vnd.stardivision.writer.xml
+-rw-r--r-- root root 3534 ./usr/share/mime/application/vnd.sun.xml.calc.template.xml
+-rw-r--r-- root root 3762 ./usr/share/mime/application/vnd.sun.xml.calc.xml
+-rw-r--r-- root root 3513 ./usr/share/mime/application/vnd.sun.xml.draw.template.xml
+-rw-r--r-- root root 3438 ./usr/share/mime/application/vnd.sun.xml.draw.xml
+-rw-r--r-- root root 3704 ./usr/share/mime/application/vnd.sun.xml.impress.template.xml
+-rw-r--r-- root root 4000 ./usr/share/mime/application/vnd.sun.xml.impress.xml
+-rw-r--r-- root root 3488 ./usr/share/mime/application/vnd.sun.xml.math.xml
+-rw-r--r-- root root 4341 ./usr/share/mime/application/vnd.sun.xml.writer.global.xml
+-rw-r--r-- root root 3819 ./usr/share/mime/application/vnd.sun.xml.writer.template.xml
+-rw-r--r-- root root 3800 ./usr/share/mime/application/vnd.sun.xml.writer.xml
+-rw-r--r-- root root 2835 ./usr/share/mime/application/vnd.symbian.install.xml
+-rw-r--r-- root root 1126 ./usr/share/mime/application/vnd.tcpdump.pcap.xml
+-rw-r--r-- root root 3046 ./usr/share/mime/application/vnd.visio.xml
+-rw-r--r-- root root 3633 ./usr/share/mime/application/vnd.wordperfect.xml
+-rw-r--r-- root root 1189 ./usr/share/mime/application/vnd.youtube.yt.xml
+-rw-r--r-- root root 2575 ./usr/share/mime/application/winhlp.xml
+-rw-r--r-- root root 2942 ./usr/share/mime/application/x-7z-compressed.xml
+-rw-r--r-- root root 3303 ./usr/share/mime/application/x-abiword.xml
+-rw-r--r-- root root 2785 ./usr/share/mime/application/x-ace.xml
+-rw-r--r-- root root 2890 ./usr/share/mime/application/x-alz.xml
+-rw-r--r-- root root 2185 ./usr/share/mime/application/x-amiga-disk-format.xml
+-rw-r--r-- root root 3479 ./usr/share/mime/application/x-amipro.xml
+-rw-r--r-- root root 3122 ./usr/share/mime/application/x-aportisdoc.xml
+-rw-r--r-- root root 2699 ./usr/share/mime/application/x-apple-diskimage.xml
+-rw-r--r-- root root 346 ./usr/share/mime/application/x-appleworks-document.xml
+-rw-r--r-- root root 3940 ./usr/share/mime/application/x-applix-spreadsheet.xml
+-rw-r--r-- root root 3574 ./usr/share/mime/application/x-applix-word.xml
+-rw-r--r-- root root 2804 ./usr/share/mime/application/x-archive.xml
+-rw-r--r-- root root 2759 ./usr/share/mime/application/x-arc.xml
+-rw-r--r-- root root 3010 ./usr/share/mime/application/x-arj.xml
+-rw-r--r-- root root 2899 ./usr/share/mime/application/x-asp.xml
+-rw-r--r-- root root 1019 ./usr/share/mime/application/x-atari-2600-rom.xml
+-rw-r--r-- root root 1019 ./usr/share/mime/application/x-atari-7800-rom.xml
+-rw-r--r-- root root 1021 ./usr/share/mime/application/x-atari-lynx-rom.xml
+-rw-r--r-- root root 3084 ./usr/share/mime/application/x-awk.xml
+-rw-r--r-- root root 3225 ./usr/share/mime/application/x-bcpio.xml
+-rw-r--r-- root root 3540 ./usr/share/mime/application/x-bittorrent.xml
+-rw-r--r-- root root 3102 ./usr/share/mime/application/x-blender.xml
+-rw-r--r-- root root 2357 ./usr/share/mime/application/x-bsdiff.xml
+-rw-r--r-- root root 4099 ./usr/share/mime/application/x-bzdvi.xml
+-rw-r--r-- root root 3945 ./usr/share/mime/application/x-bzip-compressed-tar.xml
+-rw-r--r-- root root 2986 ./usr/share/mime/application/x-bzip.xml
+-rw-r--r-- root root 3880 ./usr/share/mime/application/x-bzpdf.xml
+-rw-r--r-- root root 4236 ./usr/share/mime/application/x-bzpostscript.xml
+-rw-r--r-- root root 3190 ./usr/share/mime/application/x-cb7.xml
+-rw-r--r-- root root 3180 ./usr/share/mime/application/x-cbt.xml
+-rw-r--r-- root root 2858 ./usr/share/mime/application/x-ccmx.xml
+-rw-r--r-- root root 3292 ./usr/share/mime/application/x-cd-image.xml
+-rw-r--r-- root root 3136 ./usr/share/mime/application/x-cdrdao-toc.xml
+-rw-r--r-- root root 1099 ./usr/share/mime/application/x-cisco-vpn-settings.xml
+-rw-r--r-- root root 3042 ./usr/share/mime/application/x-class-file.xml
+-rw-r--r-- root root 3786 ./usr/share/mime/application/x-compressed-tar.xml
+-rw-r--r-- root root 3414 ./usr/share/mime/application/x-compress.xml
+-rw-r--r-- root root 3630 ./usr/share/mime/application/x-core.xml
+-rw-r--r-- root root 4192 ./usr/share/mime/application/x-cpio-compressed.xml
+-rw-r--r-- root root 3028 ./usr/share/mime/application/x-cpio.xml
+-rw-r--r-- root root 3273 ./usr/share/mime/application/x-csh.xml
+-rw-r--r-- root root 3240 ./usr/share/mime/application/x-cue.xml
+-rw-r--r-- root root 2785 ./usr/share/mime/application/x-dar.xml
+-rw-r--r-- root root 3031 ./usr/share/mime/application/x-dbf.xml
+-rw-r--r-- root root 1136 ./usr/share/mime/application/x-dc-rom.xml
+-rw-r--r-- root root 1241 ./usr/share/mime/application/x-designer.xml
+-rw-r--r-- root root 3922 ./usr/share/mime/application/x-desktop.xml
+-rw-r--r-- root root 3052 ./usr/share/mime/application/x-dia-diagram.xml
+-rw-r--r-- root root 2405 ./usr/share/mime/application/x-dia-shape.xml
+-rw-r--r-- root root 3273 ./usr/share/mime/application/x-docbook+xml.xml
+-rw-r--r-- root root 1051 ./usr/share/mime/application/x-doom-wad.xml
+-rw-r--r-- root root 3183 ./usr/share/mime/application/x-dvi.xml
+-rw-r--r-- root root 3473 ./usr/share/mime/application/x-egon.xml
+-rw-r--r-- root root 3341 ./usr/share/mime/application/x-e-theme.xml
+-rw-r--r-- root root 2837 ./usr/share/mime/application/x-executable.xml
+-rw-r--r-- root root 2172 ./usr/share/mime/application/x-fds-disk.xml
+-rw-r--r-- root root 3142 ./usr/share/mime/application/x-fictionbook+xml.xml
+-rw-r--r-- root root 3137 ./usr/share/mime/application/x-fluid.xml
+-rw-r--r-- root root 3465 ./usr/share/mime/application/x-font-afm.xml
+-rw-r--r-- root root 2866 ./usr/share/mime/application/x-font-bdf.xml
+-rw-r--r-- root root 2854 ./usr/share/mime/application/x-font-dos.xml
+-rw-r--r-- root root 3612 ./usr/share/mime/application/x-font-framemaker.xml
+-rw-r--r-- root root 3018 ./usr/share/mime/application/x-font-libgrx.xml
+-rw-r--r-- root root 3800 ./usr/share/mime/application/x-font-linux-psf.xml
+-rw-r--r-- root root 2918 ./usr/share/mime/application/x-font-pcf.xml
+-rw-r--r-- root root 3031 ./usr/share/mime/application/x-font-speedo.xml
+-rw-r--r-- root root 3244 ./usr/share/mime/application/x-font-sunos-news.xml
+-rw-r--r-- root root 3352 ./usr/share/mime/application/x-font-tex-tfm.xml
+-rw-r--r-- root root 2839 ./usr/share/mime/application/x-font-tex.xml
+-rw-r--r-- root root 3183 ./usr/share/mime/application/x-font-ttx.xml
+-rw-r--r-- root root 2200 ./usr/share/mime/application/x-font-type1.xml
+-rw-r--r-- root root 2741 ./usr/share/mime/application/x-font-vfont.xml
+-rw-r--r-- root root 1959 ./usr/share/mime/application/x-gameboy-color-rom.xml
+-rw-r--r-- root root 2895 ./usr/share/mime/application/x-gameboy-rom.xml
+-rw-r--r-- root root 2521 ./usr/share/mime/application/x-gamecube-rom.xml
+-rw-r--r-- root root 1722 ./usr/share/mime/application/x-gamegear-rom.xml
+-rw-r--r-- root root 3217 ./usr/share/mime/application/x-gba-rom.xml
+-rw-r--r-- root root 3125 ./usr/share/mime/application/x-gdbm.xml
+-rw-r--r-- root root 3528 ./usr/share/mime/application/x-gedcom.xml
+-rw-r--r-- root root 1892 ./usr/share/mime/application/x-genesis-32x-rom.xml
+-rw-r--r-- root root 2901 ./usr/share/mime/application/x-genesis-rom.xml
+-rw-r--r-- root root 4594 ./usr/share/mime/application/x-gettext-translation.xml
+-rw-r--r-- root root 3040 ./usr/share/mime/application/x-glade.xml
+-rw-r--r-- root root 3208 ./usr/share/mime/application/x-gnucash.xml
+-rw-r--r-- root root 3362 ./usr/share/mime/application/x-gnumeric.xml
+-rw-r--r-- root root 3130 ./usr/share/mime/application/x-gnuplot.xml
+-rw-r--r-- root root 2839 ./usr/share/mime/application/x-go-sgf.xml
+-rw-r--r-- root root 3559 ./usr/share/mime/application/x-graphite.xml
+-rw-r--r-- root root 1253 ./usr/share/mime/application/x-gtk-builder.xml
+-rw-r--r-- root root 3098 ./usr/share/mime/application/x-gtktalog.xml
+-rw-r--r-- root root 4096 ./usr/share/mime/application/x-gzdvi.xml
+-rw-r--r-- root root 4598 ./usr/share/mime/application/x-gz-font-linux-psf.xml
+-rw-r--r-- root root 3871 ./usr/share/mime/application/x-gzpdf.xml
+-rw-r--r-- root root 4380 ./usr/share/mime/application/x-gzpostscript.xml
+-rw-r--r-- root root 3146 ./usr/share/mime/application/x-hdf.xml
+-rw-r--r-- root root 2102 ./usr/share/mime/application/x-hfe-floppy-image.xml
+-rw-r--r-- root root 3048 ./usr/share/mime/application/xhtml+xml.xml
+-rw-r--r-- root root 3437 ./usr/share/mime/application/x-hwp.xml
+-rw-r--r-- root root 3922 ./usr/share/mime/application/x-hwt.xml
+-rw-r--r-- root root 3805 ./usr/share/mime/application/x-ica.xml
+-rw-r--r-- root root 2088 ./usr/share/mime/application/x-iff.xml
+-rw-r--r-- root root 2959 ./usr/share/mime/application/x-ipod-firmware.xml
+-rw-r--r-- root root 1098 ./usr/share/mime/application/x-ipynb+json.xml
+-rw-r--r-- root root 2355 ./usr/share/mime/application/x-iso9660-appimage.xml
+-rw-r--r-- root root 3393 ./usr/share/mime/application/x-it87.xml
+-rw-r--r-- root root 2779 ./usr/share/mime/application/x-iwork-keynote-sffkey.xml
+-rw-r--r-- root root 2956 ./usr/share/mime/application/x-java-archive.xml
+-rw-r--r-- root root 3006 ./usr/share/mime/application/x-java-jce-keystore.xml
+-rw-r--r-- root root 2826 ./usr/share/mime/application/x-java-jnlp-file.xml
+-rw-r--r-- root root 2810 ./usr/share/mime/application/x-java-keystore.xml
+-rw-r--r-- root root 3097 ./usr/share/mime/application/x-java-pack200.xml
+-rw-r--r-- root root 2902 ./usr/share/mime/application/x-java.xml
+-rw-r--r-- root root 3090 ./usr/share/mime/application/x-jbuilder-project.xml
+-rw-r--r-- root root 3023 ./usr/share/mime/application/x-karbon.xml
+-rw-r--r-- root root 2961 ./usr/share/mime/application/x-kchart.xml
+-rw-r--r-- root root 985 ./usr/share/mime/application/x-kexi-connectiondata.xml
+-rw-r--r-- root root 963 ./usr/share/mime/application/x-kexiproject-shortcut.xml
+-rw-r--r-- root root 1139 ./usr/share/mime/application/x-kexiproject-sqlite2.xml
+-rw-r--r-- root root 1235 ./usr/share/mime/application/x-kexiproject-sqlite3.xml
+-rw-r--r-- root root 3059 ./usr/share/mime/application/x-kformula.xml
+-rw-r--r-- root root 3235 ./usr/share/mime/application/x-killustrator.xml
+-rw-r--r-- root root 3186 ./usr/share/mime/application/x-kivio.xml
+-rw-r--r-- root root 2970 ./usr/share/mime/application/x-kontour.xml
+-rw-r--r-- root root 3112 ./usr/share/mime/application/x-kpovmodeler.xml
+-rw-r--r-- root root 3446 ./usr/share/mime/application/x-kpresenter.xml
+-rw-r--r-- root root 2978 ./usr/share/mime/application/x-krita.xml
+-rw-r--r-- root root 3981 ./usr/share/mime/application/x-kspread-crypt.xml
+-rw-r--r-- root root 3288 ./usr/share/mime/application/x-kspread.xml
+-rw-r--r-- root root 3087 ./usr/share/mime/application/x-ksysv-package.xml
+-rw-r--r-- root root 2981 ./usr/share/mime/application/x-kugar.xml
+-rw-r--r-- root root 3680 ./usr/share/mime/application/x-kword-crypt.xml
+-rw-r--r-- root root 3054 ./usr/share/mime/application/x-kword.xml
+-rw-r--r-- root root 2937 ./usr/share/mime/application/x-lha.xml
+-rw-r--r-- root root 2788 ./usr/share/mime/application/x-lhz.xml
+-rw-r--r-- root root 3529 ./usr/share/mime/application/xliff+xml.xml
+-rw-r--r-- root root 3509 ./usr/share/mime/application/x-lrzip-compressed-tar.xml
+-rw-r--r-- root root 2586 ./usr/share/mime/application/x-lrzip.xml
+-rw-r--r-- root root 2932 ./usr/share/mime/application/x-lyx.xml
+-rw-r--r-- root root 2407 ./usr/share/mime/application/x-lz4-compressed-tar.xml
+-rw-r--r-- root root 2047 ./usr/share/mime/application/x-lz4.xml
+-rw-r--r-- root root 2439 ./usr/share/mime/application/x-lzip-compressed-tar.xml
+-rw-r--r-- root root 2538 ./usr/share/mime/application/x-lzip.xml
+-rw-r--r-- root root 3787 ./usr/share/mime/application/x-lzma-compressed-tar.xml
+-rw-r--r-- root root 2879 ./usr/share/mime/application/x-lzma.xml
+-rw-r--r-- root root 2858 ./usr/share/mime/application/x-lzop.xml
+-rw-r--r-- root root 2450 ./usr/share/mime/application/x-lzpdf.xml
+-rw-r--r-- root root 2573 ./usr/share/mime/application/x-m4.xml
+-rw-r--r-- root root 3552 ./usr/share/mime/application/x-macbinary.xml
+-rw-r--r-- root root 3595 ./usr/share/mime/application/x-magicpoint.xml
+-rw-r--r-- root root 3076 ./usr/share/mime/application/x-markaby.xml
+-rw-r--r-- root root 2865 ./usr/share/mime/application/x-matroska.xml
+-rw-r--r-- root root 3816 ./usr/share/mime/application/x-mif.xml
+-rw-r--r-- root root 2522 ./usr/share/mime/application/x-mimearchive.xml
+-rw-r--r-- root root 2842 ./usr/share/mime/application/xml-dtd.xml
+-rw-r--r-- root root 3524 ./usr/share/mime/application/xml-external-parsed-entity.xml
+-rw-r--r-- root root 3038 ./usr/share/mime/application/xml.xml
+-rw-r--r-- root root 2798 ./usr/share/mime/application/x-mobipocket-ebook.xml
+-rw-r--r-- root root 3272 ./usr/share/mime/application/x-mozilla-bookmarks.xml
+-rw-r--r-- root root 3670 ./usr/share/mime/application/x-ms-dos-executable.xml
+-rw-r--r-- root root 3395 ./usr/share/mime/application/x-msi.xml
+-rw-r--r-- root root 1046 ./usr/share/mime/application/x-ms-wim.xml
+-rw-r--r-- root root 3069 ./usr/share/mime/application/x-mswinurl.xml
+-rw-r--r-- root root 2816 ./usr/share/mime/application/x-mswrite.xml
+-rw-r--r-- root root 2631 ./usr/share/mime/application/x-msx-rom.xml
+-rw-r--r-- root root 2950 ./usr/share/mime/application/x-n64-rom.xml
+-rw-r--r-- root root 3171 ./usr/share/mime/application/x-nautilus-link.xml
+-rw-r--r-- root root 3348 ./usr/share/mime/application/x-navi-animation.xml
+-rw-r--r-- root root 1852 ./usr/share/mime/application/x-neo-geo-pocket-color-rom.xml
+-rw-r--r-- root root 1874 ./usr/share/mime/application/x-neo-geo-pocket-rom.xml
+-rw-r--r-- root root 2681 ./usr/share/mime/application/x-nes-rom.xml
+-rw-r--r-- root root 3540 ./usr/share/mime/application/x-netcdf.xml
+-rw-r--r-- root root 3587 ./usr/share/mime/application/x-netshow-channel.xml
+-rw-r--r-- root root 2904 ./usr/share/mime/application/x-nintendo-ds-rom.xml
+-rw-r--r-- root root 2651 ./usr/share/mime/application/x-nzb.xml
+-rw-r--r-- root root 2816 ./usr/share/mime/application/x-object.xml
+-rw-r--r-- root root 3410 ./usr/share/mime/application/x-oleo.xml
+-rw-r--r-- root root 3999 ./usr/share/mime/application/x-ole-storage.xml
+-rw-r--r-- root root 1221 ./usr/share/mime/application/x-pagemaker.xml
+-rw-r--r-- root root 2785 ./usr/share/mime/application/x-pak.xml
+-rw-r--r-- root root 3058 ./usr/share/mime/application/x-par2.xml
+-rw-r--r-- root root 2817 ./usr/share/mime/application/x-partial-download.xml
+-rw-r--r-- root root 2149 ./usr/share/mime/application/x-pc-engine-rom.xml
+-rw-r--r-- root root 3072 ./usr/share/mime/application/x-pef-executable.xml
+-rw-r--r-- root root 3209 ./usr/share/mime/application/x-perl.xml
+-rw-r--r-- root root 3050 ./usr/share/mime/application/x-php.xml
+-rw-r--r-- root root 3264 ./usr/share/mime/application/x-pkcs7-certificates.xml
+-rw-r--r-- root root 3383 ./usr/share/mime/application/x-planperfect.xml
+-rw-r--r-- root root 2969 ./usr/share/mime/application/x-pocket-word.xml
+-rw-r--r-- root root 3489 ./usr/share/mime/application/x-profile.xml
+-rw-r--r-- root root 3521 ./usr/share/mime/application/x-pw.xml
+-rw-r--r-- root root 3180 ./usr/share/mime/application/x-python-bytecode.xml
+-rw-r--r-- root root 407 ./usr/share/mime/application/x-qemu-disk.xml
+-rw-r--r-- root root 2164 ./usr/share/mime/application/x-qpress.xml
+-rw-r--r-- root root 2458 ./usr/share/mime/application/x-qtiplot.xml
+-rw-r--r-- root root 3546 ./usr/share/mime/application/x-quattropro.xml
+-rw-r--r-- root root 1258 ./usr/share/mime/application/x-quicktime-media-link.xml
+-rw-r--r-- root root 3189 ./usr/share/mime/application/x-qw.xml
+-rw-r--r-- root root 2444 ./usr/share/mime/application/x-raw-disk-image.xml
+-rw-r--r-- root root 3223 ./usr/share/mime/application/x-raw-disk-image-xz-compressed.xml
+-rw-r--r-- root root 1828 ./usr/share/mime/application/x-raw-floppy-disk-image.xml
+-rw-r--r-- root root 2067 ./usr/share/mime/application/x-riff.xml
+-rw-r--r-- root root 2780 ./usr/share/mime/application/x-rpm.xml
+-rw-r--r-- root root 2941 ./usr/share/mime/application/x-ruby.xml
+-rw-r--r-- root root 3058 ./usr/share/mime/application/x-sami.xml
+-rw-r--r-- root root 2519 ./usr/share/mime/application/x-saturn-rom.xml
+-rw-r--r-- root root 3354 ./usr/share/mime/application/x-sc.xml
+-rw-r--r-- root root 2140 ./usr/share/mime/application/x-sega-cd-rom.xml
+-rw-r--r-- root root 1752 ./usr/share/mime/application/x-sega-pico-rom.xml
+-rw-r--r-- root root 1656 ./usr/share/mime/application/x-sg1000-rom.xml
+-rw-r--r-- root root 3576 ./usr/share/mime/application/x-shared-library-la.xml
+-rw-r--r-- root root 3341 ./usr/share/mime/application/x-sharedlib.xml
+-rw-r--r-- root root 3018 ./usr/share/mime/application/x-shar.xml
+-rw-r--r-- root root 3191 ./usr/share/mime/application/x-shellscript.xml
+-rw-r--r-- root root 2898 ./usr/share/mime/application/x-shorten.xml
+-rw-r--r-- root root 3125 ./usr/share/mime/application/x-siag.xml
+-rw-r--r-- root root 3067 ./usr/share/mime/application/x-slp.xml
+-rw-r--r-- root root 3271 ./usr/share/mime/application/xslt+xml.xml
+-rw-r--r-- root root 2868 ./usr/share/mime/application/x-smaf.xml
+-rw-r--r-- root root 1828 ./usr/share/mime/application/x-sms-rom.xml
+-rw-r--r-- root root 2563 ./usr/share/mime/application/x-source-rpm.xml
+-rw-r--r-- root root 3445 ./usr/share/mime/application/xspf+xml.xml
+-rw-r--r-- root root 1201 ./usr/share/mime/application/x-spss-por.xml
+-rw-r--r-- root root 1181 ./usr/share/mime/application/x-spss-sav.xml
+-rw-r--r-- root root 3154 ./usr/share/mime/application/x-sqlite2.xml
+-rw-r--r-- root root 3027 ./usr/share/mime/application/x-stuffit.xml
+-rw-r--r-- root root 3069 ./usr/share/mime/application/x-subrip.xml
+-rw-r--r-- root root 3146 ./usr/share/mime/application/x-sv4cpio.xml
+-rw-r--r-- root root 3637 ./usr/share/mime/application/x-sv4crc.xml
+-rw-r--r-- root root 2862 ./usr/share/mime/application/x-t602.xml
+-rw-r--r-- root root 2908 ./usr/share/mime/application/x-tar.xml
+-rw-r--r-- root root 3451 ./usr/share/mime/application/x-tarz.xml
+-rw-r--r-- root root 3391 ./usr/share/mime/application/x-tex-gf.xml
+-rw-r--r-- root root 3527 ./usr/share/mime/application/x-tex-pk.xml
+-rw-r--r-- root root 2916 ./usr/share/mime/application/x-tgif.xml
+-rw-r--r-- root root 2604 ./usr/share/mime/application/x-theme.xml
+-rw-r--r-- root root 2013 ./usr/share/mime/application/x-thomson-cartridge-memo7.xml
+-rw-r--r-- root root 1776 ./usr/share/mime/application/x-thomson-cassette.xml
+-rw-r--r-- root root 2342 ./usr/share/mime/application/x-thomson-sap-image.xml
+-rw-r--r-- root root 3216 ./usr/share/mime/application/x-toutdoux.xml
+-rw-r--r-- root root 3148 ./usr/share/mime/application/x-trash.xml
+-rw-r--r-- root root 3887 ./usr/share/mime/application/x-troff-man-compressed.xml
+-rw-r--r-- root root 2521 ./usr/share/mime/application/x-troff-man.xml
+-rw-r--r-- root root 3731 ./usr/share/mime/application/x-tzo.xml
+-rw-r--r-- root root 3110 ./usr/share/mime/application/x-ufraw.xml
+-rw-r--r-- root root 2836 ./usr/share/mime/application/x-ustar.xml
+-rw-r--r-- root root 1666 ./usr/share/mime/application/x-virtual-boy-rom.xml
+-rw-r--r-- root root 3242 ./usr/share/mime/application/x-wais-source.xml
+-rw-r--r-- root root 2456 ./usr/share/mime/application/x-wii-rom.xml
+-rw-r--r-- root root 1998 ./usr/share/mime/application/x-wii-wad.xml
+-rw-r--r-- root root 3595 ./usr/share/mime/application/x-windows-themepack.xml
+-rw-r--r-- root root 1989 ./usr/share/mime/application/x-wonderswan-color-rom.xml
+-rw-r--r-- root root 1825 ./usr/share/mime/application/x-wonderswan-rom.xml
+-rw-r--r-- root root 3782 ./usr/share/mime/application/x-wpg.xml
+-rw-r--r-- root root 2498 ./usr/share/mime/application/x-wwf.xml
+-rw-r--r-- root root 4757 ./usr/share/mime/application/x-x509-ca-cert.xml
+-rw-r--r-- root root 1890 ./usr/share/mime/application/x-xar.xml
+-rw-r--r-- root root 3167 ./usr/share/mime/application/x-xbel.xml
+-rw-r--r-- root root 3294 ./usr/share/mime/application/x-xpinstall.xml
+-rw-r--r-- root root 3373 ./usr/share/mime/application/x-xz-compressed-tar.xml
+-rw-r--r-- root root 3269 ./usr/share/mime/application/x-xzpdf.xml
+-rw-r--r-- root root 2449 ./usr/share/mime/application/x-xz.xml
+-rw-r--r-- root root 2822 ./usr/share/mime/application/x-yaml.xml
+-rw-r--r-- root root 2936 ./usr/share/mime/application/x-zerosize.xml
+-rw-r--r-- root root 2912 ./usr/share/mime/application/x-zip-compressed-fb2.xml
+-rw-r--r-- root root 2818 ./usr/share/mime/application/x-zoo.xml
+-rw-r--r-- root root 1995 ./usr/share/mime/application/x-zstd-compressed-tar.xml
+-rw-r--r-- root root 2901 ./usr/share/mime/application/zip.xml
+-rw-r--r-- root root 2084 ./usr/share/mime/application/zlib.xml
+-rw-r--r-- root root 1464 ./usr/share/mime/application/zstd.xml
+drwxr-xr-x root root 4096 ./usr/share/mime/audio
+-rw-r--r-- root root 2202 ./usr/share/mime/audio/aac.xml
+-rw-r--r-- root root 3368 ./usr/share/mime/audio/ac3.xml
+-rw-r--r-- root root 2944 ./usr/share/mime/audio/amr-wb.xml
+-rw-r--r-- root root 2771 ./usr/share/mime/audio/amr.xml
+-rw-r--r-- root root 1023 ./usr/share/mime/audio/annodex.xml
+-rw-r--r-- root root 3151 ./usr/share/mime/audio/basic.xml
+-rw-r--r-- root root 2798 ./usr/share/mime/audio/flac.xml
+-rw-r--r-- root root 2876 ./usr/share/mime/audio/midi.xml
+-rw-r--r-- root root 2623 ./usr/share/mime/audio/mp2.xml
+-rw-r--r-- root root 2884 ./usr/share/mime/audio/mp4.xml
+-rw-r--r-- root root 2936 ./usr/share/mime/audio/mpeg.xml
+-rw-r--r-- root root 1008 ./usr/share/mime/audio/ogg.xml
+-rw-r--r-- root root 3220 ./usr/share/mime/audio/prs.sid.xml
+-rw-r--r-- root root 1610 ./usr/share/mime/audio/usac.xml
+-rw-r--r-- root root 2180 ./usr/share/mime/audio/vnd.dts.hd.xml
+-rw-r--r-- root root 2055 ./usr/share/mime/audio/vnd.dts.xml
+-rw-r--r-- root root 3202 ./usr/share/mime/audio/vnd.rn-realaudio.xml
+-rw-r--r-- root root 2422 ./usr/share/mime/audio/webm.xml
+-rw-r--r-- root root 2713 ./usr/share/mime/audio/x-adpcm.xml
+-rw-r--r-- root root 3066 ./usr/share/mime/audio/x-aifc.xml
+-rw-r--r-- root root 3573 ./usr/share/mime/audio/x-aiff.xml
+-rw-r--r-- root root 2766 ./usr/share/mime/audio/x-amzxml.xml
+-rw-r--r-- root root 2758 ./usr/share/mime/audio/x-ape.xml
+-rw-r--r-- root root 2958 ./usr/share/mime/audio/x-flac+ogg.xml
+-rw-r--r-- root root 2864 ./usr/share/mime/audio/x-gsm.xml
+-rw-r--r-- root root 1076 ./usr/share/mime/audio/x-iriver-pla.xml
+-rw-r--r-- root root 3344 ./usr/share/mime/audio/x-it.xml
+-rw-r--r-- root root 3184 ./usr/share/mime/audio/x-m4b.xml
+-rw-r--r-- root root 1002 ./usr/share/mime/audio/x-m4r.xml
+-rw-r--r-- root root 2979 ./usr/share/mime/audio/x-matroska.xml
+-rw-r--r-- root root 3017 ./usr/share/mime/audio/x-minipsf.xml
+-rw-r--r-- root root 3256 ./usr/share/mime/audio/x-mo3.xml
+-rw-r--r-- root root 3640 ./usr/share/mime/audio/x-mod.xml
+-rw-r--r-- root root 3601 ./usr/share/mime/audio/x-mpegurl.xml
+-rw-r--r-- root root 3833 ./usr/share/mime/audio/x-ms-asx.xml
+-rw-r--r-- root root 3148 ./usr/share/mime/audio/x-ms-wma.xml
+-rw-r--r-- root root 2864 ./usr/share/mime/audio/x-musepack.xml
+-rw-r--r-- root root 2000 ./usr/share/mime/audio/x-opus+ogg.xml
+-rw-r--r-- root root 1778 ./usr/share/mime/audio/x-pn-audibleaudio.xml
+-rw-r--r-- root root 3385 ./usr/share/mime/audio/x-psflib.xml
+-rw-r--r-- root root 2682 ./usr/share/mime/audio/x-psf.xml
+-rw-r--r-- root root 2764 ./usr/share/mime/audio/x-riff.xml
+-rw-r--r-- root root 3393 ./usr/share/mime/audio/x-s3m.xml
+-rw-r--r-- root root 3693 ./usr/share/mime/audio/x-scpls.xml
+-rw-r--r-- root root 2976 ./usr/share/mime/audio/x-speex+ogg.xml
+-rw-r--r-- root root 2656 ./usr/share/mime/audio/x-speex.xml
+-rw-r--r-- root root 3290 ./usr/share/mime/audio/x-stm.xml
+-rw-r--r-- root root 2930 ./usr/share/mime/audio/x-tta.xml
+-rw-r--r-- root root 2737 ./usr/share/mime/audio/x-voc.xml
+-rw-r--r-- root root 3311 ./usr/share/mime/audio/x-vorbis+ogg.xml
+-rw-r--r-- root root 3641 ./usr/share/mime/audio/x-wavpack-correction.xml
+-rw-r--r-- root root 2833 ./usr/share/mime/audio/x-wavpack.xml
+-rw-r--r-- root root 2795 ./usr/share/mime/audio/x-wav.xml
+-rw-r--r-- root root 3518 ./usr/share/mime/audio/x-xi.xml
+-rw-r--r-- root root 2751 ./usr/share/mime/audio/x-xmf.xml
+-rw-r--r-- root root 3360 ./usr/share/mime/audio/x-xm.xml
+drwxr-xr-x root root 4096 ./usr/share/mime/font
+-rw-r--r-- root root 1752 ./usr/share/mime/font/collection.xml
+-rw-r--r-- root root 3213 ./usr/share/mime/font/otf.xml
+-rw-r--r-- root root 3063 ./usr/share/mime/font/ttf.xml
+-rw-r--r-- root root 1753 ./usr/share/mime/font/woff2.xml
+-rw-r--r-- root root 2331 ./usr/share/mime/font/woff.xml
+-rw-r--r-- root root 17449 ./usr/share/mime/generic-icons
+-rw-r--r-- root root 29350 ./usr/share/mime/globs
+-rw-r--r-- root root 32606 ./usr/share/mime/globs2
+-rw-r--r-- root root 0 ./usr/share/mime/icons
+drwxr-xr-x root root 4096 ./usr/share/mime/image
+-rw-r--r-- root root 3325 ./usr/share/mime/image/bmp.xml
+-rw-r--r-- root root 928 ./usr/share/mime/image/cgm.xml
+-rw-r--r-- root root 2788 ./usr/share/mime/image/dpx.xml
+-rw-r--r-- root root 2896 ./usr/share/mime/image/emf.xml
+-rw-r--r-- root root 1017 ./usr/share/mime/image/fax-g3.xml
+-rw-r--r-- root root 3011 ./usr/share/mime/image/fits.xml
+-rw-r--r-- root root 2851 ./usr/share/mime/image/gif.xml
+-rw-r--r-- root root 1713 ./usr/share/mime/image/heif.xml
+-rw-r--r-- root root 2775 ./usr/share/mime/image/ief.xml
+-rw-r--r-- root root 1995 ./usr/share/mime/image/jp2.xml
+-rw-r--r-- root root 2914 ./usr/share/mime/image/jpeg.xml
+-rw-r--r-- root root 1890 ./usr/share/mime/image/jpm.xml
+-rw-r--r-- root root 1891 ./usr/share/mime/image/jpx.xml
+-rw-r--r-- root root 2043 ./usr/share/mime/image/ktx.xml
+-rw-r--r-- root root 1030 ./usr/share/mime/image/openraster.xml
+-rw-r--r-- root root 2775 ./usr/share/mime/image/png.xml
+-rw-r--r-- root root 1057 ./usr/share/mime/image/rle.xml
+-rw-r--r-- root root 3368 ./usr/share/mime/image/svg+xml-compressed.xml
+-rw-r--r-- root root 2782 ./usr/share/mime/image/svg+xml.xml
+-rw-r--r-- root root 2852 ./usr/share/mime/image/tiff.xml
+-rw-r--r-- root root 3033 ./usr/share/mime/image/vnd.adobe.photoshop.xml
+-rw-r--r-- root root 2120 ./usr/share/mime/image/vnd.djvu+multipage.xml
+-rw-r--r-- root root 2911 ./usr/share/mime/image/vnd.djvu.xml
+-rw-r--r-- root root 3101 ./usr/share/mime/image/vnd.dwg.xml
+-rw-r--r-- root root 3301 ./usr/share/mime/image/vnd.dxf.xml
+-rw-r--r-- root root 2244 ./usr/share/mime/image/vnd.microsoft.icon.xml
+-rw-r--r-- root root 933 ./usr/share/mime/image/vnd.ms-modi.xml
+-rw-r--r-- root root 2993 ./usr/share/mime/image/vnd.rn-realpix.xml
+-rw-r--r-- root root 2775 ./usr/share/mime/image/vnd.wap.wbmp.xml
+-rw-r--r-- root root 2764 ./usr/share/mime/image/vnd.zbrush.pcx.xml
+-rw-r--r-- root root 1985 ./usr/share/mime/image/webp.xml
+-rw-r--r-- root root 2901 ./usr/share/mime/image/wmf.xml
+-rw-r--r-- root root 3236 ./usr/share/mime/image/x-3ds.xml
+-rw-r--r-- root root 3249 ./usr/share/mime/image/x-adobe-dng.xml
+-rw-r--r-- root root 3454 ./usr/share/mime/image/x-applix-graphics.xml
+-rw-r--r-- root root 3863 ./usr/share/mime/image/x-bzeps.xml
+-rw-r--r-- root root 3517 ./usr/share/mime/image/x-canon-cr2.xml
+-rw-r--r-- root root 3480 ./usr/share/mime/image/x-canon-crw.xml
+-rw-r--r-- root root 3346 ./usr/share/mime/image/x-cmu-raster.xml
+-rw-r--r-- root root 3323 ./usr/share/mime/image/x-compressed-xcf.xml
+-rw-r--r-- root root 3230 ./usr/share/mime/image/x-dcraw.xml
+-rw-r--r-- root root 3119 ./usr/share/mime/image/x-dds.xml
+-rw-r--r-- root root 2780 ./usr/share/mime/image/x-dib.xml
+-rw-r--r-- root root 2906 ./usr/share/mime/image/x-eps.xml
+-rw-r--r-- root root 2720 ./usr/share/mime/image/x-exr.xml
+-rw-r--r-- root root 2767 ./usr/share/mime/image/x-fpx.xml
+-rw-r--r-- root root 3445 ./usr/share/mime/image/x-fuji-raf.xml
+-rw-r--r-- root root 1569 ./usr/share/mime/image/x-gimp-gbr.xml
+-rw-r--r-- root root 1672 ./usr/share/mime/image/x-gimp-gih.xml
+-rw-r--r-- root root 1564 ./usr/share/mime/image/x-gimp-pat.xml
+-rw-r--r-- root root 3863 ./usr/share/mime/image/x-gzeps.xml
+-rw-r--r-- root root 2927 ./usr/share/mime/image/x-icns.xml
+-rw-r--r-- root root 3043 ./usr/share/mime/image/x-ilbm.xml
+-rw-r--r-- root root 2863 ./usr/share/mime/image/x-jng.xml
+-rw-r--r-- root root 1821 ./usr/share/mime/image/x-jp2-codestream.xml
+-rw-r--r-- root root 3442 ./usr/share/mime/image/x-kodak-dcr.xml
+-rw-r--r-- root root 3428 ./usr/share/mime/image/x-kodak-k25.xml
+-rw-r--r-- root root 3444 ./usr/share/mime/image/x-kodak-kdc.xml
+-rw-r--r-- root root 3140 ./usr/share/mime/image/x-lwo.xml
+-rw-r--r-- root root 3058 ./usr/share/mime/image/x-lws.xml
+-rw-r--r-- root root 3324 ./usr/share/mime/image/x-macpaint.xml
+-rw-r--r-- root root 3495 ./usr/share/mime/image/x-minolta-mrw.xml
+-rw-r--r-- root root 2793 ./usr/share/mime/image/x-msod.xml
+-rw-r--r-- root root 2665 ./usr/share/mime/image/x-niff.xml
+-rw-r--r-- root root 3442 ./usr/share/mime/image/x-nikon-nef.xml
+-rw-r--r-- root root 3607 ./usr/share/mime/image/x-olympus-orf.xml
+-rw-r--r-- root root 3360 ./usr/share/mime/image/x-panasonic-rw2.xml
+-rw-r--r-- root root 3358 ./usr/share/mime/image/x-panasonic-rw.xml
+-rw-r--r-- root root 3499 ./usr/share/mime/image/x-pentax-pef.xml
+-rw-r--r-- root root 2793 ./usr/share/mime/image/x-photo-cd.xml
+-rw-r--r-- root root 3911 ./usr/share/mime/image/x-pict.xml
+-rw-r--r-- root root 2789 ./usr/share/mime/image/x-portable-anymap.xml
+-rw-r--r-- root root 2904 ./usr/share/mime/image/x-portable-bitmap.xml
+-rw-r--r-- root root 2830 ./usr/share/mime/image/x-portable-graymap.xml
+-rw-r--r-- root root 2828 ./usr/share/mime/image/x-portable-pixmap.xml
+-rw-r--r-- root root 2989 ./usr/share/mime/image/x-quicktime.xml
+-rw-r--r-- root root 2784 ./usr/share/mime/image/x-rgb.xml
+-rw-r--r-- root root 2640 ./usr/share/mime/image/x-sgi.xml
+-rw-r--r-- root root 3400 ./usr/share/mime/image/x-sigma-x3f.xml
+-rw-r--r-- root root 2956 ./usr/share/mime/image/x-skencil.xml
+-rw-r--r-- root root 3388 ./usr/share/mime/image/x-sony-arw.xml
+-rw-r--r-- root root 3388 ./usr/share/mime/image/x-sony-sr2.xml
+-rw-r--r-- root root 3387 ./usr/share/mime/image/x-sony-srf.xml
+-rw-r--r-- root root 3040 ./usr/share/mime/image/x-sun-raster.xml
+-rw-r--r-- root root 2867 ./usr/share/mime/image/x-tga.xml
+-rw-r--r-- root root 2644 ./usr/share/mime/image/x-tiff-multipage.xml
+-rw-r--r-- root root 2941 ./usr/share/mime/image/x-win-bitmap.xml
+-rw-r--r-- root root 2721 ./usr/share/mime/image/x-xbitmap.xml
+-rw-r--r-- root root 2832 ./usr/share/mime/image/x-xcf.xml
+-rw-r--r-- root root 2592 ./usr/share/mime/image/x-xcursor.xml
+-rw-r--r-- root root 2753 ./usr/share/mime/image/x-xfig.xml
+-rw-r--r-- root root 2798 ./usr/share/mime/image/x-xpixmap.xml
+-rw-r--r-- root root 3109 ./usr/share/mime/image/x-xwindowdump.xml
+drwxr-xr-x root root 4096 ./usr/share/mime/inode
+-rw-r--r-- root root 3006 ./usr/share/mime/inode/blockdevice.xml
+-rw-r--r-- root root 3145 ./usr/share/mime/inode/chardevice.xml
+-rw-r--r-- root root 2543 ./usr/share/mime/inode/directory.xml
+-rw-r--r-- root root 2413 ./usr/share/mime/inode/fifo.xml
+-rw-r--r-- root root 3021 ./usr/share/mime/inode/mount-point.xml
+-rw-r--r-- root root 2469 ./usr/share/mime/inode/socket.xml
+-rw-r--r-- root root 3295 ./usr/share/mime/inode/symlink.xml
+-rw-r--r-- root root 27700 ./usr/share/mime/magic
+drwxr-xr-x root root 4096 ./usr/share/mime/message
+-rw-r--r-- root root 3735 ./usr/share/mime/message/delivery-status.xml
+-rw-r--r-- root root 3771 ./usr/share/mime/message/disposition-notification.xml
+-rw-r--r-- root root 3777 ./usr/share/mime/message/external-body.xml
+-rw-r--r-- root root 3617 ./usr/share/mime/message/news.xml
+-rw-r--r-- root root 3728 ./usr/share/mime/message/partial.xml
+-rw-r--r-- root root 3183 ./usr/share/mime/message/rfc822.xml
+-rw-r--r-- root root 3427 ./usr/share/mime/message/x-gnu-rmail.xml
+-rw-r--r-- root root 136104 ./usr/share/mime/mime.cache
+drwxr-xr-x root root 4096 ./usr/share/mime/model
+-rw-r--r-- root root 2003 ./usr/share/mime/model/iges.xml
+-rw-r--r-- root root 1695 ./usr/share/mime/model/stl.xml
+-rw-r--r-- root root 3189 ./usr/share/mime/model/vrml.xml
+drwxr-xr-x root root 4096 ./usr/share/mime/multipart
+-rw-r--r-- root root 3761 ./usr/share/mime/multipart/alternative.xml
+-rw-r--r-- root root 4361 ./usr/share/mime/multipart/appledouble.xml
+-rw-r--r-- root root 3157 ./usr/share/mime/multipart/digest.xml
+-rw-r--r-- root root 3267 ./usr/share/mime/multipart/encrypted.xml
+-rw-r--r-- root root 3191 ./usr/share/mime/multipart/mixed.xml
+-rw-r--r-- root root 3209 ./usr/share/mime/multipart/related.xml
+-rw-r--r-- root root 3556 ./usr/share/mime/multipart/report.xml
+-rw-r--r-- root root 3203 ./usr/share/mime/multipart/signed.xml
+-rw-r--r-- root root 3867 ./usr/share/mime/multipart/x-mixed-replace.xml
+-rw-r--r-- root root 16073 ./usr/share/mime/subclasses
+drwxr-xr-x root root 4096 ./usr/share/mime/text
+-rw-r--r-- root root 1172 ./usr/share/mime/text/cache-manifest.xml
+-rw-r--r-- root root 3178 ./usr/share/mime/text/calendar.xml
+-rw-r--r-- root root 3113 ./usr/share/mime/text/css.xml
+-rw-r--r-- root root 2266 ./usr/share/mime/text/csv-schema.xml
+-rw-r--r-- root root 3027 ./usr/share/mime/text/csv.xml
+-rw-r--r-- root root 3801 ./usr/share/mime/text/enriched.xml
+-rw-r--r-- root root 3017 ./usr/share/mime/text/htmlh.xml
+-rw-r--r-- root root 2991 ./usr/share/mime/text/html.xml
+-rw-r--r-- root root 2600 ./usr/share/mime/text/markdown.xml
+-rw-r--r-- root root 3420 ./usr/share/mime/text/plain.xml
+-rw-r--r-- root root 3291 ./usr/share/mime/text/rfc822-headers.xml
+-rw-r--r-- root root 3602 ./usr/share/mime/text/richtext.xml
+-rw-r--r-- root root 2164 ./usr/share/mime/text/rust.xml
+-rw-r--r-- root root 3073 ./usr/share/mime/text/sgml.xml
+-rw-r--r-- root root 3961 ./usr/share/mime/text/spreadsheet.xml
+-rw-r--r-- root root 2849 ./usr/share/mime/text/tab-separated-values.xml
+-rw-r--r-- root root 3191 ./usr/share/mime/text/troff.xml
+-rw-r--r-- root root 2106 ./usr/share/mime/text/turtle.xml
+-rw-r--r-- root root 3618 ./usr/share/mime/text/vcard.xml
+-rw-r--r-- root root 2914 ./usr/share/mime/text/vnd.graphviz.xml
+-rw-r--r-- root root 3253 ./usr/share/mime/text/vnd.qt.linguist.xml
+-rw-r--r-- root root 3050 ./usr/share/mime/text/vnd.rn-realtext.xml
+-rw-r--r-- root root 1636 ./usr/share/mime/text/vnd.senx.warpscript.xml
+-rw-r--r-- root root 2876 ./usr/share/mime/text/vnd.sun.j2me.app-descriptor.xml
+-rw-r--r-- root root 3020 ./usr/share/mime/text/vnd.wap.wmlscript.xml
+-rw-r--r-- root root 3039 ./usr/share/mime/text/vnd.wap.wml.xml
+-rw-r--r-- root root 2632 ./usr/share/mime/text/vtt.xml
+-rw-r--r-- root root 3143 ./usr/share/mime/text/x-adasrc.xml
+-rw-r--r-- root root 2961 ./usr/share/mime/text/x-authors.xml
+-rw-r--r-- root root 3040 ./usr/share/mime/text/x-bibtex.xml
+-rw-r--r-- root root 3310 ./usr/share/mime/text/x-changelog.xml
+-rw-r--r-- root root 3007 ./usr/share/mime/text/x-c++hdr.xml
+-rw-r--r-- root root 2803 ./usr/share/mime/text/x-chdr.xml
+-rw-r--r-- root root 3188 ./usr/share/mime/text/x-cmake.xml
+-rw-r--r-- root root 1168 ./usr/share/mime/text/x-cobol.xml
+-rw-r--r-- root root 3113 ./usr/share/mime/text/x-copying.xml
+-rw-r--r-- root root 3127 ./usr/share/mime/text/x-credits.xml
+-rw-r--r-- root root 3074 ./usr/share/mime/text/x-csharp.xml
+-rw-r--r-- root root 3250 ./usr/share/mime/text/x-c++src.xml
+-rw-r--r-- root root 3064 ./usr/share/mime/text/x-csrc.xml
+-rw-r--r-- root root 1989 ./usr/share/mime/text/x-dbus-service.xml
+-rw-r--r-- root root 3032 ./usr/share/mime/text/x-dcl.xml
+-rw-r--r-- root root 3236 ./usr/share/mime/text/x-dsl.xml
+-rw-r--r-- root root 2994 ./usr/share/mime/text/x-dsrc.xml
+-rw-r--r-- root root 3254 ./usr/share/mime/text/x-eiffel.xml
+-rw-r--r-- root root 3617 ./usr/share/mime/text/x-emacs-lisp.xml
+-rw-r--r-- root root 3221 ./usr/share/mime/text/x-erlang.xml
+-rw-r--r-- root root 3527 ./usr/share/mime/text/x-fortran.xml
+-rw-r--r-- root root 1710 ./usr/share/mime/text/x.gcode.xml
+-rw-r--r-- root root 2317 ./usr/share/mime/text/x-genie.xml
+-rw-r--r-- root root 3320 ./usr/share/mime/text/x-gettext-translation-template.xml
+-rw-r--r-- root root 3221 ./usr/share/mime/text/x-gettext-translation.xml
+-rw-r--r-- root root 1013 ./usr/share/mime/text/x-gherkin.xml
+-rw-r--r-- root root 1138 ./usr/share/mime/text/x-google-video-pointer.xml
+-rw-r--r-- root root 2539 ./usr/share/mime/text/x-go.xml
+-rw-r--r-- root root 1644 ./usr/share/mime/text/x-gradle.xml
+-rw-r--r-- root root 1179 ./usr/share/mime/text/x-groovy.xml
+-rw-r--r-- root root 3360 ./usr/share/mime/text/x-haskell.xml
+-rw-r--r-- root root 3033 ./usr/share/mime/text/x-idl.xml
+-rw-r--r-- root root 3023 ./usr/share/mime/text/x-imelody.xml
+-rw-r--r-- root root 3418 ./usr/share/mime/text/x-install.xml
+-rw-r--r-- root root 3599 ./usr/share/mime/text/x-iptables.xml
+-rw-r--r-- root root 3086 ./usr/share/mime/text/x-java.xml
+-rw-r--r-- root root 3167 ./usr/share/mime/text/x-ldif.xml
+-rw-r--r-- root root 3110 ./usr/share/mime/text/x-lilypond.xml
+-rw-r--r-- root root 3063 ./usr/share/mime/text/x-literate-haskell.xml
+-rw-r--r-- root root 3190 ./usr/share/mime/text/x-log.xml
+-rw-r--r-- root root 2802 ./usr/share/mime/text/x-lua.xml
+-rw-r--r-- root root 1200 ./usr/share/mime/text/x-makefile.xml
+-rw-r--r-- root root 985 ./usr/share/mime/text/x-matlab.xml
+-rw-r--r-- root root 1881 ./usr/share/mime/text/x-maven+xml.xml
+-rw-r--r-- root root 3157 ./usr/share/mime/text/xmcd.xml
+-rw-r--r-- root root 2231 ./usr/share/mime/text/x-meson.xml
+-rw-r--r-- root root 3177 ./usr/share/mime/text/x-microdvd.xml
+-rw-r--r-- root root 2799 ./usr/share/mime/text/x-moc.xml
+-rw-r--r-- root root 2267 ./usr/share/mime/text/x-modelica.xml
+-rw-r--r-- root root 957 ./usr/share/mime/text/x-mof.xml
+-rw-r--r-- root root 3100 ./usr/share/mime/text/x-mpsub.xml
+-rw-r--r-- root root 3359 ./usr/share/mime/text/x-mrml.xml
+-rw-r--r-- root root 3496 ./usr/share/mime/text/x-ms-regedit.xml
+-rw-r--r-- root root 1114 ./usr/share/mime/text/x-mup.xml
+-rw-r--r-- root root 2801 ./usr/share/mime/text/x-nfo.xml
+-rw-r--r-- root root 3537 ./usr/share/mime/text/x-objcsrc.xml
+-rw-r--r-- root root 3076 ./usr/share/mime/text/x-ocaml.xml
+-rw-r--r-- root root 2703 ./usr/share/mime/text/x-ocl.xml
+-rw-r--r-- root root 2654 ./usr/share/mime/text/x-ooc.xml
+-rw-r--r-- root root 1909 ./usr/share/mime/text/x-opencl-src.xml
+-rw-r--r-- root root 3116 ./usr/share/mime/text/x-opml+xml.xml
+-rw-r--r-- root root 3227 ./usr/share/mime/text/x-pascal.xml
+-rw-r--r-- root root 3558 ./usr/share/mime/text/x-patch.xml
+-rw-r--r-- root root 1829 ./usr/share/mime/text/x-python3.xml
+-rw-r--r-- root root 3116 ./usr/share/mime/text/x-python.xml
+-rw-r--r-- root root 2865 ./usr/share/mime/text/x-qml.xml
+-rw-r--r-- root root 3185 ./usr/share/mime/text/x-readme.xml
+-rw-r--r-- root root 3144 ./usr/share/mime/text/x-reject.xml
+-rw-r--r-- root root 3198 ./usr/share/mime/text/x-rpm-spec.xml
+-rw-r--r-- root root 1880 ./usr/share/mime/text/x-rst.xml
+-rw-r--r-- root root 2443 ./usr/share/mime/text/x-sass.xml
+-rw-r--r-- root root 2616 ./usr/share/mime/text/x-scala.xml
+-rw-r--r-- root root 3324 ./usr/share/mime/text/x-scheme.xml
+-rw-r--r-- root root 2573 ./usr/share/mime/text/x-scons.xml
+-rw-r--r-- root root 1132 ./usr/share/mime/text/x-scss.xml
+-rw-r--r-- root root 3114 ./usr/share/mime/text/x-setext.xml
+-rw-r--r-- root root 2929 ./usr/share/mime/text/x-ssa.xml
+-rw-r--r-- root root 3142 ./usr/share/mime/text/x-subviewer.xml
+-rw-r--r-- root root 2665 ./usr/share/mime/text/x-svhdr.xml
+-rw-r--r-- root root 2853 ./usr/share/mime/text/x-svsrc.xml
+-rw-r--r-- root root 2364 ./usr/share/mime/text/x-systemd-unit.xml
+-rw-r--r-- root root 2818 ./usr/share/mime/text/x-tcl.xml
+-rw-r--r-- root root 3204 ./usr/share/mime/text/x-texinfo.xml
+-rw-r--r-- root root 3092 ./usr/share/mime/text/x-tex.xml
+-rw-r--r-- root root 3580 ./usr/share/mime/text/x-troff-me.xml
+-rw-r--r-- root root 3580 ./usr/share/mime/text/x-troff-mm.xml
+-rw-r--r-- root root 3580 ./usr/share/mime/text/x-troff-ms.xml
+-rw-r--r-- root root 1811 ./usr/share/mime/text/x-twig.xml
+-rw-r--r-- root root 3150 ./usr/share/mime/text/x-txt2tags.xml
+-rw-r--r-- root root 3074 ./usr/share/mime/text/x-uil.xml
+-rw-r--r-- root root 3061 ./usr/share/mime/text/x-uri.xml
+-rw-r--r-- root root 2586 ./usr/share/mime/text/x-uuencode.xml
+-rw-r--r-- root root 3062 ./usr/share/mime/text/x-vala.xml
+-rw-r--r-- root root 2676 ./usr/share/mime/text/x-verilog.xml
+-rw-r--r-- root root 2711 ./usr/share/mime/text/x-vhdl.xml
+-rw-r--r-- root root 2710 ./usr/share/mime/text/x-xmi.xml
+-rw-r--r-- root root 2956 ./usr/share/mime/text/x-xslfo.xml
+-rw-r--r-- root root 1140 ./usr/share/mime/treemagic
+-rw-r--r-- root root 17478 ./usr/share/mime/types
+-rw-r--r-- root root 5 ./usr/share/mime/version
+drwxr-xr-x root root 4096 ./usr/share/mime/video
+-rw-r--r-- root root 3285 ./usr/share/mime/video/3gpp2.xml
+-rw-r--r-- root root 3885 ./usr/share/mime/video/3gpp.xml
+-rw-r--r-- root root 1021 ./usr/share/mime/video/annodex.xml
+-rw-r--r-- root root 2734 ./usr/share/mime/video/dv.xml
+-rw-r--r-- root root 2779 ./usr/share/mime/video/isivideo.xml
+-rw-r--r-- root root 1888 ./usr/share/mime/video/mj2.xml
+-rw-r--r-- root root 3455 ./usr/share/mime/video/mp2t.xml
+-rw-r--r-- root root 3007 ./usr/share/mime/video/mp4.xml
+-rw-r--r-- root root 3190 ./usr/share/mime/video/mpeg.xml
+-rw-r--r-- root root 979 ./usr/share/mime/video/ogg.xml
+-rw-r--r-- root root 3114 ./usr/share/mime/video/quicktime.xml
+-rw-r--r-- root root 2948 ./usr/share/mime/video/vnd.mpegurl.xml
+-rw-r--r-- root root 3172 ./usr/share/mime/video/vnd.rn-realvideo.xml
+-rw-r--r-- root root 2913 ./usr/share/mime/video/vnd.vivo.xml
+-rw-r--r-- root root 3006 ./usr/share/mime/video/wavelet.xml
+-rw-r--r-- root root 2461 ./usr/share/mime/video/webm.xml
+-rw-r--r-- root root 3073 ./usr/share/mime/video/x-anim.xml
+-rw-r--r-- root root 2944 ./usr/share/mime/video/x-flic.xml
+-rw-r--r-- root root 2995 ./usr/share/mime/video/x-flv.xml
+-rw-r--r-- root root 2533 ./usr/share/mime/video/x-javafx.xml
+-rw-r--r-- root root 2381 ./usr/share/mime/video/x-matroska-3d.xml
+-rw-r--r-- root root 3095 ./usr/share/mime/video/x-matroska.xml
+-rw-r--r-- root root 1841 ./usr/share/mime/video/x-mjpeg.xml
+-rw-r--r-- root root 2935 ./usr/share/mime/video/x-mng.xml
+-rw-r--r-- root root 3153 ./usr/share/mime/video/x-msvideo.xml
+-rw-r--r-- root root 3200 ./usr/share/mime/video/x-ms-wmv.xml
+-rw-r--r-- root root 2934 ./usr/share/mime/video/x-nsv.xml
+-rw-r--r-- root root 2782 ./usr/share/mime/video/x-ogm+ogg.xml
+-rw-r--r-- root root 2811 ./usr/share/mime/video/x-sgi-movie.xml
+-rw-r--r-- root root 3102 ./usr/share/mime/video/x-theora+ogg.xml
+drwxr-xr-x root root 4096 ./usr/share/mime/x-content
+-rw-r--r-- root root 2504 ./usr/share/mime/x-content/audio-cdda.xml
+-rw-r--r-- root root 2531 ./usr/share/mime/x-content/audio-dvd.xml
+-rw-r--r-- root root 3388 ./usr/share/mime/x-content/audio-player.xml
+-rw-r--r-- root root 2971 ./usr/share/mime/x-content/blank-bd.xml
+-rw-r--r-- root root 2700 ./usr/share/mime/x-content/blank-cd.xml
+-rw-r--r-- root root 2732 ./usr/share/mime/x-content/blank-dvd.xml
+-rw-r--r-- root root 2889 ./usr/share/mime/x-content/blank-hddvd.xml
+-rw-r--r-- root root 2640 ./usr/share/mime/x-content/ebook-reader.xml
+-rw-r--r-- root root 2917 ./usr/share/mime/x-content/image-dcf.xml
+-rw-r--r-- root root 2565 ./usr/share/mime/x-content/image-picturecd.xml
+-rw-r--r-- root root 1123 ./usr/share/mime/x-content/ostree-repository.xml
+-rw-r--r-- root root 2645 ./usr/share/mime/x-content/software.xml
+-rw-r--r-- root root 2645 ./usr/share/mime/x-content/unix-software.xml
+-rw-r--r-- root root 3122 ./usr/share/mime/x-content/video-bluray.xml
+-rw-r--r-- root root 2627 ./usr/share/mime/x-content/video-dvd.xml
+-rw-r--r-- root root 2977 ./usr/share/mime/x-content/video-hddvd.xml
+-rw-r--r-- root root 2791 ./usr/share/mime/x-content/video-svcd.xml
+-rw-r--r-- root root 2509 ./usr/share/mime/x-content/video-vcd.xml
+-rw-r--r-- root root 2773 ./usr/share/mime/x-content/win32-software.xml
+drwxr-xr-x root root 4096 ./usr/share/mime/x-epoc
+-rw-r--r-- root root 2878 ./usr/share/mime/x-epoc/x-sisx-app.xml
+-rw-r--r-- root root 1631 ./usr/share/mime/XMLnamespaces
+drwxr-xr-x root root 4096 ./usr/share/misc
+drwxr-xr-x root root 4096 ./usr/share/pkgconfig
+-rw-r--r-- root root 328 ./usr/share/pkgconfig/bash-completion.pc
+-rw-r--r-- root root 120 ./usr/share/pkgconfig/shared-mime-info.pc
+-rw-r--r-- root root 90 ./usr/share/pkgconfig/udev.pc
+-rw-r--r-- root root 384 ./usr/share/pkgconfig/xorg-macros.pc
+-rw-r--r-- root root 213 ./usr/share/pkgconfig/xtrans.pc
+drwxr-xr-x root root 4096 ./usr/share/ss
+-rw-r--r-- root root 1551 ./usr/share/ss/ct_c.awk
+-rw-r--r-- root root 2290 ./usr/share/ss/ct_c.sed
+drwxr-xr-x root root 4096 ./usr/share/tabset
+-rw-r--r-- root root 135 ./usr/share/tabset/std
+-rw-r--r-- root root 95 ./usr/share/tabset/stdcrt
+-rw-r--r-- root root 160 ./usr/share/tabset/vt100
+-rw-r--r-- root root 64 ./usr/share/tabset/vt300
+drwxr-xr-x root root 4096 ./usr/share/udhcpc
+-rwxr-xr-x root root 49 ./usr/share/udhcpc/default.script
+drwxr-xr-x root root 4096 ./usr/share/wayland
+-rw-r--r-- root root 1266 ./usr/share/wayland/wayland.dtd
+-rw-r--r-- root root 292 ./usr/share/wayland/wayland-scanner.mk
+-rw-r--r-- root root 131466 ./usr/share/wayland/wayland.xml
+drwxr-xr-x root root 4096 ./usr/share/X11
+-rw-r--r-- root root 1723 ./usr/share/X11/Xcms.txt
+-rw-r--r-- root root 42077 ./usr/share/X11/XErrorDB
+drwxr-xr-x root root 4096 ./usr/share/xcb
+-rw-r--r-- root root 1705 ./usr/share/xcb/bigreq.xml
+-rw-r--r-- root root 3473 ./usr/share/xcb/composite.xml
+-rw-r--r-- root root 3299 ./usr/share/xcb/damage.xml
+-rw-r--r-- root root 3155 ./usr/share/xcb/dpms.xml
+-rw-r--r-- root root 9488 ./usr/share/xcb/dri2.xml
+-rw-r--r-- root root 5638 ./usr/share/xcb/dri3.xml
+-rw-r--r-- root root 1863 ./usr/share/xcb/ge.xml
+-rw-r--r-- root root 45351 ./usr/share/xcb/glx.xml
+-rw-r--r-- root root 7335 ./usr/share/xcb/present.xml
+-rw-r--r-- root root 30366 ./usr/share/xcb/randr.xml
+-rw-r--r-- root root 5924 ./usr/share/xcb/record.xml
+-rw-r--r-- root root 23693 ./usr/share/xcb/render.xml
+-rw-r--r-- root root 5912 ./usr/share/xcb/res.xml
+-rw-r--r-- root root 6573 ./usr/share/xcb/screensaver.xml
+-rw-r--r-- root root 6039 ./usr/share/xcb/shape.xml
+-rw-r--r-- root root 4778 ./usr/share/xcb/shm.xml
+-rw-r--r-- root root 8390 ./usr/share/xcb/sync.xml
+-rw-r--r-- root root 16132 ./usr/share/xcb/xcb.xsd
+-rw-r--r-- root root 1162 ./usr/share/xcb/xc_misc.xml
+-rw-r--r-- root root 2958 ./usr/share/xcb/xevie.xml
+-rw-r--r-- root root 5900 ./usr/share/xcb/xf86dri.xml
+-rw-r--r-- root root 14673 ./usr/share/xcb/xf86vidmode.xml
+-rw-r--r-- root root 12074 ./usr/share/xcb/xfixes.xml
+-rw-r--r-- root root 3453 ./usr/share/xcb/xinerama.xml
+-rw-r--r-- root root 103534 ./usr/share/xcb/xinput.xml
+-rw-r--r-- root root 91919 ./usr/share/xcb/xkb.xml
+-rw-r--r-- root root 11134 ./usr/share/xcb/xprint.xml
+-rw-r--r-- root root 206253 ./usr/share/xcb/xproto.xml
+-rw-r--r-- root root 8260 ./usr/share/xcb/xselinux.xml
+-rw-r--r-- root root 3968 ./usr/share/xcb/xtest.xml
+-rw-r--r-- root root 5363 ./usr/share/xcb/xvmc.xml
+-rw-r--r-- root root 16061 ./usr/share/xcb/xv.xml
+drwxr-xr-x root root 4096 ./usr/share/xml
+drwxr-xr-x root root 4096 ./usr/share/xml/dbus-1
+-rw-r--r-- root root 1907 ./usr/share/xml/dbus-1/busconfig.dtd
+-rw-r--r-- root root 1226 ./usr/share/xml/dbus-1/introspect.dtd
+drwxr-xr-x root root 4096 ./usr/share/xml/fontconfig
+-rw-r--r-- root root 7250 ./usr/share/xml/fontconfig/fonts.dtd
+drwxr-xr-x root root 4096 ./usr/src
+drwxr-xr-x root root 4096 ./usr/x86_64-poky-linux
+drwxr-xr-x root root 4096 ./usr/x86_64-poky-linux/bin
+lrwxrwxrwx root root 30 ./usr/x86_64-poky-linux/bin/ar -> ../../bin/x86_64-poky-linux-ar
+lrwxrwxrwx root root 30 ./usr/x86_64-poky-linux/bin/as -> ../../bin/x86_64-poky-linux-as
+lrwxrwxrwx root root 34 ./usr/x86_64-poky-linux/bin/ld.bfd -> ../../bin/x86_64-poky-linux-ld.bfd
+lrwxrwxrwx root root 30 ./usr/x86_64-poky-linux/bin/ld -> ../../bin/x86_64-poky-linux-ld
+lrwxrwxrwx root root 35 ./usr/x86_64-poky-linux/bin/ld.gold -> ../../bin/x86_64-poky-linux-ld.gold
+lrwxrwxrwx root root 30 ./usr/x86_64-poky-linux/bin/nm -> ../../bin/x86_64-poky-linux-nm
+lrwxrwxrwx root root 35 ./usr/x86_64-poky-linux/bin/objcopy -> ../../bin/x86_64-poky-linux-objcopy
+lrwxrwxrwx root root 35 ./usr/x86_64-poky-linux/bin/objdump -> ../../bin/x86_64-poky-linux-objdump
+lrwxrwxrwx root root 34 ./usr/x86_64-poky-linux/bin/ranlib -> ../../bin/x86_64-poky-linux-ranlib
+lrwxrwxrwx root root 35 ./usr/x86_64-poky-linux/bin/readelf -> ../../bin/x86_64-poky-linux-readelf
+lrwxrwxrwx root root 33 ./usr/x86_64-poky-linux/bin/strip -> ../../bin/x86_64-poky-linux-strip
+drwxr-xr-x root root 4096 ./var
+drwxr-xr-x root root 4096 ./var/backups
+drwxr-xr-x root root 4096 ./var/cache
+drwxr-xr-x root root 4096 ./var/cache/fontconfig
+drwx------ root root 4096 ./var/cache/ldconfig
+-rw------- root root 9934 ./var/cache/ldconfig/aux-cache
+drwxr-xr-x root root 4096 ./var/db
+-rwxr-xr-x root root 4453 ./var/db/makedbs.sh
+-rw-r--r-- root root 5351 ./var/db/Makefile
+drwxr-xr-x root root 4096 ./var/lib
+drwxr-xr-x root root 4096 ./var/lib/arpd
+drwxr-xr-x messagebus messagebus 4096 ./var/lib/dbus
+drwxr-xr-x root root 4096 ./var/lib/misc
+drwxr-xr-x root root 4096 ./var/lib/urandom
+drwxr-xr-x root root 4096 ./var/local
+lrwxrwxrwx root root 11 ./var/lock -> ../run/lock
+lrwxrwxrwx root root 12 ./var/log -> volatile/log
+lrwxrwxrwx root root 6 ./var/run -> ../run
+drwxr-xr-x root root 4096 ./var/spool
+drwxrwxr-x root mail 4096 ./var/spool/mail
+lrwxrwxrwx root root 12 ./var/tmp -> volatile/tmp
+drwxr-xr-x root root 4096 ./var/volatile
diff --git a/meta/lib/oeqa/files/buildhistory_filelist2.txt b/meta/lib/oeqa/files/buildhistory_filelist2.txt
new file mode 100644
index 0000000000..ac6307060d
--- /dev/null
+++ b/meta/lib/oeqa/files/buildhistory_filelist2.txt
@@ -0,0 +1,9217 @@
+drwxr-xr-x root root 4096 ./bin
+lrwxrwxrwx root root 19 ./bin/ash -> /bin/busybox.nosuid
+lrwxrwxrwx root root 25 ./bin/base64 -> /usr/bin/base64.coreutils
+-rwxr-xr-x root root 1190872 ./bin/bash.bash
+lrwxrwxrwx root root 14 ./bin/bash -> /bin/bash.bash
+lrwxrwxrwx root root 14 ./bin/busybox -> busybox.nosuid
+-rwxr-xr-x root root 613008 ./bin/busybox.nosuid
+-rwsr-xr-x root root 59440 ./bin/busybox.suid
+lrwxrwxrwx root root 18 ./bin/cat -> /bin/cat.coreutils
+-rwxr-xr-x root root 47336 ./bin/cat.coreutils
+lrwxrwxrwx root root 21 ./bin/chattr -> /bin/chattr.e2fsprogs
+-rwxr-xr-x root root 14312 ./bin/chattr.e2fsprogs
+lrwxrwxrwx root root 20 ./bin/chgrp -> /bin/chgrp.coreutils
+-rwxr-xr-x root root 75944 ./bin/chgrp.coreutils
+lrwxrwxrwx root root 20 ./bin/chmod -> /bin/chmod.coreutils
+-rwxr-xr-x root root 71880 ./bin/chmod.coreutils
+lrwxrwxrwx root root 20 ./bin/chown -> /bin/chown.coreutils
+-rwxr-xr-x root root 80040 ./bin/chown.coreutils
+lrwxrwxrwx root root 17 ./bin/cp -> /bin/cp.coreutils
+-rwxr-xr-x root root 137416 ./bin/cp.coreutils
+lrwxrwxrwx root root 19 ./bin/cpio -> /bin/busybox.nosuid
+lrwxrwxrwx root root 19 ./bin/date -> /bin/date.coreutils
+-rwxr-xr-x root root 121032 ./bin/date.coreutils
+lrwxrwxrwx root root 17 ./bin/dd -> /bin/dd.coreutils
+-rwxr-xr-x root root 88272 ./bin/dd.coreutils
+lrwxrwxrwx root root 21 ./bin/df -> /usr/bin/df.coreutils
+lrwxrwxrwx root root 21 ./bin/dmesg -> /bin/dmesg.util-linux
+-rwxr-xr-x root root 84256 ./bin/dmesg.util-linux
+lrwxrwxrwx root root 19 ./bin/dnsdomainname -> /bin/busybox.nosuid
+lrwxrwxrwx root root 19 ./bin/dumpkmap -> /bin/busybox.nosuid
+lrwxrwxrwx root root 19 ./bin/echo -> /bin/echo.coreutils
+-rwxr-xr-x root root 39064 ./bin/echo.coreutils
+lrwxrwxrwx root root 15 ./bin/egrep -> /bin/egrep.grep
+-rwxr-xr-x root root 28 ./bin/egrep.grep
+lrwxrwxrwx root root 20 ./bin/false -> /bin/false.coreutils
+-rwxr-xr-x root root 39064 ./bin/false.coreutils
+lrwxrwxrwx root root 15 ./bin/fgrep -> /bin/fgrep.grep
+-rwxr-xr-x root root 28 ./bin/fgrep.grep
+lrwxrwxrwx root root 22 ./bin/getopt -> /bin/getopt.util-linux
+-rwxr-xr-x root root 22576 ./bin/getopt.util-linux
+lrwxrwxrwx root root 14 ./bin/grep -> /bin/grep.grep
+-rwxr-xr-x root root 244016 ./bin/grep.grep
+lrwxrwxrwx root root 19 ./bin/gunzip -> /bin/busybox.nosuid
+lrwxrwxrwx root root 19 ./bin/gzip -> /bin/busybox.nosuid
+lrwxrwxrwx root root 23 ./bin/hostname -> /bin/hostname.coreutils
+-rwxr-xr-x root root 43176 ./bin/hostname.coreutils
+lrwxrwxrwx root root 16 ./bin/kill -> /bin/kill.procps
+-rwxr-xr-x root root 47712 ./bin/kill.coreutils
+-rwxr-xr-x root root 30760 ./bin/kill.procps
+-rwxr-xr-x root root 38960 ./bin/kill.util-linux
+-rwxr-xr-x root root 149648 ./bin/kmod
+lrwxrwxrwx root root 17 ./bin/ln -> /bin/ln.coreutils
+-rwxr-xr-x root root 75984 ./bin/ln.coreutils
+lrwxrwxrwx root root 17 ./bin/login -> /bin/login.shadow
+-rwxr-xr-x root root 73120 ./bin/login.shadow
+lrwxrwxrwx root root 17 ./bin/ls -> /bin/ls.coreutils
+-rwxr-xr-x root root 162448 ./bin/ls.coreutils
+lrwxrwxrwx root root 15 ./bin/lsmod -> /bin/lsmod.kmod
+lrwxrwxrwx root root 4 ./bin/lsmod.kmod -> kmod
+lrwxrwxrwx root root 20 ./bin/mkdir -> /bin/mkdir.coreutils
+-rwxr-xr-x root root 67752 ./bin/mkdir.coreutils
+lrwxrwxrwx root root 20 ./bin/mknod -> /bin/mknod.coreutils
+-rwxr-xr-x root root 47272 ./bin/mknod.coreutils
+lrwxrwxrwx root root 25 ./bin/mktemp -> /usr/bin/mktemp.coreutils
+lrwxrwxrwx root root 20 ./bin/more -> /bin/more.util-linux
+-rwxr-xr-x root root 42976 ./bin/more.util-linux
+lrwxrwxrwx root root 21 ./bin/mount -> /bin/mount.util-linux
+lrwxrwxrwx root root 26 ./bin/mountpoint -> /bin/mountpoint.util-linux
+-rwxr-xr-x root root 14304 ./bin/mountpoint.sysvinit
+-rwxr-xr-x root root 18480 ./bin/mountpoint.util-linux
+-rwsr-xr-x root root 55344 ./bin/mount.util-linux
+lrwxrwxrwx root root 17 ./bin/mv -> /bin/mv.coreutils
+-rwxr-xr-x root root 145616 ./bin/mv.coreutils
+lrwxrwxrwx root root 19 ./bin/netstat -> /bin/busybox.nosuid
+lrwxrwxrwx root root 23 ./bin/nice -> /usr/bin/nice.coreutils
+lrwxrwxrwx root root 19 ./bin/pidof -> /bin/pidof.sysvinit
+-rwxr-xr-x root root 22568 ./bin/pidof.procps
+lrwxrwxrwx root root 14 ./bin/pidof.sysvinit -> /sbin/killall5
+lrwxrwxrwx root root 17 ./bin/ping6 -> /bin/busybox.suid
+lrwxrwxrwx root root 17 ./bin/ping -> /bin/busybox.suid
+lrwxrwxrwx root root 27 ./bin/printenv -> /usr/bin/printenv.coreutils
+lrwxrwxrwx root root 14 ./bin/ps -> /bin/ps.procps
+-rwxr-xr-x root root 137496 ./bin/ps.procps
+lrwxrwxrwx root root 18 ./bin/pwd -> /bin/pwd.coreutils
+-rwxr-xr-x root root 47272 ./bin/pwd.coreutils
+lrwxrwxrwx root root 17 ./bin/rm -> /bin/rm.coreutils
+-rwxr-xr-x root root 75976 ./bin/rm.coreutils
+lrwxrwxrwx root root 20 ./bin/rmdir -> /bin/rmdir.coreutils
+-rwxr-xr-x root root 55464 ./bin/rmdir.coreutils
+lrwxrwxrwx root root 19 ./bin/run-parts -> /bin/busybox.nosuid
+lrwxrwxrwx root root 12 ./bin/sed -> /bin/sed.sed
+-rwxr-xr-x root root 190896 ./bin/sed.sed
+lrwxrwxrwx root root 14 ./bin/sh -> /bin/bash.bash
+lrwxrwxrwx root root 20 ./bin/sleep -> /bin/sleep.coreutils
+-rwxr-xr-x root root 43176 ./bin/sleep.coreutils
+-rwxr-xr-x root root 1736 ./bin/start_getty
+lrwxrwxrwx root root 19 ./bin/stat -> /bin/stat.coreutils
+-rwxr-xr-x root root 96456 ./bin/stat.coreutils
+lrwxrwxrwx root root 19 ./bin/stty -> /bin/stty.coreutils
+-rwxr-xr-x root root 92360 ./bin/stty.coreutils
+lrwxrwxrwx root root 14 ./bin/su -> /bin/su.shadow
+-rwsr-xr-x root root 60992 ./bin/su.shadow
+lrwxrwxrwx root root 19 ./bin/sync -> /bin/sync.coreutils
+-rwxr-xr-x root root 43176 ./bin/sync.coreutils
+lrwxrwxrwx root root 19 ./bin/tar -> /bin/busybox.nosuid
+lrwxrwxrwx root root 20 ./bin/touch -> /bin/touch.coreutils
+-rwxr-xr-x root root 108744 ./bin/touch.coreutils
+lrwxrwxrwx root root 19 ./bin/true -> /bin/true.coreutils
+-rwxr-xr-x root root 39064 ./bin/true.coreutils
+lrwxrwxrwx root root 22 ./bin/umount -> /bin/umount.util-linux
+-rwsr-xr-x root root 34864 ./bin/umount.util-linux
+lrwxrwxrwx root root 20 ./bin/uname -> /bin/uname.coreutils
+-rwxr-xr-x root root 43208 ./bin/uname.coreutils
+lrwxrwxrwx root root 19 ./bin/usleep -> /bin/busybox.nosuid
+lrwxrwxrwx root root 19 ./bin/vi -> /bin/busybox.nosuid
+lrwxrwxrwx root root 17 ./bin/watch -> /bin/watch.procps
+-rwxr-xr-x root root 27016 ./bin/watch.procps
+lrwxrwxrwx root root 19 ./bin/zcat -> /bin/busybox.nosuid
+drwxr-xr-x root root 4096 ./boot
+drwxr-xr-x root root 4096 ./dev
+drwxr-xr-x root root 4096 ./etc
+-rw-r--r-- root root 45 ./etc/bash_completion
+drwxr-xr-x root root 4096 ./etc/bash_completion.d
+-rw-r--r-- root root 447 ./etc/bindresvport.blacklist
+-rw-r--r-- root root 521 ./etc/build
+-rw-r--r-- root root 2370 ./etc/busybox.links.nosuid
+-rw-r--r-- root root 91 ./etc/busybox.links.suid
+drwxr-xr-x root root 4096 ./etc/ca-certificates
+-rw-r--r-- root root 5340 ./etc/ca-certificates.conf
+drwxr-xr-x root root 4096 ./etc/ca-certificates/update.d
+drwxr-xr-x root root 4096 ./etc/dbus-1
+-rw-r--r-- root root 838 ./etc/dbus-1/session.conf
+-rw-r--r-- root root 833 ./etc/dbus-1/system.conf
+drwxr-xr-x root root 4096 ./etc/default
+-rwxr-xr-x root root 93 ./etc/default/devpts
+-rw-r--r-- root root 36 ./etc/default/mountall
+-rw-r--r-- root root 52 ./etc/default/postinst
+-rw-r--r-- root root 1040 ./etc/default/rcS
+-rw-r--r-- root root 117 ./etc/default/useradd
+drwxr-xr-x root root 4096 ./etc/default/volatiles
+-rw-r--r-- root root 1637 ./etc/default/volatiles/00_core
+-rw-r--r-- root root 36 ./etc/default/volatiles/01_bootlogd
+-rw-r--r-- root root 48 ./etc/default/volatiles/99_dbus
+drwxr-xr-x root root 4096 ./etc/depmod.d
+-rw-r--r-- root root 685 ./etc/e2scrub.conf
+drwxr-xr-x root root 4096 ./etc/fonts
+drwxr-xr-x root root 4096 ./etc/fonts/conf.d
+lrwxrwxrwx root root 63 ./etc/fonts/conf.d/10-hinting-slight.conf -> ../../../usr/share/fontconfig/conf.avail/10-hinting-slight.conf
+lrwxrwxrwx root root 67 ./etc/fonts/conf.d/10-scale-bitmap-fonts.conf -> ../../../usr/share/fontconfig/conf.avail/10-scale-bitmap-fonts.conf
+lrwxrwxrwx root root 66 ./etc/fonts/conf.d/20-unhint-small-vera.conf -> ../../../usr/share/fontconfig/conf.avail/20-unhint-small-vera.conf
+lrwxrwxrwx root root 63 ./etc/fonts/conf.d/30-metric-aliases.conf -> ../../../usr/share/fontconfig/conf.avail/30-metric-aliases.conf
+lrwxrwxrwx root root 57 ./etc/fonts/conf.d/40-nonlatin.conf -> ../../../usr/share/fontconfig/conf.avail/40-nonlatin.conf
+lrwxrwxrwx root root 56 ./etc/fonts/conf.d/45-generic.conf -> ../../../usr/share/fontconfig/conf.avail/45-generic.conf
+lrwxrwxrwx root root 54 ./etc/fonts/conf.d/45-latin.conf -> ../../../usr/share/fontconfig/conf.avail/45-latin.conf
+lrwxrwxrwx root root 58 ./etc/fonts/conf.d/49-sansserif.conf -> ../../../usr/share/fontconfig/conf.avail/49-sansserif.conf
+lrwxrwxrwx root root 53 ./etc/fonts/conf.d/50-user.conf -> ../../../usr/share/fontconfig/conf.avail/50-user.conf
+lrwxrwxrwx root root 54 ./etc/fonts/conf.d/51-local.conf -> ../../../usr/share/fontconfig/conf.avail/51-local.conf
+lrwxrwxrwx root root 56 ./etc/fonts/conf.d/60-generic.conf -> ../../../usr/share/fontconfig/conf.avail/60-generic.conf
+lrwxrwxrwx root root 54 ./etc/fonts/conf.d/60-latin.conf -> ../../../usr/share/fontconfig/conf.avail/60-latin.conf
+lrwxrwxrwx root root 62 ./etc/fonts/conf.d/65-fonts-persian.conf -> ../../../usr/share/fontconfig/conf.avail/65-fonts-persian.conf
+lrwxrwxrwx root root 57 ./etc/fonts/conf.d/65-nonlatin.conf -> ../../../usr/share/fontconfig/conf.avail/65-nonlatin.conf
+lrwxrwxrwx root root 56 ./etc/fonts/conf.d/69-unifont.conf -> ../../../usr/share/fontconfig/conf.avail/69-unifont.conf
+lrwxrwxrwx root root 58 ./etc/fonts/conf.d/80-delicious.conf -> ../../../usr/share/fontconfig/conf.avail/80-delicious.conf
+lrwxrwxrwx root root 58 ./etc/fonts/conf.d/90-synthetic.conf -> ../../../usr/share/fontconfig/conf.avail/90-synthetic.conf
+-rw-r--r-- root root 978 ./etc/fonts/conf.d/README
+-rw-r--r-- root root 2532 ./etc/fonts/fonts.conf
+-rw-r--r-- root root 650 ./etc/fstab
+-rw-r--r-- root root 501 ./etc/group
+-r-------- root root 420 ./etc/gshadow
+-rw-r--r-- root root 26 ./etc/host.conf
+-rw-r--r-- root root 11 ./etc/hostname
+-rw-r--r-- root root 258 ./etc/hosts
+drwxr-xr-x root root 4096 ./etc/init.d
+-rwxr-xr-x root root 492 ./etc/init.d/banner.sh
+-rwxr-xr-x root root 1997 ./etc/init.d/bootlogd
+-rwxr-xr-x root root 2017 ./etc/init.d/bootmisc.sh
+-rwxr-xr-x root root 3591 ./etc/init.d/checkroot.sh
+-rwxr-xr-x root root 2893 ./etc/init.d/dbus-1
+-rwxr-xr-x root root 526 ./etc/init.d/devpts.sh
+-rwxr-xr-x root root 352 ./etc/init.d/dmesg.sh
+-rw-r--r-- root root 2141 ./etc/init.d/functions
+-rwxr-xr-x root root 510 ./etc/init.d/halt
+-rwxr-xr-x root root 580 ./etc/init.d/hostname.sh
+-rwxr-xr-x root root 2541 ./etc/init.d/hwclock.sh
+-rwxr-xr-x root root 1773 ./etc/init.d/mdmonitor
+-rwxr-xr-x root root 1223 ./etc/init.d/modutils.sh
+-rwxr-xr-x root root 869 ./etc/init.d/mountall.sh
+-rwxr-xr-x root root 1589 ./etc/init.d/mountnfs.sh
+-rwxr-xr-x root root 1956 ./etc/init.d/networking
+-rwxr-xr-x root root 7823 ./etc/init.d/populate-volatile.sh
+-rwxr-xr-x root root 4457 ./etc/init.d/rc
+-rwxr-xr-x root root 525 ./etc/init.d/rcS
+-rwxr-xr-x root root 1273 ./etc/init.d/read-only-rootfs-hook.sh
+-rwxr-xr-x root root 289 ./etc/init.d/reboot
+-rwxr-xr-x root root 585 ./etc/init.d/rmnologin.sh
+-rwxr-xr-x root root 25 ./etc/init.d/run-postinsts
+-rwxr-xr-x root root 429 ./etc/init.d/save-rtc.sh
+-rwxr-xr-x root root 438 ./etc/init.d/sendsigs
+-rwxr-xr-x root root 578 ./etc/init.d/single
+lrwxrwxrwx root root 8 ./etc/init.d/stop-bootlogd -> bootlogd
+-rwxr-xr-x root root 1046 ./etc/init.d/sysfs.sh
+-rwxr-xr-x root root 2066 ./etc/init.d/syslog
+-rwxr-xr-x root root 2779 ./etc/init.d/udev
+-rwxr-xr-x root root 540 ./etc/init.d/umountfs
+-rwxr-xr-x root root 711 ./etc/init.d/umountnfs.sh
+-rwxr-xr-x root root 1473 ./etc/init.d/urandom
+-rw-r--r-- root root 1140 ./etc/inittab
+-rw-r--r-- root root 1633 ./etc/inputrc
+drwxr-xr-x root root 4096 ./etc/iproute2
+-rw-r--r-- root root 85 ./etc/iproute2/bpf_pinning
+-rw-r--r-- root root 81 ./etc/iproute2/ematch_map
+-rw-r--r-- root root 31 ./etc/iproute2/group
+-rw-r--r-- root root 262 ./etc/iproute2/nl_protos
+-rw-r--r-- root root 331 ./etc/iproute2/rt_dsfield
+-rw-r--r-- root root 201 ./etc/iproute2/rt_protos
+-rw-r--r-- root root 112 ./etc/iproute2/rt_realms
+-rw-r--r-- root root 92 ./etc/iproute2/rt_scopes
+-rw-r--r-- root root 87 ./etc/iproute2/rt_tables
+drwxr-xr-x root root 4096 ./etc/iptables
+-rw-r--r-- root root 0 ./etc/iptables/ip6tables.rules
+-rw-r--r-- root root 0 ./etc/iptables/iptables.rules
+-rw-r--r-- root root 58 ./etc/issue
+-rw-r--r-- root root 55 ./etc/issue.net
+-rw-r--r-- root root 18635 ./etc/ld.so.cache
+-rw-r--r-- root root 33 ./etc/ld.so.conf
+-rw-r--r-- root root 827 ./etc/limits
+-rw-r--r-- root root 2006 ./etc/login.access
+-rw-r--r-- root root 12001 ./etc/login.defs
+-rw-r--r-- root root 121 ./etc/logrotate-dmesg.conf
+-rw-r--r-- root root 2687 ./etc/mdadm.conf
+-rw-r--r-- root root 812 ./etc/mke2fs.conf
+drwxr-xr-x root root 4096 ./etc/modprobe.d
+-rw-r--r-- root root 0 ./etc/motd
+lrwxrwxrwx root root 12 ./etc/mtab -> /proc/mounts
+-rw-r--r-- root root 767 ./etc/netconfig
+drwxr-xr-x root root 4096 ./etc/network
+drwxr-xr-x root root 4096 ./etc/network/if-down.d
+drwxr-xr-x root root 4096 ./etc/network/if-post-down.d
+drwxr-xr-x root root 4096 ./etc/network/if-pre-up.d
+-rwxr-xr-x root root 809 ./etc/network/if-pre-up.d/nfsroot
+drwxr-xr-x root root 4096 ./etc/network/if-up.d
+-rw-r--r-- root root 132 ./etc/network/interfaces
+-rw-r--r-- root root 0 ./etc/network/nm-disabled-eth0
+-rw-r--r-- root root 465 ./etc/nsswitch.conf
+-rw-r--r-- root root 767 ./etc/passwd
+-rw-r--r-- root root 984 ./etc/profile
+drwxr-xr-x root root 4096 ./etc/profile.d
+-rw-r--r-- root root 729 ./etc/profile.d/bash_completion.sh
+-rw-r--r-- root root 1107 ./etc/profile.d/gawk.csh
+-rw-r--r-- root root 757 ./etc/profile.d/gawk.sh
+-rw-r--r-- root root 2932 ./etc/protocols
+drwxr-xr-x root root 4096 ./etc/rc0.d
+lrwxrwxrwx root root 16 ./etc/rc0.d/K20dbus-1 -> ../init.d/dbus-1
+lrwxrwxrwx root root 20 ./etc/rc0.d/K20hwclock.sh -> ../init.d/hwclock.sh
+lrwxrwxrwx root root 16 ./etc/rc0.d/K20syslog -> ../init.d/syslog
+lrwxrwxrwx root root 20 ./etc/rc0.d/K80networking -> ../init.d/networking
+lrwxrwxrwx root root 18 ./etc/rc0.d/S20sendsigs -> ../init.d/sendsigs
+lrwxrwxrwx root root 21 ./etc/rc0.d/S25save-rtc.sh -> ../init.d/save-rtc.sh
+lrwxrwxrwx root root 22 ./etc/rc0.d/S31umountnfs.sh -> ../init.d/umountnfs.sh
+lrwxrwxrwx root root 17 ./etc/rc0.d/S38urandom -> ../init.d/urandom
+lrwxrwxrwx root root 18 ./etc/rc0.d/S40umountfs -> ../init.d/umountfs
+lrwxrwxrwx root root 14 ./etc/rc0.d/S90halt -> ../init.d/halt
+drwxr-xr-x root root 4096 ./etc/rc1.d
+lrwxrwxrwx root root 16 ./etc/rc1.d/K20dbus-1 -> ../init.d/dbus-1
+lrwxrwxrwx root root 20 ./etc/rc1.d/K20hwclock.sh -> ../init.d/hwclock.sh
+lrwxrwxrwx root root 16 ./etc/rc1.d/K20syslog -> ../init.d/syslog
+lrwxrwxrwx root root 20 ./etc/rc1.d/K80networking -> ../init.d/networking
+lrwxrwxrwx root root 22 ./etc/rc1.d/S31umountnfs.sh -> ../init.d/umountnfs.sh
+drwxr-xr-x root root 4096 ./etc/rc2.d
+lrwxrwxrwx root root 20 ./etc/rc2.d/S01networking -> ../init.d/networking
+lrwxrwxrwx root root 16 ./etc/rc2.d/S02dbus-1 -> ../init.d/dbus-1
+lrwxrwxrwx root root 21 ./etc/rc2.d/S15mountnfs.sh -> ../init.d/mountnfs.sh
+lrwxrwxrwx root root 20 ./etc/rc2.d/S20hwclock.sh -> ../init.d/hwclock.sh
+lrwxrwxrwx root root 16 ./etc/rc2.d/S20syslog -> ../init.d/syslog
+lrwxrwxrwx root root 22 ./etc/rc2.d/S99rmnologin.sh -> ../init.d/rmnologin.sh
+lrwxrwxrwx root root 23 ./etc/rc2.d/S99stop-bootlogd -> ../init.d/stop-bootlogd
+drwxr-xr-x root root 4096 ./etc/rc3.d
+lrwxrwxrwx root root 20 ./etc/rc3.d/S01networking -> ../init.d/networking
+lrwxrwxrwx root root 16 ./etc/rc3.d/S02dbus-1 -> ../init.d/dbus-1
+lrwxrwxrwx root root 21 ./etc/rc3.d/S15mountnfs.sh -> ../init.d/mountnfs.sh
+lrwxrwxrwx root root 20 ./etc/rc3.d/S20hwclock.sh -> ../init.d/hwclock.sh
+lrwxrwxrwx root root 16 ./etc/rc3.d/S20syslog -> ../init.d/syslog
+lrwxrwxrwx root root 22 ./etc/rc3.d/S99rmnologin.sh -> ../init.d/rmnologin.sh
+lrwxrwxrwx root root 23 ./etc/rc3.d/S99stop-bootlogd -> ../init.d/stop-bootlogd
+drwxr-xr-x root root 4096 ./etc/rc4.d
+lrwxrwxrwx root root 20 ./etc/rc4.d/S01networking -> ../init.d/networking
+lrwxrwxrwx root root 21 ./etc/rc4.d/S15mountnfs.sh -> ../init.d/mountnfs.sh
+lrwxrwxrwx root root 20 ./etc/rc4.d/S20hwclock.sh -> ../init.d/hwclock.sh
+lrwxrwxrwx root root 16 ./etc/rc4.d/S20syslog -> ../init.d/syslog
+lrwxrwxrwx root root 22 ./etc/rc4.d/S99rmnologin.sh -> ../init.d/rmnologin.sh
+lrwxrwxrwx root root 23 ./etc/rc4.d/S99stop-bootlogd -> ../init.d/stop-bootlogd
+drwxr-xr-x root root 4096 ./etc/rc5.d
+lrwxrwxrwx root root 20 ./etc/rc5.d/S01networking -> ../init.d/networking
+lrwxrwxrwx root root 16 ./etc/rc5.d/S02dbus-1 -> ../init.d/dbus-1
+lrwxrwxrwx root root 21 ./etc/rc5.d/S15mountnfs.sh -> ../init.d/mountnfs.sh
+lrwxrwxrwx root root 20 ./etc/rc5.d/S20hwclock.sh -> ../init.d/hwclock.sh
+lrwxrwxrwx root root 16 ./etc/rc5.d/S20syslog -> ../init.d/syslog
+lrwxrwxrwx root root 22 ./etc/rc5.d/S99rmnologin.sh -> ../init.d/rmnologin.sh
+lrwxrwxrwx root root 23 ./etc/rc5.d/S99stop-bootlogd -> ../init.d/stop-bootlogd
+drwxr-xr-x root root 4096 ./etc/rc6.d
+lrwxrwxrwx root root 16 ./etc/rc6.d/K20dbus-1 -> ../init.d/dbus-1
+lrwxrwxrwx root root 20 ./etc/rc6.d/K20hwclock.sh -> ../init.d/hwclock.sh
+lrwxrwxrwx root root 16 ./etc/rc6.d/K20syslog -> ../init.d/syslog
+lrwxrwxrwx root root 20 ./etc/rc6.d/K80networking -> ../init.d/networking
+lrwxrwxrwx root root 18 ./etc/rc6.d/S20sendsigs -> ../init.d/sendsigs
+lrwxrwxrwx root root 21 ./etc/rc6.d/S25save-rtc.sh -> ../init.d/save-rtc.sh
+lrwxrwxrwx root root 22 ./etc/rc6.d/S31umountnfs.sh -> ../init.d/umountnfs.sh
+lrwxrwxrwx root root 17 ./etc/rc6.d/S38urandom -> ../init.d/urandom
+lrwxrwxrwx root root 18 ./etc/rc6.d/S40umountfs -> ../init.d/umountfs
+lrwxrwxrwx root root 16 ./etc/rc6.d/S90reboot -> ../init.d/reboot
+drwxr-xr-x root root 4096 ./etc/rcS.d
+lrwxrwxrwx root root 19 ./etc/rcS.d/S02banner.sh -> ../init.d/banner.sh
+lrwxrwxrwx root root 18 ./etc/rcS.d/S02sysfs.sh -> ../init.d/sysfs.sh
+lrwxrwxrwx root root 21 ./etc/rcS.d/S03mountall.sh -> ../init.d/mountall.sh
+lrwxrwxrwx root root 14 ./etc/rcS.d/S04udev -> ../init.d/udev
+lrwxrwxrwx root root 21 ./etc/rcS.d/S05modutils.sh -> ../init.d/modutils.sh
+lrwxrwxrwx root root 22 ./etc/rcS.d/S06checkroot.sh -> ../init.d/checkroot.sh
+lrwxrwxrwx root root 19 ./etc/rcS.d/S06devpts.sh -> ../init.d/devpts.sh
+lrwxrwxrwx root root 18 ./etc/rcS.d/S07bootlogd -> ../init.d/bootlogd
+lrwxrwxrwx root root 34 ./etc/rcS.d/S29read-only-rootfs-hook.sh -> ../init.d/read-only-rootfs-hook.sh
+lrwxrwxrwx root root 21 ./etc/rcS.d/S36bootmisc.sh -> ../init.d/bootmisc.sh
+lrwxrwxrwx root root 30 ./etc/rcS.d/S37populate-volatile.sh -> ../init.d/populate-volatile.sh
+lrwxrwxrwx root root 18 ./etc/rcS.d/S38dmesg.sh -> ../init.d/dmesg.sh
+lrwxrwxrwx root root 17 ./etc/rcS.d/S38urandom -> ../init.d/urandom
+lrwxrwxrwx root root 21 ./etc/rcS.d/S39hostname.sh -> ../init.d/hostname.sh
+-rw-r--r-- root root 887 ./etc/rpc
+-r-------- root root 1848 ./etc/securetty
+-rw-r--r-- root root 14464 ./etc/services
+-r-------- root root 404 ./etc/shadow
+-rw-r--r-- root root 52 ./etc/shells
+drwxr-xr-x root root 4096 ./etc/skel
+-rwxr-xr-x root root 410 ./etc/skel/.bashrc
+-rwxr-xr-x root root 241 ./etc/skel/.profile
+drwxr-xr-x root root 4096 ./etc/ssl
+drwxr-xr-x root root 16384 ./etc/ssl/certs
+lrwxrwxrwx root root 45 ./etc/ssl/certs/02265526.0 -> Entrust_Root_Certification_Authority_-_G2.pem
+lrwxrwxrwx root root 36 ./etc/ssl/certs/03179a64.0 -> Staat_der_Nederlanden_EV_Root_CA.pem
+lrwxrwxrwx root root 27 ./etc/ssl/certs/062cdee6.0 -> GlobalSign_Root_CA_-_R3.pem
+lrwxrwxrwx root root 25 ./etc/ssl/certs/064e0aa9.0 -> QuoVadis_Root_CA_2_G3.pem
+lrwxrwxrwx root root 50 ./etc/ssl/certs/06dc52d5.0 -> SSL.com_EV_Root_Certification_Authority_RSA_R2.pem
+lrwxrwxrwx root root 20 ./etc/ssl/certs/080911ac.0 -> QuoVadis_Root_CA.pem
+lrwxrwxrwx root root 54 ./etc/ssl/certs/09789157.0 -> Starfield_Services_Root_Certificate_Authority_-_G2.pem
+lrwxrwxrwx root root 16 ./etc/ssl/certs/0b1b94ef.0 -> CFCA_EV_ROOT.pem
+lrwxrwxrwx root root 44 ./etc/ssl/certs/0bf05006.0 -> SSL.com_Root_Certification_Authority_ECC.pem
+lrwxrwxrwx root root 34 ./etc/ssl/certs/0c4c9b6c.0 -> Global_Chambersign_Root_-_2008.pem
+lrwxrwxrwx root root 26 ./etc/ssl/certs/0f6fa695.0 -> GDCA_TrustAUTH_R5_ROOT.pem
+lrwxrwxrwx root root 46 ./etc/ssl/certs/106f3e4d.0 -> Entrust_Root_Certification_Authority_-_EC1.pem
+lrwxrwxrwx root root 49 ./etc/ssl/certs/116bf586.0 -> GeoTrust_Primary_Certification_Authority_-_G2.pem
+lrwxrwxrwx root root 35 ./etc/ssl/certs/128805a3.0 -> EE_Certification_Centre_Root_CA.pem
+lrwxrwxrwx root root 26 ./etc/ssl/certs/157753a5.0 -> AddTrust_External_Root.pem
+lrwxrwxrwx root root 59 ./etc/ssl/certs/1636090b.0 -> Hellenic_Academic_and_Research_Institutions_RootCA_2011.pem
+lrwxrwxrwx root root 23 ./etc/ssl/certs/18856ac4.0 -> SecureSign_RootCA11.pem
+lrwxrwxrwx root root 31 ./etc/ssl/certs/1d3472b9.0 -> GlobalSign_ECC_Root_CA_-_R5.pem
+lrwxrwxrwx root root 37 ./etc/ssl/certs/1e08bfd1.0 -> IdenTrust_Public_Sector_Root_CA_1.pem
+lrwxrwxrwx root root 32 ./etc/ssl/certs/1e09d511.0 -> T-TeleSec_GlobalRoot_Class_2.pem
+lrwxrwxrwx root root 38 ./etc/ssl/certs/244b5494.0 -> DigiCert_High_Assurance_EV_Root_CA.pem
+lrwxrwxrwx root root 20 ./etc/ssl/certs/2ae6433e.0 -> CA_Disig_Root_R2.pem
+lrwxrwxrwx root root 26 ./etc/ssl/certs/2b349938.0 -> AffirmTrust_Commercial.pem
+lrwxrwxrwx root root 22 ./etc/ssl/certs/2c543cd1.0 -> GeoTrust_Global_CA.pem
+lrwxrwxrwx root root 26 ./etc/ssl/certs/2e4eed3c.0 -> thawte_Primary_Root_CA.pem
+lrwxrwxrwx root root 18 ./etc/ssl/certs/2e5ac55d.0 -> DST_Root_CA_X3.pem
+lrwxrwxrwx root root 59 ./etc/ssl/certs/32888f65.0 -> Hellenic_Academic_and_Research_Institutions_RootCA_2015.pem
+lrwxrwxrwx root root 10 ./etc/ssl/certs/349f2832.0 -> EC-ACC.pem
+lrwxrwxrwx root root 27 ./etc/ssl/certs/3513523f.0 -> DigiCert_Global_Root_CA.pem
+lrwxrwxrwx root root 61 ./etc/ssl/certs/3bde41ac.0 -> Autoridad_de_Certificacion_Firmaprofesional_CIF_A62634068.pem
+lrwxrwxrwx root root 26 ./etc/ssl/certs/3e44d2f7.0 -> TrustCor_RootCert_CA-2.pem
+lrwxrwxrwx root root 27 ./etc/ssl/certs/3e45d192.0 -> Hongkong_Post_Root_CA_1.pem
+lrwxrwxrwx root root 31 ./etc/ssl/certs/40193066.0 -> Certum_Trusted_Network_CA_2.pem
+lrwxrwxrwx root root 16 ./etc/ssl/certs/4042bcee.0 -> ISRG_Root_X1.pem
+lrwxrwxrwx root root 34 ./etc/ssl/certs/40547a79.0 -> COMODO_Certification_Authority.pem
+lrwxrwxrwx root root 43 ./etc/ssl/certs/4304c5e5.0 -> Network_Solutions_Certificate_Authority.pem
+lrwxrwxrwx root root 44 ./etc/ssl/certs/480720ec.0 -> GeoTrust_Primary_Certification_Authority.pem
+lrwxrwxrwx root root 29 ./etc/ssl/certs/48bec511.0 -> Certum_Trusted_Network_CA.pem
+lrwxrwxrwx root root 27 ./etc/ssl/certs/4a6481c9.0 -> GlobalSign_Root_CA_-_R2.pem
+lrwxrwxrwx root root 45 ./etc/ssl/certs/4bfab552.0 -> Starfield_Root_Certificate_Authority_-_G2.pem
+lrwxrwxrwx root root 26 ./etc/ssl/certs/4f316efb.0 -> SwissSign_Gold_CA_-_G2.pem
+lrwxrwxrwx root root 35 ./etc/ssl/certs/5273a94c.0 -> E-Tugra_Certification_Authority.pem
+lrwxrwxrwx root root 32 ./etc/ssl/certs/5443e9e3.0 -> T-TeleSec_GlobalRoot_Class_3.pem
+lrwxrwxrwx root root 27 ./etc/ssl/certs/54657681.0 -> Buypass_Class_2_Root_CA.pem
+lrwxrwxrwx root root 28 ./etc/ssl/certs/57bcb2da.0 -> SwissSign_Silver_CA_-_G2.pem
+lrwxrwxrwx root root 38 ./etc/ssl/certs/5a4d6896.0 -> Staat_der_Nederlanden_Root_CA_-_G3.pem
+lrwxrwxrwx root root 22 ./etc/ssl/certs/5ad8a5d6.0 -> GlobalSign_Root_CA.pem
+lrwxrwxrwx root root 38 ./etc/ssl/certs/5c44d531.0 -> Staat_der_Nederlanden_Root_CA_-_G2.pem
+lrwxrwxrwx root root 26 ./etc/ssl/certs/5cd81ad7.0 -> TeliaSonera_Root_CA_v1.pem
+lrwxrwxrwx root root 26 ./etc/ssl/certs/5d3033c5.0 -> TrustCor_RootCert_CA-1.pem
+lrwxrwxrwx root root 23 ./etc/ssl/certs/5f15c80c.0 -> TWCA_Global_Root_CA.pem
+lrwxrwxrwx root root 27 ./etc/ssl/certs/607986c7.0 -> DigiCert_Global_Root_G2.pem
+lrwxrwxrwx root root 15 ./etc/ssl/certs/6410666e.0 -> Taiwan_GRCA.pem
+lrwxrwxrwx root root 29 ./etc/ssl/certs/653b494a.0 -> Baltimore_CyberTrust_Root.pem
+lrwxrwxrwx root root 40 ./etc/ssl/certs/6b99d060.0 -> Entrust_Root_Certification_Authority.pem
+lrwxrwxrwx root root 20 ./etc/ssl/certs/6d41d539.0 -> Amazon_Root_CA_2.pem
+lrwxrwxrwx root root 44 ./etc/ssl/certs/6fa5da56.0 -> SSL.com_Root_Certification_Authority_RSA.pem
+lrwxrwxrwx root root 24 ./etc/ssl/certs/706f604c.0 -> XRamp_Global_CA_Root.pem
+lrwxrwxrwx root root 25 ./etc/ssl/certs/749e9e03.0 -> QuoVadis_Root_CA_1_G3.pem
+lrwxrwxrwx root root 28 ./etc/ssl/certs/75d1b2ed.0 -> DigiCert_Trusted_Root_G4.pem
+lrwxrwxrwx root root 26 ./etc/ssl/certs/76cb8f92.0 -> Cybertrust_Global_Root.pem
+lrwxrwxrwx root root 22 ./etc/ssl/certs/76faf6c0.0 -> QuoVadis_Root_CA_3.pem
+lrwxrwxrwx root root 63 ./etc/ssl/certs/7719f463.0 -> Hellenic_Academic_and_Research_Institutions_ECC_RootCA_2015.pem
+lrwxrwxrwx root root 35 ./etc/ssl/certs/773e07ad.0 -> OISTE_WISeKey_Global_Root_GC_CA.pem
+lrwxrwxrwx root root 18 ./etc/ssl/certs/7aaf71c0.0 -> TrustCor_ECA-1.pem
+lrwxrwxrwx root root 64 ./etc/ssl/certs/7d0b38bd.0 -> VeriSign_Class_3_Public_Primary_Certification_Authority_-_G4.pem
+lrwxrwxrwx root root 31 ./etc/ssl/certs/7f3d5d1d.0 -> DigiCert_Assured_ID_Root_G3.pem
+lrwxrwxrwx root root 30 ./etc/ssl/certs/812e17de.0 -> Deutsche_Telekom_Root_CA_2.pem
+lrwxrwxrwx root root 34 ./etc/ssl/certs/8160b96c.0 -> Microsec_e-Szigno_Root_CA_2009.pem
+lrwxrwxrwx root root 27 ./etc/ssl/certs/8867006a.0 -> GeoTrust_Universal_CA_2.pem
+lrwxrwxrwx root root 20 ./etc/ssl/certs/8cb5ee0f.0 -> Amazon_Root_CA_3.pem
+lrwxrwxrwx root root 20 ./etc/ssl/certs/8d86cdd1.0 -> certSIGN_ROOT_CA.pem
+lrwxrwxrwx root root 34 ./etc/ssl/certs/930ac5d2.0 -> Actalis_Authentication_Root_CA.pem
+lrwxrwxrwx root root 26 ./etc/ssl/certs/93bc0acc.0 -> AffirmTrust_Networking.pem
+lrwxrwxrwx root root 48 ./etc/ssl/certs/988a38cb.0 -> NetLock_Arany_=Class_Gold=_Főtanúsítvány.pem
+lrwxrwxrwx root root 26 ./etc/ssl/certs/9c2e7d30.0 -> Sonera_Class_2_Root_CA.pem
+lrwxrwxrwx root root 27 ./etc/ssl/certs/9c8dfbd4.0 -> AffirmTrust_Premium_ECC.pem
+lrwxrwxrwx root root 31 ./etc/ssl/certs/9d04f354.0 -> DigiCert_Assured_ID_Root_G2.pem
+lrwxrwxrwx root root 24 ./etc/ssl/certs/9f0f5fd6.0 -> Certinomis_-_Root_CA.pem
+lrwxrwxrwx root root 13 ./etc/ssl/certs/a94d09e5.0 -> ACCVRAIZ1.pem
+lrwxrwxrwx root root 56 ./etc/ssl/certs/ACCVRAIZ1.pem -> ../../../usr/share/ca-certificates/mozilla/ACCVRAIZ1.crt
+lrwxrwxrwx root root 63 ./etc/ssl/certs/AC_RAIZ_FNMT-RCM.pem -> ../../../usr/share/ca-certificates/mozilla/AC_RAIZ_FNMT-RCM.crt
+lrwxrwxrwx root root 77 ./etc/ssl/certs/Actalis_Authentication_Root_CA.pem -> ../../../usr/share/ca-certificates/mozilla/Actalis_Authentication_Root_CA.crt
+lrwxrwxrwx root root 25 ./etc/ssl/certs/ad088e1d.0 -> GeoTrust_Universal_CA.pem
+lrwxrwxrwx root root 69 ./etc/ssl/certs/AddTrust_External_Root.pem -> ../../../usr/share/ca-certificates/mozilla/AddTrust_External_Root.crt
+lrwxrwxrwx root root 45 ./etc/ssl/certs/aee5f10d.0 -> Entrust.net_Premium_2048_Secure_Server_CA.pem
+lrwxrwxrwx root root 69 ./etc/ssl/certs/AffirmTrust_Commercial.pem -> ../../../usr/share/ca-certificates/mozilla/AffirmTrust_Commercial.crt
+lrwxrwxrwx root root 69 ./etc/ssl/certs/AffirmTrust_Networking.pem -> ../../../usr/share/ca-certificates/mozilla/AffirmTrust_Networking.crt
+lrwxrwxrwx root root 70 ./etc/ssl/certs/AffirmTrust_Premium_ECC.pem -> ../../../usr/share/ca-certificates/mozilla/AffirmTrust_Premium_ECC.crt
+lrwxrwxrwx root root 66 ./etc/ssl/certs/AffirmTrust_Premium.pem -> ../../../usr/share/ca-certificates/mozilla/AffirmTrust_Premium.crt
+lrwxrwxrwx root root 63 ./etc/ssl/certs/Amazon_Root_CA_1.pem -> ../../../usr/share/ca-certificates/mozilla/Amazon_Root_CA_1.crt
+lrwxrwxrwx root root 63 ./etc/ssl/certs/Amazon_Root_CA_2.pem -> ../../../usr/share/ca-certificates/mozilla/Amazon_Root_CA_2.crt
+lrwxrwxrwx root root 63 ./etc/ssl/certs/Amazon_Root_CA_3.pem -> ../../../usr/share/ca-certificates/mozilla/Amazon_Root_CA_3.crt
+lrwxrwxrwx root root 63 ./etc/ssl/certs/Amazon_Root_CA_4.pem -> ../../../usr/share/ca-certificates/mozilla/Amazon_Root_CA_4.crt
+lrwxrwxrwx root root 68 ./etc/ssl/certs/Atos_TrustedRoot_2011.pem -> ../../../usr/share/ca-certificates/mozilla/Atos_TrustedRoot_2011.crt
+lrwxrwxrwx root root 104 ./etc/ssl/certs/Autoridad_de_Certificacion_Firmaprofesional_CIF_A62634068.pem -> ../../../usr/share/ca-certificates/mozilla/Autoridad_de_Certificacion_Firmaprofesional_CIF_A62634068.crt
+lrwxrwxrwx root root 31 ./etc/ssl/certs/b0e59380.0 -> GlobalSign_ECC_Root_CA_-_R4.pem
+lrwxrwxrwx root root 31 ./etc/ssl/certs/b1159c4c.0 -> DigiCert_Assured_ID_Root_CA.pem
+lrwxrwxrwx root root 35 ./etc/ssl/certs/b1b8a7f3.0 -> OISTE_WISeKey_Global_Root_GA_CA.pem
+lrwxrwxrwx root root 64 ./etc/ssl/certs/b204d74a.0 -> VeriSign_Class_3_Public_Primary_Certification_Authority_-_G5.pem
+lrwxrwxrwx root root 20 ./etc/ssl/certs/b66938e9.0 -> Secure_Global_CA.pem
+lrwxrwxrwx root root 23 ./etc/ssl/certs/b727005e.0 -> AffirmTrust_Premium.pem
+lrwxrwxrwx root root 37 ./etc/ssl/certs/b7a5b843.0 -> TWCA_Root_Certification_Authority.pem
+lrwxrwxrwx root root 31 ./etc/ssl/certs/ba89ed3b.0 -> thawte_Primary_Root_CA_-_G3.pem
+lrwxrwxrwx root root 72 ./etc/ssl/certs/Baltimore_CyberTrust_Root.pem -> ../../../usr/share/ca-certificates/mozilla/Baltimore_CyberTrust_Root.crt
+lrwxrwxrwx root root 70 ./etc/ssl/certs/Buypass_Class_2_Root_CA.pem -> ../../../usr/share/ca-certificates/mozilla/Buypass_Class_2_Root_CA.crt
+lrwxrwxrwx root root 70 ./etc/ssl/certs/Buypass_Class_3_Root_CA.pem -> ../../../usr/share/ca-certificates/mozilla/Buypass_Class_3_Root_CA.crt
+lrwxrwxrwx root root 51 ./etc/ssl/certs/c01cdfa2.0 -> VeriSign_Universal_Root_Certification_Authority.pem
+lrwxrwxrwx root root 31 ./etc/ssl/certs/c089bbbd.0 -> thawte_Primary_Root_CA_-_G2.pem
+lrwxrwxrwx root root 64 ./etc/ssl/certs/c0ff1f52.0 -> Verisign_Class_3_Public_Primary_Certification_Authority_-_G3.pem
+lrwxrwxrwx root root 34 ./etc/ssl/certs/c28a8a30.0 -> D-TRUST_Root_Class_3_CA_2_2009.pem
+lrwxrwxrwx root root 36 ./etc/ssl/certs/c47d9980.0 -> Chambers_of_Commerce_Root_-_2008.pem
+lrwxrwxrwx root root 37 ./etc/ssl/certs/ca6e4ad9.0 -> ePKI_Root_Certification_Authority.pem
+-rw-r--r-- root root 200061 ./etc/ssl/certs/ca-certificates.crt
+lrwxrwxrwx root root 63 ./etc/ssl/certs/CA_Disig_Root_R2.pem -> ../../../usr/share/ca-certificates/mozilla/CA_Disig_Root_R2.crt
+lrwxrwxrwx root root 44 ./etc/ssl/certs/cbf06781.0 -> Go_Daddy_Root_Certificate_Authority_-_G2.pem
+lrwxrwxrwx root root 14 ./etc/ssl/certs/cc450945.0 -> Izenpe.com.pem
+lrwxrwxrwx root root 34 ./etc/ssl/certs/cd58d51e.0 -> Security_Communication_RootCA2.pem
+lrwxrwxrwx root root 20 ./etc/ssl/certs/cd8c0d63.0 -> AC_RAIZ_FNMT-RCM.pem
+lrwxrwxrwx root root 20 ./etc/ssl/certs/ce5e74ef.0 -> Amazon_Root_CA_1.pem
+lrwxrwxrwx root root 55 ./etc/ssl/certs/Certigna.pem -> ../../../usr/share/ca-certificates/mozilla/Certigna.crt
+lrwxrwxrwx root root 67 ./etc/ssl/certs/Certinomis_-_Root_CA.pem -> ../../../usr/share/ca-certificates/mozilla/Certinomis_-_Root_CA.crt
+lrwxrwxrwx root root 74 ./etc/ssl/certs/Certplus_Class_2_Primary_CA.pem -> ../../../usr/share/ca-certificates/mozilla/Certplus_Class_2_Primary_CA.crt
+lrwxrwxrwx root root 63 ./etc/ssl/certs/certSIGN_ROOT_CA.pem -> ../../../usr/share/ca-certificates/mozilla/certSIGN_ROOT_CA.crt
+lrwxrwxrwx root root 74 ./etc/ssl/certs/Certum_Trusted_Network_CA_2.pem -> ../../../usr/share/ca-certificates/mozilla/Certum_Trusted_Network_CA_2.crt
+lrwxrwxrwx root root 72 ./etc/ssl/certs/Certum_Trusted_Network_CA.pem -> ../../../usr/share/ca-certificates/mozilla/Certum_Trusted_Network_CA.crt
+lrwxrwxrwx root root 59 ./etc/ssl/certs/CFCA_EV_ROOT.pem -> ../../../usr/share/ca-certificates/mozilla/CFCA_EV_ROOT.crt
+lrwxrwxrwx root root 79 ./etc/ssl/certs/Chambers_of_Commerce_Root_-_2008.pem -> ../../../usr/share/ca-certificates/mozilla/Chambers_of_Commerce_Root_-_2008.crt
+lrwxrwxrwx root root 71 ./etc/ssl/certs/Comodo_AAA_Services_root.pem -> ../../../usr/share/ca-certificates/mozilla/Comodo_AAA_Services_root.crt
+lrwxrwxrwx root root 77 ./etc/ssl/certs/COMODO_Certification_Authority.pem -> ../../../usr/share/ca-certificates/mozilla/COMODO_Certification_Authority.crt
+lrwxrwxrwx root root 81 ./etc/ssl/certs/COMODO_ECC_Certification_Authority.pem -> ../../../usr/share/ca-certificates/mozilla/COMODO_ECC_Certification_Authority.crt
+lrwxrwxrwx root root 81 ./etc/ssl/certs/COMODO_RSA_Certification_Authority.pem -> ../../../usr/share/ca-certificates/mozilla/COMODO_RSA_Certification_Authority.crt
+lrwxrwxrwx root root 69 ./etc/ssl/certs/Cybertrust_Global_Root.pem -> ../../../usr/share/ca-certificates/mozilla/Cybertrust_Global_Root.crt
+lrwxrwxrwx root root 37 ./etc/ssl/certs/d4dae3dd.0 -> D-TRUST_Root_Class_3_CA_2_EV_2009.pem
+lrwxrwxrwx root root 38 ./etc/ssl/certs/d6325660.0 -> COMODO_RSA_Certification_Authority.pem
+lrwxrwxrwx root root 22 ./etc/ssl/certs/d7e8dc79.0 -> QuoVadis_Root_CA_2.pem
+lrwxrwxrwx root root 23 ./etc/ssl/certs/d853d49e.0 -> Trustis_FPS_Root_CA.pem
+lrwxrwxrwx root root 27 ./etc/ssl/certs/dc4d6a89.0 -> GlobalSign_Root_CA_-_R6.pem
+lrwxrwxrwx root root 27 ./etc/ssl/certs/dd8e9d41.0 -> DigiCert_Global_Root_G3.pem
+lrwxrwxrwx root root 20 ./etc/ssl/certs/de6d66f3.0 -> Amazon_Root_CA_4.pem
+lrwxrwxrwx root root 26 ./etc/ssl/certs/def36a68.0 -> LuxTrust_Global_Root_2.pem
+lrwxrwxrwx root root 73 ./etc/ssl/certs/Deutsche_Telekom_Root_CA_2.pem -> ../../../usr/share/ca-certificates/mozilla/Deutsche_Telekom_Root_CA_2.crt
+lrwxrwxrwx root root 74 ./etc/ssl/certs/DigiCert_Assured_ID_Root_CA.pem -> ../../../usr/share/ca-certificates/mozilla/DigiCert_Assured_ID_Root_CA.crt
+lrwxrwxrwx root root 74 ./etc/ssl/certs/DigiCert_Assured_ID_Root_G2.pem -> ../../../usr/share/ca-certificates/mozilla/DigiCert_Assured_ID_Root_G2.crt
+lrwxrwxrwx root root 74 ./etc/ssl/certs/DigiCert_Assured_ID_Root_G3.pem -> ../../../usr/share/ca-certificates/mozilla/DigiCert_Assured_ID_Root_G3.crt
+lrwxrwxrwx root root 70 ./etc/ssl/certs/DigiCert_Global_Root_CA.pem -> ../../../usr/share/ca-certificates/mozilla/DigiCert_Global_Root_CA.crt
+lrwxrwxrwx root root 70 ./etc/ssl/certs/DigiCert_Global_Root_G2.pem -> ../../../usr/share/ca-certificates/mozilla/DigiCert_Global_Root_G2.crt
+lrwxrwxrwx root root 70 ./etc/ssl/certs/DigiCert_Global_Root_G3.pem -> ../../../usr/share/ca-certificates/mozilla/DigiCert_Global_Root_G3.crt
+lrwxrwxrwx root root 81 ./etc/ssl/certs/DigiCert_High_Assurance_EV_Root_CA.pem -> ../../../usr/share/ca-certificates/mozilla/DigiCert_High_Assurance_EV_Root_CA.crt
+lrwxrwxrwx root root 71 ./etc/ssl/certs/DigiCert_Trusted_Root_G4.pem -> ../../../usr/share/ca-certificates/mozilla/DigiCert_Trusted_Root_G4.crt
+lrwxrwxrwx root root 61 ./etc/ssl/certs/DST_Root_CA_X3.pem -> ../../../usr/share/ca-certificates/mozilla/DST_Root_CA_X3.crt
+lrwxrwxrwx root root 77 ./etc/ssl/certs/D-TRUST_Root_Class_3_CA_2_2009.pem -> ../../../usr/share/ca-certificates/mozilla/D-TRUST_Root_Class_3_CA_2_2009.crt
+lrwxrwxrwx root root 80 ./etc/ssl/certs/D-TRUST_Root_Class_3_CA_2_EV_2009.pem -> ../../../usr/share/ca-certificates/mozilla/D-TRUST_Root_Class_3_CA_2_EV_2009.crt
+lrwxrwxrwx root root 12 ./etc/ssl/certs/e113c810.0 -> Certigna.pem
+lrwxrwxrwx root root 25 ./etc/ssl/certs/e18bfb83.0 -> QuoVadis_Root_CA_3_G3.pem
+lrwxrwxrwx root root 49 ./etc/ssl/certs/e2799e36.0 -> GeoTrust_Primary_Certification_Authority_-_G3.pem
+lrwxrwxrwx root root 25 ./etc/ssl/certs/e36a6752.0 -> Atos_TrustedRoot_2011.pem
+lrwxrwxrwx root root 35 ./etc/ssl/certs/e73d606e.0 -> OISTE_WISeKey_Global_Root_GB_CA.pem
+lrwxrwxrwx root root 27 ./etc/ssl/certs/e8de2f56.0 -> Buypass_Class_3_Root_CA.pem
+lrwxrwxrwx root root 53 ./etc/ssl/certs/EC-ACC.pem -> ../../../usr/share/ca-certificates/mozilla/EC-ACC.crt
+lrwxrwxrwx root root 28 ./etc/ssl/certs/ee64a828.0 -> Comodo_AAA_Services_root.pem
+lrwxrwxrwx root root 78 ./etc/ssl/certs/EE_Certification_Centre_Root_CA.pem -> ../../../usr/share/ca-certificates/mozilla/EE_Certification_Centre_Root_CA.crt
+lrwxrwxrwx root root 38 ./etc/ssl/certs/eed8c118.0 -> COMODO_ECC_Certification_Authority.pem
+lrwxrwxrwx root root 34 ./etc/ssl/certs/ef954a4e.0 -> IdenTrust_Commercial_Root_CA_1.pem
+lrwxrwxrwx root root 88 ./etc/ssl/certs/Entrust.net_Premium_2048_Secure_Server_CA.pem -> ../../../usr/share/ca-certificates/mozilla/Entrust.net_Premium_2048_Secure_Server_CA.crt
+lrwxrwxrwx root root 89 ./etc/ssl/certs/Entrust_Root_Certification_Authority_-_EC1.pem -> ../../../usr/share/ca-certificates/mozilla/Entrust_Root_Certification_Authority_-_EC1.crt
+lrwxrwxrwx root root 88 ./etc/ssl/certs/Entrust_Root_Certification_Authority_-_G2.pem -> ../../../usr/share/ca-certificates/mozilla/Entrust_Root_Certification_Authority_-_G2.crt
+lrwxrwxrwx root root 83 ./etc/ssl/certs/Entrust_Root_Certification_Authority.pem -> ../../../usr/share/ca-certificates/mozilla/Entrust_Root_Certification_Authority.crt
+lrwxrwxrwx root root 80 ./etc/ssl/certs/ePKI_Root_Certification_Authority.pem -> ../../../usr/share/ca-certificates/mozilla/ePKI_Root_Certification_Authority.crt
+lrwxrwxrwx root root 78 ./etc/ssl/certs/E-Tugra_Certification_Authority.pem -> ../../../usr/share/ca-certificates/mozilla/E-Tugra_Certification_Authority.crt
+lrwxrwxrwx root root 31 ./etc/ssl/certs/f060240e.0 -> Certplus_Class_2_Primary_CA.pem
+lrwxrwxrwx root root 23 ./etc/ssl/certs/f081611a.0 -> Go_Daddy_Class_2_CA.pem
+lrwxrwxrwx root root 47 ./etc/ssl/certs/f0c70a8d.0 -> SSL.com_EV_Root_Certification_Authority_ECC.pem
+lrwxrwxrwx root root 41 ./etc/ssl/certs/f30dd6ad.0 -> USERTrust_ECC_Certification_Authority.pem
+lrwxrwxrwx root root 34 ./etc/ssl/certs/f3377b1b.0 -> Security_Communication_Root_CA.pem
+lrwxrwxrwx root root 24 ./etc/ssl/certs/f387163d.0 -> Starfield_Class_2_CA.pem
+lrwxrwxrwx root root 18 ./etc/ssl/certs/f39fc864.0 -> SecureTrust_CA.pem
+lrwxrwxrwx root root 41 ./etc/ssl/certs/fc5a8f99.0 -> USERTrust_RSA_Certification_Authority.pem
+lrwxrwxrwx root root 19 ./etc/ssl/certs/fe8a2cd8.0 -> SZAFIR_ROOT_CA2.pem
+lrwxrwxrwx root root 49 ./etc/ssl/certs/ff34af3f.0 -> TUBITAK_Kamu_SM_SSL_Kok_Sertifikasi_-_Surum_1.pem
+lrwxrwxrwx root root 69 ./etc/ssl/certs/GDCA_TrustAUTH_R5_ROOT.pem -> ../../../usr/share/ca-certificates/mozilla/GDCA_TrustAUTH_R5_ROOT.crt
+lrwxrwxrwx root root 65 ./etc/ssl/certs/GeoTrust_Global_CA.pem -> ../../../usr/share/ca-certificates/mozilla/GeoTrust_Global_CA.crt
+lrwxrwxrwx root root 92 ./etc/ssl/certs/GeoTrust_Primary_Certification_Authority_-_G2.pem -> ../../../usr/share/ca-certificates/mozilla/GeoTrust_Primary_Certification_Authority_-_G2.crt
+lrwxrwxrwx root root 92 ./etc/ssl/certs/GeoTrust_Primary_Certification_Authority_-_G3.pem -> ../../../usr/share/ca-certificates/mozilla/GeoTrust_Primary_Certification_Authority_-_G3.crt
+lrwxrwxrwx root root 87 ./etc/ssl/certs/GeoTrust_Primary_Certification_Authority.pem -> ../../../usr/share/ca-certificates/mozilla/GeoTrust_Primary_Certification_Authority.crt
+lrwxrwxrwx root root 70 ./etc/ssl/certs/GeoTrust_Universal_CA_2.pem -> ../../../usr/share/ca-certificates/mozilla/GeoTrust_Universal_CA_2.crt
+lrwxrwxrwx root root 68 ./etc/ssl/certs/GeoTrust_Universal_CA.pem -> ../../../usr/share/ca-certificates/mozilla/GeoTrust_Universal_CA.crt
+lrwxrwxrwx root root 77 ./etc/ssl/certs/Global_Chambersign_Root_-_2008.pem -> ../../../usr/share/ca-certificates/mozilla/Global_Chambersign_Root_-_2008.crt
+lrwxrwxrwx root root 74 ./etc/ssl/certs/GlobalSign_ECC_Root_CA_-_R4.pem -> ../../../usr/share/ca-certificates/mozilla/GlobalSign_ECC_Root_CA_-_R4.crt
+lrwxrwxrwx root root 74 ./etc/ssl/certs/GlobalSign_ECC_Root_CA_-_R5.pem -> ../../../usr/share/ca-certificates/mozilla/GlobalSign_ECC_Root_CA_-_R5.crt
+lrwxrwxrwx root root 65 ./etc/ssl/certs/GlobalSign_Root_CA.pem -> ../../../usr/share/ca-certificates/mozilla/GlobalSign_Root_CA.crt
+lrwxrwxrwx root root 70 ./etc/ssl/certs/GlobalSign_Root_CA_-_R2.pem -> ../../../usr/share/ca-certificates/mozilla/GlobalSign_Root_CA_-_R2.crt
+lrwxrwxrwx root root 70 ./etc/ssl/certs/GlobalSign_Root_CA_-_R3.pem -> ../../../usr/share/ca-certificates/mozilla/GlobalSign_Root_CA_-_R3.crt
+lrwxrwxrwx root root 70 ./etc/ssl/certs/GlobalSign_Root_CA_-_R6.pem -> ../../../usr/share/ca-certificates/mozilla/GlobalSign_Root_CA_-_R6.crt
+lrwxrwxrwx root root 66 ./etc/ssl/certs/Go_Daddy_Class_2_CA.pem -> ../../../usr/share/ca-certificates/mozilla/Go_Daddy_Class_2_CA.crt
+lrwxrwxrwx root root 87 ./etc/ssl/certs/Go_Daddy_Root_Certificate_Authority_-_G2.pem -> ../../../usr/share/ca-certificates/mozilla/Go_Daddy_Root_Certificate_Authority_-_G2.crt
+lrwxrwxrwx root root 106 ./etc/ssl/certs/Hellenic_Academic_and_Research_Institutions_ECC_RootCA_2015.pem -> ../../../usr/share/ca-certificates/mozilla/Hellenic_Academic_and_Research_Institutions_ECC_RootCA_2015.crt
+lrwxrwxrwx root root 102 ./etc/ssl/certs/Hellenic_Academic_and_Research_Institutions_RootCA_2011.pem -> ../../../usr/share/ca-certificates/mozilla/Hellenic_Academic_and_Research_Institutions_RootCA_2011.crt
+lrwxrwxrwx root root 102 ./etc/ssl/certs/Hellenic_Academic_and_Research_Institutions_RootCA_2015.pem -> ../../../usr/share/ca-certificates/mozilla/Hellenic_Academic_and_Research_Institutions_RootCA_2015.crt
+lrwxrwxrwx root root 70 ./etc/ssl/certs/Hongkong_Post_Root_CA_1.pem -> ../../../usr/share/ca-certificates/mozilla/Hongkong_Post_Root_CA_1.crt
+lrwxrwxrwx root root 77 ./etc/ssl/certs/IdenTrust_Commercial_Root_CA_1.pem -> ../../../usr/share/ca-certificates/mozilla/IdenTrust_Commercial_Root_CA_1.crt
+lrwxrwxrwx root root 80 ./etc/ssl/certs/IdenTrust_Public_Sector_Root_CA_1.pem -> ../../../usr/share/ca-certificates/mozilla/IdenTrust_Public_Sector_Root_CA_1.crt
+lrwxrwxrwx root root 59 ./etc/ssl/certs/ISRG_Root_X1.pem -> ../../../usr/share/ca-certificates/mozilla/ISRG_Root_X1.crt
+lrwxrwxrwx root root 57 ./etc/ssl/certs/Izenpe.com.pem -> ../../../usr/share/ca-certificates/mozilla/Izenpe.com.crt
+lrwxrwxrwx root root 69 ./etc/ssl/certs/LuxTrust_Global_Root_2.pem -> ../../../usr/share/ca-certificates/mozilla/LuxTrust_Global_Root_2.crt
+lrwxrwxrwx root root 77 ./etc/ssl/certs/Microsec_e-Szigno_Root_CA_2009.pem -> ../../../usr/share/ca-certificates/mozilla/Microsec_e-Szigno_Root_CA_2009.crt
+lrwxrwxrwx root root 91 ./etc/ssl/certs/NetLock_Arany_=Class_Gold=_Főtanúsítvány.pem -> ../../../usr/share/ca-certificates/mozilla/NetLock_Arany_=Class_Gold=_Főtanúsítvány.crt
+lrwxrwxrwx root root 86 ./etc/ssl/certs/Network_Solutions_Certificate_Authority.pem -> ../../../usr/share/ca-certificates/mozilla/Network_Solutions_Certificate_Authority.crt
+lrwxrwxrwx root root 78 ./etc/ssl/certs/OISTE_WISeKey_Global_Root_GA_CA.pem -> ../../../usr/share/ca-certificates/mozilla/OISTE_WISeKey_Global_Root_GA_CA.crt
+lrwxrwxrwx root root 78 ./etc/ssl/certs/OISTE_WISeKey_Global_Root_GB_CA.pem -> ../../../usr/share/ca-certificates/mozilla/OISTE_WISeKey_Global_Root_GB_CA.crt
+lrwxrwxrwx root root 78 ./etc/ssl/certs/OISTE_WISeKey_Global_Root_GC_CA.pem -> ../../../usr/share/ca-certificates/mozilla/OISTE_WISeKey_Global_Root_GC_CA.crt
+lrwxrwxrwx root root 68 ./etc/ssl/certs/QuoVadis_Root_CA_1_G3.pem -> ../../../usr/share/ca-certificates/mozilla/QuoVadis_Root_CA_1_G3.crt
+lrwxrwxrwx root root 68 ./etc/ssl/certs/QuoVadis_Root_CA_2_G3.pem -> ../../../usr/share/ca-certificates/mozilla/QuoVadis_Root_CA_2_G3.crt
+lrwxrwxrwx root root 65 ./etc/ssl/certs/QuoVadis_Root_CA_2.pem -> ../../../usr/share/ca-certificates/mozilla/QuoVadis_Root_CA_2.crt
+lrwxrwxrwx root root 68 ./etc/ssl/certs/QuoVadis_Root_CA_3_G3.pem -> ../../../usr/share/ca-certificates/mozilla/QuoVadis_Root_CA_3_G3.crt
+lrwxrwxrwx root root 65 ./etc/ssl/certs/QuoVadis_Root_CA_3.pem -> ../../../usr/share/ca-certificates/mozilla/QuoVadis_Root_CA_3.crt
+lrwxrwxrwx root root 63 ./etc/ssl/certs/QuoVadis_Root_CA.pem -> ../../../usr/share/ca-certificates/mozilla/QuoVadis_Root_CA.crt
+lrwxrwxrwx root root 63 ./etc/ssl/certs/Secure_Global_CA.pem -> ../../../usr/share/ca-certificates/mozilla/Secure_Global_CA.crt
+lrwxrwxrwx root root 66 ./etc/ssl/certs/SecureSign_RootCA11.pem -> ../../../usr/share/ca-certificates/mozilla/SecureSign_RootCA11.crt
+lrwxrwxrwx root root 61 ./etc/ssl/certs/SecureTrust_CA.pem -> ../../../usr/share/ca-certificates/mozilla/SecureTrust_CA.crt
+lrwxrwxrwx root root 77 ./etc/ssl/certs/Security_Communication_RootCA2.pem -> ../../../usr/share/ca-certificates/mozilla/Security_Communication_RootCA2.crt
+lrwxrwxrwx root root 77 ./etc/ssl/certs/Security_Communication_Root_CA.pem -> ../../../usr/share/ca-certificates/mozilla/Security_Communication_Root_CA.crt
+lrwxrwxrwx root root 69 ./etc/ssl/certs/Sonera_Class_2_Root_CA.pem -> ../../../usr/share/ca-certificates/mozilla/Sonera_Class_2_Root_CA.crt
+lrwxrwxrwx root root 90 ./etc/ssl/certs/SSL.com_EV_Root_Certification_Authority_ECC.pem -> ../../../usr/share/ca-certificates/mozilla/SSL.com_EV_Root_Certification_Authority_ECC.crt
+lrwxrwxrwx root root 93 ./etc/ssl/certs/SSL.com_EV_Root_Certification_Authority_RSA_R2.pem -> ../../../usr/share/ca-certificates/mozilla/SSL.com_EV_Root_Certification_Authority_RSA_R2.crt
+lrwxrwxrwx root root 87 ./etc/ssl/certs/SSL.com_Root_Certification_Authority_ECC.pem -> ../../../usr/share/ca-certificates/mozilla/SSL.com_Root_Certification_Authority_ECC.crt
+lrwxrwxrwx root root 87 ./etc/ssl/certs/SSL.com_Root_Certification_Authority_RSA.pem -> ../../../usr/share/ca-certificates/mozilla/SSL.com_Root_Certification_Authority_RSA.crt
+lrwxrwxrwx root root 79 ./etc/ssl/certs/Staat_der_Nederlanden_EV_Root_CA.pem -> ../../../usr/share/ca-certificates/mozilla/Staat_der_Nederlanden_EV_Root_CA.crt
+lrwxrwxrwx root root 81 ./etc/ssl/certs/Staat_der_Nederlanden_Root_CA_-_G2.pem -> ../../../usr/share/ca-certificates/mozilla/Staat_der_Nederlanden_Root_CA_-_G2.crt
+lrwxrwxrwx root root 81 ./etc/ssl/certs/Staat_der_Nederlanden_Root_CA_-_G3.pem -> ../../../usr/share/ca-certificates/mozilla/Staat_der_Nederlanden_Root_CA_-_G3.crt
+lrwxrwxrwx root root 67 ./etc/ssl/certs/Starfield_Class_2_CA.pem -> ../../../usr/share/ca-certificates/mozilla/Starfield_Class_2_CA.crt
+lrwxrwxrwx root root 88 ./etc/ssl/certs/Starfield_Root_Certificate_Authority_-_G2.pem -> ../../../usr/share/ca-certificates/mozilla/Starfield_Root_Certificate_Authority_-_G2.crt
+lrwxrwxrwx root root 97 ./etc/ssl/certs/Starfield_Services_Root_Certificate_Authority_-_G2.pem -> ../../../usr/share/ca-certificates/mozilla/Starfield_Services_Root_Certificate_Authority_-_G2.crt
+lrwxrwxrwx root root 69 ./etc/ssl/certs/SwissSign_Gold_CA_-_G2.pem -> ../../../usr/share/ca-certificates/mozilla/SwissSign_Gold_CA_-_G2.crt
+lrwxrwxrwx root root 71 ./etc/ssl/certs/SwissSign_Silver_CA_-_G2.pem -> ../../../usr/share/ca-certificates/mozilla/SwissSign_Silver_CA_-_G2.crt
+lrwxrwxrwx root root 62 ./etc/ssl/certs/SZAFIR_ROOT_CA2.pem -> ../../../usr/share/ca-certificates/mozilla/SZAFIR_ROOT_CA2.crt
+lrwxrwxrwx root root 58 ./etc/ssl/certs/Taiwan_GRCA.pem -> ../../../usr/share/ca-certificates/mozilla/Taiwan_GRCA.crt
+lrwxrwxrwx root root 69 ./etc/ssl/certs/TeliaSonera_Root_CA_v1.pem -> ../../../usr/share/ca-certificates/mozilla/TeliaSonera_Root_CA_v1.crt
+lrwxrwxrwx root root 74 ./etc/ssl/certs/thawte_Primary_Root_CA_-_G2.pem -> ../../../usr/share/ca-certificates/mozilla/thawte_Primary_Root_CA_-_G2.crt
+lrwxrwxrwx root root 74 ./etc/ssl/certs/thawte_Primary_Root_CA_-_G3.pem -> ../../../usr/share/ca-certificates/mozilla/thawte_Primary_Root_CA_-_G3.crt
+lrwxrwxrwx root root 69 ./etc/ssl/certs/thawte_Primary_Root_CA.pem -> ../../../usr/share/ca-certificates/mozilla/thawte_Primary_Root_CA.crt
+lrwxrwxrwx root root 61 ./etc/ssl/certs/TrustCor_ECA-1.pem -> ../../../usr/share/ca-certificates/mozilla/TrustCor_ECA-1.crt
+lrwxrwxrwx root root 69 ./etc/ssl/certs/TrustCor_RootCert_CA-1.pem -> ../../../usr/share/ca-certificates/mozilla/TrustCor_RootCert_CA-1.crt
+lrwxrwxrwx root root 69 ./etc/ssl/certs/TrustCor_RootCert_CA-2.pem -> ../../../usr/share/ca-certificates/mozilla/TrustCor_RootCert_CA-2.crt
+lrwxrwxrwx root root 66 ./etc/ssl/certs/Trustis_FPS_Root_CA.pem -> ../../../usr/share/ca-certificates/mozilla/Trustis_FPS_Root_CA.crt
+lrwxrwxrwx root root 75 ./etc/ssl/certs/T-TeleSec_GlobalRoot_Class_2.pem -> ../../../usr/share/ca-certificates/mozilla/T-TeleSec_GlobalRoot_Class_2.crt
+lrwxrwxrwx root root 75 ./etc/ssl/certs/T-TeleSec_GlobalRoot_Class_3.pem -> ../../../usr/share/ca-certificates/mozilla/T-TeleSec_GlobalRoot_Class_3.crt
+lrwxrwxrwx root root 92 ./etc/ssl/certs/TUBITAK_Kamu_SM_SSL_Kok_Sertifikasi_-_Surum_1.pem -> ../../../usr/share/ca-certificates/mozilla/TUBITAK_Kamu_SM_SSL_Kok_Sertifikasi_-_Surum_1.crt
+lrwxrwxrwx root root 66 ./etc/ssl/certs/TWCA_Global_Root_CA.pem -> ../../../usr/share/ca-certificates/mozilla/TWCA_Global_Root_CA.crt
+lrwxrwxrwx root root 80 ./etc/ssl/certs/TWCA_Root_Certification_Authority.pem -> ../../../usr/share/ca-certificates/mozilla/TWCA_Root_Certification_Authority.crt
+lrwxrwxrwx root root 84 ./etc/ssl/certs/USERTrust_ECC_Certification_Authority.pem -> ../../../usr/share/ca-certificates/mozilla/USERTrust_ECC_Certification_Authority.crt
+lrwxrwxrwx root root 84 ./etc/ssl/certs/USERTrust_RSA_Certification_Authority.pem -> ../../../usr/share/ca-certificates/mozilla/USERTrust_RSA_Certification_Authority.crt
+lrwxrwxrwx root root 107 ./etc/ssl/certs/Verisign_Class_3_Public_Primary_Certification_Authority_-_G3.pem -> ../../../usr/share/ca-certificates/mozilla/Verisign_Class_3_Public_Primary_Certification_Authority_-_G3.crt
+lrwxrwxrwx root root 107 ./etc/ssl/certs/VeriSign_Class_3_Public_Primary_Certification_Authority_-_G4.pem -> ../../../usr/share/ca-certificates/mozilla/VeriSign_Class_3_Public_Primary_Certification_Authority_-_G4.crt
+lrwxrwxrwx root root 107 ./etc/ssl/certs/VeriSign_Class_3_Public_Primary_Certification_Authority_-_G5.pem -> ../../../usr/share/ca-certificates/mozilla/VeriSign_Class_3_Public_Primary_Certification_Authority_-_G5.crt
+lrwxrwxrwx root root 94 ./etc/ssl/certs/VeriSign_Universal_Root_Certification_Authority.pem -> ../../../usr/share/ca-certificates/mozilla/VeriSign_Universal_Root_Certification_Authority.crt
+lrwxrwxrwx root root 67 ./etc/ssl/certs/XRamp_Global_CA_Root.pem -> ../../../usr/share/ca-certificates/mozilla/XRamp_Global_CA_Root.crt
+-rw-r--r-- root root 10909 ./etc/ssl/openssl.cnf
+drwxr-xr-x root root 4096 ./etc/ssl/private
+-rw-r--r-- root root 2128 ./etc/sysctl.conf
+-rw-r--r-- root root 69 ./etc/syslog.conf
+-rw-r--r-- root root 651 ./etc/syslog-startup.conf
+drwxr-xr-x root root 4096 ./etc/terminfo
+drwxr-xr-x root root 4096 ./etc/terminfo/a
+-rw-r--r-- root root 1481 ./etc/terminfo/a/ansi
+drwxr-xr-x root root 4096 ./etc/terminfo/d
+-rw-r--r-- root root 308 ./etc/terminfo/d/dumb
+drwxr-xr-x root root 4096 ./etc/terminfo/l
+-rw-r--r-- root root 1730 ./etc/terminfo/l/linux
+drwxr-xr-x root root 4096 ./etc/terminfo/r
+-rw-r--r-- root root 2222 ./etc/terminfo/r/rxvt
+drwxr-xr-x root root 4096 ./etc/terminfo/s
+-rw-r--r-- root root 1573 ./etc/terminfo/s/screen
+-rw-r--r-- root root 1687 ./etc/terminfo/s/screen-256color
+-rw-r--r-- root root 1004 ./etc/terminfo/s/sun
+drwxr-xr-x root root 4096 ./etc/terminfo/v
+-rw-r--r-- root root 1190 ./etc/terminfo/v/vt100
+-rw-r--r-- root root 1184 ./etc/terminfo/v/vt102
+-rw-r--r-- root root 1377 ./etc/terminfo/v/vt200
+-rw-r--r-- root root 1377 ./etc/terminfo/v/vt220
+-rw-r--r-- root root 470 ./etc/terminfo/v/vt52
+drwxr-xr-x root root 4096 ./etc/terminfo/x
+-rw-r--r-- root root 3780 ./etc/terminfo/x/xterm-256color
+-rw-r--r-- root root 1551 ./etc/terminfo/x/xterm-color
+-rw-r--r-- root root 2240 ./etc/terminfo/x/xterm-xfree86
+lrwxrwxrwx root root 11 ./etc/terminfo/x/xterm -> xterm-color
+-rw-r--r-- root root 15 ./etc/timestamp
+drwxr-xr-x root root 4096 ./etc/udev
+drwxr-xr-x root root 4096 ./etc/udev/rules.d
+-rw-r--r-- root root 0 ./etc/udev/rules.d/80-net-name-slot.rules
+-rw-r--r-- root root 885 ./etc/udev/rules.d/local.rules
+-rw-r--r-- root root 49 ./etc/udev/udev.conf
+drwxr-xr-x root root 4096 ./etc/udhcpc.d
+-rwxr-xr-x root root 2652 ./etc/udhcpc.d/50default
+-rw-r--r-- root root 15 ./etc/version
+-rw-r--r-- root root 642 ./etc/xattr.conf
+drwxr-xr-x root root 4096 ./home
+drwx------ root root 4096 ./home/root
+drwxr-xr-x root root 4096 ./lib
+drwxr-xr-x root root 4096 ./lib/depmod.d
+-rw-r--r-- root root 71 ./lib/depmod.d/search.conf
+-rwxr-xr-x root root 177712 ./lib/ld-2.31.so
+lrwxrwxrwx root root 10 ./lib/ld-linux-x86-64.so.2 -> ld-2.31.so
+-rwxr-xr-x root root 18696 ./lib/libanl-2.31.so
+lrwxrwxrwx root root 14 ./lib/libanl.so.1 -> libanl-2.31.so
+-rwxr-xr-x root root 326600 ./lib/libblkid.so.1.1.0
+lrwxrwxrwx root root 17 ./lib/libblkid.so.1 -> libblkid.so.1.1.0
+-rwxr-xr-x root root 14296 ./lib/libBrokenLocale-2.31.so
+lrwxrwxrwx root root 23 ./lib/libBrokenLocale.so.1 -> libBrokenLocale-2.31.so
+-rwxr-xr-x root root 1806504 ./lib/libc-2.31.so
+-rwxr-xr-x root root 26512 ./lib/libcap-ng.so.0.0.0
+lrwxrwxrwx root root 18 ./lib/libcap-ng.so.0 -> libcap-ng.so.0.0.0
+-rw-r--r-- root root 38832 ./lib/libcap.so.2.34
+lrwxrwxrwx root root 14 ./lib/libcap.so.2 -> libcap.so.2.34
+lrwxrwxrwx root root 11 ./lib/libcap.so -> libcap.so.2
+-rwxr-xr-x root root 18320 ./lib/libcom_err.so.2.1
+lrwxrwxrwx root root 17 ./lib/libcom_err.so.2 -> libcom_err.so.2.1
+lrwxrwxrwx root root 15 ./lib/libcom_err.so -> libcom_err.so.2
+lrwxrwxrwx root root 12 ./lib/libc.so.6 -> libc-2.31.so
+-rwxr-xr-x root root 14360 ./lib/libdl-2.31.so
+lrwxrwxrwx root root 13 ./lib/libdl.so.2 -> libdl-2.31.so
+-rwxr-xr-x root root 44616 ./lib/libe2p.so.2.3
+lrwxrwxrwx root root 13 ./lib/libe2p.so.2 -> libe2p.so.2.3
+lrwxrwxrwx root root 11 ./lib/libe2p.so -> libe2p.so.2
+-rwxr-xr-x root root 426264 ./lib/libext2fs.so.2.4
+lrwxrwxrwx root root 16 ./lib/libext2fs.so.2 -> libext2fs.so.2.4
+lrwxrwxrwx root root 14 ./lib/libext2fs.so -> libext2fs.so.2
+-rwxr-xr-x root root 440104 ./lib/libfdisk.so.1.1.0
+lrwxrwxrwx root root 17 ./lib/libfdisk.so.1 -> libfdisk.so.1.1.0
+-rw-r--r-- root root 132 ./lib/libgcc_s.so
+-rw-r--r-- root root 100248 ./lib/libgcc_s.so.1
+-rwxr-xr-x root root 1312800 ./lib/libm-2.31.so
+-rwxr-xr-x root root 379432 ./lib/libmount.so.1.1.0
+lrwxrwxrwx root root 17 ./lib/libmount.so.1 -> libmount.so.1.1.0
+lrwxrwxrwx root root 12 ./lib/libm.so.6 -> libm-2.31.so
+-rwxr-xr-x root root 174104 ./lib/libmvec-2.31.so
+lrwxrwxrwx root root 15 ./lib/libmvec.so.1 -> libmvec-2.31.so
+-rwxr-xr-x root root 157512 ./lib/libncurses.so.5.9
+lrwxrwxrwx root root 17 ./lib/libncurses.so.5 -> libncurses.so.5.9
+-rwxr-xr-x root root 210760 ./lib/libncursesw.so.5.9
+lrwxrwxrwx root root 18 ./lib/libncursesw.so.5 -> libncursesw.so.5.9
+-rwxr-xr-x root root 92184 ./lib/libnsl-2.31.so
+lrwxrwxrwx root root 14 ./lib/libnsl.so.1 -> libnsl-2.31.so
+-rwxr-xr-x root root 35288 ./lib/libnss_compat-2.31.so
+lrwxrwxrwx root root 21 ./lib/libnss_compat.so.2 -> libnss_compat-2.31.so
+-rwxr-xr-x root root 30752 ./lib/libnss_db-2.31.so
+lrwxrwxrwx root root 17 ./lib/libnss_db.so.2 -> libnss_db-2.31.so
+-rwxr-xr-x root root 22560 ./lib/libnss_dns-2.31.so
+lrwxrwxrwx root root 18 ./lib/libnss_dns.so.2 -> libnss_dns-2.31.so
+-rwxr-xr-x root root 51232 ./lib/libnss_files-2.31.so
+lrwxrwxrwx root root 20 ./lib/libnss_files.so.2 -> libnss_files-2.31.so
+-rwxr-xr-x root root 22560 ./lib/libnss_hesiod-2.31.so
+lrwxrwxrwx root root 21 ./lib/libnss_hesiod.so.2 -> libnss_hesiod-2.31.so
+-rwxr-xr-x root root 113296 ./lib/libpthread-2.31.so
+lrwxrwxrwx root root 18 ./lib/libpthread.so.0 -> libpthread-2.31.so
+-rwxr-xr-x root root 88320 ./lib/libresolv-2.31.so
+lrwxrwxrwx root root 17 ./lib/libresolv.so.2 -> libresolv-2.31.so
+-rwxr-xr-x root root 39328 ./lib/librt-2.31.so
+lrwxrwxrwx root root 13 ./lib/librt.so.1 -> librt-2.31.so
+-rwxr-xr-x root root 231528 ./lib/libsmartcols.so.1.1.0
+lrwxrwxrwx root root 21 ./lib/libsmartcols.so.1 -> libsmartcols.so.1.1.0
+-rwxr-xr-x root root 34704 ./lib/libss.so.2.0
+lrwxrwxrwx root root 12 ./lib/libss.so.2 -> libss.so.2.0
+lrwxrwxrwx root root 10 ./lib/libss.so -> libss.so.2
+-rwxr-xr-x root root 35416 ./lib/libthread_db-1.0.so
+lrwxrwxrwx root root 19 ./lib/libthread_db.so.1 -> libthread_db-1.0.so
+-rwxr-xr-x root root 175208 ./lib/libtinfo.so.5.9
+lrwxrwxrwx root root 15 ./lib/libtinfo.so.5 -> libtinfo.so.5.9
+-rwxr-xr-x root root 157912 ./lib/libudev.so.1.6.3
+lrwxrwxrwx root root 16 ./lib/libudev.so.1 -> libudev.so.1.6.3
+-rwxr-xr-x root root 14360 ./lib/libutil-2.31.so
+lrwxrwxrwx root root 15 ./lib/libutil.so.1 -> libutil-2.31.so
+-rwxr-xr-x root root 30752 ./lib/libuuid.so.1.3.0
+lrwxrwxrwx root root 16 ./lib/libuuid.so.1 -> libuuid.so.1.3.0
+-rwxr-xr-x root root 39816 ./lib/libwrap.so.0.7.6
+lrwxrwxrwx root root 16 ./lib/libwrap.so.0 -> libwrap.so.0.7.6
+-rwxr-xr-x root root 100312 ./lib/libz.so.1.2.11
+lrwxrwxrwx root root 14 ./lib/libz.so.1 -> libz.so.1.2.11
+drwxr-xr-x root root 4096 ./lib/modprobe.d
+drwxr-xr-x root root 4096 ./lib/modules
+drwxr-xr-x root root 4096 ./lib/modules/5.4.43-yocto-standard
+drwxr-xr-x root root 4096 ./lib/modules/5.4.43-yocto-standard/kernel
+drwxr-xr-x root root 4096 ./lib/modules/5.4.43-yocto-standard/kernel/drivers
+drwxr-xr-x root root 4096 ./lib/modules/5.4.43-yocto-standard/kernel/drivers/video
+drwxr-xr-x root root 4096 ./lib/modules/5.4.43-yocto-standard/kernel/drivers/video/fbdev
+-rw-r--r-- root root 46440 ./lib/modules/5.4.43-yocto-standard/kernel/drivers/video/fbdev/uvesafb.ko
+drwxr-xr-x root root 4096 ./lib/modules/5.4.43-yocto-standard/kernel/net
+drwxr-xr-x root root 4096 ./lib/modules/5.4.43-yocto-standard/kernel/net/ipv4
+drwxr-xr-x root root 4096 ./lib/modules/5.4.43-yocto-standard/kernel/net/ipv4/netfilter
+-rw-r--r-- root root 6912 ./lib/modules/5.4.43-yocto-standard/kernel/net/ipv4/netfilter/iptable_filter.ko
+-rw-r--r-- root root 6272 ./lib/modules/5.4.43-yocto-standard/kernel/net/ipv4/netfilter/iptable_nat.ko
+-rw-r--r-- root root 32144 ./lib/modules/5.4.43-yocto-standard/kernel/net/ipv4/netfilter/ip_tables.ko
+-rw-r--r-- root root 6160 ./lib/modules/5.4.43-yocto-standard/kernel/net/ipv4/netfilter/nf_defrag_ipv4.ko
+drwxr-xr-x root root 4096 ./lib/modules/5.4.43-yocto-standard/kernel/net/ipv6
+drwxr-xr-x root root 4096 ./lib/modules/5.4.43-yocto-standard/kernel/net/ipv6/netfilter
+-rw-r--r-- root root 6928 ./lib/modules/5.4.43-yocto-standard/kernel/net/ipv6/netfilter/ip6table_filter.ko
+-rw-r--r-- root root 32640 ./lib/modules/5.4.43-yocto-standard/kernel/net/ipv6/netfilter/ip6_tables.ko
+-rw-r--r-- root root 16472 ./lib/modules/5.4.43-yocto-standard/kernel/net/ipv6/netfilter/nf_defrag_ipv6.ko
+drwxr-xr-x root root 4096 ./lib/modules/5.4.43-yocto-standard/kernel/net/netfilter
+-rw-r--r-- root root 164400 ./lib/modules/5.4.43-yocto-standard/kernel/net/netfilter/nf_conntrack.ko
+-rw-r--r-- root root 45712 ./lib/modules/5.4.43-yocto-standard/kernel/net/netfilter/nf_nat.ko
+-rw-r--r-- root root 49480 ./lib/modules/5.4.43-yocto-standard/kernel/net/netfilter/x_tables.ko
+-rw-r--r-- root root 199 ./lib/modules/5.4.43-yocto-standard/modules.alias
+-rw-r--r-- root root 443 ./lib/modules/5.4.43-yocto-standard/modules.alias.bin
+-rw-r--r-- root root 9285 ./lib/modules/5.4.43-yocto-standard/modules.builtin
+-rw-r--r-- root root 24578 ./lib/modules/5.4.43-yocto-standard/modules.builtin.alias.bin
+-rw-r--r-- root root 10874 ./lib/modules/5.4.43-yocto-standard/modules.builtin.bin
+-rw-r--r-- root root 68434 ./lib/modules/5.4.43-yocto-standard/modules.builtin.modinfo
+-rw-r--r-- root root 1099 ./lib/modules/5.4.43-yocto-standard/modules.dep
+-rw-r--r-- root root 1794 ./lib/modules/5.4.43-yocto-standard/modules.dep.bin
+-rw-r--r-- root root 0 ./lib/modules/5.4.43-yocto-standard/modules.devname
+-rw-r--r-- root root 17759 ./lib/modules/5.4.43-yocto-standard/modules.order
+-rw-r--r-- root root 55 ./lib/modules/5.4.43-yocto-standard/modules.softdep
+-rw-r--r-- root root 7817 ./lib/modules/5.4.43-yocto-standard/modules.symbols
+-rw-r--r-- root root 9233 ./lib/modules/5.4.43-yocto-standard/modules.symbols.bin
+drwxr-xr-x root root 4096 ./lib/udev
+-rwxr-xr-x root root 104640 ./lib/udev/ata_id
+-rwxr-xr-x root root 116936 ./lib/udev/cdrom_id
+-rwxr-xr-x root root 100552 ./lib/udev/collect
+-rwxr-xr-x root root 14296 ./lib/udev/mtd_probe
+drwxr-xr-x root root 4096 ./lib/udev/rules.d
+-rw-r--r-- root root 321 ./lib/udev/rules.d/01-md-raid-creating.rules
+-rw-r--r-- root root 121 ./lib/udev/rules.d/50-firmware.rules
+-rw-r--r-- root root 3677 ./lib/udev/rules.d/50-udev-default.rules
+-rw-r--r-- root root 620 ./lib/udev/rules.d/60-block.rules
+-rw-r--r-- root root 1071 ./lib/udev/rules.d/60-cdrom_id.rules
+-rw-r--r-- root root 413 ./lib/udev/rules.d/60-drm.rules
+-rw-r--r-- root root 974 ./lib/udev/rules.d/60-evdev.rules
+-rw-r--r-- root root 282 ./lib/udev/rules.d/60-input-id.rules
+-rw-r--r-- root root 616 ./lib/udev/rules.d/60-persistent-alsa.rules
+-rw-r--r-- root root 2710 ./lib/udev/rules.d/60-persistent-input.rules
+-rw-r--r-- root root 6521 ./lib/udev/rules.d/60-persistent-storage.rules
+-rw-r--r-- root root 1509 ./lib/udev/rules.d/60-persistent-storage-tape.rules
+-rw-r--r-- root root 769 ./lib/udev/rules.d/60-persistent-v4l.rules
+-rw-r--r-- root root 727 ./lib/udev/rules.d/60-sensor.rules
+-rw-r--r-- root root 1190 ./lib/udev/rules.d/60-serial.rules
+-rw-r--r-- root root 2134 ./lib/udev/rules.d/63-md-raid-arrays.rules
+-rw-r--r-- root root 387 ./lib/udev/rules.d/64-btrfs-dm.rules
+-rw-r--r-- root root 574 ./lib/udev/rules.d/64-btrfs.rules
+-rw-r--r-- root root 1444 ./lib/udev/rules.d/64-md-raid-assembly.rules
+-rw-r--r-- root root 846 ./lib/udev/rules.d/69-md-clustered-confirm-device.rules
+-rw-r--r-- root root 432 ./lib/udev/rules.d/70-joystick.rules
+-rw-r--r-- root root 734 ./lib/udev/rules.d/70-mouse.rules
+-rw-r--r-- root root 473 ./lib/udev/rules.d/70-touchpad.rules
+-rw-r--r-- root root 452 ./lib/udev/rules.d/75-net-description.rules
+-rw-r--r-- root root 174 ./lib/udev/rules.d/75-probe_mtd.rules
+-rw-r--r-- root root 4816 ./lib/udev/rules.d/78-sound-card.rules
+-rw-r--r-- root root 615 ./lib/udev/rules.d/80-drivers.rules
+-rw-r--r-- root root 491 ./lib/udev/rules.d/80-net-name-slot.rules
+-rwxr-xr-x root root 109304 ./lib/udev/scsi_id
+-rwxr-xr-x root root 67776 ./lib/udev/v4l_id
+drwxr-xr-x root root 4096 ./media
+drwxr-xr-x root root 4096 ./mnt
+dr-xr-xr-x root root 4096 ./proc
+drwxr-xr-x root root 4096 ./run
+drwxr-xr-x root root 4096 ./sbin
+-rwxr-xr-x root root 64736 ./sbin/agetty
+-rwxr-xr-x root root 34792 ./sbin/badblocks
+lrwxrwxrwx root root 22 ./sbin/blkid -> /sbin/blkid.util-linux
+-rwxr-xr-x root root 120912 ./sbin/blkid.util-linux
+lrwxrwxrwx root root 25 ./sbin/blockdev -> /sbin/blockdev.util-linux
+-rwxr-xr-x root root 63536 ./sbin/blockdev.util-linux
+-rwxr-xr-x root root 22736 ./sbin/bootlogd
+-rwxr-xr-x root root 104568 ./sbin/bridge
+-rwxr-xr-x root root 96664 ./sbin/cfdisk
+-rwxr-xr-x root root 38952 ./sbin/ctrlaltdel
+-rwxr-xr-x root root 239064 ./sbin/debugfs
+lrwxrwxrwx root root 11 ./sbin/depmod.kmod -> ../bin/kmod
+lrwxrwxrwx root root 17 ./sbin/depmod -> /sbin/depmod.kmod
+-rwxr-xr-x root root 30768 ./sbin/dumpe2fs
+-rwxr-xr-x root root 14376 ./sbin/e2freefrag
+-rwxr-xr-x root root 330808 ./sbin/e2fsck
+-rwxr-xr-x root root 38952 ./sbin/e2image
+-rwxr-xr-x root root 30768 ./sbin/e2mmpstatus
+-rwxr-xr-x root root 22560 ./sbin/e2undo
+-rwxr-xr-x root root 26656 ./sbin/e4crypt
+-rwxr-xr-x root root 34776 ./sbin/e4defrag
+lrwxrwxrwx root root 22 ./sbin/fdisk -> /sbin/fdisk.util-linux
+-rwxr-xr-x root root 149600 ./sbin/fdisk.util-linux
+-rwxr-xr-x root root 18416 ./sbin/filefrag
+-rwxr-xr-x root root 330808 ./sbin/fsck.ext2
+-rwxr-xr-x root root 330808 ./sbin/fsck.ext3
+-rwxr-xr-x root root 330808 ./sbin/fsck.ext4
+lrwxrwxrwx root root 21 ./sbin/fsck -> /sbin/fsck.util-linux
+-rwxr-xr-x root root 55392 ./sbin/fsck.util-linux
+-rwxr-xr-x root root 14296 ./sbin/fstab-decode
+lrwxrwxrwx root root 23 ./sbin/fstrim -> /sbin/fstrim.util-linux
+-rwxr-xr-x root root 71728 ./sbin/fstrim.util-linux
+lrwxrwxrwx root root 12 ./sbin/getty -> /sbin/agetty
+lrwxrwxrwx root root 19 ./sbin/halt -> /sbin/halt.sysvinit
+-rwsr-xr-- root shutdown 22512 ./sbin/halt.sysvinit
+lrwxrwxrwx root root 24 ./sbin/hwclock -> /sbin/hwclock.util-linux
+-rwxr-xr-x root root 80048 ./sbin/hwclock.util-linux
+-rwxr-xr-x root root 3109 ./sbin/ifcfg
+lrwxrwxrwx root root 19 ./sbin/ifconfig -> /bin/busybox.nosuid
+lrwxrwxrwx root root 19 ./sbin/ifdown -> /bin/busybox.nosuid
+lrwxrwxrwx root root 19 ./sbin/ifup -> /bin/busybox.nosuid
+lrwxrwxrwx root root 19 ./sbin/init -> /sbin/init.sysvinit
+-rwxr-xr-x root root 47944 ./sbin/init.sysvinit
+lrwxrwxrwx root root 11 ./sbin/insmod.kmod -> ../bin/kmod
+lrwxrwxrwx root root 17 ./sbin/insmod -> /sbin/insmod.kmod
+-rwxr-xr-x root root 619960 ./sbin/ip.iproute2
+lrwxrwxrwx root root 17 ./sbin/ip -> /sbin/ip.iproute2
+-rwxr-xr-x root root 26664 ./sbin/killall5
+lrwxrwxrwx root root 19 ./sbin/klogd -> /bin/busybox.nosuid
+-rwxr-xr-x root root 887640 ./sbin/ldconfig
+lrwxrwxrwx root root 19 ./sbin/loadkmap -> /bin/busybox.nosuid
+lrwxrwxrwx root root 19 ./sbin/logread -> /bin/busybox.nosuid
+-rwxr-xr-x root root 14296 ./sbin/logsave
+lrwxrwxrwx root root 24 ./sbin/losetup -> /sbin/losetup.util-linux
+-rwxr-xr-x root root 112808 ./sbin/losetup.util-linux
+lrwxrwxrwx root root 15 ./sbin/lsmod -> /bin/lsmod.kmod
+-rwxr-xr-x root root 595280 ./sbin/mdadm
+-rwxr-xr-x root root 328880 ./sbin/mdmon
+-rwxr-xr-x root root 137512 ./sbin/mke2fs.e2fsprogs
+lrwxrwxrwx root root 22 ./sbin/mke2fs -> /sbin/mke2fs.e2fsprogs
+-rwxr-xr-x root root 137512 ./sbin/mkfs.ext2.e2fsprogs
+lrwxrwxrwx root root 25 ./sbin/mkfs.ext2 -> /sbin/mkfs.ext2.e2fsprogs
+-rwxr-xr-x root root 137512 ./sbin/mkfs.ext3
+-rwxr-xr-x root root 137512 ./sbin/mkfs.ext4
+-rwxr-xr-x root root 14296 ./sbin/mklost+found
+lrwxrwxrwx root root 23 ./sbin/mkswap -> /sbin/mkswap.util-linux
+-rwxr-xr-x root root 104504 ./sbin/mkswap.util-linux
+lrwxrwxrwx root root 11 ./sbin/modinfo.kmod -> ../bin/kmod
+lrwxrwxrwx root root 18 ./sbin/modinfo -> /sbin/modinfo.kmod
+lrwxrwxrwx root root 11 ./sbin/modprobe.kmod -> ../bin/kmod
+lrwxrwxrwx root root 19 ./sbin/modprobe -> /sbin/modprobe.kmod
+lrwxrwxrwx root root 20 ./sbin/nologin -> /sbin/nologin.shadow
+-rwxr-xr-x root root 14296 ./sbin/nologin.shadow
+-rwxr-xr-x root root 14384 ./sbin/nologin.util-linux
+lrwxrwxrwx root root 27 ./sbin/pivot_root -> /sbin/pivot_root.util-linux
+-rwxr-xr-x root root 14384 ./sbin/pivot_root.util-linux
+-rwxr-xr-x root root 2460 ./sbin/populate-extfs.sh
+lrwxrwxrwx root root 23 ./sbin/poweroff -> /sbin/poweroff.sysvinit
+lrwxrwxrwx root root 13 ./sbin/poweroff.sysvinit -> halt.sysvinit
+lrwxrwxrwx root root 21 ./sbin/reboot -> /sbin/reboot.sysvinit
+lrwxrwxrwx root root 13 ./sbin/reboot.sysvinit -> halt.sysvinit
+lrwxrwxrwx root root 11 ./sbin/rmmod.kmod -> ../bin/kmod
+lrwxrwxrwx root root 16 ./sbin/rmmod -> /sbin/rmmod.kmod
+lrwxrwxrwx root root 19 ./sbin/route -> /bin/busybox.nosuid
+-rwxr-xr-x root root 208 ./sbin/routef
+-rwxr-xr-x root root 1656 ./sbin/routel
+-rwxr-xr-x root root 75832 ./sbin/rtmon
+-rwxr-xr-x root root 70 ./sbin/rtpr
+lrwxrwxrwx root root 23 ./sbin/runlevel -> /sbin/runlevel.sysvinit
+-rwxr-xr-x root root 14304 ./sbin/runlevel.sysvinit
+lrwxrwxrwx root root 19 ./sbin/setconsole -> /bin/busybox.nosuid
+lrwxrwxrwx root root 23 ./sbin/shutdown -> /sbin/shutdown.sysvinit
+-rwsr-xr-- root shutdown 30744 ./sbin/shutdown.sysvinit
+lrwxrwxrwx root root 19 ./sbin/start-stop-daemon -> /bin/busybox.nosuid
+lrwxrwxrwx root root 24 ./sbin/sulogin -> /sbin/sulogin.util-linux
+-rwxr-xr-x root root 47152 ./sbin/sulogin.util-linux
+lrwxrwxrwx root root 24 ./sbin/swapoff -> /sbin/swapoff.util-linux
+-rwxr-xr-x root root 22576 ./sbin/swapoff.util-linux
+lrwxrwxrwx root root 23 ./sbin/swapon -> /sbin/swapon.util-linux
+-rwxr-xr-x root root 51248 ./sbin/swapon.util-linux
+lrwxrwxrwx root root 28 ./sbin/switch_root -> /sbin/switch_root.util-linux
+-rwxr-xr-x root root 14384 ./sbin/switch_root.util-linux
+-rwxr-xr-x root root 30768 ./sbin/sysctl.procps
+lrwxrwxrwx root root 19 ./sbin/sysctl -> /sbin/sysctl.procps
+lrwxrwxrwx root root 19 ./sbin/syslogd -> /bin/busybox.nosuid
+lrwxrwxrwx root root 4 ./sbin/telinit -> init
+lrwxrwxrwx root root 16 ./sbin/udevadm -> /usr/bin/udevadm
+-rwxr-xr-x root root 334168 ./sbin/udevd
+lrwxrwxrwx root root 19 ./sbin/udhcpc -> /bin/busybox.nosuid
+-rwxr-xr-x root root 133264 ./sbin/v86d
+lrwxrwxrwx root root 17 ./sbin/vigr -> /sbin/vigr.shadow
+lrwxrwxrwx root root 11 ./sbin/vigr.shadow -> vipw.shadow
+lrwxrwxrwx root root 17 ./sbin/vipw -> /sbin/vipw.shadow
+-rwxr-xr-x root root 61496 ./sbin/vipw.shadow
+dr-xr-xr-x root root 4096 ./sys
+drwxrwxrwt root root 4096 ./tmp
+drwxr-xr-x root root 4096 ./usr
+drwxr-xr-x root root 20480 ./usr/bin
+lrwxrwxrwx root root 36 ./usr/bin/addr2line -> /usr/bin/x86_64-poky-linux-addr2line
+-rwxr-xr-x root root 43208 ./usr/bin/arch.coreutils
+lrwxrwxrwx root root 23 ./usr/bin/arch -> /usr/bin/arch.coreutils
+lrwxrwxrwx root root 29 ./usr/bin/ar -> /usr/bin/x86_64-poky-linux-ar
+lrwxrwxrwx root root 29 ./usr/bin/as -> /usr/bin/x86_64-poky-linux-as
+-rwxr-xr-x root root 14288 ./usr/bin/attr
+lrwxrwxrwx root root 13 ./usr/bin/awk -> /usr/bin/gawk
+-rwxr-xr-x root root 63680 ./usr/bin/b2sum
+-rwxr-xr-x root root 47264 ./usr/bin/base32
+-rwxr-xr-x root root 47272 ./usr/bin/base64.coreutils
+-rwxr-xr-x root root 43176 ./usr/bin/basename.coreutils
+lrwxrwxrwx root root 27 ./usr/bin/basename -> /usr/bin/basename.coreutils
+-rwxr-xr-x root root 59552 ./usr/bin/basenc
+-rwxr-xr-x root root 96928 ./usr/bin/bc.bc
+lrwxrwxrwx root root 14 ./usr/bin/bc -> /usr/bin/bc.bc
+lrwxrwxrwx root root 19 ./usr/bin/[[ -> /bin/busybox.nosuid
+-rwxr-xr-x root root 455224 ./usr/bin/bison
+-rwxr-xr-x root root 933632 ./usr/bin/btrfs
+lrwxrwxrwx root root 5 ./usr/bin/btrfsck -> btrfs
+-rwxr-xr-x root root 531656 ./usr/bin/btrfs-convert
+-rwxr-xr-x root root 494856 ./usr/bin/btrfs-find-root
+-rwxr-xr-x root root 523456 ./usr/bin/btrfs-image
+-rwxr-xr-x root root 498888 ./usr/bin/btrfs-map-logical
+-rwxr-xr-x root root 494792 ./usr/bin/btrfs-select-super
+-rwxr-xr-x root root 494784 ./usr/bin/btrfstune
+lrwxrwxrwx root root 11 ./usr/bin/bunzip2.bzip2 -> bzip2.bzip2
+lrwxrwxrwx root root 22 ./usr/bin/bunzip2 -> /usr/bin/bunzip2.bzip2
+lrwxrwxrwx root root 11 ./usr/bin/bzcat.bzip2 -> bzip2.bzip2
+lrwxrwxrwx root root 20 ./usr/bin/bzcat -> /usr/bin/bzcat.bzip2
+lrwxrwxrwx root root 6 ./usr/bin/bzcmp -> bzdiff
+-rwxr-xr-x root root 2140 ./usr/bin/bzdiff
+lrwxrwxrwx root root 6 ./usr/bin/bzegrep -> bzgrep
+lrwxrwxrwx root root 6 ./usr/bin/bzfgrep -> bzgrep
+-rwxr-xr-x root root 2054 ./usr/bin/bzgrep
+-rwxr-xr-x root root 38952 ./usr/bin/bzip2.bzip2
+-rwxr-xr-x root root 14296 ./usr/bin/bzip2recover
+lrwxrwxrwx root root 20 ./usr/bin/bzip2 -> /usr/bin/bzip2.bzip2
+lrwxrwxrwx root root 6 ./usr/bin/bzless -> bzmore
+-rwxr-xr-x root root 1259 ./usr/bin/bzmore
+lrwxrwxrwx root root 23 ./usr/bin/cal -> /usr/bin/cal.util-linux
+-rwxr-xr-x root root 67936 ./usr/bin/cal.util-linux
+lrwxrwxrwx root root 34 ./usr/bin/c++filt -> /usr/bin/x86_64-poky-linux-c++filt
+-rwxr-xr-x root root 14288 ./usr/bin/chacl
+-rwsr-xr-x root root 71776 ./usr/bin/chage
+-rwxr-xr-x root root 71848 ./usr/bin/chcon.coreutils
+lrwxrwxrwx root root 24 ./usr/bin/chcon -> /usr/bin/chcon.coreutils
+-rwsr-xr-x root root 54032 ./usr/bin/chfn.shadow
+lrwxrwxrwx root root 20 ./usr/bin/chfn -> /usr/bin/chfn.shadow
+-rwxr-xr-x root root 63528 ./usr/bin/chmem
+-rwxr-xr-x root root 51240 ./usr/bin/choom
+lrwxrwxrwx root root 24 ./usr/bin/chrt -> /usr/bin/chrt.util-linux
+-rwxr-xr-x root root 34864 ./usr/bin/chrt.util-linux
+-rwsr-xr-x root root 53904 ./usr/bin/chsh.shadow
+lrwxrwxrwx root root 20 ./usr/bin/chsh -> /usr/bin/chsh.shadow
+lrwxrwxrwx root root 19 ./usr/bin/chvt -> /bin/busybox.nosuid
+-rwxr-xr-x root root 43176 ./usr/bin/cksum.coreutils
+lrwxrwxrwx root root 24 ./usr/bin/cksum -> /usr/bin/cksum.coreutils
+lrwxrwxrwx root root 19 ./usr/bin/clear -> /bin/busybox.nosuid
+-rwxr-xr-x root root 47176 ./usr/bin/cmp.diffutils
+lrwxrwxrwx root root 22 ./usr/bin/cmp -> /usr/bin/cmp.diffutils
+-rwxr-xr-x root root 34848 ./usr/bin/col
+-rwxr-xr-x root root 14368 ./usr/bin/colcrt
+-rwxr-xr-x root root 30760 ./usr/bin/colrm
+-rwxr-xr-x root root 51240 ./usr/bin/column
+-rwxr-xr-x root root 51400 ./usr/bin/comm.coreutils
+lrwxrwxrwx root root 23 ./usr/bin/comm -> /usr/bin/comm.coreutils
+-rwxr-xr-x root root 1342 ./usr/bin/compile_et
+-rwxr-xr-x root root 6214 ./usr/bin/c_rehash
+-rwxr-xr-x root root 125128 ./usr/bin/csplit.coreutils
+lrwxrwxrwx root root 25 ./usr/bin/csplit -> /usr/bin/csplit.coreutils
+-rwxr-xr-x root root 55496 ./usr/bin/cut.coreutils
+lrwxrwxrwx root root 22 ./usr/bin/cut -> /usr/bin/cut.coreutils
+-rwxr-xr-x root root 14304 ./usr/bin/dbus-cleanup-sockets
+-rwxr-xr-x root root 223688 ./usr/bin/dbus-daemon
+-rwxr-xr-x root root 30680 ./usr/bin/dbus-launch
+-rwxr-xr-x root root 30688 ./usr/bin/dbus-monitor
+-rwxr-xr-x root root 14304 ./usr/bin/dbus-run-session
+-rwxr-xr-x root root 30680 ./usr/bin/dbus-send
+-rwxr-xr-x root root 26672 ./usr/bin/dbus-test-tool
+-rwxr-xr-x root root 14320 ./usr/bin/dbus-update-activation-environment
+-rwxr-xr-x root root 14296 ./usr/bin/dbus-uuidgen
+-rwxr-xr-x root root 55352 ./usr/bin/dc.bc
+lrwxrwxrwx root root 14 ./usr/bin/dc -> /usr/bin/dc.bc
+lrwxrwxrwx root root 19 ./usr/bin/deallocvt -> /bin/busybox.nosuid
+-rwxr-xr-x root root 105232 ./usr/bin/df.coreutils
+-rwxr-xr-x root root 67760 ./usr/bin/diff3
+-rwxr-xr-x root root 223544 ./usr/bin/diff.diffutils
+lrwxrwxrwx root root 23 ./usr/bin/diff -> /usr/bin/diff.diffutils
+-rwxr-xr-x root root 71864 ./usr/bin/dircolors.coreutils
+lrwxrwxrwx root root 28 ./usr/bin/dircolors -> /usr/bin/dircolors.coreutils
+-rwxr-xr-x root root 162448 ./usr/bin/dir.coreutils
+-rwxr-xr-x root root 43176 ./usr/bin/dirname.coreutils
+lrwxrwxrwx root root 26 ./usr/bin/dirname -> /usr/bin/dirname.coreutils
+lrwxrwxrwx root root 22 ./usr/bin/dir -> /usr/bin/dir.coreutils
+-rwxr-xr-x root root 194760 ./usr/bin/du.coreutils
+lrwxrwxrwx root root 19 ./usr/bin/dumpleases -> /bin/busybox.nosuid
+lrwxrwxrwx root root 21 ./usr/bin/du -> /usr/bin/du.coreutils
+lrwxrwxrwx root root 30 ./usr/bin/dwp -> /usr/bin/x86_64-poky-linux-dwp
+lrwxrwxrwx root root 25 ./usr/bin/eject -> /usr/bin/eject.util-linux
+-rwxr-xr-x root root 79920 ./usr/bin/eject.util-linux
+lrwxrwxrwx root root 34 ./usr/bin/elfedit -> /usr/bin/x86_64-poky-linux-elfedit
+-rwxr-xr-x root root 55904 ./usr/bin/env.coreutils
+lrwxrwxrwx root root 22 ./usr/bin/env -> /usr/bin/env.coreutils
+-rwxr-xr-x root root 39016 ./usr/bin/eu-ar
+-rwxr-xr-x root root 28656 ./usr/bin/eu-elfclassify
+-rwxr-xr-x root root 350840 ./usr/bin/eu-elfcmp
+-rwxr-xr-x root root 31160 ./usr/bin/eu-elfcompress
+-rwxr-xr-x root root 432760 ./usr/bin/eu-elflint
+-rwxr-xr-x root root 22672 ./usr/bin/eu-findtextrel
+-rwxr-xr-x root root 2911 ./usr/bin/eu-make-debug-archive
+-rwxr-xr-x root root 355056 ./usr/bin/eu-objdump
+-rwxr-xr-x root root 22568 ./usr/bin/eu-ranlib
+-rwxr-xr-x root root 27600 ./usr/bin/eu-stack
+-rwxr-xr-x root root 26736 ./usr/bin/eu-strings
+-rwxr-xr-x root root 51240 ./usr/bin/eu-unstrip
+-rwxr-xr-x root root 47304 ./usr/bin/expand.coreutils
+lrwxrwxrwx root root 25 ./usr/bin/expand -> /usr/bin/expand.coreutils
+-rwsr-xr-x root root 36336 ./usr/bin/expiry
+-rwxr-xr-x root root 125096 ./usr/bin/expr.coreutils
+lrwxrwxrwx root root 23 ./usr/bin/expr -> /usr/bin/expr.coreutils
+-rwxr-xr-x root root 84168 ./usr/bin/factor.coreutils
+lrwxrwxrwx root root 25 ./usr/bin/factor -> /usr/bin/factor.coreutils
+-rwxr-xr-x root root 22784 ./usr/bin/faillog
+lrwxrwxrwx root root 29 ./usr/bin/fallocate -> /usr/bin/fallocate.util-linux
+-rwxr-xr-x root root 30776 ./usr/bin/fallocate.util-linux
+-rwxr-xr-x root root 92656 ./usr/bin/filan
+-rwxr-xr-x root root 34904 ./usr/bin/fincore
+-rwxr-xr-x root root 324064 ./usr/bin/find.findutils
+-rwxr-xr-x root root 68840 ./usr/bin/findmnt
+lrwxrwxrwx root root 23 ./usr/bin/find -> /usr/bin/find.findutils
+-rwxr-xr-x root root 443016 ./usr/bin/flex
+lrwxrwxrwx root root 4 ./usr/bin/flex++ -> flex
+lrwxrwxrwx root root 25 ./usr/bin/flock -> /usr/bin/flock.util-linux
+-rwxr-xr-x root root 34944 ./usr/bin/flock.util-linux
+-rwxr-xr-x root root 55464 ./usr/bin/fmt.coreutils
+lrwxrwxrwx root root 22 ./usr/bin/fmt -> /usr/bin/fmt.coreutils
+-rwxr-xr-x root root 47272 ./usr/bin/fold.coreutils
+lrwxrwxrwx root root 23 ./usr/bin/fold -> /usr/bin/fold.coreutils
+-rwxr-xr-x root root 26672 ./usr/bin/free.procps
+lrwxrwxrwx root root 20 ./usr/bin/free -> /usr/bin/free.procps
+-rwxr-xr-x root root 1185 ./usr/bin/fsck.btrfs
+-rwxr-xr-x root root 26576 ./usr/bin/funzip
+lrwxrwxrwx root root 19 ./usr/bin/fuser -> /bin/busybox.nosuid
+-rwxr-xr-x root root 653592 ./usr/bin/gawk
+-rwxr-xr-x root root 653592 ./usr/bin/gawk-5.1.0
+-rwxr-xr-x root root 26808 ./usr/bin/gencat
+-rwxr-xr-x root root 34912 ./usr/bin/getconf
+-rwxr-xr-x root root 35280 ./usr/bin/getent
+-rwxr-xr-x root root 31312 ./usr/bin/getfacl
+-rwxr-xr-x root root 23032 ./usr/bin/getfattr
+lrwxrwxrwx root root 28 ./usr/bin/ginsttest-runner -> gnome-desktop-testing-runner
+-rwxr-xr-x root root 4049 ./usr/bin/g-ir-annotation-tool
+-rwxr-xr-x root root 187384 ./usr/bin/g-ir-compiler
+-rwxr-xr-x root root 42968 ./usr/bin/g-ir-generate
+-rwxr-xr-x root root 14296 ./usr/bin/g-ir-inspect
+-rwxr-xr-x root root 4040 ./usr/bin/g-ir-scanner
+-rwxr-xr-x root root 35384 ./usr/bin/gnome-desktop-testing-runner
+-rwsr-xr-x root root 71624 ./usr/bin/gpasswd
+lrwxrwxrwx root root 32 ./usr/bin/gprof -> /usr/bin/x86_64-poky-linux-gprof
+-rwxr-xr-x root root 43176 ./usr/bin/groups.coreutils
+-rwxr-xr-x root root 14296 ./usr/bin/groups.shadow
+lrwxrwxrwx root root 22 ./usr/bin/groups -> /usr/bin/groups.shadow
+-rwxr-xr-x root root 22568 ./usr/bin/hardlink
+-rwxr-xr-x root root 55496 ./usr/bin/head.coreutils
+lrwxrwxrwx root root 23 ./usr/bin/head -> /usr/bin/head.coreutils
+lrwxrwxrwx root root 27 ./usr/bin/hexdump -> /usr/bin/hexdump.util-linux
+-rwxr-xr-x root root 55352 ./usr/bin/hexdump.util-linux
+-rwxr-xr-x root root 43176 ./usr/bin/hostid.coreutils
+lrwxrwxrwx root root 25 ./usr/bin/hostid -> /usr/bin/hostid.coreutils
+lrwxrwxrwx root root 7 ./usr/bin/i386 -> setarch
+-rwxr-xr-x root root 59608 ./usr/bin/iconv
+-rwxr-xr-x root root 55496 ./usr/bin/id.coreutils
+lrwxrwxrwx root root 21 ./usr/bin/id -> /usr/bin/id.coreutils
+-rwxr-xr-x root root 141560 ./usr/bin/install.coreutils
+lrwxrwxrwx root root 26 ./usr/bin/install -> /usr/bin/install.coreutils
+lrwxrwxrwx root root 26 ./usr/bin/ionice -> /usr/bin/ionice.util-linux
+-rwxr-xr-x root root 30768 ./usr/bin/ionice.util-linux
+-rwxr-xr-x root root 30824 ./usr/bin/ipcmk
+-rwxr-xr-x root root 34856 ./usr/bin/ipcrm
+-rwxr-xr-x root root 71720 ./usr/bin/ipcs
+lrwxrwxrwx root root 30 ./usr/bin/iptables-xml -> /usr/sbin/xtables-legacy-multi
+-rwxr-xr-x root root 30760 ./usr/bin/isosize
+-rwxr-xr-x root root 59592 ./usr/bin/join.coreutils
+lrwxrwxrwx root root 23 ./usr/bin/join -> /usr/bin/join.coreutils
+lrwxrwxrwx root root 19 ./usr/bin/killall -> /bin/busybox.nosuid
+lrwxrwxrwx root root 13 ./usr/bin/lastb.sysvinit -> last.sysvinit
+lrwxrwxrwx root root 23 ./usr/bin/lastb -> /usr/bin/lastb.sysvinit
+lrwxrwxrwx root root 15 ./usr/bin/lastb.util-linux -> last.util-linux
+-rwxr-xr-x root root 32032 ./usr/bin/lastlog
+-rwxr-xr-x root root 22512 ./usr/bin/last.sysvinit
+lrwxrwxrwx root root 22 ./usr/bin/last -> /usr/bin/last.sysvinit
+-rwxr-xr-x root root 47152 ./usr/bin/last.util-linux
+-rwxr-xr-x root root 63648 ./usr/bin/lbracket.coreutils
+lrwxrwxrwx root root 33 ./usr/bin/ld.bfd -> /usr/bin/x86_64-poky-linux-ld.bfd
+lrwxrwxrwx root root 34 ./usr/bin/ld.gold -> /usr/bin/x86_64-poky-linux-ld.gold
+lrwxrwxrwx root root 29 ./usr/bin/ld -> /usr/bin/x86_64-poky-linux-ld
+lrwxrwxrwx root root 19 ./usr/bin/less -> /bin/busybox.nosuid
+-rwxr-xr-x root root 173 ./usr/bin/libpng16-config
+lrwxrwxrwx root root 15 ./usr/bin/libpng-config -> libpng16-config
+-rwxr-xr-x root root 43176 ./usr/bin/link.coreutils
+lrwxrwxrwx root root 23 ./usr/bin/link -> /usr/bin/link.coreutils
+lrwxrwxrwx root root 7 ./usr/bin/linux32 -> setarch
+lrwxrwxrwx root root 7 ./usr/bin/linux64 -> setarch
+-rwxr-xr-x root root 54648 ./usr/bin/locale
+-rwxr-xr-x root root 170408 ./usr/bin/locate
+lrwxrwxrwx root root 26 ./usr/bin/logger -> /usr/bin/logger.util-linux
+-rwxr-xr-x root root 47760 ./usr/bin/logger.util-linux
+-rwxr-xr-x root root 43176 ./usr/bin/logname.coreutils
+lrwxrwxrwx root root 26 ./usr/bin/logname -> /usr/bin/logname.coreutils
+-rwxr-xr-x root root 14368 ./usr/bin/look
+-rwxr-xr-x root root 14296 ./usr/bin/lsattr
+-rwxr-xr-x root root 145448 ./usr/bin/lsblk
+-rwxr-xr-x root root 100392 ./usr/bin/lscpu
+-rwxr-xr-x root root 92200 ./usr/bin/lsipc
+-rwxr-xr-x root root 39288 ./usr/bin/lslocks
+-rwxr-xr-x root root 67624 ./usr/bin/lslogins
+-rwxr-xr-x root root 67624 ./usr/bin/lsmem
+-rwxr-xr-x root root 51240 ./usr/bin/lsns
+lrwxrwxrwx root root 17 ./usr/bin/lzcat -> /usr/bin/lzcat.xz
+lrwxrwxrwx root root 5 ./usr/bin/lzcat.xz -> xz.xz
+lrwxrwxrwx root root 6 ./usr/bin/lzcmp -> xzdiff
+lrwxrwxrwx root root 6 ./usr/bin/lzdiff -> xzdiff
+lrwxrwxrwx root root 6 ./usr/bin/lzegrep -> xzgrep
+lrwxrwxrwx root root 6 ./usr/bin/lzfgrep -> xzgrep
+lrwxrwxrwx root root 6 ./usr/bin/lzgrep -> xzgrep
+lrwxrwxrwx root root 6 ./usr/bin/lzless -> xzless
+-rwxr-xr-x root root 14376 ./usr/bin/lzmadec
+-rwxr-xr-x root root 14376 ./usr/bin/lzmainfo
+lrwxrwxrwx root root 16 ./usr/bin/lzma -> /usr/bin/lzma.xz
+lrwxrwxrwx root root 5 ./usr/bin/lzma.xz -> xz.xz
+lrwxrwxrwx root root 6 ./usr/bin/lzmore -> xzmore
+-rwxr-xr-x root root 243992 ./usr/bin/m4
+-rwxr-xr-x root root 243208 ./usr/bin/make
+-rwxr-xr-x root root 22712 ./usr/bin/makedb
+-rwxr-xr-x root root 34920 ./usr/bin/mcookie
+-rwxr-xr-x root root 55496 ./usr/bin/md5sum.coreutils
+lrwxrwxrwx root root 25 ./usr/bin/md5sum -> /usr/bin/md5sum.coreutils
+-rwxr-xr-x root root 14304 ./usr/bin/mesg.sysvinit
+lrwxrwxrwx root root 22 ./usr/bin/mesg -> /usr/bin/mesg.sysvinit
+-rwxr-xr-x root root 14376 ./usr/bin/mesg.util-linux
+lrwxrwxrwx root root 19 ./usr/bin/microcom -> /bin/busybox.nosuid
+-rwxr-xr-x root root 1102 ./usr/bin/mk_cmds
+-rwxr-xr-x root root 47272 ./usr/bin/mkfifo.coreutils
+lrwxrwxrwx root root 25 ./usr/bin/mkfifo -> /usr/bin/mkfifo.coreutils
+-rwxr-xr-x root root 523456 ./usr/bin/mkfs.btrfs
+-rwxr-xr-x root root 55464 ./usr/bin/mktemp.coreutils
+-rwxr-xr-x root root 34856 ./usr/bin/namei
+lrwxrwxrwx root root 19 ./usr/bin/nc -> /bin/busybox.nosuid
+-rwxr-xr-x root root 173 ./usr/bin/ncurses5-config
+-rwxr-xr-x root root 173 ./usr/bin/ncurses6-config
+-rwxr-xr-x root root 175 ./usr/bin/ncursesw5-config
+-rwxr-xr-x root root 175 ./usr/bin/ncursesw6-config
+-rwsr-xr-x root root 41136 ./usr/bin/newgidmap
+-rwsr-xr-x root root 40312 ./usr/bin/newgrp.shadow
+lrwxrwxrwx root root 22 ./usr/bin/newgrp -> /usr/bin/newgrp.shadow
+-rwsr-xr-x root root 37040 ./usr/bin/newuidmap
+-rwxr-xr-x root root 47272 ./usr/bin/nice.coreutils
+-rwxr-xr-x root root 117000 ./usr/bin/nl.coreutils
+lrwxrwxrwx root root 21 ./usr/bin/nl -> /usr/bin/nl.coreutils
+lrwxrwxrwx root root 29 ./usr/bin/nm -> /usr/bin/x86_64-poky-linux-nm
+-rwxr-xr-x root root 47272 ./usr/bin/nohup.coreutils
+lrwxrwxrwx root root 24 ./usr/bin/nohup -> /usr/bin/nohup.coreutils
+-rwxr-xr-x root root 47272 ./usr/bin/nproc.coreutils
+lrwxrwxrwx root root 24 ./usr/bin/nproc -> /usr/bin/nproc.coreutils
+lrwxrwxrwx root root 27 ./usr/bin/nsenter -> /usr/bin/nsenter.util-linux
+-rwxr-xr-x root root 35072 ./usr/bin/nsenter.util-linux
+lrwxrwxrwx root root 19 ./usr/bin/nslookup -> /bin/busybox.nosuid
+-rwxr-xr-x root root 71904 ./usr/bin/numfmt
+lrwxrwxrwx root root 34 ./usr/bin/objcopy -> /usr/bin/x86_64-poky-linux-objcopy
+lrwxrwxrwx root root 34 ./usr/bin/objdump -> /usr/bin/x86_64-poky-linux-objdump
+-rwxr-xr-x root root 80072 ./usr/bin/od.coreutils
+lrwxrwxrwx root root 21 ./usr/bin/od -> /usr/bin/od.coreutils
+-rwxr-xr-x root root 736944 ./usr/bin/openssl
+lrwxrwxrwx root root 19 ./usr/bin/openvt -> /bin/busybox.nosuid
+-rwsr-xr-x root root 67760 ./usr/bin/passwd.shadow
+lrwxrwxrwx root root 22 ./usr/bin/passwd -> /usr/bin/passwd.shadow
+-rwxr-xr-x root root 47304 ./usr/bin/paste.coreutils
+lrwxrwxrwx root root 24 ./usr/bin/paste -> /usr/bin/paste.coreutils
+lrwxrwxrwx root root 19 ./usr/bin/patch -> /bin/busybox.nosuid
+-rwxr-xr-x root root 43176 ./usr/bin/pathchk.coreutils
+lrwxrwxrwx root root 26 ./usr/bin/pathchk -> /usr/bin/pathchk.coreutils
+-rwxr-xr-x root root 14520 ./usr/bin/pcprofiledump
+-rwxr-xr-x root root 165 ./usr/bin/pcre-config
+-rwxr-xr-x root root 14288 ./usr/bin/perl
+-rwxr-xr-x root root 30776 ./usr/bin/pgrep.procps
+lrwxrwxrwx root root 21 ./usr/bin/pgrep -> /usr/bin/pgrep.procps
+-rwxr-xr-x root root 47304 ./usr/bin/pinky.coreutils
+lrwxrwxrwx root root 24 ./usr/bin/pinky -> /usr/bin/pinky.coreutils
+-rwxr-xr-x root root 30776 ./usr/bin/pkill.procps
+lrwxrwxrwx root root 21 ./usr/bin/pkill -> /usr/bin/pkill.procps
+-rwxr-xr-x root root 22712 ./usr/bin/pldd
+-rwxr-xr-x root root 34872 ./usr/bin/pmap.procps
+lrwxrwxrwx root root 20 ./usr/bin/pmap -> /usr/bin/pmap.procps
+-rwxr-xr-x root root 84232 ./usr/bin/pr.coreutils
+-rwxr-xr-x root root 43176 ./usr/bin/printenv.coreutils
+-rwxr-xr-x root root 63648 ./usr/bin/printf.coreutils
+lrwxrwxrwx root root 25 ./usr/bin/printf -> /usr/bin/printf.coreutils
+-rwxr-xr-x root root 39480 ./usr/bin/prlimit
+-rwxr-xr-x root root 80288 ./usr/bin/procan
+lrwxrwxrwx root root 21 ./usr/bin/pr -> /usr/bin/pr.coreutils
+-rwxr-xr-x root root 145640 ./usr/bin/ptx.coreutils
+lrwxrwxrwx root root 22 ./usr/bin/ptx -> /usr/bin/ptx.coreutils
+-rwxr-xr-x root root 14376 ./usr/bin/pwdx.procps
+lrwxrwxrwx root root 20 ./usr/bin/pwdx -> /usr/bin/pwdx.procps
+-rwxr-xr-x root root 14296 ./usr/bin/python3.8
+-rwxr-xr-x root root 2114 ./usr/bin/python3.8-config-lib
+lrwxrwxrwx root root 29 ./usr/bin/python3.8-config -> /usr/bin/python3.8-config-lib
+lrwxrwxrwx root root 16 ./usr/bin/python3-config -> python3.8-config
+lrwxrwxrwx root root 9 ./usr/bin/python3 -> python3.8
+lrwxrwxrwx root root 33 ./usr/bin/ranlib -> /usr/bin/x86_64-poky-linux-ranlib
+-rwxr-xr-x root root 14296 ./usr/bin/readbootlog
+lrwxrwxrwx root root 34 ./usr/bin/readelf -> /usr/bin/x86_64-poky-linux-readelf
+-rwxr-xr-x root root 55464 ./usr/bin/readlink.coreutils
+lrwxrwxrwx root root 27 ./usr/bin/readlink -> /usr/bin/readlink.coreutils
+-rwxr-xr-x root root 55496 ./usr/bin/realpath.coreutils
+lrwxrwxrwx root root 27 ./usr/bin/realpath -> /usr/bin/realpath.coreutils
+-rwxr-xr-x root root 22560 ./usr/bin/rename
+lrwxrwxrwx root root 26 ./usr/bin/renice -> /usr/bin/renice.util-linux
+-rwxr-xr-x root root 14384 ./usr/bin/renice.util-linux
+lrwxrwxrwx root root 19 ./usr/bin/reset -> /bin/busybox.nosuid
+lrwxrwxrwx root root 19 ./usr/bin/resize -> /bin/busybox.nosuid
+lrwxrwxrwx root root 23 ./usr/bin/rev -> /usr/bin/rev.util-linux
+-rwxr-xr-x root root 14376 ./usr/bin/rev.util-linux
+-rwxr-xr-x root root 43176 ./usr/bin/runcon.coreutils
+lrwxrwxrwx root root 25 ./usr/bin/runcon -> /usr/bin/runcon.coreutils
+-rwxr-xr-x root root 67624 ./usr/bin/script
+-rwxr-xr-x root root 55336 ./usr/bin/scriptlive
+-rwxr-xr-x root root 43056 ./usr/bin/scriptreplay
+-rwxr-xr-x root root 51264 ./usr/bin/sdiff
+-rwxr-xr-x root root 63656 ./usr/bin/seq.coreutils
+lrwxrwxrwx root root 22 ./usr/bin/seq -> /usr/bin/seq.coreutils
+-rwxr-xr-x root root 26936 ./usr/bin/setarch
+-rwxr-xr-x root root 39568 ./usr/bin/setfacl
+-rwxr-xr-x root root 18696 ./usr/bin/setfattr.attr
+lrwxrwxrwx root root 22 ./usr/bin/setfattr -> /usr/bin/setfattr.attr
+lrwxrwxrwx root root 27 ./usr/bin/setpriv -> /usr/bin/setpriv.util-linux
+-rwxr-xr-x root root 47160 ./usr/bin/setpriv.util-linux
+lrwxrwxrwx root root 26 ./usr/bin/setsid -> /usr/bin/setsid.util-linux
+-rwxr-xr-x root root 14384 ./usr/bin/setsid.util-linux
+-rwxr-xr-x root root 47144 ./usr/bin/setterm
+lrwxrwxrwx root root 13 ./usr/bin/sg -> newgrp.shadow
+-rwxr-xr-x root root 59592 ./usr/bin/sha1sum.coreutils
+lrwxrwxrwx root root 26 ./usr/bin/sha1sum -> /usr/bin/sha1sum.coreutils
+-rwxr-xr-x root root 67784 ./usr/bin/sha224sum.coreutils
+lrwxrwxrwx root root 28 ./usr/bin/sha224sum -> /usr/bin/sha224sum.coreutils
+-rwxr-xr-x root root 67784 ./usr/bin/sha256sum.coreutils
+lrwxrwxrwx root root 28 ./usr/bin/sha256sum -> /usr/bin/sha256sum.coreutils
+-rwxr-xr-x root root 71880 ./usr/bin/sha384sum.coreutils
+lrwxrwxrwx root root 28 ./usr/bin/sha384sum -> /usr/bin/sha384sum.coreutils
+-rwxr-xr-x root root 71880 ./usr/bin/sha512sum.coreutils
+lrwxrwxrwx root root 28 ./usr/bin/sha512sum -> /usr/bin/sha512sum.coreutils
+-rwxr-xr-x root root 67784 ./usr/bin/shred.coreutils
+lrwxrwxrwx root root 24 ./usr/bin/shred -> /usr/bin/shred.coreutils
+-rwxr-xr-x root root 63656 ./usr/bin/shuf.coreutils
+lrwxrwxrwx root root 23 ./usr/bin/shuf -> /usr/bin/shuf.coreutils
+lrwxrwxrwx root root 31 ./usr/bin/size -> /usr/bin/x86_64-poky-linux-size
+-rwxr-xr-x root root 30768 ./usr/bin/skill.procps
+lrwxrwxrwx root root 21 ./usr/bin/skill -> /usr/bin/skill.procps
+-rwxr-xr-x root root 22568 ./usr/bin/slabtop
+-rwxr-xr-x root root 30768 ./usr/bin/snice.procps
+lrwxrwxrwx root root 21 ./usr/bin/snice -> /usr/bin/snice.procps
+-rwxr-xr-x root root 380104 ./usr/bin/socat
+-rwxr-xr-x root root 117200 ./usr/bin/sort.coreutils
+lrwxrwxrwx root root 23 ./usr/bin/sort -> /usr/bin/sort.coreutils
+-rwxr-xr-x root root 64128 ./usr/bin/split.coreutils
+lrwxrwxrwx root root 24 ./usr/bin/split -> /usr/bin/split.coreutils
+-rwxr-xr-x root root 30896 ./usr/bin/sprof
+-rwxr-xr-x root root 63648 ./usr/bin/stdbuf
+lrwxrwxrwx root root 34 ./usr/bin/strings -> /usr/bin/x86_64-poky-linux-strings
+lrwxrwxrwx root root 32 ./usr/bin/strip -> /usr/bin/x86_64-poky-linux-strip
+-rwxr-xr-x root root 51376 ./usr/bin/sum.coreutils
+lrwxrwxrwx root root 22 ./usr/bin/sum -> /usr/bin/sum.coreutils
+-rwxr-xr-x root root 112808 ./usr/bin/tac.coreutils
+lrwxrwxrwx root root 22 ./usr/bin/tac -> /usr/bin/tac.coreutils
+-rwxr-xr-x root root 80104 ./usr/bin/tail.coreutils
+lrwxrwxrwx root root 23 ./usr/bin/tail -> /usr/bin/tail.coreutils
+lrwxrwxrwx root root 27 ./usr/bin/taskset -> /usr/bin/taskset.util-linux
+-rwxr-xr-x root root 34864 ./usr/bin/taskset.util-linux
+-rwxr-xr-x root root 47304 ./usr/bin/tee.coreutils
+lrwxrwxrwx root root 22 ./usr/bin/tee -> /usr/bin/tee.coreutils
+lrwxrwxrwx root root 19 ./usr/bin/telnet -> /bin/busybox.nosuid
+-rwxr-xr-x root root 59544 ./usr/bin/test.coreutils
+lrwxrwxrwx root root 23 ./usr/bin/test -> /usr/bin/test.coreutils
+lrwxrwxrwx root root 19 ./usr/bin/tftp -> /bin/busybox.nosuid
+lrwxrwxrwx root root 19 ./usr/bin/time -> /bin/busybox.nosuid
+-rwxr-xr-x root root 51840 ./usr/bin/timeout.coreutils
+lrwxrwxrwx root root 26 ./usr/bin/timeout -> /usr/bin/timeout.coreutils
+-rwxr-xr-x root root 22576 ./usr/bin/tload
+-rwxr-xr-x root root 124784 ./usr/bin/top.procps
+lrwxrwxrwx root root 19 ./usr/bin/top -> /usr/bin/top.procps
+-rwxr-xr-x root root 22512 ./usr/bin/tput
+lrwxrwxrwx root root 17 ./usr/bin/traceroute -> /bin/busybox.suid
+-rwxr-xr-x root root 55464 ./usr/bin/tr.coreutils
+-rwxr-xr-x root root 47272 ./usr/bin/truncate.coreutils
+lrwxrwxrwx root root 27 ./usr/bin/truncate -> /usr/bin/truncate.coreutils
+lrwxrwxrwx root root 21 ./usr/bin/tr -> /usr/bin/tr.coreutils
+lrwxrwxrwx root root 19 ./usr/bin/ts -> /bin/busybox.nosuid
+-rwxr-xr-x root root 30680 ./usr/bin/tset
+-rwxr-xr-x root root 59560 ./usr/bin/tsort.coreutils
+lrwxrwxrwx root root 24 ./usr/bin/tsort -> /usr/bin/tsort.coreutils
+-rwxr-xr-x root root 43176 ./usr/bin/tty.coreutils
+lrwxrwxrwx root root 22 ./usr/bin/tty -> /usr/bin/tty.coreutils
+-rwxr-xr-x root root 354584 ./usr/bin/udevadm
+-rwxr-xr-x root root 22560 ./usr/bin/ul
+lrwxrwxrwx root root 7 ./usr/bin/uname26 -> setarch
+-rwxr-xr-x root root 47304 ./usr/bin/unexpand.coreutils
+lrwxrwxrwx root root 27 ./usr/bin/unexpand -> /usr/bin/unexpand.coreutils
+-rwxr-xr-x root root 55496 ./usr/bin/uniq.coreutils
+lrwxrwxrwx root root 23 ./usr/bin/uniq -> /usr/bin/uniq.coreutils
+-rwxr-xr-x root root 43176 ./usr/bin/unlink.coreutils
+lrwxrwxrwx root root 25 ./usr/bin/unlink -> /usr/bin/unlink.coreutils
+lrwxrwxrwx root root 18 ./usr/bin/unlzma -> /usr/bin/unlzma.xz
+lrwxrwxrwx root root 5 ./usr/bin/unlzma.xz -> xz.xz
+lrwxrwxrwx root root 27 ./usr/bin/unshare -> /usr/bin/unshare.util-linux
+-rwxr-xr-x root root 39176 ./usr/bin/unshare.util-linux
+lrwxrwxrwx root root 16 ./usr/bin/unxz -> /usr/bin/unxz.xz
+lrwxrwxrwx root root 5 ./usr/bin/unxz.xz -> xz.xz
+-rwxr-xr-x root root 88152 ./usr/bin/unzipsfx
+-rwxr-xr-x root root 186472 ./usr/bin/unzip.unzip
+lrwxrwxrwx root root 20 ./usr/bin/unzip -> /usr/bin/unzip.unzip
+-rwxr-xr-x root root 4678 ./usr/bin/update-alternatives
+-rwxr-xr-x root root 9076 ./usr/bin/updatedb
+-rwxr-xr-x root root 59584 ./usr/bin/update-mime-database
+-rwxr-xr-x root root 59560 ./usr/bin/uptime.coreutils
+-rwxr-xr-x root root 14376 ./usr/bin/uptime.procps
+lrwxrwxrwx root root 22 ./usr/bin/uptime -> /usr/bin/uptime.procps
+-rwxr-xr-x root root 43176 ./usr/bin/users.coreutils
+lrwxrwxrwx root root 24 ./usr/bin/users -> /usr/bin/users.coreutils
+lrwxrwxrwx root root 27 ./usr/bin/[ -> /usr/bin/lbracket.coreutils
+-rwxr-xr-x root root 18400 ./usr/bin/utmpdump.sysvinit
+lrwxrwxrwx root root 26 ./usr/bin/utmpdump -> /usr/bin/utmpdump.sysvinit
+-rwxr-xr-x root root 30768 ./usr/bin/utmpdump.util-linux
+-rwxr-xr-x root root 14368 ./usr/bin/uuidgen
+-rwxr-xr-x root root 38952 ./usr/bin/uuidparse
+-rwxr-xr-x root root 162448 ./usr/bin/vdir.coreutils
+lrwxrwxrwx root root 23 ./usr/bin/vdir -> /usr/bin/vdir.coreutils
+lrwxrwxrwx root root 17 ./usr/bin/vlock -> /bin/busybox.suid
+-rwxr-xr-x root root 38968 ./usr/bin/vmstat
+-rwxr-xr-x root root 18392 ./usr/bin/wall.sysvinit
+lrwxrwxrwx root root 22 ./usr/bin/wall -> /usr/bin/wall.sysvinit
+-rwxr-xr-x root root 34864 ./usr/bin/wall.util-linux
+-rwxr-xr-x root root 51248 ./usr/bin/wayland-scanner
+-rwxr-xr-x root root 55472 ./usr/bin/wc.coreutils
+lrwxrwxrwx root root 21 ./usr/bin/wc -> /usr/bin/wc.coreutils
+-rwxr-xr-x root root 63552 ./usr/bin/wdctl
+lrwxrwxrwx root root 19 ./usr/bin/wget -> /bin/busybox.nosuid
+-rwxr-xr-x root root 31176 ./usr/bin/whereis
+lrwxrwxrwx root root 20 ./usr/bin/which -> /usr/bin/which.which
+-rwxr-xr-x root root 31280 ./usr/bin/which.which
+-rwxr-xr-x root root 43176 ./usr/bin/whoami.coreutils
+lrwxrwxrwx root root 25 ./usr/bin/whoami -> /usr/bin/whoami.coreutils
+-rwxr-xr-x root root 63688 ./usr/bin/who.coreutils
+lrwxrwxrwx root root 22 ./usr/bin/who -> /usr/bin/who.coreutils
+-rwxr-xr-x root root 22568 ./usr/bin/w.procps
+-rwxr-xr-x root root 22560 ./usr/bin/write
+lrwxrwxrwx root root 17 ./usr/bin/w -> /usr/bin/w.procps
+-rwxr-xr-x root root 31304 ./usr/bin/x86_64-poky-linux-addr2line
+-rwxr-xr-x root root 63784 ./usr/bin/x86_64-poky-linux-ar
+-rwxr-xr-x root root 737584 ./usr/bin/x86_64-poky-linux-as
+-rwxr-xr-x root root 30776 ./usr/bin/x86_64-poky-linux-c++filt
+-rwxr-xr-x root root 2058648 ./usr/bin/x86_64-poky-linux-dwp
+-rwxr-xr-x root root 39320 ./usr/bin/x86_64-poky-linux-elfedit
+-rwxr-xr-x root root 102056 ./usr/bin/x86_64-poky-linux-gprof
+-rwxr-xr-x root root 1711488 ./usr/bin/x86_64-poky-linux-ld
+-rwxr-xr-x root root 1711488 ./usr/bin/x86_64-poky-linux-ld.bfd
+-rwxr-xr-x root root 2316464 ./usr/bin/x86_64-poky-linux-ld.gold
+-rwxr-xr-x root root 48344 ./usr/bin/x86_64-poky-linux-nm
+-rwxr-xr-x root root 190736 ./usr/bin/x86_64-poky-linux-objcopy
+-rwxr-xr-x root root 512664 ./usr/bin/x86_64-poky-linux-objdump
+-rwxr-xr-x root root 63824 ./usr/bin/x86_64-poky-linux-ranlib
+-rwxr-xr-x root root 670432 ./usr/bin/x86_64-poky-linux-readelf
+-rwxr-xr-x root root 35136 ./usr/bin/x86_64-poky-linux-size
+-rwxr-xr-x root root 31176 ./usr/bin/x86_64-poky-linux-strings
+-rwxr-xr-x root root 190736 ./usr/bin/x86_64-poky-linux-strip
+lrwxrwxrwx root root 7 ./usr/bin/x86_64 -> setarch
+-rwxr-xr-x root root 75976 ./usr/bin/xargs.findutils
+lrwxrwxrwx root root 24 ./usr/bin/xargs -> /usr/bin/xargs.findutils
+-rwxr-xr-x root root 16982 ./usr/bin/xkeystone
+-rwxr-xr-x root root 165 ./usr/bin/xml2-config
+-rwxr-xr-x root root 63544 ./usr/bin/xrandr
+lrwxrwxrwx root root 17 ./usr/bin/xzcat -> /usr/bin/xzcat.xz
+lrwxrwxrwx root root 5 ./usr/bin/xzcat.xz -> xz.xz
+lrwxrwxrwx root root 6 ./usr/bin/xzcmp -> xzdiff
+-rwxr-xr-x root root 14376 ./usr/bin/xzdec
+-rwxr-xr-x root root 6633 ./usr/bin/xzdiff
+lrwxrwxrwx root root 6 ./usr/bin/xzegrep -> xzgrep
+lrwxrwxrwx root root 6 ./usr/bin/xzfgrep -> xzgrep
+-rwxr-xr-x root root 5630 ./usr/bin/xzgrep
+-rwxr-xr-x root root 1799 ./usr/bin/xzless
+-rwxr-xr-x root root 2162 ./usr/bin/xzmore
+lrwxrwxrwx root root 14 ./usr/bin/xz -> /usr/bin/xz.xz
+-rwxr-xr-x root root 80184 ./usr/bin/xz.xz
+-rwxr-xr-x root root 4184 ./usr/bin/yacc
+-rwxr-xr-x root root 43176 ./usr/bin/yes.coreutils
+lrwxrwxrwx root root 22 ./usr/bin/yes -> /usr/bin/yes.coreutils
+-rwxr-xr-x root root 212088 ./usr/bin/zip
+-rwxr-xr-x root root 97872 ./usr/bin/zipcloak
+-rwxr-xr-x root root 2953 ./usr/bin/zipgrep
+-rwxr-xr-x root root 186472 ./usr/bin/zipinfo
+-rwxr-xr-x root root 89448 ./usr/bin/zipnote
+-rwxr-xr-x root root 89456 ./usr/bin/zipsplit
+drwxr-xr-x root root 4096 ./usr/games
+drwxr-xr-x root root 12288 ./usr/include
+drwxr-xr-x root root 4096 ./usr/include/acl
+-rw-r--r-- root root 2611 ./usr/include/acl/libacl.h
+-rw-r--r-- root root 7457 ./usr/include/aio.h
+-rw-r--r-- root root 2032 ./usr/include/aliases.h
+-rw-r--r-- root root 1204 ./usr/include/alloca.h
+-rw-r--r-- root root 14130 ./usr/include/ansidecl.h
+-rw-r--r-- root root 4351 ./usr/include/a.out.h
+-rw-r--r-- root root 25473 ./usr/include/argp.h
+-rw-r--r-- root root 6051 ./usr/include/argz.h
+-rw-r--r-- root root 1731 ./usr/include/ar.h
+drwxr-xr-x root root 4096 ./usr/include/arpa
+-rw-r--r-- root root 3432 ./usr/include/arpa/ftp.h
+-rw-r--r-- root root 4277 ./usr/include/arpa/inet.h
+-rw-r--r-- root root 7041 ./usr/include/arpa/nameser_compat.h
+-rw-r--r-- root root 14195 ./usr/include/arpa/nameser.h
+-rw-r--r-- root root 10263 ./usr/include/arpa/telnet.h
+-rw-r--r-- root root 3051 ./usr/include/arpa/tftp.h
+drwxr-xr-x root root 4096 ./usr/include/asm
+-rw-r--r-- root root 756 ./usr/include/asm/a.out.h
+-rw-r--r-- root root 546 ./usr/include/asm/auxvec.h
+-rw-r--r-- root root 321 ./usr/include/asm/bitsperlong.h
+-rw-r--r-- root root 323 ./usr/include/asm/boot.h
+-rw-r--r-- root root 7757 ./usr/include/asm/bootparam.h
+-rw-r--r-- root root 40 ./usr/include/asm/bpf_perf_event.h
+-rw-r--r-- root root 200 ./usr/include/asm/byteorder.h
+-rw-r--r-- root root 3285 ./usr/include/asm/debugreg.h
+-rw-r--r-- root root 2579 ./usr/include/asm/e820.h
+-rw-r--r-- root root 31 ./usr/include/asm/errno.h
+-rw-r--r-- root root 31 ./usr/include/asm/fcntl.h
+drwxr-xr-x root root 4096 ./usr/include/asm-generic
+-rw-r--r-- root root 218 ./usr/include/asm-generic/auxvec.h
+-rw-r--r-- root root 564 ./usr/include/asm-generic/bitsperlong.h
+-rw-r--r-- root root 238 ./usr/include/asm-generic/bpf_perf_event.h
+-rw-r--r-- root root 1612 ./usr/include/asm-generic/errno-base.h
+-rw-r--r-- root root 5648 ./usr/include/asm-generic/errno.h
+-rw-r--r-- root root 5423 ./usr/include/asm-generic/fcntl.h
+-rw-r--r-- root root 1740 ./usr/include/asm-generic/hugetlb_encode.h
+-rw-r--r-- root root 718 ./usr/include/asm-generic/int-l64.h
+-rw-r--r-- root root 864 ./usr/include/asm-generic/int-ll64.h
+-rw-r--r-- root root 3478 ./usr/include/asm-generic/ioctl.h
+-rw-r--r-- root root 3987 ./usr/include/asm-generic/ioctls.h
+-rw-r--r-- root root 1003 ./usr/include/asm-generic/ipcbuf.h
+-rw-r--r-- root root 96 ./usr/include/asm-generic/kvm_para.h
+-rw-r--r-- root root 3417 ./usr/include/asm-generic/mman-common.h
+-rw-r--r-- root root 740 ./usr/include/asm-generic/mman.h
+-rw-r--r-- root root 1618 ./usr/include/asm-generic/msgbuf.h
+-rw-r--r-- root root 353 ./usr/include/asm-generic/param.h
+-rw-r--r-- root root 878 ./usr/include/asm-generic/poll.h
+-rw-r--r-- root root 2331 ./usr/include/asm-generic/posix_types.h
+-rw-r--r-- root root 1872 ./usr/include/asm-generic/resource.h
+-rw-r--r-- root root 1550 ./usr/include/asm-generic/sembuf.h
+-rw-r--r-- root root 190 ./usr/include/asm-generic/setup.h
+-rw-r--r-- root root 1837 ./usr/include/asm-generic/shmbuf.h
+-rw-r--r-- root root 9969 ./usr/include/asm-generic/siginfo.h
+-rw-r--r-- root root 800 ./usr/include/asm-generic/signal-defs.h
+-rw-r--r-- root root 2709 ./usr/include/asm-generic/signal.h
+-rw-r--r-- root root 3538 ./usr/include/asm-generic/socket.h
+-rw-r--r-- root root 447 ./usr/include/asm-generic/sockios.h
+-rw-r--r-- root root 1839 ./usr/include/asm-generic/statfs.h
+-rw-r--r-- root root 2633 ./usr/include/asm-generic/stat.h
+-rw-r--r-- root root 502 ./usr/include/asm-generic/swab.h
+-rw-r--r-- root root 4716 ./usr/include/asm-generic/termbits.h
+-rw-r--r-- root root 1377 ./usr/include/asm-generic/termios.h
+-rw-r--r-- root root 233 ./usr/include/asm-generic/types.h
+-rw-r--r-- root root 357 ./usr/include/asm-generic/ucontext.h
+-rw-r--r-- root root 30377 ./usr/include/asm-generic/unistd.h
+-rw-r--r-- root root 69 ./usr/include/asm/hw_breakpoint.h
+-rw-r--r-- root root 198 ./usr/include/asm/hwcap2.h
+-rw-r--r-- root root 31 ./usr/include/asm/ioctl.h
+-rw-r--r-- root root 32 ./usr/include/asm/ioctls.h
+-rw-r--r-- root root 32 ./usr/include/asm/ipcbuf.h
+-rw-r--r-- root root 854 ./usr/include/asm/ist.h
+-rw-r--r-- root root 9244 ./usr/include/asm/kvm.h
+-rw-r--r-- root root 3341 ./usr/include/asm/kvm_para.h
+-rw-r--r-- root root 388 ./usr/include/asm/kvm_perf.h
+-rw-r--r-- root root 1306 ./usr/include/asm/ldt.h
+-rw-r--r-- root root 1688 ./usr/include/asm/mce.h
+-rw-r--r-- root root 1002 ./usr/include/asm/mman.h
+-rw-r--r-- root root 1053 ./usr/include/asm/msgbuf.h
+-rw-r--r-- root root 346 ./usr/include/asm/msr.h
+-rw-r--r-- root root 4225 ./usr/include/asm/mtrr.h
+-rw-r--r-- root root 31 ./usr/include/asm/param.h
+-rw-r--r-- root root 1403 ./usr/include/asm/perf_regs.h
+-rw-r--r-- root root 30 ./usr/include/asm/poll.h
+-rw-r--r-- root root 765 ./usr/include/asm/posix_types_32.h
+-rw-r--r-- root root 609 ./usr/include/asm/posix_types_64.h
+-rw-r--r-- root root 224 ./usr/include/asm/posix_types.h
+-rw-r--r-- root root 581 ./usr/include/asm/posix_types_x32.h
+-rw-r--r-- root root 418 ./usr/include/asm/prctl.h
+-rw-r--r-- root root 6623 ./usr/include/asm/processor-flags.h
+-rw-r--r-- root root 2037 ./usr/include/asm/ptrace-abi.h
+-rw-r--r-- root root 1495 ./usr/include/asm/ptrace.h
+-rw-r--r-- root root 34 ./usr/include/asm/resource.h
+-rw-r--r-- root root 1045 ./usr/include/asm/sembuf.h
+-rw-r--r-- root root 6 ./usr/include/asm/setup.h
+-rw-r--r-- root root 1258 ./usr/include/asm/shmbuf.h
+-rw-r--r-- root root 271 ./usr/include/asm/sigcontext32.h
+-rw-r--r-- root root 9724 ./usr/include/asm/sigcontext.h
+-rw-r--r-- root root 422 ./usr/include/asm/siginfo.h
+-rw-r--r-- root root 2901 ./usr/include/asm/signal.h
+-rw-r--r-- root root 32 ./usr/include/asm/socket.h
+-rw-r--r-- root root 33 ./usr/include/asm/sockios.h
+-rw-r--r-- root root 416 ./usr/include/asm/statfs.h
+-rw-r--r-- root root 3131 ./usr/include/asm/stat.h
+-rw-r--r-- root root 7068 ./usr/include/asm/svm.h
+-rw-r--r-- root root 724 ./usr/include/asm/swab.h
+-rw-r--r-- root root 34 ./usr/include/asm/termbits.h
+-rw-r--r-- root root 33 ./usr/include/asm/termios.h
+-rw-r--r-- root root 31 ./usr/include/asm/types.h
+-rw-r--r-- root root 2117 ./usr/include/asm/ucontext.h
+-rw-r--r-- root root 11475 ./usr/include/asm/unistd_32.h
+-rw-r--r-- root root 9286 ./usr/include/asm/unistd_64.h
+-rw-r--r-- root root 361 ./usr/include/asm/unistd.h
+-rw-r--r-- root root 16367 ./usr/include/asm/unistd_x32.h
+-rw-r--r-- root root 3118 ./usr/include/asm/vm86.h
+-rw-r--r-- root root 7032 ./usr/include/asm/vmx.h
+-rw-r--r-- root root 263 ./usr/include/asm/vsyscall.h
+-rw-r--r-- root root 4562 ./usr/include/assert.h
+drwxr-xr-x root root 4096 ./usr/include/attr
+-rw-r--r-- root root 8010 ./usr/include/attr/attributes.h
+-rw-r--r-- root root 1569 ./usr/include/attr/error_context.h
+-rw-r--r-- root root 1411 ./usr/include/attr/libattr.h
+drwxr-xr-x root root 4096 ./usr/include/bash
+-rw-r--r-- root root 2225 ./usr/include/bash/alias.h
+-rw-r--r-- root root 3561 ./usr/include/bash/arrayfunc.h
+-rw-r--r-- root root 4172 ./usr/include/bash/array.h
+-rw-r--r-- root root 2302 ./usr/include/bash/assoc.h
+-rw-r--r-- root root 1262 ./usr/include/bash/bashansi.h
+-rw-r--r-- root root 1462 ./usr/include/bash/bashintl.h
+-rw-r--r-- root root 1646 ./usr/include/bash/bashjmp.h
+-rw-r--r-- root root 1086 ./usr/include/bash/bashtypes.h
+drwxr-xr-x root root 4096 ./usr/include/bash/builtins
+-rw-r--r-- root root 1263 ./usr/include/bash/builtins/bashgetopt.h
+-rw-r--r-- root root 6715 ./usr/include/bash/builtins/builtext.h
+-rw-r--r-- root root 8372 ./usr/include/bash/builtins/common.h
+-rw-r--r-- root root 2582 ./usr/include/bash/builtins/getopt.h
+-rw-r--r-- root root 2373 ./usr/include/bash/builtins.h
+-rw-r--r-- root root 15490 ./usr/include/bash/command.h
+-rw-r--r-- root root 6514 ./usr/include/bash/config-bot.h
+-rw-r--r-- root root 32166 ./usr/include/bash/config.h
+-rw-r--r-- root root 7436 ./usr/include/bash/config-top.h
+-rw-r--r-- root root 1709 ./usr/include/bash/conftypes.h
+-rw-r--r-- root root 1397 ./usr/include/bash/dispose_cmd.h
+-rw-r--r-- root root 3053 ./usr/include/bash/error.h
+-rw-r--r-- root root 18999 ./usr/include/bash/externs.h
+-rw-r--r-- root root 11828 ./usr/include/bash/general.h
+-rw-r--r-- root root 3036 ./usr/include/bash/hashlib.h
+drwxr-xr-x root root 4096 ./usr/include/bash/include
+-rw-r--r-- root root 1437 ./usr/include/bash/include/ansi_stdlib.h
+-rw-r--r-- root root 4125 ./usr/include/bash/include/chartypes.h
+-rw-r--r-- root root 1581 ./usr/include/bash/include/filecntl.h
+-rw-r--r-- root root 3014 ./usr/include/bash/include/gettext.h
+-rw-r--r-- root root 2113 ./usr/include/bash/include/maxpath.h
+-rw-r--r-- root root 1994 ./usr/include/bash/include/memalloc.h
+-rw-r--r-- root root 3669 ./usr/include/bash/include/ocache.h
+-rw-r--r-- root root 2305 ./usr/include/bash/include/posixdir.h
+-rw-r--r-- root root 1407 ./usr/include/bash/include/posixjmp.h
+-rw-r--r-- root root 4318 ./usr/include/bash/include/posixstat.h
+-rw-r--r-- root root 1509 ./usr/include/bash/include/posixtime.h
+-rw-r--r-- root root 3068 ./usr/include/bash/include/posixwait.h
+-rw-r--r-- root root 4319 ./usr/include/bash/include/shmbchar.h
+-rw-r--r-- root root 13847 ./usr/include/bash/include/shmbutil.h
+-rw-r--r-- root root 3636 ./usr/include/bash/include/shtty.h
+-rw-r--r-- root root 6088 ./usr/include/bash/include/stat-time.h
+-rw-r--r-- root root 2652 ./usr/include/bash/include/stdc.h
+-rw-r--r-- root root 1778 ./usr/include/bash/include/systimes.h
+-rw-r--r-- root root 2890 ./usr/include/bash/include/typemax.h
+-rw-r--r-- root root 2973 ./usr/include/bash/include/unionwait.h
+-rw-r--r-- root root 9640 ./usr/include/bash/jobs.h
+-rw-r--r-- root root 2960 ./usr/include/bash/make_cmd.h
+-rw-r--r-- root root 1208 ./usr/include/bash/pathnames.h
+-rw-r--r-- root root 2541 ./usr/include/bash/quit.h
+-rw-r--r-- root root 5957 ./usr/include/bash/shell.h
+-rw-r--r-- root root 4485 ./usr/include/bash/sig.h
+-rw-r--r-- root root 1544 ./usr/include/bash/siglist.h
+-rw-r--r-- root root 247 ./usr/include/bash/signames.h
+-rw-r--r-- root root 15184 ./usr/include/bash/subst.h
+-rw-r--r-- root root 3544 ./usr/include/bash/syntax.h
+-rw-r--r-- root root 2003 ./usr/include/bash/unwind_prot.h
+-rw-r--r-- root root 17643 ./usr/include/bash/variables.h
+-rw-r--r-- root root 579 ./usr/include/bash/version.h
+-rw-r--r-- root root 1759 ./usr/include/bash/xmalloc.h
+-rw-r--r-- root root 255175 ./usr/include/bfd-64.h
+-rw-r--r-- root root 500 ./usr/include/bfd.h
+-rw-r--r-- root root 35620 ./usr/include/bfdlink.h
+-rw-r--r-- root root 848 ./usr/include/bfd_stdint.h
+drwxr-xr-x root root 4096 ./usr/include/bits
+-rw-r--r-- root root 268 ./usr/include/bits/a.out.h
+-rw-r--r-- root root 1010 ./usr/include/bits/argp-ldbl.h
+-rw-r--r-- root root 2450 ./usr/include/bits/byteswap.h
+-rw-r--r-- root root 4139 ./usr/include/bits/cmathcalls.h
+-rw-r--r-- root root 23709 ./usr/include/bits/confname.h
+-rw-r--r-- root root 4516 ./usr/include/bits/cpu-set.h
+-rw-r--r-- root root 1275 ./usr/include/bits/dirent_ext.h
+-rw-r--r-- root root 1771 ./usr/include/bits/dirent.h
+-rw-r--r-- root root 2521 ./usr/include/bits/dlfcn.h
+-rw-r--r-- root root 426 ./usr/include/bits/elfclass.h
+-rw-r--r-- root root 1905 ./usr/include/bits/endian.h
+-rw-r--r-- root root 273 ./usr/include/bits/endianness-64.h
+-rw-r--r-- root root 548 ./usr/include/bits/endianness.h
+-rw-r--r-- root root 3791 ./usr/include/bits/environments.h
+-rw-r--r-- root root 1071 ./usr/include/bits/epoll.h
+-rw-r--r-- root root 1148 ./usr/include/bits/err-ldbl.h
+-rw-r--r-- root root 1426 ./usr/include/bits/errno.h
+-rw-r--r-- root root 2684 ./usr/include/bits/error.h
+-rw-r--r-- root root 1012 ./usr/include/bits/error-ldbl.h
+-rw-r--r-- root root 1129 ./usr/include/bits/eventfd.h
+-rw-r--r-- root root 5575 ./usr/include/bits/fcntl2.h
+-rw-r--r-- root root 2246 ./usr/include/bits/fcntl.h
+-rw-r--r-- root root 13995 ./usr/include/bits/fcntl-linux.h
+-rw-r--r-- root root 4611 ./usr/include/bits/fenv.h
+-rw-r--r-- root root 190 ./usr/include/bits/fenvinline.h
+-rw-r--r-- root root 4373 ./usr/include/bits/floatn-64.h
+-rw-r--r-- root root 9765 ./usr/include/bits/floatn-common.h
+-rw-r--r-- root root 532 ./usr/include/bits/floatn.h
+-rw-r--r-- root root 1215 ./usr/include/bits/flt-eval-method.h
+-rw-r--r-- root root 1216 ./usr/include/bits/fp-fast.h
+-rw-r--r-- root root 1012 ./usr/include/bits/fp-logb.h
+-rw-r--r-- root root 3667 ./usr/include/bits/getopt_core.h
+-rw-r--r-- root root 3038 ./usr/include/bits/getopt_ext.h
+-rw-r--r-- root root 1810 ./usr/include/bits/getopt_posix.h
+-rw-r--r-- root root 972 ./usr/include/bits/hwcap.h
+-rw-r--r-- root root 1591 ./usr/include/bits/indirect-return.h
+-rw-r--r-- root root 9534 ./usr/include/bits/in.h
+-rw-r--r-- root root 25 ./usr/include/bits/initspin.h
+-rw-r--r-- root root 1080 ./usr/include/bits/inotify.h
+-rw-r--r-- root root 4478 ./usr/include/bits/ioctls.h
+-rw-r--r-- root root 2456 ./usr/include/bits/ioctl-types.h
+-rw-r--r-- root root 1523 ./usr/include/bits/ipc.h
+-rw-r--r-- root root 1745 ./usr/include/bits/ipc-perm.h
+-rw-r--r-- root root 1176 ./usr/include/bits/ipctypes.h
+-rw-r--r-- root root 2479 ./usr/include/bits/iscanonical.h
+-rw-r--r-- root root 3288 ./usr/include/bits/libc-header-start.h
+-rw-r--r-- root root 3004 ./usr/include/bits/libm-simd-decl-stubs.h
+-rw-r--r-- root root 4286 ./usr/include/bits/link.h
+-rw-r--r-- root root 1368 ./usr/include/bits/locale.h
+-rw-r--r-- root root 3185 ./usr/include/bits/local_lim.h
+-rw-r--r-- root root 962 ./usr/include/bits/long-double-64.h
+-rw-r--r-- root root 552 ./usr/include/bits/long-double.h
+-rw-r--r-- root root 13210 ./usr/include/bits/mathcalls.h
+-rw-r--r-- root root 1765 ./usr/include/bits/mathcalls-helper-functions.h
+-rw-r--r-- root root 1312 ./usr/include/bits/mathcalls-narrow.h
+-rw-r--r-- root root 891 ./usr/include/bits/mathdef.h
+-rw-r--r-- root root 337 ./usr/include/bits/mathinline.h
+-rw-r--r-- root root 2308 ./usr/include/bits/math-vector.h
+-rw-r--r-- root root 1309 ./usr/include/bits/mman.h
+-rw-r--r-- root root 4911 ./usr/include/bits/mman-linux.h
+-rw-r--r-- root root 1997 ./usr/include/bits/mman-map-flags-generic.h
+-rw-r--r-- root root 2813 ./usr/include/bits/mman-shared.h
+-rw-r--r-- root root 1047 ./usr/include/bits/monetary-ldbl.h
+-rw-r--r-- root root 2151 ./usr/include/bits/mqueue2.h
+-rw-r--r-- root root 1246 ./usr/include/bits/mqueue.h
+-rw-r--r-- root root 2818 ./usr/include/bits/msq.h
+-rw-r--r-- root root 1283 ./usr/include/bits/msq-pad.h
+-rw-r--r-- root root 1264 ./usr/include/bits/netdb.h
+-rw-r--r-- root root 1433 ./usr/include/bits/param.h
+-rw-r--r-- root root 2937 ./usr/include/bits/poll2.h
+-rw-r--r-- root root 2076 ./usr/include/bits/poll.h
+-rw-r--r-- root root 5189 ./usr/include/bits/posix1_lim.h
+-rw-r--r-- root root 2867 ./usr/include/bits/posix2_lim.h
+-rw-r--r-- root root 5913 ./usr/include/bits/posix_opt.h
+-rw-r--r-- root root 992 ./usr/include/bits/printf-ldbl.h
+-rw-r--r-- root root 963 ./usr/include/bits/procfs-extra.h
+-rw-r--r-- root root 2025 ./usr/include/bits/procfs.h
+-rw-r--r-- root root 1148 ./usr/include/bits/procfs-id.h
+-rw-r--r-- root root 1050 ./usr/include/bits/procfs-prregset.h
+-rw-r--r-- root root 1838 ./usr/include/bits/pthreadtypes-arch.h
+-rw-r--r-- root root 3072 ./usr/include/bits/pthreadtypes.h
+-rw-r--r-- root root 4091 ./usr/include/bits/ptrace-shared.h
+-rw-r--r-- root root 6299 ./usr/include/bits/resource.h
+-rw-r--r-- root root 3947 ./usr/include/bits/sched.h
+-rw-r--r-- root root 1438 ./usr/include/bits/select2.h
+-rw-r--r-- root root 2106 ./usr/include/bits/select.h
+-rw-r--r-- root root 1238 ./usr/include/bits/semaphore.h
+-rw-r--r-- root root 2905 ./usr/include/bits/sem.h
+-rw-r--r-- root root 1019 ./usr/include/bits/sem-pad.h
+-rw-r--r-- root root 1705 ./usr/include/bits/setjmp2.h
+-rw-r--r-- root root 1287 ./usr/include/bits/setjmp.h
+-rw-r--r-- root root 3872 ./usr/include/bits/shm.h
+-rw-r--r-- root root 1106 ./usr/include/bits/shmlba.h
+-rw-r--r-- root root 1668 ./usr/include/bits/shm-pad.h
+-rw-r--r-- root root 2935 ./usr/include/bits/sigaction.h
+-rw-r--r-- root root 4266 ./usr/include/bits/sigcontext.h
+-rw-r--r-- root root 1471 ./usr/include/bits/sigevent-consts.h
+-rw-r--r-- root root 729 ./usr/include/bits/siginfo-arch.h
+-rw-r--r-- root root 204 ./usr/include/bits/siginfo-consts-arch.h
+-rw-r--r-- root root 6855 ./usr/include/bits/siginfo-consts.h
+-rw-r--r-- root root 1285 ./usr/include/bits/signal_ext.h
+-rw-r--r-- root root 1067 ./usr/include/bits/signalfd.h
+-rw-r--r-- root root 4341 ./usr/include/bits/signum-generic.h
+-rw-r--r-- root root 1634 ./usr/include/bits/signum.h
+-rw-r--r-- root root 1168 ./usr/include/bits/sigstack.h
+-rw-r--r-- root root 1692 ./usr/include/bits/sigthread.h
+-rw-r--r-- root root 1514 ./usr/include/bits/sockaddr.h
+-rw-r--r-- root root 3026 ./usr/include/bits/socket2.h
+-rw-r--r-- root root 1318 ./usr/include/bits/socket-constants.h
+-rw-r--r-- root root 12261 ./usr/include/bits/socket.h
+-rw-r--r-- root root 2216 ./usr/include/bits/socket_type.h
+-rw-r--r-- root root 1188 ./usr/include/bits/ss_flags.h
+-rw-r--r-- root root 9040 ./usr/include/bits/stab.def
+-rw-r--r-- root root 1917 ./usr/include/bits/statfs.h
+-rw-r--r-- root root 7620 ./usr/include/bits/stat.h
+-rw-r--r-- root root 3423 ./usr/include/bits/statvfs.h
+-rw-r--r-- root root 2050 ./usr/include/bits/statx-generic.h
+-rw-r--r-- root root 1400 ./usr/include/bits/statx.h
+-rw-r--r-- root root 1037 ./usr/include/bits/stdint-intn.h
+-rw-r--r-- root root 1049 ./usr/include/bits/stdint-uintn.h
+-rw-r--r-- root root 12679 ./usr/include/bits/stdio2.h
+-rw-r--r-- root root 5584 ./usr/include/bits/stdio.h
+-rw-r--r-- root root 2843 ./usr/include/bits/stdio-ldbl.h
+-rw-r--r-- root root 1213 ./usr/include/bits/stdio_lim.h
+-rw-r--r-- root root 1378 ./usr/include/bits/stdlib-bsearch.h
+-rw-r--r-- root root 1115 ./usr/include/bits/stdlib-float.h
+-rw-r--r-- root root 5659 ./usr/include/bits/stdlib.h
+-rw-r--r-- root root 1377 ./usr/include/bits/stdlib-ldbl.h
+-rw-r--r-- root root 4314 ./usr/include/bits/string_fortified.h
+-rw-r--r-- root root 1209 ./usr/include/bits/strings_fortified.h
+-rw-r--r-- root root 1810 ./usr/include/bits/struct_mutex.h
+-rw-r--r-- root root 2027 ./usr/include/bits/struct_rwlock-64.h
+-rw-r--r-- root root 560 ./usr/include/bits/struct_rwlock.h
+-rw-r--r-- root root 44103 ./usr/include/bits/syscall-64.h
+-rw-r--r-- root root 536 ./usr/include/bits/syscall.h
+-rw-r--r-- root root 899 ./usr/include/bits/sysctl.h
+-rw-r--r-- root root 1216 ./usr/include/bits/sys_errlist.h
+-rw-r--r-- root root 1685 ./usr/include/bits/syslog.h
+-rw-r--r-- root root 1206 ./usr/include/bits/syslog-ldbl.h
+-rw-r--r-- root root 1061 ./usr/include/bits/syslog-path.h
+-rw-r--r-- root root 2953 ./usr/include/bits/sysmacros.h
+-rw-r--r-- root root 1824 ./usr/include/bits/termios-baud.h
+-rw-r--r-- root root 1279 ./usr/include/bits/termios-c_cc.h
+-rw-r--r-- root root 1230 ./usr/include/bits/termios-c_cflag.h
+-rw-r--r-- root root 1936 ./usr/include/bits/termios-c_iflag.h
+-rw-r--r-- root root 2594 ./usr/include/bits/termios-c_lflag.h
+-rw-r--r-- root root 2822 ./usr/include/bits/termios-c_oflag.h
+-rw-r--r-- root root 2168 ./usr/include/bits/termios.h
+-rw-r--r-- root root 969 ./usr/include/bits/termios-misc.h
+-rw-r--r-- root root 1433 ./usr/include/bits/termios-struct.h
+-rw-r--r-- root root 1062 ./usr/include/bits/termios-tcflow.h
+-rw-r--r-- root root 3982 ./usr/include/bits/thread-shared-types.h
+-rw-r--r-- root root 1340 ./usr/include/bits/time64.h
+-rw-r--r-- root root 2999 ./usr/include/bits/time.h
+-rw-r--r-- root root 1103 ./usr/include/bits/timerfd.h
+-rw-r--r-- root root 1081 ./usr/include/bits/timesize.h
+-rw-r--r-- root root 4596 ./usr/include/bits/timex.h
+drwxr-xr-x root root 4096 ./usr/include/bits/types
+-rw-r--r-- root root 174 ./usr/include/bits/types/clockid_t.h
+-rw-r--r-- root root 143 ./usr/include/bits/types/clock_t.h
+-rw-r--r-- root root 2725 ./usr/include/bits/types/cookie_io_functions_t.h
+-rw-r--r-- root root 894 ./usr/include/bits/types/error_t.h
+-rw-r--r-- root root 110 ./usr/include/bits/types/__FILE.h
+-rw-r--r-- root root 180 ./usr/include/bits/types/FILE.h
+-rw-r--r-- root root 410 ./usr/include/bits/types/__fpos64_t.h
+-rw-r--r-- root root 381 ./usr/include/bits/types/__fpos_t.h
+-rw-r--r-- root root 8757 ./usr/include/bits/types.h
+-rw-r--r-- root root 3546 ./usr/include/bits/typesizes.h
+-rw-r--r-- root root 1722 ./usr/include/bits/types/__locale_t.h
+-rw-r--r-- root root 983 ./usr/include/bits/types/locale_t.h
+-rw-r--r-- root root 564 ./usr/include/bits/types/__mbstate_t.h
+-rw-r--r-- root root 135 ./usr/include/bits/types/mbstate_t.h
+-rw-r--r-- root root 2009 ./usr/include/bits/types/res_state.h
+-rw-r--r-- root root 272 ./usr/include/bits/types/sig_atomic_t.h
+-rw-r--r-- root root 1204 ./usr/include/bits/types/sigevent_t.h
+-rw-r--r-- root root 3892 ./usr/include/bits/types/siginfo_t.h
+-rw-r--r-- root root 206 ./usr/include/bits/types/__sigset_t.h
+-rw-r--r-- root root 195 ./usr/include/bits/types/sigset_t.h
+-rw-r--r-- root root 1148 ./usr/include/bits/types/__sigval_t.h
+-rw-r--r-- root root 599 ./usr/include/bits/types/sigval_t.h
+-rw-r--r-- root root 1062 ./usr/include/bits/types/stack_t.h
+-rw-r--r-- root root 4104 ./usr/include/bits/types/struct_FILE.h
+-rw-r--r-- root root 1066 ./usr/include/bits/types/struct_iovec.h
+-rw-r--r-- root root 288 ./usr/include/bits/types/struct_itimerspec.h
+-rw-r--r-- root root 274 ./usr/include/bits/types/struct_osockaddr.h
+-rw-r--r-- root root 4121 ./usr/include/bits/types/struct_rusage.h
+-rw-r--r-- root root 1073 ./usr/include/bits/types/struct_sched_param.h
+-rw-r--r-- root root 1073 ./usr/include/bits/types/struct_sigstack.h
+-rw-r--r-- root root 1897 ./usr/include/bits/types/struct_statx.h
+-rw-r--r-- root root 1202 ./usr/include/bits/types/struct_statx_timestamp.h
+-rw-r--r-- root root 728 ./usr/include/bits/types/struct_timespec.h
+-rw-r--r-- root root 287 ./usr/include/bits/types/struct_timeval.h
+-rw-r--r-- root root 760 ./usr/include/bits/types/struct_tm.h
+-rw-r--r-- root root 159 ./usr/include/bits/types/timer_t.h
+-rw-r--r-- root root 138 ./usr/include/bits/types/time_t.h
+-rw-r--r-- root root 796 ./usr/include/bits/types/wint_t.h
+-rw-r--r-- root root 1542 ./usr/include/bits/uintn-identity.h
+-rw-r--r-- root root 1923 ./usr/include/bits/uio-ext.h
+-rw-r--r-- root root 1385 ./usr/include/bits/uio_lim.h
+-rw-r--r-- root root 1613 ./usr/include/bits/unistd_ext.h
+-rw-r--r-- root root 13316 ./usr/include/bits/unistd.h
+-rw-r--r-- root root 4067 ./usr/include/bits/utmp.h
+-rw-r--r-- root root 3578 ./usr/include/bits/utmpx.h
+-rw-r--r-- root root 1213 ./usr/include/bits/utsname.h
+-rw-r--r-- root root 1697 ./usr/include/bits/waitflags.h
+-rw-r--r-- root root 2287 ./usr/include/bits/waitstatus.h
+-rw-r--r-- root root 20506 ./usr/include/bits/wchar2.h
+-rw-r--r-- root root 1906 ./usr/include/bits/wchar.h
+-rw-r--r-- root root 2251 ./usr/include/bits/wchar-ldbl.h
+-rw-r--r-- root root 6307 ./usr/include/bits/wctype-wchar.h
+-rw-r--r-- root root 442 ./usr/include/bits/wordsize.h
+-rw-r--r-- root root 3858 ./usr/include/bits/xopen_lim.h
+drwxr-xr-x root root 4096 ./usr/include/blkid
+-rw-r--r-- root root 15478 ./usr/include/blkid/blkid.h
+drwxr-xr-x root root 4096 ./usr/include/btrfs
+-rw-r--r-- root root 5045 ./usr/include/btrfs/btrfsck.h
+-rw-r--r-- root root 4670 ./usr/include/btrfs/btrfs-list.h
+-rw-r--r-- root root 1095 ./usr/include/btrfs/crc32c.h
+-rw-r--r-- root root 94261 ./usr/include/btrfs/ctree.h
+-rw-r--r-- root root 3524 ./usr/include/btrfs/extent-cache.h
+-rw-r--r-- root root 6444 ./usr/include/btrfs/extent_io.h
+-rw-r--r-- root root 30105 ./usr/include/btrfs/ioctl.h
+-rw-r--r-- root root 10965 ./usr/include/btrfs/kerncompat.h
+-rw-r--r-- root root 14636 ./usr/include/btrfs/list.h
+-rw-r--r-- root root 3343 ./usr/include/btrfs/radix-tree.h
+-rw-r--r-- root root 2024 ./usr/include/btrfs/raid56.h
+-rw-r--r-- root root 3902 ./usr/include/btrfs/rbtree.h
+-rw-r--r-- root root 3090 ./usr/include/btrfs/send.h
+-rw-r--r-- root root 2803 ./usr/include/btrfs/send-stream.h
+-rw-r--r-- root root 3388 ./usr/include/btrfs/send-utils.h
+-rw-r--r-- root root 1223 ./usr/include/btrfs/sizes.h
+-rw-r--r-- root root 23351 ./usr/include/btrfsutil.h
+-rw-r--r-- root root 363 ./usr/include/btrfs/version.h
+-rw-r--r-- root root 1405 ./usr/include/byteswap.h
+-rw-r--r-- root root 6240 ./usr/include/bzlib.h
+drwxr-xr-x root root 4096 ./usr/include/c++
+drwxr-xr-x root root 4096 ./usr/include/c++/10.1.0
+-rw-r--r-- root root 3045 ./usr/include/c++/10.1.0/algorithm
+-rw-r--r-- root root 18236 ./usr/include/c++/10.1.0/any
+-rw-r--r-- root root 13700 ./usr/include/c++/10.1.0/array
+-rw-r--r-- root root 45341 ./usr/include/c++/10.1.0/atomic
+drwxr-xr-x root root 4096 ./usr/include/c++/10.1.0/backward
+-rw-r--r-- root root 10804 ./usr/include/c++/10.1.0/backward/auto_ptr.h
+-rw-r--r-- root root 2491 ./usr/include/c++/10.1.0/backward/backward_warning.h
+-rw-r--r-- root root 7167 ./usr/include/c++/10.1.0/backward/binders.h
+-rw-r--r-- root root 4248 ./usr/include/c++/10.1.0/backward/hash_fun.h
+-rw-r--r-- root root 17822 ./usr/include/c++/10.1.0/backward/hash_map
+-rw-r--r-- root root 17323 ./usr/include/c++/10.1.0/backward/hash_set
+-rw-r--r-- root root 33883 ./usr/include/c++/10.1.0/backward/hashtable.h
+-rw-r--r-- root root 7454 ./usr/include/c++/10.1.0/backward/strstream
+-rw-r--r-- root root 11044 ./usr/include/c++/10.1.0/bit
+drwxr-xr-x root root 4096 ./usr/include/c++/10.1.0/bits
+-rw-r--r-- root root 24547 ./usr/include/c++/10.1.0/bits/algorithmfwd.h
+-rw-r--r-- root root 3293 ./usr/include/c++/10.1.0/bits/allocated_ptr.h
+-rw-r--r-- root root 8984 ./usr/include/c++/10.1.0/bits/allocator.h
+-rw-r--r-- root root 24105 ./usr/include/c++/10.1.0/bits/alloc_traits.h
+-rw-r--r-- root root 51344 ./usr/include/c++/10.1.0/bits/atomic_base.h
+-rw-r--r-- root root 9499 ./usr/include/c++/10.1.0/bits/atomic_futex.h
+-rw-r--r-- root root 2352 ./usr/include/c++/10.1.0/bits/atomic_lockfree_defines.h
+-rw-r--r-- root root 16074 ./usr/include/c++/10.1.0/bits/basic_ios.h
+-rw-r--r-- root root 6083 ./usr/include/c++/10.1.0/bits/basic_ios.tcc
+-rw-r--r-- root root 249154 ./usr/include/c++/10.1.0/bits/basic_string.h
+-rw-r--r-- root root 54513 ./usr/include/c++/10.1.0/bits/basic_string.tcc
+-rw-r--r-- root root 27182 ./usr/include/c++/10.1.0/bits/boost_concept_check.h
+-rw-r--r-- root root 1474 ./usr/include/c++/10.1.0/bits/c++0x_warning.h
+-rw-r--r-- root root 3435 ./usr/include/c++/10.1.0/bits/charconv.h
+-rw-r--r-- root root 28509 ./usr/include/c++/10.1.0/bits/char_traits.h
+-rw-r--r-- root root 25429 ./usr/include/c++/10.1.0/bits/codecvt.h
+-rw-r--r-- root root 3423 ./usr/include/c++/10.1.0/bits/concept_check.h
+-rw-r--r-- root root 12011 ./usr/include/c++/10.1.0/bits/cpp_type_traits.h
+-rw-r--r-- root root 1811 ./usr/include/c++/10.1.0/bits/cxxabi_forced.h
+-rw-r--r-- root root 2220 ./usr/include/c++/10.1.0/bits/cxxabi_init_exception.h
+-rw-r--r-- root root 37325 ./usr/include/c++/10.1.0/bits/deque.tcc
+-rw-r--r-- root root 12387 ./usr/include/c++/10.1.0/bits/enable_special_members.h
+-rw-r--r-- root root 2037 ./usr/include/c++/10.1.0/bits/erase_if.h
+-rw-r--r-- root root 45979 ./usr/include/c++/10.1.0/bitset
+-rw-r--r-- root root 1645 ./usr/include/c++/10.1.0/bits/exception_defines.h
+-rw-r--r-- root root 2483 ./usr/include/c++/10.1.0/bits/exception.h
+-rw-r--r-- root root 6072 ./usr/include/c++/10.1.0/bits/exception_ptr.h
+-rw-r--r-- root root 50386 ./usr/include/c++/10.1.0/bits/forward_list.h
+-rw-r--r-- root root 13871 ./usr/include/c++/10.1.0/bits/forward_list.tcc
+-rw-r--r-- root root 16405 ./usr/include/c++/10.1.0/bits/fs_dir.h
+-rw-r--r-- root root 10267 ./usr/include/c++/10.1.0/bits/fs_fwd.h
+-rw-r--r-- root root 9729 ./usr/include/c++/10.1.0/bits/fs_ops.h
+-rw-r--r-- root root 38775 ./usr/include/c++/10.1.0/bits/fs_path.h
+-rw-r--r-- root root 33663 ./usr/include/c++/10.1.0/bits/fstream.tcc
+-rw-r--r-- root root 3433 ./usr/include/c++/10.1.0/bits/functexcept.h
+-rw-r--r-- root root 8567 ./usr/include/c++/10.1.0/bits/functional_hash.h
+-rw-r--r-- root root 7851 ./usr/include/c++/10.1.0/bits/gslice_array.h
+-rw-r--r-- root root 5518 ./usr/include/c++/10.1.0/bits/gslice.h
+-rw-r--r-- root root 2146 ./usr/include/c++/10.1.0/bits/hash_bytes.h
+-rw-r--r-- root root 74752 ./usr/include/c++/10.1.0/bits/hashtable.h
+-rw-r--r-- root root 67673 ./usr/include/c++/10.1.0/bits/hashtable_policy.h
+-rw-r--r-- root root 7861 ./usr/include/c++/10.1.0/bits/indirect_array.h
+-rw-r--r-- root root 2877 ./usr/include/c++/10.1.0/bits/int_limits.h
+-rw-r--r-- root root 6025 ./usr/include/c++/10.1.0/bits/invoke.h
+-rw-r--r-- root root 31179 ./usr/include/c++/10.1.0/bits/ios_base.h
+-rw-r--r-- root root 31093 ./usr/include/c++/10.1.0/bits/istream.tcc
+-rw-r--r-- root root 30948 ./usr/include/c++/10.1.0/bits/iterator_concepts.h
+-rw-r--r-- root root 16968 ./usr/include/c++/10.1.0/bits/list.tcc
+-rw-r--r-- root root 24950 ./usr/include/c++/10.1.0/bits/locale_classes.h
+-rw-r--r-- root root 8375 ./usr/include/c++/10.1.0/bits/locale_classes.tcc
+-rw-r--r-- root root 18801 ./usr/include/c++/10.1.0/bits/locale_conv.h
+-rw-r--r-- root root 92321 ./usr/include/c++/10.1.0/bits/locale_facets.h
+-rw-r--r-- root root 68980 ./usr/include/c++/10.1.0/bits/locale_facets_nonio.h
+-rw-r--r-- root root 45280 ./usr/include/c++/10.1.0/bits/locale_facets_nonio.tcc
+-rw-r--r-- root root 39548 ./usr/include/c++/10.1.0/bits/locale_facets.tcc
+-rw-r--r-- root root 5941 ./usr/include/c++/10.1.0/bits/localefwd.h
+-rw-r--r-- root root 7675 ./usr/include/c++/10.1.0/bits/mask_array.h
+-rw-r--r-- root root 2487 ./usr/include/c++/10.1.0/bits/memoryfwd.h
+-rw-r--r-- root root 6613 ./usr/include/c++/10.1.0/bits/move.h
+-rw-r--r-- root root 4886 ./usr/include/c++/10.1.0/bits/nested_exception.h
+-rw-r--r-- root root 8216 ./usr/include/c++/10.1.0/bits/node_handle.h
+-rw-r--r-- root root 4002 ./usr/include/c++/10.1.0/bits/ostream_insert.h
+-rw-r--r-- root root 12315 ./usr/include/c++/10.1.0/bits/ostream.tcc
+-rw-r--r-- root root 7943 ./usr/include/c++/10.1.0/bits/parse_numbers.h
+-rw-r--r-- root root 8465 ./usr/include/c++/10.1.0/bits/postypes.h
+-rw-r--r-- root root 10153 ./usr/include/c++/10.1.0/bits/predefined_ops.h
+-rw-r--r-- root root 6728 ./usr/include/c++/10.1.0/bits/ptr_traits.h
+-rw-r--r-- root root 5053 ./usr/include/c++/10.1.0/bits/quoted_string.h
+-rw-r--r-- root root 178118 ./usr/include/c++/10.1.0/bits/random.h
+-rw-r--r-- root root 103405 ./usr/include/c++/10.1.0/bits/random.tcc
+-rw-r--r-- root root 32001 ./usr/include/c++/10.1.0/bits/range_access.h
+-rw-r--r-- root root 6516 ./usr/include/c++/10.1.0/bits/range_cmp.h
+-rw-r--r-- root root 18319 ./usr/include/c++/10.1.0/bits/ranges_algobase.h
+-rw-r--r-- root root 121079 ./usr/include/c++/10.1.0/bits/ranges_algo.h
+-rw-r--r-- root root 18023 ./usr/include/c++/10.1.0/bits/ranges_uninitialized.h
+-rw-r--r-- root root 13207 ./usr/include/c++/10.1.0/bits/refwrap.h
+-rw-r--r-- root root 10738 ./usr/include/c++/10.1.0/bits/regex_automaton.h
+-rw-r--r-- root root 7722 ./usr/include/c++/10.1.0/bits/regex_automaton.tcc
+-rw-r--r-- root root 16481 ./usr/include/c++/10.1.0/bits/regex_compiler.h
+-rw-r--r-- root root 18929 ./usr/include/c++/10.1.0/bits/regex_compiler.tcc
+-rw-r--r-- root root 14729 ./usr/include/c++/10.1.0/bits/regex_constants.h
+-rw-r--r-- root root 4904 ./usr/include/c++/10.1.0/bits/regex_error.h
+-rw-r--r-- root root 7488 ./usr/include/c++/10.1.0/bits/regex_executor.h
+-rw-r--r-- root root 18841 ./usr/include/c++/10.1.0/bits/regex_executor.tcc
+-rw-r--r-- root root 102775 ./usr/include/c++/10.1.0/bits/regex.h
+-rw-r--r-- root root 7088 ./usr/include/c++/10.1.0/bits/regex_scanner.h
+-rw-r--r-- root root 15009 ./usr/include/c++/10.1.0/bits/regex_scanner.tcc
+-rw-r--r-- root root 16524 ./usr/include/c++/10.1.0/bits/regex.tcc
+-rw-r--r-- root root 9867 ./usr/include/c++/10.1.0/bits/shared_ptr_atomic.h
+-rw-r--r-- root root 55312 ./usr/include/c++/10.1.0/bits/shared_ptr_base.h
+-rw-r--r-- root root 30837 ./usr/include/c++/10.1.0/bits/shared_ptr.h
+-rw-r--r-- root root 9578 ./usr/include/c++/10.1.0/bits/slice_array.h
+-rw-r--r-- root root 47238 ./usr/include/c++/10.1.0/bits/specfun.h
+-rw-r--r-- root root 10142 ./usr/include/c++/10.1.0/bits/sstream.tcc
+-rw-r--r-- root root 3360 ./usr/include/c++/10.1.0/bits/std_abs.h
+-rw-r--r-- root root 21612 ./usr/include/c++/10.1.0/bits/std_function.h
+-rw-r--r-- root root 4767 ./usr/include/c++/10.1.0/bits/std_mutex.h
+-rw-r--r-- root root 71744 ./usr/include/c++/10.1.0/bits/stl_algobase.h
+-rw-r--r-- root root 214835 ./usr/include/c++/10.1.0/bits/stl_algo.h
+-rw-r--r-- root root 34767 ./usr/include/c++/10.1.0/bits/stl_bvector.h
+-rw-r--r-- root root 8521 ./usr/include/c++/10.1.0/bits/stl_construct.h
+-rw-r--r-- root root 76807 ./usr/include/c++/10.1.0/bits/stl_deque.h
+-rw-r--r-- root root 42293 ./usr/include/c++/10.1.0/bits/stl_function.h
+-rw-r--r-- root root 20756 ./usr/include/c++/10.1.0/bits/stl_heap.h
+-rw-r--r-- root root 8178 ./usr/include/c++/10.1.0/bits/stl_iterator_base_funcs.h
+-rw-r--r-- root root 9660 ./usr/include/c++/10.1.0/bits/stl_iterator_base_types.h
+-rw-r--r-- root root 69682 ./usr/include/c++/10.1.0/bits/stl_iterator.h
+-rw-r--r-- root root 68748 ./usr/include/c++/10.1.0/bits/stl_list.h
+-rw-r--r-- root root 54669 ./usr/include/c++/10.1.0/bits/stl_map.h
+-rw-r--r-- root root 43510 ./usr/include/c++/10.1.0/bits/stl_multimap.h
+-rw-r--r-- root root 37662 ./usr/include/c++/10.1.0/bits/stl_multiset.h
+-rw-r--r-- root root 14600 ./usr/include/c++/10.1.0/bits/stl_numeric.h
+-rw-r--r-- root root 20163 ./usr/include/c++/10.1.0/bits/stl_pair.h
+-rw-r--r-- root root 25036 ./usr/include/c++/10.1.0/bits/stl_queue.h
+-rw-r--r-- root root 3830 ./usr/include/c++/10.1.0/bits/stl_raw_storage_iter.h
+-rw-r--r-- root root 4594 ./usr/include/c++/10.1.0/bits/stl_relops.h
+-rw-r--r-- root root 37922 ./usr/include/c++/10.1.0/bits/stl_set.h
+-rw-r--r-- root root 12684 ./usr/include/c++/10.1.0/bits/stl_stack.h
+-rw-r--r-- root root 8623 ./usr/include/c++/10.1.0/bits/stl_tempbuf.h
+-rw-r--r-- root root 74660 ./usr/include/c++/10.1.0/bits/stl_tree.h
+-rw-r--r-- root root 33161 ./usr/include/c++/10.1.0/bits/stl_uninitialized.h
+-rw-r--r-- root root 65919 ./usr/include/c++/10.1.0/bits/stl_vector.h
+-rw-r--r-- root root 15462 ./usr/include/c++/10.1.0/bits/streambuf_iterator.h
+-rw-r--r-- root root 4929 ./usr/include/c++/10.1.0/bits/streambuf.tcc
+-rw-r--r-- root root 7694 ./usr/include/c++/10.1.0/bits/stream_iterator.h
+-rw-r--r-- root root 2690 ./usr/include/c++/10.1.0/bits/stringfwd.h
+-rw-r--r-- root root 6698 ./usr/include/c++/10.1.0/bits/string_view.tcc
+-rw-r--r-- root root 10730 ./usr/include/c++/10.1.0/bits/uniform_int_dist.h
+-rw-r--r-- root root 6090 ./usr/include/c++/10.1.0/bits/unique_lock.h
+-rw-r--r-- root root 31291 ./usr/include/c++/10.1.0/bits/unique_ptr.h
+-rw-r--r-- root root 76744 ./usr/include/c++/10.1.0/bits/unordered_map.h
+-rw-r--r-- root root 60612 ./usr/include/c++/10.1.0/bits/unordered_set.h
+-rw-r--r-- root root 6870 ./usr/include/c++/10.1.0/bits/uses_allocator.h
+-rw-r--r-- root root 22839 ./usr/include/c++/10.1.0/bits/valarray_after.h
+-rw-r--r-- root root 21295 ./usr/include/c++/10.1.0/bits/valarray_array.h
+-rw-r--r-- root root 7254 ./usr/include/c++/10.1.0/bits/valarray_array.tcc
+-rw-r--r-- root root 19142 ./usr/include/c++/10.1.0/bits/valarray_before.h
+-rw-r--r-- root root 30870 ./usr/include/c++/10.1.0/bits/vector.tcc
+-rw-r--r-- root root 1648 ./usr/include/c++/10.1.0/cassert
+-rw-r--r-- root root 1335 ./usr/include/c++/10.1.0/ccomplex
+-rw-r--r-- root root 2409 ./usr/include/c++/10.1.0/cctype
+-rw-r--r-- root root 1770 ./usr/include/c++/10.1.0/cerrno
+-rw-r--r-- root root 2051 ./usr/include/c++/10.1.0/cfenv
+-rw-r--r-- root root 1889 ./usr/include/c++/10.1.0/cfloat
+-rw-r--r-- root root 17991 ./usr/include/c++/10.1.0/charconv
+-rw-r--r-- root root 38834 ./usr/include/c++/10.1.0/chrono
+-rw-r--r-- root root 2157 ./usr/include/c++/10.1.0/cinttypes
+-rw-r--r-- root root 1464 ./usr/include/c++/10.1.0/ciso646
+-rw-r--r-- root root 1913 ./usr/include/c++/10.1.0/climits
+-rw-r--r-- root root 1905 ./usr/include/c++/10.1.0/clocale
+-rw-r--r-- root root 49130 ./usr/include/c++/10.1.0/cmath
+-rw-r--r-- root root 5275 ./usr/include/c++/10.1.0/codecvt
+-rw-r--r-- root root 27896 ./usr/include/c++/10.1.0/compare
+-rw-r--r-- root root 56646 ./usr/include/c++/10.1.0/complex
+-rw-r--r-- root root 1596 ./usr/include/c++/10.1.0/complex.h
+-rw-r--r-- root root 12267 ./usr/include/c++/10.1.0/concepts
+-rw-r--r-- root root 12993 ./usr/include/c++/10.1.0/condition_variable
+-rw-r--r-- root root 7898 ./usr/include/c++/10.1.0/coroutine
+-rw-r--r-- root root 1949 ./usr/include/c++/10.1.0/csetjmp
+-rw-r--r-- root root 1855 ./usr/include/c++/10.1.0/csignal
+-rw-r--r-- root root 1407 ./usr/include/c++/10.1.0/cstdalign
+-rw-r--r-- root root 1868 ./usr/include/c++/10.1.0/cstdarg
+-rw-r--r-- root root 1401 ./usr/include/c++/10.1.0/cstdbool
+-rw-r--r-- root root 6274 ./usr/include/c++/10.1.0/cstddef
+-rw-r--r-- root root 2335 ./usr/include/c++/10.1.0/cstdint
+-rw-r--r-- root root 4439 ./usr/include/c++/10.1.0/cstdio
+-rw-r--r-- root root 6325 ./usr/include/c++/10.1.0/cstdlib
+-rw-r--r-- root root 3156 ./usr/include/c++/10.1.0/cstring
+-rw-r--r-- root root 1360 ./usr/include/c++/10.1.0/ctgmath
+-rw-r--r-- root root 2298 ./usr/include/c++/10.1.0/ctime
+-rw-r--r-- root root 2210 ./usr/include/c++/10.1.0/cuchar
+-rw-r--r-- root root 6542 ./usr/include/c++/10.1.0/cwchar
+-rw-r--r-- root root 2793 ./usr/include/c++/10.1.0/cwctype
+-rw-r--r-- root root 22011 ./usr/include/c++/10.1.0/cxxabi.h
+drwxr-xr-x root root 4096 ./usr/include/c++/10.1.0/debug
+-rw-r--r-- root root 12476 ./usr/include/c++/10.1.0/debug/array
+-rw-r--r-- root root 2411 ./usr/include/c++/10.1.0/debug/assertions.h
+-rw-r--r-- root root 11903 ./usr/include/c++/10.1.0/debug/bitset
+-rw-r--r-- root root 5881 ./usr/include/c++/10.1.0/debug/debug.h
+-rw-r--r-- root root 17979 ./usr/include/c++/10.1.0/debug/deque
+-rw-r--r-- root root 16991 ./usr/include/c++/10.1.0/debug/formatter.h
+-rw-r--r-- root root 27420 ./usr/include/c++/10.1.0/debug/forward_list
+-rw-r--r-- root root 15612 ./usr/include/c++/10.1.0/debug/functions.h
+-rw-r--r-- root root 9985 ./usr/include/c++/10.1.0/debug/helper_functions.h
+-rw-r--r-- root root 25327 ./usr/include/c++/10.1.0/debug/list
+-rw-r--r-- root root 20915 ./usr/include/c++/10.1.0/debug/macros.h
+-rw-r--r-- root root 1656 ./usr/include/c++/10.1.0/debug/map
+-rw-r--r-- root root 23035 ./usr/include/c++/10.1.0/debug/map.h
+-rw-r--r-- root root 20301 ./usr/include/c++/10.1.0/debug/multimap.h
+-rw-r--r-- root root 19200 ./usr/include/c++/10.1.0/debug/multiset.h
+-rw-r--r-- root root 9279 ./usr/include/c++/10.1.0/debug/safe_base.h
+-rw-r--r-- root root 3413 ./usr/include/c++/10.1.0/debug/safe_container.h
+-rw-r--r-- root root 30112 ./usr/include/c++/10.1.0/debug/safe_iterator.h
+-rw-r--r-- root root 16171 ./usr/include/c++/10.1.0/debug/safe_iterator.tcc
+-rw-r--r-- root root 13739 ./usr/include/c++/10.1.0/debug/safe_local_iterator.h
+-rw-r--r-- root root 2905 ./usr/include/c++/10.1.0/debug/safe_local_iterator.tcc
+-rw-r--r-- root root 5096 ./usr/include/c++/10.1.0/debug/safe_sequence.h
+-rw-r--r-- root root 5040 ./usr/include/c++/10.1.0/debug/safe_sequence.tcc
+-rw-r--r-- root root 6895 ./usr/include/c++/10.1.0/debug/safe_unordered_base.h
+-rw-r--r-- root root 3866 ./usr/include/c++/10.1.0/debug/safe_unordered_container.h
+-rw-r--r-- root root 3263 ./usr/include/c++/10.1.0/debug/safe_unordered_container.tcc
+-rw-r--r-- root root 1620 ./usr/include/c++/10.1.0/debug/set
+-rw-r--r-- root root 19199 ./usr/include/c++/10.1.0/debug/set.h
+-rw-r--r-- root root 4542 ./usr/include/c++/10.1.0/debug/stl_iterator.h
+-rw-r--r-- root root 36471 ./usr/include/c++/10.1.0/debug/string
+-rw-r--r-- root root 41394 ./usr/include/c++/10.1.0/debug/unordered_map
+-rw-r--r-- root root 35429 ./usr/include/c++/10.1.0/debug/unordered_set
+-rw-r--r-- root root 23523 ./usr/include/c++/10.1.0/debug/vector
+drwxr-xr-x root root 4096 ./usr/include/c++/10.1.0/decimal
+-rw-r--r-- root root 17636 ./usr/include/c++/10.1.0/decimal/decimal
+-rw-r--r-- root root 16999 ./usr/include/c++/10.1.0/decimal/decimal.h
+-rw-r--r-- root root 3973 ./usr/include/c++/10.1.0/deque
+-rw-r--r-- root root 4848 ./usr/include/c++/10.1.0/exception
+-rw-r--r-- root root 1803 ./usr/include/c++/10.1.0/execution
+drwxr-xr-x root root 4096 ./usr/include/c++/10.1.0/experimental
+-rw-r--r-- root root 3688 ./usr/include/c++/10.1.0/experimental/algorithm
+-rw-r--r-- root root 16010 ./usr/include/c++/10.1.0/experimental/any
+-rw-r--r-- root root 3371 ./usr/include/c++/10.1.0/experimental/array
+drwxr-xr-x root root 4096 ./usr/include/c++/10.1.0/experimental/bits
+-rw-r--r-- root root 10799 ./usr/include/c++/10.1.0/experimental/bits/fs_dir.h
+-rw-r--r-- root root 8524 ./usr/include/c++/10.1.0/experimental/bits/fs_fwd.h
+-rw-r--r-- root root 9340 ./usr/include/c++/10.1.0/experimental/bits/fs_ops.h
+-rw-r--r-- root root 36768 ./usr/include/c++/10.1.0/experimental/bits/fs_path.h
+-rw-r--r-- root root 2227 ./usr/include/c++/10.1.0/experimental/bits/lfts_config.h
+-rw-r--r-- root root 4814 ./usr/include/c++/10.1.0/experimental/bits/net.h
+-rw-r--r-- root root 20205 ./usr/include/c++/10.1.0/experimental/bits/shared_ptr.h
+-rw-r--r-- root root 6816 ./usr/include/c++/10.1.0/experimental/bits/string_view.tcc
+-rw-r--r-- root root 28719 ./usr/include/c++/10.1.0/experimental/buffer
+-rw-r--r-- root root 1960 ./usr/include/c++/10.1.0/experimental/chrono
+-rw-r--r-- root root 2296 ./usr/include/c++/10.1.0/experimental/deque
+-rw-r--r-- root root 55081 ./usr/include/c++/10.1.0/experimental/executor
+-rw-r--r-- root root 1589 ./usr/include/c++/10.1.0/experimental/filesystem
+-rw-r--r-- root root 2367 ./usr/include/c++/10.1.0/experimental/forward_list
+-rw-r--r-- root root 12311 ./usr/include/c++/10.1.0/experimental/functional
+-rw-r--r-- root root 65288 ./usr/include/c++/10.1.0/experimental/internet
+-rw-r--r-- root root 21331 ./usr/include/c++/10.1.0/experimental/io_context
+-rw-r--r-- root root 3534 ./usr/include/c++/10.1.0/experimental/iterator
+-rw-r--r-- root root 2265 ./usr/include/c++/10.1.0/experimental/list
+-rw-r--r-- root root 2594 ./usr/include/c++/10.1.0/experimental/map
+-rw-r--r-- root root 6056 ./usr/include/c++/10.1.0/experimental/memory
+-rw-r--r-- root root 17388 ./usr/include/c++/10.1.0/experimental/memory_resource
+-rw-r--r-- root root 1542 ./usr/include/c++/10.1.0/experimental/net
+-rw-r--r-- root root 3744 ./usr/include/c++/10.1.0/experimental/netfwd
+-rw-r--r-- root root 2858 ./usr/include/c++/10.1.0/experimental/numeric
+-rw-r--r-- root root 26832 ./usr/include/c++/10.1.0/experimental/optional
+-rw-r--r-- root root 15335 ./usr/include/c++/10.1.0/experimental/propagate_const
+-rw-r--r-- root root 2499 ./usr/include/c++/10.1.0/experimental/random
+-rw-r--r-- root root 2438 ./usr/include/c++/10.1.0/experimental/ratio
+-rw-r--r-- root root 2121 ./usr/include/c++/10.1.0/experimental/regex
+-rw-r--r-- root root 2471 ./usr/include/c++/10.1.0/experimental/set
+-rw-r--r-- root root 76228 ./usr/include/c++/10.1.0/experimental/socket
+-rw-r--r-- root root 2699 ./usr/include/c++/10.1.0/experimental/source_location
+-rw-r--r-- root root 2920 ./usr/include/c++/10.1.0/experimental/string
+-rw-r--r-- root root 22662 ./usr/include/c++/10.1.0/experimental/string_view
+-rw-r--r-- root root 2045 ./usr/include/c++/10.1.0/experimental/system_error
+-rw-r--r-- root root 5794 ./usr/include/c++/10.1.0/experimental/timer
+-rw-r--r-- root root 2472 ./usr/include/c++/10.1.0/experimental/tuple
+-rw-r--r-- root root 11221 ./usr/include/c++/10.1.0/experimental/type_traits
+-rw-r--r-- root root 2845 ./usr/include/c++/10.1.0/experimental/unordered_map
+-rw-r--r-- root root 2728 ./usr/include/c++/10.1.0/experimental/unordered_set
+-rw-r--r-- root root 1657 ./usr/include/c++/10.1.0/experimental/utility
+-rw-r--r-- root root 2355 ./usr/include/c++/10.1.0/experimental/vector
+drwxr-xr-x root root 4096 ./usr/include/c++/10.1.0/ext
+-rw-r--r-- root root 19255 ./usr/include/c++/10.1.0/ext/algorithm
+-rw-r--r-- root root 3972 ./usr/include/c++/10.1.0/ext/aligned_buffer.h
+-rw-r--r-- root root 6139 ./usr/include/c++/10.1.0/ext/alloc_traits.h
+-rw-r--r-- root root 3477 ./usr/include/c++/10.1.0/ext/atomicity.h
+-rw-r--r-- root root 32193 ./usr/include/c++/10.1.0/ext/bitmap_allocator.h
+-rw-r--r-- root root 4447 ./usr/include/c++/10.1.0/ext/cast.h
+-rw-r--r-- root root 6570 ./usr/include/c++/10.1.0/ext/cmath
+-rw-r--r-- root root 16353 ./usr/include/c++/10.1.0/ext/codecvt_specializations.h
+-rw-r--r-- root root 7542 ./usr/include/c++/10.1.0/ext/concurrence.h
+-rw-r--r-- root root 5881 ./usr/include/c++/10.1.0/ext/debug_allocator.h
+-rw-r--r-- root root 2247 ./usr/include/c++/10.1.0/ext/enc_filebuf.h
+-rw-r--r-- root root 6277 ./usr/include/c++/10.1.0/ext/extptr_allocator.h
+-rw-r--r-- root root 14172 ./usr/include/c++/10.1.0/ext/functional
+-rw-r--r-- root root 17822 ./usr/include/c++/10.1.0/ext/hash_map
+-rw-r--r-- root root 17323 ./usr/include/c++/10.1.0/ext/hash_set
+-rw-r--r-- root root 4031 ./usr/include/c++/10.1.0/ext/iterator
+-rw-r--r-- root root 5696 ./usr/include/c++/10.1.0/ext/malloc_allocator.h
+-rw-r--r-- root root 7173 ./usr/include/c++/10.1.0/ext/memory
+-rw-r--r-- root root 23628 ./usr/include/c++/10.1.0/ext/mt_allocator.h
+-rw-r--r-- root root 5587 ./usr/include/c++/10.1.0/ext/new_allocator.h
+-rw-r--r-- root root 4739 ./usr/include/c++/10.1.0/ext/numeric
+-rw-r--r-- root root 4570 ./usr/include/c++/10.1.0/ext/numeric_traits.h
+drwxr-xr-x root root 4096 ./usr/include/c++/10.1.0/ext/pb_ds
+-rw-r--r-- root root 30110 ./usr/include/c++/10.1.0/ext/pb_ds/assoc_container.hpp
+drwxr-xr-x root root 4096 ./usr/include/c++/10.1.0/ext/pb_ds/detail
+drwxr-xr-x root root 4096 ./usr/include/c++/10.1.0/ext/pb_ds/detail/binary_heap_
+-rw-r--r-- root root 9027 ./usr/include/c++/10.1.0/ext/pb_ds/detail/binary_heap_/binary_heap_.hpp
+-rw-r--r-- root root 4338 ./usr/include/c++/10.1.0/ext/pb_ds/detail/binary_heap_/const_iterator.hpp
+-rw-r--r-- root root 4222 ./usr/include/c++/10.1.0/ext/pb_ds/detail/binary_heap_/constructors_destructor_fn_imps.hpp
+-rw-r--r-- root root 2574 ./usr/include/c++/10.1.0/ext/pb_ds/detail/binary_heap_/debug_fn_imps.hpp
+-rw-r--r-- root root 2802 ./usr/include/c++/10.1.0/ext/pb_ds/detail/binary_heap_/entry_cmp.hpp
+-rw-r--r-- root root 2767 ./usr/include/c++/10.1.0/ext/pb_ds/detail/binary_heap_/entry_pred.hpp
+-rw-r--r-- root root 5537 ./usr/include/c++/10.1.0/ext/pb_ds/detail/binary_heap_/erase_fn_imps.hpp
+-rw-r--r-- root root 2630 ./usr/include/c++/10.1.0/ext/pb_ds/detail/binary_heap_/find_fn_imps.hpp
+-rw-r--r-- root root 2114 ./usr/include/c++/10.1.0/ext/pb_ds/detail/binary_heap_/info_fn_imps.hpp
+-rw-r--r-- root root 5011 ./usr/include/c++/10.1.0/ext/pb_ds/detail/binary_heap_/insert_fn_imps.hpp
+-rw-r--r-- root root 2303 ./usr/include/c++/10.1.0/ext/pb_ds/detail/binary_heap_/iterators_fn_imps.hpp
+-rw-r--r-- root root 4363 ./usr/include/c++/10.1.0/ext/pb_ds/detail/binary_heap_/point_const_iterator.hpp
+-rw-r--r-- root root 1935 ./usr/include/c++/10.1.0/ext/pb_ds/detail/binary_heap_/policy_access_fn_imps.hpp
+-rw-r--r-- root root 6133 ./usr/include/c++/10.1.0/ext/pb_ds/detail/binary_heap_/resize_policy.hpp
+-rw-r--r-- root root 4956 ./usr/include/c++/10.1.0/ext/pb_ds/detail/binary_heap_/split_join_fn_imps.hpp
+-rw-r--r-- root root 2480 ./usr/include/c++/10.1.0/ext/pb_ds/detail/binary_heap_/trace_fn_imps.hpp
+drwxr-xr-x root root 4096 ./usr/include/c++/10.1.0/ext/pb_ds/detail/binomial_heap_
+drwxr-xr-x root root 4096 ./usr/include/c++/10.1.0/ext/pb_ds/detail/binomial_heap_base_
+-rw-r--r-- root root 6185 ./usr/include/c++/10.1.0/ext/pb_ds/detail/binomial_heap_base_/binomial_heap_base_.hpp
+-rw-r--r-- root root 2721 ./usr/include/c++/10.1.0/ext/pb_ds/detail/binomial_heap_base_/constructors_destructor_fn_imps.hpp
+-rw-r--r-- root root 3501 ./usr/include/c++/10.1.0/ext/pb_ds/detail/binomial_heap_base_/debug_fn_imps.hpp
+-rw-r--r-- root root 4515 ./usr/include/c++/10.1.0/ext/pb_ds/detail/binomial_heap_base_/erase_fn_imps.hpp
+-rw-r--r-- root root 2378 ./usr/include/c++/10.1.0/ext/pb_ds/detail/binomial_heap_base_/find_fn_imps.hpp
+-rw-r--r-- root root 5304 ./usr/include/c++/10.1.0/ext/pb_ds/detail/binomial_heap_base_/insert_fn_imps.hpp
+-rw-r--r-- root root 5398 ./usr/include/c++/10.1.0/ext/pb_ds/detail/binomial_heap_base_/split_join_fn_imps.hpp
+-rw-r--r-- root root 3922 ./usr/include/c++/10.1.0/ext/pb_ds/detail/binomial_heap_/binomial_heap_.hpp
+-rw-r--r-- root root 2184 ./usr/include/c++/10.1.0/ext/pb_ds/detail/binomial_heap_/constructors_destructor_fn_imps.hpp
+-rw-r--r-- root root 1930 ./usr/include/c++/10.1.0/ext/pb_ds/detail/binomial_heap_/debug_fn_imps.hpp
+drwxr-xr-x root root 4096 ./usr/include/c++/10.1.0/ext/pb_ds/detail/bin_search_tree_
+-rw-r--r-- root root 12468 ./usr/include/c++/10.1.0/ext/pb_ds/detail/bin_search_tree_/bin_search_tree_.hpp
+-rw-r--r-- root root 5539 ./usr/include/c++/10.1.0/ext/pb_ds/detail/bin_search_tree_/constructors_destructor_fn_imps.hpp
+-rw-r--r-- root root 8104 ./usr/include/c++/10.1.0/ext/pb_ds/detail/bin_search_tree_/debug_fn_imps.hpp
+-rw-r--r-- root root 2952 ./usr/include/c++/10.1.0/ext/pb_ds/detail/bin_search_tree_/erase_fn_imps.hpp
+-rw-r--r-- root root 4712 ./usr/include/c++/10.1.0/ext/pb_ds/detail/bin_search_tree_/find_fn_imps.hpp
+-rw-r--r-- root root 2132 ./usr/include/c++/10.1.0/ext/pb_ds/detail/bin_search_tree_/info_fn_imps.hpp
+-rw-r--r-- root root 5514 ./usr/include/c++/10.1.0/ext/pb_ds/detail/bin_search_tree_/insert_fn_imps.hpp
+-rw-r--r-- root root 3548 ./usr/include/c++/10.1.0/ext/pb_ds/detail/bin_search_tree_/iterators_fn_imps.hpp
+-rw-r--r-- root root 5921 ./usr/include/c++/10.1.0/ext/pb_ds/detail/bin_search_tree_/node_iterators.hpp
+-rw-r--r-- root root 8961 ./usr/include/c++/10.1.0/ext/pb_ds/detail/bin_search_tree_/point_iterators.hpp
+-rw-r--r-- root root 1938 ./usr/include/c++/10.1.0/ext/pb_ds/detail/bin_search_tree_/policy_access_fn_imps.hpp
+-rw-r--r-- root root 2942 ./usr/include/c++/10.1.0/ext/pb_ds/detail/bin_search_tree_/r_erase_fn_imps.hpp
+-rw-r--r-- root root 4223 ./usr/include/c++/10.1.0/ext/pb_ds/detail/bin_search_tree_/rotate_fn_imps.hpp
+-rw-r--r-- root root 4040 ./usr/include/c++/10.1.0/ext/pb_ds/detail/bin_search_tree_/split_join_fn_imps.hpp
+-rw-r--r-- root root 6374 ./usr/include/c++/10.1.0/ext/pb_ds/detail/bin_search_tree_/traits.hpp
+drwxr-xr-x root root 4096 ./usr/include/c++/10.1.0/ext/pb_ds/detail/branch_policy
+-rw-r--r-- root root 4020 ./usr/include/c++/10.1.0/ext/pb_ds/detail/branch_policy/branch_policy.hpp
+-rw-r--r-- root root 2379 ./usr/include/c++/10.1.0/ext/pb_ds/detail/branch_policy/null_node_metadata.hpp
+-rw-r--r-- root root 3254 ./usr/include/c++/10.1.0/ext/pb_ds/detail/branch_policy/traits.hpp
+drwxr-xr-x root root 4096 ./usr/include/c++/10.1.0/ext/pb_ds/detail/cc_hash_table_map_
+-rw-r--r-- root root 20071 ./usr/include/c++/10.1.0/ext/pb_ds/detail/cc_hash_table_map_/cc_ht_map_.hpp
+-rw-r--r-- root root 2798 ./usr/include/c++/10.1.0/ext/pb_ds/detail/cc_hash_table_map_/cmp_fn_imps.hpp
+-rw-r--r-- root root 2874 ./usr/include/c++/10.1.0/ext/pb_ds/detail/cc_hash_table_map_/cond_key_dtor_entry_dealtor.hpp
+-rw-r--r-- root root 5824 ./usr/include/c++/10.1.0/ext/pb_ds/detail/cc_hash_table_map_/constructor_destructor_fn_imps.hpp
+-rw-r--r-- root root 2259 ./usr/include/c++/10.1.0/ext/pb_ds/detail/cc_hash_table_map_/constructor_destructor_no_store_hash_fn_imps.hpp
+-rw-r--r-- root root 2339 ./usr/include/c++/10.1.0/ext/pb_ds/detail/cc_hash_table_map_/constructor_destructor_store_hash_fn_imps.hpp
+-rw-r--r-- root root 2726 ./usr/include/c++/10.1.0/ext/pb_ds/detail/cc_hash_table_map_/debug_fn_imps.hpp
+-rw-r--r-- root root 2033 ./usr/include/c++/10.1.0/ext/pb_ds/detail/cc_hash_table_map_/debug_no_store_hash_fn_imps.hpp
+-rw-r--r-- root root 2181 ./usr/include/c++/10.1.0/ext/pb_ds/detail/cc_hash_table_map_/debug_store_hash_fn_imps.hpp
+-rw-r--r-- root root 2987 ./usr/include/c++/10.1.0/ext/pb_ds/detail/cc_hash_table_map_/entry_list_fn_imps.hpp
+-rw-r--r-- root root 3278 ./usr/include/c++/10.1.0/ext/pb_ds/detail/cc_hash_table_map_/erase_fn_imps.hpp
+-rw-r--r-- root root 3297 ./usr/include/c++/10.1.0/ext/pb_ds/detail/cc_hash_table_map_/erase_no_store_hash_fn_imps.hpp
+-rw-r--r-- root root 3258 ./usr/include/c++/10.1.0/ext/pb_ds/detail/cc_hash_table_map_/erase_store_hash_fn_imps.hpp
+-rw-r--r-- root root 2518 ./usr/include/c++/10.1.0/ext/pb_ds/detail/cc_hash_table_map_/find_fn_imps.hpp
+-rw-r--r-- root root 1779 ./usr/include/c++/10.1.0/ext/pb_ds/detail/cc_hash_table_map_/find_store_hash_fn_imps.hpp
+-rw-r--r-- root root 3163 ./usr/include/c++/10.1.0/ext/pb_ds/detail/cc_hash_table_map_/info_fn_imps.hpp
+-rw-r--r-- root root 1896 ./usr/include/c++/10.1.0/ext/pb_ds/detail/cc_hash_table_map_/insert_fn_imps.hpp
+-rw-r--r-- root root 2651 ./usr/include/c++/10.1.0/ext/pb_ds/detail/cc_hash_table_map_/insert_no_store_hash_fn_imps.hpp
+-rw-r--r-- root root 2707 ./usr/include/c++/10.1.0/ext/pb_ds/detail/cc_hash_table_map_/insert_store_hash_fn_imps.hpp
+-rw-r--r-- root root 2697 ./usr/include/c++/10.1.0/ext/pb_ds/detail/cc_hash_table_map_/iterators_fn_imps.hpp
+-rw-r--r-- root root 2514 ./usr/include/c++/10.1.0/ext/pb_ds/detail/cc_hash_table_map_/policy_access_fn_imps.hpp
+-rw-r--r-- root root 4095 ./usr/include/c++/10.1.0/ext/pb_ds/detail/cc_hash_table_map_/resize_fn_imps.hpp
+-rw-r--r-- root root 2275 ./usr/include/c++/10.1.0/ext/pb_ds/detail/cc_hash_table_map_/resize_no_store_hash_fn_imps.hpp
+-rw-r--r-- root root 2307 ./usr/include/c++/10.1.0/ext/pb_ds/detail/cc_hash_table_map_/resize_store_hash_fn_imps.hpp
+-rw-r--r-- root root 2161 ./usr/include/c++/10.1.0/ext/pb_ds/detail/cc_hash_table_map_/size_fn_imps.hpp
+-rw-r--r-- root root 2396 ./usr/include/c++/10.1.0/ext/pb_ds/detail/cc_hash_table_map_/trace_fn_imps.hpp
+-rw-r--r-- root root 2772 ./usr/include/c++/10.1.0/ext/pb_ds/detail/cond_dealtor.hpp
+-rw-r--r-- root root 13120 ./usr/include/c++/10.1.0/ext/pb_ds/detail/container_base_dispatch.hpp
+-rw-r--r-- root root 8697 ./usr/include/c++/10.1.0/ext/pb_ds/detail/debug_map_base.hpp
+drwxr-xr-x root root 4096 ./usr/include/c++/10.1.0/ext/pb_ds/detail/eq_fn
+-rw-r--r-- root root 2330 ./usr/include/c++/10.1.0/ext/pb_ds/detail/eq_fn/eq_by_less.hpp
+-rw-r--r-- root root 3739 ./usr/include/c++/10.1.0/ext/pb_ds/detail/eq_fn/hash_eq_fn.hpp
+drwxr-xr-x root root 4096 ./usr/include/c++/10.1.0/ext/pb_ds/detail/gp_hash_table_map_
+-rw-r--r-- root root 6639 ./usr/include/c++/10.1.0/ext/pb_ds/detail/gp_hash_table_map_/constructor_destructor_fn_imps.hpp
+-rw-r--r-- root root 2235 ./usr/include/c++/10.1.0/ext/pb_ds/detail/gp_hash_table_map_/constructor_destructor_no_store_hash_fn_imps.hpp
+-rw-r--r-- root root 2302 ./usr/include/c++/10.1.0/ext/pb_ds/detail/gp_hash_table_map_/constructor_destructor_store_hash_fn_imps.hpp
+-rw-r--r-- root root 2207 ./usr/include/c++/10.1.0/ext/pb_ds/detail/gp_hash_table_map_/debug_fn_imps.hpp
+-rw-r--r-- root root 2538 ./usr/include/c++/10.1.0/ext/pb_ds/detail/gp_hash_table_map_/debug_no_store_hash_fn_imps.hpp
+-rw-r--r-- root root 2678 ./usr/include/c++/10.1.0/ext/pb_ds/detail/gp_hash_table_map_/debug_store_hash_fn_imps.hpp
+-rw-r--r-- root root 3237 ./usr/include/c++/10.1.0/ext/pb_ds/detail/gp_hash_table_map_/erase_fn_imps.hpp
+-rw-r--r-- root root 2918 ./usr/include/c++/10.1.0/ext/pb_ds/detail/gp_hash_table_map_/erase_no_store_hash_fn_imps.hpp
+-rw-r--r-- root root 2952 ./usr/include/c++/10.1.0/ext/pb_ds/detail/gp_hash_table_map_/erase_store_hash_fn_imps.hpp
+-rw-r--r-- root root 2511 ./usr/include/c++/10.1.0/ext/pb_ds/detail/gp_hash_table_map_/find_fn_imps.hpp
+-rw-r--r-- root root 1950 ./usr/include/c++/10.1.0/ext/pb_ds/detail/gp_hash_table_map_/find_no_store_hash_fn_imps.hpp
+-rw-r--r-- root root 1780 ./usr/include/c++/10.1.0/ext/pb_ds/detail/gp_hash_table_map_/find_store_hash_fn_imps.hpp
+-rw-r--r-- root root 20441 ./usr/include/c++/10.1.0/ext/pb_ds/detail/gp_hash_table_map_/gp_ht_map_.hpp
+-rw-r--r-- root root 2160 ./usr/include/c++/10.1.0/ext/pb_ds/detail/gp_hash_table_map_/info_fn_imps.hpp
+-rw-r--r-- root root 1896 ./usr/include/c++/10.1.0/ext/pb_ds/detail/gp_hash_table_map_/insert_fn_imps.hpp
+-rw-r--r-- root root 3810 ./usr/include/c++/10.1.0/ext/pb_ds/detail/gp_hash_table_map_/insert_no_store_hash_fn_imps.hpp
+-rw-r--r-- root root 4118 ./usr/include/c++/10.1.0/ext/pb_ds/detail/gp_hash_table_map_/insert_store_hash_fn_imps.hpp
+-rw-r--r-- root root 2652 ./usr/include/c++/10.1.0/ext/pb_ds/detail/gp_hash_table_map_/iterator_fn_imps.hpp
+-rw-r--r-- root root 2693 ./usr/include/c++/10.1.0/ext/pb_ds/detail/gp_hash_table_map_/policy_access_fn_imps.hpp
+-rw-r--r-- root root 4190 ./usr/include/c++/10.1.0/ext/pb_ds/detail/gp_hash_table_map_/resize_fn_imps.hpp
+-rw-r--r-- root root 2651 ./usr/include/c++/10.1.0/ext/pb_ds/detail/gp_hash_table_map_/resize_no_store_hash_fn_imps.hpp
+-rw-r--r-- root root 2684 ./usr/include/c++/10.1.0/ext/pb_ds/detail/gp_hash_table_map_/resize_store_hash_fn_imps.hpp
+-rw-r--r-- root root 2457 ./usr/include/c++/10.1.0/ext/pb_ds/detail/gp_hash_table_map_/trace_fn_imps.hpp
+drwxr-xr-x root root 4096 ./usr/include/c++/10.1.0/ext/pb_ds/detail/hash_fn
+-rw-r--r-- root root 2137 ./usr/include/c++/10.1.0/ext/pb_ds/detail/hash_fn/direct_mask_range_hashing_imp.hpp
+-rw-r--r-- root root 2127 ./usr/include/c++/10.1.0/ext/pb_ds/detail/hash_fn/direct_mod_range_hashing_imp.hpp
+-rw-r--r-- root root 1946 ./usr/include/c++/10.1.0/ext/pb_ds/detail/hash_fn/linear_probe_fn_imp.hpp
+-rw-r--r-- root root 3290 ./usr/include/c++/10.1.0/ext/pb_ds/detail/hash_fn/mask_based_range_hashing.hpp
+-rw-r--r-- root root 2391 ./usr/include/c++/10.1.0/ext/pb_ds/detail/hash_fn/mod_based_range_hashing.hpp
+-rw-r--r-- root root 2009 ./usr/include/c++/10.1.0/ext/pb_ds/detail/hash_fn/probe_fn_base.hpp
+-rw-r--r-- root root 1953 ./usr/include/c++/10.1.0/ext/pb_ds/detail/hash_fn/quadratic_probe_fn_imp.hpp
+-rw-r--r-- root root 10543 ./usr/include/c++/10.1.0/ext/pb_ds/detail/hash_fn/ranged_hash_fn.hpp
+-rw-r--r-- root root 10256 ./usr/include/c++/10.1.0/ext/pb_ds/detail/hash_fn/ranged_probe_fn.hpp
+-rw-r--r-- root root 2291 ./usr/include/c++/10.1.0/ext/pb_ds/detail/hash_fn/sample_probe_fn.hpp
+-rw-r--r-- root root 2469 ./usr/include/c++/10.1.0/ext/pb_ds/detail/hash_fn/sample_ranged_hash_fn.hpp
+-rw-r--r-- root root 2598 ./usr/include/c++/10.1.0/ext/pb_ds/detail/hash_fn/sample_ranged_probe_fn.hpp
+-rw-r--r-- root root 2487 ./usr/include/c++/10.1.0/ext/pb_ds/detail/hash_fn/sample_range_hashing.hpp
+drwxr-xr-x root root 4096 ./usr/include/c++/10.1.0/ext/pb_ds/detail/left_child_next_sibling_heap_
+-rw-r--r-- root root 4924 ./usr/include/c++/10.1.0/ext/pb_ds/detail/left_child_next_sibling_heap_/const_iterator.hpp
+-rw-r--r-- root root 4088 ./usr/include/c++/10.1.0/ext/pb_ds/detail/left_child_next_sibling_heap_/constructors_destructor_fn_imps.hpp
+-rw-r--r-- root root 4108 ./usr/include/c++/10.1.0/ext/pb_ds/detail/left_child_next_sibling_heap_/debug_fn_imps.hpp
+-rw-r--r-- root root 3992 ./usr/include/c++/10.1.0/ext/pb_ds/detail/left_child_next_sibling_heap_/erase_fn_imps.hpp
+-rw-r--r-- root root 2158 ./usr/include/c++/10.1.0/ext/pb_ds/detail/left_child_next_sibling_heap_/info_fn_imps.hpp
+-rw-r--r-- root root 5234 ./usr/include/c++/10.1.0/ext/pb_ds/detail/left_child_next_sibling_heap_/insert_fn_imps.hpp
+-rw-r--r-- root root 2588 ./usr/include/c++/10.1.0/ext/pb_ds/detail/left_child_next_sibling_heap_/iterators_fn_imps.hpp
+-rw-r--r-- root root 8182 ./usr/include/c++/10.1.0/ext/pb_ds/detail/left_child_next_sibling_heap_/left_child_next_sibling_heap_.hpp
+-rw-r--r-- root root 3240 ./usr/include/c++/10.1.0/ext/pb_ds/detail/left_child_next_sibling_heap_/node.hpp
+-rw-r--r-- root root 4397 ./usr/include/c++/10.1.0/ext/pb_ds/detail/left_child_next_sibling_heap_/point_const_iterator.hpp
+-rw-r--r-- root root 1960 ./usr/include/c++/10.1.0/ext/pb_ds/detail/left_child_next_sibling_heap_/policy_access_fn_imps.hpp
+-rw-r--r-- root root 2848 ./usr/include/c++/10.1.0/ext/pb_ds/detail/left_child_next_sibling_heap_/trace_fn_imps.hpp
+drwxr-xr-x root root 4096 ./usr/include/c++/10.1.0/ext/pb_ds/detail/list_update_map_
+-rw-r--r-- root root 3617 ./usr/include/c++/10.1.0/ext/pb_ds/detail/list_update_map_/constructor_destructor_fn_imps.hpp
+-rw-r--r-- root root 2128 ./usr/include/c++/10.1.0/ext/pb_ds/detail/list_update_map_/debug_fn_imps.hpp
+-rw-r--r-- root root 2117 ./usr/include/c++/10.1.0/ext/pb_ds/detail/list_update_map_/entry_metadata_base.hpp
+-rw-r--r-- root root 3515 ./usr/include/c++/10.1.0/ext/pb_ds/detail/list_update_map_/erase_fn_imps.hpp
+-rw-r--r-- root root 2894 ./usr/include/c++/10.1.0/ext/pb_ds/detail/list_update_map_/find_fn_imps.hpp
+-rw-r--r-- root root 2126 ./usr/include/c++/10.1.0/ext/pb_ds/detail/list_update_map_/info_fn_imps.hpp
+-rw-r--r-- root root 3543 ./usr/include/c++/10.1.0/ext/pb_ds/detail/list_update_map_/insert_fn_imps.hpp
+-rw-r--r-- root root 2547 ./usr/include/c++/10.1.0/ext/pb_ds/detail/list_update_map_/iterators_fn_imps.hpp
+-rw-r--r-- root root 10551 ./usr/include/c++/10.1.0/ext/pb_ds/detail/list_update_map_/lu_map_.hpp
+-rw-r--r-- root root 2061 ./usr/include/c++/10.1.0/ext/pb_ds/detail/list_update_map_/trace_fn_imps.hpp
+drwxr-xr-x root root 4096 ./usr/include/c++/10.1.0/ext/pb_ds/detail/list_update_policy
+-rw-r--r-- root root 2850 ./usr/include/c++/10.1.0/ext/pb_ds/detail/list_update_policy/lu_counter_metadata.hpp
+-rw-r--r-- root root 2672 ./usr/include/c++/10.1.0/ext/pb_ds/detail/list_update_policy/sample_update_policy.hpp
+drwxr-xr-x root root 4096 ./usr/include/c++/10.1.0/ext/pb_ds/detail/ov_tree_map_
+-rw-r--r-- root root 6916 ./usr/include/c++/10.1.0/ext/pb_ds/detail/ov_tree_map_/constructors_destructor_fn_imps.hpp
+-rw-r--r-- root root 2851 ./usr/include/c++/10.1.0/ext/pb_ds/detail/ov_tree_map_/debug_fn_imps.hpp
+-rw-r--r-- root root 5014 ./usr/include/c++/10.1.0/ext/pb_ds/detail/ov_tree_map_/erase_fn_imps.hpp
+-rw-r--r-- root root 2136 ./usr/include/c++/10.1.0/ext/pb_ds/detail/ov_tree_map_/info_fn_imps.hpp
+-rw-r--r-- root root 2306 ./usr/include/c++/10.1.0/ext/pb_ds/detail/ov_tree_map_/insert_fn_imps.hpp
+-rw-r--r-- root root 3394 ./usr/include/c++/10.1.0/ext/pb_ds/detail/ov_tree_map_/iterators_fn_imps.hpp
+-rw-r--r-- root root 8638 ./usr/include/c++/10.1.0/ext/pb_ds/detail/ov_tree_map_/node_iterators.hpp
+-rw-r--r-- root root 15509 ./usr/include/c++/10.1.0/ext/pb_ds/detail/ov_tree_map_/ov_tree_map_.hpp
+-rw-r--r-- root root 1920 ./usr/include/c++/10.1.0/ext/pb_ds/detail/ov_tree_map_/policy_access_fn_imps.hpp
+-rw-r--r-- root root 3807 ./usr/include/c++/10.1.0/ext/pb_ds/detail/ov_tree_map_/split_join_fn_imps.hpp
+-rw-r--r-- root root 4562 ./usr/include/c++/10.1.0/ext/pb_ds/detail/ov_tree_map_/traits.hpp
+drwxr-xr-x root root 4096 ./usr/include/c++/10.1.0/ext/pb_ds/detail/pairing_heap_
+-rw-r--r-- root root 2539 ./usr/include/c++/10.1.0/ext/pb_ds/detail/pairing_heap_/constructors_destructor_fn_imps.hpp
+-rw-r--r-- root root 2029 ./usr/include/c++/10.1.0/ext/pb_ds/detail/pairing_heap_/debug_fn_imps.hpp
+-rw-r--r-- root root 7224 ./usr/include/c++/10.1.0/ext/pb_ds/detail/pairing_heap_/erase_fn_imps.hpp
+-rw-r--r-- root root 1970 ./usr/include/c++/10.1.0/ext/pb_ds/detail/pairing_heap_/find_fn_imps.hpp
+-rw-r--r-- root root 2980 ./usr/include/c++/10.1.0/ext/pb_ds/detail/pairing_heap_/insert_fn_imps.hpp
+-rw-r--r-- root root 5500 ./usr/include/c++/10.1.0/ext/pb_ds/detail/pairing_heap_/pairing_heap_.hpp
+-rw-r--r-- root root 3739 ./usr/include/c++/10.1.0/ext/pb_ds/detail/pairing_heap_/split_join_fn_imps.hpp
+drwxr-xr-x root root 4096 ./usr/include/c++/10.1.0/ext/pb_ds/detail/pat_trie_
+-rw-r--r-- root root 5745 ./usr/include/c++/10.1.0/ext/pb_ds/detail/pat_trie_/constructors_destructor_fn_imps.hpp
+-rw-r--r-- root root 3824 ./usr/include/c++/10.1.0/ext/pb_ds/detail/pat_trie_/debug_fn_imps.hpp
+-rw-r--r-- root root 7978 ./usr/include/c++/10.1.0/ext/pb_ds/detail/pat_trie_/erase_fn_imps.hpp
+-rw-r--r-- root root 7908 ./usr/include/c++/10.1.0/ext/pb_ds/detail/pat_trie_/find_fn_imps.hpp
+-rw-r--r-- root root 2108 ./usr/include/c++/10.1.0/ext/pb_ds/detail/pat_trie_/info_fn_imps.hpp
+-rw-r--r-- root root 14508 ./usr/include/c++/10.1.0/ext/pb_ds/detail/pat_trie_/insert_join_fn_imps.hpp
+-rw-r--r-- root root 3513 ./usr/include/c++/10.1.0/ext/pb_ds/detail/pat_trie_/iterators_fn_imps.hpp
+-rw-r--r-- root root 36857 ./usr/include/c++/10.1.0/ext/pb_ds/detail/pat_trie_/pat_trie_base.hpp
+-rw-r--r-- root root 16777 ./usr/include/c++/10.1.0/ext/pb_ds/detail/pat_trie_/pat_trie_.hpp
+-rw-r--r-- root root 2248 ./usr/include/c++/10.1.0/ext/pb_ds/detail/pat_trie_/policy_access_fn_imps.hpp
+-rw-r--r-- root root 2953 ./usr/include/c++/10.1.0/ext/pb_ds/detail/pat_trie_/r_erase_fn_imps.hpp
+-rw-r--r-- root root 4363 ./usr/include/c++/10.1.0/ext/pb_ds/detail/pat_trie_/rotate_fn_imps.hpp
+-rw-r--r-- root root 7758 ./usr/include/c++/10.1.0/ext/pb_ds/detail/pat_trie_/split_fn_imps.hpp
+-rw-r--r-- root root 6718 ./usr/include/c++/10.1.0/ext/pb_ds/detail/pat_trie_/synth_access_traits.hpp
+-rw-r--r-- root root 3434 ./usr/include/c++/10.1.0/ext/pb_ds/detail/pat_trie_/trace_fn_imps.hpp
+-rw-r--r-- root root 6305 ./usr/include/c++/10.1.0/ext/pb_ds/detail/pat_trie_/traits.hpp
+-rw-r--r-- root root 2075 ./usr/include/c++/10.1.0/ext/pb_ds/detail/pat_trie_/update_fn_imps.hpp
+-rw-r--r-- root root 4140 ./usr/include/c++/10.1.0/ext/pb_ds/detail/priority_queue_base_dispatch.hpp
+drwxr-xr-x root root 4096 ./usr/include/c++/10.1.0/ext/pb_ds/detail/rb_tree_map_
+-rw-r--r-- root root 2816 ./usr/include/c++/10.1.0/ext/pb_ds/detail/rb_tree_map_/constructors_destructor_fn_imps.hpp
+-rw-r--r-- root root 2794 ./usr/include/c++/10.1.0/ext/pb_ds/detail/rb_tree_map_/debug_fn_imps.hpp
+-rw-r--r-- root root 7084 ./usr/include/c++/10.1.0/ext/pb_ds/detail/rb_tree_map_/erase_fn_imps.hpp
+-rw-r--r-- root root 1703 ./usr/include/c++/10.1.0/ext/pb_ds/detail/rb_tree_map_/find_fn_imps.hpp
+-rw-r--r-- root root 1874 ./usr/include/c++/10.1.0/ext/pb_ds/detail/rb_tree_map_/info_fn_imps.hpp
+-rw-r--r-- root root 3900 ./usr/include/c++/10.1.0/ext/pb_ds/detail/rb_tree_map_/insert_fn_imps.hpp
+-rw-r--r-- root root 3671 ./usr/include/c++/10.1.0/ext/pb_ds/detail/rb_tree_map_/node.hpp
+-rw-r--r-- root root 7962 ./usr/include/c++/10.1.0/ext/pb_ds/detail/rb_tree_map_/rb_tree_.hpp
+-rw-r--r-- root root 7894 ./usr/include/c++/10.1.0/ext/pb_ds/detail/rb_tree_map_/split_join_fn_imps.hpp
+-rw-r--r-- root root 3283 ./usr/include/c++/10.1.0/ext/pb_ds/detail/rb_tree_map_/traits.hpp
+drwxr-xr-x root root 4096 ./usr/include/c++/10.1.0/ext/pb_ds/detail/rc_binomial_heap_
+-rw-r--r-- root root 2500 ./usr/include/c++/10.1.0/ext/pb_ds/detail/rc_binomial_heap_/constructors_destructor_fn_imps.hpp
+-rw-r--r-- root root 3571 ./usr/include/c++/10.1.0/ext/pb_ds/detail/rc_binomial_heap_/debug_fn_imps.hpp
+-rw-r--r-- root root 2922 ./usr/include/c++/10.1.0/ext/pb_ds/detail/rc_binomial_heap_/erase_fn_imps.hpp
+-rw-r--r-- root root 4270 ./usr/include/c++/10.1.0/ext/pb_ds/detail/rc_binomial_heap_/insert_fn_imps.hpp
+-rw-r--r-- root root 5303 ./usr/include/c++/10.1.0/ext/pb_ds/detail/rc_binomial_heap_/rc_binomial_heap_.hpp
+-rw-r--r-- root root 6199 ./usr/include/c++/10.1.0/ext/pb_ds/detail/rc_binomial_heap_/rc.hpp
+-rw-r--r-- root root 2451 ./usr/include/c++/10.1.0/ext/pb_ds/detail/rc_binomial_heap_/split_join_fn_imps.hpp
+-rw-r--r-- root root 1937 ./usr/include/c++/10.1.0/ext/pb_ds/detail/rc_binomial_heap_/trace_fn_imps.hpp
+drwxr-xr-x root root 4096 ./usr/include/c++/10.1.0/ext/pb_ds/detail/resize_policy
+-rw-r--r-- root root 4932 ./usr/include/c++/10.1.0/ext/pb_ds/detail/resize_policy/cc_hash_max_collision_check_resize_trigger_imp.hpp
+-rw-r--r-- root root 2805 ./usr/include/c++/10.1.0/ext/pb_ds/detail/resize_policy/hash_exponential_size_policy_imp.hpp
+-rw-r--r-- root root 7785 ./usr/include/c++/10.1.0/ext/pb_ds/detail/resize_policy/hash_load_check_resize_trigger_imp.hpp
+-rw-r--r-- root root 2970 ./usr/include/c++/10.1.0/ext/pb_ds/detail/resize_policy/hash_load_check_resize_trigger_size_base.hpp
+-rw-r--r-- root root 6172 ./usr/include/c++/10.1.0/ext/pb_ds/detail/resize_policy/hash_prime_size_policy_imp.hpp
+-rw-r--r-- root root 6316 ./usr/include/c++/10.1.0/ext/pb_ds/detail/resize_policy/hash_standard_resize_policy_imp.hpp
+-rw-r--r-- root root 3578 ./usr/include/c++/10.1.0/ext/pb_ds/detail/resize_policy/sample_resize_policy.hpp
+-rw-r--r-- root root 3914 ./usr/include/c++/10.1.0/ext/pb_ds/detail/resize_policy/sample_resize_trigger.hpp
+-rw-r--r-- root root 2427 ./usr/include/c++/10.1.0/ext/pb_ds/detail/resize_policy/sample_size_policy.hpp
+drwxr-xr-x root root 4096 ./usr/include/c++/10.1.0/ext/pb_ds/detail/splay_tree_
+-rw-r--r-- root root 2880 ./usr/include/c++/10.1.0/ext/pb_ds/detail/splay_tree_/constructors_destructor_fn_imps.hpp
+-rw-r--r-- root root 2496 ./usr/include/c++/10.1.0/ext/pb_ds/detail/splay_tree_/debug_fn_imps.hpp
+-rw-r--r-- root root 4302 ./usr/include/c++/10.1.0/ext/pb_ds/detail/splay_tree_/erase_fn_imps.hpp
+-rw-r--r-- root root 3352 ./usr/include/c++/10.1.0/ext/pb_ds/detail/splay_tree_/find_fn_imps.hpp
+-rw-r--r-- root root 1689 ./usr/include/c++/10.1.0/ext/pb_ds/detail/splay_tree_/info_fn_imps.hpp
+-rw-r--r-- root root 3386 ./usr/include/c++/10.1.0/ext/pb_ds/detail/splay_tree_/insert_fn_imps.hpp
+-rw-r--r-- root root 3587 ./usr/include/c++/10.1.0/ext/pb_ds/detail/splay_tree_/node.hpp
+-rw-r--r-- root root 8082 ./usr/include/c++/10.1.0/ext/pb_ds/detail/splay_tree_/splay_fn_imps.hpp
+-rw-r--r-- root root 9307 ./usr/include/c++/10.1.0/ext/pb_ds/detail/splay_tree_/splay_tree_.hpp
+-rw-r--r-- root root 3667 ./usr/include/c++/10.1.0/ext/pb_ds/detail/splay_tree_/split_join_fn_imps.hpp
+-rw-r--r-- root root 3351 ./usr/include/c++/10.1.0/ext/pb_ds/detail/splay_tree_/traits.hpp
+-rw-r--r-- root root 5031 ./usr/include/c++/10.1.0/ext/pb_ds/detail/standard_policies.hpp
+drwxr-xr-x root root 4096 ./usr/include/c++/10.1.0/ext/pb_ds/detail/thin_heap_
+-rw-r--r-- root root 2979 ./usr/include/c++/10.1.0/ext/pb_ds/detail/thin_heap_/constructors_destructor_fn_imps.hpp
+-rw-r--r-- root root 3899 ./usr/include/c++/10.1.0/ext/pb_ds/detail/thin_heap_/debug_fn_imps.hpp
+-rw-r--r-- root root 6088 ./usr/include/c++/10.1.0/ext/pb_ds/detail/thin_heap_/erase_fn_imps.hpp
+-rw-r--r-- root root 1985 ./usr/include/c++/10.1.0/ext/pb_ds/detail/thin_heap_/find_fn_imps.hpp
+-rw-r--r-- root root 7516 ./usr/include/c++/10.1.0/ext/pb_ds/detail/thin_heap_/insert_fn_imps.hpp
+-rw-r--r-- root root 3188 ./usr/include/c++/10.1.0/ext/pb_ds/detail/thin_heap_/split_join_fn_imps.hpp
+-rw-r--r-- root root 8389 ./usr/include/c++/10.1.0/ext/pb_ds/detail/thin_heap_/thin_heap_.hpp
+-rw-r--r-- root root 1995 ./usr/include/c++/10.1.0/ext/pb_ds/detail/thin_heap_/trace_fn_imps.hpp
+drwxr-xr-x root root 4096 ./usr/include/c++/10.1.0/ext/pb_ds/detail/tree_policy
+-rw-r--r-- root root 3338 ./usr/include/c++/10.1.0/ext/pb_ds/detail/tree_policy/node_metadata_selector.hpp
+-rw-r--r-- root root 3756 ./usr/include/c++/10.1.0/ext/pb_ds/detail/tree_policy/order_statistics_imp.hpp
+-rw-r--r-- root root 2346 ./usr/include/c++/10.1.0/ext/pb_ds/detail/tree_policy/sample_tree_node_update.hpp
+-rw-r--r-- root root 5153 ./usr/include/c++/10.1.0/ext/pb_ds/detail/tree_trace_base.hpp
+drwxr-xr-x root root 4096 ./usr/include/c++/10.1.0/ext/pb_ds/detail/trie_policy
+-rw-r--r-- root root 3338 ./usr/include/c++/10.1.0/ext/pb_ds/detail/trie_policy/node_metadata_selector.hpp
+-rw-r--r-- root root 4734 ./usr/include/c++/10.1.0/ext/pb_ds/detail/trie_policy/order_statistics_imp.hpp
+-rw-r--r-- root root 4544 ./usr/include/c++/10.1.0/ext/pb_ds/detail/trie_policy/prefix_search_node_update_imp.hpp
+-rw-r--r-- root root 2666 ./usr/include/c++/10.1.0/ext/pb_ds/detail/trie_policy/sample_trie_access_traits.hpp
+-rw-r--r-- root root 2348 ./usr/include/c++/10.1.0/ext/pb_ds/detail/trie_policy/sample_trie_node_update.hpp
+-rw-r--r-- root root 5847 ./usr/include/c++/10.1.0/ext/pb_ds/detail/trie_policy/trie_policy_base.hpp
+-rw-r--r-- root root 3084 ./usr/include/c++/10.1.0/ext/pb_ds/detail/trie_policy/trie_string_access_traits_imp.hpp
+-rw-r--r-- root root 6450 ./usr/include/c++/10.1.0/ext/pb_ds/detail/types_traits.hpp
+-rw-r--r-- root root 4318 ./usr/include/c++/10.1.0/ext/pb_ds/detail/type_utils.hpp
+drwxr-xr-x root root 4096 ./usr/include/c++/10.1.0/ext/pb_ds/detail/unordered_iterator
+-rw-r--r-- root root 3517 ./usr/include/c++/10.1.0/ext/pb_ds/detail/unordered_iterator/const_iterator.hpp
+-rw-r--r-- root root 3966 ./usr/include/c++/10.1.0/ext/pb_ds/detail/unordered_iterator/iterator.hpp
+-rw-r--r-- root root 3975 ./usr/include/c++/10.1.0/ext/pb_ds/detail/unordered_iterator/point_const_iterator.hpp
+-rw-r--r-- root root 3742 ./usr/include/c++/10.1.0/ext/pb_ds/detail/unordered_iterator/point_iterator.hpp
+-rw-r--r-- root root 2988 ./usr/include/c++/10.1.0/ext/pb_ds/exception.hpp
+-rw-r--r-- root root 16815 ./usr/include/c++/10.1.0/ext/pb_ds/hash_policy.hpp
+-rw-r--r-- root root 4318 ./usr/include/c++/10.1.0/ext/pb_ds/list_update_policy.hpp
+-rw-r--r-- root root 5444 ./usr/include/c++/10.1.0/ext/pb_ds/priority_queue.hpp
+-rw-r--r-- root root 12268 ./usr/include/c++/10.1.0/ext/pb_ds/tag_and_trait.hpp
+-rw-r--r-- root root 5569 ./usr/include/c++/10.1.0/ext/pb_ds/tree_policy.hpp
+-rw-r--r-- root root 12201 ./usr/include/c++/10.1.0/ext/pb_ds/trie_policy.hpp
+-rw-r--r-- root root 5556 ./usr/include/c++/10.1.0/ext/pod_char_traits.h
+-rw-r--r-- root root 20480 ./usr/include/c++/10.1.0/ext/pointer.h
+-rw-r--r-- root root 8965 ./usr/include/c++/10.1.0/ext/pool_allocator.h
+-rw-r--r-- root root 113176 ./usr/include/c++/10.1.0/ext/random
+-rw-r--r-- root root 60330 ./usr/include/c++/10.1.0/ext/random.tcc
+-rw-r--r-- root root 3278 ./usr/include/c++/10.1.0/ext/rb_tree
+-rw-r--r-- root root 23794 ./usr/include/c++/10.1.0/ext/rc_string_base.h
+-rw-r--r-- root root 88598 ./usr/include/c++/10.1.0/ext/rope
+-rw-r--r-- root root 48860 ./usr/include/c++/10.1.0/ext/ropeimpl.h
+-rw-r--r-- root root 29900 ./usr/include/c++/10.1.0/ext/slist
+-rw-r--r-- root root 16393 ./usr/include/c++/10.1.0/ext/sso_string_base.h
+-rw-r--r-- root root 5670 ./usr/include/c++/10.1.0/ext/stdio_filebuf.h
+-rw-r--r-- root root 8782 ./usr/include/c++/10.1.0/ext/stdio_sync_filebuf.h
+-rw-r--r-- root root 3597 ./usr/include/c++/10.1.0/ext/string_conversions.h
+-rw-r--r-- root root 25222 ./usr/include/c++/10.1.0/ext/throw_allocator.h
+-rw-r--r-- root root 16480 ./usr/include/c++/10.1.0/ext/typelist.h
+-rw-r--r-- root root 5914 ./usr/include/c++/10.1.0/ext/type_traits.h
+-rw-r--r-- root root 3178 ./usr/include/c++/10.1.0/ext/vstring_fwd.h
+-rw-r--r-- root root 110624 ./usr/include/c++/10.1.0/ext/vstring.h
+-rw-r--r-- root root 23614 ./usr/include/c++/10.1.0/ext/vstring.tcc
+-rw-r--r-- root root 5885 ./usr/include/c++/10.1.0/ext/vstring_util.h
+-rw-r--r-- root root 2020 ./usr/include/c++/10.1.0/fenv.h
+-rw-r--r-- root root 1645 ./usr/include/c++/10.1.0/filesystem
+-rw-r--r-- root root 2690 ./usr/include/c++/10.1.0/forward_list
+-rw-r--r-- root root 40559 ./usr/include/c++/10.1.0/fstream
+-rw-r--r-- root root 40189 ./usr/include/c++/10.1.0/functional
+-rw-r--r-- root root 50826 ./usr/include/c++/10.1.0/future
+-rw-r--r-- root root 3038 ./usr/include/c++/10.1.0/initializer_list
+-rw-r--r-- root root 16547 ./usr/include/c++/10.1.0/iomanip
+-rw-r--r-- root root 1601 ./usr/include/c++/10.1.0/ios
+-rw-r--r-- root root 6918 ./usr/include/c++/10.1.0/iosfwd
+-rw-r--r-- root root 2695 ./usr/include/c++/10.1.0/iostream
+-rw-r--r-- root root 32843 ./usr/include/c++/10.1.0/istream
+-rw-r--r-- root root 2751 ./usr/include/c++/10.1.0/iterator
+-rw-r--r-- root root 71808 ./usr/include/c++/10.1.0/limits
+-rw-r--r-- root root 3657 ./usr/include/c++/10.1.0/list
+-rw-r--r-- root root 1488 ./usr/include/c++/10.1.0/locale
+-rw-r--r-- root root 3929 ./usr/include/c++/10.1.0/map
+-rw-r--r-- root root 4573 ./usr/include/c++/10.1.0/math.h
+-rw-r--r-- root root 13663 ./usr/include/c++/10.1.0/memory
+-rw-r--r-- root root 20624 ./usr/include/c++/10.1.0/memory_resource
+-rw-r--r-- root root 19755 ./usr/include/c++/10.1.0/mutex
+-rw-r--r-- root root 8199 ./usr/include/c++/10.1.0/new
+-rw-r--r-- root root 6220 ./usr/include/c++/10.1.0/numbers
+-rw-r--r-- root root 25090 ./usr/include/c++/10.1.0/numeric
+-rw-r--r-- root root 38703 ./usr/include/c++/10.1.0/optional
+-rw-r--r-- root root 24826 ./usr/include/c++/10.1.0/ostream
+drwxr-xr-x root root 4096 ./usr/include/c++/10.1.0/parallel
+-rw-r--r-- root root 18259 ./usr/include/c++/10.1.0/parallel/algobase.h
+-rw-r--r-- root root 80136 ./usr/include/c++/10.1.0/parallel/algo.h
+-rw-r--r-- root root 1381 ./usr/include/c++/10.1.0/parallel/algorithm
+-rw-r--r-- root root 32306 ./usr/include/c++/10.1.0/parallel/algorithmfwd.h
+-rw-r--r-- root root 16952 ./usr/include/c++/10.1.0/parallel/balanced_quicksort.h
+-rw-r--r-- root root 12373 ./usr/include/c++/10.1.0/parallel/base.h
+-rw-r--r-- root root 1586 ./usr/include/c++/10.1.0/parallel/basic_iterator.h
+-rw-r--r-- root root 2235 ./usr/include/c++/10.1.0/parallel/checkers.h
+-rw-r--r-- root root 3790 ./usr/include/c++/10.1.0/parallel/compatibility.h
+-rw-r--r-- root root 2871 ./usr/include/c++/10.1.0/parallel/compiletime_settings.h
+-rw-r--r-- root root 3356 ./usr/include/c++/10.1.0/parallel/equally_split.h
+-rw-r--r-- root root 3543 ./usr/include/c++/10.1.0/parallel/features.h
+-rw-r--r-- root root 13591 ./usr/include/c++/10.1.0/parallel/find.h
+-rw-r--r-- root root 6992 ./usr/include/c++/10.1.0/parallel/find_selectors.h
+-rw-r--r-- root root 3947 ./usr/include/c++/10.1.0/parallel/for_each.h
+-rw-r--r-- root root 10565 ./usr/include/c++/10.1.0/parallel/for_each_selectors.h
+-rw-r--r-- root root 5678 ./usr/include/c++/10.1.0/parallel/iterator.h
+-rw-r--r-- root root 6542 ./usr/include/c++/10.1.0/parallel/list_partition.h
+-rw-r--r-- root root 28592 ./usr/include/c++/10.1.0/parallel/losertree.h
+-rw-r--r-- root root 9578 ./usr/include/c++/10.1.0/parallel/merge.h
+-rw-r--r-- root root 22073 ./usr/include/c++/10.1.0/parallel/multiseq_selection.h
+-rw-r--r-- root root 70545 ./usr/include/c++/10.1.0/parallel/multiway_merge.h
+-rw-r--r-- root root 15281 ./usr/include/c++/10.1.0/parallel/multiway_mergesort.h
+-rw-r--r-- root root 20717 ./usr/include/c++/10.1.0/parallel/numeric
+-rw-r--r-- root root 7506 ./usr/include/c++/10.1.0/parallel/numericfwd.h
+-rw-r--r-- root root 4031 ./usr/include/c++/10.1.0/parallel/omp_loop.h
+-rw-r--r-- root root 4104 ./usr/include/c++/10.1.0/parallel/omp_loop_static.h
+-rw-r--r-- root root 1576 ./usr/include/c++/10.1.0/parallel/parallel.h
+-rw-r--r-- root root 4552 ./usr/include/c++/10.1.0/parallel/par_loop.h
+-rw-r--r-- root root 7474 ./usr/include/c++/10.1.0/parallel/partial_sum.h
+-rw-r--r-- root root 14961 ./usr/include/c++/10.1.0/parallel/partition.h
+-rw-r--r-- root root 5542 ./usr/include/c++/10.1.0/parallel/queue.h
+-rw-r--r-- root root 6126 ./usr/include/c++/10.1.0/parallel/quicksort.h
+-rw-r--r-- root root 4227 ./usr/include/c++/10.1.0/parallel/random_number.h
+-rw-r--r-- root root 18675 ./usr/include/c++/10.1.0/parallel/random_shuffle.h
+-rw-r--r-- root root 5391 ./usr/include/c++/10.1.0/parallel/search.h
+-rw-r--r-- root root 14590 ./usr/include/c++/10.1.0/parallel/set_operations.h
+-rw-r--r-- root root 12462 ./usr/include/c++/10.1.0/parallel/settings.h
+-rw-r--r-- root root 7709 ./usr/include/c++/10.1.0/parallel/sort.h
+-rw-r--r-- root root 5982 ./usr/include/c++/10.1.0/parallel/tags.h
+-rw-r--r-- root root 3716 ./usr/include/c++/10.1.0/parallel/types.h
+-rw-r--r-- root root 6165 ./usr/include/c++/10.1.0/parallel/unique_copy.h
+-rw-r--r-- root root 9610 ./usr/include/c++/10.1.0/parallel/workstealing.h
+drwxr-xr-x root root 4096 ./usr/include/c++/10.1.0/pstl
+-rw-r--r-- root root 68340 ./usr/include/c++/10.1.0/pstl/algorithm_fwd.h
+-rw-r--r-- root root 172216 ./usr/include/c++/10.1.0/pstl/algorithm_impl.h
+-rw-r--r-- root root 3694 ./usr/include/c++/10.1.0/pstl/execution_defs.h
+-rw-r--r-- root root 4834 ./usr/include/c++/10.1.0/pstl/execution_impl.h
+-rw-r--r-- root root 32278 ./usr/include/c++/10.1.0/pstl/glue_algorithm_defs.h
+-rw-r--r-- root root 64874 ./usr/include/c++/10.1.0/pstl/glue_algorithm_impl.h
+-rw-r--r-- root root 1549 ./usr/include/c++/10.1.0/pstl/glue_execution_defs.h
+-rw-r--r-- root root 3865 ./usr/include/c++/10.1.0/pstl/glue_memory_defs.h
+-rw-r--r-- root root 19574 ./usr/include/c++/10.1.0/pstl/glue_memory_impl.h
+-rw-r--r-- root root 6620 ./usr/include/c++/10.1.0/pstl/glue_numeric_defs.h
+-rw-r--r-- root root 11628 ./usr/include/c++/10.1.0/pstl/glue_numeric_impl.h
+-rw-r--r-- root root 1997 ./usr/include/c++/10.1.0/pstl/memory_impl.h
+-rw-r--r-- root root 7929 ./usr/include/c++/10.1.0/pstl/numeric_fwd.h
+-rw-r--r-- root root 18748 ./usr/include/c++/10.1.0/pstl/numeric_impl.h
+-rw-r--r-- root root 718 ./usr/include/c++/10.1.0/pstl/parallel_backend.h
+-rw-r--r-- root root 4084 ./usr/include/c++/10.1.0/pstl/parallel_backend_serial.h
+-rw-r--r-- root root 26379 ./usr/include/c++/10.1.0/pstl/parallel_backend_tbb.h
+-rw-r--r-- root root 5602 ./usr/include/c++/10.1.0/pstl/parallel_backend_utils.h
+-rw-r--r-- root root 4110 ./usr/include/c++/10.1.0/pstl/parallel_impl.h
+-rw-r--r-- root root 6990 ./usr/include/c++/10.1.0/pstl/pstl_config.h
+-rw-r--r-- root root 29256 ./usr/include/c++/10.1.0/pstl/unseq_backend_simd.h
+-rw-r--r-- root root 4606 ./usr/include/c++/10.1.0/pstl/utils.h
+-rw-r--r-- root root 2467 ./usr/include/c++/10.1.0/queue
+-rw-r--r-- root root 1692 ./usr/include/c++/10.1.0/random
+-rw-r--r-- root root 97030 ./usr/include/c++/10.1.0/ranges
+-rw-r--r-- root root 20107 ./usr/include/c++/10.1.0/ratio
+-rw-r--r-- root root 2648 ./usr/include/c++/10.1.0/regex
+-rw-r--r-- root root 17459 ./usr/include/c++/10.1.0/scoped_allocator
+-rw-r--r-- root root 3799 ./usr/include/c++/10.1.0/set
+-rw-r--r-- root root 24417 ./usr/include/c++/10.1.0/shared_mutex
+-rw-r--r-- root root 13251 ./usr/include/c++/10.1.0/span
+-rw-r--r-- root root 28524 ./usr/include/c++/10.1.0/sstream
+-rw-r--r-- root root 2391 ./usr/include/c++/10.1.0/stack
+-rw-r--r-- root root 9877 ./usr/include/c++/10.1.0/stdexcept
+-rw-r--r-- root root 2248 ./usr/include/c++/10.1.0/stdlib.h
+-rw-r--r-- root root 16254 ./usr/include/c++/10.1.0/stop_token
+-rw-r--r-- root root 30017 ./usr/include/c++/10.1.0/streambuf
+-rw-r--r-- root root 4645 ./usr/include/c++/10.1.0/string
+-rw-r--r-- root root 24878 ./usr/include/c++/10.1.0/string_view
+-rw-r--r-- root root 14871 ./usr/include/c++/10.1.0/system_error
+-rw-r--r-- root root 1360 ./usr/include/c++/10.1.0/tgmath.h
+-rw-r--r-- root root 13968 ./usr/include/c++/10.1.0/thread
+drwxr-xr-x root root 4096 ./usr/include/c++/10.1.0/tr1
+-rw-r--r-- root root 6983 ./usr/include/c++/10.1.0/tr1/array
+-rw-r--r-- root root 22937 ./usr/include/c++/10.1.0/tr1/bessel_function.tcc
+-rw-r--r-- root root 5995 ./usr/include/c++/10.1.0/tr1/beta_function.tcc
+-rw-r--r-- root root 1255 ./usr/include/c++/10.1.0/tr1/ccomplex
+-rw-r--r-- root root 1478 ./usr/include/c++/10.1.0/tr1/cctype
+-rw-r--r-- root root 2070 ./usr/include/c++/10.1.0/tr1/cfenv
+-rw-r--r-- root root 1380 ./usr/include/c++/10.1.0/tr1/cfloat
+-rw-r--r-- root root 2322 ./usr/include/c++/10.1.0/tr1/cinttypes
+-rw-r--r-- root root 1454 ./usr/include/c++/10.1.0/tr1/climits
+-rw-r--r-- root root 43874 ./usr/include/c++/10.1.0/tr1/cmath
+-rw-r--r-- root root 12384 ./usr/include/c++/10.1.0/tr1/complex
+-rw-r--r-- root root 1261 ./usr/include/c++/10.1.0/tr1/complex.h
+-rw-r--r-- root root 1246 ./usr/include/c++/10.1.0/tr1/cstdarg
+-rw-r--r-- root root 1344 ./usr/include/c++/10.1.0/tr1/cstdbool
+-rw-r--r-- root root 2687 ./usr/include/c++/10.1.0/tr1/cstdint
+-rw-r--r-- root root 1548 ./usr/include/c++/10.1.0/tr1/cstdio
+-rw-r--r-- root root 1862 ./usr/include/c++/10.1.0/tr1/cstdlib
+-rw-r--r-- root root 1248 ./usr/include/c++/10.1.0/tr1/ctgmath
+-rw-r--r-- root root 1234 ./usr/include/c++/10.1.0/tr1/ctime
+-rw-r--r-- root root 1209 ./usr/include/c++/10.1.0/tr1/ctype.h
+-rw-r--r-- root root 1784 ./usr/include/c++/10.1.0/tr1/cwchar
+-rw-r--r-- root root 1525 ./usr/include/c++/10.1.0/tr1/cwctype
+-rw-r--r-- root root 27644 ./usr/include/c++/10.1.0/tr1/ell_integral.tcc
+-rw-r--r-- root root 16013 ./usr/include/c++/10.1.0/tr1/exp_integral.tcc
+-rw-r--r-- root root 1204 ./usr/include/c++/10.1.0/tr1/fenv.h
+-rw-r--r-- root root 1209 ./usr/include/c++/10.1.0/tr1/float.h
+-rw-r--r-- root root 70545 ./usr/include/c++/10.1.0/tr1/functional
+-rw-r--r-- root root 6043 ./usr/include/c++/10.1.0/tr1/functional_hash.h
+-rw-r--r-- root root 14682 ./usr/include/c++/10.1.0/tr1/gamma.tcc
+-rw-r--r-- root root 41995 ./usr/include/c++/10.1.0/tr1/hashtable.h
+-rw-r--r-- root root 25086 ./usr/include/c++/10.1.0/tr1/hashtable_policy.h
+-rw-r--r-- root root 28066 ./usr/include/c++/10.1.0/tr1/hypergeometric.tcc
+-rw-r--r-- root root 1267 ./usr/include/c++/10.1.0/tr1/inttypes.h
+-rw-r--r-- root root 10652 ./usr/include/c++/10.1.0/tr1/legendre_function.tcc
+-rw-r--r-- root root 1214 ./usr/include/c++/10.1.0/tr1/limits.h
+-rw-r--r-- root root 4553 ./usr/include/c++/10.1.0/tr1/math.h
+-rw-r--r-- root root 1791 ./usr/include/c++/10.1.0/tr1/memory
+-rw-r--r-- root root 16324 ./usr/include/c++/10.1.0/tr1/modified_bessel_func.tcc
+-rw-r--r-- root root 3925 ./usr/include/c++/10.1.0/tr1/poly_hermite.tcc
+-rw-r--r-- root root 11676 ./usr/include/c++/10.1.0/tr1/poly_laguerre.tcc
+-rw-r--r-- root root 1589 ./usr/include/c++/10.1.0/tr1/random
+-rw-r--r-- root root 73123 ./usr/include/c++/10.1.0/tr1/random.h
+-rw-r--r-- root root 53927 ./usr/include/c++/10.1.0/tr1/random.tcc
+-rw-r--r-- root root 92899 ./usr/include/c++/10.1.0/tr1/regex
+-rw-r--r-- root root 14067 ./usr/include/c++/10.1.0/tr1/riemann_zeta.tcc
+-rw-r--r-- root root 32608 ./usr/include/c++/10.1.0/tr1/shared_ptr.h
+-rw-r--r-- root root 5055 ./usr/include/c++/10.1.0/tr1/special_function_util.h
+-rw-r--r-- root root 1214 ./usr/include/c++/10.1.0/tr1/stdarg.h
+-rw-r--r-- root root 1219 ./usr/include/c++/10.1.0/tr1/stdbool.h
+-rw-r--r-- root root 1214 ./usr/include/c++/10.1.0/tr1/stdint.h
+-rw-r--r-- root root 1209 ./usr/include/c++/10.1.0/tr1/stdio.h
+-rw-r--r-- root root 1487 ./usr/include/c++/10.1.0/tr1/stdlib.h
+-rw-r--r-- root root 1255 ./usr/include/c++/10.1.0/tr1/tgmath.h
+-rw-r--r-- root root 12119 ./usr/include/c++/10.1.0/tr1/tuple
+-rw-r--r-- root root 19019 ./usr/include/c++/10.1.0/tr1/type_traits
+-rw-r--r-- root root 1574 ./usr/include/c++/10.1.0/tr1/unordered_map
+-rw-r--r-- root root 10216 ./usr/include/c++/10.1.0/tr1/unordered_map.h
+-rw-r--r-- root root 1574 ./usr/include/c++/10.1.0/tr1/unordered_set
+-rw-r--r-- root root 9540 ./usr/include/c++/10.1.0/tr1/unordered_set.h
+-rw-r--r-- root root 3225 ./usr/include/c++/10.1.0/tr1/utility
+-rw-r--r-- root root 1249 ./usr/include/c++/10.1.0/tr1/wchar.h
+-rw-r--r-- root root 1255 ./usr/include/c++/10.1.0/tr1/wctype.h
+drwxr-xr-x root root 4096 ./usr/include/c++/10.1.0/tr2
+-rw-r--r-- root root 7370 ./usr/include/c++/10.1.0/tr2/bool_set
+-rw-r--r-- root root 8319 ./usr/include/c++/10.1.0/tr2/bool_set.tcc
+-rw-r--r-- root root 34336 ./usr/include/c++/10.1.0/tr2/dynamic_bitset
+-rw-r--r-- root root 8925 ./usr/include/c++/10.1.0/tr2/dynamic_bitset.tcc
+-rw-r--r-- root root 2130 ./usr/include/c++/10.1.0/tr2/ratio
+-rw-r--r-- root root 2699 ./usr/include/c++/10.1.0/tr2/type_traits
+-rw-r--r-- root root 60078 ./usr/include/c++/10.1.0/tuple
+-rw-r--r-- root root 3512 ./usr/include/c++/10.1.0/typeindex
+-rw-r--r-- root root 7746 ./usr/include/c++/10.1.0/typeinfo
+-rw-r--r-- root root 103356 ./usr/include/c++/10.1.0/type_traits
+-rw-r--r-- root root 3467 ./usr/include/c++/10.1.0/unordered_map
+-rw-r--r-- root root 3340 ./usr/include/c++/10.1.0/unordered_set
+-rw-r--r-- root root 14820 ./usr/include/c++/10.1.0/utility
+-rw-r--r-- root root 40362 ./usr/include/c++/10.1.0/valarray
+-rw-r--r-- root root 60701 ./usr/include/c++/10.1.0/variant
+-rw-r--r-- root root 4275 ./usr/include/c++/10.1.0/vector
+-rw-r--r-- root root 7706 ./usr/include/c++/10.1.0/version
+drwxr-xr-x root root 4096 ./usr/include/c++/10.1.0/x86_64-poky-linux
+drwxr-xr-x root root 4096 ./usr/include/c++/10.1.0/x86_64-poky-linux/bits
+-rw-r--r-- root root 1518 ./usr/include/c++/10.1.0/x86_64-poky-linux/bits/atomic_word.h
+-rw-r--r-- root root 3575 ./usr/include/c++/10.1.0/x86_64-poky-linux/bits/basic_file.h
+-rw-r--r-- root root 1979 ./usr/include/c++/10.1.0/x86_64-poky-linux/bits/c++allocator.h
+-rw-r--r-- root root 61947 ./usr/include/c++/10.1.0/x86_64-poky-linux/bits/c++config.h
+-rw-r--r-- root root 1608 ./usr/include/c++/10.1.0/x86_64-poky-linux/bits/c++io.h
+-rw-r--r-- root root 3307 ./usr/include/c++/10.1.0/x86_64-poky-linux/bits/c++locale.h
+-rw-r--r-- root root 1333 ./usr/include/c++/10.1.0/x86_64-poky-linux/bits/cpu_defines.h
+-rw-r--r-- root root 2316 ./usr/include/c++/10.1.0/x86_64-poky-linux/bits/ctype_base.h
+-rw-r--r-- root root 2284 ./usr/include/c++/10.1.0/x86_64-poky-linux/bits/ctype_inline.h
+-rw-r--r-- root root 2096 ./usr/include/c++/10.1.0/x86_64-poky-linux/bits/cxxabi_tweaks.h
+-rw-r--r-- root root 5175 ./usr/include/c++/10.1.0/x86_64-poky-linux/bits/error_constants.h
+-rw-r--r-- root root 2628 ./usr/include/c++/10.1.0/x86_64-poky-linux/bits/extc++.h
+-rw-r--r-- root root 24260 ./usr/include/c++/10.1.0/x86_64-poky-linux/bits/gthr-default.h
+-rw-r--r-- root root 5608 ./usr/include/c++/10.1.0/x86_64-poky-linux/bits/gthr.h
+-rw-r--r-- root root 24260 ./usr/include/c++/10.1.0/x86_64-poky-linux/bits/gthr-posix.h
+-rw-r--r-- root root 6808 ./usr/include/c++/10.1.0/x86_64-poky-linux/bits/gthr-single.h
+-rw-r--r-- root root 4516 ./usr/include/c++/10.1.0/x86_64-poky-linux/bits/messages_members.h
+-rw-r--r-- root root 6194 ./usr/include/c++/10.1.0/x86_64-poky-linux/bits/opt_random.h
+-rw-r--r-- root root 2007 ./usr/include/c++/10.1.0/x86_64-poky-linux/bits/os_defines.h
+-rw-r--r-- root root 3286 ./usr/include/c++/10.1.0/x86_64-poky-linux/bits/stdc++.h
+-rw-r--r-- root root 1741 ./usr/include/c++/10.1.0/x86_64-poky-linux/bits/stdtr1c++.h
+-rw-r--r-- root root 2924 ./usr/include/c++/10.1.0/x86_64-poky-linux/bits/time_members.h
+drwxr-xr-x root root 4096 ./usr/include/c++/10.1.0/x86_64-poky-linux/ext
+-rw-r--r-- root root 4756 ./usr/include/c++/10.1.0/x86_64-poky-linux/ext/opt_random.h
+drwxr-xr-x root root 4096 ./usr/include/cairo
+-rw-r--r-- root root 8698 ./usr/include/cairo/cairo-deprecated.h
+-rw-r--r-- root root 1460 ./usr/include/cairo/cairo-features.h
+-rw-r--r-- root root 3721 ./usr/include/cairo/cairo-ft.h
+-rw-r--r-- root root 5117 ./usr/include/cairo/cairo-gl.h
+-rw-r--r-- root root 6452 ./usr/include/cairo/cairo-gobject.h
+-rw-r--r-- root root 110955 ./usr/include/cairo/cairo.h
+-rw-r--r-- root root 5617 ./usr/include/cairo/cairo-pdf.h
+-rw-r--r-- root root 3632 ./usr/include/cairo/cairo-ps.h
+-rw-r--r-- root root 3072 ./usr/include/cairo/cairo-script.h
+-rw-r--r-- root root 4059 ./usr/include/cairo/cairo-script-interpreter.h
+-rw-r--r-- root root 4504 ./usr/include/cairo/cairo-svg.h
+-rw-r--r-- root root 2173 ./usr/include/cairo/cairo-tee.h
+-rw-r--r-- root root 148 ./usr/include/cairo/cairo-version.h
+-rw-r--r-- root root 3775 ./usr/include/cairo/cairo-xcb.h
+-rw-r--r-- root root 3577 ./usr/include/cairo/cairo-xlib.h
+-rw-r--r-- root root 2436 ./usr/include/cairo/cairo-xlib-xrender.h
+-rw-r--r-- root root 3198 ./usr/include/cap-ng.h
+-rw-r--r-- root root 2118 ./usr/include/com_err.h
+-rw-r--r-- root root 7164 ./usr/include/complex.h
+-rw-r--r-- root root 2268 ./usr/include/cpio.h
+-rw-r--r-- root root 11160 ./usr/include/crypt.h
+-rw-r--r-- root root 19025 ./usr/include/ctf-api.h
+-rw-r--r-- root root 25153 ./usr/include/ctf.h
+-rw-r--r-- root root 10969 ./usr/include/ctype.h
+-rw-r--r-- root root 100249 ./usr/include/curses-64.h
+-rw-r--r-- root root 6878 ./usr/include/cursesapp.h
+-rw-r--r-- root root 28021 ./usr/include/cursesf.h
+-rw-r--r-- root root 512 ./usr/include/curses.h
+-rw-r--r-- root root 19874 ./usr/include/cursesm.h
+-rw-r--r-- root root 8722 ./usr/include/cursesp.h
+-rw-r--r-- root root 49871 ./usr/include/cursesw.h
+-rw-r--r-- root root 7407 ./usr/include/cursslk.h
+drwxr-xr-x root root 4096 ./usr/include/db51
+-rw-r--r-- root root 49057 ./usr/include/db51/db_cxx.h
+-rw-r--r-- root root 123105 ./usr/include/db51/db.h
+lrwxrwxrwx root root 13 ./usr/include/db_cxx.h -> db51/db_cxx.h
+lrwxrwxrwx root root 9 ./usr/include/db.h -> db51/db.h
+-rw-r--r-- root root 1414 ./usr/include/dbm.h
+drwxr-xr-x root root 4096 ./usr/include/dbus-1.0
+drwxr-xr-x root root 4096 ./usr/include/dbus-1.0/dbus
+-rw-r--r-- root root 2812 ./usr/include/dbus-1.0/dbus/dbus-address.h
+-rw-r--r-- root root 3472 ./usr/include/dbus-1.0/dbus/dbus-bus.h
+-rw-r--r-- root root 27020 ./usr/include/dbus-1.0/dbus/dbus-connection.h
+-rw-r--r-- root root 2911 ./usr/include/dbus-1.0/dbus/dbus-errors.h
+-rw-r--r-- root root 3963 ./usr/include/dbus-1.0/dbus/dbus.h
+-rw-r--r-- root root 6757 ./usr/include/dbus-1.0/dbus/dbus-macros.h
+-rw-r--r-- root root 1963 ./usr/include/dbus-1.0/dbus/dbus-memory.h
+-rw-r--r-- root root 15005 ./usr/include/dbus-1.0/dbus/dbus-message.h
+-rw-r--r-- root root 1813 ./usr/include/dbus-1.0/dbus/dbus-misc.h
+-rw-r--r-- root root 3811 ./usr/include/dbus-1.0/dbus/dbus-pending-call.h
+-rw-r--r-- root root 23642 ./usr/include/dbus-1.0/dbus/dbus-protocol.h
+-rw-r--r-- root root 4045 ./usr/include/dbus-1.0/dbus/dbus-python.h
+-rw-r--r-- root root 5414 ./usr/include/dbus-1.0/dbus/dbus-server.h
+-rw-r--r-- root root 5394 ./usr/include/dbus-1.0/dbus/dbus-shared.h
+-rw-r--r-- root root 3049 ./usr/include/dbus-1.0/dbus/dbus-signature.h
+-rw-r--r-- root root 2359 ./usr/include/dbus-1.0/dbus/dbus-syntax.h
+-rw-r--r-- root root 8507 ./usr/include/dbus-1.0/dbus/dbus-threads.h
+-rw-r--r-- root root 4145 ./usr/include/dbus-1.0/dbus/dbus-types.h
+-rw-r--r-- root root 3332 ./usr/include/diagnostics.h
+-rw-r--r-- root root 12515 ./usr/include/dirent.h
+-rw-r--r-- root root 16687 ./usr/include/dis-asm.h
+-rw-r--r-- root root 7479 ./usr/include/dlfcn.h
+drwxr-xr-x root root 4096 ./usr/include/drm
+-rw-r--r-- root root 31894 ./usr/include/drm/amdgpu_drm.h
+-rw-r--r-- root root 1212 ./usr/include/drm/armada_drm.h
+-rw-r--r-- root root 32817 ./usr/include/drm/drm_fourcc.h
+-rw-r--r-- root root 32129 ./usr/include/drm/drm.h
+-rw-r--r-- root root 28604 ./usr/include/drm/drm_mode.h
+-rw-r--r-- root root 2782 ./usr/include/drm/drm_sarea.h
+-rw-r--r-- root root 11822 ./usr/include/drm/etnaviv_drm.h
+-rw-r--r-- root root 11132 ./usr/include/drm/exynos_drm.h
+-rw-r--r-- root root 10061 ./usr/include/drm/i810_drm.h
+-rw-r--r-- root root 70507 ./usr/include/drm/i915_drm.h
+-rw-r--r-- root root 4817 ./usr/include/drm/lima_drm.h
+-rw-r--r-- root root 13010 ./usr/include/drm/mga_drm.h
+-rw-r--r-- root root 13230 ./usr/include/drm/msm_drm.h
+-rw-r--r-- root root 6560 ./usr/include/drm/nouveau_drm.h
+-rw-r--r-- root root 4141 ./usr/include/drm/omap_drm.h
+-rw-r--r-- root root 7346 ./usr/include/drm/panfrost_drm.h
+-rw-r--r-- root root 4131 ./usr/include/drm/qxl_drm.h
+-rw-r--r-- root root 10000 ./usr/include/drm/r128_drm.h
+-rw-r--r-- root root 38236 ./usr/include/drm/radeon_drm.h
+-rw-r--r-- root root 7170 ./usr/include/drm/savage_drm.h
+-rw-r--r-- root root 2637 ./usr/include/drm/sis_drm.h
+-rw-r--r-- root root 14877 ./usr/include/drm/tegra_drm.h
+-rw-r--r-- root root 8671 ./usr/include/drm/v3d_drm.h
+-rw-r--r-- root root 14457 ./usr/include/drm/vc4_drm.h
+-rw-r--r-- root root 1971 ./usr/include/drm/vgem_drm.h
+-rw-r--r-- root root 8345 ./usr/include/drm/via_drm.h
+-rw-r--r-- root root 5010 ./usr/include/drm/virtgpu_drm.h
+-rw-r--r-- root root 35392 ./usr/include/drm/vmwgfx_drm.h
+-rw-r--r-- root root 31014 ./usr/include/dwarf.h
+drwxr-xr-x root root 4096 ./usr/include/e2p
+-rw-r--r-- root root 3252 ./usr/include/e2p/e2p.h
+-rw-r--r-- root root 180099 ./usr/include/elf.h
+drwxr-xr-x root root 4096 ./usr/include/elfutils
+-rw-r--r-- root root 3947 ./usr/include/elfutils/elf-knowledge.h
+-rw-r--r-- root root 41860 ./usr/include/elfutils/known-dwarf.h
+-rw-r--r-- root root 7098 ./usr/include/elfutils/libasm.h
+-rw-r--r-- root root 6452 ./usr/include/elfutils/libdwelf.h
+-rw-r--r-- root root 37558 ./usr/include/elfutils/libdwfl.h
+-rw-r--r-- root root 44920 ./usr/include/elfutils/libdw.h
+-rw-r--r-- root root 1274 ./usr/include/elfutils/version.h
+-rw-r--r-- root root 2299 ./usr/include/endian.h
+-rw-r--r-- root root 2867 ./usr/include/envz.h
+-rw-r--r-- root root 2267 ./usr/include/err.h
+-rw-r--r-- root root 1679 ./usr/include/errno.h
+-rw-r--r-- root root 2282 ./usr/include/error.h
+drwxr-xr-x root root 4096 ./usr/include/et
+-rw-r--r-- root root 2118 ./usr/include/et/com_err.h
+-rw-r--r-- root root 2969 ./usr/include/eti.h
+-rw-r--r-- root root 9775 ./usr/include/etip.h
+-rw-r--r-- root root 1523 ./usr/include/execinfo.h
+-rw-r--r-- root root 3830 ./usr/include/expat_config.h
+-rw-r--r-- root root 5528 ./usr/include/expat_external.h
+-rw-r--r-- root root 41473 ./usr/include/expat.h
+drwxr-xr-x root root 4096 ./usr/include/ext2fs
+-rw-r--r-- root root 22148 ./usr/include/ext2fs/bitops.h
+-rw-r--r-- root root 11847 ./usr/include/ext2fs/ext2_err.h
+-rw-r--r-- root root 2644 ./usr/include/ext2fs/ext2_ext_attr.h
+-rw-r--r-- root root 42075 ./usr/include/ext2fs/ext2_fs.h
+-rw-r--r-- root root 72208 ./usr/include/ext2fs/ext2fs.h
+-rw-r--r-- root root 5391 ./usr/include/ext2fs/ext2_io.h
+-rw-r--r-- root root 4212 ./usr/include/ext2fs/ext2_types-64.h
+-rw-r--r-- root root 556 ./usr/include/ext2fs/ext2_types.h
+-rw-r--r-- root root 4558 ./usr/include/ext2fs/ext3_extents.h
+-rw-r--r-- root root 1179 ./usr/include/ext2fs/hashmap.h
+-rw-r--r-- root root 2588 ./usr/include/ext2fs/qcow2.h
+-rw-r--r-- root root 8871 ./usr/include/ext2fs/tdb.h
+-rw-r--r-- root root 11026 ./usr/include/fcntl.h
+-rw-r--r-- root root 17235 ./usr/include/features.h
+-rw-r--r-- root root 5874 ./usr/include/fenv.h
+-rw-r--r-- root root 13934 ./usr/include/ffi-64.h
+-rw-r--r-- root root 500 ./usr/include/ffi.h
+-rw-r--r-- root root 4343 ./usr/include/ffitarget.h
+drwxr-xr-x root root 4096 ./usr/include/finclude
+-rw-r--r-- root root 2384 ./usr/include/finclude/math-vector-fortran.h
+-rw-r--r-- root root 6893 ./usr/include/FlexLexer.h
+-rw-r--r-- root root 3240 ./usr/include/fmtmsg.h
+-rw-r--r-- root root 2296 ./usr/include/fnmatch.h
+drwxr-xr-x root root 4096 ./usr/include/fontconfig
+-rw-r--r-- root root 1958 ./usr/include/fontconfig/fcfreetype.h
+-rw-r--r-- root root 4489 ./usr/include/fontconfig/fcprivate.h
+-rw-r--r-- root root 28461 ./usr/include/fontconfig/fontconfig.h
+-rw-r--r-- root root 18811 ./usr/include/form.h
+-rw-r--r-- root root 3584 ./usr/include/fpu_control.h
+drwxr-xr-x root root 4096 ./usr/include/freedreno
+-rw-r--r-- root root 4992 ./usr/include/freedreno/freedreno_drmif.h
+-rw-r--r-- root root 4963 ./usr/include/freedreno/freedreno_ringbuffer.h
+drwxr-xr-x root root 4096 ./usr/include/freetype2
+drwxr-xr-x root root 4096 ./usr/include/freetype2/freetype
+drwxr-xr-x root root 4096 ./usr/include/freetype2/freetype/config
+-rw-r--r-- root root 19859 ./usr/include/freetype2/freetype/config/ftconfig-64.h
+-rw-r--r-- root root 624 ./usr/include/freetype2/freetype/config/ftconfig.h
+-rw-r--r-- root root 23228 ./usr/include/freetype2/freetype/config/ftheader.h
+-rw-r--r-- root root 1056 ./usr/include/freetype2/freetype/config/ftmodule.h
+-rw-r--r-- root root 39330 ./usr/include/freetype2/freetype/config/ftoption.h
+-rw-r--r-- root root 4307 ./usr/include/freetype2/freetype/config/ftstdlib.h
+-rw-r--r-- root root 165664 ./usr/include/freetype2/freetype/freetype.h
+-rw-r--r-- root root 5479 ./usr/include/freetype2/freetype/ftadvanc.h
+-rw-r--r-- root root 2652 ./usr/include/freetype2/freetype/ftbbox.h
+-rw-r--r-- root root 5336 ./usr/include/freetype2/freetype/ftbdf.h
+-rw-r--r-- root root 9055 ./usr/include/freetype2/freetype/ftbitmap.h
+-rw-r--r-- root root 2745 ./usr/include/freetype2/freetype/ftbzip2.h
+-rw-r--r-- root root 33870 ./usr/include/freetype2/freetype/ftcache.h
+-rw-r--r-- root root 2510 ./usr/include/freetype2/freetype/ftchapters.h
+-rw-r--r-- root root 4036 ./usr/include/freetype2/freetype/ftcid.h
+-rw-r--r-- root root 8927 ./usr/include/freetype2/freetype/ftcolor.h
+-rw-r--r-- root root 47451 ./usr/include/freetype2/freetype/ftdriver.h
+-rw-r--r-- root root 12336 ./usr/include/freetype2/freetype/fterrdef.h
+-rw-r--r-- root root 8904 ./usr/include/freetype2/freetype/fterrors.h
+-rw-r--r-- root root 2227 ./usr/include/freetype2/freetype/ftfntfmt.h
+-rw-r--r-- root root 4152 ./usr/include/freetype2/freetype/ftgasp.h
+-rw-r--r-- root root 18505 ./usr/include/freetype2/freetype/ftglyph.h
+-rw-r--r-- root root 10639 ./usr/include/freetype2/freetype/ftgxval.h
+-rw-r--r-- root root 4170 ./usr/include/freetype2/freetype/ftgzip.h
+-rw-r--r-- root root 39169 ./usr/include/freetype2/freetype/ftimage.h
+-rw-r--r-- root root 10322 ./usr/include/freetype2/freetype/ftincrem.h
+-rw-r--r-- root root 11969 ./usr/include/freetype2/freetype/ftlcdfil.h
+-rw-r--r-- root root 7114 ./usr/include/freetype2/freetype/ftlist.h
+-rw-r--r-- root root 2726 ./usr/include/freetype2/freetype/ftlzw.h
+-rw-r--r-- root root 7793 ./usr/include/freetype2/freetype/ftmac.h
+-rw-r--r-- root root 21811 ./usr/include/freetype2/freetype/ftmm.h
+-rw-r--r-- root root 21820 ./usr/include/freetype2/freetype/ftmodapi.h
+-rw-r--r-- root root 6598 ./usr/include/freetype2/freetype/ftmoderr.h
+-rw-r--r-- root root 5360 ./usr/include/freetype2/freetype/ftotval.h
+-rw-r--r-- root root 17476 ./usr/include/freetype2/freetype/ftoutln.h
+-rw-r--r-- root root 5606 ./usr/include/freetype2/freetype/ftparams.h
+-rw-r--r-- root root 4924 ./usr/include/freetype2/freetype/ftpfr.h
+-rw-r--r-- root root 6627 ./usr/include/freetype2/freetype/ftrender.h
+-rw-r--r-- root root 4302 ./usr/include/freetype2/freetype/ftsizes.h
+-rw-r--r-- root root 7742 ./usr/include/freetype2/freetype/ftsnames.h
+-rw-r--r-- root root 21778 ./usr/include/freetype2/freetype/ftstroke.h
+-rw-r--r-- root root 3376 ./usr/include/freetype2/freetype/ftsynth.h
+-rw-r--r-- root root 8540 ./usr/include/freetype2/freetype/ftsystem.h
+-rw-r--r-- root root 7403 ./usr/include/freetype2/freetype/fttrigon.h
+-rw-r--r-- root root 14467 ./usr/include/freetype2/freetype/fttypes.h
+-rw-r--r-- root root 7980 ./usr/include/freetype2/freetype/ftwinfnt.h
+-rw-r--r-- root root 22843 ./usr/include/freetype2/freetype/t1tables.h
+-rw-r--r-- root root 58791 ./usr/include/freetype2/freetype/ttnameid.h
+-rw-r--r-- root root 25245 ./usr/include/freetype2/freetype/tttables.h
+-rw-r--r-- root root 5106 ./usr/include/freetype2/freetype/tttags.h
+-rw-r--r-- root root 1111 ./usr/include/freetype2/ft2build.h
+-rw-r--r-- root root 3111 ./usr/include/fstab.h
+-rw-r--r-- root root 8373 ./usr/include/fts.h
+-rw-r--r-- root root 5252 ./usr/include/ftw.h
+-rw-r--r-- root root 40645 ./usr/include/gawkapi.h
+-rw-r--r-- root root 4211 ./usr/include/gconv.h
+drwxr-xr-x root root 4096 ./usr/include/gdbm
+lrwxrwxrwx root root 9 ./usr/include/gdbm/gdbm.h -> ../gdbm.h
+-rw-r--r-- root root 10345 ./usr/include/gdbm.h
+lrwxrwxrwx root root 9 ./usr/include/gdbm/ndbm.h -> ../ndbm.h
+-rw-r--r-- root root 11312 ./usr/include/gelf.h
+-rw-r--r-- root root 1469 ./usr/include/getopt.h
+drwxr-xr-x root root 4096 ./usr/include/gio-unix-2.0
+drwxr-xr-x root root 4096 ./usr/include/gio-unix-2.0/gio
+-rw-r--r-- root root 8679 ./usr/include/gio-unix-2.0/gio/gdesktopappinfo.h
+-rw-r--r-- root root 2218 ./usr/include/gio-unix-2.0/gio/gfiledescriptorbased.h
+-rw-r--r-- root root 5761 ./usr/include/gio-unix-2.0/gio/gunixconnection.h
+-rw-r--r-- root root 3197 ./usr/include/gio-unix-2.0/gio/gunixcredentialsmessage.h
+-rw-r--r-- root root 4245 ./usr/include/gio-unix-2.0/gio/gunixfdlist.h
+-rw-r--r-- root root 3767 ./usr/include/gio-unix-2.0/gio/gunixfdmessage.h
+-rw-r--r-- root root 3018 ./usr/include/gio-unix-2.0/gio/gunixinputstream.h
+-rw-r--r-- root root 7349 ./usr/include/gio-unix-2.0/gio/gunixmounts.h
+-rw-r--r-- root root 3050 ./usr/include/gio-unix-2.0/gio/gunixoutputstream.h
+-rw-r--r-- root root 3424 ./usr/include/gio-unix-2.0/gio/gunixsocketaddress.h
+drwxr-xr-x root root 4096 ./usr/include/GL
+-rw-r--r-- root root 421419 ./usr/include/GL/glcorearb.h
+-rw-r--r-- root root 848217 ./usr/include/GL/glext.h
+-rw-r--r-- root root 80393 ./usr/include/GL/gl.h
+-rw-r--r-- root root 48752 ./usr/include/GL/glxext.h
+-rw-r--r-- root root 14578 ./usr/include/GL/glx.h
+-rw-r--r-- root root 4695 ./usr/include/GL/glxint.h
+-rw-r--r-- root root 2085 ./usr/include/GL/glxmd.h
+-rw-r--r-- root root 78531 ./usr/include/GL/glxproto.h
+-rw-r--r-- root root 11429 ./usr/include/GL/glxtokens.h
+drwxr-xr-x root root 4096 ./usr/include/glib-2.0
+drwxr-xr-x root root 4096 ./usr/include/glib-2.0/gio
+-rw-r--r-- root root 1768 ./usr/include/glib-2.0/gio/gactiongroupexporter.h
+-rw-r--r-- root root 9167 ./usr/include/glib-2.0/gio/gactiongroup.h
+-rw-r--r-- root root 4610 ./usr/include/glib-2.0/gio/gaction.h
+-rw-r--r-- root root 3996 ./usr/include/glib-2.0/gio/gactionmap.h
+-rw-r--r-- root root 19095 ./usr/include/glib-2.0/gio/gappinfo.h
+-rw-r--r-- root root 6168 ./usr/include/glib-2.0/gio/gapplicationcommandline.h
+-rw-r--r-- root root 14551 ./usr/include/glib-2.0/gio/gapplication.h
+-rw-r--r-- root root 4423 ./usr/include/glib-2.0/gio/gasyncinitable.h
+-rw-r--r-- root root 2818 ./usr/include/glib-2.0/gio/gasyncresult.h
+-rw-r--r-- root root 5229 ./usr/include/glib-2.0/gio/gbufferedinputstream.h
+-rw-r--r-- root root 3334 ./usr/include/glib-2.0/gio/gbufferedoutputstream.h
+-rw-r--r-- root root 1652 ./usr/include/glib-2.0/gio/gbytesicon.h
+-rw-r--r-- root root 4058 ./usr/include/glib-2.0/gio/gcancellable.h
+-rw-r--r-- root root 2518 ./usr/include/glib-2.0/gio/gcharsetconverter.h
+-rw-r--r-- root root 2971 ./usr/include/glib-2.0/gio/gcontenttype.h
+-rw-r--r-- root root 2885 ./usr/include/glib-2.0/gio/gconverter.h
+-rw-r--r-- root root 3015 ./usr/include/glib-2.0/gio/gconverterinputstream.h
+-rw-r--r-- root root 3054 ./usr/include/glib-2.0/gio/gconverteroutputstream.h
+-rw-r--r-- root root 3408 ./usr/include/glib-2.0/gio/gcredentials.h
+-rw-r--r-- root root 6661 ./usr/include/glib-2.0/gio/gdatagrambased.h
+-rw-r--r-- root root 11140 ./usr/include/glib-2.0/gio/gdatainputstream.h
+-rw-r--r-- root root 4923 ./usr/include/glib-2.0/gio/gdataoutputstream.h
+-rw-r--r-- root root 2739 ./usr/include/glib-2.0/gio/gdbusactiongroup.h
+-rw-r--r-- root root 2670 ./usr/include/glib-2.0/gio/gdbusaddress.h
+-rw-r--r-- root root 2130 ./usr/include/glib-2.0/gio/gdbusauthobserver.h
+-rw-r--r-- root root 38873 ./usr/include/glib-2.0/gio/gdbusconnection.h
+-rw-r--r-- root root 4306 ./usr/include/glib-2.0/gio/gdbuserror.h
+-rw-r--r-- root root 3069 ./usr/include/glib-2.0/gio/gdbusinterface.h
+-rw-r--r-- root root 6055 ./usr/include/glib-2.0/gio/gdbusinterfaceskeleton.h
+-rw-r--r-- root root 12393 ./usr/include/glib-2.0/gio/gdbusintrospection.h
+-rw-r--r-- root root 1730 ./usr/include/glib-2.0/gio/gdbusmenumodel.h
+-rw-r--r-- root root 11383 ./usr/include/glib-2.0/gio/gdbusmessage.h
+-rw-r--r-- root root 5801 ./usr/include/glib-2.0/gio/gdbusmethodinvocation.h
+-rw-r--r-- root root 4877 ./usr/include/glib-2.0/gio/gdbusnameowning.h
+-rw-r--r-- root root 4521 ./usr/include/glib-2.0/gio/gdbusnamewatching.h
+-rw-r--r-- root root 2941 ./usr/include/glib-2.0/gio/gdbusobject.h
+-rw-r--r-- root root 9800 ./usr/include/glib-2.0/gio/gdbusobjectmanagerclient.h
+-rw-r--r-- root root 4474 ./usr/include/glib-2.0/gio/gdbusobjectmanager.h
+-rw-r--r-- root root 4120 ./usr/include/glib-2.0/gio/gdbusobjectmanagerserver.h
+-rw-r--r-- root root 2635 ./usr/include/glib-2.0/gio/gdbusobjectproxy.h
+-rw-r--r-- root root 3957 ./usr/include/glib-2.0/gio/gdbusobjectskeleton.h
+-rw-r--r-- root root 12082 ./usr/include/glib-2.0/gio/gdbusproxy.h
+-rw-r--r-- root root 2534 ./usr/include/glib-2.0/gio/gdbusserver.h
+-rw-r--r-- root root 1779 ./usr/include/glib-2.0/gio/gdbusutils.h
+-rw-r--r-- root root 14503 ./usr/include/glib-2.0/gio/gdrive.h
+-rw-r--r-- root root 3197 ./usr/include/glib-2.0/gio/gdtlsclientconnection.h
+-rw-r--r-- root root 11430 ./usr/include/glib-2.0/gio/gdtlsconnection.h
+-rw-r--r-- root root 2446 ./usr/include/glib-2.0/gio/gdtlsserverconnection.h
+-rw-r--r-- root root 2788 ./usr/include/glib-2.0/gio/gemblemedicon.h
+-rw-r--r-- root root 2155 ./usr/include/glib-2.0/gio/gemblem.h
+-rw-r--r-- root root 2801 ./usr/include/glib-2.0/gio/gfileattribute.h
+-rw-r--r-- root root 6393 ./usr/include/glib-2.0/gio/gfileenumerator.h
+-rw-r--r-- root root 79870 ./usr/include/glib-2.0/gio/gfile.h
+-rw-r--r-- root root 1959 ./usr/include/glib-2.0/gio/gfileicon.h
+-rw-r--r-- root root 44335 ./usr/include/glib-2.0/gio/gfileinfo.h
+-rw-r--r-- root root 4656 ./usr/include/glib-2.0/gio/gfileinputstream.h
+-rw-r--r-- root root 5041 ./usr/include/glib-2.0/gio/gfileiostream.h
+-rw-r--r-- root root 3280 ./usr/include/glib-2.0/gio/gfilemonitor.h
+-rw-r--r-- root root 3090 ./usr/include/glib-2.0/gio/gfilenamecompleter.h
+-rw-r--r-- root root 5338 ./usr/include/glib-2.0/gio/gfileoutputstream.h
+-rw-r--r-- root root 2832 ./usr/include/glib-2.0/gio/gfilterinputstream.h
+-rw-r--r-- root root 2875 ./usr/include/glib-2.0/gio/gfilteroutputstream.h
+-rw-r--r-- root root 3435 ./usr/include/glib-2.0/gio/gicon.h
+-rw-r--r-- root root 4529 ./usr/include/glib-2.0/gio/ginetaddress.h
+-rw-r--r-- root root 3119 ./usr/include/glib-2.0/gio/ginetaddressmask.h
+-rw-r--r-- root root 3111 ./usr/include/glib-2.0/gio/ginetsocketaddress.h
+-rw-r--r-- root root 2976 ./usr/include/glib-2.0/gio/ginitable.h
+-rw-r--r-- root root 9188 ./usr/include/glib-2.0/gio/ginputstream.h
+-rw-r--r-- root root 9066 ./usr/include/glib-2.0/gio/gio-autocleanups.h
+-rw-r--r-- root root 76503 ./usr/include/glib-2.0/gio/gioenums.h
+-rw-r--r-- root root 12517 ./usr/include/glib-2.0/gio/gioenumtypes.h
+-rw-r--r-- root root 1558 ./usr/include/glib-2.0/gio/gioerror.h
+-rw-r--r-- root root 5646 ./usr/include/glib-2.0/gio/gio.h
+-rw-r--r-- root root 8064 ./usr/include/glib-2.0/gio/giomodule.h
+-rw-r--r-- root root 1999 ./usr/include/glib-2.0/gio/gioscheduler.h
+-rw-r--r-- root root 4862 ./usr/include/glib-2.0/gio/giostream.h
+-rw-r--r-- root root 24681 ./usr/include/glib-2.0/gio/giotypes.h
+-rw-r--r-- root root 2576 ./usr/include/glib-2.0/gio/glistmodel.h
+-rw-r--r-- root root 4178 ./usr/include/glib-2.0/gio/gliststore.h
+-rw-r--r-- root root 3671 ./usr/include/glib-2.0/gio/gloadableicon.h
+-rw-r--r-- root root 3434 ./usr/include/glib-2.0/gio/gmemoryinputstream.h
+-rw-r--r-- root root 2140 ./usr/include/glib-2.0/gio/gmemorymonitor.h
+-rw-r--r-- root root 3933 ./usr/include/glib-2.0/gio/gmemoryoutputstream.h
+-rw-r--r-- root root 1611 ./usr/include/glib-2.0/gio/gmenuexporter.h
+-rw-r--r-- root root 8940 ./usr/include/glib-2.0/gio/gmenu.h
+-rw-r--r-- root root 14334 ./usr/include/glib-2.0/gio/gmenumodel.h
+-rw-r--r-- root root 15791 ./usr/include/glib-2.0/gio/gmount.h
+-rw-r--r-- root root 6765 ./usr/include/glib-2.0/gio/gmountoperation.h
+-rw-r--r-- root root 2536 ./usr/include/glib-2.0/gio/gnativesocketaddress.h
+-rw-r--r-- root root 2270 ./usr/include/glib-2.0/gio/gnativevolumemonitor.h
+-rw-r--r-- root root 2956 ./usr/include/glib-2.0/gio/gnetworkaddress.h
+-rw-r--r-- root root 1994 ./usr/include/glib-2.0/gio/gnetworking.h
+-rw-r--r-- root root 4239 ./usr/include/glib-2.0/gio/gnetworkmonitor.h
+-rw-r--r-- root root 2756 ./usr/include/glib-2.0/gio/gnetworkservice.h
+-rw-r--r-- root root 4898 ./usr/include/glib-2.0/gio/gnotification.h
+-rw-r--r-- root root 15760 ./usr/include/glib-2.0/gio/goutputstream.h
+-rw-r--r-- root root 5862 ./usr/include/glib-2.0/gio/gpermission.h
+-rw-r--r-- root root 3829 ./usr/include/glib-2.0/gio/gpollableinputstream.h
+-rw-r--r-- root root 4919 ./usr/include/glib-2.0/gio/gpollableoutputstream.h
+-rw-r--r-- root root 2134 ./usr/include/glib-2.0/gio/gpollableutils.h
+-rw-r--r-- root root 1994 ./usr/include/glib-2.0/gio/gpropertyaction.h
+-rw-r--r-- root root 2939 ./usr/include/glib-2.0/gio/gproxyaddressenumerator.h
+-rw-r--r-- root root 3166 ./usr/include/glib-2.0/gio/gproxyaddress.h
+-rw-r--r-- root root 4067 ./usr/include/glib-2.0/gio/gproxy.h
+-rw-r--r-- root root 3393 ./usr/include/glib-2.0/gio/gproxyresolver.h
+-rw-r--r-- root root 3635 ./usr/include/glib-2.0/gio/gremoteactiongroup.h
+-rw-r--r-- root root 16852 ./usr/include/glib-2.0/gio/gresolver.h
+-rw-r--r-- root root 4651 ./usr/include/glib-2.0/gio/gresource.h
+-rw-r--r-- root root 3280 ./usr/include/glib-2.0/gio/gseekable.h
+-rw-r--r-- root root 8508 ./usr/include/glib-2.0/gio/gsettingsbackend.h
+-rw-r--r-- root root 21148 ./usr/include/glib-2.0/gio/gsettings.h
+-rw-r--r-- root root 5933 ./usr/include/glib-2.0/gio/gsettingsschema.h
+-rw-r--r-- root root 4355 ./usr/include/glib-2.0/gio/gsimpleactiongroup.h
+-rw-r--r-- root root 2915 ./usr/include/glib-2.0/gio/gsimpleaction.h
+-rw-r--r-- root root 7809 ./usr/include/glib-2.0/gio/gsimpleasyncresult.h
+-rw-r--r-- root root 1722 ./usr/include/glib-2.0/gio/gsimpleiostream.h
+-rw-r--r-- root root 1686 ./usr/include/glib-2.0/gio/gsimplepermission.h
+-rw-r--r-- root root 3531 ./usr/include/glib-2.0/gio/gsimpleproxyresolver.h
+-rw-r--r-- root root 3897 ./usr/include/glib-2.0/gio/gsocketaddressenumerator.h
+-rw-r--r-- root root 3086 ./usr/include/glib-2.0/gio/gsocketaddress.h
+-rw-r--r-- root root 11211 ./usr/include/glib-2.0/gio/gsocketclient.h
+-rw-r--r-- root root 2886 ./usr/include/glib-2.0/gio/gsocketconnectable.h
+-rw-r--r-- root root 5056 ./usr/include/glib-2.0/gio/gsocketconnection.h
+-rw-r--r-- root root 4886 ./usr/include/glib-2.0/gio/gsocketcontrolmessage.h
+-rw-r--r-- root root 16181 ./usr/include/glib-2.0/gio/gsocket.h
+-rw-r--r-- root root 7680 ./usr/include/glib-2.0/gio/gsocketlistener.h
+-rw-r--r-- root root 3620 ./usr/include/glib-2.0/gio/gsocketservice.h
+-rw-r--r-- root root 1936 ./usr/include/glib-2.0/gio/gsrvtarget.h
+-rw-r--r-- root root 8606 ./usr/include/glib-2.0/gio/gsubprocess.h
+-rw-r--r-- root root 6399 ./usr/include/glib-2.0/gio/gsubprocesslauncher.h
+-rw-r--r-- root root 8278 ./usr/include/glib-2.0/gio/gtask.h
+-rw-r--r-- root root 2957 ./usr/include/glib-2.0/gio/gtcpconnection.h
+-rw-r--r-- root root 2973 ./usr/include/glib-2.0/gio/gtcpwrapperconnection.h
+-rw-r--r-- root root 2303 ./usr/include/glib-2.0/gio/gtestdbus.h
+-rw-r--r-- root root 2643 ./usr/include/glib-2.0/gio/gthemedicon.h
+-rw-r--r-- root root 3665 ./usr/include/glib-2.0/gio/gthreadedsocketservice.h
+-rw-r--r-- root root 4587 ./usr/include/glib-2.0/gio/gtlsbackend.h
+-rw-r--r-- root root 3505 ./usr/include/glib-2.0/gio/gtlscertificate.h
+-rw-r--r-- root root 3683 ./usr/include/glib-2.0/gio/gtlsclientconnection.h
+-rw-r--r-- root root 6575 ./usr/include/glib-2.0/gio/gtlsconnection.h
+-rw-r--r-- root root 17271 ./usr/include/glib-2.0/gio/gtlsdatabase.h
+-rw-r--r-- root root 1909 ./usr/include/glib-2.0/gio/gtlsfiledatabase.h
+-rw-r--r-- root root 8333 ./usr/include/glib-2.0/gio/gtlsinteraction.h
+-rw-r--r-- root root 4818 ./usr/include/glib-2.0/gio/gtlspassword.h
+-rw-r--r-- root root 2348 ./usr/include/glib-2.0/gio/gtlsserverconnection.h
+-rw-r--r-- root root 6616 ./usr/include/glib-2.0/gio/gvfs.h
+-rw-r--r-- root root 11736 ./usr/include/glib-2.0/gio/gvolume.h
+-rw-r--r-- root root 5998 ./usr/include/glib-2.0/gio/gvolumemonitor.h
+-rw-r--r-- root root 2350 ./usr/include/glib-2.0/gio/gzlibcompressor.h
+-rw-r--r-- root root 2212 ./usr/include/glib-2.0/gio/gzlibdecompressor.h
+drwxr-xr-x root root 4096 ./usr/include/glib-2.0/glib
+drwxr-xr-x root root 4096 ./usr/include/glib-2.0/glib/deprecated
+-rw-r--r-- root root 3256 ./usr/include/glib-2.0/glib/deprecated/gallocator.h
+-rw-r--r-- root root 2987 ./usr/include/glib-2.0/glib/deprecated/gcache.h
+-rw-r--r-- root root 2922 ./usr/include/glib-2.0/glib/deprecated/gcompletion.h
+-rw-r--r-- root root 4392 ./usr/include/glib-2.0/glib/deprecated/gmain.h
+-rw-r--r-- root root 3682 ./usr/include/glib-2.0/glib/deprecated/grel.h
+-rw-r--r-- root root 10938 ./usr/include/glib-2.0/glib/deprecated/gthread.h
+-rw-r--r-- root root 3912 ./usr/include/glib-2.0/glib/galloca.h
+-rw-r--r-- root root 11385 ./usr/include/glib-2.0/glib/garray.h
+-rw-r--r-- root root 5726 ./usr/include/glib-2.0/glib/gasyncqueue.h
+-rw-r--r-- root root 23740 ./usr/include/glib-2.0/glib/gatomic.h
+-rw-r--r-- root root 2727 ./usr/include/glib-2.0/glib/gbacktrace.h
+-rw-r--r-- root root 2323 ./usr/include/glib-2.0/glib/gbase64.h
+-rw-r--r-- root root 2902 ./usr/include/glib-2.0/glib/gbitlock.h
+-rw-r--r-- root root 9596 ./usr/include/glib-2.0/glib/gbookmarkfile.h
+-rw-r--r-- root root 3334 ./usr/include/glib-2.0/glib/gbytes.h
+-rw-r--r-- root root 1578 ./usr/include/glib-2.0/glib/gcharset.h
+-rw-r--r-- root root 3864 ./usr/include/glib-2.0/glib/gchecksum.h
+-rw-r--r-- root root 5923 ./usr/include/glib-2.0/glib/gconvert.h
+-rw-r--r-- root root 6245 ./usr/include/glib-2.0/glib/gdataset.h
+-rw-r--r-- root root 12420 ./usr/include/glib-2.0/glib/gdate.h
+-rw-r--r-- root root 12738 ./usr/include/glib-2.0/glib/gdatetime.h
+-rw-r--r-- root root 1641 ./usr/include/glib-2.0/glib/gdir.h
+-rw-r--r-- root root 2364 ./usr/include/glib-2.0/glib/genviron.h
+-rw-r--r-- root root 3943 ./usr/include/glib-2.0/glib/gerror.h
+-rw-r--r-- root root 5813 ./usr/include/glib-2.0/glib/gfileutils.h
+-rw-r--r-- root root 2424 ./usr/include/glib-2.0/glib/ggettext.h
+-rw-r--r-- root root 7886 ./usr/include/glib-2.0/glib/ghash.h
+-rw-r--r-- root root 3469 ./usr/include/glib-2.0/glib/ghmac.h
+-rw-r--r-- root root 6358 ./usr/include/glib-2.0/glib/ghook.h
+-rw-r--r-- root root 1456 ./usr/include/glib-2.0/glib/ghostutils.h
+-rw-r--r-- root root 1167 ./usr/include/glib-2.0/glib/gi18n.h
+-rw-r--r-- root root 1370 ./usr/include/glib-2.0/glib/gi18n-lib.h
+-rw-r--r-- root root 13954 ./usr/include/glib-2.0/glib/giochannel.h
+-rw-r--r-- root root 14913 ./usr/include/glib-2.0/glib/gkeyfile.h
+-rw-r--r-- root root 4789 ./usr/include/glib-2.0/glib/glib-autocleanups.h
+-rw-r--r-- root root 6930 ./usr/include/glib-2.0/glib/glist.h
+-rw-r--r-- root root 42372 ./usr/include/glib-2.0/glib/gmacros.h
+-rw-r--r-- root root 28138 ./usr/include/glib-2.0/glib/gmain.h
+-rw-r--r-- root root 1986 ./usr/include/glib-2.0/glib/gmappedfile.h
+-rw-r--r-- root root 10876 ./usr/include/glib-2.0/glib/gmarkup.h
+-rw-r--r-- root root 14684 ./usr/include/glib-2.0/glib/gmem.h
+-rw-r--r-- root root 26913 ./usr/include/glib-2.0/glib/gmessages.h
+-rw-r--r-- root root 8700 ./usr/include/glib-2.0/glib/gnode.h
+-rw-r--r-- root root 16099 ./usr/include/glib-2.0/glib/goption.h
+-rw-r--r-- root root 1782 ./usr/include/glib-2.0/glib/gpattern.h
+-rw-r--r-- root root 4125 ./usr/include/glib-2.0/glib/gpoll.h
+-rw-r--r-- root root 1694 ./usr/include/glib-2.0/glib/gprimes.h
+-rw-r--r-- root root 1984 ./usr/include/glib-2.0/glib/gprintf.h
+-rw-r--r-- root root 1499 ./usr/include/glib-2.0/glib/gqsort.h
+-rw-r--r-- root root 2688 ./usr/include/glib-2.0/glib/gquark.h
+-rw-r--r-- root root 7750 ./usr/include/glib-2.0/glib/gqueue.h
+-rw-r--r-- root root 3182 ./usr/include/glib-2.0/glib/grand.h
+-rw-r--r-- root root 3764 ./usr/include/glib-2.0/glib/grcbox.h
+-rw-r--r-- root root 3988 ./usr/include/glib-2.0/glib/grefcount.h
+-rw-r--r-- root root 1868 ./usr/include/glib-2.0/glib/grefstring.h
+-rw-r--r-- root root 28095 ./usr/include/glib-2.0/glib/gregex.h
+-rw-r--r-- root root 8861 ./usr/include/glib-2.0/glib/gscanner.h
+-rw-r--r-- root root 8811 ./usr/include/glib-2.0/glib/gsequence.h
+-rw-r--r-- root root 1752 ./usr/include/glib-2.0/glib/gshell.h
+-rw-r--r-- root root 3892 ./usr/include/glib-2.0/glib/gslice.h
+-rw-r--r-- root root 6551 ./usr/include/glib-2.0/glib/gslist.h
+-rw-r--r-- root root 11874 ./usr/include/glib-2.0/glib/gspawn.h
+-rw-r--r-- root root 5109 ./usr/include/glib-2.0/glib/gstdio.h
+-rw-r--r-- root root 13232 ./usr/include/glib-2.0/glib/gstrfuncs.h
+-rw-r--r-- root root 2130 ./usr/include/glib-2.0/glib/gstringchunk.h
+-rw-r--r-- root root 8045 ./usr/include/glib-2.0/glib/gstring.h
+-rw-r--r-- root root 31435 ./usr/include/glib-2.0/glib/gtestutils.h
+-rw-r--r-- root root 17496 ./usr/include/glib-2.0/glib/gthread.h
+-rw-r--r-- root root 3824 ./usr/include/glib-2.0/glib/gthreadpool.h
+-rw-r--r-- root root 2576 ./usr/include/glib-2.0/glib/gtimer.h
+-rw-r--r-- root root 3723 ./usr/include/glib-2.0/glib/gtimezone.h
+-rw-r--r-- root root 1906 ./usr/include/glib-2.0/glib/gtrashstack.h
+-rw-r--r-- root root 4194 ./usr/include/glib-2.0/glib/gtree.h
+-rw-r--r-- root root 20493 ./usr/include/glib-2.0/glib/gtypes.h
+-rw-r--r-- root root 40690 ./usr/include/glib-2.0/glib/gunicode.h
+-rw-r--r-- root root 2716 ./usr/include/glib-2.0/glib/gurifuncs.h
+-rw-r--r-- root root 14564 ./usr/include/glib-2.0/glib/gutils.h
+-rw-r--r-- root root 1291 ./usr/include/glib-2.0/glib/guuid.h
+-rw-r--r-- root root 29560 ./usr/include/glib-2.0/glib/gvariant.h
+-rw-r--r-- root root 13244 ./usr/include/glib-2.0/glib/gvarianttype.h
+-rw-r--r-- root root 1981 ./usr/include/glib-2.0/glib/gversion.h
+-rw-r--r-- root root 40799 ./usr/include/glib-2.0/glib/gversionmacros.h
+-rw-r--r-- root root 4667 ./usr/include/glib-2.0/glib/gwin32.h
+-rw-r--r-- root root 3381 ./usr/include/glib-2.0/glib.h
+-rw-r--r-- root root 1462 ./usr/include/glib-2.0/glib-object.h
+-rw-r--r-- root root 4461 ./usr/include/glib-2.0/glib-unix.h
+-rw-r--r-- root root 4318 ./usr/include/glib-2.0/gmodule.h
+drwxr-xr-x root root 4096 ./usr/include/glib-2.0/gobject
+-rw-r--r-- root root 6342 ./usr/include/glib-2.0/gobject/gbinding.h
+-rw-r--r-- root root 3965 ./usr/include/glib-2.0/gobject/gboxed.h
+-rw-r--r-- root root 11053 ./usr/include/glib-2.0/gobject/gclosure.h
+-rw-r--r-- root root 8041 ./usr/include/glib-2.0/gobject/genums.h
+-rw-r--r-- root root 1026 ./usr/include/glib-2.0/gobject/glib-enumtypes.h
+-rw-r--r-- root root 8656 ./usr/include/glib-2.0/gobject/glib-types.h
+-rw-r--r-- root root 21841 ./usr/include/glib-2.0/gobject/gmarshal.h
+-rw-r--r-- root root 1382 ./usr/include/glib-2.0/gobject/gobject-autocleanups.h
+-rw-r--r-- root root 34088 ./usr/include/glib-2.0/gobject/gobject.h
+-rw-r--r-- root root 5516 ./usr/include/glib-2.0/gobject/gobjectnotifyqueue.c
+-rw-r--r-- root root 16431 ./usr/include/glib-2.0/gobject/gparam.h
+-rw-r--r-- root root 34850 ./usr/include/glib-2.0/gobject/gparamspecs.h
+-rw-r--r-- root root 24872 ./usr/include/glib-2.0/gobject/gsignal.h
+-rw-r--r-- root root 1275 ./usr/include/glib-2.0/gobject/gsourceclosure.h
+-rw-r--r-- root root 92450 ./usr/include/glib-2.0/gobject/gtype.h
+-rw-r--r-- root root 10837 ./usr/include/glib-2.0/gobject/gtypemodule.h
+-rw-r--r-- root root 4965 ./usr/include/glib-2.0/gobject/gtypeplugin.h
+-rw-r--r-- root root 3218 ./usr/include/glib-2.0/gobject/gvaluearray.h
+-rw-r--r-- root root 9817 ./usr/include/glib-2.0/gobject/gvaluecollector.h
+-rw-r--r-- root root 5656 ./usr/include/glib-2.0/gobject/gvalue.h
+-rw-r--r-- root root 9653 ./usr/include/glib-2.0/gobject/gvaluetypes.h
+drwxr-xr-x root root 4096 ./usr/include/GL/internal
+-rw-r--r-- root root 78637 ./usr/include/GL/internal/dri_interface.h
+-rw-r--r-- root root 6315 ./usr/include/GL/internal/glcore.h
+-rw-r--r-- root root 6617 ./usr/include/glob.h
+-rw-r--r-- root root 84177 ./usr/include/gmp-64.h
+-rw-r--r-- root root 500 ./usr/include/gmp.h
+-rw-r--r-- root root 129113 ./usr/include/gmpxx.h
+drwxr-xr-x root root 4096 ./usr/include/gnu
+-rw-r--r-- root root 1264 ./usr/include/gnu/libc-version.h
+-rw-r--r-- root root 1665 ./usr/include/gnu/lib-names-64.h
+-rw-r--r-- root root 467 ./usr/include/gnu/lib-names.h
+-rw-r--r-- root root 2912 ./usr/include/gnumake.h
+-rw-r--r-- root root 523 ./usr/include/gnu/stubs-64.h
+-rw-r--r-- root root 384 ./usr/include/gnu/stubs.h
+-rw-r--r-- root root 2343 ./usr/include/gnu-versions.h
+drwxr-xr-x root root 4096 ./usr/include/gobject-introspection-1.0
+-rw-r--r-- root root 2622 ./usr/include/gobject-introspection-1.0/giarginfo.h
+-rw-r--r-- root root 3275 ./usr/include/gobject-introspection-1.0/gibaseinfo.h
+-rw-r--r-- root root 4523 ./usr/include/gobject-introspection-1.0/gicallableinfo.h
+-rw-r--r-- root root 1769 ./usr/include/gobject-introspection-1.0/giconstantinfo.h
+-rw-r--r-- root root 2348 ./usr/include/gobject-introspection-1.0/gienuminfo.h
+-rw-r--r-- root root 2129 ./usr/include/gobject-introspection-1.0/gifieldinfo.h
+-rw-r--r-- root root 2877 ./usr/include/gobject-introspection-1.0/gifunctioninfo.h
+-rw-r--r-- root root 3418 ./usr/include/gobject-introspection-1.0/giinterfaceinfo.h
+-rw-r--r-- root root 6060 ./usr/include/gobject-introspection-1.0/giobjectinfo.h
+-rw-r--r-- root root 1685 ./usr/include/gobject-introspection-1.0/gipropertyinfo.h
+-rw-r--r-- root root 2363 ./usr/include/gobject-introspection-1.0/giregisteredtypeinfo.h
+-rw-r--r-- root root 8052 ./usr/include/gobject-introspection-1.0/girepository.h
+-rw-r--r-- root root 3468 ./usr/include/gobject-introspection-1.0/girffi.h
+-rw-r--r-- root root 1696 ./usr/include/gobject-introspection-1.0/gisignalinfo.h
+-rw-r--r-- root root 2403 ./usr/include/gobject-introspection-1.0/gistructinfo.h
+-rw-r--r-- root root 2556 ./usr/include/gobject-introspection-1.0/gitypeinfo.h
+-rw-r--r-- root root 2327 ./usr/include/gobject-introspection-1.0/gitypelib.h
+-rw-r--r-- root root 14019 ./usr/include/gobject-introspection-1.0/gitypes.h
+-rw-r--r-- root root 2558 ./usr/include/gobject-introspection-1.0/giunioninfo.h
+-rw-r--r-- root root 1578 ./usr/include/gobject-introspection-1.0/giversion.h
+-rw-r--r-- root root 5730 ./usr/include/gobject-introspection-1.0/giversionmacros.h
+-rw-r--r-- root root 2572 ./usr/include/gobject-introspection-1.0/givfuncinfo.h
+-rw-r--r-- root root 6687 ./usr/include/grp.h
+-rw-r--r-- root root 4529 ./usr/include/gshadow.h
+-rw-r--r-- root root 1858 ./usr/include/iconv.h
+-rw-r--r-- root root 4916 ./usr/include/ieee754.h
+-rw-r--r-- root root 2841 ./usr/include/ifaddrs.h
+-rw-r--r-- root root 2446 ./usr/include/initreq.h
+-rw-r--r-- root root 11893 ./usr/include/inttypes.h
+drwxr-xr-x root root 4096 ./usr/include/iproute2
+-rw-r--r-- root root 1271 ./usr/include/iproute2/bpf_elf.h
+-rw-r--r-- root root 17849 ./usr/include/langinfo.h
+-rw-r--r-- root root 126 ./usr/include/lastlog.h
+drwxr-xr-x root root 4096 ./usr/include/libdrm
+-rw-r--r-- root root 31894 ./usr/include/libdrm/amdgpu_drm.h
+-rw-r--r-- root root 55079 ./usr/include/libdrm/amdgpu.h
+-rw-r--r-- root root 32818 ./usr/include/libdrm/drm_fourcc.h
+-rw-r--r-- root root 32306 ./usr/include/libdrm/drm.h
+-rw-r--r-- root root 24920 ./usr/include/libdrm/drm_mode.h
+-rw-r--r-- root root 2782 ./usr/include/libdrm/drm_sarea.h
+-rw-r--r-- root root 6977 ./usr/include/libdrm/etnaviv_drmif.h
+-rw-r--r-- root root 62951 ./usr/include/libdrm/i915_drm.h
+-rw-r--r-- root root 5933 ./usr/include/libdrm/intel_aub.h
+-rw-r--r-- root root 12892 ./usr/include/libdrm/intel_bufmgr.h
+-rw-r--r-- root root 1585 ./usr/include/libdrm/intel_debug.h
+-rw-r--r-- root root 7895 ./usr/include/libdrm/mach64_drm.h
+-rw-r--r-- root root 13010 ./usr/include/libdrm/mga_drm.h
+-rw-r--r-- root root 12105 ./usr/include/libdrm/msm_drm.h
+drwxr-xr-x root root 4096 ./usr/include/libdrm/nouveau
+-rw-r--r-- root root 5699 ./usr/include/libdrm/nouveau_drm.h
+-rw-r--r-- root root 7766 ./usr/include/libdrm/nouveau/nouveau.h
+drwxr-xr-x root root 4096 ./usr/include/libdrm/nouveau/nvif
+-rw-r--r-- root root 1785 ./usr/include/libdrm/nouveau/nvif/cl0080.h
+-rw-r--r-- root root 2062 ./usr/include/libdrm/nouveau/nvif/cl9097.h
+-rw-r--r-- root root 8789 ./usr/include/libdrm/nouveau/nvif/class.h
+-rw-r--r-- root root 769 ./usr/include/libdrm/nouveau/nvif/if0002.h
+-rw-r--r-- root root 645 ./usr/include/libdrm/nouveau/nvif/if0003.h
+-rw-r--r-- root root 3174 ./usr/include/libdrm/nouveau/nvif/ioctl.h
+-rw-r--r-- root root 1551 ./usr/include/libdrm/nouveau/nvif/unpack.h
+-rw-r--r-- root root 2555 ./usr/include/libdrm/omap_drmif.h
+-rw-r--r-- root root 4131 ./usr/include/libdrm/qxl_drm.h
+-rw-r--r-- root root 10000 ./usr/include/libdrm/r128_drm.h
+-rw-r--r-- root root 16388 ./usr/include/libdrm/r600_pci_ids.h
+-rw-r--r-- root root 1991 ./usr/include/libdrm/radeon_bo_gem.h
+-rw-r--r-- root root 2839 ./usr/include/libdrm/radeon_bo.h
+-rw-r--r-- root root 1678 ./usr/include/libdrm/radeon_bo_int.h
+-rw-r--r-- root root 1601 ./usr/include/libdrm/radeon_cs_gem.h
+-rw-r--r-- root root 5121 ./usr/include/libdrm/radeon_cs.h
+-rw-r--r-- root root 2179 ./usr/include/libdrm/radeon_cs_int.h
+-rw-r--r-- root root 38317 ./usr/include/libdrm/radeon_drm.h
+-rw-r--r-- root root 5968 ./usr/include/libdrm/radeon_surface.h
+-rw-r--r-- root root 7170 ./usr/include/libdrm/savage_drm.h
+-rw-r--r-- root root 2633 ./usr/include/libdrm/sis_drm.h
+-rw-r--r-- root root 14877 ./usr/include/libdrm/tegra_drm.h
+-rw-r--r-- root root 14457 ./usr/include/libdrm/vc4_drm.h
+-rw-r--r-- root root 16906 ./usr/include/libdrm/vc4_packet.h
+-rw-r--r-- root root 8244 ./usr/include/libdrm/vc4_qpu_defines.h
+-rw-r--r-- root root 8372 ./usr/include/libdrm/via_drm.h
+-rw-r--r-- root root 5010 ./usr/include/libdrm/virtgpu_drm.h
+-rw-r--r-- root root 32085 ./usr/include/libdrm/vmwgfx_drm.h
+-rw-r--r-- root root 19573 ./usr/include/libelf.h
+drwxr-xr-x root root 4096 ./usr/include/libfdisk
+-rw-r--r-- root root 29857 ./usr/include/libfdisk/libfdisk.h
+-rw-r--r-- root root 1386 ./usr/include/libgen.h
+drwxr-xr-x root root 4096 ./usr/include/libiberty
+-rw-r--r-- root root 14130 ./usr/include/libiberty/ansidecl.h
+-rw-r--r-- root root 27301 ./usr/include/libiberty/demangle.h
+-rw-r--r-- root root 2706 ./usr/include/libiberty/dyn-string.h
+-rw-r--r-- root root 2937 ./usr/include/libiberty/fibheap.h
+-rw-r--r-- root root 5890 ./usr/include/libiberty/floatformat.h
+-rw-r--r-- root root 27820 ./usr/include/libiberty.h
+-rw-r--r-- root root 7270 ./usr/include/libiberty/hashtab.h
+-rw-r--r-- root root 27820 ./usr/include/libiberty/libiberty.h
+-rw-r--r-- root root 3976 ./usr/include/libiberty/objalloc.h
+-rw-r--r-- root root 2824 ./usr/include/libiberty/partition.h
+-rw-r--r-- root root 5642 ./usr/include/libiberty/safe-ctype.h
+-rw-r--r-- root root 1209 ./usr/include/libiberty/sort.h
+-rw-r--r-- root root 6238 ./usr/include/libiberty/splay-tree.h
+-rw-r--r-- root root 1296 ./usr/include/libiberty/timeval-utils.h
+-rw-r--r-- root root 4580 ./usr/include/libintl.h
+drwxr-xr-x root root 4096 ./usr/include/libiptc
+-rw-r--r-- root root 360 ./usr/include/libiptc/ipt_kernel_headers.h
+-rw-r--r-- root root 5375 ./usr/include/libiptc/libip6tc.h
+-rw-r--r-- root root 5447 ./usr/include/libiptc/libiptc.h
+-rw-r--r-- root root 724 ./usr/include/libiptc/libxtc.h
+-rw-r--r-- root root 867 ./usr/include/libiptc/xtcshared.h
+-rw-r--r-- root root 9468 ./usr/include/libkmod.h
+drwxr-xr-x root root 4096 ./usr/include/libkms
+-rw-r--r-- root root 2571 ./usr/include/libkms/libkms.h
+drwxr-xr-x root root 4096 ./usr/include/libmnl
+-rw-r--r-- root root 8002 ./usr/include/libmnl/libmnl.h
+drwxr-xr-x root root 4096 ./usr/include/libmount
+-rw-r--r-- root root 36308 ./usr/include/libmount/libmount.h
+drwxr-xr-x root root 4096 ./usr/include/libpng16
+-rw-r--r-- root root 22846 ./usr/include/libpng16/pngconf.h
+-rw-r--r-- root root 142860 ./usr/include/libpng16/png.h
+-rw-r--r-- root root 7629 ./usr/include/libpng16/pnglibconf.h
+drwxr-xr-x root root 4096 ./usr/include/libsmartcols
+-rw-r--r-- root root 15473 ./usr/include/libsmartcols/libsmartcols.h
+-rw-r--r-- root root 3466 ./usr/include/libsync.h
+-rw-r--r-- root root 10327 ./usr/include/libudev.h
+drwxr-xr-x root root 4096 ./usr/include/libxml2
+drwxr-xr-x root root 4096 ./usr/include/libxml2/libxml
+-rw-r--r-- root root 3115 ./usr/include/libxml2/libxml/c14n.h
+-rw-r--r-- root root 4906 ./usr/include/libxml2/libxml/catalog.h
+-rw-r--r-- root root 5159 ./usr/include/libxml2/libxml/chvalid.h
+-rw-r--r-- root root 5152 ./usr/include/libxml2/libxml/debugXML.h
+-rw-r--r-- root root 1814 ./usr/include/libxml2/libxml/dict.h
+-rw-r--r-- root root 3157 ./usr/include/libxml2/libxml/DOCBparser.h
+-rw-r--r-- root root 8507 ./usr/include/libxml2/libxml/encoding.h
+-rw-r--r-- root root 4712 ./usr/include/libxml2/libxml/entities.h
+-rw-r--r-- root root 14670 ./usr/include/libxml2/libxml/globals.h
+-rw-r--r-- root root 6601 ./usr/include/libxml2/libxml/hash.h
+-rw-r--r-- root root 9410 ./usr/include/libxml2/libxml/HTMLparser.h
+-rw-r--r-- root root 3646 ./usr/include/libxml2/libxml/HTMLtree.h
+-rw-r--r-- root root 3348 ./usr/include/libxml2/libxml/list.h
+-rw-r--r-- root root 3758 ./usr/include/libxml2/libxml/nanoftp.h
+-rw-r--r-- root root 2005 ./usr/include/libxml2/libxml/nanohttp.h
+-rw-r--r-- root root 39718 ./usr/include/libxml2/libxml/parser.h
+-rw-r--r-- root root 17419 ./usr/include/libxml2/libxml/parserInternals.h
+-rw-r--r-- root root 2586 ./usr/include/libxml2/libxml/pattern.h
+-rw-r--r-- root root 5996 ./usr/include/libxml2/libxml/relaxng.h
+-rw-r--r-- root root 4949 ./usr/include/libxml2/libxml/SAX2.h
+-rw-r--r-- root root 4341 ./usr/include/libxml2/libxml/SAX.h
+-rw-r--r-- root root 26224 ./usr/include/libxml2/libxml/schemasInternals.h
+-rw-r--r-- root root 4371 ./usr/include/libxml2/libxml/schematron.h
+-rw-r--r-- root root 1958 ./usr/include/libxml2/libxml/threads.h
+-rw-r--r-- root root 38108 ./usr/include/libxml2/libxml/tree.h
+-rw-r--r-- root root 2664 ./usr/include/libxml2/libxml/uri.h
+-rw-r--r-- root root 13622 ./usr/include/libxml2/libxml/valid.h
+-rw-r--r-- root root 2967 ./usr/include/libxml2/libxml/xinclude.h
+-rw-r--r-- root root 5042 ./usr/include/libxml2/libxml/xlink.h
+-rw-r--r-- root root 3956 ./usr/include/libxml2/libxml/xmlautomata.h
+-rw-r--r-- root root 36809 ./usr/include/libxml2/libxml/xmlerror.h
+-rw-r--r-- root root 3759 ./usr/include/libxml2/libxml/xmlexports.h
+-rw-r--r-- root root 10605 ./usr/include/libxml2/libxml/xmlIO.h
+-rw-r--r-- root root 5945 ./usr/include/libxml2/libxml/xmlmemory.h
+-rw-r--r-- root root 1170 ./usr/include/libxml2/libxml/xmlmodule.h
+-rw-r--r-- root root 12607 ./usr/include/libxml2/libxml/xmlreader.h
+-rw-r--r-- root root 5458 ./usr/include/libxml2/libxml/xmlregexp.h
+-rw-r--r-- root root 2337 ./usr/include/libxml2/libxml/xmlsave.h
+-rw-r--r-- root root 7069 ./usr/include/libxml2/libxml/xmlschemas.h
+-rw-r--r-- root root 4841 ./usr/include/libxml2/libxml/xmlschemastypes.h
+-rw-r--r-- root root 5511 ./usr/include/libxml2/libxml/xmlstring.h
+-rw-r--r-- root root 9993 ./usr/include/libxml2/libxml/xmlunicode.h
+-rw-r--r-- root root 8035 ./usr/include/libxml2/libxml/xmlversion.h
+-rw-r--r-- root root 21265 ./usr/include/libxml2/libxml/xmlwriter.h
+-rw-r--r-- root root 16602 ./usr/include/libxml2/libxml/xpath.h
+-rw-r--r-- root root 19353 ./usr/include/libxml2/libxml/xpathInternals.h
+-rw-r--r-- root root 3359 ./usr/include/libxml2/libxml/xpointer.h
+-rw-r--r-- root root 5417 ./usr/include/limits.h
+-rw-r--r-- root root 7207 ./usr/include/link.h
+drwxr-xr-x root root 20480 ./usr/include/linux
+-rw-r--r-- root root 3733 ./usr/include/linux/acct.h
+-rw-r--r-- root root 1140 ./usr/include/linux/adb.h
+-rw-r--r-- root root 993 ./usr/include/linux/adfs_fs.h
+-rw-r--r-- root root 1544 ./usr/include/linux/affs_hardblocks.h
+-rw-r--r-- root root 3940 ./usr/include/linux/agpgart.h
+-rw-r--r-- root root 3398 ./usr/include/linux/aio_abi.h
+-rw-r--r-- root root 3681 ./usr/include/linux/am437x-vpfe.h
+drwxr-xr-x root root 4096 ./usr/include/linux/android
+-rw-r--r-- root root 789 ./usr/include/linux/android/binderfs.h
+-rw-r--r-- root root 14535 ./usr/include/linux/android/binder.h
+-rw-r--r-- root root 6892 ./usr/include/linux/a.out.h
+-rw-r--r-- root root 3683 ./usr/include/linux/apm_bios.h
+-rw-r--r-- root root 213 ./usr/include/linux/arcfb.h
+-rw-r--r-- root root 2751 ./usr/include/linux/arm_sdei.h
+-rw-r--r-- root root 1780 ./usr/include/linux/aspeed-lpc-ctrl.h
+-rw-r--r-- root root 1906 ./usr/include/linux/aspeed-p2a-ctrl.h
+-rw-r--r-- root root 1023 ./usr/include/linux/atalk.h
+-rw-r--r-- root root 952 ./usr/include/linux/atmapi.h
+-rw-r--r-- root root 1296 ./usr/include/linux/atmarp.h
+-rw-r--r-- root root 3271 ./usr/include/linux/atmbr2684.h
+-rw-r--r-- root root 576 ./usr/include/linux/atmclip.h
+-rw-r--r-- root root 7677 ./usr/include/linux/atmdev.h
+-rw-r--r-- root root 648 ./usr/include/linux/atm_eni.h
+-rw-r--r-- root root 7888 ./usr/include/linux/atm.h
+-rw-r--r-- root root 406 ./usr/include/linux/atm_he.h
+-rw-r--r-- root root 955 ./usr/include/linux/atm_idt77105.h
+-rw-r--r-- root root 1646 ./usr/include/linux/atmioc.h
+-rw-r--r-- root root 2381 ./usr/include/linux/atmlec.h
+-rw-r--r-- root root 4226 ./usr/include/linux/atmmpc.h
+-rw-r--r-- root root 1278 ./usr/include/linux/atm_nicstar.h
+-rw-r--r-- root root 639 ./usr/include/linux/atmppp.h
+-rw-r--r-- root root 4970 ./usr/include/linux/atmsap.h
+-rw-r--r-- root root 1853 ./usr/include/linux/atmsvc.h
+-rw-r--r-- root root 1622 ./usr/include/linux/atm_tcp.h
+-rw-r--r-- root root 1540 ./usr/include/linux/atm_zatm.h
+-rw-r--r-- root root 20759 ./usr/include/linux/audit.h
+-rw-r--r-- root root 4986 ./usr/include/linux/auto_dev-ioctl.h
+-rw-r--r-- root root 451 ./usr/include/linux/auto_fs4.h
+-rw-r--r-- root root 6428 ./usr/include/linux/auto_fs.h
+-rw-r--r-- root root 1496 ./usr/include/linux/auxvec.h
+-rw-r--r-- root root 2824 ./usr/include/linux/ax25.h
+-rw-r--r-- root root 1717 ./usr/include/linux/b1lli.h
+-rw-r--r-- root root 20373 ./usr/include/linux/batadv_packet.h
+-rw-r--r-- root root 16306 ./usr/include/linux/batman_adv.h
+-rw-r--r-- root root 883 ./usr/include/linux/baycom.h
+-rw-r--r-- root root 8425 ./usr/include/linux/bcache.h
+-rw-r--r-- root root 419 ./usr/include/linux/bcm933xx_hcs.h
+-rw-r--r-- root root 1905 ./usr/include/linux/bfs_fs.h
+-rw-r--r-- root root 628 ./usr/include/linux/binfmts.h
+-rw-r--r-- root root 1634 ./usr/include/linux/blkpg.h
+-rw-r--r-- root root 4701 ./usr/include/linux/blktrace_api.h
+-rw-r--r-- root root 5368 ./usr/include/linux/blkzoned.h
+-rw-r--r-- root root 1367 ./usr/include/linux/bpf_common.h
+-rw-r--r-- root root 138331 ./usr/include/linux/bpf.h
+-rw-r--r-- root root 465 ./usr/include/linux/bpfilter.h
+-rw-r--r-- root root 529 ./usr/include/linux/bpf_perf_event.h
+-rw-r--r-- root root 981 ./usr/include/linux/bpqether.h
+-rw-r--r-- root root 2494 ./usr/include/linux/bsg.h
+-rw-r--r-- root root 572 ./usr/include/linux/bt-bmc.h
+-rw-r--r-- root root 4624 ./usr/include/linux/btf.h
+-rw-r--r-- root root 29142 ./usr/include/linux/btrfs.h
+-rw-r--r-- root root 25245 ./usr/include/linux/btrfs_tree.h
+drwxr-xr-x root root 4096 ./usr/include/linux/byteorder
+-rw-r--r-- root root 3542 ./usr/include/linux/byteorder/big_endian.h
+-rw-r--r-- root root 3611 ./usr/include/linux/byteorder/little_endian.h
+drwxr-xr-x root root 4096 ./usr/include/linux/caif
+-rw-r--r-- root root 5832 ./usr/include/linux/caif/caif_socket.h
+-rw-r--r-- root root 1041 ./usr/include/linux/caif/if_caif.h
+drwxr-xr-x root root 4096 ./usr/include/linux/can
+-rw-r--r-- root root 4116 ./usr/include/linux/can/bcm.h
+-rw-r--r-- root root 6610 ./usr/include/linux/can/error.h
+-rw-r--r-- root root 8031 ./usr/include/linux/can/gw.h
+-rw-r--r-- root root 8213 ./usr/include/linux/can.h
+-rw-r--r-- root root 2207 ./usr/include/linux/can/j1939.h
+-rw-r--r-- root root 3993 ./usr/include/linux/can/netlink.h
+-rw-r--r-- root root 2858 ./usr/include/linux/can/raw.h
+-rw-r--r-- root root 232 ./usr/include/linux/can/vxcan.h
+-rw-r--r-- root root 11780 ./usr/include/linux/capability.h
+-rw-r--r-- root root 3124 ./usr/include/linux/capi.h
+-rw-r--r-- root root 3281 ./usr/include/linux/cciss_defs.h
+-rw-r--r-- root root 2761 ./usr/include/linux/cciss_ioctl.h
+-rw-r--r-- root root 28859 ./usr/include/linux/cdrom.h
+-rw-r--r-- root root 53535 ./usr/include/linux/cec-funcs.h
+-rw-r--r-- root root 36389 ./usr/include/linux/cec.h
+-rw-r--r-- root root 2219 ./usr/include/linux/cgroupstats.h
+-rw-r--r-- root root 5344 ./usr/include/linux/chio.h
+drwxr-xr-x root root 4096 ./usr/include/linux/cifs
+-rw-r--r-- root root 1225 ./usr/include/linux/cifs/cifs_mount.h
+-rw-r--r-- root root 1806 ./usr/include/linux/cm4000_cs.h
+-rw-r--r-- root root 3456 ./usr/include/linux/cn_proc.h
+-rw-r--r-- root root 18216 ./usr/include/linux/coda.h
+-rw-r--r-- root root 12549 ./usr/include/linux/coff.h
+-rw-r--r-- root root 2253 ./usr/include/linux/connector.h
+-rw-r--r-- root root 788 ./usr/include/linux/const.h
+-rw-r--r-- root root 674 ./usr/include/linux/coresight-stm.h
+-rw-r--r-- root root 3555 ./usr/include/linux/cramfs_fs.h
+-rw-r--r-- root root 5321 ./usr/include/linux/cryptouser.h
+-rw-r--r-- root root 905 ./usr/include/linux/cuda.h
+-rw-r--r-- root root 17108 ./usr/include/linux/cyclades.h
+-rw-r--r-- root root 2990 ./usr/include/linux/cycx_cfm.h
+-rw-r--r-- root root 25291 ./usr/include/linux/dcbnl.h
+-rw-r--r-- root root 6436 ./usr/include/linux/dccp.h
+-rw-r--r-- root root 14860 ./usr/include/linux/devlink.h
+-rw-r--r-- root root 5080 ./usr/include/linux/dlmconstants.h
+-rw-r--r-- root root 2543 ./usr/include/linux/dlm_device.h
+-rw-r--r-- root root 2553 ./usr/include/linux/dlm.h
+-rw-r--r-- root root 1159 ./usr/include/linux/dlm_netlink.h
+-rw-r--r-- root root 894 ./usr/include/linux/dlm_plock.h
+-rw-r--r-- root root 1448 ./usr/include/linux/dma-buf.h
+-rw-r--r-- root root 10988 ./usr/include/linux/dm-ioctl.h
+-rw-r--r-- root root 15191 ./usr/include/linux/dm-log-userspace.h
+-rw-r--r-- root root 4642 ./usr/include/linux/dn.h
+-rw-r--r-- root root 3949 ./usr/include/linux/dns_resolver.h
+-rw-r--r-- root root 8999 ./usr/include/linux/dqblk_xfs.h
+drwxr-xr-x root root 4096 ./usr/include/linux/dvb
+-rw-r--r-- root root 3550 ./usr/include/linux/dvb/audio.h
+-rw-r--r-- root root 4247 ./usr/include/linux/dvb/ca.h
+-rw-r--r-- root root 10177 ./usr/include/linux/dvb/dmx.h
+-rw-r--r-- root root 29244 ./usr/include/linux/dvb/frontend.h
+-rw-r--r-- root root 2127 ./usr/include/linux/dvb/net.h
+-rw-r--r-- root root 5937 ./usr/include/linux/dvb/osd.h
+-rw-r--r-- root root 1082 ./usr/include/linux/dvb/version.h
+-rw-r--r-- root root 7106 ./usr/include/linux/dvb/video.h
+-rw-r--r-- root root 5604 ./usr/include/linux/edd.h
+-rw-r--r-- root root 2227 ./usr/include/linux/efs_fs_sb.h
+-rw-r--r-- root root 2995 ./usr/include/linux/elfcore.h
+-rw-r--r-- root root 2586 ./usr/include/linux/elf-em.h
+-rw-r--r-- root root 1124 ./usr/include/linux/elf-fdpic.h
+-rw-r--r-- root root 13642 ./usr/include/linux/elf.h
+-rw-r--r-- root root 23 ./usr/include/linux/errno.h
+-rw-r--r-- root root 1572 ./usr/include/linux/errqueue.h
+-rw-r--r-- root root 1059 ./usr/include/linux/erspan.h
+-rw-r--r-- root root 74781 ./usr/include/linux/ethtool.h
+-rw-r--r-- root root 2743 ./usr/include/linux/eventpoll.h
+-rw-r--r-- root root 842 ./usr/include/linux/fadvise.h
+-rw-r--r-- root root 3584 ./usr/include/linux/falloc.h
+-rw-r--r-- root root 5369 ./usr/include/linux/fanotify.h
+-rw-r--r-- root root 16412 ./usr/include/linux/fb.h
+-rw-r--r-- root root 3438 ./usr/include/linux/fcntl.h
+-rw-r--r-- root root 11672 ./usr/include/linux/fd.h
+-rw-r--r-- root root 5420 ./usr/include/linux/fdreg.h
+-rw-r--r-- root root 2036 ./usr/include/linux/fib_rules.h
+-rw-r--r-- root root 2775 ./usr/include/linux/fiemap.h
+-rw-r--r-- root root 2216 ./usr/include/linux/filter.h
+-rw-r--r-- root root 44242 ./usr/include/linux/firewire-cdev.h
+-rw-r--r-- root root 3231 ./usr/include/linux/firewire-constants.h
+-rw-r--r-- root root 894 ./usr/include/linux/fou.h
+-rw-r--r-- root root 6103 ./usr/include/linux/fpga-dfl.h
+-rw-r--r-- root root 6104 ./usr/include/linux/fscrypt.h
+-rw-r--r-- root root 12205 ./usr/include/linux/fs.h
+-rw-r--r-- root root 2255 ./usr/include/linux/fsi.h
+-rw-r--r-- root root 7301 ./usr/include/linux/fsl_hypervisor.h
+-rw-r--r-- root root 4393 ./usr/include/linux/fsmap.h
+-rw-r--r-- root root 931 ./usr/include/linux/fsverity.h
+-rw-r--r-- root root 20407 ./usr/include/linux/fuse.h
+-rw-r--r-- root root 4993 ./usr/include/linux/futex.h
+-rw-r--r-- root root 897 ./usr/include/linux/gameport.h
+-rw-r--r-- root root 1923 ./usr/include/linux/genetlink.h
+-rw-r--r-- root root 1599 ./usr/include/linux/gen_stats.h
+drwxr-xr-x root root 4096 ./usr/include/linux/genwqe
+-rw-r--r-- root root 17802 ./usr/include/linux/genwqe/genwqe_card.h
+-rw-r--r-- root root 14651 ./usr/include/linux/gfs2_ondisk.h
+-rw-r--r-- root root 1442 ./usr/include/linux/gigaset_dev.h
+-rw-r--r-- root root 5753 ./usr/include/linux/gpio.h
+-rw-r--r-- root root 1144 ./usr/include/linux/gsmmux.h
+-rw-r--r-- root root 681 ./usr/include/linux/gtp.h
+-rw-r--r-- root root 971 ./usr/include/linux/hash_info.h
+drwxr-xr-x root root 4096 ./usr/include/linux/hdlc
+-rw-r--r-- root root 2908 ./usr/include/linux/hdlcdrv.h
+-rw-r--r-- root root 637 ./usr/include/linux/hdlc.h
+-rw-r--r-- root root 2657 ./usr/include/linux/hdlc/ioctl.h
+-rw-r--r-- root root 22703 ./usr/include/linux/hdreg.h
+-rw-r--r-- root root 6345 ./usr/include/linux/hiddev.h
+-rw-r--r-- root root 1901 ./usr/include/linux/hid.h
+-rw-r--r-- root root 1511 ./usr/include/linux/hidraw.h
+-rw-r--r-- root root 743 ./usr/include/linux/hpet.h
+drwxr-xr-x root root 4096 ./usr/include/linux/hsi
+-rw-r--r-- root root 3656 ./usr/include/linux/hsi/cs-protocol.h
+-rw-r--r-- root root 1895 ./usr/include/linux/hsi/hsi_char.h
+-rw-r--r-- root root 1081 ./usr/include/linux/hsr_netlink.h
+-rw-r--r-- root root 742 ./usr/include/linux/hw_breakpoint.h
+-rw-r--r-- root root 10569 ./usr/include/linux/hyperv.h
+-rw-r--r-- root root 1382 ./usr/include/linux/hysdn_if.h
+-rw-r--r-- root root 2612 ./usr/include/linux/i2c-dev.h
+-rw-r--r-- root root 7132 ./usr/include/linux/i2c.h
+-rw-r--r-- root root 11555 ./usr/include/linux/i2o-dev.h
+-rw-r--r-- root root 1528 ./usr/include/linux/i8k.h
+-rw-r--r-- root root 2975 ./usr/include/linux/icmp.h
+-rw-r--r-- root root 4083 ./usr/include/linux/icmpv6.h
+-rw-r--r-- root root 1886 ./usr/include/linux/if_addr.h
+-rw-r--r-- root root 721 ./usr/include/linux/if_addrlabel.h
+-rw-r--r-- root root 946 ./usr/include/linux/if_alg.h
+-rw-r--r-- root root 3717 ./usr/include/linux/if_arcnet.h
+-rw-r--r-- root root 6565 ./usr/include/linux/if_arp.h
+-rw-r--r-- root root 4839 ./usr/include/linux/if_bonding.h
+-rw-r--r-- root root 7266 ./usr/include/linux/if_bridge.h
+-rw-r--r-- root root 986 ./usr/include/linux/if_cablemodem.h
+-rw-r--r-- root root 351 ./usr/include/linux/ife.h
+-rw-r--r-- root root 1349 ./usr/include/linux/if_eql.h
+-rw-r--r-- root root 8227 ./usr/include/linux/if_ether.h
+-rw-r--r-- root root 1738 ./usr/include/linux/if_fc.h
+-rw-r--r-- root root 4372 ./usr/include/linux/if_fddi.h
+-rw-r--r-- root root 3019 ./usr/include/linux/if_frad.h
+-rw-r--r-- root root 10813 ./usr/include/linux/if.h
+-rw-r--r-- root root 4235 ./usr/include/linux/if_hippi.h
+-rw-r--r-- root root 1245 ./usr/include/linux/if_infiniband.h
+-rw-r--r-- root root 23649 ./usr/include/linux/if_link.h
+-rw-r--r-- root root 210 ./usr/include/linux/if_ltalk.h
+-rw-r--r-- root root 5832 ./usr/include/linux/if_macsec.h
+-rw-r--r-- root root 7955 ./usr/include/linux/if_packet.h
+-rw-r--r-- root root 424 ./usr/include/linux/if_phonet.h
+-rw-r--r-- root root 660 ./usr/include/linux/if_plip.h
+-rw-r--r-- root root 29 ./usr/include/linux/if_ppp.h
+-rw-r--r-- root root 3292 ./usr/include/linux/if_pppol2tp.h
+-rw-r--r-- root root 4879 ./usr/include/linux/if_pppox.h
+-rw-r--r-- root root 872 ./usr/include/linux/if_slip.h
+-rw-r--r-- root root 2600 ./usr/include/linux/if_team.h
+-rw-r--r-- root root 4098 ./usr/include/linux/if_tun.h
+-rw-r--r-- root root 4512 ./usr/include/linux/if_tunnel.h
+-rw-r--r-- root root 1831 ./usr/include/linux/if_vlan.h
+-rw-r--r-- root root 881 ./usr/include/linux/if_x25.h
+-rw-r--r-- root root 2819 ./usr/include/linux/if_xdp.h
+-rw-r--r-- root root 3064 ./usr/include/linux/igmp.h
+drwxr-xr-x root root 4096 ./usr/include/linux/iio
+-rw-r--r-- root root 1390 ./usr/include/linux/iio/events.h
+-rw-r--r-- root root 2114 ./usr/include/linux/iio/types.h
+-rw-r--r-- root root 1246 ./usr/include/linux/ila.h
+-rw-r--r-- root root 7505 ./usr/include/linux/in6.h
+-rw-r--r-- root root 4540 ./usr/include/linux/inet_diag.h
+-rw-r--r-- root root 9881 ./usr/include/linux/in.h
+-rw-r--r-- root root 3292 ./usr/include/linux/inotify.h
+-rw-r--r-- root root 25218 ./usr/include/linux/input-event-codes.h
+-rw-r--r-- root root 15964 ./usr/include/linux/input.h
+-rw-r--r-- root root 936 ./usr/include/linux/in_route.h
+-rw-r--r-- root root 163 ./usr/include/linux/ioctl.h
+-rw-r--r-- root root 4578 ./usr/include/linux/iommu.h
+-rw-r--r-- root root 3478 ./usr/include/linux/io_uring.h
+-rw-r--r-- root root 1953 ./usr/include/linux/ip6_tunnel.h
+-rw-r--r-- root root 2101 ./usr/include/linux/ipc.h
+-rw-r--r-- root root 4728 ./usr/include/linux/ip.h
+-rw-r--r-- root root 488 ./usr/include/linux/ipmi_bmc.h
+-rw-r--r-- root root 15049 ./usr/include/linux/ipmi.h
+-rw-r--r-- root root 3350 ./usr/include/linux/ipmi_msgdefs.h
+-rw-r--r-- root root 947 ./usr/include/linux/ipsec.h
+-rw-r--r-- root root 3967 ./usr/include/linux/ipv6.h
+-rw-r--r-- root root 1908 ./usr/include/linux/ipv6_route.h
+-rw-r--r-- root root 14135 ./usr/include/linux/ip_vs.h
+-rw-r--r-- root root 2347 ./usr/include/linux/ipx.h
+-rw-r--r-- root root 104 ./usr/include/linux/irqnr.h
+drwxr-xr-x root root 4096 ./usr/include/linux/isdn
+-rw-r--r-- root root 4783 ./usr/include/linux/isdn/capicmd.h
+-rw-r--r-- root root 6485 ./usr/include/linux/iso_fs.h
+-rw-r--r-- root root 5408 ./usr/include/linux/isst_if.h
+-rw-r--r-- root root 1207 ./usr/include/linux/ivtvfb.h
+-rw-r--r-- root root 3022 ./usr/include/linux/ivtv.h
+-rw-r--r-- root root 6815 ./usr/include/linux/jffs2.h
+-rw-r--r-- root root 3434 ./usr/include/linux/joystick.h
+-rw-r--r-- root root 822 ./usr/include/linux/kcm.h
+-rw-r--r-- root root 522 ./usr/include/linux/kcmp.h
+-rw-r--r-- root root 1099 ./usr/include/linux/kcov.h
+-rw-r--r-- root root 383 ./usr/include/linux/kdev_t.h
+-rw-r--r-- root root 6253 ./usr/include/linux/kd.h
+-rw-r--r-- root root 1019 ./usr/include/linux/kernelcapi.h
+-rw-r--r-- root root 438 ./usr/include/linux/kernel.h
+-rw-r--r-- root root 900 ./usr/include/linux/kernel-page-flags.h
+-rw-r--r-- root root 1873 ./usr/include/linux/kexec.h
+-rw-r--r-- root root 13459 ./usr/include/linux/keyboard.h
+-rw-r--r-- root root 5837 ./usr/include/linux/keyctl.h
+-rw-r--r-- root root 16263 ./usr/include/linux/kfd_ioctl.h
+-rw-r--r-- root root 46258 ./usr/include/linux/kvm.h
+-rw-r--r-- root root 968 ./usr/include/linux/kvm_para.h
+-rw-r--r-- root root 5672 ./usr/include/linux/l2tp.h
+-rw-r--r-- root root 8289 ./usr/include/linux/libc-compat.h
+-rw-r--r-- root root 5042 ./usr/include/linux/lightnvm.h
+-rw-r--r-- root root 937 ./usr/include/linux/limits.h
+-rw-r--r-- root root 8102 ./usr/include/linux/lirc.h
+-rw-r--r-- root root 3164 ./usr/include/linux/llc.h
+-rw-r--r-- root root 2520 ./usr/include/linux/loop.h
+-rw-r--r-- root root 4190 ./usr/include/linux/lp.h
+-rw-r--r-- root root 1273 ./usr/include/linux/lwtunnel.h
+-rw-r--r-- root root 3604 ./usr/include/linux/magic.h
+-rw-r--r-- root root 4713 ./usr/include/linux/major.h
+-rw-r--r-- root root 7251 ./usr/include/linux/map_to_7segment.h
+-rw-r--r-- root root 1464 ./usr/include/linux/matroxfb.h
+-rw-r--r-- root root 1035 ./usr/include/linux/max2175.h
+-rw-r--r-- root root 15645 ./usr/include/linux/mdio.h
+-rw-r--r-- root root 6540 ./usr/include/linux/media-bus-format.h
+-rw-r--r-- root root 12641 ./usr/include/linux/media.h
+-rw-r--r-- root root 1993 ./usr/include/linux/mei.h
+-rw-r--r-- root root 7899 ./usr/include/linux/membarrier.h
+-rw-r--r-- root root 1324 ./usr/include/linux/memfd.h
+-rw-r--r-- root root 2154 ./usr/include/linux/mempolicy.h
+-rw-r--r-- root root 2529 ./usr/include/linux/meye.h
+-rw-r--r-- root root 6519 ./usr/include/linux/mic_common.h
+-rw-r--r-- root root 2252 ./usr/include/linux/mic_ioctl.h
+-rw-r--r-- root root 8281 ./usr/include/linux/mii.h
+-rw-r--r-- root root 2122 ./usr/include/linux/minix_fs.h
+-rw-r--r-- root root 1508 ./usr/include/linux/mman.h
+drwxr-xr-x root root 4096 ./usr/include/linux/mmc
+-rw-r--r-- root root 2331 ./usr/include/linux/mmc/ioctl.h
+-rw-r--r-- root root 2117 ./usr/include/linux/mmtimer.h
+-rw-r--r-- root root 255 ./usr/include/linux/module.h
+-rw-r--r-- root root 4546 ./usr/include/linux/mount.h
+-rw-r--r-- root root 2302 ./usr/include/linux/mpls.h
+-rw-r--r-- root root 761 ./usr/include/linux/mpls_iptunnel.h
+-rw-r--r-- root root 2201 ./usr/include/linux/mqueue.h
+-rw-r--r-- root root 4931 ./usr/include/linux/mroute6.h
+-rw-r--r-- root root 5881 ./usr/include/linux/mroute.h
+-rw-r--r-- root root 6731 ./usr/include/linux/msdos_fs.h
+-rw-r--r-- root root 3374 ./usr/include/linux/msg.h
+-rw-r--r-- root root 8175 ./usr/include/linux/mtio.h
+-rw-r--r-- root root 3024 ./usr/include/linux/nbd.h
+-rw-r--r-- root root 2378 ./usr/include/linux/nbd-netlink.h
+-rw-r--r-- root root 4828 ./usr/include/linux/ncsi.h
+-rw-r--r-- root root 6770 ./usr/include/linux/ndctl.h
+-rw-r--r-- root root 4406 ./usr/include/linux/neighbour.h
+-rw-r--r-- root root 614 ./usr/include/linux/netconf.h
+-rw-r--r-- root root 2253 ./usr/include/linux/netdevice.h
+-rw-r--r-- root root 2839 ./usr/include/linux/net_dropmon.h
+drwxr-xr-x root root 4096 ./usr/include/linux/netfilter
+drwxr-xr-x root root 4096 ./usr/include/linux/netfilter_arp
+-rw-r--r-- root root 5999 ./usr/include/linux/netfilter_arp/arp_tables.h
+-rw-r--r-- root root 606 ./usr/include/linux/netfilter_arp/arpt_mangle.h
+-rw-r--r-- root root 445 ./usr/include/linux/netfilter_arp.h
+drwxr-xr-x root root 4096 ./usr/include/linux/netfilter_bridge
+-rw-r--r-- root root 1274 ./usr/include/linux/netfilter_bridge/ebt_802_3.h
+-rw-r--r-- root root 9308 ./usr/include/linux/netfilter_bridge/ebtables.h
+-rw-r--r-- root root 2043 ./usr/include/linux/netfilter_bridge/ebt_among.h
+-rw-r--r-- root root 900 ./usr/include/linux/netfilter_bridge/ebt_arp.h
+-rw-r--r-- root root 289 ./usr/include/linux/netfilter_bridge/ebt_arpreply.h
+-rw-r--r-- root root 1056 ./usr/include/linux/netfilter_bridge/ebt_ip6.h
+-rw-r--r-- root root 1094 ./usr/include/linux/netfilter_bridge/ebt_ip.h
+-rw-r--r-- root root 616 ./usr/include/linux/netfilter_bridge/ebt_limit.h
+-rw-r--r-- root root 538 ./usr/include/linux/netfilter_bridge/ebt_log.h
+-rw-r--r-- root root 388 ./usr/include/linux/netfilter_bridge/ebt_mark_m.h
+-rw-r--r-- root root 831 ./usr/include/linux/netfilter_bridge/ebt_mark_t.h
+-rw-r--r-- root root 387 ./usr/include/linux/netfilter_bridge/ebt_nat.h
+-rw-r--r-- root root 510 ./usr/include/linux/netfilter_bridge/ebt_nflog.h
+-rw-r--r-- root root 267 ./usr/include/linux/netfilter_bridge/ebt_pkttype.h
+-rw-r--r-- root root 286 ./usr/include/linux/netfilter_bridge/ebt_redirect.h
+-rw-r--r-- root root 1110 ./usr/include/linux/netfilter_bridge/ebt_stp.h
+-rw-r--r-- root root 719 ./usr/include/linux/netfilter_bridge/ebt_vlan.h
+-rw-r--r-- root root 1168 ./usr/include/linux/netfilter_bridge.h
+-rw-r--r-- root root 1758 ./usr/include/linux/netfilter_decnet.h
+-rw-r--r-- root root 1674 ./usr/include/linux/netfilter.h
+drwxr-xr-x root root 4096 ./usr/include/linux/netfilter/ipset
+-rw-r--r-- root root 428 ./usr/include/linux/netfilter/ipset/ip_set_bitmap.h
+-rw-r--r-- root root 9108 ./usr/include/linux/netfilter/ipset/ip_set.h
+-rw-r--r-- root root 578 ./usr/include/linux/netfilter/ipset/ip_set_hash.h
+-rw-r--r-- root root 609 ./usr/include/linux/netfilter/ipset/ip_set_list.h
+drwxr-xr-x root root 4096 ./usr/include/linux/netfilter_ipv4
+-rw-r--r-- root root 1488 ./usr/include/linux/netfilter_ipv4.h
+-rw-r--r-- root root 6647 ./usr/include/linux/netfilter_ipv4/ip_tables.h
+-rw-r--r-- root root 425 ./usr/include/linux/netfilter_ipv4/ipt_ah.h
+-rw-r--r-- root root 821 ./usr/include/linux/netfilter_ipv4/ipt_CLUSTERIP.h
+-rw-r--r-- root root 431 ./usr/include/linux/netfilter_ipv4/ipt_ecn.h
+-rw-r--r-- root root 901 ./usr/include/linux/netfilter_ipv4/ipt_ECN.h
+-rw-r--r-- root root 654 ./usr/include/linux/netfilter_ipv4/ipt_LOG.h
+-rw-r--r-- root root 468 ./usr/include/linux/netfilter_ipv4/ipt_REJECT.h
+-rw-r--r-- root root 431 ./usr/include/linux/netfilter_ipv4/ipt_ttl.h
+-rw-r--r-- root root 375 ./usr/include/linux/netfilter_ipv4/ipt_TTL.h
+drwxr-xr-x root root 4096 ./usr/include/linux/netfilter_ipv6
+-rw-r--r-- root root 1383 ./usr/include/linux/netfilter_ipv6.h
+-rw-r--r-- root root 8011 ./usr/include/linux/netfilter_ipv6/ip6_tables.h
+-rw-r--r-- root root 657 ./usr/include/linux/netfilter_ipv6/ip6t_ah.h
+-rw-r--r-- root root 744 ./usr/include/linux/netfilter_ipv6/ip6t_frag.h
+-rw-r--r-- root root 458 ./usr/include/linux/netfilter_ipv6/ip6t_hl.h
+-rw-r--r-- root root 408 ./usr/include/linux/netfilter_ipv6/ip6t_HL.h
+-rw-r--r-- root root 645 ./usr/include/linux/netfilter_ipv6/ip6t_ipv6header.h
+-rw-r--r-- root root 662 ./usr/include/linux/netfilter_ipv6/ip6t_LOG.h
+-rw-r--r-- root root 439 ./usr/include/linux/netfilter_ipv6/ip6t_mh.h
+-rw-r--r-- root root 400 ./usr/include/linux/netfilter_ipv6/ip6t_NPT.h
+-rw-r--r-- root root 649 ./usr/include/linux/netfilter_ipv6/ip6t_opts.h
+-rw-r--r-- root root 470 ./usr/include/linux/netfilter_ipv6/ip6t_REJECT.h
+-rw-r--r-- root root 985 ./usr/include/linux/netfilter_ipv6/ip6t_rt.h
+-rw-r--r-- root root 3305 ./usr/include/linux/netfilter_ipv6/ip6t_srh.h
+-rw-r--r-- root root 4421 ./usr/include/linux/netfilter/nf_conntrack_common.h
+-rw-r--r-- root root 438 ./usr/include/linux/netfilter/nf_conntrack_ftp.h
+-rw-r--r-- root root 576 ./usr/include/linux/netfilter/nf_conntrack_sctp.h
+-rw-r--r-- root root 1415 ./usr/include/linux/netfilter/nf_conntrack_tcp.h
+-rw-r--r-- root root 896 ./usr/include/linux/netfilter/nf_conntrack_tuple_common.h
+-rw-r--r-- root root 538 ./usr/include/linux/netfilter/nf_log.h
+-rw-r--r-- root root 1522 ./usr/include/linux/netfilter/nf_nat.h
+-rw-r--r-- root root 900 ./usr/include/linux/netfilter/nfnetlink_acct.h
+-rw-r--r-- root root 2444 ./usr/include/linux/netfilter/nfnetlink_compat.h
+-rw-r--r-- root root 5924 ./usr/include/linux/netfilter/nfnetlink_conntrack.h
+-rw-r--r-- root root 1202 ./usr/include/linux/netfilter/nfnetlink_cthelper.h
+-rw-r--r-- root root 2930 ./usr/include/linux/netfilter/nfnetlink_cttimeout.h
+-rw-r--r-- root root 2428 ./usr/include/linux/netfilter/nfnetlink.h
+-rw-r--r-- root root 3106 ./usr/include/linux/netfilter/nfnetlink_log.h
+-rw-r--r-- root root 2665 ./usr/include/linux/netfilter/nfnetlink_osf.h
+-rw-r--r-- root root 3499 ./usr/include/linux/netfilter/nfnetlink_queue.h
+-rw-r--r-- root root 576 ./usr/include/linux/netfilter/nf_synproxy.h
+-rw-r--r-- root root 731 ./usr/include/linux/netfilter/nf_tables_compat.h
+-rw-r--r-- root root 51835 ./usr/include/linux/netfilter/nf_tables.h
+-rw-r--r-- root root 4467 ./usr/include/linux/netfilter/x_tables.h
+-rw-r--r-- root root 1084 ./usr/include/linux/netfilter/xt_addrtype.h
+-rw-r--r-- root root 718 ./usr/include/linux/netfilter/xt_AUDIT.h
+-rw-r--r-- root root 935 ./usr/include/linux/netfilter/xt_bpf.h
+-rw-r--r-- root root 740 ./usr/include/linux/netfilter/xt_cgroup.h
+-rw-r--r-- root root 563 ./usr/include/linux/netfilter/xt_CHECKSUM.h
+-rw-r--r-- root root 217 ./usr/include/linux/netfilter/xt_CLASSIFY.h
+-rw-r--r-- root root 374 ./usr/include/linux/netfilter/xt_cluster.h
+-rw-r--r-- root root 230 ./usr/include/linux/netfilter/xt_comment.h
+-rw-r--r-- root root 577 ./usr/include/linux/netfilter/xt_connbytes.h
+-rw-r--r-- root root 360 ./usr/include/linux/netfilter/xt_connlabel.h
+-rw-r--r-- root root 575 ./usr/include/linux/netfilter/xt_connlimit.h
+-rw-r--r-- root root 900 ./usr/include/linux/netfilter/xt_connmark.h
+-rw-r--r-- root root 199 ./usr/include/linux/netfilter/xt_CONNMARK.h
+-rw-r--r-- root root 301 ./usr/include/linux/netfilter/xt_CONNSECMARK.h
+-rw-r--r-- root root 2557 ./usr/include/linux/netfilter/xt_conntrack.h
+-rw-r--r-- root root 199 ./usr/include/linux/netfilter/xt_cpu.h
+-rw-r--r-- root root 853 ./usr/include/linux/netfilter/xt_CT.h
+-rw-r--r-- root root 483 ./usr/include/linux/netfilter/xt_dccp.h
+-rw-r--r-- root root 429 ./usr/include/linux/netfilter/xt_devgroup.h
+-rw-r--r-- root root 701 ./usr/include/linux/netfilter/xt_dscp.h
+-rw-r--r-- root root 697 ./usr/include/linux/netfilter/xt_DSCP.h
+-rw-r--r-- root root 736 ./usr/include/linux/netfilter/xt_ecn.h
+-rw-r--r-- root root 418 ./usr/include/linux/netfilter/xt_esp.h
+-rw-r--r-- root root 3256 ./usr/include/linux/netfilter/xt_hashlimit.h
+-rw-r--r-- root root 188 ./usr/include/linux/netfilter/xt_helper.h
+-rw-r--r-- root root 933 ./usr/include/linux/netfilter/xt_HMARK.h
+-rw-r--r-- root root 1393 ./usr/include/linux/netfilter/xt_IDLETIMER.h
+-rw-r--r-- root root 485 ./usr/include/linux/netfilter/xt_ipcomp.h
+-rw-r--r-- root root 581 ./usr/include/linux/netfilter/xt_iprange.h
+-rw-r--r-- root root 680 ./usr/include/linux/netfilter/xt_ipvs.h
+-rw-r--r-- root root 739 ./usr/include/linux/netfilter/xt_l2tp.h
+-rw-r--r-- root root 470 ./usr/include/linux/netfilter/xt_LED.h
+-rw-r--r-- root root 221 ./usr/include/linux/netfilter/xt_length.h
+-rw-r--r-- root root 673 ./usr/include/linux/netfilter/xt_limit.h
+-rw-r--r-- root root 642 ./usr/include/linux/netfilter/xt_LOG.h
+-rw-r--r-- root root 227 ./usr/include/linux/netfilter/xt_mac.h
+-rw-r--r-- root root 260 ./usr/include/linux/netfilter/xt_mark.h
+-rw-r--r-- root root 184 ./usr/include/linux/netfilter/xt_MARK.h
+-rw-r--r-- root root 721 ./usr/include/linux/netfilter/xt_multiport.h
+-rw-r--r-- root root 421 ./usr/include/linux/netfilter/xt_nfacct.h
+-rw-r--r-- root root 556 ./usr/include/linux/netfilter/xt_NFLOG.h
+-rw-r--r-- root root 779 ./usr/include/linux/netfilter/xt_NFQUEUE.h
+-rw-r--r-- root root 1703 ./usr/include/linux/netfilter/xt_osf.h
+-rw-r--r-- root root 535 ./usr/include/linux/netfilter/xt_owner.h
+-rw-r--r-- root root 553 ./usr/include/linux/netfilter/xt_physdev.h
+-rw-r--r-- root root 188 ./usr/include/linux/netfilter/xt_pkttype.h
+-rw-r--r-- root root 1051 ./usr/include/linux/netfilter/xt_policy.h
+-rw-r--r-- root root 400 ./usr/include/linux/netfilter/xt_quota.h
+-rw-r--r-- root root 859 ./usr/include/linux/netfilter/xt_rateest.h
+-rw-r--r-- root root 390 ./usr/include/linux/netfilter/xt_RATEEST.h
+-rw-r--r-- root root 220 ./usr/include/linux/netfilter/xt_realm.h
+-rw-r--r-- root root 1058 ./usr/include/linux/netfilter/xt_recent.h
+-rw-r--r-- root root 320 ./usr/include/linux/netfilter/xt_rpfilter.h
+-rw-r--r-- root root 2326 ./usr/include/linux/netfilter/xt_sctp.h
+-rw-r--r-- root root 549 ./usr/include/linux/netfilter/xt_SECMARK.h
+-rw-r--r-- root root 1827 ./usr/include/linux/netfilter/xt_set.h
+-rw-r--r-- root root 640 ./usr/include/linux/netfilter/xt_socket.h
+-rw-r--r-- root root 331 ./usr/include/linux/netfilter/xt_state.h
+-rw-r--r-- root root 716 ./usr/include/linux/netfilter/xt_statistic.h
+-rw-r--r-- root root 664 ./usr/include/linux/netfilter/xt_string.h
+-rw-r--r-- root root 498 ./usr/include/linux/netfilter/xt_SYNPROXY.h
+-rw-r--r-- root root 253 ./usr/include/linux/netfilter/xt_tcpmss.h
+-rw-r--r-- root root 235 ./usr/include/linux/netfilter/xt_TCPMSS.h
+-rw-r--r-- root root 407 ./usr/include/linux/netfilter/xt_TCPOPTSTRIP.h
+-rw-r--r-- root root 1250 ./usr/include/linux/netfilter/xt_tcpudp.h
+-rw-r--r-- root root 333 ./usr/include/linux/netfilter/xt_TEE.h
+-rw-r--r-- root root 730 ./usr/include/linux/netfilter/xt_time.h
+-rw-r--r-- root root 575 ./usr/include/linux/netfilter/xt_TPROXY.h
+-rw-r--r-- root root 752 ./usr/include/linux/netfilter/xt_u32.h
+-rw-r--r-- root root 2085 ./usr/include/linux/net.h
+-rw-r--r-- root root 1524 ./usr/include/linux/netlink_diag.h
+-rw-r--r-- root root 7825 ./usr/include/linux/netlink.h
+-rw-r--r-- root root 715 ./usr/include/linux/net_namespace.h
+-rw-r--r-- root root 807 ./usr/include/linux/netrom.h
+-rw-r--r-- root root 4914 ./usr/include/linux/net_tstamp.h
+-rw-r--r-- root root 1534 ./usr/include/linux/nexthop.h
+-rw-r--r-- root root 11209 ./usr/include/linux/nfc.h
+-rw-r--r-- root root 1468 ./usr/include/linux/nfs2.h
+-rw-r--r-- root root 2359 ./usr/include/linux/nfs3.h
+-rw-r--r-- root root 6338 ./usr/include/linux/nfs4.h
+-rw-r--r-- root root 1932 ./usr/include/linux/nfs4_mount.h
+-rw-r--r-- root root 668 ./usr/include/linux/nfsacl.h
+drwxr-xr-x root root 4096 ./usr/include/linux/nfsd
+-rw-r--r-- root root 3122 ./usr/include/linux/nfsd/cld.h
+-rw-r--r-- root root 736 ./usr/include/linux/nfsd/debug.h
+-rw-r--r-- root root 2113 ./usr/include/linux/nfsd/export.h
+-rw-r--r-- root root 3517 ./usr/include/linux/nfsd/nfsfh.h
+-rw-r--r-- root root 421 ./usr/include/linux/nfsd/stats.h
+-rw-r--r-- root root 1608 ./usr/include/linux/nfs_fs.h
+-rw-r--r-- root root 4500 ./usr/include/linux/nfs.h
+-rw-r--r-- root root 2243 ./usr/include/linux/nfs_idmap.h
+-rw-r--r-- root root 2142 ./usr/include/linux/nfs_mount.h
+-rw-r--r-- root root 7589 ./usr/include/linux/nilfs2_api.h
+-rw-r--r-- root root 18085 ./usr/include/linux/nilfs2_ondisk.h
+-rw-r--r-- root root 280715 ./usr/include/linux/nl80211.h
+-rw-r--r-- root root 2410 ./usr/include/linux/n_r3964.h
+-rw-r--r-- root root 639 ./usr/include/linux/nsfs.h
+-rw-r--r-- root root 8191 ./usr/include/linux/nubus.h
+-rw-r--r-- root root 1661 ./usr/include/linux/nvme_ioctl.h
+-rw-r--r-- root root 532 ./usr/include/linux/nvram.h
+-rw-r--r-- root root 20853 ./usr/include/linux/omap3isp.h
+-rw-r--r-- root root 5918 ./usr/include/linux/omapfb.h
+-rw-r--r-- root root 511 ./usr/include/linux/oom.h
+-rw-r--r-- root root 37676 ./usr/include/linux/openvswitch.h
+-rw-r--r-- root root 1672 ./usr/include/linux/packet_diag.h
+-rw-r--r-- root root 141 ./usr/include/linux/param.h
+-rw-r--r-- root root 3644 ./usr/include/linux/parport.h
+-rw-r--r-- root root 892 ./usr/include/linux/patchkey.h
+-rw-r--r-- root root 1380 ./usr/include/linux/pci.h
+-rw-r--r-- root root 56733 ./usr/include/linux/pci_regs.h
+-rw-r--r-- root root 711 ./usr/include/linux/pcitest.h
+-rw-r--r-- root root 34228 ./usr/include/linux/perf_event.h
+-rw-r--r-- root root 2097 ./usr/include/linux/personality.h
+-rw-r--r-- root root 10569 ./usr/include/linux/pfkeyv2.h
+-rw-r--r-- root root 2394 ./usr/include/linux/pg.h
+-rw-r--r-- root root 1654 ./usr/include/linux/phantom.h
+-rw-r--r-- root root 4677 ./usr/include/linux/phonet.h
+-rw-r--r-- root root 2687 ./usr/include/linux/pktcdvd.h
+-rw-r--r-- root root 15441 ./usr/include/linux/pkt_cls.h
+-rw-r--r-- root root 27648 ./usr/include/linux/pkt_sched.h
+-rw-r--r-- root root 5444 ./usr/include/linux/pmu.h
+-rw-r--r-- root root 22 ./usr/include/linux/poll.h
+-rw-r--r-- root root 1254 ./usr/include/linux/posix_acl.h
+-rw-r--r-- root root 1115 ./usr/include/linux/posix_acl_xattr.h
+-rw-r--r-- root root 1098 ./usr/include/linux/posix_types.h
+-rw-r--r-- root root 3285 ./usr/include/linux/ppdev.h
+-rw-r--r-- root root 2527 ./usr/include/linux/ppp-comp.h
+-rw-r--r-- root root 5107 ./usr/include/linux/ppp_defs.h
+-rw-r--r-- root root 5438 ./usr/include/linux/ppp-ioctl.h
+-rw-r--r-- root root 4734 ./usr/include/linux/pps.h
+-rw-r--r-- root root 8073 ./usr/include/linux/prctl.h
+-rw-r--r-- root root 1073 ./usr/include/linux/pr.h
+-rw-r--r-- root root 798 ./usr/include/linux/psample.h
+-rw-r--r-- root root 4328 ./usr/include/linux/psci.h
+-rw-r--r-- root root 4036 ./usr/include/linux/psp-sev.h
+-rw-r--r-- root root 6731 ./usr/include/linux/ptp_clock.h
+-rw-r--r-- root root 4265 ./usr/include/linux/ptrace.h
+-rw-r--r-- root root 2469 ./usr/include/linux/qemu_fw_cfg.h
+-rw-r--r-- root root 2328 ./usr/include/linux/qnx4_fs.h
+-rw-r--r-- root root 624 ./usr/include/linux/qnxtypes.h
+-rw-r--r-- root root 893 ./usr/include/linux/qrtr.h
+-rw-r--r-- root root 6291 ./usr/include/linux/quota.h
+-rw-r--r-- root root 360 ./usr/include/linux/radeonfb.h
+drwxr-xr-x root root 4096 ./usr/include/linux/raid
+-rw-r--r-- root root 16161 ./usr/include/linux/raid/md_p.h
+-rw-r--r-- root root 4484 ./usr/include/linux/raid/md_u.h
+-rw-r--r-- root root 1370 ./usr/include/linux/random.h
+-rw-r--r-- root root 365 ./usr/include/linux/raw.h
+-rw-r--r-- root root 11081 ./usr/include/linux/rds.h
+-rw-r--r-- root root 1343 ./usr/include/linux/reboot.h
+-rw-r--r-- root root 775 ./usr/include/linux/reiserfs_fs.h
+-rw-r--r-- root root 533 ./usr/include/linux/reiserfs_xattr.h
+-rw-r--r-- root root 2347 ./usr/include/linux/resource.h
+-rw-r--r-- root root 3682 ./usr/include/linux/rfkill.h
+-rw-r--r-- root root 3248 ./usr/include/linux/rio_cm_cdev.h
+-rw-r--r-- root root 9330 ./usr/include/linux/rio_mport_cdev.h
+-rw-r--r-- root root 1238 ./usr/include/linux/romfs_fs.h
+-rw-r--r-- root root 2232 ./usr/include/linux/rose.h
+-rw-r--r-- root root 2332 ./usr/include/linux/route.h
+-rw-r--r-- root root 544 ./usr/include/linux/rpmsg.h
+-rw-r--r-- root root 4904 ./usr/include/linux/rseq.h
+-rw-r--r-- root root 4009 ./usr/include/linux/rtc.h
+-rw-r--r-- root root 19055 ./usr/include/linux/rtnetlink.h
+-rw-r--r-- root root 4897 ./usr/include/linux/rxrpc.h
+-rw-r--r-- root root 4597 ./usr/include/linux/scc.h
+drwxr-xr-x root root 4096 ./usr/include/linux/sched
+-rw-r--r-- root root 4647 ./usr/include/linux/sched.h
+-rw-r--r-- root root 4480 ./usr/include/linux/sched/types.h
+-rw-r--r-- root root 6382 ./usr/include/linux/scif_ioctl.h
+-rw-r--r-- root root 2479 ./usr/include/linux/screen_info.h
+-rw-r--r-- root root 34783 ./usr/include/linux/sctp.h
+-rw-r--r-- root root 2839 ./usr/include/linux/sdla.h
+-rw-r--r-- root root 3235 ./usr/include/linux/seccomp.h
+-rw-r--r-- root root 2704 ./usr/include/linux/securebits.h
+-rw-r--r-- root root 3297 ./usr/include/linux/sed-opal.h
+-rw-r--r-- root root 589 ./usr/include/linux/seg6_genl.h
+-rw-r--r-- root root 1170 ./usr/include/linux/seg6.h
+-rw-r--r-- root root 423 ./usr/include/linux/seg6_hmac.h
+-rw-r--r-- root root 927 ./usr/include/linux/seg6_iptunnel.h
+-rw-r--r-- root root 2060 ./usr/include/linux/seg6_local.h
+-rw-r--r-- root root 1195 ./usr/include/linux/selinux_netlink.h
+-rw-r--r-- root root 3043 ./usr/include/linux/sem.h
+-rw-r--r-- root root 6436 ./usr/include/linux/serial_core.h
+-rw-r--r-- root root 3866 ./usr/include/linux/serial.h
+-rw-r--r-- root root 15496 ./usr/include/linux/serial_reg.h
+-rw-r--r-- root root 2063 ./usr/include/linux/serio.h
+-rw-r--r-- root root 3785 ./usr/include/linux/shm.h
+-rw-r--r-- root root 1233 ./usr/include/linux/signalfd.h
+-rw-r--r-- root root 388 ./usr/include/linux/signal.h
+-rw-r--r-- root root 2835 ./usr/include/linux/smc_diag.h
+-rw-r--r-- root root 780 ./usr/include/linux/smc.h
+-rw-r--r-- root root 1058 ./usr/include/linux/smiapp.h
+-rw-r--r-- root root 13014 ./usr/include/linux/snmp.h
+-rw-r--r-- root root 727 ./usr/include/linux/sock_diag.h
+-rw-r--r-- root root 819 ./usr/include/linux/socket.h
+-rw-r--r-- root root 6846 ./usr/include/linux/sockios.h
+-rw-r--r-- root root 2290 ./usr/include/linux/sonet.h
+-rw-r--r-- root root 5309 ./usr/include/linux/sonypi.h
+-rw-r--r-- root root 46038 ./usr/include/linux/soundcard.h
+-rw-r--r-- root root 1237 ./usr/include/linux/sound.h
+drwxr-xr-x root root 4096 ./usr/include/linux/spi
+-rw-r--r-- root root 5286 ./usr/include/linux/spi/spidev.h
+-rw-r--r-- root root 6100 ./usr/include/linux/stat.h
+-rw-r--r-- root root 131 ./usr/include/linux/stddef.h
+-rw-r--r-- root root 1275 ./usr/include/linux/stm.h
+-rw-r--r-- root root 238 ./usr/include/linux/string.h
+drwxr-xr-x root root 4096 ./usr/include/linux/sunrpc
+-rw-r--r-- root root 1144 ./usr/include/linux/sunrpc/debug.h
+-rw-r--r-- root root 1431 ./usr/include/linux/suspend_ioctls.h
+-rw-r--r-- root root 6711 ./usr/include/linux/swab.h
+-rw-r--r-- root root 4768 ./usr/include/linux/switchtec_ioctl.h
+-rw-r--r-- root root 2883 ./usr/include/linux/sync_file.h
+-rw-r--r-- root root 8985 ./usr/include/linux/synclink.h
+-rw-r--r-- root root 25880 ./usr/include/linux/sysctl.h
+-rw-r--r-- root root 1049 ./usr/include/linux/sysinfo.h
+-rw-r--r-- root root 3899 ./usr/include/linux/target_core_user.h
+-rw-r--r-- root root 7152 ./usr/include/linux/taskstats.h
+drwxr-xr-x root root 4096 ./usr/include/linux/tc_act
+-rw-r--r-- root root 764 ./usr/include/linux/tc_act/tc_bpf.h
+-rw-r--r-- root root 390 ./usr/include/linux/tc_act/tc_connmark.h
+-rw-r--r-- root root 644 ./usr/include/linux/tc_act/tc_csum.h
+-rw-r--r-- root root 934 ./usr/include/linux/tc_act/tc_ct.h
+-rw-r--r-- root root 556 ./usr/include/linux/tc_act/tc_ctinfo.h
+-rw-r--r-- root root 322 ./usr/include/linux/tc_act/tc_defact.h
+-rw-r--r-- root root 626 ./usr/include/linux/tc_act/tc_gact.h
+-rw-r--r-- root root 600 ./usr/include/linux/tc_act/tc_ife.h
+-rw-r--r-- root root 415 ./usr/include/linux/tc_act/tc_ipt.h
+-rw-r--r-- root root 728 ./usr/include/linux/tc_act/tc_mirred.h
+-rw-r--r-- root root 992 ./usr/include/linux/tc_act/tc_mpls.h
+-rw-r--r-- root root 424 ./usr/include/linux/tc_act/tc_nat.h
+-rw-r--r-- root root 1527 ./usr/include/linux/tc_act/tc_pedit.h
+-rw-r--r-- root root 456 ./usr/include/linux/tc_act/tc_sample.h
+-rw-r--r-- root root 1443 ./usr/include/linux/tc_act/tc_skbedit.h
+-rw-r--r-- root root 815 ./usr/include/linux/tc_act/tc_skbmod.h
+-rw-r--r-- root root 1898 ./usr/include/linux/tc_act/tc_tunnel_key.h
+-rw-r--r-- root root 816 ./usr/include/linux/tc_act/tc_vlan.h
+drwxr-xr-x root root 4096 ./usr/include/linux/tc_ematch
+-rw-r--r-- root root 414 ./usr/include/linux/tc_ematch/tc_em_cmp.h
+-rw-r--r-- root root 391 ./usr/include/linux/tc_ematch/tc_em_ipt.h
+-rw-r--r-- root root 2116 ./usr/include/linux/tc_ematch/tc_em_meta.h
+-rw-r--r-- root root 255 ./usr/include/linux/tc_ematch/tc_em_nbyte.h
+-rw-r--r-- root root 384 ./usr/include/linux/tc_ematch/tc_em_text.h
+-rw-r--r-- root root 10857 ./usr/include/linux/tcp.h
+-rw-r--r-- root root 1549 ./usr/include/linux/tcp_metrics.h
+-rw-r--r-- root root 12581 ./usr/include/linux/tee.h
+-rw-r--r-- root root 506 ./usr/include/linux/termios.h
+-rw-r--r-- root root 924 ./usr/include/linux/thermal.h
+-rw-r--r-- root root 1748 ./usr/include/linux/time.h
+-rw-r--r-- root root 936 ./usr/include/linux/timerfd.h
+-rw-r--r-- root root 278 ./usr/include/linux/times.h
+-rw-r--r-- root root 996 ./usr/include/linux/time_types.h
+-rw-r--r-- root root 7817 ./usr/include/linux/timex.h
+-rw-r--r-- root root 1729 ./usr/include/linux/tiocl.h
+-rw-r--r-- root root 14848 ./usr/include/linux/tipc_config.h
+-rw-r--r-- root root 8272 ./usr/include/linux/tipc.h
+-rw-r--r-- root root 9156 ./usr/include/linux/tipc_netlink.h
+-rw-r--r-- root root 468 ./usr/include/linux/tipc_sockets_diag.h
+-rw-r--r-- root root 4288 ./usr/include/linux/tls.h
+-rw-r--r-- root root 1930 ./usr/include/linux/toshiba.h
+-rw-r--r-- root root 4527 ./usr/include/linux/tty_flags.h
+-rw-r--r-- root root 1585 ./usr/include/linux/tty.h
+-rw-r--r-- root root 1476 ./usr/include/linux/types.h
+-rw-r--r-- root root 697 ./usr/include/linux/udf_fs_i.h
+-rw-r--r-- root root 643 ./usr/include/linux/udmabuf.h
+-rw-r--r-- root root 1613 ./usr/include/linux/udp.h
+-rw-r--r-- root root 4648 ./usr/include/linux/uhid.h
+-rw-r--r-- root root 9261 ./usr/include/linux/uinput.h
+-rw-r--r-- root root 732 ./usr/include/linux/uio.h
+-rw-r--r-- root root 798 ./usr/include/linux/uleds.h
+-rw-r--r-- root root 4562 ./usr/include/linux/ultrasound.h
+-rw-r--r-- root root 384 ./usr/include/linux/un.h
+-rw-r--r-- root root 220 ./usr/include/linux/unistd.h
+-rw-r--r-- root root 1328 ./usr/include/linux/unix_diag.h
+drwxr-xr-x root root 4096 ./usr/include/linux/usb
+-rw-r--r-- root root 19490 ./usr/include/linux/usb/audio.h
+-rw-r--r-- root root 12962 ./usr/include/linux/usb/cdc.h
+-rw-r--r-- root root 739 ./usr/include/linux/usb/cdc-wdm.h
+-rw-r--r-- root root 9149 ./usr/include/linux/usb/ch11.h
+-rw-r--r-- root root 38850 ./usr/include/linux/usb/ch9.h
+-rw-r--r-- root root 566 ./usr/include/linux/usb/charger.h
+-rw-r--r-- root root 8317 ./usr/include/linux/usbdevice_fs.h
+-rw-r--r-- root root 10370 ./usr/include/linux/usb/functionfs.h
+-rw-r--r-- root root 2818 ./usr/include/linux/usb/gadgetfs.h
+-rw-r--r-- root root 1385 ./usr/include/linux/usb/g_printer.h
+-rw-r--r-- root root 1097 ./usr/include/linux/usb/g_uvc.h
+-rw-r--r-- root root 640 ./usr/include/linux/usbip.h
+-rw-r--r-- root root 3434 ./usr/include/linux/usb/midi.h
+-rw-r--r-- root root 4713 ./usr/include/linux/usb/tmc.h
+-rw-r--r-- root root 16360 ./usr/include/linux/usb/video.h
+-rw-r--r-- root root 6811 ./usr/include/linux/userfaultfd.h
+-rw-r--r-- root root 1516 ./usr/include/linux/userio.h
+-rw-r--r-- root root 215 ./usr/include/linux/utime.h
+-rw-r--r-- root root 669 ./usr/include/linux/utsname.h
+-rw-r--r-- root root 1356 ./usr/include/linux/uuid.h
+-rw-r--r-- root root 2590 ./usr/include/linux/uvcvideo.h
+-rw-r--r-- root root 4177 ./usr/include/linux/v4l2-common.h
+-rw-r--r-- root root 52061 ./usr/include/linux/v4l2-controls.h
+-rw-r--r-- root root 31562 ./usr/include/linux/v4l2-dv-timings.h
+-rw-r--r-- root root 5101 ./usr/include/linux/v4l2-mediabus.h
+-rw-r--r-- root root 6339 ./usr/include/linux/v4l2-subdev.h
+-rw-r--r-- root root 7257 ./usr/include/linux/vbox_err.h
+-rw-r--r-- root root 8755 ./usr/include/linux/vboxguest.h
+-rw-r--r-- root root 11509 ./usr/include/linux/vbox_vmmdev_types.h
+-rw-r--r-- root root 97 ./usr/include/linux/version.h
+-rw-r--r-- root root 224 ./usr/include/linux/veth.h
+-rw-r--r-- root root 836 ./usr/include/linux/vfio_ccw.h
+-rw-r--r-- root root 33767 ./usr/include/linux/vfio.h
+-rw-r--r-- root root 5069 ./usr/include/linux/vhost.h
+-rw-r--r-- root root 3164 ./usr/include/linux/vhost_types.h
+-rw-r--r-- root root 91377 ./usr/include/linux/videodev2.h
+-rw-r--r-- root root 2041 ./usr/include/linux/virtio_9p.h
+-rw-r--r-- root root 5036 ./usr/include/linux/virtio_balloon.h
+-rw-r--r-- root root 6797 ./usr/include/linux/virtio_blk.h
+-rw-r--r-- root root 3836 ./usr/include/linux/virtio_config.h
+-rw-r--r-- root root 3136 ./usr/include/linux/virtio_console.h
+-rw-r--r-- root root 13874 ./usr/include/linux/virtio_crypto.h
+-rw-r--r-- root root 490 ./usr/include/linux/virtio_fs.h
+-rw-r--r-- root root 8540 ./usr/include/linux/virtio_gpu.h
+-rw-r--r-- root root 2592 ./usr/include/linux/virtio_ids.h
+-rw-r--r-- root root 2506 ./usr/include/linux/virtio_input.h
+-rw-r--r-- root root 3783 ./usr/include/linux/virtio_iommu.h
+-rw-r--r-- root root 4586 ./usr/include/linux/virtio_mmio.h
+-rw-r--r-- root root 10549 ./usr/include/linux/virtio_net.h
+-rw-r--r-- root root 7079 ./usr/include/linux/virtio_pci.h
+-rw-r--r-- root root 639 ./usr/include/linux/virtio_pmem.h
+-rw-r--r-- root root 7430 ./usr/include/linux/virtio_ring.h
+-rw-r--r-- root root 265 ./usr/include/linux/virtio_rng.h
+-rw-r--r-- root root 6035 ./usr/include/linux/virtio_scsi.h
+-rw-r--r-- root root 2153 ./usr/include/linux/virtio_types.h
+-rw-r--r-- root root 3086 ./usr/include/linux/virtio_vsock.h
+-rw-r--r-- root root 455 ./usr/include/linux/vmcore.h
+-rw-r--r-- root root 963 ./usr/include/linux/vm_sockets_diag.h
+-rw-r--r-- root root 5314 ./usr/include/linux/vm_sockets.h
+-rw-r--r-- root root 1885 ./usr/include/linux/vsockmon.h
+-rw-r--r-- root root 3059 ./usr/include/linux/vt.h
+-rw-r--r-- root root 1719 ./usr/include/linux/vtpm_proxy.h
+-rw-r--r-- root root 682 ./usr/include/linux/wait.h
+-rw-r--r-- root root 2335 ./usr/include/linux/watchdog.h
+drwxr-xr-x root root 4096 ./usr/include/linux/wimax
+-rw-r--r-- root root 8371 ./usr/include/linux/wimax.h
+-rw-r--r-- root root 15930 ./usr/include/linux/wimax/i2400m.h
+-rw-r--r-- root root 42713 ./usr/include/linux/wireless.h
+-rw-r--r-- root root 1761 ./usr/include/linux/wmi.h
+-rw-r--r-- root root 3562 ./usr/include/linux/x25.h
+-rw-r--r-- root root 2860 ./usr/include/linux/xattr.h
+-rw-r--r-- root root 1259 ./usr/include/linux/xdp_diag.h
+-rw-r--r-- root root 11737 ./usr/include/linux/xfrm.h
+-rw-r--r-- root root 2976 ./usr/include/linux/xilinx-v4l2-controls.h
+-rw-r--r-- root root 3296 ./usr/include/linux/zorro.h
+-rw-r--r-- root root 29963 ./usr/include/linux/zorro_ids.h
+-rw-r--r-- root root 7675 ./usr/include/locale.h
+drwxr-xr-x root root 4096 ./usr/include/lzma
+-rw-r--r-- root root 24858 ./usr/include/lzma/base.h
+-rw-r--r-- root root 2630 ./usr/include/lzma/bcj.h
+-rw-r--r-- root root 22107 ./usr/include/lzma/block.h
+-rw-r--r-- root root 4255 ./usr/include/lzma/check.h
+-rw-r--r-- root root 24844 ./usr/include/lzma/container.h
+-rw-r--r-- root root 1865 ./usr/include/lzma/delta.h
+-rw-r--r-- root root 16520 ./usr/include/lzma/filter.h
+-rw-r--r-- root root 9866 ./usr/include/lzma.h
+-rw-r--r-- root root 2604 ./usr/include/lzma/hardware.h
+-rw-r--r-- root root 23491 ./usr/include/lzma/index.h
+-rw-r--r-- root root 3914 ./usr/include/lzma/index_hash.h
+-rw-r--r-- root root 14744 ./usr/include/lzma/lzma12.h
+-rw-r--r-- root root 8253 ./usr/include/lzma/stream_flags.h
+-rw-r--r-- root root 3497 ./usr/include/lzma/version.h
+-rw-r--r-- root root 6546 ./usr/include/lzma/vli.h
+drwxr-xr-x root root 4096 ./usr/include/lzo
+-rw-r--r-- root root 2638 ./usr/include/lzo/lzo1a.h
+-rw-r--r-- root root 5387 ./usr/include/lzo/lzo1b.h
+-rw-r--r-- root root 5384 ./usr/include/lzo/lzo1c.h
+-rw-r--r-- root root 3073 ./usr/include/lzo/lzo1f.h
+-rw-r--r-- root root 2634 ./usr/include/lzo/lzo1.h
+-rw-r--r-- root root 5873 ./usr/include/lzo/lzo1x.h
+-rw-r--r-- root root 4641 ./usr/include/lzo/lzo1y.h
+-rw-r--r-- root root 3771 ./usr/include/lzo/lzo1z.h
+-rw-r--r-- root root 2525 ./usr/include/lzo/lzo2a.h
+-rw-r--r-- root root 5566 ./usr/include/lzo/lzo_asm.h
+-rw-r--r-- root root 16006 ./usr/include/lzo/lzoconf.h
+-rw-r--r-- root root 127289 ./usr/include/lzo/lzodefs.h
+-rw-r--r-- root root 1823 ./usr/include/lzo/lzoutil.h
+-rw-r--r-- root root 6186 ./usr/include/malloc.h
+-rw-r--r-- root root 46404 ./usr/include/math.h
+-rw-r--r-- root root 2435 ./usr/include/mcheck.h
+-rw-r--r-- root root 956 ./usr/include/memory.h
+-rw-r--r-- root root 12275 ./usr/include/menu.h
+drwxr-xr-x root root 4096 ./usr/include/misc
+-rw-r--r-- root root 3936 ./usr/include/misc/cxl.h
+-rw-r--r-- root root 953 ./usr/include/misc/fastrpc.h
+-rw-r--r-- root root 19004 ./usr/include/misc/habanalabs.h
+-rw-r--r-- root root 1947 ./usr/include/misc/ocxl.h
+-rw-r--r-- root root 12341 ./usr/include/misc/xilinx_sdfec.h
+-rw-r--r-- root root 3359 ./usr/include/mntent.h
+-rw-r--r-- root root 1804 ./usr/include/monetary.h
+-rw-r--r-- root root 3760 ./usr/include/mqueue.h
+drwxr-xr-x root root 4096 ./usr/include/mtd
+-rw-r--r-- root root 1644 ./usr/include/mtd/inftl-user.h
+-rw-r--r-- root root 9732 ./usr/include/mtd/mtd-abi.h
+-rw-r--r-- root root 1242 ./usr/include/mtd/mtd-user.h
+-rw-r--r-- root root 2116 ./usr/include/mtd/nftl-user.h
+-rw-r--r-- root root 18220 ./usr/include/mtd/ubi-user.h
+-rw-r--r-- root root 4240 ./usr/include/nc_tparm.h
+-rw-r--r-- root root 4522 ./usr/include/ncurses_dll.h
+lrwxrwxrwx root root 8 ./usr/include/ncurses.h -> curses.h
+-rw-r--r-- root root 2454 ./usr/include/ndbm.h
+drwxr-xr-x root root 4096 ./usr/include/net
+drwxr-xr-x root root 4096 ./usr/include/netash
+-rw-r--r-- root root 1363 ./usr/include/netash/ash.h
+drwxr-xr-x root root 4096 ./usr/include/netatalk
+-rw-r--r-- root root 1029 ./usr/include/netatalk/at.h
+drwxr-xr-x root root 4096 ./usr/include/netax25
+-rw-r--r-- root root 4810 ./usr/include/netax25/ax25.h
+-rw-r--r-- root root 28100 ./usr/include/netdb.h
+drwxr-xr-x root root 4096 ./usr/include/neteconet
+-rw-r--r-- root root 1668 ./usr/include/neteconet/ec.h
+-rw-r--r-- root root 3136 ./usr/include/net/ethernet.h
+-rw-r--r-- root root 7132 ./usr/include/net/if_arp.h
+-rw-r--r-- root root 6982 ./usr/include/net/if.h
+-rw-r--r-- root root 1262 ./usr/include/net/if_packet.h
+-rw-r--r-- root root 6714 ./usr/include/net/if_ppp.h
+-rw-r--r-- root root 1625 ./usr/include/net/if_shaper.h
+-rw-r--r-- root root 933 ./usr/include/net/if_slip.h
+drwxr-xr-x root root 4096 ./usr/include/netinet
+-rw-r--r-- root root 1985 ./usr/include/netinet/ether.h
+-rw-r--r-- root root 11515 ./usr/include/netinet/icmp6.h
+-rw-r--r-- root root 3976 ./usr/include/netinet/if_ether.h
+-rw-r--r-- root root 1186 ./usr/include/netinet/if_fddi.h
+-rw-r--r-- root root 3692 ./usr/include/netinet/if_tr.h
+-rw-r--r-- root root 4663 ./usr/include/netinet/igmp.h
+-rw-r--r-- root root 21702 ./usr/include/netinet/in.h
+-rw-r--r-- root root 1494 ./usr/include/netinet/in_systm.h
+-rw-r--r-- root root 5394 ./usr/include/netinet/ip6.h
+-rw-r--r-- root root 9436 ./usr/include/netinet/ip.h
+-rw-r--r-- root root 10131 ./usr/include/netinet/ip_icmp.h
+-rw-r--r-- root root 10490 ./usr/include/netinet/tcp.h
+-rw-r--r-- root root 3774 ./usr/include/netinet/udp.h
+drwxr-xr-x root root 4096 ./usr/include/netipx
+-rw-r--r-- root root 2900 ./usr/include/netipx/ipx.h
+drwxr-xr-x root root 4096 ./usr/include/netiucv
+-rw-r--r-- root root 1594 ./usr/include/netiucv/iucv.h
+drwxr-xr-x root root 4096 ./usr/include/netpacket
+-rw-r--r-- root root 2438 ./usr/include/netpacket/packet.h
+-rw-r--r-- root root 28 ./usr/include/net/ppp-comp.h
+-rw-r--r-- root root 162 ./usr/include/net/ppp_defs.h
+drwxr-xr-x root root 4096 ./usr/include/netrom
+-rw-r--r-- root root 2226 ./usr/include/netrom/netrom.h
+drwxr-xr-x root root 4096 ./usr/include/netrose
+-rw-r--r-- root root 3184 ./usr/include/netrose/rose.h
+-rw-r--r-- root root 4704 ./usr/include/net/route.h
+drwxr-xr-x root root 4096 ./usr/include/nfs
+-rw-r--r-- root root 23 ./usr/include/nfs/nfs.h
+-rw-r--r-- root root 1601 ./usr/include/nlist.h
+-rw-r--r-- root root 1753 ./usr/include/nl_types.h
+-rw-r--r-- root root 1879 ./usr/include/nss.h
+-rw-r--r-- root root 21307 ./usr/include/obstack.h
+drwxr-xr-x root root 4096 ./usr/include/omap
+-rw-r--r-- root root 4843 ./usr/include/omap/omap_drm.h
+drwxr-xr-x root root 4096 ./usr/include/openssl
+-rw-r--r-- root root 3349 ./usr/include/openssl/aes.h
+-rw-r--r-- root root 14599 ./usr/include/openssl/asn1err.h
+-rw-r--r-- root root 33627 ./usr/include/openssl/asn1.h
+-rw-r--r-- root root 395 ./usr/include/openssl/asn1_mac.h
+-rw-r--r-- root root 32940 ./usr/include/openssl/asn1t.h
+-rw-r--r-- root root 1326 ./usr/include/openssl/asyncerr.h
+-rw-r--r-- root root 2398 ./usr/include/openssl/async.h
+-rw-r--r-- root root 6400 ./usr/include/openssl/bioerr.h
+-rw-r--r-- root root 34907 ./usr/include/openssl/bio.h
+-rw-r--r-- root root 1847 ./usr/include/openssl/blowfish.h
+-rw-r--r-- root root 4907 ./usr/include/openssl/bnerr.h
+-rw-r--r-- root root 22135 ./usr/include/openssl/bn.h
+-rw-r--r-- root root 820 ./usr/include/openssl/buffererr.h
+-rw-r--r-- root root 1600 ./usr/include/openssl/buffer.h
+-rw-r--r-- root root 3179 ./usr/include/openssl/camellia.h
+-rw-r--r-- root root 1674 ./usr/include/openssl/cast.h
+-rw-r--r-- root root 1064 ./usr/include/openssl/cmac.h
+-rw-r--r-- root root 11160 ./usr/include/openssl/cmserr.h
+-rw-r--r-- root root 16379 ./usr/include/openssl/cms.h
+-rw-r--r-- root root 1212 ./usr/include/openssl/comperr.h
+-rw-r--r-- root root 1328 ./usr/include/openssl/comp.h
+-rw-r--r-- root root 1300 ./usr/include/openssl/conf_api.h
+-rw-r--r-- root root 3429 ./usr/include/openssl/conferr.h
+-rw-r--r-- root root 5601 ./usr/include/openssl/conf.h
+-rw-r--r-- root root 2261 ./usr/include/openssl/cryptoerr.h
+-rw-r--r-- root root 17239 ./usr/include/openssl/crypto.h
+-rw-r--r-- root root 3470 ./usr/include/openssl/cterr.h
+-rw-r--r-- root root 15872 ./usr/include/openssl/ct.h
+-rw-r--r-- root root 7627 ./usr/include/openssl/des.h
+-rw-r--r-- root root 3974 ./usr/include/openssl/dherr.h
+-rw-r--r-- root root 13403 ./usr/include/openssl/dh.h
+-rw-r--r-- root root 2972 ./usr/include/openssl/dsaerr.h
+-rw-r--r-- root root 10051 ./usr/include/openssl/dsa.h
+-rw-r--r-- root root 1578 ./usr/include/openssl/dtls1.h
+-rw-r--r-- root root 924 ./usr/include/openssl/ebcdic.h
+-rw-r--r-- root root 358 ./usr/include/openssl/ecdh.h
+-rw-r--r-- root root 358 ./usr/include/openssl/ecdsa.h
+-rw-r--r-- root root 15758 ./usr/include/openssl/ecerr.h
+-rw-r--r-- root root 63596 ./usr/include/openssl/ec.h
+-rw-r--r-- root root 5447 ./usr/include/openssl/engineerr.h
+-rw-r--r-- root root 34661 ./usr/include/openssl/engine.h
+-rw-r--r-- root root 8888 ./usr/include/openssl/e_os2.h
+-rw-r--r-- root root 11269 ./usr/include/openssl/err.h
+-rw-r--r-- root root 11427 ./usr/include/openssl/evperr.h
+-rw-r--r-- root root 76828 ./usr/include/openssl/evp.h
+-rw-r--r-- root root 1591 ./usr/include/openssl/hmac.h
+-rw-r--r-- root root 2099 ./usr/include/openssl/idea.h
+-rw-r--r-- root root 2122 ./usr/include/openssl/kdferr.h
+-rw-r--r-- root root 4326 ./usr/include/openssl/kdf.h
+-rw-r--r-- root root 9271 ./usr/include/openssl/lhash.h
+-rw-r--r-- root root 1054 ./usr/include/openssl/md2.h
+-rw-r--r-- root root 1322 ./usr/include/openssl/md4.h
+-rw-r--r-- root root 1320 ./usr/include/openssl/md5.h
+-rw-r--r-- root root 1053 ./usr/include/openssl/mdc2.h
+-rw-r--r-- root root 10478 ./usr/include/openssl/modes.h
+-rw-r--r-- root root 1316 ./usr/include/openssl/objectserr.h
+-rw-r--r-- root root 6633 ./usr/include/openssl/objects.h
+-rw-r--r-- root root 217522 ./usr/include/openssl/obj_mac.h
+-rw-r--r-- root root 3356 ./usr/include/openssl/ocsperr.h
+-rw-r--r-- root root 15305 ./usr/include/openssl/ocsp.h
+-rw-r--r-- root root 4520 ./usr/include/openssl/opensslconf-64.h
+-rw-r--r-- root root 564 ./usr/include/openssl/opensslconf.h
+-rw-r--r-- root root 4102 ./usr/include/openssl/opensslv.h
+-rw-r--r-- root root 6266 ./usr/include/openssl/ossl_typ.h
+-rw-r--r-- root root 415 ./usr/include/openssl/pem2.h
+-rw-r--r-- root root 5098 ./usr/include/openssl/pemerr.h
+-rw-r--r-- root root 15468 ./usr/include/openssl/pem.h
+-rw-r--r-- root root 3749 ./usr/include/openssl/pkcs12err.h
+-rw-r--r-- root root 9871 ./usr/include/openssl/pkcs12.h
+-rw-r--r-- root root 5110 ./usr/include/openssl/pkcs7err.h
+-rw-r--r-- root root 11590 ./usr/include/openssl/pkcs7.h
+-rw-r--r-- root root 4763 ./usr/include/openssl/rand_drbg.h
+-rw-r--r-- root root 4633 ./usr/include/openssl/randerr.h
+-rw-r--r-- root root 2213 ./usr/include/openssl/rand.h
+-rw-r--r-- root root 1534 ./usr/include/openssl/rc2.h
+-rw-r--r-- root root 825 ./usr/include/openssl/rc4.h
+-rw-r--r-- root root 1988 ./usr/include/openssl/rc5.h
+-rw-r--r-- root root 1243 ./usr/include/openssl/ripemd.h
+-rw-r--r-- root root 9075 ./usr/include/openssl/rsaerr.h
+-rw-r--r-- root root 22202 ./usr/include/openssl/rsa.h
+-rw-r--r-- root root 8139 ./usr/include/openssl/safestack.h
+-rw-r--r-- root root 3479 ./usr/include/openssl/seed.h
+-rw-r--r-- root root 3831 ./usr/include/openssl/sha.h
+-rw-r--r-- root root 3827 ./usr/include/openssl/srp.h
+-rw-r--r-- root root 1316 ./usr/include/openssl/srtp.h
+-rw-r--r-- root root 542 ./usr/include/openssl/ssl2.h
+-rw-r--r-- root root 14576 ./usr/include/openssl/ssl3.h
+-rw-r--r-- root root 46676 ./usr/include/openssl/sslerr.h
+-rw-r--r-- root root 111253 ./usr/include/openssl/ssl.h
+-rw-r--r-- root root 3095 ./usr/include/openssl/stack.h
+-rw-r--r-- root root 4399 ./usr/include/openssl/storeerr.h
+-rw-r--r-- root root 11199 ./usr/include/openssl/store.h
+-rw-r--r-- root root 1311 ./usr/include/openssl/symhacks.h
+-rw-r--r-- root root 72490 ./usr/include/openssl/tls1.h
+-rw-r--r-- root root 6746 ./usr/include/openssl/tserr.h
+-rw-r--r-- root root 22429 ./usr/include/openssl/ts.h
+-rw-r--r-- root root 1666 ./usr/include/openssl/txt_db.h
+-rw-r--r-- root root 2737 ./usr/include/openssl/uierr.h
+-rw-r--r-- root root 16052 ./usr/include/openssl/ui.h
+-rw-r--r-- root root 1377 ./usr/include/openssl/whrlpool.h
+-rw-r--r-- root root 6777 ./usr/include/openssl/x509err.h
+-rw-r--r-- root root 43123 ./usr/include/openssl/x509.h
+-rw-r--r-- root root 8777 ./usr/include/openssl/x509v3err.h
+-rw-r--r-- root root 33377 ./usr/include/openssl/x509v3.h
+-rw-r--r-- root root 32179 ./usr/include/openssl/x509_vfy.h
+-rw-r--r-- root root 4201 ./usr/include/panel.h
+-rw-r--r-- root root 2977 ./usr/include/paths.h
+-rw-r--r-- root root 15456 ./usr/include/pciaccess.h
+-rw-r--r-- root root 6783 ./usr/include/pcrecpparg.h
+-rw-r--r-- root root 26529 ./usr/include/pcrecpp.h
+-rw-r--r-- root root 31718 ./usr/include/pcre.h
+-rw-r--r-- root root 5631 ./usr/include/pcreposix.h
+-rw-r--r-- root root 6600 ./usr/include/pcre_scanner.h
+-rw-r--r-- root root 6312 ./usr/include/pcre_stringpiece.h
+drwxr-xr-x root root 4096 ./usr/include/pixman-1
+-rw-r--r-- root root 47735 ./usr/include/pixman-1/pixman.h
+-rw-r--r-- root root 1786 ./usr/include/pixman-1/pixman-version.h
+-rw-r--r-- root root 15029 ./usr/include/plugin-api.h
+lrwxrwxrwx root root 18 ./usr/include/pngconf.h -> libpng16/pngconf.h
+lrwxrwxrwx root root 14 ./usr/include/png.h -> libpng16/png.h
+lrwxrwxrwx root root 21 ./usr/include/pnglibconf.h -> libpng16/pnglibconf.h
+-rw-r--r-- root root 22 ./usr/include/poll.h
+-rw-r--r-- root root 6801 ./usr/include/printf.h
+drwxr-xr-x root root 4096 ./usr/include/proc
+-rw-r--r-- root root 509 ./usr/include/proc/alloc.h
+-rw-r--r-- root root 457 ./usr/include/proc/devname.h
+-rw-r--r-- root root 913 ./usr/include/proc/escape.h
+-rw-r--r-- root root 1068 ./usr/include/proc/numa.h
+-rw-r--r-- root root 2936 ./usr/include/proc/procps.h
+-rw-r--r-- root root 305 ./usr/include/proc/pwcache.h
+-rw-r--r-- root root 15204 ./usr/include/proc/readproc.h
+-rw-r--r-- root root 3477 ./usr/include/proc_service.h
+-rw-r--r-- root root 1000 ./usr/include/proc/sig.h
+-rw-r--r-- root root 1797 ./usr/include/proc/slab.h
+-rw-r--r-- root root 4820 ./usr/include/proc/sysinfo.h
+-rw-r--r-- root root 1480 ./usr/include/proc/version.h
+-rw-r--r-- root root 160 ./usr/include/proc/wchan.h
+-rw-r--r-- root root 202 ./usr/include/proc/whattime.h
+drwxr-xr-x root root 4096 ./usr/include/protocols
+-rw-r--r-- root root 3844 ./usr/include/protocols/routed.h
+-rw-r--r-- root root 2567 ./usr/include/protocols/rwhod.h
+-rw-r--r-- root root 4826 ./usr/include/protocols/talkd.h
+-rw-r--r-- root root 3881 ./usr/include/protocols/timed.h
+-rw-r--r-- root root 41701 ./usr/include/pthread.h
+-rw-r--r-- root root 1570 ./usr/include/pty.h
+-rw-r--r-- root root 6159 ./usr/include/pwd.h
+drwxr-xr-x root root 4096 ./usr/include/pycairo
+-rw-r--r-- root root 9152 ./usr/include/pycairo/py3cairo.h
+drwxr-xr-x root root 4096 ./usr/include/pygobject-3.0
+-rw-r--r-- root root 24983 ./usr/include/pygobject-3.0/pygobject.h
+drwxr-xr-x root root 4096 ./usr/include/python3.8
+-rw-r--r-- root root 30286 ./usr/include/python3.8/abstract.h
+-rw-r--r-- root root 1229 ./usr/include/python3.8/asdl.h
+-rw-r--r-- root root 948 ./usr/include/python3.8/ast.h
+-rw-r--r-- root root 468 ./usr/include/python3.8/bitset.h
+-rw-r--r-- root root 264 ./usr/include/python3.8/bltinmodule.h
+-rw-r--r-- root root 886 ./usr/include/python3.8/boolobject.h
+-rw-r--r-- root root 2114 ./usr/include/python3.8/bytearrayobject.h
+-rw-r--r-- root root 3301 ./usr/include/python3.8/bytes_methods.h
+-rw-r--r-- root root 8493 ./usr/include/python3.8/bytesobject.h
+-rw-r--r-- root root 713 ./usr/include/python3.8/cellobject.h
+-rw-r--r-- root root 8366 ./usr/include/python3.8/ceval.h
+-rw-r--r-- root root 1710 ./usr/include/python3.8/classobject.h
+-rw-r--r-- root root 6793 ./usr/include/python3.8/codecs.h
+-rw-r--r-- root root 7178 ./usr/include/python3.8/code.h
+-rw-r--r-- root root 3582 ./usr/include/python3.8/compile.h
+-rw-r--r-- root root 1807 ./usr/include/python3.8/complexobject.h
+-rw-r--r-- root root 2014 ./usr/include/python3.8/context.h
+drwxr-xr-x root root 4096 ./usr/include/python3.8/cpython
+-rw-r--r-- root root 12295 ./usr/include/python3.8/cpython/abstract.h
+-rw-r--r-- root root 3845 ./usr/include/python3.8/cpython/dictobject.h
+-rw-r--r-- root root 951 ./usr/include/python3.8/cpython/fileobject.h
+-rw-r--r-- root root 16028 ./usr/include/python3.8/cpython/initconfig.h
+-rw-r--r-- root root 456 ./usr/include/python3.8/cpython/interpreteridobject.h
+-rw-r--r-- root root 15691 ./usr/include/python3.8/cpython/object.h
+-rw-r--r-- root root 3600 ./usr/include/python3.8/cpython/objimpl.h
+-rw-r--r-- root root 4607 ./usr/include/python3.8/cpython/pyerrors.h
+-rw-r--r-- root root 2263 ./usr/include/python3.8/cpython/pylifecycle.h
+-rw-r--r-- root root 3511 ./usr/include/python3.8/cpython/pymem.h
+-rw-r--r-- root root 9810 ./usr/include/python3.8/cpython/pystate.h
+-rw-r--r-- root root 547 ./usr/include/python3.8/cpython/sysmodule.h
+-rw-r--r-- root root 473 ./usr/include/python3.8/cpython/traceback.h
+-rw-r--r-- root root 1036 ./usr/include/python3.8/cpython/tupleobject.h
+-rw-r--r-- root root 46299 ./usr/include/python3.8/cpython/unicodeobject.h
+-rw-r--r-- root root 9260 ./usr/include/python3.8/datetime.h
+-rw-r--r-- root root 3019 ./usr/include/python3.8/descrobject.h
+-rw-r--r-- root root 3716 ./usr/include/python3.8/dictobject.h
+-rw-r--r-- root root 458 ./usr/include/python3.8/dtoa.h
+-rw-r--r-- root root 22469 ./usr/include/python3.8/dynamic_annotations.h
+-rw-r--r-- root root 253 ./usr/include/python3.8/enumobject.h
+-rw-r--r-- root root 1695 ./usr/include/python3.8/errcode.h
+-rw-r--r-- root root 1209 ./usr/include/python3.8/eval.h
+-rw-r--r-- root root 1342 ./usr/include/python3.8/fileobject.h
+-rw-r--r-- root root 4352 ./usr/include/python3.8/fileutils.h
+-rw-r--r-- root root 4794 ./usr/include/python3.8/floatobject.h
+-rw-r--r-- root root 3317 ./usr/include/python3.8/frameobject.h
+-rw-r--r-- root root 4200 ./usr/include/python3.8/funcobject.h
+-rw-r--r-- root root 3720 ./usr/include/python3.8/genobject.h
+-rw-r--r-- root root 2118 ./usr/include/python3.8/graminit.h
+-rw-r--r-- root root 1821 ./usr/include/python3.8/grammar.h
+-rw-r--r-- root root 4926 ./usr/include/python3.8/import.h
+drwxr-xr-x root root 4096 ./usr/include/python3.8/internal
+-rw-r--r-- root root 1126 ./usr/include/python3.8/internal/pycore_accu.h
+-rw-r--r-- root root 16944 ./usr/include/python3.8/internal/pycore_atomic.h
+-rw-r--r-- root root 966 ./usr/include/python3.8/internal/pycore_ceval.h
+-rw-r--r-- root root 542 ./usr/include/python3.8/internal/pycore_code.h
+-rw-r--r-- root root 2809 ./usr/include/python3.8/internal/pycore_condvar.h
+-rw-r--r-- root root 779 ./usr/include/python3.8/internal/pycore_context.h
+-rw-r--r-- root root 1254 ./usr/include/python3.8/internal/pycore_fileutils.h
+-rw-r--r-- root root 490 ./usr/include/python3.8/internal/pycore_getopt.h
+-rw-r--r-- root root 1520 ./usr/include/python3.8/internal/pycore_gil.h
+-rw-r--r-- root root 3128 ./usr/include/python3.8/internal/pycore_hamt.h
+-rw-r--r-- root root 5168 ./usr/include/python3.8/internal/pycore_initconfig.h
+-rw-r--r-- root root 2896 ./usr/include/python3.8/internal/pycore_object.h
+-rw-r--r-- root root 2037 ./usr/include/python3.8/internal/pycore_pathconfig.h
+-rw-r--r-- root root 1329 ./usr/include/python3.8/internal/pycore_pyerrors.h
+-rw-r--r-- root root 206 ./usr/include/python3.8/internal/pycore_pyhash.h
+-rw-r--r-- root root 3758 ./usr/include/python3.8/internal/pycore_pylifecycle.h
+-rw-r--r-- root root 8217 ./usr/include/python3.8/internal/pycore_pymem.h
+-rw-r--r-- root root 9494 ./usr/include/python3.8/internal/pycore_pystate.h
+-rw-r--r-- root root 3076 ./usr/include/python3.8/internal/pycore_traceback.h
+-rw-r--r-- root root 418 ./usr/include/python3.8/internal/pycore_tupleobject.h
+-rw-r--r-- root root 591 ./usr/include/python3.8/internal/pycore_warnings.h
+-rw-r--r-- root root 334 ./usr/include/python3.8/interpreteridobject.h
+-rw-r--r-- root root 861 ./usr/include/python3.8/intrcheck.h
+-rw-r--r-- root root 567 ./usr/include/python3.8/iterobject.h
+-rw-r--r-- root root 2927 ./usr/include/python3.8/listobject.h
+-rw-r--r-- root root 3799 ./usr/include/python3.8/longintrepr.h
+-rw-r--r-- root root 9520 ./usr/include/python3.8/longobject.h
+-rw-r--r-- root root 803 ./usr/include/python3.8/marshal.h
+-rw-r--r-- root root 2765 ./usr/include/python3.8/memoryobject.h
+-rw-r--r-- root root 4406 ./usr/include/python3.8/methodobject.h
+-rw-r--r-- root root 9591 ./usr/include/python3.8/modsupport.h
+-rw-r--r-- root root 2362 ./usr/include/python3.8/moduleobject.h
+-rw-r--r-- root root 349 ./usr/include/python3.8/namespaceobject.h
+-rw-r--r-- root root 1328 ./usr/include/python3.8/node.h
+-rw-r--r-- root root 29599 ./usr/include/python3.8/object.h
+-rw-r--r-- root root 10537 ./usr/include/python3.8/objimpl.h
+-rw-r--r-- root root 1300 ./usr/include/python3.8/odictobject.h
+-rw-r--r-- root root 5164 ./usr/include/python3.8/opcode.h
+-rw-r--r-- root root 737 ./usr/include/python3.8/osdefs.h
+-rw-r--r-- root root 291 ./usr/include/python3.8/osmodule.h
+-rw-r--r-- root root 2958 ./usr/include/python3.8/parsetok.h
+-rw-r--r-- root root 1297 ./usr/include/python3.8/patchlevel.h
+-rw-r--r-- root root 847 ./usr/include/python3.8/picklebufobject.h
+-rw-r--r-- root root 2744 ./usr/include/python3.8/pyarena.h
+-rw-r--r-- root root 1726 ./usr/include/python3.8/pycapsule.h
+-rw-r--r-- root root 47511 ./usr/include/python3.8/pyconfig-64.h
+-rw-r--r-- root root 560 ./usr/include/python3.8/pyconfig.h
+-rw-r--r-- root root 1320 ./usr/include/python3.8/pyctype.h
+-rw-r--r-- root root 2477 ./usr/include/python3.8/py_curses.h
+-rw-r--r-- root root 1214 ./usr/include/python3.8/pydebug.h
+-rw-r--r-- root root 2413 ./usr/include/python3.8/pydtrace.h
+-rw-r--r-- root root 12786 ./usr/include/python3.8/pyerrors.h
+-rw-r--r-- root root 2450 ./usr/include/python3.8/pyexpat.h
+-rw-r--r-- root root 341 ./usr/include/python3.8/pyfpe.h
+-rw-r--r-- root root 4140 ./usr/include/python3.8/pyhash.h
+-rw-r--r-- root root 2081 ./usr/include/python3.8/pylifecycle.h
+-rw-r--r-- root root 2989 ./usr/include/python3.8/pymacconfig.h
+-rw-r--r-- root root 3778 ./usr/include/python3.8/pymacro.h
+-rw-r--r-- root root 8312 ./usr/include/python3.8/pymath.h
+-rw-r--r-- root root 5406 ./usr/include/python3.8/pymem.h
+-rw-r--r-- root root 30221 ./usr/include/python3.8/pyport.h
+-rw-r--r-- root root 4686 ./usr/include/python3.8/pystate.h
+-rw-r--r-- root root 436 ./usr/include/python3.8/pystrcmp.h
+-rw-r--r-- root root 849 ./usr/include/python3.8/pystrhex.h
+-rw-r--r-- root root 1483 ./usr/include/python3.8/pystrtod.h
+-rw-r--r-- root root 26491 ./usr/include/python3.8/Python-ast.h
+-rw-r--r-- root root 3615 ./usr/include/python3.8/Python.h
+-rw-r--r-- root root 7688 ./usr/include/python3.8/pythonrun.h
+-rw-r--r-- root root 5660 ./usr/include/python3.8/pythread.h
+-rw-r--r-- root root 8926 ./usr/include/python3.8/pytime.h
+-rw-r--r-- root root 629 ./usr/include/python3.8/rangeobject.h
+-rw-r--r-- root root 3362 ./usr/include/python3.8/setobject.h
+-rw-r--r-- root root 2517 ./usr/include/python3.8/sliceobject.h
+-rw-r--r-- root root 2030 ./usr/include/python3.8/structmember.h
+-rw-r--r-- root root 1377 ./usr/include/python3.8/structseq.h
+-rw-r--r-- root root 5308 ./usr/include/python3.8/symtable.h
+-rw-r--r-- root root 1242 ./usr/include/python3.8/sysmodule.h
+-rw-r--r-- root root 2429 ./usr/include/python3.8/token.h
+-rw-r--r-- root root 601 ./usr/include/python3.8/traceback.h
+-rw-r--r-- root root 1114 ./usr/include/python3.8/tracemalloc.h
+-rw-r--r-- root root 1661 ./usr/include/python3.8/tupleobject.h
+-rw-r--r-- root root 2253 ./usr/include/python3.8/typeslots.h
+-rw-r--r-- root root 1056 ./usr/include/python3.8/ucnhash.h
+-rw-r--r-- root root 35732 ./usr/include/python3.8/unicodeobject.h
+-rw-r--r-- root root 1776 ./usr/include/python3.8/warnings.h
+-rw-r--r-- root root 2866 ./usr/include/python3.8/weakrefobject.h
+drwxr-xr-x root root 4096 ./usr/include/rdma
+-rw-r--r-- root root 3291 ./usr/include/rdma/bnxt_re-abi.h
+-rw-r--r-- root root 2468 ./usr/include/rdma/cxgb3-abi.h
+-rw-r--r-- root root 3122 ./usr/include/rdma/cxgb4-abi.h
+-rw-r--r-- root root 2141 ./usr/include/rdma/efa-abi.h
+drwxr-xr-x root root 4096 ./usr/include/rdma/hfi
+-rw-r--r-- root root 6618 ./usr/include/rdma/hfi/hfi1_ioctl.h
+-rw-r--r-- root root 9225 ./usr/include/rdma/hfi/hfi1_user.h
+-rw-r--r-- root root 2388 ./usr/include/rdma/hns-abi.h
+-rw-r--r-- root root 3030 ./usr/include/rdma/i40iw-abi.h
+-rw-r--r-- root root 6046 ./usr/include/rdma/ib_user_ioctl_cmds.h
+-rw-r--r-- root root 5655 ./usr/include/rdma/ib_user_ioctl_verbs.h
+-rw-r--r-- root root 8531 ./usr/include/rdma/ib_user_mad.h
+-rw-r--r-- root root 2305 ./usr/include/rdma/ib_user_sa.h
+-rw-r--r-- root root 26750 ./usr/include/rdma/ib_user_verbs.h
+-rw-r--r-- root root 5117 ./usr/include/rdma/mlx4-abi.h
+-rw-r--r-- root root 12968 ./usr/include/rdma/mlx5-abi.h
+-rw-r--r-- root root 7368 ./usr/include/rdma/mlx5_user_ioctl_cmds.h
+-rw-r--r-- root root 2624 ./usr/include/rdma/mlx5_user_ioctl_verbs.h
+-rw-r--r-- root root 3055 ./usr/include/rdma/mthca-abi.h
+-rw-r--r-- root root 3487 ./usr/include/rdma/nes-abi.h
+-rw-r--r-- root root 4116 ./usr/include/rdma/ocrdma-abi.h
+-rw-r--r-- root root 3160 ./usr/include/rdma/qedr-abi.h
+-rw-r--r-- root root 14231 ./usr/include/rdma/rdma_netlink.h
+-rw-r--r-- root root 6903 ./usr/include/rdma/rdma_user_cm.h
+-rw-r--r-- root root 3008 ./usr/include/rdma/rdma_user_ioctl_cmds.h
+-rw-r--r-- root root 3749 ./usr/include/rdma/rdma_user_ioctl.h
+-rw-r--r-- root root 3839 ./usr/include/rdma/rdma_user_rxe.h
+-rw-r--r-- root root 1771 ./usr/include/rdma/rvt-abi.h
+-rw-r--r-- root root 3430 ./usr/include/rdma/siw-abi.h
+-rw-r--r-- root root 7807 ./usr/include/rdma/vmw_pvrdma-abi.h
+drwxr-xr-x root root 4096 ./usr/include/readline
+-rw-r--r-- root root 4697 ./usr/include/readline/chardefs.h
+-rw-r--r-- root root 10779 ./usr/include/readline/history.h
+-rw-r--r-- root root 3260 ./usr/include/readline/keymaps.h
+-rw-r--r-- root root 39338 ./usr/include/readline/readline.h
+-rw-r--r-- root root 2829 ./usr/include/readline/rlconf.h
+-rw-r--r-- root root 1835 ./usr/include/readline/rlstdc.h
+-rw-r--r-- root root 3193 ./usr/include/readline/rltypedefs.h
+-rw-r--r-- root root 3046 ./usr/include/readline/tilde.h
+-rw-r--r-- root root 963 ./usr/include/re_comp.h
+-rw-r--r-- root root 24715 ./usr/include/regex.h
+-rw-r--r-- root root 1448 ./usr/include/regexp.h
+-rw-r--r-- root root 11873 ./usr/include/resolv.h
+drwxr-xr-x root root 4096 ./usr/include/rpc
+-rw-r--r-- root root 2897 ./usr/include/rpc/netdb.h
+drwxr-xr-x root root 4096 ./usr/include/rpcsvc
+-rw-r--r-- root root 2675 ./usr/include/rpcsvc/nis_callback.h
+-rw-r--r-- root root 2178 ./usr/include/rpcsvc/nis_callback.x
+-rw-r--r-- root root 15879 ./usr/include/rpcsvc/nis.h
+-rw-r--r-- root root 12340 ./usr/include/rpcsvc/nislib.h
+-rw-r--r-- root root 13090 ./usr/include/rpcsvc/nis_object.x
+-rw-r--r-- root root 5370 ./usr/include/rpcsvc/nis_tags.h
+-rw-r--r-- root root 16802 ./usr/include/rpcsvc/nis.x
+-rw-r--r-- root root 3481 ./usr/include/rpcsvc/ypclnt.h
+-rw-r--r-- root root 7964 ./usr/include/rpcsvc/yp.h
+-rw-r--r-- root root 913 ./usr/include/rpcsvc/yppasswd.h
+-rw-r--r-- root root 2286 ./usr/include/rpcsvc/yppasswd.x
+-rw-r--r-- root root 14920 ./usr/include/rpcsvc/yp_prot.h
+-rw-r--r-- root root 3027 ./usr/include/rpcsvc/ypupd.h
+-rw-r--r-- root root 6981 ./usr/include/rpcsvc/yp.x
+-rw-r--r-- root root 4733 ./usr/include/sched.h
+drwxr-xr-x root root 4096 ./usr/include/scsi
+-rw-r--r-- root root 10168 ./usr/include/scsi/cxlflash_ioctl.h
+drwxr-xr-x root root 4096 ./usr/include/scsi/fc
+-rw-r--r-- root root 26902 ./usr/include/scsi/fc/fc_els.h
+-rw-r--r-- root root 11703 ./usr/include/scsi/fc/fc_fs.h
+-rw-r--r-- root root 2231 ./usr/include/scsi/fc/fc_gs.h
+-rw-r--r-- root root 4317 ./usr/include/scsi/fc/fc_ns.h
+-rw-r--r-- root root 8027 ./usr/include/scsi/scsi_bsg_fc.h
+-rw-r--r-- root root 2795 ./usr/include/scsi/scsi_bsg_ufs.h
+-rw-r--r-- root root 6970 ./usr/include/scsi/scsi.h
+-rw-r--r-- root root 1316 ./usr/include/scsi/scsi_ioctl.h
+-rw-r--r-- root root 1264 ./usr/include/scsi/scsi_netlink_fc.h
+-rw-r--r-- root root 2906 ./usr/include/scsi/scsi_netlink.h
+-rw-r--r-- root root 11662 ./usr/include/scsi/sg.h
+-rw-r--r-- root root 5450 ./usr/include/search.h
+-rw-r--r-- root root 2735 ./usr/include/semaphore.h
+-rw-r--r-- root root 3670 ./usr/include/setjmp.h
+-rw-r--r-- root root 1344 ./usr/include/sgtty.h
+-rw-r--r-- root root 5472 ./usr/include/shadow.h
+-rw-r--r-- root root 12309 ./usr/include/signal.h
+drwxr-xr-x root root 4096 ./usr/include/sound
+-rw-r--r-- root root 21847 ./usr/include/sound/asequencer.h
+-rw-r--r-- root root 22222 ./usr/include/sound/asoc.h
+-rw-r--r-- root root 4377 ./usr/include/sound/asound_fm.h
+-rw-r--r-- root root 46564 ./usr/include/sound/asound.h
+-rw-r--r-- root root 6743 ./usr/include/sound/compress_offload.h
+-rw-r--r-- root root 16992 ./usr/include/sound/compress_params.h
+-rw-r--r-- root root 17240 ./usr/include/sound/emu10k1.h
+-rw-r--r-- root root 3245 ./usr/include/sound/firewire.h
+-rw-r--r-- root root 3140 ./usr/include/sound/hdsp.h
+-rw-r--r-- root root 5486 ./usr/include/sound/hdspm.h
+-rw-r--r-- root root 4304 ./usr/include/sound/sb16_csp.h
+-rw-r--r-- root root 7494 ./usr/include/sound/sfnt_info.h
+-rw-r--r-- root root 5195 ./usr/include/sound/skl-tplg-interface.h
+-rw-r--r-- root root 12191 ./usr/include/sound/snd_sst_tokens.h
+drwxr-xr-x root root 4096 ./usr/include/sound/sof
+-rw-r--r-- root root 2036 ./usr/include/sound/sof/abi.h
+-rw-r--r-- root root 2267 ./usr/include/sound/sof/fw.h
+-rw-r--r-- root root 922 ./usr/include/sound/sof/header.h
+-rw-r--r-- root root 3267 ./usr/include/sound/sof/tokens.h
+-rw-r--r-- root root 4601 ./usr/include/sound/tlv.h
+-rw-r--r-- root root 1939 ./usr/include/sound/usb_stream.h
+-rw-r--r-- root root 7758 ./usr/include/spawn.h
+-rw-r--r-- root root 34802 ./usr/include/sqlite3ext.h
+-rw-r--r-- root root 576161 ./usr/include/sqlite3.h
+drwxr-xr-x root root 4096 ./usr/include/ss
+-rw-r--r-- root root 1193 ./usr/include/ss/ss_err.h
+-rw-r--r-- root root 3166 ./usr/include/ss/ss.h
+-rw-r--r-- root root 264 ./usr/include/stab.h
+-rw-r--r-- root root 2290 ./usr/include/stdc-predef.h
+-rw-r--r-- root root 8474 ./usr/include/stdint.h
+-rw-r--r-- root root 2800 ./usr/include/stdio_ext.h
+-rw-r--r-- root root 29950 ./usr/include/stdio.h
+-rw-r--r-- root root 35835 ./usr/include/stdlib.h
+-rw-r--r-- root root 17660 ./usr/include/string.h
+-rw-r--r-- root root 4753 ./usr/include/strings.h
+-rw-r--r-- root root 2191 ./usr/include/symcat.h
+drwxr-xr-x root root 4096 ./usr/include/sys
+-rw-r--r-- root root 3302 ./usr/include/sys/acct.h
+-rw-r--r-- root root 3700 ./usr/include/sys/acl.h
+-rw-r--r-- root root 1260 ./usr/include/sys/auxv.h
+-rw-r--r-- root root 86 ./usr/include/sys/bitypes.h
+-rw-r--r-- root root 25 ./usr/include/syscall.h
+-rw-r--r-- root root 6996 ./usr/include/sys/capability.h
+-rw-r--r-- root root 18308 ./usr/include/sys/cdefs.h
+-rw-r--r-- root root 3576 ./usr/include/sys/debugreg.h
+-rw-r--r-- root root 922 ./usr/include/sys/dir.h
+-rw-r--r-- root root 1024 ./usr/include/sys/elf.h
+-rw-r--r-- root root 4411 ./usr/include/sys/epoll.h
+-rw-r--r-- root root 19 ./usr/include/sys/errno.h
+-rw-r--r-- root root 1400 ./usr/include/sys/eventfd.h
+-rw-r--r-- root root 5232 ./usr/include/sysexits.h
+-rw-r--r-- root root 1292 ./usr/include/sys/fanotify.h
+-rw-r--r-- root root 19 ./usr/include/sys/fcntl.h
+-rw-r--r-- root root 1675 ./usr/include/sys/file.h
+-rw-r--r-- root root 1188 ./usr/include/sys/fsuid.h
+-rw-r--r-- root root 6210 ./usr/include/sys/gmon.h
+-rw-r--r-- root root 2636 ./usr/include/sys/gmon_out.h
+-rw-r--r-- root root 3901 ./usr/include/sys/inotify.h
+-rw-r--r-- root root 1740 ./usr/include/sys/ioctl.h
+-rw-r--r-- root root 5086 ./usr/include/sys/io.h
+-rw-r--r-- root root 1462 ./usr/include/sys/ipc.h
+-rw-r--r-- root root 1112 ./usr/include/sys/kd.h
+-rw-r--r-- root root 1204 ./usr/include/sys/klog.h
+-rw-r--r-- root root 24 ./usr/include/syslog.h
+-rw-r--r-- root root 5552 ./usr/include/sys/mman.h
+-rw-r--r-- root root 5612 ./usr/include/sys/mount.h
+-rw-r--r-- root root 2366 ./usr/include/sys/msg.h
+-rw-r--r-- root root 11163 ./usr/include/sys/mtio.h
+-rw-r--r-- root root 3149 ./usr/include/sys/param.h
+-rw-r--r-- root root 923 ./usr/include/sys/pci.h
+-rw-r--r-- root root 1127 ./usr/include/sys/perm.h
+-rw-r--r-- root root 2723 ./usr/include/sys/personality.h
+-rw-r--r-- root root 2550 ./usr/include/sys/poll.h
+-rw-r--r-- root root 1059 ./usr/include/sys/prctl.h
+-rw-r--r-- root root 4338 ./usr/include/sys/procfs.h
+-rw-r--r-- root root 1959 ./usr/include/sys/profil.h
+-rw-r--r-- root root 4680 ./usr/include/sys/psx_syscall.h
+-rw-r--r-- root root 6126 ./usr/include/sys/ptrace.h
+-rw-r--r-- root root 19539 ./usr/include/sys/queue.h
+-rw-r--r-- root root 5173 ./usr/include/sys/quota.h
+-rw-r--r-- root root 1444 ./usr/include/sys/random.h
+-rw-r--r-- root root 1182 ./usr/include/sys/raw.h
+-rw-r--r-- root root 1633 ./usr/include/sys/reboot.h
+-rw-r--r-- root root 1827 ./usr/include/sys/reg.h
+-rw-r--r-- root root 3646 ./usr/include/sys/resource.h
+-rw-r--r-- root root 4141 ./usr/include/sys/select.h
+-rw-r--r-- root root 2037 ./usr/include/sys/sem.h
+-rw-r--r-- root root 1806 ./usr/include/sys/sendfile.h
+-rw-r--r-- root root 1874 ./usr/include/sys/shm.h
+-rw-r--r-- root root 1714 ./usr/include/sys/signalfd.h
+-rw-r--r-- root root 20 ./usr/include/sys/signal.h
+-rw-r--r-- root root 10205 ./usr/include/sys/socket.h
+-rw-r--r-- root root 141 ./usr/include/sys/socketvar.h
+-rw-r--r-- root root 29 ./usr/include/sys/soundcard.h
+-rw-r--r-- root root 2094 ./usr/include/sys/statfs.h
+-rw-r--r-- root root 16237 ./usr/include/sys/stat.h
+-rw-r--r-- root root 2820 ./usr/include/sys/statvfs.h
+-rw-r--r-- root root 1593 ./usr/include/sys/swap.h
+-rw-r--r-- root root 1256 ./usr/include/sys/syscall.h
+-rw-r--r-- root root 2105 ./usr/include/sys/sysctl.h
+-rw-r--r-- root root 1518 ./usr/include/sys/sysinfo.h
+-rw-r--r-- root root 7702 ./usr/include/sys/syslog.h
+-rw-r--r-- root root 2103 ./usr/include/sys/sysmacros.h
+-rw-r--r-- root root 74 ./usr/include/sys/termios.h
+-rw-r--r-- root root 1420 ./usr/include/sys/timeb.h
+-rw-r--r-- root root 6754 ./usr/include/sys/time.h
+-rw-r--r-- root root 1874 ./usr/include/sys/timerfd.h
+-rw-r--r-- root root 1597 ./usr/include/sys/times.h
+-rw-r--r-- root root 2206 ./usr/include/sys/timex.h
+-rw-r--r-- root root 2499 ./usr/include/sys/ttychars.h
+-rw-r--r-- root root 3568 ./usr/include/sys/ttydefaults.h
+-rw-r--r-- root root 5713 ./usr/include/sys/types.h
+-rw-r--r-- root root 5842 ./usr/include/sys/ucontext.h
+-rw-r--r-- root root 6280 ./usr/include/sys/uio.h
+-rw-r--r-- root root 1453 ./usr/include/sys/un.h
+-rw-r--r-- root root 20 ./usr/include/sys/unistd.h
+-rw-r--r-- root root 5208 ./usr/include/sys/user.h
+-rw-r--r-- root root 2481 ./usr/include/sys/utsname.h
+-rw-r--r-- root root 161 ./usr/include/sys/vfs.h
+-rw-r--r-- root root 1880 ./usr/include/sys/vlimit.h
+-rw-r--r-- root root 1199 ./usr/include/sys/vm86.h
+-rw-r--r-- root root 22 ./usr/include/sys/vt.h
+-rw-r--r-- root root 2463 ./usr/include/sys/vtimes.h
+-rw-r--r-- root root 5605 ./usr/include/sys/wait.h
+-rw-r--r-- root root 4275 ./usr/include/sys/xattr.h
+-rw-r--r-- root root 3786 ./usr/include/tar.h
+-rw-r--r-- root root 9130 ./usr/include/tcpd.h
+-rw-r--r-- root root 3471 ./usr/include/termcap.h
+-rw-r--r-- root root 9096 ./usr/include/term_entry.h
+-rw-r--r-- root root 40447 ./usr/include/term.h
+-rw-r--r-- root root 214 ./usr/include/termio.h
+-rw-r--r-- root root 3599 ./usr/include/termios.h
+-rw-r--r-- root root 37419 ./usr/include/tgmath.h
+-rw-r--r-- root root 16024 ./usr/include/thread_db.h
+-rw-r--r-- root root 6661 ./usr/include/threads.h
+-rw-r--r-- root root 14830 ./usr/include/tic.h
+-rw-r--r-- root root 10276 ./usr/include/time.h
+drwxr-xr-x root root 4096 ./usr/include/tirpc
+-rw-r--r-- root root 2195 ./usr/include/tirpc/netconfig.h
+drwxr-xr-x root root 4096 ./usr/include/tirpc/rpc
+-rw-r--r-- root root 4143 ./usr/include/tirpc/rpc/auth_des.h
+-rw-r--r-- root root 11085 ./usr/include/tirpc/rpc/auth.h
+-rw-r--r-- root root 3009 ./usr/include/tirpc/rpc/auth_unix.h
+-rw-r--r-- root root 17067 ./usr/include/tirpc/rpc/clnt.h
+-rw-r--r-- root root 3904 ./usr/include/tirpc/rpc/clnt_soc.h
+-rw-r--r-- root root 2202 ./usr/include/tirpc/rpc/clnt_stat.h
+-rw-r--r-- root root 3706 ./usr/include/tirpc/rpc/des_crypt.h
+-rw-r--r-- root root 3045 ./usr/include/tirpc/rpc/des.h
+-rw-r--r-- root root 8021 ./usr/include/tirpc/rpc/key_prot.h
+-rw-r--r-- root root 2431 ./usr/include/tirpc/rpc/nettype.h
+-rw-r--r-- root root 3582 ./usr/include/tirpc/rpc/pmap_clnt.h
+-rw-r--r-- root root 4064 ./usr/include/tirpc/rpc/pmap_prot.h
+-rw-r--r-- root root 2450 ./usr/include/tirpc/rpc/pmap_rmt.h
+-rw-r--r-- root root 2117 ./usr/include/tirpc/rpc/raw.h
+-rw-r--r-- root root 3496 ./usr/include/tirpc/rpc/rpcb_clnt.h
+-rw-r--r-- root root 25776 ./usr/include/tirpc/rpc/rpcb_prot.h
+-rw-r--r-- root root 14673 ./usr/include/tirpc/rpc/rpcb_prot.x
+-rw-r--r-- root root 3102 ./usr/include/tirpc/rpc/rpc_com.h
+-rw-r--r-- root root 2712 ./usr/include/tirpc/rpc/rpcent.h
+-rw-r--r-- root root 4130 ./usr/include/tirpc/rpc/rpc.h
+-rw-r--r-- root root 5340 ./usr/include/tirpc/rpc/rpc_msg.h
+drwxr-xr-x root root 4096 ./usr/include/tirpc/rpcsvc
+-rw-r--r-- root root 3041 ./usr/include/tirpc/rpc/svc_auth.h
+-rw-r--r-- root root 2414 ./usr/include/tirpc/rpcsvc/crypt.h
+-rw-r--r-- root root 3929 ./usr/include/tirpc/rpcsvc/crypt.x
+-rw-r--r-- root root 2462 ./usr/include/tirpc/rpc/svc_dg.h
+-rw-r--r-- root root 14589 ./usr/include/tirpc/rpc/svc.h
+-rw-r--r-- root root 1912 ./usr/include/tirpc/rpc/svc_mt.h
+-rw-r--r-- root root 3749 ./usr/include/tirpc/rpc/svc_soc.h
+-rw-r--r-- root root 3756 ./usr/include/tirpc/rpc/types.h
+-rw-r--r-- root root 13372 ./usr/include/tirpc/rpc/xdr.h
+-rw-r--r-- root root 2494 ./usr/include/ttyent.h
+-rw-r--r-- root root 2002 ./usr/include/uchar.h
+-rw-r--r-- root root 2037 ./usr/include/ucontext.h
+-rw-r--r-- root root 8998 ./usr/include/udev.h
+-rw-r--r-- root root 1584 ./usr/include/ulimit.h
+-rw-r--r-- root root 3177 ./usr/include/unctrl.h
+-rw-r--r-- root root 42804 ./usr/include/unistd.h
+-rw-r--r-- root root 1502 ./usr/include/utime.h
+-rw-r--r-- root root 3223 ./usr/include/utmp.h
+-rw-r--r-- root root 4100 ./usr/include/utmpx.h
+drwxr-xr-x root root 4096 ./usr/include/uuid
+-rw-r--r-- root root 3910 ./usr/include/uuid/uuid.h
+-rw-r--r-- root root 1956 ./usr/include/values.h
+drwxr-xr-x root root 4096 ./usr/include/video
+-rw-r--r-- root root 213 ./usr/include/video/edid.h
+-rw-r--r-- root root 7643 ./usr/include/video/sisfb.h
+-rw-r--r-- root root 1078 ./usr/include/video/uvesafb.h
+-rw-r--r-- root root 22 ./usr/include/wait.h
+-rw-r--r-- root root 8755 ./usr/include/wayland-client-core.h
+-rw-r--r-- root root 1573 ./usr/include/wayland-client.h
+-rw-r--r-- root root 184232 ./usr/include/wayland-client-protocol.h
+-rw-r--r-- root root 2260 ./usr/include/wayland-cursor.h
+-rw-r--r-- root root 1848 ./usr/include/wayland-egl-backend.h
+-rw-r--r-- root root 1788 ./usr/include/wayland-egl-core.h
+-rw-r--r-- root root 1313 ./usr/include/wayland-egl.h
+-rw-r--r-- root root 19021 ./usr/include/wayland-server-core.h
+-rw-r--r-- root root 3237 ./usr/include/wayland-server.h
+-rw-r--r-- root root 144281 ./usr/include/wayland-server-protocol.h
+-rw-r--r-- root root 24118 ./usr/include/wayland-util.h
+-rw-r--r-- root root 1354 ./usr/include/wayland-version.h
+-rw-r--r-- root root 31111 ./usr/include/wchar.h
+-rw-r--r-- root root 5549 ./usr/include/wctype.h
+-rw-r--r-- root root 2502 ./usr/include/wordexp.h
+drwxr-xr-x root root 4096 ./usr/include/X11
+-rw-r--r-- root root 2293 ./usr/include/X11/ap_keysym.h
+-rw-r--r-- root root 3118 ./usr/include/X11/cursorfont.h
+-rw-r--r-- root root 2815 ./usr/include/X11/DECkeysym.h
+drwxr-xr-x root root 4096 ./usr/include/X11/dri
+-rw-r--r-- root root 2445 ./usr/include/X11/dri/xf86dri.h
+-rw-r--r-- root root 9669 ./usr/include/X11/dri/xf86driproto.h
+-rw-r--r-- root root 174 ./usr/include/X11/dri/xf86dristr.h
+drwxr-xr-x root root 4096 ./usr/include/X11/extensions
+-rw-r--r-- root root 1705 ./usr/include/X11/extensions/ag.h
+-rw-r--r-- root root 5005 ./usr/include/X11/extensions/agproto.h
+-rw-r--r-- root root 2900 ./usr/include/X11/extensions/applewmconst.h
+-rw-r--r-- root root 8098 ./usr/include/X11/extensions/applewmproto.h
+-rw-r--r-- root root 1909 ./usr/include/X11/extensions/bigreqsproto.h
+-rw-r--r-- root root 187 ./usr/include/X11/extensions/bigreqstr.h
+-rw-r--r-- root root 3130 ./usr/include/X11/extensions/composite.h
+-rw-r--r-- root root 5462 ./usr/include/X11/extensions/compositeproto.h
+-rw-r--r-- root root 1353 ./usr/include/X11/extensions/cup.h
+-rw-r--r-- root root 3065 ./usr/include/X11/extensions/cupproto.h
+-rw-r--r-- root root 3615 ./usr/include/X11/extensions/damageproto.h
+-rw-r--r-- root root 1893 ./usr/include/X11/extensions/damagewire.h
+-rw-r--r-- root root 2159 ./usr/include/X11/extensions/dbe.h
+-rw-r--r-- root root 7343 ./usr/include/X11/extensions/dbeproto.h
+-rw-r--r-- root root 2373 ./usr/include/X11/extensions/dmx.h
+-rw-r--r-- root root 13343 ./usr/include/X11/extensions/dmxproto.h
+-rw-r--r-- root root 1778 ./usr/include/X11/extensions/dpmsconst.h
+-rw-r--r-- root root 2161 ./usr/include/X11/extensions/dpms.h
+-rw-r--r-- root root 5288 ./usr/include/X11/extensions/dpmsproto.h
+-rw-r--r-- root root 8318 ./usr/include/X11/extensions/dri2proto.h
+-rw-r--r-- root root 2468 ./usr/include/X11/extensions/dri2tokens.h
+-rw-r--r-- root root 6129 ./usr/include/X11/extensions/dri3proto.h
+-rw-r--r-- root root 1563 ./usr/include/X11/extensions/EVI.h
+-rw-r--r-- root root 3006 ./usr/include/X11/extensions/EVIproto.h
+-rw-r--r-- root root 6096 ./usr/include/X11/extensions/extutil.h
+-rw-r--r-- root root 1782 ./usr/include/X11/extensions/ge.h
+-rw-r--r-- root root 2351 ./usr/include/X11/extensions/geproto.h
+-rw-r--r-- root root 2236 ./usr/include/X11/extensions/lbx.h
+-rw-r--r-- root root 24782 ./usr/include/X11/extensions/lbxproto.h
+-rw-r--r-- root root 1509 ./usr/include/X11/extensions/mitmiscconst.h
+-rw-r--r-- root root 1741 ./usr/include/X11/extensions/MITMisc.h
+-rw-r--r-- root root 2229 ./usr/include/X11/extensions/mitmiscproto.h
+-rw-r--r-- root root 2575 ./usr/include/X11/extensions/multibufconst.h
+-rw-r--r-- root root 5835 ./usr/include/X11/extensions/multibuf.h
+-rw-r--r-- root root 8600 ./usr/include/X11/extensions/multibufproto.h
+-rw-r--r-- root root 5473 ./usr/include/X11/extensions/panoramiXproto.h
+-rw-r--r-- root root 5409 ./usr/include/X11/extensions/presentproto.h
+-rw-r--r-- root root 3597 ./usr/include/X11/extensions/presenttokens.h
+-rw-r--r-- root root 6909 ./usr/include/X11/extensions/randr.h
+-rw-r--r-- root root 25751 ./usr/include/X11/extensions/randrproto.h
+-rw-r--r-- root root 2064 ./usr/include/X11/extensions/recordconst.h
+-rw-r--r-- root root 7634 ./usr/include/X11/extensions/recordproto.h
+-rw-r--r-- root root 258 ./usr/include/X11/extensions/recordstr.h
+-rw-r--r-- root root 6933 ./usr/include/X11/extensions/render.h
+-rw-r--r-- root root 13218 ./usr/include/X11/extensions/renderproto.h
+-rw-r--r-- root root 1900 ./usr/include/X11/extensions/saver.h
+-rw-r--r-- root root 5132 ./usr/include/X11/extensions/saverproto.h
+-rw-r--r-- root root 2141 ./usr/include/X11/extensions/secur.h
+-rw-r--r-- root root 2457 ./usr/include/X11/extensions/security.h
+-rw-r--r-- root root 3177 ./usr/include/X11/extensions/securproto.h
+-rw-r--r-- root root 1878 ./usr/include/X11/extensions/shapeconst.h
+-rw-r--r-- root root 4133 ./usr/include/X11/extensions/shape.h
+-rw-r--r-- root root 6730 ./usr/include/X11/extensions/shapeproto.h
+-rw-r--r-- root root 252 ./usr/include/X11/extensions/shapestr.h
+-rw-r--r-- root root 1645 ./usr/include/X11/extensions/shm.h
+-rw-r--r-- root root 6045 ./usr/include/X11/extensions/shmproto.h
+-rw-r--r-- root root 2123 ./usr/include/X11/extensions/shmstr.h
+-rw-r--r-- root root 6750 ./usr/include/X11/extensions/syncconst.h
+-rw-r--r-- root root 9676 ./usr/include/X11/extensions/sync.h
+-rw-r--r-- root root 11001 ./usr/include/X11/extensions/syncproto.h
+-rw-r--r-- root root 5606 ./usr/include/X11/extensions/syncstr.h
+-rw-r--r-- root root 2377 ./usr/include/X11/extensions/Xag.h
+-rw-r--r-- root root 3057 ./usr/include/X11/extensions/xcmiscproto.h
+-rw-r--r-- root root 185 ./usr/include/X11/extensions/xcmiscstr.h
+-rw-r--r-- root root 1710 ./usr/include/X11/extensions/Xcup.h
+-rw-r--r-- root root 2307 ./usr/include/X11/extensions/Xdamage.h
+-rw-r--r-- root root 4170 ./usr/include/X11/extensions/Xdbe.h
+-rw-r--r-- root root 2130 ./usr/include/X11/extensions/XEVI.h
+-rw-r--r-- root root 1655 ./usr/include/X11/extensions/Xext.h
+-rw-r--r-- root root 414 ./usr/include/X11/extensions/xf86bigfont.h
+-rw-r--r-- root root 2544 ./usr/include/X11/extensions/xf86bigfproto.h
+-rw-r--r-- root root 191 ./usr/include/X11/extensions/xf86bigfstr.h
+-rw-r--r-- root root 931 ./usr/include/X11/extensions/xf86dga1const.h
+-rw-r--r-- root root 4506 ./usr/include/X11/extensions/xf86dga1proto.h
+-rw-r--r-- root root 191 ./usr/include/X11/extensions/xf86dga1str.h
+-rw-r--r-- root root 2533 ./usr/include/X11/extensions/xf86dgaconst.h
+-rw-r--r-- root root 369 ./usr/include/X11/extensions/xf86dga.h
+-rw-r--r-- root root 7106 ./usr/include/X11/extensions/xf86dgaproto.h
+-rw-r--r-- root root 188 ./usr/include/X11/extensions/xf86dgastr.h
+-rw-r--r-- root root 2106 ./usr/include/X11/extensions/xf86vm.h
+-rw-r--r-- root root 7619 ./usr/include/X11/extensions/xf86vmode.h
+-rw-r--r-- root root 15700 ./usr/include/X11/extensions/xf86vmproto.h
+-rw-r--r-- root root 185 ./usr/include/X11/extensions/xf86vmstr.h
+-rw-r--r-- root root 7588 ./usr/include/X11/extensions/Xfixes.h
+-rw-r--r-- root root 12752 ./usr/include/X11/extensions/xfixesproto.h
+-rw-r--r-- root root 5396 ./usr/include/X11/extensions/xfixeswire.h
+-rw-r--r-- root root 1927 ./usr/include/X11/extensions/Xge.h
+-rw-r--r-- root root 10542 ./usr/include/X11/extensions/XI2.h
+-rw-r--r-- root root 37577 ./usr/include/X11/extensions/XI2proto.h
+-rw-r--r-- root root 9823 ./usr/include/X11/extensions/XI.h
+-rw-r--r-- root root 41010 ./usr/include/X11/extensions/XIproto.h
+-rw-r--r-- root root 15808 ./usr/include/X11/extensions/XKBgeom.h
+-rw-r--r-- root root 28211 ./usr/include/X11/extensions/XKB.h
+-rw-r--r-- root root 29105 ./usr/include/X11/extensions/XKBproto.h
+-rw-r--r-- root root 28018 ./usr/include/X11/extensions/XKBsrv.h
+-rw-r--r-- root root 19630 ./usr/include/X11/extensions/XKBstr.h
+-rw-r--r-- root root 1601 ./usr/include/X11/extensions/XLbx.h
+-rw-r--r-- root root 17120 ./usr/include/X11/extensions/Xrandr.h
+-rw-r--r-- root root 12805 ./usr/include/X11/extensions/Xrender.h
+-rw-r--r-- root root 5168 ./usr/include/X11/extensions/XResproto.h
+-rw-r--r-- root root 3735 ./usr/include/X11/extensions/XShm.h
+-rw-r--r-- root root 1392 ./usr/include/X11/extensions/xtestconst.h
+-rw-r--r-- root root 5439 ./usr/include/X11/extensions/xtestext1const.h
+-rw-r--r-- root root 3708 ./usr/include/X11/extensions/xtestext1.h
+-rw-r--r-- root root 7790 ./usr/include/X11/extensions/xtestext1proto.h
+-rw-r--r-- root root 3254 ./usr/include/X11/extensions/xtestproto.h
+-rw-r--r-- root root 3027 ./usr/include/X11/extensions/Xv.h
+-rw-r--r-- root root 3620 ./usr/include/X11/extensions/XvMC.h
+-rw-r--r-- root root 4484 ./usr/include/X11/extensions/XvMCproto.h
+-rw-r--r-- root root 12109 ./usr/include/X11/extensions/Xvproto.h
+drwxr-xr-x root root 4096 ./usr/include/X11/fonts
+-rw-r--r-- root root 4253 ./usr/include/X11/fonts/font.h
+-rw-r--r-- root root 3450 ./usr/include/X11/fonts/fontproto.h
+-rw-r--r-- root root 9401 ./usr/include/X11/fonts/fontstruct.h
+-rw-r--r-- root root 4075 ./usr/include/X11/fonts/FS.h
+-rw-r--r-- root root 3992 ./usr/include/X11/fonts/fsmasks.h
+-rw-r--r-- root root 19889 ./usr/include/X11/fonts/FSproto.h
+-rw-r--r-- root root 6046 ./usr/include/X11/HPkeysym.h
+drwxr-xr-x root root 4096 ./usr/include/X11/ICE
+-rw-r--r-- root root 7413 ./usr/include/X11/ICE/ICEconn.h
+-rw-r--r-- root root 2512 ./usr/include/X11/ICE/ICE.h
+-rw-r--r-- root root 9925 ./usr/include/X11/ICE/ICElib.h
+-rw-r--r-- root root 8206 ./usr/include/X11/ICE/ICEmsg.h
+-rw-r--r-- root root 4604 ./usr/include/X11/ICE/ICEproto.h
+-rw-r--r-- root root 3154 ./usr/include/X11/ICE/ICEutil.h
+-rw-r--r-- root root 459 ./usr/include/X11/ImUtil.h
+-rw-r--r-- root root 175248 ./usr/include/X11/keysymdef.h
+-rw-r--r-- root root 2769 ./usr/include/X11/keysym.h
+drwxr-xr-x root root 4096 ./usr/include/X11/SM
+-rw-r--r-- root root 2927 ./usr/include/X11/SM/SM.h
+-rw-r--r-- root root 11268 ./usr/include/X11/SM/SMlib.h
+-rw-r--r-- root root 4852 ./usr/include/X11/SM/SMproto.h
+-rw-r--r-- root root 4022 ./usr/include/X11/Sunkeysym.h
+-rw-r--r-- root root 4587 ./usr/include/X11/Xalloca.h
+-rw-r--r-- root root 2951 ./usr/include/X11/Xarch.h
+-rw-r--r-- root root 2518 ./usr/include/X11/Xatom.h
+-rw-r--r-- root root 3817 ./usr/include/X11/Xauth.h
+-rw-r--r-- root root 21346 ./usr/include/X11/Xcms.h
+-rw-r--r-- root root 2401 ./usr/include/X11/Xdefs.h
+-rw-r--r-- root root 6371 ./usr/include/X11/Xdmcp.h
+-rw-r--r-- root root 13612 ./usr/include/X11/XF86keysym.h
+-rw-r--r-- root root 7863 ./usr/include/X11/Xfuncproto.h
+-rw-r--r-- root root 2256 ./usr/include/X11/Xfuncs.h
+-rw-r--r-- root root 20137 ./usr/include/X11/X.h
+-rw-r--r-- root root 30995 ./usr/include/X11/XKBlib.h
+-rw-r--r-- root root 1567 ./usr/include/X11/XlibConf.h
+-rw-r--r-- root root 99532 ./usr/include/X11/Xlib.h
+-rw-r--r-- root root 40597 ./usr/include/X11/Xlibint.h
+-rw-r--r-- root root 506 ./usr/include/X11/Xlib-xcb.h
+-rw-r--r-- root root 1297 ./usr/include/X11/Xlocale.h
+-rw-r--r-- root root 5122 ./usr/include/X11/Xmd.h
+-rw-r--r-- root root 3115 ./usr/include/X11/Xosdefs.h
+-rw-r--r-- root root 4362 ./usr/include/X11/Xos.h
+-rw-r--r-- root root 33693 ./usr/include/X11/Xos_r.h
+-rw-r--r-- root root 7743 ./usr/include/X11/Xpoll.h
+-rw-r--r-- root root 52399 ./usr/include/X11/Xproto.h
+-rw-r--r-- root root 2743 ./usr/include/X11/Xprotostr.h
+-rw-r--r-- root root 5949 ./usr/include/X11/Xregion.h
+-rw-r--r-- root root 10628 ./usr/include/X11/Xresource.h
+-rw-r--r-- root root 1719 ./usr/include/X11/xshmfence.h
+-rw-r--r-- root root 12395 ./usr/include/X11/Xthreads.h
+drwxr-xr-x root root 4096 ./usr/include/X11/Xtrans
+-rw-r--r-- root root 2876 ./usr/include/X11/Xtrans/transport.c
+-rw-r--r-- root root 29462 ./usr/include/X11/Xtrans/Xtrans.c
+-rw-r--r-- root root 8785 ./usr/include/X11/Xtrans/Xtrans.h
+-rw-r--r-- root root 10158 ./usr/include/X11/Xtrans/Xtransint.h
+-rw-r--r-- root root 55410 ./usr/include/X11/Xtrans/Xtranslcl.c
+-rw-r--r-- root root 62655 ./usr/include/X11/Xtrans/Xtranssock.c
+-rw-r--r-- root root 14937 ./usr/include/X11/Xtrans/Xtransutil.c
+-rw-r--r-- root root 21353 ./usr/include/X11/Xutil.h
+-rw-r--r-- root root 1909 ./usr/include/X11/Xw32defs.h
+-rw-r--r-- root root 3872 ./usr/include/X11/XWDFile.h
+-rw-r--r-- root root 3283 ./usr/include/X11/Xwindows.h
+-rw-r--r-- root root 2261 ./usr/include/X11/Xwinsock.h
+drwxr-xr-x root root 4096 ./usr/include/xcb
+-rw-r--r-- root root 2407 ./usr/include/xcb/bigreq.h
+-rw-r--r-- root root 13867 ./usr/include/xcb/composite.h
+-rw-r--r-- root root 9285 ./usr/include/xcb/damage.h
+-rw-r--r-- root root 11924 ./usr/include/xcb/dpms.h
+-rw-r--r-- root root 35759 ./usr/include/xcb/dri2.h
+-rw-r--r-- root root 24241 ./usr/include/xcb/dri3.h
+-rw-r--r-- root root 2981 ./usr/include/xcb/ge.h
+-rw-r--r-- root root 252818 ./usr/include/xcb/glx.h
+-rw-r--r-- root root 19292 ./usr/include/xcb/present.h
+-rw-r--r-- root root 139534 ./usr/include/xcb/randr.h
+-rw-r--r-- root root 27912 ./usr/include/xcb/record.h
+-rw-r--r-- root root 103726 ./usr/include/xcb/render.h
+-rw-r--r-- root root 24483 ./usr/include/xcb/res.h
+-rw-r--r-- root root 16460 ./usr/include/xcb/screensaver.h
+-rw-r--r-- root root 20806 ./usr/include/xcb/shape.h
+-rw-r--r-- root root 17261 ./usr/include/xcb/shm.h
+-rw-r--r-- root root 43756 ./usr/include/xcb/sync.h
+-rw-r--r-- root root 13990 ./usr/include/xcb/xcbext.h
+-rw-r--r-- root root 22260 ./usr/include/xcb/xcb.h
+-rw-r--r-- root root 7137 ./usr/include/xcb/xc_misc.h
+-rw-r--r-- root root 11593 ./usr/include/xcb/xevie.h
+-rw-r--r-- root root 28034 ./usr/include/xcb/xf86dri.h
+-rw-r--r-- root root 58079 ./usr/include/xcb/xfixes.h
+-rw-r--r-- root root 14955 ./usr/include/xcb/xinerama.h
+-rw-r--r-- root root 305557 ./usr/include/xcb/xinput.h
+-rw-r--r-- root root 246448 ./usr/include/xcb/xkb.h
+-rw-r--r-- root root 57187 ./usr/include/xcb/xprint.h
+-rw-r--r-- root root 385800 ./usr/include/xcb/xproto.h
+-rw-r--r-- root root 56622 ./usr/include/xcb/xselinux.h
+-rw-r--r-- root root 7589 ./usr/include/xcb/xtest.h
+-rw-r--r-- root root 57788 ./usr/include/xcb/xv.h
+-rw-r--r-- root root 24530 ./usr/include/xcb/xvmc.h
+drwxr-xr-x root root 4096 ./usr/include/xen
+-rw-r--r-- root root 3553 ./usr/include/xen/evtchn.h
+-rw-r--r-- root root 2619 ./usr/include/xen/gntalloc.h
+-rw-r--r-- root root 10647 ./usr/include/xen/gntdev.h
+-rw-r--r-- root root 4206 ./usr/include/xen/privcmd.h
+-rw-r--r-- root root 35465 ./usr/include/xf86drm.h
+-rw-r--r-- root root 18016 ./usr/include/xf86drmMode.h
+-rw-r--r-- root root 19283 ./usr/include/xtables.h
+-rw-r--r-- root root 75 ./usr/include/xtables-version.h
+-rw-r--r-- root root 16262 ./usr/include/zconf.h
+-rw-r--r-- root root 96239 ./usr/include/zlib.h
+drwxr-xr-x root root 20480 ./usr/lib
+drwxr-xr-x root root 4096 ./usr/lib/cmake
+drwxr-xr-x root root 4096 ./usr/lib/cmake/DBus1
+-rw-r--r-- root root 2883 ./usr/lib/cmake/DBus1/DBus1Config.cmake
+-rw-r--r-- root root 367 ./usr/lib/cmake/DBus1/DBus1ConfigVersion.cmake
+drwxr-xr-x root root 4096 ./usr/lib/cmake/libxml2
+-rw-r--r-- root root 1642 ./usr/lib/cmake/libxml2/libxml2-config.cmake
+drwxr-xr-x root root 4096 ./usr/lib/coreutils
+-rwxr-xr-x root root 14144 ./usr/lib/coreutils/libstdbuf.so
+-rw-r--r-- root root 4280 ./usr/lib/crt1.o
+-rw-r--r-- root root 2808 ./usr/lib/crti.o
+-rw-r--r-- root root 2552 ./usr/lib/crtn.o
+drwxr-xr-x root root 4096 ./usr/lib/dbus-1.0
+drwxr-xr-x root root 4096 ./usr/lib/dbus-1.0/include
+drwxr-xr-x root root 4096 ./usr/lib/dbus-1.0/include/dbus
+-rw-r--r-- root root 2052 ./usr/lib/dbus-1.0/include/dbus/dbus-arch-deps.h
+drwxr-xr-x root root 4096 ./usr/lib/dri
+-rwxr-xr-x root root 12207640 ./usr/lib/dri/i915_dri.so
+-rwxr-xr-x root root 12207640 ./usr/lib/dri/i965_dri.so
+-rwxr-xr-x root root 9195384 ./usr/lib/dri/kms_swrast_dri.so
+-rwxr-xr-x root root 12207640 ./usr/lib/dri/nouveau_vieux_dri.so
+-rwxr-xr-x root root 12207640 ./usr/lib/dri/r200_dri.so
+-rwxr-xr-x root root 12207640 ./usr/lib/dri/radeon_dri.so
+-rwxr-xr-x root root 9195384 ./usr/lib/dri/swrast_dri.so
+-rwxr-xr-x root root 9195384 ./usr/lib/dri/virtio_gpu_dri.so
+-rwxr-xr-x root root 14376 ./usr/lib/e2initrd_helper
+drwxr-xr-x root root 4096 ./usr/libexec
+drwxr-xr-x root root 4096 ./usr/libexec/awk
+-rwxr-xr-x root root 14288 ./usr/libexec/awk/grcat
+-rwxr-xr-x root root 14288 ./usr/libexec/awk/pwcat
+-rwsr-xr-x root messagebus 63592 ./usr/libexec/dbus-daemon-launch-helper
+-rwxr-xr-x root root 43168 ./usr/libexec/frcode
+-rwxr-xr-x root root 14304 ./usr/libexec/gio-querymodules
+-rwxr-xr-x root root 354584 ./usr/libexec/udevadm
+drwxr-xr-x root root 4096 ./usr/lib/gawk
+-rwxr-xr-x root root 39016 ./usr/lib/gawk/filefuncs.so
+-rwxr-xr-x root root 14288 ./usr/lib/gawk/fnmatch.so
+-rwxr-xr-x root root 14304 ./usr/lib/gawk/fork.so
+-rwxr-xr-x root root 14288 ./usr/lib/gawk/inplace.so
+-rwxr-xr-x root root 14208 ./usr/lib/gawk/intdiv.so
+-rwxr-xr-x root root 14256 ./usr/lib/gawk/ordchr.so
+-rwxr-xr-x root root 14192 ./usr/lib/gawk/readdir.so
+-rwxr-xr-x root root 14256 ./usr/lib/gawk/readfile.so
+-rwxr-xr-x root root 14200 ./usr/lib/gawk/revoutput.so
+-rwxr-xr-x root root 14200 ./usr/lib/gawk/revtwoway.so
+-rwxr-xr-x root root 18352 ./usr/lib/gawk/rwarray.so
+-rwxr-xr-x root root 14256 ./usr/lib/gawk/time.so
+-rw-r--r-- root root 7064 ./usr/lib/gcrt1.o
+drwxr-xr-x root root 4096 ./usr/lib/gio
+drwxr-xr-x root root 4096 ./usr/lib/gio/modules
+drwxr-xr-x root root 4096 ./usr/lib/girepository-1.0
+-rw-r--r-- root root 14344 ./usr/lib/girepository-1.0/cairo-1.0.typelib
+-rw-r--r-- root root 712 ./usr/lib/girepository-1.0/DBus-1.0.typelib
+-rw-r--r-- root root 560 ./usr/lib/girepository-1.0/DBusGLib-1.0.typelib
+-rw-r--r-- root root 348 ./usr/lib/girepository-1.0/fontconfig-2.0.typelib
+-rw-r--r-- root root 420 ./usr/lib/girepository-1.0/freetype2-2.0.typelib
+-rw-r--r-- root root 353336 ./usr/lib/girepository-1.0/Gio-2.0.typelib
+-rw-r--r-- root root 27752 ./usr/lib/girepository-1.0/GIRepository-2.0.typelib
+-rw-r--r-- root root 948 ./usr/lib/girepository-1.0/GL-1.0.typelib
+-rw-r--r-- root root 191884 ./usr/lib/girepository-1.0/GLib-2.0.typelib
+-rw-r--r-- root root 1340 ./usr/lib/girepository-1.0/GModule-2.0.typelib
+-rw-r--r-- root root 58972 ./usr/lib/girepository-1.0/GObject-2.0.typelib
+-rw-r--r-- root root 668 ./usr/lib/girepository-1.0/libxml2-2.0.typelib
+-rw-r--r-- root root 59380 ./usr/lib/girepository-1.0/Vulkan-1.0.typelib
+-rw-r--r-- root root 176 ./usr/lib/girepository-1.0/win32-1.0.typelib
+-rw-r--r-- root root 240 ./usr/lib/girepository-1.0/xfixes-4.0.typelib
+-rw-r--r-- root root 464 ./usr/lib/girepository-1.0/xft-2.0.typelib
+-rw-r--r-- root root 836 ./usr/lib/girepository-1.0/xlib-2.0.typelib
+-rw-r--r-- root root 640 ./usr/lib/girepository-1.0/xrandr-1.3.typelib
+drwxr-xr-x root root 4096 ./usr/lib/glib-2.0
+drwxr-xr-x root root 4096 ./usr/lib/glib-2.0/include
+-rw-r--r-- root root 5649 ./usr/lib/glib-2.0/include/glibconfig.h
+drwxr-xr-x root root 4096 ./usr/lib/gobject-introspection
+drwxr-xr-x root root 4096 ./usr/lib/gobject-introspection/giscanner
+-rw-r--r-- root root 3526 ./usr/lib/gobject-introspection/giscanner/annotationmain.py
+-rw-r--r-- root root 101376 ./usr/lib/gobject-introspection/giscanner/annotationparser.py
+-rw-r--r-- root root 43411 ./usr/lib/gobject-introspection/giscanner/ast.py
+-rw-r--r-- root root 5852 ./usr/lib/gobject-introspection/giscanner/cachestore.py
+-rw-r--r-- root root 19524 ./usr/lib/gobject-introspection/giscanner/ccompiler.py
+-rw-r--r-- root root 6190 ./usr/lib/gobject-introspection/giscanner/codegen.py
+-rw-r--r-- root root 3268 ./usr/lib/gobject-introspection/giscanner/docmain.py
+drwxr-xr-x root root 4096 ./usr/lib/gobject-introspection/giscanner/doctemplates
+drwxr-xr-x root root 4096 ./usr/lib/gobject-introspection/giscanner/doctemplates/devdocs
+drwxr-xr-x root root 4096 ./usr/lib/gobject-introspection/giscanner/doctemplates/devdocs/Gjs
+-rw-r--r-- root root 567 ./usr/lib/gobject-introspection/giscanner/doctemplates/devdocs/Gjs/base.tmpl
+-rw-r--r-- root root 113 ./usr/lib/gobject-introspection/giscanner/doctemplates/devdocs/Gjs/callback.tmpl
+-rw-r--r-- root root 29 ./usr/lib/gobject-introspection/giscanner/doctemplates/devdocs/Gjs/class.tmpl
+-rw-r--r-- root root 847 ./usr/lib/gobject-introspection/giscanner/doctemplates/devdocs/Gjs/default.tmpl
+-rw-r--r-- root root 890 ./usr/lib/gobject-introspection/giscanner/doctemplates/devdocs/Gjs/_doc.tmpl
+-rw-r--r-- root root 313 ./usr/lib/gobject-introspection/giscanner/doctemplates/devdocs/Gjs/enum.tmpl
+-rw-r--r-- root root 113 ./usr/lib/gobject-introspection/giscanner/doctemplates/devdocs/Gjs/function.tmpl
+-rw-r--r-- root root 5189 ./usr/lib/gobject-introspection/giscanner/doctemplates/devdocs/Gjs/_index.tmpl
+-rw-r--r-- root root 29 ./usr/lib/gobject-introspection/giscanner/doctemplates/devdocs/Gjs/interface.tmpl
+-rw-r--r-- root root 120 ./usr/lib/gobject-introspection/giscanner/doctemplates/devdocs/Gjs/_methods.tmpl
+-rw-r--r-- root root 1899 ./usr/lib/gobject-introspection/giscanner/doctemplates/devdocs/Gjs/_method.tmpl
+-rw-r--r-- root root 32 ./usr/lib/gobject-introspection/giscanner/doctemplates/devdocs/Gjs/method.tmpl
+-rw-r--r-- root root 1278 ./usr/lib/gobject-introspection/giscanner/doctemplates/devdocs/Gjs/namespace.tmpl
+-rw-r--r-- root root 1123 ./usr/lib/gobject-introspection/giscanner/doctemplates/devdocs/Gjs/_properties.tmpl
+-rw-r--r-- root root 652 ./usr/lib/gobject-introspection/giscanner/doctemplates/devdocs/Gjs/_signals.tmpl
+-rw-r--r-- root root 176 ./usr/lib/gobject-introspection/giscanner/doctemplates/devdocs/Gjs/_staticmethods.tmpl
+-rw-r--r-- root root 183 ./usr/lib/gobject-introspection/giscanner/doctemplates/devdocs/Gjs/_vfuncs.tmpl
+drwxr-xr-x root root 4096 ./usr/lib/gobject-introspection/giscanner/doctemplates/mallard
+-rw-r--r-- root root 765 ./usr/lib/gobject-introspection/giscanner/doctemplates/mallard/base.tmpl
+drwxr-xr-x root root 4096 ./usr/lib/gobject-introspection/giscanner/doctemplates/mallard/C
+-rw-r--r-- root root 141 ./usr/lib/gobject-introspection/giscanner/doctemplates/mallard/C/callback.tmpl
+-rw-r--r-- root root 57 ./usr/lib/gobject-introspection/giscanner/doctemplates/mallard/C/class.tmpl
+-rw-r--r-- root root 35 ./usr/lib/gobject-introspection/giscanner/doctemplates/mallard/C/constructor.tmpl
+-rw-r--r-- root root 30 ./usr/lib/gobject-introspection/giscanner/doctemplates/mallard/C/default.tmpl
+-rw-r--r-- root root 56 ./usr/lib/gobject-introspection/giscanner/doctemplates/mallard/C/enum.tmpl
+-rw-r--r-- root root 30 ./usr/lib/gobject-introspection/giscanner/doctemplates/mallard/C/field.tmpl
+-rw-r--r-- root root 1654 ./usr/lib/gobject-introspection/giscanner/doctemplates/mallard/C/function.tmpl
+-rw-r--r-- root root 57 ./usr/lib/gobject-introspection/giscanner/doctemplates/mallard/C/interface.tmpl
+-rw-r--r-- root root 1982 ./usr/lib/gobject-introspection/giscanner/doctemplates/mallard/class.tmpl
+-rw-r--r-- root root 35 ./usr/lib/gobject-introspection/giscanner/doctemplates/mallard/C/method.tmpl
+-rw-r--r-- root root 35 ./usr/lib/gobject-introspection/giscanner/doctemplates/mallard/C/namespace.tmpl
+-rw-r--r-- root root 191 ./usr/lib/gobject-introspection/giscanner/doctemplates/mallard/C/property.tmpl
+-rw-r--r-- root root 30 ./usr/lib/gobject-introspection/giscanner/doctemplates/mallard/C/record.tmpl
+-rw-r--r-- root root 196 ./usr/lib/gobject-introspection/giscanner/doctemplates/mallard/C/signal.tmpl
+-rw-r--r-- root root 139 ./usr/lib/gobject-introspection/giscanner/doctemplates/mallard/C/vfunc.tmpl
+drwxr-xr-x root root 4096 ./usr/lib/gobject-introspection/giscanner/doctemplates/mallard/Gjs
+-rw-r--r-- root root 780 ./usr/lib/gobject-introspection/giscanner/doctemplates/mallard/Gjs/callback.tmpl
+-rw-r--r-- root root 863 ./usr/lib/gobject-introspection/giscanner/doctemplates/mallard/Gjs/class.tmpl
+-rw-r--r-- root root 35 ./usr/lib/gobject-introspection/giscanner/doctemplates/mallard/Gjs/constructor.tmpl
+-rw-r--r-- root root 30 ./usr/lib/gobject-introspection/giscanner/doctemplates/mallard/Gjs/default.tmpl
+-rw-r--r-- root root 511 ./usr/lib/gobject-introspection/giscanner/doctemplates/mallard/Gjs/enum.tmpl
+-rw-r--r-- root root 423 ./usr/lib/gobject-introspection/giscanner/doctemplates/mallard/Gjs/field.tmpl
+-rw-r--r-- root root 1469 ./usr/lib/gobject-introspection/giscanner/doctemplates/mallard/Gjs/function.tmpl
+-rw-r--r-- root root 558 ./usr/lib/gobject-introspection/giscanner/doctemplates/mallard/Gjs/interface.tmpl
+-rw-r--r-- root root 35 ./usr/lib/gobject-introspection/giscanner/doctemplates/mallard/Gjs/method.tmpl
+-rw-r--r-- root root 61 ./usr/lib/gobject-introspection/giscanner/doctemplates/mallard/Gjs/namespace.tmpl
+-rw-r--r-- root root 423 ./usr/lib/gobject-introspection/giscanner/doctemplates/mallard/Gjs/property.tmpl
+-rw-r--r-- root root 56 ./usr/lib/gobject-introspection/giscanner/doctemplates/mallard/Gjs/record.tmpl
+-rw-r--r-- root root 1185 ./usr/lib/gobject-introspection/giscanner/doctemplates/mallard/Gjs/signal.tmpl
+-rw-r--r-- root root 746 ./usr/lib/gobject-introspection/giscanner/doctemplates/mallard/Gjs/vfunc.tmpl
+-rw-r--r-- root root 551 ./usr/lib/gobject-introspection/giscanner/doctemplates/mallard/namespace.tmpl
+drwxr-xr-x root root 4096 ./usr/lib/gobject-introspection/giscanner/doctemplates/mallard/Python
+-rw-r--r-- root root 849 ./usr/lib/gobject-introspection/giscanner/doctemplates/mallard/Python/callback.tmpl
+-rw-r--r-- root root 593 ./usr/lib/gobject-introspection/giscanner/doctemplates/mallard/Python/class.tmpl
+-rw-r--r-- root root 35 ./usr/lib/gobject-introspection/giscanner/doctemplates/mallard/Python/constructor.tmpl
+-rw-r--r-- root root 30 ./usr/lib/gobject-introspection/giscanner/doctemplates/mallard/Python/default.tmpl
+-rw-r--r-- root root 264 ./usr/lib/gobject-introspection/giscanner/doctemplates/mallard/Python/enum.tmpl
+-rw-r--r-- root root 30 ./usr/lib/gobject-introspection/giscanner/doctemplates/mallard/Python/field.tmpl
+-rw-r--r-- root root 1572 ./usr/lib/gobject-introspection/giscanner/doctemplates/mallard/Python/function.tmpl
+-rw-r--r-- root root 535 ./usr/lib/gobject-introspection/giscanner/doctemplates/mallard/Python/interface.tmpl
+-rw-r--r-- root root 35 ./usr/lib/gobject-introspection/giscanner/doctemplates/mallard/Python/method.tmpl
+-rw-r--r-- root root 61 ./usr/lib/gobject-introspection/giscanner/doctemplates/mallard/Python/namespace.tmpl
+-rw-r--r-- root root 407 ./usr/lib/gobject-introspection/giscanner/doctemplates/mallard/Python/property.tmpl
+-rw-r--r-- root root 56 ./usr/lib/gobject-introspection/giscanner/doctemplates/mallard/Python/record.tmpl
+-rw-r--r-- root root 1235 ./usr/lib/gobject-introspection/giscanner/doctemplates/mallard/Python/signal.tmpl
+-rw-r--r-- root root 849 ./usr/lib/gobject-introspection/giscanner/doctemplates/mallard/Python/vfunc.tmpl
+-rw-r--r-- root root 50143 ./usr/lib/gobject-introspection/giscanner/docwriter.py
+-rw-r--r-- root root 10639 ./usr/lib/gobject-introspection/giscanner/dumper.py
+-rw-r--r-- root root 21322 ./usr/lib/gobject-introspection/giscanner/gdumpparser.py
+-rw-r--r-- root root 28229 ./usr/lib/gobject-introspection/giscanner/girparser.py
+-rw-r--r-- root root 28222 ./usr/lib/gobject-introspection/giscanner/girwriter.py
+-rwxr-xr-x root root 101672 ./usr/lib/gobject-introspection/giscanner/_giscanner.cpython-38-x86_64-linux-gnu.so
+-rw-r--r-- root root 1105 ./usr/lib/gobject-introspection/giscanner/__init__.py
+-rw-r--r-- root root 9398 ./usr/lib/gobject-introspection/giscanner/introspectablepass.py
+-rw-r--r-- root root 2554 ./usr/lib/gobject-introspection/giscanner/libtoolimporter.py
+-rw-r--r-- root root 65300 ./usr/lib/gobject-introspection/giscanner/maintransformer.py
+-rw-r--r-- root root 392 ./usr/lib/gobject-introspection/giscanner/mdextensions.py
+-rw-r--r-- root root 7612 ./usr/lib/gobject-introspection/giscanner/message.py
+-rw-r--r-- root root 3756 ./usr/lib/gobject-introspection/giscanner/msvccompiler.py
+-rw-r--r-- root root 2283 ./usr/lib/gobject-introspection/giscanner/pkgconfig.py
+-rw-r--r-- root root 27285 ./usr/lib/gobject-introspection/giscanner/scannermain.py
+-rw-r--r-- root root 4790 ./usr/lib/gobject-introspection/giscanner/sectionparser.py
+-rw-r--r-- root root 6259 ./usr/lib/gobject-introspection/giscanner/shlibs.py
+-rw-r--r-- root root 9628 ./usr/lib/gobject-introspection/giscanner/sourcescanner.py
+-rw-r--r-- root root 5699 ./usr/lib/gobject-introspection/giscanner/testcodegen.py
+-rw-r--r-- root root 44647 ./usr/lib/gobject-introspection/giscanner/transformer.py
+-rw-r--r-- root root 10521 ./usr/lib/gobject-introspection/giscanner/utils.py
+-rw-r--r-- root root 23 ./usr/lib/gobject-introspection/giscanner/_version.py
+-rw-r--r-- root root 5798 ./usr/lib/gobject-introspection/giscanner/xmlwriter.py
+-rwxr-xr-x root root 38904 ./usr/lib/libacl.so.1.1.2253
+lrwxrwxrwx root root 18 ./usr/lib/libacl.so.1 -> libacl.so.1.1.2253
+lrwxrwxrwx root root 18 ./usr/lib/libacl.so -> libacl.so.1.1.2253
+lrwxrwxrwx root root 21 ./usr/lib/libanl.so -> ../../lib/libanl.so.1
+-rwxr-xr-x root root 34856 ./usr/lib/libasm-0.179.so
+lrwxrwxrwx root root 15 ./usr/lib/libasm.so.1 -> libasm-0.179.so
+lrwxrwxrwx root root 11 ./usr/lib/libasm.so -> libasm.so.1
+-rwxr-xr-x root root 26512 ./usr/lib/libattr.so.1.1.2448
+lrwxrwxrwx root root 19 ./usr/lib/libattr.so.1 -> libattr.so.1.1.2448
+lrwxrwxrwx root root 19 ./usr/lib/libattr.so -> libattr.so.1.1.2448
+-rwxr-xr-x root root 1310600 ./usr/lib/libbfd-2.34.0.20200220.so
+lrwxrwxrwx root root 25 ./usr/lib/libbfd.so -> libbfd-2.34.0.20200220.so
+lrwxrwxrwx root root 27 ./usr/lib/libblkid.so -> ../../lib/libblkid.so.1.1.0
+lrwxrwxrwx root root 30 ./usr/lib/libBrokenLocale.so -> ../../lib/libBrokenLocale.so.1
+-rwxr-xr-x root root 387680 ./usr/lib/libbtrfs.so.0.1
+lrwxrwxrwx root root 15 ./usr/lib/libbtrfs.so.0 -> libbtrfs.so.0.1
+lrwxrwxrwx root root 15 ./usr/lib/libbtrfs.so -> libbtrfs.so.0.1
+-rwxr-xr-x root root 34784 ./usr/lib/libbtrfsutil.so.1.2.0
+lrwxrwxrwx root root 21 ./usr/lib/libbtrfsutil.so.1 -> libbtrfsutil.so.1.2.0
+lrwxrwxrwx root root 21 ./usr/lib/libbtrfsutil.so -> libbtrfsutil.so.1.2.0
+-rwxr-xr-x root root 74656 ./usr/lib/libbz2.so.1.0.6
+lrwxrwxrwx root root 15 ./usr/lib/libbz2.so.1 -> libbz2.so.1.0.6
+lrwxrwxrwx root root 15 ./usr/lib/libbz2.so -> libbz2.so.1.0.6
+-rwxr-xr-x root root 42752 ./usr/lib/libcairo-gobject.so.2.11600.0
+lrwxrwxrwx root root 29 ./usr/lib/libcairo-gobject.so.2 -> libcairo-gobject.so.2.11600.0
+lrwxrwxrwx root root 29 ./usr/lib/libcairo-gobject.so -> libcairo-gobject.so.2.11600.0
+-rwxr-xr-x root root 156384 ./usr/lib/libcairo-script-interpreter.so.2.11600.0
+lrwxrwxrwx root root 40 ./usr/lib/libcairo-script-interpreter.so.2 -> libcairo-script-interpreter.so.2.11600.0
+lrwxrwxrwx root root 40 ./usr/lib/libcairo-script-interpreter.so -> libcairo-script-interpreter.so.2.11600.0
+-rwxr-xr-x root root 1291312 ./usr/lib/libcairo.so.2.11600.0
+lrwxrwxrwx root root 21 ./usr/lib/libcairo.so.2 -> libcairo.so.2.11600.0
+lrwxrwxrwx root root 21 ./usr/lib/libcairo.so -> libcairo.so.2.11600.0
+lrwxrwxrwx root root 28 ./usr/lib/libcap-ng.so -> ../../lib/libcap-ng.so.0.0.0
+-rw-r--r-- root root 76674 ./usr/lib/libc_nonshared.a
+-rwxr-xr-x root root 2872136 ./usr/lib/libcrypto.so.1.1
+lrwxrwxrwx root root 16 ./usr/lib/libcrypto.so -> libcrypto.so.1.1
+-rwxr-xr-x root root 202648 ./usr/lib/libcrypt.so.2.0.0
+lrwxrwxrwx root root 17 ./usr/lib/libcrypt.so.2 -> libcrypt.so.2.0.0
+lrwxrwxrwx root root 17 ./usr/lib/libcrypt.so -> libcrypt.so.2.0.0
+-rw-r--r-- root root 247 ./usr/lib/libc.so
+-rwxr-xr-x root root 116736 ./usr/lib/libctf-nobfd.so.0.0.0
+lrwxrwxrwx root root 21 ./usr/lib/libctf-nobfd.so.0 -> libctf-nobfd.so.0.0.0
+lrwxrwxrwx root root 21 ./usr/lib/libctf-nobfd.so -> libctf-nobfd.so.0.0.0
+-rwxr-xr-x root root 116728 ./usr/lib/libctf.so.0.0.0
+lrwxrwxrwx root root 15 ./usr/lib/libctf.so.0 -> libctf.so.0.0.0
+lrwxrwxrwx root root 15 ./usr/lib/libctf.so -> libctf.so.0.0.0
+lrwxrwxrwx root root 13 ./usr/lib/libcurses.so -> libncurses.so
+-rwxr-xr-x root root 1267928 ./usr/lib/libdb-5.3.so
+lrwxrwxrwx root root 12 ./usr/lib/libdb-5.so -> libdb-5.3.so
+lrwxrwxrwx root root 12 ./usr/lib/libdb.so -> libdb-5.3.so
+-rwxr-xr-x root root 346240 ./usr/lib/libdbus-1.so.3.19.11
+lrwxrwxrwx root root 20 ./usr/lib/libdbus-1.so.3 -> libdbus-1.so.3.19.11
+lrwxrwxrwx root root 20 ./usr/lib/libdbus-1.so -> libdbus-1.so.3.19.11
+lrwxrwxrwx root root 20 ./usr/lib/libdl.so -> ../../lib/libdl.so.2
+-rwxr-xr-x root root 42824 ./usr/lib/libdrm_amdgpu.so.1.0.0
+lrwxrwxrwx root root 22 ./usr/lib/libdrm_amdgpu.so.1 -> libdrm_amdgpu.so.1.0.0
+lrwxrwxrwx root root 18 ./usr/lib/libdrm_amdgpu.so -> libdrm_amdgpu.so.1
+-rwxr-xr-x root root 30536 ./usr/lib/libdrm_etnaviv.so.1.0.0
+lrwxrwxrwx root root 23 ./usr/lib/libdrm_etnaviv.so.1 -> libdrm_etnaviv.so.1.0.0
+lrwxrwxrwx root root 19 ./usr/lib/libdrm_etnaviv.so -> libdrm_etnaviv.so.1
+-rwxr-xr-x root root 34712 ./usr/lib/libdrm_freedreno.so.1.0.0
+lrwxrwxrwx root root 25 ./usr/lib/libdrm_freedreno.so.1 -> libdrm_freedreno.so.1.0.0
+lrwxrwxrwx root root 21 ./usr/lib/libdrm_freedreno.so -> libdrm_freedreno.so.1
+-rwxr-xr-x root root 146920 ./usr/lib/libdrm_intel.so.1.0.0
+lrwxrwxrwx root root 21 ./usr/lib/libdrm_intel.so.1 -> libdrm_intel.so.1.0.0
+lrwxrwxrwx root root 17 ./usr/lib/libdrm_intel.so -> libdrm_intel.so.1
+-rwxr-xr-x root root 34632 ./usr/lib/libdrm_nouveau.so.2.0.0
+lrwxrwxrwx root root 23 ./usr/lib/libdrm_nouveau.so.2 -> libdrm_nouveau.so.2.0.0
+lrwxrwxrwx root root 19 ./usr/lib/libdrm_nouveau.so -> libdrm_nouveau.so.2
+-rwxr-xr-x root root 14080 ./usr/lib/libdrm_omap.so.1.0.0
+lrwxrwxrwx root root 20 ./usr/lib/libdrm_omap.so.1 -> libdrm_omap.so.1.0.0
+lrwxrwxrwx root root 16 ./usr/lib/libdrm_omap.so -> libdrm_omap.so.1
+-rwxr-xr-x root root 55184 ./usr/lib/libdrm_radeon.so.1.0.1
+lrwxrwxrwx root root 22 ./usr/lib/libdrm_radeon.so.1 -> libdrm_radeon.so.1.0.1
+lrwxrwxrwx root root 18 ./usr/lib/libdrm_radeon.so -> libdrm_radeon.so.1
+-rwxr-xr-x root root 79752 ./usr/lib/libdrm.so.2.4.0
+lrwxrwxrwx root root 15 ./usr/lib/libdrm.so.2 -> libdrm.so.2.4.0
+lrwxrwxrwx root root 11 ./usr/lib/libdrm.so -> libdrm.so.2
+-rwxr-xr-x root root 650160 ./usr/lib/libdw-0.179.so
+lrwxrwxrwx root root 14 ./usr/lib/libdw.so.1 -> libdw-0.179.so
+lrwxrwxrwx root root 10 ./usr/lib/libdw.so -> libdw.so.1
+-rwxr-xr-x root root 100384 ./usr/lib/libelf-0.179.so
+lrwxrwxrwx root root 15 ./usr/lib/libelf.so.1 -> libelf-0.179.so
+lrwxrwxrwx root root 11 ./usr/lib/libelf.so -> libelf.so.1
+-rwxr-xr-x root root 182160 ./usr/lib/libexpat.so.1.6.11
+lrwxrwxrwx root root 18 ./usr/lib/libexpat.so.1 -> libexpat.so.1.6.11
+lrwxrwxrwx root root 18 ./usr/lib/libexpat.so -> libexpat.so.1.6.11
+lrwxrwxrwx root root 27 ./usr/lib/libfdisk.so -> ../../lib/libfdisk.so.1.1.0
+-rwxr-xr-x root root 43032 ./usr/lib/libffi.so.7.1.0
+lrwxrwxrwx root root 15 ./usr/lib/libffi.so.7 -> libffi.so.7.1.0
+lrwxrwxrwx root root 15 ./usr/lib/libffi.so -> libffi.so.7.1.0
+-rwxr-xr-x root root 14072 ./usr/lib/libfl.so.2.0.0
+lrwxrwxrwx root root 14 ./usr/lib/libfl.so.2 -> libfl.so.2.0.0
+lrwxrwxrwx root root 14 ./usr/lib/libfl.so -> libfl.so.2.0.0
+-rwxr-xr-x root root 288664 ./usr/lib/libfontconfig.so.1.12.0
+lrwxrwxrwx root root 23 ./usr/lib/libfontconfig.so.1 -> libfontconfig.so.1.12.0
+lrwxrwxrwx root root 23 ./usr/lib/libfontconfig.so -> libfontconfig.so.1.12.0
+-rwxr-xr-x root root 68696 ./usr/lib/libform.so.5.9
+lrwxrwxrwx root root 14 ./usr/lib/libform.so.5 -> libform.so.5.9
+lrwxrwxrwx root root 12 ./usr/lib/libform.so -> libform.so.5
+-rwxr-xr-x root root 76952 ./usr/lib/libformw.so.5.9
+lrwxrwxrwx root root 15 ./usr/lib/libformw.so.5 -> libformw.so.5.9
+lrwxrwxrwx root root 13 ./usr/lib/libformw.so -> libformw.so.5
+-rwxr-xr-x root root 722832 ./usr/lib/libfreetype.so.6.17.2
+lrwxrwxrwx root root 21 ./usr/lib/libfreetype.so.6 -> libfreetype.so.6.17.2
+lrwxrwxrwx root root 21 ./usr/lib/libfreetype.so -> libfreetype.so.6.17.2
+-rwxr-xr-x root root 14080 ./usr/lib/libgdbm_compat.so.4.0.0
+lrwxrwxrwx root root 23 ./usr/lib/libgdbm_compat.so.4 -> libgdbm_compat.so.4.0.0
+lrwxrwxrwx root root 23 ./usr/lib/libgdbm_compat.so -> libgdbm_compat.so.4.0.0
+-rwxr-xr-x root root 59392 ./usr/lib/libgdbm.so.6.0.0
+lrwxrwxrwx root root 16 ./usr/lib/libgdbm.so.6 -> libgdbm.so.6.0.0
+lrwxrwxrwx root root 16 ./usr/lib/libgdbm.so -> libgdbm.so.6.0.0
+-rwxr-xr-x root root 1932600 ./usr/lib/libgio-2.0.so.0.6400.2
+lrwxrwxrwx root root 22 ./usr/lib/libgio-2.0.so.0 -> libgio-2.0.so.0.6400.2
+lrwxrwxrwx root root 15 ./usr/lib/libgio-2.0.so -> libgio-2.0.so.0
+-rwxr-xr-x root root 223248 ./usr/lib/libgirepository-1.0.so.1.0.0
+lrwxrwxrwx root root 28 ./usr/lib/libgirepository-1.0.so.1 -> libgirepository-1.0.so.1.0.0
+lrwxrwxrwx root root 24 ./usr/lib/libgirepository-1.0.so -> libgirepository-1.0.so.1
+-rwxr-xr-x root root 325664 ./usr/lib/libglapi.so.0.0.0
+lrwxrwxrwx root root 17 ./usr/lib/libglapi.so.0 -> libglapi.so.0.0.0
+lrwxrwxrwx root root 13 ./usr/lib/libglapi.so -> libglapi.so.0
+-rwxr-xr-x root root 1203480 ./usr/lib/libglib-2.0.so.0.6400.2
+lrwxrwxrwx root root 23 ./usr/lib/libglib-2.0.so.0 -> libglib-2.0.so.0.6400.2
+lrwxrwxrwx root root 16 ./usr/lib/libglib-2.0.so -> libglib-2.0.so.0
+-rwxr-xr-x root root 498608 ./usr/lib/libGL.so.1.2.0
+lrwxrwxrwx root root 14 ./usr/lib/libGL.so.1 -> libGL.so.1.2.0
+lrwxrwxrwx root root 10 ./usr/lib/libGL.so -> libGL.so.1
+-rwxr-xr-x root root 18304 ./usr/lib/libgmodule-2.0.so.0.6400.2
+lrwxrwxrwx root root 26 ./usr/lib/libgmodule-2.0.so.0 -> libgmodule-2.0.so.0.6400.2
+lrwxrwxrwx root root 19 ./usr/lib/libgmodule-2.0.so -> libgmodule-2.0.so.0
+-rwxr-xr-x root root 489440 ./usr/lib/libgmp.so.10.4.0
+lrwxrwxrwx root root 16 ./usr/lib/libgmp.so.10 -> libgmp.so.10.4.0
+lrwxrwxrwx root root 16 ./usr/lib/libgmp.so -> libgmp.so.10.4.0
+-rwxr-xr-x root root 30696 ./usr/lib/libgmpxx.so.4.6.0
+lrwxrwxrwx root root 17 ./usr/lib/libgmpxx.so.4 -> libgmpxx.so.4.6.0
+lrwxrwxrwx root root 17 ./usr/lib/libgmpxx.so -> libgmpxx.so.4.6.0
+-rwxr-xr-x root root 354344 ./usr/lib/libgobject-2.0.so.0.6400.2
+lrwxrwxrwx root root 26 ./usr/lib/libgobject-2.0.so.0 -> libgobject-2.0.so.0.6400.2
+lrwxrwxrwx root root 19 ./usr/lib/libgobject-2.0.so -> libgobject-2.0.so.0
+-rwxr-xr-x root root 14000 ./usr/lib/libgthread-2.0.so.0.6400.2
+lrwxrwxrwx root root 26 ./usr/lib/libgthread-2.0.so.0 -> libgthread-2.0.so.0.6400.2
+lrwxrwxrwx root root 19 ./usr/lib/libgthread-2.0.so -> libgthread-2.0.so.0
+-rwxr-xr-x root root 46944 ./usr/lib/libhistory.so.8.0
+lrwxrwxrwx root root 17 ./usr/lib/libhistory.so.8 -> libhistory.so.8.0
+lrwxrwxrwx root root 17 ./usr/lib/libhistory.so -> libhistory.so.8.0
+-rwxr-xr-x root root 101096 ./usr/lib/libICE.so.6.3.0
+lrwxrwxrwx root root 15 ./usr/lib/libICE.so.6 -> libICE.so.6.3.0
+lrwxrwxrwx root root 15 ./usr/lib/libICE.so -> libICE.so.6.3.0
+-rwxr-xr-x root root 35256 ./usr/lib/libip4tc.so.2.0.0
+lrwxrwxrwx root root 17 ./usr/lib/libip4tc.so.2 -> libip4tc.so.2.0.0
+lrwxrwxrwx root root 17 ./usr/lib/libip4tc.so -> libip4tc.so.2.0.0
+-rwxr-xr-x root root 35256 ./usr/lib/libip6tc.so.2.0.0
+lrwxrwxrwx root root 17 ./usr/lib/libip6tc.so.2 -> libip6tc.so.2.0.0
+lrwxrwxrwx root root 17 ./usr/lib/libip6tc.so -> libip6tc.so.2.0.0
+-rwxr-xr-x root root 83992 ./usr/lib/libkmod.so.2.3.5
+lrwxrwxrwx root root 16 ./usr/lib/libkmod.so.2 -> libkmod.so.2.3.5
+lrwxrwxrwx root root 16 ./usr/lib/libkmod.so -> libkmod.so.2.3.5
+-rwxr-xr-x root root 18240 ./usr/lib/libkms.so.1.0.0
+lrwxrwxrwx root root 15 ./usr/lib/libkms.so.1 -> libkms.so.1.0.0
+lrwxrwxrwx root root 11 ./usr/lib/libkms.so -> libkms.so.1
+-rwxr-xr-x root root 161760 ./usr/lib/liblzma.so.5.2.5
+lrwxrwxrwx root root 16 ./usr/lib/liblzma.so.5 -> liblzma.so.5.2.5
+lrwxrwxrwx root root 16 ./usr/lib/liblzma.so -> liblzma.so.5.2.5
+-rwxr-xr-x root root 141200 ./usr/lib/liblzo2.so.2.0.0
+lrwxrwxrwx root root 16 ./usr/lib/liblzo2.so.2 -> liblzo2.so.2.0.0
+lrwxrwxrwx root root 16 ./usr/lib/liblzo2.so -> liblzo2.so.2.0.0
+-rwxr-xr-x root root 34976 ./usr/lib/libmenu.so.5.9
+lrwxrwxrwx root root 14 ./usr/lib/libmenu.so.5 -> libmenu.so.5.9
+lrwxrwxrwx root root 12 ./usr/lib/libmenu.so -> libmenu.so.5
+-rwxr-xr-x root root 39072 ./usr/lib/libmenuw.so.5.9
+lrwxrwxrwx root root 15 ./usr/lib/libmenuw.so.5 -> libmenuw.so.5.9
+lrwxrwxrwx root root 13 ./usr/lib/libmenuw.so -> libmenuw.so.5
+-rwxr-xr-x root root 26584 ./usr/lib/libmnl.so.0.2.0
+lrwxrwxrwx root root 15 ./usr/lib/libmnl.so.0 -> libmnl.so.0.2.0
+lrwxrwxrwx root root 15 ./usr/lib/libmnl.so -> libmnl.so.0.2.0
+lrwxrwxrwx root root 27 ./usr/lib/libmount.so -> ../../lib/libmount.so.1.1.0
+-rw-r--r-- root root 106 ./usr/lib/libm.so
+lrwxrwxrwx root root 22 ./usr/lib/libmvec.so -> ../../lib/libmvec.so.1
+-rw-r--r-- root root 62 ./usr/lib/libncurses.so
+-rw-r--r-- root root 63 ./usr/lib/libncursesw.so
+-rwxr-xr-x root root 96288 ./usr/lib/libnsl.so.2.0.0
+lrwxrwxrwx root root 15 ./usr/lib/libnsl.so.2 -> libnsl.so.2.0.0
+lrwxrwxrwx root root 15 ./usr/lib/libnsl.so -> libnsl.so.2.0.0
+lrwxrwxrwx root root 28 ./usr/lib/libnss_compat.so -> ../../lib/libnss_compat.so.2
+lrwxrwxrwx root root 24 ./usr/lib/libnss_db.so -> ../../lib/libnss_db.so.2
+lrwxrwxrwx root root 25 ./usr/lib/libnss_dns.so -> ../../lib/libnss_dns.so.2
+lrwxrwxrwx root root 27 ./usr/lib/libnss_files.so -> ../../lib/libnss_files.so.2
+lrwxrwxrwx root root 28 ./usr/lib/libnss_hesiod.so -> ../../lib/libnss_hesiod.so.2
+-rwxr-xr-x root root 1426544 ./usr/lib/libopcodes-2.34.0.20200220.so
+lrwxrwxrwx root root 29 ./usr/lib/libopcodes.so -> libopcodes-2.34.0.20200220.so
+-rwxr-xr-x root root 18168 ./usr/lib/libpanel.so.5.9
+lrwxrwxrwx root root 15 ./usr/lib/libpanel.so.5 -> libpanel.so.5.9
+lrwxrwxrwx root root 13 ./usr/lib/libpanel.so -> libpanel.so.5
+-rwxr-xr-x root root 18168 ./usr/lib/libpanelw.so.5.9
+lrwxrwxrwx root root 16 ./usr/lib/libpanelw.so.5 -> libpanelw.so.5.9
+lrwxrwxrwx root root 14 ./usr/lib/libpanelw.so -> libpanelw.so.5
+-rwxr-xr-x root root 42896 ./usr/lib/libpciaccess.so.0.11.1
+lrwxrwxrwx root root 22 ./usr/lib/libpciaccess.so.0 -> libpciaccess.so.0.11.1
+lrwxrwxrwx root root 22 ./usr/lib/libpciaccess.so -> libpciaccess.so.0.11.1
+-rwxr-xr-x root root 42984 ./usr/lib/libpcrecpp.so.0.0.2
+lrwxrwxrwx root root 19 ./usr/lib/libpcrecpp.so.0 -> libpcrecpp.so.0.0.2
+lrwxrwxrwx root root 19 ./usr/lib/libpcrecpp.so -> libpcrecpp.so.0.0.2
+-rwxr-xr-x root root 14224 ./usr/lib/libpcreposix.so.0.0.7
+lrwxrwxrwx root root 21 ./usr/lib/libpcreposix.so.0 -> libpcreposix.so.0.0.7
+lrwxrwxrwx root root 21 ./usr/lib/libpcreposix.so -> libpcreposix.so.0.0.7
+-rwxr-xr-x root root 489400 ./usr/lib/libpcre.so.1.2.12
+lrwxrwxrwx root root 17 ./usr/lib/libpcre.so.1 -> libpcre.so.1.2.12
+lrwxrwxrwx root root 17 ./usr/lib/libpcre.so -> libpcre.so.1.2.12
+-r-xr-xr-x root root 3351136 ./usr/lib/libperl.so.5.30.0
+lrwxrwxrwx root root 17 ./usr/lib/libperl.so.5 -> libperl.so.5.30.0
+lrwxrwxrwx root root 17 ./usr/lib/libperl.so -> libperl.so.5.30.0
+-rwxr-xr-x root root 694264 ./usr/lib/libpixman-1.so.0.40.0
+lrwxrwxrwx root root 21 ./usr/lib/libpixman-1.so.0 -> libpixman-1.so.0.40.0
+lrwxrwxrwx root root 16 ./usr/lib/libpixman-1.so -> libpixman-1.so.0
+-rwxr-xr-x root root 219024 ./usr/lib/libpng16.so.16.37.0
+lrwxrwxrwx root root 19 ./usr/lib/libpng16.so.16 -> libpng16.so.16.37.0
+lrwxrwxrwx root root 19 ./usr/lib/libpng16.so -> libpng16.so.16.37.0
+lrwxrwxrwx root root 11 ./usr/lib/libpng.so -> libpng16.so
+-rwxr-xr-x root root 79888 ./usr/lib/libprocps.so.8.0.2
+lrwxrwxrwx root root 18 ./usr/lib/libprocps.so.8 -> libprocps.so.8.0.2
+lrwxrwxrwx root root 18 ./usr/lib/libprocps.so -> libprocps.so.8.0.2
+lrwxrwxrwx root root 25 ./usr/lib/libpthread.so -> ../../lib/libpthread.so.0
+-rwxr-xr-x root root 3271808 ./usr/lib/libpython3.8.so.1.0
+lrwxrwxrwx root root 19 ./usr/lib/libpython3.8.so -> libpython3.8.so.1.0
+-rwxr-xr-x root root 13920 ./usr/lib/libpython3.so
+-rwxr-xr-x root root 330696 ./usr/lib/libreadline.so.8.0
+lrwxrwxrwx root root 18 ./usr/lib/libreadline.so.8 -> libreadline.so.8.0
+lrwxrwxrwx root root 18 ./usr/lib/libreadline.so -> libreadline.so.8.0
+lrwxrwxrwx root root 24 ./usr/lib/libresolv.so -> ../../lib/libresolv.so.2
+lrwxrwxrwx root root 20 ./usr/lib/librt.so -> ../../lib/librt.so.1
+lrwxrwxrwx root root 31 ./usr/lib/libsmartcols.so -> ../../lib/libsmartcols.so.1.1.0
+-rwxr-xr-x root root 38736 ./usr/lib/libSM.so.6.0.1
+lrwxrwxrwx root root 14 ./usr/lib/libSM.so.6 -> libSM.so.6.0.1
+lrwxrwxrwx root root 14 ./usr/lib/libSM.so -> libSM.so.6.0.1
+-rwxr-xr-x root root 1244736 ./usr/lib/libsqlite3.so.0.8.6
+lrwxrwxrwx root root 19 ./usr/lib/libsqlite3.so.0 -> libsqlite3.so.0.8.6
+lrwxrwxrwx root root 19 ./usr/lib/libsqlite3.so -> libsqlite3.so.0.8.6
+-rwxr-xr-x root root 593728 ./usr/lib/libssl.so.1.1
+lrwxrwxrwx root root 13 ./usr/lib/libssl.so -> libssl.so.1.1
+-rwxr-xr-x root root 1866240 ./usr/lib/libstdc++.so.6.0.28
+lrwxrwxrwx root root 19 ./usr/lib/libstdc++.so.6 -> libstdc++.so.6.0.28
+lrwxrwxrwx root root 19 ./usr/lib/libstdc++.so -> libstdc++.so.6.0.28
+-rw-r--r-- root root 46 ./usr/lib/libtermcap.so
+lrwxrwxrwx root root 27 ./usr/lib/libthread_db.so -> ../../lib/libthread_db.so.1
+-rwxr-xr-x root root 67472 ./usr/lib/libtic.so.5.9
+lrwxrwxrwx root root 13 ./usr/lib/libtic.so.5 -> libtic.so.5.9
+lrwxrwxrwx root root 11 ./usr/lib/libtic.so -> libtic.so.5
+-rwxr-xr-x root root 67472 ./usr/lib/libticw.so.5.9
+lrwxrwxrwx root root 14 ./usr/lib/libticw.so.5 -> libticw.so.5.9
+lrwxrwxrwx root root 12 ./usr/lib/libticw.so -> libticw.so.5
+lrwxrwxrwx root root 23 ./usr/lib/libtinfo.so -> ../../lib/libtinfo.so.5
+-rwxr-xr-x root root 161888 ./usr/lib/libtirpc.so.3.0.0
+lrwxrwxrwx root root 17 ./usr/lib/libtirpc.so.3 -> libtirpc.so.3.0.0
+lrwxrwxrwx root root 17 ./usr/lib/libtirpc.so -> libtirpc.so.3.0.0
+lrwxrwxrwx root root 26 ./usr/lib/libudev.so -> ../../lib/libudev.so.1.6.3
+lrwxrwxrwx root root 22 ./usr/lib/libutil.so -> ../../lib/libutil.so.1
+lrwxrwxrwx root root 26 ./usr/lib/libuuid.so -> ../../lib/libuuid.so.1.3.0
+-rwxr-xr-x root root 68272 ./usr/lib/libwayland-client.so.0.3.0
+lrwxrwxrwx root root 26 ./usr/lib/libwayland-client.so.0 -> libwayland-client.so.0.3.0
+lrwxrwxrwx root root 22 ./usr/lib/libwayland-client.so -> libwayland-client.so.0
+-rwxr-xr-x root root 30720 ./usr/lib/libwayland-cursor.so.0.0.0
+lrwxrwxrwx root root 26 ./usr/lib/libwayland-cursor.so.0 -> libwayland-cursor.so.0.0.0
+lrwxrwxrwx root root 22 ./usr/lib/libwayland-cursor.so -> libwayland-cursor.so.0
+-rwxr-xr-x root root 14080 ./usr/lib/libwayland-egl.so.1.0.0
+lrwxrwxrwx root root 23 ./usr/lib/libwayland-egl.so.1 -> libwayland-egl.so.1.0.0
+lrwxrwxrwx root root 19 ./usr/lib/libwayland-egl.so -> libwayland-egl.so.1
+-rwxr-xr-x root root 88784 ./usr/lib/libwayland-server.so.0.1.0
+lrwxrwxrwx root root 26 ./usr/lib/libwayland-server.so.0 -> libwayland-server.so.0.1.0
+lrwxrwxrwx root root 22 ./usr/lib/libwayland-server.so -> libwayland-server.so.0
+lrwxrwxrwx root root 26 ./usr/lib/libwrap.so -> ../../lib/libwrap.so.0.7.6
+-rwxr-xr-x root root 1308960 ./usr/lib/libX11.so.6.3.0
+lrwxrwxrwx root root 15 ./usr/lib/libX11.so.6 -> libX11.so.6.3.0
+lrwxrwxrwx root root 15 ./usr/lib/libX11.so -> libX11.so.6.3.0
+-rwxr-xr-x root root 13848 ./usr/lib/libX11-xcb.so.1.0.0
+lrwxrwxrwx root root 19 ./usr/lib/libX11-xcb.so.1 -> libX11-xcb.so.1.0.0
+lrwxrwxrwx root root 19 ./usr/lib/libX11-xcb.so -> libX11-xcb.so.1.0.0
+-rwxr-xr-x root root 14144 ./usr/lib/libXau.so.6.0.0
+lrwxrwxrwx root root 15 ./usr/lib/libXau.so.6 -> libXau.so.6.0.0
+lrwxrwxrwx root root 15 ./usr/lib/libXau.so -> libXau.so.6.0.0
+-rwxr-xr-x root root 14256 ./usr/lib/libxcb-composite.so.0.0.0
+lrwxrwxrwx root root 25 ./usr/lib/libxcb-composite.so.0 -> libxcb-composite.so.0.0.0
+lrwxrwxrwx root root 25 ./usr/lib/libxcb-composite.so -> libxcb-composite.so.0.0.0
+-rwxr-xr-x root root 14248 ./usr/lib/libxcb-damage.so.0.0.0
+lrwxrwxrwx root root 22 ./usr/lib/libxcb-damage.so.0 -> libxcb-damage.so.0.0.0
+lrwxrwxrwx root root 22 ./usr/lib/libxcb-damage.so -> libxcb-damage.so.0.0.0
+-rwxr-xr-x root root 14248 ./usr/lib/libxcb-dpms.so.0.0.0
+lrwxrwxrwx root root 20 ./usr/lib/libxcb-dpms.so.0 -> libxcb-dpms.so.0.0.0
+lrwxrwxrwx root root 20 ./usr/lib/libxcb-dpms.so -> libxcb-dpms.so.0.0.0
+-rwxr-xr-x root root 22440 ./usr/lib/libxcb-dri2.so.0.0.0
+lrwxrwxrwx root root 20 ./usr/lib/libxcb-dri2.so.0 -> libxcb-dri2.so.0.0.0
+lrwxrwxrwx root root 20 ./usr/lib/libxcb-dri2.so -> libxcb-dri2.so.0.0.0
+-rwxr-xr-x root root 18344 ./usr/lib/libxcb-dri3.so.0.0.0
+lrwxrwxrwx root root 20 ./usr/lib/libxcb-dri3.so.0 -> libxcb-dri3.so.0.0.0
+lrwxrwxrwx root root 20 ./usr/lib/libxcb-dri3.so -> libxcb-dri3.so.0.0.0
+-rwxr-xr-x root root 116648 ./usr/lib/libxcb-glx.so.0.0.0
+lrwxrwxrwx root root 19 ./usr/lib/libxcb-glx.so.0 -> libxcb-glx.so.0.0.0
+lrwxrwxrwx root root 19 ./usr/lib/libxcb-glx.so -> libxcb-glx.so.0.0.0
+-rwxr-xr-x root root 14248 ./usr/lib/libxcb-present.so.0.0.0
+lrwxrwxrwx root root 23 ./usr/lib/libxcb-present.so.0 -> libxcb-present.so.0.0.0
+lrwxrwxrwx root root 23 ./usr/lib/libxcb-present.so -> libxcb-present.so.0.0.0
+-rwxr-xr-x root root 67496 ./usr/lib/libxcb-randr.so.0.1.0
+lrwxrwxrwx root root 21 ./usr/lib/libxcb-randr.so.0 -> libxcb-randr.so.0.1.0
+lrwxrwxrwx root root 21 ./usr/lib/libxcb-randr.so -> libxcb-randr.so.0.1.0
+-rwxr-xr-x root root 18344 ./usr/lib/libxcb-record.so.0.0.0
+lrwxrwxrwx root root 22 ./usr/lib/libxcb-record.so.0 -> libxcb-record.so.0.0.0
+lrwxrwxrwx root root 22 ./usr/lib/libxcb-record.so -> libxcb-record.so.0.0.0
+-rwxr-xr-x root root 59304 ./usr/lib/libxcb-render.so.0.0.0
+lrwxrwxrwx root root 22 ./usr/lib/libxcb-render.so.0 -> libxcb-render.so.0.0.0
+lrwxrwxrwx root root 22 ./usr/lib/libxcb-render.so -> libxcb-render.so.0.0.0
+-rwxr-xr-x root root 18344 ./usr/lib/libxcb-res.so.0.0.0
+lrwxrwxrwx root root 19 ./usr/lib/libxcb-res.so.0 -> libxcb-res.so.0.0.0
+lrwxrwxrwx root root 19 ./usr/lib/libxcb-res.so -> libxcb-res.so.0.0.0
+-rwxr-xr-x root root 14256 ./usr/lib/libxcb-screensaver.so.0.0.0
+lrwxrwxrwx root root 27 ./usr/lib/libxcb-screensaver.so.0 -> libxcb-screensaver.so.0.0.0
+lrwxrwxrwx root root 27 ./usr/lib/libxcb-screensaver.so -> libxcb-screensaver.so.0.0.0
+-rwxr-xr-x root root 14248 ./usr/lib/libxcb-shape.so.0.0.0
+lrwxrwxrwx root root 21 ./usr/lib/libxcb-shape.so.0 -> libxcb-shape.so.0.0.0
+lrwxrwxrwx root root 21 ./usr/lib/libxcb-shape.so -> libxcb-shape.so.0.0.0
+-rwxr-xr-x root root 14248 ./usr/lib/libxcb-shm.so.0.0.0
+lrwxrwxrwx root root 19 ./usr/lib/libxcb-shm.so.0 -> libxcb-shm.so.0.0.0
+lrwxrwxrwx root root 19 ./usr/lib/libxcb-shm.so -> libxcb-shm.so.0.0.0
+-rwxr-xr-x root root 169920 ./usr/lib/libxcb.so.1.1.0
+lrwxrwxrwx root root 15 ./usr/lib/libxcb.so.1 -> libxcb.so.1.1.0
+lrwxrwxrwx root root 15 ./usr/lib/libxcb.so -> libxcb.so.1.1.0
+-rwxr-xr-x root root 34728 ./usr/lib/libxcb-sync.so.1.0.0
+lrwxrwxrwx root root 20 ./usr/lib/libxcb-sync.so.1 -> libxcb-sync.so.1.0.0
+lrwxrwxrwx root root 20 ./usr/lib/libxcb-sync.so -> libxcb-sync.so.1.0.0
+-rwxr-xr-x root root 18344 ./usr/lib/libxcb-xf86dri.so.0.0.0
+lrwxrwxrwx root root 23 ./usr/lib/libxcb-xf86dri.so.0 -> libxcb-xf86dri.so.0.0.0
+lrwxrwxrwx root root 23 ./usr/lib/libxcb-xf86dri.so -> libxcb-xf86dri.so.0.0.0
+-rwxr-xr-x root root 34728 ./usr/lib/libxcb-xfixes.so.0.0.0
+lrwxrwxrwx root root 22 ./usr/lib/libxcb-xfixes.so.0 -> libxcb-xfixes.so.0.0.0
+lrwxrwxrwx root root 22 ./usr/lib/libxcb-xfixes.so -> libxcb-xfixes.so.0.0.0
+-rwxr-xr-x root root 14256 ./usr/lib/libxcb-xinerama.so.0.0.0
+lrwxrwxrwx root root 24 ./usr/lib/libxcb-xinerama.so.0 -> libxcb-xinerama.so.0.0.0
+lrwxrwxrwx root root 24 ./usr/lib/libxcb-xinerama.so -> libxcb-xinerama.so.0.0.0
+-rwxr-xr-x root root 149416 ./usr/lib/libxcb-xinput.so.0.1.0
+lrwxrwxrwx root root 22 ./usr/lib/libxcb-xinput.so.0 -> libxcb-xinput.so.0.1.0
+lrwxrwxrwx root root 22 ./usr/lib/libxcb-xinput.so -> libxcb-xinput.so.0.1.0
+-rwxr-xr-x root root 120744 ./usr/lib/libxcb-xkb.so.1.0.0
+lrwxrwxrwx root root 19 ./usr/lib/libxcb-xkb.so.1 -> libxcb-xkb.so.1.0.0
+lrwxrwxrwx root root 19 ./usr/lib/libxcb-xkb.so -> libxcb-xkb.so.1.0.0
+-rwxr-xr-x root root 14248 ./usr/lib/libxcb-xtest.so.0.0.0
+lrwxrwxrwx root root 21 ./usr/lib/libxcb-xtest.so.0 -> libxcb-xtest.so.0.0.0
+lrwxrwxrwx root root 21 ./usr/lib/libxcb-xtest.so -> libxcb-xtest.so.0.0.0
+-rwxr-xr-x root root 18344 ./usr/lib/libxcb-xvmc.so.0.0.0
+lrwxrwxrwx root root 20 ./usr/lib/libxcb-xvmc.so.0 -> libxcb-xvmc.so.0.0.0
+lrwxrwxrwx root root 20 ./usr/lib/libxcb-xvmc.so -> libxcb-xvmc.so.0.0.0
+-rwxr-xr-x root root 34728 ./usr/lib/libxcb-xv.so.0.0.0
+lrwxrwxrwx root root 18 ./usr/lib/libxcb-xv.so.0 -> libxcb-xv.so.0.0.0
+lrwxrwxrwx root root 18 ./usr/lib/libxcb-xv.so -> libxcb-xv.so.0.0.0
+-rwxr-xr-x root root 14144 ./usr/lib/libXdamage.so.1.1.0
+lrwxrwxrwx root root 19 ./usr/lib/libXdamage.so.1 -> libXdamage.so.1.1.0
+lrwxrwxrwx root root 19 ./usr/lib/libXdamage.so -> libXdamage.so.1.1.0
+-rwxr-xr-x root root 26432 ./usr/lib/libXdmcp.so.6.0.0
+lrwxrwxrwx root root 17 ./usr/lib/libXdmcp.so.6 -> libXdmcp.so.6.0.0
+lrwxrwxrwx root root 17 ./usr/lib/libXdmcp.so -> libXdmcp.so.6.0.0
+-rwxr-xr-x root root 80992 ./usr/lib/libXext.so.6.4.0
+lrwxrwxrwx root root 16 ./usr/lib/libXext.so.6 -> libXext.so.6.4.0
+lrwxrwxrwx root root 16 ./usr/lib/libXext.so -> libXext.so.6.4.0
+-rwxr-xr-x root root 30464 ./usr/lib/libXfixes.so.3.1.0
+lrwxrwxrwx root root 18 ./usr/lib/libXfixes.so.3 -> libXfixes.so.3.1.0
+lrwxrwxrwx root root 18 ./usr/lib/libXfixes.so -> libXfixes.so.3.1.0
+-rwxr-xr-x root root 1409880 ./usr/lib/libxml2.so.2.9.10
+lrwxrwxrwx root root 17 ./usr/lib/libxml2.so.2 -> libxml2.so.2.9.10
+lrwxrwxrwx root root 17 ./usr/lib/libxml2.so -> libxml2.so.2.9.10
+-rwxr-xr-x root root 47024 ./usr/lib/libXrandr.so.2.2.0
+lrwxrwxrwx root root 18 ./usr/lib/libXrandr.so.2 -> libXrandr.so.2.2.0
+lrwxrwxrwx root root 18 ./usr/lib/libXrandr.so -> libXrandr.so.2.2.0
+-rwxr-xr-x root root 47184 ./usr/lib/libXrender.so.1.3.0
+lrwxrwxrwx root root 19 ./usr/lib/libXrender.so.1 -> libXrender.so.1.3.0
+lrwxrwxrwx root root 19 ./usr/lib/libXrender.so -> libXrender.so.1.3.0
+-rwxr-xr-x root root 14152 ./usr/lib/libxshmfence.so.1.0.0
+lrwxrwxrwx root root 21 ./usr/lib/libxshmfence.so.1 -> libxshmfence.so.1.0.0
+lrwxrwxrwx root root 21 ./usr/lib/libxshmfence.so -> libxshmfence.so.1.0.0
+-rwxr-xr-x root root 63384 ./usr/lib/libxtables.so.12.2.0
+lrwxrwxrwx root root 20 ./usr/lib/libxtables.so.12 -> libxtables.so.12.2.0
+lrwxrwxrwx root root 20 ./usr/lib/libxtables.so -> libxtables.so.12.2.0
+-rwxr-xr-x root root 22456 ./usr/lib/libXxf86vm.so.1.0.0
+lrwxrwxrwx root root 19 ./usr/lib/libXxf86vm.so.1 -> libXxf86vm.so.1.0.0
+lrwxrwxrwx root root 19 ./usr/lib/libXxf86vm.so -> libXxf86vm.so.1.0.0
+lrwxrwxrwx root root 24 ./usr/lib/libz.so -> ../../lib/libz.so.1.2.11
+-rw-r--r-- root root 1368 ./usr/lib/Mcrt1.o
+drwxr-xr-x root root 4096 ./usr/lib/opkg
+drwxr-xr-x root root 12288 ./usr/lib/opkg/alternatives
+-rw-r--r-- root root 35 ./usr/lib/opkg/alternatives/[[
+-rw-r--r-- root root 42 ./usr/lib/opkg/alternatives/addgroup
+-rw-r--r-- root root 60 ./usr/lib/opkg/alternatives/addr2line
+-rw-r--r-- root root 41 ./usr/lib/opkg/alternatives/adduser
+-rw-r--r-- root root 46 ./usr/lib/opkg/alternatives/ar
+-rw-r--r-- root root 42 ./usr/lib/opkg/alternatives/arch
+-rw-r--r-- root root 46 ./usr/lib/opkg/alternatives/as
+-rw-r--r-- root root 32 ./usr/lib/opkg/alternatives/ash
+-rw-r--r-- root root 54 ./usr/lib/opkg/alternatives/awk
+-rw-r--r-- root root 42 ./usr/lib/opkg/alternatives/base64
+-rw-r--r-- root root 73 ./usr/lib/opkg/alternatives/basename
+-rw-r--r-- root root 29 ./usr/lib/opkg/alternatives/bash
+-rw-r--r-- root root 31 ./usr/lib/opkg/alternatives/bc
+-rw-r--r-- root root 30 ./usr/lib/opkg/alternatives/bin-lsmod
+-rw-r--r-- root root 61 ./usr/lib/opkg/alternatives/blkid
+-rw-r--r-- root root 44 ./usr/lib/opkg/alternatives/blockdev
+-rw-r--r-- root root 67 ./usr/lib/opkg/alternatives/bunzip2
+-rw-r--r-- root root 63 ./usr/lib/opkg/alternatives/bzcat
+-rw-r--r-- root root 63 ./usr/lib/opkg/alternatives/bzip2
+-rw-r--r-- root root 40 ./usr/lib/opkg/alternatives/cal
+-rw-r--r-- root root 55 ./usr/lib/opkg/alternatives/cat
+-rw-r--r-- root root 56 ./usr/lib/opkg/alternatives/c++filt
+-rw-r--r-- root root 61 ./usr/lib/opkg/alternatives/chattr
+-rw-r--r-- root root 44 ./usr/lib/opkg/alternatives/chcon
+-rw-r--r-- root root 39 ./usr/lib/opkg/alternatives/chfn
+-rw-r--r-- root root 59 ./usr/lib/opkg/alternatives/chgrp
+-rw-r--r-- root root 59 ./usr/lib/opkg/alternatives/chmod
+-rw-r--r-- root root 59 ./usr/lib/opkg/alternatives/chown
+-rw-r--r-- root root 49 ./usr/lib/opkg/alternatives/chpasswd
+-rw-r--r-- root root 71 ./usr/lib/opkg/alternatives/chroot
+-rw-r--r-- root root 42 ./usr/lib/opkg/alternatives/chrt
+-rw-r--r-- root root 39 ./usr/lib/opkg/alternatives/chsh
+-rw-r--r-- root root 37 ./usr/lib/opkg/alternatives/chvt
+-rw-r--r-- root root 44 ./usr/lib/opkg/alternatives/cksum
+-rw-r--r-- root root 38 ./usr/lib/opkg/alternatives/clear
+-rw-r--r-- root root 63 ./usr/lib/opkg/alternatives/cmp
+-rw-r--r-- root root 42 ./usr/lib/opkg/alternatives/comm
+-rw-r--r-- root root 53 ./usr/lib/opkg/alternatives/cp
+-rw-r--r-- root root 33 ./usr/lib/opkg/alternatives/cpio
+-rw-r--r-- root root 46 ./usr/lib/opkg/alternatives/csplit
+-rw-r--r-- root root 63 ./usr/lib/opkg/alternatives/cut
+-rw-r--r-- root root 57 ./usr/lib/opkg/alternatives/date
+-rw-r--r-- root root 54 ./usr/lib/opkg/alternatives/dc
+-rw-r--r-- root root 53 ./usr/lib/opkg/alternatives/dd
+-rw-r--r-- root root 42 ./usr/lib/opkg/alternatives/deallocvt
+-rw-r--r-- root root 42 ./usr/lib/opkg/alternatives/delgroup
+-rw-r--r-- root root 41 ./usr/lib/opkg/alternatives/deluser
+-rw-r--r-- root root 57 ./usr/lib/opkg/alternatives/depmod
+-rw-r--r-- root root 57 ./usr/lib/opkg/alternatives/df
+-rw-r--r-- root root 65 ./usr/lib/opkg/alternatives/diff
+-rw-r--r-- root root 40 ./usr/lib/opkg/alternatives/dir
+-rw-r--r-- root root 52 ./usr/lib/opkg/alternatives/dircolors
+-rw-r--r-- root root 71 ./usr/lib/opkg/alternatives/dirname
+-rw-r--r-- root root 59 ./usr/lib/opkg/alternatives/dmesg
+-rw-r--r-- root root 42 ./usr/lib/opkg/alternatives/dnsdomainname
+-rw-r--r-- root root 61 ./usr/lib/opkg/alternatives/du
+-rw-r--r-- root root 37 ./usr/lib/opkg/alternatives/dumpkmap
+-rw-r--r-- root root 43 ./usr/lib/opkg/alternatives/dumpleases
+-rw-r--r-- root root 48 ./usr/lib/opkg/alternatives/dwp
+-rw-r--r-- root root 57 ./usr/lib/opkg/alternatives/echo
+-rw-r--r-- root root 54 ./usr/lib/opkg/alternatives/egrep
+-rw-r--r-- root root 44 ./usr/lib/opkg/alternatives/eject
+-rw-r--r-- root root 56 ./usr/lib/opkg/alternatives/elfedit
+-rw-r--r-- root root 63 ./usr/lib/opkg/alternatives/env
+-rw-r--r-- root root 46 ./usr/lib/opkg/alternatives/expand
+-rw-r--r-- root root 65 ./usr/lib/opkg/alternatives/expr
+-rw-r--r-- root root 46 ./usr/lib/opkg/alternatives/factor
+-rw-r--r-- root root 52 ./usr/lib/opkg/alternatives/fallocate
+-rw-r--r-- root root 59 ./usr/lib/opkg/alternatives/false
+-rw-r--r-- root root 39 ./usr/lib/opkg/alternatives/fbset
+-rw-r--r-- root root 61 ./usr/lib/opkg/alternatives/fdisk
+-rw-r--r-- root root 54 ./usr/lib/opkg/alternatives/fgrep
+-rw-r--r-- root root 65 ./usr/lib/opkg/alternatives/find
+-rw-r--r-- root root 67 ./usr/lib/opkg/alternatives/flock
+-rw-r--r-- root root 40 ./usr/lib/opkg/alternatives/fmt
+-rw-r--r-- root root 42 ./usr/lib/opkg/alternatives/fold
+-rw-r--r-- root root 62 ./usr/lib/opkg/alternatives/free
+-rw-r--r-- root root 59 ./usr/lib/opkg/alternatives/fsck
+-rw-r--r-- root root 52 ./usr/lib/opkg/alternatives/fsfreeze
+-rw-r--r-- root root 63 ./usr/lib/opkg/alternatives/fstrim
+-rw-r--r-- root root 38 ./usr/lib/opkg/alternatives/fuser
+-rw-r--r-- root root 61 ./usr/lib/opkg/alternatives/getopt
+-rw-r--r-- root root 51 ./usr/lib/opkg/alternatives/getty
+-rw-r--r-- root root 52 ./usr/lib/opkg/alternatives/gprof
+-rw-r--r-- root root 52 ./usr/lib/opkg/alternatives/grep
+-rw-r--r-- root root 96 ./usr/lib/opkg/alternatives/groups
+-rw-r--r-- root root 35 ./usr/lib/opkg/alternatives/gunzip
+-rw-r--r-- root root 33 ./usr/lib/opkg/alternatives/gzip
+-rw-r--r-- root root 35 ./usr/lib/opkg/alternatives/halt
+-rw-r--r-- root root 65 ./usr/lib/opkg/alternatives/head
+-rw-r--r-- root root 71 ./usr/lib/opkg/alternatives/hexdump
+-rw-r--r-- root root 46 ./usr/lib/opkg/alternatives/hostid
+-rw-r--r-- root root 64 ./usr/lib/opkg/alternatives/hostname
+-rw-r--r-- root root 65 ./usr/lib/opkg/alternatives/hwclock
+-rw-r--r-- root root 61 ./usr/lib/opkg/alternatives/id
+-rw-r--r-- root root 38 ./usr/lib/opkg/alternatives/ifconfig
+-rw-r--r-- root root 36 ./usr/lib/opkg/alternatives/ifdown
+-rw-r--r-- root root 34 ./usr/lib/opkg/alternatives/ifup
+-rw-r--r-- root root 34 ./usr/lib/opkg/alternatives/init
+-rw-r--r-- root root 57 ./usr/lib/opkg/alternatives/insmod
+-rw-r--r-- root root 48 ./usr/lib/opkg/alternatives/install
+-rw-r--r-- root root 46 ./usr/lib/opkg/alternatives/ionice
+-rw-r--r-- root root 54 ./usr/lib/opkg/alternatives/ip
+-rw-r--r-- root root 42 ./usr/lib/opkg/alternatives/join
+-rw-r--r-- root root 102 ./usr/lib/opkg/alternatives/kill
+-rw-r--r-- root root 40 ./usr/lib/opkg/alternatives/killall
+-rw-r--r-- root root 35 ./usr/lib/opkg/alternatives/klogd
+-rw-r--r-- root root 69 ./usr/lib/opkg/alternatives/last
+-rw-r--r-- root root 72 ./usr/lib/opkg/alternatives/lastb
+-rw-r--r-- root root 66 ./usr/lib/opkg/alternatives/lbracket
+-rw-r--r-- root root 46 ./usr/lib/opkg/alternatives/ld
+-rw-r--r-- root root 54 ./usr/lib/opkg/alternatives/ld.bfd
+-rw-r--r-- root root 56 ./usr/lib/opkg/alternatives/ld.gold
+-rw-r--r-- root root 37 ./usr/lib/opkg/alternatives/less
+-rw-r--r-- root root 42 ./usr/lib/opkg/alternatives/link
+-rw-r--r-- root root 53 ./usr/lib/opkg/alternatives/ln
+-rw-r--r-- root root 42 ./usr/lib/opkg/alternatives/loadfont
+-rw-r--r-- root root 38 ./usr/lib/opkg/alternatives/loadkmap
+-rw-r--r-- root root 69 ./usr/lib/opkg/alternatives/logger
+-rw-r--r-- root root 54 ./usr/lib/opkg/alternatives/login
+-rw-r--r-- root root 71 ./usr/lib/opkg/alternatives/logname
+-rw-r--r-- root root 37 ./usr/lib/opkg/alternatives/logread
+-rw-r--r-- root root 65 ./usr/lib/opkg/alternatives/losetup
+-rw-r--r-- root root 53 ./usr/lib/opkg/alternatives/ls
+-rw-r--r-- root root 54 ./usr/lib/opkg/alternatives/lsmod
+-rw-r--r-- root root 60 ./usr/lib/opkg/alternatives/lzcat
+-rw-r--r-- root root 35 ./usr/lib/opkg/alternatives/lzma
+-rw-r--r-- root root 69 ./usr/lib/opkg/alternatives/md5sum
+-rw-r--r-- root root 92 ./usr/lib/opkg/alternatives/mesg
+-rw-r--r-- root root 41 ./usr/lib/opkg/alternatives/microcom
+-rw-r--r-- root root 59 ./usr/lib/opkg/alternatives/mkdir
+-rw-r--r-- root root 40 ./usr/lib/opkg/alternatives/mke2fs
+-rw-r--r-- root root 69 ./usr/lib/opkg/alternatives/mkfifo
+-rw-r--r-- root root 46 ./usr/lib/opkg/alternatives/mkfs.ext2
+-rw-r--r-- root root 59 ./usr/lib/opkg/alternatives/mknod
+-rw-r--r-- root root 63 ./usr/lib/opkg/alternatives/mkswap
+-rw-r--r-- root root 65 ./usr/lib/opkg/alternatives/mktemp
+-rw-r--r-- root root 36 ./usr/lib/opkg/alternatives/modinfo
+-rw-r--r-- root root 61 ./usr/lib/opkg/alternatives/modprobe
+-rw-r--r-- root root 57 ./usr/lib/opkg/alternatives/more
+-rw-r--r-- root root 59 ./usr/lib/opkg/alternatives/mount
+-rw-r--r-- root root 97 ./usr/lib/opkg/alternatives/mountpoint
+-rw-r--r-- root root 53 ./usr/lib/opkg/alternatives/mv
+-rw-r--r-- root root 35 ./usr/lib/opkg/alternatives/nc
+-rw-r--r-- root root 36 ./usr/lib/opkg/alternatives/netstat
+-rw-r--r-- root root 43 ./usr/lib/opkg/alternatives/newgrp
+-rw-r--r-- root root 38 ./usr/lib/opkg/alternatives/nice
+-rw-r--r-- root root 38 ./usr/lib/opkg/alternatives/nl
+-rw-r--r-- root root 46 ./usr/lib/opkg/alternatives/nm
+-rw-r--r-- root root 67 ./usr/lib/opkg/alternatives/nohup
+-rw-r--r-- root root 67 ./usr/lib/opkg/alternatives/nologin
+-rw-r--r-- root root 67 ./usr/lib/opkg/alternatives/nproc
+-rw-r--r-- root root 48 ./usr/lib/opkg/alternatives/nsenter
+-rw-r--r-- root root 41 ./usr/lib/opkg/alternatives/nslookup
+-rw-r--r-- root root 56 ./usr/lib/opkg/alternatives/objcopy
+-rw-r--r-- root root 56 ./usr/lib/opkg/alternatives/objdump
+-rw-r--r-- root root 61 ./usr/lib/opkg/alternatives/od
+-rw-r--r-- root root 39 ./usr/lib/opkg/alternatives/openvt
+-rw-r--r-- root root 64 ./usr/lib/opkg/alternatives/passwd
+-rw-r--r-- root root 44 ./usr/lib/opkg/alternatives/paste
+-rw-r--r-- root root 38 ./usr/lib/opkg/alternatives/patch
+-rw-r--r-- root root 48 ./usr/lib/opkg/alternatives/pathchk
+-rw-r--r-- root root 41 ./usr/lib/opkg/alternatives/pgrep
+-rw-r--r-- root root 80 ./usr/lib/opkg/alternatives/pidof
+-rw-r--r-- root root 31 ./usr/lib/opkg/alternatives/ping
+-rw-r--r-- root root 32 ./usr/lib/opkg/alternatives/ping6
+-rw-r--r-- root root 44 ./usr/lib/opkg/alternatives/pinky
+-rw-r--r-- root root 71 ./usr/lib/opkg/alternatives/pivot_root
+-rw-r--r-- root root 41 ./usr/lib/opkg/alternatives/pkill
+-rw-r--r-- root root 39 ./usr/lib/opkg/alternatives/pmap
+-rw-r--r-- root root 43 ./usr/lib/opkg/alternatives/poweroff
+-rw-r--r-- root root 38 ./usr/lib/opkg/alternatives/pr
+-rw-r--r-- root root 46 ./usr/lib/opkg/alternatives/printenv
+-rw-r--r-- root root 69 ./usr/lib/opkg/alternatives/printf
+-rw-r--r-- root root 50 ./usr/lib/opkg/alternatives/ps
+-rw-r--r-- root root 40 ./usr/lib/opkg/alternatives/ptx
+-rw-r--r-- root root 55 ./usr/lib/opkg/alternatives/pwd
+-rw-r--r-- root root 39 ./usr/lib/opkg/alternatives/pwdx
+-rw-r--r-- root root 59 ./usr/lib/opkg/alternatives/python3-config
+-rw-r--r-- root root 54 ./usr/lib/opkg/alternatives/ranlib
+-rw-r--r-- root root 39 ./usr/lib/opkg/alternatives/rdate
+-rw-r--r-- root root 56 ./usr/lib/opkg/alternatives/readelf
+-rw-r--r-- root root 73 ./usr/lib/opkg/alternatives/readlink
+-rw-r--r-- root root 58 ./usr/lib/opkg/alternatives/readprofile
+-rw-r--r-- root root 73 ./usr/lib/opkg/alternatives/realpath
+-rw-r--r-- root root 62 ./usr/lib/opkg/alternatives/reboot
+-rw-r--r-- root root 69 ./usr/lib/opkg/alternatives/renice
+-rw-r--r-- root root 38 ./usr/lib/opkg/alternatives/reset
+-rw-r--r-- root root 39 ./usr/lib/opkg/alternatives/resize
+-rw-r--r-- root root 40 ./usr/lib/opkg/alternatives/rev
+-rw-r--r-- root root 71 ./usr/lib/opkg/alternatives/rfkill
+-rw-r--r-- root root 53 ./usr/lib/opkg/alternatives/rm
+-rw-r--r-- root root 59 ./usr/lib/opkg/alternatives/rmdir
+-rw-r--r-- root root 55 ./usr/lib/opkg/alternatives/rmmod
+-rw-r--r-- root root 35 ./usr/lib/opkg/alternatives/route
+-rw-r--r-- root root 50 ./usr/lib/opkg/alternatives/rtcwake
+-rw-r--r-- root root 46 ./usr/lib/opkg/alternatives/runcon
+-rw-r--r-- root root 43 ./usr/lib/opkg/alternatives/runlevel
+-rw-r--r-- root root 38 ./usr/lib/opkg/alternatives/run-parts
+-rw-r--r-- root root 49 ./usr/lib/opkg/alternatives/sed
+-rw-r--r-- root root 63 ./usr/lib/opkg/alternatives/seq
+-rw-r--r-- root root 40 ./usr/lib/opkg/alternatives/setconsole
+-rw-r--r-- root root 45 ./usr/lib/opkg/alternatives/setfattr
+-rw-r--r-- root root 48 ./usr/lib/opkg/alternatives/setpriv
+-rw-r--r-- root root 69 ./usr/lib/opkg/alternatives/setsid
+-rw-r--r-- root root 50 ./usr/lib/opkg/alternatives/sh
+-rw-r--r-- root root 71 ./usr/lib/opkg/alternatives/sha1sum
+-rw-r--r-- root root 52 ./usr/lib/opkg/alternatives/sha224sum
+-rw-r--r-- root root 75 ./usr/lib/opkg/alternatives/sha256sum
+-rw-r--r-- root root 52 ./usr/lib/opkg/alternatives/sha384sum
+-rw-r--r-- root root 52 ./usr/lib/opkg/alternatives/sha512sum
+-rw-r--r-- root root 44 ./usr/lib/opkg/alternatives/shred
+-rw-r--r-- root root 65 ./usr/lib/opkg/alternatives/shuf
+-rw-r--r-- root root 43 ./usr/lib/opkg/alternatives/shutdown
+-rw-r--r-- root root 50 ./usr/lib/opkg/alternatives/size
+-rw-r--r-- root root 41 ./usr/lib/opkg/alternatives/skill
+-rw-r--r-- root root 59 ./usr/lib/opkg/alternatives/sleep
+-rw-r--r-- root root 41 ./usr/lib/opkg/alternatives/snice
+-rw-r--r-- root root 65 ./usr/lib/opkg/alternatives/sort
+-rw-r--r-- root root 44 ./usr/lib/opkg/alternatives/split
+-rw-r--r-- root root 47 ./usr/lib/opkg/alternatives/start-stop-daemon
+-rw-r--r-- root root 57 ./usr/lib/opkg/alternatives/stat
+-rw-r--r-- root root 79 ./usr/lib/opkg/alternatives/strings
+-rw-r--r-- root root 52 ./usr/lib/opkg/alternatives/strip
+-rw-r--r-- root root 57 ./usr/lib/opkg/alternatives/stty
+-rw-r--r-- root root 48 ./usr/lib/opkg/alternatives/su
+-rw-r--r-- root root 65 ./usr/lib/opkg/alternatives/sulogin
+-rw-r--r-- root root 40 ./usr/lib/opkg/alternatives/sum
+-rw-r--r-- root root 65 ./usr/lib/opkg/alternatives/swapoff
+-rw-r--r-- root root 63 ./usr/lib/opkg/alternatives/swapon
+-rw-r--r-- root root 73 ./usr/lib/opkg/alternatives/switch_root
+-rw-r--r-- root root 57 ./usr/lib/opkg/alternatives/sync
+-rw-r--r-- root root 60 ./usr/lib/opkg/alternatives/sysctl
+-rw-r--r-- root root 37 ./usr/lib/opkg/alternatives/syslogd
+-rw-r--r-- root root 40 ./usr/lib/opkg/alternatives/tac
+-rw-r--r-- root root 65 ./usr/lib/opkg/alternatives/tail
+-rw-r--r-- root root 32 ./usr/lib/opkg/alternatives/tar
+-rw-r--r-- root root 48 ./usr/lib/opkg/alternatives/taskset
+-rw-r--r-- root root 63 ./usr/lib/opkg/alternatives/tee
+-rw-r--r-- root root 39 ./usr/lib/opkg/alternatives/telnet
+-rw-r--r-- root root 65 ./usr/lib/opkg/alternatives/test
+-rw-r--r-- root root 37 ./usr/lib/opkg/alternatives/tftp
+-rw-r--r-- root root 37 ./usr/lib/opkg/alternatives/time
+-rw-r--r-- root root 48 ./usr/lib/opkg/alternatives/timeout
+-rw-r--r-- root root 60 ./usr/lib/opkg/alternatives/top
+-rw-r--r-- root root 59 ./usr/lib/opkg/alternatives/touch
+-rw-r--r-- root root 61 ./usr/lib/opkg/alternatives/tr
+-rw-r--r-- root root 41 ./usr/lib/opkg/alternatives/traceroute
+-rw-r--r-- root root 57 ./usr/lib/opkg/alternatives/true
+-rw-r--r-- root root 50 ./usr/lib/opkg/alternatives/truncate
+-rw-r--r-- root root 35 ./usr/lib/opkg/alternatives/ts
+-rw-r--r-- root root 44 ./usr/lib/opkg/alternatives/tsort
+-rw-r--r-- root root 63 ./usr/lib/opkg/alternatives/tty
+-rw-r--r-- root root 36 ./usr/lib/opkg/alternatives/udhcpc
+-rw-r--r-- root root 40 ./usr/lib/opkg/alternatives/udhcpd
+-rw-r--r-- root root 61 ./usr/lib/opkg/alternatives/umount
+-rw-r--r-- root root 59 ./usr/lib/opkg/alternatives/uname
+-rw-r--r-- root root 50 ./usr/lib/opkg/alternatives/unexpand
+-rw-r--r-- root root 65 ./usr/lib/opkg/alternatives/uniq
+-rw-r--r-- root root 69 ./usr/lib/opkg/alternatives/unlink
+-rw-r--r-- root root 39 ./usr/lib/opkg/alternatives/unlzma
+-rw-r--r-- root root 48 ./usr/lib/opkg/alternatives/unshare
+-rw-r--r-- root root 35 ./usr/lib/opkg/alternatives/unxz
+-rw-r--r-- root root 63 ./usr/lib/opkg/alternatives/unzip
+-rw-r--r-- root root 96 ./usr/lib/opkg/alternatives/uptime
+-rw-r--r-- root root 67 ./usr/lib/opkg/alternatives/users
+-rw-r--r-- root root 35 ./usr/lib/opkg/alternatives/usleep
+-rw-r--r-- root root 81 ./usr/lib/opkg/alternatives/utmpdump
+-rw-r--r-- root root 42 ./usr/lib/opkg/alternatives/vdir
+-rw-r--r-- root root 31 ./usr/lib/opkg/alternatives/vi
+-rw-r--r-- root root 33 ./usr/lib/opkg/alternatives/vigr
+-rw-r--r-- root root 33 ./usr/lib/opkg/alternatives/vipw
+-rw-r--r-- root root 36 ./usr/lib/opkg/alternatives/vlock
+-rw-r--r-- root root 33 ./usr/lib/opkg/alternatives/w
+-rw-r--r-- root root 69 ./usr/lib/opkg/alternatives/wall
+-rw-r--r-- root root 56 ./usr/lib/opkg/alternatives/watch
+-rw-r--r-- root root 61 ./usr/lib/opkg/alternatives/wc
+-rw-r--r-- root root 37 ./usr/lib/opkg/alternatives/wget
+-rw-r--r-- root root 63 ./usr/lib/opkg/alternatives/which
+-rw-r--r-- root root 63 ./usr/lib/opkg/alternatives/who
+-rw-r--r-- root root 69 ./usr/lib/opkg/alternatives/whoami
+-rw-r--r-- root root 67 ./usr/lib/opkg/alternatives/xargs
+-rw-r--r-- root root 31 ./usr/lib/opkg/alternatives/xz
+-rw-r--r-- root root 60 ./usr/lib/opkg/alternatives/xzcat
+-rw-r--r-- root root 63 ./usr/lib/opkg/alternatives/yes
+-rw-r--r-- root root 33 ./usr/lib/opkg/alternatives/zcat
+drwxr-xr-x root root 4096 ./usr/lib/perl5
+drwxr-xr-x root root 4096 ./usr/lib/perl5/5.30.2
+-rwxr-xr-x root root 3305 ./usr/lib/perl5/5.30.2/Config.pm
+drwxr-xr-x root root 4096 ./usr/lib/perl5/5.30.2/ExtUtils
+-r--r--r-- root root 1105 ./usr/lib/perl5/5.30.2/ExtUtils/MANIFEST.SKIP
+-rwxr-xr-x root root 11315 ./usr/lib/perl5/5.30.2/ExtUtils/typemap
+-r--r--r-- root root 5071 ./usr/lib/perl5/5.30.2/ExtUtils/xsubpp
+-r--r--r-- root root 4738 ./usr/lib/perl5/5.30.2/strict.pm
+-r--r--r-- root root 2458 ./usr/lib/perl5/5.30.2/vars.pm
+drwxr-xr-x root root 4096 ./usr/lib/perl5/5.30.2/warnings
+-r--r--r-- root root 49989 ./usr/lib/perl5/5.30.2/warnings.pm
+-r--r--r-- root root 759 ./usr/lib/perl5/5.30.2/warnings/register.pm
+drwxr-xr-x root root 4096 ./usr/lib/perl5/5.30.2/x86_64-linux
+-r--r--r-- root root 409 ./usr/lib/perl5/5.30.2/x86_64-linux/Config_git.pl
+-r--r--r-- root root 43123 ./usr/lib/perl5/5.30.2/x86_64-linux/Config_heavy.pl
+lrwxrwxrwx root root 15 ./usr/lib/perl5/5.30.2/x86_64-linux/Config_heavy-target.pl -> Config_heavy.pl
+-r--r--r-- root root 3305 ./usr/lib/perl5/5.30.2/x86_64-linux/Config.pm
+drwxr-xr-x root root 4096 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE
+-r--r--r-- root root 3294 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/av.h
+-r--r--r-- root root 850 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/bitcount.h
+-r--r--r-- root root 4114121 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/charclass_invlists.h
+-r--r--r-- root root 162839 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/config.h
+-r--r--r-- root root 40671 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/cop.h
+-r--r--r-- root root 12323 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/cv.h
+-r--r--r-- root root 5461 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/dosish.h
+-r--r--r-- root root 1861 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/dquote_inline.h
+-r--r--r-- root root 49548 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/ebcdic_tables.h
+-r--r--r-- root root 102635 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/embed.h
+-r--r--r-- root root 23467 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/embedvar.h
+-r--r--r-- root root 1652 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/EXTERN.h
+-r--r--r-- root root 3210 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/fakesdio.h
+-r--r--r-- root root 5046 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/feature.h
+-r--r--r-- root root 1463 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/form.h
+-r--r--r-- root root 357 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/git_version.h
+-r--r--r-- root root 10711 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/gv.h
+-r--r--r-- root root 126538 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/handy.h
+-r--r--r-- root root 10786 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/hv_func.h
+-r--r--r-- root root 25545 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/hv.h
+-r--r--r-- root root 2953 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/hv_macro.h
+-r--r--r-- root root 68866 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/inline.h
+-r--r--r-- root root 1309 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/INTERN.h
+-r--r--r-- root root 29425 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/intrpvar.h
+-r--r--r-- root root 2976 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/invlist_inline.h
+-r--r--r-- root root 48759 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/iperlsys.h
+-r--r--r-- root root 6587 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/keywords.h
+-r--r--r-- root root 126938 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/l1_char_class_tab.h
+lrwxrwxrwx root root 29 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/libperl.so -> ../../../../libperl.so.5.30.0
+-r--r--r-- root root 1524 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/malloc_ctl.h
+-r--r--r-- root root 952 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/metaconfig.h
+-r--r--r-- root root 5021 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/mg_data.h
+-r--r--r-- root root 3013 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/mg.h
+-r--r--r-- root root 4377 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/mg_raw.h
+-r--r--r-- root root 9562 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/mg_vtable.h
+-r--r--r-- root root 1693 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/mydtrace.h
+-r--r--r-- root root 3392 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/nostdio.h
+-r--r--r-- root root 93275 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/opcode.h
+-r--r--r-- root root 36350 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/op.h
+-r--r--r-- root root 8860 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/opnames.h
+-r--r--r-- root root 5911 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/op_reg_common.h
+-r--r--r-- root root 3276 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/overload.h
+-r--r--r-- root root 17220 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/pad.h
+-r--r--r-- root root 6993 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/parser.h
+-r--r--r-- root root 5321 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/patchlevel.h
+-r--r--r-- root root 10170 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/perlapi.h
+-r--r--r-- root root 270251 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/perl.h
+-r--r--r-- root root 6223 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/perl_inc_macro.h
+-r--r--r-- root root 9464 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/perlio.h
+-r--r--r-- root root 13761 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/perliol.h
+-r--r--r-- root root 2973 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/perl_langinfo.h
+-r--r--r-- root root 527 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/perlsdio.h
+-r--r--r-- root root 13314 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/perlvars.h
+-r--r--r-- root root 4434 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/perly.h
+-r--r--r-- root root 28969 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/pp.h
+-r--r--r-- root root 12131 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/pp_proto.h
+-r--r--r-- root root 258888 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/proto.h
+-r--r--r-- root root 78454 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/reentr.h
+-r--r--r-- root root 140155 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/regcharclass.h
+-r--r--r-- root root 48923 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/regcomp.h
+-r--r--r-- root root 36671 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/regexp.h
+-r--r--r-- root root 38053 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/regnodes.h
+-r--r--r-- root root 57294 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/sbox32_hash.h
+-r--r--r-- root root 11887 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/scope.h
+-r--r--r-- root root 10477 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/stadtx_hash.h
+-r--r--r-- root root 85432 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/sv.h
+-r--r--r-- root root 12095 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/thread.h
+-r--r--r-- root root 2048 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/time64_config.h
+-r--r--r-- root root 1588 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/time64.h
+-r--r--r-- root root 44 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/try.h
+-r--r--r-- root root 163425 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/uconfig.h
+-r--r--r-- root root 8027 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/unicode_constants.h
+-r--r--r-- root root 535594 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/uni_keywords.h
+-r--r--r-- root root 5193 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/unixish.h
+-r--r--r-- root root 47587 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/utf8.h
+-r--r--r-- root root 67051 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/utfebcdic.h
+-r--r--r-- root root 10011 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/util.h
+-r--r--r-- root root 904 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/uudmap.h
+-r--r--r-- root root 7993 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/vutil.h
+-r--r--r-- root root 8230 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/warnings.h
+-r--r--r-- root root 24399 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/XSUB.h
+-r--r--r-- root root 10541 ./usr/lib/perl5/5.30.2/x86_64-linux/CORE/zaphod32_hash.h
+-rwxr-xr-x root root 36089 ./usr/lib/perl5/config.sh
+drwxr-xr-x root root 4096 ./usr/lib/perl5/site_perl
+drwxr-xr-x root root 4096 ./usr/lib/perl5/site_perl/5.30.2
+drwxr-xr-x root root 4096 ./usr/lib/perl5/site_perl/5.30.2/x86_64-linux
+drwxr-xr-x root root 4096 ./usr/lib/pkgconfig
+-rw-r--r-- root root 154 ./usr/lib/pkgconfig/applewmproto.pc
+-rw-r--r-- root root 900 ./usr/lib/pkgconfig/bash.pc
+-rw-r--r-- root root 154 ./usr/lib/pkgconfig/bigreqsproto.pc
+-rw-r--r-- root root 191 ./usr/lib/pkgconfig/blkid.pc
+-rw-r--r-- root root 242 ./usr/lib/pkgconfig/cairo-fc.pc
+-rw-r--r-- root root 239 ./usr/lib/pkgconfig/cairo-ft.pc
+-rw-r--r-- root root 223 ./usr/lib/pkgconfig/cairo-gl.pc
+-rw-r--r-- root root 217 ./usr/lib/pkgconfig/cairo-glx.pc
+-rw-r--r-- root root 276 ./usr/lib/pkgconfig/cairo-gobject.pc
+-rw-r--r-- root root 446 ./usr/lib/pkgconfig/cairo.pc
+-rw-r--r-- root root 222 ./usr/lib/pkgconfig/cairo-pdf.pc
+-rw-r--r-- root root 219 ./usr/lib/pkgconfig/cairo-png.pc
+-rw-r--r-- root root 228 ./usr/lib/pkgconfig/cairo-ps.pc
+-rw-r--r-- root root 228 ./usr/lib/pkgconfig/cairo-script.pc
+-rw-r--r-- root root 219 ./usr/lib/pkgconfig/cairo-svg.pc
+-rw-r--r-- root root 219 ./usr/lib/pkgconfig/cairo-tee.pc
+-rw-r--r-- root root 247 ./usr/lib/pkgconfig/cairo-xcb.pc
+-rw-r--r-- root root 228 ./usr/lib/pkgconfig/cairo-xcb-shm.pc
+-rw-r--r-- root root 229 ./usr/lib/pkgconfig/cairo-xlib.pc
+-rw-r--r-- root root 256 ./usr/lib/pkgconfig/cairo-xlib-xrender.pc
+-rw-r--r-- root root 247 ./usr/lib/pkgconfig/com_err.pc
+-rw-r--r-- root root 158 ./usr/lib/pkgconfig/compositeproto.pc
+-rw-r--r-- root root 152 ./usr/lib/pkgconfig/damageproto.pc
+-rw-r--r-- root root 607 ./usr/lib/pkgconfig/dbus-1.pc
+-rw-r--r-- root root 275 ./usr/lib/pkgconfig/dbus-python.pc
+-rw-r--r-- root root 146 ./usr/lib/pkgconfig/dmxproto.pc
+-rw-r--r-- root root 146 ./usr/lib/pkgconfig/dpmsproto.pc
+-rw-r--r-- root root 146 ./usr/lib/pkgconfig/dri2proto.pc
+-rw-r--r-- root root 146 ./usr/lib/pkgconfig/dri3proto.pc
+-rw-r--r-- root root 226 ./usr/lib/pkgconfig/e2p.pc
+-rw-r--r-- root root 206 ./usr/lib/pkgconfig/expat.pc
+-rw-r--r-- root root 223 ./usr/lib/pkgconfig/ext2fs.pc
+-rw-r--r-- root root 213 ./usr/lib/pkgconfig/fdisk.pc
+-rw-r--r-- root root 148 ./usr/lib/pkgconfig/fixesproto.pc
+-rw-r--r-- root root 407 ./usr/lib/pkgconfig/fontconfig.pc
+-rw-r--r-- root root 150 ./usr/lib/pkgconfig/fontsproto.pc
+-rw-r--r-- root root 469 ./usr/lib/pkgconfig/form.pc
+-rw-r--r-- root root 454 ./usr/lib/pkgconfig/formw.pc
+-rw-r--r-- root root 310 ./usr/lib/pkgconfig/freetype2.pc
+-rw-r--r-- root root 630 ./usr/lib/pkgconfig/gio-2.0.pc
+-rw-r--r-- root root 231 ./usr/lib/pkgconfig/gio-unix-2.0.pc
+-rw-r--r-- root root 377 ./usr/lib/pkgconfig/glib-2.0.pc
+-rw-r--r-- root root 354 ./usr/lib/pkgconfig/gl.pc
+-rw-r--r-- root root 145 ./usr/lib/pkgconfig/glproto.pc
+-rw-r--r-- root root 253 ./usr/lib/pkgconfig/gmodule-2.0.pc
+-rw-r--r-- root root 253 ./usr/lib/pkgconfig/gmodule-export-2.0.pc
+-rw-r--r-- root root 272 ./usr/lib/pkgconfig/gmodule-no-export-2.0.pc
+-rw-r--r-- root root 225 ./usr/lib/pkgconfig/gmp.pc
+-rw-r--r-- root root 260 ./usr/lib/pkgconfig/gmpxx.pc
+-rw-r--r-- root root 286 ./usr/lib/pkgconfig/gobject-2.0.pc
+-rw-r--r-- root root 649 ./usr/lib/pkgconfig/gobject-introspection-1.0.pc
+-rw-r--r-- root root 612 ./usr/lib/pkgconfig/gobject-introspection-no-export-1.0.pc
+-rw-r--r-- root root 222 ./usr/lib/pkgconfig/gthread-2.0.pc
+-rw-r--r-- root root 206 ./usr/lib/pkgconfig/ice.pc
+-rw-r--r-- root root 150 ./usr/lib/pkgconfig/inputproto.pc
+-rw-r--r-- root root 144 ./usr/lib/pkgconfig/kbproto.pc
+-rw-r--r-- root root 204 ./usr/lib/pkgconfig/libacl.pc
+-rw-r--r-- root root 217 ./usr/lib/pkgconfig/libattr.pc
+-rw-r--r-- root root 208 ./usr/lib/pkgconfig/libcap-ng.pc
+-rw-r--r-- root root 209 ./usr/lib/pkgconfig/libcap.pc
+-rw-r--r-- root root 275 ./usr/lib/pkgconfig/libcrypto.pc
+lrwxrwxrwx root root 12 ./usr/lib/pkgconfig/libcrypt.pc -> libxcrypt.pc
+-rw-r--r-- root root 269 ./usr/lib/pkgconfig/libdrm_amdgpu.pc
+-rw-r--r-- root root 266 ./usr/lib/pkgconfig/libdrm_etnaviv.pc
+-rw-r--r-- root root 300 ./usr/lib/pkgconfig/libdrm_freedreno.pc
+-rw-r--r-- root root 254 ./usr/lib/pkgconfig/libdrm_intel.pc
+-rw-r--r-- root root 299 ./usr/lib/pkgconfig/libdrm_nouveau.pc
+-rw-r--r-- root root 276 ./usr/lib/pkgconfig/libdrm_omap.pc
+-rw-r--r-- root root 219 ./usr/lib/pkgconfig/libdrm.pc
+-rw-r--r-- root root 269 ./usr/lib/pkgconfig/libdrm_radeon.pc
+-rw-r--r-- root root 205 ./usr/lib/pkgconfig/libdrm_vc4.pc
+-rw-r--r-- root root 633 ./usr/lib/pkgconfig/libdw.pc
+-rw-r--r-- root root 262 ./usr/lib/pkgconfig/libelf.pc
+-rw-r--r-- root root 237 ./usr/lib/pkgconfig/libffi.pc
+-rw-r--r-- root root 213 ./usr/lib/pkgconfig/libip4tc.pc
+-rw-r--r-- root root 213 ./usr/lib/pkgconfig/libip6tc.pc
+-rw-r--r-- root root 190 ./usr/lib/pkgconfig/libiptc.pc
+-rw-r--r-- root root 213 ./usr/lib/pkgconfig/libkmod.pc
+-rw-r--r-- root root 258 ./usr/lib/pkgconfig/libkms.pc
+-rw-r--r-- root root 390 ./usr/lib/pkgconfig/liblzma.pc
+-rw-r--r-- root root 292 ./usr/lib/pkgconfig/libmnl.pc
+-rw-r--r-- root root 247 ./usr/lib/pkgconfig/libnsl.pc
+-rw-r--r-- root root 243 ./usr/lib/pkgconfig/libpcrecpp.pc
+-rw-r--r-- root root 305 ./usr/lib/pkgconfig/libpcre.pc
+-rw-r--r-- root root 285 ./usr/lib/pkgconfig/libpcreposix.pc
+-rw-r--r-- root root 239 ./usr/lib/pkgconfig/libpng16.pc
+lrwxrwxrwx root root 11 ./usr/lib/pkgconfig/libpng.pc -> libpng16.pc
+-rw-r--r-- root root 223 ./usr/lib/pkgconfig/libprocps.pc
+-rw-r--r-- root root 254 ./usr/lib/pkgconfig/libpsx.pc
+-rw-r--r-- root root 254 ./usr/lib/pkgconfig/libssl.pc
+-rw-r--r-- root root 235 ./usr/lib/pkgconfig/libtirpc.pc
+-rw-r--r-- root root 493 ./usr/lib/pkgconfig/libudev.pc
+-rw-r--r-- root root 367 ./usr/lib/pkgconfig/libxcrypt.pc
+-rw-r--r-- root root 243 ./usr/lib/pkgconfig/libxml-2.0.pc
+-rw-r--r-- root root 500 ./usr/lib/pkgconfig/lzo2.pc
+-rw-r--r-- root root 469 ./usr/lib/pkgconfig/menu.pc
+-rw-r--r-- root root 454 ./usr/lib/pkgconfig/menuw.pc
+-rw-r--r-- root root 627 ./usr/lib/pkgconfig/mount.pc
+-rw-r--r-- root root 469 ./usr/lib/pkgconfig/ncurses.pc
+-rw-r--r-- root root 498 ./usr/lib/pkgconfig/ncurses++.pc
+-rw-r--r-- root root 486 ./usr/lib/pkgconfig/ncurses++w.pc
+-rw-r--r-- root root 453 ./usr/lib/pkgconfig/ncursesw.pc
+-rw-r--r-- root root 208 ./usr/lib/pkgconfig/openssl.pc
+-rw-r--r-- root root 471 ./usr/lib/pkgconfig/panel.pc
+-rw-r--r-- root root 456 ./usr/lib/pkgconfig/panelw.pc
+-rw-r--r-- root root 228 ./usr/lib/pkgconfig/pciaccess.pc
+-rw-r--r-- root root 224 ./usr/lib/pkgconfig/pixman-1.pc
+-rw-r--r-- root root 152 ./usr/lib/pkgconfig/presentproto.pc
+-rw-r--r-- root root 224 ./usr/lib/pkgconfig/pthread-stubs.pc
+-rw-r--r-- root root 182 ./usr/lib/pkgconfig/py3cairo.pc
+-rw-r--r-- root root 706 ./usr/lib/pkgconfig/pygobject-3.0.pc
+-rw-r--r-- root root 297 ./usr/lib/pkgconfig/python-3.8-embed.pc
+-rw-r--r-- root root 271 ./usr/lib/pkgconfig/python-3.8.pc
+lrwxrwxrwx root root 19 ./usr/lib/pkgconfig/python3-embed.pc -> python-3.8-embed.pc
+lrwxrwxrwx root root 13 ./usr/lib/pkgconfig/python3.pc -> python-3.8.pc
+-rw-r--r-- root root 150 ./usr/lib/pkgconfig/randrproto.pc
+-rw-r--r-- root root 302 ./usr/lib/pkgconfig/readline.pc
+-rw-r--r-- root root 153 ./usr/lib/pkgconfig/recordproto.pc
+-rw-r--r-- root root 153 ./usr/lib/pkgconfig/renderproto.pc
+-rw-r--r-- root root 156 ./usr/lib/pkgconfig/resourceproto.pc
+-rw-r--r-- root root 158 ./usr/lib/pkgconfig/scrnsaverproto.pc
+-rw-r--r-- root root 204 ./usr/lib/pkgconfig/smartcols.pc
+-rw-r--r-- root root 222 ./usr/lib/pkgconfig/sm.pc
+-rw-r--r-- root root 256 ./usr/lib/pkgconfig/sqlite3.pc
+-rw-r--r-- root root 249 ./usr/lib/pkgconfig/ss.pc
+-rw-r--r-- root root 467 ./usr/lib/pkgconfig/tic.pc
+-rw-r--r-- root root 452 ./usr/lib/pkgconfig/ticw.pc
+-rw-r--r-- root root 458 ./usr/lib/pkgconfig/tinfo.pc
+-rw-r--r-- root root 204 ./usr/lib/pkgconfig/uuid.pc
+-rw-r--r-- root root 150 ./usr/lib/pkgconfig/videoproto.pc
+-rw-r--r-- root root 314 ./usr/lib/pkgconfig/wayland-client.pc
+-rw-r--r-- root root 234 ./usr/lib/pkgconfig/wayland-cursor.pc
+-rw-r--r-- root root 166 ./usr/lib/pkgconfig/wayland-egl-backend.pc
+-rw-r--r-- root root 219 ./usr/lib/pkgconfig/wayland-egl.pc
+-rw-r--r-- root root 269 ./usr/lib/pkgconfig/wayland-scanner.pc
+-rw-r--r-- root root 337 ./usr/lib/pkgconfig/wayland-server.pc
+-rw-r--r-- root root 270 ./usr/lib/pkgconfig/x11.pc
+-rw-r--r-- root root 206 ./usr/lib/pkgconfig/x11-xcb.pc
+-rw-r--r-- root root 212 ./usr/lib/pkgconfig/xau.pc
+-rw-r--r-- root root 232 ./usr/lib/pkgconfig/xcb-composite.pc
+-rw-r--r-- root root 223 ./usr/lib/pkgconfig/xcb-damage.pc
+-rw-r--r-- root root 206 ./usr/lib/pkgconfig/xcb-dpms.pc
+-rw-r--r-- root root 206 ./usr/lib/pkgconfig/xcb-dri2.pc
+-rw-r--r-- root root 206 ./usr/lib/pkgconfig/xcb-dri3.pc
+-rw-r--r-- root root 203 ./usr/lib/pkgconfig/xcb-glx.pc
+-rw-r--r-- root root 251 ./usr/lib/pkgconfig/xcb.pc
+-rw-r--r-- root root 245 ./usr/lib/pkgconfig/xcb-present.pc
+-rw-r--r-- root root 273 ./usr/lib/pkgconfig/xcb-proto.pc
+-rw-r--r-- root root 220 ./usr/lib/pkgconfig/xcb-randr.pc
+-rw-r--r-- root root 212 ./usr/lib/pkgconfig/xcb-record.pc
+-rw-r--r-- root root 212 ./usr/lib/pkgconfig/xcb-render.pc
+-rw-r--r-- root root 210 ./usr/lib/pkgconfig/xcb-res.pc
+-rw-r--r-- root root 227 ./usr/lib/pkgconfig/xcb-screensaver.pc
+-rw-r--r-- root root 209 ./usr/lib/pkgconfig/xcb-shape.pc
+-rw-r--r-- root root 203 ./usr/lib/pkgconfig/xcb-shm.pc
+-rw-r--r-- root root 206 ./usr/lib/pkgconfig/xcb-sync.pc
+-rw-r--r-- root root 223 ./usr/lib/pkgconfig/xcb-xf86dri.pc
+-rw-r--r-- root root 233 ./usr/lib/pkgconfig/xcb-xfixes.pc
+-rw-r--r-- root root 218 ./usr/lib/pkgconfig/xcb-xinerama.pc
+-rw-r--r-- root root 238 ./usr/lib/pkgconfig/xcb-xinput.pc
+-rw-r--r-- root root 223 ./usr/lib/pkgconfig/xcb-xkb.pc
+-rw-r--r-- root root 209 ./usr/lib/pkgconfig/xcb-xtest.pc
+-rw-r--r-- root root 213 ./usr/lib/pkgconfig/xcb-xvmc.pc
+-rw-r--r-- root root 208 ./usr/lib/pkgconfig/xcb-xv.pc
+-rw-r--r-- root root 152 ./usr/lib/pkgconfig/xcmiscproto.pc
+-rw-r--r-- root root 254 ./usr/lib/pkgconfig/xdamage.pc
+-rw-r--r-- root root 220 ./usr/lib/pkgconfig/xdmcp.pc
+-rw-r--r-- root root 225 ./usr/lib/pkgconfig/xext.pc
+-rw-r--r-- root root 148 ./usr/lib/pkgconfig/xextproto.pc
+-rw-r--r-- root root 162 ./usr/lib/pkgconfig/xf86bigfontproto.pc
+-rw-r--r-- root root 152 ./usr/lib/pkgconfig/xf86dgaproto.pc
+-rw-r--r-- root root 162 ./usr/lib/pkgconfig/xf86driproto.pc
+-rw-r--r-- root root 162 ./usr/lib/pkgconfig/xf86vidmodeproto.pc
+-rw-r--r-- root root 236 ./usr/lib/pkgconfig/xfixes.pc
+-rw-r--r-- root root 156 ./usr/lib/pkgconfig/xineramaproto.pc
+-rw-r--r-- root root 143 ./usr/lib/pkgconfig/xproto.pc
+-rw-r--r-- root root 248 ./usr/lib/pkgconfig/xrandr.pc
+-rw-r--r-- root root 244 ./usr/lib/pkgconfig/xrender.pc
+-rw-r--r-- root root 216 ./usr/lib/pkgconfig/xshmfence.pc
+-rw-r--r-- root root 261 ./usr/lib/pkgconfig/xtables.pc
+-rw-r--r-- root root 255 ./usr/lib/pkgconfig/xxf86vm.pc
+-rw-r--r-- root root 233 ./usr/lib/pkgconfig/zlib.pc
+drwxr-xr-x root root 4096 ./usr/lib/python3.8
+-rw-r--r-- root root 4489 ./usr/lib/python3.8/abc.py
+-rw-r--r-- root root 96015 ./usr/lib/python3.8/argparse.py
+-rw-r--r-- root root 18608 ./usr/lib/python3.8/ast.py
+-rwxr-xr-x root root 20382 ./usr/lib/python3.8/base64.py
+-rw-r--r-- root root 2214 ./usr/lib/python3.8/bisect.py
+-rw-r--r-- root root 1801 ./usr/lib/python3.8/_bootlocale.py
+-rw-r--r-- root root 12558 ./usr/lib/python3.8/bz2.py
+-rw-r--r-- root root 24832 ./usr/lib/python3.8/calendar.py
+-rw-r--r-- root root 14860 ./usr/lib/python3.8/cmd.py
+-rw-r--r-- root root 36667 ./usr/lib/python3.8/codecs.py
+-rw-r--r-- root root 6059 ./usr/lib/python3.8/codeop.py
+-rw-r--r-- root root 10622 ./usr/lib/python3.8/code.py
+drwxr-xr-x root root 4096 ./usr/lib/python3.8/collections
+-rw-r--r-- root root 26100 ./usr/lib/python3.8/_collections_abc.py
+-rw-r--r-- root root 68 ./usr/lib/python3.8/collections/abc.py
+-rw-r--r-- root root 47938 ./usr/lib/python3.8/collections/__init__.py
+drwxr-xr-x root root 4096 ./usr/lib/python3.8/collections/__pycache__
+-rw-r--r-- root root 191 ./usr/lib/python3.8/collections/__pycache__/abc.cpython-38.opt-1.pyc
+-rw-r--r-- root root 191 ./usr/lib/python3.8/collections/__pycache__/abc.cpython-38.opt-2.pyc
+-rw-r--r-- root root 191 ./usr/lib/python3.8/collections/__pycache__/abc.cpython-38.pyc
+-rw-r--r-- root root 46435 ./usr/lib/python3.8/collections/__pycache__/__init__.cpython-38.opt-1.pyc
+-rw-r--r-- root root 35846 ./usr/lib/python3.8/collections/__pycache__/__init__.cpython-38.opt-2.pyc
+-rw-r--r-- root root 46435 ./usr/lib/python3.8/collections/__pycache__/__init__.cpython-38.pyc
+-rw-r--r-- root root 8749 ./usr/lib/python3.8/_compat_pickle.py
+-rw-r--r-- root root 5340 ./usr/lib/python3.8/_compression.py
+drwxr-xr-x root root 4096 ./usr/lib/python3.8/config-3.8-x86_64-linux-gnu
+-rw-r--r-- root root 3303 ./usr/lib/python3.8/config-3.8-x86_64-linux-gnu/config.c
+-rw-r--r-- root root 1623 ./usr/lib/python3.8/config-3.8-x86_64-linux-gnu/config.c.in
+-rwxr-xr-x root root 15368 ./usr/lib/python3.8/config-3.8-x86_64-linux-gnu/install-sh
+-rw-r--r-- root root 78513 ./usr/lib/python3.8/config-3.8-x86_64-linux-gnu/Makefile
+-rwxr-xr-x root root 7848 ./usr/lib/python3.8/config-3.8-x86_64-linux-gnu/makesetup
+drwxr-xr-x root root 4096 ./usr/lib/python3.8/config-3.8-x86_64-linux-gnu/__pycache__
+-rw-r--r-- root root 1959 ./usr/lib/python3.8/config-3.8-x86_64-linux-gnu/__pycache__/python-config.cpython-38.opt-1.pyc
+-rw-r--r-- root root 1959 ./usr/lib/python3.8/config-3.8-x86_64-linux-gnu/__pycache__/python-config.cpython-38.opt-2.pyc
+-rw-r--r-- root root 1959 ./usr/lib/python3.8/config-3.8-x86_64-linux-gnu/__pycache__/python-config.cpython-38.pyc
+-rwxr-xr-x root root 2114 ./usr/lib/python3.8/config-3.8-x86_64-linux-gnu/python-config.py
+-rw-r--r-- root root 4488 ./usr/lib/python3.8/config-3.8-x86_64-linux-gnu/python.o
+-rw-r--r-- root root 14786 ./usr/lib/python3.8/config-3.8-x86_64-linux-gnu/Setup
+-rw-r--r-- root root 13 ./usr/lib/python3.8/config-3.8-x86_64-linux-gnu/Setup.local
+-rw-r--r-- root root 54374 ./usr/lib/python3.8/configparser.py
+-rw-r--r-- root root 24995 ./usr/lib/python3.8/contextlib.py
+-rw-r--r-- root root 8661 ./usr/lib/python3.8/copy.py
+-rw-r--r-- root root 7135 ./usr/lib/python3.8/copyreg.py
+-rw-r--r-- root root 3610 ./usr/lib/python3.8/crypt.py
+-rw-r--r-- root root 16144 ./usr/lib/python3.8/csv.py
+-rw-r--r-- root root 88074 ./usr/lib/python3.8/datetime.py
+-rw-r--r-- root root 20566 ./usr/lib/python3.8/dis.py
+drwxr-xr-x root root 4096 ./usr/lib/python3.8/distutils
+-rw-r--r-- root root 8572 ./usr/lib/python3.8/distutils/archive_util.py
+-rw-r--r-- root root 14935 ./usr/lib/python3.8/distutils/bcppcompiler.py
+-rw-r--r-- root root 47433 ./usr/lib/python3.8/distutils/ccompiler.py
+-rw-r--r-- root root 18079 ./usr/lib/python3.8/distutils/cmd.py
+drwxr-xr-x root root 4096 ./usr/lib/python3.8/distutils/command
+-rw-r--r-- root root 4913 ./usr/lib/python3.8/distutils/command/bdist_dumb.py
+-rw-r--r-- root root 35295 ./usr/lib/python3.8/distutils/command/bdist_msi.py
+-rw-r--r-- root root 5562 ./usr/lib/python3.8/distutils/command/bdist.py
+-rw-r--r-- root root 21577 ./usr/lib/python3.8/distutils/command/bdist_rpm.py
+-rw-r--r-- root root 16043 ./usr/lib/python3.8/distutils/command/bdist_wininst.py
+-rw-r--r-- root root 8022 ./usr/lib/python3.8/distutils/command/build_clib.py
+-rw-r--r-- root root 31568 ./usr/lib/python3.8/distutils/command/build_ext.py
+-rw-r--r-- root root 5767 ./usr/lib/python3.8/distutils/command/build.py
+-rw-r--r-- root root 17164 ./usr/lib/python3.8/distutils/command/build_py.py
+-rw-r--r-- root root 6232 ./usr/lib/python3.8/distutils/command/build_scripts.py
+-rw-r--r-- root root 5599 ./usr/lib/python3.8/distutils/command/check.py
+-rw-r--r-- root root 2776 ./usr/lib/python3.8/distutils/command/clean.py
+-rw-r--r-- root root 633 ./usr/lib/python3.8/distutils/command/command_template
+-rw-r--r-- root root 13117 ./usr/lib/python3.8/distutils/command/config.py
+-rw-r--r-- root root 799 ./usr/lib/python3.8/distutils/command/__init__.py
+-rw-r--r-- root root 2822 ./usr/lib/python3.8/distutils/command/install_data.py
+-rw-r--r-- root root 2603 ./usr/lib/python3.8/distutils/command/install_egg_info.py
+-rw-r--r-- root root 1298 ./usr/lib/python3.8/distutils/command/install_headers.py
+-rw-r--r-- root root 8397 ./usr/lib/python3.8/distutils/command/install_lib.py
+-rw-r--r-- root root 26774 ./usr/lib/python3.8/distutils/command/install.py
+-rw-r--r-- root root 2017 ./usr/lib/python3.8/distutils/command/install_scripts.py
+drwxr-xr-x root root 4096 ./usr/lib/python3.8/distutils/command/__pycache__
+-rw-r--r-- root root 3666 ./usr/lib/python3.8/distutils/command/__pycache__/bdist.cpython-38.opt-1.pyc
+-rw-r--r-- root root 3472 ./usr/lib/python3.8/distutils/command/__pycache__/bdist.cpython-38.opt-2.pyc
+-rw-r--r-- root root 3666 ./usr/lib/python3.8/distutils/command/__pycache__/bdist.cpython-38.pyc
+-rw-r--r-- root root 3592 ./usr/lib/python3.8/distutils/command/__pycache__/bdist_dumb.cpython-38.opt-1.pyc
+-rw-r--r-- root root 3392 ./usr/lib/python3.8/distutils/command/__pycache__/bdist_dumb.cpython-38.opt-2.pyc
+-rw-r--r-- root root 3592 ./usr/lib/python3.8/distutils/command/__pycache__/bdist_dumb.cpython-38.pyc
+-rw-r--r-- root root 19535 ./usr/lib/python3.8/distutils/command/__pycache__/bdist_msi.cpython-38.opt-1.pyc
+-rw-r--r-- root root 17994 ./usr/lib/python3.8/distutils/command/__pycache__/bdist_msi.cpython-38.opt-2.pyc
+-rw-r--r-- root root 19623 ./usr/lib/python3.8/distutils/command/__pycache__/bdist_msi.cpython-38.pyc
+-rw-r--r-- root root 12362 ./usr/lib/python3.8/distutils/command/__pycache__/bdist_rpm.cpython-38.opt-1.pyc
+-rw-r--r-- root root 12043 ./usr/lib/python3.8/distutils/command/__pycache__/bdist_rpm.cpython-38.opt-2.pyc
+-rw-r--r-- root root 12428 ./usr/lib/python3.8/distutils/command/__pycache__/bdist_rpm.cpython-38.pyc
+-rw-r--r-- root root 8423 ./usr/lib/python3.8/distutils/command/__pycache__/bdist_wininst.cpython-38.opt-1.pyc
+-rw-r--r-- root root 8284 ./usr/lib/python3.8/distutils/command/__pycache__/bdist_wininst.cpython-38.opt-2.pyc
+-rw-r--r-- root root 8489 ./usr/lib/python3.8/distutils/command/__pycache__/bdist_wininst.cpython-38.pyc
+-rw-r--r-- root root 4814 ./usr/lib/python3.8/distutils/command/__pycache__/build_clib.cpython-38.opt-1.pyc
+-rw-r--r-- root root 4260 ./usr/lib/python3.8/distutils/command/__pycache__/build_clib.cpython-38.opt-2.pyc
+-rw-r--r-- root root 4814 ./usr/lib/python3.8/distutils/command/__pycache__/build_clib.cpython-38.pyc
+-rw-r--r-- root root 3881 ./usr/lib/python3.8/distutils/command/__pycache__/build.cpython-38.opt-1.pyc
+-rw-r--r-- root root 3798 ./usr/lib/python3.8/distutils/command/__pycache__/build.cpython-38.opt-2.pyc
+-rw-r--r-- root root 3881 ./usr/lib/python3.8/distutils/command/__pycache__/build.cpython-38.pyc
+-rw-r--r-- root root 16137 ./usr/lib/python3.8/distutils/command/__pycache__/build_ext.cpython-38.opt-1.pyc
+-rw-r--r-- root root 14180 ./usr/lib/python3.8/distutils/command/__pycache__/build_ext.cpython-38.opt-2.pyc
+-rw-r--r-- root root 16137 ./usr/lib/python3.8/distutils/command/__pycache__/build_ext.cpython-38.pyc
+-rw-r--r-- root root 10405 ./usr/lib/python3.8/distutils/command/__pycache__/build_py.cpython-38.opt-1.pyc
+-rw-r--r-- root root 9198 ./usr/lib/python3.8/distutils/command/__pycache__/build_py.cpython-38.opt-2.pyc
+-rw-r--r-- root root 10462 ./usr/lib/python3.8/distutils/command/__pycache__/build_py.cpython-38.pyc
+-rw-r--r-- root root 4324 ./usr/lib/python3.8/distutils/command/__pycache__/build_scripts.cpython-38.opt-1.pyc
+-rw-r--r-- root root 3930 ./usr/lib/python3.8/distutils/command/__pycache__/build_scripts.cpython-38.opt-2.pyc
+-rw-r--r-- root root 4324 ./usr/lib/python3.8/distutils/command/__pycache__/build_scripts.cpython-38.pyc
+-rw-r--r-- root root 4885 ./usr/lib/python3.8/distutils/command/__pycache__/check.cpython-38.opt-1.pyc
+-rw-r--r-- root root 4317 ./usr/lib/python3.8/distutils/command/__pycache__/check.cpython-38.opt-2.pyc
+-rw-r--r-- root root 4885 ./usr/lib/python3.8/distutils/command/__pycache__/check.cpython-38.pyc
+-rw-r--r-- root root 2100 ./usr/lib/python3.8/distutils/command/__pycache__/clean.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2017 ./usr/lib/python3.8/distutils/command/__pycache__/clean.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2100 ./usr/lib/python3.8/distutils/command/__pycache__/clean.cpython-38.pyc
+-rw-r--r-- root root 10227 ./usr/lib/python3.8/distutils/command/__pycache__/config.cpython-38.opt-1.pyc
+-rw-r--r-- root root 6891 ./usr/lib/python3.8/distutils/command/__pycache__/config.cpython-38.opt-2.pyc
+-rw-r--r-- root root 10227 ./usr/lib/python3.8/distutils/command/__pycache__/config.cpython-38.pyc
+-rw-r--r-- root root 543 ./usr/lib/python3.8/distutils/command/__pycache__/__init__.cpython-38.opt-1.pyc
+-rw-r--r-- root root 434 ./usr/lib/python3.8/distutils/command/__pycache__/__init__.cpython-38.opt-2.pyc
+-rw-r--r-- root root 543 ./usr/lib/python3.8/distutils/command/__pycache__/__init__.cpython-38.pyc
+-rw-r--r-- root root 13568 ./usr/lib/python3.8/distutils/command/__pycache__/install.cpython-38.opt-1.pyc
+-rw-r--r-- root root 12513 ./usr/lib/python3.8/distutils/command/__pycache__/install.cpython-38.opt-2.pyc
+-rw-r--r-- root root 13568 ./usr/lib/python3.8/distutils/command/__pycache__/install.cpython-38.pyc
+-rw-r--r-- root root 2289 ./usr/lib/python3.8/distutils/command/__pycache__/install_data.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2144 ./usr/lib/python3.8/distutils/command/__pycache__/install_data.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2289 ./usr/lib/python3.8/distutils/command/__pycache__/install_data.cpython-38.pyc
+-rw-r--r-- root root 2996 ./usr/lib/python3.8/distutils/command/__pycache__/install_egg_info.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2317 ./usr/lib/python3.8/distutils/command/__pycache__/install_egg_info.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2996 ./usr/lib/python3.8/distutils/command/__pycache__/install_egg_info.cpython-38.pyc
+-rw-r--r-- root root 1708 ./usr/lib/python3.8/distutils/command/__pycache__/install_headers.cpython-38.opt-1.pyc
+-rw-r--r-- root root 1542 ./usr/lib/python3.8/distutils/command/__pycache__/install_headers.cpython-38.opt-2.pyc
+-rw-r--r-- root root 1708 ./usr/lib/python3.8/distutils/command/__pycache__/install_headers.cpython-38.pyc
+-rw-r--r-- root root 5113 ./usr/lib/python3.8/distutils/command/__pycache__/install_lib.cpython-38.opt-1.pyc
+-rw-r--r-- root root 4532 ./usr/lib/python3.8/distutils/command/__pycache__/install_lib.cpython-38.opt-2.pyc
+-rw-r--r-- root root 5113 ./usr/lib/python3.8/distutils/command/__pycache__/install_lib.cpython-38.pyc
+-rw-r--r-- root root 2141 ./usr/lib/python3.8/distutils/command/__pycache__/install_scripts.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2007 ./usr/lib/python3.8/distutils/command/__pycache__/install_scripts.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2141 ./usr/lib/python3.8/distutils/command/__pycache__/install_scripts.cpython-38.pyc
+-rw-r--r-- root root 8455 ./usr/lib/python3.8/distutils/command/__pycache__/register.cpython-38.opt-1.pyc
+-rw-r--r-- root root 7190 ./usr/lib/python3.8/distutils/command/__pycache__/register.cpython-38.opt-2.pyc
+-rw-r--r-- root root 8455 ./usr/lib/python3.8/distutils/command/__pycache__/register.cpython-38.pyc
+-rw-r--r-- root root 14516 ./usr/lib/python3.8/distutils/command/__pycache__/sdist.cpython-38.opt-1.pyc
+-rw-r--r-- root root 11157 ./usr/lib/python3.8/distutils/command/__pycache__/sdist.cpython-38.opt-2.pyc
+-rw-r--r-- root root 14516 ./usr/lib/python3.8/distutils/command/__pycache__/sdist.cpython-38.pyc
+-rw-r--r-- root root 4939 ./usr/lib/python3.8/distutils/command/__pycache__/upload.cpython-38.opt-1.pyc
+-rw-r--r-- root root 4813 ./usr/lib/python3.8/distutils/command/__pycache__/upload.cpython-38.opt-2.pyc
+-rw-r--r-- root root 4939 ./usr/lib/python3.8/distutils/command/__pycache__/upload.cpython-38.pyc
+-rw-r--r-- root root 11712 ./usr/lib/python3.8/distutils/command/register.py
+-rw-r--r-- root root 19005 ./usr/lib/python3.8/distutils/command/sdist.py
+-rw-r--r-- root root 7001 ./usr/lib/python3.8/distutils/command/upload.py
+-rw-r--r-- root root 222208 ./usr/lib/python3.8/distutils/command/wininst-10.0-amd64.exe
+-rw-r--r-- root root 190976 ./usr/lib/python3.8/distutils/command/wininst-10.0.exe
+-rw-r--r-- root root 587776 ./usr/lib/python3.8/distutils/command/wininst-14.0-amd64.exe
+-rw-r--r-- root root 458240 ./usr/lib/python3.8/distutils/command/wininst-14.0.exe
+-rw-r--r-- root root 61440 ./usr/lib/python3.8/distutils/command/wininst-6.0.exe
+-rw-r--r-- root root 65536 ./usr/lib/python3.8/distutils/command/wininst-7.1.exe
+-rw-r--r-- root root 61440 ./usr/lib/python3.8/distutils/command/wininst-8.0.exe
+-rw-r--r-- root root 224256 ./usr/lib/python3.8/distutils/command/wininst-9.0-amd64.exe
+-rw-r--r-- root root 196096 ./usr/lib/python3.8/distutils/command/wininst-9.0.exe
+-rw-r--r-- root root 4827 ./usr/lib/python3.8/distutils/config.py
+-rw-r--r-- root root 8876 ./usr/lib/python3.8/distutils/core.py
+-rw-r--r-- root root 16478 ./usr/lib/python3.8/distutils/cygwinccompiler.py
+-rw-r--r-- root root 139 ./usr/lib/python3.8/distutils/debug.py
+-rw-r--r-- root root 3491 ./usr/lib/python3.8/distutils/dep_util.py
+-rw-r--r-- root root 7778 ./usr/lib/python3.8/distutils/dir_util.py
+-rw-r--r-- root root 50385 ./usr/lib/python3.8/distutils/dist.py
+-rw-r--r-- root root 3577 ./usr/lib/python3.8/distutils/errors.py
+-rw-r--r-- root root 10515 ./usr/lib/python3.8/distutils/extension.py
+-rw-r--r-- root root 17784 ./usr/lib/python3.8/distutils/fancy_getopt.py
+-rw-r--r-- root root 12832 ./usr/lib/python3.8/distutils/filelist.py
+-rw-r--r-- root root 8148 ./usr/lib/python3.8/distutils/file_util.py
+-rw-r--r-- root root 236 ./usr/lib/python3.8/distutils/__init__.py
+-rw-r--r-- root root 1969 ./usr/lib/python3.8/distutils/log.py
+-rw-r--r-- root root 30511 ./usr/lib/python3.8/distutils/msvc9compiler.py
+-rw-r--r-- root root 20050 ./usr/lib/python3.8/distutils/_msvccompiler.py
+-rw-r--r-- root root 23564 ./usr/lib/python3.8/distutils/msvccompiler.py
+drwxr-xr-x root root 4096 ./usr/lib/python3.8/distutils/__pycache__
+-rw-r--r-- root root 6539 ./usr/lib/python3.8/distutils/__pycache__/archive_util.cpython-38.opt-1.pyc
+-rw-r--r-- root root 4497 ./usr/lib/python3.8/distutils/__pycache__/archive_util.cpython-38.opt-2.pyc
+-rw-r--r-- root root 6539 ./usr/lib/python3.8/distutils/__pycache__/archive_util.cpython-38.pyc
+-rw-r--r-- root root 6523 ./usr/lib/python3.8/distutils/__pycache__/bcppcompiler.cpython-38.opt-1.pyc
+-rw-r--r-- root root 6235 ./usr/lib/python3.8/distutils/__pycache__/bcppcompiler.cpython-38.opt-2.pyc
+-rw-r--r-- root root 6523 ./usr/lib/python3.8/distutils/__pycache__/bcppcompiler.cpython-38.pyc
+-rw-r--r-- root root 33170 ./usr/lib/python3.8/distutils/__pycache__/ccompiler.cpython-38.opt-1.pyc
+-rw-r--r-- root root 16864 ./usr/lib/python3.8/distutils/__pycache__/ccompiler.cpython-38.opt-2.pyc
+-rw-r--r-- root root 33297 ./usr/lib/python3.8/distutils/__pycache__/ccompiler.cpython-38.pyc
+-rw-r--r-- root root 13948 ./usr/lib/python3.8/distutils/__pycache__/cmd.cpython-38.opt-1.pyc
+-rw-r--r-- root root 8082 ./usr/lib/python3.8/distutils/__pycache__/cmd.cpython-38.opt-2.pyc
+-rw-r--r-- root root 13948 ./usr/lib/python3.8/distutils/__pycache__/cmd.cpython-38.pyc
+-rw-r--r-- root root 3509 ./usr/lib/python3.8/distutils/__pycache__/config.cpython-38.opt-1.pyc
+-rw-r--r-- root root 3118 ./usr/lib/python3.8/distutils/__pycache__/config.cpython-38.opt-2.pyc
+-rw-r--r-- root root 3509 ./usr/lib/python3.8/distutils/__pycache__/config.cpython-38.pyc
+-rw-r--r-- root root 6614 ./usr/lib/python3.8/distutils/__pycache__/core.cpython-38.opt-1.pyc
+-rw-r--r-- root root 3227 ./usr/lib/python3.8/distutils/__pycache__/core.cpython-38.opt-2.pyc
+-rw-r--r-- root root 6614 ./usr/lib/python3.8/distutils/__pycache__/core.cpython-38.pyc
+-rw-r--r-- root root 8612 ./usr/lib/python3.8/distutils/__pycache__/cygwinccompiler.cpython-38.opt-1.pyc
+-rw-r--r-- root root 6982 ./usr/lib/python3.8/distutils/__pycache__/cygwinccompiler.cpython-38.opt-2.pyc
+-rw-r--r-- root root 8612 ./usr/lib/python3.8/distutils/__pycache__/cygwinccompiler.cpython-38.pyc
+-rw-r--r-- root root 194 ./usr/lib/python3.8/distutils/__pycache__/debug.cpython-38.opt-1.pyc
+-rw-r--r-- root root 194 ./usr/lib/python3.8/distutils/__pycache__/debug.cpython-38.opt-2.pyc
+-rw-r--r-- root root 194 ./usr/lib/python3.8/distutils/__pycache__/debug.cpython-38.pyc
+-rw-r--r-- root root 2714 ./usr/lib/python3.8/distutils/__pycache__/dep_util.cpython-38.opt-1.pyc
+-rw-r--r-- root root 1270 ./usr/lib/python3.8/distutils/__pycache__/dep_util.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2714 ./usr/lib/python3.8/distutils/__pycache__/dep_util.cpython-38.pyc
+-rw-r--r-- root root 5823 ./usr/lib/python3.8/distutils/__pycache__/dir_util.cpython-38.opt-1.pyc
+-rw-r--r-- root root 3445 ./usr/lib/python3.8/distutils/__pycache__/dir_util.cpython-38.opt-2.pyc
+-rw-r--r-- root root 5823 ./usr/lib/python3.8/distutils/__pycache__/dir_util.cpython-38.pyc
+-rw-r--r-- root root 34492 ./usr/lib/python3.8/distutils/__pycache__/dist.cpython-38.opt-1.pyc
+-rw-r--r-- root root 25201 ./usr/lib/python3.8/distutils/__pycache__/dist.cpython-38.opt-2.pyc
+-rw-r--r-- root root 34492 ./usr/lib/python3.8/distutils/__pycache__/dist.cpython-38.pyc
+-rw-r--r-- root root 5250 ./usr/lib/python3.8/distutils/__pycache__/errors.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2702 ./usr/lib/python3.8/distutils/__pycache__/errors.cpython-38.opt-2.pyc
+-rw-r--r-- root root 5250 ./usr/lib/python3.8/distutils/__pycache__/errors.cpython-38.pyc
+-rw-r--r-- root root 6923 ./usr/lib/python3.8/distutils/__pycache__/extension.cpython-38.opt-1.pyc
+-rw-r--r-- root root 3433 ./usr/lib/python3.8/distutils/__pycache__/extension.cpython-38.opt-2.pyc
+-rw-r--r-- root root 6923 ./usr/lib/python3.8/distutils/__pycache__/extension.cpython-38.pyc
+-rw-r--r-- root root 10512 ./usr/lib/python3.8/distutils/__pycache__/fancy_getopt.cpython-38.opt-1.pyc
+-rw-r--r-- root root 7709 ./usr/lib/python3.8/distutils/__pycache__/fancy_getopt.cpython-38.opt-2.pyc
+-rw-r--r-- root root 10656 ./usr/lib/python3.8/distutils/__pycache__/fancy_getopt.cpython-38.pyc
+-rw-r--r-- root root 9777 ./usr/lib/python3.8/distutils/__pycache__/filelist.cpython-38.opt-1.pyc
+-rw-r--r-- root root 6906 ./usr/lib/python3.8/distutils/__pycache__/filelist.cpython-38.opt-2.pyc
+-rw-r--r-- root root 9867 ./usr/lib/python3.8/distutils/__pycache__/filelist.cpython-38.pyc
+-rw-r--r-- root root 5933 ./usr/lib/python3.8/distutils/__pycache__/file_util.cpython-38.opt-1.pyc
+-rw-r--r-- root root 3796 ./usr/lib/python3.8/distutils/__pycache__/file_util.cpython-38.opt-2.pyc
+-rw-r--r-- root root 5933 ./usr/lib/python3.8/distutils/__pycache__/file_util.cpython-38.pyc
+-rw-r--r-- root root 384 ./usr/lib/python3.8/distutils/__pycache__/__init__.cpython-38.opt-1.pyc
+-rw-r--r-- root root 202 ./usr/lib/python3.8/distutils/__pycache__/__init__.cpython-38.opt-2.pyc
+-rw-r--r-- root root 384 ./usr/lib/python3.8/distutils/__pycache__/__init__.cpython-38.pyc
+-rw-r--r-- root root 2315 ./usr/lib/python3.8/distutils/__pycache__/log.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2254 ./usr/lib/python3.8/distutils/__pycache__/log.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2315 ./usr/lib/python3.8/distutils/__pycache__/log.cpython-38.pyc
+-rw-r--r-- root root 17451 ./usr/lib/python3.8/distutils/__pycache__/msvc9compiler.cpython-38.opt-1.pyc
+-rw-r--r-- root root 15830 ./usr/lib/python3.8/distutils/__pycache__/msvc9compiler.cpython-38.opt-2.pyc
+-rw-r--r-- root root 17510 ./usr/lib/python3.8/distutils/__pycache__/msvc9compiler.cpython-38.pyc
+-rw-r--r-- root root 12907 ./usr/lib/python3.8/distutils/__pycache__/_msvccompiler.cpython-38.opt-1.pyc
+-rw-r--r-- root root 14723 ./usr/lib/python3.8/distutils/__pycache__/msvccompiler.cpython-38.opt-1.pyc
+-rw-r--r-- root root 11757 ./usr/lib/python3.8/distutils/__pycache__/_msvccompiler.cpython-38.opt-2.pyc
+-rw-r--r-- root root 13148 ./usr/lib/python3.8/distutils/__pycache__/msvccompiler.cpython-38.opt-2.pyc
+-rw-r--r-- root root 12966 ./usr/lib/python3.8/distutils/__pycache__/_msvccompiler.cpython-38.pyc
+-rw-r--r-- root root 14723 ./usr/lib/python3.8/distutils/__pycache__/msvccompiler.cpython-38.pyc
+-rw-r--r-- root root 5106 ./usr/lib/python3.8/distutils/__pycache__/spawn.cpython-38.opt-1.pyc
+-rw-r--r-- root root 3802 ./usr/lib/python3.8/distutils/__pycache__/spawn.cpython-38.opt-2.pyc
+-rw-r--r-- root root 5106 ./usr/lib/python3.8/distutils/__pycache__/spawn.cpython-38.pyc
+-rw-r--r-- root root 12101 ./usr/lib/python3.8/distutils/__pycache__/sysconfig.cpython-38.opt-1.pyc
+-rw-r--r-- root root 8616 ./usr/lib/python3.8/distutils/__pycache__/sysconfig.cpython-38.opt-2.pyc
+-rw-r--r-- root root 12101 ./usr/lib/python3.8/distutils/__pycache__/sysconfig.cpython-38.pyc
+-rw-r--r-- root root 8439 ./usr/lib/python3.8/distutils/__pycache__/text_file.cpython-38.opt-1.pyc
+-rw-r--r-- root root 3341 ./usr/lib/python3.8/distutils/__pycache__/text_file.cpython-38.opt-2.pyc
+-rw-r--r-- root root 8439 ./usr/lib/python3.8/distutils/__pycache__/text_file.cpython-38.pyc
+-rw-r--r-- root root 6618 ./usr/lib/python3.8/distutils/__pycache__/unixccompiler.cpython-38.opt-1.pyc
+-rw-r--r-- root root 6029 ./usr/lib/python3.8/distutils/__pycache__/unixccompiler.cpython-38.opt-2.pyc
+-rw-r--r-- root root 6618 ./usr/lib/python3.8/distutils/__pycache__/unixccompiler.cpython-38.pyc
+-rw-r--r-- root root 15546 ./usr/lib/python3.8/distutils/__pycache__/util.cpython-38.opt-1.pyc
+-rw-r--r-- root root 9662 ./usr/lib/python3.8/distutils/__pycache__/util.cpython-38.opt-2.pyc
+-rw-r--r-- root root 15546 ./usr/lib/python3.8/distutils/__pycache__/util.cpython-38.pyc
+-rw-r--r-- root root 7266 ./usr/lib/python3.8/distutils/__pycache__/version.cpython-38.opt-1.pyc
+-rw-r--r-- root root 3981 ./usr/lib/python3.8/distutils/__pycache__/version.cpython-38.opt-2.pyc
+-rw-r--r-- root root 7311 ./usr/lib/python3.8/distutils/__pycache__/version.cpython-38.pyc
+-rw-r--r-- root root 5135 ./usr/lib/python3.8/distutils/__pycache__/versionpredicate.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2655 ./usr/lib/python3.8/distutils/__pycache__/versionpredicate.cpython-38.opt-2.pyc
+-rw-r--r-- root root 5135 ./usr/lib/python3.8/distutils/__pycache__/versionpredicate.cpython-38.pyc
+-rw-r--r-- root root 242 ./usr/lib/python3.8/distutils/README
+-rw-r--r-- root root 7843 ./usr/lib/python3.8/distutils/spawn.py
+-rw-r--r-- root root 20390 ./usr/lib/python3.8/distutils/sysconfig.py
+-rw-r--r-- root root 12483 ./usr/lib/python3.8/distutils/text_file.py
+-rw-r--r-- root root 14696 ./usr/lib/python3.8/distutils/unixccompiler.py
+-rw-r--r-- root root 20892 ./usr/lib/python3.8/distutils/util.py
+-rw-r--r-- root root 5133 ./usr/lib/python3.8/distutils/versionpredicate.py
+-rw-r--r-- root root 12345 ./usr/lib/python3.8/distutils/version.py
+-rw-r--r-- root root 6027 ./usr/lib/python3.8/_dummy_thread.py
+drwxr-xr-x root root 4096 ./usr/lib/python3.8/email
+-rw-r--r-- root root 9561 ./usr/lib/python3.8/email/architecture.rst
+-rw-r--r-- root root 3558 ./usr/lib/python3.8/email/base64mime.py
+-rw-r--r-- root root 17128 ./usr/lib/python3.8/email/charset.py
+-rw-r--r-- root root 10672 ./usr/lib/python3.8/email/contentmanager.py
+-rw-r--r-- root root 8524 ./usr/lib/python3.8/email/_encoded_words.py
+-rw-r--r-- root root 1786 ./usr/lib/python3.8/email/encoders.py
+-rw-r--r-- root root 3647 ./usr/lib/python3.8/email/errors.py
+-rw-r--r-- root root 22780 ./usr/lib/python3.8/email/feedparser.py
+-rw-r--r-- root root 19975 ./usr/lib/python3.8/email/generator.py
+-rw-r--r-- root root 24102 ./usr/lib/python3.8/email/header.py
+-rw-r--r-- root root 20591 ./usr/lib/python3.8/email/headerregistry.py
+-rw-r--r-- root root 106460 ./usr/lib/python3.8/email/_header_value_parser.py
+-rw-r--r-- root root 1766 ./usr/lib/python3.8/email/__init__.py
+-rw-r--r-- root root 2135 ./usr/lib/python3.8/email/iterators.py
+-rw-r--r-- root root 47072 ./usr/lib/python3.8/email/message.py
+drwxr-xr-x root root 4096 ./usr/lib/python3.8/email/mime
+-rw-r--r-- root root 1321 ./usr/lib/python3.8/email/mime/application.py
+-rw-r--r-- root root 2739 ./usr/lib/python3.8/email/mime/audio.py
+-rw-r--r-- root root 916 ./usr/lib/python3.8/email/mime/base.py
+-rw-r--r-- root root 1829 ./usr/lib/python3.8/email/mime/image.py
+-rw-r--r-- root root 0 ./usr/lib/python3.8/email/mime/__init__.py
+-rw-r--r-- root root 1317 ./usr/lib/python3.8/email/mime/message.py
+-rw-r--r-- root root 1621 ./usr/lib/python3.8/email/mime/multipart.py
+-rw-r--r-- root root 691 ./usr/lib/python3.8/email/mime/nonmultipart.py
+drwxr-xr-x root root 4096 ./usr/lib/python3.8/email/mime/__pycache__
+-rw-r--r-- root root 1459 ./usr/lib/python3.8/email/mime/__pycache__/application.cpython-38.opt-1.pyc
+-rw-r--r-- root root 805 ./usr/lib/python3.8/email/mime/__pycache__/application.cpython-38.opt-2.pyc
+-rw-r--r-- root root 1459 ./usr/lib/python3.8/email/mime/__pycache__/application.cpython-38.pyc
+-rw-r--r-- root root 2624 ./usr/lib/python3.8/email/mime/__pycache__/audio.cpython-38.opt-1.pyc
+-rw-r--r-- root root 1184 ./usr/lib/python3.8/email/mime/__pycache__/audio.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2624 ./usr/lib/python3.8/email/mime/__pycache__/audio.cpython-38.pyc
+-rw-r--r-- root root 1041 ./usr/lib/python3.8/email/mime/__pycache__/base.cpython-38.opt-1.pyc
+-rw-r--r-- root root 717 ./usr/lib/python3.8/email/mime/__pycache__/base.cpython-38.opt-2.pyc
+-rw-r--r-- root root 1041 ./usr/lib/python3.8/email/mime/__pycache__/base.cpython-38.pyc
+-rw-r--r-- root root 1904 ./usr/lib/python3.8/email/mime/__pycache__/image.cpython-38.opt-1.pyc
+-rw-r--r-- root root 827 ./usr/lib/python3.8/email/mime/__pycache__/image.cpython-38.opt-2.pyc
+-rw-r--r-- root root 1904 ./usr/lib/python3.8/email/mime/__pycache__/image.cpython-38.pyc
+-rw-r--r-- root root 132 ./usr/lib/python3.8/email/mime/__pycache__/__init__.cpython-38.opt-1.pyc
+-rw-r--r-- root root 132 ./usr/lib/python3.8/email/mime/__pycache__/__init__.cpython-38.opt-2.pyc
+-rw-r--r-- root root 132 ./usr/lib/python3.8/email/mime/__pycache__/__init__.cpython-38.pyc
+-rw-r--r-- root root 1282 ./usr/lib/python3.8/email/mime/__pycache__/message.cpython-38.opt-1.pyc
+-rw-r--r-- root root 790 ./usr/lib/python3.8/email/mime/__pycache__/message.cpython-38.opt-2.pyc
+-rw-r--r-- root root 1282 ./usr/lib/python3.8/email/mime/__pycache__/message.cpython-38.pyc
+-rw-r--r-- root root 1502 ./usr/lib/python3.8/email/mime/__pycache__/multipart.cpython-38.opt-1.pyc
+-rw-r--r-- root root 706 ./usr/lib/python3.8/email/mime/__pycache__/multipart.cpython-38.opt-2.pyc
+-rw-r--r-- root root 1502 ./usr/lib/python3.8/email/mime/__pycache__/multipart.cpython-38.pyc
+-rw-r--r-- root root 764 ./usr/lib/python3.8/email/mime/__pycache__/nonmultipart.cpython-38.opt-1.pyc
+-rw-r--r-- root root 629 ./usr/lib/python3.8/email/mime/__pycache__/nonmultipart.cpython-38.opt-2.pyc
+-rw-r--r-- root root 764 ./usr/lib/python3.8/email/mime/__pycache__/nonmultipart.cpython-38.pyc
+-rw-r--r-- root root 1311 ./usr/lib/python3.8/email/mime/__pycache__/text.cpython-38.opt-1.pyc
+-rw-r--r-- root root 800 ./usr/lib/python3.8/email/mime/__pycache__/text.cpython-38.opt-2.pyc
+-rw-r--r-- root root 1311 ./usr/lib/python3.8/email/mime/__pycache__/text.cpython-38.pyc
+-rw-r--r-- root root 1437 ./usr/lib/python3.8/email/mime/text.py
+-rw-r--r-- root root 17604 ./usr/lib/python3.8/email/_parseaddr.py
+-rw-r--r-- root root 5041 ./usr/lib/python3.8/email/parser.py
+-rw-r--r-- root root 15073 ./usr/lib/python3.8/email/_policybase.py
+-rw-r--r-- root root 10383 ./usr/lib/python3.8/email/policy.py
+drwxr-xr-x root root 4096 ./usr/lib/python3.8/email/__pycache__
+-rw-r--r-- root root 3235 ./usr/lib/python3.8/email/__pycache__/base64mime.cpython-38.opt-1.pyc
+-rw-r--r-- root root 1458 ./usr/lib/python3.8/email/__pycache__/base64mime.cpython-38.opt-2.pyc
+-rw-r--r-- root root 3235 ./usr/lib/python3.8/email/__pycache__/base64mime.cpython-38.pyc
+-rw-r--r-- root root 11422 ./usr/lib/python3.8/email/__pycache__/charset.cpython-38.opt-1.pyc
+-rw-r--r-- root root 5093 ./usr/lib/python3.8/email/__pycache__/charset.cpython-38.opt-2.pyc
+-rw-r--r-- root root 11459 ./usr/lib/python3.8/email/__pycache__/charset.cpython-38.pyc
+-rw-r--r-- root root 7343 ./usr/lib/python3.8/email/__pycache__/contentmanager.cpython-38.opt-1.pyc
+-rw-r--r-- root root 7343 ./usr/lib/python3.8/email/__pycache__/contentmanager.cpython-38.opt-2.pyc
+-rw-r--r-- root root 7343 ./usr/lib/python3.8/email/__pycache__/contentmanager.cpython-38.pyc
+-rw-r--r-- root root 5686 ./usr/lib/python3.8/email/__pycache__/_encoded_words.cpython-38.opt-1.pyc
+-rw-r--r-- root root 3800 ./usr/lib/python3.8/email/__pycache__/_encoded_words.cpython-38.opt-2.pyc
+-rw-r--r-- root root 5686 ./usr/lib/python3.8/email/__pycache__/_encoded_words.cpython-38.pyc
+-rw-r--r-- root root 1612 ./usr/lib/python3.8/email/__pycache__/encoders.cpython-38.opt-1.pyc
+-rw-r--r-- root root 1261 ./usr/lib/python3.8/email/__pycache__/encoders.cpython-38.opt-2.pyc
+-rw-r--r-- root root 1612 ./usr/lib/python3.8/email/__pycache__/encoders.cpython-38.pyc
+-rw-r--r-- root root 5905 ./usr/lib/python3.8/email/__pycache__/errors.cpython-38.opt-1.pyc
+-rw-r--r-- root root 4473 ./usr/lib/python3.8/email/__pycache__/errors.cpython-38.opt-2.pyc
+-rw-r--r-- root root 5905 ./usr/lib/python3.8/email/__pycache__/errors.cpython-38.pyc
+-rw-r--r-- root root 10490 ./usr/lib/python3.8/email/__pycache__/feedparser.cpython-38.opt-1.pyc
+-rw-r--r-- root root 8827 ./usr/lib/python3.8/email/__pycache__/feedparser.cpython-38.opt-2.pyc
+-rw-r--r-- root root 10642 ./usr/lib/python3.8/email/__pycache__/feedparser.cpython-38.pyc
+-rw-r--r-- root root 12482 ./usr/lib/python3.8/email/__pycache__/generator.cpython-38.opt-1.pyc
+-rw-r--r-- root root 8783 ./usr/lib/python3.8/email/__pycache__/generator.cpython-38.opt-2.pyc
+-rw-r--r-- root root 12482 ./usr/lib/python3.8/email/__pycache__/generator.cpython-38.pyc
+-rw-r--r-- root root 16439 ./usr/lib/python3.8/email/__pycache__/header.cpython-38.opt-1.pyc
+-rw-r--r-- root root 10815 ./usr/lib/python3.8/email/__pycache__/header.cpython-38.opt-2.pyc
+-rw-r--r-- root root 16439 ./usr/lib/python3.8/email/__pycache__/header.cpython-38.pyc
+-rw-r--r-- root root 21848 ./usr/lib/python3.8/email/__pycache__/headerregistry.cpython-38.opt-1.pyc
+-rw-r--r-- root root 16085 ./usr/lib/python3.8/email/__pycache__/headerregistry.cpython-38.opt-2.pyc
+-rw-r--r-- root root 21900 ./usr/lib/python3.8/email/__pycache__/headerregistry.cpython-38.pyc
+-rw-r--r-- root root 79739 ./usr/lib/python3.8/email/__pycache__/_header_value_parser.cpython-38.opt-1.pyc
+-rw-r--r-- root root 62867 ./usr/lib/python3.8/email/__pycache__/_header_value_parser.cpython-38.opt-2.pyc
+-rw-r--r-- root root 79787 ./usr/lib/python3.8/email/__pycache__/_header_value_parser.cpython-38.pyc
+-rw-r--r-- root root 1691 ./usr/lib/python3.8/email/__pycache__/__init__.cpython-38.opt-1.pyc
+-rw-r--r-- root root 1066 ./usr/lib/python3.8/email/__pycache__/__init__.cpython-38.opt-2.pyc
+-rw-r--r-- root root 1691 ./usr/lib/python3.8/email/__pycache__/__init__.cpython-38.pyc
+-rw-r--r-- root root 1920 ./usr/lib/python3.8/email/__pycache__/iterators.cpython-38.opt-1.pyc
+-rw-r--r-- root root 1300 ./usr/lib/python3.8/email/__pycache__/iterators.cpython-38.opt-2.pyc
+-rw-r--r-- root root 1920 ./usr/lib/python3.8/email/__pycache__/iterators.cpython-38.pyc
+-rw-r--r-- root root 37878 ./usr/lib/python3.8/email/__pycache__/message.cpython-38.opt-1.pyc
+-rw-r--r-- root root 21316 ./usr/lib/python3.8/email/__pycache__/message.cpython-38.opt-2.pyc
+-rw-r--r-- root root 37878 ./usr/lib/python3.8/email/__pycache__/message.cpython-38.pyc
+-rw-r--r-- root root 12454 ./usr/lib/python3.8/email/__pycache__/_parseaddr.cpython-38.opt-1.pyc
+-rw-r--r-- root root 9494 ./usr/lib/python3.8/email/__pycache__/_parseaddr.cpython-38.opt-2.pyc
+-rw-r--r-- root root 12454 ./usr/lib/python3.8/email/__pycache__/_parseaddr.cpython-38.pyc
+-rw-r--r-- root root 5722 ./usr/lib/python3.8/email/__pycache__/parser.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2704 ./usr/lib/python3.8/email/__pycache__/parser.cpython-38.opt-2.pyc
+-rw-r--r-- root root 5722 ./usr/lib/python3.8/email/__pycache__/parser.cpython-38.pyc
+-rw-r--r-- root root 14810 ./usr/lib/python3.8/email/__pycache__/_policybase.cpython-38.opt-1.pyc
+-rw-r--r-- root root 5982 ./usr/lib/python3.8/email/__pycache__/_policybase.cpython-38.opt-2.pyc
+-rw-r--r-- root root 14810 ./usr/lib/python3.8/email/__pycache__/_policybase.cpython-38.pyc
+-rw-r--r-- root root 9658 ./usr/lib/python3.8/email/__pycache__/policy.cpython-38.opt-1.pyc
+-rw-r--r-- root root 3443 ./usr/lib/python3.8/email/__pycache__/policy.cpython-38.opt-2.pyc
+-rw-r--r-- root root 9658 ./usr/lib/python3.8/email/__pycache__/policy.cpython-38.pyc
+-rw-r--r-- root root 7678 ./usr/lib/python3.8/email/__pycache__/quoprimime.cpython-38.opt-1.pyc
+-rw-r--r-- root root 4205 ./usr/lib/python3.8/email/__pycache__/quoprimime.cpython-38.opt-2.pyc
+-rw-r--r-- root root 7678 ./usr/lib/python3.8/email/__pycache__/quoprimime.cpython-38.pyc
+-rw-r--r-- root root 9547 ./usr/lib/python3.8/email/__pycache__/utils.cpython-38.opt-1.pyc
+-rw-r--r-- root root 6218 ./usr/lib/python3.8/email/__pycache__/utils.cpython-38.opt-2.pyc
+-rw-r--r-- root root 9547 ./usr/lib/python3.8/email/__pycache__/utils.cpython-38.pyc
+-rw-r--r-- root root 9858 ./usr/lib/python3.8/email/quoprimime.py
+-rw-r--r-- root root 13488 ./usr/lib/python3.8/email/utils.py
+drwxr-xr-x root root 4096 ./usr/lib/python3.8/encodings
+-rw-r--r-- root root 15693 ./usr/lib/python3.8/encodings/aliases.py
+-rw-r--r-- root root 1248 ./usr/lib/python3.8/encodings/ascii.py
+-rw-r--r-- root root 1533 ./usr/lib/python3.8/encodings/base64_codec.py
+-rw-r--r-- root root 1039 ./usr/lib/python3.8/encodings/big5hkscs.py
+-rw-r--r-- root root 1019 ./usr/lib/python3.8/encodings/big5.py
+-rw-r--r-- root root 2249 ./usr/lib/python3.8/encodings/bz2_codec.py
+-rw-r--r-- root root 2084 ./usr/lib/python3.8/encodings/charmap.py
+-rw-r--r-- root root 13121 ./usr/lib/python3.8/encodings/cp037.py
+-rw-r--r-- root root 13568 ./usr/lib/python3.8/encodings/cp1006.py
+-rw-r--r-- root root 13113 ./usr/lib/python3.8/encodings/cp1026.py
+-rw-r--r-- root root 34597 ./usr/lib/python3.8/encodings/cp1125.py
+-rw-r--r-- root root 13105 ./usr/lib/python3.8/encodings/cp1140.py
+-rw-r--r-- root root 13686 ./usr/lib/python3.8/encodings/cp1250.py
+-rw-r--r-- root root 13361 ./usr/lib/python3.8/encodings/cp1251.py
+-rw-r--r-- root root 13511 ./usr/lib/python3.8/encodings/cp1252.py
+-rw-r--r-- root root 13094 ./usr/lib/python3.8/encodings/cp1253.py
+-rw-r--r-- root root 13502 ./usr/lib/python3.8/encodings/cp1254.py
+-rw-r--r-- root root 12466 ./usr/lib/python3.8/encodings/cp1255.py
+-rw-r--r-- root root 12814 ./usr/lib/python3.8/encodings/cp1256.py
+-rw-r--r-- root root 13374 ./usr/lib/python3.8/encodings/cp1257.py
+-rw-r--r-- root root 13364 ./usr/lib/python3.8/encodings/cp1258.py
+-rw-r--r-- root root 14132 ./usr/lib/python3.8/encodings/cp273.py
+-rw-r--r-- root root 12055 ./usr/lib/python3.8/encodings/cp424.py
+-rw-r--r-- root root 34564 ./usr/lib/python3.8/encodings/cp437.py
+-rw-r--r-- root root 13121 ./usr/lib/python3.8/encodings/cp500.py
+-rw-r--r-- root root 13686 ./usr/lib/python3.8/encodings/cp720.py
+-rw-r--r-- root root 34681 ./usr/lib/python3.8/encodings/cp737.py
+-rw-r--r-- root root 34476 ./usr/lib/python3.8/encodings/cp775.py
+-rw-r--r-- root root 34105 ./usr/lib/python3.8/encodings/cp850.py
+-rw-r--r-- root root 35002 ./usr/lib/python3.8/encodings/cp852.py
+-rw-r--r-- root root 33850 ./usr/lib/python3.8/encodings/cp855.py
+-rw-r--r-- root root 12423 ./usr/lib/python3.8/encodings/cp856.py
+-rw-r--r-- root root 33908 ./usr/lib/python3.8/encodings/cp857.py
+-rw-r--r-- root root 34015 ./usr/lib/python3.8/encodings/cp858.py
+-rw-r--r-- root root 34681 ./usr/lib/python3.8/encodings/cp860.py
+-rw-r--r-- root root 34633 ./usr/lib/python3.8/encodings/cp861.py
+-rw-r--r-- root root 33370 ./usr/lib/python3.8/encodings/cp862.py
+-rw-r--r-- root root 34252 ./usr/lib/python3.8/encodings/cp863.py
+-rw-r--r-- root root 33663 ./usr/lib/python3.8/encodings/cp864.py
+-rw-r--r-- root root 34618 ./usr/lib/python3.8/encodings/cp865.py
+-rw-r--r-- root root 34396 ./usr/lib/python3.8/encodings/cp866.py
+-rw-r--r-- root root 32965 ./usr/lib/python3.8/encodings/cp869.py
+-rw-r--r-- root root 12595 ./usr/lib/python3.8/encodings/cp874.py
+-rw-r--r-- root root 12854 ./usr/lib/python3.8/encodings/cp875.py
+-rw-r--r-- root root 1023 ./usr/lib/python3.8/encodings/cp932.py
+-rw-r--r-- root root 1023 ./usr/lib/python3.8/encodings/cp949.py
+-rw-r--r-- root root 1023 ./usr/lib/python3.8/encodings/cp950.py
+-rw-r--r-- root root 1051 ./usr/lib/python3.8/encodings/euc_jis_2004.py
+-rw-r--r-- root root 1051 ./usr/lib/python3.8/encodings/euc_jisx0213.py
+-rw-r--r-- root root 1027 ./usr/lib/python3.8/encodings/euc_jp.py
+-rw-r--r-- root root 1027 ./usr/lib/python3.8/encodings/euc_kr.py
+-rw-r--r-- root root 1031 ./usr/lib/python3.8/encodings/gb18030.py
+-rw-r--r-- root root 1027 ./usr/lib/python3.8/encodings/gb2312.py
+-rw-r--r-- root root 1015 ./usr/lib/python3.8/encodings/gbk.py
+-rw-r--r-- root root 1508 ./usr/lib/python3.8/encodings/hex_codec.py
+-rw-r--r-- root root 13475 ./usr/lib/python3.8/encodings/hp_roman8.py
+-rw-r--r-- root root 1011 ./usr/lib/python3.8/encodings/hz.py
+-rw-r--r-- root root 9170 ./usr/lib/python3.8/encodings/idna.py
+-rw-r--r-- root root 5588 ./usr/lib/python3.8/encodings/__init__.py
+-rw-r--r-- root root 1061 ./usr/lib/python3.8/encodings/iso2022_jp_1.py
+-rw-r--r-- root root 1073 ./usr/lib/python3.8/encodings/iso2022_jp_2004.py
+-rw-r--r-- root root 1061 ./usr/lib/python3.8/encodings/iso2022_jp_2.py
+-rw-r--r-- root root 1061 ./usr/lib/python3.8/encodings/iso2022_jp_3.py
+-rw-r--r-- root root 1069 ./usr/lib/python3.8/encodings/iso2022_jp_ext.py
+-rw-r--r-- root root 1053 ./usr/lib/python3.8/encodings/iso2022_jp.py
+-rw-r--r-- root root 1053 ./usr/lib/python3.8/encodings/iso2022_kr.py
+-rw-r--r-- root root 13589 ./usr/lib/python3.8/encodings/iso8859_10.py
+-rw-r--r-- root root 12335 ./usr/lib/python3.8/encodings/iso8859_11.py
+-rw-r--r-- root root 13271 ./usr/lib/python3.8/encodings/iso8859_13.py
+-rw-r--r-- root root 13652 ./usr/lib/python3.8/encodings/iso8859_14.py
+-rw-r--r-- root root 13212 ./usr/lib/python3.8/encodings/iso8859_15.py
+-rw-r--r-- root root 13557 ./usr/lib/python3.8/encodings/iso8859_16.py
+-rw-r--r-- root root 13176 ./usr/lib/python3.8/encodings/iso8859_1.py
+-rw-r--r-- root root 13404 ./usr/lib/python3.8/encodings/iso8859_2.py
+-rw-r--r-- root root 13089 ./usr/lib/python3.8/encodings/iso8859_3.py
+-rw-r--r-- root root 13376 ./usr/lib/python3.8/encodings/iso8859_4.py
+-rw-r--r-- root root 13015 ./usr/lib/python3.8/encodings/iso8859_5.py
+-rw-r--r-- root root 10833 ./usr/lib/python3.8/encodings/iso8859_6.py
+-rw-r--r-- root root 12844 ./usr/lib/python3.8/encodings/iso8859_7.py
+-rw-r--r-- root root 11036 ./usr/lib/python3.8/encodings/iso8859_8.py
+-rw-r--r-- root root 13156 ./usr/lib/python3.8/encodings/iso8859_9.py
+-rw-r--r-- root root 1023 ./usr/lib/python3.8/encodings/johab.py
+-rw-r--r-- root root 13779 ./usr/lib/python3.8/encodings/koi8_r.py
+-rw-r--r-- root root 13193 ./usr/lib/python3.8/encodings/koi8_t.py
+-rw-r--r-- root root 13762 ./usr/lib/python3.8/encodings/koi8_u.py
+-rw-r--r-- root root 13723 ./usr/lib/python3.8/encodings/kz1048.py
+-rw-r--r-- root root 1264 ./usr/lib/python3.8/encodings/latin_1.py
+-rw-r--r-- root root 36467 ./usr/lib/python3.8/encodings/mac_arabic.py
+-rw-r--r-- root root 14102 ./usr/lib/python3.8/encodings/mac_centeuro.py
+-rw-r--r-- root root 13633 ./usr/lib/python3.8/encodings/mac_croatian.py
+-rw-r--r-- root root 13454 ./usr/lib/python3.8/encodings/mac_cyrillic.py
+-rw-r--r-- root root 15170 ./usr/lib/python3.8/encodings/mac_farsi.py
+-rw-r--r-- root root 13721 ./usr/lib/python3.8/encodings/mac_greek.py
+-rw-r--r-- root root 13498 ./usr/lib/python3.8/encodings/mac_iceland.py
+-rw-r--r-- root root 14118 ./usr/lib/python3.8/encodings/mac_latin2.py
+-rw-r--r-- root root 13661 ./usr/lib/python3.8/encodings/mac_romanian.py
+-rw-r--r-- root root 13480 ./usr/lib/python3.8/encodings/mac_roman.py
+-rw-r--r-- root root 13513 ./usr/lib/python3.8/encodings/mac_turkish.py
+-rw-r--r-- root root 1211 ./usr/lib/python3.8/encodings/mbcs.py
+-rw-r--r-- root root 1019 ./usr/lib/python3.8/encodings/oem.py
+-rw-r--r-- root root 13519 ./usr/lib/python3.8/encodings/palmos.py
+-rw-r--r-- root root 14015 ./usr/lib/python3.8/encodings/ptcp154.py
+-rw-r--r-- root root 6883 ./usr/lib/python3.8/encodings/punycode.py
+drwxr-xr-x root root 20480 ./usr/lib/python3.8/encodings/__pycache__
+-rw-r--r-- root root 6330 ./usr/lib/python3.8/encodings/__pycache__/aliases.cpython-38.opt-1.pyc
+-rw-r--r-- root root 5738 ./usr/lib/python3.8/encodings/__pycache__/aliases.cpython-38.opt-2.pyc
+-rw-r--r-- root root 6330 ./usr/lib/python3.8/encodings/__pycache__/aliases.cpython-38.pyc
+-rw-r--r-- root root 1881 ./usr/lib/python3.8/encodings/__pycache__/ascii.cpython-38.opt-1.pyc
+-rw-r--r-- root root 1735 ./usr/lib/python3.8/encodings/__pycache__/ascii.cpython-38.opt-2.pyc
+-rw-r--r-- root root 1881 ./usr/lib/python3.8/encodings/__pycache__/ascii.cpython-38.pyc
+-rw-r--r-- root root 2295 ./usr/lib/python3.8/encodings/__pycache__/base64_codec.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2120 ./usr/lib/python3.8/encodings/__pycache__/base64_codec.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2399 ./usr/lib/python3.8/encodings/__pycache__/base64_codec.cpython-38.pyc
+-rw-r--r-- root root 1409 ./usr/lib/python3.8/encodings/__pycache__/big5.cpython-38.opt-1.pyc
+-rw-r--r-- root root 1409 ./usr/lib/python3.8/encodings/__pycache__/big5.cpython-38.opt-2.pyc
+-rw-r--r-- root root 1409 ./usr/lib/python3.8/encodings/__pycache__/big5.cpython-38.pyc
+-rw-r--r-- root root 1419 ./usr/lib/python3.8/encodings/__pycache__/big5hkscs.cpython-38.opt-1.pyc
+-rw-r--r-- root root 1419 ./usr/lib/python3.8/encodings/__pycache__/big5hkscs.cpython-38.opt-2.pyc
+-rw-r--r-- root root 1419 ./usr/lib/python3.8/encodings/__pycache__/big5hkscs.cpython-38.pyc
+-rw-r--r-- root root 3200 ./usr/lib/python3.8/encodings/__pycache__/bz2_codec.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2904 ./usr/lib/python3.8/encodings/__pycache__/bz2_codec.cpython-38.opt-2.pyc
+-rw-r--r-- root root 3290 ./usr/lib/python3.8/encodings/__pycache__/bz2_codec.cpython-38.pyc
+-rw-r--r-- root root 2891 ./usr/lib/python3.8/encodings/__pycache__/charmap.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2597 ./usr/lib/python3.8/encodings/__pycache__/charmap.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2891 ./usr/lib/python3.8/encodings/__pycache__/charmap.cpython-38.pyc
+-rw-r--r-- root root 2422 ./usr/lib/python3.8/encodings/__pycache__/cp037.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2290 ./usr/lib/python3.8/encodings/__pycache__/cp037.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2422 ./usr/lib/python3.8/encodings/__pycache__/cp037.cpython-38.pyc
+-rw-r--r-- root root 2498 ./usr/lib/python3.8/encodings/__pycache__/cp1006.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2373 ./usr/lib/python3.8/encodings/__pycache__/cp1006.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2498 ./usr/lib/python3.8/encodings/__pycache__/cp1006.cpython-38.pyc
+-rw-r--r-- root root 2426 ./usr/lib/python3.8/encodings/__pycache__/cp1026.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2292 ./usr/lib/python3.8/encodings/__pycache__/cp1026.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2426 ./usr/lib/python3.8/encodings/__pycache__/cp1026.cpython-38.pyc
+-rw-r--r-- root root 8129 ./usr/lib/python3.8/encodings/__pycache__/cp1125.cpython-38.opt-1.pyc
+-rw-r--r-- root root 8066 ./usr/lib/python3.8/encodings/__pycache__/cp1125.cpython-38.opt-2.pyc
+-rw-r--r-- root root 8129 ./usr/lib/python3.8/encodings/__pycache__/cp1125.cpython-38.pyc
+-rw-r--r-- root root 2412 ./usr/lib/python3.8/encodings/__pycache__/cp1140.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2293 ./usr/lib/python3.8/encodings/__pycache__/cp1140.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2412 ./usr/lib/python3.8/encodings/__pycache__/cp1140.cpython-38.pyc
+-rw-r--r-- root root 2449 ./usr/lib/python3.8/encodings/__pycache__/cp1250.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2314 ./usr/lib/python3.8/encodings/__pycache__/cp1250.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2449 ./usr/lib/python3.8/encodings/__pycache__/cp1250.cpython-38.pyc
+-rw-r--r-- root root 2446 ./usr/lib/python3.8/encodings/__pycache__/cp1251.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2311 ./usr/lib/python3.8/encodings/__pycache__/cp1251.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2446 ./usr/lib/python3.8/encodings/__pycache__/cp1251.cpython-38.pyc
+-rw-r--r-- root root 2449 ./usr/lib/python3.8/encodings/__pycache__/cp1252.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2314 ./usr/lib/python3.8/encodings/__pycache__/cp1252.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2449 ./usr/lib/python3.8/encodings/__pycache__/cp1252.cpython-38.pyc
+-rw-r--r-- root root 2462 ./usr/lib/python3.8/encodings/__pycache__/cp1253.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2327 ./usr/lib/python3.8/encodings/__pycache__/cp1253.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2462 ./usr/lib/python3.8/encodings/__pycache__/cp1253.cpython-38.pyc
+-rw-r--r-- root root 2451 ./usr/lib/python3.8/encodings/__pycache__/cp1254.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2316 ./usr/lib/python3.8/encodings/__pycache__/cp1254.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2451 ./usr/lib/python3.8/encodings/__pycache__/cp1254.cpython-38.pyc
+-rw-r--r-- root root 2470 ./usr/lib/python3.8/encodings/__pycache__/cp1255.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2335 ./usr/lib/python3.8/encodings/__pycache__/cp1255.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2470 ./usr/lib/python3.8/encodings/__pycache__/cp1255.cpython-38.pyc
+-rw-r--r-- root root 2448 ./usr/lib/python3.8/encodings/__pycache__/cp1256.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2313 ./usr/lib/python3.8/encodings/__pycache__/cp1256.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2448 ./usr/lib/python3.8/encodings/__pycache__/cp1256.cpython-38.pyc
+-rw-r--r-- root root 2456 ./usr/lib/python3.8/encodings/__pycache__/cp1257.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2321 ./usr/lib/python3.8/encodings/__pycache__/cp1257.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2456 ./usr/lib/python3.8/encodings/__pycache__/cp1257.cpython-38.pyc
+-rw-r--r-- root root 2454 ./usr/lib/python3.8/encodings/__pycache__/cp1258.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2319 ./usr/lib/python3.8/encodings/__pycache__/cp1258.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2454 ./usr/lib/python3.8/encodings/__pycache__/cp1258.cpython-38.pyc
+-rw-r--r-- root root 2408 ./usr/lib/python3.8/encodings/__pycache__/cp273.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2291 ./usr/lib/python3.8/encodings/__pycache__/cp273.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2408 ./usr/lib/python3.8/encodings/__pycache__/cp273.cpython-38.pyc
+-rw-r--r-- root root 2452 ./usr/lib/python3.8/encodings/__pycache__/cp424.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2329 ./usr/lib/python3.8/encodings/__pycache__/cp424.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2452 ./usr/lib/python3.8/encodings/__pycache__/cp424.cpython-38.pyc
+-rw-r--r-- root root 7846 ./usr/lib/python3.8/encodings/__pycache__/cp437.cpython-38.opt-1.pyc
+-rw-r--r-- root root 7725 ./usr/lib/python3.8/encodings/__pycache__/cp437.cpython-38.opt-2.pyc
+-rw-r--r-- root root 7846 ./usr/lib/python3.8/encodings/__pycache__/cp437.cpython-38.pyc
+-rw-r--r-- root root 2422 ./usr/lib/python3.8/encodings/__pycache__/cp500.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2290 ./usr/lib/python3.8/encodings/__pycache__/cp500.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2422 ./usr/lib/python3.8/encodings/__pycache__/cp500.cpython-38.pyc
+-rw-r--r-- root root 2519 ./usr/lib/python3.8/encodings/__pycache__/cp720.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2344 ./usr/lib/python3.8/encodings/__pycache__/cp720.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2519 ./usr/lib/python3.8/encodings/__pycache__/cp720.cpython-38.pyc
+-rw-r--r-- root root 8168 ./usr/lib/python3.8/encodings/__pycache__/cp737.cpython-38.opt-1.pyc
+-rw-r--r-- root root 8047 ./usr/lib/python3.8/encodings/__pycache__/cp737.cpython-38.opt-2.pyc
+-rw-r--r-- root root 8168 ./usr/lib/python3.8/encodings/__pycache__/cp737.cpython-38.pyc
+-rw-r--r-- root root 7876 ./usr/lib/python3.8/encodings/__pycache__/cp775.cpython-38.opt-1.pyc
+-rw-r--r-- root root 7755 ./usr/lib/python3.8/encodings/__pycache__/cp775.cpython-38.opt-2.pyc
+-rw-r--r-- root root 7876 ./usr/lib/python3.8/encodings/__pycache__/cp775.cpython-38.pyc
+-rw-r--r-- root root 7507 ./usr/lib/python3.8/encodings/__pycache__/cp850.cpython-38.opt-1.pyc
+-rw-r--r-- root root 7392 ./usr/lib/python3.8/encodings/__pycache__/cp850.cpython-38.opt-2.pyc
+-rw-r--r-- root root 7507 ./usr/lib/python3.8/encodings/__pycache__/cp850.cpython-38.pyc
+-rw-r--r-- root root 7884 ./usr/lib/python3.8/encodings/__pycache__/cp852.cpython-38.opt-1.pyc
+-rw-r--r-- root root 7769 ./usr/lib/python3.8/encodings/__pycache__/cp852.cpython-38.opt-2.pyc
+-rw-r--r-- root root 7884 ./usr/lib/python3.8/encodings/__pycache__/cp852.cpython-38.pyc
+-rw-r--r-- root root 8137 ./usr/lib/python3.8/encodings/__pycache__/cp855.cpython-38.opt-1.pyc
+-rw-r--r-- root root 8022 ./usr/lib/python3.8/encodings/__pycache__/cp855.cpython-38.opt-2.pyc
+-rw-r--r-- root root 8137 ./usr/lib/python3.8/encodings/__pycache__/cp855.cpython-38.pyc
+-rw-r--r-- root root 2484 ./usr/lib/python3.8/encodings/__pycache__/cp856.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2361 ./usr/lib/python3.8/encodings/__pycache__/cp856.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2484 ./usr/lib/python3.8/encodings/__pycache__/cp856.cpython-38.pyc
+-rw-r--r-- root root 7487 ./usr/lib/python3.8/encodings/__pycache__/cp857.cpython-38.opt-1.pyc
+-rw-r--r-- root root 7372 ./usr/lib/python3.8/encodings/__pycache__/cp857.cpython-38.opt-2.pyc
+-rw-r--r-- root root 7487 ./usr/lib/python3.8/encodings/__pycache__/cp857.cpython-38.pyc
+-rw-r--r-- root root 7477 ./usr/lib/python3.8/encodings/__pycache__/cp858.cpython-38.opt-1.pyc
+-rw-r--r-- root root 7393 ./usr/lib/python3.8/encodings/__pycache__/cp858.cpython-38.opt-2.pyc
+-rw-r--r-- root root 7477 ./usr/lib/python3.8/encodings/__pycache__/cp858.cpython-38.pyc
+-rw-r--r-- root root 7825 ./usr/lib/python3.8/encodings/__pycache__/cp860.cpython-38.opt-1.pyc
+-rw-r--r-- root root 7710 ./usr/lib/python3.8/encodings/__pycache__/cp860.cpython-38.opt-2.pyc
+-rw-r--r-- root root 7825 ./usr/lib/python3.8/encodings/__pycache__/cp860.cpython-38.pyc
+-rw-r--r-- root root 7840 ./usr/lib/python3.8/encodings/__pycache__/cp861.cpython-38.opt-1.pyc
+-rw-r--r-- root root 7725 ./usr/lib/python3.8/encodings/__pycache__/cp861.cpython-38.opt-2.pyc
+-rw-r--r-- root root 7840 ./usr/lib/python3.8/encodings/__pycache__/cp861.cpython-38.pyc
+-rw-r--r-- root root 8029 ./usr/lib/python3.8/encodings/__pycache__/cp862.cpython-38.opt-1.pyc
+-rw-r--r-- root root 7914 ./usr/lib/python3.8/encodings/__pycache__/cp862.cpython-38.opt-2.pyc
+-rw-r--r-- root root 8029 ./usr/lib/python3.8/encodings/__pycache__/cp862.cpython-38.pyc
+-rw-r--r-- root root 7840 ./usr/lib/python3.8/encodings/__pycache__/cp863.cpython-38.opt-1.pyc
+-rw-r--r-- root root 7725 ./usr/lib/python3.8/encodings/__pycache__/cp863.cpython-38.opt-2.pyc
+-rw-r--r-- root root 7840 ./usr/lib/python3.8/encodings/__pycache__/cp863.cpython-38.pyc
+-rw-r--r-- root root 7984 ./usr/lib/python3.8/encodings/__pycache__/cp864.cpython-38.opt-1.pyc
+-rw-r--r-- root root 7869 ./usr/lib/python3.8/encodings/__pycache__/cp864.cpython-38.opt-2.pyc
+-rw-r--r-- root root 7984 ./usr/lib/python3.8/encodings/__pycache__/cp864.cpython-38.pyc
+-rw-r--r-- root root 7840 ./usr/lib/python3.8/encodings/__pycache__/cp865.cpython-38.opt-1.pyc
+-rw-r--r-- root root 7725 ./usr/lib/python3.8/encodings/__pycache__/cp865.cpython-38.opt-2.pyc
+-rw-r--r-- root root 7840 ./usr/lib/python3.8/encodings/__pycache__/cp865.cpython-38.pyc
+-rw-r--r-- root root 8173 ./usr/lib/python3.8/encodings/__pycache__/cp866.cpython-38.opt-1.pyc
+-rw-r--r-- root root 8058 ./usr/lib/python3.8/encodings/__pycache__/cp866.cpython-38.opt-2.pyc
+-rw-r--r-- root root 8173 ./usr/lib/python3.8/encodings/__pycache__/cp866.cpython-38.pyc
+-rw-r--r-- root root 7864 ./usr/lib/python3.8/encodings/__pycache__/cp869.cpython-38.opt-1.pyc
+-rw-r--r-- root root 7749 ./usr/lib/python3.8/encodings/__pycache__/cp869.cpython-38.opt-2.pyc
+-rw-r--r-- root root 7864 ./usr/lib/python3.8/encodings/__pycache__/cp869.cpython-38.pyc
+-rw-r--r-- root root 2550 ./usr/lib/python3.8/encodings/__pycache__/cp874.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2417 ./usr/lib/python3.8/encodings/__pycache__/cp874.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2550 ./usr/lib/python3.8/encodings/__pycache__/cp874.cpython-38.pyc
+-rw-r--r-- root root 2419 ./usr/lib/python3.8/encodings/__pycache__/cp875.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2287 ./usr/lib/python3.8/encodings/__pycache__/cp875.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2419 ./usr/lib/python3.8/encodings/__pycache__/cp875.cpython-38.pyc
+-rw-r--r-- root root 1411 ./usr/lib/python3.8/encodings/__pycache__/cp932.cpython-38.opt-1.pyc
+-rw-r--r-- root root 1411 ./usr/lib/python3.8/encodings/__pycache__/cp932.cpython-38.opt-2.pyc
+-rw-r--r-- root root 1411 ./usr/lib/python3.8/encodings/__pycache__/cp932.cpython-38.pyc
+-rw-r--r-- root root 1411 ./usr/lib/python3.8/encodings/__pycache__/cp949.cpython-38.opt-1.pyc
+-rw-r--r-- root root 1411 ./usr/lib/python3.8/encodings/__pycache__/cp949.cpython-38.opt-2.pyc
+-rw-r--r-- root root 1411 ./usr/lib/python3.8/encodings/__pycache__/cp949.cpython-38.pyc
+-rw-r--r-- root root 1411 ./usr/lib/python3.8/encodings/__pycache__/cp950.cpython-38.opt-1.pyc
+-rw-r--r-- root root 1411 ./usr/lib/python3.8/encodings/__pycache__/cp950.cpython-38.opt-2.pyc
+-rw-r--r-- root root 1411 ./usr/lib/python3.8/encodings/__pycache__/cp950.cpython-38.pyc
+-rw-r--r-- root root 1425 ./usr/lib/python3.8/encodings/__pycache__/euc_jis_2004.cpython-38.opt-1.pyc
+-rw-r--r-- root root 1425 ./usr/lib/python3.8/encodings/__pycache__/euc_jis_2004.cpython-38.opt-2.pyc
+-rw-r--r-- root root 1425 ./usr/lib/python3.8/encodings/__pycache__/euc_jis_2004.cpython-38.pyc
+-rw-r--r-- root root 1425 ./usr/lib/python3.8/encodings/__pycache__/euc_jisx0213.cpython-38.opt-1.pyc
+-rw-r--r-- root root 1425 ./usr/lib/python3.8/encodings/__pycache__/euc_jisx0213.cpython-38.opt-2.pyc
+-rw-r--r-- root root 1425 ./usr/lib/python3.8/encodings/__pycache__/euc_jisx0213.cpython-38.pyc
+-rw-r--r-- root root 1413 ./usr/lib/python3.8/encodings/__pycache__/euc_jp.cpython-38.opt-1.pyc
+-rw-r--r-- root root 1413 ./usr/lib/python3.8/encodings/__pycache__/euc_jp.cpython-38.opt-2.pyc
+-rw-r--r-- root root 1413 ./usr/lib/python3.8/encodings/__pycache__/euc_jp.cpython-38.pyc
+-rw-r--r-- root root 1413 ./usr/lib/python3.8/encodings/__pycache__/euc_kr.cpython-38.opt-1.pyc
+-rw-r--r-- root root 1413 ./usr/lib/python3.8/encodings/__pycache__/euc_kr.cpython-38.opt-2.pyc
+-rw-r--r-- root root 1413 ./usr/lib/python3.8/encodings/__pycache__/euc_kr.cpython-38.pyc
+-rw-r--r-- root root 1415 ./usr/lib/python3.8/encodings/__pycache__/gb18030.cpython-38.opt-1.pyc
+-rw-r--r-- root root 1415 ./usr/lib/python3.8/encodings/__pycache__/gb18030.cpython-38.opt-2.pyc
+-rw-r--r-- root root 1415 ./usr/lib/python3.8/encodings/__pycache__/gb18030.cpython-38.pyc
+-rw-r--r-- root root 1413 ./usr/lib/python3.8/encodings/__pycache__/gb2312.cpython-38.opt-1.pyc
+-rw-r--r-- root root 1413 ./usr/lib/python3.8/encodings/__pycache__/gb2312.cpython-38.opt-2.pyc
+-rw-r--r-- root root 1413 ./usr/lib/python3.8/encodings/__pycache__/gb2312.cpython-38.pyc
+-rw-r--r-- root root 1407 ./usr/lib/python3.8/encodings/__pycache__/gbk.cpython-38.opt-1.pyc
+-rw-r--r-- root root 1407 ./usr/lib/python3.8/encodings/__pycache__/gbk.cpython-38.opt-2.pyc
+-rw-r--r-- root root 1407 ./usr/lib/python3.8/encodings/__pycache__/gbk.cpython-38.pyc
+-rw-r--r-- root root 2282 ./usr/lib/python3.8/encodings/__pycache__/hex_codec.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2105 ./usr/lib/python3.8/encodings/__pycache__/hex_codec.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2386 ./usr/lib/python3.8/encodings/__pycache__/hex_codec.cpython-38.pyc
+-rw-r--r-- root root 2623 ./usr/lib/python3.8/encodings/__pycache__/hp_roman8.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2302 ./usr/lib/python3.8/encodings/__pycache__/hp_roman8.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2623 ./usr/lib/python3.8/encodings/__pycache__/hp_roman8.cpython-38.pyc
+-rw-r--r-- root root 1405 ./usr/lib/python3.8/encodings/__pycache__/hz.cpython-38.opt-1.pyc
+-rw-r--r-- root root 1405 ./usr/lib/python3.8/encodings/__pycache__/hz.cpython-38.opt-2.pyc
+-rw-r--r-- root root 1405 ./usr/lib/python3.8/encodings/__pycache__/hz.cpython-38.pyc
+-rw-r--r-- root root 5617 ./usr/lib/python3.8/encodings/__pycache__/idna.cpython-38.opt-1.pyc
+-rw-r--r-- root root 5617 ./usr/lib/python3.8/encodings/__pycache__/idna.cpython-38.opt-2.pyc
+-rw-r--r-- root root 5617 ./usr/lib/python3.8/encodings/__pycache__/idna.cpython-38.pyc
+-rw-r--r-- root root 3903 ./usr/lib/python3.8/encodings/__pycache__/__init__.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2448 ./usr/lib/python3.8/encodings/__pycache__/__init__.cpython-38.opt-2.pyc
+-rw-r--r-- root root 3903 ./usr/lib/python3.8/encodings/__pycache__/__init__.cpython-38.pyc
+-rw-r--r-- root root 1430 ./usr/lib/python3.8/encodings/__pycache__/iso2022_jp_1.cpython-38.opt-1.pyc
+-rw-r--r-- root root 1430 ./usr/lib/python3.8/encodings/__pycache__/iso2022_jp_1.cpython-38.opt-2.pyc
+-rw-r--r-- root root 1430 ./usr/lib/python3.8/encodings/__pycache__/iso2022_jp_1.cpython-38.pyc
+-rw-r--r-- root root 1436 ./usr/lib/python3.8/encodings/__pycache__/iso2022_jp_2004.cpython-38.opt-1.pyc
+-rw-r--r-- root root 1436 ./usr/lib/python3.8/encodings/__pycache__/iso2022_jp_2004.cpython-38.opt-2.pyc
+-rw-r--r-- root root 1436 ./usr/lib/python3.8/encodings/__pycache__/iso2022_jp_2004.cpython-38.pyc
+-rw-r--r-- root root 1430 ./usr/lib/python3.8/encodings/__pycache__/iso2022_jp_2.cpython-38.opt-1.pyc
+-rw-r--r-- root root 1430 ./usr/lib/python3.8/encodings/__pycache__/iso2022_jp_2.cpython-38.opt-2.pyc
+-rw-r--r-- root root 1430 ./usr/lib/python3.8/encodings/__pycache__/iso2022_jp_2.cpython-38.pyc
+-rw-r--r-- root root 1430 ./usr/lib/python3.8/encodings/__pycache__/iso2022_jp_3.cpython-38.opt-1.pyc
+-rw-r--r-- root root 1430 ./usr/lib/python3.8/encodings/__pycache__/iso2022_jp_3.cpython-38.opt-2.pyc
+-rw-r--r-- root root 1430 ./usr/lib/python3.8/encodings/__pycache__/iso2022_jp_3.cpython-38.pyc
+-rw-r--r-- root root 1426 ./usr/lib/python3.8/encodings/__pycache__/iso2022_jp.cpython-38.opt-1.pyc
+-rw-r--r-- root root 1426 ./usr/lib/python3.8/encodings/__pycache__/iso2022_jp.cpython-38.opt-2.pyc
+-rw-r--r-- root root 1426 ./usr/lib/python3.8/encodings/__pycache__/iso2022_jp.cpython-38.pyc
+-rw-r--r-- root root 1434 ./usr/lib/python3.8/encodings/__pycache__/iso2022_jp_ext.cpython-38.opt-1.pyc
+-rw-r--r-- root root 1434 ./usr/lib/python3.8/encodings/__pycache__/iso2022_jp_ext.cpython-38.opt-2.pyc
+-rw-r--r-- root root 1434 ./usr/lib/python3.8/encodings/__pycache__/iso2022_jp_ext.cpython-38.pyc
+-rw-r--r-- root root 1426 ./usr/lib/python3.8/encodings/__pycache__/iso2022_kr.cpython-38.opt-1.pyc
+-rw-r--r-- root root 1426 ./usr/lib/python3.8/encodings/__pycache__/iso2022_kr.cpython-38.opt-2.pyc
+-rw-r--r-- root root 1426 ./usr/lib/python3.8/encodings/__pycache__/iso2022_kr.cpython-38.pyc
+-rw-r--r-- root root 2426 ./usr/lib/python3.8/encodings/__pycache__/iso8859_10.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2301 ./usr/lib/python3.8/encodings/__pycache__/iso8859_10.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2426 ./usr/lib/python3.8/encodings/__pycache__/iso8859_10.cpython-38.pyc
+-rw-r--r-- root root 2520 ./usr/lib/python3.8/encodings/__pycache__/iso8859_11.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2395 ./usr/lib/python3.8/encodings/__pycache__/iso8859_11.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2520 ./usr/lib/python3.8/encodings/__pycache__/iso8859_11.cpython-38.pyc
+-rw-r--r-- root root 2429 ./usr/lib/python3.8/encodings/__pycache__/iso8859_13.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2304 ./usr/lib/python3.8/encodings/__pycache__/iso8859_13.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2429 ./usr/lib/python3.8/encodings/__pycache__/iso8859_13.cpython-38.pyc
+-rw-r--r-- root root 2447 ./usr/lib/python3.8/encodings/__pycache__/iso8859_14.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2322 ./usr/lib/python3.8/encodings/__pycache__/iso8859_14.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2447 ./usr/lib/python3.8/encodings/__pycache__/iso8859_14.cpython-38.pyc
+-rw-r--r-- root root 2426 ./usr/lib/python3.8/encodings/__pycache__/iso8859_15.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2301 ./usr/lib/python3.8/encodings/__pycache__/iso8859_15.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2426 ./usr/lib/python3.8/encodings/__pycache__/iso8859_15.cpython-38.pyc
+-rw-r--r-- root root 2428 ./usr/lib/python3.8/encodings/__pycache__/iso8859_16.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2303 ./usr/lib/python3.8/encodings/__pycache__/iso8859_16.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2428 ./usr/lib/python3.8/encodings/__pycache__/iso8859_16.cpython-38.pyc
+-rw-r--r-- root root 2421 ./usr/lib/python3.8/encodings/__pycache__/iso8859_1.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2298 ./usr/lib/python3.8/encodings/__pycache__/iso8859_1.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2421 ./usr/lib/python3.8/encodings/__pycache__/iso8859_1.cpython-38.pyc
+-rw-r--r-- root root 2421 ./usr/lib/python3.8/encodings/__pycache__/iso8859_2.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2298 ./usr/lib/python3.8/encodings/__pycache__/iso8859_2.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2421 ./usr/lib/python3.8/encodings/__pycache__/iso8859_2.cpython-38.pyc
+-rw-r--r-- root root 2428 ./usr/lib/python3.8/encodings/__pycache__/iso8859_3.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2305 ./usr/lib/python3.8/encodings/__pycache__/iso8859_3.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2428 ./usr/lib/python3.8/encodings/__pycache__/iso8859_3.cpython-38.pyc
+-rw-r--r-- root root 2421 ./usr/lib/python3.8/encodings/__pycache__/iso8859_4.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2298 ./usr/lib/python3.8/encodings/__pycache__/iso8859_4.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2421 ./usr/lib/python3.8/encodings/__pycache__/iso8859_4.cpython-38.pyc
+-rw-r--r-- root root 2422 ./usr/lib/python3.8/encodings/__pycache__/iso8859_5.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2299 ./usr/lib/python3.8/encodings/__pycache__/iso8859_5.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2422 ./usr/lib/python3.8/encodings/__pycache__/iso8859_5.cpython-38.pyc
+-rw-r--r-- root root 2466 ./usr/lib/python3.8/encodings/__pycache__/iso8859_6.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2343 ./usr/lib/python3.8/encodings/__pycache__/iso8859_6.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2466 ./usr/lib/python3.8/encodings/__pycache__/iso8859_6.cpython-38.pyc
+-rw-r--r-- root root 2429 ./usr/lib/python3.8/encodings/__pycache__/iso8859_7.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2306 ./usr/lib/python3.8/encodings/__pycache__/iso8859_7.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2429 ./usr/lib/python3.8/encodings/__pycache__/iso8859_7.cpython-38.pyc
+-rw-r--r-- root root 2460 ./usr/lib/python3.8/encodings/__pycache__/iso8859_8.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2337 ./usr/lib/python3.8/encodings/__pycache__/iso8859_8.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2460 ./usr/lib/python3.8/encodings/__pycache__/iso8859_8.cpython-38.pyc
+-rw-r--r-- root root 2421 ./usr/lib/python3.8/encodings/__pycache__/iso8859_9.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2298 ./usr/lib/python3.8/encodings/__pycache__/iso8859_9.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2421 ./usr/lib/python3.8/encodings/__pycache__/iso8859_9.cpython-38.pyc
+-rw-r--r-- root root 1411 ./usr/lib/python3.8/encodings/__pycache__/johab.cpython-38.opt-1.pyc
+-rw-r--r-- root root 1411 ./usr/lib/python3.8/encodings/__pycache__/johab.cpython-38.opt-2.pyc
+-rw-r--r-- root root 1411 ./usr/lib/python3.8/encodings/__pycache__/johab.cpython-38.pyc
+-rw-r--r-- root root 2473 ./usr/lib/python3.8/encodings/__pycache__/koi8_r.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2348 ./usr/lib/python3.8/encodings/__pycache__/koi8_r.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2473 ./usr/lib/python3.8/encodings/__pycache__/koi8_r.cpython-38.pyc
+-rw-r--r-- root root 2384 ./usr/lib/python3.8/encodings/__pycache__/koi8_t.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2328 ./usr/lib/python3.8/encodings/__pycache__/koi8_t.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2384 ./usr/lib/python3.8/encodings/__pycache__/koi8_t.cpython-38.pyc
+-rw-r--r-- root root 2459 ./usr/lib/python3.8/encodings/__pycache__/koi8_u.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2340 ./usr/lib/python3.8/encodings/__pycache__/koi8_u.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2459 ./usr/lib/python3.8/encodings/__pycache__/koi8_u.cpython-38.pyc
+-rw-r--r-- root root 2436 ./usr/lib/python3.8/encodings/__pycache__/kz1048.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2311 ./usr/lib/python3.8/encodings/__pycache__/kz1048.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2436 ./usr/lib/python3.8/encodings/__pycache__/kz1048.cpython-38.pyc
+-rw-r--r-- root root 1893 ./usr/lib/python3.8/encodings/__pycache__/latin_1.cpython-38.opt-1.pyc
+-rw-r--r-- root root 1745 ./usr/lib/python3.8/encodings/__pycache__/latin_1.cpython-38.opt-2.pyc
+-rw-r--r-- root root 1893 ./usr/lib/python3.8/encodings/__pycache__/latin_1.cpython-38.pyc
+-rw-r--r-- root root 7740 ./usr/lib/python3.8/encodings/__pycache__/mac_arabic.cpython-38.opt-1.pyc
+-rw-r--r-- root root 7628 ./usr/lib/python3.8/encodings/__pycache__/mac_arabic.cpython-38.opt-2.pyc
+-rw-r--r-- root root 7740 ./usr/lib/python3.8/encodings/__pycache__/mac_arabic.cpython-38.pyc
+-rw-r--r-- root root 2460 ./usr/lib/python3.8/encodings/__pycache__/mac_centeuro.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2326 ./usr/lib/python3.8/encodings/__pycache__/mac_centeuro.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2460 ./usr/lib/python3.8/encodings/__pycache__/mac_centeuro.cpython-38.pyc
+-rw-r--r-- root root 2468 ./usr/lib/python3.8/encodings/__pycache__/mac_croatian.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2334 ./usr/lib/python3.8/encodings/__pycache__/mac_croatian.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2468 ./usr/lib/python3.8/encodings/__pycache__/mac_croatian.cpython-38.pyc
+-rw-r--r-- root root 2458 ./usr/lib/python3.8/encodings/__pycache__/mac_cyrillic.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2324 ./usr/lib/python3.8/encodings/__pycache__/mac_cyrillic.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2458 ./usr/lib/python3.8/encodings/__pycache__/mac_cyrillic.cpython-38.pyc
+-rw-r--r-- root root 2402 ./usr/lib/python3.8/encodings/__pycache__/mac_farsi.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2274 ./usr/lib/python3.8/encodings/__pycache__/mac_farsi.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2402 ./usr/lib/python3.8/encodings/__pycache__/mac_farsi.cpython-38.pyc
+-rw-r--r-- root root 2442 ./usr/lib/python3.8/encodings/__pycache__/mac_greek.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2314 ./usr/lib/python3.8/encodings/__pycache__/mac_greek.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2442 ./usr/lib/python3.8/encodings/__pycache__/mac_greek.cpython-38.pyc
+-rw-r--r-- root root 2461 ./usr/lib/python3.8/encodings/__pycache__/mac_iceland.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2329 ./usr/lib/python3.8/encodings/__pycache__/mac_iceland.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2461 ./usr/lib/python3.8/encodings/__pycache__/mac_iceland.cpython-38.pyc
+-rw-r--r-- root root 2602 ./usr/lib/python3.8/encodings/__pycache__/mac_latin2.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2322 ./usr/lib/python3.8/encodings/__pycache__/mac_latin2.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2602 ./usr/lib/python3.8/encodings/__pycache__/mac_latin2.cpython-38.pyc
+-rw-r--r-- root root 2459 ./usr/lib/python3.8/encodings/__pycache__/mac_roman.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2331 ./usr/lib/python3.8/encodings/__pycache__/mac_roman.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2459 ./usr/lib/python3.8/encodings/__pycache__/mac_roman.cpython-38.pyc
+-rw-r--r-- root root 2469 ./usr/lib/python3.8/encodings/__pycache__/mac_romanian.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2335 ./usr/lib/python3.8/encodings/__pycache__/mac_romanian.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2469 ./usr/lib/python3.8/encodings/__pycache__/mac_romanian.cpython-38.pyc
+-rw-r--r-- root root 2462 ./usr/lib/python3.8/encodings/__pycache__/mac_turkish.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2330 ./usr/lib/python3.8/encodings/__pycache__/mac_turkish.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2462 ./usr/lib/python3.8/encodings/__pycache__/mac_turkish.cpython-38.pyc
+-rw-r--r-- root root 1711 ./usr/lib/python3.8/encodings/__pycache__/mbcs.cpython-38.opt-1.pyc
+-rw-r--r-- root root 1478 ./usr/lib/python3.8/encodings/__pycache__/mbcs.cpython-38.opt-2.pyc
+-rw-r--r-- root root 1711 ./usr/lib/python3.8/encodings/__pycache__/mbcs.cpython-38.pyc
+-rw-r--r-- root root 1524 ./usr/lib/python3.8/encodings/__pycache__/oem.cpython-38.opt-1.pyc
+-rw-r--r-- root root 1474 ./usr/lib/python3.8/encodings/__pycache__/oem.cpython-38.opt-2.pyc
+-rw-r--r-- root root 1524 ./usr/lib/python3.8/encodings/__pycache__/oem.cpython-38.pyc
+-rw-r--r-- root root 2449 ./usr/lib/python3.8/encodings/__pycache__/palmos.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2312 ./usr/lib/python3.8/encodings/__pycache__/palmos.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2449 ./usr/lib/python3.8/encodings/__pycache__/palmos.cpython-38.pyc
+-rw-r--r-- root root 2543 ./usr/lib/python3.8/encodings/__pycache__/ptcp154.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2304 ./usr/lib/python3.8/encodings/__pycache__/ptcp154.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2543 ./usr/lib/python3.8/encodings/__pycache__/ptcp154.cpython-38.pyc
+-rw-r--r-- root root 6315 ./usr/lib/python3.8/encodings/__pycache__/punycode.cpython-38.opt-1.pyc
+-rw-r--r-- root root 5723 ./usr/lib/python3.8/encodings/__pycache__/punycode.cpython-38.opt-2.pyc
+-rw-r--r-- root root 6315 ./usr/lib/python3.8/encodings/__pycache__/punycode.cpython-38.pyc
+-rw-r--r-- root root 2358 ./usr/lib/python3.8/encodings/__pycache__/quopri_codec.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2260 ./usr/lib/python3.8/encodings/__pycache__/quopri_codec.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2415 ./usr/lib/python3.8/encodings/__pycache__/quopri_codec.cpython-38.pyc
+-rw-r--r-- root root 1762 ./usr/lib/python3.8/encodings/__pycache__/raw_unicode_escape.cpython-38.opt-1.pyc
+-rw-r--r-- root root 1603 ./usr/lib/python3.8/encodings/__pycache__/raw_unicode_escape.cpython-38.opt-2.pyc
+-rw-r--r-- root root 1762 ./usr/lib/python3.8/encodings/__pycache__/raw_unicode_escape.cpython-38.pyc
+-rw-r--r-- root root 3001 ./usr/lib/python3.8/encodings/__pycache__/rot_13.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2851 ./usr/lib/python3.8/encodings/__pycache__/rot_13.cpython-38.opt-2.pyc
+-rw-r--r-- root root 3001 ./usr/lib/python3.8/encodings/__pycache__/rot_13.cpython-38.pyc
+-rw-r--r-- root root 1429 ./usr/lib/python3.8/encodings/__pycache__/shift_jis_2004.cpython-38.opt-1.pyc
+-rw-r--r-- root root 1429 ./usr/lib/python3.8/encodings/__pycache__/shift_jis_2004.cpython-38.opt-2.pyc
+-rw-r--r-- root root 1429 ./usr/lib/python3.8/encodings/__pycache__/shift_jis_2004.cpython-38.pyc
+-rw-r--r-- root root 1419 ./usr/lib/python3.8/encodings/__pycache__/shift_jis.cpython-38.opt-1.pyc
+-rw-r--r-- root root 1419 ./usr/lib/python3.8/encodings/__pycache__/shift_jis.cpython-38.opt-2.pyc
+-rw-r--r-- root root 1419 ./usr/lib/python3.8/encodings/__pycache__/shift_jis.cpython-38.pyc
+-rw-r--r-- root root 1429 ./usr/lib/python3.8/encodings/__pycache__/shift_jisx0213.cpython-38.opt-1.pyc
+-rw-r--r-- root root 1429 ./usr/lib/python3.8/encodings/__pycache__/shift_jisx0213.cpython-38.opt-2.pyc
+-rw-r--r-- root root 1429 ./usr/lib/python3.8/encodings/__pycache__/shift_jisx0213.cpython-38.pyc
+-rw-r--r-- root root 2511 ./usr/lib/python3.8/encodings/__pycache__/tis_620.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2390 ./usr/lib/python3.8/encodings/__pycache__/tis_620.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2511 ./usr/lib/python3.8/encodings/__pycache__/tis_620.cpython-38.pyc
+-rw-r--r-- root root 2095 ./usr/lib/python3.8/encodings/__pycache__/undefined.cpython-38.opt-1.pyc
+-rw-r--r-- root root 1766 ./usr/lib/python3.8/encodings/__pycache__/undefined.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2095 ./usr/lib/python3.8/encodings/__pycache__/undefined.cpython-38.pyc
+-rw-r--r-- root root 1742 ./usr/lib/python3.8/encodings/__pycache__/unicode_escape.cpython-38.opt-1.pyc
+-rw-r--r-- root root 1587 ./usr/lib/python3.8/encodings/__pycache__/unicode_escape.cpython-38.opt-2.pyc
+-rw-r--r-- root root 1742 ./usr/lib/python3.8/encodings/__pycache__/unicode_escape.cpython-38.pyc
+-rw-r--r-- root root 1650 ./usr/lib/python3.8/encodings/__pycache__/utf_16_be.cpython-38.opt-1.pyc
+-rw-r--r-- root root 1500 ./usr/lib/python3.8/encodings/__pycache__/utf_16_be.cpython-38.opt-2.pyc
+-rw-r--r-- root root 1650 ./usr/lib/python3.8/encodings/__pycache__/utf_16_be.cpython-38.pyc
+-rw-r--r-- root root 4872 ./usr/lib/python3.8/encodings/__pycache__/utf_16.cpython-38.opt-1.pyc
+-rw-r--r-- root root 4725 ./usr/lib/python3.8/encodings/__pycache__/utf_16.cpython-38.opt-2.pyc
+-rw-r--r-- root root 4872 ./usr/lib/python3.8/encodings/__pycache__/utf_16.cpython-38.pyc
+-rw-r--r-- root root 1650 ./usr/lib/python3.8/encodings/__pycache__/utf_16_le.cpython-38.opt-1.pyc
+-rw-r--r-- root root 1500 ./usr/lib/python3.8/encodings/__pycache__/utf_16_le.cpython-38.opt-2.pyc
+-rw-r--r-- root root 1650 ./usr/lib/python3.8/encodings/__pycache__/utf_16_le.cpython-38.pyc
+-rw-r--r-- root root 1543 ./usr/lib/python3.8/encodings/__pycache__/utf_32_be.cpython-38.opt-1.pyc
+-rw-r--r-- root root 1500 ./usr/lib/python3.8/encodings/__pycache__/utf_32_be.cpython-38.opt-2.pyc
+-rw-r--r-- root root 1543 ./usr/lib/python3.8/encodings/__pycache__/utf_32_be.cpython-38.pyc
+-rw-r--r-- root root 4765 ./usr/lib/python3.8/encodings/__pycache__/utf_32.cpython-38.opt-1.pyc
+-rw-r--r-- root root 4725 ./usr/lib/python3.8/encodings/__pycache__/utf_32.cpython-38.opt-2.pyc
+-rw-r--r-- root root 4765 ./usr/lib/python3.8/encodings/__pycache__/utf_32.cpython-38.pyc
+-rw-r--r-- root root 1543 ./usr/lib/python3.8/encodings/__pycache__/utf_32_le.cpython-38.opt-1.pyc
+-rw-r--r-- root root 1500 ./usr/lib/python3.8/encodings/__pycache__/utf_32_le.cpython-38.opt-2.pyc
+-rw-r--r-- root root 1543 ./usr/lib/python3.8/encodings/__pycache__/utf_32_le.cpython-38.pyc
+-rw-r--r-- root root 1571 ./usr/lib/python3.8/encodings/__pycache__/utf_7.cpython-38.opt-1.pyc
+-rw-r--r-- root root 1484 ./usr/lib/python3.8/encodings/__pycache__/utf_7.cpython-38.opt-2.pyc
+-rw-r--r-- root root 1571 ./usr/lib/python3.8/encodings/__pycache__/utf_7.cpython-38.pyc
+-rw-r--r-- root root 1630 ./usr/lib/python3.8/encodings/__pycache__/utf_8.cpython-38.opt-1.pyc
+-rw-r--r-- root root 1484 ./usr/lib/python3.8/encodings/__pycache__/utf_8.cpython-38.opt-2.pyc
+-rw-r--r-- root root 1630 ./usr/lib/python3.8/encodings/__pycache__/utf_8.cpython-38.pyc
+-rw-r--r-- root root 4546 ./usr/lib/python3.8/encodings/__pycache__/utf_8_sig.cpython-38.opt-1.pyc
+-rw-r--r-- root root 4244 ./usr/lib/python3.8/encodings/__pycache__/utf_8_sig.cpython-38.opt-2.pyc
+-rw-r--r-- root root 4546 ./usr/lib/python3.8/encodings/__pycache__/utf_8_sig.cpython-38.pyc
+-rw-r--r-- root root 3190 ./usr/lib/python3.8/encodings/__pycache__/uu_codec.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2897 ./usr/lib/python3.8/encodings/__pycache__/uu_codec.cpython-38.opt-2.pyc
+-rw-r--r-- root root 3249 ./usr/lib/python3.8/encodings/__pycache__/uu_codec.cpython-38.pyc
+-rw-r--r-- root root 3019 ./usr/lib/python3.8/encodings/__pycache__/zlib_codec.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2853 ./usr/lib/python3.8/encodings/__pycache__/zlib_codec.cpython-38.opt-2.pyc
+-rw-r--r-- root root 3109 ./usr/lib/python3.8/encodings/__pycache__/zlib_codec.cpython-38.pyc
+-rw-r--r-- root root 1525 ./usr/lib/python3.8/encodings/quopri_codec.py
+-rw-r--r-- root root 1208 ./usr/lib/python3.8/encodings/raw_unicode_escape.py
+-rwxr-xr-x root root 2448 ./usr/lib/python3.8/encodings/rot_13.py
+-rw-r--r-- root root 1059 ./usr/lib/python3.8/encodings/shift_jis_2004.py
+-rw-r--r-- root root 1039 ./usr/lib/python3.8/encodings/shift_jis.py
+-rw-r--r-- root root 1059 ./usr/lib/python3.8/encodings/shift_jisx0213.py
+-rw-r--r-- root root 12300 ./usr/lib/python3.8/encodings/tis_620.py
+-rw-r--r-- root root 1299 ./usr/lib/python3.8/encodings/undefined.py
+-rw-r--r-- root root 1184 ./usr/lib/python3.8/encodings/unicode_escape.py
+-rw-r--r-- root root 1037 ./usr/lib/python3.8/encodings/utf_16_be.py
+-rw-r--r-- root root 1037 ./usr/lib/python3.8/encodings/utf_16_le.py
+-rw-r--r-- root root 5236 ./usr/lib/python3.8/encodings/utf_16.py
+-rw-r--r-- root root 930 ./usr/lib/python3.8/encodings/utf_32_be.py
+-rw-r--r-- root root 930 ./usr/lib/python3.8/encodings/utf_32_le.py
+-rw-r--r-- root root 5129 ./usr/lib/python3.8/encodings/utf_32.py
+-rw-r--r-- root root 946 ./usr/lib/python3.8/encodings/utf_7.py
+-rw-r--r-- root root 1005 ./usr/lib/python3.8/encodings/utf_8.py
+-rw-r--r-- root root 4133 ./usr/lib/python3.8/encodings/utf_8_sig.py
+-rw-r--r-- root root 2851 ./usr/lib/python3.8/encodings/uu_codec.py
+-rw-r--r-- root root 2204 ./usr/lib/python3.8/encodings/zlib_codec.py
+-rw-r--r-- root root 34616 ./usr/lib/python3.8/enum.py
+-rw-r--r-- root root 4056 ./usr/lib/python3.8/fnmatch.py
+-rw-r--r-- root root 34768 ./usr/lib/python3.8/ftplib.py
+-rw-r--r-- root root 37406 ./usr/lib/python3.8/functools.py
+-rw-r--r-- root root 5109 ./usr/lib/python3.8/__future__.py
+-rw-r--r-- root root 4975 ./usr/lib/python3.8/genericpath.py
+-rw-r--r-- root root 7489 ./usr/lib/python3.8/getopt.py
+-rw-r--r-- root root 27138 ./usr/lib/python3.8/gettext.py
+-rw-r--r-- root root 5697 ./usr/lib/python3.8/glob.py
+-rw-r--r-- root root 21441 ./usr/lib/python3.8/gzip.py
+-rw-r--r-- root root 9730 ./usr/lib/python3.8/hashlib.py
+-rw-r--r-- root root 22877 ./usr/lib/python3.8/heapq.py
+-rw-r--r-- root root 6629 ./usr/lib/python3.8/hmac.py
+drwxr-xr-x root root 4096 ./usr/lib/python3.8/http
+-rw-r--r-- root root 54908 ./usr/lib/python3.8/http/client.py
+-rw-r--r-- root root 76835 ./usr/lib/python3.8/http/cookiejar.py
+-rw-r--r-- root root 20412 ./usr/lib/python3.8/http/cookies.py
+-rw-r--r-- root root 6378 ./usr/lib/python3.8/http/__init__.py
+drwxr-xr-x root root 4096 ./usr/lib/python3.8/http/__pycache__
+-rw-r--r-- root root 34204 ./usr/lib/python3.8/http/__pycache__/client.cpython-38.opt-1.pyc
+-rw-r--r-- root root 25225 ./usr/lib/python3.8/http/__pycache__/client.cpython-38.opt-2.pyc
+-rw-r--r-- root root 34303 ./usr/lib/python3.8/http/__pycache__/client.cpython-38.pyc
+-rw-r--r-- root root 53442 ./usr/lib/python3.8/http/__pycache__/cookiejar.cpython-38.opt-1.pyc
+-rw-r--r-- root root 37805 ./usr/lib/python3.8/http/__pycache__/cookiejar.cpython-38.opt-2.pyc
+-rw-r--r-- root root 53642 ./usr/lib/python3.8/http/__pycache__/cookiejar.cpython-38.pyc
+-rw-r--r-- root root 15220 ./usr/lib/python3.8/http/__pycache__/cookies.cpython-38.opt-1.pyc
+-rw-r--r-- root root 10823 ./usr/lib/python3.8/http/__pycache__/cookies.cpython-38.opt-2.pyc
+-rw-r--r-- root root 15268 ./usr/lib/python3.8/http/__pycache__/cookies.cpython-38.pyc
+-rw-r--r-- root root 6064 ./usr/lib/python3.8/http/__pycache__/__init__.cpython-38.opt-1.pyc
+-rw-r--r-- root root 5383 ./usr/lib/python3.8/http/__pycache__/__init__.cpython-38.opt-2.pyc
+-rw-r--r-- root root 6064 ./usr/lib/python3.8/http/__pycache__/__init__.cpython-38.pyc
+-rw-r--r-- root root 34392 ./usr/lib/python3.8/http/__pycache__/server.cpython-38.opt-1.pyc
+-rw-r--r-- root root 22456 ./usr/lib/python3.8/http/__pycache__/server.cpython-38.opt-2.pyc
+-rw-r--r-- root root 34392 ./usr/lib/python3.8/http/__pycache__/server.cpython-38.pyc
+-rw-r--r-- root root 47254 ./usr/lib/python3.8/http/server.py
+-rw-r--r-- root root 53606 ./usr/lib/python3.8/imaplib.py
+drwxr-xr-x root root 4096 ./usr/lib/python3.8/importlib
+-rw-r--r-- root root 12873 ./usr/lib/python3.8/importlib/abc.py
+-rw-r--r-- root root 62357 ./usr/lib/python3.8/importlib/_bootstrap_external.py
+-rw-r--r-- root root 39644 ./usr/lib/python3.8/importlib/_bootstrap.py
+-rw-r--r-- root root 6061 ./usr/lib/python3.8/importlib/__init__.py
+-rw-r--r-- root root 844 ./usr/lib/python3.8/importlib/machinery.py
+-rw-r--r-- root root 17607 ./usr/lib/python3.8/importlib/metadata.py
+drwxr-xr-x root root 4096 ./usr/lib/python3.8/importlib/__pycache__
+-rw-r--r-- root root 13573 ./usr/lib/python3.8/importlib/__pycache__/abc.cpython-38.opt-1.pyc
+-rw-r--r-- root root 6762 ./usr/lib/python3.8/importlib/__pycache__/abc.cpython-38.opt-2.pyc
+-rw-r--r-- root root 13573 ./usr/lib/python3.8/importlib/__pycache__/abc.cpython-38.pyc
+-rw-r--r-- root root 28573 ./usr/lib/python3.8/importlib/__pycache__/_bootstrap.cpython-38.opt-1.pyc
+-rw-r--r-- root root 21814 ./usr/lib/python3.8/importlib/__pycache__/_bootstrap.cpython-38.opt-2.pyc
+-rw-r--r-- root root 28605 ./usr/lib/python3.8/importlib/__pycache__/_bootstrap.cpython-38.pyc
+-rw-r--r-- root root 43406 ./usr/lib/python3.8/importlib/__pycache__/_bootstrap_external.cpython-38.opt-1.pyc
+-rw-r--r-- root root 32285 ./usr/lib/python3.8/importlib/__pycache__/_bootstrap_external.cpython-38.opt-2.pyc
+-rw-r--r-- root root 43710 ./usr/lib/python3.8/importlib/__pycache__/_bootstrap_external.cpython-38.pyc
+-rw-r--r-- root root 3758 ./usr/lib/python3.8/importlib/__pycache__/__init__.cpython-38.opt-1.pyc
+-rw-r--r-- root root 3079 ./usr/lib/python3.8/importlib/__pycache__/__init__.cpython-38.opt-2.pyc
+-rw-r--r-- root root 3758 ./usr/lib/python3.8/importlib/__pycache__/__init__.cpython-38.pyc
+-rw-r--r-- root root 962 ./usr/lib/python3.8/importlib/__pycache__/machinery.cpython-38.opt-1.pyc
+-rw-r--r-- root root 822 ./usr/lib/python3.8/importlib/__pycache__/machinery.cpython-38.opt-2.pyc
+-rw-r--r-- root root 962 ./usr/lib/python3.8/importlib/__pycache__/machinery.cpython-38.pyc
+-rw-r--r-- root root 20840 ./usr/lib/python3.8/importlib/__pycache__/metadata.cpython-38.opt-1.pyc
+-rw-r--r-- root root 15073 ./usr/lib/python3.8/importlib/__pycache__/metadata.cpython-38.opt-2.pyc
+-rw-r--r-- root root 20840 ./usr/lib/python3.8/importlib/__pycache__/metadata.cpython-38.pyc
+-rw-r--r-- root root 6480 ./usr/lib/python3.8/importlib/__pycache__/resources.cpython-38.opt-1.pyc
+-rw-r--r-- root root 5135 ./usr/lib/python3.8/importlib/__pycache__/resources.cpython-38.opt-2.pyc
+-rw-r--r-- root root 6480 ./usr/lib/python3.8/importlib/__pycache__/resources.cpython-38.pyc
+-rw-r--r-- root root 9292 ./usr/lib/python3.8/importlib/__pycache__/util.cpython-38.opt-1.pyc
+-rw-r--r-- root root 6423 ./usr/lib/python3.8/importlib/__pycache__/util.cpython-38.opt-2.pyc
+-rw-r--r-- root root 9292 ./usr/lib/python3.8/importlib/__pycache__/util.cpython-38.pyc
+-rw-r--r-- root root 9437 ./usr/lib/python3.8/importlib/resources.py
+-rw-r--r-- root root 11319 ./usr/lib/python3.8/importlib/util.py
+-rw-r--r-- root root 10536 ./usr/lib/python3.8/imp.py
+-rw-r--r-- root root 118040 ./usr/lib/python3.8/inspect.py
+-rw-r--r-- root root 3541 ./usr/lib/python3.8/io.py
+-rw-r--r-- root root 71160 ./usr/lib/python3.8/ipaddress.py
+-rw-r--r-- root root 945 ./usr/lib/python3.8/keyword.py
+drwxr-xr-x root root 4096 ./usr/lib/python3.8/lib-dynload
+-rwxr-xr-x root root 65816 ./usr/lib/python3.8/lib-dynload/array.cpython-38-x86_64-linux-gnu.so
+-rwxr-xr-x root root 31736 ./usr/lib/python3.8/lib-dynload/binascii.cpython-38-x86_64-linux-gnu.so
+-rwxr-xr-x root root 14760 ./usr/lib/python3.8/lib-dynload/_bisect.cpython-38-x86_64-linux-gnu.so
+-rwxr-xr-x root root 44664 ./usr/lib/python3.8/lib-dynload/_blake2.cpython-38-x86_64-linux-gnu.so
+-rwxr-xr-x root root 27896 ./usr/lib/python3.8/lib-dynload/_bz2.cpython-38-x86_64-linux-gnu.so
+-rwxr-xr-x root root 43896 ./usr/lib/python3.8/lib-dynload/cmath.cpython-38-x86_64-linux-gnu.so
+-rwxr-xr-x root root 14384 ./usr/lib/python3.8/lib-dynload/_crypt.cpython-38-x86_64-linux-gnu.so
+-rwxr-xr-x root root 37240 ./usr/lib/python3.8/lib-dynload/_csv.cpython-38-x86_64-linux-gnu.so
+-rwxr-xr-x root root 99712 ./usr/lib/python3.8/lib-dynload/_datetime.cpython-38-x86_64-linux-gnu.so
+-rwxr-xr-x root root 76160 ./usr/lib/python3.8/lib-dynload/_elementtree.cpython-38-x86_64-linux-gnu.so
+-rwxr-xr-x root root 18856 ./usr/lib/python3.8/lib-dynload/grp.cpython-38-x86_64-linux-gnu.so
+-rwxr-xr-x root root 36600 ./usr/lib/python3.8/lib-dynload/_hashlib.cpython-38-x86_64-linux-gnu.so
+-rwxr-xr-x root root 22640 ./usr/lib/python3.8/lib-dynload/_heapq.cpython-38-x86_64-linux-gnu.so
+-rwxr-xr-x root root 40920 ./usr/lib/python3.8/lib-dynload/_lzma.cpython-38-x86_64-linux-gnu.so
+-rwxr-xr-x root root 57208 ./usr/lib/python3.8/lib-dynload/math.cpython-38-x86_64-linux-gnu.so
+-rwxr-xr-x root root 19352 ./usr/lib/python3.8/lib-dynload/_md5.cpython-38-x86_64-linux-gnu.so
+-rwxr-xr-x root root 14520 ./usr/lib/python3.8/lib-dynload/_opcode.cpython-38-x86_64-linux-gnu.so
+-rwxr-xr-x root root 27856 ./usr/lib/python3.8/lib-dynload/parser.cpython-38-x86_64-linux-gnu.so
+-rwxr-xr-x root root 113208 ./usr/lib/python3.8/lib-dynload/_pickle.cpython-38-x86_64-linux-gnu.so
+-rwxr-xr-x root root 22680 ./usr/lib/python3.8/lib-dynload/_posixsubprocess.cpython-38-x86_64-linux-gnu.so
+-rwxr-xr-x root root 233072 ./usr/lib/python3.8/lib-dynload/pyexpat.cpython-38-x86_64-linux-gnu.so
+-rwxr-xr-x root root 19320 ./usr/lib/python3.8/lib-dynload/_queue.cpython-38-x86_64-linux-gnu.so
+-rwxr-xr-x root root 19024 ./usr/lib/python3.8/lib-dynload/_random.cpython-38-x86_64-linux-gnu.so
+-rwxr-xr-x root root 35672 ./usr/lib/python3.8/lib-dynload/readline.cpython-38-x86_64-linux-gnu.so
+-rwxr-xr-x root root 32632 ./usr/lib/python3.8/lib-dynload/select.cpython-38-x86_64-linux-gnu.so
+-rwxr-xr-x root root 15256 ./usr/lib/python3.8/lib-dynload/_sha1.cpython-38-x86_64-linux-gnu.so
+-rwxr-xr-x root root 24024 ./usr/lib/python3.8/lib-dynload/_sha256.cpython-38-x86_64-linux-gnu.so
+-rwxr-xr-x root root 82960 ./usr/lib/python3.8/lib-dynload/_sha3.cpython-38-x86_64-linux-gnu.so
+-rwxr-xr-x root root 28120 ./usr/lib/python3.8/lib-dynload/_sha512.cpython-38-x86_64-linux-gnu.so
+-rwxr-xr-x root root 99056 ./usr/lib/python3.8/lib-dynload/_socket.cpython-38-x86_64-linux-gnu.so
+-rwxr-xr-x root root 191272 ./usr/lib/python3.8/lib-dynload/_ssl.cpython-38-x86_64-linux-gnu.so
+-rwxr-xr-x root root 50392 ./usr/lib/python3.8/lib-dynload/_struct.cpython-38-x86_64-linux-gnu.so
+-rwxr-xr-x root root 30576 ./usr/lib/python3.8/lib-dynload/termios.cpython-38-x86_64-linux-gnu.so
+-rwxr-xr-x root root 1091200 ./usr/lib/python3.8/lib-dynload/unicodedata.cpython-38-x86_64-linux-gnu.so
+-rwxr-xr-x root root 14384 ./usr/lib/python3.8/lib-dynload/_uuid.cpython-38-x86_64-linux-gnu.so
+-rwxr-xr-x root root 40888 ./usr/lib/python3.8/lib-dynload/zlib.cpython-38-x86_64-linux-gnu.so
+-rw-r--r-- root root 5312 ./usr/lib/python3.8/linecache.py
+-rw-r--r-- root root 78191 ./usr/lib/python3.8/locale.py
+drwxr-xr-x root root 4096 ./usr/lib/python3.8/logging
+-rw-r--r-- root root 36357 ./usr/lib/python3.8/logging/config.py
+-rw-r--r-- root root 57885 ./usr/lib/python3.8/logging/handlers.py
+-rw-r--r-- root root 77642 ./usr/lib/python3.8/logging/__init__.py
+drwxr-xr-x root root 4096 ./usr/lib/python3.8/logging/__pycache__
+-rw-r--r-- root root 23178 ./usr/lib/python3.8/logging/__pycache__/config.cpython-38.opt-1.pyc
+-rw-r--r-- root root 19068 ./usr/lib/python3.8/logging/__pycache__/config.cpython-38.opt-2.pyc
+-rw-r--r-- root root 23224 ./usr/lib/python3.8/logging/__pycache__/config.cpython-38.pyc
+-rw-r--r-- root root 43156 ./usr/lib/python3.8/logging/__pycache__/handlers.cpython-38.opt-1.pyc
+-rw-r--r-- root root 24449 ./usr/lib/python3.8/logging/__pycache__/handlers.cpython-38.opt-2.pyc
+-rw-r--r-- root root 43156 ./usr/lib/python3.8/logging/__pycache__/handlers.cpython-38.pyc
+-rw-r--r-- root root 64839 ./usr/lib/python3.8/logging/__pycache__/__init__.cpython-38.opt-1.pyc
+-rw-r--r-- root root 36341 ./usr/lib/python3.8/logging/__pycache__/__init__.cpython-38.opt-2.pyc
+-rw-r--r-- root root 64871 ./usr/lib/python3.8/logging/__pycache__/__init__.cpython-38.pyc
+-rw-r--r-- root root 12983 ./usr/lib/python3.8/lzma.py
+-rw-r--r-- root root 14598 ./usr/lib/python3.8/_markupbase.py
+-rw-r--r-- root root 21604 ./usr/lib/python3.8/mimetypes.py
+-rw-r--r-- root root 43261 ./usr/lib/python3.8/nntplib.py
+-rw-r--r-- root root 27734 ./usr/lib/python3.8/ntpath.py
+-rw-r--r-- root root 5808 ./usr/lib/python3.8/opcode.py
+-rw-r--r-- root root 10711 ./usr/lib/python3.8/operator.py
+-rw-r--r-- root root 60369 ./usr/lib/python3.8/optparse.py
+-rw-r--r-- root root 38995 ./usr/lib/python3.8/os.py
+-rw-r--r-- root root 51839 ./usr/lib/python3.8/pathlib.py
+-rw-r--r-- root root 64395 ./usr/lib/python3.8/pickle.py
+-rw-r--r-- root root 93486 ./usr/lib/python3.8/pickletools.py
+-rw-r--r-- root root 8916 ./usr/lib/python3.8/pipes.py
+-rw-r--r-- root root 21461 ./usr/lib/python3.8/pkgutil.py
+-rwxr-xr-x root root 40328 ./usr/lib/python3.8/platform.py
+-rw-r--r-- root root 15077 ./usr/lib/python3.8/poplib.py
+-rw-r--r-- root root 15627 ./usr/lib/python3.8/posixpath.py
+drwxr-xr-x root root 20480 ./usr/lib/python3.8/__pycache__
+-rw-r--r-- root root 5334 ./usr/lib/python3.8/__pycache__/abc.cpython-38.opt-1.pyc
+-rw-r--r-- root root 3212 ./usr/lib/python3.8/__pycache__/abc.cpython-38.opt-2.pyc
+-rw-r--r-- root root 5334 ./usr/lib/python3.8/__pycache__/abc.cpython-38.pyc
+-rw-r--r-- root root 62128 ./usr/lib/python3.8/__pycache__/argparse.cpython-38.opt-1.pyc
+-rw-r--r-- root root 52887 ./usr/lib/python3.8/__pycache__/argparse.cpython-38.opt-2.pyc
+-rw-r--r-- root root 62277 ./usr/lib/python3.8/__pycache__/argparse.cpython-38.pyc
+-rw-r--r-- root root 16485 ./usr/lib/python3.8/__pycache__/ast.cpython-38.opt-1.pyc
+-rw-r--r-- root root 10094 ./usr/lib/python3.8/__pycache__/ast.cpython-38.opt-2.pyc
+-rw-r--r-- root root 16520 ./usr/lib/python3.8/__pycache__/ast.cpython-38.pyc
+-rw-r--r-- root root 16908 ./usr/lib/python3.8/__pycache__/base64.cpython-38.opt-1.pyc
+-rw-r--r-- root root 11324 ./usr/lib/python3.8/__pycache__/base64.cpython-38.opt-2.pyc
+-rw-r--r-- root root 17071 ./usr/lib/python3.8/__pycache__/base64.cpython-38.pyc
+-rw-r--r-- root root 2354 ./usr/lib/python3.8/__pycache__/bisect.cpython-38.opt-1.pyc
+-rw-r--r-- root root 1042 ./usr/lib/python3.8/__pycache__/bisect.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2354 ./usr/lib/python3.8/__pycache__/bisect.cpython-38.pyc
+-rw-r--r-- root root 1217 ./usr/lib/python3.8/__pycache__/_bootlocale.cpython-38.opt-1.pyc
+-rw-r--r-- root root 992 ./usr/lib/python3.8/__pycache__/_bootlocale.cpython-38.opt-2.pyc
+-rw-r--r-- root root 1243 ./usr/lib/python3.8/__pycache__/_bootlocale.cpython-38.pyc
+-rw-r--r-- root root 11445 ./usr/lib/python3.8/__pycache__/bz2.cpython-38.opt-1.pyc
+-rw-r--r-- root root 6387 ./usr/lib/python3.8/__pycache__/bz2.cpython-38.opt-2.pyc
+-rw-r--r-- root root 11445 ./usr/lib/python3.8/__pycache__/bz2.cpython-38.pyc
+-rw-r--r-- root root 27064 ./usr/lib/python3.8/__pycache__/calendar.cpython-38.opt-1.pyc
+-rw-r--r-- root root 22472 ./usr/lib/python3.8/__pycache__/calendar.cpython-38.opt-2.pyc
+-rw-r--r-- root root 27064 ./usr/lib/python3.8/__pycache__/calendar.cpython-38.pyc
+-rw-r--r-- root root 12626 ./usr/lib/python3.8/__pycache__/cmd.cpython-38.opt-1.pyc
+-rw-r--r-- root root 7201 ./usr/lib/python3.8/__pycache__/cmd.cpython-38.opt-2.pyc
+-rw-r--r-- root root 12626 ./usr/lib/python3.8/__pycache__/cmd.cpython-38.pyc
+-rw-r--r-- root root 9913 ./usr/lib/python3.8/__pycache__/code.cpython-38.opt-1.pyc
+-rw-r--r-- root root 4642 ./usr/lib/python3.8/__pycache__/code.cpython-38.opt-2.pyc
+-rw-r--r-- root root 9913 ./usr/lib/python3.8/__pycache__/code.cpython-38.pyc
+-rw-r--r-- root root 33956 ./usr/lib/python3.8/__pycache__/codecs.cpython-38.opt-1.pyc
+-rw-r--r-- root root 18390 ./usr/lib/python3.8/__pycache__/codecs.cpython-38.opt-2.pyc
+-rw-r--r-- root root 33956 ./usr/lib/python3.8/__pycache__/codecs.cpython-38.pyc
+-rw-r--r-- root root 6297 ./usr/lib/python3.8/__pycache__/codeop.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2259 ./usr/lib/python3.8/__pycache__/codeop.cpython-38.opt-2.pyc
+-rw-r--r-- root root 6297 ./usr/lib/python3.8/__pycache__/codeop.cpython-38.pyc
+-rw-r--r-- root root 28741 ./usr/lib/python3.8/__pycache__/_collections_abc.cpython-38.opt-1.pyc
+-rw-r--r-- root root 23682 ./usr/lib/python3.8/__pycache__/_collections_abc.cpython-38.opt-2.pyc
+-rw-r--r-- root root 28741 ./usr/lib/python3.8/__pycache__/_collections_abc.cpython-38.pyc
+-rw-r--r-- root root 5443 ./usr/lib/python3.8/__pycache__/_compat_pickle.cpython-38.opt-1.pyc
+-rw-r--r-- root root 5443 ./usr/lib/python3.8/__pycache__/_compat_pickle.cpython-38.opt-2.pyc
+-rw-r--r-- root root 5501 ./usr/lib/python3.8/__pycache__/_compat_pickle.cpython-38.pyc
+-rw-r--r-- root root 4146 ./usr/lib/python3.8/__pycache__/_compression.cpython-38.opt-1.pyc
+-rw-r--r-- root root 3932 ./usr/lib/python3.8/__pycache__/_compression.cpython-38.opt-2.pyc
+-rw-r--r-- root root 4146 ./usr/lib/python3.8/__pycache__/_compression.cpython-38.pyc
+-rw-r--r-- root root 45718 ./usr/lib/python3.8/__pycache__/configparser.cpython-38.opt-1.pyc
+-rw-r--r-- root root 30792 ./usr/lib/python3.8/__pycache__/configparser.cpython-38.opt-2.pyc
+-rw-r--r-- root root 45718 ./usr/lib/python3.8/__pycache__/configparser.cpython-38.pyc
+-rw-r--r-- root root 20176 ./usr/lib/python3.8/__pycache__/contextlib.cpython-38.opt-1.pyc
+-rw-r--r-- root root 14596 ./usr/lib/python3.8/__pycache__/contextlib.cpython-38.opt-2.pyc
+-rw-r--r-- root root 20229 ./usr/lib/python3.8/__pycache__/contextlib.cpython-38.pyc
+-rw-r--r-- root root 6987 ./usr/lib/python3.8/__pycache__/copy.cpython-38.opt-1.pyc
+-rw-r--r-- root root 4673 ./usr/lib/python3.8/__pycache__/copy.cpython-38.opt-2.pyc
+-rw-r--r-- root root 6987 ./usr/lib/python3.8/__pycache__/copy.cpython-38.pyc
+-rw-r--r-- root root 4283 ./usr/lib/python3.8/__pycache__/copyreg.cpython-38.opt-1.pyc
+-rw-r--r-- root root 3481 ./usr/lib/python3.8/__pycache__/copyreg.cpython-38.opt-2.pyc
+-rw-r--r-- root root 4318 ./usr/lib/python3.8/__pycache__/copyreg.cpython-38.pyc
+-rw-r--r-- root root 3387 ./usr/lib/python3.8/__pycache__/crypt.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2725 ./usr/lib/python3.8/__pycache__/crypt.cpython-38.opt-2.pyc
+-rw-r--r-- root root 3387 ./usr/lib/python3.8/__pycache__/crypt.cpython-38.pyc
+-rw-r--r-- root root 11910 ./usr/lib/python3.8/__pycache__/csv.cpython-38.opt-1.pyc
+-rw-r--r-- root root 9871 ./usr/lib/python3.8/__pycache__/csv.cpython-38.opt-2.pyc
+-rw-r--r-- root root 11910 ./usr/lib/python3.8/__pycache__/csv.cpython-38.pyc
+-rw-r--r-- root root 55741 ./usr/lib/python3.8/__pycache__/datetime.cpython-38.opt-1.pyc
+-rw-r--r-- root root 47501 ./usr/lib/python3.8/__pycache__/datetime.cpython-38.opt-2.pyc
+-rw-r--r-- root root 56978 ./usr/lib/python3.8/__pycache__/datetime.cpython-38.pyc
+-rw-r--r-- root root 15802 ./usr/lib/python3.8/__pycache__/dis.cpython-38.opt-1.pyc
+-rw-r--r-- root root 11995 ./usr/lib/python3.8/__pycache__/dis.cpython-38.opt-2.pyc
+-rw-r--r-- root root 15802 ./usr/lib/python3.8/__pycache__/dis.cpython-38.pyc
+-rw-r--r-- root root 6037 ./usr/lib/python3.8/__pycache__/_dummy_thread.cpython-38.opt-1.pyc
+-rw-r--r-- root root 3392 ./usr/lib/python3.8/__pycache__/_dummy_thread.cpython-38.opt-2.pyc
+-rw-r--r-- root root 6037 ./usr/lib/python3.8/__pycache__/_dummy_thread.cpython-38.pyc
+-rw-r--r-- root root 24399 ./usr/lib/python3.8/__pycache__/enum.cpython-38.opt-1.pyc
+-rw-r--r-- root root 20110 ./usr/lib/python3.8/__pycache__/enum.cpython-38.opt-2.pyc
+-rw-r--r-- root root 24399 ./usr/lib/python3.8/__pycache__/enum.cpython-38.pyc
+-rw-r--r-- root root 3332 ./usr/lib/python3.8/__pycache__/fnmatch.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2147 ./usr/lib/python3.8/__pycache__/fnmatch.cpython-38.opt-2.pyc
+-rw-r--r-- root root 3332 ./usr/lib/python3.8/__pycache__/fnmatch.cpython-38.pyc
+-rw-r--r-- root root 27849 ./usr/lib/python3.8/__pycache__/ftplib.cpython-38.opt-1.pyc
+-rw-r--r-- root root 18116 ./usr/lib/python3.8/__pycache__/ftplib.cpython-38.opt-2.pyc
+-rw-r--r-- root root 27849 ./usr/lib/python3.8/__pycache__/ftplib.cpython-38.pyc
+-rw-r--r-- root root 27901 ./usr/lib/python3.8/__pycache__/functools.cpython-38.opt-1.pyc
+-rw-r--r-- root root 21248 ./usr/lib/python3.8/__pycache__/functools.cpython-38.opt-2.pyc
+-rw-r--r-- root root 27901 ./usr/lib/python3.8/__pycache__/functools.cpython-38.pyc
+-rw-r--r-- root root 4131 ./usr/lib/python3.8/__pycache__/__future__.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2159 ./usr/lib/python3.8/__pycache__/__future__.cpython-38.opt-2.pyc
+-rw-r--r-- root root 4131 ./usr/lib/python3.8/__pycache__/__future__.cpython-38.pyc
+-rw-r--r-- root root 4001 ./usr/lib/python3.8/__pycache__/genericpath.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2865 ./usr/lib/python3.8/__pycache__/genericpath.cpython-38.opt-2.pyc
+-rw-r--r-- root root 4001 ./usr/lib/python3.8/__pycache__/genericpath.cpython-38.pyc
+-rw-r--r-- root root 6237 ./usr/lib/python3.8/__pycache__/getopt.cpython-38.opt-1.pyc
+-rw-r--r-- root root 3683 ./usr/lib/python3.8/__pycache__/getopt.cpython-38.opt-2.pyc
+-rw-r--r-- root root 6271 ./usr/lib/python3.8/__pycache__/getopt.cpython-38.pyc
+-rw-r--r-- root root 17883 ./usr/lib/python3.8/__pycache__/gettext.cpython-38.opt-1.pyc
+-rw-r--r-- root root 17192 ./usr/lib/python3.8/__pycache__/gettext.cpython-38.opt-2.pyc
+-rw-r--r-- root root 17883 ./usr/lib/python3.8/__pycache__/gettext.cpython-38.pyc
+-rw-r--r-- root root 4278 ./usr/lib/python3.8/__pycache__/glob.cpython-38.opt-1.pyc
+-rw-r--r-- root root 3418 ./usr/lib/python3.8/__pycache__/glob.cpython-38.opt-2.pyc
+-rw-r--r-- root root 4343 ./usr/lib/python3.8/__pycache__/glob.cpython-38.pyc
+-rw-r--r-- root root 18191 ./usr/lib/python3.8/__pycache__/gzip.cpython-38.opt-1.pyc
+-rw-r--r-- root root 14323 ./usr/lib/python3.8/__pycache__/gzip.cpython-38.opt-2.pyc
+-rw-r--r-- root root 18191 ./usr/lib/python3.8/__pycache__/gzip.cpython-38.pyc
+-rw-r--r-- root root 6727 ./usr/lib/python3.8/__pycache__/hashlib.cpython-38.opt-1.pyc
+-rw-r--r-- root root 6159 ./usr/lib/python3.8/__pycache__/hashlib.cpython-38.opt-2.pyc
+-rw-r--r-- root root 6727 ./usr/lib/python3.8/__pycache__/hashlib.cpython-38.pyc
+-rw-r--r-- root root 14070 ./usr/lib/python3.8/__pycache__/heapq.cpython-38.opt-1.pyc
+-rw-r--r-- root root 11054 ./usr/lib/python3.8/__pycache__/heapq.cpython-38.opt-2.pyc
+-rw-r--r-- root root 14070 ./usr/lib/python3.8/__pycache__/heapq.cpython-38.pyc
+-rw-r--r-- root root 6388 ./usr/lib/python3.8/__pycache__/hmac.cpython-38.opt-1.pyc
+-rw-r--r-- root root 3871 ./usr/lib/python3.8/__pycache__/hmac.cpython-38.opt-2.pyc
+-rw-r--r-- root root 6388 ./usr/lib/python3.8/__pycache__/hmac.cpython-38.pyc
+-rw-r--r-- root root 39159 ./usr/lib/python3.8/__pycache__/imaplib.cpython-38.opt-1.pyc
+-rw-r--r-- root root 27182 ./usr/lib/python3.8/__pycache__/imaplib.cpython-38.opt-2.pyc
+-rw-r--r-- root root 41342 ./usr/lib/python3.8/__pycache__/imaplib.cpython-38.pyc
+-rw-r--r-- root root 9809 ./usr/lib/python3.8/__pycache__/imp.cpython-38.opt-1.pyc
+-rw-r--r-- root root 7444 ./usr/lib/python3.8/__pycache__/imp.cpython-38.opt-2.pyc
+-rw-r--r-- root root 9809 ./usr/lib/python3.8/__pycache__/imp.cpython-38.pyc
+-rw-r--r-- root root 80098 ./usr/lib/python3.8/__pycache__/inspect.cpython-38.opt-1.pyc
+-rw-r--r-- root root 54985 ./usr/lib/python3.8/__pycache__/inspect.cpython-38.opt-2.pyc
+-rw-r--r-- root root 80383 ./usr/lib/python3.8/__pycache__/inspect.cpython-38.pyc
+-rw-r--r-- root root 3454 ./usr/lib/python3.8/__pycache__/io.cpython-38.opt-1.pyc
+-rw-r--r-- root root 1965 ./usr/lib/python3.8/__pycache__/io.cpython-38.opt-2.pyc
+-rw-r--r-- root root 3454 ./usr/lib/python3.8/__pycache__/io.cpython-38.pyc
+-rw-r--r-- root root 59559 ./usr/lib/python3.8/__pycache__/ipaddress.cpython-38.opt-1.pyc
+-rw-r--r-- root root 35711 ./usr/lib/python3.8/__pycache__/ipaddress.cpython-38.opt-2.pyc
+-rw-r--r-- root root 59559 ./usr/lib/python3.8/__pycache__/ipaddress.cpython-38.pyc
+-rw-r--r-- root root 998 ./usr/lib/python3.8/__pycache__/keyword.cpython-38.opt-1.pyc
+-rw-r--r-- root root 571 ./usr/lib/python3.8/__pycache__/keyword.cpython-38.opt-2.pyc
+-rw-r--r-- root root 998 ./usr/lib/python3.8/__pycache__/keyword.cpython-38.pyc
+-rw-r--r-- root root 3839 ./usr/lib/python3.8/__pycache__/linecache.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2734 ./usr/lib/python3.8/__pycache__/linecache.cpython-38.opt-2.pyc
+-rw-r--r-- root root 3839 ./usr/lib/python3.8/__pycache__/linecache.cpython-38.pyc
+-rw-r--r-- root root 34689 ./usr/lib/python3.8/__pycache__/locale.cpython-38.opt-1.pyc
+-rw-r--r-- root root 30074 ./usr/lib/python3.8/__pycache__/locale.cpython-38.opt-2.pyc
+-rw-r--r-- root root 34689 ./usr/lib/python3.8/__pycache__/locale.cpython-38.pyc
+-rw-r--r-- root root 12018 ./usr/lib/python3.8/__pycache__/lzma.cpython-38.opt-1.pyc
+-rw-r--r-- root root 5849 ./usr/lib/python3.8/__pycache__/lzma.cpython-38.opt-2.pyc
+-rw-r--r-- root root 12018 ./usr/lib/python3.8/__pycache__/lzma.cpython-38.pyc
+-rw-r--r-- root root 7618 ./usr/lib/python3.8/__pycache__/_markupbase.cpython-38.opt-1.pyc
+-rw-r--r-- root root 7240 ./usr/lib/python3.8/__pycache__/_markupbase.cpython-38.opt-2.pyc
+-rw-r--r-- root root 7790 ./usr/lib/python3.8/__pycache__/_markupbase.cpython-38.pyc
+-rw-r--r-- root root 15988 ./usr/lib/python3.8/__pycache__/mimetypes.cpython-38.opt-1.pyc
+-rw-r--r-- root root 9973 ./usr/lib/python3.8/__pycache__/mimetypes.cpython-38.opt-2.pyc
+-rw-r--r-- root root 15988 ./usr/lib/python3.8/__pycache__/mimetypes.cpython-38.pyc
+-rw-r--r-- root root 33974 ./usr/lib/python3.8/__pycache__/nntplib.cpython-38.opt-1.pyc
+-rw-r--r-- root root 21464 ./usr/lib/python3.8/__pycache__/nntplib.cpython-38.opt-2.pyc
+-rw-r--r-- root root 33974 ./usr/lib/python3.8/__pycache__/nntplib.cpython-38.pyc
+-rw-r--r-- root root 14657 ./usr/lib/python3.8/__pycache__/ntpath.cpython-38.opt-1.pyc
+-rw-r--r-- root root 12606 ./usr/lib/python3.8/__pycache__/ntpath.cpython-38.opt-2.pyc
+-rw-r--r-- root root 14657 ./usr/lib/python3.8/__pycache__/ntpath.cpython-38.pyc
+-rw-r--r-- root root 5420 ./usr/lib/python3.8/__pycache__/opcode.cpython-38.opt-1.pyc
+-rw-r--r-- root root 5280 ./usr/lib/python3.8/__pycache__/opcode.cpython-38.opt-2.pyc
+-rw-r--r-- root root 5420 ./usr/lib/python3.8/__pycache__/opcode.cpython-38.pyc
+-rw-r--r-- root root 13691 ./usr/lib/python3.8/__pycache__/operator.cpython-38.opt-1.pyc
+-rw-r--r-- root root 11322 ./usr/lib/python3.8/__pycache__/operator.cpython-38.opt-2.pyc
+-rw-r--r-- root root 13691 ./usr/lib/python3.8/__pycache__/operator.cpython-38.pyc
+-rw-r--r-- root root 47974 ./usr/lib/python3.8/__pycache__/optparse.cpython-38.opt-1.pyc
+-rw-r--r-- root root 35659 ./usr/lib/python3.8/__pycache__/optparse.cpython-38.opt-2.pyc
+-rw-r--r-- root root 48057 ./usr/lib/python3.8/__pycache__/optparse.cpython-38.pyc
+-rw-r--r-- root root 31365 ./usr/lib/python3.8/__pycache__/os.cpython-38.opt-1.pyc
+-rw-r--r-- root root 19174 ./usr/lib/python3.8/__pycache__/os.cpython-38.opt-2.pyc
+-rw-r--r-- root root 31397 ./usr/lib/python3.8/__pycache__/os.cpython-38.pyc
+-rw-r--r-- root root 43552 ./usr/lib/python3.8/__pycache__/pathlib.cpython-38.opt-1.pyc
+-rw-r--r-- root root 35495 ./usr/lib/python3.8/__pycache__/pathlib.cpython-38.opt-2.pyc
+-rw-r--r-- root root 43552 ./usr/lib/python3.8/__pycache__/pathlib.cpython-38.pyc
+-rw-r--r-- root root 46761 ./usr/lib/python3.8/__pycache__/pickle.cpython-38.opt-1.pyc
+-rw-r--r-- root root 40889 ./usr/lib/python3.8/__pycache__/pickle.cpython-38.opt-2.pyc
+-rw-r--r-- root root 46878 ./usr/lib/python3.8/__pycache__/pickle.cpython-38.pyc
+-rw-r--r-- root root 66314 ./usr/lib/python3.8/__pycache__/pickletools.cpython-38.opt-1.pyc
+-rw-r--r-- root root 57221 ./usr/lib/python3.8/__pycache__/pickletools.cpython-38.opt-2.pyc
+-rw-r--r-- root root 67204 ./usr/lib/python3.8/__pycache__/pickletools.cpython-38.pyc
+-rw-r--r-- root root 7795 ./usr/lib/python3.8/__pycache__/pipes.cpython-38.opt-1.pyc
+-rw-r--r-- root root 4928 ./usr/lib/python3.8/__pycache__/pipes.cpython-38.opt-2.pyc
+-rw-r--r-- root root 7795 ./usr/lib/python3.8/__pycache__/pipes.cpython-38.pyc
+-rw-r--r-- root root 16309 ./usr/lib/python3.8/__pycache__/pkgutil.cpython-38.opt-1.pyc
+-rw-r--r-- root root 11053 ./usr/lib/python3.8/__pycache__/pkgutil.cpython-38.opt-2.pyc
+-rw-r--r-- root root 16309 ./usr/lib/python3.8/__pycache__/pkgutil.cpython-38.pyc
+-rw-r--r-- root root 24240 ./usr/lib/python3.8/__pycache__/platform.cpython-38.opt-1.pyc
+-rw-r--r-- root root 16364 ./usr/lib/python3.8/__pycache__/platform.cpython-38.opt-2.pyc
+-rw-r--r-- root root 24240 ./usr/lib/python3.8/__pycache__/platform.cpython-38.pyc
+-rw-r--r-- root root 13459 ./usr/lib/python3.8/__pycache__/poplib.cpython-38.opt-1.pyc
+-rw-r--r-- root root 8528 ./usr/lib/python3.8/__pycache__/poplib.cpython-38.opt-2.pyc
+-rw-r--r-- root root 13459 ./usr/lib/python3.8/__pycache__/poplib.cpython-38.pyc
+-rw-r--r-- root root 10428 ./usr/lib/python3.8/__pycache__/posixpath.cpython-38.opt-1.pyc
+-rw-r--r-- root root 8713 ./usr/lib/python3.8/__pycache__/posixpath.cpython-38.opt-2.pyc
+-rw-r--r-- root root 10428 ./usr/lib/python3.8/__pycache__/posixpath.cpython-38.pyc
+-rw-r--r-- root root 74059 ./usr/lib/python3.8/__pycache__/_pyio.cpython-38.opt-1.pyc
+-rw-r--r-- root root 51166 ./usr/lib/python3.8/__pycache__/_pyio.cpython-38.opt-2.pyc
+-rw-r--r-- root root 74079 ./usr/lib/python3.8/__pycache__/_pyio.cpython-38.pyc
+-rw-r--r-- root root 10626 ./usr/lib/python3.8/__pycache__/queue.cpython-38.opt-1.pyc
+-rw-r--r-- root root 6289 ./usr/lib/python3.8/__pycache__/queue.cpython-38.opt-2.pyc
+-rw-r--r-- root root 10626 ./usr/lib/python3.8/__pycache__/queue.cpython-38.pyc
+-rw-r--r-- root root 5573 ./usr/lib/python3.8/__pycache__/quopri.cpython-38.opt-1.pyc
+-rw-r--r-- root root 4537 ./usr/lib/python3.8/__pycache__/quopri.cpython-38.opt-2.pyc
+-rw-r--r-- root root 5748 ./usr/lib/python3.8/__pycache__/quopri.cpython-38.pyc
+-rw-r--r-- root root 20108 ./usr/lib/python3.8/__pycache__/random.cpython-38.opt-1.pyc
+-rw-r--r-- root root 13132 ./usr/lib/python3.8/__pycache__/random.cpython-38.opt-2.pyc
+-rw-r--r-- root root 20108 ./usr/lib/python3.8/__pycache__/random.cpython-38.pyc
+-rw-r--r-- root root 14422 ./usr/lib/python3.8/__pycache__/re.cpython-38.opt-1.pyc
+-rw-r--r-- root root 6084 ./usr/lib/python3.8/__pycache__/re.cpython-38.opt-2.pyc
+-rw-r--r-- root root 14422 ./usr/lib/python3.8/__pycache__/re.cpython-38.pyc
+-rw-r--r-- root root 5303 ./usr/lib/python3.8/__pycache__/reprlib.cpython-38.opt-1.pyc
+-rw-r--r-- root root 5147 ./usr/lib/python3.8/__pycache__/reprlib.cpython-38.opt-2.pyc
+-rw-r--r-- root root 5303 ./usr/lib/python3.8/__pycache__/reprlib.cpython-38.pyc
+-rw-r--r-- root root 5755 ./usr/lib/python3.8/__pycache__/rlcompleter.cpython-38.opt-1.pyc
+-rw-r--r-- root root 3092 ./usr/lib/python3.8/__pycache__/rlcompleter.cpython-38.opt-2.pyc
+-rw-r--r-- root root 5755 ./usr/lib/python3.8/__pycache__/rlcompleter.cpython-38.pyc
+-rw-r--r-- root root 8181 ./usr/lib/python3.8/__pycache__/runpy.cpython-38.opt-1.pyc
+-rw-r--r-- root root 6615 ./usr/lib/python3.8/__pycache__/runpy.cpython-38.opt-2.pyc
+-rw-r--r-- root root 8181 ./usr/lib/python3.8/__pycache__/runpy.cpython-38.pyc
+-rw-r--r-- root root 16935 ./usr/lib/python3.8/__pycache__/selectors.cpython-38.opt-1.pyc
+-rw-r--r-- root root 12900 ./usr/lib/python3.8/__pycache__/selectors.cpython-38.opt-2.pyc
+-rw-r--r-- root root 16935 ./usr/lib/python3.8/__pycache__/selectors.cpython-38.pyc
+-rw-r--r-- root root 9490 ./usr/lib/python3.8/__pycache__/shelve.cpython-38.opt-1.pyc
+-rw-r--r-- root root 5339 ./usr/lib/python3.8/__pycache__/shelve.cpython-38.opt-2.pyc
+-rw-r--r-- root root 9490 ./usr/lib/python3.8/__pycache__/shelve.cpython-38.pyc
+-rw-r--r-- root root 7536 ./usr/lib/python3.8/__pycache__/shlex.cpython-38.opt-1.pyc
+-rw-r--r-- root root 6979 ./usr/lib/python3.8/__pycache__/shlex.cpython-38.opt-2.pyc
+-rw-r--r-- root root 7536 ./usr/lib/python3.8/__pycache__/shlex.cpython-38.pyc
+-rw-r--r-- root root 36569 ./usr/lib/python3.8/__pycache__/shutil.cpython-38.opt-1.pyc
+-rw-r--r-- root root 25114 ./usr/lib/python3.8/__pycache__/shutil.cpython-38.opt-2.pyc
+-rw-r--r-- root root 36569 ./usr/lib/python3.8/__pycache__/shutil.cpython-38.pyc
+-rw-r--r-- root root 2843 ./usr/lib/python3.8/__pycache__/signal.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2619 ./usr/lib/python3.8/__pycache__/signal.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2843 ./usr/lib/python3.8/__pycache__/signal.cpython-38.pyc
+-rw-r--r-- root root 3481 ./usr/lib/python3.8/__pycache__/_sitebuiltins.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2957 ./usr/lib/python3.8/__pycache__/_sitebuiltins.cpython-38.opt-2.pyc
+-rw-r--r-- root root 3481 ./usr/lib/python3.8/__pycache__/_sitebuiltins.cpython-38.pyc
+-rw-r--r-- root root 16700 ./usr/lib/python3.8/__pycache__/site.cpython-38.opt-1.pyc
+-rw-r--r-- root root 11164 ./usr/lib/python3.8/__pycache__/site.cpython-38.opt-2.pyc
+-rw-r--r-- root root 16700 ./usr/lib/python3.8/__pycache__/site.cpython-38.pyc
+-rw-r--r-- root root 35252 ./usr/lib/python3.8/__pycache__/smtplib.cpython-38.opt-1.pyc
+-rw-r--r-- root root 18892 ./usr/lib/python3.8/__pycache__/smtplib.cpython-38.opt-2.pyc
+-rw-r--r-- root root 35313 ./usr/lib/python3.8/__pycache__/smtplib.cpython-38.pyc
+-rw-r--r-- root root 27747 ./usr/lib/python3.8/__pycache__/socket.cpython-38.opt-1.pyc
+-rw-r--r-- root root 19424 ./usr/lib/python3.8/__pycache__/socket.cpython-38.opt-2.pyc
+-rw-r--r-- root root 27787 ./usr/lib/python3.8/__pycache__/socket.cpython-38.pyc
+-rw-r--r-- root root 14916 ./usr/lib/python3.8/__pycache__/sre_compile.cpython-38.opt-1.pyc
+-rw-r--r-- root root 14502 ./usr/lib/python3.8/__pycache__/sre_compile.cpython-38.opt-2.pyc
+-rw-r--r-- root root 15142 ./usr/lib/python3.8/__pycache__/sre_compile.cpython-38.pyc
+-rw-r--r-- root root 6359 ./usr/lib/python3.8/__pycache__/sre_constants.cpython-38.opt-1.pyc
+-rw-r--r-- root root 5934 ./usr/lib/python3.8/__pycache__/sre_constants.cpython-38.opt-2.pyc
+-rw-r--r-- root root 6359 ./usr/lib/python3.8/__pycache__/sre_constants.cpython-38.pyc
+-rw-r--r-- root root 21600 ./usr/lib/python3.8/__pycache__/sre_parse.cpython-38.opt-1.pyc
+-rw-r--r-- root root 21552 ./usr/lib/python3.8/__pycache__/sre_parse.cpython-38.opt-2.pyc
+-rw-r--r-- root root 21647 ./usr/lib/python3.8/__pycache__/sre_parse.cpython-38.pyc
+-rw-r--r-- root root 44596 ./usr/lib/python3.8/__pycache__/ssl.cpython-38.opt-1.pyc
+-rw-r--r-- root root 33618 ./usr/lib/python3.8/__pycache__/ssl.cpython-38.opt-2.pyc
+-rw-r--r-- root root 44596 ./usr/lib/python3.8/__pycache__/ssl.cpython-38.pyc
+-rw-r--r-- root root 4372 ./usr/lib/python3.8/__pycache__/stat.cpython-38.opt-1.pyc
+-rw-r--r-- root root 3589 ./usr/lib/python3.8/__pycache__/stat.cpython-38.opt-2.pyc
+-rw-r--r-- root root 4372 ./usr/lib/python3.8/__pycache__/stat.cpython-38.pyc
+-rw-r--r-- root root 7300 ./usr/lib/python3.8/__pycache__/string.cpython-38.opt-1.pyc
+-rw-r--r-- root root 6194 ./usr/lib/python3.8/__pycache__/string.cpython-38.opt-2.pyc
+-rw-r--r-- root root 7300 ./usr/lib/python3.8/__pycache__/string.cpython-38.pyc
+-rw-r--r-- root root 10959 ./usr/lib/python3.8/__pycache__/stringprep.cpython-38.opt-1.pyc
+-rw-r--r-- root root 10739 ./usr/lib/python3.8/__pycache__/stringprep.cpython-38.opt-2.pyc
+-rw-r--r-- root root 11017 ./usr/lib/python3.8/__pycache__/stringprep.cpython-38.pyc
+-rw-r--r-- root root 16044 ./usr/lib/python3.8/__pycache__/_strptime.cpython-38.opt-1.pyc
+-rw-r--r-- root root 12316 ./usr/lib/python3.8/__pycache__/_strptime.cpython-38.opt-2.pyc
+-rw-r--r-- root root 16044 ./usr/lib/python3.8/__pycache__/_strptime.cpython-38.pyc
+-rw-r--r-- root root 330 ./usr/lib/python3.8/__pycache__/struct.cpython-38.opt-1.pyc
+-rw-r--r-- root root 330 ./usr/lib/python3.8/__pycache__/struct.cpython-38.opt-2.pyc
+-rw-r--r-- root root 330 ./usr/lib/python3.8/__pycache__/struct.cpython-38.pyc
+-rw-r--r-- root root 41843 ./usr/lib/python3.8/__pycache__/subprocess.cpython-38.opt-1.pyc
+-rw-r--r-- root root 29913 ./usr/lib/python3.8/__pycache__/subprocess.cpython-38.opt-2.pyc
+-rw-r--r-- root root 41940 ./usr/lib/python3.8/__pycache__/subprocess.cpython-38.pyc
+-rw-r--r-- root root 2404 ./usr/lib/python3.8/__pycache__/symbol.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2328 ./usr/lib/python3.8/__pycache__/symbol.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2404 ./usr/lib/python3.8/__pycache__/symbol.cpython-38.pyc
+-rw-r--r-- root root 15462 ./usr/lib/python3.8/__pycache__/sysconfig.cpython-38.opt-1.pyc
+-rw-r--r-- root root 13084 ./usr/lib/python3.8/__pycache__/sysconfig.cpython-38.opt-2.pyc
+-rw-r--r-- root root 15462 ./usr/lib/python3.8/__pycache__/sysconfig.cpython-38.pyc
+-rw-r--r-- root root 62519 ./usr/lib/python3.8/__pycache__/tarfile.cpython-38.opt-1.pyc
+-rw-r--r-- root root 48629 ./usr/lib/python3.8/__pycache__/tarfile.cpython-38.opt-2.pyc
+-rw-r--r-- root root 62550 ./usr/lib/python3.8/__pycache__/tarfile.cpython-38.pyc
+-rw-r--r-- root root 18237 ./usr/lib/python3.8/__pycache__/telnetlib.cpython-38.opt-1.pyc
+-rw-r--r-- root root 10735 ./usr/lib/python3.8/__pycache__/telnetlib.cpython-38.opt-2.pyc
+-rw-r--r-- root root 18237 ./usr/lib/python3.8/__pycache__/telnetlib.cpython-38.pyc
+-rw-r--r-- root root 23455 ./usr/lib/python3.8/__pycache__/tempfile.cpython-38.opt-1.pyc
+-rw-r--r-- root root 16871 ./usr/lib/python3.8/__pycache__/tempfile.cpython-38.opt-2.pyc
+-rw-r--r-- root root 23455 ./usr/lib/python3.8/__pycache__/tempfile.cpython-38.pyc
+-rw-r--r-- root root 13445 ./usr/lib/python3.8/__pycache__/textwrap.cpython-38.opt-1.pyc
+-rw-r--r-- root root 6236 ./usr/lib/python3.8/__pycache__/textwrap.cpython-38.opt-2.pyc
+-rw-r--r-- root root 13519 ./usr/lib/python3.8/__pycache__/textwrap.cpython-38.pyc
+-rw-r--r-- root root 39425 ./usr/lib/python3.8/__pycache__/threading.cpython-38.opt-1.pyc
+-rw-r--r-- root root 22848 ./usr/lib/python3.8/__pycache__/threading.cpython-38.opt-2.pyc
+-rw-r--r-- root root 39976 ./usr/lib/python3.8/__pycache__/threading.cpython-38.pyc
+-rw-r--r-- root root 6446 ./usr/lib/python3.8/__pycache__/_threading_local.cpython-38.opt-1.pyc
+-rw-r--r-- root root 3126 ./usr/lib/python3.8/__pycache__/_threading_local.cpython-38.opt-2.pyc
+-rw-r--r-- root root 6446 ./usr/lib/python3.8/__pycache__/_threading_local.cpython-38.pyc
+-rw-r--r-- root root 2485 ./usr/lib/python3.8/__pycache__/token.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2452 ./usr/lib/python3.8/__pycache__/token.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2485 ./usr/lib/python3.8/__pycache__/token.cpython-38.pyc
+-rw-r--r-- root root 17116 ./usr/lib/python3.8/__pycache__/tokenize.cpython-38.opt-1.pyc
+-rw-r--r-- root root 13352 ./usr/lib/python3.8/__pycache__/tokenize.cpython-38.opt-2.pyc
+-rw-r--r-- root root 17160 ./usr/lib/python3.8/__pycache__/tokenize.cpython-38.pyc
+-rw-r--r-- root root 19889 ./usr/lib/python3.8/__pycache__/traceback.cpython-38.opt-1.pyc
+-rw-r--r-- root root 10986 ./usr/lib/python3.8/__pycache__/traceback.cpython-38.opt-2.pyc
+-rw-r--r-- root root 19889 ./usr/lib/python3.8/__pycache__/traceback.cpython-38.pyc
+-rw-r--r-- root root 9177 ./usr/lib/python3.8/__pycache__/types.cpython-38.opt-1.pyc
+-rw-r--r-- root root 7955 ./usr/lib/python3.8/__pycache__/types.cpython-38.opt-2.pyc
+-rw-r--r-- root root 9177 ./usr/lib/python3.8/__pycache__/types.cpython-38.pyc
+-rw-r--r-- root root 3605 ./usr/lib/python3.8/__pycache__/uu.cpython-38.opt-1.pyc
+-rw-r--r-- root root 3361 ./usr/lib/python3.8/__pycache__/uu.cpython-38.opt-2.pyc
+-rw-r--r-- root root 3605 ./usr/lib/python3.8/__pycache__/uu.cpython-38.pyc
+-rw-r--r-- root root 23532 ./usr/lib/python3.8/__pycache__/uuid.cpython-38.opt-1.pyc
+-rw-r--r-- root root 16376 ./usr/lib/python3.8/__pycache__/uuid.cpython-38.opt-2.pyc
+-rw-r--r-- root root 23666 ./usr/lib/python3.8/__pycache__/uuid.cpython-38.pyc
+-rw-r--r-- root root 13192 ./usr/lib/python3.8/__pycache__/warnings.cpython-38.opt-1.pyc
+-rw-r--r-- root root 10917 ./usr/lib/python3.8/__pycache__/warnings.cpython-38.opt-2.pyc
+-rw-r--r-- root root 13652 ./usr/lib/python3.8/__pycache__/warnings.cpython-38.pyc
+-rw-r--r-- root root 19488 ./usr/lib/python3.8/__pycache__/weakref.cpython-38.opt-1.pyc
+-rw-r--r-- root root 16204 ./usr/lib/python3.8/__pycache__/weakref.cpython-38.opt-2.pyc
+-rw-r--r-- root root 19518 ./usr/lib/python3.8/__pycache__/weakref.cpython-38.pyc
+-rw-r--r-- root root 7600 ./usr/lib/python3.8/__pycache__/_weakrefset.cpython-38.opt-1.pyc
+-rw-r--r-- root root 7600 ./usr/lib/python3.8/__pycache__/_weakrefset.cpython-38.opt-2.pyc
+-rw-r--r-- root root 7600 ./usr/lib/python3.8/__pycache__/_weakrefset.cpython-38.pyc
+-rw-r--r-- root root 58420 ./usr/lib/python3.8/__pycache__/zipfile.cpython-38.opt-1.pyc
+-rw-r--r-- root root 49731 ./usr/lib/python3.8/__pycache__/zipfile.cpython-38.opt-2.pyc
+-rw-r--r-- root root 58457 ./usr/lib/python3.8/__pycache__/zipfile.cpython-38.pyc
+-rw-r--r-- root root 93177 ./usr/lib/python3.8/_pyio.py
+-rw-r--r-- root root 11356 ./usr/lib/python3.8/queue.py
+-rwxr-xr-x root root 7254 ./usr/lib/python3.8/quopri.py
+-rw-r--r-- root root 28802 ./usr/lib/python3.8/random.py
+-rw-r--r-- root root 5267 ./usr/lib/python3.8/reprlib.py
+-rw-r--r-- root root 15861 ./usr/lib/python3.8/re.py
+-rw-r--r-- root root 7097 ./usr/lib/python3.8/rlcompleter.py
+-rw-r--r-- root root 12052 ./usr/lib/python3.8/runpy.py
+-rw-r--r-- root root 18561 ./usr/lib/python3.8/selectors.py
+-rw-r--r-- root root 8527 ./usr/lib/python3.8/shelve.py
+-rw-r--r-- root root 13325 ./usr/lib/python3.8/shlex.py
+-rw-r--r-- root root 50752 ./usr/lib/python3.8/shutil.py
+-rw-r--r-- root root 2273 ./usr/lib/python3.8/signal.py
+-rw-r--r-- root root 3115 ./usr/lib/python3.8/_sitebuiltins.py
+drwxr-xr-x root root 4096 ./usr/lib/python3.8/site-packages
+drwxr-xr-x root root 4096 ./usr/lib/python3.8/site-packages/btrfsutil-1.2.0-py3.8.egg-info
+-rw-r--r-- root root 1 ./usr/lib/python3.8/site-packages/btrfsutil-1.2.0-py3.8.egg-info/dependency_links.txt
+-rw-r--r-- root root 242 ./usr/lib/python3.8/site-packages/btrfsutil-1.2.0-py3.8.egg-info/PKG-INFO
+-rw-r--r-- root root 203 ./usr/lib/python3.8/site-packages/btrfsutil-1.2.0-py3.8.egg-info/SOURCES.txt
+-rw-r--r-- root root 10 ./usr/lib/python3.8/site-packages/btrfsutil-1.2.0-py3.8.egg-info/top_level.txt
+-rwxr-xr-x root root 45936 ./usr/lib/python3.8/site-packages/btrfsutil.cpython-38-x86_64-linux-gnu.so
+drwxr-xr-x root root 4096 ./usr/lib/python3.8/site-packages/cairo
+-rwxr-xr-x root root 220616 ./usr/lib/python3.8/site-packages/cairo/_cairo.cpython-38-x86_64-linux-gnu.so
+drwxr-xr-x root root 4096 ./usr/lib/python3.8/site-packages/cairo/include
+-rw-r--r-- root root 9152 ./usr/lib/python3.8/site-packages/cairo/include/py3cairo.h
+-rwxr-xr-x root root 660 ./usr/lib/python3.8/site-packages/cairo/__init__.py
+-rw-r--r-- root root 33334 ./usr/lib/python3.8/site-packages/cairo/__init__.pyi
+-rw-r--r-- root root 0 ./usr/lib/python3.8/site-packages/cairo/py.typed
+drwxr-xr-x root root 4096 ./usr/lib/python3.8/site-packages/dbus
+-rwxr-xr-x root root 167752 ./usr/lib/python3.8/site-packages/_dbus_bindings.so
+-rw-r--r-- root root 17960 ./usr/lib/python3.8/site-packages/dbus/bus.py
+-rw-r--r-- root root 148 ./usr/lib/python3.8/site-packages/dbus/_compat.py
+-rw-r--r-- root root 27806 ./usr/lib/python3.8/site-packages/dbus/connection.py
+-rw-r--r-- root root 8837 ./usr/lib/python3.8/site-packages/dbus/_dbus.py
+-rw-r--r-- root root 15240 ./usr/lib/python3.8/site-packages/dbus/decorators.py
+-rw-r--r-- root root 4707 ./usr/lib/python3.8/site-packages/dbus/exceptions.py
+-rw-r--r-- root root 3409 ./usr/lib/python3.8/site-packages/dbus/_expat_introspect_parser.py
+-rw-r--r-- root root 3517 ./usr/lib/python3.8/site-packages/dbus/gi_service.py
+-rwxr-xr-x root root 22736 ./usr/lib/python3.8/site-packages/_dbus_glib_bindings.so
+-rw-r--r-- root root 2130 ./usr/lib/python3.8/site-packages/dbus/glib.py
+-rw-r--r-- root root 3756 ./usr/lib/python3.8/site-packages/dbus/__init__.py
+-rw-r--r-- root root 1864 ./usr/lib/python3.8/site-packages/dbus/lowlevel.py
+drwxr-xr-x root root 4096 ./usr/lib/python3.8/site-packages/dbus/mainloop
+-rw-r--r-- root root 1806 ./usr/lib/python3.8/site-packages/dbus/mainloop/glib.py
+-rw-r--r-- root root 2369 ./usr/lib/python3.8/site-packages/dbus/mainloop/__init__.py
+drwxr-xr-x root root 4096 ./usr/lib/python3.8/site-packages/dbus/mainloop/__pycache__
+-rw-r--r-- root root 655 ./usr/lib/python3.8/site-packages/dbus/mainloop/__pycache__/glib.cpython-38.opt-1.pyc
+-rw-r--r-- root root 655 ./usr/lib/python3.8/site-packages/dbus/mainloop/__pycache__/glib.cpython-38.pyc
+-rw-r--r-- root root 435 ./usr/lib/python3.8/site-packages/dbus/mainloop/__pycache__/__init__.cpython-38.opt-1.pyc
+-rw-r--r-- root root 435 ./usr/lib/python3.8/site-packages/dbus/mainloop/__pycache__/__init__.cpython-38.pyc
+drwxr-xr-x root root 4096 ./usr/lib/python3.8/site-packages/dbusmock
+-rw-r--r-- root root 856 ./usr/lib/python3.8/site-packages/dbusmock/__init__.py
+-rw-r--r-- root root 4533 ./usr/lib/python3.8/site-packages/dbusmock/__main__.py
+-rw-r--r-- root root 28848 ./usr/lib/python3.8/site-packages/dbusmock/mockobject.py
+drwxr-xr-x root root 4096 ./usr/lib/python3.8/site-packages/dbusmock/__pycache__
+-rw-r--r-- root root 641 ./usr/lib/python3.8/site-packages/dbusmock/__pycache__/__init__.cpython-38.pyc
+-rw-r--r-- root root 3142 ./usr/lib/python3.8/site-packages/dbusmock/__pycache__/__main__.cpython-38.pyc
+-rw-r--r-- root root 22372 ./usr/lib/python3.8/site-packages/dbusmock/__pycache__/mockobject.cpython-38.pyc
+-rw-r--r-- root root 7903 ./usr/lib/python3.8/site-packages/dbusmock/__pycache__/testcase.cpython-38.pyc
+drwxr-xr-x root root 4096 ./usr/lib/python3.8/site-packages/dbusmock/templates
+-rw-r--r-- root root 16490 ./usr/lib/python3.8/site-packages/dbusmock/templates/bluez4.py
+-rw-r--r-- root root 10784 ./usr/lib/python3.8/site-packages/dbusmock/templates/bluez5-obex.py
+-rw-r--r-- root root 15264 ./usr/lib/python3.8/site-packages/dbusmock/templates/bluez5.py
+-rw-r--r-- root root 1250 ./usr/lib/python3.8/site-packages/dbusmock/templates/gnome_screensaver.py
+-rw-r--r-- root root 382 ./usr/lib/python3.8/site-packages/dbusmock/templates/__init__.py
+-rw-r--r-- root root 10765 ./usr/lib/python3.8/site-packages/dbusmock/templates/logind.py
+-rw-r--r-- root root 1139 ./usr/lib/python3.8/site-packages/dbusmock/templates/low_memory_monitor.py
+-rw-r--r-- root root 34680 ./usr/lib/python3.8/site-packages/dbusmock/templates/networkmanager.py
+-rw-r--r-- root root 1777 ./usr/lib/python3.8/site-packages/dbusmock/templates/notification_daemon.py
+-rw-r--r-- root root 18046 ./usr/lib/python3.8/site-packages/dbusmock/templates/ofono.py
+-rw-r--r-- root root 2089 ./usr/lib/python3.8/site-packages/dbusmock/templates/polkitd.py
+drwxr-xr-x root root 4096 ./usr/lib/python3.8/site-packages/dbusmock/templates/__pycache__
+-rw-r--r-- root root 10255 ./usr/lib/python3.8/site-packages/dbusmock/templates/__pycache__/bluez4.cpython-38.pyc
+-rw-r--r-- root root 9287 ./usr/lib/python3.8/site-packages/dbusmock/templates/__pycache__/bluez5.cpython-38.pyc
+-rw-r--r-- root root 7996 ./usr/lib/python3.8/site-packages/dbusmock/templates/__pycache__/bluez5-obex.cpython-38.pyc
+-rw-r--r-- root root 1052 ./usr/lib/python3.8/site-packages/dbusmock/templates/__pycache__/gnome_screensaver.cpython-38.pyc
+-rw-r--r-- root root 206 ./usr/lib/python3.8/site-packages/dbusmock/templates/__pycache__/__init__.cpython-38.pyc
+-rw-r--r-- root root 6563 ./usr/lib/python3.8/site-packages/dbusmock/templates/__pycache__/logind.cpython-38.pyc
+-rw-r--r-- root root 1111 ./usr/lib/python3.8/site-packages/dbusmock/templates/__pycache__/low_memory_monitor.cpython-38.pyc
+-rw-r--r-- root root 23374 ./usr/lib/python3.8/site-packages/dbusmock/templates/__pycache__/networkmanager.cpython-38.pyc
+-rw-r--r-- root root 1419 ./usr/lib/python3.8/site-packages/dbusmock/templates/__pycache__/notification_daemon.cpython-38.pyc
+-rw-r--r-- root root 9250 ./usr/lib/python3.8/site-packages/dbusmock/templates/__pycache__/ofono.cpython-38.pyc
+-rw-r--r-- root root 1890 ./usr/lib/python3.8/site-packages/dbusmock/templates/__pycache__/polkitd.cpython-38.pyc
+-rw-r--r-- root root 1342 ./usr/lib/python3.8/site-packages/dbusmock/templates/__pycache__/timedated.cpython-38.pyc
+-rw-r--r-- root root 6843 ./usr/lib/python3.8/site-packages/dbusmock/templates/__pycache__/upower.cpython-38.pyc
+-rw-r--r-- root root 2520 ./usr/lib/python3.8/site-packages/dbusmock/templates/__pycache__/urfkill.cpython-38.pyc
+-rw-r--r-- root root 1796 ./usr/lib/python3.8/site-packages/dbusmock/templates/timedated.py
+-rw-r--r-- root root 10801 ./usr/lib/python3.8/site-packages/dbusmock/templates/upower.py
+-rw-r--r-- root root 3709 ./usr/lib/python3.8/site-packages/dbusmock/templates/urfkill.py
+-rw-r--r-- root root 9445 ./usr/lib/python3.8/site-packages/dbusmock/testcase.py
+-rw-r--r-- root root 24821 ./usr/lib/python3.8/site-packages/dbus/proxies.py
+drwxr-xr-x root root 4096 ./usr/lib/python3.8/site-packages/dbus/__pycache__
+-rw-r--r-- root root 13609 ./usr/lib/python3.8/site-packages/dbus/__pycache__/bus.cpython-38.opt-1.pyc
+-rw-r--r-- root root 13609 ./usr/lib/python3.8/site-packages/dbus/__pycache__/bus.cpython-38.pyc
+-rw-r--r-- root root 218 ./usr/lib/python3.8/site-packages/dbus/__pycache__/_compat.cpython-38.opt-1.pyc
+-rw-r--r-- root root 218 ./usr/lib/python3.8/site-packages/dbus/__pycache__/_compat.cpython-38.pyc
+-rw-r--r-- root root 17806 ./usr/lib/python3.8/site-packages/dbus/__pycache__/connection.cpython-38.opt-1.pyc
+-rw-r--r-- root root 17806 ./usr/lib/python3.8/site-packages/dbus/__pycache__/connection.cpython-38.pyc
+-rw-r--r-- root root 7385 ./usr/lib/python3.8/site-packages/dbus/__pycache__/_dbus.cpython-38.opt-1.pyc
+-rw-r--r-- root root 7385 ./usr/lib/python3.8/site-packages/dbus/__pycache__/_dbus.cpython-38.pyc
+-rw-r--r-- root root 11569 ./usr/lib/python3.8/site-packages/dbus/__pycache__/decorators.cpython-38.opt-1.pyc
+-rw-r--r-- root root 11569 ./usr/lib/python3.8/site-packages/dbus/__pycache__/decorators.cpython-38.pyc
+-rw-r--r-- root root 3916 ./usr/lib/python3.8/site-packages/dbus/__pycache__/exceptions.cpython-38.opt-1.pyc
+-rw-r--r-- root root 3916 ./usr/lib/python3.8/site-packages/dbus/__pycache__/exceptions.cpython-38.pyc
+-rw-r--r-- root root 2206 ./usr/lib/python3.8/site-packages/dbus/__pycache__/_expat_introspect_parser.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2206 ./usr/lib/python3.8/site-packages/dbus/__pycache__/_expat_introspect_parser.cpython-38.pyc
+-rw-r--r-- root root 1954 ./usr/lib/python3.8/site-packages/dbus/__pycache__/gi_service.cpython-38.opt-1.pyc
+-rw-r--r-- root root 1954 ./usr/lib/python3.8/site-packages/dbus/__pycache__/gi_service.cpython-38.pyc
+-rw-r--r-- root root 1018 ./usr/lib/python3.8/site-packages/dbus/__pycache__/glib.cpython-38.opt-1.pyc
+-rw-r--r-- root root 1018 ./usr/lib/python3.8/site-packages/dbus/__pycache__/glib.cpython-38.pyc
+-rw-r--r-- root root 2185 ./usr/lib/python3.8/site-packages/dbus/__pycache__/__init__.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2185 ./usr/lib/python3.8/site-packages/dbus/__pycache__/__init__.cpython-38.pyc
+-rw-r--r-- root root 677 ./usr/lib/python3.8/site-packages/dbus/__pycache__/lowlevel.cpython-38.opt-1.pyc
+-rw-r--r-- root root 677 ./usr/lib/python3.8/site-packages/dbus/__pycache__/lowlevel.cpython-38.pyc
+-rw-r--r-- root root 17730 ./usr/lib/python3.8/site-packages/dbus/__pycache__/proxies.cpython-38.opt-1.pyc
+-rw-r--r-- root root 17730 ./usr/lib/python3.8/site-packages/dbus/__pycache__/proxies.cpython-38.pyc
+-rw-r--r-- root root 3462 ./usr/lib/python3.8/site-packages/dbus/__pycache__/server.cpython-38.opt-1.pyc
+-rw-r--r-- root root 3462 ./usr/lib/python3.8/site-packages/dbus/__pycache__/server.cpython-38.pyc
+-rw-r--r-- root root 22086 ./usr/lib/python3.8/site-packages/dbus/__pycache__/service.cpython-38.opt-1.pyc
+-rw-r--r-- root root 22086 ./usr/lib/python3.8/site-packages/dbus/__pycache__/service.cpython-38.pyc
+-rw-r--r-- root root 730 ./usr/lib/python3.8/site-packages/dbus/__pycache__/types.cpython-38.opt-1.pyc
+-rw-r--r-- root root 730 ./usr/lib/python3.8/site-packages/dbus/__pycache__/types.cpython-38.pyc
+-rw-r--r-- root root 4657 ./usr/lib/python3.8/site-packages/dbus/server.py
+-rw-r--r-- root root 35473 ./usr/lib/python3.8/site-packages/dbus/service.py
+-rw-r--r-- root root 561 ./usr/lib/python3.8/site-packages/dbus/types.py
+drwxr-xr-x root root 4096 ./usr/lib/python3.8/site-packages/gi
+-rw-r--r-- root root 1493 ./usr/lib/python3.8/site-packages/gi/_compat.py
+-rw-r--r-- root root 1969 ./usr/lib/python3.8/site-packages/gi/_constants.py
+-rw-r--r-- root root 6688 ./usr/lib/python3.8/site-packages/gi/docstring.py
+-rw-r--r-- root root 2082 ./usr/lib/python3.8/site-packages/gi/_error.py
+-rwxr-xr-x root root 22488 ./usr/lib/python3.8/site-packages/gi/_gi_cairo.cpython-38-x86_64-linux-gnu.so
+-rwxr-xr-x root root 344488 ./usr/lib/python3.8/site-packages/gi/_gi.cpython-38-x86_64-linux-gnu.so
+-rw-r--r-- root root 7833 ./usr/lib/python3.8/site-packages/gi/_gtktemplate.py
+-rw-r--r-- root root 5280 ./usr/lib/python3.8/site-packages/gi/importer.py
+-rw-r--r-- root root 5894 ./usr/lib/python3.8/site-packages/gi/__init__.py
+-rw-r--r-- root root 9705 ./usr/lib/python3.8/site-packages/gi/module.py
+-rw-r--r-- root root 13192 ./usr/lib/python3.8/site-packages/gi/_option.py
+-rw-r--r-- root root 8083 ./usr/lib/python3.8/site-packages/gi/_ossighelper.py
+drwxr-xr-x root root 4096 ./usr/lib/python3.8/site-packages/gi/overrides
+-rw-r--r-- root root 1724 ./usr/lib/python3.8/site-packages/gi/overrides/GdkPixbuf.py
+-rw-r--r-- root root 16239 ./usr/lib/python3.8/site-packages/gi/overrides/Gdk.py
+-rw-r--r-- root root 2242 ./usr/lib/python3.8/site-packages/gi/overrides/GIMarshallingTests.py
+-rw-r--r-- root root 19033 ./usr/lib/python3.8/site-packages/gi/overrides/Gio.py
+-rw-r--r-- root root 29897 ./usr/lib/python3.8/site-packages/gi/overrides/GLib.py
+-rw-r--r-- root root 24640 ./usr/lib/python3.8/site-packages/gi/overrides/GObject.py
+-rw-r--r-- root root 59669 ./usr/lib/python3.8/site-packages/gi/overrides/Gtk.py
+-rw-r--r-- root root 12590 ./usr/lib/python3.8/site-packages/gi/overrides/__init__.py
+-rw-r--r-- root root 1705 ./usr/lib/python3.8/site-packages/gi/overrides/keysyms.py
+-rw-r--r-- root root 1774 ./usr/lib/python3.8/site-packages/gi/overrides/Pango.py
+-rw-r--r-- root root 14331 ./usr/lib/python3.8/site-packages/gi/_propertyhelper.py
+-rw-r--r-- root root 766 ./usr/lib/python3.8/site-packages/gi/pygtkcompat.py
+drwxr-xr-x root root 4096 ./usr/lib/python3.8/site-packages/gi/repository
+-rw-r--r-- root root 1042 ./usr/lib/python3.8/site-packages/gi/repository/__init__.py
+-rw-r--r-- root root 9303 ./usr/lib/python3.8/site-packages/gi/_signalhelper.py
+-rw-r--r-- root root 14330 ./usr/lib/python3.8/site-packages/gi/types.py
+-rw-r--r-- root root 1024 ./usr/lib/python3.8/site-packages/pycairo-1.19.1.egg-info
+-rw-r--r-- root root 810 ./usr/lib/python3.8/site-packages/PyGObject-3.36.1.egg-info
+drwxr-xr-x root root 4096 ./usr/lib/python3.8/site-packages/pygtkcompat
+-rw-r--r-- root root 14200 ./usr/lib/python3.8/site-packages/pygtkcompat/generictreemodel.py
+-rw-r--r-- root root 547 ./usr/lib/python3.8/site-packages/pygtkcompat/__init__.py
+-rw-r--r-- root root 20890 ./usr/lib/python3.8/site-packages/pygtkcompat/pygtkcompat.py
+drwxr-xr-x root root 4096 ./usr/lib/python3.8/site-packages/python_dbusmock-0.19-py3.8.egg-info
+-rw-r--r-- root root 1 ./usr/lib/python3.8/site-packages/python_dbusmock-0.19-py3.8.egg-info/dependency_links.txt
+-rw-r--r-- root root 14631 ./usr/lib/python3.8/site-packages/python_dbusmock-0.19-py3.8.egg-info/PKG-INFO
+-rw-r--r-- root root 1137 ./usr/lib/python3.8/site-packages/python_dbusmock-0.19-py3.8.egg-info/SOURCES.txt
+-rw-r--r-- root root 9 ./usr/lib/python3.8/site-packages/python_dbusmock-0.19-py3.8.egg-info/top_level.txt
+-rw-r--r-- root root 21342 ./usr/lib/python3.8/site.py
+-rwxr-xr-x root root 44328 ./usr/lib/python3.8/smtplib.py
+-rw-r--r-- root root 35243 ./usr/lib/python3.8/socket.py
+-rw-r--r-- root root 26695 ./usr/lib/python3.8/sre_compile.py
+-rw-r--r-- root root 7154 ./usr/lib/python3.8/sre_constants.py
+-rw-r--r-- root root 40230 ./usr/lib/python3.8/sre_parse.py
+-rw-r--r-- root root 50760 ./usr/lib/python3.8/ssl.py
+-rw-r--r-- root root 5485 ./usr/lib/python3.8/stat.py
+-rw-r--r-- root root 12917 ./usr/lib/python3.8/stringprep.py
+-rw-r--r-- root root 10535 ./usr/lib/python3.8/string.py
+-rw-r--r-- root root 25268 ./usr/lib/python3.8/_strptime.py
+-rw-r--r-- root root 257 ./usr/lib/python3.8/struct.py
+-rw-r--r-- root root 77289 ./usr/lib/python3.8/subprocess.py
+-rw-r--r-- root root 2109 ./usr/lib/python3.8/symbol.py
+-rw-r--r-- root root 26693 ./usr/lib/python3.8/_sysconfigdata__linux_x86_64-linux-gnu.py
+-rw-r--r-- root root 24339 ./usr/lib/python3.8/sysconfig.py
+-rwxr-xr-x root root 93575 ./usr/lib/python3.8/tarfile.py
+-rw-r--r-- root root 23254 ./usr/lib/python3.8/telnetlib.py
+-rw-r--r-- root root 27595 ./usr/lib/python3.8/tempfile.py
+-rw-r--r-- root root 19407 ./usr/lib/python3.8/textwrap.py
+-rw-r--r-- root root 7220 ./usr/lib/python3.8/_threading_local.py
+-rw-r--r-- root root 50820 ./usr/lib/python3.8/threading.py
+-rw-r--r-- root root 25841 ./usr/lib/python3.8/tokenize.py
+-rw-r--r-- root root 2368 ./usr/lib/python3.8/token.py
+-rw-r--r-- root root 23478 ./usr/lib/python3.8/traceback.py
+-rw-r--r-- root root 9713 ./usr/lib/python3.8/types.py
+drwxr-xr-x root root 4096 ./usr/lib/python3.8/urllib
+-rw-r--r-- root root 2632 ./usr/lib/python3.8/urllib/error.py
+-rw-r--r-- root root 0 ./usr/lib/python3.8/urllib/__init__.py
+-rw-r--r-- root root 41583 ./usr/lib/python3.8/urllib/parse.py
+drwxr-xr-x root root 4096 ./usr/lib/python3.8/urllib/__pycache__
+-rw-r--r-- root root 2809 ./usr/lib/python3.8/urllib/__pycache__/error.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2134 ./usr/lib/python3.8/urllib/__pycache__/error.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2809 ./usr/lib/python3.8/urllib/__pycache__/error.cpython-38.pyc
+-rw-r--r-- root root 128 ./usr/lib/python3.8/urllib/__pycache__/__init__.cpython-38.opt-1.pyc
+-rw-r--r-- root root 128 ./usr/lib/python3.8/urllib/__pycache__/__init__.cpython-38.opt-2.pyc
+-rw-r--r-- root root 128 ./usr/lib/python3.8/urllib/__pycache__/__init__.cpython-38.pyc
+-rw-r--r-- root root 33932 ./usr/lib/python3.8/urllib/__pycache__/parse.cpython-38.opt-1.pyc
+-rw-r--r-- root root 24496 ./usr/lib/python3.8/urllib/__pycache__/parse.cpython-38.opt-2.pyc
+-rw-r--r-- root root 33932 ./usr/lib/python3.8/urllib/__pycache__/parse.cpython-38.pyc
+-rw-r--r-- root root 72417 ./usr/lib/python3.8/urllib/__pycache__/request.cpython-38.opt-1.pyc
+-rw-r--r-- root root 60124 ./usr/lib/python3.8/urllib/__pycache__/request.cpython-38.opt-2.pyc
+-rw-r--r-- root root 72531 ./usr/lib/python3.8/urllib/__pycache__/request.cpython-38.pyc
+-rw-r--r-- root root 3289 ./usr/lib/python3.8/urllib/__pycache__/response.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2710 ./usr/lib/python3.8/urllib/__pycache__/response.cpython-38.opt-2.pyc
+-rw-r--r-- root root 3289 ./usr/lib/python3.8/urllib/__pycache__/response.cpython-38.pyc
+-rw-r--r-- root root 7327 ./usr/lib/python3.8/urllib/__pycache__/robotparser.cpython-38.opt-1.pyc
+-rw-r--r-- root root 5959 ./usr/lib/python3.8/urllib/__pycache__/robotparser.cpython-38.opt-2.pyc
+-rw-r--r-- root root 7327 ./usr/lib/python3.8/urllib/__pycache__/robotparser.cpython-38.pyc
+-rw-r--r-- root root 101308 ./usr/lib/python3.8/urllib/request.py
+-rw-r--r-- root root 2299 ./usr/lib/python3.8/urllib/response.py
+-rw-r--r-- root root 9424 ./usr/lib/python3.8/urllib/robotparser.py
+-rw-r--r-- root root 30394 ./usr/lib/python3.8/uuid.py
+-rwxr-xr-x root root 6959 ./usr/lib/python3.8/uu.py
+-rw-r--r-- root root 19688 ./usr/lib/python3.8/warnings.py
+-rw-r--r-- root root 21387 ./usr/lib/python3.8/weakref.py
+-rw-r--r-- root root 5735 ./usr/lib/python3.8/_weakrefset.py
+drwxr-xr-x root root 4096 ./usr/lib/python3.8/xml
+drwxr-xr-x root root 4096 ./usr/lib/python3.8/xml/dom
+-rw-r--r-- root root 3451 ./usr/lib/python3.8/xml/dom/domreg.py
+-rw-r--r-- root root 35756 ./usr/lib/python3.8/xml/dom/expatbuilder.py
+-rw-r--r-- root root 4019 ./usr/lib/python3.8/xml/dom/__init__.py
+-rw-r--r-- root root 3367 ./usr/lib/python3.8/xml/dom/minicompat.py
+-rw-r--r-- root root 66857 ./usr/lib/python3.8/xml/dom/minidom.py
+-rw-r--r-- root root 936 ./usr/lib/python3.8/xml/dom/NodeFilter.py
+-rw-r--r-- root root 11997 ./usr/lib/python3.8/xml/dom/pulldom.py
+drwxr-xr-x root root 4096 ./usr/lib/python3.8/xml/dom/__pycache__
+-rw-r--r-- root root 2850 ./usr/lib/python3.8/xml/dom/__pycache__/domreg.cpython-38.opt-1.pyc
+-rw-r--r-- root root 1648 ./usr/lib/python3.8/xml/dom/__pycache__/domreg.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2850 ./usr/lib/python3.8/xml/dom/__pycache__/domreg.cpython-38.pyc
+-rw-r--r-- root root 26806 ./usr/lib/python3.8/xml/dom/__pycache__/expatbuilder.cpython-38.opt-1.pyc
+-rw-r--r-- root root 24201 ./usr/lib/python3.8/xml/dom/__pycache__/expatbuilder.cpython-38.opt-2.pyc
+-rw-r--r-- root root 27341 ./usr/lib/python3.8/xml/dom/__pycache__/expatbuilder.cpython-38.pyc
+-rw-r--r-- root root 5530 ./usr/lib/python3.8/xml/dom/__pycache__/__init__.cpython-38.opt-1.pyc
+-rw-r--r-- root root 4735 ./usr/lib/python3.8/xml/dom/__pycache__/__init__.cpython-38.opt-2.pyc
+-rw-r--r-- root root 5530 ./usr/lib/python3.8/xml/dom/__pycache__/__init__.cpython-38.pyc
+-rw-r--r-- root root 2650 ./usr/lib/python3.8/xml/dom/__pycache__/minicompat.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2472 ./usr/lib/python3.8/xml/dom/__pycache__/minicompat.cpython-38.opt-2.pyc
+-rw-r--r-- root root 2742 ./usr/lib/python3.8/xml/dom/__pycache__/minicompat.cpython-38.pyc
+-rw-r--r-- root root 55272 ./usr/lib/python3.8/xml/dom/__pycache__/minidom.cpython-38.opt-1.pyc
+-rw-r--r-- root root 53701 ./usr/lib/python3.8/xml/dom/__pycache__/minidom.cpython-38.opt-2.pyc
+-rw-r--r-- root root 55374 ./usr/lib/python3.8/xml/dom/__pycache__/minidom.cpython-38.pyc
+-rw-r--r-- root root 967 ./usr/lib/python3.8/xml/dom/__pycache__/NodeFilter.cpython-38.opt-1.pyc
+-rw-r--r-- root root 874 ./usr/lib/python3.8/xml/dom/__pycache__/NodeFilter.cpython-38.opt-2.pyc
+-rw-r--r-- root root 967 ./usr/lib/python3.8/xml/dom/__pycache__/NodeFilter.cpython-38.pyc
+-rw-r--r-- root root 10691 ./usr/lib/python3.8/xml/dom/__pycache__/pulldom.cpython-38.opt-1.pyc
+-rw-r--r-- root root 10255 ./usr/lib/python3.8/xml/dom/__pycache__/pulldom.cpython-38.opt-2.pyc
+-rw-r--r-- root root 10691 ./usr/lib/python3.8/xml/dom/__pycache__/pulldom.cpython-38.pyc
+-rw-r--r-- root root 12464 ./usr/lib/python3.8/xml/dom/__pycache__/xmlbuilder.cpython-38.opt-1.pyc
+-rw-r--r-- root root 12035 ./usr/lib/python3.8/xml/dom/__pycache__/xmlbuilder.cpython-38.opt-2.pyc
+-rw-r--r-- root root 12494 ./usr/lib/python3.8/xml/dom/__pycache__/xmlbuilder.cpython-38.pyc
+-rw-r--r-- root root 12403 ./usr/lib/python3.8/xml/dom/xmlbuilder.py
+drwxr-xr-x root root 4096 ./usr/lib/python3.8/xml/etree
+-rw-r--r-- root root 82 ./usr/lib/python3.8/xml/etree/cElementTree.py
+-rw-r--r-- root root 5151 ./usr/lib/python3.8/xml/etree/ElementInclude.py
+-rw-r--r-- root root 13118 ./usr/lib/python3.8/xml/etree/ElementPath.py
+-rw-r--r-- root root 72728 ./usr/lib/python3.8/xml/etree/ElementTree.py
+-rw-r--r-- root root 1604 ./usr/lib/python3.8/xml/etree/__init__.py
+drwxr-xr-x root root 4096 ./usr/lib/python3.8/xml/etree/__pycache__
+-rw-r--r-- root root 173 ./usr/lib/python3.8/xml/etree/__pycache__/cElementTree.cpython-38.opt-1.pyc
+-rw-r--r-- root root 173 ./usr/lib/python3.8/xml/etree/__pycache__/cElementTree.cpython-38.opt-2.pyc
+-rw-r--r-- root root 173 ./usr/lib/python3.8/xml/etree/__pycache__/cElementTree.cpython-38.pyc
+-rw-r--r-- root root 1579 ./usr/lib/python3.8/xml/etree/__pycache__/ElementInclude.cpython-38.opt-1.pyc
+-rw-r--r-- root root 1579 ./usr/lib/python3.8/xml/etree/__pycache__/ElementInclude.cpython-38.opt-2.pyc
+-rw-r--r-- root root 1579 ./usr/lib/python3.8/xml/etree/__pycache__/ElementInclude.cpython-38.pyc
+-rw-r--r-- root root 8434 ./usr/lib/python3.8/xml/etree/__pycache__/ElementPath.cpython-38.opt-1.pyc
+-rw-r--r-- root root 8434 ./usr/lib/python3.8/xml/etree/__pycache__/ElementPath.cpython-38.opt-2.pyc
+-rw-r--r-- root root 8434 ./usr/lib/python3.8/xml/etree/__pycache__/ElementPath.cpython-38.pyc
+-rw-r--r-- root root 55298 ./usr/lib/python3.8/xml/etree/__pycache__/ElementTree.cpython-38.opt-1.pyc
+-rw-r--r-- root root 36901 ./usr/lib/python3.8/xml/etree/__pycache__/ElementTree.cpython-38.opt-2.pyc
+-rw-r--r-- root root 55612 ./usr/lib/python3.8/xml/etree/__pycache__/ElementTree.cpython-38.pyc
+-rw-r--r-- root root 131 ./usr/lib/python3.8/xml/etree/__pycache__/__init__.cpython-38.opt-1.pyc
+-rw-r--r-- root root 131 ./usr/lib/python3.8/xml/etree/__pycache__/__init__.cpython-38.opt-2.pyc
+-rw-r--r-- root root 131 ./usr/lib/python3.8/xml/etree/__pycache__/__init__.cpython-38.pyc
+-rw-r--r-- root root 557 ./usr/lib/python3.8/xml/__init__.py
+drwxr-xr-x root root 4096 ./usr/lib/python3.8/xml/parsers
+-rw-r--r-- root root 248 ./usr/lib/python3.8/xml/parsers/expat.py
+-rw-r--r-- root root 167 ./usr/lib/python3.8/xml/parsers/__init__.py
+drwxr-xr-x root root 4096 ./usr/lib/python3.8/xml/parsers/__pycache__
+-rw-r--r-- root root 334 ./usr/lib/python3.8/xml/parsers/__pycache__/expat.cpython-38.opt-1.pyc
+-rw-r--r-- root root 268 ./usr/lib/python3.8/xml/parsers/__pycache__/expat.cpython-38.opt-2.pyc
+-rw-r--r-- root root 334 ./usr/lib/python3.8/xml/parsers/__pycache__/expat.cpython-38.pyc
+-rw-r--r-- root root 305 ./usr/lib/python3.8/xml/parsers/__pycache__/__init__.cpython-38.opt-1.pyc
+-rw-r--r-- root root 133 ./usr/lib/python3.8/xml/parsers/__pycache__/__init__.cpython-38.opt-2.pyc
+-rw-r--r-- root root 305 ./usr/lib/python3.8/xml/parsers/__pycache__/__init__.cpython-38.pyc
+drwxr-xr-x root root 4096 ./usr/lib/python3.8/xml/__pycache__
+-rw-r--r-- root root 692 ./usr/lib/python3.8/xml/__pycache__/__init__.cpython-38.opt-1.pyc
+-rw-r--r-- root root 169 ./usr/lib/python3.8/xml/__pycache__/__init__.cpython-38.opt-2.pyc
+-rw-r--r-- root root 692 ./usr/lib/python3.8/xml/__pycache__/__init__.cpython-38.pyc
+drwxr-xr-x root root 4096 ./usr/lib/python3.8/xml/sax
+-rw-r--r-- root root 4785 ./usr/lib/python3.8/xml/sax/_exceptions.py
+-rw-r--r-- root root 15704 ./usr/lib/python3.8/xml/sax/expatreader.py
+-rw-r--r-- root root 13922 ./usr/lib/python3.8/xml/sax/handler.py
+-rw-r--r-- root root 3647 ./usr/lib/python3.8/xml/sax/__init__.py
+drwxr-xr-x root root 4096 ./usr/lib/python3.8/xml/sax/__pycache__
+-rw-r--r-- root root 5444 ./usr/lib/python3.8/xml/sax/__pycache__/_exceptions.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2841 ./usr/lib/python3.8/xml/sax/__pycache__/_exceptions.cpython-38.opt-2.pyc
+-rw-r--r-- root root 5444 ./usr/lib/python3.8/xml/sax/__pycache__/_exceptions.cpython-38.pyc
+-rw-r--r-- root root 12495 ./usr/lib/python3.8/xml/sax/__pycache__/expatreader.cpython-38.opt-1.pyc
+-rw-r--r-- root root 12084 ./usr/lib/python3.8/xml/sax/__pycache__/expatreader.cpython-38.opt-2.pyc
+-rw-r--r-- root root 12495 ./usr/lib/python3.8/xml/sax/__pycache__/expatreader.cpython-38.pyc
+-rw-r--r-- root root 12422 ./usr/lib/python3.8/xml/sax/__pycache__/handler.cpython-38.opt-1.pyc
+-rw-r--r-- root root 4651 ./usr/lib/python3.8/xml/sax/__pycache__/handler.cpython-38.opt-2.pyc
+-rw-r--r-- root root 12422 ./usr/lib/python3.8/xml/sax/__pycache__/handler.cpython-38.pyc
+-rw-r--r-- root root 3219 ./usr/lib/python3.8/xml/sax/__pycache__/__init__.cpython-38.opt-1.pyc
+-rw-r--r-- root root 2156 ./usr/lib/python3.8/xml/sax/__pycache__/__init__.cpython-38.opt-2.pyc
+-rw-r--r-- root root 3219 ./usr/lib/python3.8/xml/sax/__pycache__/__init__.cpython-38.pyc
+-rw-r--r-- root root 12919 ./usr/lib/python3.8/xml/sax/__pycache__/saxutils.cpython-38.opt-1.pyc
+-rw-r--r-- root root 11264 ./usr/lib/python3.8/xml/sax/__pycache__/saxutils.cpython-38.opt-2.pyc
+-rw-r--r-- root root 12919 ./usr/lib/python3.8/xml/sax/__pycache__/saxutils.cpython-38.pyc
+-rw-r--r-- root root 16844 ./usr/lib/python3.8/xml/sax/__pycache__/xmlreader.cpython-38.opt-1.pyc
+-rw-r--r-- root root 10407 ./usr/lib/python3.8/xml/sax/__pycache__/xmlreader.cpython-38.opt-2.pyc
+-rw-r--r-- root root 16844 ./usr/lib/python3.8/xml/sax/__pycache__/xmlreader.cpython-38.pyc
+-rw-r--r-- root root 12255 ./usr/lib/python3.8/xml/sax/saxutils.py
+-rw-r--r-- root root 12684 ./usr/lib/python3.8/xml/sax/xmlreader.py
+-rw-r--r-- root root 87626 ./usr/lib/python3.8/zipfile.py
+-rw-r--r-- root root 3920 ./usr/lib/Scrt1.o
+drwxr-xr-x root root 4096 ./usr/lib/ssl-1.1
+lrwxrwxrwx root root 22 ./usr/lib/ssl-1.1/certs -> ../../../etc/ssl/certs
+-rw-r--r-- root root 412 ./usr/lib/ssl-1.1/ct_log_list.cnf
+-rw-r--r-- root root 412 ./usr/lib/ssl-1.1/ct_log_list.cnf.dist
+-rw-r--r-- root root 10909 ./usr/lib/ssl-1.1/openssl.cnf.dist
+lrwxrwxrwx root root 28 ./usr/lib/ssl-1.1/openssl.cnf -> ../../../etc/ssl/openssl.cnf
+lrwxrwxrwx root root 24 ./usr/lib/ssl-1.1/private -> ../../../etc/ssl/private
+drwxr-xr-x root root 4096 ./usr/lib/systemd
+drwxr-xr-x root root 4096 ./usr/lib/systemd/user
+-rw-r--r-- root root 360 ./usr/lib/systemd/user/dbus.service
+-rw-r--r-- root root 174 ./usr/lib/systemd/user/dbus.socket
+drwxr-xr-x root root 4096 ./usr/lib/systemd/user/sockets.target.wants
+lrwxrwxrwx root root 14 ./usr/lib/systemd/user/sockets.target.wants/dbus.socket -> ../dbus.socket
+drwxr-xr-x root root 4096 ./usr/lib/x86_64-poky-linux
+drwxr-xr-x root root 4096 ./usr/lib/x86_64-poky-linux/10.1.0
+-rw-r--r-- root root 2432 ./usr/lib/x86_64-poky-linux/10.1.0/crtbegin.o
+-rw-r--r-- root root 2752 ./usr/lib/x86_64-poky-linux/10.1.0/crtbeginS.o
+-rw-r--r-- root root 2944 ./usr/lib/x86_64-poky-linux/10.1.0/crtbeginT.o
+-rw-r--r-- root root 1200 ./usr/lib/x86_64-poky-linux/10.1.0/crtend.o
+-rw-r--r-- root root 1200 ./usr/lib/x86_64-poky-linux/10.1.0/crtendS.o
+-rw-r--r-- root root 3848 ./usr/lib/x86_64-poky-linux/10.1.0/crtfastmath.o
+-rw-r--r-- root root 3400 ./usr/lib/x86_64-poky-linux/10.1.0/crtprec32.o
+-rw-r--r-- root root 3416 ./usr/lib/x86_64-poky-linux/10.1.0/crtprec64.o
+-rw-r--r-- root root 3400 ./usr/lib/x86_64-poky-linux/10.1.0/crtprec80.o
+-rw-r--r-- root root 6179894 ./usr/lib/x86_64-poky-linux/10.1.0/libgcc.a
+-rw-r--r-- root root 405636 ./usr/lib/x86_64-poky-linux/10.1.0/libgcc_eh.a
+-rw-r--r-- root root 267062 ./usr/lib/x86_64-poky-linux/10.1.0/libgcov.a
+-rw-r--r-- root root 201 ./usr/lib/xml2Conf.sh
+drwxr-xr-x root root 4096 ./usr/lib/xtables
+-rwxr-xr-x root root 14432 ./usr/lib/xtables/libip6t_ah.so
+-rwxr-xr-x root root 14640 ./usr/lib/xtables/libip6t_DNAT.so
+-rwxr-xr-x root root 14440 ./usr/lib/xtables/libip6t_DNPT.so
+-rwxr-xr-x root root 14432 ./usr/lib/xtables/libip6t_dst.so
+-rwxr-xr-x root root 14208 ./usr/lib/xtables/libip6t_eui64.so
+-rwxr-xr-x root root 14432 ./usr/lib/xtables/libip6t_frag.so
+-rwxr-xr-x root root 14432 ./usr/lib/xtables/libip6t_hbh.so
+-rwxr-xr-x root root 14432 ./usr/lib/xtables/libip6t_hl.so
+-rwxr-xr-x root root 14440 ./usr/lib/xtables/libip6t_HL.so
+-rwxr-xr-x root root 14440 ./usr/lib/xtables/libip6t_icmp6.so
+-rwxr-xr-x root root 14440 ./usr/lib/xtables/libip6t_ipv6header.so
+-rwxr-xr-x root root 14440 ./usr/lib/xtables/libip6t_LOG.so
+-rwxr-xr-x root root 14448 ./usr/lib/xtables/libip6t_MASQUERADE.so
+-rwxr-xr-x root root 14432 ./usr/lib/xtables/libip6t_mh.so
+-rwxr-xr-x root root 14448 ./usr/lib/xtables/libip6t_NETMAP.so
+-rwxr-xr-x root root 14448 ./usr/lib/xtables/libip6t_REDIRECT.so
+-rwxr-xr-x root root 14448 ./usr/lib/xtables/libip6t_REJECT.so
+-rwxr-xr-x root root 14432 ./usr/lib/xtables/libip6t_rt.so
+-rwxr-xr-x root root 14440 ./usr/lib/xtables/libip6t_SNAT.so
+-rwxr-xr-x root root 14440 ./usr/lib/xtables/libip6t_SNPT.so
+-rwxr-xr-x root root 22816 ./usr/lib/xtables/libip6t_srh.so
+-rwxr-xr-x root root 14432 ./usr/lib/xtables/libipt_ah.so
+-rwxr-xr-x root root 14448 ./usr/lib/xtables/libipt_CLUSTERIP.so
+-rwxr-xr-x root root 18736 ./usr/lib/xtables/libipt_DNAT.so
+-rwxr-xr-x root root 14440 ./usr/lib/xtables/libipt_ECN.so
+-rwxr-xr-x root root 14432 ./usr/lib/xtables/libipt_icmp.so
+-rwxr-xr-x root root 14440 ./usr/lib/xtables/libipt_LOG.so
+-rwxr-xr-x root root 14448 ./usr/lib/xtables/libipt_MASQUERADE.so
+-rwxr-xr-x root root 14448 ./usr/lib/xtables/libipt_NETMAP.so
+-rwxr-xr-x root root 14432 ./usr/lib/xtables/libipt_realm.so
+-rwxr-xr-x root root 14448 ./usr/lib/xtables/libipt_REDIRECT.so
+-rwxr-xr-x root root 14448 ./usr/lib/xtables/libipt_REJECT.so
+-rwxr-xr-x root root 14440 ./usr/lib/xtables/libipt_SNAT.so
+-rwxr-xr-x root root 14432 ./usr/lib/xtables/libipt_ttl.so
+-rwxr-xr-x root root 14440 ./usr/lib/xtables/libipt_TTL.so
+-rwxr-xr-x root root 14440 ./usr/lib/xtables/libipt_ULOG.so
+-rwxr-xr-x root root 14632 ./usr/lib/xtables/libxt_addrtype.so
+-rwxr-xr-x root root 14440 ./usr/lib/xtables/libxt_AUDIT.so
+-rwxr-xr-x root root 14624 ./usr/lib/xtables/libxt_bpf.so
+-rwxr-xr-x root root 14816 ./usr/lib/xtables/libxt_cgroup.so
+-rwxr-xr-x root root 14448 ./usr/lib/xtables/libxt_CHECKSUM.so
+-rwxr-xr-x root root 14648 ./usr/lib/xtables/libxt_CLASSIFY.so
+-rwxr-xr-x root root 14440 ./usr/lib/xtables/libxt_cluster.so
+-rwxr-xr-x root root 14440 ./usr/lib/xtables/libxt_comment.so
+-rwxr-xr-x root root 14440 ./usr/lib/xtables/libxt_connbytes.so
+-rwxr-xr-x root root 15016 ./usr/lib/xtables/libxt_connlimit.so
+-rwxr-xr-x root root 14632 ./usr/lib/xtables/libxt_connmark.so
+-rwxr-xr-x root root 18944 ./usr/lib/xtables/libxt_CONNMARK.so
+-rwxr-xr-x root root 14448 ./usr/lib/xtables/libxt_CONNSECMARK.so
+-rwxr-xr-x root root 32744 ./usr/lib/xtables/libxt_conntrack.so
+-rwxr-xr-x root root 14432 ./usr/lib/xtables/libxt_cpu.so
+-rwxr-xr-x root root 19736 ./usr/lib/xtables/libxt_CT.so
+-rwxr-xr-x root root 14432 ./usr/lib/xtables/libxt_dccp.so
+-rwxr-xr-x root root 14440 ./usr/lib/xtables/libxt_devgroup.so
+-rwxr-xr-x root root 14624 ./usr/lib/xtables/libxt_dscp.so
+-rwxr-xr-x root root 14640 ./usr/lib/xtables/libxt_DSCP.so
+-rwxr-xr-x root root 14432 ./usr/lib/xtables/libxt_ecn.so
+-rwxr-xr-x root root 14432 ./usr/lib/xtables/libxt_esp.so
+-rwxr-xr-x root root 36136 ./usr/lib/xtables/libxt_hashlimit.so
+-rwxr-xr-x root root 14432 ./usr/lib/xtables/libxt_helper.so
+-rwxr-xr-x root root 14640 ./usr/lib/xtables/libxt_HMARK.so
+-rwxr-xr-x root root 14448 ./usr/lib/xtables/libxt_IDLETIMER.so
+-rwxr-xr-x root root 14432 ./usr/lib/xtables/libxt_ipcomp.so
+-rwxr-xr-x root root 14824 ./usr/lib/xtables/libxt_iprange.so
+-rwxr-xr-x root root 14624 ./usr/lib/xtables/libxt_ipvs.so
+-rwxr-xr-x root root 14440 ./usr/lib/xtables/libxt_LED.so
+-rwxr-xr-x root root 14432 ./usr/lib/xtables/libxt_length.so
+-rwxr-xr-x root root 14624 ./usr/lib/xtables/libxt_limit.so
+-rwxr-xr-x root root 14432 ./usr/lib/xtables/libxt_mac.so
+-rwxr-xr-x root root 14624 ./usr/lib/xtables/libxt_mark.so
+-rwxr-xr-x root root 15168 ./usr/lib/xtables/libxt_MARK.so
+-rwxr-xr-x root root 19112 ./usr/lib/xtables/libxt_multiport.so
+-rwxr-xr-x root root 14624 ./usr/lib/xtables/libxt_nfacct.so
+-rwxr-xr-x root root 14440 ./usr/lib/xtables/libxt_NFLOG.so
+-rwxr-xr-x root root 15048 ./usr/lib/xtables/libxt_NFQUEUE.so
+lrwxrwxrwx root root 11 ./usr/lib/xtables/libxt_NOTRACK.so -> libxt_CT.so
+-rwxr-xr-x root root 14432 ./usr/lib/xtables/libxt_osf.so
+-rwxr-xr-x root root 23008 ./usr/lib/xtables/libxt_owner.so
+-rwxr-xr-x root root 14440 ./usr/lib/xtables/libxt_physdev.so
+-rwxr-xr-x root root 14440 ./usr/lib/xtables/libxt_pkttype.so
+-rwxr-xr-x root root 14624 ./usr/lib/xtables/libxt_policy.so
+-rwxr-xr-x root root 14432 ./usr/lib/xtables/libxt_quota.so
+-rwxr-xr-x root root 14440 ./usr/lib/xtables/libxt_rateest.so
+-rwxr-xr-x root root 14448 ./usr/lib/xtables/libxt_RATEEST.so
+-rwxr-xr-x root root 18912 ./usr/lib/xtables/libxt_recent.so
+-rwxr-xr-x root root 14440 ./usr/lib/xtables/libxt_rpfilter.so
+-rwxr-xr-x root root 14432 ./usr/lib/xtables/libxt_sctp.so
+-rwxr-xr-x root root 14448 ./usr/lib/xtables/libxt_SECMARK.so
+-rwxr-xr-x root root 23392 ./usr/lib/xtables/libxt_set.so
+-rwxr-xr-x root root 23232 ./usr/lib/xtables/libxt_SET.so
+-rwxr-xr-x root root 15008 ./usr/lib/xtables/libxt_socket.so
+-rwxr-xr-x root root 14368 ./usr/lib/xtables/libxt_standard.so
+lrwxrwxrwx root root 18 ./usr/lib/xtables/libxt_state.so -> libxt_conntrack.so
+-rwxr-xr-x root root 14440 ./usr/lib/xtables/libxt_statistic.so
+-rwxr-xr-x root root 14624 ./usr/lib/xtables/libxt_string.so
+-rwxr-xr-x root root 14448 ./usr/lib/xtables/libxt_SYNPROXY.so
+-rwxr-xr-x root root 14432 ./usr/lib/xtables/libxt_tcpmss.so
+-rwxr-xr-x root root 14640 ./usr/lib/xtables/libxt_TCPMSS.so
+-rwxr-xr-x root root 14448 ./usr/lib/xtables/libxt_TCPOPTSTRIP.so
+-rwxr-xr-x root root 14432 ./usr/lib/xtables/libxt_tcp.so
+-rwxr-xr-x root root 14640 ./usr/lib/xtables/libxt_TEE.so
+-rwxr-xr-x root root 14432 ./usr/lib/xtables/libxt_time.so
+-rwxr-xr-x root root 14624 ./usr/lib/xtables/libxt_tos.so
+-rwxr-xr-x root root 14640 ./usr/lib/xtables/libxt_TOS.so
+-rwxr-xr-x root root 14840 ./usr/lib/xtables/libxt_TPROXY.so
+-rwxr-xr-x root root 14208 ./usr/lib/xtables/libxt_TRACE.so
+-rwxr-xr-x root root 14432 ./usr/lib/xtables/libxt_u32.so
+-rwxr-xr-x root root 14432 ./usr/lib/xtables/libxt_udp.so
+drwxr-xr-x root root 4096 ./usr/sbin
+lrwxrwxrwx root root 19 ./usr/sbin/addgroup -> /bin/busybox.nosuid
+-rwxr-xr-x root root 26664 ./usr/sbin/addpart
+lrwxrwxrwx root root 19 ./usr/sbin/adduser -> /bin/busybox.nosuid
+-rwxr-xr-x root root 30760 ./usr/sbin/blkdiscard
+-rwxr-xr-x root root 71720 ./usr/sbin/blkzone
+-rwxr-xr-x root root 47136 ./usr/sbin/chcpu
+-rwxr-xr-x root root 59152 ./usr/sbin/chgpasswd
+-rwxr-xr-x root root 55056 ./usr/sbin/chpasswd.shadow
+lrwxrwxrwx root root 25 ./usr/sbin/chpasswd -> /usr/sbin/chpasswd.shadow
+-rwxr-xr-x root root 55464 ./usr/sbin/chroot.coreutils
+lrwxrwxrwx root root 26 ./usr/sbin/chroot -> /usr/sbin/chroot.coreutils
+lrwxrwxrwx root root 19 ./usr/sbin/delgroup -> /bin/busybox.nosuid
+-rwxr-xr-x root root 26664 ./usr/sbin/delpart
+lrwxrwxrwx root root 19 ./usr/sbin/deluser -> /bin/busybox.nosuid
+lrwxrwxrwx root root 19 ./usr/sbin/fbset -> /bin/busybox.nosuid
+-rwxr-xr-x root root 34856 ./usr/sbin/fdformat
+-rwxr-xr-x root root 14368 ./usr/sbin/findfs
+-rwxr-xr-x root root 38984 ./usr/sbin/fsck.cramfs
+lrwxrwxrwx root root 29 ./usr/sbin/fsfreeze -> /usr/sbin/fsfreeze.util-linux
+-rwxr-xr-x root root 14384 ./usr/sbin/fsfreeze.util-linux
+-rwxr-xr-x root root 84336 ./usr/sbin/groupadd
+-rwxr-xr-x root root 75952 ./usr/sbin/groupdel
+-rwxr-xr-x root root 59160 ./usr/sbin/groupmems
+-rwxr-xr-x root root 84272 ./usr/sbin/groupmod
+-rwxr-xr-x root root 59120 ./usr/sbin/grpck
+-rwxr-xr-x root root 54896 ./usr/sbin/grpconv
+-rwxr-xr-x root root 54904 ./usr/sbin/grpunconv
+-rwxr-xr-x root root 30936 ./usr/sbin/iconvconfig
+lrwxrwxrwx root root 20 ./usr/sbin/ip6tables-legacy-restore -> xtables-legacy-multi
+lrwxrwxrwx root root 20 ./usr/sbin/ip6tables-legacy-save -> xtables-legacy-multi
+lrwxrwxrwx root root 20 ./usr/sbin/ip6tables-legacy -> xtables-legacy-multi
+lrwxrwxrwx root root 20 ./usr/sbin/ip6tables-restore -> xtables-legacy-multi
+lrwxrwxrwx root root 20 ./usr/sbin/ip6tables-save -> xtables-legacy-multi
+lrwxrwxrwx root root 20 ./usr/sbin/ip6tables -> xtables-legacy-multi
+lrwxrwxrwx root root 20 ./usr/sbin/iptables-legacy-restore -> xtables-legacy-multi
+lrwxrwxrwx root root 20 ./usr/sbin/iptables-legacy-save -> xtables-legacy-multi
+lrwxrwxrwx root root 20 ./usr/sbin/iptables-legacy -> xtables-legacy-multi
+lrwxrwxrwx root root 20 ./usr/sbin/iptables-restore -> xtables-legacy-multi
+lrwxrwxrwx root root 20 ./usr/sbin/iptables-save -> xtables-legacy-multi
+lrwxrwxrwx root root 20 ./usr/sbin/iptables -> xtables-legacy-multi
+-rwxr-xr-x root root 34856 ./usr/sbin/ldattach
+lrwxrwxrwx root root 19 ./usr/sbin/loadfont -> /bin/busybox.nosuid
+-rwxr-xr-x root root 14288 ./usr/sbin/logoutd
+-rwxr-xr-x root root 14368 ./usr/sbin/mkfs
+-rwxr-xr-x root root 38880 ./usr/sbin/mkfs.cramfs
+-rwxr-xr-x root root 96560 ./usr/sbin/newusers
+-rwxr-xr-x root root 116776 ./usr/sbin/partx
+-rwxr-xr-x root root 55016 ./usr/sbin/pwck
+-rwxr-xr-x root root 50792 ./usr/sbin/pwconv
+-rwxr-xr-x root root 50808 ./usr/sbin/pwunconv
+-rwxr-xr-x root root 14368 ./usr/sbin/raw
+lrwxrwxrwx root root 19 ./usr/sbin/rdate -> /bin/busybox.nosuid
+lrwxrwxrwx root root 32 ./usr/sbin/readprofile -> /usr/sbin/readprofile.util-linux
+-rwxr-xr-x root root 22616 ./usr/sbin/readprofile.util-linux
+-rwxr-xr-x root root 63528 ./usr/sbin/resizepart
+lrwxrwxrwx root root 27 ./usr/sbin/rfkill -> /usr/sbin/rfkill.util-linux
+-rwxr-xr-x root root 47152 ./usr/sbin/rfkill.util-linux
+lrwxrwxrwx root root 28 ./usr/sbin/rtcwake -> /usr/sbin/rtcwake.util-linux
+-rwxr-xr-x root root 47152 ./usr/sbin/rtcwake.util-linux
+-rwxr-xr-x root root 1986 ./usr/sbin/run-postinsts
+-rwxr-xr-x root root 141352 ./usr/sbin/sfdisk
+-rwxr-xr-x root root 18472 ./usr/sbin/swaplabel
+lrwxrwxrwx root root 19 ./usr/sbin/udhcpd -> /bin/busybox.nosuid
+-rwxr-xr-x root root 5990 ./usr/sbin/update-ca-certificates
+-rwxr-xr-x root root 6365 ./usr/sbin/update-rc.d
+-rwxr-xr-x root root 130136 ./usr/sbin/useradd
+-rwxr-xr-x root root 88328 ./usr/sbin/userdel
+-rwxr-xr-x root root 125880 ./usr/sbin/usermod
+-rwxr-xr-x root root 39032 ./usr/sbin/uuidd
+-rwxr-xr-x root root 47144 ./usr/sbin/wipefs
+-rwxr-xr-x root root 98960 ./usr/sbin/xtables-legacy-multi
+-rwxr-xr-x root root 112792 ./usr/sbin/zramctl
+drwxr-xr-x root root 4096 ./usr/share
+drwxr-xr-x root root 4096 ./usr/share/aclocal
+-rw-r--r-- root root 2221 ./usr/share/aclocal/bison-i18n.m4
+-rw-r--r-- root root 1184 ./usr/share/aclocal/cap-ng.m4
+-rw-r--r-- root root 6337 ./usr/share/aclocal/freetype2.m4
+-rw-r--r-- root root 8316 ./usr/share/aclocal/glib-2.0.m4
+-rw-r--r-- root root 15838 ./usr/share/aclocal/glib-gettext.m4
+-rw-r--r-- root root 3589 ./usr/share/aclocal/gsettings.m4
+-rw-r--r-- root root 5132 ./usr/share/aclocal/introspection.m4
+-rw-r--r-- root root 357 ./usr/share/aclocal/libxml.m4
+-rw-r--r-- root root 428 ./usr/share/aclocal/wayland-scanner.m4
+-rw-r--r-- root root 71315 ./usr/share/aclocal/xorg-macros.m4
+-rw-r--r-- root root 6537 ./usr/share/aclocal/xtrans.m4
+drwxr-xr-x root root 4096 ./usr/share/awk
+-rw-r--r-- root root 383 ./usr/share/awk/assert.awk
+-rw-r--r-- root root 334 ./usr/share/awk/bits2str.awk
+-rw-r--r-- root root 307 ./usr/share/awk/cliff_rand.awk
+-rw-r--r-- root root 234 ./usr/share/awk/ctime.awk
+-rw-r--r-- root root 315 ./usr/share/awk/ftrans.awk
+-rw-r--r-- root root 3278 ./usr/share/awk/getopt.awk
+-rw-r--r-- root root 2491 ./usr/share/awk/gettime.awk
+-rw-r--r-- root root 1765 ./usr/share/awk/group.awk
+-rw-r--r-- root root 221 ./usr/share/awk/have_mpfr.awk
+-rw-r--r-- root root 2340 ./usr/share/awk/inplace.awk
+-rw-r--r-- root root 462 ./usr/share/awk/intdiv0.awk
+-rw-r--r-- root root 378 ./usr/share/awk/join.awk
+-rw-r--r-- root root 238 ./usr/share/awk/libintl.awk
+-rw-r--r-- root root 422 ./usr/share/awk/noassign.awk
+-rw-r--r-- root root 1282 ./usr/share/awk/ns_passwd.awk
+-rw-r--r-- root root 937 ./usr/share/awk/ord.awk
+-rw-r--r-- root root 1199 ./usr/share/awk/passwd.awk
+-rw-r--r-- root root 355 ./usr/share/awk/processarray.awk
+-rw-r--r-- root root 1031 ./usr/share/awk/quicksort.awk
+-rw-r--r-- root root 489 ./usr/share/awk/readable.awk
+-rw-r--r-- root root 267 ./usr/share/awk/readfile.awk
+-rw-r--r-- root root 404 ./usr/share/awk/rewind.awk
+-rw-r--r-- root root 661 ./usr/share/awk/round.awk
+-rw-r--r-- root root 472 ./usr/share/awk/shellquote.awk
+-rw-r--r-- root root 1454 ./usr/share/awk/strtonum.awk
+-rw-r--r-- root root 214 ./usr/share/awk/walkarray.awk
+-rw-r--r-- root root 424 ./usr/share/awk/zerofile.awk
+drwxr-xr-x root root 4096 ./usr/share/bash-completion
+-rw-r--r-- root root 74302 ./usr/share/bash-completion/bash_completion
+drwxr-xr-x root root 4096 ./usr/share/bison
+-rw-r--r-- root root 1206 ./usr/share/bison/bison-default.css
+drwxr-xr-x root root 4096 ./usr/share/bison/m4sugar
+-rw-r--r-- root root 14755 ./usr/share/bison/m4sugar/foreach.m4
+-rw-r--r-- root root 122297 ./usr/share/bison/m4sugar/m4sugar.m4
+-rw-r--r-- root root 7134 ./usr/share/bison/README.md
+drwxr-xr-x root root 4096 ./usr/share/bison/skeletons
+-rw-r--r-- root root 41025 ./usr/share/bison/skeletons/bison.m4
+-rw-r--r-- root root 2571 ./usr/share/bison/skeletons/c-like.m4
+-rw-r--r-- root root 32297 ./usr/share/bison/skeletons/c.m4
+-rw-r--r-- root root 21273 ./usr/share/bison/skeletons/c++.m4
+-rw-r--r-- root root 1163 ./usr/share/bison/skeletons/c-skel.m4
+-rw-r--r-- root root 1169 ./usr/share/bison/skeletons/c++-skel.m4
+-rw-r--r-- root root 10492 ./usr/share/bison/skeletons/d.m4
+-rw-r--r-- root root 1135 ./usr/share/bison/skeletons/d-skel.m4
+-rw-r--r-- root root 91038 ./usr/share/bison/skeletons/glr.c
+-rw-r--r-- root root 12766 ./usr/share/bison/skeletons/glr.cc
+-rw-r--r-- root root 14410 ./usr/share/bison/skeletons/java.m4
+-rw-r--r-- root root 1166 ./usr/share/bison/skeletons/java-skel.m4
+-rw-r--r-- root root 51533 ./usr/share/bison/skeletons/lalr1.cc
+-rw-r--r-- root root 30671 ./usr/share/bison/skeletons/lalr1.d
+-rw-r--r-- root root 37180 ./usr/share/bison/skeletons/lalr1.java
+-rw-r--r-- root root 10331 ./usr/share/bison/skeletons/location.cc
+-rw-r--r-- root root 1896 ./usr/share/bison/skeletons/README-D.txt
+-rw-r--r-- root root 3975 ./usr/share/bison/skeletons/stack.hh
+-rw-r--r-- root root 13220 ./usr/share/bison/skeletons/variant.hh
+-rw-r--r-- root root 70766 ./usr/share/bison/skeletons/yacc.c
+drwxr-xr-x root root 4096 ./usr/share/bison/xslt
+-rw-r--r-- root root 3364 ./usr/share/bison/xslt/bison.xsl
+-rw-r--r-- root root 12820 ./usr/share/bison/xslt/xml2dot.xsl
+-rw-r--r-- root root 18554 ./usr/share/bison/xslt/xml2text.xsl
+-rw-r--r-- root root 22678 ./usr/share/bison/xslt/xml2xhtml.xsl
+drwxr-xr-x root root 4096 ./usr/share/ca-certificates
+drwxr-xr-x root root 12288 ./usr/share/ca-certificates/mozilla
+-rw-r--r-- root root 2772 ./usr/share/ca-certificates/mozilla/ACCVRAIZ1.crt
+-rw-r--r-- root root 1972 ./usr/share/ca-certificates/mozilla/AC_RAIZ_FNMT-RCM.crt
+-rw-r--r-- root root 2049 ./usr/share/ca-certificates/mozilla/Actalis_Authentication_Root_CA.crt
+-rw-r--r-- root root 1521 ./usr/share/ca-certificates/mozilla/AddTrust_External_Root.crt
+-rw-r--r-- root root 1204 ./usr/share/ca-certificates/mozilla/AffirmTrust_Commercial.crt
+-rw-r--r-- root root 1204 ./usr/share/ca-certificates/mozilla/AffirmTrust_Networking.crt
+-rw-r--r-- root root 1891 ./usr/share/ca-certificates/mozilla/AffirmTrust_Premium.crt
+-rw-r--r-- root root 753 ./usr/share/ca-certificates/mozilla/AffirmTrust_Premium_ECC.crt
+-rw-r--r-- root root 1188 ./usr/share/ca-certificates/mozilla/Amazon_Root_CA_1.crt
+-rw-r--r-- root root 1883 ./usr/share/ca-certificates/mozilla/Amazon_Root_CA_2.crt
+-rw-r--r-- root root 656 ./usr/share/ca-certificates/mozilla/Amazon_Root_CA_3.crt
+-rw-r--r-- root root 737 ./usr/share/ca-certificates/mozilla/Amazon_Root_CA_4.crt
+-rw-r--r-- root root 1261 ./usr/share/ca-certificates/mozilla/Atos_TrustedRoot_2011.crt
+-rw-r--r-- root root 2167 ./usr/share/ca-certificates/mozilla/Autoridad_de_Certificacion_Firmaprofesional_CIF_A62634068.crt
+-rw-r--r-- root root 1261 ./usr/share/ca-certificates/mozilla/Baltimore_CyberTrust_Root.crt
+-rw-r--r-- root root 1915 ./usr/share/ca-certificates/mozilla/Buypass_Class_2_Root_CA.crt
+-rw-r--r-- root root 1915 ./usr/share/ca-certificates/mozilla/Buypass_Class_3_Root_CA.crt
+-rw-r--r-- root root 1935 ./usr/share/ca-certificates/mozilla/CA_Disig_Root_R2.crt
+-rw-r--r-- root root 1330 ./usr/share/ca-certificates/mozilla/Certigna.crt
+-rw-r--r-- root root 1992 ./usr/share/ca-certificates/mozilla/Certinomis_-_Root_CA.crt
+-rw-r--r-- root root 1298 ./usr/share/ca-certificates/mozilla/Certplus_Class_2_Primary_CA.crt
+-rw-r--r-- root root 1176 ./usr/share/ca-certificates/mozilla/certSIGN_ROOT_CA.crt
+-rw-r--r-- root root 2078 ./usr/share/ca-certificates/mozilla/Certum_Trusted_Network_CA_2.crt
+-rw-r--r-- root root 1354 ./usr/share/ca-certificates/mozilla/Certum_Trusted_Network_CA.crt
+-rw-r--r-- root root 1984 ./usr/share/ca-certificates/mozilla/CFCA_EV_ROOT.crt
+-rw-r--r-- root root 2594 ./usr/share/ca-certificates/mozilla/Chambers_of_Commerce_Root_-_2008.crt
+-rw-r--r-- root root 1517 ./usr/share/ca-certificates/mozilla/Comodo_AAA_Services_root.crt
+-rw-r--r-- root root 1489 ./usr/share/ca-certificates/mozilla/COMODO_Certification_Authority.crt
+-rw-r--r-- root root 940 ./usr/share/ca-certificates/mozilla/COMODO_ECC_Certification_Authority.crt
+-rw-r--r-- root root 2086 ./usr/share/ca-certificates/mozilla/COMODO_RSA_Certification_Authority.crt
+-rw-r--r-- root root 1318 ./usr/share/ca-certificates/mozilla/Cybertrust_Global_Root.crt
+-rw-r--r-- root root 1318 ./usr/share/ca-certificates/mozilla/Deutsche_Telekom_Root_CA_2.crt
+-rw-r--r-- root root 1350 ./usr/share/ca-certificates/mozilla/DigiCert_Assured_ID_Root_CA.crt
+-rw-r--r-- root root 1306 ./usr/share/ca-certificates/mozilla/DigiCert_Assured_ID_Root_G2.crt
+-rw-r--r-- root root 851 ./usr/share/ca-certificates/mozilla/DigiCert_Assured_ID_Root_G3.crt
+-rw-r--r-- root root 1338 ./usr/share/ca-certificates/mozilla/DigiCert_Global_Root_CA.crt
+-rw-r--r-- root root 1294 ./usr/share/ca-certificates/mozilla/DigiCert_Global_Root_G2.crt
+-rw-r--r-- root root 839 ./usr/share/ca-certificates/mozilla/DigiCert_Global_Root_G3.crt
+-rw-r--r-- root root 1367 ./usr/share/ca-certificates/mozilla/DigiCert_High_Assurance_EV_Root_CA.crt
+-rw-r--r-- root root 1988 ./usr/share/ca-certificates/mozilla/DigiCert_Trusted_Root_G4.crt
+-rw-r--r-- root root 1200 ./usr/share/ca-certificates/mozilla/DST_Root_CA_X3.crt
+-rw-r--r-- root root 1517 ./usr/share/ca-certificates/mozilla/D-TRUST_Root_Class_3_CA_2_2009.crt
+-rw-r--r-- root root 1537 ./usr/share/ca-certificates/mozilla/D-TRUST_Root_Class_3_CA_2_EV_2009.crt
+-rw-r--r-- root root 1911 ./usr/share/ca-certificates/mozilla/EC-ACC.crt
+-rw-r--r-- root root 1452 ./usr/share/ca-certificates/mozilla/EE_Certification_Centre_Root_CA.crt
+-rw-r--r-- root root 1505 ./usr/share/ca-certificates/mozilla/Entrust.net_Premium_2048_Secure_Server_CA.crt
+-rw-r--r-- root root 1643 ./usr/share/ca-certificates/mozilla/Entrust_Root_Certification_Authority.crt
+-rw-r--r-- root root 1090 ./usr/share/ca-certificates/mozilla/Entrust_Root_Certification_Authority_-_EC1.crt
+-rw-r--r-- root root 1533 ./usr/share/ca-certificates/mozilla/Entrust_Root_Certification_Authority_-_G2.crt
+-rw-r--r-- root root 2033 ./usr/share/ca-certificates/mozilla/ePKI_Root_Certification_Authority.crt
+-rw-r--r-- root root 2244 ./usr/share/ca-certificates/mozilla/E-Tugra_Certification_Authority.crt
+-rw-r--r-- root root 1980 ./usr/share/ca-certificates/mozilla/GDCA_TrustAUTH_R5_ROOT.crt
+-rw-r--r-- root root 1216 ./usr/share/ca-certificates/mozilla/GeoTrust_Global_CA.crt
+-rw-r--r-- root root 1269 ./usr/share/ca-certificates/mozilla/GeoTrust_Primary_Certification_Authority.crt
+-rw-r--r-- root root 989 ./usr/share/ca-certificates/mozilla/GeoTrust_Primary_Certification_Authority_-_G2.crt
+-rw-r--r-- root root 1444 ./usr/share/ca-certificates/mozilla/GeoTrust_Primary_Certification_Authority_-_G3.crt
+-rw-r--r-- root root 1939 ./usr/share/ca-certificates/mozilla/GeoTrust_Universal_CA_2.crt
+-rw-r--r-- root root 1935 ./usr/share/ca-certificates/mozilla/GeoTrust_Universal_CA.crt
+-rw-r--r-- root root 2585 ./usr/share/ca-certificates/mozilla/Global_Chambersign_Root_-_2008.crt
+-rw-r--r-- root root 713 ./usr/share/ca-certificates/mozilla/GlobalSign_ECC_Root_CA_-_R4.crt
+-rw-r--r-- root root 794 ./usr/share/ca-certificates/mozilla/GlobalSign_ECC_Root_CA_-_R5.crt
+-rw-r--r-- root root 1261 ./usr/share/ca-certificates/mozilla/GlobalSign_Root_CA.crt
+-rw-r--r-- root root 1354 ./usr/share/ca-certificates/mozilla/GlobalSign_Root_CA_-_R2.crt
+-rw-r--r-- root root 1229 ./usr/share/ca-certificates/mozilla/GlobalSign_Root_CA_-_R3.crt
+-rw-r--r-- root root 1972 ./usr/share/ca-certificates/mozilla/GlobalSign_Root_CA_-_R6.crt
+-rw-r--r-- root root 1448 ./usr/share/ca-certificates/mozilla/Go_Daddy_Class_2_CA.crt
+-rw-r--r-- root root 1367 ./usr/share/ca-certificates/mozilla/Go_Daddy_Root_Certificate_Authority_-_G2.crt
+-rw-r--r-- root root 1017 ./usr/share/ca-certificates/mozilla/Hellenic_Academic_and_Research_Institutions_ECC_RootCA_2015.crt
+-rw-r--r-- root root 1513 ./usr/share/ca-certificates/mozilla/Hellenic_Academic_and_Research_Institutions_RootCA_2011.crt
+-rw-r--r-- root root 2155 ./usr/share/ca-certificates/mozilla/Hellenic_Academic_and_Research_Institutions_RootCA_2015.crt
+-rw-r--r-- root root 1168 ./usr/share/ca-certificates/mozilla/Hongkong_Post_Root_CA_1.crt
+-rw-r--r-- root root 1923 ./usr/share/ca-certificates/mozilla/IdenTrust_Commercial_Root_CA_1.crt
+-rw-r--r-- root root 1931 ./usr/share/ca-certificates/mozilla/IdenTrust_Public_Sector_Root_CA_1.crt
+-rw-r--r-- root root 1939 ./usr/share/ca-certificates/mozilla/ISRG_Root_X1.crt
+-rw-r--r-- root root 2122 ./usr/share/ca-certificates/mozilla/Izenpe.com.crt
+-rw-r--r-- root root 2057 ./usr/share/ca-certificates/mozilla/LuxTrust_Global_Root_2.crt
+-rw-r--r-- root root 1460 ./usr/share/ca-certificates/mozilla/Microsec_e-Szigno_Root_CA_2009.crt
+-rw-r--r-- root root 1476 ./usr/share/ca-certificates/mozilla/NetLock_Arany_=Class_Gold=_Főtanúsítvány.crt
+-rw-r--r-- root root 1411 ./usr/share/ca-certificates/mozilla/Network_Solutions_Certificate_Authority.crt
+-rw-r--r-- root root 1428 ./usr/share/ca-certificates/mozilla/OISTE_WISeKey_Global_Root_GA_CA.crt
+-rw-r--r-- root root 1346 ./usr/share/ca-certificates/mozilla/OISTE_WISeKey_Global_Root_GB_CA.crt
+-rw-r--r-- root root 895 ./usr/share/ca-certificates/mozilla/OISTE_WISeKey_Global_Root_GC_CA.crt
+-rw-r--r-- root root 1923 ./usr/share/ca-certificates/mozilla/QuoVadis_Root_CA_1_G3.crt
+-rw-r--r-- root root 2041 ./usr/share/ca-certificates/mozilla/QuoVadis_Root_CA_2.crt
+-rw-r--r-- root root 1923 ./usr/share/ca-certificates/mozilla/QuoVadis_Root_CA_2_G3.crt
+-rw-r--r-- root root 2354 ./usr/share/ca-certificates/mozilla/QuoVadis_Root_CA_3.crt
+-rw-r--r-- root root 1923 ./usr/share/ca-certificates/mozilla/QuoVadis_Root_CA_3_G3.crt
+-rw-r--r-- root root 2078 ./usr/share/ca-certificates/mozilla/QuoVadis_Root_CA.crt
+-rw-r--r-- root root 1354 ./usr/share/ca-certificates/mozilla/Secure_Global_CA.crt
+-rw-r--r-- root root 1249 ./usr/share/ca-certificates/mozilla/SecureSign_RootCA11.crt
+-rw-r--r-- root root 1350 ./usr/share/ca-certificates/mozilla/SecureTrust_CA.crt
+-rw-r--r-- root root 1261 ./usr/share/ca-certificates/mozilla/Security_Communication_RootCA2.crt
+-rw-r--r-- root root 1224 ./usr/share/ca-certificates/mozilla/Security_Communication_Root_CA.crt
+-rw-r--r-- root root 1143 ./usr/share/ca-certificates/mozilla/Sonera_Class_2_Root_CA.crt
+-rw-r--r-- root root 956 ./usr/share/ca-certificates/mozilla/SSL.com_EV_Root_Certification_Authority_ECC.crt
+-rw-r--r-- root root 2114 ./usr/share/ca-certificates/mozilla/SSL.com_EV_Root_Certification_Authority_RSA_R2.crt
+-rw-r--r-- root root 944 ./usr/share/ca-certificates/mozilla/SSL.com_Root_Certification_Authority_ECC.crt
+-rw-r--r-- root root 2094 ./usr/share/ca-certificates/mozilla/SSL.com_Root_Certification_Authority_RSA.crt
+-rw-r--r-- root root 1948 ./usr/share/ca-certificates/mozilla/Staat_der_Nederlanden_EV_Root_CA.crt
+-rw-r--r-- root root 2069 ./usr/share/ca-certificates/mozilla/Staat_der_Nederlanden_Root_CA_-_G2.crt
+-rw-r--r-- root root 1952 ./usr/share/ca-certificates/mozilla/Staat_der_Nederlanden_Root_CA_-_G3.crt
+-rw-r--r-- root root 1468 ./usr/share/ca-certificates/mozilla/Starfield_Class_2_CA.crt
+-rw-r--r-- root root 1399 ./usr/share/ca-certificates/mozilla/Starfield_Root_Certificate_Authority_-_G2.crt
+-rw-r--r-- root root 1424 ./usr/share/ca-certificates/mozilla/Starfield_Services_Root_Certificate_Authority_-_G2.crt
+-rw-r--r-- root root 2045 ./usr/share/ca-certificates/mozilla/SwissSign_Gold_CA_-_G2.crt
+-rw-r--r-- root root 2049 ./usr/share/ca-certificates/mozilla/SwissSign_Silver_CA_-_G2.crt
+-rw-r--r-- root root 1257 ./usr/share/ca-certificates/mozilla/SZAFIR_ROOT_CA2.crt
+-rw-r--r-- root root 1948 ./usr/share/ca-certificates/mozilla/Taiwan_GRCA.crt
+-rw-r--r-- root root 1870 ./usr/share/ca-certificates/mozilla/TeliaSonera_Root_CA_v1.crt
+-rw-r--r-- root root 1493 ./usr/share/ca-certificates/mozilla/thawte_Primary_Root_CA.crt
+-rw-r--r-- root root 940 ./usr/share/ca-certificates/mozilla/thawte_Primary_Root_CA_-_G2.crt
+-rw-r--r-- root root 1505 ./usr/share/ca-certificates/mozilla/thawte_Primary_Root_CA_-_G3.crt
+-rw-r--r-- root root 1493 ./usr/share/ca-certificates/mozilla/TrustCor_ECA-1.crt
+-rw-r--r-- root root 1513 ./usr/share/ca-certificates/mozilla/TrustCor_RootCert_CA-1.crt
+-rw-r--r-- root root 2204 ./usr/share/ca-certificates/mozilla/TrustCor_RootCert_CA-2.crt
+-rw-r--r-- root root 1241 ./usr/share/ca-certificates/mozilla/Trustis_FPS_Root_CA.crt
+-rw-r--r-- root root 1367 ./usr/share/ca-certificates/mozilla/T-TeleSec_GlobalRoot_Class_2.crt
+-rw-r--r-- root root 1367 ./usr/share/ca-certificates/mozilla/T-TeleSec_GlobalRoot_Class_3.crt
+-rw-r--r-- root root 1582 ./usr/share/ca-certificates/mozilla/TUBITAK_Kamu_SM_SSL_Kok_Sertifikasi_-_Surum_1.crt
+-rw-r--r-- root root 1883 ./usr/share/ca-certificates/mozilla/TWCA_Global_Root_CA.crt
+-rw-r--r-- root root 1269 ./usr/share/ca-certificates/mozilla/TWCA_Root_Certification_Authority.crt
+-rw-r--r-- root root 948 ./usr/share/ca-certificates/mozilla/USERTrust_ECC_Certification_Authority.crt
+-rw-r--r-- root root 2094 ./usr/share/ca-certificates/mozilla/USERTrust_RSA_Certification_Authority.crt
+-rw-r--r-- root root 1484 ./usr/share/ca-certificates/mozilla/Verisign_Class_3_Public_Primary_Certification_Authority_-_G3.crt
+-rw-r--r-- root root 1281 ./usr/share/ca-certificates/mozilla/VeriSign_Class_3_Public_Primary_Certification_Authority_-_G4.crt
+-rw-r--r-- root root 1732 ./usr/share/ca-certificates/mozilla/VeriSign_Class_3_Public_Primary_Certification_Authority_-_G5.crt
+-rw-r--r-- root root 1700 ./usr/share/ca-certificates/mozilla/VeriSign_Universal_Root_Certification_Authority.crt
+-rw-r--r-- root root 1513 ./usr/share/ca-certificates/mozilla/XRamp_Global_CA_Root.crt
+drwxr-xr-x root root 4096 ./usr/share/cmake
+drwxr-xr-x root root 4096 ./usr/share/cmake/bash-completion
+-rw-r--r-- root root 393 ./usr/share/cmake/bash-completion/bash-completion-config.cmake
+-rw-r--r-- root root 252 ./usr/share/cmake/bash-completion/bash-completion-config-version.cmake
+drwxr-xr-x root root 4096 ./usr/share/dbus-1
+drwxr-xr-x root root 4096 ./usr/share/dbus-1/services
+-rw-r--r-- root root 3561 ./usr/share/dbus-1/session.conf
+drwxr-xr-x root root 4096 ./usr/share/dbus-1/session.d
+-rw-r--r-- root root 5692 ./usr/share/dbus-1/system.conf
+drwxr-xr-x root root 4096 ./usr/share/dbus-1/system.d
+drwxr-xr-x root root 4096 ./usr/share/dbus-1/system-services
+drwxr-xr-x root root 4096 ./usr/share/dict
+drwxr-xr-x root root 4096 ./usr/share/drirc.d
+-rw-r--r-- root root 27422 ./usr/share/drirc.d/00-mesa-defaults.conf
+drwxr-xr-x root root 4096 ./usr/share/et
+-rw-r--r-- root root 6485 ./usr/share/et/et_c.awk
+-rw-r--r-- root root 4539 ./usr/share/et/et_h.awk
+drwxr-xr-x root root 4096 ./usr/share/fontconfig
+drwxr-xr-x root root 4096 ./usr/share/fontconfig/conf.avail
+-rw-r--r-- root root 706 ./usr/share/fontconfig/conf.avail/10-autohint.conf
+-rw-r--r-- root root 692 ./usr/share/fontconfig/conf.avail/10-hinting-full.conf
+-rw-r--r-- root root 696 ./usr/share/fontconfig/conf.avail/10-hinting-medium.conf
+-rw-r--r-- root root 692 ./usr/share/fontconfig/conf.avail/10-hinting-none.conf
+-rw-r--r-- root root 696 ./usr/share/fontconfig/conf.avail/10-hinting-slight.conf
+-rw-r--r-- root root 723 ./usr/share/fontconfig/conf.avail/10-no-sub-pixel.conf
+-rw-r--r-- root root 2228 ./usr/share/fontconfig/conf.avail/10-scale-bitmap-fonts.conf
+-rw-r--r-- root root 748 ./usr/share/fontconfig/conf.avail/10-sub-pixel-bgr.conf
+-rw-r--r-- root root 748 ./usr/share/fontconfig/conf.avail/10-sub-pixel-rgb.conf
+-rw-r--r-- root root 758 ./usr/share/fontconfig/conf.avail/10-sub-pixel-vbgr.conf
+-rw-r--r-- root root 758 ./usr/share/fontconfig/conf.avail/10-sub-pixel-vrgb.conf
+-rw-r--r-- root root 701 ./usr/share/fontconfig/conf.avail/10-unhinted.conf
+-rw-r--r-- root root 771 ./usr/share/fontconfig/conf.avail/11-lcdfilter-default.conf
+-rw-r--r-- root root 768 ./usr/share/fontconfig/conf.avail/11-lcdfilter-legacy.conf
+-rw-r--r-- root root 765 ./usr/share/fontconfig/conf.avail/11-lcdfilter-light.conf
+-rw-r--r-- root root 1537 ./usr/share/fontconfig/conf.avail/20-unhint-small-vera.conf
+-rw-r--r-- root root 3489 ./usr/share/fontconfig/conf.avail/25-unhint-nonlatin.conf
+-rw-r--r-- root root 13274 ./usr/share/fontconfig/conf.avail/30-metric-aliases.conf
+-rw-r--r-- root root 5424 ./usr/share/fontconfig/conf.avail/40-nonlatin.conf
+-rw-r--r-- root root 3543 ./usr/share/fontconfig/conf.avail/45-generic.conf
+-rw-r--r-- root root 6600 ./usr/share/fontconfig/conf.avail/45-latin.conf
+-rw-r--r-- root root 799 ./usr/share/fontconfig/conf.avail/49-sansserif.conf
+-rw-r--r-- root root 911 ./usr/share/fontconfig/conf.avail/50-user.conf
+-rw-r--r-- root root 423 ./usr/share/fontconfig/conf.avail/51-local.conf
+-rw-r--r-- root root 2041 ./usr/share/fontconfig/conf.avail/60-generic.conf
+-rw-r--r-- root root 2068 ./usr/share/fontconfig/conf.avail/60-latin.conf
+-rw-r--r-- root root 10293 ./usr/share/fontconfig/conf.avail/65-fonts-persian.conf
+-rw-r--r-- root root 464 ./usr/share/fontconfig/conf.avail/65-khmer.conf
+-rw-r--r-- root root 8170 ./usr/share/fontconfig/conf.avail/65-nonlatin.conf
+-rw-r--r-- root root 847 ./usr/share/fontconfig/conf.avail/69-unifont.conf
+-rw-r--r-- root root 487 ./usr/share/fontconfig/conf.avail/70-no-bitmaps.conf
+-rw-r--r-- root root 487 ./usr/share/fontconfig/conf.avail/70-yes-bitmaps.conf
+-rw-r--r-- root root 597 ./usr/share/fontconfig/conf.avail/80-delicious.conf
+-rw-r--r-- root root 1917 ./usr/share/fontconfig/conf.avail/90-synthetic.conf
+drwxr-xr-x root root 4096 ./usr/share/gettext
+drwxr-xr-x root root 4096 ./usr/share/gettext/its
+-rw-r--r-- root root 189 ./usr/share/gettext/its/fontconfig.its
+-rw-r--r-- root root 189 ./usr/share/gettext/its/fontconfig.loc
+-rw-r--r-- root root 1048 ./usr/share/gettext/its/gschema.its
+-rw-r--r-- root root 333 ./usr/share/gettext/its/gschema.loc
+drwxr-xr-x root root 4096 ./usr/share/gir-1.0
+-rw-r--r-- root root 23723 ./usr/share/gir-1.0/cairo-1.0.gir
+-rw-r--r-- root root 1185 ./usr/share/gir-1.0/DBus-1.0.gir
+-rw-r--r-- root root 797 ./usr/share/gir-1.0/DBusGLib-1.0.gir
+-rw-r--r-- root root 620 ./usr/share/gir-1.0/fontconfig-2.0.gir
+-rw-r--r-- root root 768 ./usr/share/gir-1.0/freetype2-2.0.gir
+-rw-r--r-- root root 6332887 ./usr/share/gir-1.0/Gio-2.0.gir
+-rw-r--r-- root root 29235 ./usr/share/gir-1.0/gir-1.2.rnc
+-rw-r--r-- root root 324506 ./usr/share/gir-1.0/GIRepository-2.0.gir
+-rw-r--r-- root root 1122 ./usr/share/gir-1.0/GL-1.0.gir
+-rw-r--r-- root root 3544680 ./usr/share/gir-1.0/GLib-2.0.gir
+-rw-r--r-- root root 19691 ./usr/share/gir-1.0/GModule-2.0.gir
+-rw-r--r-- root root 1247584 ./usr/share/gir-1.0/GObject-2.0.gir
+-rw-r--r-- root root 938 ./usr/share/gir-1.0/libxml2-2.0.gir
+-rw-r--r-- root root 65349 ./usr/share/gir-1.0/Vulkan-1.0.gir
+-rw-r--r-- root root 611 ./usr/share/gir-1.0/win32-1.0.gir
+-rw-r--r-- root root 361 ./usr/share/gir-1.0/xfixes-4.0.gir
+-rw-r--r-- root root 745 ./usr/share/gir-1.0/xft-2.0.gir
+-rw-r--r-- root root 2325 ./usr/share/gir-1.0/xlib-2.0.gir
+-rw-r--r-- root root 808 ./usr/share/gir-1.0/xrandr-1.3.gir
+drwxr-xr-x root root 4096 ./usr/share/glib-2.0
+drwxr-xr-x root root 4096 ./usr/share/glib-2.0/gettext
+drwxr-xr-x root root 4096 ./usr/share/glib-2.0/gettext/po
+-rw-r--r-- root root 8076 ./usr/share/glib-2.0/gettext/po/Makefile.in.in
+drwxr-xr-x root root 4096 ./usr/share/glib-2.0/schemas
+-rw-r--r-- root root 2916 ./usr/share/glib-2.0/schemas/gschema.dtd
+drwxr-xr-x root root 4096 ./usr/share/glib-2.0/valgrind
+-rw-r--r-- root root 15263 ./usr/share/glib-2.0/valgrind/glib.supp
+drwxr-xr-x root root 4096 ./usr/share/gobject-introspection-1.0
+-rw-r--r-- root root 15228 ./usr/share/gobject-introspection-1.0/gdump.c
+-rw-r--r-- root root 7177 ./usr/share/gobject-introspection-1.0/Makefile.introspection
+drwxr-xr-x root root 4096 ./usr/share/info
+drwxr-xr-x root root 4096 ./usr/share/libdrm
+-rw-r--r-- root root 7547 ./usr/share/libdrm/amdgpu.ids
+drwxr-xr-x root root 4096 ./usr/share/man
+drwxr-xr-x root root 4096 ./usr/share/mime
+-rw-r--r-- root root 10777 ./usr/share/mime/aliases
+drwxr-xr-x root root 20480 ./usr/share/mime/application
+-rw-r--r-- root root 2700 ./usr/share/mime/application/andrew-inset.xml
+-rw-r--r-- root root 3200 ./usr/share/mime/application/annodex.xml
+-rw-r--r-- root root 3123 ./usr/share/mime/application/atom+xml.xml
+-rw-r--r-- root root 3009 ./usr/share/mime/application/dicom.xml
+-rw-r--r-- root root 3299 ./usr/share/mime/application/ecmascript.xml
+-rw-r--r-- root root 3513 ./usr/share/mime/application/epub+zip.xml
+-rw-r--r-- root root 2263 ./usr/share/mime/application/geo+json.xml
+-rw-r--r-- root root 2304 ./usr/share/mime/application/gml+xml.xml
+-rw-r--r-- root root 3264 ./usr/share/mime/application/gnunet-directory.xml
+-rw-r--r-- root root 2354 ./usr/share/mime/application/gpx+xml.xml
+-rw-r--r-- root root 2813 ./usr/share/mime/application/gzip.xml
+-rw-r--r-- root root 3757 ./usr/share/mime/application/illustrator.xml
+-rw-r--r-- root root 3404 ./usr/share/mime/application/javascript.xml
+-rw-r--r-- root root 2140 ./usr/share/mime/application/jrd+json.xml
+-rw-r--r-- root root 1993 ./usr/share/mime/application/json-patch+json.xml
+-rw-r--r-- root root 2281 ./usr/share/mime/application/json.xml
+-rw-r--r-- root root 2255 ./usr/share/mime/application/ld+json.xml
+-rw-r--r-- root root 4240 ./usr/share/mime/application/mac-binhex40.xml
+-rw-r--r-- root root 1136 ./usr/share/mime/application/mathematica.xml
+-rw-r--r-- root root 3328 ./usr/share/mime/application/mathml+xml.xml
+-rw-r--r-- root root 3112 ./usr/share/mime/application/mbox.xml
+-rw-r--r-- root root 2759 ./usr/share/mime/application/metalink4+xml.xml
+-rw-r--r-- root root 2761 ./usr/share/mime/application/metalink+xml.xml
+-rw-r--r-- root root 2925 ./usr/share/mime/application/msword-template.xml
+-rw-r--r-- root root 3057 ./usr/share/mime/application/msword.xml
+-rw-r--r-- root root 2615 ./usr/share/mime/application/mxf.xml
+-rw-r--r-- root root 2687 ./usr/share/mime/application/octet-stream.xml
+-rw-r--r-- root root 3111 ./usr/share/mime/application/oda.xml
+-rw-r--r-- root root 3393 ./usr/share/mime/application/ogg.xml
+-rw-r--r-- root root 2057 ./usr/share/mime/application/owl+xml.xml
+-rw-r--r-- root root 3059 ./usr/share/mime/application/oxps.xml
+-rw-r--r-- root root 3131 ./usr/share/mime/application/pdf.xml
+-rw-r--r-- root root 4545 ./usr/share/mime/application/pgp-encrypted.xml
+-rw-r--r-- root root 3138 ./usr/share/mime/application/pgp-keys.xml
+-rw-r--r-- root root 3716 ./usr/share/mime/application/pgp-signature.xml
+-rw-r--r-- root root 3686 ./usr/share/mime/application/pkcs10.xml
+-rw-r--r-- root root 3703 ./usr/share/mime/application/pkcs12.xml
+-rw-r--r-- root root 1090 ./usr/share/mime/application/pkcs7-mime.xml
+-rw-r--r-- root root 3684 ./usr/share/mime/application/pkcs7-signature.xml
+-rw-r--r-- root root 2231 ./usr/share/mime/application/pkcs8-encrypted.xml
+-rw-r--r-- root root 2936 ./usr/share/mime/application/pkcs8.xml
+-rw-r--r-- root root 2674 ./usr/share/mime/application/pkix-cert.xml
+-rw-r--r-- root root 1120 ./usr/share/mime/application/pkix-crl.xml
+-rw-r--r-- root root 3306 ./usr/share/mime/application/pkix-pkipath.xml
+-rw-r--r-- root root 1110 ./usr/share/mime/application/postscript.xml
+-rw-r--r-- root root 3011 ./usr/share/mime/application/prs.plucker.xml
+-rw-r--r-- root root 1992 ./usr/share/mime/application/raml+yaml.xml
+-rw-r--r-- root root 1115 ./usr/share/mime/application/ram.xml
+-rw-r--r-- root root 2800 ./usr/share/mime/application/rdf+xml.xml
+-rw-r--r-- root root 2940 ./usr/share/mime/application/relax-ng-compact-syntax.xml
+-rw-r--r-- root root 2927 ./usr/share/mime/application/rss+xml.xml
+-rw-r--r-- root root 2954 ./usr/share/mime/application/rtf.xml
+-rw-r--r-- root root 3857 ./usr/share/mime/application/sdp.xml
+-rw-r--r-- root root 3701 ./usr/share/mime/application/sieve.xml
+-rw-r--r-- root root 3131 ./usr/share/mime/application/smil+xml.xml
+-rw-r--r-- root root 2733 ./usr/share/mime/application/sql.xml
+-rw-r--r-- root root 2434 ./usr/share/mime/application/trig.xml
+-rw-r--r-- root root 3433 ./usr/share/mime/application/vnd.adobe.flash.movie.xml
+-rw-r--r-- root root 432 ./usr/share/mime/application/vnd.amazon.mobi8-ebook.xml
+-rw-r--r-- root root 2605 ./usr/share/mime/application/vnd.android.package-archive.xml
+-rw-r--r-- root root 2358 ./usr/share/mime/application/vnd.appimage.xml
+-rw-r--r-- root root 3597 ./usr/share/mime/application/vnd.apple.mpegurl.xml
+-rw-r--r-- root root 3598 ./usr/share/mime/application/vnd.chess-pgn.xml
+-rw-r--r-- root root 2381 ./usr/share/mime/application/vnd.coffeescript.xml
+-rw-r--r-- root root 3230 ./usr/share/mime/application/vnd.comicbook-rar.xml
+-rw-r--r-- root root 3226 ./usr/share/mime/application/vnd.comicbook+zip.xml
+-rw-r--r-- root root 3655 ./usr/share/mime/application/vnd.corel-draw.xml
+-rw-r--r-- root root 3205 ./usr/share/mime/application/vnd.debian.binary-package.xml
+-rw-r--r-- root root 3403 ./usr/share/mime/application/vnd.emusic-emusic_package.xml
+-rw-r--r-- root root 2211 ./usr/share/mime/application/vnd.flatpak.ref.xml
+-rw-r--r-- root root 2273 ./usr/share/mime/application/vnd.flatpak.repo.xml
+-rw-r--r-- root root 2279 ./usr/share/mime/application/vnd.flatpak.xml
+-rw-r--r-- root root 3675 ./usr/share/mime/application/vnd.framemaker.xml
+-rw-r--r-- root root 3051 ./usr/share/mime/application/vnd.google-earth.kml+xml.xml
+-rw-r--r-- root root 3579 ./usr/share/mime/application/vnd.google-earth.kmz.xml
+-rw-r--r-- root root 2820 ./usr/share/mime/application/vnd.hp-hpgl.xml
+-rw-r--r-- root root 2769 ./usr/share/mime/application/vnd.hp-pcl.xml
+-rw-r--r-- root root 2536 ./usr/share/mime/application/vnd.iccprofile.xml
+-rw-r--r-- root root 3991 ./usr/share/mime/application/vnd.lotus-1-2-3.xml
+-rw-r--r-- root root 1142 ./usr/share/mime/application/vnd.lotus-wordpro.xml
+-rw-r--r-- root root 3540 ./usr/share/mime/application/vnd.mozilla.xul+xml.xml
+-rw-r--r-- root root 3419 ./usr/share/mime/application/vnd.ms-access.xml
+-rw-r--r-- root root 2921 ./usr/share/mime/application/vnd.ms-asf.xml
+-rw-r--r-- root root 3299 ./usr/share/mime/application/vnd.ms-cab-compressed.xml
+-rw-r--r-- root root 2619 ./usr/share/mime/application/vnd.ms-excel.addin.macroenabled.12.xml
+-rw-r--r-- root root 3407 ./usr/share/mime/application/vnd.ms-excel.sheet.binary.macroenabled.12.xml
+-rw-r--r-- root root 3330 ./usr/share/mime/application/vnd.ms-excel.sheet.macroenabled.12.xml
+-rw-r--r-- root root 2685 ./usr/share/mime/application/vnd.ms-excel.template.macroenabled.12.xml
+-rw-r--r-- root root 3525 ./usr/share/mime/application/vnd.ms-excel.xml
+-rw-r--r-- root root 3011 ./usr/share/mime/application/vnd.ms-htmlhelp.xml
+-rw-r--r-- root root 2734 ./usr/share/mime/application/vnd.ms-powerpoint.addin.macroenabled.12.xml
+-rw-r--r-- root root 3491 ./usr/share/mime/application/vnd.ms-powerpoint.presentation.macroenabled.12.xml
+-rw-r--r-- root root 2420 ./usr/share/mime/application/vnd.ms-powerpoint.slide.macroenabled.12.xml
+-rw-r--r-- root root 3485 ./usr/share/mime/application/vnd.ms-powerpoint.slideshow.macroenabled.12.xml
+-rw-r--r-- root root 2906 ./usr/share/mime/application/vnd.ms-powerpoint.template.macroenabled.12.xml
+-rw-r--r-- root root 3569 ./usr/share/mime/application/vnd.ms-powerpoint.xml
+-rw-r--r-- root root 2757 ./usr/share/mime/application/vnd.ms-publisher.xml
+-rw-r--r-- root root 2977 ./usr/share/mime/application/vnd.ms-tnef.xml
+-rw-r--r-- root root 1161 ./usr/share/mime/application/vnd.ms-visio.drawing.macroenabled.main+xml.xml
+-rw-r--r-- root root 1148 ./usr/share/mime/application/vnd.ms-visio.drawing.main+xml.xml
+-rw-r--r-- root root 1163 ./usr/share/mime/application/vnd.ms-visio.stencil.macroenabled.main+xml.xml
+-rw-r--r-- root root 1150 ./usr/share/mime/application/vnd.ms-visio.stencil.main+xml.xml
+-rw-r--r-- root root 1226 ./usr/share/mime/application/vnd.ms-visio.template.macroenabled.main+xml.xml
+-rw-r--r-- root root 1213 ./usr/share/mime/application/vnd.ms-visio.template.main+xml.xml
+-rw-r--r-- root root 3004 ./usr/share/mime/application/vnd.ms-word.document.macroenabled.12.xml
+-rw-r--r-- root root 2541 ./usr/share/mime/application/vnd.ms-word.template.macroenabled.12.xml
+-rw-r--r-- root root 3639 ./usr/share/mime/application/vnd.ms-works.xml
+-rw-r--r-- root root 3039 ./usr/share/mime/application/vnd.ms-wpl.xml
+-rw-r--r-- root root 2927 ./usr/share/mime/application/vnd.nintendo.snes.rom.xml
+-rw-r--r-- root root 2760 ./usr/share/mime/application/vnd.oasis.opendocument.chart-template.xml
+-rw-r--r-- root root 2879 ./usr/share/mime/application/vnd.oasis.opendocument.chart.xml
+-rw-r--r-- root root 3262 ./usr/share/mime/application/vnd.oasis.opendocument.database.xml
+-rw-r--r-- root root 2776 ./usr/share/mime/application/vnd.oasis.opendocument.formula-template.xml
+-rw-r--r-- root root 2954 ./usr/share/mime/application/vnd.oasis.opendocument.formula.xml
+-rw-r--r-- root root 3235 ./usr/share/mime/application/vnd.oasis.opendocument.graphics-flat-xml.xml
+-rw-r--r-- root root 2958 ./usr/share/mime/application/vnd.oasis.opendocument.graphics-template.xml
+-rw-r--r-- root root 2918 ./usr/share/mime/application/vnd.oasis.opendocument.graphics.xml
+-rw-r--r-- root root 2956 ./usr/share/mime/application/vnd.oasis.opendocument.image.xml
+-rw-r--r-- root root 3480 ./usr/share/mime/application/vnd.oasis.opendocument.presentation-flat-xml.xml
+-rw-r--r-- root root 2974 ./usr/share/mime/application/vnd.oasis.opendocument.presentation-template.xml
+-rw-r--r-- root root 3204 ./usr/share/mime/application/vnd.oasis.opendocument.presentation.xml
+-rw-r--r-- root root 3506 ./usr/share/mime/application/vnd.oasis.opendocument.spreadsheet-flat-xml.xml
+-rw-r--r-- root root 2970 ./usr/share/mime/application/vnd.oasis.opendocument.spreadsheet-template.xml
+-rw-r--r-- root root 3226 ./usr/share/mime/application/vnd.oasis.opendocument.spreadsheet.xml
+-rw-r--r-- root root 3352 ./usr/share/mime/application/vnd.oasis.opendocument.text-flat-xml.xml
+-rw-r--r-- root root 3033 ./usr/share/mime/application/vnd.oasis.opendocument.text-master.xml
+-rw-r--r-- root root 2956 ./usr/share/mime/application/vnd.oasis.opendocument.text-template.xml
+-rw-r--r-- root root 2925 ./usr/share/mime/application/vnd.oasis.opendocument.text-web.xml
+-rw-r--r-- root root 3024 ./usr/share/mime/application/vnd.oasis.opendocument.text.xml
+-rw-r--r-- root root 3524 ./usr/share/mime/application/vnd.openofficeorg.extension.xml
+-rw-r--r-- root root 3394 ./usr/share/mime/application/vnd.openxmlformats-officedocument.presentationml.presentation.xml
+-rw-r--r-- root root 3257 ./usr/share/mime/application/vnd.openxmlformats-officedocument.presentationml.slideshow.xml
+-rw-r--r-- root root 2932 ./usr/share/mime/application/vnd.openxmlformats-officedocument.presentationml.slide.xml
+-rw-r--r-- root root 3563 ./usr/share/mime/application/vnd.openxmlformats-officedocument.presentationml.template.xml
+-rw-r--r-- root root 3250 ./usr/share/mime/application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.xml
+-rw-r--r-- root root 3378 ./usr/share/mime/application/vnd.openxmlformats-officedocument.spreadsheetml.template.xml
+-rw-r--r-- root root 2957 ./usr/share/mime/application/vnd.openxmlformats-officedocument.wordprocessingml.document.xml
+-rw-r--r-- root root 3210 ./usr/share/mime/application/vnd.openxmlformats-officedocument.wordprocessingml.template.xml
+-rw-r--r-- root root 3457 ./usr/share/mime/application/vnd.palm.xml
+-rw-r--r-- root root 2983 ./usr/share/mime/application/vnd.rar.xml
+-rw-r--r-- root root 3320 ./usr/share/mime/application/vnd.rn-realmedia.xml
+-rw-r--r-- root root 1759 ./usr/share/mime/application/vnd.snap.xml
+-rw-r--r-- root root 3196 ./usr/share/mime/application/vnd.sqlite3.xml
+-rw-r--r-- root root 1139 ./usr/share/mime/application/vnd.squashfs.xml
+-rw-r--r-- root root 3467 ./usr/share/mime/application/vnd.stardivision.calc.xml
+-rw-r--r-- root root 3228 ./usr/share/mime/application/vnd.stardivision.chart.xml
+-rw-r--r-- root root 3156 ./usr/share/mime/application/vnd.stardivision.draw.xml
+-rw-r--r-- root root 3619 ./usr/share/mime/application/vnd.stardivision.impress.xml
+-rw-r--r-- root root 3181 ./usr/share/mime/application/vnd.stardivision.mail.xml
+-rw-r--r-- root root 3090 ./usr/share/mime/application/vnd.stardivision.math.xml
+-rw-r--r-- root root 3489 ./usr/share/mime/application/vnd.stardivision.writer.xml
+-rw-r--r-- root root 3534 ./usr/share/mime/application/vnd.sun.xml.calc.template.xml
+-rw-r--r-- root root 3762 ./usr/share/mime/application/vnd.sun.xml.calc.xml
+-rw-r--r-- root root 3513 ./usr/share/mime/application/vnd.sun.xml.draw.template.xml
+-rw-r--r-- root root 3438 ./usr/share/mime/application/vnd.sun.xml.draw.xml
+-rw-r--r-- root root 3704 ./usr/share/mime/application/vnd.sun.xml.impress.template.xml
+-rw-r--r-- root root 4000 ./usr/share/mime/application/vnd.sun.xml.impress.xml
+-rw-r--r-- root root 3488 ./usr/share/mime/application/vnd.sun.xml.math.xml
+-rw-r--r-- root root 4341 ./usr/share/mime/application/vnd.sun.xml.writer.global.xml
+-rw-r--r-- root root 3819 ./usr/share/mime/application/vnd.sun.xml.writer.template.xml
+-rw-r--r-- root root 3800 ./usr/share/mime/application/vnd.sun.xml.writer.xml
+-rw-r--r-- root root 2835 ./usr/share/mime/application/vnd.symbian.install.xml
+-rw-r--r-- root root 1126 ./usr/share/mime/application/vnd.tcpdump.pcap.xml
+-rw-r--r-- root root 3046 ./usr/share/mime/application/vnd.visio.xml
+-rw-r--r-- root root 3633 ./usr/share/mime/application/vnd.wordperfect.xml
+-rw-r--r-- root root 1189 ./usr/share/mime/application/vnd.youtube.yt.xml
+-rw-r--r-- root root 2575 ./usr/share/mime/application/winhlp.xml
+-rw-r--r-- root root 2942 ./usr/share/mime/application/x-7z-compressed.xml
+-rw-r--r-- root root 3303 ./usr/share/mime/application/x-abiword.xml
+-rw-r--r-- root root 2785 ./usr/share/mime/application/x-ace.xml
+-rw-r--r-- root root 2890 ./usr/share/mime/application/x-alz.xml
+-rw-r--r-- root root 2185 ./usr/share/mime/application/x-amiga-disk-format.xml
+-rw-r--r-- root root 3479 ./usr/share/mime/application/x-amipro.xml
+-rw-r--r-- root root 3122 ./usr/share/mime/application/x-aportisdoc.xml
+-rw-r--r-- root root 2699 ./usr/share/mime/application/x-apple-diskimage.xml
+-rw-r--r-- root root 346 ./usr/share/mime/application/x-appleworks-document.xml
+-rw-r--r-- root root 3940 ./usr/share/mime/application/x-applix-spreadsheet.xml
+-rw-r--r-- root root 3574 ./usr/share/mime/application/x-applix-word.xml
+-rw-r--r-- root root 2804 ./usr/share/mime/application/x-archive.xml
+-rw-r--r-- root root 2759 ./usr/share/mime/application/x-arc.xml
+-rw-r--r-- root root 3010 ./usr/share/mime/application/x-arj.xml
+-rw-r--r-- root root 2899 ./usr/share/mime/application/x-asp.xml
+-rw-r--r-- root root 1019 ./usr/share/mime/application/x-atari-2600-rom.xml
+-rw-r--r-- root root 1019 ./usr/share/mime/application/x-atari-7800-rom.xml
+-rw-r--r-- root root 1021 ./usr/share/mime/application/x-atari-lynx-rom.xml
+-rw-r--r-- root root 3084 ./usr/share/mime/application/x-awk.xml
+-rw-r--r-- root root 3225 ./usr/share/mime/application/x-bcpio.xml
+-rw-r--r-- root root 3540 ./usr/share/mime/application/x-bittorrent.xml
+-rw-r--r-- root root 3102 ./usr/share/mime/application/x-blender.xml
+-rw-r--r-- root root 2357 ./usr/share/mime/application/x-bsdiff.xml
+-rw-r--r-- root root 4099 ./usr/share/mime/application/x-bzdvi.xml
+-rw-r--r-- root root 3945 ./usr/share/mime/application/x-bzip-compressed-tar.xml
+-rw-r--r-- root root 2986 ./usr/share/mime/application/x-bzip.xml
+-rw-r--r-- root root 3880 ./usr/share/mime/application/x-bzpdf.xml
+-rw-r--r-- root root 4236 ./usr/share/mime/application/x-bzpostscript.xml
+-rw-r--r-- root root 3190 ./usr/share/mime/application/x-cb7.xml
+-rw-r--r-- root root 3180 ./usr/share/mime/application/x-cbt.xml
+-rw-r--r-- root root 2858 ./usr/share/mime/application/x-ccmx.xml
+-rw-r--r-- root root 3292 ./usr/share/mime/application/x-cd-image.xml
+-rw-r--r-- root root 3136 ./usr/share/mime/application/x-cdrdao-toc.xml
+-rw-r--r-- root root 1099 ./usr/share/mime/application/x-cisco-vpn-settings.xml
+-rw-r--r-- root root 3042 ./usr/share/mime/application/x-class-file.xml
+-rw-r--r-- root root 3786 ./usr/share/mime/application/x-compressed-tar.xml
+-rw-r--r-- root root 3414 ./usr/share/mime/application/x-compress.xml
+-rw-r--r-- root root 3630 ./usr/share/mime/application/x-core.xml
+-rw-r--r-- root root 4192 ./usr/share/mime/application/x-cpio-compressed.xml
+-rw-r--r-- root root 3028 ./usr/share/mime/application/x-cpio.xml
+-rw-r--r-- root root 3273 ./usr/share/mime/application/x-csh.xml
+-rw-r--r-- root root 3240 ./usr/share/mime/application/x-cue.xml
+-rw-r--r-- root root 2785 ./usr/share/mime/application/x-dar.xml
+-rw-r--r-- root root 3031 ./usr/share/mime/application/x-dbf.xml
+-rw-r--r-- root root 1136 ./usr/share/mime/application/x-dc-rom.xml
+-rw-r--r-- root root 1241 ./usr/share/mime/application/x-designer.xml
+-rw-r--r-- root root 3922 ./usr/share/mime/application/x-desktop.xml
+-rw-r--r-- root root 3052 ./usr/share/mime/application/x-dia-diagram.xml
+-rw-r--r-- root root 2405 ./usr/share/mime/application/x-dia-shape.xml
+-rw-r--r-- root root 3273 ./usr/share/mime/application/x-docbook+xml.xml
+-rw-r--r-- root root 1051 ./usr/share/mime/application/x-doom-wad.xml
+-rw-r--r-- root root 3183 ./usr/share/mime/application/x-dvi.xml
+-rw-r--r-- root root 3473 ./usr/share/mime/application/x-egon.xml
+-rw-r--r-- root root 3341 ./usr/share/mime/application/x-e-theme.xml
+-rw-r--r-- root root 2837 ./usr/share/mime/application/x-executable.xml
+-rw-r--r-- root root 2172 ./usr/share/mime/application/x-fds-disk.xml
+-rw-r--r-- root root 3142 ./usr/share/mime/application/x-fictionbook+xml.xml
+-rw-r--r-- root root 3137 ./usr/share/mime/application/x-fluid.xml
+-rw-r--r-- root root 3465 ./usr/share/mime/application/x-font-afm.xml
+-rw-r--r-- root root 2866 ./usr/share/mime/application/x-font-bdf.xml
+-rw-r--r-- root root 2854 ./usr/share/mime/application/x-font-dos.xml
+-rw-r--r-- root root 3612 ./usr/share/mime/application/x-font-framemaker.xml
+-rw-r--r-- root root 3018 ./usr/share/mime/application/x-font-libgrx.xml
+-rw-r--r-- root root 3800 ./usr/share/mime/application/x-font-linux-psf.xml
+-rw-r--r-- root root 2918 ./usr/share/mime/application/x-font-pcf.xml
+-rw-r--r-- root root 3031 ./usr/share/mime/application/x-font-speedo.xml
+-rw-r--r-- root root 3244 ./usr/share/mime/application/x-font-sunos-news.xml
+-rw-r--r-- root root 3352 ./usr/share/mime/application/x-font-tex-tfm.xml
+-rw-r--r-- root root 2839 ./usr/share/mime/application/x-font-tex.xml
+-rw-r--r-- root root 3183 ./usr/share/mime/application/x-font-ttx.xml
+-rw-r--r-- root root 2200 ./usr/share/mime/application/x-font-type1.xml
+-rw-r--r-- root root 2741 ./usr/share/mime/application/x-font-vfont.xml
+-rw-r--r-- root root 1959 ./usr/share/mime/application/x-gameboy-color-rom.xml
+-rw-r--r-- root root 2895 ./usr/share/mime/application/x-gameboy-rom.xml
+-rw-r--r-- root root 2521 ./usr/share/mime/application/x-gamecube-rom.xml
+-rw-r--r-- root root 1722 ./usr/share/mime/application/x-gamegear-rom.xml
+-rw-r--r-- root root 3217 ./usr/share/mime/application/x-gba-rom.xml
+-rw-r--r-- root root 3125 ./usr/share/mime/application/x-gdbm.xml
+-rw-r--r-- root root 3528 ./usr/share/mime/application/x-gedcom.xml
+-rw-r--r-- root root 1892 ./usr/share/mime/application/x-genesis-32x-rom.xml
+-rw-r--r-- root root 2901 ./usr/share/mime/application/x-genesis-rom.xml
+-rw-r--r-- root root 4594 ./usr/share/mime/application/x-gettext-translation.xml
+-rw-r--r-- root root 3040 ./usr/share/mime/application/x-glade.xml
+-rw-r--r-- root root 3208 ./usr/share/mime/application/x-gnucash.xml
+-rw-r--r-- root root 3362 ./usr/share/mime/application/x-gnumeric.xml
+-rw-r--r-- root root 3130 ./usr/share/mime/application/x-gnuplot.xml
+-rw-r--r-- root root 2839 ./usr/share/mime/application/x-go-sgf.xml
+-rw-r--r-- root root 3559 ./usr/share/mime/application/x-graphite.xml
+-rw-r--r-- root root 1253 ./usr/share/mime/application/x-gtk-builder.xml
+-rw-r--r-- root root 3098 ./usr/share/mime/application/x-gtktalog.xml
+-rw-r--r-- root root 4096 ./usr/share/mime/application/x-gzdvi.xml
+-rw-r--r-- root root 4598 ./usr/share/mime/application/x-gz-font-linux-psf.xml
+-rw-r--r-- root root 3871 ./usr/share/mime/application/x-gzpdf.xml
+-rw-r--r-- root root 4380 ./usr/share/mime/application/x-gzpostscript.xml
+-rw-r--r-- root root 3146 ./usr/share/mime/application/x-hdf.xml
+-rw-r--r-- root root 2102 ./usr/share/mime/application/x-hfe-floppy-image.xml
+-rw-r--r-- root root 3048 ./usr/share/mime/application/xhtml+xml.xml
+-rw-r--r-- root root 3437 ./usr/share/mime/application/x-hwp.xml
+-rw-r--r-- root root 3922 ./usr/share/mime/application/x-hwt.xml
+-rw-r--r-- root root 3805 ./usr/share/mime/application/x-ica.xml
+-rw-r--r-- root root 2088 ./usr/share/mime/application/x-iff.xml
+-rw-r--r-- root root 2959 ./usr/share/mime/application/x-ipod-firmware.xml
+-rw-r--r-- root root 1098 ./usr/share/mime/application/x-ipynb+json.xml
+-rw-r--r-- root root 2355 ./usr/share/mime/application/x-iso9660-appimage.xml
+-rw-r--r-- root root 3393 ./usr/share/mime/application/x-it87.xml
+-rw-r--r-- root root 2779 ./usr/share/mime/application/x-iwork-keynote-sffkey.xml
+-rw-r--r-- root root 2956 ./usr/share/mime/application/x-java-archive.xml
+-rw-r--r-- root root 3006 ./usr/share/mime/application/x-java-jce-keystore.xml
+-rw-r--r-- root root 2826 ./usr/share/mime/application/x-java-jnlp-file.xml
+-rw-r--r-- root root 2810 ./usr/share/mime/application/x-java-keystore.xml
+-rw-r--r-- root root 3097 ./usr/share/mime/application/x-java-pack200.xml
+-rw-r--r-- root root 2902 ./usr/share/mime/application/x-java.xml
+-rw-r--r-- root root 3090 ./usr/share/mime/application/x-jbuilder-project.xml
+-rw-r--r-- root root 3023 ./usr/share/mime/application/x-karbon.xml
+-rw-r--r-- root root 2961 ./usr/share/mime/application/x-kchart.xml
+-rw-r--r-- root root 985 ./usr/share/mime/application/x-kexi-connectiondata.xml
+-rw-r--r-- root root 963 ./usr/share/mime/application/x-kexiproject-shortcut.xml
+-rw-r--r-- root root 1139 ./usr/share/mime/application/x-kexiproject-sqlite2.xml
+-rw-r--r-- root root 1235 ./usr/share/mime/application/x-kexiproject-sqlite3.xml
+-rw-r--r-- root root 3059 ./usr/share/mime/application/x-kformula.xml
+-rw-r--r-- root root 3235 ./usr/share/mime/application/x-killustrator.xml
+-rw-r--r-- root root 3186 ./usr/share/mime/application/x-kivio.xml
+-rw-r--r-- root root 2970 ./usr/share/mime/application/x-kontour.xml
+-rw-r--r-- root root 3112 ./usr/share/mime/application/x-kpovmodeler.xml
+-rw-r--r-- root root 3446 ./usr/share/mime/application/x-kpresenter.xml
+-rw-r--r-- root root 2978 ./usr/share/mime/application/x-krita.xml
+-rw-r--r-- root root 3981 ./usr/share/mime/application/x-kspread-crypt.xml
+-rw-r--r-- root root 3288 ./usr/share/mime/application/x-kspread.xml
+-rw-r--r-- root root 3087 ./usr/share/mime/application/x-ksysv-package.xml
+-rw-r--r-- root root 2981 ./usr/share/mime/application/x-kugar.xml
+-rw-r--r-- root root 3680 ./usr/share/mime/application/x-kword-crypt.xml
+-rw-r--r-- root root 3054 ./usr/share/mime/application/x-kword.xml
+-rw-r--r-- root root 2937 ./usr/share/mime/application/x-lha.xml
+-rw-r--r-- root root 2788 ./usr/share/mime/application/x-lhz.xml
+-rw-r--r-- root root 3529 ./usr/share/mime/application/xliff+xml.xml
+-rw-r--r-- root root 3509 ./usr/share/mime/application/x-lrzip-compressed-tar.xml
+-rw-r--r-- root root 2586 ./usr/share/mime/application/x-lrzip.xml
+-rw-r--r-- root root 2932 ./usr/share/mime/application/x-lyx.xml
+-rw-r--r-- root root 2407 ./usr/share/mime/application/x-lz4-compressed-tar.xml
+-rw-r--r-- root root 2047 ./usr/share/mime/application/x-lz4.xml
+-rw-r--r-- root root 2439 ./usr/share/mime/application/x-lzip-compressed-tar.xml
+-rw-r--r-- root root 2538 ./usr/share/mime/application/x-lzip.xml
+-rw-r--r-- root root 3787 ./usr/share/mime/application/x-lzma-compressed-tar.xml
+-rw-r--r-- root root 2879 ./usr/share/mime/application/x-lzma.xml
+-rw-r--r-- root root 2858 ./usr/share/mime/application/x-lzop.xml
+-rw-r--r-- root root 2450 ./usr/share/mime/application/x-lzpdf.xml
+-rw-r--r-- root root 2573 ./usr/share/mime/application/x-m4.xml
+-rw-r--r-- root root 3552 ./usr/share/mime/application/x-macbinary.xml
+-rw-r--r-- root root 3595 ./usr/share/mime/application/x-magicpoint.xml
+-rw-r--r-- root root 3076 ./usr/share/mime/application/x-markaby.xml
+-rw-r--r-- root root 2865 ./usr/share/mime/application/x-matroska.xml
+-rw-r--r-- root root 3816 ./usr/share/mime/application/x-mif.xml
+-rw-r--r-- root root 2522 ./usr/share/mime/application/x-mimearchive.xml
+-rw-r--r-- root root 2842 ./usr/share/mime/application/xml-dtd.xml
+-rw-r--r-- root root 3524 ./usr/share/mime/application/xml-external-parsed-entity.xml
+-rw-r--r-- root root 3038 ./usr/share/mime/application/xml.xml
+-rw-r--r-- root root 2798 ./usr/share/mime/application/x-mobipocket-ebook.xml
+-rw-r--r-- root root 3272 ./usr/share/mime/application/x-mozilla-bookmarks.xml
+-rw-r--r-- root root 3670 ./usr/share/mime/application/x-ms-dos-executable.xml
+-rw-r--r-- root root 3395 ./usr/share/mime/application/x-msi.xml
+-rw-r--r-- root root 1046 ./usr/share/mime/application/x-ms-wim.xml
+-rw-r--r-- root root 3069 ./usr/share/mime/application/x-mswinurl.xml
+-rw-r--r-- root root 2816 ./usr/share/mime/application/x-mswrite.xml
+-rw-r--r-- root root 2631 ./usr/share/mime/application/x-msx-rom.xml
+-rw-r--r-- root root 2950 ./usr/share/mime/application/x-n64-rom.xml
+-rw-r--r-- root root 3171 ./usr/share/mime/application/x-nautilus-link.xml
+-rw-r--r-- root root 3348 ./usr/share/mime/application/x-navi-animation.xml
+-rw-r--r-- root root 1852 ./usr/share/mime/application/x-neo-geo-pocket-color-rom.xml
+-rw-r--r-- root root 1874 ./usr/share/mime/application/x-neo-geo-pocket-rom.xml
+-rw-r--r-- root root 2681 ./usr/share/mime/application/x-nes-rom.xml
+-rw-r--r-- root root 3540 ./usr/share/mime/application/x-netcdf.xml
+-rw-r--r-- root root 3587 ./usr/share/mime/application/x-netshow-channel.xml
+-rw-r--r-- root root 2904 ./usr/share/mime/application/x-nintendo-ds-rom.xml
+-rw-r--r-- root root 2651 ./usr/share/mime/application/x-nzb.xml
+-rw-r--r-- root root 2816 ./usr/share/mime/application/x-object.xml
+-rw-r--r-- root root 3410 ./usr/share/mime/application/x-oleo.xml
+-rw-r--r-- root root 3999 ./usr/share/mime/application/x-ole-storage.xml
+-rw-r--r-- root root 1221 ./usr/share/mime/application/x-pagemaker.xml
+-rw-r--r-- root root 2785 ./usr/share/mime/application/x-pak.xml
+-rw-r--r-- root root 3058 ./usr/share/mime/application/x-par2.xml
+-rw-r--r-- root root 2817 ./usr/share/mime/application/x-partial-download.xml
+-rw-r--r-- root root 2149 ./usr/share/mime/application/x-pc-engine-rom.xml
+-rw-r--r-- root root 3072 ./usr/share/mime/application/x-pef-executable.xml
+-rw-r--r-- root root 3209 ./usr/share/mime/application/x-perl.xml
+-rw-r--r-- root root 3050 ./usr/share/mime/application/x-php.xml
+-rw-r--r-- root root 3264 ./usr/share/mime/application/x-pkcs7-certificates.xml
+-rw-r--r-- root root 3383 ./usr/share/mime/application/x-planperfect.xml
+-rw-r--r-- root root 2969 ./usr/share/mime/application/x-pocket-word.xml
+-rw-r--r-- root root 3489 ./usr/share/mime/application/x-profile.xml
+-rw-r--r-- root root 3521 ./usr/share/mime/application/x-pw.xml
+-rw-r--r-- root root 3180 ./usr/share/mime/application/x-python-bytecode.xml
+-rw-r--r-- root root 407 ./usr/share/mime/application/x-qemu-disk.xml
+-rw-r--r-- root root 2164 ./usr/share/mime/application/x-qpress.xml
+-rw-r--r-- root root 2458 ./usr/share/mime/application/x-qtiplot.xml
+-rw-r--r-- root root 3546 ./usr/share/mime/application/x-quattropro.xml
+-rw-r--r-- root root 1258 ./usr/share/mime/application/x-quicktime-media-link.xml
+-rw-r--r-- root root 3189 ./usr/share/mime/application/x-qw.xml
+-rw-r--r-- root root 2444 ./usr/share/mime/application/x-raw-disk-image.xml
+-rw-r--r-- root root 3223 ./usr/share/mime/application/x-raw-disk-image-xz-compressed.xml
+-rw-r--r-- root root 1828 ./usr/share/mime/application/x-raw-floppy-disk-image.xml
+-rw-r--r-- root root 2067 ./usr/share/mime/application/x-riff.xml
+-rw-r--r-- root root 2780 ./usr/share/mime/application/x-rpm.xml
+-rw-r--r-- root root 2941 ./usr/share/mime/application/x-ruby.xml
+-rw-r--r-- root root 3058 ./usr/share/mime/application/x-sami.xml
+-rw-r--r-- root root 2519 ./usr/share/mime/application/x-saturn-rom.xml
+-rw-r--r-- root root 3354 ./usr/share/mime/application/x-sc.xml
+-rw-r--r-- root root 2140 ./usr/share/mime/application/x-sega-cd-rom.xml
+-rw-r--r-- root root 1752 ./usr/share/mime/application/x-sega-pico-rom.xml
+-rw-r--r-- root root 1656 ./usr/share/mime/application/x-sg1000-rom.xml
+-rw-r--r-- root root 3576 ./usr/share/mime/application/x-shared-library-la.xml
+-rw-r--r-- root root 3341 ./usr/share/mime/application/x-sharedlib.xml
+-rw-r--r-- root root 3018 ./usr/share/mime/application/x-shar.xml
+-rw-r--r-- root root 3191 ./usr/share/mime/application/x-shellscript.xml
+-rw-r--r-- root root 2898 ./usr/share/mime/application/x-shorten.xml
+-rw-r--r-- root root 3125 ./usr/share/mime/application/x-siag.xml
+-rw-r--r-- root root 3067 ./usr/share/mime/application/x-slp.xml
+-rw-r--r-- root root 3271 ./usr/share/mime/application/xslt+xml.xml
+-rw-r--r-- root root 2868 ./usr/share/mime/application/x-smaf.xml
+-rw-r--r-- root root 1828 ./usr/share/mime/application/x-sms-rom.xml
+-rw-r--r-- root root 2563 ./usr/share/mime/application/x-source-rpm.xml
+-rw-r--r-- root root 3445 ./usr/share/mime/application/xspf+xml.xml
+-rw-r--r-- root root 1201 ./usr/share/mime/application/x-spss-por.xml
+-rw-r--r-- root root 1181 ./usr/share/mime/application/x-spss-sav.xml
+-rw-r--r-- root root 3154 ./usr/share/mime/application/x-sqlite2.xml
+-rw-r--r-- root root 3027 ./usr/share/mime/application/x-stuffit.xml
+-rw-r--r-- root root 3069 ./usr/share/mime/application/x-subrip.xml
+-rw-r--r-- root root 3146 ./usr/share/mime/application/x-sv4cpio.xml
+-rw-r--r-- root root 3637 ./usr/share/mime/application/x-sv4crc.xml
+-rw-r--r-- root root 2862 ./usr/share/mime/application/x-t602.xml
+-rw-r--r-- root root 2908 ./usr/share/mime/application/x-tar.xml
+-rw-r--r-- root root 3451 ./usr/share/mime/application/x-tarz.xml
+-rw-r--r-- root root 3391 ./usr/share/mime/application/x-tex-gf.xml
+-rw-r--r-- root root 3527 ./usr/share/mime/application/x-tex-pk.xml
+-rw-r--r-- root root 2916 ./usr/share/mime/application/x-tgif.xml
+-rw-r--r-- root root 2604 ./usr/share/mime/application/x-theme.xml
+-rw-r--r-- root root 2013 ./usr/share/mime/application/x-thomson-cartridge-memo7.xml
+-rw-r--r-- root root 1776 ./usr/share/mime/application/x-thomson-cassette.xml
+-rw-r--r-- root root 2342 ./usr/share/mime/application/x-thomson-sap-image.xml
+-rw-r--r-- root root 3216 ./usr/share/mime/application/x-toutdoux.xml
+-rw-r--r-- root root 3148 ./usr/share/mime/application/x-trash.xml
+-rw-r--r-- root root 3887 ./usr/share/mime/application/x-troff-man-compressed.xml
+-rw-r--r-- root root 2521 ./usr/share/mime/application/x-troff-man.xml
+-rw-r--r-- root root 3731 ./usr/share/mime/application/x-tzo.xml
+-rw-r--r-- root root 3110 ./usr/share/mime/application/x-ufraw.xml
+-rw-r--r-- root root 2836 ./usr/share/mime/application/x-ustar.xml
+-rw-r--r-- root root 1666 ./usr/share/mime/application/x-virtual-boy-rom.xml
+-rw-r--r-- root root 3242 ./usr/share/mime/application/x-wais-source.xml
+-rw-r--r-- root root 2456 ./usr/share/mime/application/x-wii-rom.xml
+-rw-r--r-- root root 1998 ./usr/share/mime/application/x-wii-wad.xml
+-rw-r--r-- root root 3595 ./usr/share/mime/application/x-windows-themepack.xml
+-rw-r--r-- root root 1989 ./usr/share/mime/application/x-wonderswan-color-rom.xml
+-rw-r--r-- root root 1825 ./usr/share/mime/application/x-wonderswan-rom.xml
+-rw-r--r-- root root 3782 ./usr/share/mime/application/x-wpg.xml
+-rw-r--r-- root root 2498 ./usr/share/mime/application/x-wwf.xml
+-rw-r--r-- root root 4757 ./usr/share/mime/application/x-x509-ca-cert.xml
+-rw-r--r-- root root 1890 ./usr/share/mime/application/x-xar.xml
+-rw-r--r-- root root 3167 ./usr/share/mime/application/x-xbel.xml
+-rw-r--r-- root root 3294 ./usr/share/mime/application/x-xpinstall.xml
+-rw-r--r-- root root 3373 ./usr/share/mime/application/x-xz-compressed-tar.xml
+-rw-r--r-- root root 3269 ./usr/share/mime/application/x-xzpdf.xml
+-rw-r--r-- root root 2449 ./usr/share/mime/application/x-xz.xml
+-rw-r--r-- root root 2822 ./usr/share/mime/application/x-yaml.xml
+-rw-r--r-- root root 2936 ./usr/share/mime/application/x-zerosize.xml
+-rw-r--r-- root root 2912 ./usr/share/mime/application/x-zip-compressed-fb2.xml
+-rw-r--r-- root root 2818 ./usr/share/mime/application/x-zoo.xml
+-rw-r--r-- root root 1995 ./usr/share/mime/application/x-zstd-compressed-tar.xml
+-rw-r--r-- root root 2901 ./usr/share/mime/application/zip.xml
+-rw-r--r-- root root 2084 ./usr/share/mime/application/zlib.xml
+-rw-r--r-- root root 1464 ./usr/share/mime/application/zstd.xml
+drwxr-xr-x root root 4096 ./usr/share/mime/audio
+-rw-r--r-- root root 2202 ./usr/share/mime/audio/aac.xml
+-rw-r--r-- root root 3368 ./usr/share/mime/audio/ac3.xml
+-rw-r--r-- root root 2944 ./usr/share/mime/audio/amr-wb.xml
+-rw-r--r-- root root 2771 ./usr/share/mime/audio/amr.xml
+-rw-r--r-- root root 1023 ./usr/share/mime/audio/annodex.xml
+-rw-r--r-- root root 3151 ./usr/share/mime/audio/basic.xml
+-rw-r--r-- root root 2798 ./usr/share/mime/audio/flac.xml
+-rw-r--r-- root root 2876 ./usr/share/mime/audio/midi.xml
+-rw-r--r-- root root 2623 ./usr/share/mime/audio/mp2.xml
+-rw-r--r-- root root 2884 ./usr/share/mime/audio/mp4.xml
+-rw-r--r-- root root 2936 ./usr/share/mime/audio/mpeg.xml
+-rw-r--r-- root root 1008 ./usr/share/mime/audio/ogg.xml
+-rw-r--r-- root root 3220 ./usr/share/mime/audio/prs.sid.xml
+-rw-r--r-- root root 1610 ./usr/share/mime/audio/usac.xml
+-rw-r--r-- root root 2180 ./usr/share/mime/audio/vnd.dts.hd.xml
+-rw-r--r-- root root 2055 ./usr/share/mime/audio/vnd.dts.xml
+-rw-r--r-- root root 3202 ./usr/share/mime/audio/vnd.rn-realaudio.xml
+-rw-r--r-- root root 2422 ./usr/share/mime/audio/webm.xml
+-rw-r--r-- root root 2713 ./usr/share/mime/audio/x-adpcm.xml
+-rw-r--r-- root root 3066 ./usr/share/mime/audio/x-aifc.xml
+-rw-r--r-- root root 3573 ./usr/share/mime/audio/x-aiff.xml
+-rw-r--r-- root root 2766 ./usr/share/mime/audio/x-amzxml.xml
+-rw-r--r-- root root 2758 ./usr/share/mime/audio/x-ape.xml
+-rw-r--r-- root root 2958 ./usr/share/mime/audio/x-flac+ogg.xml
+-rw-r--r-- root root 2864 ./usr/share/mime/audio/x-gsm.xml
+-rw-r--r-- root root 1076 ./usr/share/mime/audio/x-iriver-pla.xml
+-rw-r--r-- root root 3344 ./usr/share/mime/audio/x-it.xml
+-rw-r--r-- root root 3184 ./usr/share/mime/audio/x-m4b.xml
+-rw-r--r-- root root 1002 ./usr/share/mime/audio/x-m4r.xml
+-rw-r--r-- root root 2979 ./usr/share/mime/audio/x-matroska.xml
+-rw-r--r-- root root 3017 ./usr/share/mime/audio/x-minipsf.xml
+-rw-r--r-- root root 3256 ./usr/share/mime/audio/x-mo3.xml
+-rw-r--r-- root root 3640 ./usr/share/mime/audio/x-mod.xml
+-rw-r--r-- root root 3601 ./usr/share/mime/audio/x-mpegurl.xml
+-rw-r--r-- root root 3833 ./usr/share/mime/audio/x-ms-asx.xml
+-rw-r--r-- root root 3148 ./usr/share/mime/audio/x-ms-wma.xml
+-rw-r--r-- root root 2864 ./usr/share/mime/audio/x-musepack.xml
+-rw-r--r-- root root 2000 ./usr/share/mime/audio/x-opus+ogg.xml
+-rw-r--r-- root root 1778 ./usr/share/mime/audio/x-pn-audibleaudio.xml
+-rw-r--r-- root root 3385 ./usr/share/mime/audio/x-psflib.xml
+-rw-r--r-- root root 2682 ./usr/share/mime/audio/x-psf.xml
+-rw-r--r-- root root 2764 ./usr/share/mime/audio/x-riff.xml
+-rw-r--r-- root root 3393 ./usr/share/mime/audio/x-s3m.xml
+-rw-r--r-- root root 3693 ./usr/share/mime/audio/x-scpls.xml
+-rw-r--r-- root root 2976 ./usr/share/mime/audio/x-speex+ogg.xml
+-rw-r--r-- root root 2656 ./usr/share/mime/audio/x-speex.xml
+-rw-r--r-- root root 3290 ./usr/share/mime/audio/x-stm.xml
+-rw-r--r-- root root 2930 ./usr/share/mime/audio/x-tta.xml
+-rw-r--r-- root root 2737 ./usr/share/mime/audio/x-voc.xml
+-rw-r--r-- root root 3311 ./usr/share/mime/audio/x-vorbis+ogg.xml
+-rw-r--r-- root root 3641 ./usr/share/mime/audio/x-wavpack-correction.xml
+-rw-r--r-- root root 2833 ./usr/share/mime/audio/x-wavpack.xml
+-rw-r--r-- root root 2795 ./usr/share/mime/audio/x-wav.xml
+-rw-r--r-- root root 3518 ./usr/share/mime/audio/x-xi.xml
+-rw-r--r-- root root 2751 ./usr/share/mime/audio/x-xmf.xml
+-rw-r--r-- root root 3360 ./usr/share/mime/audio/x-xm.xml
+drwxr-xr-x root root 4096 ./usr/share/mime/font
+-rw-r--r-- root root 1752 ./usr/share/mime/font/collection.xml
+-rw-r--r-- root root 3213 ./usr/share/mime/font/otf.xml
+-rw-r--r-- root root 3063 ./usr/share/mime/font/ttf.xml
+-rw-r--r-- root root 1753 ./usr/share/mime/font/woff2.xml
+-rw-r--r-- root root 2331 ./usr/share/mime/font/woff.xml
+-rw-r--r-- root root 17449 ./usr/share/mime/generic-icons
+-rw-r--r-- root root 29350 ./usr/share/mime/globs
+-rw-r--r-- root root 32606 ./usr/share/mime/globs2
+-rw-r--r-- root root 0 ./usr/share/mime/icons
+drwxr-xr-x root root 4096 ./usr/share/mime/image
+-rw-r--r-- root root 3325 ./usr/share/mime/image/bmp.xml
+-rw-r--r-- root root 928 ./usr/share/mime/image/cgm.xml
+-rw-r--r-- root root 2788 ./usr/share/mime/image/dpx.xml
+-rw-r--r-- root root 2896 ./usr/share/mime/image/emf.xml
+-rw-r--r-- root root 1017 ./usr/share/mime/image/fax-g3.xml
+-rw-r--r-- root root 3011 ./usr/share/mime/image/fits.xml
+-rw-r--r-- root root 2851 ./usr/share/mime/image/gif.xml
+-rw-r--r-- root root 1713 ./usr/share/mime/image/heif.xml
+-rw-r--r-- root root 2775 ./usr/share/mime/image/ief.xml
+-rw-r--r-- root root 1995 ./usr/share/mime/image/jp2.xml
+-rw-r--r-- root root 2914 ./usr/share/mime/image/jpeg.xml
+-rw-r--r-- root root 1890 ./usr/share/mime/image/jpm.xml
+-rw-r--r-- root root 1891 ./usr/share/mime/image/jpx.xml
+-rw-r--r-- root root 2043 ./usr/share/mime/image/ktx.xml
+-rw-r--r-- root root 1030 ./usr/share/mime/image/openraster.xml
+-rw-r--r-- root root 2775 ./usr/share/mime/image/png.xml
+-rw-r--r-- root root 1057 ./usr/share/mime/image/rle.xml
+-rw-r--r-- root root 3368 ./usr/share/mime/image/svg+xml-compressed.xml
+-rw-r--r-- root root 2782 ./usr/share/mime/image/svg+xml.xml
+-rw-r--r-- root root 2852 ./usr/share/mime/image/tiff.xml
+-rw-r--r-- root root 3033 ./usr/share/mime/image/vnd.adobe.photoshop.xml
+-rw-r--r-- root root 2120 ./usr/share/mime/image/vnd.djvu+multipage.xml
+-rw-r--r-- root root 2911 ./usr/share/mime/image/vnd.djvu.xml
+-rw-r--r-- root root 3101 ./usr/share/mime/image/vnd.dwg.xml
+-rw-r--r-- root root 3301 ./usr/share/mime/image/vnd.dxf.xml
+-rw-r--r-- root root 2244 ./usr/share/mime/image/vnd.microsoft.icon.xml
+-rw-r--r-- root root 933 ./usr/share/mime/image/vnd.ms-modi.xml
+-rw-r--r-- root root 2993 ./usr/share/mime/image/vnd.rn-realpix.xml
+-rw-r--r-- root root 2775 ./usr/share/mime/image/vnd.wap.wbmp.xml
+-rw-r--r-- root root 2764 ./usr/share/mime/image/vnd.zbrush.pcx.xml
+-rw-r--r-- root root 1985 ./usr/share/mime/image/webp.xml
+-rw-r--r-- root root 2901 ./usr/share/mime/image/wmf.xml
+-rw-r--r-- root root 3236 ./usr/share/mime/image/x-3ds.xml
+-rw-r--r-- root root 3249 ./usr/share/mime/image/x-adobe-dng.xml
+-rw-r--r-- root root 3454 ./usr/share/mime/image/x-applix-graphics.xml
+-rw-r--r-- root root 3863 ./usr/share/mime/image/x-bzeps.xml
+-rw-r--r-- root root 3517 ./usr/share/mime/image/x-canon-cr2.xml
+-rw-r--r-- root root 3480 ./usr/share/mime/image/x-canon-crw.xml
+-rw-r--r-- root root 3346 ./usr/share/mime/image/x-cmu-raster.xml
+-rw-r--r-- root root 3323 ./usr/share/mime/image/x-compressed-xcf.xml
+-rw-r--r-- root root 3230 ./usr/share/mime/image/x-dcraw.xml
+-rw-r--r-- root root 3119 ./usr/share/mime/image/x-dds.xml
+-rw-r--r-- root root 2780 ./usr/share/mime/image/x-dib.xml
+-rw-r--r-- root root 2906 ./usr/share/mime/image/x-eps.xml
+-rw-r--r-- root root 2720 ./usr/share/mime/image/x-exr.xml
+-rw-r--r-- root root 2767 ./usr/share/mime/image/x-fpx.xml
+-rw-r--r-- root root 3445 ./usr/share/mime/image/x-fuji-raf.xml
+-rw-r--r-- root root 1569 ./usr/share/mime/image/x-gimp-gbr.xml
+-rw-r--r-- root root 1672 ./usr/share/mime/image/x-gimp-gih.xml
+-rw-r--r-- root root 1564 ./usr/share/mime/image/x-gimp-pat.xml
+-rw-r--r-- root root 3863 ./usr/share/mime/image/x-gzeps.xml
+-rw-r--r-- root root 2927 ./usr/share/mime/image/x-icns.xml
+-rw-r--r-- root root 3043 ./usr/share/mime/image/x-ilbm.xml
+-rw-r--r-- root root 2863 ./usr/share/mime/image/x-jng.xml
+-rw-r--r-- root root 1821 ./usr/share/mime/image/x-jp2-codestream.xml
+-rw-r--r-- root root 3442 ./usr/share/mime/image/x-kodak-dcr.xml
+-rw-r--r-- root root 3428 ./usr/share/mime/image/x-kodak-k25.xml
+-rw-r--r-- root root 3444 ./usr/share/mime/image/x-kodak-kdc.xml
+-rw-r--r-- root root 3140 ./usr/share/mime/image/x-lwo.xml
+-rw-r--r-- root root 3058 ./usr/share/mime/image/x-lws.xml
+-rw-r--r-- root root 3324 ./usr/share/mime/image/x-macpaint.xml
+-rw-r--r-- root root 3495 ./usr/share/mime/image/x-minolta-mrw.xml
+-rw-r--r-- root root 2793 ./usr/share/mime/image/x-msod.xml
+-rw-r--r-- root root 2665 ./usr/share/mime/image/x-niff.xml
+-rw-r--r-- root root 3442 ./usr/share/mime/image/x-nikon-nef.xml
+-rw-r--r-- root root 3607 ./usr/share/mime/image/x-olympus-orf.xml
+-rw-r--r-- root root 3360 ./usr/share/mime/image/x-panasonic-rw2.xml
+-rw-r--r-- root root 3358 ./usr/share/mime/image/x-panasonic-rw.xml
+-rw-r--r-- root root 3499 ./usr/share/mime/image/x-pentax-pef.xml
+-rw-r--r-- root root 2793 ./usr/share/mime/image/x-photo-cd.xml
+-rw-r--r-- root root 3911 ./usr/share/mime/image/x-pict.xml
+-rw-r--r-- root root 2789 ./usr/share/mime/image/x-portable-anymap.xml
+-rw-r--r-- root root 2904 ./usr/share/mime/image/x-portable-bitmap.xml
+-rw-r--r-- root root 2830 ./usr/share/mime/image/x-portable-graymap.xml
+-rw-r--r-- root root 2828 ./usr/share/mime/image/x-portable-pixmap.xml
+-rw-r--r-- root root 2989 ./usr/share/mime/image/x-quicktime.xml
+-rw-r--r-- root root 2784 ./usr/share/mime/image/x-rgb.xml
+-rw-r--r-- root root 2640 ./usr/share/mime/image/x-sgi.xml
+-rw-r--r-- root root 3400 ./usr/share/mime/image/x-sigma-x3f.xml
+-rw-r--r-- root root 2956 ./usr/share/mime/image/x-skencil.xml
+-rw-r--r-- root root 3388 ./usr/share/mime/image/x-sony-arw.xml
+-rw-r--r-- root root 3388 ./usr/share/mime/image/x-sony-sr2.xml
+-rw-r--r-- root root 3387 ./usr/share/mime/image/x-sony-srf.xml
+-rw-r--r-- root root 3040 ./usr/share/mime/image/x-sun-raster.xml
+-rw-r--r-- root root 2867 ./usr/share/mime/image/x-tga.xml
+-rw-r--r-- root root 2644 ./usr/share/mime/image/x-tiff-multipage.xml
+-rw-r--r-- root root 2941 ./usr/share/mime/image/x-win-bitmap.xml
+-rw-r--r-- root root 2721 ./usr/share/mime/image/x-xbitmap.xml
+-rw-r--r-- root root 2832 ./usr/share/mime/image/x-xcf.xml
+-rw-r--r-- root root 2592 ./usr/share/mime/image/x-xcursor.xml
+-rw-r--r-- root root 2753 ./usr/share/mime/image/x-xfig.xml
+-rw-r--r-- root root 2798 ./usr/share/mime/image/x-xpixmap.xml
+-rw-r--r-- root root 3109 ./usr/share/mime/image/x-xwindowdump.xml
+drwxr-xr-x root root 4096 ./usr/share/mime/inode
+-rw-r--r-- root root 3006 ./usr/share/mime/inode/blockdevice.xml
+-rw-r--r-- root root 3145 ./usr/share/mime/inode/chardevice.xml
+-rw-r--r-- root root 2543 ./usr/share/mime/inode/directory.xml
+-rw-r--r-- root root 2413 ./usr/share/mime/inode/fifo.xml
+-rw-r--r-- root root 3021 ./usr/share/mime/inode/mount-point.xml
+-rw-r--r-- root root 2469 ./usr/share/mime/inode/socket.xml
+-rw-r--r-- root root 3295 ./usr/share/mime/inode/symlink.xml
+-rw-r--r-- root root 27700 ./usr/share/mime/magic
+drwxr-xr-x root root 4096 ./usr/share/mime/message
+-rw-r--r-- root root 3735 ./usr/share/mime/message/delivery-status.xml
+-rw-r--r-- root root 3771 ./usr/share/mime/message/disposition-notification.xml
+-rw-r--r-- root root 3777 ./usr/share/mime/message/external-body.xml
+-rw-r--r-- root root 3617 ./usr/share/mime/message/news.xml
+-rw-r--r-- root root 3728 ./usr/share/mime/message/partial.xml
+-rw-r--r-- root root 3183 ./usr/share/mime/message/rfc822.xml
+-rw-r--r-- root root 3427 ./usr/share/mime/message/x-gnu-rmail.xml
+-rw-r--r-- root root 136104 ./usr/share/mime/mime.cache
+drwxr-xr-x root root 4096 ./usr/share/mime/model
+-rw-r--r-- root root 2003 ./usr/share/mime/model/iges.xml
+-rw-r--r-- root root 1695 ./usr/share/mime/model/stl.xml
+-rw-r--r-- root root 3189 ./usr/share/mime/model/vrml.xml
+drwxr-xr-x root root 4096 ./usr/share/mime/multipart
+-rw-r--r-- root root 3761 ./usr/share/mime/multipart/alternative.xml
+-rw-r--r-- root root 4361 ./usr/share/mime/multipart/appledouble.xml
+-rw-r--r-- root root 3157 ./usr/share/mime/multipart/digest.xml
+-rw-r--r-- root root 3267 ./usr/share/mime/multipart/encrypted.xml
+-rw-r--r-- root root 3191 ./usr/share/mime/multipart/mixed.xml
+-rw-r--r-- root root 3209 ./usr/share/mime/multipart/related.xml
+-rw-r--r-- root root 3556 ./usr/share/mime/multipart/report.xml
+-rw-r--r-- root root 3203 ./usr/share/mime/multipart/signed.xml
+-rw-r--r-- root root 3867 ./usr/share/mime/multipart/x-mixed-replace.xml
+-rw-r--r-- root root 16073 ./usr/share/mime/subclasses
+drwxr-xr-x root root 4096 ./usr/share/mime/text
+-rw-r--r-- root root 1172 ./usr/share/mime/text/cache-manifest.xml
+-rw-r--r-- root root 3178 ./usr/share/mime/text/calendar.xml
+-rw-r--r-- root root 3113 ./usr/share/mime/text/css.xml
+-rw-r--r-- root root 2266 ./usr/share/mime/text/csv-schema.xml
+-rw-r--r-- root root 3027 ./usr/share/mime/text/csv.xml
+-rw-r--r-- root root 3801 ./usr/share/mime/text/enriched.xml
+-rw-r--r-- root root 3017 ./usr/share/mime/text/htmlh.xml
+-rw-r--r-- root root 2991 ./usr/share/mime/text/html.xml
+-rw-r--r-- root root 2600 ./usr/share/mime/text/markdown.xml
+-rw-r--r-- root root 3420 ./usr/share/mime/text/plain.xml
+-rw-r--r-- root root 3291 ./usr/share/mime/text/rfc822-headers.xml
+-rw-r--r-- root root 3602 ./usr/share/mime/text/richtext.xml
+-rw-r--r-- root root 2164 ./usr/share/mime/text/rust.xml
+-rw-r--r-- root root 3073 ./usr/share/mime/text/sgml.xml
+-rw-r--r-- root root 3961 ./usr/share/mime/text/spreadsheet.xml
+-rw-r--r-- root root 2849 ./usr/share/mime/text/tab-separated-values.xml
+-rw-r--r-- root root 3191 ./usr/share/mime/text/troff.xml
+-rw-r--r-- root root 2106 ./usr/share/mime/text/turtle.xml
+-rw-r--r-- root root 3618 ./usr/share/mime/text/vcard.xml
+-rw-r--r-- root root 2914 ./usr/share/mime/text/vnd.graphviz.xml
+-rw-r--r-- root root 3253 ./usr/share/mime/text/vnd.qt.linguist.xml
+-rw-r--r-- root root 3050 ./usr/share/mime/text/vnd.rn-realtext.xml
+-rw-r--r-- root root 1636 ./usr/share/mime/text/vnd.senx.warpscript.xml
+-rw-r--r-- root root 2876 ./usr/share/mime/text/vnd.sun.j2me.app-descriptor.xml
+-rw-r--r-- root root 3020 ./usr/share/mime/text/vnd.wap.wmlscript.xml
+-rw-r--r-- root root 3039 ./usr/share/mime/text/vnd.wap.wml.xml
+-rw-r--r-- root root 2632 ./usr/share/mime/text/vtt.xml
+-rw-r--r-- root root 3143 ./usr/share/mime/text/x-adasrc.xml
+-rw-r--r-- root root 2961 ./usr/share/mime/text/x-authors.xml
+-rw-r--r-- root root 3040 ./usr/share/mime/text/x-bibtex.xml
+-rw-r--r-- root root 3310 ./usr/share/mime/text/x-changelog.xml
+-rw-r--r-- root root 3007 ./usr/share/mime/text/x-c++hdr.xml
+-rw-r--r-- root root 2803 ./usr/share/mime/text/x-chdr.xml
+-rw-r--r-- root root 3188 ./usr/share/mime/text/x-cmake.xml
+-rw-r--r-- root root 1168 ./usr/share/mime/text/x-cobol.xml
+-rw-r--r-- root root 3113 ./usr/share/mime/text/x-copying.xml
+-rw-r--r-- root root 3127 ./usr/share/mime/text/x-credits.xml
+-rw-r--r-- root root 3074 ./usr/share/mime/text/x-csharp.xml
+-rw-r--r-- root root 3250 ./usr/share/mime/text/x-c++src.xml
+-rw-r--r-- root root 3064 ./usr/share/mime/text/x-csrc.xml
+-rw-r--r-- root root 1989 ./usr/share/mime/text/x-dbus-service.xml
+-rw-r--r-- root root 3032 ./usr/share/mime/text/x-dcl.xml
+-rw-r--r-- root root 3236 ./usr/share/mime/text/x-dsl.xml
+-rw-r--r-- root root 2994 ./usr/share/mime/text/x-dsrc.xml
+-rw-r--r-- root root 3254 ./usr/share/mime/text/x-eiffel.xml
+-rw-r--r-- root root 3617 ./usr/share/mime/text/x-emacs-lisp.xml
+-rw-r--r-- root root 3221 ./usr/share/mime/text/x-erlang.xml
+-rw-r--r-- root root 3527 ./usr/share/mime/text/x-fortran.xml
+-rw-r--r-- root root 1710 ./usr/share/mime/text/x.gcode.xml
+-rw-r--r-- root root 2317 ./usr/share/mime/text/x-genie.xml
+-rw-r--r-- root root 3320 ./usr/share/mime/text/x-gettext-translation-template.xml
+-rw-r--r-- root root 3221 ./usr/share/mime/text/x-gettext-translation.xml
+-rw-r--r-- root root 1013 ./usr/share/mime/text/x-gherkin.xml
+-rw-r--r-- root root 1138 ./usr/share/mime/text/x-google-video-pointer.xml
+-rw-r--r-- root root 2539 ./usr/share/mime/text/x-go.xml
+-rw-r--r-- root root 1644 ./usr/share/mime/text/x-gradle.xml
+-rw-r--r-- root root 1179 ./usr/share/mime/text/x-groovy.xml
+-rw-r--r-- root root 3360 ./usr/share/mime/text/x-haskell.xml
+-rw-r--r-- root root 3033 ./usr/share/mime/text/x-idl.xml
+-rw-r--r-- root root 3023 ./usr/share/mime/text/x-imelody.xml
+-rw-r--r-- root root 3418 ./usr/share/mime/text/x-install.xml
+-rw-r--r-- root root 3599 ./usr/share/mime/text/x-iptables.xml
+-rw-r--r-- root root 3086 ./usr/share/mime/text/x-java.xml
+-rw-r--r-- root root 3167 ./usr/share/mime/text/x-ldif.xml
+-rw-r--r-- root root 3110 ./usr/share/mime/text/x-lilypond.xml
+-rw-r--r-- root root 3063 ./usr/share/mime/text/x-literate-haskell.xml
+-rw-r--r-- root root 3190 ./usr/share/mime/text/x-log.xml
+-rw-r--r-- root root 2802 ./usr/share/mime/text/x-lua.xml
+-rw-r--r-- root root 1200 ./usr/share/mime/text/x-makefile.xml
+-rw-r--r-- root root 985 ./usr/share/mime/text/x-matlab.xml
+-rw-r--r-- root root 1881 ./usr/share/mime/text/x-maven+xml.xml
+-rw-r--r-- root root 3157 ./usr/share/mime/text/xmcd.xml
+-rw-r--r-- root root 2231 ./usr/share/mime/text/x-meson.xml
+-rw-r--r-- root root 3177 ./usr/share/mime/text/x-microdvd.xml
+-rw-r--r-- root root 2799 ./usr/share/mime/text/x-moc.xml
+-rw-r--r-- root root 2267 ./usr/share/mime/text/x-modelica.xml
+-rw-r--r-- root root 957 ./usr/share/mime/text/x-mof.xml
+-rw-r--r-- root root 3100 ./usr/share/mime/text/x-mpsub.xml
+-rw-r--r-- root root 3359 ./usr/share/mime/text/x-mrml.xml
+-rw-r--r-- root root 3496 ./usr/share/mime/text/x-ms-regedit.xml
+-rw-r--r-- root root 1114 ./usr/share/mime/text/x-mup.xml
+-rw-r--r-- root root 2801 ./usr/share/mime/text/x-nfo.xml
+-rw-r--r-- root root 3537 ./usr/share/mime/text/x-objcsrc.xml
+-rw-r--r-- root root 3076 ./usr/share/mime/text/x-ocaml.xml
+-rw-r--r-- root root 2703 ./usr/share/mime/text/x-ocl.xml
+-rw-r--r-- root root 2654 ./usr/share/mime/text/x-ooc.xml
+-rw-r--r-- root root 1909 ./usr/share/mime/text/x-opencl-src.xml
+-rw-r--r-- root root 3116 ./usr/share/mime/text/x-opml+xml.xml
+-rw-r--r-- root root 3227 ./usr/share/mime/text/x-pascal.xml
+-rw-r--r-- root root 3558 ./usr/share/mime/text/x-patch.xml
+-rw-r--r-- root root 1829 ./usr/share/mime/text/x-python3.xml
+-rw-r--r-- root root 3116 ./usr/share/mime/text/x-python.xml
+-rw-r--r-- root root 2865 ./usr/share/mime/text/x-qml.xml
+-rw-r--r-- root root 3185 ./usr/share/mime/text/x-readme.xml
+-rw-r--r-- root root 3144 ./usr/share/mime/text/x-reject.xml
+-rw-r--r-- root root 3198 ./usr/share/mime/text/x-rpm-spec.xml
+-rw-r--r-- root root 1880 ./usr/share/mime/text/x-rst.xml
+-rw-r--r-- root root 2443 ./usr/share/mime/text/x-sass.xml
+-rw-r--r-- root root 2616 ./usr/share/mime/text/x-scala.xml
+-rw-r--r-- root root 3324 ./usr/share/mime/text/x-scheme.xml
+-rw-r--r-- root root 2573 ./usr/share/mime/text/x-scons.xml
+-rw-r--r-- root root 1132 ./usr/share/mime/text/x-scss.xml
+-rw-r--r-- root root 3114 ./usr/share/mime/text/x-setext.xml
+-rw-r--r-- root root 2929 ./usr/share/mime/text/x-ssa.xml
+-rw-r--r-- root root 3142 ./usr/share/mime/text/x-subviewer.xml
+-rw-r--r-- root root 2665 ./usr/share/mime/text/x-svhdr.xml
+-rw-r--r-- root root 2853 ./usr/share/mime/text/x-svsrc.xml
+-rw-r--r-- root root 2364 ./usr/share/mime/text/x-systemd-unit.xml
+-rw-r--r-- root root 2818 ./usr/share/mime/text/x-tcl.xml
+-rw-r--r-- root root 3204 ./usr/share/mime/text/x-texinfo.xml
+-rw-r--r-- root root 3092 ./usr/share/mime/text/x-tex.xml
+-rw-r--r-- root root 3580 ./usr/share/mime/text/x-troff-me.xml
+-rw-r--r-- root root 3580 ./usr/share/mime/text/x-troff-mm.xml
+-rw-r--r-- root root 3580 ./usr/share/mime/text/x-troff-ms.xml
+-rw-r--r-- root root 1811 ./usr/share/mime/text/x-twig.xml
+-rw-r--r-- root root 3150 ./usr/share/mime/text/x-txt2tags.xml
+-rw-r--r-- root root 3074 ./usr/share/mime/text/x-uil.xml
+-rw-r--r-- root root 3061 ./usr/share/mime/text/x-uri.xml
+-rw-r--r-- root root 2586 ./usr/share/mime/text/x-uuencode.xml
+-rw-r--r-- root root 3062 ./usr/share/mime/text/x-vala.xml
+-rw-r--r-- root root 2676 ./usr/share/mime/text/x-verilog.xml
+-rw-r--r-- root root 2711 ./usr/share/mime/text/x-vhdl.xml
+-rw-r--r-- root root 2710 ./usr/share/mime/text/x-xmi.xml
+-rw-r--r-- root root 2956 ./usr/share/mime/text/x-xslfo.xml
+-rw-r--r-- root root 1140 ./usr/share/mime/treemagic
+-rw-r--r-- root root 17478 ./usr/share/mime/types
+-rw-r--r-- root root 5 ./usr/share/mime/version
+drwxr-xr-x root root 4096 ./usr/share/mime/video
+-rw-r--r-- root root 3285 ./usr/share/mime/video/3gpp2.xml
+-rw-r--r-- root root 3885 ./usr/share/mime/video/3gpp.xml
+-rw-r--r-- root root 1021 ./usr/share/mime/video/annodex.xml
+-rw-r--r-- root root 2734 ./usr/share/mime/video/dv.xml
+-rw-r--r-- root root 2779 ./usr/share/mime/video/isivideo.xml
+-rw-r--r-- root root 1888 ./usr/share/mime/video/mj2.xml
+-rw-r--r-- root root 3455 ./usr/share/mime/video/mp2t.xml
+-rw-r--r-- root root 3007 ./usr/share/mime/video/mp4.xml
+-rw-r--r-- root root 3190 ./usr/share/mime/video/mpeg.xml
+-rw-r--r-- root root 979 ./usr/share/mime/video/ogg.xml
+-rw-r--r-- root root 3114 ./usr/share/mime/video/quicktime.xml
+-rw-r--r-- root root 2948 ./usr/share/mime/video/vnd.mpegurl.xml
+-rw-r--r-- root root 3172 ./usr/share/mime/video/vnd.rn-realvideo.xml
+-rw-r--r-- root root 2913 ./usr/share/mime/video/vnd.vivo.xml
+-rw-r--r-- root root 3006 ./usr/share/mime/video/wavelet.xml
+-rw-r--r-- root root 2461 ./usr/share/mime/video/webm.xml
+-rw-r--r-- root root 3073 ./usr/share/mime/video/x-anim.xml
+-rw-r--r-- root root 2944 ./usr/share/mime/video/x-flic.xml
+-rw-r--r-- root root 2995 ./usr/share/mime/video/x-flv.xml
+-rw-r--r-- root root 2533 ./usr/share/mime/video/x-javafx.xml
+-rw-r--r-- root root 2381 ./usr/share/mime/video/x-matroska-3d.xml
+-rw-r--r-- root root 3095 ./usr/share/mime/video/x-matroska.xml
+-rw-r--r-- root root 1841 ./usr/share/mime/video/x-mjpeg.xml
+-rw-r--r-- root root 2935 ./usr/share/mime/video/x-mng.xml
+-rw-r--r-- root root 3153 ./usr/share/mime/video/x-msvideo.xml
+-rw-r--r-- root root 3200 ./usr/share/mime/video/x-ms-wmv.xml
+-rw-r--r-- root root 2934 ./usr/share/mime/video/x-nsv.xml
+-rw-r--r-- root root 2782 ./usr/share/mime/video/x-ogm+ogg.xml
+-rw-r--r-- root root 2811 ./usr/share/mime/video/x-sgi-movie.xml
+-rw-r--r-- root root 3102 ./usr/share/mime/video/x-theora+ogg.xml
+drwxr-xr-x root root 4096 ./usr/share/mime/x-content
+-rw-r--r-- root root 2504 ./usr/share/mime/x-content/audio-cdda.xml
+-rw-r--r-- root root 2531 ./usr/share/mime/x-content/audio-dvd.xml
+-rw-r--r-- root root 3388 ./usr/share/mime/x-content/audio-player.xml
+-rw-r--r-- root root 2971 ./usr/share/mime/x-content/blank-bd.xml
+-rw-r--r-- root root 2700 ./usr/share/mime/x-content/blank-cd.xml
+-rw-r--r-- root root 2732 ./usr/share/mime/x-content/blank-dvd.xml
+-rw-r--r-- root root 2889 ./usr/share/mime/x-content/blank-hddvd.xml
+-rw-r--r-- root root 2640 ./usr/share/mime/x-content/ebook-reader.xml
+-rw-r--r-- root root 2917 ./usr/share/mime/x-content/image-dcf.xml
+-rw-r--r-- root root 2565 ./usr/share/mime/x-content/image-picturecd.xml
+-rw-r--r-- root root 1123 ./usr/share/mime/x-content/ostree-repository.xml
+-rw-r--r-- root root 2645 ./usr/share/mime/x-content/software.xml
+-rw-r--r-- root root 2645 ./usr/share/mime/x-content/unix-software.xml
+-rw-r--r-- root root 3122 ./usr/share/mime/x-content/video-bluray.xml
+-rw-r--r-- root root 2627 ./usr/share/mime/x-content/video-dvd.xml
+-rw-r--r-- root root 2977 ./usr/share/mime/x-content/video-hddvd.xml
+-rw-r--r-- root root 2791 ./usr/share/mime/x-content/video-svcd.xml
+-rw-r--r-- root root 2509 ./usr/share/mime/x-content/video-vcd.xml
+-rw-r--r-- root root 2773 ./usr/share/mime/x-content/win32-software.xml
+drwxr-xr-x root root 4096 ./usr/share/mime/x-epoc
+-rw-r--r-- root root 2878 ./usr/share/mime/x-epoc/x-sisx-app.xml
+-rw-r--r-- root root 1631 ./usr/share/mime/XMLnamespaces
+drwxr-xr-x root root 4096 ./usr/share/misc
+drwxr-xr-x root root 4096 ./usr/share/pkgconfig
+-rw-r--r-- root root 328 ./usr/share/pkgconfig/bash-completion.pc
+-rw-r--r-- root root 120 ./usr/share/pkgconfig/shared-mime-info.pc
+-rw-r--r-- root root 90 ./usr/share/pkgconfig/udev.pc
+-rw-r--r-- root root 384 ./usr/share/pkgconfig/xorg-macros.pc
+-rw-r--r-- root root 213 ./usr/share/pkgconfig/xtrans.pc
+drwxr-xr-x root root 4096 ./usr/share/ss
+-rw-r--r-- root root 1551 ./usr/share/ss/ct_c.awk
+-rw-r--r-- root root 2290 ./usr/share/ss/ct_c.sed
+drwxr-xr-x root root 4096 ./usr/share/tabset
+-rw-r--r-- root root 135 ./usr/share/tabset/std
+-rw-r--r-- root root 95 ./usr/share/tabset/stdcrt
+-rw-r--r-- root root 160 ./usr/share/tabset/vt100
+-rw-r--r-- root root 64 ./usr/share/tabset/vt300
+drwxr-xr-x root root 4096 ./usr/share/udhcpc
+-rwxr-xr-x root root 49 ./usr/share/udhcpc/default.script
+drwxr-xr-x root root 4096 ./usr/share/wayland
+-rw-r--r-- root root 1266 ./usr/share/wayland/wayland.dtd
+-rw-r--r-- root root 292 ./usr/share/wayland/wayland-scanner.mk
+-rw-r--r-- root root 131466 ./usr/share/wayland/wayland.xml
+drwxr-xr-x root root 4096 ./usr/share/X11
+-rw-r--r-- root root 1723 ./usr/share/X11/Xcms.txt
+-rw-r--r-- root root 42077 ./usr/share/X11/XErrorDB
+drwxr-xr-x root root 4096 ./usr/share/xcb
+-rw-r--r-- root root 1705 ./usr/share/xcb/bigreq.xml
+-rw-r--r-- root root 3473 ./usr/share/xcb/composite.xml
+-rw-r--r-- root root 3299 ./usr/share/xcb/damage.xml
+-rw-r--r-- root root 3155 ./usr/share/xcb/dpms.xml
+-rw-r--r-- root root 9488 ./usr/share/xcb/dri2.xml
+-rw-r--r-- root root 5638 ./usr/share/xcb/dri3.xml
+-rw-r--r-- root root 1863 ./usr/share/xcb/ge.xml
+-rw-r--r-- root root 45351 ./usr/share/xcb/glx.xml
+-rw-r--r-- root root 7335 ./usr/share/xcb/present.xml
+-rw-r--r-- root root 30366 ./usr/share/xcb/randr.xml
+-rw-r--r-- root root 5924 ./usr/share/xcb/record.xml
+-rw-r--r-- root root 23693 ./usr/share/xcb/render.xml
+-rw-r--r-- root root 5912 ./usr/share/xcb/res.xml
+-rw-r--r-- root root 6573 ./usr/share/xcb/screensaver.xml
+-rw-r--r-- root root 6039 ./usr/share/xcb/shape.xml
+-rw-r--r-- root root 4778 ./usr/share/xcb/shm.xml
+-rw-r--r-- root root 8390 ./usr/share/xcb/sync.xml
+-rw-r--r-- root root 16132 ./usr/share/xcb/xcb.xsd
+-rw-r--r-- root root 1162 ./usr/share/xcb/xc_misc.xml
+-rw-r--r-- root root 2958 ./usr/share/xcb/xevie.xml
+-rw-r--r-- root root 5900 ./usr/share/xcb/xf86dri.xml
+-rw-r--r-- root root 14673 ./usr/share/xcb/xf86vidmode.xml
+-rw-r--r-- root root 12074 ./usr/share/xcb/xfixes.xml
+-rw-r--r-- root root 3453 ./usr/share/xcb/xinerama.xml
+-rw-r--r-- root root 103534 ./usr/share/xcb/xinput.xml
+-rw-r--r-- root root 91919 ./usr/share/xcb/xkb.xml
+-rw-r--r-- root root 11134 ./usr/share/xcb/xprint.xml
+-rw-r--r-- root root 206253 ./usr/share/xcb/xproto.xml
+-rw-r--r-- root root 8260 ./usr/share/xcb/xselinux.xml
+-rw-r--r-- root root 3968 ./usr/share/xcb/xtest.xml
+-rw-r--r-- root root 5363 ./usr/share/xcb/xvmc.xml
+-rw-r--r-- root root 16061 ./usr/share/xcb/xv.xml
+drwxr-xr-x root root 4096 ./usr/share/xml
+drwxr-xr-x root root 4096 ./usr/share/xml/dbus-1
+-rw-r--r-- root root 1907 ./usr/share/xml/dbus-1/busconfig.dtd
+-rw-r--r-- root root 1226 ./usr/share/xml/dbus-1/introspect.dtd
+drwxr-xr-x root root 4096 ./usr/share/xml/fontconfig
+-rw-r--r-- root root 7250 ./usr/share/xml/fontconfig/fonts.dtd
+drwxr-xr-x root root 4096 ./usr/src
+drwxr-xr-x root root 4096 ./usr/x86_64-poky-linux
+drwxr-xr-x root root 4096 ./usr/x86_64-poky-linux/bin
+lrwxrwxrwx root root 30 ./usr/x86_64-poky-linux/bin/ar -> ../../bin/x86_64-poky-linux-ar
+lrwxrwxrwx root root 30 ./usr/x86_64-poky-linux/bin/as -> ../../bin/x86_64-poky-linux-as
+lrwxrwxrwx root root 34 ./usr/x86_64-poky-linux/bin/ld.bfd -> ../../bin/x86_64-poky-linux-ld.bfd
+lrwxrwxrwx root root 30 ./usr/x86_64-poky-linux/bin/ld -> ../../bin/x86_64-poky-linux-ld
+lrwxrwxrwx root root 35 ./usr/x86_64-poky-linux/bin/ld.gold -> ../../bin/x86_64-poky-linux-ld.gold
+lrwxrwxrwx root root 30 ./usr/x86_64-poky-linux/bin/nm -> ../../bin/x86_64-poky-linux-nm
+lrwxrwxrwx root root 35 ./usr/x86_64-poky-linux/bin/objcopy -> ../../bin/x86_64-poky-linux-objcopy
+lrwxrwxrwx root root 35 ./usr/x86_64-poky-linux/bin/objdump -> ../../bin/x86_64-poky-linux-objdump
+lrwxrwxrwx root root 34 ./usr/x86_64-poky-linux/bin/ranlib -> ../../bin/x86_64-poky-linux-ranlib
+lrwxrwxrwx root root 35 ./usr/x86_64-poky-linux/bin/readelf -> ../../bin/x86_64-poky-linux-readelf
+lrwxrwxrwx root root 33 ./usr/x86_64-poky-linux/bin/strip -> ../../bin/x86_64-poky-linux-strip
+drwxr-xr-x root root 4096 ./var
+drwxr-xr-x root root 4096 ./var/backups
+drwxr-xr-x root root 4096 ./var/cache
+drwxr-xr-x root root 4096 ./var/cache/fontconfig
+drwx------ root root 4096 ./var/cache/ldconfig
+-rw------- root root 9934 ./var/cache/ldconfig/aux-cache
+drwxr-xr-x root root 4096 ./var/db
+-rwxr-xr-x root root 4453 ./var/db/makedbs.sh
+-rw-r--r-- root root 5351 ./var/db/Makefile
+drwxr-xr-x root root 4096 ./var/lib
+drwxr-xr-x root root 4096 ./var/lib/arpd
+drwxr-xr-x messagebus messagebus 4096 ./var/lib/dbus
+drwxr-xr-x root root 4096 ./var/lib/misc
+drwxr-xr-x root root 4096 ./var/lib/urandom
+drwxr-xr-x root root 4096 ./var/local
+lrwxrwxrwx root root 11 ./var/lock -> ../run/lock
+lrwxrwxrwx root root 12 ./var/log -> volatile/log
+lrwxrwxrwx root root 6 ./var/run -> ../run
+drwxr-xr-x root root 4096 ./var/spool
+drwxrwxr-x root mail 4096 ./var/spool/mail
+lrwxrwxrwx root root 12 ./var/tmp -> volatile/tmp
+drwxr-xr-x root root 4096 ./var/volatile
diff --git a/meta/lib/oeqa/runtime/files/test.c b/meta/lib/oeqa/files/test.c
index 2d8389c92e..2d8389c92e 100644
--- a/meta/lib/oeqa/runtime/files/test.c
+++ b/meta/lib/oeqa/files/test.c
diff --git a/meta/lib/oeqa/runtime/files/test.cpp b/meta/lib/oeqa/files/test.cpp
index 9e1a76473d..9e1a76473d 100644
--- a/meta/lib/oeqa/runtime/files/test.cpp
+++ b/meta/lib/oeqa/files/test.cpp
diff --git a/meta/lib/oeqa/files/test.rs b/meta/lib/oeqa/files/test.rs
new file mode 100644
index 0000000000..f79c691f08
--- /dev/null
+++ b/meta/lib/oeqa/files/test.rs
@@ -0,0 +1,2 @@
+fn main() {
+}
diff --git a/meta/lib/oeqa/files/testresults/testresults.json b/meta/lib/oeqa/files/testresults/testresults.json
new file mode 100644
index 0000000000..86e5e412af
--- /dev/null
+++ b/meta/lib/oeqa/files/testresults/testresults.json
@@ -0,0 +1,40 @@
+{
+ "runtime_core-image-minimal:qemuarm_20181225195701": {
+ "configuration": {
+ "DISTRO": "poky",
+ "HOST_DISTRO": "ubuntu-16.04",
+ "IMAGE_BASENAME": "core-image-minimal",
+ "IMAGE_PKGTYPE": "rpm",
+ "LAYERS": {
+ "meta": {
+ "branch": "master",
+ "commit": "801745d918e83f976c706f29669779f5b292ade3",
+ "commit_count": 52782
+ },
+ "meta-poky": {
+ "branch": "master",
+ "commit": "801745d918e83f976c706f29669779f5b292ade3",
+ "commit_count": 52782
+ },
+ "meta-yocto-bsp": {
+ "branch": "master",
+ "commit": "801745d918e83f976c706f29669779f5b292ade3",
+ "commit_count": 52782
+ }
+ },
+ "MACHINE": "qemuarm",
+ "STARTTIME": "20181225195701",
+ "TEST_TYPE": "runtime"
+ },
+ "result": {
+ "apt.AptRepoTest.test_apt_install_from_repo": {
+ "log": "Test requires apt to be installed",
+ "status": "PASSED"
+ },
+ "buildcpio.BuildCpioTest.test_cpio": {
+ "log": "Test requires autoconf to be installed",
+ "status": "ERROR"
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/meta/lib/oeqa/manual/abat.patch b/meta/lib/oeqa/manual/abat.patch
new file mode 100644
index 0000000000..1541ac80cb
--- /dev/null
+++ b/meta/lib/oeqa/manual/abat.patch
@@ -0,0 +1,64 @@
+########
+diff --git a/glxgears_check.sh b/glxgears_check.sh
+index 17622b8..c4d3b97 100755
+--- a/glxgears_check.sh
++++ b/glxgears_check.sh
+@@ -31,7 +31,7 @@ else
+
+ sleep 6
+
+- XPID=$( ps ax | awk '{print $1, $5}' | grep glxgears | awk '{print $1}')
++ XPID=$( ps | awk '{print $1, $5}' | grep glxgears | awk '{print $1}')
+ if [ ! -z "$XPID" ]; then
+ kill -9 $XPID >/dev/null 2>&1
+ echo "glxgears can run, PASS!"
+diff --git a/x_close.sh b/x_close.sh
+index e287be1..3429f1a 100755
+--- a/x_close.sh
++++ b/x_close.sh
+@@ -22,7 +22,7 @@
+ #
+ function close_proc(){
+ echo "kill process Xorg"
+-XPID=$( ps ax | awk '{print $1, $5}' | egrep "X$|Xorg$" | awk '{print $1}')
++XPID=$( ps | awk '{print $1, $6}' | egrep "X$|Xorg$" | awk '{print $1}')
+ if [ ! -z "$XPID" ]; then
+ kill $XPID
+ sleep 4
+diff --git a/x_start.sh b/x_start.sh
+index 9cf6eab..2305796 100755
+--- a/x_start.sh
++++ b/x_start.sh
+@@ -24,7 +24,7 @@
+ X_ERROR=0
+
+ #test whether X has started
+-PXID=$(ps ax |awk '{print $1,$5}' |egrep "Xorg$|X$" |grep -v grep | awk '{print $1}')
++PXID=$(ps |awk '{print $1,$6}' |egrep "Xorg$|X$" |grep -v grep | awk '{print $1}')
+ if [ ! -z "$PXID" ]; then
+ echo "[WARNING] Xorg has started!"
+ XORG_STATUS="started"
+@@ -35,9 +35,11 @@ else
+ #start up the x server
+ echo "Start up the X server for test in display $DISPLAY................"
+
+- $XORG_DIR/bin/X >/dev/null 2>&1 &
++ #$XORG_DIR/bin/X >/dev/null 2>&1 &
++ #sleep 8
++ #xterm &
++ /etc/init.d/xserver-nodm start &
+ sleep 8
+- xterm &
+ fi
+ XLOG_FILE=/var/log/Xorg.0.log
+ [ -f $XORG_DIR/var/log/Xorg.0.log ] && XLOG_FILE=$XORG_DIR/var/log/Xorg.0.log
+@@ -54,7 +56,7 @@ fi
+ X_ERROR=1
+ fi
+
+- XPID=$( ps ax | awk '{print $1, $5}' | egrep "X$|Xorg$" |grep -v grep| awk '{print $1}')
++ XPID=$( ps | awk '{print $1, $6}' | egrep "X$|Xorg$" |grep -v grep| awk '{print $1}')
+ if [ -z "$XPID" ]; then
+ echo "Start up X server FAIL!"
+ echo
+######## \ No newline at end of file
diff --git a/meta/lib/oeqa/manual/bsp-hw.json b/meta/lib/oeqa/manual/bsp-hw.json
new file mode 100644
index 0000000000..308a0807f3
--- /dev/null
+++ b/meta/lib/oeqa/manual/bsp-hw.json
@@ -0,0 +1,626 @@
+[
+ {
+ "test": {
+ "@alias": "bsps-hw.bsps-hw.boot_and_install_from_USB",
+ "author": [
+ {
+ "email": "alexandru.c.georgescu@intel.com",
+ "name": "alexandru.c.georgescu@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "plugin usb which contains live image burned",
+ "expected_results": "User can choose install system from usb stick onto harddisk from boot menu or command line option \n"
+ },
+ "2": {
+ "action": "configure device BIOS to firstly boot from USB if necessary",
+ "expected_results": "Installed system can boot up"
+ },
+ "3": {
+ "action": "boot the device and select option \"Install\" from boot menu",
+ "expected_results": ""
+ },
+ "4": {
+ "action": "proceed through default install process",
+ "expected_results": ""
+ },
+ "5": {
+ "action": "Remove USB, and reboot into new installed system. \nNote: If installation was successfully completed and received this message \"\"(sdx): Volume was not properly unmounted...Please run fsck.\"\" ignore it because this was allowed according to bug 9652.",
+ "expected_results": ""
+ }
+ },
+ "summary": "boot_and_install_from_USB"
+ }
+ },
+ {
+ "test": {
+ "@alias": "bsps-hw.bsps-hw.live_boot_from_USB",
+ "author": [
+ {
+ "email": "juan.fernandox.ramos.frayle@intel.com",
+ "name": "juan.fernandox.ramos.frayle@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "Plugin usb which contains live image burned.",
+ "expected_results": "User can choose boot from live image on usb stick from boot menu or command line option"
+ },
+ "2": {
+ "action": "Configure device BIOS to firstly boot from USB if necessary.",
+ "expected_results": ""
+ },
+ "3": {
+ "action": "Reboot the device and boot from USB stick.",
+ "expected_results": "Live image can boot up with usb stick"
+ }
+ },
+ "summary": "live_boot_from_USB"
+ }
+ },
+ {
+ "test": {
+ "@alias": "bsps-hw.bsps-hw.switch_among_multi_applications_and_desktop",
+ "author": [
+ {
+ "email": "alexandru.c.georgescu@intel.com",
+ "name": "alexandru.c.georgescu@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "launch several applications(like contacts, file manager, notes, etc)",
+ "expected_results": "user could switch among multi applications and desktop"
+ },
+ "2": {
+ "action": "launch terminal",
+ "expected_results": ""
+ },
+ "3": {
+ "action": "switch among multi applications and desktop",
+ "expected_results": ""
+ },
+ "4": {
+ "action": "close applications \nNote: The case is for sato image only. ",
+ "expected_results": ""
+ }
+ },
+ "summary": "switch_among_multi_applications_and_desktop"
+ }
+ },
+ {
+ "test": {
+ "@alias": "bsps-hw.bsps-hw.connman_offline_mode_in_connman-gnome",
+ "author": [
+ {
+ "email": "alexandru.c.georgescu@intel.com",
+ "name": "alexandru.c.georgescu@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "Launch connman-properties after system booting \n\n",
+ "expected_results": ""
+ },
+ "2": {
+ "action": "choose \"offline mode\" and check the connection of all network interfaces ",
+ "expected_results": "All connection should be off after clicking \"offline mode\" . "
+ }
+ },
+ "summary": "connman_offline_mode_in_connman-gnome"
+ }
+ },
+ {
+ "test": {
+ "@alias": "bsps-hw.bsps-hw.check_CPU_utilization_after_standby",
+ "author": [
+ {
+ "email": "alexandru.c.georgescu@intel.com",
+ "name": "alexandru.c.georgescu@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "Start up system",
+ "expected_results": ""
+ },
+ "2": {
+ "action": "run \"top\" command and check if there is any process eating CPU time",
+ "expected_results": ""
+ },
+ "3": {
+ "action": "make system into standby and resume it",
+ "expected_results": ""
+ },
+ "4": {
+ "action": "run \"top\" command and check if there is any difference with the data before standby",
+ "expected_results": "There should be no big difference before/after standby with \"top\" . "
+ }
+ },
+ "summary": "check_CPU_utilization_after_standby"
+ }
+ },
+ {
+ "test": {
+ "@alias": "bsps-hw.bsps-hw.Add_multiple_files_in_media_player",
+ "author": [
+ {
+ "email": "alexandru.c.georgescu@intel.com",
+ "name": "alexandru.c.georgescu@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "Launch media player",
+ "expected_results": ""
+ },
+ "2": {
+ "action": "Add multiple files(5 files) in media player at same time (ogg or wav)",
+ "expected_results": ""
+ },
+ "3": {
+ "action": "Verify the sound.",
+ "expected_results": "Media player should be OK with this action, it reproduce files correctly."
+ }
+ },
+ "summary": "Add_multiple_files_in_media_player"
+ }
+ },
+ {
+ "test": {
+ "@alias": "bsps-hw.bsps-hw.video_-_libva_check_(ogg_video_play)",
+ "author": [
+ {
+ "email": "alexandru.c.georgescu@intel.com",
+ "name": "alexandru.c.georgescu@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "check if libva is installed on system (or libogg)",
+ "expected_results": ""
+ },
+ "2": {
+ "action": "copy sample ogg file to system",
+ "expected_results": ""
+ },
+ "3": {
+ "action": "launch media player can play the ogg file",
+ "expected_results": "ogg file can be played without problem when libva is used (or libogg) "
+ }
+ },
+ "summary": "video_-_libva_check_(ogg_video_play)"
+ }
+ },
+ {
+ "test": {
+ "@alias": "bsps-hw.bsps-hw.media_player_-_play_video_(ogv)",
+ "author": [
+ {
+ "email": "alexandru.c.georgescu@intel.com",
+ "name": "alexandru.c.georgescu@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "copy sample ogv file to system",
+ "expected_results": ""
+ },
+ "2": {
+ "action": "launch media player and make sure it can play the ogv file",
+ "expected_results": "ogv file can be played without problem"
+ }
+ },
+ "summary": "media_player_-_play_video_(ogv)"
+ }
+ },
+ {
+ "test": {
+ "@alias": "bsps-hw.bsps-hw.media_player_-_stop/play_button_(ogv)",
+ "author": [
+ {
+ "email": "alexandru.c.georgescu@intel.com",
+ "name": "alexandru.c.georgescu@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "copy sample ogv file to system",
+ "expected_results": ""
+ },
+ "2": {
+ "action": "launch media player can play the ogv file",
+ "expected_results": ""
+ },
+ "3": {
+ "action": "click \"stop\" button to stop playing",
+ "expected_results": ""
+ },
+ "4": {
+ "action": "click \"start\" button to resume playing",
+ "expected_results": "ogv file can be start/stop without problem"
+ }
+ },
+ "summary": "media_player_-_stop/play_button_(ogv)"
+ }
+ },
+ {
+ "test": {
+ "@alias": "bsps-hw.bsps-hw.audio_-_play_(ogg)_with_HDMI",
+ "author": [
+ {
+ "email": "alexandru.c.georgescu@intel.com",
+ "name": "alexandru.c.georgescu@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "copy sample ogg file to system",
+ "expected_results": ""
+ },
+ "2": {
+ "action": "connect system with a monitor with HDMI",
+ "expected_results": ""
+ },
+ "3": {
+ "action": "launch media player and play the ogg file",
+ "expected_results": "ogg file can be played without problem with HDMI"
+ }
+ },
+ "summary": "audio_-_play_(ogg)_with_HDMI"
+ }
+ },
+ {
+ "test": {
+ "@alias": "bsps-hw.bsps-hw.audio_-_play_(wav)_with_HDMI",
+ "author": [
+ {
+ "email": "alexandru.c.georgescu@intel.com",
+ "name": "alexandru.c.georgescu@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "copy sample wav file to system",
+ "expected_results": ""
+ },
+ "2": {
+ "action": "connect system with a monitor with HDMI",
+ "expected_results": ""
+ },
+ "3": {
+ "action": "launch media player and play the wav file",
+ "expected_results": "wav file can be played without problem, with HDMI"
+ }
+ },
+ "summary": "audio_-_play_(wav)_with_HDMI"
+ }
+ },
+ {
+ "test": {
+ "@alias": "bsps-hw.bsps-hw.Graphics_-_ABAT",
+ "author": [
+ {
+ "email": "alexandru.c.georgescu@intel.com",
+ "name": "alexandru.c.georgescu@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "Download ABAT test suite from internal git repository, git clone git://tinderbox.sh.intel.com/git/abat",
+ "expected_results": ""
+ },
+ "2": {
+ "action": "Apply following patch to make it work on yocto environment",
+ "expected_results": ""
+ },
+ "3": {
+ "action": "Run \"./abat.sh\" to run ABAT test refer to abat.patch",
+ "expected_results": "All ABAT test should pass. \nNote : If below 3 fails appears ignore them. \n- start up X server fail.. due is already up \n- module [intel_agp] \n- module [i915]"
+ }
+ },
+ "summary": "Graphics_-_ABAT"
+ }
+ },
+ {
+ "test": {
+ "@alias": "bsps-hw.bsps-hw.Graphics_-_x11perf_-_2D",
+ "author": [
+ {
+ "email": "alexandru.c.georgescu@intel.com",
+ "name": "alexandru.c.georgescu@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "Run \"x11perf -aa10text\" and \"x11perf -rgb10text\"",
+ "expected_results": ""
+ },
+ "2": {
+ "action": "Get the FPS result and compare it with upstream graphics data on Sandybridge",
+ "expected_results": "There should not be big regression between Yocto and upstream linux . "
+ }
+ },
+ "summary": "Graphics_-_x11perf_-_2D"
+ }
+ },
+ {
+ "test": {
+ "@alias": "bsps-hw.bsps-hw.Check_if_SATA_disk_can_work_correctly",
+ "author": [
+ {
+ "email": "yi.zhao@windriver.com",
+ "name": "yi.zhao@windriver.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "Run fdisk command to create partition on SATA disk. ",
+ "expected_results": "The SATA device can mount, umount, read and write. "
+ },
+ "2": {
+ "action": "Mount/Umount \n mke2fs /dev/sda1 \n mount -t ext2 /dev/sda1 /mnt/disk \n umount /mnt/disk",
+ "expected_results": ""
+ },
+ "3": {
+ "action": "Read/Write (filesystem) \n touch /mnt/disk/test.txt \n echo abcd > /mnt/disk/test.txt \n cat /mnt/disk/test.txt",
+ "expected_results": ""
+ },
+ "4": {
+ "action": "Read/Write (raw) \n dd if=/dev/sda1 of=/tmp/test bs=1k count=1k \n This command will read 1MB from /dev/sda1 to /tmp/test",
+ "expected_results": ""
+ }
+ },
+ "summary": "Check_if_SATA_disk_can_work_correctly"
+ }
+ },
+ {
+ "test": {
+ "@alias": "bsps-hw.bsps-hw.Install_and_boot_from_USB-drive_to_HDD-drive",
+ "author": [
+ {
+ "email": "david.israelx.rodriguez.castellanos@intel.com",
+ "name": "david.israelx.rodriguez.castellanos@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "Get a HDD drive.",
+ "expected_results": "User can choose install system from USB stick on HDD drive from boot menu or command line option \n"
+ },
+ "2": {
+ "action": "Plugin USB which contains live image burned (USB1).",
+ "expected_results": "Installed system can boot up."
+ },
+ "3": {
+ "action": "Configure device BIOS to firstly boot from USB if necessary",
+ "expected_results": ""
+ },
+ "4": {
+ "action": "Boot the device and select option \"Install\" from boot menu.",
+ "expected_results": ""
+ },
+ "5": {
+ "action": "Make sure that the divice in which image is going to be installed is the HDD drive.",
+ "expected_results": ""
+ },
+ "6": {
+ "action": "Proceed through default install process.",
+ "expected_results": ""
+ },
+ "7": {
+ "action": "Remove USB1, and reboot into new installed system.",
+ "expected_results": ""
+ }
+ },
+ "summary": "Install_and_boot_from_USB-drive_to_HDD-drive"
+ }
+ },
+ {
+ "test": {
+ "@alias": "bsps-hw.bsps-hw.Install_and_boot_from_USB-drive_to_SD-drive",
+ "author": [
+ {
+ "email": "david.israelx.rodriguez.castellanos@intel.com",
+ "name": "david.israelx.rodriguez.castellanos@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "Get a SD-drive with enough free space to install an image.",
+ "expected_results": "User can choose install system from USB stick on SD-drive from boot menu or command line option. \n"
+ },
+ "2": {
+ "action": "Plugin USB which contains live image burned (USB1).",
+ "expected_results": "Installed system can boot up."
+ },
+ "3": {
+ "action": "Configure device BIOS to firstly boot from USB if necessary",
+ "expected_results": ""
+ },
+ "4": {
+ "action": "Boot the device and select option \"Install\" from boot menu.",
+ "expected_results": ""
+ },
+ "5": {
+ "action": "Make sure that the device in which image is going to be installed is the SD-drive.",
+ "expected_results": ""
+ },
+ "6": {
+ "action": "Proceed through default install process.",
+ "expected_results": ""
+ },
+ "7": {
+ "action": "Remove USB1, and reboot into new installed system.",
+ "expected_results": ""
+ }
+ },
+ "summary": "Install_and_boot_from_USB-drive_to_SD-drive"
+ }
+ },
+ {
+ "test": {
+ "@alias": "bsps-hw.bsps-hw.Test_boot_on_serial_communication_SD",
+ "author": [
+ {
+ "email": "juan.fernandox.ramos.frayle@intel.com",
+ "name": "juan.fernandox.ramos.frayle@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "1.- Create a yocto project image in a SD card \nexample \n2 - Configure a connection like shown in the link avobe: \nhttps://wiki.yoctoproject.org/wiki/MinnowMax_board_Serial_video_connection_guide \n3 - Verify the Minow Max board is connected to the host \n4 - Boot the system to desktop \n5 - Open a Terminal and check the IP \nIn Terminal type $ifconfig\"",
+ "expected_results": "Verify you can create a live image \n"
+ }
+ },
+ "summary": "Test_boot_on_serial_communication_SD"
+ }
+ },
+ {
+ "test": {
+ "@alias": "bsps-hw.bsps-hw.Test_boot_on_serial_communication_HDD",
+ "author": [
+ {
+ "email": "juan.fernandox.ramos.frayle@intel.com",
+ "name": "juan.fernandox.ramos.frayle@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "1 - Create a yocto project image in a HDD \nexample \n2 - Configure a connection like shown in the link avobe: \nhttps://wiki.yoctoproject.org/wiki/MinnowMax_board_Serial_video_connection_guide \n3 - Verify the Minow Max board is connected to the host \n4 - Boot the system to desktop \n5 - Open a Terminal and check the IP \nIn Terminal type $ifconfig\"> ",
+ "expected_results": "Verify you can create a live image \n"
+ }
+ },
+ "summary": "Test_boot_on_serial_communication_HDD"
+ }
+ },
+ {
+ "test": {
+ "@alias": "bsps-hw.bsps-hw.Test_boot_on_serial_communication_USB",
+ "author": [
+ {
+ "email": "juan.fernandox.ramos.frayle@intel.com",
+ "name": "juan.fernandox.ramos.frayle@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "1.- Create a yocto project image in a USB \nexample <dd if= core-image-sato-sdk.hddimg of =/dev/sdb>",
+ "expected_results": "Verify you can create a live image \n"
+ },
+ "2": {
+ "action": "Configure a connection like shown in the link avobe: \nhttps://wiki.yoctoproject.org/wiki/MinnowMax_board_Serial_video_connection_guide\n\n",
+ "expected_results": "Video signal is present and not delayed \n"
+ },
+ "3": {
+ "action": " Verify the Minow Max board is connected to the host",
+ "expected_results": "Verify the system boot ok and no errors are present \n"
+ },
+ "4": {
+ "action": " Boot the system to desktop",
+ "expected_results": " Check that a valid IP is retrieved"
+ },
+ "5": {
+ "action": " Open a Terminal and check the IP \nIn Terminal type $ifconfig\" ",
+ "expected_results": ""
+ }
+ },
+ "summary": "Test_boot_on_serial_communication_USB"
+ }
+ },
+ {
+ "test": {
+ "@alias": "bsps-hw.bsps-hw.Test_Seek_bar_and_volume_control",
+ "author": [
+ {
+ "email": "juan.fernandox.ramos.frayle@intel.com",
+ "name": "juan.fernandox.ramos.frayle@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "Run media player and load a media file ",
+ "expected_results": "Media player correctly open audio/video file \n"
+ },
+ "2": {
+ "action": "Verify that seek and volume control are present ",
+ "expected_results": "Seek bar and volume control are present \n"
+ },
+ "3": {
+ "action": "Verify that selecting the speaker icon opens the volume control",
+ "expected_results": "Volume control bar must appear \n"
+ },
+ "4": {
+ "action": "Verify you can increase and decrease volume level with the volume control",
+ "expected_results": "Volume level must be increased and decreased \n"
+ },
+ "5": {
+ "action": "Observe that slider on the seek bar moves along with the video/audio play",
+ "expected_results": "Video/audio file can be played and slider moves along with the video/audio play \n"
+ },
+ "6": {
+ "action": "Verify you can navigate the video with the slider back and forward",
+ "expected_results": "The slider can move back and forward in the seek bar \n"
+ },
+ "7": {
+ "action": "Verify that seek and volume control are functional in full screen mode",
+ "expected_results": "Press the full screen mode icon, seek bar and volume control must work fine \n"
+ },
+ "8": {
+ "action": "Verify that pressing << or >> while playing a file makes the slide goes slow/backwards or faster",
+ "expected_results": "Verify << and >> works correctly"
+ }
+ },
+ "summary": "Test_Seek_bar_and_volume_control"
+ }
+ },
+ {
+ "test": {
+ "@alias": "bsps-hw.bsps-hw.Check_if_watchdog_can_reset_the_target_system",
+ "author": [
+ {
+ "email": "yi.zhao@windriver.com",
+ "name": "yi.zhao@windriver.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "1.Check if watchdog device exist in /dev/ directory. Run command echo 1 > /dev/watchdog and wait for 60s. Then, the target will reboot.",
+ "expected_results": "The watchdog device exist in /dev/ directory and can reboot the target.\n"
+ }
+ },
+ "summary": "Check_if_watchdog_can_reset_the_target_system"
+ }
+ },
+ {
+ "test": {
+ "@alias": "bsps-hw.bsps-hw.System_can_boot_up_via_NFS",
+ "author": [
+ {
+ "email": "yi.zhao@windriver.com",
+ "name": "yi.zhao@windriver.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "Connect the board's first serial port to your workstation and then start up your favourite serial terminal so that you will be able to interact with the serial console. If you don't have a favourite, picocom is suggested: $ picocom /dev/ttyS0 -b 115200 ",
+ "expected_results": "The system can boot up without problem\n"
+ },
+ "2": {
+ "action": "Power up or reset the board and press a key on the terminal when prompted to get to the U-Boot command line ",
+ "expected_results": ""
+ },
+ "3": {
+ "action": "Set up the environment in U-Boot: => setenv ipaddr => setenv serverip ",
+ "expected_results": ""
+ },
+ "4": {
+ "action": "Download the kernel and boot: => tftp tftp $loadaddr vmlinux => bootoctlinux $loadaddr coremask=0x3 root=/dev/nfs rw nfsroot=: ip=::::edgerouter:eth0:off mtdparts=phys_mapped_flash:512k(boot0),512k(boot1),64k@3072k(eeprom)\n",
+ "expected_results": ""
+ }
+ },
+ "summary": "System_can_boot_up_via_NFS"
+ }
+ }
+]
diff --git a/meta/lib/oeqa/manual/build-appliance.json b/meta/lib/oeqa/manual/build-appliance.json
new file mode 100644
index 0000000000..82a556e93e
--- /dev/null
+++ b/meta/lib/oeqa/manual/build-appliance.json
@@ -0,0 +1,96 @@
+[
+ {
+ "test": {
+ "@alias": "build-appliance.build-appliance.Build_core-image-minimal_with_build-appliance-image",
+ "author": [
+ {
+ "email": "corneliux.stoicescu@intel.com",
+ "name": "corneliux.stoicescu@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "Build with AUTOREV or download from Autobuilder an image for Yocto Build Appliance. ",
+ "expected_results": ""
+ },
+ "2": {
+ "action": "Boot the image under VMWare Player. ",
+ "expected_results": ""
+ },
+ "3": {
+ "action": "Build qemux86 core-image-minimal using bitbake command line in the build-appliance-image ",
+ "expected_results": ""
+ },
+ "4": {
+ "action": "Launch the image just built using runqemu. ",
+ "expected_results": "core-image-minimal should build and boot. "
+ }
+ },
+ "summary": "Build_core-image-minimal_with_build-appliance-image"
+ }
+ },
+ {
+ "test": {
+ "@alias": "build-appliance.build-appliance.Build_a_image_without_error_(added_recipe)",
+ "author": [
+ {
+ "email": "sstncr@gmail.com",
+ "name": "sstncr@gmail.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "Launch Build Appliance",
+ "expected_results": "User could build a image without error and the added package is in the image"
+ },
+ "2": {
+ "action": "Set \"Machine\" in conf/local.conf, for example, qemuarm",
+ "expected_results": ""
+ },
+ "3": {
+ "action": "Install a new package to the image, for example, acpid. Set the following line in conf/local.conf: IMAGE_INSTALL:append = \" acpid\"",
+ "expected_results": ""
+ },
+ "4": {
+ "action": "Build a image using bitbake command line, for example, bitbake core-image-minimal",
+ "expected_results": ""
+ },
+ "5": {
+ "action": "After build finished, launch the image and check if the added package built into image",
+ "expected_results": ""
+ }
+ },
+ "summary": "Build_a_image_without_error_(added_recipe)."
+ }
+ },
+ {
+ "test": {
+ "@alias": "build-appliance.build-appliance.Create_core-image-sato-sdk_using_build_appliance",
+ "author": [
+ {
+ "email": "ee.peng.yeoh@intel.com",
+ "name": "ee.peng.yeoh@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "Build with AUTOREV or download from Autobuilder an image for Yocto Build Appliance. ",
+ "expected_results": ""
+ },
+ "2": {
+ "action": "Boot the image under VMWare Player. ",
+ "expected_results": ""
+ },
+ "3": {
+ "action": "Build qemux86 core-image-sato-sdk using bitbake command line in the build-appliance-image ",
+ "expected_results": ""
+ },
+ "4": {
+ "action": "Launch the image just built using runqemu. ",
+ "expected_results": ""
+ }
+ },
+ "summary": "Create_core-image-sato-sdk_using_build_appliance"
+ }
+ }
+] \ No newline at end of file
diff --git a/meta/lib/oeqa/manual/crops.json b/meta/lib/oeqa/manual/crops.json
new file mode 100644
index 0000000000..5cfa653843
--- /dev/null
+++ b/meta/lib/oeqa/manual/crops.json
@@ -0,0 +1,294 @@
+[
+ {
+ "test": {
+ "@alias": "crops-default.crops-default.sdkext_eSDK_devtool_build_make",
+ "author": [
+ {
+ "email": "francisco.j.pedraza.gonzalez@intel.com",
+ "name": "francisco.j.pedraza.gonzalez@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "IMPORTANT NOTE: The firsts 5 steps refer to configuration of the environment to run the rest of the steps. These only apply for CROPS-eSDK. \n\n\n\n",
+ "expected_results": ""
+ },
+ "2": {
+ "action": " Initiate your Crops-esdk environment as it says in wiki https://github.com/crops/docker-win-mac-docs/wiki \n\n",
+ "expected_results": ""
+ },
+ "3": {
+ "action": "Create the following tree of files <crops-esdk-workdir-workspace>/sdkext/files/myapp <crops-esdk-workdir-workspace>/sdkext/files/myapp_cmake \n\n\n",
+ "expected_results": ""
+ },
+ "4": {
+ "action": " Create the following files withing the myapp directory myapp.c and the Makefile. Write the following inside of each file: \n---------------------------------------- \nMakefile should contain \n\nall: myapp \n\nmyapp: myapp.o \n\t$(CC) $(LDFLAGS) $< -o $@ \n\nmyapp.o: myapp.c \n\t$(CC) $(CFLAGS) -c $< -o $@ \n\nclean: \n\trm -rf myapp.o myapp \n\n----------------------------- \nmyapp.c shold contain \n\n\n#include <stdio.h> \n\nint \nmain(int argc, char *argv[]) \n{ \n\tprintf(\"Hello world\\n\"); \n \n\treturn 0; \n} \n------------------------------------ \n\n",
+ "expected_results": "be sure that the indentations on the makefile are tabs not spaces. \n\n"
+ },
+ "5": {
+ "action": " Create the following files within the myapp_cmake directory CMakeLists.txt and myapp.c. Write the following inside each file: \n\n------------------------------------ \nCMakeLists.txt should contain: \n\ncmake_minimum_required (VERSION 2.6) \nproject (myapp) \n# The version number. \nset (myapp_VERSION_MAJOR 1) \nset (myapp_VERSION_MINOR 0) \n\n# add the executable \nadd_executable (myapp myapp.c) \n\ninstall(TARGETS myapp \nRUNTIME DESTINATION bin) \n\n------------------------------------------ \nmyapp.c should contain: \n\n#include <stdio.h> \n\nint \nmain(int argc, char *argv[]) \n{ \n\tprintf(\"Hello world\\n\"); \n\n\treturn 0; \n} \n------------------------------------------------- \n\n",
+ "expected_results": "Be sure that the indentations on CMakeLists.txt is tabs not spaces."
+ },
+ "6": {
+ "action": " source environment-setup-i586-poky-linux \n\n",
+ "expected_results": "This should output a message that says SDK environment now set up; additionally you may now run devtool to perform development tasks etc etc ... \n\n"
+ },
+ "7": {
+ "action": " run command which devtool \n\n",
+ "expected_results": "this should output the directory of the devtool script and it should be within the sdk workdir you are working in. \n\n "
+ },
+ "8": {
+ "action": "devtool add myapp <directory>(this is myapp dir) \n\n\n",
+ "expected_results": "The directory you should input is the myapp directory. This should automatically create the recipe myapp.bb under <crops-esdk-workdir-workspace>/recipes/myapp/myapp.bb"
+ },
+ "9": {
+ "action": " devtool build myapp \n\n",
+ "expected_results": "This should compile an image"
+ },
+ "10": {
+ "action": " devtool reset myapp ",
+ "expected_results": "This cleans sysroot of the myapp recipe, but it leaves the source tree intact. meaning it does not erase."
+ }
+ },
+ "summary": "sdkext_eSDK_devtool_build_make"
+ }
+ },
+ {
+ "test": {
+ "@alias": "crops-default.crops-default.sdkext_devtool_build_esdk_package",
+ "author": [
+ {
+ "email": "francisco.j.pedraza.gonzalez@intel.com",
+ "name": "francisco.j.pedraza.gonzalez@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "IMPORTANT NOTE: The firsts 5 steps refer to configuration of the environment to run the rest of the steps. These only apply for CROPS-eSDK. \n\n\n\n",
+ "expected_results": ""
+ },
+ "2": {
+ "action": " Initiate your Crops-esdk environment as it says in wiki https://github.com/crops/docker-win-mac-docs/wiki \n\n",
+ "expected_results": ""
+ },
+ "3": {
+ "action": " Create the following tree of files <crops-esdk-workdir-workspace>/sdkext/files/myapp/ \n <crops-esdk-workdir-workspace>/sdkext/files/myapp_cmake \n\n",
+ "expected_results": ""
+ },
+ "4": {
+ "action": " Create the following files withing the myapp directory myapp.c and the Makefile. Write the following inside of each file: \n---------------------------------------- \nMakefile should contain \n\nall: myapp \n\nmyapp: myapp.o \n\t$(CC) $(LDFLAGS) $< -o $@ \n\nmyapp.o: myapp.c \n\t$(CC) $(CFLAGS) -c $< -o $@ \n\nclean: \n\trm -rf myapp.o myapp \n\n----------------------------- \nmyapp.c shold contain \n\n#include <stdio.h> \n\nint \nmain(int argc, char *argv[]) \n{ \n\tprintf(\"Hello world\\n\"); \n \n\treturn 0; \n} \n------------------------------------ \n\n",
+ "expected_results": "be sure that the indentations on the makefile are tabs not spaces. \n\n"
+ },
+ "5": {
+ "action": " Create the following files within the myapp_cmake directory CMakeLists.txt and myapp.c. Write the following inside each file: \n\n------------------------------------ \nCMakeLists.txt should contain: \n\ncmake_minimum_required (VERSION 2.6) \nproject (myapp) \n# The version number. \nset (myapp_VERSION_MAJOR 1) \nset (myapp_VERSION_MINOR 0) \n\n# add the executable \nadd_executable (myapp myapp.c) \n\ninstall(TARGETS myapp \nRUNTIME DESTINATION bin) \n\n------------------------------------------ \nmyapp.c should contain: \n\n#include<stdio.h> \n\nint \nmain(int argc, char *argv[]) \n{ \n\tprintf(\"Hello world\\n\"); \n\n\treturn 0; \n} \n------------------------------------------------- \n\n",
+ "expected_results": "Be sure that the indentations on CMakeLists.txt is tabs not spaces. \n\n"
+ },
+ "6": {
+ "action": " source environment-setup-i586-poky-linux \n\n",
+ "expected_results": "This should output a message that says SDK environment now set up; additionally you may now run devtool to perform development tasks etc etc ... \n\n"
+ },
+ "7": {
+ "action": " run command which devtool \n\n",
+ "expected_results": " this should output the directory of the devtool script and it should be within the sdk workdir you are working in. \n\n"
+ },
+ "8": {
+ "action": " devtool add myapp <directory> (this is myapp dir) \n\n",
+ "expected_results": " The directory you should input is the myapp directory. This should automatically create the recipe myapp.bb under <crops-esdk-workdir-workspace>/recipes/myapp/myapp.bb \n\n"
+ },
+ "9": {
+ "action": " devtool package myapp \n\n",
+ "expected_results": " you should expect a package creation of myapp and it should be under the /tmp/deploy/ \n\n"
+ },
+ "10": {
+ "action": " devtool reset myapp ",
+ "expected_results": "This cleans sysroot of the myapp recipe, but it leaves the source tree intact. meaning it does not erase.\n</package_format>"
+ }
+ },
+ "summary": "sdkext_devtool_build_esdk_package"
+ }
+ },
+ {
+ "test": {
+ "@alias": "crops-default.crops-default.sdkext_devtool_build_cmake",
+ "author": [
+ {
+ "email": "francisco.j.pedraza.gonzalez@intel.com",
+ "name": "francisco.j.pedraza.gonzalez@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "IMPORTANT NOTE: The firsts 5 steps refer to configuration of the environment to run the rest of the steps. These only apply for CROPS-eSDK. \n\n\n\n",
+ "expected_results": ""
+ },
+ "2": {
+ "action": " Initiate your Crops-esdk environment as it says in wiki https://github.com/crops/docker-win-mac-docs/wiki \n\n",
+ "expected_results": ""
+ },
+ "3": {
+ "action": " Create the following tree of files <crops-esdk-workdir-workspace>/sdkext/files/myapp \n <crops-esdk-workdir-workspace>/sdkext/files/myapp_cmake \n\n",
+ "expected_results": ""
+ },
+ "4": {
+ "action": " Create the following files withing the myapp directory myapp.c and the Makefile. Write the following inside of each file: \n---------------------------------------- \nMakefile should contain \n\nall: myapp \n\nmyapp: myapp.o \n\t$(CC) $(LDFLAGS) $< -o $@ \n\nmyapp.o: myapp.c \n\t$(CC) $(CFLAGS) -c $< -o $@ \n\nclean: \n\trm -rf myapp.o myapp \n\n----------------------------- \nmyapp.c shold contain \n\n#include <stdio.h> \n\nint \nmain(int argc, char *argv[]) \n{ \n\tprintf(\"Hello world\\n\"); \n \n\treturn 0; \n} \n------------------------------------ \n\n",
+ "expected_results": "be sure that the indentations on the makefile are tabs not spaces. \n\n"
+ },
+ "5": {
+ "action": " Create the following files within the myapp_cmake directory CMakeLists.txt and myapp.c. Write the following inside each file: \n\n------------------------------------ \nCMakeLists.txt should contain: \n\ncmake_minimum_required (VERSION 2.6) \nproject (myapp) \n# The version number. \nset (myapp_VERSION_MAJOR 1) \nset (myapp_VERSION_MINOR 0) \n\n# add the executable \nadd_executable (myapp myapp.c) \n\ninstall(TARGETS myapp \nRUNTIME DESTINATION bin) \n\n------------------------------------------ \nmyapp.c should contain: \n\n#include \n\nint \nmain(int argc, char *argv[]) \n{ \n\tprintf(\"Hello world\\n\"); \n\n\treturn 0; \n} \n------------------------------------------------- \n\n",
+ "expected_results": "Be sure that the indentations on CMakeLists.txt is tabs not spaces. \n\n"
+ },
+ "6": {
+ "action": " source environment-setup-i586-poky-linux \n\n",
+ "expected_results": "This should output a message that says SDK environment now set up; additionally you may now run devtool to perform development tasks etc etc ... \n\n"
+ },
+ "7": {
+ "action": " run command which devtool \n\n",
+ "expected_results": "this should output the directory of the devtool script and it should be within the sdk workdir you are working in. \n\n"
+ },
+ "8": {
+ "action": " devtool add myapp <directory> (this is myapp_cmake dir) \n\n",
+ "expected_results": "The directory you should input is the myapp_cmake directory. This should automatically create the recipe myapp.bb under <crops-esdk-workdir-workspace>/recipes/myapp/myapp.bb \n\n"
+ },
+ "9": {
+ "action": " devtool build myapp \n\n",
+ "expected_results": "This should compile an image \n\n"
+ },
+ "10": {
+ "action": " devtool reset myapp ",
+ "expected_results": "This cleans sysroot of the myapp recipe, but it leaves the source tree intact. meaning it does not erase. "
+ }
+ },
+ "summary": "sdkext_devtool_build_cmake"
+ }
+ },
+ {
+ "test": {
+ "@alias": "crops-default.crops-default.sdkext_extend_autotools_recipe_creation",
+ "author": [
+ {
+ "email": "francisco.j.pedraza.gonzalez@intel.com",
+ "name": "francisco.j.pedraza.gonzalez@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "IMPORTANT NOTE: The firsts 2 steps refer to configuration of the environment to run the rest of the steps. These only apply for CROPS-eSDK. \n\n\n\n",
+ "expected_results": ""
+ },
+ "2": {
+ "action": "Initiate your Crops-esdk environment as it says in wiki https://github.com/crops/docker-win-mac-docs/wiki \n\n",
+ "expected_results": ""
+ },
+ "3": {
+ "action": " source environment-setup-i586-poky-linux \n\n",
+ "expected_results": " This should output a message that says SDK environment now set up; additionally you may now run devtool to perform development tasks etc etc ... \n\n"
+ },
+ "4": {
+ "action": "run command which devtool \n\n",
+ "expected_results": "this should output the directory of the devtool script and it should be within the sdk workdir you are working in. \n\n"
+ },
+ "5": {
+ "action": "devtool sdk-install -s libxml2 \n\n",
+ "expected_results": "this should install libxml2 \n\n"
+ },
+ "6": {
+ "action": "devtool add librdfa https://github.com/rdfa/librdfa \n\n",
+ "expected_results": "This should automatically create the recipe librdfa.bb under /recipes/librdfa/librdfa.bb \n\n"
+ },
+ "7": {
+ "action": "devtool build librdfa \n\n",
+ "expected_results": "This should compile \n\n"
+ },
+ "8": {
+ "action": "devtool reset librdfa ",
+ "expected_results": "This cleans sysroot of the librdfa recipe, but it leaves the source tree intact. meaning it does not erase."
+ }
+ },
+ "summary": "sdkext_extend_autotools_recipe_creation"
+ }
+ },
+ {
+ "test": {
+ "@alias": "crops-default.crops-default.sdkext_devtool_kernelmodule",
+ "author": [
+ {
+ "email": "francisco.j.pedraza.gonzalez@intel.com",
+ "name": "francisco.j.pedraza.gonzalez@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "IMPORTANT NOTE: The firsts 2 steps refer to configuration of the environment to run the rest of the steps. These only apply for CROPS-eSDK. \n\n\n",
+ "expected_results": ""
+ },
+ "2": {
+ "action": " Initiate your Crops-esdk environment as it says in wiki https://github.com/crops/docker-win-mac-docs/wiki \n\n",
+ "expected_results": ""
+ },
+ "3": {
+ "action": "source environment-setup-i586-poky-linux \n\n",
+ "expected_results": "This should output a message that says SDK environment now set up; additionally you may now run devtool to perform development tasks etc etc ... \n \n"
+ },
+ "4": {
+ "action": "run command which devtool \n\n",
+ "expected_results": "this should output the directory of the devtool script and it should be within the sdk workdir you are working in. \n\n"
+ },
+ "5": {
+ "action": "devtool add kernel-module-hello-world https://git.yoctoproject.org/git/kernel-module-hello-world \n\n",
+ "expected_results": "This should automatically create the recipe kernel-module-hello-world.bb under <crops-esdk-workdir-workspace>/recipes/kernel-module-hello-world/kernel-module-hello-world.bb "
+ },
+ "6": {
+ "action": "devtool build kernel-module-hello-world \n\n",
+ "expected_results": "This should compile an image \n\n"
+ },
+ "7": {
+ "action": "devtool reset kernel-module-hello-world ",
+ "expected_results": "This cleans sysroot of the kernel-module-hello-world recipe, but it leaves the source tree intact. meaning it does not erase."
+ }
+ },
+ "summary": "sdkext_devtool_kernelmodule"
+ }
+ },
+ {
+ "test": {
+ "@alias": "crops-default.crops-default.sdkext_recipes_for_nodejs",
+ "author": [
+ {
+ "email": "francisco.j.pedraza.gonzalez@intel.com",
+ "name": "francisco.j.pedraza.gonzalez@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "IMPORTANT NOTE: The firsts 2 steps refer to configuration of the environment to run the rest of the steps. These only apply for CROPS-eSDK. \n\n\nlets say variable npm = npm://registry.npmjs.org;name=winston;version=2.2.0 \n\n",
+ "expected_results": ""
+ },
+ "2": {
+ "action": "Initiate your Crops-esdk environment as it says in wiki https://github.com/crops/docker-win-mac-docs/wiki \n\n",
+ "expected_results": ""
+ },
+ "3": {
+ "action": "source environment-setup-i586-poky-linux \n\n",
+ "expected_results": "This should output a message that says SDK environment now set up; additionally you may now run devtool to perform development tasks etc etc ... \n\n"
+ },
+ "4": {
+ "action": "run command which devtool \n\n",
+ "expected_results": "this should output the directory of the devtool script and it should be within the sdk workdir you are working in. \n\n"
+ },
+ "5": {
+ "action": " 4a) git clone git://git.openembedded.org/meta-openembedded in layers/build directory \n \n4b) Add meta-openembedded/meta-oe in bblayer.conf as mentioned below: ${SDKBASEMETAPATH}/layers/build/meta-openembedded/meta-oe \\ \n\n4c) devtool add \"npm://registry.npmjs.org;name=npm;version=2.2.0\" \n\n",
+ "expected_results": " This should automatically create the recipe npm.bb under /recipes/npm/npm.bb \n\n"
+ },
+ "6": {
+ "action": "devtool build npm \n\n",
+ "expected_results": "This should compile an image \n\n"
+ },
+ "7": {
+ "action": " devtool reset npm",
+ "expected_results": "This cleans sysroot of the npm recipe, but it leaves the source tree intact. meaning it does not erase."
+ }
+ },
+ "summary": "sdkext_recipes_for_nodejs"
+ }
+ }
+]
diff --git a/meta/lib/oeqa/manual/eclipse-plugin.json b/meta/lib/oeqa/manual/eclipse-plugin.json
new file mode 100644
index 0000000000..6c110d0656
--- /dev/null
+++ b/meta/lib/oeqa/manual/eclipse-plugin.json
@@ -0,0 +1,322 @@
+[
+ {
+ "test": {
+ "@alias": "eclipse-plugin.eclipse-plugin.support_SSH_connection_to_Target",
+ "author": [
+ {
+ "email": "ee.peng.yeoh@intel.com",
+ "name": "ee.peng.yeoh@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "In Eclipse, swich to Remote System Explorer to create a connention baseed on SSH, input the remote target IP address as the Host name, make sure disable the proxy in Window->Preferences->General->Network Connection, set Direct as Active Provider field. ",
+ "expected_results": "the connection based on SSH could be set up."
+ },
+ "2": {
+ "action": "Configure connection from Eclipse: Run->Run Configurations->C/C++ Remote Application\\ ->New Connection->General->SSH Only ",
+ "expected_results": ""
+ },
+ "3": {
+ "action": "Then right click to connect, input the user ID and password. ",
+ "expected_results": ""
+ },
+ "4": {
+ "action": "expand the connection, it will show the Sftp Files etc. \nNOTE. Might need to change dropbear to openssh and add the packagegroup-core-eclipse-debug recipe",
+ "expected_results": ""
+ }
+ },
+ "summary": "support_SSH_connection_to_Target"
+ }
+ },
+ {
+ "test": {
+ "@alias": "eclipse-plugin.eclipse-plugin.Launch_QEMU_from_Eclipse",
+ "author": [
+ {
+ "email": "ee.peng.yeoh@intel.com",
+ "name": "ee.peng.yeoh@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "Set the Yocto ADT's toolchain root location, sysroot location and kernel, in the menu Window -> Preferences -> Yocto ADT. \n \n",
+ "expected_results": ""
+ },
+ "2": {
+ "action": "wget https://downloads.yoctoproject.org/releases/yocto/yocto-$VERSION/machines/qemu/qemux86/ (ex:core-image-sato-sdk-qemux86-date-rootfs-tar-bz2) \nsource /opt/poky/version/environment-setup-i585-poky-linux \n\nExtract qemu with runqemu-extract-sdk /home/user/file(ex.core-image-sato-sdk-qemux86.bz2) \n/home/user/qemux86-sato-sdk \n\n",
+ "expected_results": " Qemu can be lauched normally."
+ },
+ "3": {
+ "action": "(a)Point to the Toolchain: \n \nIf you are using a stand-alone pre-built toolchain, you should be pointing to the /opt/poky/{test-version} directory as Toolchain Root Location. This is the default location for toolchains installed by the ADT Installer or by hand. If ADT is installed in other location, use that location as Toolchain location.\nIf you are using a system-derived toolchain, the path you provide for the Toolchain Root Location field is the Yocto Project's build directory. \n \n E.g:/home/user/yocto/poky/build \n",
+ "expected_results": ""
+ },
+ "4": {
+ "action": "(b)Specify the Sysroot Location: \nSysroot Location is the location where the root filesystem for the target hardware is created on the development system by the ADT Installer (SYSROOT in step 2 of the case ADT installer Installation). \n \n Local : e.g: /home/user/qemux86-sato-sdk \nUsing ADT : e.g :/home/user/test-yocto/qemux86 \n\n",
+ "expected_results": ""
+ },
+ "5": {
+ "action": "(c)Select the Target Architecture: \n \nThe target architecture is the type of hardware you are going to use or emulate. Use the pull-down Target Architecture menu to make your selection. \n \n\n",
+ "expected_results": ""
+ },
+ "6": {
+ "action": "(d) QEMU: \nSelect this option if you will be using the QEMU emulator. Specify the Kernel matching the QEMU architecture you are using. \n wget https://downloads.yoctoproject.org/releases/yocto/yocto-$VERSION/machines/qemu/qemux86/bzImage-qemux86.bin \n e.g: /home/$USER/yocto/adt-installer/download_image/bzImage-qemux86.bin \n\n",
+ "expected_results": ""
+ },
+ "7": {
+ "action": "(e) select OK to save the settings. \n\n\n1: In the Eclipse toolbar, expose the Run -> External Tools menu. Your image should appear as a selectable menu item. \n2: Select your image in the navigation pane to launch the emulator in a new window. \n3: If needed, enter your host root password in the shell window at the prompt. This sets up a Tap 0 connection needed for running in user-space NFS mode. \n",
+ "expected_results": ""
+ }
+ },
+ "summary": "Launch_QEMU_from_Eclipse"
+ }
+ },
+ {
+ "test": {
+ "@alias": "eclipse-plugin.eclipse-plugin.Relocatable_SDK_-_C_-_Build_Hello_World_ANSI_C_Autotools_Project",
+ "author": [
+ {
+ "email": "ee.peng.yeoh@intel.com",
+ "name": "ee.peng.yeoh@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "Launch a QEMU of target environment.(Reference to case \"ADT - Launch qemu by eclipse\") ",
+ "expected_results": ""
+ },
+ "2": {
+ "action": "Select File -> New -> Project.",
+ "expected_results": ""
+ },
+ "3": {
+ "action": "Double click C/C++.",
+ "expected_results": ""
+ },
+ "4": {
+ "action": "Click C or C++ Project to create the project.",
+ "expected_results": ""
+ },
+ "5": {
+ "action": "Expand Yocto ADT Project.",
+ "expected_results": ""
+ },
+ "6": {
+ "action": "Select Hello World ANSI C Autotools Project.",
+ "expected_results": ""
+ },
+ "7": {
+ "action": "Put a name in the Project name. Do not use hyphens as part of the name. \n \n",
+ "expected_results": ""
+ },
+ "8": {
+ "action": "Click Next.",
+ "expected_results": ""
+ },
+ "9": {
+ "action": "Add information in the Author and Copyright notice fields. \n1",
+ "expected_results": ""
+ },
+ "10": {
+ "action": "Click Finish. \n1",
+ "expected_results": ""
+ },
+ "11": {
+ "action": "If the \"open perspective\" prompt appears, click \"Yes\" so that you open the C/C++ perspective. \n1",
+ "expected_results": ""
+ },
+ "12": {
+ "action": "In the Project Explorer window, right click the project -> Reconfigure project. \n1",
+ "expected_results": ""
+ },
+ "13": {
+ "action": "In the Project Explorer window, right click the project -> Build project. \n1",
+ "expected_results": "Under the Project files, a new folder appears called Binaries. This indicates that the compilation have been successful and the project binary have been created. \n"
+ },
+ "14": {
+ "action": "Right click it again and Run as -> Run Configurations. \n\t\t\tUnder Run Configurations expand \"C/C++ Remote Application\". A configuration for the current project should appear. Clicking it will display the configuration settings. \n\t\t\tin \"C/C++ Application\" field input Remote Absolute File path for C/C++ Application. e.g.: /home/root/myapplication \n\t\t\tIn \"Connection\" drop-down list make sure a TCF connection is set up for your target. If not, create a new one by clicking the New button. \n1",
+ "expected_results": "step 14 to step 16 -> Build succeed and the console outputs Hello world, you can also check the output on target."
+ },
+ "15": {
+ "action": "After all settings are done, select the Run button on the bottom right corner \n\n1",
+ "expected_results": ""
+ },
+ "16": {
+ "action": "Repeat the steps 14-15, but instead of using Run Configurations use Debug Configurations: \nRight click it again and Debug as -> Debug Configurations \nUnder Debug Configurations expand \"C/C++ Remote Application\". A configuration for the current project should appear. Clicking it will display the configuration settings. \nin \"C/C++ Application\" field input Remote Absolute File path for C/C++ Application.\ne.g.: /home/root/myapplication \nIn \"Connection\" drop-down list make sure a TCF connection is set up for your target. If not, create a new one by clicking the New button \n1",
+ "expected_results": ""
+ },
+ "17": {
+ "action": "After all settings are done, select the Debug button on the bottom right corner",
+ "expected_results": ""
+ }
+ },
+ "summary": "Relocatable_SDK_-_C_-_Build_Hello_World_ANSI_C_Autotools_Project"
+ }
+ },
+ {
+ "test": {
+ "@alias": "eclipse-plugin.eclipse-plugin.Relocatable_SDK_-_C++_-_Build_Hello_World_C++_Autotools_project",
+ "author": [
+ {
+ "email": "ee.peng.yeoh@intel.com",
+ "name": "ee.peng.yeoh@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "Launch a QEMU of target environment.(Reference to case \"ADT - Launch qemu by eclipse\") ",
+ "expected_results": ""
+ },
+ "2": {
+ "action": "Select File -> New -> Project. ",
+ "expected_results": ""
+ },
+ "3": {
+ "action": "Double click C/C++. ",
+ "expected_results": ""
+ },
+ "4": {
+ "action": "Click C or C++ Project to create the project. ",
+ "expected_results": ""
+ },
+ "5": {
+ "action": "Expand Yocto ADT Project. ",
+ "expected_results": ""
+ },
+ "6": {
+ "action": "Select Hello World ANSI C++ Autotools Project. ",
+ "expected_results": ""
+ },
+ "7": {
+ "action": "Put a name in the Project name. Do not use hyphens as part of the name. \n \n",
+ "expected_results": ""
+ },
+ "8": {
+ "action": "Click Next.",
+ "expected_results": ""
+ },
+ "9": {
+ "action": "Add information in the Author and Copyright notice fields.",
+ "expected_results": ""
+ },
+ "10": {
+ "action": "Click Finish. \n1",
+ "expected_results": ""
+ },
+ "11": {
+ "action": "If the \"open perspective\" prompt appears, click \"Yes\" so that you open the C/C++ perspective. \n1",
+ "expected_results": ""
+ },
+ "12": {
+ "action": "In the Project Explorer window, right click the project -> Reconfigure project. \n1",
+ "expected_results": ""
+ },
+ "13": {
+ "action": "In the Project Explorer window, right click the project -> Build project. \n\n1",
+ "expected_results": "under the Project files, a new folder appears called Binaries. This indicates that the compilation have been successful and the project binary have been created. \n"
+ },
+ "14": {
+ "action": "Right click it again and Run as -> Run Configurations. \n\t\t\tUnder Run Configurations expand \"C/C++ Remote Application\". A configuration for the current project should appear. Clicking it will display the configuration settings. \n\t\t\tin \"C/C++ Application\" field input Remote Absolute File path for C/C++ Application. e.g.: /home/root/myapplication \n\t\t\tIn \"Connection\" drop-down list make sure a TCF connection is set up for your target. If not, create a new one by clicking the New button. \n1",
+ "expected_results": "step 14 to step 16 -> Build succeed and the console outputs Hello world, you can also check the output on target."
+ },
+ "15": {
+ "action": "After all settings are done, select the Run button on the bottom right corner \n\n1",
+ "expected_results": ""
+ },
+ "16": {
+ "action": "Repeat the steps 14-15, but instead of using Run Configurations use Debug Configurations: \n\t\tRight click it again and Debug as -> Debug Configurations \n\t\tUnder Debug Configurations expand \"C/C++ Remote Application\". A configuration for the current project should appear. Clicking it will display the configuration settings. \n\t\tin \"C/C++ Application\" field input Remote Absolute File path for C/C++ Application. \n\t\te.g.: /home/root/myapplication \n\t\tIn \"Connection\" drop-down list make sure a TCF connection is set up for your target. If not, create a new one by clicking the New button \n1",
+ "expected_results": ""
+ },
+ "17": {
+ "action": "After all settings are done, select the Debug button on the bottom right corner",
+ "expected_results": ""
+ }
+ },
+ "summary": "Relocatable_SDK_-_C++_-_Build_Hello_World_C++_Autotools_project"
+ }
+ },
+ {
+ "test": {
+ "@alias": "eclipse-plugin.eclipse-plugin.Build_Eclipse_Plugin_from_source",
+ "author": [
+ {
+ "email": "laurentiu.serban@intel.com",
+ "name": "laurentiu.serban@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "Clone eclipse-poky source. \n \n - git clone git://git.yoctoproject.org/eclipse-poky \n\n",
+ "expected_results": "Eclipse plugin is successfully installed \n\nDocumentation is there. For example if you have release yocto-2.0.1 you will found on https://downloads.yoctoproject.org/releases/yocto/yocto-2.0.1/eclipse-plugin/mars/ archive with documentation like org.yocto.doc-development-$date.zip \n \n"
+ },
+ "2": {
+ "action": "Checkout correct tag. \n\n - git checkout <eclipse-version>/<yocto-version> \n\n",
+ "expected_results": "After plugin is build you must have 4 archive in foder scripts from eclipse-poky: \n - org.yocto.bc - mars-master-$date.zip \n - org.yocto.doc - mars-master-$date.zip --> documentation \n - org.yocto.sdk - mars-master-$date.zip \n - org.yocto.sdk - mars-master-$date.-archive.zip --> plugin "
+ },
+ "3": {
+ "action": "Move to scripts/ folder. \n\n",
+ "expected_results": ""
+ },
+ "4": {
+ "action": "Run ./setup.sh \n\n",
+ "expected_results": ""
+ },
+ "5": {
+ "action": "When the script finishes, it prompts a command to issue to build the plugin. It should look similar to the following: \n\n$ ECLIPSE_HOME=/eclipse-poky/scripts/eclipse ./build.sh /&1 | tee -a build.log \n\nHere, the three arguments to the build script are tag name, branch for documentation and release name. \n\n",
+ "expected_results": ""
+ },
+ "6": {
+ "action": "On an eclipse without the Yocto Plugin, select \"Install New Software\" from Help pull-down menu \n\n",
+ "expected_results": ""
+ },
+ "7": {
+ "action": "Select Add and from the dialog choose Archive... Look for the *archive.zip file that was built previously with the build.sh script. Click OK. \n\n",
+ "expected_results": ""
+ },
+ "8": {
+ "action": "Select all components and proceed with Installation of plugin. Restarting eclipse might be required.\n",
+ "expected_results": ""
+ }
+ },
+ "summary": "Build_Eclipse_Plugin_from_source"
+ }
+ },
+ {
+ "test": {
+ "@alias": "eclipse-plugin.eclipse-plugin.Eclipse_Poky_installation_and_setup",
+ "author": [
+ {
+ "email": "ee.peng.yeoh@intel.com",
+ "name": "ee.peng.yeoh@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "Install SDK \n\ta)Download https://autobuilder.yocto.io/pub/releases//toolchain/x86_64/poky-glibc-x86_64-core-\timage-sato-i586-toolchain-.sh \n\tb)Run the SDK installer and accept the default installation directory ",
+ "expected_results": ""
+ },
+ "2": {
+ "action": "Install \"Eclipse IDE for C/C++ Developers\" Oxygen release (4.7.0) \n\ta) Go to https://www.eclipse.org/downloads/packages/all, click \"Oxygen R\" \n\tb) Click to download the build for your OS \n\tc) Click \"Download\" button to download from a mirror \n\td) Run \"tar xf\" to extract the downloaded archive ",
+ "expected_result": ""
+ },
+ "3": {
+ "action": "Install \"Eclipse IDE for C/C++ Developers\" Oxygen release (4.7.0) (Continue) \n\te) Run \"eclipse/eclipse\" to start Eclipse \n\tf) Optional step for host machine within Intel network: In Eclipse workbench window, go to \"Window\" menu -> \"Preferences...\". \n\tg) In \"Preferences\" dialog, go to \"General\" -> \"Network Connections\", set \"Active Provider\" to \"Manual\". In \"Proxy \tentries\" table, select HTTP and click \"Edit\" and enter host \"proxy-chain.intel.com\" port 911, click OK. Repeat for HTTPS with port 912 \nClick OK to close \"Preferences\" dialog. \n\th) Go to \"File\" menu -> \"Restart\" to restart Eclipse for proxy settings to take effect. ",
+ "expected_result": ""
+ },
+ "4": {
+ "action": "Install Eclipse Poky plugins \n\ta) Download https://autobuilder.yocto.io/pub/releases/<yocto-version>/eclipse-plugin/<eclipse-version>/org.yocto.sdk-development-<date>-archive.zip \n\tb) In Eclipse workbench window, go to \"Help\" menu -> \"Install New Software...\" \n\tc) In \"Install\" dialog, click \"Add...\" button \n\td) In \"Add Repository\" dialog, enter \"Eclipse Poky\" for (repository) Name, click \"Archive...\" ",
+ "expected_results": ""
+ },
+ "5": {
+ "action": "Install Eclipse Poky plugins (continue) \n\te) In \"Repository archive\" browse dialog, select the downloaded Eclipse Poky repository archive \n\tf) Back in \"Add Repository\" dialog, click \"OK\" \n\tg) Back in \"Install\" dialog, make sure \"Work with:\" is set to \"Eclipse Poky\" repository, tick \"Yocto Project \tDocumentation Plug-in\" and \"Yocto Project SDK Plug-in\", click \"Next >\" and verify plugins/features name/version, \tclick \"Next >\" and accept license agreement, click \"Finish\" \n\th) If \"Security Warning\" dialog appears, click \"OK\" to install unsigned content. \n\ti) In \"Software Updates\" dialog, click \"Yes\" to restart Eclipse to complete Eclipse Poky plugins installation. ",
+ "expected_results": ""
+ },
+ "6": {
+ "action": "Setup Eclipse Poky to use SDK \n\ta) In Eclipse workbench window, go to \"Window\" menu -> \"Preferences\". \n\tb) In \"Preferences\" window, go to \"Yocto Project SDK\", in \"Cross Compiler Options\" frame, select \"Standalone pre-\tbuilt toolchain\". ",
+ "expected_results": "Eclipse Poky plugins installed and running successfully, e.g. observe that \"Yocto Project Tools\" menu is available on Eclipse workbench window."
+ }
+ },
+ "summary": "Eclipse_Poky_installation_and_setup"
+ }
+ }
+]
diff --git a/meta/lib/oeqa/manual/kernel-dev.json b/meta/lib/oeqa/manual/kernel-dev.json
new file mode 100644
index 0000000000..0dd99199dc
--- /dev/null
+++ b/meta/lib/oeqa/manual/kernel-dev.json
@@ -0,0 +1,200 @@
+[
+ {
+ "test": {
+ "@alias": "kernel-dev.kernel-dev.Kernel_dev_defconfig",
+ "author": [
+ {
+ "email": "ee.peng.yeoh@intel.com",
+ "name": "ee.peng.yeoh@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "Follow the Set Up procedure to complete the common and specific prerequisites for this test case. https://wiki.yoctoproject.org/wiki/Kernel_Development_Test_Cases#Setup https://wiki.yoctoproject.org/wiki/Kernel_Development_Test_Cases#Prerequisites_7 ",
+ "expected_results": ""
+ },
+ "2": {
+ "action": "Execute the test case steps asdocumented on the \"Kernel Development Test Cases\" wiki. https://wiki.yoctoproject.org/wiki/Kernel_Development_Test_Cases#Steps_7",
+ "expected_results": "Review expected results on thethe \"Kernel Development Test Cases\"wiki. https://wiki.yoctoproject.org/wiki/Kernel_Development_Test_Cases#Expected_Results_7"
+ }
+ },
+ "summary": "Kernel_dev_defconfig"
+ }
+ },
+ {
+ "test": {
+ "@alias": "kernel-dev.kernel-dev.Kernel_dev_defconfig+fragments",
+ "author": [
+ {
+ "email": "ee.peng.yeoh@intel.com",
+ "name": "ee.peng.yeoh@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "Follow the Set Up procedure to complete the common and specific prerequisites for this test case. https://wiki.yoctoproject.org/wiki/Kernel_Development_Test_Cases#Setup https://wiki.yoctoproject.org/wiki/Kernel_Development_Test_Cases#Prerequisites_8 ",
+ "expected_results": ""
+ },
+ "2": {
+ "action": "Execute the test case steps asdocumented on the \"Kernel Development Test Cases\" wiki. https://wiki.yoctoproject.org/wiki/Kernel_Development_Test_Cases#Steps_8",
+ "expected_results": "Review expected results on thethe \"Kernel Development Test Cases\"wiki. https://wiki.yoctoproject.org/wiki/Kernel_Development_Test_Cases#Expected_Results_8"
+ }
+ },
+ "summary": "Kernel_dev_defconfig+fragments"
+ }
+ },
+ {
+ "test": {
+ "@alias": "kernel-dev.kernel-dev.Kernel_dev_Applying_patches",
+ "author": [
+ {
+ "email": "ee.peng.yeoh@intel.com",
+ "name": "ee.peng.yeoh@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "Follow the Set Up procedure to complete the common and specific prerequisites for this test case. https://wiki.yoctoproject.org/wiki/Kernel_Development_Test_Cases#Setup https://wiki.yoctoproject.org/wiki/Kernel_Development_Test_Cases#Prerequisites ",
+ "expected_results": ""
+ },
+ "2": {
+ "action": "Execute the test case steps asdocumented on the \"Kernel Development Test Cases\" wiki. https://wiki.yoctoproject.org/wiki/Kernel_Development_Test_Cases#Steps",
+ "expected_results": "Review expected results on thethe \"Kernel Development Test Cases\"wiki. https://wiki.yoctoproject.org/wiki/Kernel_Development_Test_Cases#Expected_Results"
+ }
+ },
+ "summary": "Kernel_dev_Applying_patches"
+ }
+ },
+ {
+ "test": {
+ "@alias": "kernel-dev.kernel-dev.Kernel_dev_linux-yocto-local-source",
+ "author": [
+ {
+ "email": "ee.peng.yeoh@intel.com",
+ "name": "ee.peng.yeoh@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "Follow the Set Up procedure to complete the common and specific prerequisites for this test case. https://wiki.yoctoproject.org/wiki/Kernel_Development_Test_Cases#Setup https://wiki.yoctoproject.org/wiki/Kernel_Development_Test_Cases#Prerequisites_2 ",
+ "expected_results": ""
+ },
+ "2": {
+ "action": "Execute the test case steps asdocumented on the \"Kernel Development Test Cases\" wiki. https://wiki.yoctoproject.org/wiki/Kernel_Development_Test_Cases#Steps_2",
+ "expected_results": "Review expected results on thethe \"Kernel Development Test Cases\"wiki. https://wiki.yoctoproject.org/wiki/Kernel_Development_Test_Cases#Expected_Results_2"
+ }
+ },
+ "summary": "Kernel_dev_linux-yocto-local-source"
+ }
+ },
+ {
+ "test": {
+ "@alias": "kernel-dev.kernel-dev.Kernel_dev_linux-yocto-custom-local-source",
+ "author": [
+ {
+ "email": "ee.peng.yeoh@intel.com",
+ "name": "ee.peng.yeoh@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "Follow the Set Up procedure to complete the common and specific prerequisites for this test case. https://wiki.yoctoproject.org/wiki/Kernel_Development_Test_Cases#Setup https://wiki.yoctoproject.org/wiki/Kernel_Development_Test_Cases#Prerequisites_3 ",
+ "expected_results": ""
+ },
+ "2": {
+ "action": "Execute the test case steps asdocumented on the \"Kernel Development Test Cases\" wiki. https://wiki.yoctoproject.org/wiki/Kernel_Development_Test_Cases#Steps_3",
+ "expected_results": "Review expected results on thethe \"Kernel Development Test Cases\"wiki. https://wiki.yoctoproject.org/wiki/Kernel_Development_Test_Cases#Expected_Results_3"
+ }
+ },
+ "summary": "Kernel_dev_linux-yocto-custom-local-source"
+ }
+ },
+ {
+ "test": {
+ "@alias": "kernel-dev.kernel-dev.Kernel_dev_recipe-space_meta",
+ "author": [
+ {
+ "email": "ee.peng.yeoh@intel.com",
+ "name": "ee.peng.yeoh@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "Follow the Set Up procedure to complete the common and specific prerequisites for this test case. https://wiki.yoctoproject.org/wiki/Kernel_Development_Test_Cases#Setup https://wiki.yoctoproject.org/wiki/Kernel_Development_Test_Cases#Prerequisites_5 ",
+ "expected_results": ""
+ },
+ "2": {
+ "action": "Execute the test case steps asdocumented on the \"Kernel Development Test Cases\" wiki. https://wiki.yoctoproject.org/wiki/Kernel_Development_Test_Cases#Steps_5",
+ "expected_results": "Review expected results on thethe \"Kernel Development Test Cases\"wiki. https://wiki.yoctoproject.org/wiki/Kernel_Development_Test_Cases#Expected_Results_5"
+ }
+ },
+ "summary": "Kernel_dev_recipe-space_meta"
+ }
+ },
+ {
+ "test": {
+ "@alias": "kernel-dev.kernel-dev.Kernel_dev_External_source",
+ "author": [
+ {
+ "email": "ee.peng.yeoh@intel.com",
+ "name": "ee.peng.yeoh@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "Follow the Set Up procedure to complete the common and specific prerequisites for this test case. https://wiki.yoctoproject.org/wiki/Kernel_Development_Test_Cases#Setup https://wiki.yoctoproject.org/wiki/Kernel_Development_Test_Cases#Prerequisites_6 ",
+ "expected_results": ""
+ },
+ "2": {
+ "action": "Execute the test case steps asdocumented on the \"Kernel Development Test Cases\" wiki. https://wiki.yoctoproject.org/wiki/Kernel_Development_Test_Cases#Steps_6",
+ "expected_results": "Review expected results on thethe \"Kernel Development Test Cases\"wiki. https://wiki.yoctoproject.org/wiki/Kernel_Development_Test_Cases#Expected_Results_6"
+ }
+ },
+ "summary": "Kernel_dev_External_source"
+ }
+ },
+ {
+ "test": {
+ "@alias": "kernel-dev.kernel-dev.Kernel_dev_building_external_modules(hello-mod)",
+ "author": [
+ {
+ "email": "ee.peng.yeoh@intel.com",
+ "name": "ee.peng.yeoh@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "Follow the Set Up procedure to complete the common and specific prerequisites for this test case. https://wiki.yoctoproject.org/wiki/Kernel_Development_Test_Cases#Setup https://wiki.yoctoproject.org/wiki/Kernel_Development_Test_Cases#Prerequisites_10 ",
+ "expected_results": ""
+ },
+ "2": {
+ "action": "Execute the test case steps asdocumented on the \"Kernel Development Test Cases\" wiki. https://wiki.yoctoproject.org/wiki/Kernel_Development_Test_Cases#Setup_10",
+ "expected_results": "Review expected results on thethe \"Kernel Development Test Cases\"wiki. https://wiki.yoctoproject.org/wiki/Kernel_Development_Test_Cases#Expected_Results_10"
+ }
+ },
+ "summary": "Kernel_dev_building_external_modules(hello-mod)"
+ }
+ },
+ {
+ "test": {
+ "@alias": "kernel-dev.kernel-dev.Kernel_dev_local_parallel_meta",
+ "author": [
+ {
+ "email": "ee.peng.yeoh@intel.com",
+ "name": "ee.peng.yeoh@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "Follow the Set Up procedure to complete the common and specific prerequisites for this test case. https://wiki.yoctoproject.org/wiki/Kernel_Development_Test_Cases#Setup https://wikioproject.org/wiki/Kernel_Development_Test_Cases#Prerequisites_4 ",
+ "expected_results": ""
+ },
+ "2": {
+ "action": "Execute the test case steps asdocumented on the \"Kernel Development Test Cases\" wiki. https://wiki.yoctoproject.org/wiki/Kernel_Development_Test_Cases#Steps_4",
+ "expected_results": "Review expected results on thethe \"Kernel Development Test Cases\"wiki. https://wiki.yoctoproject.org/wiki/Kernel_Development_Test_Cases#Expected_Results_4"
+ }
+ },
+ "summary": "Kernel_dev_local_parallel_meta"
+ }
+ }
+] \ No newline at end of file
diff --git a/meta/lib/oeqa/manual/oe-core.json b/meta/lib/oeqa/manual/oe-core.json
new file mode 100644
index 0000000000..4ad524d89b
--- /dev/null
+++ b/meta/lib/oeqa/manual/oe-core.json
@@ -0,0 +1,158 @@
+[
+ {
+ "test": {
+ "@alias": "oe-core.bitbake.Test_bitbake_menuconfig",
+ "author": [
+ {
+ "email": "jose.perez.carranza@intel.com",
+ "name": "jose.perez.carranza@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "clone poky \n \n",
+ "expected_results": ""
+ },
+ "2": {
+ "action": "cd poky \n\n",
+ "expected_results": ""
+ },
+ "3": {
+ "action": "source oe-init-build-env && cd build \n\n",
+ "expected_results": ""
+ },
+ "4": {
+ "action": "set below in local.conf \n\n \tMACHINE = \"qemux86\" \n\n",
+ "expected_results": ""
+ },
+ "5": {
+ "action": "bitbake linux-yocto -c kernel_configme -f \n\n",
+ "expected_results": ""
+ },
+ "6": {
+ "action": "bitbake linux-yocto -c menuconfig \n\n",
+ "expected_results": ""
+ },
+ "7": {
+ "action": "Once menuconfig launches, use the interface to navigate through the selections and \n enable option \"64-bit kernel\" \n\n",
+ "expected_results": ""
+ },
+ "8": {
+ "action": "Save changes and set name of the file as \"test.config\" ",
+ "expected_results": "Open file: \n \npoky/build//tmp/work/qemux86-poky-linux/linux-yocto/4.X.X+*/linux-qemux86-standard-build/test.config \n \n \n\nand verify that changes are present in the file as follows: \n \nCONFIG_64BIT=y \n \nCONFIG_X86_64=y"
+ }
+ },
+ "summary": "Test_bitbake_menuconfig"
+ }
+ },
+ {
+ "test": {
+ "@alias": "oe-core.bitbake.test_bitbake_devshell",
+ "author": [
+ {
+ "email": "jose.perez.carranza@intel.com",
+ "name": "jose.perez.carranza@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "clone poky ",
+ "expected_results": ""
+ },
+ "2": {
+ "action": "cd poky ",
+ "expected_results": ""
+ },
+ "3": {
+ "action": "source oe-init-build-env && cd build ",
+ "expected_results": ""
+ },
+ "4": {
+ "action": "bitbake matchbox-desktop ",
+ "expected_results": "Package was build correctly "
+ },
+ "5": {
+ "action": "bitbake matchbox-desktop -c devshell ",
+ "expected_results": "A terminal with a shell prompt within the OpenEmbedded build environment is opened "
+ },
+ "6": {
+ "action": "Verify that \"matchbox-desktop\" binary file is not created under\"src\" directory ",
+ "expected_results": ""
+ },
+ "7": {
+ "action": "Run command:./configure ${CONFIGUREOPTS} && make ",
+ "expected_results": "Verify that \"matchbox-desktop\" binary file was created successfully under \"src/\" directory "
+ },
+ "8": {
+ "action": "Exit fromthe devshell terminal,exit ",
+ "expected_results": "Terminal back to the build directory"
+ }
+ },
+ "summary": "test_bitbake_devshell"
+ }
+ },
+ {
+ "test": {
+ "@alias": "oe-core.bitbake.test_dependency_explorer_is_launched",
+ "author": [
+ {
+ "email": "jose.perez.carranza@intel.com",
+ "name": "jose.perez.carranza@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "clone poky ",
+ "expected_results": ""
+ },
+ "2": {
+ "action": "cd poky ",
+ "expected_results": ""
+ },
+ "3": {
+ "action": "source oe-init-build-env ",
+ "expected_results": ""
+ },
+ "4": {
+ "action": "bitbake -u taskexp -g core-image-full-cmdline \n\nNOTE: To execute the last command of this test, it's necessary that the machine is executing an X11 server, or if that's not the case (for example, if running the test on a headless server), it is required to enable ssh X11 forwarding on both, the server and the client, and have the X11 server running on the client. \n\nThe instructions to enable X11 forwarding vary between distributions. But for example, these are the steps to enable it between a server running openSUSE Leap 42.1 and a client with Fedora 24: \nA. On the server, make sure /home//.ssh/config contains the line: \n ForwardX11 yes \nB. On the server, make sure xauth is installed by running: \n which xauth \nC. On the client, connect to the server, enabling X11 forwarding, for example by using: \n ssh -X user@server \nNOTE 2: depexp was renamed to taskexp on 2.3 M4",
+ "expected_results": "Verify that a \"dependency explorer\" is opened and file \n dependencies are listed "
+ }
+ },
+ "summary": "test_dependency_explorer_is_launched"
+ }
+ },
+ {
+ "test": {
+ "@alias": "oe-core.bitbake.test_bitbake_sane_error_for_invalid_layer",
+ "author": [
+ {
+ "email": "jose.perez.carranza@intel.com",
+ "name": "jose.perez.carranza@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "clone poky \n",
+ "expected_results": ""
+ },
+ "2": {
+ "action": "cd poky \n \n",
+ "expected_results": ""
+ },
+ "3": {
+ "action": "source oe-init-build-env && cd build \n \n",
+ "expected_results": ""
+ },
+ "4": {
+ "action": "Add a invalid layer to conf/bblayers.conf \"<poky dir>/my-invalid-layer\" \n\t\n",
+ "expected_results": ""
+ },
+ "5": {
+ "action": "bitbake core-image-minimal",
+ "expected_results": "Below error should be displayed:\n\"ERROR: Layer directory does not exist! Please check BBLAYERS in <poky dir>/<build dir>/conf/bblayers.conf\""
+ }
+ },
+ "summary": "test_bitbake_sane_error_for_invalid_layer"
+ }
+ }
+]
diff --git a/meta/lib/oeqa/manual/sdk.json b/meta/lib/oeqa/manual/sdk.json
new file mode 100644
index 0000000000..21d892d26d
--- /dev/null
+++ b/meta/lib/oeqa/manual/sdk.json
@@ -0,0 +1,32 @@
+[
+ {
+ "test": {
+ "@alias": "sdk.sdk_runqemu.test_install_cross_toolchain_can_run_multiple_qemu_for_x86",
+ "author": [
+ {
+ "email": "ee.peng.yeoh@intel.com",
+ "name": "ee.peng.yeoh@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "Prepare kernel, rootfs tar.bz2 image, and qemu configuration \n \ta. Download kernel, rootfs tar.bz2 image and qemu configuration from public autobuilder webpage \n \tb. Goto https://autobuilder.yocto.io/pub/releases/<target_release>/machines/qemu/qemux86/ \n \tc. Download \n \t \ti. rootfs tar.bz2: core-image-sato-sdk-qemux86.tar.bz2 \n \t\tii. kernel: bzImage-qemux86.bin \n \t\tiii. qemu configuration: core-image-sato-sdk-qemux86.qemuboot.conf ",
+ "expected_results": "Download completes successfully."
+ },
+ "2": {
+ "action": "Download & install toolchain tarball matching your host from public autobuilder \n \ta. Goto https://autobuilder.yocto.io/pub/releases/<target_release>/toolchain/x86_64/ \n \tb. Download poky-glibc-x86_64-core-image-sato-<type-arch>-toolchain-<release-version>.sh \n \tc. Run command: poky-glibc-x86_64-core-image-sato-<type-arch>-toolchain-<release-version>.sh \n \td. After installation toolchain Run source command : source /toolchain-installed-path/environment-setup-<architecture name>-poky-linux",
+ "expected_results": "Toolchain gets installed successfully."
+ },
+ "3": {
+ "action": "Extract rootfs twice into two images \n \ta. Run 2 commands below: \n runqemu-extract-sdk core-image-sato-sdk-qemux86.tar.bz2 qemux86_rootfs_image1 \n runqemu-extract-sdk core-image-sato-sdk-qemux86.tar.bz2 qemux86_rootfs_image2",
+ "expected_results": "Both images build successfully."
+ },
+ "4": {
+ "action": " From the 2 terminals, start qemu to boot up both two images \n \ta. Run 2 commands below: \n runqemu <kernel-name> core-image-sato-sdk-qemux86.qemuboot.conf qemux86_rootfs_image1 \n runqemu <kernel-name> core-image-sato-sdk-qemux86.qemuboot.conf qemux86_rootfs_image2 ",
+ "expected_results": "Expect both qemu to boot up successfully."
+ }
+ },
+ "summary": "test_install_cross_toolchain_can_run_multiple_qemu_for:x86"
+ }
+ }
+] \ No newline at end of file
diff --git a/meta/lib/oeqa/manual/toaster-managed-mode.json b/meta/lib/oeqa/manual/toaster-managed-mode.json
new file mode 100644
index 0000000000..1a71985c3c
--- /dev/null
+++ b/meta/lib/oeqa/manual/toaster-managed-mode.json
@@ -0,0 +1,2572 @@
+[
+ {
+ "test": {
+ "@alias": "toaster-managed-mode.toaster-managed.All_layers:_default_view",
+ "author": [
+ {
+ "email": "stanciux.mihail@intel.com",
+ "name": "stanciux.mihail@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": " Access a project page, either by creating a new project or accessing an existing project from the \"All builds\" table.",
+ "expected_results": ""
+ },
+ "2": {
+ "action": "On the project page click on the \"View compatible layers\" link situated on the right-hand side, mid-page, under the \"Project configuration\" menu, in the \"Layers\" table.",
+ "expected_results": ""
+ },
+ "3": {
+ "action": "Check that the table is populated with the default layers (eg. meta-yocto-bsp, meta-yocto)",
+ "expected_results": ""
+ },
+ "4": {
+ "action": "Check that by default the following columns are shown: Layer, Summary, Revision, Dependencies and Add/Delete",
+ "expected_results": ""
+ },
+ "5": {
+ "action": "Check that the \"Revision\" entries match the release entry from the main project page, in the project details section.",
+ "expected_results": ""
+ },
+ "6": {
+ "action": "Check that only one instance of the core layers (openembedded-core, meta-yocto and meta-yocto-bsp) shows in this table, and that instance has a branch that matches the selected project release from the main project page.",
+ "expected_results": ""
+ },
+ "7": {
+ "action": "Check that in the \"Dependencies\" column some of the layers should have a square box with a number in it. When clicking on it, a small popup should appear containing a list of other layers required for this layer to work. Every layer listed here should also be a link to the layer's detail page. \n \n",
+ "expected_results": ""
+ },
+ "8": {
+ "action": "From the \"Edit columns\" menu, activate the \"Git repository URL\" and the \"Subdirectory\" columns. In \"Git repository URL\": all the entries should have a link to the external site where the layer was downloaded from. Similarly, in \"Subdirectory\" links should exist, if a subdirectory entry is present.",
+ "expected_results": "All mentioned elements should be present and functional."
+ }
+ },
+ "summary": "All_layers:_default_view"
+ }
+ },
+ {
+ "test": {
+ "@alias": "toaster-managed-mode.toaster-managed.All_layers:_Add/delete_layers",
+ "author": [
+ {
+ "email": "stanciux.mihail@intel.com",
+ "name": "stanciux.mihail@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": " Access a project page, either by creating a new project or accessing an existing project from the \"All builds\" table. \n\n\n",
+ "expected_results": ""
+ },
+ "2": {
+ "action": "On the project page click on the \"View compatible layers\" link situated on the right-hand side, mid-page, under the \"Project configuration\" menus, in the \"Layers\" table. \n\n\n",
+ "expected_results": ""
+ },
+ "3": {
+ "action": "Check that the Add/delete column is enabled. \n\n",
+ "expected_results": ""
+ },
+ "4": {
+ "action": "Add a new layer \nPick a layer that hasn't been added to the project. \n \nClick on the \"Add layer\" button present in the \"Add/delete\" column. \nIf the layer has unsatisfied dependencies a dialog will appear listing the dependencies (in alphabetical order), each of them with a checkbox so that you can select / deselect them. All checkboxes are checked by default. If you click the \"Cancel\" button the dialog closes. If you click the \"Add layers\" button, the layers are added to the project. \n\nMake sure to uncheck at least 1 of the dependencies so you can check that only the checked dependencies are added, and not the unchecked one(s). ",
+ "expected_results": ""
+ },
+ "5": {
+ "action": "Check that the \"Add layer\" button fades out and is replaced temporarily by a message like \"1 layer added\" and then it is replaced by the \"Delete layer\" button. \nCheck that a confirmation message is displayed at the top of the page similar to \"You have added 1 layer to project_name_here: meta-yocto-bsp\". \n\n",
+ "expected_results": ""
+ },
+ "6": {
+ "action": "Delete an existing layer \nPick a layer that's already been added to the project. \nClick on the \"Delete layer\" button present in the \"Add/delete\" column. \nCheck that once the button is pressed, it fades out and is replaced temporarily by the message \"1 layer deleted\" and then it is replaced by the \"Add layer\" button. \nCheck that a confirmation is displayed at the top of the page similar to \"You have deleted 1 layer from project_name_here: meta-yocto-bsp\". ",
+ "expected_results": "All actions should complete successfully."
+ }
+ },
+ "summary": "All_layers:_Add/delete_layers"
+ }
+ },
+ {
+ "test": {
+ "@alias": "toaster-managed-mode.toaster-managed.All_targets:_Default_view",
+ "author": [
+ {
+ "email": "stanciux.mihail@intel.com",
+ "name": "stanciux.mihail@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": " Access a project page, either by creating a new project or accessing an existing project from the \"All builds\" table. \n\n",
+ "expected_results": ""
+ },
+ "2": {
+ "action": " If no images exist in the project, build an image by inserting \"core-image-minimal\" in the \"Recipes\" field and press the \"Build\" button. Wait for the image to finish building. \n\n",
+ "expected_results": ""
+ },
+ "3": {
+ "action": "On the project page click on the \"Image Recipes\" link situated in the left-handed side of the page, under the \"Project configuration\" menus, in the \"COMPATIBLE METADATA\" table. \n\n",
+ "expected_results": ""
+ },
+ "4": {
+ "action": "Check that \"Compatible image recipes\" table is populated. \n\n",
+ "expected_results": ""
+ },
+ "5": {
+ "action": "Check that the following columns are shown by default: \n\t\tImage recipe \n\t\tDescription \n \n\t\tLayer \n\t\tBuild \n\t\t Version ",
+ "expected_results": ""
+ }
+ },
+ "summary": "All_targets:_Default_view"
+ }
+ },
+ {
+ "test": {
+ "@alias": "toaster-managed-mode.toaster-managed.Configuration_variables:_default_view",
+ "author": [
+ {
+ "email": "stanciux.mihail@intel.com",
+ "name": "stanciux.mihail@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": " Access a project page, either by creating a new project or accessing an existing project from the \"All builds\" table. \n\n\n",
+ "expected_results": ""
+ },
+ "2": {
+ "action": "In the main project page, click on \"BitBake variables\" in the left-hand side of the page, under the \"CONFIGURATION\" menu. \n\n",
+ "expected_results": ""
+ },
+ "3": {
+ "action": "Check that default values are as follows: \n\tDISTRO - poky \n\tIMAGE_FSTYPES - ext3 jffs2 tar.bz2 \n\tIMAGE_INSTALL:append - \"Not set\" \n\tPACKAGE_CLASSES - package_rpm \n SSTATE_DIR - /homeDirectory/poky/sstate-cache \n\n",
+ "expected_results": ""
+ },
+ "4": {
+ "action": "Check that under the \"Add variable\" section, the \"Variable\" field has the default text \"Type variable name\" present, the \"Value\" field has the default text \"Type variable value\" present and that the \"Add variable\" button is inactive. \n\n",
+ "expected_results": ""
+ },
+ "5": {
+ "action": "Check that under the \"Add variable\" section, there is text present that describes the variables that Toaster cannot modify. ",
+ "expected_results": "All mentioned elements should be present and functional."
+ }
+ },
+ "summary": "Configuration_variables:_default_view"
+ }
+ },
+ {
+ "test": {
+ "@alias": "toaster-managed-mode.toaster-managed.Configuration_variables:_Test_UI_elements",
+ "author": [
+ {
+ "email": "stanciux.mihail@intel.com",
+ "name": "stanciux.mihail@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": " Access a project page, either by creating a new project or accessing an existing project from the \"All builds\" table. \n\n",
+ "expected_results": ""
+ },
+ "2": {
+ "action": "In the main project page, click on \"BitBake variables\" in the left-hand side of the page, under the \"CONFIGURATION\" menu. \n\n",
+ "expected_results": ""
+ },
+ "3": {
+ "action": "DISTRO: \n\t- check that the \"change\" icon is present (represented by a pen icon) \n\t- click on the \"change\" icon and check that the variable becomes an editable text field, populated with the current value of the variable \n\t- check that, if you delete the content of the text field, the save button is disabled \n\t- enter a distro name containing spaces (for example, \"poky tiny\") - check that an error message is shown explaining that the value entered cannot contain spaces \n\n",
+ "expected_results": ""
+ },
+ "4": {
+ "action": "IMAGE_FSTYPES: \n\t- check that the \"change\" icon is present (represented by a pen icon) \n\t- click on the \"change\" icon and check that the variable becomes editable like so: the main input control is a set of checkboxes. There is a checkbox for each supported image type. The checkboxes are listed in ascending alphabetical order, broken down in 2 groups: \n\t\t",
+ "expected_results": ""
+ },
+ "5": {
+ "action": "The selected types are checked and listed at the top \n\t\t",
+ "expected_results": ""
+ },
+ "6": {
+ "action": "The other types are not checked and listed afterwards \n\t- check that all this is inside a scrollable div, and a text field is present above that filters out the content of the div as you type. \n\t- check that if there are no image types matching your typed string, a message is shown notifying you of this: \"No image types found\" \n\t- unselect all checkboxes and check that the save button is disabled and a message is shown: \"You must select at least one image type\" \n\t- select different checkboxes and hit save then make sure that the \tsaved value is consistent with the selected checkboxes \n\n",
+ "expected_results": ""
+ },
+ "7": {
+ "action": "IMAGE_INSTALL:append: \n\t- check that the \"change\" icon is present (represented by a pen icon) \n\t- click on the \"change\" icon and check that the variable becomes a text field, populated with the current value of the variable. \n\n\t- check that the save button is disabled when the text field is empty \n\t- insert test in the text field (for example \"package1\") and hit save; be aware that there is no input validation for this variable \n\t- check that a new \"delete\" icon(a trashcan) has appeared next to the pen icon \n\t- check that clicking on the trashcan icon resets the value to \"Not set\" and makes the trashcan icon dissapear \n\n",
+ "expected_results": ""
+ },
+ "8": {
+ "action": "PACKAGE_CLASSES: \n\t- check that the \"change\" icon is present (represented by a pen icon) \n\t- click on the \"change\" icon and check that the variable becomes editable with the following components: \n\t\t",
+ "expected_results": ""
+ },
+ "9": {
+ "action": "A dropdown menu with values 'package_dev', 'package_ipk' and 'package_rpm' in this order. The value selected when you enter the editable state matches the first value of the variable (e.g. if the value is set to 'package_dev package_ipk' the value selected is 'package_dev'). \n \n\t\t",
+ "expected_results": ""
+ },
+ "10": {
+ "action": "Two checkboxes, showing the 2 unselected values in the dropdown menu. \n\n\t- verify that the checkboxes are checked or unchecked to reflect the variable value (e.g. if the value is set to 'package_dev package_ipk', the 'package_ipk' checkbox is checked, and the 'package_rpm' checkbox is unchecked). \n\n\tBoth checkboxes can be unchecked. The value of the checkboxes changes dynamically as I change the selected value in the dropdown menu. This means that any changes to the dropdown menu should uncheck the checkboxes. \n\n\t- click on save and check that the value selected in the dropdown menu is the first value in the variable, followed by any checked checkboxes. \n\n\n",
+ "expected_results": ""
+ },
+ "11": {
+ "action": "Adding variables: \n\t- check that the \"add variable\" form has 2 text fields: one for the variable name and a second one for the variable value, plus an \"add\" button that is disabled until both text fields have some input in them. \n \n\t- check variable name validation: variable names cannot have spaces, and can only include letters, numbers, underscores and dashes; variable names entered cannot match the name of a variable already on the list; variable names cannot match the blacklisted variables mentioned in the text on the right-hand side of the page \n\n\t - check that an error message is shown indicating validation has failed and why once you try to put in the value or click on the \"Add variable\" button ",
+ "expected_results": "All mentioned elements should be present and functional."
+ },
+ "12": {
+ "action": "insert a valid combination and click on \"Add variable\"; check that a new variable/value pair is added at the bottom of the variable list and that the text fields in the \"add variable\" form are cleared and the \"add\" button is disabled \n\t- check that the added variable has a \"change\" icon present next to the variable value, and also that a \"delete\" icon is present next to the variable name \n\t- check that clicking the \"change\" icon makes the variable editable in a text field containing the value of the variable \n\t- check that, if you delete the content of the text field, the save button is\tdisabled\n\t- check that clicking on the \"delete\" button causes both the variable name and the variable value to be removed from the variables list",
+ "expected_results": "All mentioned elements should be present and functional."
+ }
+ },
+ "summary": "Configuration_variables:_Test_UI_elements"
+ }
+ },
+ {
+ "test": {
+ "@alias": "toaster-managed-mode.toaster-managed.Project_builds:_Default_view",
+ "author": [
+ {
+ "email": "stanciux.mihail@intel.com",
+ "name": "stanciux.mihail@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": " Access a project page, either by creating a new project or accessing an existing project from the \"All builds\" table. \n\n",
+ "expected_results": ""
+ },
+ "2": {
+ "action": "Click on the \"Builds\" , next to the \"Configuration\" Button. \n\n",
+ "expected_results": ""
+ },
+ "3": {
+ "action": "Check that the page heading includes a counter with the number of builds run for the project(eg. \"Project builds (4)\"). \n\n",
+ "expected_results": ""
+ },
+ "4": {
+ "action": "Check that the following table heads are visible by default: outcome, completed on, failed tasks, errors, warnings, image files. \n\n",
+ "expected_results": ""
+ },
+ "5": {
+ "action": "Check that by default the table is sorted by \"Completed on\" in descending order",
+ "expected_results": "All mentioned elements should be present."
+ }
+ },
+ "summary": "Project_builds:_Default_view"
+ }
+ },
+ {
+ "test": {
+ "@alias": "toaster-managed-mode.toaster-managed.Project_builds:_Sorting_the_project_builds_table",
+ "author": [
+ {
+ "email": "stanciux.mihail@intel.com",
+ "name": "stanciux.mihail@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": " Access a project page, either by creating a new project or accessing an existing project from the \"All builds\" table. \n\n",
+ "expected_results": ""
+ },
+ "2": {
+ "action": "Click on the \"View all project builds\" link situated below the top-most \"Build\" button and text field, next to the \"View all targets\" link \n\n\n",
+ "expected_results": ""
+ },
+ "3": {
+ "action": "Verify that, by default, the table is sorted by \"Completed on\" in descending order. \n\n",
+ "expected_results": ""
+ },
+ "4": {
+ "action": "Activate all columns from the \"Edit columns\" table. \n\n",
+ "expected_results": ""
+ },
+ "5": {
+ "action": "Check that the following columns are sortable, both in ascending and descending order: outcome, target, machine, started on, completed on, warning, project \n\n",
+ "expected_results": ""
+ },
+ "6": {
+ "action": "Verify that hiding a column that is currently being used as the sorting criteria causes the sorting to reset to the default - i.e \"Completed on\" in descending order.",
+ "expected_results": "All mentioned elements should be present and functional."
+ }
+ },
+ "summary": "Project_builds:_Sorting_the_project_builds_table"
+ }
+ },
+ {
+ "test": {
+ "@alias": "toaster-managed-mode.toaster-managed.Project_builds:_customize_the_columns_of_the_table",
+ "author": [
+ {
+ "email": "stanciux.mihail@intel.com",
+ "name": "stanciux.mihail@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": " Access a project page, either by creating a new project or accessing an existing project from the \"All builds\" table. \n\n",
+ "expected_results": ""
+ },
+ "2": {
+ "action": "Click on the \"View all project builds\" link situated below the top-most \"Build\" button and text field, next to the \"View all targets\" link \n\n",
+ "expected_results": ""
+ },
+ "3": {
+ "action": "Click on the \"Edit column\" menu and check that the selected columns match the columns currently being shown. \n\n",
+ "expected_results": ""
+ },
+ "4": {
+ "action": "Check that the following columns cannot be removed from the shown columns: completed on, outcome, recipe \n\n",
+ "expected_results": ""
+ },
+ "5": {
+ "action": "Check that unchecked items changed to checked immediately appear in the table and that checked items changed to unchecked immediately disappear from the table.",
+ "expected_results": "All mentioned elements should be present and functional."
+ }
+ },
+ "summary": "Project_builds:_customize_the_columns_of_the_table"
+ }
+ },
+ {
+ "test": {
+ "@alias": "toaster-managed-mode.toaster-managed.Project_builds:_filter_the_contents_of_the_table",
+ "author": [
+ {
+ "email": "stanciux.mihail@intel.com",
+ "name": "stanciux.mihail@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": " Access a project page, either by creating a new project or accessing an existing project from the \"All builds\" table. \n\n",
+ "expected_results": ""
+ },
+ "2": {
+ "action": "Click on the \"View all project builds\" link situated below the top-most \"Build\" button and text field, next to the \"View all targets\" link. \n\n",
+ "expected_results": ""
+ },
+ "3": {
+ "action": "Make sure the following columns have filters: outcome, started on, completed on, failed tasks. \n\n",
+ "expected_results": ""
+ },
+ "4": {
+ "action": "Filters are mutually exclusive. Click a filter button of a one column and a filter dialogue occurs. Select a filter item. The filter result would be showed. Then select another filter item of another column and the previously applied filter is overridden by the newly selected filter when a filter from a different column is applied to the table. This filter will override the current filter.\" \n\n",
+ "expected_results": ""
+ },
+ "5": {
+ "action": "Filters are overridden by search. Run a search query and you can see previous filter results are overridden by the results of the search query.",
+ "expected_results": "All mentioned elements should be present and functional."
+ }
+ },
+ "summary": "Project_builds:_filter_the_contents_of_the_table"
+ }
+ },
+ {
+ "test": {
+ "@alias": "toaster-managed-mode.toaster-managed.Project_builds:_search_the_contents_of_the_table",
+ "author": [
+ {
+ "email": "stanciux.mihail@intel.com",
+ "name": "stanciux.mihail@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": " Access a project page, either by creating a new project or accessing an existing project from the \"All builds\" table. \n\n\n",
+ "expected_results": ""
+ },
+ "2": {
+ "action": "Click on the \"View all project builds\" link situated below the top-most \"Build\" button and text field, next to the \"View all targets\" link. \n\n",
+ "expected_results": ""
+ },
+ "3": {
+ "action": "When no search query has been entered, we have placeholder text saying: \"Search builds\". The placeholder text disappears when the first character is typed. \n\n",
+ "expected_results": ""
+ },
+ "4": {
+ "action": "When a search query has been submitted and results returned: \n- We keep the search string in the text input field. \n- We provide a \"Clear search\" icon (icon-remove-sign). Click it to clear the search and display all packages. \n- We change the page heading to indicate the number of results returned by the search query. \n\n",
+ "expected_results": ""
+ },
+ "5": {
+ "action": "If your search query returns no results, the page heading changes to \"No packages found\", and we show you an alert with a search form and an option to show all packages. \n\n",
+ "expected_results": ""
+ },
+ "6": {
+ "action": "Searching does not change the state of the table: the same columns remain hidden and the same sorting applied. ",
+ "expected_results": "All mentioned elements should be present and functional."
+ }
+ },
+ "summary": "Project_builds:_search_the_contents_of_the_table"
+ }
+ },
+ {
+ "test": {
+ "@alias": "toaster-managed-mode.toaster-managed.Layer_details_page:_Default_view",
+ "author": [
+ {
+ "email": "stanciux.mihail@intel.com",
+ "name": "stanciux.mihail@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": " Access a project page, either by creating a new project or accessing an existing project from the \"All builds\" table. \n\n",
+ "expected_results": ""
+ },
+ "2": {
+ "action": "Click on the \"View compatible layers\" link situated in the \"Project configuration\" portion of the page, under \"Layers\" table. \n\n",
+ "expected_results": ""
+ },
+ "3": {
+ "action": "Click on a layer (for example \"meta-aarch64\"). Notice that the page is divided into 2 columns: the left one is broken down into tabs; the right one provides information about the layer. \n\n",
+ "expected_results": ""
+ },
+ "4": {
+ "action": "Check that breadcrumbs exist at the top of the page. Check that they work by clicking on them, then hitting back to return to the layer detail page. \n\n",
+ "expected_results": ""
+ },
+ "5": {
+ "action": "Check that the page heading includes the layer branch name - it should look something like meta-aarch64(dizzy) if the dizzy branch was selected. The branch name should also be present in the breadcrumbs. \n\n",
+ "expected_results": ""
+ },
+ "6": {
+ "action": "The \"About\" information: \nit shows summary, description in this order, if not empty. If an information item is empty (like the Summary in the example shown in this page), it does not display. \n \n\n",
+ "expected_results": ""
+ },
+ "7": {
+ "action": "The tabs: \nCheck that there are 3 tabs: \"layer details\", \"recipes\", \"machines\" showing up in this order. \n\n",
+ "expected_results": ""
+ },
+ "8": {
+ "action": "\"Layer details\" tab: \nCheck that the tab shows: \n- A button to add / remove the layer to / from the project. In this tab, the button labels are\"Add the $layer_name layer to your project\" \"Delete the $layer_name layer from your project\" \n- Some details about the layer: repository URL, repository subdirectory, revision (the branch) and the list of layer dependencies. If any of the above details is blank (most likely, the subdirectory) it does not display.The icons next to the repository and subdirectory information are links to their web instances. Those links should open in a new window. \n\n",
+ "expected_results": ""
+ },
+ "9": {
+ "action": "The \"Recipes\" tab: \nCheck that it shows: \n\t",
+ "expected_results": ""
+ },
+ "10": {
+ "action": "A counter in the tab label showing the total number of targets provided by the layer \n\t",
+ "expected_results": ""
+ },
+ "11": {
+ "action": "A button to add / remove the layer to / from the project. In this tab, the button labels are \"Add the $layer_name layer to your project to enable these targets\"/\"Delete the $layer_name layer from your project\" \n\t",
+ "expected_results": ""
+ },
+ "12": {
+ "action": "A recipes table with the following columns: \n \n- Recipe \n- Description: the value of the DESCRIPTION variable. If not set, then the value of the SUMMARY variable. \n- Build recipe, which shows a \"build recipe\" button. The \"build recipe\" button is disabled when the layer is not added to the project. \n\nThe recipes table is sorted by \"Recipe\" in ascending alphabetical order. \n\n1",
+ "expected_results": ""
+ },
+ "13": {
+ "action": "The \"Machines\" tab: \n\t",
+ "expected_results": ""
+ },
+ "14": {
+ "action": "A counter in the tab label showing the total number of machines provided by the layer \n\t",
+ "expected_results": ""
+ },
+ "15": {
+ "action": "A button to add/remove the layer to/from the project. In this tab, the button labels are \"Add the $layer_name layer to your project to enable these machines\"/\"Delete the $layer_name layer from your project\" \n\t",
+ "expected_results": ""
+ },
+ "16": {
+ "action": "A machines table with the following columns: \n \n- Machine. \n \n- Description: The value of the DESCRIPTION variable in the .conf file \n- Select machine, which shows a \"select\" button. The \"select\" button is disabled when the layer is not added to the project. \nThe machines table is sorted by \"Machine\" in ascending alphabetical order. \n",
+ "expected_results": "All mentioned elements should be present and functional."
+ }
+ },
+ "summary": "Layer_details_page:_Default_view"
+ }
+ },
+ {
+ "test": {
+ "@alias": "toaster-managed-mode.toaster-managed.Layer_details_page:_UI_functionality",
+ "author": [
+ {
+ "email": "stanciux.mihail@intel.com",
+ "name": "stanciux.mihail@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": " Access a project page, either by creating a new project or accessing an existing project from the \"All builds\" table. \n\n",
+ "expected_results": ""
+ },
+ "2": {
+ "action": "Click on the \"View compatible layers\" link situated in the \"Project configuration\" portion of the page, under \"Layers\" \n\n",
+ "expected_results": ""
+ },
+ "3": {
+ "action": "Click on a layer (for example \"meta-aarch64\"). \n\n",
+ "expected_results": ""
+ },
+ "4": {
+ "action": "Adding/removing a layer: \nClick on \"Add the $layer_name_here layer to your project\" and verify that the \"Add layer\" button turns into a red button with the label \"Delete the $layer_name_here layer from your project\" and that at the top of the page, below the header, you see a message \"You have added 1 layer to $project_name_here: $layer_name_here\". This message can be dismissed by clicking on the \"X\" at the top right side of the message. ",
+ "expected_results": ""
+ },
+ "5": {
+ "action": "Click on the red \"Delete the $layer_name_here from your project\" button and verify that the \"Delete layer\" button turns back into a grey button with the label \"Add the $layer_name_here to your project\" and that at the top of the page, below the header, you see a message \"You have deleted 1 layer to $project_name_here: $layer_name_here\". This message can be dismissed by clicking on the \"X\" at the top right side of the message. \n\n",
+ "expected_results": ""
+ },
+ "6": {
+ "action": "Dependencies window: \n For a layer that has dependencies( for example \"meta-ettus\"), once you click the \"Add layer\" button, verify that you get a message window that presents the dependencies for this layer with the message \"$layer_name_here depends on some layers that are not added to your project. Select the ones you want to add:\", a list with a checkbox for each one and 2 options: \"Add layers\" or \"Cancel\". \nClicking on \"Add layers\" adds all the dependencies and the current layer. Clicking on \"Cancel\" takes you back to the layer detail page without adding any of the layers. \n\n",
+ "expected_results": ""
+ },
+ "7": {
+ "action": "\"Recipes\" table \nCheck that if the layer hasn't been added to the project, the \"Build recipe\" button(s) are disabled. After the project is added, check that the \"Build recipe\" button(s) become active and clicking on a button sends you to the main project page and starts a build. \n\n",
+ "expected_results": ""
+ },
+ "8": {
+ "action": "\"Machines table\" \nCheck that if the layer hasn't been added to the project, the \"Select machine\" button(s) are disabled. After the project is added, check that the \"Build machine\" button(s) become active and clicking on a button sends you to the main project page and modifies the project machine to the one selected. ",
+ "expected_results": "All mentioned elements should be present and functional."
+ }
+ },
+ "summary": "Layer_details_page:_UI_functionality"
+ }
+ },
+ {
+ "test": {
+ "@alias": "toaster-managed-mode.toaster-managed.Importing_new_layers",
+ "author": [
+ {
+ "email": "stanciux.mihail@intel.com",
+ "name": "stanciux.mihail@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": " Access a project page, either by creating a new project or accessing an existing project from the \"All builds\" table. \n\n",
+ "expected_results": ""
+ },
+ "2": {
+ "action": "Click on the \"Import layer\" link situated in the \"Project configuration\" portion of the page, under \"Layers\" table. \n\n",
+ "expected_results": ""
+ },
+ "3": {
+ "action": "Check that the import layer form is shown, with the following elements as text fields to be filled out: \nLayer name (example: meta-imported) \nGit repository URL (example: git://github.com/shr-distribution/meta-smartphone.git) \nRepository subdirectory (optional) (example: meta-acer) \nRevision (example: master) \n\nIn addition, a separate portion of the form will be the \"Layer dependencies\" portion, where you can add dependency layers for the layer you are importing. This portion will contain a list of dependencies already added, with a trashcan icon next to them that will delete them when pressed and a text field with a \"add layer\" button next to it for adding dependencies. (for example: meta-android, meta-oe) \n\n",
+ "expected_results": ""
+ },
+ "4": {
+ "action": "At the bottom of the form, check that a button exists with the label \"Import and add to project\". Check that this button is inactive until the required fields are filled out. \nCheck that clicking on the \"Import button\" takes you back to the main project page and that the imported layer, along with any dependencies, were added in the project's layers. ",
+ "expected_results": "All mentioned elements should be present and functional."
+ }
+ },
+ "summary": "Importing_new_layers"
+ }
+ },
+ {
+ "test": {
+ "@alias": "toaster-managed-mode.toaster-managed.Layer_details_page:_UI_functionality_for_imported_layers",
+ "author": [
+ {
+ "email": "stanciux.mihail@intel.com",
+ "name": "stanciux.mihail@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": " Access a project page, either by creating a new project or accessing an existing project from the \"All builds\" table. \n\n",
+ "expected_results": ""
+ },
+ "2": {
+ "action": "Click on the \"View compatible layers\" link situated in the \"Project configuration\" portion of the page, under \"Layers\" table. \n\n",
+ "expected_results": ""
+ },
+ "3": {
+ "action": "Select an imported layer (see in TC 1112 how to import a layer). \n\n",
+ "expected_results": ""
+ },
+ "4": {
+ "action": "Page heading \nCheck that the page heading includes the branch, tag or commit as entered when importing the layer.\nIf it's a commit, Check that only the first 10 characters are shown followed by an ellipsis character. The full commit shows on hover.The branch, tag or commit information also shows in the breadcrumb. \n\n",
+ "expected_results": ""
+ },
+ "5": {
+ "action": "The \"About\" information \nIt shows: \n- Summary \n- Description \nin this order. Those two items always show, independently of them being blank or not, since they can be edited by users. \n\nWhen an information item is empty, it shows as \"not set\" with a \"change\" icon. Click on the icon to add a value. \n\nFor \"Summary\" and \"Description\" clicking the \"change\" icon shows the selected information item in its editable state. It consists of a text area, set to 2 rows for the \"Summary\" and to 6 rows for the \"Description\", plus 'save' and 'cancel' buttons. \nThe 'save' buttons only activate when there is at least one character in the text area. \n\n",
+ "expected_results": ""
+ },
+ "6": {
+ "action": "The tabs \nCheck that the tabs shown are: \n- \"Layer details\" \n- \"Recipes\" \n- \"Machines\" \nThe tabs should show in the order in which they are listed above. \n\n\"Layer details\" tab: \nIn not-editable pages, the tab shows: \n- A button to add / remove the layer to / from the project. In this tab, the button labels are: \n\t- \"Add the $layer_name layer to your project\" \n\t- \"Delete the $layer_name layer from your project\" \n\n- Some details about the layer: repository URL, repository subdirectory, revision (branch / tag / commit) and the list of layer dependencies. This is the information required from users when importing a layer. The subdirectory and the layer dependencies can be blank.",
+ "expected_results": ""
+ },
+ "7": {
+ "action": "If blank, they show as \"not set\". \n\nEditing the \"Repository URL\" \nThe \"Git repository URL\" cannot be blank. Therefore, we show only a \"change\" icon next to it. When you click the icon, the text input field is set to the current value. If you delete the value from the input field, we disable the \"save\" button. We enable it again when you type something in the field. \n\nEditing the \"Repository subdirectory\" \nThe \"Repository subdirectory\" can be blank. Therefore, we show both \"change\" and \"delete\" icons. When you click the \"delete\" icon, we \nshow the label \"Not set\".",
+ "expected_results": ""
+ },
+ "8": {
+ "action": "\nWhen you click the \"change\" icon, the text input field is set \nto the current value. \nIf you delete the value from the input field, we disable the \"save\" button. We enable it again when you type something in the field. \n \n\nEditing the \"Revision\" \nThe \"Revision\" cannot be blank. Therefore, we show only a \"change\" icon next to it. When you click the icon, the text input field is set to the current value. If you delete the value from the input field, we disable the \"save\" button. We enable it again when you type something in the field. \n\nThe \"Recipes\" tab \nIt shows: \n1: A counter in the tab label showing the total number of targets provided by the layer \n2: A button to add/remove the layer to/from the project. ",
+ "expected_results": ""
+ },
+ "9": {
+ "action": "In this tab, the button labels are \n \n\"Add the $layer_name layer to your project to enable \nthese targets\" \n\"Delete the $layer_name layer from your project\" \n\n3: A \"Recipes\" table with the following columns: \n \n- Recipe \n- Description: the value of the DESCRIPTION variable. If not set, then the value of the SUMMARY variable. \n- Build recipe, which shows a \"build recipe\" button. The \"build recipe\" button is disabled when the layer is not added to the project. \nThe recipes table is sorted by \"Recipe\" in ascending alphabetical order. \n\nThe \"Machines\" tab: \nIt shows: \n1: A counter in the tab label showing the total number of machines provided by the layer \n2: A button to add/remove the layer to/from the project.",
+ "expected_results": ""
+ },
+ "10": {
+ "action": "In this tab, the button labels are \n \n\t- \"Add the $layer_name layer to your project to enable these machines\" \n\t- \"Delete the $layer_name layer from your project\" \n3: A \"machines\" table with the following columns: \n- Machine. \n \n- Description: The value of the DESCRIPTION variable in the .conf file \n- Select machine, which shows a \"select\" button. The \"select\" button is disabled when the layer is not added to the project. \nThe machines table is sorted by \"Machine\" in ascending alphabetical order. ",
+ "expected_results": "All mentioned elements should be present and functional."
+ }
+ },
+ "summary": "Layer_details_page:_UI_functionality_for_imported_layers"
+ }
+ },
+ {
+ "test": {
+ "@alias": "toaster-managed-mode.toaster-managed.Multiple_build_directories",
+ "author": [
+ {
+ "email": "stanciux.mihail@intel.com",
+ "name": "stanciux.mihail@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "after starting Toaster for the first time, go to http://[localhost]:8000/admin/ and login with the admin user you created during setup. Click on the Build environments section, and on the BuildEnvironment object. \n\n\n\nNote: you can create a superuser to enter as admin with ... poky/bitbake/lib/toaster/manage.py createsuperuser \n\n\n",
+ "expected_results": ""
+ },
+ "2": {
+ "action": "make note of the \"sourcedir\" and \"builddir\" values. The build dir will be something like \"/home/user/path/build\" \n\n",
+ "expected_results": ""
+ },
+ "3": {
+ "action": " click \"back\", and click on the \"Add build environment\" button in the upper right corner. \n\n",
+ "expected_results": ""
+ },
+ "4": {
+ "action": "enter Address \"2\", Betype: \"local\", \"sourcedir\" is to be set to whatever the original build env is set, and \"builddir\" is ANOTHER path at the same level as the original builddir - e.g. \"/home/user/path/build2\" \n\n",
+ "expected_results": ""
+ },
+ "5": {
+ "action": "Click save \n\n",
+ "expected_results": ""
+ },
+ "6": {
+ "action": "Execute command : /poky$ source oe-init-build-env build2 \n\n",
+ "expected_results": ""
+ },
+ "7": {
+ "action": "Create new project \n\n",
+ "expected_results": ""
+ },
+ "8": {
+ "action": "issue 2 build (e.g. core-image-minimal core-image-sato)\n\n\n\n\n\n",
+ "expected_results": "Both build commands should run simultaneously."
+ }
+ },
+ "summary": "Multiple_build_directories"
+ }
+ },
+ {
+ "test": {
+ "@alias": "toaster-managed-mode.toaster-managed.Run_again_button_from_all_builds_page_must_run_the_specified_task",
+ "author": [
+ {
+ "email": "alexandru.costinx.roman@intel.com",
+ "name": "alexandru.costinx.roman@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "Start Toaster.",
+ "expected_results": "Toaster starts. \n"
+ },
+ "2": {
+ "action": "Click on new project button.",
+ "expected_results": " Open create a new project page. \n"
+ },
+ "3": {
+ "action": "Enter a project name, select a release and click on create project or select an existing project.",
+ "expected_results": " Project Created. \n"
+ },
+ "4": {
+ "action": "Build a image task (ex: core-image-minimal:clean) and wait until build finish.\nfrom all build page.",
+ "expected_results": " Build task finishes successfully. \n"
+ },
+ "5": {
+ "action": "Click on rebuild button from all build page.",
+ "expected_results": "Specified task will run again. \n"
+ },
+ "6": {
+ "action": "Click on the build and verify if the number of tasks executed = 1.",
+ "expected_results": "Only the specified task is executed. \n"
+ },
+ "7": {
+ "action": "From project builds page click on run again button.",
+ "expected_results": "Specified task will run again.\n"
+ },
+ "8": {
+ "action": "Click on the build and verify if the number of tasks executed = 1.",
+ "expected_results": ""
+ }
+ },
+ "summary": "Run_again_button_from_all_builds_page_must_run_the_specified_task"
+ }
+ },
+ {
+ "test": {
+ "@alias": "toaster-managed-mode.toaster-managed.Intel_layers_builds",
+ "author": [
+ {
+ "email": "alexandru.costinx.roman@intel.com",
+ "name": "alexandru.costinx.roman@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "Start Toaster.",
+ "expected_results": "Toaster starts. \n"
+ },
+ "2": {
+ "action": "Click on new project button.",
+ "expected_results": "Open create a new project page. \n"
+ },
+ "3": {
+ "action": "Enter a project name, select a release and click on create project.",
+ "expected_results": "Project Created. \n"
+ },
+ "4": {
+ "action": "Click on layers tab.",
+ "expected_results": "Open compatible layers page. \n"
+ },
+ "5": {
+ "action": "Search for intel.",
+ "expected_results": "Return results \n"
+ },
+ "6": {
+ "action": "Add intel layers like: meta-intel, meta-intel-quark.",
+ "expected_results": "Layers added to project. \n"
+ },
+ "7": {
+ "action": "Click on the added layer.",
+ "expected_results": "Open layer page. \n"
+ },
+ "8": {
+ "action": "From machine tab, select a machine.",
+ "expected_results": "Machine has changed. \n"
+ },
+ "9": {
+ "action": "Build a recipe(core-image-minimal) or a recipe from recipe tab.",
+ "expected_results": "Build finishes successfully."
+ }
+ },
+ "summary": "Intel_layers_builds"
+ }
+ },
+ {
+ "test": {
+ "@alias": "toaster-managed-mode.toaster-managed.Download_other_artifacts",
+ "author": [
+ {
+ "email": "alexandru.costinx.roman@intel.com",
+ "name": "alexandru.costinx.roman@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "Delete the build/tmp folder. (to make sure the rootfs task runs and other artifacts are generated for the build)",
+ "expected_results": ""
+ },
+ "2": {
+ "action": "Start Toaster.",
+ "expected_results": "Toaster starts. \n\t"
+ },
+ "3": {
+ "action": "Click on new project button.",
+ "expected_results": "Open create a new project page. \n\t"
+ },
+ "4": {
+ "action": "Enter a project name, select a release and click on create project.",
+ "expected_results": "Project Created. \n\t"
+ },
+ "5": {
+ "action": "Build an image recipe (ex: core-image-minimal) and wait until build finish.",
+ "expected_results": "Build finishes successfully. \n\t"
+ },
+ "6": {
+ "action": "Click on the built recipe.",
+ "expected_results": "Open build summary page. \n\t"
+ },
+ "7": {
+ "action": "From other artifacts tab click on a link.",
+ "expected_results": "You can download other artifacts."
+ }
+ },
+ "summary": "Download_other_artifacts"
+ }
+ },
+ {
+ "test": {
+ "@alias": "toaster-managed-mode.toaster-managed.Download_licence_manifest",
+ "author": [
+ {
+ "email": "alexandru.costinx.roman@intel.com",
+ "name": "alexandru.costinx.roman@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "Delete the build/tmp folder. (to make sure license manifest is generated)",
+ "expected_results": ""
+ },
+ "2": {
+ "action": "Start Toaster \n\n",
+ "expected_results": "Toaster starts. \n"
+ },
+ "3": {
+ "action": "Click on new project button. \n\n",
+ "expected_results": "Open create a new project page. \n"
+ },
+ "4": {
+ "action": "Enter a project name, select a release and click on create project. \n\n",
+ "expected_results": "Project Created. \n"
+ },
+ "5": {
+ "action": "Build an image recipe (ex: core-image-minimal) and wait until build finish. \n\n",
+ "expected_results": "Build finishes successfully. \n"
+ },
+ "6": {
+ "action": "Click on the built recipe. \n\n",
+ "expected_results": "Open build summary page. \n"
+ },
+ "7": {
+ "action": "From Image tab click on \"Download\" button for License manifest.",
+ "expected_results": "You can download license manifest."
+ }
+ },
+ "summary": "Download_licence_manifest"
+ }
+ },
+ {
+ "test": {
+ "@alias": "toaster-managed-mode.toaster-managed.Test_dependencies_layers",
+ "author": [
+ {
+ "email": "alexandru.costinx.roman@intel.com",
+ "name": "alexandru.costinx.roman@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "Start Toaster.",
+ "expected_results": "Toaster starts. \n"
+ },
+ "2": {
+ "action": "Click on new project button.",
+ "expected_results": "Open create a new project page. \n"
+ },
+ "3": {
+ "action": "Enter a project name, select a release and click on create project.",
+ "expected_results": "Project Created. \n"
+ },
+ "4": {
+ "action": "Click on Layers.",
+ "expected_results": "Open compatible layers page. \n"
+ },
+ "5": {
+ "action": "Add a layer with multi-level dependencies. (ex: meta-acer) \nThis layer depends on meta-networking, which in turn depends on meta-android. \n \n",
+ "expected_results": "The selected layer and dependencies were added to project. \n"
+ },
+ "6": {
+ "action": "Check if meta-python appears in the dependencies list, and add the layers to project.",
+ "expected_results": ""
+ },
+ "7": {
+ "action": "Delete a dependency layer.",
+ "expected_results": "Layer removed from project. \n \n"
+ },
+ "8": {
+ "action": "Build a recipe (ex: core-image-minimal) and wait until build finish.\n",
+ "expected_results": "Build will fail with an error.\n\n\t"
+ }
+ },
+ "summary": "Test_dependencies_layers"
+ }
+ },
+ {
+ "test": {
+ "@alias": "toaster-managed-mode.toaster-managed.Test_build_recipe_button_from_recipes_page",
+ "author": [
+ {
+ "email": "alexandru.costinx.roman@intel.com",
+ "name": "alexandru.costinx.roman@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "Start Toaster.",
+ "expected_results": "Toaster starts. \n"
+ },
+ "2": {
+ "action": "Click on new project button.",
+ "expected_results": "Open create a new project page. \n"
+ },
+ "3": {
+ "action": "Enter a project name, select a release and click on create project.",
+ "expected_results": "Project Created. \n"
+ },
+ "4": {
+ "action": "Click on software recipes / image recipes.",
+ "expected_results": "Open compatible software recipes page. \n"
+ },
+ "5": {
+ "action": "Select a recipe and click on 'add layer' button.",
+ "expected_results": "Layer added to project and the 'add layer' button becomes 'build recipe'. \n"
+ },
+ "6": {
+ "action": "Click on \"Build recipe\" button for one recipe (ex : core-image-minimal / busybox).",
+ "expected_results": "Build finishes successfully."
+ },
+ "7": {
+ "action": "Test this for software and image recipes tables.",
+ "expected_results": ""
+ }
+ },
+ "summary": "Test_build_recipe_button_from_recipes_page"
+ }
+ },
+ {
+ "test": {
+ "@alias": "toaster-managed-mode.toaster-managed.Test_compatible_machines",
+ "author": [
+ {
+ "email": "alexandru.costinx.roman@intel.com",
+ "name": "alexandru.costinx.roman@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "Start Toaster.",
+ "expected_results": "Toaster starts. \n"
+ },
+ "2": {
+ "action": "Click on new project button.",
+ "expected_results": "Open create a new project page. \n"
+ },
+ "3": {
+ "action": "Enter a project name, select a master release and click on create project.",
+ "expected_results": "Project Created. \n"
+ },
+ "4": {
+ "action": "Go to machines page.",
+ "expected_results": "Open compatible machines page. \n"
+ },
+ "5": {
+ "action": "Choose a machine and click on add layer for it. (intel-core2-32)",
+ "expected_results": "Layers added to project and add layer button becomes select machine. \n"
+ },
+ "6": {
+ "action": "Click on select machine.",
+ "expected_results": "Machine has changed. \n"
+ },
+ "7": {
+ "action": "Go to layer page that generate the machine. (meta-intel)",
+ "expected_results": "Open layer page \n"
+ },
+ "8": {
+ "action": "Build a recipe generated by that layer.",
+ "expected_results": "Build finishes successfully."
+ }
+ },
+ "summary": "Test_compatible_machines"
+ }
+ },
+ {
+ "test": {
+ "@alias": "toaster-managed-mode.toaster-managed.Builds_with_different_machines",
+ "author": [
+ {
+ "email": "alexandru.costinx.roman@intel.com",
+ "name": "alexandru.costinx.roman@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "Start Toaster.",
+ "expected_results": "Toaster starts. \n"
+ },
+ "2": {
+ "action": "Click on new project button.",
+ "expected_results": "Open create a new project page. \n"
+ },
+ "3": {
+ "action": "Enter a project name, select a master release and click on create project.",
+ "expected_results": "Project Created. \n"
+ },
+ "4": {
+ "action": "Select a machine (ex: qemux86-64)",
+ "expected_results": "The machine has changed. \n"
+ },
+ "5": {
+ "action": "Build a recipe (ex: core-image-minimal) and wait until buid finish.",
+ "expected_results": "Build finishes successfully. \n"
+ },
+ "6": {
+ "action": "Go to project page and change the machine (ex: qemumips)",
+ "expected_results": "The machine has changed. \n"
+ },
+ "7": {
+ "action": "Build a recipe (ex: core-image-sato) and wait until build finish.",
+ "expected_results": "Build finishes successfully. \n\nYou can build recipes with different machines."
+ },
+ "8": {
+ "action": "Check on build summary page that the machine match the machine selected.",
+ "expected_results": ""
+ }
+ },
+ "summary": "Builds_with_different_machines"
+ }
+ },
+ {
+ "test": {
+ "@alias": "toaster-managed-mode.toaster-managed.Test_bitbake_variables_-_IMAGE_FSTYPES",
+ "author": [
+ {
+ "email": "alexandru.costinx.roman@intel.com",
+ "name": "alexandru.costinx.roman@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "Start Toaster.",
+ "expected_results": "Toaster starts. \n"
+ },
+ "2": {
+ "action": "Click on new project button.",
+ "expected_results": "Open create a new project page. \n"
+ },
+ "3": {
+ "action": "Enter a project name, select release and click on create project.",
+ "expected_results": "Project Created. \n"
+ },
+ "4": {
+ "action": "Go to Configuration --> BitBake variables",
+ "expected_results": "Open Bitbake variables page. \n"
+ },
+ "5": {
+ "action": "Change IMAGE_FSTYPES variable, add some image types like: hddimg, ext4, etc.",
+ "expected_results": "Image types were added. \n"
+ },
+ "6": {
+ "action": "Build a recipe (ex: core-image-minimal) and wait until build finish.",
+ "expected_results": "Build finishes successfully. \n"
+ },
+ "7": {
+ "action": "Verify in the build summary page if the image types selected were built.",
+ "expected_results": "All the image types selected appears in the build summary page."
+ }
+ },
+ "summary": "Test_bitbake_variables_-_IMAGE_FSTYPES"
+ }
+ },
+ {
+ "test": {
+ "@alias": "toaster-managed-mode.toaster-managed.Software_recipes:_default_view",
+ "author": [
+ {
+ "email": "alexandru.costinx.roman@intel.com",
+ "name": "alexandru.costinx.roman@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": " Access a project page, either by creating a new project or accessing an existing project from the \"All builds\" table. \n\n\n",
+ "expected_results": ""
+ },
+ "2": {
+ "action": " If no images exist in the project, build an image by inserting \"core-image-minimal\" in the \"Recipes\" field and press the \"Build\" button. Wait for the image to finish building. \n\n",
+ "expected_results": ""
+ },
+ "3": {
+ "action": "On the project page click on the \"Software Recipes\" link situated in the left-handed side of the page, under the \"Project configuration\" menus, in the \"COMPATIBLE METADATA\" table. \n\n\n",
+ "expected_results": ""
+ },
+ "4": {
+ "action": "Check that \"Compatible software recipes\" table is populated. \n\n",
+ "expected_results": ""
+ },
+ "5": {
+ "action": "Check that the following columns are shown by default: \n\n\t\tSoftware recipe \n\t\tDescription \n \n\t\tLayer \n\t\tBuild \n\t\t Version ",
+ "expected_results": ""
+ }
+ },
+ "summary": "Software_recipes:_default_view"
+ }
+ },
+ {
+ "test": {
+ "@alias": "toaster-managed-mode.toaster-managed.Software_recipes:_sorting_the_content_of_the_software_recipes_table",
+ "author": [
+ {
+ "email": "alexandru.costinx.roman@intel.com",
+ "name": "alexandru.costinx.roman@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "Access a project page, either by creating a new project or accessing an existing project from the \"All builds\" table. \n\n",
+ "expected_results": ""
+ },
+ "2": {
+ "action": "Navigate to the \"Software Recipes\" page. \n\n",
+ "expected_results": ""
+ },
+ "3": {
+ "action": "Make sure the table is sorted on the \"Software Recipe\" column by default in ascending order. \n\n",
+ "expected_results": ""
+ },
+ "4": {
+ "action": "Activate all columns from the \"Edit column\" drop-down menu. Check that \"Build\" and \"Software Recipe\" columns cannot be unchecked. \n\n",
+ "expected_results": ""
+ },
+ "5": {
+ "action": "Check that \"Software Recipe\", \"Section\", \"License\", \"Layer\" are the only sortable table heads. \n\n",
+ "expected_results": ""
+ },
+ "6": {
+ "action": "Sort the table by \"Layer\" and then navigate away by selecting a layer(such as meta-yocto). When you click \"back\" button in web-browser to go back to the \"Compatible image recipes\" table it should still be sorted by \"Layer\". \n\n",
+ "expected_results": ""
+ },
+ "7": {
+ "action": "Sorting and \"Edit columns\" \nIf you use the \"Edit columns\" menu to hide the column with the applied sorting, we revert the sorting to the default sorting (i.e. \"Recipe\"). The default sorting always uses one of the core columns, which cannot be hidden using the \"Edit columns\" menu. \n\n",
+ "expected_results": ""
+ },
+ "8": {
+ "action": "Sorting and search \nSearching should have no impact on the applied sorting. Any results returned should be sorted by the sorting criteria selected when the search query was submitted. \nSort recipes by \"Layer\" column heading. Input a string (such as \"meta\") in search box and click search button. Make sure results returned are sorted by \"Layer\".",
+ "expected_results": ""
+ }
+ },
+ "summary": "Software_recipes:_sorting_the_content_of_the_software_recipes_table"
+ }
+ },
+ {
+ "test": {
+ "@alias": "toaster-managed-mode.toaster-managed.Software_recipes:_Searching_the_content_of_the_software_recipes_table",
+ "author": [
+ {
+ "email": "alexandru.costinx.roman@intel.com",
+ "name": "alexandru.costinx.roman@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "Access a project page, either by creating a new project or accessing an existing project from the \"All builds\" table. \n\n",
+ "expected_results": ""
+ },
+ "2": {
+ "action": "Navigate to the \"Software Recipes\" page. \n\n",
+ "expected_results": ""
+ },
+ "3": {
+ "action": "Check that the search is made of a text input field and a \"Search\" button in a toolbar above the table. \n\n",
+ "expected_results": ""
+ },
+ "4": {
+ "action": "When no search query has been entered, we have placeholder text saying: \"Search compatible software recipes\". \n\n",
+ "expected_results": ""
+ },
+ "5": {
+ "action": "Input \"core\" in the text input field. The placeholder text disappears when the first character is typed. Click search button. \n\n",
+ "expected_results": ""
+ },
+ "6": {
+ "action": " \n(1) returned results \nThe search string is kept in the text input field. The results returned occur. Click \"Clear search\" icon to clear the search and display the compatible recipes. \n(2) no results returned \nIf your search query returns no results, the page heading changes to \"No recipes found\", and we show you an alert with a search form and an option to show all targets. Check that \"show compatible recipes\" button is available. \n\n",
+ "expected_results": ""
+ },
+ "7": {
+ "action": "When I run a search, the search happens against the following columns (independently of they being shown or hidden):\n- Software Recipe\n- Recipe version\n- Description\n- Recipe file\n- Section\n- License\n- Layer\n- Revision\nInput a string to search for the above column headings separately to make sure that the search happens against the columns. \n",
+ "expected_results": ""
+ },
+ "8": {
+ "action": "Search, sorting and \"Edit columns\" \nSearching does not change the state of the table: the same columns remain hidden and the same sorting applied when search results are displayed, but filters are cleared by the search results.\nSearch a string and make sure that the same columns remain hidden and the same sorting applied. \n\n",
+ "expected_results": ""
+ },
+ "9": {
+ "action": "Search and filters \nThe scope of the filters is the content currently on the table (this means all table pages, not only the one displayed). The scope of the search is always the content of the database. \n\nIf I run a search query, any filter applied afterwards will filter the content returned by the search query. \n\nIf I run a search query while a filter is applied, the filter is cleared by the results of the search query (i.e. we display the results of the search query and clear the filter applied beforehand). The same happens if I click the \"Clear search\" icon when a filter is applied to a set of search results (both search results and applied filter are cleared, and the table shows all the targets). ",
+ "expected_results": ""
+ }
+ },
+ "summary": "Software_recipes:_Searching_the_content_of_the_software_recipes_table"
+ }
+ },
+ {
+ "test": {
+ "@alias": "toaster-managed-mode.toaster-managed.Software_recipes:_Filter_the_contents_of_the_software_recipes_table",
+ "author": [
+ {
+ "email": "alexandru.costinx.roman@intel.com",
+ "name": "alexandru.costinx.roman@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "Access a project page, either by creating a new project or accessing an existing project from the \"All builds\" table.",
+ "expected_results": ""
+ },
+ "2": {
+ "action": "Navigate to the \"Software Recipes\" page.",
+ "expected_results": ""
+ },
+ "3": {
+ "action": "Make sure the following table column has filters: \n- Build",
+ "expected_results": ""
+ },
+ "4": {
+ "action": "Filters are mutually exclusive. Click a filter button of a one column and a filter dialogue occurs. Select a filter item. The filter result would be showed. Then select another filter item of another column and the previously applied filter is overridden by the newly selected filter when a filter from a different column is applied to the table. In this state, we show some help text next to the \"Apply\" button, saying \"You can only apply one filter to the table. This filter will override the current filter.\"",
+ "expected_results": ""
+ },
+ "5": {
+ "action": "Filters are overridden by search. Run a search query and you can see previous filter results are overridden by the results of the search query.",
+ "expected_results": ""
+ }
+ },
+ "summary": "Software_recipes:_Filter_the_contents_of_the_software_recipes_table"
+ }
+ },
+ {
+ "test": {
+ "@alias": "toaster-managed-mode.toaster-managed.Test_the_packages_included_in_the_image",
+ "author": [
+ {
+ "email": "alexandru.costinx.roman@intel.com",
+ "name": "alexandru.costinx.roman@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "Start Toaster.",
+ "expected_results": "Toaster starts. \n"
+ },
+ "2": {
+ "action": " Click on new project button.",
+ "expected_results": " Open create a new project page. \n"
+ },
+ "3": {
+ "action": " Enter a project name, select a release and click on create project.",
+ "expected_results": " Project Created. \n"
+ },
+ "4": {
+ "action": " Build a recipe (ex: core-image-minimal) and wait until build finish.",
+ "expected_results": " Build finishes successfully. \n"
+ },
+ "5": {
+ "action": " Click on the built recipe.",
+ "expected_results": " Open build summary page. \n"
+ },
+ "6": {
+ "action": " Under IMAGES tab click on the recipe built.",
+ "expected_results": "Image page open. \n"
+ },
+ "7": {
+ "action": "Click on a package name.",
+ "expected_results": "Open the package page. \n"
+ },
+ "8": {
+ "action": "Under file title click on the link to file.",
+ "expected_results": "You are redirected to directory structure and you can see where the file is located."
+ }
+ },
+ "summary": "Test_the_packages_included_in_the_image"
+ }
+ },
+ {
+ "test": {
+ "@alias": "toaster-managed-mode.toaster-managed.Test_the_filters_from_a_image_page",
+ "author": [
+ {
+ "email": "alexandru.costinx.roman@intel.com",
+ "name": "alexandru.costinx.roman@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": " Start Toaster.",
+ "expected_results": "Toaster starts. \n"
+ },
+ "2": {
+ "action": " Click on new project button.",
+ "expected_results": " Open create a new project page. \n"
+ },
+ "3": {
+ "action": " Enter a project name, select a release and click on create project.",
+ "expected_results": " Project Created. \n"
+ },
+ "4": {
+ "action": " Build a recipe (ex: core-image-minimal) and wait until build finish.",
+ "expected_results": " Build finishes successfully. \n"
+ },
+ "5": {
+ "action": " Click on the built recipe.",
+ "expected_results": " Open build summary page. \n"
+ },
+ "6": {
+ "action": "Click on Configuration - Bitbake Variables.",
+ "expected_results": "Open bitbake variables page. \n"
+ },
+ "7": {
+ "action": "Test Description filter. ",
+ "expected_results": "Filter works ok. (filter returns only items that match the selected criteria) "
+ }
+ },
+ "summary": "Test_the_filters_from_a_image_page"
+ }
+ },
+ {
+ "test": {
+ "@alias": "toaster-managed-mode.toaster-managed.Test_dependencies_link",
+ "author": [
+ {
+ "email": "alexandru.costinx.roman@intel.com",
+ "name": "alexandru.costinx.roman@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": " Start Toaster.",
+ "expected_results": "Toaster starts. \n"
+ },
+ "2": {
+ "action": " Click on new project button.",
+ "expected_results": " Open create a new project page. \n"
+ },
+ "3": {
+ "action": " Enter a project name, select a release and click on create project.",
+ "expected_results": " Project Created. \n"
+ },
+ "4": {
+ "action": " Build a recipe (ex: core-image-minimal) and wait until build finish.",
+ "expected_results": " Build finishes successfully. \n"
+ },
+ "5": {
+ "action": " Click on the built recipe.",
+ "expected_results": " Open build summary page. \n"
+ },
+ "6": {
+ "action": "Click on recipes tab.",
+ "expected_results": "Open recipes page. \n"
+ },
+ "7": {
+ "action": "Click on edit columns and select Dependencies.",
+ "expected_results": "Dependencies column is shown in the table. \n"
+ },
+ "8": {
+ "action": "Click on a number of dependencies.",
+ "expected_results": "A pop up with dependencies will appear. \n"
+ },
+ "9": {
+ "action": "Click on a dependency. ",
+ "expected_results": "Open recipe dependency page. "
+ }
+ },
+ "summary": "Test_dependencies_link"
+ }
+ },
+ {
+ "test": {
+ "@alias": "toaster-managed-mode.toaster-managed.Test_recipe_file_link",
+ "author": [
+ {
+ "email": "alexandru.costinx.roman@intel.com",
+ "name": "alexandru.costinx.roman@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "Start Toaster. \n\n\t",
+ "expected_results": "Toaster starts. \n\n\t"
+ },
+ "2": {
+ "action": " Click on new project button. \n\n\t",
+ "expected_results": " Open create a new project page. \n\n\t"
+ },
+ "3": {
+ "action": " Enter a project name, select a release (ex: master) and click on create project. \n\n\t",
+ "expected_results": " Project Created. \n\n\t"
+ },
+ "4": {
+ "action": "Click on Image recipes tab. \n\n\t",
+ "expected_results": "Open Compatible image recipes table. \n\n\t"
+ },
+ "5": {
+ "action": "Click on edit columns and select recipe file. \n\n\t",
+ "expected_results": "Recipe file column appears in the table. \n\n\t"
+ },
+ "6": {
+ "action": "Click on the blue button near a recipe file. \n\n\t",
+ "expected_results": ""
+ },
+ "7": {
+ "action": "Repet steps - 4 to 6 for software recipes.",
+ "expected_results": ""
+ }
+ },
+ "summary": "Test_recipe_file_link"
+ }
+ },
+ {
+ "test": {
+ "@alias": "toaster-managed-mode.toaster-managed.See_packages_size",
+ "author": [
+ {
+ "email": "alexandru.costinx.roman@intel.com",
+ "name": "alexandru.costinx.roman@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "Start Toaster. \n\n\t",
+ "expected_results": " Toaster starts. \n\n\t"
+ },
+ "2": {
+ "action": " Click on new project button. \n\n\t",
+ "expected_results": " Open create a new project page. \n\n\t"
+ },
+ "3": {
+ "action": " Enter a project name, select a release and click on create project. \n\n\t",
+ "expected_results": " Project Created. \n\n\t"
+ },
+ "4": {
+ "action": " Build a recipe (ex: core-image-minimal) and wait until build finish. \n\n\t",
+ "expected_results": " Build finishes successfully. \n\n\t"
+ },
+ "5": {
+ "action": " Click on the built recipe. \n\n\t",
+ "expected_results": " Open build summary page. \n\n\t"
+ },
+ "6": {
+ "action": "Click on packages tab. \n\n\t",
+ "expected_results": "Open packages page. \n\n\t"
+ },
+ "7": {
+ "action": "Click on size to sort the table. ",
+ "expected_results": "You can check the size of each package. \n\nWhen you click on 'Size' the first time, the correct sorting is the inverse one (biggest package on top). Clicking a second time will invert the sorting (you'll see packages with 0 B size on top)."
+ }
+ },
+ "summary": "See_packages_size"
+ }
+ },
+ {
+ "test": {
+ "@alias": "toaster-managed-mode.toaster-managed.Build_multiple_recipes",
+ "author": [
+ {
+ "email": "alexandru.costinx.roman@intel.com",
+ "name": "alexandru.costinx.roman@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": " Start Toaster. \n\n\t",
+ "expected_results": " Toaster starts. \n\n\t"
+ },
+ "2": {
+ "action": " Click on new project button. \n\n\t",
+ "expected_results": " Open create a new project page. \n\n\t"
+ },
+ "3": {
+ "action": " Enter a project name, select a release and click on create project. \n\n\t",
+ "expected_results": " Project Created. \n\n\t"
+ },
+ "4": {
+ "action": " Build a multiple recipes (ex: \"core-image-minimal core-image-sato\") and wait until build finish. ",
+ "expected_results": "Builds finishes successfully. \n\nYou can build multiple recipes with toaster"
+ }
+ },
+ "summary": "Build_multiple_recipes"
+ }
+ },
+ {
+ "test": {
+ "@alias": "toaster-managed-mode.toaster-managed.Build_a_recipe_with_different_distro",
+ "author": [
+ {
+ "email": "alexandru.costinx.roman@intel.com",
+ "name": "alexandru.costinx.roman@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": " Start Toaster. \n\n\t",
+ "expected_results": " Toaster starts. \n\n\t"
+ },
+ "2": {
+ "action": " Click on new project button. \n\n\t",
+ "expected_results": " Open create a new project page. \n\n\t"
+ },
+ "3": {
+ "action": " Enter a project name, select a release and click on create project. \n\n\t",
+ "expected_results": " Project Created. \n\n\t"
+ },
+ "4": {
+ "action": "From project page click on Bitbake variables tab. \n\n\t",
+ "expected_results": "Open Bitbake variables page. \n\n\t"
+ },
+ "5": {
+ "action": "Click on change button for distro. \n\n\t",
+ "expected_results": "A type in form appears. \n\n\t"
+ },
+ "6": {
+ "action": "Change distro (ex: poky-tiny). \n\n\t",
+ "expected_results": "Distro has changed. \n\n\t"
+ },
+ "7": {
+ "action": "Add specific layers for distro (meta-qt3, meta-qt4) \n\t\n\t",
+ "expected_results": "Layers added to the project \n\n\t"
+ },
+ "8": {
+ "action": " Build a recipe (ex: core-image-minimal) and wait until build finish.",
+ "expected_results": "Build finishes successfully. \n\nThe 'success' criteria for this one should be that the build is reported as using the poky-tiny distro in the build summary page, and that the DISTRO variable value in the bitbake variables table is set to the value specified in toaster (poky-tiny again)."
+ }
+ },
+ "summary": "Build_a_recipe_with_different_distro"
+ }
+ },
+ {
+ "test": {
+ "@alias": "toaster-managed-mode.toaster-managed.Test_package_format_-_ipk_rpm_deb",
+ "author": [
+ {
+ "email": "alexandru.costinx.roman@intel.com",
+ "name": "alexandru.costinx.roman@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": " Start Toaster. \n\n\t",
+ "expected_results": " Toaster starts. \n\n\t"
+ },
+ "2": {
+ "action": " Click on new project button. \n\n\t",
+ "expected_results": " Open create a new project page. \n\n\t"
+ },
+ "3": {
+ "action": " Enter a project name, select a release and click on create project. \n\n\t",
+ "expected_results": " Project Created. \n\n\t"
+ },
+ "4": {
+ "action": "From the project page click on bitbake variables tab. \n\n\t",
+ "expected_results": "Open bitbake variables page. \n\n\t"
+ },
+ "5": {
+ "action": "Click on change button near PACKAGE_CLASSES and select all the package formats (rpm, deb, ipk). \n\n\t",
+ "expected_results": "Package classes selected. \n\n\t"
+ },
+ "6": {
+ "action": "Build a recipe (ex: core-image-minimal) and wait until build finish.",
+ "expected_results": "Build finishes successfully.\nYou can see the package classes in the build summary page."
+ }
+ },
+ "summary": "Test_package_format_-_ipk_rpm_deb"
+ }
+ },
+ {
+ "test": {
+ "@alias": "toaster-managed-mode.toaster-managed.Test_IMAGE_INSTALL_append_variable",
+ "author": [
+ {
+ "email": "alexandru.costinx.roman@intel.com",
+ "name": "alexandru.costinx.roman@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "Start Toaster. \n\n",
+ "expected_results": " Toaster starts. \n\n\t"
+ },
+ "2": {
+ "action": " Click on new project button. \n\n",
+ "expected_results": " Open create a new project page. \n\n\t"
+ },
+ "3": {
+ "action": " Enter a project name, select a release and click on create project. \n\n",
+ "expected_results": " Project Created. \n\n\t"
+ },
+ "4": {
+ "action": "From the project page click on bitbake variables tab. \n\n",
+ "expected_results": "Open bitbake variables page. \n\n\t"
+ },
+ "5": {
+ "action": "Click on change button for IMAGE_INSTALL:append and add a variable (ex: acpid). \n\n",
+ "expected_results": "Variable added. \n\n\t"
+ },
+ "6": {
+ "action": "Build a recipe (ex: core-image-minimal) and wait until build finish. \n\n",
+ "expected_results": "Build finishes successfully. \n\n\t"
+ },
+ "7": {
+ "action": "After build finishes go to build page. \n\n",
+ "expected_results": "Open build summary page. \n\n\t"
+ },
+ "8": {
+ "action": "Go to package tab and search for acpid.",
+ "expected_results": "You should get results for ssh packages."
+ }
+ },
+ "summary": "Test_IMAGE_INSTALL:append_variable"
+ }
+ },
+ {
+ "test": {
+ "@alias": "toaster-managed-mode.toaster-managed.New_custom_image:_default_view",
+ "author": [
+ {
+ "email": "alexandru.costinx.roman@intel.com",
+ "name": "alexandru.costinx.roman@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "Access a project page, either by creating a new project or accessing an existing project from the \"All projects\" table. \n\n\n",
+ "expected_results": ""
+ },
+ "2": {
+ "action": "On the project page click on the \"New custom image\" link situated on the left-hand side, near Configuration, builds, import layer \n\n\n",
+ "expected_results": ""
+ },
+ "3": {
+ "action": "Check that the table is populated with the list of image recipes (eg. core-image minimal) \n\n\n",
+ "expected_results": ""
+ },
+ "4": {
+ "action": " Check that by default the following columns are shown: Image recipe, Version, Description, Layer, Customise \n\n\n",
+ "expected_results": ""
+ },
+ "5": {
+ "action": "From the \"Edit columns\" menu, activate the: Recipe file, Section, License, Git revision \n\n\n",
+ "expected_results": ""
+ },
+ "6": {
+ "action": "Check that the \"Git revision\" entries match the release entry from the main project page, in the project details section. \n\n\n",
+ "expected_results": ""
+ },
+ "7": {
+ "action": "Check that the image recipes provided by layers added to the project show a 'customise' button, while image recipes provided by layers not added to the project show an 'add layer' button ",
+ "expected_results": ""
+ }
+ },
+ "summary": "New_custom_image:_default_view"
+ }
+ },
+ {
+ "test": {
+ "@alias": "toaster-managed-mode.toaster-managed.New_custom_image:_sorting_the_content_of_new_custom_image_table",
+ "author": [
+ {
+ "email": "alexandru.costinx.roman@intel.com",
+ "name": "alexandru.costinx.roman@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "Access a project page, either by creating a new project or accessing an existing project from the \"All projects\" table. \n\n",
+ "expected_results": ""
+ },
+ "2": {
+ "action": "On the project page click on the \"New custom image\" link situated on the left-hand side, near Configuration, builds, import layer \n\n",
+ "expected_results": ""
+ },
+ "3": {
+ "action": "Make sure that the table is sorted on the ‘Image recipe’ column by default in ascending order. \n\n",
+ "expected_results": ""
+ },
+ "4": {
+ "action": "Clicking on Image recipe should revert the sorting. (from 'a to z' changes to 'z to a') \n\n",
+ "expected_results": ""
+ },
+ "5": {
+ "action": "From the \"Edit columns\" menu activate all the columns. Check that ‘Image recipe’ and ‘Customise’ columns cannot be unchecked. \n\n",
+ "expected_results": ""
+ },
+ "6": {
+ "action": "Check that Image recipe, Section, Layer and License are the only sortable table heads. \n\n",
+ "expected_results": ""
+ },
+ "7": {
+ "action": "Sort the table by \"Layer\" and then navigate away by selecting an image. When you click the \"back\" button in the web-browser to go back, the \"New custom image\" table should still be sorted by \"Layer\". \nThis should apply also by navigating back to the page by any other means. \n\n",
+ "expected_results": ""
+ },
+ "8": {
+ "action": "Sorting and \"Edit columns\" menu: If you use the \"Edit columns\" menu to hide the column with the applied sorting, we revert the sorting to the default sorting (i.e. \"Image recipe\"). The default sorting always uses one of the core columns, which cannot be hidden using the \"Edit columns\" menu \n\n",
+ "expected_results": ""
+ },
+ "9": {
+ "action": "Sorting and search: Searching should have no impact on the applied sorting. Any results returned should be sorted by the sorting criteria selected when the search query was submitted. Sort recipes by \"Layer\" column heading. Input a string (such as \"core-image\") in search box and click search button. Make sure results returned are sorted by \"Layer\".",
+ "expected_results": "N/A"
+ }
+ },
+ "summary": "New_custom_image:_sorting_the_content_of_new_custom_image_table"
+ }
+ },
+ {
+ "test": {
+ "@alias": "toaster-managed-mode.toaster-managed.New_custom_image:_searching_the_content_of_new_custom_image_table",
+ "author": [
+ {
+ "email": "alexandru.costinx.roman@intel.com",
+ "name": "alexandru.costinx.roman@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "Access a project page, either by creating a new project or accessing an existing project from the \"All projects\" table. \n \n\n\n",
+ "expected_results": ""
+ },
+ "2": {
+ "action": "On the project page click on the \"New custom image\" link situated on the left-hand side, near Configuration, builds, import layer \n \n\n\n",
+ "expected_results": ""
+ },
+ "3": {
+ "action": "Check that the search is made of a text input field and a \"Search\" button in a toolbar above the table. When no search query has been entered, the text input field should show the following placeholder text: \"Search select the image recipe you want to customise\" \n \n\n\n",
+ "expected_results": ""
+ },
+ "4": {
+ "action": "Input \"core\" in the text input field. The placeholder text disappears when the first character is typed. Click search button. \n \n\n\n",
+ "expected_results": ""
+ },
+ "5": {
+ "action": "The search string is kept in the text input field. The results returned occur. Click \"Clear search\" icon to clear the search and display the image recipes. If your search query returns no results, we show you an alert with a search form and an option to show all image recipes. Check that \"show all\" link is available. \n\n\n",
+ "expected_results": ""
+ },
+ "6": {
+ "action": "Search, sorting and \"Edit columns\": Searching does not change the state of the table: the same columns remain hidden and the same sorting applied when search results are displayed, but filters are cleared by the search results. Search a string and make sure that the same columns remain hidden and the same sorting applied. \n\n\n",
+ "expected_results": ""
+ },
+ "7": {
+ "action": "Search and filters \n \n\t•\tThe scope of the filters is the content currently on the table (this means all table pages, not only the one displayed). The scope of the search is always the content of the database. \n\n\n",
+ "expected_results": ""
+ },
+ "8": {
+ "action": "If I run a search query, any filter applied afterwards will filter the content returned by the search query. \tIf I run a search query while a filter is applied, the filter is cleared by the results of the search query (i.e. we display the results of the search query and clear the filter applied beforehand). The same happens if I click the \"Clear search\" icon when a filter is applied to a set of search results (both search results and applied filter are cleared, and the table shows all the targets). ",
+ "expected_results": "\n \n"
+ }
+ },
+ "summary": "New_custom_image:_searching_the_content_of_new_custom_image_table"
+ }
+ },
+ {
+ "test": {
+ "@alias": "toaster-managed-mode.toaster-managed.New_custom_image:_Filter_the_contents_of_the_new_custom_image_table",
+ "author": [
+ {
+ "email": "alexandru.costinx.roman@intel.com",
+ "name": "alexandru.costinx.roman@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "Access a project page, either by creating a new project or accessing an existing project from the \"All projects\" table. \n\n\n",
+ "expected_results": ""
+ },
+ "2": {
+ "action": "On the project page click on the \"New custom image\" link situated on the left-hand side, near Configuration, builds, import layer \n\n\n",
+ "expected_results": ""
+ },
+ "3": {
+ "action": "Make sure the following table column has filters: Customise \n\n\n",
+ "expected_results": ""
+ },
+ "4": {
+ "action": "Click the filter button in the \"Customise\" column and a filter dialogue comes up. Select a filter option. The filter results should be showed. \n\n\n",
+ "expected_results": ""
+ },
+ "5": {
+ "action": "Filters are overridden by search. Run a search query and you can see previous filter results are overridden by the results of the search query.",
+ "expected_results": "N/A"
+ }
+ },
+ "summary": "New_custom_image:_Filter_the_contents_of_the_new_custom_image_table"
+ }
+ },
+ {
+ "test": {
+ "@alias": "toaster-managed-mode.toaster-managed.Create_new_custom_image",
+ "author": [
+ {
+ "email": "alexandru.costinx.roman@intel.com",
+ "name": "alexandru.costinx.roman@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "Access a project page, either by creating a new project or accessing an existing project from the \"All projects\" table. \n \n\n\n",
+ "expected_results": ""
+ },
+ "2": {
+ "action": "On the project page click on the \"New custom image\" link situated on the left-hand side, near Configuration, builds, import layer \n\n\n",
+ "expected_results": ""
+ },
+ "3": {
+ "action": "Search for rpi-basic-image, click on 'add layer' button. Make sure a \"layer added\" notification shows and a \"customise\" button is displayed. Click the \"customise\" button, type a name for you new custom image and click on create custom image. \n\n",
+ "expected_results": ""
+ },
+ "4": {
+ "action": "Verify that image was created: when you create the custom image you will be redirected to the custom image details page, and a notification at the top of the page should tell you: ‘Your custom image X has been created. You can now add or remove packages as needed. \n\n",
+ "expected_results": ""
+ },
+ "5": {
+ "action": "If you select an image that has not been built beforehand you should not see the 'add / remove' packages table until you build the image. \n\n",
+ "expected_results": ""
+ },
+ "6": {
+ "action": "If you select an image that has been built beforehand you should see the 'add / remove' packages table when you create the custom image. ",
+ "expected_results": "N/A"
+ }
+ },
+ "summary": "Create_new_custom_image"
+ }
+ },
+ {
+ "test": {
+ "@alias": "toaster-managed-mode.toaster-managed.Custom_image_page_details",
+ "author": [
+ {
+ "email": "alexandru.costinx.roman@intel.com",
+ "name": "alexandru.costinx.roman@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "After you create a new custom image go to the custom image page, by clicking on the custom image. \n\n",
+ "expected_results": ""
+ },
+ "2": {
+ "action": "Breadcrumbs \n \n\t * Observe that the 3 breadcrumbs at the top left are: \n \n\t\ta live link that will take you back to the project page \n\t\tCustom images: a live link that will take you back to the custom images table \n\t\timage name(toaster-custom-images): the name of the current custom image (not a link) \n \n\n\n",
+ "expected_results": ""
+ },
+ "3": {
+ "action": "Observe the 2 buttons build Custom image and Download recipe file \n \n\ti.\tTest this 2 buttons \n\tii.\tYou should always be able to build the custom image, but you only should be able to download the recipe file when the package content of the custom image is known. When you cannot download the recipe file, the 'download' button at the top of the page is disabled, and the right hand column does not show information about the recipe file. \n\n",
+ "expected_results": ""
+ },
+ "4": {
+ "action": "Observe that there is a right-hand box, with information about the images \n \n\ti.\tThere is a number of packages included in the custom image \n\tii.\tApprox package size \n \n\tiii.\tLayer \n \n\tiv.\tImage based on \n \n\tv.\tRecipe file (only when you can download it_ \n\tvi.\tVersion \n \n\tvii.\tLicense \n\n",
+ "expected_results": ""
+ },
+ "5": {
+ "action": "Observe that the page includes a table with packages and you can add or remove packages from the custom image. The packages table only appears when: \n\na) the image recipe you chose as your base image when creating the custom image has been built within the project \n\nb) the custom image itself has been built \n\nIf no packages table shows, you see a notification with a build button instead. ",
+ "expected_results": "N/A"
+ }
+ },
+ "summary": "Custom_image_page_details"
+ }
+ },
+ {
+ "test": {
+ "@alias": "toaster-managed-mode.toaster-managed.Custom_image_page_–_Add_|_Remove_packages_table",
+ "author": [
+ {
+ "email": "alexandru.costinx.roman@intel.com",
+ "name": "alexandru.costinx.roman@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "After you create a new custom image go to the custom image page, by clicking on the custom image. \n\n\n",
+ "expected_results": ""
+ },
+ "2": {
+ "action": "Make sure that the table is sorted on the ‘Package’ column by default in ascending order. \n\n\n",
+ "expected_results": ""
+ },
+ "3": {
+ "action": "Check that by default the following columns are shown: Package, Package Version, Approx Size \n\n\n",
+ "expected_results": ""
+ },
+ "4": {
+ "action": "From the \"Edit columns\" menu, activate the: License, Recipe, Recipe version and Reverse dependencies columns \n\n",
+ "expected_results": ""
+ },
+ "5": {
+ "action": "Check that ‘Package’, Approx Size, License, Recipe are the only sortable table heads. \n\n",
+ "expected_results": ""
+ },
+ "6": {
+ "action": "Sorting and \"Edit columns\": If you use the \"Edit columns\" menu to hide the column with the applied sorting, we revert the sorting to the default sorting (i.e. \"Package\"). The default sorting always uses one of the core columns, which cannot be hidden using the \"Edit columns\" menu \n\n",
+ "expected_results": ""
+ },
+ "7": {
+ "action": "Sorting and search: Searching should have no impact on the applied sorting. Any results returned should be sorted by the sorting criteria selected when the search query was submitted. Sort recipes by \"Recipe\" column heading. Input a string (such as \"acl\") in search box and click search button. Make sure results returned are still sorted by \"Recipe\". \n\n",
+ "expected_results": ""
+ },
+ "8": {
+ "action": "Click \"Clear search\" icon to clear the search and display the Packages. \n\n",
+ "expected_results": ""
+ },
+ "9": {
+ "action": "Make sure the following table column has filters: Add | Remove (Click on 'Edit custom image' in the left pane of the custom image) \n\n1",
+ "expected_results": ""
+ },
+ "10": {
+ "action": "Click the filter button: a filter dialogue displays. Select a filter option. The filter results should be showed. \n\n1",
+ "expected_results": ""
+ },
+ "11": {
+ "action": "Filters are overridden by search. Run a search query and you can see previous filter results are overridden by the results of the search query. \n\n1",
+ "expected_results": ""
+ },
+ "12": {
+ "action": "This page needs a special no results message for the search. You can see in the doc attached to\nhttps://bugzilla.yoctoproject.org/show_bug.cgi?id=9154 \n\nTo test it, enter a random string in the search input field (something like \"bbb\") and click the 'search' button. The special no results message includes the following: \n\na) instructions about searching and building recipes in order to generate new packages \n\nb) a search text input field with the search string you typed, a 'clear' icon and a search button. Click the 'clear' icon: the search field should be cleared and the full list of packages should be shown. \n\nc) a 'show all packages' link. Click the link: the search field should be cleared and the full list of packages should be shown. ",
+ "expected_results": "N/A"
+ }
+ },
+ "summary": "Custom_image_page_–_Add_|_Remove_packages_table"
+ }
+ },
+ {
+ "test": {
+ "@alias": "toaster-managed-mode.toaster-managed.Adding_packages_without_dependencies_from_custom_images",
+ "author": [
+ {
+ "email": "libertad.gonzalez.de.la.cruz@intel.com",
+ "name": "libertad.gonzalez.de.la.cruz@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "Access a project page, either by creating a new project or accessing an existing project from the \"All projects\" table. \n\n ",
+ "expected_results": ""
+ },
+ "2": {
+ "action": "On the project page click on the \"New custom image\" link situated on the left-hand side, near Configuration, builds, import layer \n\n\n ",
+ "expected_results": " "
+ },
+ "3": {
+ "action": "Choose an image recipe example:(core-image-sato) and click on the customise button on the far right (note if that layer is not added the button will say +Add layer, add it and then customise) \n\n\n ",
+ "expected_results": " A pop out should appear and you should get to give the new image a customized name. Then you will be redirected to a page of Add|Remove Packages. If this image has not been build it will not have packages.\n\n"
+ },
+ "4": {
+ "action": "Build the new image if it has not been build, else start adding packages without dependencies example: attr-doc \n\n \n ",
+ "expected_results": "You should get a message in blue that says \"You have added 1 package to $image-custom-name: $package-name\" "
+ },
+ "5": {
+ "action": "Build the image again.\n",
+ "expected_results": "Expected Result on step 5: the packages you have added should be installed in the image."
+ }
+ },
+ "summary": "Adding_packages_without_dependencies_from_custom_images"
+ }
+ },
+ {
+ "test": {
+ "@alias": "toaster-managed-mode.toaster-managed.Removing_packages_without_and_with_dependencies__from_custom_images",
+ "author": [
+ {
+ "email": "libertad.gonzalez.de.la.cruz@intel.com",
+ "name": "libertad.gonzalez.de.la.cruz@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "Access a project page, either by creating a new project or accessing an existing project from the \"All projects\" table. \n\n ",
+ "expected_results": ""
+ },
+ "2": {
+ "action": "On the project page click on the \"New custom image\" link situated on the left-hand side, near Configuration, builds, import layer \n\n\n\n ",
+ "expected_results": " A pop out should appear and you should get to give the new image a customized name. Then you will be redirected to a page of Add|Remove Packages. If this image has not been build it will not have packages. \n\n"
+ },
+ "3": {
+ "action": "Choose an image recipe example:(core-image-sato) and click on the customise button on the far right (note if that layer is not added the button will say +Add layer, add it and then customise) \n\n\n\n ",
+ "expected_results": "A pop out should appear and you should get to give the new image a customized name. Then you will be redirected to a page of Add|Remove Packages. If this image has not been build it will not have packages.\n\n"
+ },
+ "4": {
+ "action": "Build the new image if it has not been build else start removing a packages (click on 'Edit custom image' in the left pane of the custom image) that have dependencies and packages that have no dependencies that are already included by clicking on the red button \"Remove Package\" \n\n\n \n ",
+ "expected_results": "You should get a message in blue that says \"You have removed 1 package to $image-custom-name: $package-name\" "
+ },
+ "5": {
+ "action": "Build the image again.",
+ "expected_results": "the packages you have removed should not be installed in the image."
+ }
+ },
+ "summary": "Removing_packages_without_and_with_dependencies__from_custom_images"
+ }
+ },
+ {
+ "test": {
+ "@alias": "toaster-managed-mode.toaster-managed.Adding_packages_with_dependencies",
+ "author": [
+ {
+ "email": "libertad.gonzalez.de.la.cruz@intel.com",
+ "name": "libertad.gonzalez.de.la.cruz@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "Access a project page, either by creating a new project or accessing an existing project from the \"All projects\" table. \n\n ",
+ "expected_results": ""
+ },
+ "2": {
+ "action": "On the project page click on the \"New custom image\" link situated on the left-hand side, near Configuration, builds, import layer \n\n\n ",
+ "expected_results": " "
+ },
+ "3": {
+ "action": "Choose an image recipe example:(core-image-sato) and click on the customise button on the far right (note if that layer is not added the button will say +Add layer, add it and then customise) \n\n\n ",
+ "expected_results": "A pop out should appear and you should get to give the new image a customized name. Then you will be redirected to a page of Add|Remove Packages. If this image has not been build it will not have packages."
+ },
+ "4": {
+ "action": "Build the new image if it has not been build else start adding packages that have dependencies ( you will be able to see in the dependencies column a little square with a number, that tells you the dependencies it holds) example: libattr this holds 2 dependencies( bash and glibc) ",
+ "expected_results": " You should get a pop-out that that say \"$package_name dependencies\" then it should list the dependencies. Once clicked on the add packages button it should add the packages listed in the pop-out."
+ },
+ "5": {
+ "action": "Build the image again.",
+ "expected_results": ""
+ }
+ },
+ "summary": "Adding_packages_with_dependencies"
+ }
+ },
+ {
+ "test": {
+ "@alias": "toaster-managed-mode.toaster-managed.Create_Project",
+ "author": [
+ {
+ "email": "libertad.gonzalez.de.la.cruz@intel.com",
+ "name": "libertad.gonzalez.de.la.cruz@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "Start toaster",
+ "expected_results": ""
+ },
+ "2": {
+ "action": "Create a toaster project by issuing a name and selecting a release version.",
+ "expected_results": "Once project is created it should redirect you to a new project configuration page"
+ },
+ "3": {
+ "action": "Check that the h1 page title is set to the name the user typed in the new project form. ",
+ "expected_results": ""
+ }
+ },
+ "summary": "Create_Project"
+ }
+ },
+ {
+ "test": {
+ "@alias": "toaster-managed-mode.toaster-managed.Verify_project_detail_page_left_bar_menu",
+ "author": [
+ {
+ "email": "libertad.gonzalez.de.la.cruz@intel.com",
+ "name": "libertad.gonzalez.de.la.cruz@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "Start toaster",
+ "expected_results": ""
+ },
+ "2": {
+ "action": "Create a toaster project \n \n",
+ "expected_results": "Once project is created it should redirect you to a new project configuration page. \n\n"
+ },
+ "3": {
+ "action": "Check the page contains the tabs \n Configuration ---> selected by default \n Compatible Metadata (separation label) \n Custom images \n Image recipes \n Software recipes \n Machines \n Layers \n Extra Configuration (separation label) \n BitBake variables \n\n",
+ "expected_results": " All elements are present. \n\n"
+ },
+ "4": {
+ "action": "Click on each element to see if the h2 title is changing to the respective link clicked. Example if clicked on \"Custom Images\" then the h2 title should change to \"Custom images\"",
+ "expected_results": "All elements are clickable and h2 title changes to the corresponding title.."
+ }
+ },
+ "summary": "Verify_project_detail_page_left_bar_menu"
+ }
+ },
+ {
+ "test": {
+ "@alias": "toaster-managed-mode.toaster-managed.Configuration_information_of_Project_Detail_page",
+ "author": [
+ {
+ "email": "libertad.gonzalez.de.la.cruz@intel.com",
+ "name": "libertad.gonzalez.de.la.cruz@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "Clone Poky and start toaster \n\n",
+ "expected_results": ""
+ },
+ "2": {
+ "action": "Create a master toaster project \n \n",
+ "expected_results": "Once project is created it should redirect you to a new project configuration page \n\n"
+ },
+ "3": {
+ "action": "Check that the configuration button on the left side bar is selected by default \n\n",
+ "expected_results": " Expected result step 3 & 4: The configuration link next to the build link should be selected see attachment. \n\n\n\n"
+ },
+ "4": {
+ "action": "The configuration details should include canvas: \n Machine \n Most built recipes \n Layers \n Project Release ",
+ "expected_results": "Expected result step 4: A machine must always be set. \n\nThe default layers specified in the Toaster configuration must always be listed in the layer section (in our case, for the poky configuration we should have openembedded-core, meta-poky and meta-yocto-bsp)"
+ }
+ },
+ "summary": "Configuration_information_of_Project_Detail_page"
+ }
+ },
+ {
+ "test": {
+ "@alias": "toaster-managed-mode.toaster-managed.Verify_Machine_information_of_project_detail_page",
+ "author": [
+ {
+ "email": "libertad.gonzalez.de.la.cruz@intel.com",
+ "name": "libertad.gonzalez.de.la.cruz@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "Start toaster",
+ "expected_results": ""
+ },
+ "2": {
+ "action": "Create a toaster project \n \n",
+ "expected_results": "Expected result step 2: Once project is created it should redirect you to a new project Configuration page \n\n"
+ },
+ "3": {
+ "action": "The configuration details should include a label in bold font that says: \n Machine: this canvas should have the machine label type under it and an editing button on the side ",
+ "expected_results": "Expected result step 3: Compare to the attached snapshot. The machine must always be set."
+ }
+ },
+ "summary": "Verify_Machine_information_of_project_detail_page"
+ }
+ },
+ {
+ "test": {
+ "@alias": "toaster-managed-mode.toaster-managed.Verify_most_built_recipes_information_of_the_project_detail_page",
+ "author": [
+ {
+ "email": "libertad.gonzalez.de.la.cruz@intel.com",
+ "name": "libertad.gonzalez.de.la.cruz@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "Start toaster ",
+ "expected_results": ""
+ },
+ "2": {
+ "action": "Create a toaster project \n \n",
+ "expected_results": "Expected result step 2: Once project is created it should redirect you to a new project configuration page "
+ },
+ "3": {
+ "action": "The configuration details should include a label in bold font that says: \n Most built recipes: In this canvas one of the following information should show: \n\n a) If there has been no built recipes it should have a label that says: \n \"You haven't built any recipes yet, choose a recipe to build\" \n\n b) Else it should have a list of built recipes and a check box in front of it. So that it could be selected and built again ",
+ "expected_results": "Expected result step a: See ProjectDetailPage2.png attachment.\n\nExpected result step b: See ProjectDetailPage.png attachment."
+ }
+ },
+ "summary": "Verify_most_built_recipes_information_of_the_project_detail_page"
+ }
+ },
+ {
+ "test": {
+ "@alias": "toaster-managed-mode.toaster-managed.Verify_project_release_information_on_project_detail_page",
+ "author": [
+ {
+ "email": "libertad.gonzalez.de.la.cruz@intel.com",
+ "name": "libertad.gonzalez.de.la.cruz@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "Start toaster",
+ "expected_results": ""
+ },
+ "2": {
+ "action": "Create a toaster project \n \n",
+ "expected_results": "Expected result step 2: Once project is created it should redirect you to a new project configuration page. "
+ },
+ "3": {
+ "action": "The configuration details should include a label in bold font that says: \n Project release: this canvas should also have a label that show the release project you chose at the beginning.",
+ "expected_results": "Expected result step 3: See attachment ProjectDetailPage.jnp."
+ }
+ },
+ "summary": "Verify_project_release_information_on_project_detail_page"
+ }
+ },
+ {
+ "test": {
+ "@alias": "toaster-managed-mode.toaster-managed.Verify_layer_information_of_the_project_detail_page",
+ "author": [
+ {
+ "email": "libertad.gonzalez.de.la.cruz@intel.com",
+ "name": "libertad.gonzalez.de.la.cruz@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "Clone the poky environment git clone http://git.yoctoproject.org/git/poky",
+ "expected_results": ""
+ },
+ "2": {
+ "action": "Start toaster",
+ "expected_results": "Expected result step 2: Once project is created it should redirect you to a new project configuration page. \n\n"
+ },
+ "3": {
+ "action": "Create a toaster project \n \n",
+ "expected_results": "Expected result step 3: See attachment of layerCanvas.png\n"
+ },
+ "4": {
+ "action": "The configuration details should include a label with bold font that says: \n Layer: this canvas should have 3 layers listed by default (openembedded-core, meta-poky, and meta-yocto-bsp). \n Each layer should have a trashcan icon at the side that can be used to erase the label from the project. \n The layer canvas should have a text box with the text \"type a layer name\" a button \"Add layer\" next to it. \n just underneath a \"view compatible layer | import layer\" link. ",
+ "expected_results": ""
+ }
+ },
+ "summary": "Verify_layer_information_of_the_project_detail_page"
+ }
+ },
+ {
+ "test": {
+ "@alias": "toaster-managed-mode.toaster-managed.Verify_project_detail_links",
+ "author": [
+ {
+ "email": "libertad.gonzalez.de.la.cruz@intel.com",
+ "name": "libertad.gonzalez.de.la.cruz@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "Start toaster ",
+ "expected_results": ""
+ },
+ "2": {
+ "action": "Create a toaster project \n\n",
+ "expected_results": "Expected result step 2: Once project is created it should redirect you to a new project configuration page. \n\n"
+ },
+ "3": {
+ "action": "The configuration details should include \n 4 links, starting in the upper left side the Configuration link, Builds(#) link, Import layer link, and the New custom image link. \n\n ",
+ "expected_results": "Expected result step 3: All links should be clickable and should have information or tables, or forms. see attachment projectDetailLinks.png"
+ }
+ },
+ "summary": "Verify_project_detail_links"
+ }
+ },
+ {
+ "test": {
+ "@alias": "toaster-managed-mode.toaster-managed.Verify_build_texbox_exists_and_works",
+ "author": [
+ {
+ "email": "libertad.gonzalez.de.la.cruz@intel.com",
+ "name": "libertad.gonzalez.de.la.cruz@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "Start toaster",
+ "expected_results": ""
+ },
+ "2": {
+ "action": "Create a toaster project \n \n",
+ "expected_results": " Once project is created it should redirect you to a new project configuration page. \n\n\n"
+ },
+ "3": {
+ "action": "The configuration details should include \n After the 4 links (Configuration, Build(#), Import layer & New custom image) at the far right there should be a textbox with the label that says....\"Type the recipe you want to build\" and a button \"Build\" \n\n",
+ "expected_results": "See attachment buildTXT.png, The build button should be disabled whenever the text input field is empty, so that you cannot start a build with a blank target \n\n"
+ },
+ "4": {
+ "action": "Type in the textbox an image you would like to build example (core-image-minimal) and click the build button.\n\n",
+ "expected_results": " Image starts building. Whenever there is information in the image recipes and software recipes tables, the text input field should present suggestions from the list of recipes provided by the layers in the \"layers\" list. The suggestions contain the string typed in the input field, and update as you type. They appear on typing the second character. A maximum of 8 suggestions can be shown. They are sorted as follows: first recipes starting with the string, in alphabetical order; then recipes containing the string, also in alphabetical order \n\n\nWhen you click the build button you are brought to the \"Builds\" tab, and a new build in progress appears at the top of the \"Latest project builds\" section"
+ }
+ },
+ "summary": "Verify_build_texbox_exists_and_works."
+ }
+ },
+ {
+ "test": {
+ "@alias": "toaster-managed-mode.toaster-managed.Veryfing_the_builds_link_show_proper_information",
+ "author": [
+ {
+ "email": "libertad.gonzalez.de.la.cruz@intel.com",
+ "name": "libertad.gonzalez.de.la.cruz@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "Start toaster",
+ "expected_results": ""
+ },
+ "2": {
+ "action": "Create a toaster project \n \n",
+ "expected_results": " Once project is created it should redirect you to a new project configuration page. \n\n\n"
+ },
+ "3": {
+ "action": "The configuration details should include \n A builds tab that when clicking on, it should display one of the following: \n \n\n a) A label that says \"Latest project builds\" then a label with \"All project builds\" \n If you have a finished build or there is an ongoing builds then: \n You should see a progress bar of the ongoing builds in the project. \n You should see a table with the already done builds in the project. \n\n\n b) \"All project builds\" and a search textbox with a button nothing else only if there are no builds done in the project \n ",
+ "expected_results": "Expected result for step a): See ExistingBuilds.png attachment. \n\n\nExpected result for step b): See ZeroBuilds.png attachment. "
+ }
+ },
+ "summary": "Veryfing_the_builds_link_show_proper_information"
+ }
+ },
+ {
+ "test": {
+ "@alias": "toaster-managed-mode.toaster-managed.Verify_that_the_Import_layer_link_shows_the_form",
+ "author": [
+ {
+ "email": "libertad.gonzalez.de.la.cruz@intel.com",
+ "name": "libertad.gonzalez.de.la.cruz@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "Start toaster",
+ "expected_results": ""
+ },
+ "2": {
+ "action": "Create a toaster project \n\n",
+ "expected_results": " Once project is created it should redirect you to a new project configuration page. \n\n\n"
+ },
+ "3": {
+ "action": "The configuration details should include \n An Import layer link that when clicking on, it should display: \n A label that says \"Layer repository information\" \n A label that says \"The layer you are importing must be compatible with Yocto Project master, which is the release you are using in this project.\" \n Form composed of the following elements: \n Layer name : textbox \n Git repository URL : textbox \n Repository subdirectory (optional) : textbox \n Git revision : textbox \n Layer dependencies (optional) : \"openembedded-core\" link and (trash icon), textbox and \"Add layer\" button \n Import and add to project : button",
+ "expected_results": " See attachment ImportLayerForm.png"
+ }
+ },
+ "summary": "Verify_that_the_Import_layer_link_shows_the_form"
+ }
+ },
+ {
+ "test": {
+ "@alias": "toaster-managed-mode.toaster-managed.Verify_that_New_Custom_Image_link_works_and_shows_information",
+ "author": [
+ {
+ "email": "libertad.gonzalez.de.la.cruz@intel.com",
+ "name": "libertad.gonzalez.de.la.cruz@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "Start toaster",
+ "expected_results": ""
+ },
+ "2": {
+ "action": "Create a toaster project \n\n",
+ "expected_results": " Once project is created it should redirect you to a new project configuration page \n\n\n"
+ },
+ "3": {
+ "action": "The configuration details should include \n A \"New custom image\" tab that when clicking on, it should display: \n a Title label that says: \"Select the image recipe you want to customise(#number_or_recipes_available)\" \n A search textbox with the label of: \"Search and select the image recipe you want to customise\" \n A \"Search button\" \n A \"Edit columns\" button \n A table that will display the customise images available ",
+ "expected_results": "See attachment CustomImage.png"
+ }
+ },
+ "summary": "Verify_that_New_Custom_Image_link_works_and_shows_information"
+ }
+ },
+ {
+ "test": {
+ "@alias": "toaster-managed-mode.toaster-managed.Verify_most_built_recipe_shows_a_maximum_of_5_recipes",
+ "author": [
+ {
+ "email": "libertad.gonzalez.de.la.cruz@intel.com",
+ "name": "libertad.gonzalez.de.la.cruz@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "Start toaster",
+ "expected_results": ""
+ },
+ "2": {
+ "action": "Create a toaster project",
+ "expected_results": ""
+ },
+ "3": {
+ "action": "Build 6 recipes example (core-image-sato, core-image-minimal, core-image-base) to name a few. ",
+ "expected_results": " All recipes are built correctly \n\n"
+ },
+ "4": {
+ "action": "Wait for the recipes to finish ",
+ "expected_results": ""
+ },
+ "5": {
+ "action": "Go to the configuration details.",
+ "expected_results": " You should see 5 of the 6 recipes that were build. If you order the recipes in alphabetical order you should see that the first 5 made the list. "
+ }
+ },
+ "summary": "Verify_most_built_recipe_shows_a_maximum_of_5_recipes"
+ }
+ },
+ {
+ "test": {
+ "@alias": "toaster-managed-mode.toaster-managed.Verify_order_sequence_of_listing_in_Most_build_recipes",
+ "author": [
+ {
+ "email": "libertad.gonzalez.de.la.cruz@intel.com",
+ "name": "libertad.gonzalez.de.la.cruz@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "Start toaster",
+ "expected_results": ""
+ },
+ "2": {
+ "action": "Create a toaster project",
+ "expected_results": ""
+ },
+ "3": {
+ "action": "Build 6 recipes example (core-image-sato, core-image-minimal, core-image-base) to name a few. \n\n",
+ "expected_results": "All recipes are built correctly \n\n"
+ },
+ "4": {
+ "action": "Wait for the recipes to finish \n\n",
+ "expected_results": ""
+ },
+ "5": {
+ "action": "Go to the configuration details. \n\n",
+ "expected_results": " If you order the recipes in alphabetical order you should see that the first 5 made the list. Only 5 out of the 6 should make the list. \n\n"
+ },
+ "6": {
+ "action": "Select the 6th recipe that did not make the list and build it again. ",
+ "expected_results": " Since the 6th recipe is now built twice it should make the list and the recipe in the 5th place should not appear."
+ }
+ },
+ "summary": "Verify_order_sequence_of_listing_in_Most_build_recipes"
+ }
+ },
+ {
+ "test": {
+ "@alias": "toaster-managed-mode.toaster-managed.Verify_Most_build_recipes_multiple_selection",
+ "author": [
+ {
+ "email": "libertad.gonzalez.de.la.cruz@intel.com",
+ "name": "libertad.gonzalez.de.la.cruz@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "Start toaster",
+ "expected_results": ""
+ },
+ "2": {
+ "action": "Create a toaster project",
+ "expected_results": ""
+ },
+ "3": {
+ "action": "Build 4 recipes example (core-image-sato, core-image-minimal, core-image-base) to name a few. \n\n",
+ "expected_results": " All recipes are built correctly \n\n"
+ },
+ "4": {
+ "action": "Wait for the recipes to finish. \n\n",
+ "expected_results": ""
+ },
+ "5": {
+ "action": "Go to the configuration details. \n\n",
+ "expected_results": " You should see the 4 recipes in alphabetical order. You should also note that the Build button on the upper right hand corner is disabled since no recipe has been selected. \n\n"
+ },
+ "6": {
+ "action": "Select 1 of the recipes in the most built recipes section. \n\n",
+ "expected_results": "The build button is automatically enabled. \n\n"
+ },
+ "7": {
+ "action": "Select multiple (example 2 or 3) recipes in the most built recipes section. \n\n",
+ "expected_results": " The build button is enabled. \n\n"
+ },
+ "8": {
+ "action": "Click on the build button to start building the recipes.",
+ "expected_results": "One recipe start to build and the others are on queue."
+ }
+ },
+ "summary": "Verify_Most_build_recipes_multiple_selection"
+ }
+ },
+ {
+ "test": {
+ "@alias": "toaster-managed-mode.toaster-managed.Verify_layer_addition_functionality",
+ "author": [
+ {
+ "email": "libertad.gonzalez.de.la.cruz@intel.com",
+ "name": "libertad.gonzalez.de.la.cruz@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "Clone the poky environment git clone http://git.yoctoproject.org/git/poky",
+ "expected_results": ""
+ },
+ "2": {
+ "action": "Start toaster",
+ "expected_results": " Once project is created it should redirect you to a new project configuration page. \n\n"
+ },
+ "3": {
+ "action": "Create a toaster project with master release \n \n\n",
+ "expected_results": " See attachment of layerCanvas.png \n\n\n"
+ },
+ "4": {
+ "action": "Add layers by typing the name in the \"Type a layer name\" input box and adding by clicking the button. \n\n",
+ "expected_results": " A list of layers with similar name to the one you are typing should appear, giving you the choice to add it. The default text \"Type a layer name\" should disappear as soon as you start typing. \n\n"
+ },
+ "5": {
+ "action": "Add layers by clicking on the View compatible layers link just bellow the input text box. \n\n",
+ "expected_results": "This should redirect you to the compatible layers page where a list of compatible layers should appear and allow you to Add layers to the project. \n\n"
+ },
+ "6": {
+ "action": "Add a layer by importing a layer clicking in the Import layer",
+ "expected_results": "This link should redirect you to the import layer form where you will be able to add layers from git repository or a local directory. \n\n\n"
+ }
+ },
+ "summary": "Verify_layer_addition_functionality"
+ }
+ },
+ {
+ "test": {
+ "@alias": "toaster-managed-mode.toaster-managed.Verify_delete_layer_functionality",
+ "author": [
+ {
+ "email": "libertad.gonzalez.de.la.cruz@intel.com",
+ "name": "libertad.gonzalez.de.la.cruz@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "Clone the poky environment git clone http://git.yoctoproject.org/git/poky\n",
+ "expected_results": ""
+ },
+ "2": {
+ "action": "Start toaster",
+ "expected_results": " Once project is created it should redirect you to a new project configuration page.\n\n"
+ },
+ "3": {
+ "action": "Create a toaster project master release \n \n",
+ "expected_results": "See attachment of layerCanvas.png \n\n"
+ },
+ "4": {
+ "action": "Remove openembedded-core layer from the project by clicking the trash icon next to it. \n\n",
+ "expected_results": "The layer should disappear from the list and a notification should appear at the top of the page saying: \"You have removed 1 layer from your project: \". The layer_name should be a link to the corresponding layer detail page. The layer counter next to the \"layers\" heading should decrease by one. \n"
+ },
+ "5": {
+ "action": "Remove all the layers from the project",
+ "expected_results": " you should see a message that reads: \n\nYou need to add some layers. For that you can: \n\n-View all layers compatible with this project \n\n-Import a layer \n\n-Read about layers in the documentation \n\nOr type a layer name below. \n\n\n The \"Choose from the layers compatible with this project\" link should go to the compatible layers page The \"Import a layer\" link should go to the import layer page The \"Read about layers in the documentation\" link should open in a new window and bring you to http://www.yoctoproject.org/docs/current/dev-manual/dev-manual.html#understanding-and-creating-layers"
+ }
+ },
+ "summary": "Verify_delete_layer_functionality"
+ }
+ },
+ {
+ "test": {
+ "@alias": "toaster-managed-mode.toaster-managed.Download_task_log",
+ "author": [
+ {
+ "email": "alexandru.costinx.roman@intel.com",
+ "name": "alexandru.costinx.roman@intel.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "Start Toaster. ",
+ "expected_results": "Toaster starts."
+ },
+ "2": {
+ "action": "Click on new project button.\n\n",
+ "expected_results": "Open create a new project page."
+ },
+ "3": {
+ "action": " Enter a project name, select a release and click on create project or select an existing project. \n\n",
+ "expected_results": "Project Created."
+ },
+ "4": {
+ "action": "Build a recipe (ex: core-image-minimal). \n\n",
+ "expected_results": "Build finish."
+ },
+ "5": {
+ "action": "Click on the built recipe. \n\n",
+ "expected_results": "Open build summary page."
+ },
+ "6": {
+ "action": "Click on tasks tab. \n\n",
+ "expected_results": "Open tasks page."
+ },
+ "7": {
+ "action": "Click on a task executed successfully. \n\n",
+ "expected_results": "Open task page."
+ },
+ "8": {
+ "action": "Click on \"Download task log\" button. \n",
+ "expected_results": "You can download the task log. \n"
+ },
+ "9": {
+ "action": "Click on a failed task. \n",
+ "expected_results": "Open task page, not appear download task \n"
+ }
+ },
+ "summary": "Download_task_log"
+ }
+ }
+]
diff --git a/meta/lib/oeqa/manual/toaster-unmanaged-mode.json b/meta/lib/oeqa/manual/toaster-unmanaged-mode.json
new file mode 100644
index 0000000000..29d11a87d5
--- /dev/null
+++ b/meta/lib/oeqa/manual/toaster-unmanaged-mode.json
@@ -0,0 +1,1170 @@
+[
+ {
+ "test": {
+ "@alias": "toaster-unmanaged-mode.toaster-unmanaged.Create_a_Yocto_project_and_start_the_Toaster",
+ "author": [
+ {
+ "email": "Yuan.Sun2@windriver.com",
+ "name": "Yuan.Sun2@windriver.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "Set up yocto project and toaster test environment. \ncd ${installdir} \ngit clone git://git.yoctoproject.org/poky \n\n",
+ "expected_results": "NA \n\n"
+ },
+ "2": {
+ "action": "Start up toaster. \ncd ${installdir} \nsource poky/oe-init-build-env \nsource toaster start \n\n",
+ "expected_results": " \nlog: \nThe system will start. \nSyncing... \nCreating tables ... \nCreating table south_migrationhistory \nInstalling custom SQL ... \nInstalling indexes ... \nInstalled 0 object(s) from 0 fixture(s) \n > south \n\nNot synced (use migrations): \n - orm \n(use ./manage.py migrate to migrate these) \nRunning migrations for orm: \n - Migrating forwards to 0004_auto__add_field_package_installed_name. \n > orm:0001_initial \n > orm:0002_auto__add_field_build_timespent \n > orm:0003_timespent \n - Migration 'orm:0003_timespent' is marked for no-dry-run. \n > orm:0004_auto__add_field_package_installed_name \n - Loading initial data for orm. \nInstalled 0 object(s) from 0 fixture(s) \nserver address: 127.0.0.1, server port: 8200 \nSuccessful start."
+ },
+ "3": {
+ "action": "Build the yocto project. \nbitbake core-image-minimal \n\n",
+ "expected_results": "Build successfully. \n"
+ },
+ "4": {
+ "action": "Use a default web brower to see project build process. \nxdg-open http://localhost:8000/ \nWait for build completion. \n",
+ "expected_results": "You can open http://localhost:8000/ in a default browser. The build process is showed. "
+ }
+ },
+ "summary": "Create_a_Yocto_project_and_start_the_Toaster."
+ }
+ },
+ {
+ "test": {
+ "@alias": "toaster-unmanaged-mode.toaster-unmanaged.Sort_the_content_of_the_builds_table",
+ "author": [
+ {
+ "email": "Yuan.Sun2@windriver.com",
+ "name": "Yuan.Sun2@windriver.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "Start up toaster.",
+ "expected_results": "Succeed to start up toaster. "
+ },
+ "2": {
+ "action": "Create 2 builds, such as \"bitbake core-image-minimal\" and \"bitbake core-image-sato\". Wait for successful builds and then run: http://localhost:8000/",
+ "expected_results": "Succeed to build the targets. "
+ },
+ "3": {
+ "action": "Enter \"All build\" table in web browser.",
+ "expected_results": "NA "
+ },
+ "4": {
+ "action": "Click \"Completed on\" component to sort.",
+ "expected_results": "Build targets are sorted out by the \"Completed on\". "
+ },
+ "5": {
+ "action": "Click \"Completed on\" component again to invert the sorting .",
+ "expected_results": "The sorting is inverted. "
+ },
+ "6": {
+ "action": "Have a sort try in other columns. outcome, machine, started on, completed on, errors, warnings, project.",
+ "expected_results": "See item 4 and 5."
+ }
+ },
+ "summary": "Sort_the_content_of_the_builds_table."
+ }
+ },
+ {
+ "test": {
+ "@alias": "toaster-unmanaged-mode.toaster-unmanaged.Search_the_content_of_the_builds_table",
+ "author": [
+ {
+ "email": "Yuan.Sun2@windriver.com",
+ "name": "Yuan.Sun2@windriver.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "Start up toaster.",
+ "expected_results": "NA "
+ },
+ "2": {
+ "action": "Create 2 builds, such as \"bitbake core-image-minimal\" and \"bitbake core-image-sato\". Wait for successful builds and then run: xdg-open http://localhost:8000/",
+ "expected_results": "NA "
+ },
+ "3": {
+ "action": "Enter \"All build\" table in web browser.",
+ "expected_results": "NA "
+ },
+ "4": {
+ "action": "Input a string in search component and click search.",
+ "expected_results": "Show returned search results. When no search query has been entered, we have placeholder text saying: \"Search builds\". The placeholder text disappears when the first character is typed. "
+ },
+ "5": {
+ "action": "See returned search results.",
+ "expected_results": "If your search query returns no results, the section heading changes to \"No builds found\", and we show you an alert with a search form and an option to show all builds. "
+ },
+ "6": {
+ "action": "Click \"Clear search\" icon (icon-remove-sign). Observe all builds are showed. ",
+ "expected_results": "Click it to clear the search and display all builds."
+ }
+ },
+ "summary": "Search_the_content_of_the_builds_table."
+ }
+ },
+ {
+ "test": {
+ "@alias": "toaster-unmanaged-mode.toaster-unmanaged.Filter_the_content_of_the_builds_table",
+ "author": [
+ {
+ "email": "Yuan.Sun2@windriver.com",
+ "name": "Yuan.Sun2@windriver.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "Start up toaster.",
+ "expected_results": ""
+ },
+ "2": {
+ "action": "Create 2 builds, such as \"bitbake core-image-minimal\" and \"bitbake core-image-sato\". Wait for successful builds and then run: xdg-open http://localhost:8000/.",
+ "expected_results": ""
+ },
+ "3": {
+ "action": "Enter \"All build\" table in web browser.",
+ "expected_results": ""
+ },
+ "4": {
+ "action": "Make sure the following table columns have filters. \n- Outcome \n-- Started on \n- Completed on \n- Failed tasks",
+ "expected_results": ""
+ },
+ "5": {
+ "action": "Filters are mutually exclusive. Click a filter button of a one column and a filter dialogue occurs. Select a filter item. The filter result would be showed. Then select another filter item of another column and the previously applied filter is overridden by the newly selected filter when a filter from a different column is applied to the table. In this state, we show some help text next to the \"Apply\" button, saying \"You can only apply one filter to the table. This filter will override the current filter.\"",
+ "expected_results": ""
+ },
+ "6": {
+ "action": "Filters are overridden by search. Run a search query and you can see previous filter results are overridden by the results of the search query.",
+ "expected_results": ""
+ },
+ "7": {
+ "action": "Have a try in filters of the following table columns. \n- Outcome \n- Started on \n- Completed on \n- Failed tasks \n",
+ "expected_results": "NA"
+ }
+ },
+ "summary": "Filter_the_content_of_the_builds_table."
+ }
+ },
+ {
+ "test": {
+ "@alias": "toaster-unmanaged-mode.toaster-unmanaged.Tasks_in_toaster_UI",
+ "author": [
+ {
+ "email": "Yuan.Sun2@windriver.com",
+ "name": "Yuan.Sun2@windriver.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": " === TOASTER: Test Instructions for \"Tasks\", \"Time\", \"CPU Usage\", and \"Disk I/O\" pages === \n \nNOTE TO TESTERS: The three pages \"Time\", \"CPU Usage\", and \"Disk I/O\" are simple variations on the \"Tasks\" page. Those test instructions will demonstrate the respective unique parts. \n \n \n",
+ "expected_results": ""
+ },
+ "2": {
+ "action": "Start with a default Yocto project (qemux86), start the Toaster, and build \"bitbake core-image-minimal\". \n \n",
+ "expected_results": ""
+ },
+ "3": {
+ "action": "In Toaster, select the build, and select the \"Tasks\" link in the left sidebar \n \n",
+ "expected_results": ""
+ },
+ "4": {
+ "action": "Breadcrumbs \n \n * Observe that the 4 breadcrumbs at the top left are: \n \n : a live link that will take you back to the project page \n \t: a live link that will take you back to the project Builds page \n : a live link that will take you back to the image dashboard page \n \"Tasks\" \n \n * Test the breadcrumb live links, return to this page \n \n \n",
+ "expected_results": ""
+ },
+ "5": {
+ "action": "General Layout \n \n * Observe the left-hand box with links to the other pages of the build \n \n * Observe the title of the table is \"Tasks\", in bold \n \n * Observe the search/filter bar above the table \n \n * Observe the number of table rows in each page matches the number selected in the \"Show rows\" dropdown menu \n \n * Observe at the bottom of the page the \"Showing XX to XX out of xxx entries\", the page selection links, and the \"Show Rows\" selection. \n \n \n",
+ "expected_results": ""
+ },
+ "6": {
+ "action": "Columns \n \nNote: to restore the default columns in your browser, for example in Firefox, select \"Tools > Privacy > remove individual cookies\", find the cookies for the IP address of the Toaster engine (for example \"localhost\"), and remove each sub-cookie with the prefix \"_displaycols_*\" (or the whole cookie if those are the only sub-cookies). \n \n * Observe that the default columns are: \n \n \"Order, Recipe, Task, Executed, Outcome, Cache attempt\" \n \n * Click the \"Edit Columns\" button. ",
+ "expected_results": ""
+ },
+ "7": {
+ "action": "Observe that the fields are sorted as follows (with the indicated items greyed) \n \n [ ] CPU usage \n [x] Cache attempt \n [ ] Disk I/O (ms) \n [x] Executed \n [x] Order {greyed} \n [x] Outcome \n [x] Recipe {greyed} \n [ ] Recipe version \n [x] Task {greyed} \n [ ] Time (secs) \n \n * For each of the greyed items, attempt to click them. Observe that they do not change. \n \n * For each of the non-greyed items, attempt to click them. Observe that the respective column dynamically appears when checked and disappears when un-checked. ",
+ "expected_results": ""
+ },
+ "8": {
+ "action": "Search \n \n * Observe that the search text box background text is \"Search tasks\". \n \n * Set the search text to \"busybox\" and click \"Search\". Observe that only the busybox tasks are listed (about 16). \n \n * Click the \"X\" next to the search text box. Observe that all of the tasks re-appear. \n \n \n",
+ "expected_results": ""
+ },
+ "9": {
+ "action": "Column sorts \n \n * Enable all of the columns. \n \n * Observe that by default the \"Order\" column header is in bold, it has a down-arrow icon, and that the table is sorted by this column in ascending order. \n \n * Observe that the columns are in this order, and are sortable only if indicated: \n \n Order {sortable} \n Recipe {sortable} \n Recipe version \n Task {sortable} \n Executed {sortable} \n Outcome {sortable} \n Cache attempt {sortable} \n Time (secs) {sortable} \n CPU usage {sortable} \n Disk I/O (ms) {sortable} ",
+ "expected_results": ""
+ },
+ "10": {
+ "action": " Test that each of the sortable columns do sort, ascending and descending \n \n * Observe that each of the column headers have a question mark icon, and that hovering over it provides help text.",
+ "expected_results": ""
+ },
+ "11": {
+ "action": "\"Executed\" Filter \n \n * Observe that the \"Executed\" column has the filter icon. Click on it and observe these values, where \"All Tasks\" is the default \n \n (*) All Tasks \n ( ) Executed Tasks \n ( ) Not Executed Tasks \n \n * Click on \"Executed Tasks\" and observe that only rows with the value \"Executed\" are displayed. \n \n * Click on \"Not Executed Tasks\" and observe that only rows with the value \"Not Executed\" are displayed. \n \n * Click on \"All Tasks\" and observe that all rows are displayed. \n \n \n",
+ "expected_results": ""
+ },
+ "12": {
+ "action": "\"Outcome\" Filter \n \n * Observe that the \"Outcome\" column has the filter icon. Click on it and observe these values, where \"All Tasks\" is the default \n \n (*) All Tasks \n ( ) Succeeded Tasks \n ( ) Failed Tasks \n ( ) Cached Tasks \n ( ) Prebuilt Tasks \n ( ) Covered Tasks \n ( ) Empty Tasks \n \n * Click on each of the filter selections, and observe that the resulting row \"Outcome\" values match the selection. \n \n * Click on \"All Tasks\" and observe that all rows are displayed. \n \n \n1",
+ "expected_results": ""
+ },
+ "13": {
+ "action": "\"Cache attempt\" Filter \n \n * Observe that the \"Cache attempt\" column has the filter icon. Click on it and observe these values, where \"All Tasks\" is the default \n \n (*) All Tasks \n ( ) Tasks with cache attempts \n ( ) Tasks with 'File not in cache' attempts \n ( ) Tasks with 'Failed' cache attempts \n ( ) Tasks with 'Succeeded' cache attempts \n \n * Click on each of the filter selections, and observe that the resulting row \"Outcome\" values match the selection. \n \n Note the with a clean build, only the \"All Tasks\" and \"Tasks with cache attempts\" will return rows. \n \n * Click on \"All Tasks\" and observe that all rows are displayed. \n \n \n1",
+ "expected_results": ""
+ },
+ "14": {
+ "action": "Order, Task, Executed, Outcome, Cache attempt links \n \n * Observe that for a given row, the above values are live links that will both take you to the respective task detail page. Click the back button to return. \n\n * Observe that for a given row the values in \"Recipe\" and \"Recipe version\" are live links that will both take you to the respective recipe details page. Click the back button to return \n \n \n1",
+ "expected_results": ""
+ },
+ "15": {
+ "action": "Time Page \n \n * \"In Toaster, select the build, and select the \"Time\" link in the left sidebar \n \n * Observe that the default columns are: \n \n \"Recipe\", \"Task\", \"Executed\", \" Outcome\", \"Time (secs)\" \n \n * Observe that the default sort is \"Time (secs)\", in descending order. \n \n * In the \"Edit Columns\" button, turn on all of the columns. \n \n * Observe that the page now matches the \"Tasks\" page, and passes the same tests. \n \n \n1",
+ "expected_results": ""
+ },
+ "16": {
+ "action": "CPU Usage Page \n \n * \"In Toaster, select the build, and select the \"CPU Usage\" link in the left sidebar \n \n * Observe that the default columns are: \n \n \"Recipe\", \"Task\", \"Executed\", \"Outcome\", \"CPU Usage\" \n \n * Observe that the default sort is \"CPU Usage\", in descending order. \n \n * In the \"Edit Columns\" button, turn on all of the columns. \n \n * Observe that the page now matches the \"Tasks\" page, and passes the same tests. \n \n \n1",
+ "expected_results": ""
+ },
+ "17": {
+ "action": "Disk I/O Page \n \n * \"In Toaster, select the build, and select the \"Disk I/O\" link in the left sidebar \n \n * Observe that the default columns are: \n \n \"Recipe\", \"Task\", \"Executed\", \"Outcome\", \"Disk I/O (ms)\" \n \n * Observe that the default sort is \"Disk I/O (ms)\", in descending order. \n \n * In the \"Edit Columns\" button, turn on all of the columns. \n \n * Observe that the page now matches the \"Tasks\" page, and passes the same tests. ",
+ "expected_results": "NA"
+ }
+ },
+ "summary": "Tasks_in_toaster_UI"
+ }
+ },
+ {
+ "test": {
+ "@alias": "toaster-unmanaged-mode.toaster-unmanaged.package_detail_in_toaster_UI",
+ "author": [
+ {
+ "email": "Yuan.Sun2@windriver.com",
+ "name": "Yuan.Sun2@windriver.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "TOASTER: Test Instructions for \"Package Detail\" page \n \n",
+ "expected_results": ""
+ },
+ "2": {
+ "action": "Start with a default Yocto project (qemux86), start the Toaster, and build \"bitbake core-image-minimal\". ",
+ "expected_results": ""
+ },
+ "3": {
+ "action": "In Toaster, select the build, and select the \"Packages\" link in the left sidebar.",
+ "expected_results": ""
+ },
+ "4": {
+ "action": "Select a package from the \"Package\" column.",
+ "expected_results": ""
+ },
+ "5": {
+ "action": "Breadcrumbs \n * Observe that the 3 breadcrumbs at the top left are: \n : a live link that will take you back to the image dashboard page \n \"Packages\": a live link that will take you back to the Packages page \n \"bash\": the name of the current package (not a link) \n * Test the breadcrumb live links, return to this page ",
+ "expected_results": ""
+ },
+ "6": {
+ "action": "General Layout \n * Click on any package \n * Observe that there is no the left-hand box \n * Observe that there is a right-hand box, with information about the package \n * Observe the title is the package name and version, in bold \n * Observe that, if the package is installed in an image, there is a link to the image(s) the package appears in \n * Observe that, if the package is not installed in the image, there are two tab buttons below the title ",
+ "expected_results": ""
+ },
+ "7": {
+ "action": "Observe that the tab buttons are: \n Generated files (2) {highlighted} \n Runtime dependencies (4) \n",
+ "expected_results": ""
+ },
+ "8": {
+ "action": "Generated files tab \n * Click the \"Generated files\" tab (which should be selected by default) \n * Observe that the number of files in the table matches the number in parenthesis after the \"Generated files\" tab title. \n * Observe that the columns in the table are \"File\" and \"Size\" \n * Observe that the table is sorted by \"File\" in ascending alphabetical order (A to Z). ",
+ "expected_results": ""
+ },
+ "9": {
+ "action": "Runtime dependencies tab \n * Click the \"Runtime dependencies\" tab \n * Observe that the number of dependencies in the table matches the number in parenthesis after the \"Runtime dependencies\" tab title. \n * Observe that the columns in the table are: \n \"Package, Version, Size\" \n * Observe that the table is sorted by Package in ascending alphabetical order (A to Z) \n * Observe that the package name values are live links to the respective package details page. ",
+ "expected_results": "The information icon was eliminated on the columns that where self explanatory. "
+ },
+ "10": {
+ "action": "Package information box \n * Observe that there is a right-hand box, with information about the package, including in this example the fields: \n \"Size, License, Recipe, Recipe version, Layer, Layer branch, Layer commit\" \n * Observe that each of the field has a question mark icon, and that hovering will provide help text. \n * Observe that none of the values in the right-hand box are blank \n * Observe that the \"Recipe\" value is a live link to the respective recipe detail page. ",
+ "expected_results": ""
+ }
+ },
+ "summary": "package_detail_in_toaster_UI"
+ }
+ },
+ {
+ "test": {
+ "@alias": "toaster-unmanaged-mode.toaster-unmanaged.recipes:_Sort_the_content_of_the_recipes_table",
+ "author": [
+ {
+ "email": "Yuan.Sun2@windriver.com",
+ "name": "Yuan.Sun2@windriver.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "Start with a default Yocto project (qemux86), start the Toaster, and build \"bitbake core-image-minimal\". \n \n",
+ "expected_results": ""
+ },
+ "2": {
+ "action": "In Toaster, select the build, and select the \"Recipes\" link in the left sidebar. \n\n",
+ "expected_results": ""
+ },
+ "3": {
+ "action": "Make sure that by default the \"Recipes\" table is sorted by \"Recipe\" in ascending alphabetical order (A to Z). \n\n",
+ "expected_results": ""
+ },
+ "4": {
+ "action": "Sort my \"Recipes\" table by \"Section\" and then navigate away by selecting a recipe(such as click busybox recipe). When you click \"back\" button in web-browser to go back to the \"Recipes\" table it should still be sorted by \"Section\". \n\n",
+ "expected_results": ""
+ },
+ "5": {
+ "action": "Make sure all column headings are sortable, except \"Recipe version\", \"Dependencies\", \"Reverse dependencies\" and \"Layer commit\". \n\n",
+ "expected_results": ""
+ },
+ "6": {
+ "action": "Sorting and \"Edit columns\" \nIf you use the \"Edit columns\" menu to hide the column with the applied sorting, we revert the sorting to the default sorting (i.e. \"Recipe\"). The default sorting always uses one of the core columns, which cannot be hidden using the \"Edit columns\" menu. \nSort recipes by \"section\" column heading. Then hide \"Section\" column by \"Edit columns\". Make sure that the \"Recipes\" table is sorted by \"Recipe\" in ascending alphabetical order (A to Z). \nNOTE: Bug 5919 is filed against the issue. \n\n",
+ "expected_results": ""
+ },
+ "7": {
+ "action": "Sorting and search \nSearching should have no impact on the applied sorting. Any results returned should be sorted by the sorting criteria selected when the search query was submitted. \nSort recipes by \"section\" column heading. Input a string (such as \"lib\") in search box and click search button. Make sure results returned should be sorted by \"section\". \n",
+ "expected_results": "NA"
+ }
+ },
+ "summary": "recipes:_Sort_the_content_of_the_recipes_table."
+ }
+ },
+ {
+ "test": {
+ "@alias": "toaster-unmanaged-mode.toaster-unmanaged.recipes:_Search_the_content_of_the_recipes_table",
+ "author": [
+ {
+ "email": "Yuan.Sun2@windriver.com",
+ "name": "Yuan.Sun2@windriver.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "recipes: Search the content of the recipes table \n\n",
+ "expected_results": ""
+ },
+ "2": {
+ "action": "Start with a default Yocto project (qemux86), start the Toaster, and build \"bitbake core-image-minimal\". \n \n",
+ "expected_results": ""
+ },
+ "3": {
+ "action": "In Toaster, select the build, and select the \"Recipes\" link in the left sidebar. \n\n",
+ "expected_results": ""
+ },
+ "4": {
+ "action": "Observe the search is made of a text input field and a \"Search\" button in a toolbar above the table. \n\n",
+ "expected_results": ""
+ },
+ "5": {
+ "action": "When no search query has been entered, we have placeholder text saying: \"Search recipes\". \n\n",
+ "expected_results": ""
+ },
+ "6": {
+ "action": "Input \"lib\" in the text input field. The placeholder text disappears when the first character is typed. Click search button. \n\n",
+ "expected_results": ""
+ },
+ "7": {
+ "action": " \n(1) returned results \nThe search string is kept in the text input field. The results returned occur. Click \"Clear search\" icon to clear the search and display all recipes. \n(2) no results returned \nIf your search query returns no results, the page heading changes to \"No recipes found\", and we show you an alert with a search form and an option to show all recipes. Observe \"show all recipes\" button is available. \n\n",
+ "expected_results": ""
+ },
+ "8": {
+ "action": "When I run a search, the search happens against the following columns (independently of they being shown or hidden): \n- Recipe \n- Recipe version \n- Recipe file \n- Section \n- License \n- Layer \n- Layer branch \n- Layer commit \n\nInput a string to search for the above 8 column headings separately to make sure that the search happens against the columns. \n\n \n\n",
+ "expected_results": ""
+ },
+ "9": {
+ "action": "Search, sorting and \"Edit columns\" \nSearching does not change the state of the table: the same columns remain hidden and the same sorting applied when search results are displayed, but filters are cleared by the search results.\nSearch a string and make sure that the same columns remain hidden and the same sorting applied. Since filter feature of recipes (4296) is obsolete, we don't have to test filter. \n\n",
+ "expected_results": ""
+ },
+ "10": {
+ "action": "Search and filters \nThe scope of the filters is the content currently on the table (this means all table pages, not only the one displayed). The scope of the search is always the content of the database.\nSince filter feature of recipes (4296) is obsolete, we don't have to test filter. \n\nIf I run a search query, any filter applied afterwards will filter the content returned by the search query. \n\nIf I run a search query while a filter is applied, the filter is cleared by the results of the search query (i.e. we display the results of the search query and clear the filter applied beforehand).",
+ "expected_results": "NA"
+ },
+ "11": {
+ "action": " The same happens if I click the \"Clear search\" icon when a filter is applied to a set of search results (both search results and applied filter are cleared, and the table shows all the tasks). \nSince filter feature of recipes (4296) is obsolete, we don't have to test filter. \n\n",
+ "expected_results": "NA"
+ }
+ },
+ "summary": "recipes:_Search_the_content_of_the_recipes_table."
+ }
+ },
+ {
+ "test": {
+ "@alias": "toaster-unmanaged-mode.toaster-unmanaged.recipes:_Customise_the_columns_of_the_recipes_table",
+ "author": [
+ {
+ "email": "Yuan.Sun2@windriver.com",
+ "name": "Yuan.Sun2@windriver.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "Start with a default Yocto project (qemux86), start the Toaster, and build \"bitbake core-image-minimal\". \n \n",
+ "expected_results": ""
+ },
+ "2": {
+ "action": "In Toaster, select the build, and select the \"Recipes\" link in the left sidebar. \n\n",
+ "expected_results": ""
+ },
+ "3": {
+ "action": "* Observe that the default columns are: \n \"Recipe, Recipe version, Recipe file, Section , License, Layer\" \n \n * Click the \"Edit Columns\" button. \n * Observe that the fields are sorted as follows (with the indicated items greyed) \n [ ] Dependencies \n [x] Layer \n [ ] Layer branch \n [ ] Layer commit \n [x] License \n [x] Recipe {greyed} \n [x] Recipe file \n [x] Recipe version {greyed} \n [ ] Reverse dependencies \n [x] Section \n \n * For each of the greyed items, attempt to click them. Observe that they do not change. \n * For each of the non-greyed items, attempt to click them. Observe that the respective column dynamically appears when checked and disappears when un-checked.\n",
+ "expected_results": "NA"
+ }
+ },
+ "summary": "recipes:_Customise_the_columns_of_the_recipes_table."
+ }
+ },
+ {
+ "test": {
+ "@alias": "toaster-unmanaged-mode.toaster-unmanaged.recipes:_View_a_table_with_all_the_recipes_included_in_an_image_recipe",
+ "author": [
+ {
+ "email": "Yuan.Sun2@windriver.com",
+ "name": "Yuan.Sun2@windriver.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "Start with a default Yocto project (qemux86), start the Toaster, and build \"bitbake core-image-minimal\". \n \n",
+ "expected_results": ""
+ },
+ "2": {
+ "action": "In Toaster, select the build, and select the \"Recipes\" link in the left sidebar. \n\n",
+ "expected_results": ""
+ },
+ "3": {
+ "action": "By default, the all recipes table displays the following columns in this order: \n(1) Recipe (2) Recipe version: the target version and revision (3) Dependencies (4)Reverse Dependencies (5) License: the value of the target's LICENSE variable (6) Layer: the name of the layer providing the target \n\n",
+ "expected_results": ""
+ },
+ "4": {
+ "action": "In the \"Edit columns\" menu, table columns appear listed alphabetically. \nIn the table itself, the default order of columns is as follows: \n(1) Dependencies (2) Layer (3) Layer branch (4) Layer commit (5) License (6) Recipe (7) Recipe file (8) Reverse dependencies (9) Section (10) Version \n\nThe minimum table is made of the 2 columns that provide the information needed to identify a target: Recipe and Recipe version.",
+ "expected_results": "NA"
+ }
+ },
+ "summary": "recipes:_View_a_table_with_all_the_recipes_included_in_an_image_recipe"
+ }
+ },
+ {
+ "test": {
+ "@alias": "toaster-unmanaged-mode.toaster-unmanaged.recipes:_View_detailed_information_about_a_recipe。",
+ "author": [
+ {
+ "email": "Yuan.Sun2@windriver.com",
+ "name": "Yuan.Sun2@windriver.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "Create a default Yocto project (qemux86), and start the Toaster. \n \n $ source poky/oe-init-build-env \n $ source toaster start \n $ bitbake core-image-minimal \n $ http://localhost:8000/ \n \n",
+ "expected_results": ""
+ },
+ "2": {
+ "action": "Select the \"core-image-minimal\" build link \n \n",
+ "expected_results": ""
+ },
+ "3": {
+ "action": "Select the \"Recipes\" link in the left sidebar \n \nObserve that the recipes are listed in a table, and that each recipe name is a live URL link. \n \n",
+ "expected_results": ""
+ },
+ "4": {
+ "action": "Observe that \"Packages\" link. It should have an appended value like \"(4)\". Now click on this link. \n \nObserve: \n a) The number of packages matches the previous number in parenthesis. \n \n b) Each package has a version and a size. The size may be zero. \n \n c) Note that if you hover on a package name, it will reveal a URL of the following form. This link should take you to the corresponding package detail page. \n \n localhost:8000/gui/build//package/ \n \n",
+ "expected_results": ""
+ },
+ "5": {
+ "action": "Observe that recipes of \"Build Dependencies\" link has an appended value like \"(0)\". Now click on this link. \n \nObserve: \n a) No dependencies appear, and you get a message of the form: \n \n \"$RECIPE_NAME_VERSION has no build dependencies.\" \n \n",
+ "expected_results": ""
+ },
+ "6": {
+ "action": "Observe that \"Reverse build dependencies\" link has an appended value like \"(1)\". Now click on this link. \n \nObserve: \n a) The number of packages matches the previous number in parenthesis. \n \n b) The recipe dependency should be \"packagegroup-core-boot\", \n \n c) There should be a respective version displayed, for example \"1.0-r11\" \n \n d) If you hover on the recipe name, it will reveal a URL of the following form. This link should take you to the corresponding recipe detail page. \n \n localhost:8000/gui/build//recipe/ \n \n",
+ "expected_results": ""
+ },
+ "7": {
+ "action": "Click the breadcrumb \"Recipes\" at the top, locate the \"gdbm\" recipe, and select it. \n \n",
+ "expected_results": ""
+ },
+ "8": {
+ "action": "Observe that \"Packages\" link. It should have an appended value like \"(0)\". Now click on this link. \n \nObserve: \n a) No packages appear, and you get a message of the form: \n \n \"$PACKAGE_NAME_VERSION does not build any packages.\" \n \n",
+ "expected_results": ""
+ },
+ "9": {
+ "action": "Observe that \"Build dependencies\" link. It should have an appended value like \"(2)\". Now click on this link. \n \nObserve: \n a) The number of build dependencies matches the previous number in parenthesis. \n \n b) The recipe dependency should have values like \"gettext-native\" and \"libtool-cross\". \n \n c) There should be a respective versions displayed for each dependency. \n \n d) If you hover on a recipe name, it will reveal a URL of the following form. This link should take you to the corresponding recipe detail page. \n \n localhost:8000/gui/build//recipe/ \n \n1",
+ "expected_results": ""
+ },
+ "10": {
+ "action": "Observe that \"Reverse build dependencies\" link. It should have an appended value like \"(0)\". Now click on this link. \n \nObserve: \n a) No reverse dependencies appear, and you get a message of the form: \n \n \"$RECIPE_NAME_VERSION does not build any packages.",
+ "expected_results": "NA"
+ }
+ },
+ "summary": "recipes:_View_detailed_information_about_a_recipe。"
+ }
+ },
+ {
+ "test": {
+ "@alias": "toaster-unmanaged-mode.toaster-unmanaged.variables:_Search_the_content_of_the_bitbake_variables_table",
+ "author": [
+ {
+ "email": "Yuan.Sun2@windriver.com",
+ "name": "Yuan.Sun2@windriver.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "Start with a default Yocto project (qemux86), start the Toaster, and build \"bitbake core-image-minimal\". \n \n",
+ "expected_results": ""
+ },
+ "2": {
+ "action": "In Toaster, select the build, and select the \"Configuration\" link in the left sidebar. Then click \"BitBake variables\" tab. \n\n",
+ "expected_results": ""
+ },
+ "3": {
+ "action": "When no search query has been entered, we have placeholder text saying: \"Search BitBake variables\". \n\n",
+ "expected_results": ""
+ },
+ "4": {
+ "action": "Input \"lib\" in text input field. The placeholder text disappears when the first character is typed. Click search button. \n\n",
+ "expected_results": ""
+ },
+ "5": {
+ "action": "Observe \"4 variables found\" is showed. (It may be other number.) \n If your search query returns no results, we display an alert with: \n - A h3 heading saying: \"No variables found\" \n - A search box \n - The search query is showed in the text input shield. \n - A link to show all variables. we show the variables table. \n\n",
+ "expected_results": ""
+ },
+ "6": {
+ "action": "We provide a \"Clear search\" icon (icon-remove-sign). Click it to clear the search and display all variables. Check that the \"Clear search\" icon cannot be accessed using the tab key. \n\n",
+ "expected_results": ""
+ },
+ "7": {
+ "action": "Verify search scope. \nWhen I run a search, the search happens against the following columns (independently of they being shown or hidden): \n- Variable \n- Value \n- Set in file \n- Description \n\n",
+ "expected_results": ""
+ },
+ "8": {
+ "action": "Verify \"search, sorting and 'Edit columns'\" \nSearching does not change the state of the table: the same columns remain hidden and the same sorting applied \nwhen search results are displayed, but filters are cleared by the search results. \n\n",
+ "expected_results": ""
+ },
+ "9": {
+ "action": "Search and filters \nIf I run a search query, any filter applied afterwards will filter the content returned by the search query. \nIf I run a search query while a filter is applied, the filter is cleared by the results of the search query. \n",
+ "expected_results": "NA"
+ }
+ },
+ "summary": "variables:_Search_the_content_of_the_bitbake_variables_table"
+ }
+ },
+ {
+ "test": {
+ "@alias": "toaster-unmanaged-mode.toaster-unmanaged.variables:_Sort_the_content_of_the_bitbake_variables_table",
+ "author": [
+ {
+ "email": "Yuan.Sun2@windriver.com",
+ "name": "Yuan.Sun2@windriver.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "Start with a default Yocto project (qemux86), start the Toaster, and build \"bitbake core-image-minimal\". \n \n",
+ "expected_results": ""
+ },
+ "2": {
+ "action": "In Toaster, select the build, and select the \"Configuration\" link in the left sidebar. Then click \"BitBake variables\" tab. \n\n",
+ "expected_results": ""
+ },
+ "3": {
+ "action": "By default, the \"variables\" table is sorted by \"Variable\" in ascending alphabetical order (A to Z). \n\n",
+ "expected_results": ""
+ },
+ "4": {
+ "action": "Make sure that \"Variable\" column is sortable (Developers have disabled sort function of all other columns to avoid bug 6004) \n\n",
+ "expected_results": ""
+ },
+ "5": {
+ "action": "Sorting and search \nSearching should have no impact on the applied sorting. Any results returned should be sorted by the sorting criteria selected when the search query was submitted.",
+ "expected_results": "NA"
+ }
+ },
+ "summary": "variables:_Sort_the_content_of_the_bitbake_variables_table."
+ }
+ },
+ {
+ "test": {
+ "@alias": "toaster-unmanaged-mode.toaster-unmanaged.builds:_View_a_table_of_all_the_builds_run_for_a_certain_build_directory",
+ "author": [
+ {
+ "email": "Yuan.Sun2@windriver.com",
+ "name": "Yuan.Sun2@windriver.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "Start up toaster and open localhost:8000. ",
+ "expected_results": ""
+ },
+ "2": {
+ "action": "You can see 'Latest builds' section lists. - Builds in progress, sorted by inverse start time (last one starting at the top). - 3 latest completed builds, as long as they are less than 24 hours old. If there are no builds in progress or builds completed within the last 24 hours we don't display it: the page shows only the 'All builds' section. ",
+ "expected_results": ""
+ },
+ "3": {
+ "action": "You can see the following column headings. You can see the their description in https://bugzilla.yoctoproject.org/attachment.cgi?id=1617. outcome, recipe, machine, started on, completed on, failed tasks, errors, warnings, time, image files, project",
+ "expected_results": "NA"
+ }
+ },
+ "summary": "builds:_View_a_table_of_all_the_builds_run_for_a_certain_build_directory"
+ }
+ },
+ {
+ "test": {
+ "@alias": "toaster-unmanaged-mode.toaster-unmanaged.builds:_Customise_the_columns_of_the_builds_table",
+ "author": [
+ {
+ "email": "Yuan.Sun2@windriver.com",
+ "name": "Yuan.Sun2@windriver.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "Start up toaster.",
+ "expected_results": ""
+ },
+ "2": {
+ "action": "Create 2 builds, such as \"bitbake core-image-minimal\" and \"bitbake core-image-sato\". Wait for successful builds and then run: xdg-open http://localhost:8000/",
+ "expected_results": ""
+ },
+ "3": {
+ "action": "Enter \"All build\" table in web browser.",
+ "expected_results": ""
+ },
+ "4": {
+ "action": "Select a few item in \"Edit columns\" to show or hide them in all builds.",
+ "expected_results": "Unchecked items changed to checked should immediately appear in the table. Checked items changed to unchecked should immediately disappear from the table. If you uncheck the column with the applied sorting, when you close the \"Edit columns\" menu the applied sorting should revert to the table default sorting. Bug 5919 is filed for the function."
+ }
+ },
+ "summary": "builds:_Customise_the_columns_of_the_builds_table"
+ }
+ },
+ {
+ "test": {
+ "@alias": "toaster-unmanaged-mode.toaster-unmanaged.packages:_View_a_table_with_all_the_packages_built_for_an_image_recipe",
+ "author": [
+ {
+ "email": "Yuan.Sun2@windriver.com",
+ "name": "Yuan.Sun2@windriver.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "Start with a default Yocto project (qemux86), start the Toaster, and build \"bitbake core-image-minimal\". ",
+ "expected_results": ""
+ },
+ "2": {
+ "action": "In Toaster, select the build, and select the \"Packages\" link in the left sidebar. ",
+ "expected_results": ""
+ },
+ "3": {
+ "action": "By default, the built packages table displays the following columns in this order: Package, Package version, Size ",
+ "expected_results": ""
+ },
+ "4": {
+ "action": "Apart from the columns shown by default, the following additional columns are also available to users via the \"Edit columns\" menu: Layer, Layer branch, Layer commit, License, Recipe version ",
+ "expected_results": ""
+ },
+ "5": {
+ "action": "Enable these columns and observe that table columns appear listed alphabetically in the \"Edit columns\" menu (1)Package (2)Package version (3)Size (4)License (5)Recipe (6)Recipe version (7)Layer (8)Layer branch (9)Layer commit ",
+ "expected_results": ""
+ },
+ "6": {
+ "action": "The minimum table is made of the 2 columns that provide the information needed to identify a package: Package and Package version. Their corresponding checkboxes in the \"Edit columns\" menu appear always selected and are in an inactive state. ",
+ "expected_results": "NA"
+ }
+ },
+ "summary": "packages:_View_a_table_with_all_the_packages_built_for_an_image_recipe"
+ }
+ },
+ {
+ "test": {
+ "@alias": "toaster-unmanaged-mode.toaster-unmanaged.packages:_Sort_the_content_of_the_packages_table",
+ "author": [
+ {
+ "email": "Yuan.Sun2@windriver.com",
+ "name": "Yuan.Sun2@windriver.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "Start with a default Yocto project (qemux86), start the Toaster, and build \"bitbake core-image-minimal\". ",
+ "expected_results": ""
+ },
+ "2": {
+ "action": "In Toaster, select the build, and select the \"Packages\" link in the left sidebar. ",
+ "expected_results": ""
+ },
+ "3": {
+ "action": "Observe that by default the \"built packages\" table is sorted by \"Package\" in ascending alphabetical order (A to Z). ",
+ "expected_results": ""
+ },
+ "4": {
+ "action": "Click \"Size\" column heading to sort my \"built packages\" table by \"Size\". Then navigate away by selecting a package and you can see the package page. After click \"go back\" button in browser to return to the \"built packages\" table it should still be sorted by \"Size\". ",
+ "expected_results": ""
+ },
+ "5": {
+ "action": "Observe that all except \"Package version\", \"Recipe version\", \"Layer commit\" are sortable. ",
+ "expected_results": ""
+ },
+ "6": {
+ "action": "If you use the \"Edit columns\" menu to hide the column with the applied sorting, we revert the sorting to the default sorting (i.e. \"Package\"). The default sorting always uses one of the core columns, which cannot be hidden using the \"Edit columns\" menu. Bug 5919 is filed for the issue. ",
+ "expected_results": ""
+ },
+ "7": {
+ "action": "Searching should have no impact on the applied sorting. Any results returned should be sorted by the sorting criteria selected when the search query was submitted. Sort packages by size and search a string. Observe that results returned should be sorted by size. ",
+ "expected_results": ""
+ },
+ "8": {
+ "action": "In Toaster, select the build, and select the \"core-image*\" link in the left sidebar. Observe that by default the \"built packages\" table is sorted by \"Package\" in ascending alphabetical order (A to Z). ",
+ "expected_results": ""
+ },
+ "9": {
+ "action": "If choose to sort my \"included packages\" table by \"Size\" and then navigate away by selecting a package, when I go back to the \"included packages\" table it should still be sorted by \"Size\". ",
+ "expected_results": ""
+ },
+ "10": {
+ "action": "Enable all columns by \"Edit columns\". All except \"Package version\", \"Recipe version\", \"Dependencies\", \"Reverse dependencies\", \"Layer commit\", should be sortable. ",
+ "expected_results": ""
+ },
+ "11": {
+ "action": "If you use the \"Edit columns\" menu to hide the column with the applied sorting, we revert the sorting to the default sorting (i.e. \"Package\"). The default sorting always uses one of the core columns, which cannot be hidden using the \"Edit columns\" menu. Bug 5919 is filed for the issue. ",
+ "expected_results": ""
+ },
+ "12": {
+ "action": "Searching should have no impact on the applied sorting. Any results returned should be sorted by the sorting criteria selected when the search query was submitted. Sort packages by size and search a string. Observe that results returned should be sorted by size.",
+ "expected_results": "NA"
+ }
+ },
+ "summary": "packages:_Sort_the_content_of_the_packages_table"
+ }
+ },
+ {
+ "test": {
+ "@alias": "toaster-unmanaged-mode.toaster-unmanaged.packages:_Customise_the_columns_of_the_packages_table",
+ "author": [
+ {
+ "email": "Yuan.Sun2@windriver.com",
+ "name": "Yuan.Sun2@windriver.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "Start with a default Yocto project (qemux86), start the Toaster, and build \"bitbake core-image-minimal\". ",
+ "expected_results": ""
+ },
+ "2": {
+ "action": "In Toaster, select the build, and select the \"Packages\" link in the left sidebar. ",
+ "expected_results": ""
+ },
+ "3": {
+ "action": "Observe that by default the \"built packages\" table is sorted by \"Package\" in ascending alphabetical order (A to Z). ",
+ "expected_results": ""
+ },
+ "4": {
+ "action": "Select 1 column in \"Edit column\" to show the column. ",
+ "expected_results": ""
+ },
+ "5": {
+ "action": "Deselect 1 column in \"Edit column\" to hide 1 column by \"Edit columns\".",
+ "expected_results": "NA"
+ }
+ },
+ "summary": "packages:_Customise_the_columns_of_the_packages_table"
+ }
+ },
+ {
+ "test": {
+ "@alias": "toaster-unmanaged-mode.toaster-unmanaged.packages:_Search_the_content_of_the_packages_table",
+ "author": [
+ {
+ "email": "Yuan.Sun2@windriver.com",
+ "name": "Yuan.Sun2@windriver.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "Start with a default Yocto project (qemux86), start the Toaster, and build \"bitbake core-image-minimal\". ",
+ "expected_results": ""
+ },
+ "2": {
+ "action": "In Toaster, select the build, and select the \"Packages\" link in the left sidebar. ",
+ "expected_results": ""
+ },
+ "3": {
+ "action": "Observe that by default the \"built packages\" table is sorted by \"Package\" in ascending alphabetical order (A to Z). ",
+ "expected_results": ""
+ },
+ "4": {
+ "action": "When no search query has been entered, we have placeholder text saying: \"Search packages built\". The placeholder text disappears when the first character is typed. ",
+ "expected_results": ""
+ },
+ "5": {
+ "action": "When a search query has been submitted and results returned: â–ª We keep the search string in the text input field. â–ª We provide a \"Clear search\" icon (icon-remove-sign). Click it to clear the search and display all packages. â–ª We change the page heading to indicate the number of results returned by the search query. ",
+ "expected_results": ""
+ },
+ "6": {
+ "action": "If your search query returns no results, the page heading changes to \"No packages found\", and we show you an alert with a search form and an option to show all packages. ",
+ "expected_results": ""
+ },
+ "7": {
+ "action": "Searching does not change the state of the table: the same columns remain hidden and the same sorting applied. ",
+ "expected_results": ""
+ },
+ "8": {
+ "action": "When I run a search, the search happens against the following columns (independently of they being shown or hidden): - Package - Package version - License - Recipe - Recipe version - Layer - Layer branch - Layer commit ",
+ "expected_results": ""
+ },
+ "9": {
+ "action": "Hide all columns except \"Package\" and \"Package version\". Search a string which is included in other hidden columns, not the 2 columns. See if returned results occur. ",
+ "expected_results": ""
+ },
+ "10": {
+ "action": "In Toaster, select the build, and select the \"core-image*\" link in the left sidebar. Observe that by default the \"included packages\" table is sorted by \"Package\" in ascending alphabetical order (A to Z). Rerun tests according to step 4~9.",
+ "expected_results": "NA"
+ }
+ },
+ "summary": "packages:_Search_the_content_of_the_packages_table"
+ }
+ },
+ {
+ "test": {
+ "@alias": "toaster-unmanaged-mode.toaster-unmanaged.View_detailed_information_about_a_layer",
+ "author": [
+ {
+ "email": "Yuan.Sun2@windriver.com",
+ "name": "Yuan.Sun2@windriver.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "Start with a default Yocto project (qemux86), start the Toaster, and build \"bitbake core-image-minimal\". \n\n",
+ "expected_results": ""
+ },
+ "2": {
+ "action": "Make sure that layer information is shown in: \n* recipes table \n All builds-> core-image-minimal-> recipes \n Select \"Layer\", \"Layer branch\", \"Layer commit\" in Edit columns and observe the 3 columns are showed. Note that the \"Layer branch\" column can be empty. \n\n* recipe details \n All builds-> core-image-minimal-> recipes \n Click a recipe and you can see \"Layer\", \"Layer branch\", \"Layer commit\", \"Recipe details\" information. Note that \"Layer branch\" is not required. If there is no layer branch, you should not see the \"Layer branch\" item on the list.",
+ "expected_results": "NA"
+ },
+ "3": {
+ "action": "built packages table \n All builds-> core-image-minimal-> packages \n Select \"Layer\", \"Layer branch\", \"Layer commit\" in Edit columns and observer the 3 columns is showed. Note that the \"Layer branch\" column can be empty. \n\n* built package details \n All builds-> core-image-minimal-> packages \n Click a package and you can see \"Layer\", \"Layer branch\", \"Layer commit\" in package information. Note that \"Layer branch\" is not required. If there is no layer branch, you should not see the \"Layer branch\" item on the list. \n\n* image information \n All builds-> core-image-minimal-> core-image-minimal(images) \n Select \"Layer\", \"Layer branch\", \"Layer commit\" in Edit columns and observer the 3 columns is showed.",
+ "expected_results": "NA"
+ },
+ "4": {
+ "action": "Note that the \"Layer branch\" column can be empty. \n\n* installed package details \n All builds-> core-image-minimal-> core-image-minimal(images) \n Click a package and you can see layer information in package information. Note that \"Layer branch\" is not required. If there is no layer branch, you should not see the \"Layer branch\" item on the list. \n\n* configuration \n All builds-> core-image-minimal-> Configuration \n You can see \"Layer\", \"Layer branch\", \"Layer commit\" in configuration summary. Note that the \"Layer branch\" column can be empty. \n\n* build dashboard \n All builds-> core-image-minimal \n You can see \"Layers\" in build summary. ",
+ "expected_results": "NA"
+ }
+ },
+ "summary": "View_detailed_information_about_a_layer"
+ }
+ },
+ {
+ "test": {
+ "@alias": "toaster-unmanaged-mode.toaster-unmanaged.Select_the_number_of_table_rows_displayed_per_page",
+ "author": [
+ {
+ "email": "Yuan.Sun2@windriver.com",
+ "name": "Yuan.Sun2@windriver.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "Start with a default Yocto project (qemux86), start the Toaster, and build \"bitbake core-image-minimal\". ",
+ "expected_results": ""
+ },
+ "2": {
+ "action": "In Toaster, select the build, and select the \"Packages\" link in the left sidebar. ",
+ "expected_results": ""
+ },
+ "3": {
+ "action": "Users can select the number of rows they want to see in a table using the \"Show rows\" dropdown menu, which displays above and below each table. The options of the \"Show rows\" dropdown are: 10, 25, 50, 100, 150. ",
+ "expected_results": ""
+ },
+ "4": {
+ "action": "The last selected option from the \"Show rows\" menu should be remembered: * Select one option, for example 10 * Click on a package name to navigate away from the built packages table * Click on the \"Packages\" link in the breadcrumb at the top of the page to go back to the packages table Note that 25 is still selected in the \"Show rows\" menu. ",
+ "expected_results": ""
+ },
+ "5": {
+ "action": "Observe that the pagination widget is made of: - A \"Previous\" button - A \"Next\" button - A maximum of 5 page buttons. ",
+ "expected_results": ""
+ },
+ "6": {
+ "action": "See the pagination function of \"Tasks\", \"Recipes\" links according to steps 3~4.",
+ "expected_results": "Expected result for step 4: This widget has no previous or next button if testing in toaster 2.2. see Bug 9831"
+ }
+ },
+ "summary": "Select_the_number_of_table_rows_displayed_per_page"
+ }
+ },
+ {
+ "test": {
+ "@alias": "toaster-unmanaged-mode.toaster-unmanaged.View_detailed_configuration_information_for_a_build",
+ "author": [
+ {
+ "email": "Yuan.Sun2@windriver.com",
+ "name": "Yuan.Sun2@windriver.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "Start with a default Yocto project (qemux86), start the Toaster, and build \"bitbake core-image-minimal\". ",
+ "expected_results": ""
+ },
+ "2": {
+ "action": "In Toaster, select the build, and select the \"Configuration\" link in the left sidebar. ",
+ "expected_results": ""
+ },
+ "3": {
+ "action": "Observe that the configuration page has 2 tabs: - Summary - BitBake variables The Summary tab is the default tab. ",
+ "expected_results": ""
+ },
+ "4": {
+ "action": "The following content is included in summary tab. (1) Build configuration (2) Layers (Layer, Layer branch - if any, Layer commit) ",
+ "expected_results": ""
+ },
+ "5": {
+ "action": "Observe that \"BitBake variables\" tab includes \"Variable\", \"Value\", \" Set in file\", \"Description\" columns. ",
+ "expected_results": ""
+ },
+ "6": {
+ "action": "Click filter button of \"Set in file\" column. Select \"Local configuration variables\" and click \"Apply\" button to see if filter function works well. ",
+ "expected_results": ""
+ },
+ "7": {
+ "action": "In the \"Edit columns\" menu, table columns appear listed alphabetically: Description, Set in file, Value, Variable ",
+ "expected_results": ""
+ },
+ "8": {
+ "action": "The minimum table is made of the \"Variable\" and \"Value\" columns. ",
+ "expected_results": ""
+ },
+ "9": {
+ "action": "Click a variable and a \"History of ${variable}\" dialog will occur. The modal dialog shows the variable value followed by the history table, which has the following columns: - Order: indicates the sequence in which the files set the variable - Configuration file: the location in disk of the file that set the variable - Operation: the value of the operation field as stored in the database. - Line number: the line number where the operation is performed in the configuration file. For such variables, whose value is an empty string, the Value cell in the variables table isempty, which is probably the right thing. In the modal, instead of the variable value, we show an alert (with the class .alert-info) saying: \"The value of is an empty string\" ",
+ "expected_results": ""
+ },
+ "10": {
+ "action": "Click arrow links in description tab to see linking variables to the Yocto Project reference manual.",
+ "expected_results": "NA"
+ }
+ },
+ "summary": "View_detailed_configuration_information_for_a_build"
+ }
+ },
+ {
+ "test": {
+ "@alias": "toaster-unmanaged-mode.toaster-unmanaged.variables:_Customise_the_columns_of_the_bitbake_variables_table",
+ "author": [
+ {
+ "email": "Yuan.Sun2@windriver.com",
+ "name": "Yuan.Sun2@windriver.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "Start with a default Yocto project (qemux86), start the Toaster, and build \"bitbake core-image-minimal\". ",
+ "expected_results": ""
+ },
+ "2": {
+ "action": "In Toaster, select the build, and select the \"Configuration\" link in the left sidebar. Then click \"BitBake variables\" tab. ",
+ "expected_results": ""
+ },
+ "3": {
+ "action": "Show or hide columns by select or deselect options of \"Edit columns\".",
+ "expected_results": "NA"
+ }
+ },
+ "summary": "variables:_Customise_the_columns_of_the_bitbake_variables_table"
+ }
+ },
+ {
+ "test": {
+ "@alias": "toaster-unmanaged-mode.toaster-unmanaged.variables:_Filter_the_content_of_the_bitbake_variables_table",
+ "author": [
+ {
+ "email": "Yuan.Sun2@windriver.com",
+ "name": "Yuan.Sun2@windriver.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "Start with a default Yocto project (qemux86), start the Toaster, and build \"bitbake core-image-minimal\". \n \n",
+ "expected_results": ""
+ },
+ "2": {
+ "action": "In Toaster, select the build, and select the \"Configuration\" link in the left sidebar. Then click \"BitBake variables\" tab. \n\n",
+ "expected_results": ""
+ },
+ "3": {
+ "action": "Observe \"Set in file\" and \"Description\" columns have filters. \n\n",
+ "expected_results": ""
+ },
+ "4": {
+ "action": "Filters are mutually exclusive. Only one column filter can be applied to a table at any given time. \n\n",
+ "expected_results": ""
+ },
+ "5": {
+ "action": "Filters are overridden by search. \nThe scope of the filters is the content currently on the table. \nThe scope of the search is always the full content of the database. \nSo: \n- if I run a search query, any filter applied afterwards will filter the content returned by the search query. \nSearch a string and apply a filter. Observe it would filter the content returned by the search query. \n\n- if I run a search query while a filter is applied, the filter is overridden by the results of the search query. \nApply a filter and search a string. Observe that the previous filtered result is overridden by the search. ",
+ "expected_results": "NA"
+ }
+ },
+ "summary": "variables:_Filter_the_content_of_the_bitbake_variables_table"
+ }
+ },
+ {
+ "test": {
+ "@alias": "toaster-unmanaged-mode.toaster-unmanaged.View_and_navigate_the_full_directory_structure_of_built_images",
+ "author": [
+ {
+ "email": "Yuan.Sun2@windriver.com",
+ "name": "Yuan.Sun2@windriver.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "Start with a default Yocto project (qemux86), start the Toaster, and build \"bitbake core-image-minimal\". \n \n",
+ "expected_results": ""
+ },
+ "2": {
+ "action": "In Toaster, select the build, and select the \"core-image-minimal\" link in the left sidebar. \n\n",
+ "expected_results": ""
+ },
+ "3": {
+ "action": "Observe image information page has 2 tabs: \n- Packages included: this tab shows a table with all the packages installed in the image. The tab label includes the total number of packages listed in the table and their size. \n- Directory structure: this tab shows all the files included in the image. \n\n",
+ "expected_results": ""
+ },
+ "4": {
+ "action": "By default, the included packages table displays the following columns in this order: \nPackage, Package version, Size, Dependencies \n\n",
+ "expected_results": ""
+ },
+ "5": {
+ "action": "Apart from the columns shown by default, the following additional columns are also available to users via the \"Edit columns\" menu: \nLayer, Layer branch, Layer commit, License, Recipe, Recipe version. \n\n",
+ "expected_results": ""
+ },
+ "6": {
+ "action": "The minimum table is made of the 2 columns that provide the information needed to identify a package: Package and Package version. \n\n",
+ "expected_results": ""
+ },
+ "7": {
+ "action": "By default, the directory structure table shows the top level directories and files in the file system.\nThe table includes the following columns: \nDirectory/File, Symbolic link to, Source package, Size, Permissions, Owner, Group \nOpen some directories and see files. ",
+ "expected_results": "NA"
+ }
+ },
+ "summary": "View_and_navigate_the_full_directory_structure_of_built_images"
+ }
+ },
+ {
+ "test": {
+ "@alias": "toaster-unmanaged-mode.toaster-unmanaged.View_a_summary_of_all_the_information_available_for_a_build",
+ "author": [
+ {
+ "email": "Yuan.Sun2@windriver.com",
+ "name": "Yuan.Sun2@windriver.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "Start with a default Yocto project (qemux86), start the Toaster, and build \"bitbake core-image-minimal\". \n \n",
+ "expected_results": ""
+ },
+ "2": {
+ "action": "In Toaster, select the build. \n\n",
+ "expected_results": ""
+ },
+ "3": {
+ "action": "A 'Build dashboard' page is showed. \nThe 'Build dashboard' page has two main states: \n(1) Success state: when the build completes successfully. In the success state, if the build target(s) include an image recipe, the page displays an image content module, and the left navigation has an \"Images\" section at the top. \n(2) Fail state: when the build fails (shown in this page). In the fail state, the page always displays an errors content module, and the left navigation does not have an \"Images\" section at the top. \n\n",
+ "expected_results": ""
+ },
+ "4": {
+ "action": "Observe that the page provides access to all information available for the selected build. \n(1) Images \n(2) Build: this group provides links to the following pages: \nConfiguration, Tasks, Recipes, Packages \n(3) Performance: this group provides links to the following pages: \nTime, CPU usage, Disk I/O \n\n",
+ "expected_results": ""
+ },
+ "5": {
+ "action": "The page heading is made of the build target(s) and the machine, such as \"core-image-minimal qemux86\". If the build has more than one target, they show in ascending alphabetical order (A to Z) both in the page heading and in the \"Images\" section of the left navigation. If the build was successful, there is an image content module for each target that is an image recipe. The modules also show in ascending alphabetical order by target name. \n\n",
+ "expected_results": ""
+ },
+ "6": {
+ "action": "Packages included, total package size, license manifest, image files are included in the images section. \n\n",
+ "expected_results": ""
+ },
+ "7": {
+ "action": "The information of Machine, Distro, Layers is included in configuration content module of \"Build summary\" section. \nThe information of \"Total number of task\", \"Tasks executed\", \" Tasks not executed\", \"Reuse\" is included in the tasks content module. \nThe information of \"Recipes built\" and \"Packages built\" is included in the \"Recipes&Packages\" content module. ",
+ "expected_results": "NA"
+ }
+ },
+ "summary": "View_a_summary_of_all_the_information_available_for_a_build"
+ }
+ },
+ {
+ "test": {
+ "@alias": "toaster-unmanaged-mode.toaster-unmanaged.Display_the_content_of_error_messages_and_warnings",
+ "author": [
+ {
+ "email": "Yuan.Sun2@windriver.com",
+ "name": "Yuan.Sun2@windriver.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "Start with a default Yocto project (qemux86), start the Toaster, and create a successful build and a failed build. You can force a build to terminate by ctrl+c. ",
+ "expected_results": ""
+ },
+ "2": {
+ "action": "Observe that the number of errors and warnings thrown by a build shows in both 'All builds' page and the 'Latest builds' section. ",
+ "expected_results": ""
+ },
+ "3": {
+ "action": "Observe that the number and content of errors and warnings thrown by a build shows in the 'Build dashboard' page. ",
+ "expected_results": ""
+ },
+ "4": {
+ "action": "Click warning or error links to see warning and error details. ",
+ "expected_results": "NA"
+ }
+ },
+ "summary": "Display_the_content_of_error_messages_and_warnings."
+ }
+ },
+ {
+ "test": {
+ "@alias": "toaster-unmanaged-mode.toaster-unmanaged.Build_summary_information_fully_implemented",
+ "author": [
+ {
+ "email": "Yuan.Sun2@windriver.com",
+ "name": "Yuan.Sun2@windriver.com"
+ }
+ ],
+ "execution": {
+ "1": {
+ "action": "Start with a default Yocto project (qemux86), start the Toaster, and create 4 builds. \na) a successful build with images (bitbake core-image-minimal) \nb) a successful build without images (bitbake mtools-native) \nc) a failed build with errors and warnings (run \"bitbake core-image-sato\", then press control+c to terminate the build)",
+ "expected_results": ""
+ },
+ "2": {
+ "action": "In Toaster, select a core-image-minimal build.",
+ "expected_results": ""
+ },
+ "3": {
+ "action": "Observe that there is a 'Build dashboard' page captured by Toaster. The page does not exist for builds in progress, only for finished builds. \nThe 'Build dashboard' page is made of: \na) Breadcrumb \nb) Navigation \n IMAGES: core-image-minimal \n BUILD: \n Configuration \n Tasks \n Recipes \n Packages \n PERFORMANCE: \n Time \n CPU usage \n Disk I/O \nc) Page heading (core-image-minimal qemux86) \nd) Section heading (Images, Build summary) \ne) Build status notification (Completed on xx/xx/xx... Build time:xx:xx:xx)",
+ "expected_results": ""
+ },
+ "4": {
+ "action": "Observe \"images\" section is made of the following \n.\na) Heading: core-image-minimal, which links to the \"Packages included\" tab of the image information page \nb) Number of packages installed: (packages included xx), which is a link to the \"Packages included\" tab of the image information page \nc) Total installed package size: xxMB \nd) License manifest (which is a link to the \"Packages included\" tab of the information page with the following columns showing: \"Package\", \"Package version\", \"License\" and \"Recipe\". We have bug 6079 open for this). Next to the license manifest is the path to the directory where you can find the license manifest file. \n \ne) Image files (rootfs file names and rootfs file sizes)",
+ "expected_results": ""
+ },
+ "5": {
+ "action": "Observe \"Build summary\" section is made of the following. \na) Configuration (which is a link to the configuration page): \n Machine \n Distro \n Layers (sorted in alphabetical order) \nb) Tasks (which is a link to the tasks page) \n Total number of tasks (which is a link to the tasks page) \n Tasks executed (which is a link to the tasks page with the tasks executed filter applied) \n Tasks not executed (which is a link to the tasks pages with the tasks not executed filter applied)\n Reuse \nc) Note that \"Total number of tasks\" should equal number of \"Tasks executed\" + number of \"Tasks not executed\" \nd) Recipes (which is a link to the recipes page) & Packages (which is a link to the packages built page) ",
+ "expected_results": ""
+ },
+ "6": {
+ "action": " Number of recipes built (which is a link to the recipes page) \n \n Number of packages built (which is a link to the packages built page)",
+ "expected_results": ""
+ },
+ "7": {
+ "action": "Return to localhost:8000 and select a successful build without images (mtools-native) \n.\nObserve the build dashboard for a successful build of a target that is not an image recipe. There is no image content module, and no \"Images\" section in the left navigation.",
+ "expected_results": ""
+ },
+ "8": {
+ "action": "Return to localhost:8000 and select the failed build (core-image-sato). Observe the build dashboard for the failed build. \n \na) the errors content module: \nThis module exists for those builds that throw error(s). It appears immediately below the build status notification. \nThe module has 2 states: \nâ–ª Expanded (shows number of errors and error content) \nâ–ª Collapsed (shows only the number of errors) \nBy default, the errors module is in the expanded state. \nErrors content modules include the following information: \n(1.1) A heading, which indicates the number of errors thrown by the build, and toggles the module between its 2 states on click. ",
+ "expected_results": "NA"
+ },
+ "9": {
+ "action": "Transitions between states should use a slide up / slide down animation. \n(1.2) Error(s) content \n\nb) the warning content module: \nThis module exists for those builds that throw warning(s). \nIt is the last content module shown on the build dashboard. \nThe module has 2 states: \nâ–ª Expanded (shows number of warnings and warning content) \nâ–ª Collapsed (shows only the number of warnings) \nBy default, the warning module is in the collapsed state. Warnings content modules include the following information: \n(2.1) A heading, which indicates the number of warnings thrown by the build, and toggles the module between its 2 \nstates on click. Transitions between states should use a slide up / slide down animation. \n(2.2) Warning(s) content ",
+ "expected_results": "NA"
+ }
+ },
+ "summary": "Build_summary_information_fully_implemented"
+ }
+ }
+] \ No newline at end of file
diff --git a/meta/lib/oeqa/oetest.py b/meta/lib/oeqa/oetest.py
index e63ca56165..cf417db0d4 100644
--- a/meta/lib/oeqa/oetest.py
+++ b/meta/lib/oeqa/oetest.py
@@ -1,13 +1,15 @@
+#
# Copyright (C) 2013 Intel Corporation
#
-# Released under the MIT license (see COPYING.MIT)
+# SPDX-License-Identifier: MIT
+#
# Main unittest module used by testimage.bbclass
# This provides the oeRuntimeTest base class which is inherited by all tests in meta/lib/oeqa/runtime.
# It also has some helper functions and it's responsible for actually starting the tests
-import os, re, mmap, sys
+import os, re, sys
import unittest
import inspect
import subprocess
@@ -26,8 +28,7 @@ try:
import oeqa.sdkext
except ImportError:
pass
-from oeqa.utils.decorators import LogResults, gettag, getResults
-from oeqa.utils import avoid_paths_in_environ
+from oeqa.utils.decorators import LogResults, gettag
logger = logging.getLogger("BitBake")
@@ -56,7 +57,6 @@ def filterByTagExp(testsuite, tagexp):
@LogResults
class oeTest(unittest.TestCase):
- pscmd = "ps"
longMessage = True
@classmethod
@@ -107,62 +107,14 @@ class oeRuntimeTest(oeTest):
pass
def tearDown(self):
- # Unistall packages in the DUT
+ # Uninstall packages in the DUT
self.tc.install_uninstall_packages(self.id(), False)
-
- res = getResults()
- # If a test fails or there is an exception dump
- # for QemuTarget only
- if (type(self.target).__name__ == "QemuTarget" and
- (self.id() in res.getErrorList() or
- self.id() in res.getFailList())):
- self.tc.host_dumper.create_dir(self._testMethodName)
- self.tc.host_dumper.dump_host()
- self.target.target_dumper.dump_target(
- self.tc.host_dumper.dump_dir)
- print ("%s dump data stored in %s" % (self._testMethodName,
- self.tc.host_dumper.dump_dir))
-
self.tearDownLocal()
# Method to be run after tearDown and implemented by child classes
def tearDownLocal(self):
pass
- #TODO: use package_manager.py to install packages on any type of image
- def install_packages(self, packagelist):
- for package in packagelist:
- (status, result) = self.target.run("smart install -y "+package)
- if status != 0:
- return status
-
-class oeSDKTest(oeTest):
- def __init__(self, methodName='runTest'):
- self.sdktestdir = oeSDKTest.tc.sdktestdir
- super(oeSDKTest, self).__init__(methodName)
-
- @classmethod
- def hasHostPackage(self, pkg):
-
- if re.search(pkg, oeTest.tc.hostpkgmanifest):
- return True
- return False
-
- def _run(self, cmd):
- return subprocess.check_output(". %s > /dev/null; %s;" % (self.tc.sdkenv, cmd), shell=True).decode("utf-8")
-
-class oeSDKExtTest(oeSDKTest):
- def _run(self, cmd):
- # extensible sdk shows a warning if found bitbake in the path
- # because can cause contamination, i.e. use devtool from
- # poky/scripts instead of eSDK one.
- env = os.environ.copy()
- paths_to_avoid = ['bitbake/bin', 'poky/scripts']
- env['PATH'] = avoid_paths_in_environ(paths_to_avoid)
-
- return subprocess.check_output(". %s > /dev/null;"\
- " %s;" % (self.tc.sdkenv, cmd), shell=True, env=env).decode("utf-8")
-
def getmodule(pos=2):
# stack returns a list of tuples containg frame information
# First element of the list the is current frame, caller is 1
@@ -213,15 +165,16 @@ class TestContext(object):
path = [os.path.dirname(os.path.abspath(__file__))]
extrapath = ""
else:
- path = d.getVar("BBPATH", True).split(':')
+ path = d.getVar("BBPATH").split(':')
extrapath = "lib/oeqa"
self.testslist = self._get_tests_list(path, extrapath)
self.testsrequired = self._get_test_suites_required()
self.filesdir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "runtime/files")
- self.imagefeatures = d.getVar("IMAGE_FEATURES", True).split()
- self.distrofeatures = d.getVar("DISTRO_FEATURES", True).split()
+ self.corefilesdir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "files")
+ self.imagefeatures = d.getVar("IMAGE_FEATURES").split()
+ self.distrofeatures = d.getVar("DISTRO_FEATURES").split()
# get testcase list from specified file
# if path is a relative path, then relative to build/conf/
@@ -265,8 +218,6 @@ class TestContext(object):
if "auto" in self.testsuites:
def add_auto_list(path):
- if not os.path.exists(os.path.join(path, '__init__.py')):
- bb.fatal('Tests directory %s exists but is missing __init__.py' % path)
files = sorted([f for f in os.listdir(path) if f.endswith('.py') and not f.startswith('_')])
for f in files:
module = 'oeqa.' + type + '.' + f[:-3]
@@ -397,14 +348,12 @@ class RuntimeTestContext(TestContext):
def __init__(self, d, target, exported=False):
super(RuntimeTestContext, self).__init__(d, exported)
- self.tagexp = d.getVar("TEST_SUITES_TAGS", True)
-
self.target = target
self.pkgmanifest = {}
- manifest = os.path.join(d.getVar("DEPLOY_DIR_IMAGE", True),
- d.getVar("IMAGE_LINK_NAME", True) + ".manifest")
- nomanifest = d.getVar("IMAGE_NO_MANIFEST", True)
+ manifest = os.path.join(d.getVar("DEPLOY_DIR_IMAGE"),
+ d.getVar("IMAGE_LINK_NAME") + ".manifest")
+ nomanifest = d.getVar("IMAGE_NO_MANIFEST")
if nomanifest is None or nomanifest != "1":
try:
with open(manifest) as f:
@@ -420,24 +369,19 @@ class RuntimeTestContext(TestContext):
def _get_test_suites(self):
testsuites = []
- manifests = (self.d.getVar("TEST_SUITES_MANIFEST", True) or '').split()
+ manifests = (self.d.getVar("TEST_SUITES_MANIFEST") or '').split()
if manifests:
for manifest in manifests:
testsuites.extend(self._read_testlist(manifest,
- self.d.getVar("TOPDIR", True)).split())
+ self.d.getVar("TOPDIR")).split())
else:
- testsuites = self.d.getVar("TEST_SUITES", True).split()
+ testsuites = self.d.getVar("TEST_SUITES").split()
return testsuites
def _get_test_suites_required(self):
- return [t for t in self.d.getVar("TEST_SUITES", True).split() if t != "auto"]
-
- def loadTests(self):
- super(RuntimeTestContext, self).loadTests()
- if oeTest.hasPackage("procps"):
- oeRuntimeTest.pscmd = "ps -ef"
+ return [t for t in self.d.getVar("TEST_SUITES").split() if t != "auto"]
def extract_packages(self):
"""
@@ -445,8 +389,10 @@ class RuntimeTestContext(TestContext):
"""
modules = self.getTestModules()
- bbpaths = self.d.getVar("BBPATH", True).split(":")
+ bbpaths = self.d.getVar("BBPATH").split(":")
+ shutil.rmtree(self.d.getVar("TEST_EXTRACTED_DIR"))
+ shutil.rmtree(self.d.getVar("TEST_PACKAGED_DIR"))
for module in modules:
json_file = self._getJsonFile(module)
if json_file:
@@ -458,8 +404,10 @@ class RuntimeTestContext(TestContext):
Extract packages that will be needed during runtime.
"""
- extracted_path = self.d.getVar("TEST_EXTRACTED_DIR", True)
- packaged_path = self.d.getVar("TEST_PACKAGED_DIR", True)
+ import oe.path
+
+ extracted_path = self.d.getVar("TEST_EXTRACTED_DIR")
+ packaged_path = self.d.getVar("TEST_PACKAGED_DIR")
for key,value in needed_packages.items():
packages = ()
@@ -481,13 +429,18 @@ class RuntimeTestContext(TestContext):
dst_dir = os.path.join(packaged_path)
# Extract package and copy it to TEST_EXTRACTED_DIR
- if extract and not os.path.exists(dst_dir):
- pkg_dir = self._extract_in_tmpdir(pkg)
- shutil.copytree(pkg_dir, dst_dir)
+ pkg_dir = self._extract_in_tmpdir(pkg)
+ if extract:
+
+ # Same package used for more than one test,
+ # don't need to extract again.
+ if os.path.exists(dst_dir):
+ continue
+ oe.path.copytree(pkg_dir, dst_dir)
shutil.rmtree(pkg_dir)
# Copy package to TEST_PACKAGED_DIR
- elif not extract:
+ else:
self._copy_package(pkg)
def _getJsonFile(self, module):
@@ -535,7 +488,7 @@ class RuntimeTestContext(TestContext):
from oeqa.utils.package_manager import get_package_manager
- pkg_path = os.path.join(self.d.getVar("TEST_INSTALL_TMP_DIR", True), pkg)
+ pkg_path = os.path.join(self.d.getVar("TEST_INSTALL_TMP_DIR"), pkg)
pm = get_package_manager(self.d, pkg_path)
extract_dir = pm.extract(pkg)
shutil.rmtree(pkg_path)
@@ -549,8 +502,8 @@ class RuntimeTestContext(TestContext):
from oeqa.utils.package_manager import get_package_manager
- pkg_path = os.path.join(self.d.getVar("TEST_INSTALL_TMP_DIR", True), pkg)
- dst_dir = self.d.getVar("TEST_PACKAGED_DIR", True)
+ pkg_path = os.path.join(self.d.getVar("TEST_INSTALL_TMP_DIR"), pkg)
+ dst_dir = self.d.getVar("TEST_PACKAGED_DIR")
pm = get_package_manager(self.d, pkg_path)
pkg_info = pm.package_info(pkg)
file_path = pkg_info[pkg]["filepath"]
@@ -559,7 +512,7 @@ class RuntimeTestContext(TestContext):
def install_uninstall_packages(self, test_id, pkg_dir, install):
"""
- Check if the test requires a package and Install/Unistall it in the DUT
+ Check if the test requires a package and Install/Uninstall it in the DUT
"""
test = test_id.split(".")[4]
@@ -572,7 +525,7 @@ class RuntimeTestContext(TestContext):
def _install_uninstall_packages(self, needed_packages, pkg_dir, install=True):
"""
- Install/Unistall packages in the DUT without using a package manager
+ Install/Uninstall packages in the DUT without using a package manager
"""
if isinstance(needed_packages, dict):
@@ -590,7 +543,7 @@ class RuntimeTestContext(TestContext):
if install and extract:
self.target.connection.copy_dir_to(src_dir, "/")
- # Unistall package
+ # Uninstall package
elif not install and rm:
self.target.connection.delete_dir_structure(src_dir, "/")
@@ -598,6 +551,8 @@ class ImageTestContext(RuntimeTestContext):
def __init__(self, d, target, host_dumper):
super(ImageTestContext, self).__init__(d, target)
+ self.tagexp = d.getVar("TEST_SUITES_TAGS")
+
self.host_dumper = host_dumper
self.sigterm = False
@@ -611,87 +566,33 @@ class ImageTestContext(RuntimeTestContext):
def install_uninstall_packages(self, test_id, install=True):
"""
- Check if the test requires a package and Install/Unistall it in the DUT
+ Check if the test requires a package and Install/Uninstall it in the DUT
"""
- pkg_dir = self.d.getVar("TEST_EXTRACTED_DIR", True)
+ pkg_dir = self.d.getVar("TEST_EXTRACTED_DIR")
super(ImageTestContext, self).install_uninstall_packages(test_id, pkg_dir, install)
class ExportTestContext(RuntimeTestContext):
- def __init__(self, d, target, exported=False):
+ def __init__(self, d, target, exported=False, parsedArgs={}):
+ """
+ This class is used when exporting tests and when are executed outside OE environment.
+
+ parsedArgs can contain the following:
+ - tag: Filter test by tag.
+ """
super(ExportTestContext, self).__init__(d, target, exported)
+
+ tag = parsedArgs.get("tag", None)
+ self.tagexp = tag if tag != None else d.getVar("TEST_SUITES_TAGS")
+
self.sigterm = None
def install_uninstall_packages(self, test_id, install=True):
"""
- Check if the test requires a package and Install/Unistall it in the DUT
+ Check if the test requires a package and Install/Uninstall it in the DUT
"""
export_dir = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
- extracted_dir = self.d.getVar("TEST_EXPORT_EXTRACTED_DIR", True)
+ extracted_dir = self.d.getVar("TEST_EXPORT_EXTRACTED_DIR")
pkg_dir = os.path.join(export_dir, extracted_dir)
super(ExportTestContext, self).install_uninstall_packages(test_id, pkg_dir, install)
-
-class SDKTestContext(TestContext):
- def __init__(self, d, sdktestdir, sdkenv, tcname, *args):
- super(SDKTestContext, self).__init__(d)
-
- self.sdktestdir = sdktestdir
- self.sdkenv = sdkenv
- self.tcname = tcname
-
- if not hasattr(self, 'target_manifest'):
- self.target_manifest = d.getVar("SDK_TARGET_MANIFEST", True)
- try:
- self.pkgmanifest = {}
- with open(self.target_manifest) as f:
- for line in f:
- (pkg, arch, version) = line.strip().split()
- self.pkgmanifest[pkg] = (version, arch)
- except IOError as e:
- bb.fatal("No package manifest file found. Did you build the sdk image?\n%s" % e)
-
- if not hasattr(self, 'host_manifest'):
- self.host_manifest = d.getVar("SDK_HOST_MANIFEST", True)
- try:
- with open(self.host_manifest) as f:
- self.hostpkgmanifest = f.read()
- except IOError as e:
- bb.fatal("No host package manifest file found. Did you build the sdk image?\n%s" % e)
-
- def _get_test_namespace(self):
- return "sdk"
-
- def _get_test_suites(self):
- return (self.d.getVar("TEST_SUITES_SDK", True) or "auto").split()
-
- def _get_test_suites_required(self):
- return [t for t in (self.d.getVar("TEST_SUITES_SDK", True) or \
- "auto").split() if t != "auto"]
-
-class SDKExtTestContext(SDKTestContext):
- def __init__(self, d, sdktestdir, sdkenv, tcname, *args):
- self.target_manifest = d.getVar("SDK_EXT_TARGET_MANIFEST", True)
- self.host_manifest = d.getVar("SDK_EXT_HOST_MANIFEST", True)
- if args:
- self.cm = args[0] # Compatibility mode for run SDK tests
- else:
- self.cm = False
-
- super(SDKExtTestContext, self).__init__(d, sdktestdir, sdkenv, tcname)
-
- self.sdkextfilesdir = os.path.join(os.path.dirname(os.path.abspath(
- oeqa.sdkext.__file__)), "files")
-
- def _get_test_namespace(self):
- if self.cm:
- return "sdk"
- else:
- return "sdkext"
-
- def _get_test_suites(self):
- return (self.d.getVar("TEST_SUITES_SDK_EXT", True) or "auto").split()
-
- def _get_test_suites_required(self):
- return [t for t in (self.d.getVar("TEST_SUITES_SDK_EXT", True) or \
- "auto").split() if t != "auto"]
diff --git a/meta/lib/oeqa/runexported.py b/meta/lib/oeqa/runexported.py
index 125e86d0e6..7e37213df6 100755
--- a/meta/lib/oeqa/runexported.py
+++ b/meta/lib/oeqa/runexported.py
@@ -1,9 +1,9 @@
#!/usr/bin/env python3
-
-
+#
# Copyright (C) 2013 Intel Corporation
#
-# Released under the MIT license (see COPYING.MIT)
+# SPDX-License-Identifier: MIT
+#
# This script should be used outside of the build system to run image tests.
# It needs a json file as input as exported by the build.
@@ -43,8 +43,8 @@ class FakeTarget(object):
self.ip = None
self.server_ip = None
self.datetime = time.strftime('%Y%m%d%H%M%S',time.gmtime())
- self.testdir = d.getVar("TEST_LOG_DIR", True)
- self.pn = d.getVar("PN", True)
+ self.testdir = d.getVar("TEST_LOG_DIR")
+ self.pn = d.getVar("PN")
def exportStart(self):
self.sshlog = os.path.join(self.testdir, "ssh_target_log.%s" % self.datetime)
@@ -81,6 +81,7 @@ def main():
specified in the json if that directory actually exists or it will error out.")
parser.add_argument("-l", "--log-dir", dest="log_dir", help="This sets the path for TEST_LOG_DIR. If not specified \
the current dir is used. This is used for usually creating a ssh log file and a scp test file.")
+ parser.add_argument("-a", "--tag", dest="tag", help="Only run test with specified tag.")
parser.add_argument("json", help="The json file exported by the build system", default="testdata.json", nargs='?')
args = parser.parse_args()
@@ -107,6 +108,9 @@ def main():
if not os.path.isdir(d["DEPLOY_DIR"]):
print("WARNING: The path to DEPLOY_DIR does not exist: %s" % d["DEPLOY_DIR"])
+ parsedArgs = {}
+ parsedArgs["tag"] = args.tag
+
extract_sdk(d)
target = FakeTarget(d)
@@ -114,7 +118,7 @@ def main():
setattr(target, key, loaded["target"][key])
target.exportStart()
- tc = ExportTestContext(d, target, True)
+ tc = ExportTestContext(d, target, True, parsedArgs)
tc.loadTests()
tc.runTests()
@@ -126,8 +130,8 @@ def extract_sdk(d):
"""
export_dir = os.path.dirname(os.path.realpath(__file__))
- tools_dir = d.getVar("TEST_EXPORT_SDK_DIR", True)
- tarball_name = "%s.sh" % d.getVar("TEST_EXPORT_SDK_NAME", True)
+ tools_dir = d.getVar("TEST_EXPORT_SDK_DIR")
+ tarball_name = "%s.sh" % d.getVar("TEST_EXPORT_SDK_NAME")
tarball_path = os.path.join(export_dir, tools_dir, tarball_name)
extract_path = os.path.join(export_dir, "sysroot")
if os.path.isfile(tarball_path):
diff --git a/meta/lib/oeqa/runtime/_ptest.py b/meta/lib/oeqa/runtime/_ptest.py
deleted file mode 100644
index 71324d3da2..0000000000
--- a/meta/lib/oeqa/runtime/_ptest.py
+++ /dev/null
@@ -1,125 +0,0 @@
-import unittest, os, shutil
-from oeqa.oetest import oeRuntimeTest, skipModule
-from oeqa.utils.decorators import *
-from oeqa.utils.logparser import *
-from oeqa.utils.httpserver import HTTPService
-import bb
-import glob
-from oe.package_manager import RpmPkgsList
-import subprocess
-
-def setUpModule():
- if not oeRuntimeTest.hasFeature("package-management"):
- skipModule("Image doesn't have package management feature")
- if not oeRuntimeTest.hasPackage("smartpm"):
- skipModule("Image doesn't have smart installed")
- if "package_rpm" != oeRuntimeTest.tc.d.getVar("PACKAGE_CLASSES", True).split()[0]:
- skipModule("Rpm is not the primary package manager")
-
-class PtestRunnerTest(oeRuntimeTest):
-
- # a ptest log parser
- def parse_ptest(self, logfile):
- parser = Lparser(test_0_pass_regex="^PASS:(.+)", test_0_fail_regex="^FAIL:(.+)", section_0_begin_regex="^BEGIN: .*/(.+)/ptest", section_0_end_regex="^END: .*/(.+)/ptest")
- parser.init()
- result = Result()
-
- with open(logfile) as f:
- for line in f:
- result_tuple = parser.parse_line(line)
- if not result_tuple:
- continue
- result_tuple = line_type, category, status, name = parser.parse_line(line)
-
- if line_type == 'section' and status == 'begin':
- current_section = name
- continue
-
- if line_type == 'section' and status == 'end':
- current_section = None
- continue
-
- if line_type == 'test' and status == 'pass':
- result.store(current_section, name, status)
- continue
-
- if line_type == 'test' and status == 'fail':
- result.store(current_section, name, status)
- continue
-
- result.sort_tests()
- return result
-
- @classmethod
- def setUpClass(self):
- #note the existing channels that are on the board before creating new ones
-# self.existingchannels = set()
-# (status, result) = oeRuntimeTest.tc.target.run('smart channel --show | grep "\["', 0)
-# for x in result.split("\n"):
-# self.existingchannels.add(x)
- self.repo_server = HTTPService(oeRuntimeTest.tc.d.getVar('DEPLOY_DIR', True), oeRuntimeTest.tc.target.server_ip)
- self.repo_server.start()
-
- @classmethod
- def tearDownClass(self):
- self.repo_server.stop()
- #remove created channels to be able to repeat the tests on same image
-# (status, result) = oeRuntimeTest.tc.target.run('smart channel --show | grep "\["', 0)
-# for x in result.split("\n"):
-# if x not in self.existingchannels:
-# oeRuntimeTest.tc.target.run('smart channel --remove '+x[1:-1]+' -y', 0)
-
- def add_smart_channel(self):
- image_pkgtype = self.tc.d.getVar('IMAGE_PKGTYPE', True)
- deploy_url = 'http://%s:%s/%s' %(self.target.server_ip, self.repo_server.port, image_pkgtype)
- pkgarchs = self.tc.d.getVar('PACKAGE_ARCHS', True).replace("-","_").split()
- for arch in os.listdir('%s/%s' % (self.repo_server.root_dir, image_pkgtype)):
- if arch in pkgarchs:
- self.target.run('smart channel -y --add {a} type=rpm-md baseurl={u}/{a}'.format(a=arch, u=deploy_url), 0)
- self.target.run('smart update', 0)
-
- def install_complementary(self, globs=None):
- installed_pkgs_file = os.path.join(oeRuntimeTest.tc.d.getVar('WORKDIR', True),
- "installed_pkgs.txt")
- self.pkgs_list = RpmPkgsList(oeRuntimeTest.tc.d, oeRuntimeTest.tc.d.getVar('IMAGE_ROOTFS', True), oeRuntimeTest.tc.d.getVar('arch_var', True), oeRuntimeTest.tc.d.getVar('os_var', True))
- with open(installed_pkgs_file, "w+") as installed_pkgs:
- installed_pkgs.write(self.pkgs_list.list("arch"))
-
- cmd = [bb.utils.which(os.getenv('PATH'), "oe-pkgdata-util"),
- "-p", oeRuntimeTest.tc.d.getVar('PKGDATA_DIR', True), "glob", installed_pkgs_file,
- globs]
- try:
- bb.note("Installing complementary packages ...")
- complementary_pkgs = subprocess.check_output(cmd, stderr=subprocess.STDOUT)
- except subprocess.CalledProcessError as e:
- bb.fatal("Could not compute complementary packages list. Command "
- "'%s' returned %d:\n%s" %
- (' '.join(cmd), e.returncode, e.output))
-
- return complementary_pkgs.split()
-
- def setUpLocal(self):
- self.ptest_log = os.path.join(oeRuntimeTest.tc.d.getVar("TEST_LOG_DIR",True), "ptest-%s.log" % oeRuntimeTest.tc.d.getVar('DATETIME', True))
-
- @skipUnlessPassed('test_ssh')
- def test_ptestrunner(self):
- self.add_smart_channel()
- (runnerstatus, result) = self.target.run('which ptest-runner', 0)
- cond = oeRuntimeTest.hasPackage("ptest-runner") and oeRuntimeTest.hasFeature("ptest") and oeRuntimeTest.hasPackageMatch("-ptest") and (runnerstatus != 0)
- if cond:
- self.install_packages(self.install_complementary("*-ptest"))
- self.install_packages(['ptest-runner'])
-
- (runnerstatus, result) = self.target.run('/usr/bin/ptest-runner > /tmp/ptest.log 2>&1', 0)
- #exit code is !=0 even if ptest-runner executes because some ptest tests fail.
- self.assertTrue(runnerstatus != 127, msg="Cannot execute ptest-runner!")
- self.target.copy_from('/tmp/ptest.log', self.ptest_log)
- shutil.copyfile(self.ptest_log, "ptest.log")
-
- result = self.parse_ptest("ptest.log")
- log_results_to_location = "./results"
- if os.path.exists(log_results_to_location):
- shutil.rmtree(log_results_to_location)
- os.makedirs(log_results_to_location)
-
- result.log_as_files(log_results_to_location, test_status = ['pass','fail'])
diff --git a/meta/lib/oeqa/runtime/_qemutiny.py b/meta/lib/oeqa/runtime/_qemutiny.py
deleted file mode 100644
index a3c29f3572..0000000000
--- a/meta/lib/oeqa/runtime/_qemutiny.py
+++ /dev/null
@@ -1,9 +0,0 @@
-import unittest
-from oeqa.oetest import oeRuntimeTest
-from oeqa.utils.qemutinyrunner import *
-
-class QemuTinyTest(oeRuntimeTest):
-
- def test_boot_tiny(self):
- (status, output) = self.target.run_serial('uname -a')
- self.assertTrue("yocto-tiny" in output, msg="Cannot detect poky tiny boot!") \ No newline at end of file
diff --git a/meta/lib/oeqa/runtime/buildcvs.py b/meta/lib/oeqa/runtime/buildcvs.py
deleted file mode 100644
index fe6cbfbcd5..0000000000
--- a/meta/lib/oeqa/runtime/buildcvs.py
+++ /dev/null
@@ -1,31 +0,0 @@
-from oeqa.oetest import oeRuntimeTest, skipModule
-from oeqa.utils.decorators import *
-from oeqa.utils.targetbuild import TargetBuildProject
-
-def setUpModule():
- if not oeRuntimeTest.hasFeature("tools-sdk"):
- skipModule("Image doesn't have tools-sdk in IMAGE_FEATURES")
-
-class BuildCvsTest(oeRuntimeTest):
-
- @classmethod
- def setUpClass(self):
- self.project = TargetBuildProject(oeRuntimeTest.tc.target, oeRuntimeTest.tc.d,
- "http://ftp.gnu.org/non-gnu/cvs/source/feature/1.12.13/cvs-1.12.13.tar.bz2")
- self.project.download_archive()
-
- @testcase(205)
- @skipUnlessPassed("test_ssh")
- def test_cvs(self):
- self.assertEqual(self.project.run_configure(), 0,
- msg="Running configure failed")
-
- self.assertEqual(self.project.run_make(), 0,
- msg="Running make failed")
-
- self.assertEqual(self.project.run_install(), 0,
- msg="Running make install failed")
-
- @classmethod
- def tearDownClass(self):
- self.project.clean()
diff --git a/meta/lib/oeqa/runtime/buildgalculator.py b/meta/lib/oeqa/runtime/buildgalculator.py
deleted file mode 100644
index 28ba29e5c2..0000000000
--- a/meta/lib/oeqa/runtime/buildgalculator.py
+++ /dev/null
@@ -1,23 +0,0 @@
-from oeqa.oetest import oeRuntimeTest, skipModule
-from oeqa.utils.decorators import *
-from oeqa.utils.targetbuild import TargetBuildProject
-
-def setUpModule():
- if not oeRuntimeTest.hasFeature("tools-sdk"):
- skipModule("Image doesn't have tools-sdk in IMAGE_FEATURES")
-
-class GalculatorTest(oeRuntimeTest):
- @skipUnlessPassed("test_ssh")
- def test_galculator(self):
- try:
- project = TargetBuildProject(oeRuntimeTest.tc.target, oeRuntimeTest.tc.d,
- "http://galculator.mnim.org/downloads/galculator-2.1.4.tar.bz2")
- project.download_archive()
-
- self.assertEqual(project.run_configure(), 0,
- msg="Running configure failed")
-
- self.assertEqual(project.run_make(), 0,
- msg="Running make failed")
- finally:
- project.clean()
diff --git a/meta/lib/oeqa/runtime/buildiptables.py b/meta/lib/oeqa/runtime/buildiptables.py
deleted file mode 100644
index 09e252df8c..0000000000
--- a/meta/lib/oeqa/runtime/buildiptables.py
+++ /dev/null
@@ -1,31 +0,0 @@
-from oeqa.oetest import oeRuntimeTest, skipModule
-from oeqa.utils.decorators import *
-from oeqa.utils.targetbuild import TargetBuildProject
-
-def setUpModule():
- if not oeRuntimeTest.hasFeature("tools-sdk"):
- skipModule("Image doesn't have tools-sdk in IMAGE_FEATURES")
-
-class BuildIptablesTest(oeRuntimeTest):
-
- @classmethod
- def setUpClass(self):
- self.project = TargetBuildProject(oeRuntimeTest.tc.target, oeRuntimeTest.tc.d,
- "http://netfilter.org/projects/iptables/files/iptables-1.4.13.tar.bz2")
- self.project.download_archive()
-
- @testcase(206)
- @skipUnlessPassed("test_ssh")
- def test_iptables(self):
- self.assertEqual(self.project.run_configure(), 0,
- msg="Running configure failed")
-
- self.assertEqual(self.project.run_make(), 0,
- msg="Running make failed")
-
- self.assertEqual(self.project.run_install(), 0,
- msg="Running make install failed")
-
- @classmethod
- def tearDownClass(self):
- self.project.clean()
diff --git a/meta/lib/oeqa/runtime/case.py b/meta/lib/oeqa/runtime/case.py
new file mode 100644
index 0000000000..f036982e1f
--- /dev/null
+++ b/meta/lib/oeqa/runtime/case.py
@@ -0,0 +1,20 @@
+#
+# Copyright (C) 2016 Intel Corporation
+#
+# SPDX-License-Identifier: MIT
+#
+
+from oeqa.core.case import OETestCase
+from oeqa.utils.package_manager import install_package, uninstall_package
+
+class OERuntimeTestCase(OETestCase):
+ # target instance set by OERuntimeTestLoader.
+ target = None
+
+ def setUp(self):
+ super(OERuntimeTestCase, self).setUp()
+ install_package(self)
+
+ def tearDown(self):
+ super(OERuntimeTestCase, self).tearDown()
+ uninstall_package(self)
diff --git a/meta/lib/oeqa/runtime/cases/_qemutiny.py b/meta/lib/oeqa/runtime/cases/_qemutiny.py
new file mode 100644
index 0000000000..14ff8b98b2
--- /dev/null
+++ b/meta/lib/oeqa/runtime/cases/_qemutiny.py
@@ -0,0 +1,14 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
+from oeqa.runtime.case import OERuntimeTestCase
+
+class QemuTinyTest(OERuntimeTestCase):
+
+ def test_boot_tiny(self):
+ status, output = self.target.run_serial('uname -a')
+ msg = "Cannot detect poky tiny boot!"
+ self.assertTrue("yocto-tiny" in output, msg)
diff --git a/meta/lib/oeqa/runtime/cases/apt.py b/meta/lib/oeqa/runtime/cases/apt.py
new file mode 100644
index 0000000000..4e09374add
--- /dev/null
+++ b/meta/lib/oeqa/runtime/cases/apt.py
@@ -0,0 +1,79 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
+import os
+from oeqa.utils.httpserver import HTTPService
+from oeqa.runtime.case import OERuntimeTestCase
+from oeqa.core.decorator.data import skipIfNotDataVar, skipIfNotFeature
+from oeqa.runtime.decorator.package import OEHasPackage
+
+class AptTest(OERuntimeTestCase):
+
+ def pkg(self, command, expected = 0):
+ command = 'apt-get %s' % command
+ status, output = self.target.run(command, 1500)
+ message = os.linesep.join([command, output])
+ self.assertEqual(status, expected, message)
+ return output
+
+class AptRepoTest(AptTest):
+
+ @classmethod
+ def setUpClass(cls):
+ service_repo = os.path.join(cls.tc.td['DEPLOY_DIR_DEB'], '')
+ cls.repo_server = HTTPService(service_repo,
+ '0.0.0.0', port=cls.tc.target.server_port,
+ logger=cls.tc.logger)
+ cls.repo_server.start()
+
+ @classmethod
+ def tearDownClass(cls):
+ cls.repo_server.stop()
+
+ def setup_source_config_for_package_install(self):
+ apt_get_source_server = 'http://%s:%s/' % (self.tc.target.server_ip, self.repo_server.port)
+ apt_get_sourceslist_dir = '/etc/apt/'
+ self.target.run('cd %s; echo deb [ allow-insecure=yes ] %s/all ./ > sources.list' % (apt_get_sourceslist_dir, apt_get_source_server))
+
+ def setup_source_config_for_package_install_signed(self):
+ apt_get_source_server = 'http:\/\/%s:%s' % (self.tc.target.server_ip, self.repo_server.port)
+ apt_get_sourceslist_dir = '/etc/apt/'
+ self.target.run("cd %s; cp sources.list sources.list.bak; sed -i 's/\[trusted=yes\] http:\/\/bogus_ip:bogus_port/%s/g' sources.list" % (apt_get_sourceslist_dir, apt_get_source_server))
+
+ def cleanup_source_config_for_package_install(self):
+ apt_get_sourceslist_dir = '/etc/apt/'
+ self.target.run('cd %s; rm sources.list' % (apt_get_sourceslist_dir))
+
+ def cleanup_source_config_for_package_install_signed(self):
+ apt_get_sourceslist_dir = '/etc/apt/'
+ self.target.run('cd %s; mv sources.list.bak sources.list' % (apt_get_sourceslist_dir))
+
+ def setup_key(self):
+ # the key is found on the target /etc/pki/packagefeed-gpg/
+ # named PACKAGEFEED-GPG-KEY-poky-branch
+ self.target.run('cd %s; apt-key add P*' % ('/etc/pki/packagefeed-gpg'))
+
+ @skipIfNotFeature('package-management',
+ 'Test requires package-management to be in IMAGE_FEATURES')
+ @skipIfNotDataVar('IMAGE_PKGTYPE', 'deb',
+ 'DEB is not the primary package manager')
+ @OEHasPackage(['apt'])
+ def test_apt_install_from_repo(self):
+ if not self.tc.td.get('PACKAGE_FEED_GPG_NAME'):
+ self.setup_source_config_for_package_install()
+ self.pkg('update')
+ self.pkg('remove --yes run-postinsts-dev')
+ self.pkg('install --yes --allow-unauthenticated run-postinsts-dev')
+ self.cleanup_source_config_for_package_install()
+ else:
+ # when we are here a key has been set to sign the package feed and
+ # public key and gnupg installed on the image by test_testimage_apt
+ self.setup_source_config_for_package_install_signed()
+ self.setup_key()
+ self.pkg('update')
+ self.pkg('install --yes run-postinsts-dev')
+ self.pkg('remove --yes run-postinsts-dev')
+ self.cleanup_source_config_for_package_install_signed()
diff --git a/meta/lib/oeqa/runtime/cases/boot.py b/meta/lib/oeqa/runtime/cases/boot.py
new file mode 100644
index 0000000000..dcee3311f7
--- /dev/null
+++ b/meta/lib/oeqa/runtime/cases/boot.py
@@ -0,0 +1,35 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
+from subprocess import Popen, PIPE
+import time
+
+from oeqa.runtime.case import OERuntimeTestCase
+from oeqa.core.decorator.depends import OETestDepends
+from oeqa.core.decorator.oetimeout import OETimeout
+from oeqa.core.decorator.data import skipIfQemu
+
+class BootTest(OERuntimeTestCase):
+
+ @OETimeout(120)
+ @skipIfQemu()
+ @OETestDepends(['ssh.SSHTest.test_ssh'])
+ def test_reboot(self):
+ output = ''
+ count = 0
+ (status, output) = self.target.run('reboot -h')
+ while count < 5:
+ time.sleep(5)
+ cmd = 'ping -c 1 %s' % self.target.ip
+ proc = Popen(cmd, shell=True, stdout=PIPE)
+ output += proc.communicate()[0].decode('utf-8')
+ if proc.poll() == 0:
+ count += 1
+ else:
+ count = 0
+ msg = ('Expected 5 consecutive, got %d.\n'
+ 'ping output is:\n%s' % (count,output))
+ self.assertEqual(count, 5, msg = msg)
diff --git a/meta/lib/oeqa/runtime/cases/buildcpio.py b/meta/lib/oeqa/runtime/cases/buildcpio.py
new file mode 100644
index 0000000000..bd3b46d9ef
--- /dev/null
+++ b/meta/lib/oeqa/runtime/cases/buildcpio.py
@@ -0,0 +1,35 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
+from oeqa.runtime.case import OERuntimeTestCase
+from oeqa.core.decorator.depends import OETestDepends
+from oeqa.runtime.decorator.package import OEHasPackage
+
+from oeqa.runtime.utils.targetbuildproject import TargetBuildProject
+
+class BuildCpioTest(OERuntimeTestCase):
+
+ @classmethod
+ def setUpClass(cls):
+ uri = 'https://downloads.yoctoproject.org/mirror/sources/cpio-2.13.tar.gz'
+ cls.project = TargetBuildProject(cls.tc.target,
+ uri,
+ dl_dir = cls.tc.td['DL_DIR'])
+
+ @classmethod
+ def tearDownClass(cls):
+ cls.project.clean()
+
+ @OETestDepends(['ssh.SSHTest.test_ssh'])
+ @OEHasPackage(['gcc'])
+ @OEHasPackage(['make'])
+ @OEHasPackage(['autoconf'])
+ def test_cpio(self):
+ self.project.download_archive()
+ self.project.run_configure('--disable-maintainer-mode',
+ 'sed -i -e "/char \*program_name/d" src/global.c;')
+ self.project.run_make()
+ self.project.run_install()
diff --git a/meta/lib/oeqa/runtime/cases/buildgalculator.py b/meta/lib/oeqa/runtime/cases/buildgalculator.py
new file mode 100644
index 0000000000..2cfb3243dc
--- /dev/null
+++ b/meta/lib/oeqa/runtime/cases/buildgalculator.py
@@ -0,0 +1,34 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
+from oeqa.runtime.case import OERuntimeTestCase
+from oeqa.core.decorator.depends import OETestDepends
+from oeqa.runtime.decorator.package import OEHasPackage
+
+from oeqa.runtime.utils.targetbuildproject import TargetBuildProject
+
+class GalculatorTest(OERuntimeTestCase):
+
+ @classmethod
+ def setUpClass(cls):
+ uri = 'http://galculator.mnim.org/downloads/galculator-2.1.4.tar.bz2'
+ cls.project = TargetBuildProject(cls.tc.target,
+ uri,
+ dl_dir = cls.tc.td['DL_DIR'])
+
+ @classmethod
+ def tearDownClass(cls):
+ cls.project.clean()
+
+ @OETestDepends(['ssh.SSHTest.test_ssh'])
+ @OEHasPackage(['gcc'])
+ @OEHasPackage(['make'])
+ @OEHasPackage(['autoconf'])
+ @OEHasPackage(['gtk+3'])
+ def test_galculator(self):
+ self.project.download_archive()
+ self.project.run_configure()
+ self.project.run_make()
diff --git a/meta/lib/oeqa/runtime/cases/buildlzip.py b/meta/lib/oeqa/runtime/cases/buildlzip.py
new file mode 100644
index 0000000000..44f4f1be71
--- /dev/null
+++ b/meta/lib/oeqa/runtime/cases/buildlzip.py
@@ -0,0 +1,36 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
+from oeqa.runtime.case import OERuntimeTestCase
+from oeqa.core.decorator.depends import OETestDepends
+from oeqa.runtime.decorator.package import OEHasPackage
+
+from oeqa.runtime.utils.targetbuildproject import TargetBuildProject
+
+class BuildLzipTest(OERuntimeTestCase):
+
+ @classmethod
+ def setUpClass(cls):
+ uri = 'http://downloads.yoctoproject.org/mirror/sources'
+ uri = '%s/lzip-1.19.tar.gz' % uri
+ cls.project = TargetBuildProject(cls.tc.target,
+ uri,
+ dl_dir = cls.tc.td['DL_DIR'])
+
+ @classmethod
+ def tearDownClass(cls):
+ cls.project.clean()
+
+ @OETestDepends(['ssh.SSHTest.test_ssh'])
+ @OEHasPackage(['gcc'])
+ @OEHasPackage(['make'])
+ @OEHasPackage(['autoconf'])
+ def test_lzip(self):
+ self.project.download_archive()
+ self.project.run_configure()
+ self.project.run_make()
+ self.project.run_install()
+
diff --git a/meta/lib/oeqa/runtime/cases/connman.py b/meta/lib/oeqa/runtime/cases/connman.py
new file mode 100644
index 0000000000..a488752e3f
--- /dev/null
+++ b/meta/lib/oeqa/runtime/cases/connman.py
@@ -0,0 +1,33 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
+from oeqa.runtime.case import OERuntimeTestCase
+from oeqa.core.decorator.depends import OETestDepends
+from oeqa.runtime.decorator.package import OEHasPackage
+
+class ConnmanTest(OERuntimeTestCase):
+
+ def service_status(self, service):
+ if 'systemd' in self.tc.td['DISTRO_FEATURES']:
+ (_, output) = self.target.run('systemctl status -l %s' % service)
+ return output
+ else:
+ return "Unable to get status or logs for %s" % service
+
+ @OETestDepends(['ssh.SSHTest.test_ssh'])
+ @OEHasPackage(["connman"])
+ def test_connmand_help(self):
+ (status, output) = self.target.run('/usr/sbin/connmand --help')
+ msg = 'Failed to get connman help. Output: %s' % output
+ self.assertEqual(status, 0, msg=msg)
+
+ @OETestDepends(['connman.ConnmanTest.test_connmand_help'])
+ def test_connmand_running(self):
+ cmd = '%s | grep [c]onnmand' % self.tc.target_cmds['ps']
+ (status, output) = self.target.run(cmd)
+ if status != 0:
+ self.logger.info(self.service_status("connman"))
+ self.fail("No connmand process running")
diff --git a/meta/lib/oeqa/runtime/cases/date.py b/meta/lib/oeqa/runtime/cases/date.py
new file mode 100644
index 0000000000..a2523de67a
--- /dev/null
+++ b/meta/lib/oeqa/runtime/cases/date.py
@@ -0,0 +1,43 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
+import re
+
+from oeqa.runtime.case import OERuntimeTestCase
+from oeqa.core.decorator.depends import OETestDepends
+from oeqa.runtime.decorator.package import OEHasPackage
+
+class DateTest(OERuntimeTestCase):
+
+ def setUp(self):
+ if self.tc.td.get('VIRTUAL-RUNTIME_init_manager') == 'systemd':
+ self.logger.debug('Stopping systemd-timesyncd daemon')
+ self.target.run('systemctl disable --now --runtime systemd-timesyncd')
+
+ def tearDown(self):
+ if self.tc.td.get('VIRTUAL-RUNTIME_init_manager') == 'systemd':
+ self.logger.debug('Starting systemd-timesyncd daemon')
+ self.target.run('systemctl enable --now --runtime systemd-timesyncd')
+
+ @OETestDepends(['ssh.SSHTest.test_ssh'])
+ @OEHasPackage(['coreutils', 'busybox'])
+ def test_date(self):
+ (status, output) = self.target.run('date +"%Y-%m-%d %T"')
+ msg = 'Failed to get initial date, output: %s' % output
+ self.assertEqual(status, 0, msg=msg)
+ oldDate = output
+
+ sampleTimestamp = 1488800000
+ (status, output) = self.target.run("date -s @%d" % sampleTimestamp)
+ self.assertEqual(status, 0, msg='Date set failed, output: %s' % output)
+
+ (status, output) = self.target.run('date +"%s"')
+ msg = 'The date was not set correctly, output: %s' % output
+ self.assertTrue(int(output) - sampleTimestamp < 300, msg=msg)
+
+ (status, output) = self.target.run('date -s "%s"' % oldDate)
+ msg = 'Failed to reset date, output: %s' % output
+ self.assertEqual(status, 0, msg=msg)
diff --git a/meta/lib/oeqa/runtime/cases/df.py b/meta/lib/oeqa/runtime/cases/df.py
new file mode 100644
index 0000000000..43e0ebf9ea
--- /dev/null
+++ b/meta/lib/oeqa/runtime/cases/df.py
@@ -0,0 +1,21 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
+from oeqa.runtime.case import OERuntimeTestCase
+from oeqa.core.decorator.depends import OETestDepends
+from oeqa.core.decorator.data import skipIfDataVar, skipIfInDataVar
+from oeqa.runtime.decorator.package import OEHasPackage
+
+class DfTest(OERuntimeTestCase):
+
+ @OETestDepends(['ssh.SSHTest.test_ssh'])
+ @OEHasPackage(['coreutils', 'busybox'])
+ @skipIfInDataVar('IMAGE_FEATURES', 'read-only-rootfs', 'Test case df requires a writable rootfs')
+ def test_df(self):
+ cmd = "df -P / | sed -n '2p' | awk '{print $4}'"
+ (status,output) = self.target.run(cmd)
+ msg = 'Not enough space on image. Current size is %s' % output
+ self.assertTrue(int(output)>5120, msg=msg)
diff --git a/meta/lib/oeqa/runtime/cases/dnf.py b/meta/lib/oeqa/runtime/cases/dnf.py
new file mode 100644
index 0000000000..3ccb18ce83
--- /dev/null
+++ b/meta/lib/oeqa/runtime/cases/dnf.py
@@ -0,0 +1,173 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
+import os
+import re
+import subprocess
+from oeqa.utils.httpserver import HTTPService
+
+from oeqa.runtime.case import OERuntimeTestCase
+from oeqa.core.decorator.depends import OETestDepends
+from oeqa.core.decorator.data import skipIfNotDataVar, skipIfNotFeature, skipIfInDataVar, skipIfNotInDataVar
+from oeqa.runtime.decorator.package import OEHasPackage
+
+class DnfTest(OERuntimeTestCase):
+
+ def dnf(self, command, expected = 0):
+ command = 'dnf %s' % command
+ status, output = self.target.run(command, 1500)
+ message = os.linesep.join([command, output])
+ self.assertEqual(status, expected, message)
+ return output
+
+class DnfBasicTest(DnfTest):
+
+ @skipIfNotFeature('package-management',
+ 'Test requires package-management to be in IMAGE_FEATURES')
+ @skipIfNotDataVar('IMAGE_PKGTYPE', 'rpm',
+ 'RPM is not the primary package manager')
+ @OEHasPackage(['dnf'])
+ @OETestDepends(['ssh.SSHTest.test_ssh'])
+ def test_dnf_help(self):
+ self.dnf('--help')
+
+ @OETestDepends(['dnf.DnfBasicTest.test_dnf_help'])
+ def test_dnf_version(self):
+ self.dnf('--version')
+
+ @OETestDepends(['dnf.DnfBasicTest.test_dnf_help'])
+ def test_dnf_info(self):
+ self.dnf('info dnf')
+
+ @OETestDepends(['dnf.DnfBasicTest.test_dnf_help'])
+ def test_dnf_search(self):
+ self.dnf('search dnf')
+
+ @OETestDepends(['dnf.DnfBasicTest.test_dnf_help'])
+ def test_dnf_history(self):
+ self.dnf('history')
+
+class DnfRepoTest(DnfTest):
+
+ @classmethod
+ def setUpClass(cls):
+ cls.repo_server = HTTPService(os.path.join(cls.tc.td['WORKDIR'], 'oe-testimage-repo'),
+ '0.0.0.0', port=cls.tc.target.server_port,
+ logger=cls.tc.logger)
+ cls.repo_server.start()
+
+ @classmethod
+ def tearDownClass(cls):
+ cls.repo_server.stop()
+
+ def dnf_with_repo(self, command):
+ pkgarchs = os.listdir(os.path.join(self.tc.td['WORKDIR'], 'oe-testimage-repo'))
+ deploy_url = 'http://%s:%s/' %(self.target.server_ip, self.repo_server.port)
+ cmdlinerepoopts = ["--repofrompath=oe-testimage-repo-%s,%s%s" %(arch, deploy_url, arch) for arch in pkgarchs]
+
+ output = self.dnf(" ".join(cmdlinerepoopts) + " --nogpgcheck " + command)
+ return output
+
+ @OETestDepends(['dnf.DnfBasicTest.test_dnf_help'])
+ def test_dnf_makecache(self):
+ self.dnf_with_repo('makecache')
+
+ @OETestDepends(['dnf.DnfRepoTest.test_dnf_makecache'])
+ def test_dnf_repoinfo(self):
+ self.dnf_with_repo('repoinfo')
+
+ @OETestDepends(['dnf.DnfRepoTest.test_dnf_makecache'])
+ def test_dnf_install(self):
+ self.dnf_with_repo('remove -y dnf-test-*')
+ self.dnf_with_repo('install -y dnf-test-dep')
+
+ @OETestDepends(['dnf.DnfRepoTest.test_dnf_install'])
+ def test_dnf_install_dependency(self):
+ self.dnf_with_repo('remove -y dnf-test-*')
+ self.dnf_with_repo('install -y dnf-test-main')
+ output = self.dnf('list --installed dnf-test-*')
+ self.assertIn("dnf-test-main.", output)
+ self.assertIn("dnf-test-dep.", output)
+
+ @OETestDepends(['dnf.DnfRepoTest.test_dnf_install_dependency'])
+ def test_dnf_install_from_disk(self):
+ self.dnf_with_repo('remove -y dnf-test-dep')
+ self.dnf_with_repo('install -y --downloadonly dnf-test-dep')
+ status, output = self.target.run('find /var/cache/dnf -name dnf-test-dep*rpm')
+ self.assertEqual(status, 0, output)
+ self.dnf_with_repo('install -y %s' % output)
+
+ @OETestDepends(['dnf.DnfRepoTest.test_dnf_install_from_disk'])
+ def test_dnf_install_from_http(self):
+ output = subprocess.check_output('%s %s -name dnf-test-dep*' % (bb.utils.which(os.getenv('PATH'), "find"),
+ os.path.join(self.tc.td['WORKDIR'], 'oe-testimage-repo')), shell=True).decode("utf-8")
+ rpm_path = output.split("/")[-2] + "/" + output.split("/")[-1]
+ url = 'http://%s:%s/%s' %(self.target.server_ip, self.repo_server.port, rpm_path)
+ self.dnf_with_repo('remove -y dnf-test-dep')
+ self.dnf_with_repo('install -y %s' % url)
+
+ @OETestDepends(['dnf.DnfRepoTest.test_dnf_install'])
+ def test_dnf_reinstall(self):
+ self.dnf_with_repo('reinstall -y dnf-test-main')
+
+ @OETestDepends(['dnf.DnfRepoTest.test_dnf_makecache'])
+ @skipIfInDataVar('DISTRO_FEATURES', 'usrmerge', 'Test run when not enable usrmerge')
+ @OEHasPackage('busybox')
+ def test_dnf_installroot(self):
+ rootpath = '/home/root/chroot/test'
+ #Copy necessary files to avoid errors with not yet installed tools on
+ #installroot directory.
+ self.target.run('mkdir -p %s/etc' % rootpath, 1500)
+ self.target.run('mkdir -p %s/bin %s/sbin %s/usr/bin %s/usr/sbin' % (rootpath, rootpath, rootpath, rootpath), 1500)
+ self.target.run('mkdir -p %s/dev' % rootpath, 1500)
+ #Handle different architectures lib dirs
+ self.target.run('mkdir -p %s/lib' % rootpath, 1500)
+ self.target.run('mkdir -p %s/libx32' % rootpath, 1500)
+ self.target.run('mkdir -p %s/lib64' % rootpath, 1500)
+ self.target.run('cp /lib/libtinfo.so.5 %s/lib' % rootpath, 1500)
+ self.target.run('cp /libx32/libtinfo.so.5 %s/libx32' % rootpath, 1500)
+ self.target.run('cp /lib64/libtinfo.so.5 %s/lib64' % rootpath, 1500)
+ self.target.run('cp -r /etc/rpm %s/etc' % rootpath, 1500)
+ self.target.run('cp -r /etc/dnf %s/etc' % rootpath, 1500)
+ self.target.run('cp /bin/sh %s/bin' % rootpath, 1500)
+ self.target.run('mount -o bind /dev %s/dev/' % rootpath, 1500)
+ self.dnf_with_repo('install --installroot=%s -v -y --rpmverbosity=debug busybox' % rootpath)
+ status, output = self.target.run('test -e %s/var/cache/dnf' % rootpath, 1500)
+ self.assertEqual(0, status, output)
+ status, output = self.target.run('test -e %s/bin/busybox' % rootpath, 1500)
+ self.assertEqual(0, status, output)
+
+ @OETestDepends(['dnf.DnfRepoTest.test_dnf_makecache'])
+ @skipIfNotInDataVar('DISTRO_FEATURES', 'usrmerge', 'Test run when enable usrmerge')
+ @OEHasPackage('busybox')
+ def test_dnf_installroot_usrmerge(self):
+ rootpath = '/home/root/chroot/test'
+ #Copy necessary files to avoid errors with not yet installed tools on
+ #installroot directory.
+ self.target.run('mkdir -p %s/etc' % rootpath)
+ self.target.run('mkdir -p %s/usr/bin %s/usr/sbin' % (rootpath, rootpath))
+ self.target.run('ln -sf usr/bin %s/bin' % (rootpath))
+ self.target.run('ln -sf usr/sbin %s/sbin' % (rootpath))
+ self.target.run('mkdir -p %s/dev' % rootpath)
+ #Handle different architectures lib dirs
+ self.target.run("for l in /lib*; do mkdir -p %s/usr/$l; ln -s usr/$l %s/$l; done" % (rootpath, rootpath))
+ self.target.run('cp -r /etc/rpm %s/etc' % rootpath)
+ self.target.run('cp -r /etc/dnf %s/etc' % rootpath)
+ self.target.run('cp /bin/busybox %s/bin/sh' % rootpath)
+ self.target.run('mount -o bind /dev %s/dev/' % rootpath)
+ self.dnf_with_repo('install --installroot=%s -v -y --rpmverbosity=debug busybox' % rootpath)
+ status, output = self.target.run('test -e %s/var/cache/dnf' % rootpath)
+ self.assertEqual(0, status, output)
+ status, output = self.target.run('test -e %s/bin/busybox' % rootpath)
+ self.assertEqual(0, status, output)
+
+ @OETestDepends(['dnf.DnfRepoTest.test_dnf_makecache'])
+ def test_dnf_exclude(self):
+ self.dnf_with_repo('remove -y dnf-test-*')
+ self.dnf_with_repo('install -y --exclude=dnf-test-dep dnf-test-*')
+ output = self.dnf('list --installed dnf-test-*')
+ self.assertIn("dnf-test-main.", output)
+ self.assertNotIn("dnf-test-dev.", output)
diff --git a/meta/lib/oeqa/runtime/cases/ethernet_ip_connman.py b/meta/lib/oeqa/runtime/cases/ethernet_ip_connman.py
new file mode 100644
index 0000000000..eac8f2d082
--- /dev/null
+++ b/meta/lib/oeqa/runtime/cases/ethernet_ip_connman.py
@@ -0,0 +1,42 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+from oeqa.runtime.case import OERuntimeTestCase
+from oeqa.core.decorator.depends import OETestDepends
+from oeqa.core.decorator.data import skipIfQemu
+
+class Ethernet_Test(OERuntimeTestCase):
+
+ def set_ip(self, x):
+ x = x.split(".")
+ sample_host_address = '150'
+ x[3] = sample_host_address
+ x = '.'.join(x)
+ return x
+
+ @skipIfQemu()
+ @OETestDepends(['ssh.SSHTest.test_ssh'])
+ def test_set_virtual_ip(self):
+ (status, output) = self.target.run("ifconfig eth0 | grep 'inet ' | awk '{print $2}'")
+ self.assertEqual(status, 0, msg='Failed to get ip address. Make sure you have an ethernet connection on your device, output: %s' % output)
+ original_ip = output
+ virtual_ip = self.set_ip(original_ip)
+
+ (status, output) = self.target.run("ifconfig eth0:1 %s netmask 255.255.255.0 && sleep 2 && ping -c 5 %s && ifconfig eth0:1 down" % (virtual_ip,virtual_ip))
+ self.assertEqual(status, 0, msg='Failed to create virtual ip address, output: %s' % output)
+
+ @skipIfQemu()
+ @OETestDepends(['ethernet_ip_connman.Ethernet_Test.test_set_virtual_ip'])
+ def test_get_ip_from_dhcp(self):
+ (status, output) = self.target.run("connmanctl services | grep -E '*AO Wired|*AR Wired' | awk '{print $3}'")
+ self.assertEqual(status, 0, msg='No wired interfaces are detected, output: %s' % output)
+ wired_interfaces = output
+
+ (status, output) = self.target.run("ip route | grep default | awk '{print $3}'")
+ self.assertEqual(status, 0, msg='Failed to retrieve the default gateway, output: %s' % output)
+ default_gateway = output
+
+ (status, output) = self.target.run("connmanctl config %s --ipv4 dhcp && sleep 2 && ping -c 5 %s" % (wired_interfaces,default_gateway))
+ self.assertEqual(status, 0, msg='Failed to get dynamic IP address via DHCP in connmand, output: %s' % output) \ No newline at end of file
diff --git a/meta/lib/oeqa/runtime/cases/gcc.py b/meta/lib/oeqa/runtime/cases/gcc.py
new file mode 100644
index 0000000000..17b1483e8d
--- /dev/null
+++ b/meta/lib/oeqa/runtime/cases/gcc.py
@@ -0,0 +1,71 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
+import os
+
+from oeqa.runtime.case import OERuntimeTestCase
+from oeqa.core.decorator.depends import OETestDepends
+from oeqa.runtime.decorator.package import OEHasPackage
+
+class GccCompileTest(OERuntimeTestCase):
+
+ @classmethod
+ def setUp(cls):
+ dst = '/tmp/'
+ src = os.path.join(cls.tc.files_dir, 'test.c')
+ cls.tc.target.copyTo(src, dst)
+
+ src = os.path.join(cls.tc.runtime_files_dir, 'testmakefile')
+ cls.tc.target.copyTo(src, dst)
+
+ src = os.path.join(cls.tc.files_dir, 'test.cpp')
+ cls.tc.target.copyTo(src, dst)
+
+ @classmethod
+ def tearDown(cls):
+ files = '/tmp/test.c /tmp/test.o /tmp/test /tmp/testmakefile'
+ cls.tc.target.run('rm %s' % files)
+
+ @OETestDepends(['ssh.SSHTest.test_ssh'])
+ @OEHasPackage(['gcc'])
+ def test_gcc_compile(self):
+ status, output = self.target.run('gcc /tmp/test.c -o /tmp/test -lm')
+ msg = 'gcc compile failed, output: %s' % output
+ self.assertEqual(status, 0, msg=msg)
+
+ status, output = self.target.run('/tmp/test')
+ msg = 'running compiled file failed, output: %s' % output
+ self.assertEqual(status, 0, msg=msg)
+
+ @OETestDepends(['ssh.SSHTest.test_ssh'])
+ @OEHasPackage(['g++'])
+ def test_gpp_compile(self):
+ status, output = self.target.run('g++ /tmp/test.c -o /tmp/test -lm')
+ msg = 'g++ compile failed, output: %s' % output
+ self.assertEqual(status, 0, msg=msg)
+
+ status, output = self.target.run('/tmp/test')
+ msg = 'running compiled file failed, output: %s' % output
+ self.assertEqual(status, 0, msg=msg)
+
+ @OETestDepends(['ssh.SSHTest.test_ssh'])
+ @OEHasPackage(['g++'])
+ def test_gpp2_compile(self):
+ status, output = self.target.run('g++ /tmp/test.cpp -o /tmp/test -lm')
+ msg = 'g++ compile failed, output: %s' % output
+ self.assertEqual(status, 0, msg=msg)
+
+ status, output = self.target.run('/tmp/test')
+ msg = 'running compiled file failed, output: %s' % output
+ self.assertEqual(status, 0, msg=msg)
+
+ @OETestDepends(['ssh.SSHTest.test_ssh'])
+ @OEHasPackage(['gcc'])
+ @OEHasPackage(['make'])
+ def test_make(self):
+ status, output = self.target.run('cd /tmp; make -f testmakefile')
+ msg = 'running make failed, output %s' % output
+ self.assertEqual(status, 0, msg=msg)
diff --git a/meta/lib/oeqa/runtime/cases/gi.py b/meta/lib/oeqa/runtime/cases/gi.py
new file mode 100644
index 0000000000..78c7ddda2c
--- /dev/null
+++ b/meta/lib/oeqa/runtime/cases/gi.py
@@ -0,0 +1,21 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
+import os
+
+from oeqa.runtime.case import OERuntimeTestCase
+from oeqa.core.decorator.depends import OETestDepends
+from oeqa.runtime.decorator.package import OEHasPackage
+
+class GObjectIntrospectionTest(OERuntimeTestCase):
+
+ @OETestDepends(["ssh.SSHTest.test_ssh"])
+ @OEHasPackage(["python3-pygobject"])
+ def test_python(self):
+ script = """from gi.repository import GLib; print(GLib.markup_escape_text("<testing&testing>"))"""
+ status, output = self.target.run("python3 -c '%s'" % script)
+ self.assertEqual(status, 0, msg="Python failed (%s)" % (output))
+ self.assertEqual(output, "&lt;testing&amp;testing&gt;", msg="Unexpected output (%s)" % output)
diff --git a/meta/lib/oeqa/runtime/cases/go.py b/meta/lib/oeqa/runtime/cases/go.py
new file mode 100644
index 0000000000..7514d108f1
--- /dev/null
+++ b/meta/lib/oeqa/runtime/cases/go.py
@@ -0,0 +1,21 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
+from oeqa.runtime.case import OERuntimeTestCase
+from oeqa.core.decorator.depends import OETestDepends
+from oeqa.runtime.decorator.package import OEHasPackage
+
+class GoHelloworldTest(OERuntimeTestCase):
+ @OETestDepends(['ssh.SSHTest.test_ssh'])
+ @OEHasPackage(['go-helloworld'])
+ def test_gohelloworld(self):
+ cmd = "go-helloworld"
+ status, output = self.target.run(cmd)
+ msg = 'Exit status was not 0. Output: %s' % output
+ self.assertEqual(status, 0, msg=msg)
+
+ msg = 'Incorrect output: %s' % output
+ self.assertEqual(output, "Hello, Go examples!", msg=msg)
diff --git a/meta/lib/oeqa/runtime/cases/gstreamer.py b/meta/lib/oeqa/runtime/cases/gstreamer.py
new file mode 100644
index 0000000000..2295769cfd
--- /dev/null
+++ b/meta/lib/oeqa/runtime/cases/gstreamer.py
@@ -0,0 +1,20 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
+from oeqa.runtime.case import OERuntimeTestCase
+from oeqa.runtime.decorator.package import OEHasPackage
+
+class GstreamerCliTest(OERuntimeTestCase):
+
+ @OEHasPackage(['gstreamer1.0'])
+ def test_gst_inspect_can_list_all_plugins(self):
+ status, output = self.target.run('gst-inspect-1.0')
+ self.assertEqual(status, 0, 'gst-inspect-1.0 does not appear to be running.')
+
+ @OEHasPackage(['gstreamer1.0'])
+ def test_gst_launch_can_create_video_pipeline(self):
+ status, output = self.target.run('gst-launch-1.0 -v fakesrc silent=false num-buffers=3 ! fakesink silent=false')
+ self.assertEqual(status, 0, 'gst-launch-1.0 does not appear to be running.')
diff --git a/meta/lib/oeqa/runtime/cases/kernelmodule.py b/meta/lib/oeqa/runtime/cases/kernelmodule.py
new file mode 100644
index 0000000000..9c42fcc586
--- /dev/null
+++ b/meta/lib/oeqa/runtime/cases/kernelmodule.py
@@ -0,0 +1,48 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
+import os
+
+from oeqa.runtime.case import OERuntimeTestCase
+from oeqa.core.decorator.depends import OETestDepends
+from oeqa.core.decorator.data import skipIfNotFeature
+from oeqa.runtime.decorator.package import OEHasPackage
+
+class KernelModuleTest(OERuntimeTestCase):
+
+ @classmethod
+ def setUp(cls):
+ src = os.path.join(cls.tc.runtime_files_dir, 'hellomod.c')
+ dst = '/tmp/hellomod.c'
+ cls.tc.target.copyTo(src, dst)
+
+ src = os.path.join(cls.tc.runtime_files_dir, 'hellomod_makefile')
+ dst = '/tmp/Makefile'
+ cls.tc.target.copyTo(src, dst)
+
+ @classmethod
+ def tearDown(cls):
+ files = '/tmp/Makefile /tmp/hellomod.c'
+ cls.tc.target.run('rm %s' % files)
+
+ @skipIfNotFeature('tools-sdk',
+ 'Test requires tools-sdk to be in IMAGE_FEATURES')
+ @OETestDepends(['gcc.GccCompileTest.test_gcc_compile'])
+ @OEHasPackage(['kernel-devsrc'])
+ @OEHasPackage(['make'])
+ @OEHasPackage(['gcc'])
+ def test_kernel_module(self):
+ cmds = [
+ 'cd /usr/src/kernel && make scripts prepare',
+ 'cd /tmp && make',
+ 'cd /tmp && insmod hellomod.ko',
+ 'lsmod | grep hellomod',
+ 'dmesg | grep Hello',
+ 'rmmod hellomod', 'dmesg | grep "Cleaning up hellomod"'
+ ]
+ for cmd in cmds:
+ status, output = self.target.run(cmd, 900)
+ self.assertEqual(status, 0, msg='\n'.join([cmd, output]))
diff --git a/meta/lib/oeqa/runtime/cases/ksample.py b/meta/lib/oeqa/runtime/cases/ksample.py
new file mode 100644
index 0000000000..b6848762e3
--- /dev/null
+++ b/meta/lib/oeqa/runtime/cases/ksample.py
@@ -0,0 +1,233 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
+import os
+import time
+
+from oeqa.runtime.case import OERuntimeTestCase
+from oeqa.core.decorator.depends import OETestDepends
+from oeqa.core.decorator.data import skipIfNotFeature
+
+# need some kernel fragments
+# echo "KERNEL_FEATURES:append = \" features\/kernel\-sample\/kernel\-sample.scc\"" >> local.conf
+class KSample(OERuntimeTestCase):
+ def cmd_and_check(self, cmd='', match_string=''):
+ status, output = self.target.run(cmd)
+ if not match_string:
+ # send cmd
+ msg = '%s failed, %s' % (cmd, output)
+ self.assertEqual(status, 0, msg=msg)
+ else:
+ # check result
+ result = ("%s" % match_string) in output
+ msg = output
+ self.assertTrue(result, msg)
+ self.assertEqual(status, 0, cmd)
+
+ def check_arch(self, archset=''):
+ status, output = self.target.run("uname -m")
+ result = ("%s" % output) in archset
+ if not result:
+ self.skipTest("This case doesn't support %s" % output)
+
+ def check_config(self, config_opt=''):
+ cmd = "zcat /proc/config.gz | grep %s" % config_opt
+ status, output = self.target.run(cmd)
+ result = ("%s=y" % config_opt) in output
+ if not result:
+ self.skipTest("%s is not set" % config_opt)
+
+ def check_module_exist(self, path='', module_name=''):
+ status, output = self.target.run("uname -r")
+ cmd = "ls " + "/lib/modules/" + output + "/kernel/samples/" + path + module_name
+ status, output = self.target.run(cmd)
+ if status != 0:
+ error_info = module_name + " doesn't exist"
+ self.skipTest(error_info)
+
+ def kfifo_func(self, name=''):
+ module_prename = name + "-example"
+ module_name = name + "-example.ko"
+ sysmbol_name = name + "_example"
+
+ # make sure if module exists
+ self.check_module_exist("kfifo/", module_name)
+ # modprobe
+ self.cmd_and_check("modprobe %s" % module_prename)
+ # lsmod
+ self.cmd_and_check("lsmod | grep %s | cut -d\' \' -f1" % sysmbol_name, sysmbol_name)
+ # check result
+ self.cmd_and_check("dmesg | grep \"test passed\" ", "test passed")
+ # rmmod
+ self.cmd_and_check("rmmod %s" % module_prename)
+
+ def kprobe_func(self, name=''):
+ # check config
+ self.check_config("CONFIG_KPROBES")
+
+ module_prename = name + "_example"
+ module_name = name + "_example.ko"
+ sysmbol_name = module_prename
+
+ # make sure if module exists
+ self.check_module_exist("kprobes/", module_name)
+ # modprobe
+ self.cmd_and_check("modprobe %s" % module_prename)
+ # lsmod
+ self.cmd_and_check("lsmod | grep %s | cut -d\' \' -f1" % sysmbol_name, sysmbol_name)
+ # check result
+ self.cmd_and_check("dmesg | grep Planted | head -n10", "Planted")
+ # rmmod
+ self.cmd_and_check("rmmod %s" % module_prename)
+
+ def kobject_func(self, name=''):
+ module_prename = name + "_example"
+ module_name = name + "-example.ko"
+ sysmbol_name = module_prename
+
+ # make sure if module exists
+ self.check_module_exist("kobject/", module_name)
+ # modprobe
+ self.cmd_and_check("modprobe %s" % module_prename)
+ # lsmod
+ self.cmd_and_check("lsmod | grep %s | cut -d\' \' -f1" % sysmbol_name, sysmbol_name)
+ # check result
+ self.cmd_and_check("ls /sys/kernel/%s/" % sysmbol_name, "bar")
+ # rmmod
+ self.cmd_and_check("rmmod %s" % module_prename)
+
+class KSampleTest(KSample):
+ # kfifo
+ @OETestDepends(['ssh.SSHTest.test_ssh'])
+ def test_kfifo_test(self):
+ index = ["dma", "bytestream", "inttype", "record"]
+ for i in index:
+ self.kfifo_func(i)
+
+ # kprobe
+ @OETestDepends(['ssh.SSHTest.test_ssh'])
+ def test_kprobe_test(self):
+ self.check_arch("x86_64 i686 ppc")
+ index = ["kprobe", "kretprobe"]
+ for i in index:
+ self.kprobe_func(i)
+
+ # kobject
+ @OETestDepends(['ssh.SSHTest.test_ssh'])
+ def test_kobject_test(self):
+ index = ["kobject", "kset"]
+ for i in index:
+ self.kobject_func(i)
+
+ #trace
+ @OETestDepends(['ssh.SSHTest.test_ssh'])
+ def test_trace_events(self):
+ # check config
+ self.check_config("CONFIG_TRACING_SUPPORT")
+ # make sure if module exists
+ self.check_module_exist("trace_events/", "trace-events-sample.ko")
+ # modprobe
+ self.cmd_and_check("modprobe trace-events-sample")
+ # lsmod
+ self.cmd_and_check("lsmod | grep trace_events_sample | cut -d\' \' -f1", "trace_events_sample")
+ # check dir
+ self.cmd_and_check("ls /sys/kernel/debug/tracing/events/ | grep sample-trace", "sample-trace")
+ # enable trace
+ self.cmd_and_check("echo 1 > /sys/kernel/debug/tracing/events/sample-trace/enable")
+ self.cmd_and_check("cat /sys/kernel/debug/tracing/events/sample-trace/enable")
+ # check result
+ status = 1
+ count = 0
+ while status != 0:
+ time.sleep(1)
+ status, output = self.target.run('cat /sys/kernel/debug/tracing/trace | grep hello | head -n1 | cut -d\':\' -f2')
+ if " foo_bar" in output:
+ break
+ count = count + 1
+ if count > 5:
+ self.assertTrue(False, "Time out when check result")
+ # disable trace
+ self.cmd_and_check("echo 0 > /sys/kernel/debug/tracing/events/sample-trace/enable")
+ # clean up trace
+ self.cmd_and_check("echo > /sys/kernel/debug/tracing/trace")
+ # rmmod
+ self.cmd_and_check("rmmod trace-events-sample")
+
+ @OETestDepends(['ssh.SSHTest.test_ssh'])
+ def test_trace_printk(self):
+ # check config
+ self.check_config("CONFIG_TRACING_SUPPORT")
+ # make sure if module exists
+ self.check_module_exist("trace_printk/", "trace-printk.ko")
+ # modprobe
+ self.cmd_and_check("modprobe trace-printk")
+ # lsmod
+ self.cmd_and_check("lsmod | grep trace_printk | cut -d\' \' -f1", "trace_printk")
+ # check result
+ self.cmd_and_check("cat /sys/kernel/debug/tracing/trace | grep trace_printk_irq_work | head -n1 | cut -d\':\' -f2", " trace_printk_irq_work")
+ # clean up trace
+ self.cmd_and_check("echo > /sys/kernel/debug/tracing/trace")
+ # rmmod
+ self.cmd_and_check("rmmod trace-printk")
+
+ # hw breakpoint
+ @OETestDepends(['ssh.SSHTest.test_ssh'])
+ def test_hw_breakpoint_example(self):
+ # check arch
+ status, output = self.target.run("uname -m")
+ result = ("x86_64" in output) or ("aarch64" in output)
+ if not result:
+ self.skipTest("the arch %s doesn't support hw breakpoint" % output)
+ # check config
+ self.check_config("CONFIG_KALLSYMS_ALL")
+ # make sure if module exists
+ self.check_module_exist("hw_breakpoint/", "data_breakpoint.ko")
+ # modprobe
+ self.cmd_and_check("modprobe data_breakpoint")
+ # lsmod
+ self.cmd_and_check("lsmod | grep data_breakpoint | cut -d\' \' -f1", "data_breakpoint")
+ # check result
+ self.cmd_and_check("cat /var/log/messages | grep sample_hbp_handler", "sample_hbp_handler")
+ # rmmod
+ self.cmd_and_check("rmmod data_breakpoint")
+
+ @OETestDepends(['ssh.SSHTest.test_ssh'])
+ def test_configfs_sample(self):
+ # check config
+ status, ret = self.target.run('zcat /proc/config.gz | grep CONFIG_CONFIGFS_FS')
+ if not ["CONFIG_CONFIGFS_FS=m" in ret or "CONFIG_CONFIGFS_FS=y" in ret]:
+ self.skipTest("CONFIG error")
+ # make sure if module exists
+ self.check_module_exist("configfs/", "configfs_sample.ko")
+ # modprobe
+ self.cmd_and_check("modprobe configfs_sample")
+ # lsmod
+ self.cmd_and_check("lsmod | grep configfs_sample | cut -d\' \' -f1 | head -n1", "configfs_sample")
+
+ status = 1
+ count = 0
+ while status != 0:
+ time.sleep(1)
+ status, ret = self.target.run('cat /sys/kernel/config/01-childless/description')
+ count = count + 1
+ if count > 200:
+ self.skipTest("Time out for check dir")
+
+ # rmmod
+ self.cmd_and_check("rmmod configfs_sample")
+
+ @OETestDepends(['ssh.SSHTest.test_ssh'])
+ def test_cn_test(self):
+ # make sure if module exists
+ self.check_module_exist("connector/", "cn_test.ko")
+ # modprobe
+ self.cmd_and_check("modprobe cn_test")
+ # lsmod
+ self.cmd_and_check("lsmod | grep cn_test | cut -d\' \' -f1", "cn_test")
+ # check result
+ self.cmd_and_check("cat /proc/net/connector | grep cn_test | head -n1 | cut -d\' \' -f1", "cn_test")
+ # rmmod
+ self.cmd_and_check("rmmod cn_test")
diff --git a/meta/lib/oeqa/runtime/cases/ldd.py b/meta/lib/oeqa/runtime/cases/ldd.py
new file mode 100644
index 0000000000..f6841c6675
--- /dev/null
+++ b/meta/lib/oeqa/runtime/cases/ldd.py
@@ -0,0 +1,28 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
+from oeqa.runtime.case import OERuntimeTestCase
+from oeqa.core.decorator.depends import OETestDepends
+from oeqa.core.decorator.data import skipIfNotFeature
+from oeqa.runtime.decorator.package import OEHasPackage
+
+class LddTest(OERuntimeTestCase):
+
+ @OEHasPackage(["ldd"])
+ @OETestDepends(['ssh.SSHTest.test_ssh'])
+ def test_ldd(self):
+ status, output = self.target.run('which ldd')
+ msg = 'ldd does not exist in PATH: which ldd: %s' % output
+ self.assertEqual(status, 0, msg=msg)
+
+ cmd = ('for i in $(which ldd | xargs cat | grep "^RTLDLIST"| '
+ 'cut -d\'=\' -f2|tr -d \'"\'); '
+ 'do test -f $i && echo $i && break; done')
+ status, output = self.target.run(cmd)
+ self.assertEqual(status, 0, msg="ldd path not correct or RTLDLIST files don't exist.")
+
+ status, output = self.target.run("ldd /bin/true")
+ self.assertEqual(status, 0, msg="ldd failed to execute: %s" % output)
diff --git a/meta/lib/oeqa/runtime/cases/logrotate.py b/meta/lib/oeqa/runtime/cases/logrotate.py
new file mode 100644
index 0000000000..6ad980cb6a
--- /dev/null
+++ b/meta/lib/oeqa/runtime/cases/logrotate.py
@@ -0,0 +1,73 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
+# This test should cover https://bugzilla.yoctoproject.org/tr_show_case.cgi?case_id=289 testcase
+# Note that the image under test must have logrotate installed
+
+from oeqa.runtime.case import OERuntimeTestCase
+from oeqa.core.decorator.depends import OETestDepends
+from oeqa.runtime.decorator.package import OEHasPackage
+
+class LogrotateTest(OERuntimeTestCase):
+
+ @classmethod
+ def setUpClass(cls):
+ cls.tc.target.run('cp /etc/logrotate.d/wtmp $HOME/wtmp.oeqabak')
+
+ @classmethod
+ def tearDownClass(cls):
+ cls.tc.target.run('mv -f $HOME/wtmp.oeqabak /etc/logrotate.d/wtmp && rm -rf /var/log//logrotate_dir')
+ cls.tc.target.run('rm -rf /var/log/logrotate_testfile && rm -rf /etc/logrotate.d/logrotate_testfile')
+
+ @OETestDepends(['ssh.SSHTest.test_ssh'])
+ @OEHasPackage(['logrotate'])
+ def test_logrotate_wtmp(self):
+
+ # /var/log/wtmp may not always exist initially, so use touch to ensure it is present
+ status, output = self.target.run('touch /var/log/wtmp')
+ msg = ('Could not create/update /var/log/wtmp with touch')
+ self.assertEqual(status, 0, msg = msg)
+
+ status, output = self.target.run('mkdir /var/log//logrotate_dir')
+ msg = ('Could not create logrotate_dir. Output: %s' % output)
+ self.assertEqual(status, 0, msg = msg)
+
+ status, output = self.target.run('echo "create \n olddir /var/log//logrotate_dir \n include /etc/logrotate.d/wtmp" > /tmp/logrotate-test.conf')
+ msg = ('Could not write to /tmp/logrotate-test.conf')
+ self.assertEqual(status, 0, msg = msg)
+
+ # If logrotate fails to rotate the log, view the verbose output of logrotate to see what prevented it
+ _, logrotate_output = self.target.run('logrotate -vf /tmp/logrotate-test.conf')
+ status, _ = self.target.run('find /var/log//logrotate_dir -type f | grep wtmp.1')
+ msg = ("logrotate did not successfully rotate the wtmp log. Output from logrotate -vf: \n%s" % (logrotate_output))
+ self.assertEqual(status, 0, msg = msg)
+
+ @OETestDepends(['logrotate.LogrotateTest.test_logrotate_wtmp'])
+ def test_logrotate_newlog(self):
+
+ status, output = self.target.run('echo "oeqa logrotate test file" > /var/log/logrotate_testfile')
+ msg = ('Could not create logrotate test file in /var/log')
+ self.assertEqual(status, 0, msg = msg)
+
+ status, output = self.target.run('echo "/var/log/logrotate_testfile {\n missingok \n monthly \n rotate 1" > /etc/logrotate.d/logrotate_testfile')
+ msg = ('Could not write to /etc/logrotate.d/logrotate_testfile')
+ self.assertEqual(status, 0, msg = msg)
+
+ status, output = self.target.run('echo "create \n olddir /var/log//logrotate_dir \n include /etc/logrotate.d/logrotate_testfile" > /tmp/logrotate-test2.conf')
+ msg = ('Could not write to /tmp/logrotate_test2.conf')
+ self.assertEqual(status, 0, msg = msg)
+
+ status, output = self.target.run('find /var/log//logrotate_dir -type f | grep logrotate_testfile.1')
+ msg = ('A rotated log for logrotate_testfile is already present in logrotate_dir')
+ self.assertEqual(status, 1, msg = msg)
+
+ # If logrotate fails to rotate the log, view the verbose output of logrotate instead of just listing the files in olddir
+ _, logrotate_output = self.target.run('logrotate -vf /tmp/logrotate-test2.conf')
+ status, _ = self.target.run('find /var/log//logrotate_dir -type f | grep logrotate_testfile.1')
+ msg = ('logrotate did not successfully rotate the logrotate_test log. Output from logrotate -vf: \n%s' % (logrotate_output))
+ self.assertEqual(status, 0, msg = msg)
+
+
diff --git a/meta/lib/oeqa/runtime/cases/ltp.py b/meta/lib/oeqa/runtime/cases/ltp.py
new file mode 100644
index 0000000000..a66d5d13d7
--- /dev/null
+++ b/meta/lib/oeqa/runtime/cases/ltp.py
@@ -0,0 +1,119 @@
+# LTP runtime
+#
+# Copyright (c) 2019 MontaVista Software, LLC
+#
+# SPDX-License-Identifier: GPL-2.0-only
+#
+
+import time
+import datetime
+import pprint
+
+from oeqa.runtime.case import OERuntimeTestCase
+from oeqa.core.decorator.depends import OETestDepends
+from oeqa.runtime.decorator.package import OEHasPackage
+from oeqa.utils.logparser import LtpParser
+
+class LtpTestBase(OERuntimeTestCase):
+
+ @classmethod
+ def setUpClass(cls):
+ cls.ltp_startup()
+
+ @classmethod
+ def tearDownClass(cls):
+ cls.ltp_finishup()
+
+ @classmethod
+ def ltp_startup(cls):
+ cls.sections = {}
+ cls.failmsg = ""
+ test_log_dir = os.path.join(cls.td.get('WORKDIR', ''), 'testimage')
+ timestamp = datetime.datetime.now().strftime('%Y%m%d%H%M%S')
+
+ cls.ltptest_log_dir_link = os.path.join(test_log_dir, 'ltp_log')
+ cls.ltptest_log_dir = '%s.%s' % (cls.ltptest_log_dir_link, timestamp)
+ os.makedirs(cls.ltptest_log_dir)
+
+ cls.tc.target.run("mkdir -p /opt/ltp/results")
+
+ if not hasattr(cls.tc, "extraresults"):
+ cls.tc.extraresults = {}
+ cls.extras = cls.tc.extraresults
+ cls.extras['ltpresult.rawlogs'] = {'log': ""}
+
+
+ @classmethod
+ def ltp_finishup(cls):
+ cls.extras['ltpresult.sections'] = cls.sections
+
+ # update symlink to ltp_log
+ if os.path.exists(cls.ltptest_log_dir_link):
+ os.remove(cls.ltptest_log_dir_link)
+ os.symlink(os.path.basename(cls.ltptest_log_dir), cls.ltptest_log_dir_link)
+
+ if cls.failmsg:
+ cls.fail(cls.failmsg)
+
+class LtpTest(LtpTestBase):
+
+ ltp_groups = ["math", "syscalls", "dio", "io", "mm", "ipc", "sched", "nptl", "pty", "containers", "controllers", "filecaps", "cap_bounds", "fcntl-locktests", "connectors", "commands", "net.ipv6_lib", "input","fs_perms_simple"]
+
+ ltp_fs = ["fs", "fsx", "fs_bind"]
+ # skip kernel cpuhotplug
+ ltp_kernel = ["power_management_tests", "hyperthreading ", "kernel_misc", "hugetlb"]
+ ltp_groups += ltp_fs
+
+ def runltp(self, ltp_group):
+ cmd = '/opt/ltp/runltp -f %s -p -q -r /opt/ltp -l /opt/ltp/results/%s -I 1 -d /opt/ltp' % (ltp_group, ltp_group)
+ starttime = time.time()
+ (status, output) = self.target.run(cmd)
+ endtime = time.time()
+
+ with open(os.path.join(self.ltptest_log_dir, "%s-raw.log" % ltp_group), 'w') as f:
+ f.write(output)
+
+ self.extras['ltpresult.rawlogs']['log'] = self.extras['ltpresult.rawlogs']['log'] + output
+
+ # copy nice log from DUT
+ dst = os.path.join(self.ltptest_log_dir, "%s" % ltp_group )
+ remote_src = "/opt/ltp/results/%s" % ltp_group
+ (status, output) = self.target.copyFrom(remote_src, dst, True)
+ msg = 'File could not be copied. Output: %s' % output
+ if status:
+ self.target.logger.warning(msg)
+
+ parser = LtpParser()
+ results, sections = parser.parse(dst)
+
+ runtime = int(endtime-starttime)
+ sections['duration'] = runtime
+ self.sections[ltp_group] = sections
+
+ failed_tests = {}
+ for test in results:
+ result = results[test]
+ testname = ("ltpresult." + ltp_group + "." + test)
+ self.extras[testname] = {'status': result}
+ if result == 'FAILED':
+ failed_tests[ltp_group] = test
+
+ if failed_tests:
+ self.failmsg = self.failmsg + "Failed ptests:\n%s" % pprint.pformat(failed_tests)
+
+ # LTP runtime tests
+ @OETestDepends(['ssh.SSHTest.test_ssh'])
+ @OEHasPackage(["ltp"])
+ def test_ltp_help(self):
+ (status, output) = self.target.run('/opt/ltp/runltp --help')
+ msg = 'Failed to get ltp help. Output: %s' % output
+ self.assertEqual(status, 0, msg=msg)
+
+ @OETestDepends(['ltp.LtpTest.test_ltp_help'])
+ def test_ltp_groups(self):
+ for ltp_group in self.ltp_groups:
+ self.runltp(ltp_group)
+
+ @OETestDepends(['ltp.LtpTest.test_ltp_groups'])
+ def test_ltp_runltp_cve(self):
+ self.runltp("cve")
diff --git a/meta/lib/oeqa/runtime/cases/ltp_compliance.py b/meta/lib/oeqa/runtime/cases/ltp_compliance.py
new file mode 100644
index 0000000000..ba47c78fd4
--- /dev/null
+++ b/meta/lib/oeqa/runtime/cases/ltp_compliance.py
@@ -0,0 +1,97 @@
+# LTP compliance runtime
+#
+# Copyright (c) 2019 MontaVista Software, LLC
+#
+# SPDX-License-Identifier: GPL-2.0-only
+#
+
+import time
+import datetime
+import pprint
+
+from oeqa.runtime.case import OERuntimeTestCase
+from oeqa.core.decorator.depends import OETestDepends
+from oeqa.runtime.decorator.package import OEHasPackage
+from oeqa.utils.logparser import LtpComplianceParser
+
+class LtpPosixBase(OERuntimeTestCase):
+
+ @classmethod
+ def setUpClass(cls):
+ cls.ltp_startup()
+
+ @classmethod
+ def tearDownClass(cls):
+ cls.ltp_finishup()
+
+ @classmethod
+ def ltp_startup(cls):
+ cls.sections = {}
+ cls.failmsg = ""
+ test_log_dir = os.path.join(cls.td.get('WORKDIR', ''), 'testimage')
+ timestamp = datetime.datetime.now().strftime('%Y%m%d%H%M%S')
+
+ cls.ltptest_log_dir_link = os.path.join(test_log_dir, 'ltpcomp_log')
+ cls.ltptest_log_dir = '%s.%s' % (cls.ltptest_log_dir_link, timestamp)
+ os.makedirs(cls.ltptest_log_dir)
+
+ cls.tc.target.run("mkdir -p /opt/ltp/results")
+
+ if not hasattr(cls.tc, "extraresults"):
+ cls.tc.extraresults = {}
+ cls.extras = cls.tc.extraresults
+ cls.extras['ltpposixresult.rawlogs'] = {'log': ""}
+
+
+ @classmethod
+ def ltp_finishup(cls):
+ cls.extras['ltpposixresult.sections'] = cls.sections
+
+ # update symlink to ltp_log
+ if os.path.exists(cls.ltptest_log_dir_link):
+ os.remove(cls.ltptest_log_dir_link)
+
+ os.symlink(os.path.basename(cls.ltptest_log_dir), cls.ltptest_log_dir_link)
+
+ if cls.failmsg:
+ cls.fail(cls.failmsg)
+
+class LtpPosixTest(LtpPosixBase):
+ posix_groups = ["AIO", "MEM", "MSG", "SEM", "SIG", "THR", "TMR", "TPS"]
+
+ def runltp(self, posix_group):
+ cmd = "/opt/ltp/bin/run-posix-option-group-test.sh %s 2>@1 | tee /opt/ltp/results/%s" % (posix_group, posix_group)
+ starttime = time.time()
+ (status, output) = self.target.run(cmd)
+ endtime = time.time()
+
+ with open(os.path.join(self.ltptest_log_dir, "%s" % posix_group), 'w') as f:
+ f.write(output)
+
+ self.extras['ltpposixresult.rawlogs']['log'] = self.extras['ltpposixresult.rawlogs']['log'] + output
+
+ parser = LtpComplianceParser()
+ results, sections = parser.parse(os.path.join(self.ltptest_log_dir, "%s" % posix_group))
+
+ runtime = int(endtime-starttime)
+ sections['duration'] = runtime
+ self.sections[posix_group] = sections
+
+ failed_tests = {}
+ for test in results:
+ result = results[test]
+ testname = ("ltpposixresult." + posix_group + "." + test)
+ self.extras[testname] = {'status': result}
+ if result == 'FAILED':
+ failed_tests[posix_group] = test
+
+ if failed_tests:
+ self.failmsg = self.failmsg + "Failed ptests:\n%s" % pprint.pformat(failed_tests)
+
+ # LTP Posix compliance runtime tests
+
+ @OETestDepends(['ssh.SSHTest.test_ssh'])
+ @OEHasPackage(["ltp"])
+ def test_posix_groups(self):
+ for posix_group in self.posix_groups:
+ self.runltp(posix_group)
diff --git a/meta/lib/oeqa/runtime/cases/ltp_stress.py b/meta/lib/oeqa/runtime/cases/ltp_stress.py
new file mode 100644
index 0000000000..ce6f4bf59d
--- /dev/null
+++ b/meta/lib/oeqa/runtime/cases/ltp_stress.py
@@ -0,0 +1,97 @@
+# LTP Stress runtime
+#
+# Copyright (c) 2019 MontaVista Software, LLC
+#
+# SPDX-License-Identifier: MIT
+#
+
+import time
+import datetime
+import pprint
+
+from oeqa.runtime.case import OERuntimeTestCase
+from oeqa.core.decorator.depends import OETestDepends
+from oeqa.runtime.decorator.package import OEHasPackage
+from oeqa.core.decorator.data import skipIfQemu
+from oeqa.utils.logparser import LtpParser
+
+class LtpStressBase(OERuntimeTestCase):
+
+ @classmethod
+ def setUpClass(cls):
+ cls.ltp_startup()
+
+ @classmethod
+ def tearDownClass(cls):
+ cls.ltp_finishup()
+
+ @classmethod
+ def ltp_startup(cls):
+ cls.sections = {}
+ cls.failmsg = ""
+ test_log_dir = os.path.join(cls.td.get('WORKDIR', ''), 'testimage')
+ timestamp = datetime.datetime.now().strftime('%Y%m%d%H%M%S')
+
+ cls.ltptest_log_dir_link = os.path.join(test_log_dir, 'ltpstress_log')
+ cls.ltptest_log_dir = '%s.%s' % (cls.ltptest_log_dir_link, timestamp)
+ os.makedirs(cls.ltptest_log_dir)
+
+ cls.tc.target.run("mkdir -p /opt/ltp/results")
+
+ if not hasattr(cls.tc, "extraresults"):
+ cls.tc.extraresults = {}
+ cls.extras = cls.tc.extraresults
+ cls.extras['ltpstressresult.rawlogs'] = {'log': ""}
+
+
+ @classmethod
+ def ltp_finishup(cls):
+ cls.extras['ltpstressresult.sections'] = cls.sections
+
+ # update symlink to ltp_log
+ if os.path.exists(cls.ltptest_log_dir_link):
+ os.remove(cls.ltptest_log_dir_link)
+
+ os.symlink(os.path.basename(cls.ltptest_log_dir), cls.ltptest_log_dir_link)
+
+ if cls.failmsg:
+ cls.fail(cls.failmsg)
+
+class LtpStressTest(LtpStressBase):
+
+ def runltp(self, stress_group):
+ cmd = '/opt/ltp/runltp -f %s -p -q 2>@1 | tee /opt/ltp/results/%s' % (stress_group, stress_group)
+ starttime = time.time()
+ (status, output) = self.target.run(cmd)
+ endtime = time.time()
+ with open(os.path.join(self.ltptest_log_dir, "%s" % stress_group), 'w') as f:
+ f.write(output)
+
+ self.extras['ltpstressresult.rawlogs']['log'] = self.extras['ltpstressresult.rawlogs']['log'] + output
+
+ parser = LtpParser()
+ results, sections = parser.parse(os.path.join(self.ltptest_log_dir, "%s" % stress_group))
+
+ runtime = int(endtime-starttime)
+ sections['duration'] = runtime
+ self.sections[stress_group] = sections
+
+ failed_tests = {}
+ for test in results:
+ result = results[test]
+ testname = ("ltpstressresult." + stress_group + "." + test)
+ self.extras[testname] = {'status': result}
+ if result == 'FAILED':
+ failed_tests[stress_group] = test
+
+ if failed_tests:
+ self.failmsg = self.failmsg + "Failed ptests:\n%s" % pprint.pformat(failed_tests)
+
+ # LTP stress runtime tests
+ #
+ @skipIfQemu()
+ @OETestDepends(['ssh.SSHTest.test_ssh'])
+ @OEHasPackage(["ltp"])
+ def test_ltp_stress(self):
+ self.tc.target.run("sed -i -r 's/^fork12.*//' /opt/ltp/runtest/crashme")
+ self.runltp('crashme')
diff --git a/meta/lib/oeqa/runtime/cases/multilib.py b/meta/lib/oeqa/runtime/cases/multilib.py
new file mode 100644
index 0000000000..68556e45c5
--- /dev/null
+++ b/meta/lib/oeqa/runtime/cases/multilib.py
@@ -0,0 +1,49 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
+from oeqa.runtime.case import OERuntimeTestCase
+from oeqa.core.decorator.depends import OETestDepends
+from oeqa.core.decorator.data import skipIfNotInDataVar
+from oeqa.runtime.decorator.package import OEHasPackage
+
+import subprocess
+
+class MultilibTest(OERuntimeTestCase):
+
+ def archtest(self, binary, arch):
+ """
+ Check that ``binary`` has the ELF class ``arch`` (e.g. ELF32/ELF64).
+ """
+
+ dest = "{}/test_binary".format(self.td.get('T', ''))
+ self.target.copyFrom(binary, dest)
+ output = subprocess.check_output("readelf -h {}".format(dest), shell=True).decode()
+ os.remove(dest)
+
+ l = [l.split()[1] for l in output.split('\n') if "Class:" in l]
+ if l:
+ theclass = l[0]
+ else:
+ self.fail('Cannot parse readelf. Output:\n%s' % output)
+
+ msg = "%s isn't %s (is %s)" % (binary, arch, theclass)
+ self.assertEqual(theclass, arch, msg=msg)
+
+ @skipIfNotInDataVar('MULTILIBS', 'multilib:lib32',
+ "This isn't a multilib:lib32 image")
+ @OETestDepends(['ssh.SSHTest.test_ssh'])
+ @OEHasPackage(['lib32-libc6'])
+ def test_check_multilib_libc(self):
+ """
+ Check that a multilib image has both 32-bit and 64-bit libc in.
+ """
+ self.archtest("/lib/libc.so.6", "ELF32")
+ self.archtest("/lib64/libc.so.6", "ELF64")
+
+ @OETestDepends(['multilib.MultilibTest.test_check_multilib_libc'])
+ @OEHasPackage(['lib32-connman'])
+ def test_file_connman(self):
+ self.archtest("/usr/sbin/connmand", "ELF32")
diff --git a/meta/lib/oeqa/runtime/cases/oe_syslog.py b/meta/lib/oeqa/runtime/cases/oe_syslog.py
new file mode 100644
index 0000000000..cad0c88d26
--- /dev/null
+++ b/meta/lib/oeqa/runtime/cases/oe_syslog.py
@@ -0,0 +1,138 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
+from oeqa.runtime.case import OERuntimeTestCase
+from oeqa.core.decorator.depends import OETestDepends
+from oeqa.core.decorator.data import skipIfDataVar
+from oeqa.runtime.decorator.package import OEHasPackage
+import time
+
+class SyslogTest(OERuntimeTestCase):
+
+ @OETestDepends(['ssh.SSHTest.test_ssh'])
+ @OEHasPackage(["busybox-syslog", "sysklogd", "rsyslog", "syslog-ng"])
+ def test_syslog_running(self):
+ status, output = self.target.run(self.tc.target_cmds['ps'])
+ msg = "Failed to execute %s" % self.tc.target_cmds['ps']
+ self.assertEqual(status, 0, msg=msg)
+ msg = "No syslog daemon process; %s output:\n%s" % (self.tc.target_cmds['ps'], output)
+ hasdaemon = "syslogd" in output or "syslog-ng" in output or "svlogd" in output
+ self.assertTrue(hasdaemon, msg=msg)
+
+class SyslogTestConfig(OERuntimeTestCase):
+
+ def verif_not_running(self, pids):
+ for pid in pids:
+ status, err_output = self.target.run('kill -0 %s' %pid)
+ if not status:
+ self.logger.debug("previous %s is still running" %pid)
+ return 1
+
+ def verify_running(self, names):
+ pids = []
+ for name in names:
+ status, pid = self.target.run('pidof %s' %name)
+ if status:
+ self.logger.debug("%s is not running" %name)
+ return 1, pids
+ pids.append(pid)
+ return 0, pids
+
+
+ def restart_sanity(self, names, restart_cmd, pidchange=True):
+ status, original_pids = self.verify_running(names)
+ if status:
+ return False
+
+ status, output = self.target.run(restart_cmd)
+
+ msg = ('Could not restart %s service. Status and output: %s and %s' % (names, status, output))
+ self.assertEqual(status, 0, msg)
+
+ if not pidchange:
+ return True
+
+ # Always check for an error, most likely a race between shutting down and starting up
+ timeout = time.time() + 30
+
+ restarted = False
+ status = ""
+ while time.time() < timeout:
+ # Verify the previous ones are no longer running
+ status = self.verif_not_running(original_pids)
+ if status:
+ status = "Original syslog processes still running"
+ continue
+
+ status, pids = self.verify_running(names)
+ if status:
+ status = "New syslog processes not running"
+ continue
+
+ # Everything is fine now, so exit to continue the test
+ restarted = True
+ break
+
+ msg = ('%s didn\'t appear to restart: %s' % (names, status))
+ self.assertTrue(restarted, msg)
+
+ return True
+
+ @OETestDepends(['oe_syslog.SyslogTest.test_syslog_running'])
+ def test_syslog_logger(self):
+ status, output = self.target.run('logger foobar')
+ msg = "Can't log into syslog. Output: %s " % output
+ self.assertEqual(status, 0, msg=msg)
+
+ # There is no way to flush the logger to disk in all cases
+ time.sleep(1)
+
+ status, output = self.target.run('grep foobar /var/log/messages')
+ if status != 0:
+ if self.tc.td.get("VIRTUAL-RUNTIME_init_manager") == "systemd":
+ status, output = self.target.run('journalctl -o cat | grep foobar')
+ else:
+ status, output = self.target.run('logread | grep foobar')
+ msg = ('Test log string not found in /var/log/messages or logread.'
+ ' Output: %s ' % output)
+ self.assertEqual(status, 0, msg=msg)
+
+
+ @OETestDepends(['oe_syslog.SyslogTest.test_syslog_running'])
+ def test_syslog_restart(self):
+ if self.restart_sanity(['systemd-journald'], 'systemctl restart syslog.service', pidchange=False):
+ pass
+ elif self.restart_sanity(['rsyslogd'], '/etc/init.d/rsyslog restart'):
+ pass
+ elif self.restart_sanity(['syslogd', 'klogd'], '/etc/init.d/syslog restart'):
+ pass
+ else:
+ self.logger.info("No syslog found to restart, ignoring")
+
+
+ @OETestDepends(['oe_syslog.SyslogTestConfig.test_syslog_logger'])
+ @OEHasPackage(["busybox-syslog"])
+ @skipIfDataVar('VIRTUAL-RUNTIME_init_manager', 'systemd',
+ 'Not appropiate for systemd image')
+ def test_syslog_startup_config(self):
+ cmd = 'echo "LOGFILE=/var/log/test" >> /etc/syslog-startup.conf'
+ self.target.run(cmd)
+
+ self.test_syslog_restart()
+
+ cmd = 'logger foobar'
+ status, output = self.target.run(cmd)
+ msg = 'Logger command failed, %s. Output: %s ' % (status, output)
+ self.assertEqual(status, 0, msg=msg)
+
+ cmd = 'cat /var/log/test'
+ status, output = self.target.run(cmd)
+ if "foobar" not in output or status:
+ self.fail("'foobar' not found in logfile, status %s, contents %s" % (status, output))
+
+ cmd = "sed -i 's#LOGFILE=/var/log/test##' /etc/syslog-startup.conf"
+ self.target.run(cmd)
+ self.test_syslog_restart()
diff --git a/meta/lib/oeqa/runtime/cases/opkg.py b/meta/lib/oeqa/runtime/cases/opkg.py
new file mode 100644
index 0000000000..a29c93e59a
--- /dev/null
+++ b/meta/lib/oeqa/runtime/cases/opkg.py
@@ -0,0 +1,60 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
+import os
+from oeqa.utils.httpserver import HTTPService
+from oeqa.runtime.case import OERuntimeTestCase
+from oeqa.core.decorator.data import skipIfNotDataVar, skipIfNotFeature, skipIfFeature
+from oeqa.runtime.decorator.package import OEHasPackage
+
+class OpkgTest(OERuntimeTestCase):
+
+ def pkg(self, command, expected = 0):
+ command = 'opkg %s' % command
+ status, output = self.target.run(command, 1500)
+ message = os.linesep.join([command, output])
+ self.assertEqual(status, expected, message)
+ return output
+
+class OpkgRepoTest(OpkgTest):
+
+ @classmethod
+ def setUp(cls):
+ allarchfeed = 'all'
+ if cls.tc.td["MULTILIB_VARIANTS"]:
+ allarchfeed = cls.tc.td["TUNE_PKGARCH"]
+ service_repo = os.path.join(cls.tc.td['DEPLOY_DIR_IPK'], allarchfeed)
+ cls.repo_server = HTTPService(service_repo,
+ '0.0.0.0', port=cls.tc.target.server_port,
+ logger=cls.tc.logger)
+ cls.repo_server.start()
+
+ @classmethod
+ def tearDown(cls):
+ cls.repo_server.stop()
+
+ def setup_source_config_for_package_install(self):
+ apt_get_source_server = 'http://%s:%s/' % (self.tc.target.server_ip, self.repo_server.port)
+ apt_get_sourceslist_dir = '/etc/opkg/'
+ self.target.run('cd %s; echo src/gz all %s >> opkg.conf' % (apt_get_sourceslist_dir, apt_get_source_server))
+
+ def cleanup_source_config_for_package_install(self):
+ apt_get_sourceslist_dir = '/etc/opkg/'
+ self.target.run('cd %s; sed -i "/^src/d" opkg.conf' % (apt_get_sourceslist_dir))
+
+ @skipIfNotFeature('package-management',
+ 'Test requires package-management to be in IMAGE_FEATURES')
+ @skipIfNotDataVar('IMAGE_PKGTYPE', 'ipk',
+ 'IPK is not the primary package manager')
+ @skipIfFeature('read-only-rootfs',
+ 'Test does not work with read-only-rootfs in IMAGE_FEATURES')
+ @OEHasPackage(['opkg'])
+ def test_opkg_install_from_repo(self):
+ self.setup_source_config_for_package_install()
+ self.pkg('update')
+ self.pkg('remove run-postinsts-dev')
+ self.pkg('install run-postinsts-dev')
+ self.cleanup_source_config_for_package_install()
diff --git a/meta/lib/oeqa/runtime/cases/pam.py b/meta/lib/oeqa/runtime/cases/pam.py
new file mode 100644
index 0000000000..b3e8b56c3c
--- /dev/null
+++ b/meta/lib/oeqa/runtime/cases/pam.py
@@ -0,0 +1,40 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
+# This test should cover https://bugzilla.yoctoproject.org/tr_show_case.cgi?case_id=287 testcase
+# Note that the image under test must have "pam" in DISTRO_FEATURES
+
+from oeqa.runtime.case import OERuntimeTestCase
+from oeqa.core.decorator.depends import OETestDepends
+from oeqa.core.decorator.data import skipIfNotFeature
+from oeqa.runtime.decorator.package import OEHasPackage
+
+class PamBasicTest(OERuntimeTestCase):
+
+ @skipIfNotFeature('pam', 'Test requires pam to be in DISTRO_FEATURES')
+ @OETestDepends(['ssh.SSHTest.test_ssh'])
+ @OEHasPackage(['shadow'])
+ @OEHasPackage(['shadow-base'])
+ def test_pam(self):
+ status, output = self.target.run('login --help')
+ msg = ('login command does not work as expected. '
+ 'Status and output:%s and %s' % (status, output))
+ self.assertEqual(status, 1, msg = msg)
+
+ status, output = self.target.run('passwd --help')
+ msg = ('passwd command does not work as expected. '
+ 'Status and output:%s and %s' % (status, output))
+ self.assertEqual(status, 0, msg = msg)
+
+ status, output = self.target.run('su --help')
+ msg = ('su command does not work as expected. '
+ 'Status and output:%s and %s' % (status, output))
+ self.assertEqual(status, 0, msg = msg)
+
+ status, output = self.target.run('useradd --help')
+ msg = ('useradd command does not work as expected. '
+ 'Status and output:%s and %s' % (status, output))
+ self.assertEqual(status, 0, msg = msg)
diff --git a/meta/lib/oeqa/runtime/cases/parselogs.py b/meta/lib/oeqa/runtime/cases/parselogs.py
new file mode 100644
index 0000000000..e67d3750da
--- /dev/null
+++ b/meta/lib/oeqa/runtime/cases/parselogs.py
@@ -0,0 +1,393 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
+import os
+
+from subprocess import check_output
+from shutil import rmtree
+from oeqa.runtime.case import OERuntimeTestCase
+from oeqa.core.decorator.depends import OETestDepends
+from oeqa.core.decorator.data import skipIfDataVar
+from oeqa.runtime.decorator.package import OEHasPackage
+
+#in the future these lists could be moved outside of module
+errors = ["error", "cannot", "can\'t", "failed"]
+
+common_errors = [
+ "(WW) warning, (EE) error, (NI) not implemented, (??) unknown.",
+ "dma timeout",
+ "can\'t add hid device:",
+ "usbhid: probe of ",
+ "_OSC failed (AE_ERROR)",
+ "_OSC failed (AE_SUPPORT)",
+ "AE_ALREADY_EXISTS",
+ "ACPI _OSC request failed (AE_SUPPORT)",
+ "can\'t disable ASPM",
+ "Failed to load module \"vesa\"",
+ "Failed to load module vesa",
+ "Failed to load module \"modesetting\"",
+ "Failed to load module modesetting",
+ "Failed to load module \"glx\"",
+ "Failed to load module \"fbdev\"",
+ "Failed to load module fbdev",
+ "Failed to load module glx",
+ "[drm] Cannot find any crtc or sizes",
+ "_OSC failed (AE_NOT_FOUND); disabling ASPM",
+ "Open ACPI failed (/var/run/acpid.socket) (No such file or directory)",
+ "NX (Execute Disable) protection cannot be enabled: non-PAE kernel!",
+ "hd.: possibly failed opcode",
+ 'NETLINK INITIALIZATION FAILED',
+ 'kernel: Cannot find map file',
+ 'omap_hwmod: debugss: _wait_target_disable failed',
+ 'VGA arbiter: cannot open kernel arbiter, no multi-card support',
+ 'Failed to find URL:http://ipv4.connman.net/online/status.html',
+ 'Online check failed for',
+ 'netlink init failed',
+ 'Fast TSC calibration',
+ "BAR 0-9",
+ "Failed to load module \"ati\"",
+ "controller can't do DEVSLP, turning off",
+ "stmmac_dvr_probe: warning: cannot get CSR clock",
+ "error: couldn\'t mount because of unsupported optional features",
+ "GPT: Use GNU Parted to correct GPT errors",
+ "Cannot set xattr user.Librepo.DownloadInProgress",
+ "Failed to read /var/lib/nfs/statd/state: Success",
+ "error retry time-out =",
+ "logind: cannot setup systemd-logind helper (-61), using legacy fallback",
+ "Failed to rename network interface",
+ "Failed to process device, ignoring: Device or resource busy",
+ "Cannot find a map file",
+ "[rdrand]: Initialization Failed",
+ "[rndr ]: Initialization Failed",
+ "[pulseaudio] authkey.c: Failed to open cookie file",
+ "[pulseaudio] authkey.c: Failed to load authentication key",
+ "was skipped because of a failed condition check",
+ "was skipped because all trigger condition checks failed",
+ "xf86OpenConsole: Switching VT failed",
+ "Failed to read LoaderConfigTimeoutOneShot variable, ignoring: Operation not supported",
+ "Failed to read LoaderEntryOneShot variable, ignoring: Operation not supported",
+ ]
+
+video_related = [
+]
+
+x86_common = [
+ '[drm:psb_do_init] *ERROR* Debug is',
+ 'wrong ELF class',
+ 'Could not enable PowerButton event',
+ 'probe of LNXPWRBN:00 failed with error -22',
+ 'pmd_set_huge: Cannot satisfy',
+ 'failed to setup card detect gpio',
+ 'amd_nb: Cannot enumerate AMD northbridges',
+ 'failed to retrieve link info, disabling eDP',
+ 'Direct firmware load for iwlwifi',
+ 'Direct firmware load for regulatory.db',
+ 'failed to load regulatory.db',
+] + common_errors
+
+qemux86_common = [
+ 'wrong ELF class',
+ "fail to add MMCONFIG information, can't access extended PCI configuration space under this bridge.",
+ "can't claim BAR ",
+ 'amd_nb: Cannot enumerate AMD northbridges',
+ 'tsc: HPET/PMTIMER calibration failed',
+ "modeset(0): Failed to initialize the DRI2 extension",
+ "glamor initialization failed",
+ "blk_update_request: I/O error, dev fd0, sector 0 op 0x0:(READ)",
+ "floppy: error",
+ 'failed to IDENTIFY (I/O error, err_mask=0x4)',
+] + common_errors
+
+ignore_errors = {
+ 'default' : common_errors,
+ 'qemux86' : [
+ 'Failed to access perfctr msr (MSR',
+ 'pci 0000:00:00.0: [Firmware Bug]: reg 0x..: invalid BAR (can\'t size)',
+ ] + qemux86_common,
+ 'qemux86-64' : qemux86_common,
+ 'qemumips' : [
+ 'Failed to load module "glx"',
+ 'pci 0000:00:00.0: [Firmware Bug]: reg 0x..: invalid BAR (can\'t size)',
+ 'cacheinfo: Failed to find cpu0 device node',
+ ] + common_errors,
+ 'qemumips64' : [
+ 'pci 0000:00:00.0: [Firmware Bug]: reg 0x..: invalid BAR (can\'t size)',
+ 'cacheinfo: Failed to find cpu0 device node',
+ ] + common_errors,
+ 'qemuppc' : [
+ 'PCI 0000:00 Cannot reserve Legacy IO [io 0x0000-0x0fff]',
+ 'host side 80-wire cable detection failed, limiting max speed',
+ 'mode "640x480" test failed',
+ 'Failed to load module "glx"',
+ 'can\'t handle BAR above 4GB',
+ 'Cannot reserve Legacy IO',
+ ] + common_errors,
+ 'qemuppc64' : [
+ 'vio vio: uevent: failed to send synthetic uevent',
+ 'synth uevent: /devices/vio: failed to send uevent',
+ 'PCI 0000:00 Cannot reserve Legacy IO [io 0x10000-0x10fff]',
+ ] + common_errors,
+ 'qemuarmv5' : [
+ 'mmci-pl18x: probe of fpga:05 failed with error -22',
+ 'mmci-pl18x: probe of fpga:0b failed with error -22',
+ 'Failed to load module "glx"',
+ 'OF: amba_device_add() failed (-19) for /amba/smc@10100000',
+ 'OF: amba_device_add() failed (-19) for /amba/mpmc@10110000',
+ 'OF: amba_device_add() failed (-19) for /amba/sctl@101e0000',
+ 'OF: amba_device_add() failed (-19) for /amba/watchdog@101e1000',
+ 'OF: amba_device_add() failed (-19) for /amba/sci@101f0000',
+ 'OF: amba_device_add() failed (-19) for /amba/spi@101f4000',
+ 'OF: amba_device_add() failed (-19) for /amba/ssp@101f4000',
+ 'OF: amba_device_add() failed (-19) for /amba/fpga/sci@a000',
+ 'Failed to initialize \'/amba/timer@101e3000\': -22',
+ 'jitterentropy: Initialization failed with host not compliant with requirements: 2',
+ 'clcd-pl11x: probe of 10120000.display failed with error -2',
+ 'arm-charlcd 10008000.lcd: error -ENXIO: IRQ index 0 not found'
+ ] + common_errors,
+ 'qemuarm64' : [
+ 'Fatal server error:',
+ '(EE) Server terminated with error (1). Closing log file.',
+ 'dmi: Firmware registration failed.',
+ 'irq: type mismatch, failed to map hwirq-27 for /intc',
+ 'logind: failed to get session seat',
+ ] + common_errors,
+ 'intel-core2-32' : [
+ 'ACPI: No _BQC method, cannot determine initial brightness',
+ '[Firmware Bug]: ACPI: No _BQC method, cannot determine initial brightness',
+ '(EE) Failed to load module "psb"',
+ '(EE) Failed to load module psb',
+ '(EE) Failed to load module "psbdrv"',
+ '(EE) Failed to load module psbdrv',
+ '(EE) open /dev/fb0: No such file or directory',
+ '(EE) AIGLX: reverting to software rendering',
+ 'dmi: Firmware registration failed.',
+ 'ioremap error for 0x78',
+ ] + x86_common,
+ 'intel-corei7-64' : [
+ 'can\'t set Max Payload Size to 256',
+ 'intel_punit_ipc: can\'t request region for resource',
+ '[drm] parse error at position 4 in video mode \'efifb\'',
+ 'ACPI Error: Could not enable RealTimeClock event',
+ 'ACPI Warning: Could not enable fixed event - RealTimeClock',
+ 'hci_intel INT33E1:00: Unable to retrieve gpio',
+ 'hci_intel: probe of INT33E1:00 failed',
+ 'can\'t derive routing for PCI INT A',
+ 'failed to read out thermal zone',
+ 'Bluetooth: hci0: Setting Intel event mask failed',
+ 'ttyS2 - failed to request DMA',
+ 'Bluetooth: hci0: Failed to send firmware data (-38)',
+ 'atkbd serio0: Failed to enable keyboard on isa0060/serio0',
+ ] + x86_common,
+ 'genericx86' : x86_common,
+ 'genericx86-64' : [
+ 'Direct firmware load for i915',
+ 'Failed to load firmware i915',
+ 'Failed to fetch GuC',
+ 'Failed to initialize GuC',
+ 'Failed to load DMC firmware',
+ 'The driver is built-in, so to load the firmware you need to',
+ ] + x86_common,
+ 'edgerouter' : [
+ 'not creating \'/sys/firmware/fdt\'',
+ 'Failed to find cpu0 device node',
+ 'Fatal server error:',
+ 'Server terminated with error',
+ ] + common_errors,
+ 'beaglebone-yocto' : [
+ 'Direct firmware load for regulatory.db',
+ 'failed to load regulatory.db',
+ 'l4_wkup_cm',
+ 'Failed to load module "glx"',
+ 'Failed to make EGL context current',
+ 'glamor initialization failed',
+ ] + common_errors,
+}
+
+log_locations = ["/var/log/","/var/log/dmesg", "/tmp/dmesg_output.log"]
+
+class ParseLogsTest(OERuntimeTestCase):
+
+ @classmethod
+ def setUpClass(cls):
+ cls.errors = errors
+
+ # When systemd is enabled we need to notice errors on
+ # circular dependencies in units.
+ if 'systemd' in cls.td.get('DISTRO_FEATURES', ''):
+ cls.errors.extend([
+ 'Found ordering cycle on',
+ 'Breaking ordering cycle by deleting job',
+ 'deleted to break ordering cycle',
+ 'Ordering cycle found, skipping',
+ ])
+
+ cls.ignore_errors = ignore_errors
+ cls.log_locations = log_locations
+ cls.msg = ''
+ is_lsb, _ = cls.tc.target.run("which LSB_Test.sh")
+ if is_lsb == 0:
+ for machine in cls.ignore_errors:
+ cls.ignore_errors[machine] = cls.ignore_errors[machine] \
+ + video_related
+
+ def getMachine(self):
+ return self.td.get('MACHINE', '')
+
+ def getWorkdir(self):
+ return self.td.get('WORKDIR', '')
+
+ # Get some information on the CPU of the machine to display at the
+ # beginning of the output. This info might be useful in some cases.
+ def getHardwareInfo(self):
+ hwi = ""
+ cmd = ('cat /proc/cpuinfo | grep "model name" | head -n1 | '
+ " awk 'BEGIN{FS=\":\"}{print $2}'")
+ _, cpu_name = self.target.run(cmd)
+
+ cmd = ('cat /proc/cpuinfo | grep "cpu cores" | head -n1 | '
+ "awk {'print $4'}")
+ _, cpu_physical_cores = self.target.run(cmd)
+
+ cmd = 'cat /proc/cpuinfo | grep "processor" | wc -l'
+ _, cpu_logical_cores = self.target.run(cmd)
+
+ _, cpu_arch = self.target.run('uname -m')
+
+ hwi += 'Machine information: \n'
+ hwi += '*******************************\n'
+ hwi += 'Machine name: ' + self.getMachine() + '\n'
+ hwi += 'CPU: ' + str(cpu_name) + '\n'
+ hwi += 'Arch: ' + str(cpu_arch)+ '\n'
+ hwi += 'Physical cores: ' + str(cpu_physical_cores) + '\n'
+ hwi += 'Logical cores: ' + str(cpu_logical_cores) + '\n'
+ hwi += '*******************************\n'
+
+ return hwi
+
+ # Go through the log locations provided and if it's a folder
+ # create a list with all the .log files in it, if it's a file
+ # just add it to that list.
+ def getLogList(self, log_locations):
+ logs = []
+ for location in log_locations:
+ status, _ = self.target.run('test -f ' + str(location))
+ if status == 0:
+ logs.append(str(location))
+ else:
+ status, _ = self.target.run('test -d ' + str(location))
+ if status == 0:
+ cmd = 'find ' + str(location) + '/*.log -maxdepth 1 -type f'
+ status, output = self.target.run(cmd)
+ if status == 0:
+ output = output.splitlines()
+ for logfile in output:
+ logs.append(os.path.join(location, str(logfile)))
+ return logs
+
+ # Copy the log files to be parsed locally
+ def transfer_logs(self, log_list):
+ workdir = self.getWorkdir()
+ self.target_logs = workdir + '/' + 'target_logs'
+ target_logs = self.target_logs
+ if os.path.exists(target_logs):
+ rmtree(self.target_logs)
+ os.makedirs(target_logs)
+ for f in log_list:
+ self.target.copyFrom(str(f), target_logs)
+
+ # Get the local list of logs
+ def get_local_log_list(self, log_locations):
+ self.transfer_logs(self.getLogList(log_locations))
+ list_dir = os.listdir(self.target_logs)
+ dir_files = [os.path.join(self.target_logs, f) for f in list_dir]
+ logs = [f for f in dir_files if os.path.isfile(f)]
+ return logs
+
+ # Build the grep command to be used with filters and exclusions
+ def build_grepcmd(self, errors, ignore_errors, log):
+ grepcmd = 'grep '
+ grepcmd += '-Ei "'
+ for error in errors:
+ grepcmd += r'\<' + error + r'\>' + '|'
+ grepcmd = grepcmd[:-1]
+ grepcmd += '" ' + str(log) + " | grep -Eiv \'"
+
+ try:
+ errorlist = ignore_errors[self.getMachine()]
+ except KeyError:
+ self.msg += 'No ignore list found for this machine, using default\n'
+ errorlist = ignore_errors['default']
+
+ for ignore_error in errorlist:
+ ignore_error = ignore_error.replace('(', r'\(')
+ ignore_error = ignore_error.replace(')', r'\)')
+ ignore_error = ignore_error.replace("'", '.')
+ ignore_error = ignore_error.replace('?', r'\?')
+ ignore_error = ignore_error.replace('[', r'\[')
+ ignore_error = ignore_error.replace(']', r'\]')
+ ignore_error = ignore_error.replace('*', r'\*')
+ ignore_error = ignore_error.replace('0-9', '[0-9]')
+ grepcmd += ignore_error + '|'
+ grepcmd = grepcmd[:-1]
+ grepcmd += "\'"
+
+ return grepcmd
+
+ # Grep only the errors so that their context could be collected.
+ # Default context is 10 lines before and after the error itself
+ def parse_logs(self, errors, ignore_errors, logs,
+ lines_before = 10, lines_after = 10):
+ results = {}
+ rez = []
+ grep_output = ''
+
+ for log in logs:
+ result = None
+ thegrep = self.build_grepcmd(errors, ignore_errors, log)
+
+ try:
+ result = check_output(thegrep, shell=True).decode('utf-8')
+ except:
+ pass
+
+ if result is not None:
+ results[log] = {}
+ rez = result.splitlines()
+
+ for xrez in rez:
+ try:
+ cmd = ['grep', '-F', xrez, '-B', str(lines_before)]
+ cmd += ['-A', str(lines_after), log]
+ grep_output = check_output(cmd).decode('utf-8')
+ except:
+ pass
+ results[log][xrez]=grep_output
+
+ return results
+
+ # Get the output of dmesg and write it in a file.
+ # This file is added to log_locations.
+ def write_dmesg(self):
+ (status, dmesg) = self.target.run('dmesg > /tmp/dmesg_output.log')
+
+ @OETestDepends(['ssh.SSHTest.test_ssh'])
+ def test_parselogs(self):
+ self.write_dmesg()
+ log_list = self.get_local_log_list(self.log_locations)
+ result = self.parse_logs(self.errors, self.ignore_errors, log_list)
+ print(self.getHardwareInfo())
+ errcount = 0
+ for log in result:
+ self.msg += 'Log: ' + log + '\n'
+ self.msg += '-----------------------\n'
+ for error in result[log]:
+ errcount += 1
+ self.msg += 'Central error: ' + str(error) + '\n'
+ self.msg += '***********************\n'
+ self.msg += result[str(log)][str(error)] + '\n'
+ self.msg += '***********************\n'
+ self.msg += '%s errors found in logs.' % errcount
+ self.assertEqual(errcount, 0, msg=self.msg)
diff --git a/meta/lib/oeqa/runtime/cases/perl.py b/meta/lib/oeqa/runtime/cases/perl.py
new file mode 100644
index 0000000000..f11b300836
--- /dev/null
+++ b/meta/lib/oeqa/runtime/cases/perl.py
@@ -0,0 +1,19 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
+import os
+
+from oeqa.runtime.case import OERuntimeTestCase
+from oeqa.core.decorator.depends import OETestDepends
+from oeqa.runtime.decorator.package import OEHasPackage
+
+class PerlTest(OERuntimeTestCase):
+ @OETestDepends(['ssh.SSHTest.test_ssh'])
+ @OEHasPackage(['perl'])
+ def test_perl_works(self):
+ status, output = self.target.run("perl -e '$_=\"Uryyb, jbeyq\"; tr/a-zA-Z/n-za-mN-ZA-M/;print'")
+ self.assertEqual(status, 0)
+ self.assertEqual(output, "Hello, world")
diff --git a/meta/lib/oeqa/runtime/cases/ping.py b/meta/lib/oeqa/runtime/cases/ping.py
new file mode 100644
index 0000000000..967b44175f
--- /dev/null
+++ b/meta/lib/oeqa/runtime/cases/ping.py
@@ -0,0 +1,32 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
+from subprocess import Popen, PIPE
+
+from oeqa.runtime.case import OERuntimeTestCase
+from oeqa.core.decorator.oetimeout import OETimeout
+from oeqa.core.exception import OEQATimeoutError
+
+class PingTest(OERuntimeTestCase):
+
+ @OETimeout(30)
+ def test_ping(self):
+ output = ''
+ count = 0
+ try:
+ while count < 5:
+ cmd = 'ping -c 1 %s' % self.target.ip
+ proc = Popen(cmd, shell=True, stdout=PIPE)
+ output += proc.communicate()[0].decode('utf-8')
+ if proc.poll() == 0:
+ count += 1
+ else:
+ count = 0
+ except OEQATimeoutError:
+ self.fail("Ping timeout error for address %s, count %s, output: %s" % (self.target.ip, count, output))
+ msg = ('Expected 5 consecutive, got %d.\n'
+ 'ping output is:\n%s' % (count,output))
+ self.assertEqual(count, 5, msg = msg)
diff --git a/meta/lib/oeqa/runtime/cases/ptest.py b/meta/lib/oeqa/runtime/cases/ptest.py
new file mode 100644
index 0000000000..3ef9022188
--- /dev/null
+++ b/meta/lib/oeqa/runtime/cases/ptest.py
@@ -0,0 +1,114 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
+import os
+import unittest
+import pprint
+import datetime
+
+from oeqa.runtime.case import OERuntimeTestCase
+from oeqa.core.decorator.depends import OETestDepends
+from oeqa.core.decorator.data import skipIfNotFeature
+from oeqa.runtime.decorator.package import OEHasPackage
+from oeqa.utils.logparser import PtestParser
+
+class PtestRunnerTest(OERuntimeTestCase):
+
+ @skipIfNotFeature('ptest', 'Test requires ptest to be in DISTRO_FEATURES')
+ @OETestDepends(['ssh.SSHTest.test_ssh'])
+ @OEHasPackage(['ptest-runner'])
+ @unittest.expectedFailure
+ def test_ptestrunner_expectfail(self):
+ if not self.td.get('PTEST_EXPECT_FAILURE'):
+ self.skipTest('Cannot run ptests with @expectedFailure as ptests are required to pass')
+ self.do_ptestrunner()
+
+ @skipIfNotFeature('ptest', 'Test requires ptest to be in DISTRO_FEATURES')
+ @OETestDepends(['ssh.SSHTest.test_ssh'])
+ @OEHasPackage(['ptest-runner'])
+ def test_ptestrunner_expectsuccess(self):
+ if self.td.get('PTEST_EXPECT_FAILURE'):
+ self.skipTest('Cannot run ptests without @expectedFailure as ptests are expected to fail')
+ self.do_ptestrunner()
+
+ def do_ptestrunner(self):
+ status, output = self.target.run('which ptest-runner', 0)
+ if status != 0:
+ self.skipTest("No -ptest packages are installed in the image")
+
+ test_log_dir = self.td.get('TEST_LOG_DIR', '')
+ # The TEST_LOG_DIR maybe NULL when testimage is added after
+ # testdata.json is generated.
+ if not test_log_dir:
+ test_log_dir = os.path.join(self.td.get('WORKDIR', ''), 'testimage')
+ # Make the test output path absolute, otherwise the output content will be
+ # created relative to current directory
+ if not os.path.isabs(test_log_dir):
+ test_log_dir = os.path.join(self.td.get('TOPDIR', ''), test_log_dir)
+ # Don't use self.td.get('DATETIME'), it's from testdata.json, not
+ # up-to-date, and may cause "File exists" when re-reun.
+ timestamp = datetime.datetime.now().strftime('%Y%m%d%H%M%S')
+ ptest_log_dir_link = os.path.join(test_log_dir, 'ptest_log')
+ ptest_log_dir = '%s.%s' % (ptest_log_dir_link, timestamp)
+ ptest_runner_log = os.path.join(ptest_log_dir, 'ptest-runner.log')
+
+ libdir = self.td.get('libdir', '')
+ ptest_dirs = [ '/usr/lib' ]
+ if not libdir in ptest_dirs:
+ ptest_dirs.append(libdir)
+ status, output = self.target.run('ptest-runner -t 450 -d \"{}\"'.format(' '.join(ptest_dirs)), 0)
+ os.makedirs(ptest_log_dir)
+ with open(ptest_runner_log, 'w') as f:
+ f.write(output)
+
+ # status != 0 is OK since some ptest tests may fail
+ self.assertTrue(status != 127, msg="Cannot execute ptest-runner!")
+
+ if not hasattr(self.tc, "extraresults"):
+ self.tc.extraresults = {}
+ extras = self.tc.extraresults
+ extras['ptestresult.rawlogs'] = {'log': output}
+
+ # Parse and save results
+ parser = PtestParser()
+ results, sections = parser.parse(ptest_runner_log)
+ parser.results_as_files(ptest_log_dir)
+ if os.path.exists(ptest_log_dir_link):
+ # Remove the old link to create a new one
+ os.remove(ptest_log_dir_link)
+ os.symlink(os.path.basename(ptest_log_dir), ptest_log_dir_link)
+
+ extras['ptestresult.sections'] = sections
+
+ trans = str.maketrans("()", "__")
+ for section in results:
+ for test in results[section]:
+ result = results[section][test]
+ testname = "ptestresult." + (section or "No-section") + "." + "_".join(test.translate(trans).split())
+ extras[testname] = {'status': result}
+
+ failed_tests = {}
+
+ for section in sections:
+ if 'exitcode' in sections[section].keys():
+ failed_tests[section] = sections[section]["log"]
+
+ for section in results:
+ failed_testcases = [ "_".join(test.translate(trans).split()) for test in results[section] if results[section][test] == 'FAILED' ]
+ if failed_testcases:
+ failed_tests[section] = failed_testcases
+
+ failmsg = ""
+ status, output = self.target.run('dmesg | grep "Killed process"', 0)
+ if output:
+ failmsg = "ERROR: Processes were killed by the OOM Killer:\n%s\n" % output
+
+ if failed_tests:
+ failmsg = failmsg + "Failed ptests:\n%s" % pprint.pformat(failed_tests)
+
+ if failmsg:
+ self.logger.warning("There were failing ptests.")
+ self.fail(failmsg)
diff --git a/meta/lib/oeqa/runtime/cases/python.py b/meta/lib/oeqa/runtime/cases/python.py
new file mode 100644
index 0000000000..5d6d133480
--- /dev/null
+++ b/meta/lib/oeqa/runtime/cases/python.py
@@ -0,0 +1,21 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
+from oeqa.runtime.case import OERuntimeTestCase
+from oeqa.core.decorator.depends import OETestDepends
+from oeqa.runtime.decorator.package import OEHasPackage
+
+class PythonTest(OERuntimeTestCase):
+ @OETestDepends(['ssh.SSHTest.test_ssh'])
+ @OEHasPackage(['python3-core'])
+ def test_python3(self):
+ cmd = "python3 -c \"import codecs; print(codecs.encode('Uryyb, jbeyq', 'rot13'))\""
+ status, output = self.target.run(cmd)
+ msg = 'Exit status was not 0. Output: %s' % output
+ self.assertEqual(status, 0, msg=msg)
+
+ msg = 'Incorrect output: %s' % output
+ self.assertEqual(output, "Hello, world", msg=msg)
diff --git a/meta/lib/oeqa/runtime/cases/rpm.py b/meta/lib/oeqa/runtime/cases/rpm.py
new file mode 100644
index 0000000000..fa86eb0537
--- /dev/null
+++ b/meta/lib/oeqa/runtime/cases/rpm.py
@@ -0,0 +1,145 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
+import os
+import fnmatch
+import time
+
+from oeqa.runtime.case import OERuntimeTestCase
+from oeqa.core.decorator.depends import OETestDepends
+from oeqa.core.decorator.data import skipIfDataVar
+from oeqa.runtime.decorator.package import OEHasPackage
+from oeqa.core.utils.path import findFile
+
+class RpmBasicTest(OERuntimeTestCase):
+
+ @OEHasPackage(['rpm'])
+ @OETestDepends(['ssh.SSHTest.test_ssh'])
+ def test_rpm_help(self):
+ status, output = self.target.run('rpm --help')
+ msg = 'status and output: %s and %s' % (status, output)
+ self.assertEqual(status, 0, msg=msg)
+
+ @OETestDepends(['rpm.RpmBasicTest.test_rpm_help'])
+ def test_rpm_query(self):
+ status, output = self.target.run('ls /var/lib/rpm/')
+ if status != 0:
+ self.skipTest('No /var/lib/rpm on target')
+ status, output = self.target.run('rpm -q rpm')
+ msg = 'status and output: %s and %s' % (status, output)
+ self.assertEqual(status, 0, msg=msg)
+
+ @OETestDepends(['rpm.RpmBasicTest.test_rpm_query'])
+ def test_rpm_query_nonroot(self):
+
+ def set_up_test_user(u):
+ status, output = self.target.run('id -u %s' % u)
+ if status:
+ status, output = self.target.run('useradd %s' % u)
+ msg = 'Failed to create new user: %s' % output
+ self.assertTrue(status == 0, msg=msg)
+
+ def exec_as_test_user(u):
+ status, output = self.target.run('su -c id %s' % u)
+ msg = 'Failed to execute as new user'
+ self.assertTrue("({0})".format(u) in output, msg=msg)
+
+ status, output = self.target.run('su -c "rpm -qa" %s ' % u)
+ msg = 'status: %s. Cannot run rpm -qa: %s' % (status, output)
+ self.assertEqual(status, 0, msg=msg)
+
+ def wait_for_no_process_for_user(u, timeout = 120):
+ timeout_at = time.time() + timeout
+ while time.time() < timeout_at:
+ _, output = self.target.run(self.tc.target_cmds['ps'])
+ if u + ' ' not in output:
+ return
+ time.sleep(1)
+ user_pss = [ps for ps in output.split("\n") if u + ' ' in ps]
+ msg = "There're %s 's process(es) still running: %s".format(u, "\n".join(user_pss))
+ assertTrue(True, msg=msg)
+
+ def unset_up_test_user(u):
+ # ensure no test1 process in running
+ wait_for_no_process_for_user(u)
+ status, output = self.target.run('userdel -r %s' % u)
+ msg = 'Failed to erase user: %s' % output
+ self.assertTrue(status == 0, msg=msg)
+
+ tuser = 'test1'
+
+ try:
+ set_up_test_user(tuser)
+ exec_as_test_user(tuser)
+ finally:
+ unset_up_test_user(tuser)
+
+
+class RpmInstallRemoveTest(OERuntimeTestCase):
+
+ @classmethod
+ def setUpClass(cls):
+ pkgarch = cls.td['TUNE_PKGARCH'].replace('-', '_')
+ rpmdir = os.path.join(cls.tc.td['DEPLOY_DIR'], 'rpm', pkgarch)
+ # Pick base-passwd-doc as a test file to get installed, because it's small
+ # and it will always be built for standard targets
+ rpm_doc = 'base-passwd-doc-*.%s.rpm' % pkgarch
+ if not os.path.exists(rpmdir):
+ return
+ for f in fnmatch.filter(os.listdir(rpmdir), rpm_doc):
+ cls.test_file = os.path.join(rpmdir, f)
+ cls.dst = '/tmp/base-passwd-doc.rpm'
+
+ @OETestDepends(['rpm.RpmBasicTest.test_rpm_query'])
+ def test_rpm_install(self):
+ self.tc.target.copyTo(self.test_file, self.dst)
+ status, output = self.target.run('rpm -ivh /tmp/base-passwd-doc.rpm')
+ msg = 'Failed to install base-passwd-doc package: %s' % output
+ self.assertEqual(status, 0, msg=msg)
+ self.tc.target.run('rm -f %s' % self.dst)
+
+ @OETestDepends(['rpm.RpmInstallRemoveTest.test_rpm_install'])
+ def test_rpm_remove(self):
+ status,output = self.target.run('rpm -e base-passwd-doc')
+ msg = 'Failed to remove base-passwd-doc package: %s' % output
+ self.assertEqual(status, 0, msg=msg)
+
+ @OETestDepends(['rpm.RpmInstallRemoveTest.test_rpm_remove'])
+ def test_check_rpm_install_removal_log_file_size(self):
+ """
+ Summary: Check that rpm writes into /var/log/messages
+ Expected: There should be some RPM prefixed entries in the above file.
+ Product: BSPs
+ Author: Alexandru Georgescu <alexandru.c.georgescu@intel.com>
+ Author: Alexander Kanavin <alex.kanavin@gmail.com>
+ AutomatedBy: Daniel Istrate <daniel.alexandrux.istrate@intel.com>
+ """
+ db_files_cmd = 'ls /var/lib/rpm/rpmdb.sqlite*'
+ check_log_cmd = "grep RPM /var/log/messages | wc -l"
+
+ # Make sure that some database files are under /var/lib/rpm as 'rpmdb.sqlite'
+ status, output = self.target.run(db_files_cmd)
+ msg = 'Failed to find database files under /var/lib/rpm/ as rpmdb.sqlite'
+ self.assertEqual(0, status, msg=msg)
+
+ self.tc.target.copyTo(self.test_file, self.dst)
+
+ # Remove the package just in case
+ self.target.run('rpm -e base-passwd-doc')
+
+ # Install/Remove a package 10 times
+ for i in range(10):
+ status, output = self.target.run('rpm -ivh /tmp/base-passwd-doc.rpm')
+ msg = 'Failed to install base-passwd-doc package. Reason: {}'.format(output)
+ self.assertEqual(0, status, msg=msg)
+
+ status, output = self.target.run('rpm -e base-passwd-doc')
+ msg = 'Failed to remove base-passwd-doc package. Reason: {}'.format(output)
+ self.assertEqual(0, status, msg=msg)
+
+ self.tc.target.run('rm -f %s' % self.dst)
+
+
diff --git a/meta/lib/oeqa/runtime/cases/rt.py b/meta/lib/oeqa/runtime/cases/rt.py
new file mode 100644
index 0000000000..15ab4dbbbb
--- /dev/null
+++ b/meta/lib/oeqa/runtime/cases/rt.py
@@ -0,0 +1,19 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
+from oeqa.runtime.case import OERuntimeTestCase
+from oeqa.core.decorator.depends import OETestDepends
+
+class RtTest(OERuntimeTestCase):
+ @OETestDepends(['ssh.SSHTest.test_ssh'])
+ def test_is_rt(self):
+ """
+ Check that the kernel has CONFIG_PREEMPT_RT enabled.
+ """
+ status, output = self.target.run("uname -a")
+ self.assertEqual(status, 0, msg=output)
+ # Split so we don't get a substring false-positive
+ self.assertIn("PREEMPT_RT", output.split())
diff --git a/meta/lib/oeqa/runtime/cases/rtc.py b/meta/lib/oeqa/runtime/cases/rtc.py
new file mode 100644
index 0000000000..b2159b1134
--- /dev/null
+++ b/meta/lib/oeqa/runtime/cases/rtc.py
@@ -0,0 +1,43 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+from oeqa.runtime.case import OERuntimeTestCase
+from oeqa.core.decorator.depends import OETestDepends
+from oeqa.runtime.decorator.package import OEHasPackage
+
+import re
+
+class RTCTest(OERuntimeTestCase):
+
+ def setUp(self):
+ if self.tc.td.get('VIRTUAL-RUNTIME_init_manager') == 'systemd':
+ self.logger.debug('Stopping systemd-timesyncd daemon')
+ self.target.run('systemctl disable --now --runtime systemd-timesyncd')
+
+ def tearDown(self):
+ if self.tc.td.get('VIRTUAL-RUNTIME_init_manager') == 'systemd':
+ self.logger.debug('Starting systemd-timesyncd daemon')
+ self.target.run('systemctl enable --now --runtime systemd-timesyncd')
+
+ @OETestDepends(['ssh.SSHTest.test_ssh'])
+ @OEHasPackage(['coreutils', 'busybox'])
+ def test_rtc(self):
+ (status, output) = self.target.run('hwclock -r')
+ self.assertEqual(status, 0, msg='Failed to get RTC time, output: %s' % output)
+
+ (status, current_datetime) = self.target.run('date +"%m%d%H%M%Y"')
+ self.assertEqual(status, 0, msg='Failed to get system current date & time, output: %s' % current_datetime)
+
+ example_datetime = '062309452008'
+ (status, output) = self.target.run('date %s ; hwclock -w ; hwclock -r' % example_datetime)
+ check_hwclock = re.search('2008-06-23 09:45:..', output)
+ self.assertTrue(check_hwclock, msg='The RTC time was not set correctly, output: %s' % output)
+
+ (status, output) = self.target.run('date %s' % current_datetime)
+ self.assertEqual(status, 0, msg='Failed to reset system date & time, output: %s' % output)
+
+ (status, output) = self.target.run('hwclock -w')
+ self.assertEqual(status, 0, msg='Failed to reset RTC time, output: %s' % output)
+
diff --git a/meta/lib/oeqa/runtime/cases/runlevel.py b/meta/lib/oeqa/runtime/cases/runlevel.py
new file mode 100644
index 0000000000..6734b0f5ed
--- /dev/null
+++ b/meta/lib/oeqa/runtime/cases/runlevel.py
@@ -0,0 +1,27 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+from oeqa.runtime.case import OERuntimeTestCase
+from oeqa.core.decorator.depends import OETestDepends
+
+import time
+
+class RunLevel_Test(OERuntimeTestCase):
+
+ @OETestDepends(['ssh.SSHTest.test_ssh'])
+ def test_runlevel_3(self):
+ (status, output) = self.target.run("init 3 && sleep 5 && runlevel")
+ runlevel= '5 3'
+ self.assertEqual(output, runlevel, msg='Failed to set current runlevel to runlevel 3, current runlevel : %s' % output[-1])
+ (status, output) = self.target.run("uname -a")
+ self.assertEqual(status, 0, msg='Failed to run uname command, output: %s' % output)
+
+ @OETestDepends(['runlevel.RunLevel_Test.test_runlevel_3'])
+ def test_runlevel_5(self):
+ (status, output) = self.target.run("init 5 && sleep 5 && runlevel")
+ runlevel = '3 5'
+ self.assertEqual(output, runlevel, msg='Failed to set current runlevel to runlevel 5, current runlevel : %s' % output[-1])
+ (status, output) = self.target.run('export DISPLAY=:0 && x11perf -aa10text')
+ self.assertEqual(status, 0, msg='Failed to run 2D graphic test, output: %s' % output)
diff --git a/meta/lib/oeqa/runtime/cases/rust.py b/meta/lib/oeqa/runtime/cases/rust.py
new file mode 100644
index 0000000000..c9c60e16fd
--- /dev/null
+++ b/meta/lib/oeqa/runtime/cases/rust.py
@@ -0,0 +1,62 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
+from oeqa.runtime.case import OERuntimeTestCase
+from oeqa.core.decorator.depends import OETestDepends
+from oeqa.runtime.decorator.package import OEHasPackage
+
+class RustCompileTest(OERuntimeTestCase):
+
+ @classmethod
+ def setUp(cls):
+ dst = '/tmp/'
+ src = os.path.join(cls.tc.files_dir, 'test.rs')
+ cls.tc.target.copyTo(src, dst)
+
+ @classmethod
+ def tearDown(cls):
+ files = '/tmp/test.rs /tmp/test'
+ cls.tc.target.run('rm %s' % files)
+ dirs = '/tmp/hello'
+ cls.tc.target.run('rm -r %s' % dirs)
+
+ @OETestDepends(['ssh.SSHTest.test_ssh'])
+ @OEHasPackage(['rust'])
+ def test_rust_compile(self):
+ status, output = self.target.run('rustc /tmp/test.rs -o /tmp/test')
+ msg = 'rust compile failed, output: %s' % output
+ self.assertEqual(status, 0, msg=msg)
+
+ status, output = self.target.run('/tmp/test')
+ msg = 'running compiled file failed, output: %s' % output
+ self.assertEqual(status, 0, msg=msg)
+
+ @OETestDepends(['ssh.SSHTest.test_ssh'])
+ @OEHasPackage(['cargo'])
+ def test_cargo_compile(self):
+ status, output = self.target.run('cargo new /tmp/hello')
+ msg = 'cargo new failed, output: %s' % output
+ self.assertEqual(status, 0, msg=msg)
+
+ status, output = self.target.run('cargo build --manifest-path=/tmp/hello/Cargo.toml')
+ msg = 'cargo build failed, output: %s' % output
+ self.assertEqual(status, 0, msg=msg)
+
+ status, output = self.target.run('cargo run --manifest-path=/tmp/hello/Cargo.toml')
+ msg = 'running compiled file failed, output: %s' % output
+ self.assertEqual(status, 0, msg=msg)
+
+class RustHelloworldTest(OERuntimeTestCase):
+ @OETestDepends(['ssh.SSHTest.test_ssh'])
+ @OEHasPackage(['rust-hello-world'])
+ def test_rusthelloworld(self):
+ cmd = "rust-hello-world"
+ status, output = self.target.run(cmd)
+ msg = 'Exit status was not 0. Output: %s' % output
+ self.assertEqual(status, 0, msg=msg)
+
+ msg = 'Incorrect output: %s' % output
+ self.assertEqual(output, "Hello, world!", msg=msg)
diff --git a/meta/lib/oeqa/runtime/cases/scons.py b/meta/lib/oeqa/runtime/cases/scons.py
new file mode 100644
index 0000000000..4a8d4d40ba
--- /dev/null
+++ b/meta/lib/oeqa/runtime/cases/scons.py
@@ -0,0 +1,39 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
+import os
+
+from oeqa.runtime.case import OERuntimeTestCase
+from oeqa.core.decorator.depends import OETestDepends
+from oeqa.runtime.decorator.package import OEHasPackage
+
+class SconsCompileTest(OERuntimeTestCase):
+
+ @classmethod
+ def setUp(cls):
+ dst = '/tmp/'
+ src = os.path.join(cls.tc.runtime_files_dir, 'hello.c')
+ cls.tc.target.copyTo(src, dst)
+
+ src = os.path.join(cls.tc.runtime_files_dir, 'SConstruct')
+ cls.tc.target.copyTo(src, dst)
+
+ @classmethod
+ def tearDown(cls):
+ files = '/tmp/hello.c /tmp/hello.o /tmp/hello /tmp/SConstruct'
+ cls.tc.target.run('rm %s' % files)
+
+ @OETestDepends(['ssh.SSHTest.test_ssh'])
+ @OEHasPackage(['gcc'])
+ @OEHasPackage(['python3-scons'])
+ def test_scons_compile(self):
+ status, output = self.target.run('cd /tmp/ && scons')
+ msg = 'scons compile failed, output: %s' % output
+ self.assertEqual(status, 0, msg=msg)
+
+ status, output = self.target.run('/tmp/hello')
+ msg = 'running compiled file failed, output: %s' % output
+ self.assertEqual(status, 0, msg=msg)
diff --git a/meta/lib/oeqa/runtime/cases/scp.py b/meta/lib/oeqa/runtime/cases/scp.py
new file mode 100644
index 0000000000..ee97b8ef66
--- /dev/null
+++ b/meta/lib/oeqa/runtime/cases/scp.py
@@ -0,0 +1,39 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
+import os
+from tempfile import mkstemp
+
+from oeqa.runtime.case import OERuntimeTestCase
+from oeqa.core.decorator.depends import OETestDepends
+from oeqa.runtime.decorator.package import OEHasPackage
+
+class ScpTest(OERuntimeTestCase):
+
+ @classmethod
+ def setUpClass(cls):
+ cls.tmp_fd, cls.tmp_path = mkstemp()
+ with os.fdopen(cls.tmp_fd, 'w') as f:
+ f.seek(2 ** 22 -1)
+ f.write(os.linesep)
+
+ @classmethod
+ def tearDownClass(cls):
+ os.remove(cls.tmp_path)
+
+ @OETestDepends(['ssh.SSHTest.test_ssh'])
+ @OEHasPackage(['openssh-scp'])
+ def test_scp_file(self):
+ dst = '/tmp/test_scp_file'
+
+ (status, output) = self.target.copyTo(self.tmp_path, dst)
+ msg = 'File could not be copied. Output: %s' % output
+ self.assertEqual(status, 0, msg=msg)
+
+ (status, output) = self.target.run('ls -la %s' % dst)
+ self.assertEqual(status, 0, msg = 'SCP test failed')
+
+ self.target.run('rm %s' % dst)
diff --git a/meta/lib/oeqa/runtime/cases/skeletoninit.py b/meta/lib/oeqa/runtime/cases/skeletoninit.py
new file mode 100644
index 0000000000..75951beda9
--- /dev/null
+++ b/meta/lib/oeqa/runtime/cases/skeletoninit.py
@@ -0,0 +1,37 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
+# This test should cover https://bugzilla.yoctoproject.org/tr_show_case.cgi?case_id=284
+# testcase. Image under test must have meta-skeleton layer in bblayers and
+# IMAGE_INSTALL:append = " service" in local.conf
+from oeqa.runtime.case import OERuntimeTestCase
+from oeqa.core.decorator.depends import OETestDepends
+from oeqa.core.decorator.data import skipIfDataVar
+from oeqa.runtime.decorator.package import OEHasPackage
+
+class SkeletonBasicTest(OERuntimeTestCase):
+
+ @OETestDepends(['ssh.SSHTest.test_ssh'])
+ @OEHasPackage(['service'])
+ @skipIfDataVar('VIRTUAL-RUNTIME_init_manager', 'systemd',
+ 'Not appropiate for systemd image')
+ def test_skeleton_availability(self):
+ status, output = self.target.run('ls /etc/init.d/skeleton')
+ msg = 'skeleton init script not found. Output:\n%s' % output
+ self.assertEqual(status, 0, msg=msg)
+
+ status, output = self.target.run('ls /usr/sbin/skeleton-test')
+ msg = 'skeleton-test not found. Output:\n%s' % output
+ self.assertEqual(status, 0, msg=msg)
+
+ @OETestDepends(['skeletoninit.SkeletonBasicTest.test_skeleton_availability'])
+ def test_skeleton_script(self):
+ output1 = self.target.run("/etc/init.d/skeleton start")[1]
+ cmd = '%s | grep [s]keleton-test' % self.tc.target_cmds['ps']
+ status, output2 = self.target.run(cmd)
+ msg = ('Skeleton script could not be started:'
+ '\n%s\n%s' % (output1, output2))
+ self.assertEqual(status, 0, msg=msg)
diff --git a/meta/lib/oeqa/runtime/cases/ssh.py b/meta/lib/oeqa/runtime/cases/ssh.py
new file mode 100644
index 0000000000..13aac54396
--- /dev/null
+++ b/meta/lib/oeqa/runtime/cases/ssh.py
@@ -0,0 +1,21 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
+from oeqa.runtime.case import OERuntimeTestCase
+from oeqa.core.decorator.depends import OETestDepends
+from oeqa.runtime.decorator.package import OEHasPackage
+
+class SSHTest(OERuntimeTestCase):
+
+ @OETestDepends(['ping.PingTest.test_ping'])
+ @OEHasPackage(['dropbear', 'openssh-sshd'])
+ def test_ssh(self):
+ (status, output) = self.target.run('uname -a')
+ self.assertEqual(status, 0, msg='SSH Test failed: %s' % output)
+ (status, output) = self.target.run('cat /etc/controllerimage')
+ msg = "This isn't the right image - /etc/controllerimage " \
+ "shouldn't be here %s" % output
+ self.assertEqual(status, 1, msg=msg)
diff --git a/meta/lib/oeqa/runtime/cases/stap.py b/meta/lib/oeqa/runtime/cases/stap.py
new file mode 100644
index 0000000000..3be4162108
--- /dev/null
+++ b/meta/lib/oeqa/runtime/cases/stap.py
@@ -0,0 +1,34 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
+import os
+
+from oeqa.runtime.case import OERuntimeTestCase
+from oeqa.core.decorator.data import skipIfNotFeature
+from oeqa.runtime.decorator.package import OEHasPackage
+
+class StapTest(OERuntimeTestCase):
+ @skipIfNotFeature('tools-profile', 'Test requires tools-profile to be in IMAGE_FEATURES')
+ @OEHasPackage(['systemtap'])
+ @OEHasPackage(['gcc-symlinks'])
+ @OEHasPackage(['kernel-devsrc'])
+ def test_stap(self):
+ try:
+ cmd = 'make -j -C /usr/src/kernel scripts prepare'
+ status, output = self.target.run(cmd, 900)
+ self.assertEqual(status, 0, msg='\n'.join([cmd, output]))
+
+ cmd = 'stap -v -p4 -m stap-hello --disable-cache -DSTP_NO_VERREL_CHECK -e \'probe oneshot { print("Hello, "); println("SystemTap!") }\''
+ status, output = self.target.run(cmd, 900)
+ self.assertEqual(status, 0, msg='\n'.join([cmd, output]))
+
+ cmd = 'staprun -v -R -b1 stap-hello.ko'
+ self.assertEqual(status, 0, msg='\n'.join([cmd, output]))
+ self.assertIn('Hello, SystemTap!', output, msg='\n'.join([cmd, output]))
+ except:
+ status, dmesg = self.target.run('dmesg')
+ if status == 0:
+ print(dmesg)
diff --git a/meta/lib/oeqa/runtime/cases/storage.py b/meta/lib/oeqa/runtime/cases/storage.py
new file mode 100644
index 0000000000..b05622fea8
--- /dev/null
+++ b/meta/lib/oeqa/runtime/cases/storage.py
@@ -0,0 +1,151 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
+import re
+import time
+
+from oeqa.runtime.case import OERuntimeTestCase
+from oeqa.core.decorator.depends import OETestDepends
+from oeqa.core.decorator.data import skipIfQemu
+
+class StorageBase(OERuntimeTestCase):
+ def storage_mount(cls, tmo=1):
+
+ (status, output) = cls.target.run('mkdir -p %s' % cls.mount_point)
+ (status, output) = cls.target.run('mount %s %s' % (cls.device, cls.mount_point))
+ msg = ('Mount failed: %s.' % status)
+ cls.assertFalse(output, msg = msg)
+ time.sleep(tmo)
+ (status, output) = cls.target.run('cat /proc/mounts')
+ match = re.search('%s' % cls.device, output)
+ if match:
+ msg = ('Device %s not mounted.' % cls.device)
+ cls.assertTrue(match, msg = msg)
+
+ (status, output) = cls.target.run('mkdir -p %s' % cls.test_dir)
+
+ (status, output) = cls.target.run('rm -f %s/*' % cls.test_dir)
+ msg = ('Failed to cleanup files @ %s/*' % cls.test_dir)
+ cls.assertFalse(output, msg = msg)
+
+
+ def storage_basic(cls):
+ # create file on device
+ (status, output) = cls.target.run('touch %s/%s' % (cls.test_dir, cls.test_file))
+ msg = ('File %s not created on %s' % (cls.test_file, cls.device))
+ cls.assertFalse(status, msg = msg)
+ # move file
+ (status, output) = cls.target.run('mv %s/%s %s/%s1' %
+ (cls.test_dir, cls.test_file, cls.test_dir, cls.test_file))
+ msg = ('File %s not moved to %s' % (cls.test_file, cls.device))
+ cls.assertFalse(status, msg = msg)
+ # remove file
+ (status, output) = cls.target.run('rm %s/%s1' % (cls.test_dir, cls.test_file))
+ msg = ('File %s not removed on %s' % (cls.test_file, cls.device))
+ cls.assertFalse(status, msg = msg)
+
+ def storage_read(cls):
+ # check if message is in file
+ (status, output) = cls.target.run('cat %s/%s' %
+ (cls.test_dir, cls.test_file))
+
+ match = re.search('%s' % cls.test_msg, output)
+ msg = ('Test message %s not in file %s.' % (cls.test_msg, cls.test_file))
+ cls.assertEqual(status, 0, msg = msg)
+
+ def storage_write(cls):
+ # create test message in file on device
+ (status, output) = cls.target.run('echo "%s" > %s/%s' %
+ (cls.test_msg, cls.test_dir, cls.test_file))
+ msg = ('File %s not create test message on %s' % (cls.test_file, cls.device))
+ cls.assertEqual(status, 0, msg = msg)
+
+ def storage_umount(cls, tmo=1):
+ time.sleep(tmo)
+ (status, output) = cls.target.run('umount %s' % cls.mount_point)
+
+ if status == 32:
+ # already unmounted, should it fail?
+ return
+ else:
+ msg = ('Device not unmount %s' % cls.mount_point)
+ cls.assertEqual(status, 0, msg = msg)
+
+ (status, output) = cls.target.run('cat /proc/mounts')
+ match = re.search('%s' % cls.device, output)
+ if match:
+ msg = ('Device %s still mounted.' % cls.device)
+ cls.assertTrue(match, msg = msg)
+
+
+class UsbTest(StorageBase):
+ '''
+ This is to mimic the usb test previously done in manual bsp-hw.json
+ '''
+ @classmethod
+ def setUpClass(self):
+ self.test_msg = "Hello World - USB"
+ self.mount_point = "/media/usb"
+ self.device = "/dev/sda1"
+ self.test_file = "usb.tst"
+ self.test_dir = os.path.join(self.mount_point, "oeqa")
+
+ @skipIfQemu()
+ @OETestDepends(['ssh.SSHTest.test_ssh'])
+ def test_usb_mount(self):
+ self.storage_umount(2)
+ self.storage_mount(5)
+
+ @skipIfQemu()
+ @OETestDepends(['storage.UsbTest.test_usb_mount'])
+ def test_usb_basic_operations(self):
+ self.storage_basic()
+
+ @skipIfQemu()
+ @OETestDepends(['storage.UsbTest.test_usb_basic_operations'])
+ def test_usb_basic_rw(self):
+ self.storage_write()
+ self.storage_read()
+
+ @skipIfQemu()
+ @OETestDepends(['storage.UsbTest.test_usb_mount'])
+ def test_usb_umount(self):
+ self.storage_umount(2)
+
+
+class MMCTest(StorageBase):
+ '''
+ This is to mimic the usb test previously done in manual bsp-hw.json
+ '''
+ @classmethod
+ def setUpClass(self):
+ self.test_msg = "Hello World - MMC"
+ self.mount_point = "/media/mmc"
+ self.device = "/dev/mmcblk1p1"
+ self.test_file = "mmc.tst"
+ self.test_dir = os.path.join(self.mount_point, "oeqa")
+
+ @skipIfQemu()
+ @OETestDepends(['ssh.SSHTest.test_ssh'])
+ def test_mmc_mount(self):
+ self.storage_umount(2)
+ self.storage_mount()
+
+ @skipIfQemu()
+ @OETestDepends(['storage.MMCTest.test_mmc_mount'])
+ def test_mmc_basic_operations(self):
+ self.storage_basic()
+
+ @skipIfQemu()
+ @OETestDepends(['storage.MMCTest.test_mmc_basic_operations'])
+ def test_mmc_basic_rw(self):
+ self.storage_write()
+ self.storage_read()
+
+ @skipIfQemu()
+ @OETestDepends(['storage.MMCTest.test_mmc_mount'])
+ def test_mmc_umount(self):
+ self.storage_umount(2)
diff --git a/meta/lib/oeqa/runtime/cases/suspend.py b/meta/lib/oeqa/runtime/cases/suspend.py
new file mode 100644
index 0000000000..a625cc5901
--- /dev/null
+++ b/meta/lib/oeqa/runtime/cases/suspend.py
@@ -0,0 +1,38 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+from oeqa.runtime.case import OERuntimeTestCase
+from oeqa.core.decorator.depends import OETestDepends
+from oeqa.core.decorator.data import skipIfQemu
+import threading
+import time
+
+class Suspend_Test(OERuntimeTestCase):
+
+ def test_date(self):
+ (status, output) = self.target.run('date')
+ self.assertEqual(status, 0, msg = 'Failed to run date command, output : %s' % output)
+
+ def test_ping(self):
+ t_thread = threading.Thread(target=self.target.run, args=("ping 8.8.8.8",))
+ t_thread.start()
+ time.sleep(2)
+
+ status, output = self.target.run('pidof ping')
+ self.target.run('kill -9 %s' % output)
+ self.assertEqual(status, 0, msg = 'Not able to find process that runs ping, output : %s' % output)
+
+ def set_suspend(self):
+ (status, output) = self.target.run('sudo rtcwake -m mem -s 10')
+ self.assertEqual(status, 0, msg = 'Failed to suspends your system to RAM, output : %s' % output)
+
+ @skipIfQemu()
+ @OETestDepends(['ssh.SSHTest.test_ssh'])
+ def test_suspend(self):
+ self.test_date()
+ self.test_ping()
+ self.set_suspend()
+ self.test_date()
+ self.test_ping()
diff --git a/meta/lib/oeqa/runtime/cases/systemd.py b/meta/lib/oeqa/runtime/cases/systemd.py
new file mode 100644
index 0000000000..720b4b517a
--- /dev/null
+++ b/meta/lib/oeqa/runtime/cases/systemd.py
@@ -0,0 +1,196 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
+import re
+import time
+
+from oeqa.runtime.case import OERuntimeTestCase
+from oeqa.core.decorator.depends import OETestDepends
+from oeqa.core.decorator.data import skipIfDataVar, skipIfNotDataVar
+from oeqa.runtime.decorator.package import OEHasPackage
+from oeqa.core.decorator.data import skipIfNotFeature, skipIfFeature
+
+class SystemdTest(OERuntimeTestCase):
+
+ def systemctl(self, action='', target='', expected=0, verbose=False):
+ command = 'SYSTEMD_BUS_TIMEOUT=240s systemctl %s %s' % (action, target)
+ status, output = self.target.run(command)
+ message = '\n'.join([command, output])
+ if status != expected and verbose:
+ cmd = 'SYSTEMD_BUS_TIMEOUT=240s systemctl status --full %s' % target
+ message += self.target.run(cmd)[1]
+ self.assertEqual(status, expected, message)
+ return output
+
+ #TODO: use pyjournalctl instead
+ def journalctl(self, args='',l_match_units=None):
+ """
+ Request for the journalctl output to the current target system
+
+ Arguments:
+ -args, an optional argument pass through argument
+ -l_match_units, an optional list of units to filter the output
+ Returns:
+ -string output of the journalctl command
+ Raises:
+ -AssertionError, on remote commands that fail
+ -ValueError, on a journalctl call with filtering by l_match_units that
+ returned no entries
+ """
+
+ query_units=''
+ if l_match_units:
+ query_units = ['_SYSTEMD_UNIT='+unit for unit in l_match_units]
+ query_units = ' '.join(query_units)
+ command = 'journalctl %s %s' %(args, query_units)
+ status, output = self.target.run(command)
+ if status:
+ raise AssertionError("Command '%s' returned non-zero exit "
+ 'code %d:\n%s' % (command, status, output))
+ if len(output) == 1 and "-- No entries --" in output:
+ raise ValueError('List of units to match: %s, returned no entries'
+ % l_match_units)
+ return output
+
+class SystemdBasicTests(SystemdTest):
+
+ def settle(self):
+ """
+ Block until systemd has finished activating any units being activated,
+ or until two minutes has elapsed.
+
+ Returns a tuple, either (True, '') if all units have finished
+ activating, or (False, message string) if there are still units
+ activating (generally, failing units that restart).
+ """
+ endtime = time.time() + (60 * 2)
+ while True:
+ status, output = self.target.run('SYSTEMD_BUS_TIMEOUT=240s systemctl --state=activating')
+ if "0 loaded units listed" in output:
+ return (True, '')
+ if time.time() >= endtime:
+ return (False, output)
+ time.sleep(10)
+
+ @skipIfNotFeature('systemd',
+ 'Test requires systemd to be in DISTRO_FEATURES')
+ @skipIfNotDataVar('VIRTUAL-RUNTIME_init_manager', 'systemd',
+ 'systemd is not the init manager for this image')
+ @OETestDepends(['ssh.SSHTest.test_ssh'])
+ def test_systemd_basic(self):
+ self.systemctl('--version')
+
+ @OETestDepends(['systemd.SystemdBasicTests.test_systemd_basic'])
+ def test_systemd_list(self):
+ self.systemctl('list-unit-files')
+
+ @OETestDepends(['systemd.SystemdBasicTests.test_systemd_basic'])
+ def test_systemd_failed(self):
+ settled, output = self.settle()
+ msg = "Timed out waiting for systemd to settle:\n%s" % output
+ self.assertTrue(settled, msg=msg)
+
+ output = self.systemctl('list-units', '--failed')
+ match = re.search('0 loaded units listed', output)
+ if not match:
+ output += self.systemctl('status --full --failed')
+ self.assertTrue(match, msg='Some systemd units failed:\n%s' % output)
+
+
+class SystemdServiceTests(SystemdTest):
+
+ @OEHasPackage(['avahi-daemon'])
+ @OETestDepends(['systemd.SystemdBasicTests.test_systemd_basic'])
+ def test_systemd_status(self):
+ self.systemctl('status --full', 'avahi-daemon.service')
+
+ @OETestDepends(['systemd.SystemdServiceTests.test_systemd_status'])
+ def test_systemd_stop_start(self):
+ self.systemctl('stop', 'avahi-daemon.service')
+ self.systemctl('is-active', 'avahi-daemon.service',
+ expected=3, verbose=True)
+ self.systemctl('start','avahi-daemon.service')
+ self.systemctl('is-active', 'avahi-daemon.service', verbose=True)
+
+ @OETestDepends(['systemd.SystemdServiceTests.test_systemd_status'])
+ @skipIfFeature('read-only-rootfs',
+ 'Test is only meant to run without read-only-rootfs in IMAGE_FEATURES')
+ def test_systemd_disable_enable(self):
+ self.systemctl('disable', 'avahi-daemon.service')
+ self.systemctl('is-enabled', 'avahi-daemon.service', expected=1)
+ self.systemctl('enable', 'avahi-daemon.service')
+ self.systemctl('is-enabled', 'avahi-daemon.service')
+
+ @OETestDepends(['systemd.SystemdServiceTests.test_systemd_status'])
+ @skipIfNotFeature('read-only-rootfs',
+ 'Test is only meant to run with read-only-rootfs in IMAGE_FEATURES')
+ def test_systemd_disable_enable_ro(self):
+ status = self.target.run('mount -orw,remount /')[0]
+ self.assertTrue(status == 0, msg='Remounting / as r/w failed')
+ try:
+ self.test_systemd_disable_enable()
+ finally:
+ status = self.target.run('mount -oro,remount /')[0]
+ self.assertTrue(status == 0, msg='Remounting / as r/o failed')
+
+class SystemdJournalTests(SystemdTest):
+
+ @OETestDepends(['systemd.SystemdBasicTests.test_systemd_basic'])
+ def test_systemd_journal(self):
+ status, output = self.target.run('journalctl')
+ self.assertEqual(status, 0, output)
+
+ @OETestDepends(['systemd.SystemdBasicTests.test_systemd_basic'])
+ def test_systemd_boot_time(self, systemd_TimeoutStartSec=90):
+ """
+ Get the target boot time from journalctl and log it
+
+ Arguments:
+ -systemd_TimeoutStartSec, an optional argument containing systemd's
+ unit start timeout to compare against
+ """
+
+ # The expression chain that uniquely identifies the time boot message.
+ expr_items=['Startup finished', 'kernel', 'userspace','\.$']
+ try:
+ output = self.journalctl(args='-o cat --reverse')
+ except AssertionError:
+ self.fail('Error occurred while calling journalctl')
+ if not len(output):
+ self.fail('Error, unable to get startup time from systemd journal')
+
+ # Check for the regular expression items that match the startup time.
+ for line in output.split('\n'):
+ check_match = ''.join(re.findall('.*'.join(expr_items), line))
+ if check_match:
+ break
+ # Put the startup time in the test log
+ if check_match:
+ self.tc.logger.info('%s' % check_match)
+ else:
+ self.skipTest('Error at obtaining the boot time from journalctl')
+ boot_time_sec = 0
+
+ # Get the numeric values from the string and convert them to seconds
+ # same data will be placed in list and string for manipulation.
+ l_boot_time = check_match.split(' ')[-2:]
+ s_boot_time = ' '.join(l_boot_time)
+ try:
+ # Obtain the minutes it took to boot.
+ if l_boot_time[0].endswith('min') and l_boot_time[0][0].isdigit():
+ boot_time_min = s_boot_time.split('min')[0]
+ # Convert to seconds and accumulate it.
+ boot_time_sec += int(boot_time_min) * 60
+ # Obtain the seconds it took to boot and accumulate.
+ boot_time_sec += float(l_boot_time[1].split('s')[0])
+ except ValueError:
+ self.skipTest('Error when parsing time from boot string')
+
+ # Assert the target boot time against systemd's unit start timeout.
+ if boot_time_sec > systemd_TimeoutStartSec:
+ msg = ("Target boot time %s exceeds systemd's TimeoutStartSec %s"
+ % (boot_time_sec, systemd_TimeoutStartSec))
+ self.tc.logger.info(msg)
diff --git a/meta/lib/oeqa/runtime/cases/terminal.py b/meta/lib/oeqa/runtime/cases/terminal.py
new file mode 100644
index 0000000000..96ba3c3195
--- /dev/null
+++ b/meta/lib/oeqa/runtime/cases/terminal.py
@@ -0,0 +1,26 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+from oeqa.runtime.case import OERuntimeTestCase
+from oeqa.core.decorator.depends import OETestDepends
+from oeqa.runtime.decorator.package import OEHasPackage
+
+import threading
+import time
+
+class TerminalTest(OERuntimeTestCase):
+
+ @OEHasPackage(['matchbox-terminal'])
+ @OETestDepends(['ssh.SSHTest.test_ssh'])
+ def test_terminal_running(self):
+ t_thread = threading.Thread(target=self.target.run, args=("export DISPLAY=:0 && matchbox-terminal -e 'sh -c \"uname -a && exec sh\"'",))
+ t_thread.start()
+ time.sleep(2)
+
+ status, output = self.target.run('pidof matchbox-terminal')
+ number_of_terminal = len(output.split())
+ self.assertEqual(number_of_terminal, 1, msg='There should be only one terminal being launched. Number of terminal launched : %s' % number_of_terminal)
+ self.target.run('kill -9 %s' % output)
+ self.assertEqual(status, 0, msg='Not able to find process that runs terminal.')
diff --git a/meta/lib/oeqa/runtime/cases/usb_hid.py b/meta/lib/oeqa/runtime/cases/usb_hid.py
new file mode 100644
index 0000000000..6f23d2ff51
--- /dev/null
+++ b/meta/lib/oeqa/runtime/cases/usb_hid.py
@@ -0,0 +1,27 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+from oeqa.runtime.case import OERuntimeTestCase
+from oeqa.core.decorator.depends import OETestDepends
+from oeqa.core.decorator.data import skipIfQemu
+from oeqa.runtime.decorator.package import OEHasPackage
+
+class USB_HID_Test(OERuntimeTestCase):
+
+ def keyboard_mouse_simulation(self):
+ (status, output) = self.target.run('export DISPLAY=:0 && xdotool key F2 && xdotool mousemove 100 100')
+ return self.assertEqual(status, 0, msg = 'Failed to simulate keyboard/mouse input event, output : %s' % output)
+
+ def set_suspend(self):
+ (status, output) = self.target.run('sudo rtcwake -m mem -s 10')
+ return self.assertEqual(status, 0, msg = 'Failed to suspends your system to RAM, output : %s' % output)
+
+ @OEHasPackage(['xdotool'])
+ @skipIfQemu()
+ @OETestDepends(['ssh.SSHTest.test_ssh'])
+ def test_USB_Hid_input(self):
+ self.keyboard_mouse_simulation()
+ self.set_suspend()
+ self.keyboard_mouse_simulation()
diff --git a/meta/lib/oeqa/runtime/cases/weston.py b/meta/lib/oeqa/runtime/cases/weston.py
new file mode 100644
index 0000000000..ee4d336482
--- /dev/null
+++ b/meta/lib/oeqa/runtime/cases/weston.py
@@ -0,0 +1,89 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
+from oeqa.runtime.case import OERuntimeTestCase
+from oeqa.core.decorator.depends import OETestDepends
+from oeqa.core.decorator.data import skipIfNotFeature
+from oeqa.runtime.decorator.package import OEHasPackage
+import threading
+import time
+
+class WestonTest(OERuntimeTestCase):
+ weston_log_file = '/tmp/weston-2.log'
+
+ @classmethod
+ def tearDownClass(cls):
+ cls.tc.target.run('rm %s' % cls.weston_log_file)
+
+ @OETestDepends(['ssh.SSHTest.test_ssh'])
+ @OEHasPackage(['weston'])
+ def test_weston_running(self):
+ cmd ='%s | grep [w]eston-desktop-shell' % self.tc.target_cmds['ps']
+ status, output = self.target.run(cmd)
+ msg = ('Weston does not appear to be running %s' %
+ self.target.run(self.tc.target_cmds['ps'])[1])
+ self.assertEqual(status, 0, msg=msg)
+
+ def get_processes_of(self, target, error_msg):
+ status, output = self.target.run('pidof %s' % target)
+ self.assertEqual(status, 0, msg='Retrieve %s (%s) processes error: %s' % (target, error_msg, output))
+ return output.split(" ")
+
+ def get_weston_command(self, cmd):
+ return 'export XDG_RUNTIME_DIR=/run/user/`id -u weston`; export WAYLAND_DISPLAY=wayland-1; %s' % cmd
+
+ def run_weston_init(self):
+ if 'systemd' in self.tc.td['VIRTUAL-RUNTIME_init_manager']:
+ self.target.run('systemd-run --collect --unit=weston-ptest.service --uid=0 -p PAMName=login -p TTYPath=/dev/tty6 -E XDG_RUNTIME_DIR=/tmp -E WAYLAND_DISPLAY=wayland-0 /usr/bin/weston --socket=wayland-1 --log=%s' % self.weston_log_file)
+ else:
+ self.target.run(self.get_weston_command('openvt -- weston --socket=wayland-2 --log=%s' % self.weston_log_file))
+
+ def get_new_wayland_processes(self, existing_wl_processes):
+ try_cnt = 0
+ while try_cnt < 5:
+ time.sleep(5 + 5*try_cnt)
+ try_cnt += 1
+ wl_processes = self.get_processes_of('weston-desktop-shell', 'existing and new')
+ new_wl_processes = [x for x in wl_processes if x not in existing_wl_processes]
+ if new_wl_processes:
+ return new_wl_processes, try_cnt
+
+ return new_wl_processes, try_cnt
+
+ @OEHasPackage(['wayland-utils'])
+ def test_wayland_info(self):
+ if 'systemd' in self.tc.td['VIRTUAL-RUNTIME_init_manager']:
+ command = 'XDG_RUNTIME_DIR=/run wayland-info'
+ else:
+ command = self.get_weston_command('wayland-info')
+ status, output = self.target.run(command)
+ self.assertEqual(status, 0, msg='wayland-info error: %s' % output)
+
+ @OEHasPackage(['weston'])
+ def test_weston_can_initialize_new_wayland_compositor(self):
+ existing_wl_processes = self.get_processes_of('weston-desktop-shell', 'existing')
+ existing_weston_processes = self.get_processes_of('weston', 'existing')
+
+ weston_thread = threading.Thread(target=self.run_weston_init)
+ weston_thread.start()
+ new_wl_processes, try_cnt = self.get_new_wayland_processes(existing_wl_processes)
+ existing_and_new_weston_processes = self.get_processes_of('weston', 'existing and new')
+ new_weston_processes = [x for x in existing_and_new_weston_processes if x not in existing_weston_processes]
+ if 'systemd' in self.tc.td['VIRTUAL-RUNTIME_init_manager']:
+ self.target.run('systemctl stop weston-ptest.service')
+ else:
+ for w in new_weston_processes:
+ self.target.run('kill -9 %s' % w)
+ __, weston_log = self.target.run('cat %s' % self.weston_log_file)
+ self.assertTrue(new_wl_processes, msg='Could not get new weston-desktop-shell processes (%s, try_cnt:%s) weston log: %s' % (new_wl_processes, try_cnt, weston_log))
+
+ @skipIfNotFeature('x11', 'Test requires x11 to be in DISTRO_FEATURES')
+ @OEHasPackage(['weston'])
+ def test_weston_supports_xwayland(self):
+ cmd ='cat %s | grep "xserver listening on display"' % self.weston_log_file
+ status, output = self.target.run(cmd)
+ msg = ('xwayland does not appear to be running')
+ self.assertEqual(status, 0, msg=msg)
diff --git a/meta/lib/oeqa/runtime/cases/x32lib.py b/meta/lib/oeqa/runtime/cases/x32lib.py
new file mode 100644
index 0000000000..014da4b386
--- /dev/null
+++ b/meta/lib/oeqa/runtime/cases/x32lib.py
@@ -0,0 +1,28 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
+from oeqa.runtime.case import OERuntimeTestCase
+from oeqa.core.decorator.depends import OETestDepends
+from oeqa.core.decorator.data import skipIfNotInDataVar
+
+import subprocess
+
+class X32libTest(OERuntimeTestCase):
+
+ @skipIfNotInDataVar('DEFAULTTUNE', 'x86-64-x32',
+ 'DEFAULTTUNE is not set to x86-64-x32')
+ @OETestDepends(['ssh.SSHTest.test_ssh'])
+ def test_x32_file(self):
+ dest = self.td.get('T', '') + "/ls.x32test"
+ self.target.copyFrom("/bin/ls", dest)
+ cmd = 'readelf -h {} | grep Class | grep ELF32'.format(dest)
+ status1 = subprocess.call(cmd, shell=True)
+ cmd = 'readelf -h {} | grep Machine | grep X86-64'.format(dest)
+ status2 = subprocess.call(cmd, shell=True)
+ msg = ("/bin/ls isn't an X86-64 ELF32 binary. readelf says:\n{}".format(
+ subprocess.check_output("readelf -h {}".format(dest), shell=True).decode()))
+ os.remove(dest)
+ self.assertTrue(status1 == 0 and status2 == 0, msg=msg)
diff --git a/meta/lib/oeqa/runtime/cases/xorg.py b/meta/lib/oeqa/runtime/cases/xorg.py
new file mode 100644
index 0000000000..09afb1e3d1
--- /dev/null
+++ b/meta/lib/oeqa/runtime/cases/xorg.py
@@ -0,0 +1,23 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
+from oeqa.runtime.case import OERuntimeTestCase
+from oeqa.core.decorator.depends import OETestDepends
+from oeqa.core.decorator.data import skipIfNotFeature
+from oeqa.runtime.decorator.package import OEHasPackage
+
+class XorgTest(OERuntimeTestCase):
+
+ @skipIfNotFeature('x11-base',
+ 'Test requires x11 to be in IMAGE_FEATURES')
+ @OETestDepends(['ssh.SSHTest.test_ssh'])
+ @OEHasPackage(['xserver-nodm-init'])
+ def test_xorg_running(self):
+ cmd ='%s | grep -v xinit | grep [X]org' % self.tc.target_cmds['ps']
+ status, output = self.target.run(cmd)
+ msg = ('Xorg does not appear to be running %s' %
+ self.target.run(self.tc.target_cmds['ps'])[1])
+ self.assertEqual(status, 0, msg=msg)
diff --git a/meta/lib/oeqa/runtime/connman.py b/meta/lib/oeqa/runtime/connman.py
deleted file mode 100644
index 003fefe2ce..0000000000
--- a/meta/lib/oeqa/runtime/connman.py
+++ /dev/null
@@ -1,31 +0,0 @@
-import unittest
-from oeqa.oetest import oeRuntimeTest, skipModule
-from oeqa.utils.decorators import *
-
-def setUpModule():
- if not oeRuntimeTest.hasPackage("connman"):
- skipModule("No connman package in image")
-
-
-class ConnmanTest(oeRuntimeTest):
-
- def service_status(self, service):
- if oeRuntimeTest.hasFeature("systemd"):
- (status, output) = self.target.run('systemctl status -l %s' % service)
- return output
- else:
- return "Unable to get status or logs for %s" % service
-
- @testcase(961)
- @skipUnlessPassed('test_ssh')
- def test_connmand_help(self):
- (status, output) = self.target.run('/usr/sbin/connmand --help')
- self.assertEqual(status, 0, msg="status and output: %s and %s" % (status,output))
-
- @testcase(221)
- @skipUnlessPassed('test_connmand_help')
- def test_connmand_running(self):
- (status, output) = self.target.run(oeRuntimeTest.pscmd + ' | grep [c]onnmand')
- if status != 0:
- print(self.service_status("connman"))
- self.fail("No connmand process running")
diff --git a/meta/lib/oeqa/runtime/context.py b/meta/lib/oeqa/runtime/context.py
new file mode 100644
index 0000000000..0c5d1869ab
--- /dev/null
+++ b/meta/lib/oeqa/runtime/context.py
@@ -0,0 +1,226 @@
+#
+# Copyright (C) 2016 Intel Corporation
+#
+# SPDX-License-Identifier: MIT
+#
+
+import os
+import sys
+
+from oeqa.core.context import OETestContext, OETestContextExecutor
+from oeqa.core.target.ssh import OESSHTarget
+from oeqa.core.target.qemu import OEQemuTarget
+from oeqa.utils.dump import HostDumper
+
+from oeqa.runtime.loader import OERuntimeTestLoader
+
+class OERuntimeTestContext(OETestContext):
+ loaderClass = OERuntimeTestLoader
+ runtime_files_dir = os.path.join(
+ os.path.dirname(os.path.abspath(__file__)), "files")
+
+ def __init__(self, td, logger, target,
+ host_dumper, image_packages, extract_dir):
+ super(OERuntimeTestContext, self).__init__(td, logger)
+
+ self.target = target
+ self.image_packages = image_packages
+ self.host_dumper = host_dumper
+ self.extract_dir = extract_dir
+ self._set_target_cmds()
+
+ def _set_target_cmds(self):
+ self.target_cmds = {}
+
+ self.target_cmds['ps'] = 'ps'
+ if 'procps' in self.image_packages:
+ self.target_cmds['ps'] = self.target_cmds['ps'] + ' -ef'
+
+class OERuntimeTestContextExecutor(OETestContextExecutor):
+ _context_class = OERuntimeTestContext
+
+ name = 'runtime'
+ help = 'runtime test component'
+ description = 'executes runtime tests over targets'
+
+ default_cases = os.path.join(os.path.abspath(os.path.dirname(__file__)),
+ 'cases')
+ default_data = None
+ default_test_data = 'data/testdata.json'
+ default_tests = ''
+ default_json_result_dir = '%s-results' % name
+
+ default_target_type = 'simpleremote'
+ default_manifest = 'data/manifest'
+ default_server_ip = '192.168.7.1'
+ default_target_ip = '192.168.7.2'
+ default_extract_dir = 'packages/extracted'
+
+ def register_commands(self, logger, subparsers):
+ super(OERuntimeTestContextExecutor, self).register_commands(logger, subparsers)
+
+ runtime_group = self.parser.add_argument_group('runtime options')
+
+ runtime_group.add_argument('--target-type', action='store',
+ default=self.default_target_type, choices=['simpleremote', 'qemu'],
+ help="Target type of device under test, default: %s" \
+ % self.default_target_type)
+ runtime_group.add_argument('--target-ip', action='store',
+ default=self.default_target_ip,
+ help="IP address and optionally ssh port (default 22) of device under test, for example '192.168.0.7:22'. Default: %s" \
+ % self.default_target_ip)
+ runtime_group.add_argument('--server-ip', action='store',
+ default=self.default_target_ip,
+ help="IP address of the test host from test target machine, default: %s" \
+ % self.default_server_ip)
+
+ runtime_group.add_argument('--host-dumper-dir', action='store',
+ help="Directory where host status is dumped, if tests fails")
+
+ runtime_group.add_argument('--packages-manifest', action='store',
+ default=self.default_manifest,
+ help="Package manifest of the image under test, default: %s" \
+ % self.default_manifest)
+
+ runtime_group.add_argument('--extract-dir', action='store',
+ default=self.default_extract_dir,
+ help='Directory where extracted packages reside, default: %s' \
+ % self.default_extract_dir)
+
+ runtime_group.add_argument('--qemu-boot', action='store',
+ help="Qemu boot configuration, only needed when target_type is QEMU.")
+
+ @staticmethod
+ def getTarget(target_type, logger, target_ip, server_ip, **kwargs):
+ target = None
+
+ if target_ip:
+ target_ip_port = target_ip.split(':')
+ if len(target_ip_port) == 2:
+ target_ip = target_ip_port[0]
+ kwargs['port'] = target_ip_port[1]
+
+ if server_ip:
+ server_ip_port = server_ip.split(':')
+ if len(server_ip_port) == 2:
+ server_ip = server_ip_port[0]
+ kwargs['server_port'] = int(server_ip_port[1])
+
+ if target_type == 'simpleremote':
+ target = OESSHTarget(logger, target_ip, server_ip, **kwargs)
+ elif target_type == 'qemu':
+ target = OEQemuTarget(logger, server_ip, **kwargs)
+ else:
+ # XXX: This code uses the old naming convention for controllers and
+ # targets, the idea it is to leave just targets as the controller
+ # most of the time was just a wrapper.
+ # XXX: This code tries to import modules from lib/oeqa/controllers
+ # directory and treat them as controllers, it will less error prone
+ # to use introspection to load such modules.
+ # XXX: Don't base your targets on this code it will be refactored
+ # in the near future.
+ # Custom target module loading
+ controller = OERuntimeTestContextExecutor.getControllerModule(target_type)
+ target = controller(logger, target_ip, server_ip, **kwargs)
+
+ return target
+
+ # Search oeqa.controllers module directory for and return a controller
+ # corresponding to the given target name.
+ # AttributeError raised if not found.
+ # ImportError raised if a provided module can not be imported.
+ @staticmethod
+ def getControllerModule(target):
+ controllerslist = OERuntimeTestContextExecutor._getControllerModulenames()
+ controller = OERuntimeTestContextExecutor._loadControllerFromName(target, controllerslist)
+ return controller
+
+ # Return a list of all python modules in lib/oeqa/controllers for each
+ # layer in bbpath
+ @staticmethod
+ def _getControllerModulenames():
+
+ controllerslist = []
+
+ def add_controller_list(path):
+ if not os.path.exists(os.path.join(path, '__init__.py')):
+ raise OSError('Controllers directory %s exists but is missing __init__.py' % path)
+ files = sorted([f for f in os.listdir(path) if f.endswith('.py') and not f.startswith('_') and not f.startswith('.#')])
+ for f in files:
+ module = 'oeqa.controllers.' + f[:-3]
+ if module not in controllerslist:
+ controllerslist.append(module)
+ else:
+ raise RuntimeError("Duplicate controller module found for %s. Layers should create unique controller module names" % module)
+
+ # sys.path can contain duplicate paths, but because of the login in
+ # add_controller_list this doesn't work and causes testimage to abort.
+ # Remove duplicates using an intermediate dictionary to ensure this
+ # doesn't happen.
+ for p in list(dict.fromkeys(sys.path)):
+ controllerpath = os.path.join(p, 'oeqa', 'controllers')
+ if os.path.exists(controllerpath):
+ add_controller_list(controllerpath)
+ return controllerslist
+
+ # Search for and return a controller from given target name and
+ # set of module names.
+ # Raise AttributeError if not found.
+ # Raise ImportError if a provided module can not be imported
+ @staticmethod
+ def _loadControllerFromName(target, modulenames):
+ for name in modulenames:
+ obj = OERuntimeTestContextExecutor._loadControllerFromModule(target, name)
+ if obj:
+ return obj
+ raise AttributeError("Unable to load {0} from available modules: {1}".format(target, str(modulenames)))
+
+ # Search for and return a controller or None from given module name
+ @staticmethod
+ def _loadControllerFromModule(target, modulename):
+ try:
+ import importlib
+ module = importlib.import_module(modulename)
+ return getattr(module, target)
+ except AttributeError:
+ return None
+
+ @staticmethod
+ def readPackagesManifest(manifest):
+ if not manifest or not os.path.exists(manifest):
+ raise OSError("Manifest file not exists: %s" % manifest)
+
+ image_packages = set()
+ with open(manifest, 'r') as f:
+ for line in f.readlines():
+ line = line.strip()
+ if line and not line.startswith("#"):
+ image_packages.add(line.split()[0])
+
+ return image_packages
+
+ @staticmethod
+ def getHostDumper(cmds, directory):
+ return HostDumper(cmds, directory)
+
+ def _process_args(self, logger, args):
+ if not args.packages_manifest:
+ raise TypeError('Manifest file not provided')
+
+ super(OERuntimeTestContextExecutor, self)._process_args(logger, args)
+
+ target_kwargs = {}
+ target_kwargs['qemuboot'] = args.qemu_boot
+
+ self.tc_kwargs['init']['target'] = \
+ OERuntimeTestContextExecutor.getTarget(args.target_type,
+ None, args.target_ip, args.server_ip, **target_kwargs)
+ self.tc_kwargs['init']['host_dumper'] = \
+ OERuntimeTestContextExecutor.getHostDumper(None,
+ args.host_dumper_dir)
+ self.tc_kwargs['init']['image_packages'] = \
+ OERuntimeTestContextExecutor.readPackagesManifest(
+ args.packages_manifest)
+ self.tc_kwargs['init']['extract_dir'] = args.extract_dir
+
+_executor_class = OERuntimeTestContextExecutor
diff --git a/meta/lib/oeqa/runtime/date.py b/meta/lib/oeqa/runtime/date.py
deleted file mode 100644
index 447987e075..0000000000
--- a/meta/lib/oeqa/runtime/date.py
+++ /dev/null
@@ -1,31 +0,0 @@
-from oeqa.oetest import oeRuntimeTest
-from oeqa.utils.decorators import *
-import re
-
-class DateTest(oeRuntimeTest):
-
- def setUpLocal(self):
- if oeRuntimeTest.tc.d.getVar("VIRTUAL-RUNTIME_init_manager", True) == "systemd":
- self.target.run('systemctl stop systemd-timesyncd')
-
- def tearDownLocal(self):
- if oeRuntimeTest.tc.d.getVar("VIRTUAL-RUNTIME_init_manager", True) == "systemd":
- self.target.run('systemctl start systemd-timesyncd')
-
- @testcase(211)
- @skipUnlessPassed("test_ssh")
- def test_date(self):
- (status, output) = self.target.run('date +"%Y-%m-%d %T"')
- self.assertEqual(status, 0, msg="Failed to get initial date, output: %s" % output)
- oldDate = output
-
- sampleDate = '"2016-08-09 10:00:00"'
- (status, output) = self.target.run("date -s %s" % sampleDate)
- self.assertEqual(status, 0, msg="Date set failed, output: %s" % output)
-
- (status, output) = self.target.run("date -R")
- p = re.match('Tue, 09 Aug 2016 10:00:.. \+0000', output)
- self.assertTrue(p, msg="The date was not set correctly, output: %s" % output)
-
- (status, output) = self.target.run('date -s "%s"' % oldDate)
- self.assertEqual(status, 0, msg="Failed to reset date, output: %s" % output)
diff --git a/meta/lib/oeqa/runtime/decorator/package.py b/meta/lib/oeqa/runtime/decorator/package.py
new file mode 100644
index 0000000000..8aba3f325b
--- /dev/null
+++ b/meta/lib/oeqa/runtime/decorator/package.py
@@ -0,0 +1,89 @@
+#
+# Copyright (C) 2016 Intel Corporation
+#
+# SPDX-License-Identifier: MIT
+#
+
+from oeqa.core.decorator import OETestDecorator, registerDecorator
+
+@registerDecorator
+class OEHasPackage(OETestDecorator):
+ """
+ Checks if image has packages (un)installed.
+
+ The argument must be a string, set, or list of packages that must be
+ installed or not present in the image.
+
+ The way to tell a package must not be in an image is using an
+ exclamation point ('!') before the name of the package.
+
+ If test depends on pkg1 or pkg2 you need to use:
+ @OEHasPackage({'pkg1', 'pkg2'})
+
+ If test depends on pkg1 and pkg2 you need to use:
+ @OEHasPackage('pkg1')
+ @OEHasPackage('pkg2')
+
+ If test depends on pkg1 but pkg2 must not be present use:
+ @OEHasPackage({'pkg1', '!pkg2'})
+ """
+
+ attrs = ('need_pkgs',)
+
+ def setUpDecorator(self):
+ need_pkgs = set()
+ unneed_pkgs = set()
+
+ # Turn literal strings into a list so we can just iterate over it
+ if isinstance(self.need_pkgs, str):
+ self.need_pkgs = [self.need_pkgs,]
+
+ for pkg in self.need_pkgs:
+ if pkg.startswith('!'):
+ unneed_pkgs.add(pkg[1:])
+ else:
+ need_pkgs.add(pkg)
+
+ if unneed_pkgs:
+ msg = 'Checking if %s is not installed' % ', '.join(unneed_pkgs)
+ self.logger.debug(msg)
+ if not self.case.tc.image_packages.isdisjoint(unneed_pkgs):
+ msg = "Test can't run with %s installed" % ', or '.join(unneed_pkgs)
+ self._decorator_fail(msg)
+
+ if need_pkgs:
+ msg = 'Checking if at least one of %s is installed' % ', '.join(need_pkgs)
+ self.logger.debug(msg)
+ if self.case.tc.image_packages.isdisjoint(need_pkgs):
+ msg = "Test requires %s to be installed" % ', or '.join(need_pkgs)
+ self._decorator_fail(msg)
+
+ def _decorator_fail(self, msg):
+ self.case.skipTest(msg)
+
+@registerDecorator
+class OERequirePackage(OEHasPackage):
+ """
+ Checks if image has packages (un)installed.
+ It is almost the same as OEHasPackage, but if dependencies are missing
+ the test case fails.
+
+ The argument must be a string, set, or list of packages that must be
+ installed or not present in the image.
+
+ The way to tell a package must not be in an image is using an
+ exclamation point ('!') before the name of the package.
+
+ If test depends on pkg1 or pkg2 you need to use:
+ @OERequirePackage({'pkg1', 'pkg2'})
+
+ If test depends on pkg1 and pkg2 you need to use:
+ @OERequirePackage('pkg1')
+ @OERequirePackage('pkg2')
+
+ If test depends on pkg1 but pkg2 must not be present use:
+ @OERequirePackage({'pkg1', '!pkg2'})
+ """
+
+ def _decorator_fail(self, msg):
+ self.case.fail(msg)
diff --git a/meta/lib/oeqa/runtime/df.py b/meta/lib/oeqa/runtime/df.py
deleted file mode 100644
index 09569d5ff6..0000000000
--- a/meta/lib/oeqa/runtime/df.py
+++ /dev/null
@@ -1,12 +0,0 @@
-import unittest
-from oeqa.oetest import oeRuntimeTest
-from oeqa.utils.decorators import *
-
-
-class DfTest(oeRuntimeTest):
-
- @testcase(234)
- @skipUnlessPassed("test_ssh")
- def test_df(self):
- (status,output) = self.target.run("df / | sed -n '2p' | awk '{print $4}'")
- self.assertTrue(int(output)>5120, msg="Not enough space on image. Current size is %s" % output)
diff --git a/meta/lib/oeqa/runtime/files/SConstruct b/meta/lib/oeqa/runtime/files/SConstruct
new file mode 100644
index 0000000000..d2cb6dd122
--- /dev/null
+++ b/meta/lib/oeqa/runtime/files/SConstruct
@@ -0,0 +1 @@
+Program('hello.c')
diff --git a/meta/lib/oeqa/runtime/files/hello.c b/meta/lib/oeqa/runtime/files/hello.c
new file mode 100644
index 0000000000..b0697a3304
--- /dev/null
+++ b/meta/lib/oeqa/runtime/files/hello.c
@@ -0,0 +1,5 @@
+int
+ main()
+ {
+ printf("Hello, world!\n");
+ }
diff --git a/meta/lib/oeqa/runtime/files/test.pl b/meta/lib/oeqa/runtime/files/test.pl
deleted file mode 100644
index 689c8f1635..0000000000
--- a/meta/lib/oeqa/runtime/files/test.pl
+++ /dev/null
@@ -1,2 +0,0 @@
-$a = 9.01e+21 - 9.01e+21 + 0.01;
-print ("the value of a is ", $a, "\n");
diff --git a/meta/lib/oeqa/runtime/files/test.py b/meta/lib/oeqa/runtime/files/test.py
deleted file mode 100644
index f389225d72..0000000000
--- a/meta/lib/oeqa/runtime/files/test.py
+++ /dev/null
@@ -1,6 +0,0 @@
-import os
-
-os.system('touch /tmp/testfile.python')
-
-a = 9.01e+21 - 9.01e+21 + 0.01
-print("the value of a is %s" % a)
diff --git a/meta/lib/oeqa/runtime/gcc.py b/meta/lib/oeqa/runtime/gcc.py
deleted file mode 100644
index d90cd1799a..0000000000
--- a/meta/lib/oeqa/runtime/gcc.py
+++ /dev/null
@@ -1,47 +0,0 @@
-import unittest
-import os
-from oeqa.oetest import oeRuntimeTest, skipModule
-from oeqa.utils.decorators import *
-
-def setUpModule():
- if not oeRuntimeTest.hasFeature("tools-sdk"):
- skipModule("Image doesn't have tools-sdk in IMAGE_FEATURES")
-
-
-class GccCompileTest(oeRuntimeTest):
-
- @classmethod
- def setUpClass(self):
- oeRuntimeTest.tc.target.copy_to(os.path.join(oeRuntimeTest.tc.filesdir, "test.c"), "/tmp/test.c")
- oeRuntimeTest.tc.target.copy_to(os.path.join(oeRuntimeTest.tc.filesdir, "testmakefile"), "/tmp/testmakefile")
- oeRuntimeTest.tc.target.copy_to(os.path.join(oeRuntimeTest.tc.filesdir, "test.cpp"), "/tmp/test.cpp")
-
- @testcase(203)
- def test_gcc_compile(self):
- (status, output) = self.target.run('gcc /tmp/test.c -o /tmp/test -lm')
- self.assertEqual(status, 0, msg="gcc compile failed, output: %s" % output)
- (status, output) = self.target.run('/tmp/test')
- self.assertEqual(status, 0, msg="running compiled file failed, output %s" % output)
-
- @testcase(200)
- def test_gpp_compile(self):
- (status, output) = self.target.run('g++ /tmp/test.c -o /tmp/test -lm')
- self.assertEqual(status, 0, msg="g++ compile failed, output: %s" % output)
- (status, output) = self.target.run('/tmp/test')
- self.assertEqual(status, 0, msg="running compiled file failed, output %s" % output)
-
- @testcase(1142)
- def test_gpp2_compile(self):
- (status, output) = self.target.run('g++ /tmp/test.cpp -o /tmp/test -lm')
- self.assertEqual(status, 0, msg="g++ compile failed, output: %s" % output)
- (status, output) = self.target.run('/tmp/test')
- self.assertEqual(status, 0, msg="running compiled file failed, output %s" % output)
-
- @testcase(204)
- def test_make(self):
- (status, output) = self.target.run('cd /tmp; make -f testmakefile')
- self.assertEqual(status, 0, msg="running make failed, output %s" % output)
-
- @classmethod
- def tearDownClass(self):
- oeRuntimeTest.tc.target.run("rm /tmp/test.c /tmp/test.o /tmp/test /tmp/testmakefile")
diff --git a/meta/lib/oeqa/runtime/kernelmodule.py b/meta/lib/oeqa/runtime/kernelmodule.py
deleted file mode 100644
index 38ca184540..0000000000
--- a/meta/lib/oeqa/runtime/kernelmodule.py
+++ /dev/null
@@ -1,34 +0,0 @@
-import unittest
-import os
-from oeqa.oetest import oeRuntimeTest, skipModule
-from oeqa.utils.decorators import *
-
-def setUpModule():
- if not oeRuntimeTest.hasFeature("tools-sdk"):
- skipModule("Image doesn't have tools-sdk in IMAGE_FEATURES")
-
-
-class KernelModuleTest(oeRuntimeTest):
-
- def setUpLocal(self):
- self.target.copy_to(os.path.join(oeRuntimeTest.tc.filesdir, "hellomod.c"), "/tmp/hellomod.c")
- self.target.copy_to(os.path.join(oeRuntimeTest.tc.filesdir, "hellomod_makefile"), "/tmp/Makefile")
-
- @testcase('316')
- @skipUnlessPassed('test_ssh')
- @skipUnlessPassed('test_gcc_compile')
- def test_kernel_module(self):
- cmds = [
- 'cd /usr/src/kernel && make scripts',
- 'cd /tmp && make',
- 'cd /tmp && insmod hellomod.ko',
- 'lsmod | grep hellomod',
- 'dmesg | grep Hello',
- 'rmmod hellomod', 'dmesg | grep "Cleaning up hellomod"'
- ]
- for cmd in cmds:
- (status, output) = self.target.run(cmd, 900)
- self.assertEqual(status, 0, msg="\n".join([cmd, output]))
-
- def tearDownLocal(self):
- self.target.run('rm -f /tmp/Makefile /tmp/hellomod.c')
diff --git a/meta/lib/oeqa/runtime/ldd.py b/meta/lib/oeqa/runtime/ldd.py
deleted file mode 100644
index 47b3885df2..0000000000
--- a/meta/lib/oeqa/runtime/ldd.py
+++ /dev/null
@@ -1,21 +0,0 @@
-import unittest
-from oeqa.oetest import oeRuntimeTest, skipModule
-from oeqa.utils.decorators import *
-
-def setUpModule():
- if not oeRuntimeTest.hasFeature("tools-sdk"):
- skipModule("Image doesn't have tools-sdk in IMAGE_FEATURES")
-
-class LddTest(oeRuntimeTest):
-
- @testcase(962)
- @skipUnlessPassed('test_ssh')
- def test_ldd_exists(self):
- (status, output) = self.target.run('which ldd')
- self.assertEqual(status, 0, msg = "ldd does not exist in PATH: which ldd: %s" % output)
-
- @testcase(239)
- @skipUnlessPassed('test_ldd_exists')
- def test_ldd_rtldlist_check(self):
- (status, output) = self.target.run('for i in $(which ldd | xargs cat | grep "^RTLDLIST"|cut -d\'=\' -f2|tr -d \'"\'); do test -f $i && echo $i && break; done')
- self.assertEqual(status, 0, msg = "ldd path not correct or RTLDLIST files don't exist. ")
diff --git a/meta/lib/oeqa/runtime/loader.py b/meta/lib/oeqa/runtime/loader.py
new file mode 100644
index 0000000000..7041ddfde8
--- /dev/null
+++ b/meta/lib/oeqa/runtime/loader.py
@@ -0,0 +1,19 @@
+#
+# Copyright (C) 2016 Intel Corporation
+#
+# SPDX-License-Identifier: MIT
+#
+
+from oeqa.core.loader import OETestLoader
+from oeqa.runtime.case import OERuntimeTestCase
+
+class OERuntimeTestLoader(OETestLoader):
+ caseClass = OERuntimeTestCase
+
+ def _getTestCase(self, testCaseClass, tcName):
+ case = super(OERuntimeTestLoader, self)._getTestCase(testCaseClass, tcName)
+
+ # Adds custom attributes to the OERuntimeTestCase
+ setattr(case, 'target', self.tc.target)
+
+ return case
diff --git a/meta/lib/oeqa/runtime/logrotate.py b/meta/lib/oeqa/runtime/logrotate.py
deleted file mode 100644
index de300bf55f..0000000000
--- a/meta/lib/oeqa/runtime/logrotate.py
+++ /dev/null
@@ -1,28 +0,0 @@
-# This test should cover https://bugzilla.yoctoproject.org/tr_show_case.cgi?case_id=289 testcase
-# Note that the image under test must have logrotate installed
-
-import unittest
-from oeqa.oetest import oeRuntimeTest, skipModule
-from oeqa.utils.decorators import *
-
-def setUpModule():
- if not oeRuntimeTest.hasPackage("logrotate"):
- skipModule("No logrotate package in image")
-
-
-class LogrotateTest(oeRuntimeTest):
-
- @skipUnlessPassed("test_ssh")
- def test_1_logrotate_setup(self):
- (status, output) = self.target.run('mkdir $HOME/logrotate_dir')
- self.assertEqual(status, 0, msg = "Could not create logrotate_dir. Output: %s" % output)
- (status, output) = self.target.run("sed -i \"s#wtmp {#wtmp {\\n olddir $HOME/logrotate_dir#\" /etc/logrotate.conf")
- self.assertEqual(status, 0, msg = "Could not write to logrotate.conf file. Status and output: %s and %s)" % (status, output))
-
- @testcase(289)
- @skipUnlessPassed("test_1_logrotate_setup")
- def test_2_logrotate(self):
- (status, output) = self.target.run('logrotate -f /etc/logrotate.conf')
- self.assertEqual(status, 0, msg = "logrotate service could not be reloaded. Status and output: %s and %s" % (status, output))
- output = self.target.run('ls -la $HOME/logrotate_dir/ | wc -l')[1]
- self.assertTrue(int(output)>=3, msg = "new logfile could not be created. List of files within log directory: %s" %(self.target.run('ls -la $HOME/logrotate_dir')[1]))
diff --git a/meta/lib/oeqa/runtime/multilib.py b/meta/lib/oeqa/runtime/multilib.py
deleted file mode 100644
index 593d385021..0000000000
--- a/meta/lib/oeqa/runtime/multilib.py
+++ /dev/null
@@ -1,42 +0,0 @@
-import unittest
-from oeqa.oetest import oeRuntimeTest, skipModule
-from oeqa.utils.decorators import *
-
-def setUpModule():
- multilibs = oeRuntimeTest.tc.d.getVar("MULTILIBS", True) or ""
- if "multilib:lib32" not in multilibs:
- skipModule("this isn't a multilib:lib32 image")
-
-
-class MultilibTest(oeRuntimeTest):
-
- def archtest(self, binary, arch):
- """
- Check that ``binary`` has the ELF class ``arch`` (e.g. ELF32/ELF64).
- """
-
- (status, output) = self.target.run("readelf -h %s" % binary)
- self.assertEqual(status, 0, "Failed to readelf %s" % binary)
-
- l = [l.split()[1] for l in output.split('\n') if "Class:" in l]
- if l:
- theclass = l[0]
- else:
- self.fail("Cannot parse readelf output\n" + s)
-
- self.assertEqual(theclass, arch, msg="%s isn't %s (is %s)" % (binary, arch, theclass))
-
- @skipUnlessPassed('test_ssh')
- def test_check_multilib_libc(self):
- """
- Check that a multilib image has both 32-bit and 64-bit libc in.
- """
- self.archtest("/lib/libc.so.6", "ELF32")
- self.archtest("/lib64/libc.so.6", "ELF64")
-
- @testcase('279')
- @skipUnlessPassed('test_check_multilib_libc')
- def test_file_connman(self):
- self.assertTrue(oeRuntimeTest.hasPackage('lib32-connman'), msg="This test assumes lib32-connman is installed")
-
- self.archtest("/usr/sbin/connmand", "ELF32")
diff --git a/meta/lib/oeqa/runtime/pam.py b/meta/lib/oeqa/runtime/pam.py
deleted file mode 100644
index c8205c9abc..0000000000
--- a/meta/lib/oeqa/runtime/pam.py
+++ /dev/null
@@ -1,25 +0,0 @@
-# This test should cover https://bugzilla.yoctoproject.org/tr_show_case.cgi?case_id=287 testcase
-# Note that the image under test must have "pam" in DISTRO_FEATURES
-
-import unittest
-from oeqa.oetest import oeRuntimeTest, skipModule
-from oeqa.utils.decorators import *
-
-def setUpModule():
- if not oeRuntimeTest.hasFeature("pam"):
- skipModule("target doesn't have 'pam' in DISTRO_FEATURES")
-
-
-class PamBasicTest(oeRuntimeTest):
-
- @testcase(287)
- @skipUnlessPassed('test_ssh')
- def test_pam(self):
- (status, output) = self.target.run('login --help')
- self.assertEqual(status, 1, msg = "login command does not work as expected. Status and output:%s and %s" %(status, output))
- (status, output) = self.target.run('passwd --help')
- self.assertEqual(status, 0, msg = "passwd command does not work as expected. Status and output:%s and %s" %(status, output))
- (status, output) = self.target.run('su --help')
- self.assertEqual(status, 0, msg = "su command does not work as expected. Status and output:%s and %s" %(status, output))
- (status, output) = self.target.run('useradd --help')
- self.assertEqual(status, 0, msg = "useradd command does not work as expected. Status and output:%s and %s" %(status, output))
diff --git a/meta/lib/oeqa/runtime/parselogs.py b/meta/lib/oeqa/runtime/parselogs.py
deleted file mode 100644
index 242cd8cdd5..0000000000
--- a/meta/lib/oeqa/runtime/parselogs.py
+++ /dev/null
@@ -1,277 +0,0 @@
-import os
-import unittest
-import subprocess
-from oeqa.oetest import oeRuntimeTest
-from oeqa.utils.decorators import *
-
-#in the future these lists could be moved outside of module
-errors = ["error", "cannot", "can\'t", "failed"]
-
-common_errors = [
- "(WW) warning, (EE) error, (NI) not implemented, (??) unknown.",
- "dma timeout",
- "can\'t add hid device:",
- "usbhid: probe of ",
- "_OSC failed (AE_ERROR)",
- "_OSC failed (AE_SUPPORT)",
- "AE_ALREADY_EXISTS",
- "ACPI _OSC request failed (AE_SUPPORT)",
- "can\'t disable ASPM",
- "Failed to load module \"vesa\"",
- "Failed to load module vesa",
- "Failed to load module \"modesetting\"",
- "Failed to load module modesetting",
- "Failed to load module \"glx\"",
- "Failed to load module \"fbdev\"",
- "Failed to load module fbdev",
- "Failed to load module glx",
- "[drm] Cannot find any crtc or sizes - going 1024x768",
- "_OSC failed (AE_NOT_FOUND); disabling ASPM",
- "Open ACPI failed (/var/run/acpid.socket) (No such file or directory)",
- "NX (Execute Disable) protection cannot be enabled: non-PAE kernel!",
- "hd.: possibly failed opcode",
- 'NETLINK INITIALIZATION FAILED',
- 'kernel: Cannot find map file',
- 'omap_hwmod: debugss: _wait_target_disable failed',
- 'VGA arbiter: cannot open kernel arbiter, no multi-card support',
- 'Failed to find URL:http://ipv4.connman.net/online/status.html',
- 'Online check failed for',
- 'netlink init failed',
- 'Fast TSC calibration',
- "BAR 0-9",
- "Failed to load module \"ati\"",
- "controller can't do DEVSLP, turning off",
- "stmmac_dvr_probe: warning: cannot get CSR clock",
- "error: couldn\'t mount because of unsupported optional features",
- ]
-
-video_related = [
- "uvesafb",
-]
-
-x86_common = [
- '[drm:psb_do_init] *ERROR* Debug is',
- 'wrong ELF class',
- 'Could not enable PowerButton event',
- 'probe of LNXPWRBN:00 failed with error -22',
- 'pmd_set_huge: Cannot satisfy',
-] + common_errors
-
-qemux86_common = [
- 'wrong ELF class',
- "fail to add MMCONFIG information, can't access extended PCI configuration space under this bridge.",
- "can't claim BAR ",
-] + common_errors
-
-ignore_errors = {
- 'default' : common_errors,
- 'qemux86' : [
- 'Failed to access perfctr msr (MSR',
- ] + qemux86_common,
- 'qemux86-64' : qemux86_common,
- 'qemumips' : [
- 'Failed to load module "glx"',
- 'pci 0000:00:00.0: [Firmware Bug]: reg 0x..: invalid BAR (can\'t size)',
- ] + common_errors,
- 'qemumips64' : [
- 'pci 0000:00:00.0: [Firmware Bug]: reg 0x..: invalid BAR (can\'t size)',
- ] + common_errors,
- 'qemuppc' : [
- 'PCI 0000:00 Cannot reserve Legacy IO [io 0x0000-0x0fff]',
- 'host side 80-wire cable detection failed, limiting max speed',
- 'mode "640x480" test failed',
- 'Failed to load module "glx"',
- ] + common_errors,
- 'qemuarm' : [
- 'mmci-pl18x: probe of fpga:05 failed with error -22',
- 'mmci-pl18x: probe of fpga:0b failed with error -22',
- 'Failed to load module "glx"'
- ] + common_errors,
- 'qemuarm64' : [
- 'Fatal server error:',
- '(EE) Server terminated with error (1). Closing log file.',
- 'dmi: Firmware registration failed.',
- ] + common_errors,
- 'emenlow' : [
- '[Firmware Bug]: ACPI: No _BQC method, cannot determine initial brightness',
- '(EE) Failed to load module "psb"',
- '(EE) Failed to load module psb',
- '(EE) Failed to load module "psbdrv"',
- '(EE) Failed to load module psbdrv',
- '(EE) open /dev/fb0: No such file or directory',
- '(EE) AIGLX: reverting to software rendering',
- ] + x86_common,
- 'intel-core2-32' : [
- 'ACPI: No _BQC method, cannot determine initial brightness',
- '[Firmware Bug]: ACPI: No _BQC method, cannot determine initial brightness',
- '(EE) Failed to load module "psb"',
- '(EE) Failed to load module psb',
- '(EE) Failed to load module "psbdrv"',
- '(EE) Failed to load module psbdrv',
- '(EE) open /dev/fb0: No such file or directory',
- '(EE) AIGLX: reverting to software rendering',
- ] + x86_common,
- 'intel-corei7-64' : x86_common,
- 'crownbay' : x86_common,
- 'genericx86' : x86_common,
- 'genericx86-64' : x86_common,
- 'edgerouter' : [
- 'Fatal server error:',
- ] + common_errors,
- 'jasperforest' : [
- 'Activated service \'org.bluez\' failed:',
- 'Unable to find NFC netlink family',
- ] + common_errors,
-}
-
-log_locations = ["/var/log/","/var/log/dmesg", "/tmp/dmesg_output.log"]
-
-class ParseLogsTest(oeRuntimeTest):
-
- @classmethod
- def setUpClass(self):
- self.errors = errors
-
- # When systemd is enabled we need to notice errors on
- # circular dependencies in units.
- if self.hasFeature("systemd"):
- self.errors.extend([
- 'Found ordering cycle on',
- 'Breaking ordering cycle by deleting job',
- 'deleted to break ordering cycle',
- 'Ordering cycle found, skipping',
- ])
-
- self.ignore_errors = ignore_errors
- self.log_locations = log_locations
- self.msg = ""
- (is_lsb, location) = oeRuntimeTest.tc.target.run("which LSB_Test.sh")
- if is_lsb == 0:
- for machine in self.ignore_errors:
- self.ignore_errors[machine] = self.ignore_errors[machine] + video_related
-
- def getMachine(self):
- return oeRuntimeTest.tc.d.getVar("MACHINE", True)
-
- #get some information on the CPU of the machine to display at the beginning of the output. This info might be useful in some cases.
- def getHardwareInfo(self):
- hwi = ""
- (status, cpu_name) = self.target.run("cat /proc/cpuinfo | grep \"model name\" | head -n1 | awk 'BEGIN{FS=\":\"}{print $2}'")
- (status, cpu_physical_cores) = self.target.run("cat /proc/cpuinfo | grep \"cpu cores\" | head -n1 | awk {'print $4'}")
- (status, cpu_logical_cores) = self.target.run("cat /proc/cpuinfo | grep \"processor\" | wc -l")
- (status, cpu_arch) = self.target.run("uname -m")
- hwi += "Machine information: \n"
- hwi += "*******************************\n"
- hwi += "Machine name: "+self.getMachine()+"\n"
- hwi += "CPU: "+str(cpu_name)+"\n"
- hwi += "Arch: "+str(cpu_arch)+"\n"
- hwi += "Physical cores: "+str(cpu_physical_cores)+"\n"
- hwi += "Logical cores: "+str(cpu_logical_cores)+"\n"
- hwi += "*******************************\n"
- return hwi
-
- #go through the log locations provided and if it's a folder create a list with all the .log files in it, if it's a file just add
- #it to that list
- def getLogList(self, log_locations):
- logs = []
- for location in log_locations:
- (status, output) = self.target.run("test -f "+str(location))
- if (status == 0):
- logs.append(str(location))
- else:
- (status, output) = self.target.run("test -d "+str(location))
- if (status == 0):
- (status, output) = self.target.run("find "+str(location)+"/*.log -maxdepth 1 -type f")
- if (status == 0):
- output = output.splitlines()
- for logfile in output:
- logs.append(os.path.join(location,str(logfile)))
- return logs
-
- #copy the log files to be parsed locally
- def transfer_logs(self, log_list):
- target_logs = 'target_logs'
- if not os.path.exists(target_logs):
- os.makedirs(target_logs)
- for f in log_list:
- self.target.copy_from(f, target_logs)
-
- #get the local list of logs
- def get_local_log_list(self, log_locations):
- self.transfer_logs(self.getLogList(log_locations))
- logs = [ os.path.join('target_logs',f) for f in os.listdir('target_logs') if os.path.isfile(os.path.join('target_logs',f)) ]
- return logs
-
- #build the grep command to be used with filters and exclusions
- def build_grepcmd(self, errors, ignore_errors, log):
- grepcmd = "grep "
- grepcmd +="-Ei \""
- for error in errors:
- grepcmd += error+"|"
- grepcmd = grepcmd[:-1]
- grepcmd += "\" "+str(log)+" | grep -Eiv \'"
- try:
- errorlist = ignore_errors[self.getMachine()]
- except KeyError:
- self.msg += "No ignore list found for this machine, using default\n"
- errorlist = ignore_errors['default']
- for ignore_error in errorlist:
- ignore_error = ignore_error.replace("(", "\(")
- ignore_error = ignore_error.replace(")", "\)")
- ignore_error = ignore_error.replace("'", ".")
- ignore_error = ignore_error.replace("?", "\?")
- ignore_error = ignore_error.replace("[", "\[")
- ignore_error = ignore_error.replace("]", "\]")
- ignore_error = ignore_error.replace("*", "\*")
- ignore_error = ignore_error.replace("0-9", "[0-9]")
- grepcmd += ignore_error+"|"
- grepcmd = grepcmd[:-1]
- grepcmd += "\'"
- return grepcmd
-
- #grep only the errors so that their context could be collected. Default context is 10 lines before and after the error itself
- def parse_logs(self, errors, ignore_errors, logs, lines_before = 10, lines_after = 10):
- results = {}
- rez = []
- grep_output = ''
- for log in logs:
- result = None
- thegrep = self.build_grepcmd(errors, ignore_errors, log)
- try:
- result = subprocess.check_output(thegrep, shell=True).decode("utf-8")
- except:
- pass
- if (result is not None):
- results[log.replace('target_logs/','')] = {}
- rez = result.splitlines()
- for xrez in rez:
- try:
- grep_output = subprocess.check_output(['grep', '-F', xrez, '-B', str(lines_before), '-A', str(lines_after), log]).decode("utf-8")
- except:
- pass
- results[log.replace('target_logs/','')][xrez]=grep_output
- return results
-
- #get the output of dmesg and write it in a file. This file is added to log_locations.
- def write_dmesg(self):
- (status, dmesg) = self.target.run("dmesg > /tmp/dmesg_output.log")
-
- @testcase(1059)
- @skipUnlessPassed('test_ssh')
- def test_parselogs(self):
- self.write_dmesg()
- log_list = self.get_local_log_list(self.log_locations)
- result = self.parse_logs(self.errors, self.ignore_errors, log_list)
- print(self.getHardwareInfo())
- errcount = 0
- for log in result:
- self.msg += "Log: "+log+"\n"
- self.msg += "-----------------------\n"
- for error in result[log]:
- errcount += 1
- self.msg += "Central error: "+str(error)+"\n"
- self.msg += "***********************\n"
- self.msg += result[str(log)][str(error)]+"\n"
- self.msg += "***********************\n"
- self.msg += "%s errors found in logs." % errcount
- self.assertEqual(errcount, 0, msg=self.msg)
diff --git a/meta/lib/oeqa/runtime/perl.py b/meta/lib/oeqa/runtime/perl.py
deleted file mode 100644
index e044d0a5fe..0000000000
--- a/meta/lib/oeqa/runtime/perl.py
+++ /dev/null
@@ -1,30 +0,0 @@
-import unittest
-import os
-from oeqa.oetest import oeRuntimeTest, skipModule
-from oeqa.utils.decorators import *
-
-def setUpModule():
- if not oeRuntimeTest.hasPackage("perl"):
- skipModule("No perl package in the image")
-
-
-class PerlTest(oeRuntimeTest):
-
- @classmethod
- def setUpClass(self):
- oeRuntimeTest.tc.target.copy_to(os.path.join(oeRuntimeTest.tc.filesdir, "test.pl"), "/tmp/test.pl")
-
- @testcase(1141)
- def test_perl_exists(self):
- (status, output) = self.target.run('which perl')
- self.assertEqual(status, 0, msg="Perl binary not in PATH or not on target.")
-
- @testcase(208)
- def test_perl_works(self):
- (status, output) = self.target.run('perl /tmp/test.pl')
- self.assertEqual(status, 0, msg="Exit status was not 0. Output: %s" % output)
- self.assertEqual(output, "the value of a is 0.01", msg="Incorrect output: %s" % output)
-
- @classmethod
- def tearDownClass(self):
- oeRuntimeTest.tc.target.run("rm /tmp/test.pl")
diff --git a/meta/lib/oeqa/runtime/ping.py b/meta/lib/oeqa/runtime/ping.py
deleted file mode 100644
index 0f27447926..0000000000
--- a/meta/lib/oeqa/runtime/ping.py
+++ /dev/null
@@ -1,22 +0,0 @@
-import subprocess
-import unittest
-import sys
-import time
-from oeqa.oetest import oeRuntimeTest
-from oeqa.utils.decorators import *
-
-class PingTest(oeRuntimeTest):
-
- @testcase(964)
- def test_ping(self):
- output = ''
- count = 0
- endtime = time.time() + 60
- while count < 5 and time.time() < endtime:
- proc = subprocess.Popen("ping -c 1 %s" % self.target.ip, shell=True, stdout=subprocess.PIPE)
- output += proc.communicate()[0].decode("utf-8")
- if proc.poll() == 0:
- count += 1
- else:
- count = 0
- self.assertEqual(count, 5, msg = "Expected 5 consecutive replies, got %d.\nping output is:\n%s" % (count,output))
diff --git a/meta/lib/oeqa/runtime/python.py b/meta/lib/oeqa/runtime/python.py
deleted file mode 100644
index 29a231c7c3..0000000000
--- a/meta/lib/oeqa/runtime/python.py
+++ /dev/null
@@ -1,35 +0,0 @@
-import unittest
-import os
-from oeqa.oetest import oeRuntimeTest, skipModule
-from oeqa.utils.decorators import *
-
-def setUpModule():
- if not oeRuntimeTest.hasPackage("python-core"):
- skipModule("No python package in the image")
-
-
-class PythonTest(oeRuntimeTest):
-
- @classmethod
- def setUpClass(self):
- oeRuntimeTest.tc.target.copy_to(os.path.join(oeRuntimeTest.tc.filesdir, "test.py"), "/tmp/test.py")
-
- @testcase(1145)
- def test_python_exists(self):
- (status, output) = self.target.run('which python')
- self.assertEqual(status, 0, msg="Python binary not in PATH or not on target.")
-
- @testcase(965)
- def test_python_stdout(self):
- (status, output) = self.target.run('python /tmp/test.py')
- self.assertEqual(status, 0, msg="Exit status was not 0. Output: %s" % output)
- self.assertEqual(output, "the value of a is 0.01", msg="Incorrect output: %s" % output)
-
- @testcase(1146)
- def test_python_testfile(self):
- (status, output) = self.target.run('ls /tmp/testfile.python')
- self.assertEqual(status, 0, msg="Python test file generate failed.")
-
- @classmethod
- def tearDownClass(self):
- oeRuntimeTest.tc.target.run("rm /tmp/test.py /tmp/testfile.python")
diff --git a/meta/lib/oeqa/runtime/rpm.py b/meta/lib/oeqa/runtime/rpm.py
deleted file mode 100644
index 624c515aad..0000000000
--- a/meta/lib/oeqa/runtime/rpm.py
+++ /dev/null
@@ -1,101 +0,0 @@
-import unittest
-import os
-import fnmatch
-from oeqa.oetest import oeRuntimeTest, skipModule
-from oeqa.utils.decorators import *
-
-def setUpModule():
- if not oeRuntimeTest.hasFeature("package-management"):
- skipModule("rpm module skipped: target doesn't have package-management in IMAGE_FEATURES")
- if "package_rpm" != oeRuntimeTest.tc.d.getVar("PACKAGE_CLASSES", True).split()[0]:
- skipModule("rpm module skipped: target doesn't have rpm as primary package manager")
-
-
-class RpmBasicTest(oeRuntimeTest):
-
- @testcase(960)
- @skipUnlessPassed('test_ssh')
- def test_rpm_help(self):
- (status, output) = self.target.run('rpm --help')
- self.assertEqual(status, 0, msg="status and output: %s and %s" % (status,output))
-
- @testcase(191)
- @skipUnlessPassed('test_rpm_help')
- def test_rpm_query(self):
- (status, output) = self.target.run('rpm -q rpm')
- self.assertEqual(status, 0, msg="status and output: %s and %s" % (status,output))
-
-class RpmInstallRemoveTest(oeRuntimeTest):
-
- @classmethod
- def setUpClass(self):
- pkgarch = oeRuntimeTest.tc.d.getVar('TUNE_PKGARCH', True).replace("-", "_")
- rpmdir = os.path.join(oeRuntimeTest.tc.d.getVar('DEPLOY_DIR', True), "rpm", pkgarch)
- # pick rpm-doc as a test file to get installed, because it's small and it will always be built for standard targets
- for f in fnmatch.filter(os.listdir(rpmdir), "rpm-doc-*.%s.rpm" % pkgarch):
- testrpmfile = f
- oeRuntimeTest.tc.target.copy_to(os.path.join(rpmdir,testrpmfile), "/tmp/rpm-doc.rpm")
-
- @testcase(192)
- @skipUnlessPassed('test_rpm_help')
- def test_rpm_install(self):
- (status, output) = self.target.run('rpm -ivh /tmp/rpm-doc.rpm')
- self.assertEqual(status, 0, msg="Failed to install rpm-doc package: %s" % output)
-
- @testcase(194)
- @skipUnlessPassed('test_rpm_install')
- def test_rpm_remove(self):
- (status,output) = self.target.run('rpm -e rpm-doc')
- self.assertEqual(status, 0, msg="Failed to remove rpm-doc package: %s" % output)
-
- @testcase(1096)
- @skipUnlessPassed('test_ssh')
- def test_rpm_query_nonroot(self):
- (status, output) = self.target.run('useradd test1')
- self.assertTrue(status == 0, msg="Failed to create new user: " + output)
- (status, output) = self.target.run('sudo -u test1 id')
- self.assertTrue('(test1)' in output, msg="Failed to execute as new user")
- (status, output) = self.target.run('sudo -u test1 rpm -qa')
- self.assertEqual(status, 0, msg="status: %s. Cannot run rpm -qa: %s" % (status, output))
-
- @testcase(195)
- @skipUnlessPassed('test_rpm_install')
- def test_check_rpm_install_removal_log_file_size(self):
- """
- Summary: Check rpm install/removal log file size
- Expected: There should be some method to keep rpm log in a small size .
- Product: BSPs
- Author: Alexandru Georgescu <alexandru.c.georgescu@intel.com>
- AutomatedBy: Daniel Istrate <daniel.alexandrux.istrate@intel.com>
- """
- db_files_cmd = 'ls /var/lib/rpm/__db.*'
- get_log_size_cmd = "du /var/lib/rpm/log/log.* | awk '{print $1}'"
-
- # Make sure that some database files are under /var/lib/rpm as '__db.xxx'
- (status, output) = self.target.run(db_files_cmd)
- self.assertEqual(0, status, 'Failed to find database files under /var/lib/rpm/ as __db.xxx')
-
- # Remove the package just in case
- self.target.run('rpm -e rpm-doc')
-
- # Install/Remove a package 10 times
- for i in range(10):
- (status, output) = self.target.run('rpm -ivh /tmp/rpm-doc.rpm')
- self.assertEqual(0, status, "Failed to install rpm-doc package. Reason: {}".format(output))
-
- (status, output) = self.target.run('rpm -e rpm-doc')
- self.assertEqual(0, status, "Failed to remove rpm-doc package. Reason: {}".format(output))
-
- # Get the size of log file
- (status, output) = self.target.run(get_log_size_cmd)
- self.assertEqual(0, status, 'Failed to get the final size of the log file.')
-
- # Compare each log size
- for log_file_size in output:
- self.assertLessEqual(int(log_file_size), 11264,
- 'Log file size is greater that expected (~10MB), found {} bytes'.format(log_file_size))
-
- @classmethod
- def tearDownClass(self):
- oeRuntimeTest.tc.target.run('rm -f /tmp/rpm-doc.rpm')
-
diff --git a/meta/lib/oeqa/runtime/scanelf.py b/meta/lib/oeqa/runtime/scanelf.py
deleted file mode 100644
index 67e02ff455..0000000000
--- a/meta/lib/oeqa/runtime/scanelf.py
+++ /dev/null
@@ -1,28 +0,0 @@
-import unittest
-from oeqa.oetest import oeRuntimeTest, skipModule
-from oeqa.utils.decorators import *
-
-def setUpModule():
- if not oeRuntimeTest.hasPackage("pax-utils"):
- skipModule("pax-utils package not installed")
-
-class ScanelfTest(oeRuntimeTest):
-
- def setUpLocal(self):
- self.scancmd = 'scanelf --quiet --recursive --mount --ldpath --path'
-
- @testcase(966)
- @skipUnlessPassed('test_ssh')
- def test_scanelf_textrel(self):
- # print TEXTREL information
- self.scancmd += " --textrel"
- (status, output) = self.target.run(self.scancmd)
- self.assertEqual(output.strip(), "", "\n".join([self.scancmd, output]))
-
- @testcase(967)
- @skipUnlessPassed('test_ssh')
- def test_scanelf_rpath(self):
- # print RPATH information
- self.scancmd += " --rpath"
- (status, output) = self.target.run(self.scancmd)
- self.assertEqual(output.strip(), "", "\n".join([self.scancmd, output]))
diff --git a/meta/lib/oeqa/runtime/scp.py b/meta/lib/oeqa/runtime/scp.py
deleted file mode 100644
index 48e87d2d0b..0000000000
--- a/meta/lib/oeqa/runtime/scp.py
+++ /dev/null
@@ -1,22 +0,0 @@
-import os
-from oeqa.oetest import oeRuntimeTest, skipModule
-from oeqa.utils.decorators import skipUnlessPassed, testcase
-
-def setUpModule():
- if not (oeRuntimeTest.hasPackage("dropbear") or oeRuntimeTest.hasPackage("openssh-sshd")):
- skipModule("No ssh package in image")
-
-class ScpTest(oeRuntimeTest):
-
- @testcase(220)
- @skipUnlessPassed('test_ssh')
- def test_scp_file(self):
- test_log_dir = oeRuntimeTest.tc.d.getVar("TEST_LOG_DIR", True)
- test_file_path = os.path.join(test_log_dir, 'test_scp_file')
- with open(test_file_path, 'w') as test_scp_file:
- test_scp_file.seek(2 ** 22 - 1)
- test_scp_file.write(os.linesep)
- (status, output) = self.target.copy_to(test_file_path, '/tmp/test_scp_file')
- self.assertEqual(status, 0, msg = "File could not be copied. Output: %s" % output)
- (status, output) = self.target.run("ls -la /tmp/test_scp_file")
- self.assertEqual(status, 0, msg = "SCP test failed")
diff --git a/meta/lib/oeqa/runtime/skeletoninit.py b/meta/lib/oeqa/runtime/skeletoninit.py
deleted file mode 100644
index cb0cb9b4cf..0000000000
--- a/meta/lib/oeqa/runtime/skeletoninit.py
+++ /dev/null
@@ -1,29 +0,0 @@
-# This test should cover https://bugzilla.yoctoproject.org/tr_show_case.cgi?case_id=284 testcase
-# Note that the image under test must have meta-skeleton layer in bblayers and IMAGE_INSTALL_append = " service" in local.conf
-
-import unittest
-from oeqa.oetest import oeRuntimeTest, skipModule
-from oeqa.utils.decorators import *
-
-def setUpModule():
- if not oeRuntimeTest.hasPackage("service"):
- skipModule("No service package in image")
-
-
-class SkeletonBasicTest(oeRuntimeTest):
-
- @skipUnlessPassed('test_ssh')
- @unittest.skipIf("systemd" == oeRuntimeTest.tc.d.getVar("VIRTUAL-RUNTIME_init_manager", False), "Not appropiate for systemd image")
- def test_skeleton_availability(self):
- (status, output) = self.target.run('ls /etc/init.d/skeleton')
- self.assertEqual(status, 0, msg = "skeleton init script not found. Output:\n%s " % output)
- (status, output) = self.target.run('ls /usr/sbin/skeleton-test')
- self.assertEqual(status, 0, msg = "skeleton-test not found. Output:\n%s" % output)
-
- @testcase(284)
- @skipUnlessPassed('test_skeleton_availability')
- @unittest.skipIf("systemd" == oeRuntimeTest.tc.d.getVar("VIRTUAL-RUNTIME_init_manager", False), "Not appropiate for systemd image")
- def test_skeleton_script(self):
- output1 = self.target.run("/etc/init.d/skeleton start")[1]
- (status, output2) = self.target.run(oeRuntimeTest.pscmd + ' | grep [s]keleton-test')
- self.assertEqual(status, 0, msg = "Skeleton script could not be started:\n%s\n%s" % (output1, output2))
diff --git a/meta/lib/oeqa/runtime/smart.py b/meta/lib/oeqa/runtime/smart.py
deleted file mode 100644
index c7a5753991..0000000000
--- a/meta/lib/oeqa/runtime/smart.py
+++ /dev/null
@@ -1,175 +0,0 @@
-import unittest
-import re
-from oeqa.oetest import oeRuntimeTest, skipModule
-from oeqa.utils.decorators import *
-from oeqa.utils.httpserver import HTTPService
-
-def setUpModule():
- if not oeRuntimeTest.hasFeature("package-management"):
- skipModule("Image doesn't have package management feature")
- if not oeRuntimeTest.hasPackage("smartpm"):
- skipModule("Image doesn't have smart installed")
- if "package_rpm" != oeRuntimeTest.tc.d.getVar("PACKAGE_CLASSES", True).split()[0]:
- skipModule("Rpm is not the primary package manager")
-
-class SmartTest(oeRuntimeTest):
-
- @skipUnlessPassed('test_smart_help')
- def smart(self, command, expected = 0):
- command = 'smart %s' % command
- status, output = self.target.run(command, 1500)
- message = os.linesep.join([command, output])
- self.assertEqual(status, expected, message)
- self.assertFalse("Cannot allocate memory" in output, message)
- return output
-
-class SmartBasicTest(SmartTest):
-
- @testcase(716)
- @skipUnlessPassed('test_ssh')
- def test_smart_help(self):
- self.smart('--help')
-
- @testcase(968)
- def test_smart_version(self):
- self.smart('--version')
-
- @testcase(721)
- def test_smart_info(self):
- self.smart('info python-smartpm')
-
- @testcase(421)
- def test_smart_query(self):
- self.smart('query python-smartpm')
-
- @testcase(720)
- def test_smart_search(self):
- self.smart('search python-smartpm')
-
- @testcase(722)
- def test_smart_stats(self):
- self.smart('stats')
-
-class SmartRepoTest(SmartTest):
-
- @classmethod
- def setUpClass(self):
- self.repolist = []
- self.repo_server = HTTPService(oeRuntimeTest.tc.d.getVar('DEPLOY_DIR', True), oeRuntimeTest.tc.target.server_ip)
- self.repo_server.start()
-
- @classmethod
- def tearDownClass(self):
- self.repo_server.stop()
- for i in self.repolist:
- oeRuntimeTest.tc.target.run('smart channel -y --remove '+str(i))
-
- @testcase(1143)
- def test_smart_channel(self):
- self.smart('channel', 1)
-
- @testcase(719)
- def test_smart_channel_add(self):
- image_pkgtype = self.tc.d.getVar('IMAGE_PKGTYPE', True)
- deploy_url = 'http://%s:%s/%s' %(self.target.server_ip, self.repo_server.port, image_pkgtype)
- pkgarchs = self.tc.d.getVar('PACKAGE_ARCHS', True).replace("-","_").split()
- for arch in os.listdir('%s/%s' % (self.repo_server.root_dir, image_pkgtype)):
- if arch in pkgarchs:
- self.smart('channel -y --add {a} type=rpm-md baseurl={u}/{a}'.format(a=arch, u=deploy_url))
- self.repolist.append(arch)
- self.smart('update')
-
- @testcase(969)
- def test_smart_channel_help(self):
- self.smart('channel --help')
-
- @testcase(970)
- def test_smart_channel_list(self):
- self.smart('channel --list')
-
- @testcase(971)
- def test_smart_channel_show(self):
- self.smart('channel --show')
-
- @testcase(717)
- def test_smart_channel_rpmsys(self):
- self.smart('channel --show rpmsys')
- self.smart('channel --disable rpmsys')
- self.smart('channel --enable rpmsys')
-
- @testcase(1144)
- @skipUnlessPassed('test_smart_channel_add')
- def test_smart_install(self):
- self.smart('remove -y psplash-default')
- self.smart('install -y psplash-default')
-
- @testcase(728)
- @skipUnlessPassed('test_smart_install')
- def test_smart_install_dependency(self):
- self.smart('remove -y psplash')
- self.smart('install -y psplash-default')
-
- @testcase(723)
- @skipUnlessPassed('test_smart_channel_add')
- def test_smart_install_from_disk(self):
- self.smart('remove -y psplash-default')
- self.smart('download psplash-default')
- self.smart('install -y ./psplash-default*')
-
- @testcase(725)
- @skipUnlessPassed('test_smart_channel_add')
- def test_smart_install_from_http(self):
- output = self.smart('download --urls psplash-default')
- url = re.search('(http://.*/psplash-default.*\.rpm)', output)
- self.assertTrue(url, msg="Couln't find download url in %s" % output)
- self.smart('remove -y psplash-default')
- self.smart('install -y %s' % url.group(0))
-
- @testcase(729)
- @skipUnlessPassed('test_smart_install')
- def test_smart_reinstall(self):
- self.smart('reinstall -y psplash-default')
-
- @testcase(727)
- @skipUnlessPassed('test_smart_channel_add')
- def test_smart_remote_repo(self):
- self.smart('update')
- self.smart('install -y psplash')
- self.smart('remove -y psplash')
-
- @testcase(726)
- def test_smart_local_dir(self):
- self.target.run('mkdir /tmp/myrpmdir')
- self.smart('channel --add myrpmdir type=rpm-dir path=/tmp/myrpmdir -y')
- self.target.run('cd /tmp/myrpmdir')
- self.smart('download psplash')
- output = self.smart('channel --list')
- for i in output.split("\n"):
- if ("rpmsys" != str(i)) and ("myrpmdir" != str(i)):
- self.smart('channel --disable '+str(i))
- self.target.run('cd $HOME')
- self.smart('install psplash')
- for i in output.split("\n"):
- if ("rpmsys" != str(i)) and ("myrpmdir" != str(i)):
- self.smart('channel --enable '+str(i))
- self.smart('channel --remove myrpmdir -y')
- self.target.run("rm -rf /tmp/myrpmdir")
-
- @testcase(718)
- def test_smart_add_rpmdir(self):
- self.target.run('mkdir /tmp/myrpmdir')
- self.smart('channel --add myrpmdir type=rpm-dir path=/tmp/myrpmdir -y')
- self.smart('channel --disable myrpmdir -y')
- output = self.smart('channel --show myrpmdir')
- self.assertTrue("disabled = yes" in output, msg="Failed to disable rpm dir")
- self.smart('channel --enable myrpmdir -y')
- output = self.smart('channel --show myrpmdir')
- self.assertFalse("disabled = yes" in output, msg="Failed to enable rpm dir")
- self.smart('channel --remove myrpmdir -y')
- self.target.run("rm -rf /tmp/myrpmdir")
-
- @testcase(731)
- @skipUnlessPassed('test_smart_channel_add')
- def test_smart_remove_package(self):
- self.smart('install -y psplash')
- self.smart('remove -y psplash')
diff --git a/meta/lib/oeqa/runtime/ssh.py b/meta/lib/oeqa/runtime/ssh.py
deleted file mode 100644
index 0e76d5d512..0000000000
--- a/meta/lib/oeqa/runtime/ssh.py
+++ /dev/null
@@ -1,19 +0,0 @@
-import subprocess
-import unittest
-import sys
-from oeqa.oetest import oeRuntimeTest, skipModule
-from oeqa.utils.decorators import *
-
-def setUpModule():
- if not (oeRuntimeTest.hasPackage("dropbear") or oeRuntimeTest.hasPackage("openssh")):
- skipModule("No ssh package in image")
-
-class SshTest(oeRuntimeTest):
-
- @testcase(224)
- @skipUnlessPassed('test_ping')
- def test_ssh(self):
- (status, output) = self.target.run('uname -a')
- self.assertEqual(status, 0, msg="SSH Test failed: %s" % output)
- (status, output) = self.target.run('cat /etc/masterimage')
- self.assertEqual(status, 1, msg="This isn't the right image - /etc/masterimage shouldn't be here %s" % output)
diff --git a/meta/lib/oeqa/runtime/syslog.py b/meta/lib/oeqa/runtime/syslog.py
deleted file mode 100644
index f7421ec8c5..0000000000
--- a/meta/lib/oeqa/runtime/syslog.py
+++ /dev/null
@@ -1,44 +0,0 @@
-import unittest
-from oeqa.oetest import oeRuntimeTest, skipModule
-from oeqa.utils.decorators import *
-
-def setUpModule():
- if not (oeRuntimeTest.hasPackage("busybox-syslog") or oeRuntimeTest.hasPackage("sysklogd")):
- skipModule("No syslog package in image")
-
-class SyslogTest(oeRuntimeTest):
-
- @testcase(201)
- def test_syslog_running(self):
- (status,output) = self.target.run(oeRuntimeTest.pscmd + ' | grep -i [s]yslogd')
- self.assertEqual(status, 0, msg="no syslogd process, ps output: %s" % self.target.run(oeRuntimeTest.pscmd)[1])
-
-class SyslogTestConfig(oeRuntimeTest):
-
- @testcase(1149)
- @skipUnlessPassed("test_syslog_running")
- def test_syslog_logger(self):
- (status,output) = self.target.run('logger foobar && test -e /var/log/messages && grep foobar /var/log/messages || logread | grep foobar')
- self.assertEqual(status, 0, msg="Test log string not found in /var/log/messages. Output: %s " % output)
-
- @testcase(1150)
- @skipUnlessPassed("test_syslog_running")
- def test_syslog_restart(self):
- if "systemd" != oeRuntimeTest.tc.d.getVar("VIRTUAL-RUNTIME_init_manager", False):
- (status,output) = self.target.run('/etc/init.d/syslog restart')
- else:
- (status,output) = self.target.run('systemctl restart syslog.service')
-
- @testcase(202)
- @skipUnlessPassed("test_syslog_restart")
- @skipUnlessPassed("test_syslog_logger")
- @unittest.skipIf("systemd" == oeRuntimeTest.tc.d.getVar("VIRTUAL-RUNTIME_init_manager", False), "Not appropiate for systemd image")
- @unittest.skipIf(oeRuntimeTest.hasPackage("sysklogd") or not oeRuntimeTest.hasPackage("busybox"), "Non-busybox syslog")
- def test_syslog_startup_config(self):
- self.target.run('echo "LOGFILE=/var/log/test" >> /etc/syslog-startup.conf')
- (status,output) = self.target.run('/etc/init.d/syslog restart')
- self.assertEqual(status, 0, msg="Could not restart syslog service. Status and output: %s and %s" % (status,output))
- (status,output) = self.target.run('logger foobar && grep foobar /var/log/test')
- self.assertEqual(status, 0, msg="Test log string not found. Output: %s " % output)
- self.target.run("sed -i 's#LOGFILE=/var/log/test##' /etc/syslog-startup.conf")
- self.target.run('/etc/init.d/syslog restart')
diff --git a/meta/lib/oeqa/runtime/systemd.py b/meta/lib/oeqa/runtime/systemd.py
deleted file mode 100644
index 8de799cd63..0000000000
--- a/meta/lib/oeqa/runtime/systemd.py
+++ /dev/null
@@ -1,178 +0,0 @@
-import unittest
-import re
-from oeqa.oetest import oeRuntimeTest, skipModule
-from oeqa.utils.decorators import *
-
-def setUpModule():
- if not oeRuntimeTest.hasFeature("systemd"):
- skipModule("target doesn't have systemd in DISTRO_FEATURES")
- if "systemd" != oeRuntimeTest.tc.d.getVar("VIRTUAL-RUNTIME_init_manager", True):
- skipModule("systemd is not the init manager for this image")
-
-
-class SystemdTest(oeRuntimeTest):
-
- def systemctl(self, action = '', target = '', expected = 0, verbose = False):
- command = 'systemctl %s %s' % (action, target)
- status, output = self.target.run(command)
- message = '\n'.join([command, output])
- if status != expected and verbose:
- message += self.target.run('systemctl status --full %s' % target)[1]
- self.assertEqual(status, expected, message)
- return output
-
- #TODO: use pyjournalctl instead
- def journalctl(self, args='',l_match_units=[]):
- """
- Request for the journalctl output to the current target system
-
- Arguments:
- -args, an optional argument pass through argument
- -l_match_units, an optional list of units to filter the output
- Returns:
- -string output of the journalctl command
- Raises:
- -AssertionError, on remote commands that fail
- -ValueError, on a journalctl call with filtering by l_match_units that
- returned no entries
- """
- query_units=""
- if len(l_match_units):
- query_units = ['_SYSTEMD_UNIT='+unit for unit in l_match_units]
- query_units = " ".join(query_units)
- command = 'journalctl %s %s' %(args, query_units)
- status, output = self.target.run(command)
- if status:
- raise AssertionError("Command '%s' returned non-zero exit \
- code %d:\n%s" % (command, status, output))
- if len(output) == 1 and "-- No entries --" in output:
- raise ValueError("List of units to match: %s, returned no entries"
- % l_match_units)
- return output
-
-class SystemdBasicTests(SystemdTest):
-
- @skipUnlessPassed('test_ssh')
- def test_systemd_basic(self):
- self.systemctl('--version')
-
- @testcase(551)
- @skipUnlessPassed('test_systemd_basic')
- def test_systemd_list(self):
- self.systemctl('list-unit-files')
-
- def settle(self):
- """
- Block until systemd has finished activating any units being activated,
- or until two minutes has elapsed.
-
- Returns a tuple, either (True, '') if all units have finished
- activating, or (False, message string) if there are still units
- activating (generally, failing units that restart).
- """
- import time
- endtime = time.time() + (60 * 2)
- while True:
- status, output = self.target.run('systemctl --state=activating')
- if "0 loaded units listed" in output:
- return (True, '')
- if time.time() >= endtime:
- return (False, output)
- time.sleep(10)
-
- @testcase(550)
- @skipUnlessPassed('test_systemd_basic')
- def test_systemd_failed(self):
- settled, output = self.settle()
- self.assertTrue(settled, msg="Timed out waiting for systemd to settle:\n" + output)
-
- output = self.systemctl('list-units', '--failed')
- match = re.search("0 loaded units listed", output)
- if not match:
- output += self.systemctl('status --full --failed')
- self.assertTrue(match, msg="Some systemd units failed:\n%s" % output)
-
-
-class SystemdServiceTests(SystemdTest):
-
- def check_for_avahi(self):
- if not self.hasPackage('avahi-daemon'):
- raise unittest.SkipTest("Testcase dependency not met: need avahi-daemon installed on target")
-
- @skipUnlessPassed('test_systemd_basic')
- def test_systemd_status(self):
- self.check_for_avahi()
- self.systemctl('status --full', 'avahi-daemon.service')
-
- @testcase(695)
- @skipUnlessPassed('test_systemd_status')
- def test_systemd_stop_start(self):
- self.check_for_avahi()
- self.systemctl('stop', 'avahi-daemon.service')
- self.systemctl('is-active', 'avahi-daemon.service', expected=3, verbose=True)
- self.systemctl('start','avahi-daemon.service')
- self.systemctl('is-active', 'avahi-daemon.service', verbose=True)
-
- @testcase(696)
- @skipUnlessPassed('test_systemd_basic')
- def test_systemd_disable_enable(self):
- self.check_for_avahi()
- self.systemctl('disable', 'avahi-daemon.service')
- self.systemctl('is-enabled', 'avahi-daemon.service', expected=1)
- self.systemctl('enable', 'avahi-daemon.service')
- self.systemctl('is-enabled', 'avahi-daemon.service')
-
-class SystemdJournalTests(SystemdTest):
- @skipUnlessPassed('test_ssh')
- def test_systemd_journal(self):
- (status, output) = self.target.run('journalctl')
- self.assertEqual(status, 0, output)
-
- @skipUnlessPassed('test_systemd_basic')
- def test_systemd_boot_time(self, systemd_TimeoutStartSec=90):
- """
- Get the target boot time from journalctl and log it
-
- Arguments:
- -systemd_TimeoutStartSec, an optional argument containing systemd's
- unit start timeout to compare against
- """
-
- # the expression chain that uniquely identifies the time boot message
- expr_items=["Startup finished","kernel", "userspace","\.$"]
- try:
- output = self.journalctl(args="-o cat --reverse")
- except AssertionError:
- self.fail("Error occurred while calling journalctl")
- if not len(output):
- self.fail("Error, unable to get startup time from systemd journal")
-
- # check for the regular expression items that match the startup time
- for line in output.split('\n'):
- check_match = "".join(re.findall(".*".join(expr_items), line))
- if check_match: break
- # put the startup time in the test log
- if check_match:
- print("%s" % check_match)
- else:
- self.skipTest("Error at obtaining the boot time from journalctl")
- boot_time_sec = 0
-
- # get the numeric values from the string and convert them to seconds
- # same data will be placed in list and string for manipulation
- l_boot_time = check_match.split(" ")[-2:]
- s_boot_time = " ".join(l_boot_time)
- try:
- # Obtain the minutes it took to boot
- if l_boot_time[0].endswith('min') and l_boot_time[0][0].isdigit():
- boot_time_min = s_boot_time.split("min")[0]
- # convert to seconds and accumulate it
- boot_time_sec += int(boot_time_min) * 60
- # Obtain the seconds it took to boot and accumulate
- boot_time_sec += float(l_boot_time[1].split("s")[0])
- except ValueError:
- self.skipTest("Error when parsing time from boot string")
- #Assert the target boot time against systemd's unit start timeout
- if boot_time_sec > systemd_TimeoutStartSec:
- print("Target boot time %s exceeds systemd's TimeoutStartSec %s"\
- %(boot_time_sec, systemd_TimeoutStartSec))
diff --git a/meta/lib/oeqa/runtime/utils/__init__.py b/meta/lib/oeqa/runtime/utils/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/meta/lib/oeqa/runtime/utils/__init__.py
diff --git a/meta/lib/oeqa/runtime/utils/targetbuildproject.py b/meta/lib/oeqa/runtime/utils/targetbuildproject.py
new file mode 100644
index 0000000000..f4f4816a9b
--- /dev/null
+++ b/meta/lib/oeqa/runtime/utils/targetbuildproject.py
@@ -0,0 +1,44 @@
+#
+# Copyright (C) 2016 Intel Corporation
+#
+# SPDX-License-Identifier: MIT
+#
+
+from oeqa.utils.buildproject import BuildProject
+
+class TargetBuildProject(BuildProject):
+
+ def __init__(self, target, uri, foldername=None, dl_dir=None):
+ self.target = target
+ self.targetdir = "~/buildtest/"
+ BuildProject.__init__(self, uri, foldername, dl_dir=dl_dir)
+
+ def download_archive(self):
+ self.target.run("mkdir " + self.targetdir + " || true")
+
+ self._download_archive()
+
+ status, output = self.target.copyTo(self.localarchive, self.targetdir)
+ if status:
+ raise Exception('Failed to copy archive to target, '
+ 'output: %s' % output)
+
+ cmd = 'tar xf %s%s -C %s' % (self.targetdir,
+ self.archive,
+ self.targetdir)
+ status, output = self.target.run(cmd)
+ if status:
+ raise Exception('Failed to extract archive, '
+ 'output: %s' % output)
+
+ # Change targetdir to project folder
+ self.targetdir = self.targetdir + self.fname
+
+ # The timeout parameter of target.run is set to 0
+ # to make the ssh command run with no timeout.
+ def _run(self, cmd):
+ ret = self.target.run(cmd, 0)
+ msg = "Command %s failed with exit code %s: %s" % (cmd, ret[0], ret[1])
+ if ret[0] != 0:
+ raise Exception(msg)
+ return ret[0]
diff --git a/meta/lib/oeqa/runtime/x32lib.py b/meta/lib/oeqa/runtime/x32lib.py
deleted file mode 100644
index ce5e214035..0000000000
--- a/meta/lib/oeqa/runtime/x32lib.py
+++ /dev/null
@@ -1,18 +0,0 @@
-import unittest
-from oeqa.oetest import oeRuntimeTest, skipModule
-from oeqa.utils.decorators import *
-
-def setUpModule():
- #check if DEFAULTTUNE is set and it's value is: x86-64-x32
- defaulttune = oeRuntimeTest.tc.d.getVar("DEFAULTTUNE", True)
- if "x86-64-x32" not in defaulttune:
- skipModule("DEFAULTTUNE is not set to x86-64-x32")
-
-class X32libTest(oeRuntimeTest):
-
- @testcase(281)
- @skipUnlessPassed("test_ssh")
- def test_x32_file(self):
- status1 = self.target.run("readelf -h /bin/ls | grep Class | grep ELF32")[0]
- status2 = self.target.run("readelf -h /bin/ls | grep Machine | grep X86-64")[0]
- self.assertTrue(status1 == 0 and status2 == 0, msg="/bin/ls isn't an X86-64 ELF32 binary. readelf says: %s" % self.target.run("readelf -h /bin/ls")[1])
diff --git a/meta/lib/oeqa/runtime/xorg.py b/meta/lib/oeqa/runtime/xorg.py
deleted file mode 100644
index 12bcd371af..0000000000
--- a/meta/lib/oeqa/runtime/xorg.py
+++ /dev/null
@@ -1,16 +0,0 @@
-import unittest
-from oeqa.oetest import oeRuntimeTest, skipModule
-from oeqa.utils.decorators import *
-
-def setUpModule():
- if not oeRuntimeTest.hasFeature("x11-base"):
- skipModule("target doesn't have x11 in IMAGE_FEATURES")
-
-
-class XorgTest(oeRuntimeTest):
-
- @testcase(1151)
- @skipUnlessPassed('test_ssh')
- def test_xorg_running(self):
- (status, output) = self.target.run(oeRuntimeTest.pscmd + ' | grep -v xinit | grep [X]org')
- self.assertEqual(status, 0, msg="Xorg does not appear to be running %s" % self.target.run(oeRuntimeTest.pscmd)[1])
diff --git a/meta/lib/oeqa/sdk/__init__.py b/meta/lib/oeqa/sdk/__init__.py
index 4cf3fa76b6..e69de29bb2 100644
--- a/meta/lib/oeqa/sdk/__init__.py
+++ b/meta/lib/oeqa/sdk/__init__.py
@@ -1,3 +0,0 @@
-# Enable other layers to have tests in the same named directory
-from pkgutil import extend_path
-__path__ = extend_path(__path__, __name__)
diff --git a/meta/lib/oeqa/sdk/buildcvs.py b/meta/lib/oeqa/sdk/buildcvs.py
deleted file mode 100644
index c7146fa4af..0000000000
--- a/meta/lib/oeqa/sdk/buildcvs.py
+++ /dev/null
@@ -1,25 +0,0 @@
-from oeqa.oetest import oeSDKTest, skipModule
-from oeqa.utils.decorators import *
-from oeqa.utils.targetbuild import SDKBuildProject
-
-class BuildCvsTest(oeSDKTest):
-
- @classmethod
- def setUpClass(self):
- self.project = SDKBuildProject(oeSDKTest.tc.sdktestdir + "/cvs/", oeSDKTest.tc.sdkenv, oeSDKTest.tc.d,
- "http://ftp.gnu.org/non-gnu/cvs/source/feature/1.12.13/cvs-1.12.13.tar.bz2")
- self.project.download_archive()
-
- def test_cvs(self):
- self.assertEqual(self.project.run_configure(), 0,
- msg="Running configure failed")
-
- self.assertEqual(self.project.run_make(), 0,
- msg="Running make failed")
-
- self.assertEqual(self.project.run_install(), 0,
- msg="Running make install failed")
-
- @classmethod
- def tearDownClass(self):
- self.project.clean()
diff --git a/meta/lib/oeqa/sdk/buildgalculator.py b/meta/lib/oeqa/sdk/buildgalculator.py
deleted file mode 100644
index be14d222c2..0000000000
--- a/meta/lib/oeqa/sdk/buildgalculator.py
+++ /dev/null
@@ -1,24 +0,0 @@
-from oeqa.oetest import oeSDKTest, skipModule
-from oeqa.utils.decorators import *
-from oeqa.utils.targetbuild import SDKBuildProject
-
-def setUpModule():
- if not (oeSDKTest.hasPackage("gtk+3") or oeSDKTest.hasPackage("libgtk-3.0")):
- skipModule("Image doesn't have gtk+3 in manifest")
-
-class GalculatorTest(oeSDKTest):
- def test_galculator(self):
- try:
- project = SDKBuildProject(oeSDKTest.tc.sdktestdir + "/galculator/",
- oeSDKTest.tc.sdkenv, oeSDKTest.tc.d,
- "http://galculator.mnim.org/downloads/galculator-2.1.4.tar.bz2")
-
- project.download_archive()
-
- self.assertEqual(project.run_configure(), 0,
- msg="Running configure failed")
-
- self.assertEqual(project.run_make(), 0,
- msg="Running make failed")
- finally:
- project.clean()
diff --git a/meta/lib/oeqa/sdk/buildiptables.py b/meta/lib/oeqa/sdk/buildiptables.py
deleted file mode 100644
index 062e5316e7..0000000000
--- a/meta/lib/oeqa/sdk/buildiptables.py
+++ /dev/null
@@ -1,26 +0,0 @@
-from oeqa.oetest import oeSDKTest
-from oeqa.utils.decorators import *
-from oeqa.utils.targetbuild import SDKBuildProject
-
-
-class BuildIptablesTest(oeSDKTest):
-
- @classmethod
- def setUpClass(self):
- self.project = SDKBuildProject(oeSDKTest.tc.sdktestdir + "/iptables/", oeSDKTest.tc.sdkenv, oeSDKTest.tc.d,
- "http://netfilter.org/projects/iptables/files/iptables-1.4.13.tar.bz2")
- self.project.download_archive()
-
- def test_iptables(self):
- self.assertEqual(self.project.run_configure(), 0,
- msg="Running configure failed")
-
- self.assertEqual(self.project.run_make(), 0,
- msg="Running make failed")
-
- self.assertEqual(self.project.run_install(), 0,
- msg="Running make install failed")
-
- @classmethod
- def tearDownClass(self):
- self.project.clean()
diff --git a/meta/lib/oeqa/sdk/buildtools-cases/README b/meta/lib/oeqa/sdk/buildtools-cases/README
new file mode 100644
index 0000000000..d4f20faa9f
--- /dev/null
+++ b/meta/lib/oeqa/sdk/buildtools-cases/README
@@ -0,0 +1,2 @@
+These test cases are used by buildtools-tarball, and are not used by the testsdk
+class.
diff --git a/meta/lib/oeqa/sdk/buildtools-cases/build.py b/meta/lib/oeqa/sdk/buildtools-cases/build.py
new file mode 100644
index 0000000000..c85c32496b
--- /dev/null
+++ b/meta/lib/oeqa/sdk/buildtools-cases/build.py
@@ -0,0 +1,32 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
+import os, tempfile
+import time
+from oeqa.sdk.case import OESDKTestCase
+from oeqa.utils.subprocesstweak import errors_have_output
+errors_have_output()
+
+class BuildTests(OESDKTestCase):
+ """
+ Verify that bitbake can build virtual/libc inside the buildtools.
+ """
+ def test_libc(self):
+ with tempfile.TemporaryDirectory(prefix='bitbake-build-', dir=self.tc.sdk_dir) as testdir:
+ corebase = self.td['COREBASE']
+
+ self._run('. %s/oe-init-build-env %s' % (corebase, testdir))
+ with open(os.path.join(testdir, 'conf', 'local.conf'), 'ta') as conf:
+ conf.write('\n')
+ conf.write('DL_DIR = "%s"\n' % self.td['DL_DIR'])
+
+ try:
+ self._run('. %s/oe-init-build-env %s && bitbake virtual/libc' % (corebase, testdir))
+ finally:
+ delay = 10
+ while delay and (os.path.exists(testdir + "/bitbake.lock") or os.path.exists(testdir + "/cache/hashserv.db-wal")):
+ time.sleep(1)
+ delay = delay - 1
diff --git a/meta/lib/oeqa/sdk/buildtools-cases/gcc.py b/meta/lib/oeqa/sdk/buildtools-cases/gcc.py
new file mode 100644
index 0000000000..a62c4d0bc4
--- /dev/null
+++ b/meta/lib/oeqa/sdk/buildtools-cases/gcc.py
@@ -0,0 +1,31 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
+import os.path
+from oeqa.sdk.case import OESDKTestCase
+
+class GccTests(OESDKTestCase):
+ def test_verify_specs(self):
+ """
+ Verify that the compiler has been relocated successfully and isn't
+ looking in the hard-coded prefix.
+ """
+ # Canonicalise the SDK root
+ sdk_base = os.path.realpath(self.tc.sdk_dir)
+ # Canonicalise the location of GCC
+ gcc_path = os.path.realpath(self._run("command -v gcc").strip())
+ # Skip the test if the GCC didn't come from the buildtools, as it only
+ # comes with buildtools-extended-tarball.
+ if os.path.commonprefix((sdk_base, gcc_path)) != sdk_base:
+ self.skipTest("Buildtools does not provide GCC")
+
+ # This is the prefix that GCC is build with, and should be replaced at
+ # installation time.
+ sdkpath = self.td.get("SDKPATH")
+ self.assertTrue(sdkpath)
+
+ for line in self._run('gcc -dumpspecs').splitlines():
+ self.assertNotIn(sdkpath, line)
diff --git a/meta/lib/oeqa/sdk/buildtools-cases/https.py b/meta/lib/oeqa/sdk/buildtools-cases/https.py
new file mode 100644
index 0000000000..4525e3d758
--- /dev/null
+++ b/meta/lib/oeqa/sdk/buildtools-cases/https.py
@@ -0,0 +1,22 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
+from oeqa.sdk.case import OESDKTestCase
+from oeqa.utils.subprocesstweak import errors_have_output
+errors_have_output()
+
+class HTTPTests(OESDKTestCase):
+ """
+ Verify that HTTPS certificates are working correctly, as this depends on
+ environment variables being set correctly.
+ """
+
+ def test_wget(self):
+ self._run('env -i wget --debug --output-document /dev/null https://yoctoproject.org/connectivity.html')
+
+ def test_python(self):
+ # urlopen() returns a file-like object on success and throws an exception otherwise
+ self._run('python3 -c \'import urllib.request; urllib.request.urlopen("https://yoctoproject.org/connectivity.html")\'')
diff --git a/meta/lib/oeqa/sdk/buildtools-cases/sanity.py b/meta/lib/oeqa/sdk/buildtools-cases/sanity.py
new file mode 100644
index 0000000000..b9dfa39a06
--- /dev/null
+++ b/meta/lib/oeqa/sdk/buildtools-cases/sanity.py
@@ -0,0 +1,24 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
+import shutil
+import os.path
+from oeqa.sdk.case import OESDKTestCase
+
+class SanityTests(OESDKTestCase):
+ def test_tools(self):
+ """
+ Test that wget and tar come from the buildtools, not the host. This
+ verifies that the buildtools have installed correctly. We can't check
+ for gcc as that is only installed by buildtools-extended.
+ """
+ for command in ("tar", "wget"):
+ # Canonicalise the SDK root
+ sdk_base = os.path.realpath(self.tc.sdk_dir)
+ # Canonicalise the location of this command
+ tool_path = os.path.realpath(self._run("command -v %s" % command).strip())
+ # Assert that the tool was found inside the SDK root
+ self.assertEquals(os.path.commonprefix((sdk_base, tool_path)), sdk_base)
diff --git a/meta/lib/oeqa/sdk/buildtools-docs-cases/README b/meta/lib/oeqa/sdk/buildtools-docs-cases/README
new file mode 100644
index 0000000000..f8edbc7dad
--- /dev/null
+++ b/meta/lib/oeqa/sdk/buildtools-docs-cases/README
@@ -0,0 +1,2 @@
+These test cases are used by build-docs-tarball, and are not used by the testsdk
+class.
diff --git a/meta/lib/oeqa/sdk/buildtools-docs-cases/build.py b/meta/lib/oeqa/sdk/buildtools-docs-cases/build.py
new file mode 100644
index 0000000000..6e3ee94292
--- /dev/null
+++ b/meta/lib/oeqa/sdk/buildtools-docs-cases/build.py
@@ -0,0 +1,19 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
+import tempfile
+from oeqa.sdk.case import OESDKTestCase
+from oeqa.utils.subprocesstweak import errors_have_output
+errors_have_output()
+
+class BuildTests(OESDKTestCase):
+ """
+ Verify that our docs can build using our docs tools tarball.
+ """
+ def test_docs_build(self):
+ with tempfile.TemporaryDirectory(prefix='docs-tarball-build-', dir=self.tc.sdk_dir) as testdir:
+ self._run('git clone git://git.yoctoproject.org/yocto-docs %s' % testdir)
+ self._run('cd %s/documentation && make html' % testdir)
diff --git a/meta/lib/oeqa/sdk/case.py b/meta/lib/oeqa/sdk/case.py
new file mode 100644
index 0000000000..c45882689c
--- /dev/null
+++ b/meta/lib/oeqa/sdk/case.py
@@ -0,0 +1,54 @@
+#
+# Copyright (C) 2016 Intel Corporation
+#
+# SPDX-License-Identifier: MIT
+#
+
+import os
+import subprocess
+
+from oeqa.core.case import OETestCase
+
+class OESDKTestCase(OETestCase):
+ def _run(self, cmd):
+ return subprocess.check_output(". %s > /dev/null; %s;" % \
+ (self.tc.sdk_env, cmd), shell=True, executable="/bin/bash",
+ stderr=subprocess.STDOUT, universal_newlines=True)
+
+ def fetch(self, workdir, dl_dir, url, archive=None):
+ if not archive:
+ from urllib.parse import urlparse
+ archive = os.path.basename(urlparse(url).path)
+
+ if dl_dir:
+ tarball = os.path.join(dl_dir, archive)
+ if os.path.exists(tarball):
+ return tarball
+
+ tarball = os.path.join(workdir, archive)
+ subprocess.check_output(["wget", "-O", tarball, url], stderr=subprocess.STDOUT)
+ return tarball
+
+ def check_elf(self, path, target_os=None, target_arch=None):
+ """
+ Verify that the ELF binary $path matches the specified target
+ OS/architecture, or if not specified the currently configured MACHINE's
+ OS/architecture.
+ """
+ import oe.qa, oe.elf
+
+ if not target_os or not target_arch:
+ output = self._run("echo $OECORE_TARGET_OS:$OECORE_TARGET_ARCH")
+ target_os, target_arch = output.strip().split(":")
+
+ machine_data = oe.elf.machine_dict(None)[target_os][target_arch]
+ (machine, osabi, abiversion, endian, bits) = machine_data
+
+ elf = oe.qa.ELFFile(path)
+ elf.open()
+
+ self.assertEqual(machine, elf.machine(),
+ "Binary was %s but expected %s" %
+ (oe.qa.elf_machine_to_string(elf.machine()), oe.qa.elf_machine_to_string(machine)))
+ self.assertEqual(bits, elf.abiSize())
+ self.assertEqual(endian, elf.isLittleEndian())
diff --git a/meta/lib/oeqa/sdk/cases/assimp.py b/meta/lib/oeqa/sdk/cases/assimp.py
new file mode 100644
index 0000000000..aa6541c6f6
--- /dev/null
+++ b/meta/lib/oeqa/sdk/cases/assimp.py
@@ -0,0 +1,42 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
+import os
+import subprocess
+import tempfile
+import unittest
+from oeqa.sdk.case import OESDKTestCase
+
+from oeqa.utils.subprocesstweak import errors_have_output
+errors_have_output()
+
+class BuildAssimp(OESDKTestCase):
+ """
+ Test case to build a project using cmake.
+ """
+
+ def setUp(self):
+ if not (self.tc.hasHostPackage("nativesdk-cmake") or
+ self.tc.hasHostPackage("cmake-native")):
+ raise unittest.SkipTest("Needs cmake")
+
+ def test_assimp(self):
+ with tempfile.TemporaryDirectory(prefix="assimp", dir=self.tc.sdk_dir) as testdir:
+ tarball = self.fetch(testdir, self.td["DL_DIR"], "https://github.com/assimp/assimp/archive/v4.1.0.tar.gz")
+
+ dirs = {}
+ dirs["source"] = os.path.join(testdir, "assimp-4.1.0")
+ dirs["build"] = os.path.join(testdir, "build")
+ dirs["install"] = os.path.join(testdir, "install")
+
+ subprocess.check_output(["tar", "xf", tarball, "-C", testdir], stderr=subprocess.STDOUT)
+ self.assertTrue(os.path.isdir(dirs["source"]))
+ os.makedirs(dirs["build"])
+
+ self._run("cd {build} && cmake -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON {source}".format(**dirs))
+ self._run("cmake --build {build} -- -j".format(**dirs))
+ self._run("cmake --build {build} --target install -- DESTDIR={install}".format(**dirs))
+ self.check_elf(os.path.join(dirs["install"], "usr", "local", "lib", "libassimp.so.4.1.0"))
diff --git a/meta/lib/oeqa/sdk/cases/buildcpio.py b/meta/lib/oeqa/sdk/cases/buildcpio.py
new file mode 100644
index 0000000000..c42c670add
--- /dev/null
+++ b/meta/lib/oeqa/sdk/cases/buildcpio.py
@@ -0,0 +1,38 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
+import os
+import tempfile
+import subprocess
+import unittest
+
+from oeqa.sdk.case import OESDKTestCase
+from oeqa.utils.subprocesstweak import errors_have_output
+errors_have_output()
+
+class BuildCpioTest(OESDKTestCase):
+ """
+ Check that autotools will cross-compile correctly.
+ """
+ def test_cpio(self):
+ with tempfile.TemporaryDirectory(prefix="cpio-", dir=self.tc.sdk_dir) as testdir:
+ tarball = self.fetch(testdir, self.td["DL_DIR"], "https://ftp.gnu.org/gnu/cpio/cpio-2.13.tar.gz")
+
+ dirs = {}
+ dirs["source"] = os.path.join(testdir, "cpio-2.13")
+ dirs["build"] = os.path.join(testdir, "build")
+ dirs["install"] = os.path.join(testdir, "install")
+
+ subprocess.check_output(["tar", "xf", tarball, "-C", testdir], stderr=subprocess.STDOUT)
+ self.assertTrue(os.path.isdir(dirs["source"]))
+ os.makedirs(dirs["build"])
+
+ self._run("sed -i -e '/char.*program_name/d' {source}/src/global.c".format(**dirs))
+ self._run("cd {build} && {source}/configure --disable-maintainer-mode $CONFIGURE_FLAGS".format(**dirs))
+ self._run("cd {build} && make -j".format(**dirs))
+ self._run("cd {build} && make install DESTDIR={install}".format(**dirs))
+
+ self.check_elf(os.path.join(dirs["install"], "usr", "local", "bin", "cpio"))
diff --git a/meta/lib/oeqa/sdk/cases/buildepoxy.py b/meta/lib/oeqa/sdk/cases/buildepoxy.py
new file mode 100644
index 0000000000..ee515be188
--- /dev/null
+++ b/meta/lib/oeqa/sdk/cases/buildepoxy.py
@@ -0,0 +1,44 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
+import os
+import subprocess
+import tempfile
+import unittest
+
+from oeqa.sdk.case import OESDKTestCase
+from oeqa.utils.subprocesstweak import errors_have_output
+errors_have_output()
+
+class EpoxyTest(OESDKTestCase):
+ """
+ Test that Meson builds correctly.
+ """
+ def setUp(self):
+ if not (self.tc.hasHostPackage("nativesdk-meson") or
+ self.tc.hasHostPackage("meson-native")):
+ raise unittest.SkipTest("EpoxyTest class: SDK doesn't contain Meson")
+
+ def test_epoxy(self):
+ with tempfile.TemporaryDirectory(prefix="epoxy", dir=self.tc.sdk_dir) as testdir:
+ tarball = self.fetch(testdir, self.td["DL_DIR"], "https://github.com/anholt/libepoxy/releases/download/1.5.3/libepoxy-1.5.3.tar.xz")
+
+ dirs = {}
+ dirs["source"] = os.path.join(testdir, "libepoxy-1.5.3")
+ dirs["build"] = os.path.join(testdir, "build")
+ dirs["install"] = os.path.join(testdir, "install")
+
+ subprocess.check_output(["tar", "xf", tarball, "-C", testdir], stderr=subprocess.STDOUT)
+ self.assertTrue(os.path.isdir(dirs["source"]))
+ os.makedirs(dirs["build"])
+
+ log = self._run("meson -Degl=no -Dglx=no -Dx11=false {build} {source}".format(**dirs))
+ # Check that Meson thinks we're doing a cross build and not a native
+ self.assertIn("Build type: cross build", log)
+ self._run("ninja -C {build} -v".format(**dirs))
+ self._run("DESTDIR={install} ninja -C {build} -v install".format(**dirs))
+
+ self.check_elf(os.path.join(dirs["install"], "usr", "local", "lib", "libepoxy.so"))
diff --git a/meta/lib/oeqa/sdk/cases/buildgalculator.py b/meta/lib/oeqa/sdk/cases/buildgalculator.py
new file mode 100644
index 0000000000..178f07472d
--- /dev/null
+++ b/meta/lib/oeqa/sdk/cases/buildgalculator.py
@@ -0,0 +1,46 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
+import os
+import subprocess
+import tempfile
+import unittest
+
+from oeqa.sdk.case import OESDKTestCase
+from oeqa.utils.subprocesstweak import errors_have_output
+errors_have_output()
+
+class GalculatorTest(OESDKTestCase):
+ """
+ Test that autotools and GTK+ 3 compiles correctly.
+ """
+ def setUp(self):
+ if not (self.tc.hasTargetPackage("gtk+3", multilib=True) or \
+ self.tc.hasTargetPackage("libgtk-3.0", multilib=True)):
+ raise unittest.SkipTest("GalculatorTest class: SDK don't support gtk+3")
+ if not (self.tc.hasHostPackage("nativesdk-gettext-dev") or
+ self.tc.hasHostPackage("gettext-native")):
+ raise unittest.SkipTest("GalculatorTest class: SDK doesn't contain gettext")
+
+ def test_galculator(self):
+ with tempfile.TemporaryDirectory(prefix="galculator", dir=self.tc.sdk_dir) as testdir:
+ tarball = self.fetch(testdir, self.td["DL_DIR"], "http://galculator.mnim.org/downloads/galculator-2.1.4.tar.bz2")
+
+ dirs = {}
+ dirs["source"] = os.path.join(testdir, "galculator-2.1.4")
+ dirs["build"] = os.path.join(testdir, "build")
+ dirs["install"] = os.path.join(testdir, "install")
+
+ subprocess.check_output(["tar", "xf", tarball, "-C", testdir], stderr=subprocess.STDOUT)
+ self.assertTrue(os.path.isdir(dirs["source"]))
+ os.makedirs(dirs["build"])
+
+ self._run("cd {source} && sed -i -e '/s_preferences.*prefs;/d' src/main.c && autoreconf -i -f -I $OECORE_TARGET_SYSROOT/usr/share/aclocal -I m4".format(**dirs))
+ self._run("cd {build} && {source}/configure $CONFIGURE_FLAGS".format(**dirs))
+ self._run("cd {build} && make -j".format(**dirs))
+ self._run("cd {build} && make install DESTDIR={install}".format(**dirs))
+
+ self.check_elf(os.path.join(dirs["install"], "usr", "local", "bin", "galculator"))
diff --git a/meta/lib/oeqa/sdk/cases/buildlzip.py b/meta/lib/oeqa/sdk/cases/buildlzip.py
new file mode 100644
index 0000000000..b4b7d85b88
--- /dev/null
+++ b/meta/lib/oeqa/sdk/cases/buildlzip.py
@@ -0,0 +1,39 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
+import os, tempfile, subprocess, unittest
+from oeqa.sdk.case import OESDKTestCase
+from oeqa.utils.subprocesstweak import errors_have_output
+errors_have_output()
+
+class BuildLzipTest(OESDKTestCase):
+ """
+ Test that "plain" compilation works, using just $CC $CFLAGS etc.
+ """
+ def test_lzip(self):
+ with tempfile.TemporaryDirectory(prefix="lzip", dir=self.tc.sdk_dir) as testdir:
+ tarball = self.fetch(testdir, self.td["DL_DIR"], "http://downloads.yoctoproject.org/mirror/sources/lzip-1.19.tar.gz")
+
+ dirs = {}
+ dirs["source"] = os.path.join(testdir, "lzip-1.19")
+ dirs["build"] = os.path.join(testdir, "build")
+ dirs["install"] = os.path.join(testdir, "install")
+
+ subprocess.check_output(["tar", "xf", tarball, "-C", testdir], stderr=subprocess.STDOUT)
+ self.assertTrue(os.path.isdir(dirs["source"]))
+ os.makedirs(dirs["build"])
+
+ cmd = """cd {build} && \
+ {source}/configure --srcdir {source} \
+ CXX="$CXX" \
+ CPPFLAGS="$CPPFLAGS" \
+ CXXFLAGS="$CXXFLAGS" \
+ LDFLAGS="$LDFLAGS" \
+ """
+ self._run(cmd.format(**dirs))
+ self._run("cd {build} && make -j".format(**dirs))
+ self._run("cd {build} && make install DESTDIR={install}".format(**dirs))
+ self.check_elf(os.path.join(dirs["install"], "usr", "local", "bin", "lzip"))
diff --git a/meta/lib/oeqa/sdk/cases/gcc.py b/meta/lib/oeqa/sdk/cases/gcc.py
new file mode 100644
index 0000000000..fc28b9c3d4
--- /dev/null
+++ b/meta/lib/oeqa/sdk/cases/gcc.py
@@ -0,0 +1,52 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
+import os
+import shutil
+import unittest
+
+from oeqa.core.utils.path import remove_safe
+from oeqa.sdk.case import OESDKTestCase
+
+from oeqa.utils.subprocesstweak import errors_have_output
+errors_have_output()
+
+class GccCompileTest(OESDKTestCase):
+ td_vars = ['MACHINE']
+
+ @classmethod
+ def setUpClass(self):
+ files = {'test.c' : self.tc.files_dir, 'test.cpp' : self.tc.files_dir,
+ 'testsdkmakefile' : self.tc.sdk_files_dir}
+ for f in files:
+ shutil.copyfile(os.path.join(files[f], f),
+ os.path.join(self.tc.sdk_dir, f))
+
+ def setUp(self):
+ machine = self.td.get("MACHINE")
+ if not (self.tc.hasHostPackage("packagegroup-cross-canadian-%s" % machine) or
+ self.tc.hasHostPackage("^gcc-", regex=True)):
+ raise unittest.SkipTest("GccCompileTest class: SDK doesn't contain a cross-canadian toolchain")
+
+ def test_gcc_compile(self):
+ self._run('$CC %s/test.c -o %s/test -lm' % (self.tc.sdk_dir, self.tc.sdk_dir))
+
+ def test_gpp_compile(self):
+ self._run('$CXX %s/test.c -o %s/test -lm' % (self.tc.sdk_dir, self.tc.sdk_dir))
+
+ def test_gpp2_compile(self):
+ self._run('$CXX %s/test.cpp -o %s/test -lm' % (self.tc.sdk_dir, self.tc.sdk_dir))
+
+ def test_make(self):
+ self._run('cd %s; make -f testsdkmakefile' % self.tc.sdk_dir)
+
+ @classmethod
+ def tearDownClass(self):
+ files = [os.path.join(self.tc.sdk_dir, f) \
+ for f in ['test.c', 'test.cpp', 'test.o', 'test',
+ 'testsdkmakefile']]
+ for f in files:
+ remove_safe(f)
diff --git a/meta/lib/oeqa/sdk/cases/perl.py b/meta/lib/oeqa/sdk/cases/perl.py
new file mode 100644
index 0000000000..8eab4442e8
--- /dev/null
+++ b/meta/lib/oeqa/sdk/cases/perl.py
@@ -0,0 +1,22 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
+import unittest
+from oeqa.sdk.case import OESDKTestCase
+
+from oeqa.utils.subprocesstweak import errors_have_output
+errors_have_output()
+
+class PerlTest(OESDKTestCase):
+ def setUp(self):
+ if not (self.tc.hasHostPackage("nativesdk-perl") or
+ self.tc.hasHostPackage("perl-native")):
+ raise unittest.SkipTest("No perl package in the SDK")
+
+ def test_perl(self):
+ cmd = "perl -e '$_=\"Uryyb, jbeyq\"; tr/a-zA-Z/n-za-mN-ZA-M/;print'"
+ output = self._run(cmd)
+ self.assertEqual(output, "Hello, world")
diff --git a/meta/lib/oeqa/sdk/cases/python.py b/meta/lib/oeqa/sdk/cases/python.py
new file mode 100644
index 0000000000..5ea992b9f3
--- /dev/null
+++ b/meta/lib/oeqa/sdk/cases/python.py
@@ -0,0 +1,22 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
+import subprocess, unittest
+from oeqa.sdk.case import OESDKTestCase
+
+from oeqa.utils.subprocesstweak import errors_have_output
+errors_have_output()
+
+class Python3Test(OESDKTestCase):
+ def setUp(self):
+ if not (self.tc.hasHostPackage("nativesdk-python3-core") or
+ self.tc.hasHostPackage("python3-core-native")):
+ raise unittest.SkipTest("No python3 package in the SDK")
+
+ def test_python3(self):
+ cmd = "python3 -c \"import codecs; print(codecs.encode('Uryyb, jbeyq', 'rot13'))\""
+ output = self._run(cmd)
+ self.assertEqual(output, "Hello, world\n")
diff --git a/meta/lib/oeqa/sdk/cases/rust.py b/meta/lib/oeqa/sdk/cases/rust.py
new file mode 100644
index 0000000000..31036f0f14
--- /dev/null
+++ b/meta/lib/oeqa/sdk/cases/rust.py
@@ -0,0 +1,35 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
+import os
+import shutil
+import unittest
+
+from oeqa.core.utils.path import remove_safe
+from oeqa.sdk.case import OESDKTestCase
+
+from oeqa.utils.subprocesstweak import errors_have_output
+errors_have_output()
+
+class RustCompileTest(OESDKTestCase):
+ td_vars = ['MACHINE']
+
+ @classmethod
+ def setUpClass(self):
+ targetdir = os.path.join(self.tc.sdk_dir, "hello")
+ try:
+ shutil.rmtree(targetdir)
+ except FileNotFoundError:
+ pass
+ shutil.copytree(os.path.join(self.tc.sdk_files_dir, "rust/hello"), targetdir)
+
+ def setUp(self):
+ machine = self.td.get("MACHINE")
+ if not self.tc.hasHostPackage("packagegroup-rust-cross-canadian-%s" % machine):
+ raise unittest.SkipTest("RustCompileTest class: SDK doesn't contain a Rust cross-canadian toolchain")
+
+ def test_cargo_build(self):
+ self._run('cd %s/hello; cargo build' % self.tc.sdk_dir)
diff --git a/meta/lib/oeqa/sdk/context.py b/meta/lib/oeqa/sdk/context.py
new file mode 100644
index 0000000000..01c38c24e6
--- /dev/null
+++ b/meta/lib/oeqa/sdk/context.py
@@ -0,0 +1,153 @@
+#
+# Copyright (C) 2016 Intel Corporation
+#
+# SPDX-License-Identifier: MIT
+#
+
+import os
+import sys
+import glob
+import re
+
+from oeqa.core.context import OETestContext, OETestContextExecutor
+
+class OESDKTestContext(OETestContext):
+ sdk_files_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "files")
+
+ def __init__(self, td=None, logger=None, sdk_dir=None, sdk_env=None,
+ target_pkg_manifest=None, host_pkg_manifest=None):
+ super(OESDKTestContext, self).__init__(td, logger)
+
+ self.sdk_dir = sdk_dir
+ self.sdk_env = sdk_env
+ self.target_pkg_manifest = target_pkg_manifest
+ self.host_pkg_manifest = host_pkg_manifest
+
+ def _hasPackage(self, manifest, pkg, regex=False):
+ if regex:
+ # do regex match
+ pat = re.compile(pkg)
+ for p in manifest.keys():
+ if pat.search(p):
+ return True
+ else:
+ # do exact match
+ if pkg in manifest.keys():
+ return True
+ return False
+
+ def hasHostPackage(self, pkg, regex=False):
+ return self._hasPackage(self.host_pkg_manifest, pkg, regex=regex)
+
+ def hasTargetPackage(self, pkg, multilib=False, regex=False):
+ if multilib:
+ # match multilib according to sdk_env
+ mls = self.td.get('MULTILIB_VARIANTS', '').split()
+ for ml in mls:
+ if ('ml'+ml) in self.sdk_env:
+ pkg = ml + '-' + pkg
+ return self._hasPackage(self.target_pkg_manifest, pkg, regex=regex)
+
+class OESDKTestContextExecutor(OETestContextExecutor):
+ _context_class = OESDKTestContext
+
+ name = 'sdk'
+ help = 'sdk test component'
+ description = 'executes sdk tests'
+
+ default_cases = [os.path.join(os.path.abspath(os.path.dirname(__file__)),
+ 'cases')]
+ default_test_data = None
+
+ def register_commands(self, logger, subparsers):
+ super(OESDKTestContextExecutor, self).register_commands(logger, subparsers)
+
+ sdk_group = self.parser.add_argument_group('sdk options')
+ sdk_group.add_argument('--sdk-env', action='store',
+ help='sdk environment')
+ sdk_group.add_argument('--target-manifest', action='store',
+ help='sdk target manifest')
+ sdk_group.add_argument('--host-manifest', action='store',
+ help='sdk host manifest')
+
+ sdk_dgroup = self.parser.add_argument_group('sdk display options')
+ sdk_dgroup.add_argument('--list-sdk-env', action='store_true',
+ default=False, help='sdk list available environment')
+
+ # XXX this option is required but argparse_oe has a bug handling
+ # required options, seems that don't keep track of already parsed
+ # options
+ sdk_rgroup = self.parser.add_argument_group('sdk required options')
+ sdk_rgroup.add_argument('--sdk-dir', required=False, action='store',
+ help='sdk installed directory')
+
+ self.parser.add_argument('-j', '--num-processes', dest='processes', action='store',
+ type=int, help="number of processes to execute in parallel with")
+
+ @staticmethod
+ def _load_manifest(manifest):
+ pkg_manifest = {}
+ if manifest:
+ with open(manifest) as f:
+ for line in f:
+ (pkg, arch, version) = line.strip().split()
+ pkg_manifest[pkg] = (version, arch)
+
+ return pkg_manifest
+
+ def _process_args(self, logger, args):
+ super(OESDKTestContextExecutor, self)._process_args(logger, args)
+
+ self.tc_kwargs['init']['sdk_dir'] = args.sdk_dir
+ self.tc_kwargs['init']['sdk_env'] = self.sdk_env
+ self.tc_kwargs['init']['target_pkg_manifest'] = \
+ OESDKTestContextExecutor._load_manifest(args.target_manifest)
+ self.tc_kwargs['init']['host_pkg_manifest'] = \
+ OESDKTestContextExecutor._load_manifest(args.host_manifest)
+ self.tc_kwargs['run']['processes'] = args.processes
+
+ @staticmethod
+ def _get_sdk_environs(sdk_dir):
+ sdk_env = {}
+
+ environ_pattern = sdk_dir + '/environment-setup-*'
+ full_sdk_env = glob.glob(sdk_dir + '/environment-setup-*')
+ for env in full_sdk_env:
+ m = re.search('environment-setup-(.*)', env)
+ if m:
+ sdk_env[m.group(1)] = env
+
+ return sdk_env
+
+ def _display_sdk_envs(self, log, args, sdk_envs):
+ log("Available SDK environments at directory %s:" \
+ % args.sdk_dir)
+ log("")
+ for env in sdk_envs:
+ log(env)
+
+ def run(self, logger, args):
+ import argparse_oe
+
+ if not args.sdk_dir:
+ raise argparse_oe.ArgumentUsageError("No SDK directory "\
+ "specified please do, --sdk-dir SDK_DIR", self.name)
+
+ sdk_envs = OESDKTestContextExecutor._get_sdk_environs(args.sdk_dir)
+ if not sdk_envs:
+ raise argparse_oe.ArgumentUsageError("No available SDK "\
+ "environments found at %s" % args.sdk_dir, self.name)
+
+ if args.list_sdk_env:
+ self._display_sdk_envs(logger.info, args, sdk_envs)
+ sys.exit(0)
+
+ if not args.sdk_env in sdk_envs:
+ self._display_sdk_envs(logger.error, args, sdk_envs)
+ raise argparse_oe.ArgumentUsageError("No valid SDK "\
+ "environment (%s) specified" % args.sdk_env, self.name)
+
+ self.sdk_env = sdk_envs[args.sdk_env]
+ return super(OESDKTestContextExecutor, self).run(logger, args)
+
+_executor_class = OESDKTestContextExecutor
diff --git a/meta/lib/oeqa/sdk/files/rust/hello/Cargo.toml b/meta/lib/oeqa/sdk/files/rust/hello/Cargo.toml
new file mode 100644
index 0000000000..fe619478a6
--- /dev/null
+++ b/meta/lib/oeqa/sdk/files/rust/hello/Cargo.toml
@@ -0,0 +1,6 @@
+[package]
+name = "hello"
+version = "0.1.0"
+edition = "2021"
+
+[dependencies]
diff --git a/meta/lib/oeqa/sdk/files/rust/hello/build.rs b/meta/lib/oeqa/sdk/files/rust/hello/build.rs
new file mode 100644
index 0000000000..b1a533d5df
--- /dev/null
+++ b/meta/lib/oeqa/sdk/files/rust/hello/build.rs
@@ -0,0 +1,3 @@
+/* This is the simplest build script just to invoke host compiler
+ in the build process. */
+fn main() {}
diff --git a/meta/lib/oeqa/sdk/files/rust/hello/src/main.rs b/meta/lib/oeqa/sdk/files/rust/hello/src/main.rs
new file mode 100644
index 0000000000..a06c03f82a
--- /dev/null
+++ b/meta/lib/oeqa/sdk/files/rust/hello/src/main.rs
@@ -0,0 +1,3 @@
+fn main() {
+ println!("Hello, OpenEmbedded world!");
+}
diff --git a/meta/lib/oeqa/runtime/files/testsdkmakefile b/meta/lib/oeqa/sdk/files/testsdkmakefile
index fb05f822f3..fb05f822f3 100644
--- a/meta/lib/oeqa/runtime/files/testsdkmakefile
+++ b/meta/lib/oeqa/sdk/files/testsdkmakefile
diff --git a/meta/lib/oeqa/sdk/gcc.py b/meta/lib/oeqa/sdk/gcc.py
deleted file mode 100644
index 8395b9b908..0000000000
--- a/meta/lib/oeqa/sdk/gcc.py
+++ /dev/null
@@ -1,36 +0,0 @@
-import unittest
-import os
-import shutil
-from oeqa.oetest import oeSDKTest, skipModule
-from oeqa.utils.decorators import *
-
-def setUpModule():
- machine = oeSDKTest.tc.d.getVar("MACHINE", True)
- if not oeSDKTest.hasHostPackage("packagegroup-cross-canadian-" + machine):
- skipModule("SDK doesn't contain a cross-canadian toolchain")
-
-
-class GccCompileTest(oeSDKTest):
-
- @classmethod
- def setUpClass(self):
- for f in ['test.c', 'test.cpp', 'testsdkmakefile']:
- shutil.copyfile(os.path.join(self.tc.filesdir, f), self.tc.sdktestdir + f)
-
- def test_gcc_compile(self):
- self._run('$CC %s/test.c -o %s/test -lm' % (self.tc.sdktestdir, self.tc.sdktestdir))
-
- def test_gpp_compile(self):
- self._run('$CXX %s/test.c -o %s/test -lm' % (self.tc.sdktestdir, self.tc.sdktestdir))
-
- def test_gpp2_compile(self):
- self._run('$CXX %s/test.cpp -o %s/test -lm' % (self.tc.sdktestdir, self.tc.sdktestdir))
-
- def test_make(self):
- self._run('cd %s; make -f testsdkmakefile' % self.tc.sdktestdir)
-
- @classmethod
- def tearDownClass(self):
- files = [self.tc.sdktestdir + f for f in ['test.c', 'test.cpp', 'test.o', 'test', 'testsdkmakefile']]
- for f in files:
- bb.utils.remove(f)
diff --git a/meta/lib/oeqa/sdk/perl.py b/meta/lib/oeqa/sdk/perl.py
deleted file mode 100644
index 45f422ef0b..0000000000
--- a/meta/lib/oeqa/sdk/perl.py
+++ /dev/null
@@ -1,28 +0,0 @@
-import unittest
-import os
-import shutil
-from oeqa.oetest import oeSDKTest, skipModule
-from oeqa.utils.decorators import *
-
-def setUpModule():
- if not oeSDKTest.hasHostPackage("nativesdk-perl"):
- skipModule("No perl package in the SDK")
-
-
-class PerlTest(oeSDKTest):
-
- @classmethod
- def setUpClass(self):
- for f in ['test.pl']:
- shutil.copyfile(os.path.join(self.tc.filesdir, f), self.tc.sdktestdir + f)
- self.testfile = self.tc.sdktestdir + "test.pl"
-
- def test_perl_exists(self):
- self._run('which perl')
-
- def test_perl_works(self):
- self._run('perl %s/test.pl' % self.tc.sdktestdir)
-
- @classmethod
- def tearDownClass(self):
- bb.utils.remove("%s/test.pl" % self.tc.sdktestdir)
diff --git a/meta/lib/oeqa/sdk/python.py b/meta/lib/oeqa/sdk/python.py
deleted file mode 100644
index 896fab4dfb..0000000000
--- a/meta/lib/oeqa/sdk/python.py
+++ /dev/null
@@ -1,32 +0,0 @@
-import unittest
-import os
-import shutil
-from oeqa.oetest import oeSDKTest, skipModule
-from oeqa.utils.decorators import *
-
-def setUpModule():
- if not oeSDKTest.hasHostPackage("nativesdk-python"):
- skipModule("No python package in the SDK")
-
-
-class PythonTest(oeSDKTest):
-
- @classmethod
- def setUpClass(self):
- for f in ['test.py']:
- shutil.copyfile(os.path.join(self.tc.filesdir, f), self.tc.sdktestdir + f)
-
- def test_python_exists(self):
- self._run('which python')
-
- def test_python_stdout(self):
- output = self._run('python %s/test.py' % self.tc.sdktestdir)
- self.assertEqual(output.strip(), "the value of a is 0.01", msg="Incorrect output: %s" % output)
-
- def test_python_testfile(self):
- self._run('ls /tmp/testfile.python')
-
- @classmethod
- def tearDownClass(self):
- bb.utils.remove("%s/test.py" % self.tc.sdktestdir)
- bb.utils.remove("/tmp/testfile.python")
diff --git a/meta/lib/oeqa/sdk/testmetaidesupport.py b/meta/lib/oeqa/sdk/testmetaidesupport.py
new file mode 100644
index 0000000000..00ef30e82e
--- /dev/null
+++ b/meta/lib/oeqa/sdk/testmetaidesupport.py
@@ -0,0 +1,45 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
+class TestSDK(object):
+ def run(self, d):
+ import json
+ import logging
+ from oeqa.sdk.context import OESDKTestContext, OESDKTestContextExecutor
+ from oeqa.utils import make_logger_bitbake_compatible
+
+ pn = d.getVar("PN")
+
+ logger = make_logger_bitbake_compatible(logging.getLogger("BitBake"))
+
+ sdk_dir = d.expand("${WORKDIR}/testsdk/")
+ bb.utils.remove(sdk_dir, True)
+ bb.utils.mkdirhier(sdk_dir)
+
+ sdk_envs = OESDKTestContextExecutor._get_sdk_environs(d.getVar("DEPLOY_DIR_IMAGE"))
+ tdname = d.expand("${DEPLOY_DIR_IMAGE}/${PN}.testdata.json")
+ test_data = json.load(open(tdname, "r"))
+
+ host_pkg_manifest = {"cmake-native":"", "gcc-cross":"", "gettext-native":"", "meson-native":"", "perl-native":"", "python3-core-native":"", }
+ target_pkg_manifest = {"gtk+3":""}
+
+ for s in sdk_envs:
+ bb.plain("meta-ide-support based SDK testing environment: %s" % s)
+
+ sdk_env = sdk_envs[s]
+
+ tc = OESDKTestContext(td=test_data, logger=logger, sdk_dir=sdk_dir,
+ sdk_env=sdk_env, target_pkg_manifest=target_pkg_manifest,
+ host_pkg_manifest=host_pkg_manifest)
+
+ tc.loadTests(OESDKTestContextExecutor.default_cases)
+
+ results = tc.runTests()
+ if results:
+ results.logSummary(pn)
+
+ if (not results) or (not results.wasSuccessful()):
+ bb.fatal('%s - FAILED' % (pn,), forcelog=True)
diff --git a/meta/lib/oeqa/sdk/testsdk.py b/meta/lib/oeqa/sdk/testsdk.py
new file mode 100644
index 0000000000..35e40187bc
--- /dev/null
+++ b/meta/lib/oeqa/sdk/testsdk.py
@@ -0,0 +1,145 @@
+#
+# Copyright 2018 by Garmin Ltd. or its subsidiaries
+#
+# SPDX-License-Identifier: MIT
+#
+
+from oeqa.sdk.context import OESDKTestContext, OESDKTestContextExecutor
+
+class TestSDKBase(object):
+ @staticmethod
+ def get_sdk_configuration(d, test_type):
+ import platform
+ import oe.lsb
+ from oeqa.utils.metadata import get_layers
+ configuration = {'TEST_TYPE': test_type,
+ 'MACHINE': d.getVar("MACHINE"),
+ 'SDKMACHINE': d.getVar("SDKMACHINE"),
+ 'IMAGE_BASENAME': d.getVar("IMAGE_BASENAME"),
+ 'IMAGE_PKGTYPE': d.getVar("IMAGE_PKGTYPE"),
+ 'STARTTIME': d.getVar("DATETIME"),
+ 'HOST_DISTRO': oe.lsb.distro_identifier().replace(' ', '-'),
+ 'LAYERS': get_layers(d.getVar("BBLAYERS"))}
+ return configuration
+
+ @staticmethod
+ def get_sdk_json_result_dir(d):
+ json_result_dir = os.path.join(d.getVar("LOG_DIR"), 'oeqa')
+ custom_json_result_dir = d.getVar("OEQA_JSON_RESULT_DIR")
+ if custom_json_result_dir:
+ json_result_dir = custom_json_result_dir
+ return json_result_dir
+
+ @staticmethod
+ def get_sdk_result_id(configuration):
+ return '%s_%s_%s_%s_%s' % (configuration['TEST_TYPE'], configuration['IMAGE_BASENAME'], configuration['SDKMACHINE'], configuration['MACHINE'], configuration['STARTTIME'])
+
+class TestSDK(TestSDKBase):
+ context_executor_class = OESDKTestContextExecutor
+ context_class = OESDKTestContext
+ test_type = 'sdk'
+
+ def get_tcname(self, d):
+ """
+ Get the name of the SDK file
+ """
+ return d.expand("${SDK_DEPLOY}/${TOOLCHAIN_OUTPUTNAME}.sh")
+
+ def extract_sdk(self, tcname, sdk_dir, d):
+ """
+ Extract the SDK to the specified location
+ """
+ import subprocess
+
+ try:
+ subprocess.check_output("cd %s; %s <<EOF\n./\nY\nEOF" % (sdk_dir, tcname), shell=True)
+ except subprocess.CalledProcessError as e:
+ bb.fatal("Couldn't install the SDK:\n%s" % e.output.decode("utf-8"))
+
+ def setup_context(self, d):
+ """
+ Return a dictionary of additional arguments that should be passed to
+ the context_class on construction
+ """
+ return dict()
+
+ def run(self, d):
+
+ import os
+ import subprocess
+ import json
+ import logging
+
+ from bb.utils import export_proxies
+ from oeqa.utils import make_logger_bitbake_compatible
+
+ pn = d.getVar("PN")
+ logger = make_logger_bitbake_compatible(logging.getLogger("BitBake"))
+
+ # sdk use network for download projects for build
+ export_proxies(d)
+
+ tcname = self.get_tcname(d)
+
+ if not os.path.exists(tcname):
+ bb.fatal("The toolchain %s is not built. Build it before running the tests: 'bitbake <image> -c populate_sdk' ." % tcname)
+
+ tdname = d.expand("${SDK_DEPLOY}/${TOOLCHAIN_OUTPUTNAME}.testdata.json")
+ test_data = json.load(open(tdname, "r"))
+
+ target_pkg_manifest = self.context_executor_class._load_manifest(
+ d.expand("${SDK_DEPLOY}/${TOOLCHAIN_OUTPUTNAME}.target.manifest"))
+ host_pkg_manifest = self.context_executor_class._load_manifest(
+ d.expand("${SDK_DEPLOY}/${TOOLCHAIN_OUTPUTNAME}.host.manifest"))
+
+ processes = d.getVar("TESTIMAGE_NUMBER_THREADS") or d.getVar("BB_NUMBER_THREADS")
+ if processes:
+ try:
+ import testtools, subunit
+ except ImportError:
+ bb.warn("Failed to import testtools or subunit, the testcases will run serially")
+ processes = None
+
+ sdk_dir = d.expand("${WORKDIR}/testimage-sdk/")
+ bb.utils.remove(sdk_dir, True)
+ bb.utils.mkdirhier(sdk_dir)
+
+ context_args = self.setup_context(d)
+
+ self.extract_sdk(tcname, sdk_dir, d)
+
+ fail = False
+ sdk_envs = self.context_executor_class._get_sdk_environs(sdk_dir)
+ for s in sdk_envs:
+ sdk_env = sdk_envs[s]
+ bb.plain("SDK testing environment: %s" % s)
+ tc = self.context_class(td=test_data, logger=logger, sdk_dir=sdk_dir,
+ sdk_env=sdk_env, target_pkg_manifest=target_pkg_manifest,
+ host_pkg_manifest=host_pkg_manifest, **context_args)
+
+ try:
+ tc.loadTests(self.context_executor_class.default_cases)
+ except Exception as e:
+ import traceback
+ bb.fatal("Loading tests failed:\n%s" % traceback.format_exc())
+
+ if processes:
+ result = tc.runTests(processes=int(processes))
+ else:
+ result = tc.runTests()
+
+ component = "%s %s" % (pn, self.context_executor_class.name)
+ context_msg = "%s:%s" % (os.path.basename(tcname), os.path.basename(sdk_env))
+ configuration = self.get_sdk_configuration(d, self.test_type)
+ result.logDetails(self.get_sdk_json_result_dir(d),
+ configuration,
+ self.get_sdk_result_id(configuration))
+ result.logSummary(component, context_msg)
+
+ if not result.wasSuccessful():
+ fail = True
+
+ if fail:
+ bb.fatal("%s - FAILED - check the task log and the commands log" % pn)
+
+
diff --git a/meta/lib/oeqa/sdk/utils/__init__.py b/meta/lib/oeqa/sdk/utils/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/meta/lib/oeqa/sdk/utils/__init__.py
diff --git a/meta/lib/oeqa/sdk/utils/sdkbuildproject.py b/meta/lib/oeqa/sdk/utils/sdkbuildproject.py
new file mode 100644
index 0000000000..32f5e3310d
--- /dev/null
+++ b/meta/lib/oeqa/sdk/utils/sdkbuildproject.py
@@ -0,0 +1,53 @@
+#
+# Copyright (C) 2016 Intel Corporation
+#
+# SPDX-License-Identifier: MIT
+#
+
+import os
+import subprocess
+
+from oeqa.utils.buildproject import BuildProject
+
+class SDKBuildProject(BuildProject):
+ def __init__(self, testpath, sdkenv, uri, testlogdir, builddatetime,
+ foldername=None, dl_dir=None):
+ self.sdkenv = sdkenv
+ self.testdir = testpath
+ self.targetdir = testpath
+ os.makedirs(testpath, exist_ok=True)
+ self.datetime = builddatetime
+ self.testlogdir = testlogdir
+ os.makedirs(self.testlogdir, exist_ok=True)
+ self.logfile = os.path.join(self.testlogdir, "sdk_target_log.%s" % self.datetime)
+ BuildProject.__init__(self, uri, foldername, tmpdir=testpath, dl_dir=dl_dir)
+
+ def download_archive(self):
+ self._download_archive()
+
+ cmd = 'tar xf %s -C %s' % (os.path.join(self.targetdir, self.archive), self.targetdir)
+ subprocess.check_output(cmd, shell=True)
+
+ #Change targetdir to project folder
+ self.targetdir = os.path.join(self.targetdir, self.fname)
+
+ def run_configure(self, configure_args='', extra_cmds=''):
+ return super(SDKBuildProject, self).run_configure(configure_args=(configure_args or '$CONFIGURE_FLAGS'), extra_cmds=extra_cmds)
+
+ def run_install(self, install_args=''):
+ return super(SDKBuildProject, self).run_install(install_args=(install_args or "DESTDIR=%s/../install" % self.targetdir))
+
+ def log(self, msg):
+ if self.logfile:
+ with open(self.logfile, "a") as f:
+ f.write("%s\n" % msg)
+
+ def _run(self, cmd):
+ self.log("Running . %s; " % self.sdkenv + cmd)
+ try:
+ output = subprocess.check_output(". %s; " % self.sdkenv + cmd, shell=True,
+ executable='/bin/bash', stderr=subprocess.STDOUT)
+ except subprocess.CalledProcessError as exc:
+ print(exc.output.decode('utf-8'))
+ return exc.returncode
+ return 0
diff --git a/meta/lib/oeqa/sdkext/__init__.py b/meta/lib/oeqa/sdkext/__init__.py
index 4cf3fa76b6..e69de29bb2 100644
--- a/meta/lib/oeqa/sdkext/__init__.py
+++ b/meta/lib/oeqa/sdkext/__init__.py
@@ -1,3 +0,0 @@
-# Enable other layers to have tests in the same named directory
-from pkgutil import extend_path
-__path__ = extend_path(__path__, __name__)
diff --git a/meta/lib/oeqa/sdkext/case.py b/meta/lib/oeqa/sdkext/case.py
new file mode 100644
index 0000000000..668faec9b9
--- /dev/null
+++ b/meta/lib/oeqa/sdkext/case.py
@@ -0,0 +1,24 @@
+#
+# Copyright (C) 2016 Intel Corporation
+#
+# SPDX-License-Identifier: MIT
+#
+
+import os
+import subprocess
+
+from oeqa.utils import avoid_paths_in_environ
+from oeqa.sdk.case import OESDKTestCase
+
+class OESDKExtTestCase(OESDKTestCase):
+ def _run(self, cmd):
+ # extensible sdk shows a warning if found bitbake in the path
+ # because can cause contamination, i.e. use devtool from
+ # poky/scripts instead of eSDK one.
+ env = os.environ.copy()
+ paths_to_avoid = ['bitbake/bin', 'poky/scripts']
+ env['PATH'] = avoid_paths_in_environ(paths_to_avoid)
+
+ return subprocess.check_output(". %s > /dev/null;"\
+ " %s;" % (self.tc.sdk_env, cmd), stderr=subprocess.STDOUT,
+ shell=True, env=env, universal_newlines=True)
diff --git a/meta/lib/oeqa/sdkext/cases/devtool.py b/meta/lib/oeqa/sdkext/cases/devtool.py
new file mode 100644
index 0000000000..5ffb732556
--- /dev/null
+++ b/meta/lib/oeqa/sdkext/cases/devtool.py
@@ -0,0 +1,126 @@
+#
+# Copyright (C) 2016 Intel Corporation
+#
+# SPDX-License-Identifier: MIT
+#
+
+import os
+import shutil
+import subprocess
+
+from oeqa.sdkext.case import OESDKExtTestCase
+from oeqa.utils.httpserver import HTTPService
+
+from oeqa.utils.subprocesstweak import errors_have_output
+errors_have_output()
+
+class DevtoolTest(OESDKExtTestCase):
+ @classmethod
+ def setUpClass(cls):
+ myapp_src = os.path.join(cls.tc.esdk_files_dir, "myapp")
+ cls.myapp_dst = os.path.join(cls.tc.sdk_dir, "myapp")
+ shutil.copytree(myapp_src, cls.myapp_dst)
+ subprocess.check_output(['git', 'init', '.'], cwd=cls.myapp_dst)
+ subprocess.check_output(['git', 'add', '.'], cwd=cls.myapp_dst)
+ subprocess.check_output(['git', 'commit', '-m', "'test commit'"], cwd=cls.myapp_dst)
+
+ myapp_cmake_src = os.path.join(cls.tc.esdk_files_dir, "myapp_cmake")
+ cls.myapp_cmake_dst = os.path.join(cls.tc.sdk_dir, "myapp_cmake")
+ shutil.copytree(myapp_cmake_src, cls.myapp_cmake_dst)
+ subprocess.check_output(['git', 'init', '.'], cwd=cls.myapp_cmake_dst)
+ subprocess.check_output(['git', 'add', '.'], cwd=cls.myapp_cmake_dst)
+ subprocess.check_output(['git', 'commit', '-m', "'test commit'"], cwd=cls.myapp_cmake_dst)
+
+ @classmethod
+ def tearDownClass(cls):
+ shutil.rmtree(cls.myapp_dst)
+ shutil.rmtree(cls.myapp_cmake_dst)
+
+ def _test_devtool_build(self, directory):
+ self._run('devtool add myapp %s' % directory)
+ try:
+ self._run('devtool build myapp')
+ finally:
+ self._run('devtool reset myapp')
+
+ def _test_devtool_build_package(self, directory):
+ self._run('devtool add myapp %s' % directory)
+ try:
+ self._run('devtool package myapp')
+ finally:
+ self._run('devtool reset myapp')
+
+ def test_devtool_location(self):
+ output = self._run('which devtool')
+ self.assertEqual(output.startswith(self.tc.sdk_dir), True, \
+ msg="Seems that devtool isn't the eSDK one: %s" % output)
+
+ def test_devtool_add_reset(self):
+ self._run('devtool add myapp %s' % self.myapp_dst)
+ self._run('devtool reset myapp')
+
+ def test_devtool_build_make(self):
+ self._test_devtool_build(self.myapp_dst)
+
+ def test_devtool_build_esdk_package(self):
+ self._test_devtool_build_package(self.myapp_dst)
+
+ def test_devtool_build_cmake(self):
+ self._test_devtool_build(self.myapp_cmake_dst)
+
+ def test_extend_autotools_recipe_creation(self):
+ req = 'https://github.com/rdfa/librdfa'
+ recipe = "librdfa"
+ self._run('devtool sdk-install libxml2')
+ self._run('devtool add %s %s' % (recipe, req) )
+ try:
+ self._run('devtool build %s' % recipe)
+ finally:
+ self._run('devtool reset %s' % recipe)
+
+ def test_devtool_kernelmodule(self):
+ docfile = 'https://git.yoctoproject.org/git/kernel-module-hello-world'
+ recipe = 'kernel-module-hello-world'
+ self._run('devtool add %s %s' % (recipe, docfile) )
+ try:
+ self._run('devtool build %s' % recipe)
+ finally:
+ self._run('devtool reset %s' % recipe)
+
+ def test_recipes_for_nodejs(self):
+ package_nodejs = "npm://registry.npmjs.org;name=winston;version=2.2.0"
+ self._run('devtool add %s ' % package_nodejs)
+ try:
+ self._run('devtool build %s ' % package_nodejs)
+ finally:
+ self._run('devtool reset %s '% package_nodejs)
+
+class SdkUpdateTest(OESDKExtTestCase):
+ @classmethod
+ def setUpClass(self):
+ self.publish_dir = os.path.join(self.tc.sdk_dir, 'esdk_publish')
+ if os.path.exists(self.publish_dir):
+ shutil.rmtree(self.publish_dir)
+ os.mkdir(self.publish_dir)
+
+ base_tcname = "%s/%s" % (self.td.get("SDK_DEPLOY", ''),
+ self.td.get("TOOLCHAINEXT_OUTPUTNAME", ''))
+ tcname_new = "%s-new.sh" % base_tcname
+ if not os.path.exists(tcname_new):
+ tcname_new = "%s.sh" % base_tcname
+
+ cmd = 'oe-publish-sdk %s %s' % (tcname_new, self.publish_dir)
+ subprocess.check_output(cmd, shell=True)
+
+ self.http_service = HTTPService(self.publish_dir, logger=self.logger)
+ self.http_service.start()
+
+ self.http_url = "http://127.0.0.1:%d" % self.http_service.port
+
+ def test_sdk_update_http(self):
+ output = self._run("devtool sdk-update \"%s\"" % self.http_url)
+
+ @classmethod
+ def tearDownClass(self):
+ self.http_service.stop()
+ shutil.rmtree(self.publish_dir)
diff --git a/meta/lib/oeqa/sdkext/context.py b/meta/lib/oeqa/sdkext/context.py
new file mode 100644
index 0000000000..2ac2bf6ff7
--- /dev/null
+++ b/meta/lib/oeqa/sdkext/context.py
@@ -0,0 +1,32 @@
+#
+# Copyright (C) 2016 Intel Corporation
+#
+# SPDX-License-Identifier: MIT
+#
+
+import os
+from oeqa.sdk.context import OESDKTestContext, OESDKTestContextExecutor
+
+class OESDKExtTestContext(OESDKTestContext):
+ esdk_files_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "files")
+
+ # FIXME - We really need to do better mapping of names here, this at
+ # least allows some tests to run
+ def hasHostPackage(self, pkg):
+ # We force a toolchain to be installed into the eSDK even if its minimal
+ if pkg.startswith("packagegroup-cross-canadian-"):
+ return True
+ return self._hasPackage(self.host_pkg_manifest, pkg)
+
+class OESDKExtTestContextExecutor(OESDKTestContextExecutor):
+ _context_class = OESDKExtTestContext
+
+ name = 'esdk'
+ help = 'esdk test component'
+ description = 'executes esdk tests'
+
+ default_cases = OESDKTestContextExecutor.default_cases + \
+ [os.path.join(os.path.abspath(os.path.dirname(__file__)), 'cases')]
+ default_test_data = None
+
+_executor_class = OESDKExtTestContextExecutor
diff --git a/meta/lib/oeqa/sdkext/devtool.py b/meta/lib/oeqa/sdkext/devtool.py
deleted file mode 100644
index c5bb3102a6..0000000000
--- a/meta/lib/oeqa/sdkext/devtool.py
+++ /dev/null
@@ -1,32 +0,0 @@
-import shutil
-
-from oeqa.oetest import oeSDKExtTest
-from oeqa.utils.decorators import *
-
-class DevtoolTest(oeSDKExtTest):
-
- @classmethod
- def setUpClass(self):
- self.myapp_src = os.path.join(self.tc.sdkextfilesdir, "myapp")
- self.myapp_dst = os.path.join(self.tc.sdktestdir, "myapp")
- shutil.copytree(self.myapp_src, self.myapp_dst)
-
- def test_devtool_location(self):
- output = self._run('which devtool')
- self.assertEqual(output.startswith(self.tc.sdktestdir), True, \
- msg="Seems that devtool isn't the eSDK one: %s" % output)
-
- @skipUnlessPassed('test_devtool_location')
- def test_devtool_add_reset(self):
- self._run('devtool add myapp %s' % self.myapp_dst)
- self._run('devtool reset myapp')
-
- @skipUnlessPassed('test_devtool_location')
- def test_devtool_build(self):
- self._run('devtool add myapp %s' % self.myapp_dst)
- self._run('devtool build myapp')
- self._run('devtool reset myapp')
-
- @classmethod
- def tearDownClass(self):
- shutil.rmtree(self.myapp_dst)
diff --git a/meta/lib/oeqa/sdkext/files/myapp_cmake/CMakeLists.txt b/meta/lib/oeqa/sdkext/files/myapp_cmake/CMakeLists.txt
new file mode 100644
index 0000000000..19d773dd63
--- /dev/null
+++ b/meta/lib/oeqa/sdkext/files/myapp_cmake/CMakeLists.txt
@@ -0,0 +1,11 @@
+cmake_minimum_required (VERSION 2.6)
+project (myapp)
+# The version number.
+set (myapp_VERSION_MAJOR 1)
+set (myapp_VERSION_MINOR 0)
+
+# add the executable
+add_executable (myapp myapp.c)
+
+install(TARGETS myapp
+ RUNTIME DESTINATION bin)
diff --git a/meta/lib/oeqa/sdkext/files/myapp_cmake/myapp.c b/meta/lib/oeqa/sdkext/files/myapp_cmake/myapp.c
new file mode 100644
index 0000000000..f0b63f03f3
--- /dev/null
+++ b/meta/lib/oeqa/sdkext/files/myapp_cmake/myapp.c
@@ -0,0 +1,9 @@
+#include <stdio.h>
+
+int
+main(int argc, char *argv[])
+{
+ printf("Hello world\n");
+
+ return 0;
+}
diff --git a/meta/lib/oeqa/sdkext/sdk_update.py b/meta/lib/oeqa/sdkext/sdk_update.py
deleted file mode 100644
index 2ade839c05..0000000000
--- a/meta/lib/oeqa/sdkext/sdk_update.py
+++ /dev/null
@@ -1,36 +0,0 @@
-import os
-import shutil
-import subprocess
-
-from oeqa.oetest import oeSDKExtTest
-from oeqa.utils.httpserver import HTTPService
-
-class SdkUpdateTest(oeSDKExtTest):
-
- @classmethod
- def setUpClass(self):
- self.publish_dir = os.path.join(self.tc.sdktestdir, 'esdk_publish')
- if os.path.exists(self.publish_dir):
- shutil.rmtree(self.publish_dir)
- os.mkdir(self.publish_dir)
-
- tcname_new = self.tc.d.expand(
- "${SDK_DEPLOY}/${TOOLCHAINEXT_OUTPUTNAME}-new.sh")
- if not os.path.exists(tcname_new):
- tcname_new = self.tc.tcname
-
- cmd = 'oe-publish-sdk %s %s' % (tcname_new, self.publish_dir)
- subprocess.check_output(cmd, shell=True)
-
- self.http_service = HTTPService(self.publish_dir)
- self.http_service.start()
-
- self.http_url = "http://127.0.0.1:%d" % self.http_service.port
-
- def test_sdk_update_http(self):
- output = self._run("devtool sdk-update \"%s\"" % self.http_url)
-
- @classmethod
- def tearDownClass(self):
- self.http_service.stop()
- shutil.rmtree(self.publish_dir)
diff --git a/meta/lib/oeqa/sdkext/testsdk.py b/meta/lib/oeqa/sdkext/testsdk.py
new file mode 100644
index 0000000000..159f0d135b
--- /dev/null
+++ b/meta/lib/oeqa/sdkext/testsdk.py
@@ -0,0 +1,107 @@
+#
+# Copyright 2018 by Garmin Ltd. or its subsidiaries
+#
+# SPDX-License-Identifier: MIT
+#
+
+from oeqa.sdk.testsdk import TestSDKBase
+
+class TestSDKExt(TestSDKBase):
+ def run(self, d):
+ import os
+ import json
+ import subprocess
+ import logging
+
+ from bb.utils import export_proxies
+ from oeqa.utils import avoid_paths_in_environ, make_logger_bitbake_compatible, subprocesstweak
+ from oeqa.sdkext.context import OESDKExtTestContext, OESDKExtTestContextExecutor
+
+ pn = d.getVar("PN")
+ logger = make_logger_bitbake_compatible(logging.getLogger("BitBake"))
+
+ # extensible sdk use network
+ export_proxies(d)
+
+ subprocesstweak.errors_have_output()
+
+ # We need the original PATH for testing the eSDK, not with our manipulations
+ os.environ['PATH'] = d.getVar("BB_ORIGENV", False).getVar("PATH")
+
+ tcname = d.expand("${SDK_DEPLOY}/${TOOLCHAINEXT_OUTPUTNAME}.sh")
+ if not os.path.exists(tcname):
+ bb.fatal("The toolchain ext %s is not built. Build it before running the" \
+ " tests: 'bitbake <image> -c populate_sdk_ext' ." % tcname)
+
+ tdname = d.expand("${SDK_DEPLOY}/${TOOLCHAINEXT_OUTPUTNAME}.testdata.json")
+ test_data = json.load(open(tdname, "r"))
+
+ target_pkg_manifest = OESDKExtTestContextExecutor._load_manifest(
+ d.expand("${SDK_DEPLOY}/${TOOLCHAINEXT_OUTPUTNAME}.target.manifest"))
+ host_pkg_manifest = OESDKExtTestContextExecutor._load_manifest(
+ d.expand("${SDK_DEPLOY}/${TOOLCHAINEXT_OUTPUTNAME}.host.manifest"))
+
+ sdk_dir = d.expand("${WORKDIR}/testsdkext/")
+ bb.utils.remove(sdk_dir, True)
+ bb.utils.mkdirhier(sdk_dir)
+ try:
+ subprocess.check_output("%s -y -d %s" % (tcname, sdk_dir), shell=True)
+ except subprocess.CalledProcessError as e:
+ msg = "Couldn't install the extensible SDK:\n%s" % e.output.decode("utf-8")
+ logfn = os.path.join(sdk_dir, 'preparing_build_system.log')
+ if os.path.exists(logfn):
+ msg += '\n\nContents of preparing_build_system.log:\n'
+ with open(logfn, 'r') as f:
+ for line in f:
+ msg += line
+ bb.fatal(msg)
+
+ fail = False
+ sdk_envs = OESDKExtTestContextExecutor._get_sdk_environs(sdk_dir)
+ for s in sdk_envs:
+ bb.plain("Extensible SDK testing environment: %s" % s)
+
+ sdk_env = sdk_envs[s]
+
+ # Use our own SSTATE_DIR and DL_DIR so that updates to the eSDK come from our sstate cache
+ # and we don't spend hours downloading kernels for the kernel module test
+ # Abuse auto.conf since local.conf would be overwritten by the SDK
+ with open(os.path.join(sdk_dir, 'conf', 'auto.conf'), 'a+') as f:
+ f.write('SSTATE_MIRRORS += "file://.* file://%s/PATH"\n' % test_data.get('SSTATE_DIR'))
+ f.write('SOURCE_MIRROR_URL = "file://%s"\n' % test_data.get('DL_DIR'))
+ f.write('INHERIT += "own-mirrors"\n')
+ f.write('PREMIRRORS:prepend = "git://git.yoctoproject.org/.* git://%s/git2/git.yoctoproject.org.BASENAME "\n' % test_data.get('DL_DIR'))
+
+ # We need to do this in case we have a minimal SDK
+ subprocess.check_output(". %s > /dev/null; devtool sdk-install meta-extsdk-toolchain" % \
+ sdk_env, cwd=sdk_dir, shell=True, stderr=subprocess.STDOUT)
+
+ tc = OESDKExtTestContext(td=test_data, logger=logger, sdk_dir=sdk_dir,
+ sdk_env=sdk_env, target_pkg_manifest=target_pkg_manifest,
+ host_pkg_manifest=host_pkg_manifest)
+
+ try:
+ tc.loadTests(OESDKExtTestContextExecutor.default_cases)
+ except Exception as e:
+ import traceback
+ bb.fatal("Loading tests failed:\n%s" % traceback.format_exc())
+
+ result = tc.runTests()
+
+ component = "%s %s" % (pn, OESDKExtTestContextExecutor.name)
+ context_msg = "%s:%s" % (os.path.basename(tcname), os.path.basename(sdk_env))
+ configuration = self.get_sdk_configuration(d, 'sdkext')
+ result.logDetails(self.get_sdk_json_result_dir(d),
+ configuration,
+ self.get_sdk_result_id(configuration))
+ result.logSummary(component, context_msg)
+
+ if not result.wasSuccessful():
+ fail = True
+
+ # Clean the workspace/sources to avoid `devtool add' failure because of non-empty source directory
+ bb.utils.remove(sdk_dir+'workspace/sources', True)
+
+ if fail:
+ bb.fatal("%s - FAILED - check the task log and the commands log" % pn)
+
diff --git a/meta/lib/oeqa/selftest/__init__.py b/meta/lib/oeqa/selftest/__init__.py
deleted file mode 100644
index 3ad9513f40..0000000000
--- a/meta/lib/oeqa/selftest/__init__.py
+++ /dev/null
@@ -1,2 +0,0 @@
-from pkgutil import extend_path
-__path__ = extend_path(__path__, __name__)
diff --git a/meta/lib/oeqa/selftest/_toaster.py b/meta/lib/oeqa/selftest/_toaster.py
deleted file mode 100644
index 15ea9df9ef..0000000000
--- a/meta/lib/oeqa/selftest/_toaster.py
+++ /dev/null
@@ -1,320 +0,0 @@
-import unittest
-import os
-import sys
-import shlex, subprocess
-import urllib.request, urllib.parse, urllib.error, subprocess, time, getpass, re, json, shlex
-
-import oeqa.utils.ftools as ftools
-from oeqa.selftest.base import oeSelfTest
-from oeqa.utils.commands import runCmd
-
-sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '../../../../', 'bitbake/lib/toaster')))
-os.environ.setdefault("DJANGO_SETTINGS_MODULE", "toastermain.settings")
-
-import toastermain.settings
-from django.db.models import Q
-from orm.models import *
-from oeqa.utils.decorators import testcase
-
-class ToasterSetup(oeSelfTest):
-
- def recipe_parse(self, file_path, var):
- for line in open(file_path,'r'):
- if line.find(var) > -1:
- val = line.split(" = ")[1].replace("\"", "").strip()
- return val
-
- def fix_file_path(self, file_path):
- if ":" in file_path:
- file_path=file_path.split(":")[2]
- return file_path
-
-class Toaster_DB_Tests(ToasterSetup):
-
- # Check if build name is unique - tc_id=795
- @testcase(795)
- def test_Build_Unique_Name(self):
- all_builds = Build.objects.all().count()
- distinct_builds = Build.objects.values('id').distinct().count()
- self.assertEqual(distinct_builds, all_builds, msg = 'Build name is not unique')
-
- # Check if build coocker log path is unique - tc_id=819
- @testcase(819)
- def test_Build_Unique_Cooker_Log_Path(self):
- distinct_path = Build.objects.values('cooker_log_path').distinct().count()
- total_builds = Build.objects.values('id').count()
- self.assertEqual(distinct_path, total_builds, msg = 'Build coocker log path is not unique')
-
- # Check if task order is unique for one build - tc=824
- @testcase(824)
- def test_Task_Unique_Order(self):
- builds = Build.objects.values('id')
- cnt_err = []
- for build in builds:
- total_task_order = Task.objects.filter(build = build['id']).values('order').count()
- distinct_task_order = Task.objects.filter(build = build['id']).values('order').distinct().count()
- if (total_task_order != distinct_task_order):
- cnt_err.append(build['id'])
- self.assertEqual(len(cnt_err), 0, msg = 'Errors for build id: %s' % cnt_err)
-
- # Check task order sequence for one build - tc=825
- @testcase(825)
- def test_Task_Order_Sequence(self):
- builds = builds = Build.objects.values('id')
- cnt_err = []
- for build in builds:
- tasks = Task.objects.filter(Q(build = build['id']), ~Q(order = None), ~Q(task_name__contains = '_setscene')).values('id', 'order').order_by("order")
- cnt_tasks = 0
- for task in tasks:
- cnt_tasks += 1
- if (task['order'] != cnt_tasks):
- cnt_err.append(task['id'])
- self.assertEqual(len(cnt_err), 0, msg = 'Errors for task id: %s' % cnt_err)
-
- # Check if disk_io matches the difference between EndTimeIO and StartTimeIO in build stats - tc=828
- ### this needs to be updated ###
- #def test_Task_Disk_IO_TC828(self):
-
- # Check if outcome = 2 (SSTATE) then sstate_result must be 3 (RESTORED) - tc=832
- @testcase(832)
- def test_Task_If_Outcome_2_Sstate_Result_Must_Be_3(self):
- tasks = Task.objects.filter(outcome = 2).values('id', 'sstate_result')
- cnt_err = []
- for task in tasks:
- if (row['sstate_result'] != 3):
- cnt_err.append(task['id'])
- self.assertEqual(len(cnt_err), 0, msg = 'Errors for task id: %s' % cnt_err)
-
- # Check if outcome = 1 (COVERED) or 3 (EXISTING) then sstate_result must be 0 (SSTATE_NA) - tc=833
- @testcase(833)
- def test_Task_If_Outcome_1_3_Sstate_Result_Must_Be_0(self):
- tasks = Task.objects.filter(outcome__in = (1, 3)).values('id', 'sstate_result')
- cnt_err = []
- for task in tasks:
- if (task['sstate_result'] != 0):
- cnt_err.append(task['id'])
- self.assertEqual(len(cnt_err), 0, msg = 'Errors for task id: %s' % cnt_err)
-
- # Check if outcome is 0 (SUCCESS) or 4 (FAILED) then sstate_result must be 0 (NA), 1 (MISS) or 2 (FAILED) - tc=834
- @testcase(834)
- def test_Task_If_Outcome_0_4_Sstate_Result_Must_Be_0_1_2(self):
- tasks = Task.objects.filter(outcome__in = (0, 4)).values('id', 'sstate_result')
- cnt_err = []
- for task in tasks:
- if (task['sstate_result'] not in [0, 1, 2]):
- cnt_err.append(task['id'])
- self.assertEqual(len(cnt_err), 0, msg = 'Errors for task id: %s' % cnt_err)
-
- # Check if task_executed = TRUE (1), script_type must be 0 (CODING_NA), 2 (CODING_PYTHON), 3 (CODING_SHELL) - tc=891
- @testcase(891)
- def test_Task_If_Task_Executed_True_Script_Type_0_2_3(self):
- tasks = Task.objects.filter(task_executed = 1).values('id', 'script_type')
- cnt_err = []
- for task in tasks:
- if (task['script_type'] not in [0, 2, 3]):
- cnt_err.append(task['id'])
- self.assertEqual(len(cnt_err), 0, msg = 'Errors for task id: %s' % cnt_err)
-
- # Check if task_executed = TRUE (1), outcome must be 0 (SUCCESS) or 4 (FAILED) - tc=836
- @testcase(836)
- def test_Task_If_Task_Executed_True_Outcome_0_4(self):
- tasks = Task.objects.filter(task_executed = 1).values('id', 'outcome')
- cnt_err = []
- for task in tasks:
- if (task['outcome'] not in [0, 4]):
- cnt_err.append(task['id'])
- self.assertEqual(len(cnt_err), 0, msg = 'Errors for task id: %s' % cnt_err)
-
- # Check if task_executed = FALSE (0), script_type must be 0 - tc=890
- @testcase(890)
- def test_Task_If_Task_Executed_False_Script_Type_0(self):
- tasks = Task.objects.filter(task_executed = 0).values('id', 'script_type')
- cnt_err = []
- for task in tasks:
- if (task['script_type'] != 0):
- cnt_err.append(task['id'])
- self.assertEqual(len(cnt_err), 0, msg = 'Errors for task id: %s' % cnt_err)
-
- # Check if task_executed = FALSE (0) and build outcome = SUCCEEDED (0), task outcome must be 1 (COVERED), 2 (CACHED), 3 (PREBUILT), 5 (EMPTY) - tc=837
- @testcase(837)
- def test_Task_If_Task_Executed_False_Outcome_1_2_3_5(self):
- builds = Build.objects.filter(outcome = 0).values('id')
- cnt_err = []
- for build in builds:
- tasks = Task.objects.filter(build = build['id'], task_executed = 0).values('id', 'outcome')
- for task in tasks:
- if (task['outcome'] not in [1, 2, 3, 5]):
- cnt_err.append(task['id'])
- self.assertEqual(len(cnt_err), 0, msg = 'Errors for task id: %s' % cnt_err)
-
- # Key verification - tc=888
- @testcase(888)
- def test_Target_Installed_Package(self):
- rows = Target_Installed_Package.objects.values('id', 'target_id', 'package_id')
- cnt_err = []
- for row in rows:
- target = Target.objects.filter(id = row['target_id']).values('id')
- package = Package.objects.filter(id = row['package_id']).values('id')
- if (not target or not package):
- cnt_err.append(row['id'])
- self.assertEqual(len(cnt_err), 0, msg = 'Errors for target installed package id: %s' % cnt_err)
-
- # Key verification - tc=889
- @testcase(889)
- def test_Task_Dependency(self):
- rows = Task_Dependency.objects.values('id', 'task_id', 'depends_on_id')
- cnt_err = []
- for row in rows:
- task_id = Task.objects.filter(id = row['task_id']).values('id')
- depends_on_id = Task.objects.filter(id = row['depends_on_id']).values('id')
- if (not task_id or not depends_on_id):
- cnt_err.append(row['id'])
- self.assertEqual(len(cnt_err), 0, msg = 'Errors for task dependency id: %s' % cnt_err)
-
- # Check if build target file_name is populated only if is_image=true AND orm_build.outcome=0 then if the file exists and its size matches the file_size value
- ### Need to add the tc in the test run
- @testcase(1037)
- def test_Target_File_Name_Populated(self):
- builds = Build.objects.filter(outcome = 0).values('id')
- for build in builds:
- targets = Target.objects.filter(build_id = build['id'], is_image = 1).values('id')
- for target in targets:
- target_files = Target_Image_File.objects.filter(target_id = target['id']).values('id', 'file_name', 'file_size')
- cnt_err = []
- for file_info in target_files:
- target_id = file_info['id']
- target_file_name = file_info['file_name']
- target_file_size = file_info['file_size']
- if (not target_file_name or not target_file_size):
- cnt_err.append(target_id)
- else:
- if (not os.path.exists(target_file_name)):
- cnt_err.append(target_id)
- else:
- if (os.path.getsize(target_file_name) != target_file_size):
- cnt_err.append(target_id)
- self.assertEqual(len(cnt_err), 0, msg = 'Errors for target image file id: %s' % cnt_err)
-
- # Key verification - tc=884
- @testcase(884)
- def test_Package_Dependency(self):
- cnt_err = []
- deps = Package_Dependency.objects.values('id', 'package_id', 'depends_on_id')
- for dep in deps:
- if (dep['package_id'] == dep['depends_on_id']):
- cnt_err.append(dep['id'])
- self.assertEqual(len(cnt_err), 0, msg = 'Errors for package dependency id: %s' % cnt_err)
-
- # Recipe key verification, recipe name does not depends on a recipe having the same name - tc=883
- @testcase(883)
- def test_Recipe_Dependency(self):
- deps = Recipe_Dependency.objects.values('id', 'recipe_id', 'depends_on_id')
- cnt_err = []
- for dep in deps:
- if (not dep['recipe_id'] or not dep['depends_on_id']):
- cnt_err.append(dep['id'])
- else:
- name = Recipe.objects.filter(id = dep['recipe_id']).values('name')
- dep_name = Recipe.objects.filter(id = dep['depends_on_id']).values('name')
- if (name == dep_name):
- cnt_err.append(dep['id'])
- self.assertEqual(len(cnt_err), 0, msg = 'Errors for recipe dependency id: %s' % cnt_err)
-
- # Check if package name does not start with a number (0-9) - tc=846
- @testcase(846)
- def test_Package_Name_For_Number(self):
- packages = Package.objects.filter(~Q(size = -1)).values('id', 'name')
- cnt_err = []
- for package in packages:
- if (package['name'][0].isdigit() is True):
- cnt_err.append(package['id'])
- self.assertEqual(len(cnt_err), 0, msg = 'Errors for package id: %s' % cnt_err)
-
- # Check if package version starts with a number (0-9) - tc=847
- @testcase(847)
- def test_Package_Version_Starts_With_Number(self):
- packages = Package.objects.filter(~Q(size = -1)).values('id', 'version')
- cnt_err = []
- for package in packages:
- if (package['version'][0].isdigit() is False):
- cnt_err.append(package['id'])
- self.assertEqual(len(cnt_err), 0, msg = 'Errors for package id: %s' % cnt_err)
-
- # Check if package revision starts with 'r' - tc=848
- @testcase(848)
- def test_Package_Revision_Starts_With_r(self):
- packages = Package.objects.filter(~Q(size = -1)).values('id', 'revision')
- cnt_err = []
- for package in packages:
- if (package['revision'][0].startswith("r") is False):
- cnt_err.append(package['id'])
- self.assertEqual(len(cnt_err), 0, msg = 'Errors for package id: %s' % cnt_err)
-
- # Check the validity of the package build_id
- ### TC must be added in test run
- @testcase(1038)
- def test_Package_Build_Id(self):
- packages = Package.objects.filter(~Q(size = -1)).values('id', 'build_id')
- cnt_err = []
- for package in packages:
- build_id = Build.objects.filter(id = package['build_id']).values('id')
- if (not build_id):
- cnt_err.append(package['id'])
- self.assertEqual(len(cnt_err), 0, msg = 'Errors for package id: %s' % cnt_err)
-
- # Check the validity of package recipe_id
- ### TC must be added in test run
- @testcase(1039)
- def test_Package_Recipe_Id(self):
- packages = Package.objects.filter(~Q(size = -1)).values('id', 'recipe_id')
- cnt_err = []
- for package in packages:
- recipe_id = Recipe.objects.filter(id = package['recipe_id']).values('id')
- if (not recipe_id):
- cnt_err.append(package['id'])
- self.assertEqual(len(cnt_err), 0, msg = 'Errors for package id: %s' % cnt_err)
-
- # Check if package installed_size field is not null
- ### TC must be aded in test run
- @testcase(1040)
- def test_Package_Installed_Size_Not_NULL(self):
- packages = Package.objects.filter(installed_size__isnull = True).values('id')
- cnt_err = []
- for package in packages:
- cnt_err.append(package['id'])
- self.assertEqual(len(cnt_err), 0, msg = 'Errors for package id: %s' % cnt_err)
-
- # Check if all layers requests return exit code is 200 - tc=843
- @testcase(843)
- def test_Layers_Requests_Exit_Code(self):
- layers = Layer.objects.values('id', 'layer_index_url')
- cnt_err = []
- for layer in layers:
- resp = urllib.request.urlopen(layer['layer_index_url'])
- if (resp.getcode() != 200):
- cnt_err.append(layer['id'])
- self.assertEqual(len(cnt_err), 0, msg = 'Errors for layer id: %s' % cnt_err)
-
- # Check if django server starts regardless of the timezone set on the machine - tc=905
- @testcase(905)
- def test_Start_Django_Timezone(self):
- current_path = os.getcwd()
- zonefilelist = []
- ZONEINFOPATH = '/usr/share/zoneinfo/'
- os.chdir("../bitbake/lib/toaster/")
- cnt_err = 0
- for filename in os.listdir(ZONEINFOPATH):
- if os.path.isfile(os.path.join(ZONEINFOPATH, filename)):
- zonefilelist.append(filename)
- for k in range(len(zonefilelist)):
- if k <= 5:
- files = zonefilelist[k]
- os.system("export TZ="+str(files)+"; python manage.py runserver > /dev/null 2>&1 &")
- time.sleep(3)
- pid = subprocess.check_output("ps aux | grep '[/u]sr/bin/python manage.py runserver' | awk '{print $2}'", shell = True)
- if pid:
- os.system("kill -9 "+str(pid))
- else:
- cnt_err.append(zonefilelist[k])
- self.assertEqual(cnt_err, 0, msg = 'Errors django server does not start with timezone: %s' % cnt_err)
- os.chdir(current_path)
diff --git a/meta/lib/oeqa/selftest/archiver.py b/meta/lib/oeqa/selftest/archiver.py
deleted file mode 100644
index f2030c446d..0000000000
--- a/meta/lib/oeqa/selftest/archiver.py
+++ /dev/null
@@ -1,50 +0,0 @@
-from oeqa.selftest.base import oeSelfTest
-from oeqa.utils.commands import bitbake, get_bb_var
-from oeqa.utils.decorators import testcase
-import glob
-import os
-import shutil
-
-
-class Archiver(oeSelfTest):
-
- @testcase(1345)
- def test_archiver_allows_to_filter_on_recipe_name(self):
- """
- Summary: The archiver should offer the possibility to filter on the recipe. (#6929)
- Expected: 1. Included recipe (busybox) should be included
- 2. Excluded recipe (zlib) should be excluded
- Product: oe-core
- Author: Daniel Istrate <daniel.alexandrux.istrate@intel.com>
- AutomatedBy: Daniel Istrate <daniel.alexandrux.istrate@intel.com>
- """
-
- include_recipe = 'busybox'
- exclude_recipe = 'zlib'
-
- features = 'INHERIT += "archiver"\n'
- features += 'ARCHIVER_MODE[src] = "original"\n'
- features += 'COPYLEFT_PN_INCLUDE = "%s"\n' % include_recipe
- features += 'COPYLEFT_PN_EXCLUDE = "%s"\n' % exclude_recipe
-
- # Update local.conf
- self.write_config(features)
-
- tmp_dir = get_bb_var('TMPDIR')
- deploy_dir_src = get_bb_var('DEPLOY_DIR_SRC')
- target_sys = get_bb_var('TARGET_SYS')
- src_path = os.path.join(deploy_dir_src, target_sys)
-
- # Delete tmp directory
- shutil.rmtree(tmp_dir)
-
- # Build core-image-minimal
- bitbake('core-image-minimal')
-
- # Check that include_recipe was included
- is_included = len(glob.glob(src_path + '/%s*' % include_recipe))
- self.assertEqual(1, is_included, 'Recipe %s was not included.' % include_recipe)
-
- # Check that exclude_recipe was excluded
- is_excluded = len(glob.glob(src_path + '/%s*' % exclude_recipe))
- self.assertEqual(0, is_excluded, 'Recipe %s was not excluded.' % exclude_recipe)
diff --git a/meta/lib/oeqa/selftest/base.py b/meta/lib/oeqa/selftest/base.py
deleted file mode 100644
index b5a52fe57a..0000000000
--- a/meta/lib/oeqa/selftest/base.py
+++ /dev/null
@@ -1,205 +0,0 @@
-# Copyright (c) 2013 Intel Corporation
-#
-# Released under the MIT license (see COPYING.MIT)
-
-
-# DESCRIPTION
-# Base class inherited by test classes in meta/lib/oeqa/selftest
-
-import unittest
-import os
-import sys
-import shutil
-import logging
-import errno
-
-import oeqa.utils.ftools as ftools
-from oeqa.utils.commands import runCmd, bitbake, get_bb_var, get_test_layer
-from oeqa.utils.decorators import LogResults
-from random import choice
-import glob
-
-@LogResults
-class oeSelfTest(unittest.TestCase):
-
- log = logging.getLogger("selftest.base")
- longMessage = True
-
- def __init__(self, methodName="runTest"):
- self.builddir = os.environ.get("BUILDDIR")
- self.localconf_path = os.path.join(self.builddir, "conf/local.conf")
- self.testinc_path = os.path.join(self.builddir, "conf/selftest.inc")
- self.local_bblayers_path = os.path.join(self.builddir, "conf/bblayers.conf")
- self.testinc_bblayers_path = os.path.join(self.builddir, "conf/bblayers.inc")
- self.machineinc_path = os.path.join(self.builddir, "conf/machine.inc")
- self.testlayer_path = oeSelfTest.testlayer_path
- self._extra_tear_down_commands = []
- self._track_for_cleanup = [self.testinc_path, self.testinc_bblayers_path, self.machineinc_path]
- super(oeSelfTest, self).__init__(methodName)
-
- def setUp(self):
- os.chdir(self.builddir)
- # we don't know what the previous test left around in config or inc files
- # if it failed so we need a fresh start
- try:
- os.remove(self.testinc_path)
- except OSError as e:
- if e.errno != errno.ENOENT:
- raise
- for root, _, files in os.walk(self.testlayer_path):
- for f in files:
- if f == 'test_recipe.inc':
- os.remove(os.path.join(root, f))
-
- for incl_file in [self.testinc_bblayers_path, self.machineinc_path]:
- try:
- os.remove(incl_file)
- except OSError as e:
- if e.errno != errno.ENOENT:
- raise
-
- # Get CUSTOMMACHINE from env (set by --machine argument to oe-selftest)
- custommachine = os.getenv('CUSTOMMACHINE')
- if custommachine:
- if custommachine == 'random':
- machine = get_random_machine()
- else:
- machine = custommachine
- machine_conf = 'MACHINE ??= "%s"\n' % machine
- self.set_machine_config(machine_conf)
- print('MACHINE: %s' % machine)
-
- # tests might need their own setup
- # but if they overwrite this one they have to call
- # super each time, so let's give them an alternative
- self.setUpLocal()
-
- def setUpLocal(self):
- pass
-
- def tearDown(self):
- if self._extra_tear_down_commands:
- failed_extra_commands = []
- for command in self._extra_tear_down_commands:
- result = runCmd(command, ignore_status=True)
- if not result.status == 0:
- failed_extra_commands.append(command)
- if failed_extra_commands:
- self.log.warning("tearDown commands have failed: %s" % ', '.join(map(str, failed_extra_commands)))
- self.log.debug("Trying to move on.")
- self._extra_tear_down_commands = []
-
- if self._track_for_cleanup:
- for path in self._track_for_cleanup:
- if os.path.isdir(path):
- shutil.rmtree(path)
- if os.path.isfile(path):
- os.remove(path)
- self._track_for_cleanup = []
-
- self.tearDownLocal()
-
- def tearDownLocal(self):
- pass
-
- # add test specific commands to the tearDown method.
- def add_command_to_tearDown(self, command):
- self.log.debug("Adding command '%s' to tearDown for this test." % command)
- self._extra_tear_down_commands.append(command)
- # add test specific files or directories to be removed in the tearDown method
- def track_for_cleanup(self, path):
- self.log.debug("Adding path '%s' to be cleaned up when test is over" % path)
- self._track_for_cleanup.append(path)
-
- # write to <builddir>/conf/selftest.inc
- def write_config(self, data):
- self.log.debug("Writing to: %s\n%s\n" % (self.testinc_path, data))
- ftools.write_file(self.testinc_path, data)
-
- custommachine = os.getenv('CUSTOMMACHINE')
- if custommachine and 'MACHINE' in data:
- machine = get_bb_var('MACHINE')
- self.log.warning('MACHINE overridden: %s' % machine)
-
- # append to <builddir>/conf/selftest.inc
- def append_config(self, data):
- self.log.debug("Appending to: %s\n%s\n" % (self.testinc_path, data))
- ftools.append_file(self.testinc_path, data)
-
- custommachine = os.getenv('CUSTOMMACHINE')
- if custommachine and 'MACHINE' in data:
- machine = get_bb_var('MACHINE')
- self.log.warning('MACHINE overridden: %s' % machine)
-
- # remove data from <builddir>/conf/selftest.inc
- def remove_config(self, data):
- self.log.debug("Removing from: %s\n\%s\n" % (self.testinc_path, data))
- ftools.remove_from_file(self.testinc_path, data)
-
- # write to meta-sefltest/recipes-test/<recipe>/test_recipe.inc
- def write_recipeinc(self, recipe, data):
- inc_file = os.path.join(self.testlayer_path, 'recipes-test', recipe, 'test_recipe.inc')
- self.log.debug("Writing to: %s\n%s\n" % (inc_file, data))
- ftools.write_file(inc_file, data)
-
- # append data to meta-sefltest/recipes-test/<recipe>/test_recipe.inc
- def append_recipeinc(self, recipe, data):
- inc_file = os.path.join(self.testlayer_path, 'recipes-test', recipe, 'test_recipe.inc')
- self.log.debug("Appending to: %s\n%s\n" % (inc_file, data))
- ftools.append_file(inc_file, data)
-
- # remove data from meta-sefltest/recipes-test/<recipe>/test_recipe.inc
- def remove_recipeinc(self, recipe, data):
- inc_file = os.path.join(self.testlayer_path, 'recipes-test', recipe, 'test_recipe.inc')
- self.log.debug("Removing from: %s\n%s\n" % (inc_file, data))
- ftools.remove_from_file(inc_file, data)
-
- # delete meta-sefltest/recipes-test/<recipe>/test_recipe.inc file
- def delete_recipeinc(self, recipe):
- inc_file = os.path.join(self.testlayer_path, 'recipes-test', recipe, 'test_recipe.inc')
- self.log.debug("Deleting file: %s" % inc_file)
- try:
- os.remove(inc_file)
- except OSError as e:
- if e.errno != errno.ENOENT:
- raise
-
- # write to <builddir>/conf/bblayers.inc
- def write_bblayers_config(self, data):
- self.log.debug("Writing to: %s\n%s\n" % (self.testinc_bblayers_path, data))
- ftools.write_file(self.testinc_bblayers_path, data)
-
- # append to <builddir>/conf/bblayers.inc
- def append_bblayers_config(self, data):
- self.log.debug("Appending to: %s\n%s\n" % (self.testinc_bblayers_path, data))
- ftools.append_file(self.testinc_bblayers_path, data)
-
- # remove data from <builddir>/conf/bblayers.inc
- def remove_bblayers_config(self, data):
- self.log.debug("Removing from: %s\n\%s\n" % (self.testinc_bblayers_path, data))
- ftools.remove_from_file(self.testinc_bblayers_path, data)
-
- # write to <builddir>/conf/machine.inc
- def set_machine_config(self, data):
- self.log.debug("Writing to: %s\n%s\n" % (self.machineinc_path, data))
- ftools.write_file(self.machineinc_path, data)
-
-
-def get_available_machines():
- # Get a list of all available machines
- bbpath = get_bb_var('BBPATH').split(':')
- machines = []
-
- for path in bbpath:
- found_machines = glob.glob(os.path.join(path, 'conf', 'machine', '*.conf'))
- if found_machines:
- for i in found_machines:
- # eg: '/home/<user>/poky/meta-intel/conf/machine/intel-core2-32.conf'
- machines.append(os.path.splitext(os.path.basename(i))[0])
-
- return machines
-
-
-def get_random_machine():
- # Get a random machine
- return choice(get_available_machines())
diff --git a/meta/lib/oeqa/selftest/bbtests.py b/meta/lib/oeqa/selftest/bbtests.py
deleted file mode 100644
index 4b423237b0..0000000000
--- a/meta/lib/oeqa/selftest/bbtests.py
+++ /dev/null
@@ -1,272 +0,0 @@
-import os
-import re
-
-import oeqa.utils.ftools as ftools
-from oeqa.selftest.base import oeSelfTest
-from oeqa.utils.commands import runCmd, bitbake, get_bb_var
-from oeqa.utils.decorators import testcase
-
-class BitbakeTests(oeSelfTest):
-
- def getline(self, res, line):
- for l in res.output.split('\n'):
- if line in l:
- return l
-
- @testcase(789)
- def test_run_bitbake_from_dir_1(self):
- os.chdir(os.path.join(self.builddir, 'conf'))
- self.assertEqual(bitbake('-e').status, 0, msg = "bitbake couldn't run from \"conf\" dir")
-
- @testcase(790)
- def test_run_bitbake_from_dir_2(self):
- my_env = os.environ.copy()
- my_env['BBPATH'] = my_env['BUILDDIR']
- os.chdir(os.path.dirname(os.environ['BUILDDIR']))
- self.assertEqual(bitbake('-e', env=my_env).status, 0, msg = "bitbake couldn't run from builddir")
-
- @testcase(806)
- def test_event_handler(self):
- self.write_config("INHERIT += \"test_events\"")
- result = bitbake('m4-native')
- find_build_started = re.search("NOTE: Test for bb\.event\.BuildStarted(\n.*)*NOTE: Executing RunQueue Tasks", result.output)
- find_build_completed = re.search("Tasks Summary:.*(\n.*)*NOTE: Test for bb\.event\.BuildCompleted", result.output)
- self.assertTrue(find_build_started, msg = "Match failed in:\n%s" % result.output)
- self.assertTrue(find_build_completed, msg = "Match failed in:\n%s" % result.output)
- self.assertFalse('Test for bb.event.InvalidEvent' in result.output, msg = "\"Test for bb.event.InvalidEvent\" message found during bitbake process. bitbake output: %s" % result.output)
-
- @testcase(103)
- def test_local_sstate(self):
- bitbake('m4-native -ccleansstate')
- bitbake('m4-native')
- bitbake('m4-native -cclean')
- result = bitbake('m4-native')
- find_setscene = re.search("m4-native.*do_.*_setscene", result.output)
- self.assertTrue(find_setscene, msg = "No \"m4-native.*do_.*_setscene\" message found during bitbake m4-native. bitbake output: %s" % result.output )
-
- @testcase(105)
- def test_bitbake_invalid_recipe(self):
- result = bitbake('-b asdf', ignore_status=True)
- self.assertTrue("ERROR: Unable to find any recipe file matching 'asdf'" in result.output, msg = "Though asdf recipe doesn't exist, bitbake didn't output any err. message. bitbake output: %s" % result.output)
-
- @testcase(107)
- def test_bitbake_invalid_target(self):
- result = bitbake('asdf', ignore_status=True)
- self.assertTrue("ERROR: Nothing PROVIDES 'asdf'" in result.output, msg = "Though no 'asdf' target exists, bitbake didn't output any err. message. bitbake output: %s" % result.output)
-
- @testcase(106)
- def test_warnings_errors(self):
- result = bitbake('-b asdf', ignore_status=True)
- find_warnings = re.search("Summary: There w.{2,3}? [1-9][0-9]* WARNING messages* shown", result.output)
- find_errors = re.search("Summary: There w.{2,3}? [1-9][0-9]* ERROR messages* shown", result.output)
- self.assertTrue(find_warnings, msg="Did not find the mumber of warnings at the end of the build:\n" + result.output)
- self.assertTrue(find_errors, msg="Did not find the mumber of errors at the end of the build:\n" + result.output)
-
- @testcase(108)
- def test_invalid_patch(self):
- self.write_recipeinc('man', 'SRC_URI += "file://man-1.5h1-make.patch"')
- result = bitbake('man -c patch', ignore_status=True)
- self.delete_recipeinc('man')
- bitbake('-cclean man')
- line = self.getline(result, "Function failed: patch_do_patch")
- self.assertTrue(line and line.startswith("ERROR:"), msg = "Though no man-1.5h1-make.patch file exists, bitbake didn't output any err. message. bitbake output: %s" % result.output)
-
- @testcase(1354)
- def test_force_task_1(self):
- # test 1 from bug 5875
- test_recipe = 'zlib'
- test_data = "Microsoft Made No Profit From Anyone's Zunes Yo"
- image_dir = get_bb_var('D', test_recipe)
- pkgsplit_dir = get_bb_var('PKGDEST', test_recipe)
- man_dir = get_bb_var('mandir', test_recipe)
-
- bitbake('-c cleansstate %s' % test_recipe)
- bitbake(test_recipe)
- self.add_command_to_tearDown('bitbake -c clean %s' % test_recipe)
-
- man_file = os.path.join(image_dir + man_dir, 'man3/zlib.3')
- ftools.append_file(man_file, test_data)
- bitbake('-c package -f %s' % test_recipe)
-
- man_split_file = os.path.join(pkgsplit_dir, 'zlib-doc' + man_dir, 'man3/zlib.3')
- man_split_content = ftools.read_file(man_split_file)
- self.assertIn(test_data, man_split_content, 'The man file has not changed in packages-split.')
-
- ret = bitbake(test_recipe)
- self.assertIn('task do_package_write_rpm:', ret.output, 'Task do_package_write_rpm did not re-executed.')
-
- @testcase(163)
- def test_force_task_2(self):
- # test 2 from bug 5875
- test_recipe = 'zlib'
-
- bitbake('-c cleansstate %s' % test_recipe)
- bitbake(test_recipe)
- self.add_command_to_tearDown('bitbake -c clean %s' % test_recipe)
-
- result = bitbake('-C compile %s' % test_recipe)
- look_for_tasks = ['do_compile:', 'do_install:', 'do_populate_sysroot:', 'do_package:']
- for task in look_for_tasks:
- self.assertIn(task, result.output, msg="Couldn't find %s task.")
-
- @testcase(167)
- def test_bitbake_g(self):
- result = bitbake('-g core-image-full-cmdline')
- for f in ['pn-buildlist', 'pn-depends.dot', 'package-depends.dot', 'task-depends.dot']:
- self.addCleanup(os.remove, f)
- self.assertTrue('NOTE: PN build list saved to \'pn-buildlist\'' in result.output, msg = "No dependency \"pn-buildlist\" file was generated for the given task target. bitbake output: %s" % result.output)
- self.assertTrue('openssh' in ftools.read_file(os.path.join(self.builddir, 'pn-buildlist')), msg = "No \"openssh\" dependency found in pn-buildlist file.")
-
- @testcase(899)
- def test_image_manifest(self):
- bitbake('core-image-minimal')
- deploydir = get_bb_var("DEPLOY_DIR_IMAGE", target="core-image-minimal")
- imagename = get_bb_var("IMAGE_LINK_NAME", target="core-image-minimal")
- manifest = os.path.join(deploydir, imagename + ".manifest")
- self.assertTrue(os.path.islink(manifest), msg="No manifest file created for image. It should have been created in %s" % manifest)
-
- @testcase(168)
- def test_invalid_recipe_src_uri(self):
- data = 'SRC_URI = "file://invalid"'
- self.write_recipeinc('man', data)
- self.write_config("""DL_DIR = \"${TOPDIR}/download-selftest\"
-SSTATE_DIR = \"${TOPDIR}/download-selftest\"
-""")
- self.track_for_cleanup(os.path.join(self.builddir, "download-selftest"))
-
- bitbake('-ccleanall man')
- result = bitbake('-c fetch man', ignore_status=True)
- bitbake('-ccleanall man')
- self.delete_recipeinc('man')
- self.assertEqual(result.status, 1, msg="Command succeded when it should have failed. bitbake output: %s" % result.output)
- self.assertTrue('Fetcher failure: Unable to find file file://invalid anywhere. The paths that were searched were:' in result.output, msg = "\"invalid\" file \
-doesn't exist, yet no error message encountered. bitbake output: %s" % result.output)
- line = self.getline(result, 'Function failed: Fetcher failure for URL: \'file://invalid\'. Unable to fetch URL from any source.')
- self.assertTrue(line and line.startswith("ERROR:"), msg = "\"invalid\" file \
-doesn't exist, yet fetcher didn't report any error. bitbake output: %s" % result.output)
-
- @testcase(171)
- def test_rename_downloaded_file(self):
- self.write_config("""DL_DIR = \"${TOPDIR}/download-selftest\"
-SSTATE_DIR = \"${TOPDIR}/download-selftest\"
-""")
- self.track_for_cleanup(os.path.join(self.builddir, "download-selftest"))
-
- data = 'SRC_URI_append = ";downloadfilename=test-aspell.tar.gz"'
- self.write_recipeinc('aspell', data)
- bitbake('-ccleanall aspell')
- result = bitbake('-c fetch aspell', ignore_status=True)
- self.delete_recipeinc('aspell')
- self.assertEqual(result.status, 0, msg = "Couldn't fetch aspell. %s" % result.output)
- self.assertTrue(os.path.isfile(os.path.join(get_bb_var("DL_DIR"), 'test-aspell.tar.gz')), msg = "File rename failed. No corresponding test-aspell.tar.gz file found under %s" % str(get_bb_var("DL_DIR")))
- self.assertTrue(os.path.isfile(os.path.join(get_bb_var("DL_DIR"), 'test-aspell.tar.gz.done')), "File rename failed. No corresponding test-aspell.tar.gz.done file found under %s" % str(get_bb_var("DL_DIR")))
-
- @testcase(1028)
- def test_environment(self):
- self.write_config("TEST_ENV=\"localconf\"")
- result = runCmd('bitbake -e | grep TEST_ENV=')
- self.assertTrue('localconf' in result.output, msg = "bitbake didn't report any value for TEST_ENV variable. To test, run 'bitbake -e | grep TEST_ENV='")
-
- @testcase(1029)
- def test_dry_run(self):
- result = runCmd('bitbake -n m4-native')
- self.assertEqual(0, result.status, "bitbake dry run didn't run as expected. %s" % result.output)
-
- @testcase(1030)
- def test_just_parse(self):
- result = runCmd('bitbake -p')
- self.assertEqual(0, result.status, "errors encountered when parsing recipes. %s" % result.output)
-
- @testcase(1031)
- def test_version(self):
- result = runCmd('bitbake -s | grep wget')
- find = re.search("wget *:([0-9a-zA-Z\.\-]+)", result.output)
- self.assertTrue(find, "No version returned for searched recipe. bitbake output: %s" % result.output)
-
- @testcase(1032)
- def test_prefile(self):
- preconf = os.path.join(self.builddir, 'conf/prefile.conf')
- self.track_for_cleanup(preconf)
- ftools.write_file(preconf ,"TEST_PREFILE=\"prefile\"")
- result = runCmd('bitbake -r conf/prefile.conf -e | grep TEST_PREFILE=')
- self.assertTrue('prefile' in result.output, "Preconfigure file \"prefile.conf\"was not taken into consideration. ")
- self.write_config("TEST_PREFILE=\"localconf\"")
- result = runCmd('bitbake -r conf/prefile.conf -e | grep TEST_PREFILE=')
- self.assertTrue('localconf' in result.output, "Preconfigure file \"prefile.conf\"was not taken into consideration.")
-
- @testcase(1033)
- def test_postfile(self):
- postconf = os.path.join(self.builddir, 'conf/postfile.conf')
- self.track_for_cleanup(postconf)
- ftools.write_file(postconf , "TEST_POSTFILE=\"postfile\"")
- self.write_config("TEST_POSTFILE=\"localconf\"")
- result = runCmd('bitbake -R conf/postfile.conf -e | grep TEST_POSTFILE=')
- self.assertTrue('postfile' in result.output, "Postconfigure file \"postfile.conf\"was not taken into consideration.")
-
- @testcase(1034)
- def test_checkuri(self):
- result = runCmd('bitbake -c checkuri m4')
- self.assertEqual(0, result.status, msg = "\"checkuri\" task was not executed. bitbake output: %s" % result.output)
-
- @testcase(1035)
- def test_continue(self):
- self.write_config("""DL_DIR = \"${TOPDIR}/download-selftest\"
-SSTATE_DIR = \"${TOPDIR}/download-selftest\"
-""")
- self.track_for_cleanup(os.path.join(self.builddir, "download-selftest"))
- self.write_recipeinc('man',"\ndo_fail_task () {\nexit 1 \n}\n\naddtask do_fail_task before do_fetch\n" )
- runCmd('bitbake -c cleanall man xcursor-transparent-theme')
- result = runCmd('bitbake man xcursor-transparent-theme -k', ignore_status=True)
- errorpos = result.output.find('ERROR: Function failed: do_fail_task')
- manver = re.search("NOTE: recipe xcursor-transparent-theme-(.*?): task do_unpack: Started", result.output)
- continuepos = result.output.find('NOTE: recipe xcursor-transparent-theme-%s: task do_unpack: Started' % manver.group(1))
- self.assertLess(errorpos,continuepos, msg = "bitbake didn't pass do_fail_task. bitbake output: %s" % result.output)
-
- @testcase(1119)
- def test_non_gplv3(self):
- data = 'INCOMPATIBLE_LICENSE = "GPLv3"'
- conf = os.path.join(self.builddir, 'conf/local.conf')
- ftools.append_file(conf ,data)
- self.addCleanup(ftools.remove_from_file, conf ,data)
- result = bitbake('readline', ignore_status=True)
- self.assertEqual(result.status, 0, "Bitbake failed, exit code %s, output %s" % (result.status, result.output))
- self.assertFalse(os.path.isfile(os.path.join(self.builddir, 'tmp/deploy/licenses/readline/generic_GPLv3')))
- self.assertTrue(os.path.isfile(os.path.join(self.builddir, 'tmp/deploy/licenses/readline/generic_GPLv2')))
-
- @testcase(1422)
- def test_setscene_only(self):
- """ Bitbake option to restore from sstate only within a build (i.e. execute no real tasks, only setscene)"""
- test_recipe = 'ed'
-
- bitbake(test_recipe)
- bitbake('-c clean %s' % test_recipe)
- ret = bitbake('--setscene-only %s' % test_recipe)
-
- tasks = re.findall(r'task\s+(do_\S+):', ret.output)
-
- for task in tasks:
- self.assertIn('_setscene', task, 'A task different from _setscene ran: %s.\n'
- 'Executed tasks were: %s' % (task, str(tasks)))
-
- @testcase(1425)
- def test_bbappend_order(self):
- """ Bitbake should bbappend to recipe in a predictable order """
- test_recipe = 'ed'
- test_recipe_summary_before = get_bb_var('SUMMARY', test_recipe)
- test_recipe_pv = get_bb_var('PV', test_recipe)
- recipe_append_file = test_recipe + '_' + test_recipe_pv + '.bbappend'
- expected_recipe_summary = test_recipe_summary_before
-
- for i in range(5):
- recipe_append_dir = test_recipe + '_test_' + str(i)
- recipe_append_path = os.path.join(self.testlayer_path, 'recipes-test', recipe_append_dir, recipe_append_file)
- os.mkdir(os.path.join(self.testlayer_path, 'recipes-test', recipe_append_dir))
- feature = 'SUMMARY += "%s"\n' % i
- ftools.write_file(recipe_append_path, feature)
- expected_recipe_summary += ' %s' % i
-
- self.add_command_to_tearDown('rm -rf %s' % os.path.join(self.testlayer_path, 'recipes-test',
- test_recipe + '_test_*'))
-
- test_recipe_summary_after = get_bb_var('SUMMARY', test_recipe)
- self.assertEqual(expected_recipe_summary, test_recipe_summary_after)
diff --git a/meta/lib/oeqa/selftest/buildoptions.py b/meta/lib/oeqa/selftest/buildoptions.py
deleted file mode 100644
index 4d0192115b..0000000000
--- a/meta/lib/oeqa/selftest/buildoptions.py
+++ /dev/null
@@ -1,215 +0,0 @@
-import os
-import re
-import glob as g
-import shutil
-import tempfile
-from oeqa.selftest.base import oeSelfTest
-from oeqa.selftest.buildhistory import BuildhistoryBase
-from oeqa.utils.commands import runCmd, bitbake, get_bb_var
-import oeqa.utils.ftools as ftools
-from oeqa.utils.decorators import testcase
-
-class ImageOptionsTests(oeSelfTest):
-
- @testcase(761)
- def test_incremental_image_generation(self):
- image_pkgtype = get_bb_var("IMAGE_PKGTYPE")
- if image_pkgtype != 'rpm':
- self.skipTest('Not using RPM as main package format')
- bitbake("-c cleanall core-image-minimal")
- self.write_config('INC_RPM_IMAGE_GEN = "1"')
- self.append_config('IMAGE_FEATURES += "ssh-server-openssh"')
- bitbake("core-image-minimal")
- log_data_file = os.path.join(get_bb_var("WORKDIR", "core-image-minimal"), "temp/log.do_rootfs")
- log_data_created = ftools.read_file(log_data_file)
- incremental_created = re.search("NOTE: load old install solution for incremental install\nNOTE: old install solution not exist\nNOTE: creating new install solution for incremental install(\n.*)*NOTE: Installing the following packages:.*packagegroup-core-ssh-openssh", log_data_created)
- self.remove_config('IMAGE_FEATURES += "ssh-server-openssh"')
- self.assertTrue(incremental_created, msg = "Match failed in:\n%s" % log_data_created)
- bitbake("core-image-minimal")
- log_data_removed = ftools.read_file(log_data_file)
- incremental_removed = re.search("NOTE: load old install solution for incremental install\nNOTE: creating new install solution for incremental install(\n.*)*NOTE: incremental removed:.*openssh-sshd-.*", log_data_removed)
- self.assertTrue(incremental_removed, msg = "Match failed in:\n%s" % log_data_removed)
-
- @testcase(925)
- def test_rm_old_image(self):
- bitbake("core-image-minimal")
- deploydir = get_bb_var("DEPLOY_DIR_IMAGE", target="core-image-minimal")
- imagename = get_bb_var("IMAGE_LINK_NAME", target="core-image-minimal")
- deploydir_files = os.listdir(deploydir)
- track_original_files = []
- for image_file in deploydir_files:
- if imagename in image_file and os.path.islink(os.path.join(deploydir, image_file)):
- track_original_files.append(os.path.realpath(os.path.join(deploydir, image_file)))
- self.write_config("RM_OLD_IMAGE = \"1\"")
- bitbake("-C rootfs core-image-minimal")
- deploydir_files = os.listdir(deploydir)
- remaining_not_expected = [path for path in track_original_files if os.path.basename(path) in deploydir_files]
- self.assertFalse(remaining_not_expected, msg="\nThe following image files were not removed: %s" % ', '.join(map(str, remaining_not_expected)))
-
- @testcase(286)
- def test_ccache_tool(self):
- bitbake("ccache-native")
- self.assertTrue(os.path.isfile(os.path.join(get_bb_var('STAGING_BINDIR_NATIVE', 'ccache-native'), "ccache")), msg = "No ccache found under %s" % str(get_bb_var('STAGING_BINDIR_NATIVE', 'ccache-native')))
- self.write_config('INHERIT += "ccache"')
- bitbake("m4 -c cleansstate")
- bitbake("m4 -c compile")
- self.addCleanup(bitbake, 'ccache-native -ccleansstate')
- res = runCmd("grep ccache %s" % (os.path.join(get_bb_var("WORKDIR","m4"),"temp/log.do_compile")), ignore_status=True)
- self.assertEqual(0, res.status, msg="No match for ccache in m4 log.do_compile. For further details: %s" % os.path.join(get_bb_var("WORKDIR","m4"),"temp/log.do_compile"))
-
- @testcase(1435)
- def test_read_only_image(self):
- self.write_config('IMAGE_FEATURES += "read-only-rootfs"')
- bitbake("core-image-sato")
- # do_image will fail if there are any pending postinsts
-
-class DiskMonTest(oeSelfTest):
-
- @testcase(277)
- def test_stoptask_behavior(self):
- self.write_config('BB_DISKMON_DIRS = "STOPTASKS,${TMPDIR},100000G,100K"')
- res = bitbake("m4", ignore_status = True)
- self.assertTrue('ERROR: No new tasks can be executed since the disk space monitor action is "STOPTASKS"!' in res.output, msg = "Tasks should have stopped. Disk monitor is set to STOPTASK: %s" % res.output)
- self.assertEqual(res.status, 1, msg = "bitbake reported exit code %s. It should have been 1. Bitbake output: %s" % (str(res.status), res.output))
- self.write_config('BB_DISKMON_DIRS = "ABORT,${TMPDIR},100000G,100K"')
- res = bitbake("m4", ignore_status = True)
- self.assertTrue('ERROR: Immediately abort since the disk space monitor action is "ABORT"!' in res.output, "Tasks should have been aborted immediatelly. Disk monitor is set to ABORT: %s" % res.output)
- self.assertEqual(res.status, 1, msg = "bitbake reported exit code %s. It should have been 1. Bitbake output: %s" % (str(res.status), res.output))
- self.write_config('BB_DISKMON_DIRS = "WARN,${TMPDIR},100000G,100K"')
- res = bitbake("m4")
- self.assertTrue('WARNING: The free space' in res.output, msg = "A warning should have been displayed for disk monitor is set to WARN: %s" %res.output)
-
-class SanityOptionsTest(oeSelfTest):
- def getline(self, res, line):
- for l in res.output.split('\n'):
- if line in l:
- return l
-
- @testcase(927)
- def test_options_warnqa_errorqa_switch(self):
- bitbake("xcursor-transparent-theme -ccleansstate")
-
- if "packages-list" not in get_bb_var("ERROR_QA"):
- self.write_config("ERROR_QA_append = \" packages-list\"")
-
- self.write_recipeinc('xcursor-transparent-theme', 'PACKAGES += \"${PN}-dbg\"')
- res = bitbake("xcursor-transparent-theme", ignore_status=True)
- self.delete_recipeinc('xcursor-transparent-theme')
- line = self.getline(res, "QA Issue: xcursor-transparent-theme-dbg is listed in PACKAGES multiple times, this leads to packaging errors.")
- self.assertTrue(line and line.startswith("ERROR:"), msg=res.output)
- self.assertEqual(res.status, 1, msg = "bitbake reported exit code %s. It should have been 1. Bitbake output: %s" % (str(res.status), res.output))
- self.write_recipeinc('xcursor-transparent-theme', 'PACKAGES += \"${PN}-dbg\"')
- self.append_config('ERROR_QA_remove = "packages-list"')
- self.append_config('WARN_QA_append = " packages-list"')
- bitbake("xcursor-transparent-theme -ccleansstate")
- res = bitbake("xcursor-transparent-theme")
- self.delete_recipeinc('xcursor-transparent-theme')
- line = self.getline(res, "QA Issue: xcursor-transparent-theme-dbg is listed in PACKAGES multiple times, this leads to packaging errors.")
- self.assertTrue(line and line.startswith("WARNING:"), msg=res.output)
-
- @testcase(278)
- def test_sanity_unsafe_script_references(self):
- self.write_config('WARN_QA_append = " unsafe-references-in-scripts"')
-
- bitbake("-ccleansstate gzip")
- res = bitbake("gzip")
- line = self.getline(res, "QA Issue: gzip")
- self.assertFalse(line, "WARNING: QA Issue: gzip message is present in bitbake's output and shouldn't be: %s" % res.output)
-
- self.append_config("""
-do_install_append_pn-gzip () {
- echo "\n${bindir}/test" >> ${D}${bindir}/zcat
-}
-""")
- res = bitbake("gzip")
- line = self.getline(res, "QA Issue: gzip")
- self.assertTrue(line and line.startswith("WARNING:"), "WARNING: QA Issue: gzip message is not present in bitbake's output: %s" % res.output)
-
- @testcase(1434)
- def test_sanity_unsafe_binary_references(self):
- self.write_config('WARN_QA_append = " unsafe-references-in-binaries"')
-
- bitbake("-ccleansstate nfs-utils")
- #res = bitbake("nfs-utils")
- # FIXME when nfs-utils passes this test
- #line = self.getline(res, "QA Issue: nfs-utils")
- #self.assertFalse(line, "WARNING: QA Issue: nfs-utils message is present in bitbake's output and shouldn't be: %s" % res.output)
-
-# self.append_config("""
-#do_install_append_pn-nfs-utils () {
-# echo "\n${bindir}/test" >> ${D}${base_sbindir}/osd_login
-#}
-#""")
- res = bitbake("nfs-utils")
- line = self.getline(res, "QA Issue: nfs-utils")
- self.assertTrue(line and line.startswith("WARNING:"), "WARNING: QA Issue: nfs-utils message is not present in bitbake's output: %s" % res.output)
-
- @testcase(1421)
- def test_layer_without_git_dir(self):
- """
- Summary: Test that layer git revisions are displayed and do not fail without git repository
- Expected: The build to be successful and without "fatal" errors
- Product: oe-core
- Author: Daniel Istrate <daniel.alexandrux.istrate@intel.com>
- AutomatedBy: Daniel Istrate <daniel.alexandrux.istrate@intel.com>
- """
-
- dirpath = tempfile.mkdtemp()
-
- dummy_layer_name = 'meta-dummy'
- dummy_layer_path = os.path.join(dirpath, dummy_layer_name)
- dummy_layer_conf_dir = os.path.join(dummy_layer_path, 'conf')
- os.makedirs(dummy_layer_conf_dir)
- dummy_layer_conf_path = os.path.join(dummy_layer_conf_dir, 'layer.conf')
-
- dummy_layer_content = 'BBPATH .= ":${LAYERDIR}"\n' \
- 'BBFILES += "${LAYERDIR}/recipes-*/*/*.bb ${LAYERDIR}/recipes-*/*/*.bbappend"\n' \
- 'BBFILE_COLLECTIONS += "%s"\n' \
- 'BBFILE_PATTERN_%s = "^${LAYERDIR}/"\n' \
- 'BBFILE_PRIORITY_%s = "6"\n' % (dummy_layer_name, dummy_layer_name, dummy_layer_name)
-
- ftools.write_file(dummy_layer_conf_path, dummy_layer_content)
-
- bblayers_conf = 'BBLAYERS += "%s"\n' % dummy_layer_path
- self.write_bblayers_config(bblayers_conf)
-
- test_recipe = 'ed'
-
- ret = bitbake('-n %s' % test_recipe)
-
- err = 'fatal: Not a git repository'
-
- shutil.rmtree(dirpath)
-
- self.assertNotIn(err, ret.output)
-
-
-class BuildhistoryTests(BuildhistoryBase):
-
- @testcase(293)
- def test_buildhistory_basic(self):
- self.run_buildhistory_operation('xcursor-transparent-theme')
- self.assertTrue(os.path.isdir(get_bb_var('BUILDHISTORY_DIR')), "buildhistory dir was not created.")
-
- @testcase(294)
- def test_buildhistory_buildtime_pr_backwards(self):
- self.add_command_to_tearDown('cleanup-workdir')
- target = 'xcursor-transparent-theme'
- error = "ERROR:.*QA Issue: Package version for package %s went backwards which would break package feeds from (.*-r1.* to .*-r0.*)" % target
- self.run_buildhistory_operation(target, target_config="PR = \"r1\"", change_bh_location=True)
- self.run_buildhistory_operation(target, target_config="PR = \"r0\"", change_bh_location=False, expect_error=True, error_regex=error)
-
-class ArchiverTest(oeSelfTest):
- @testcase(926)
- def test_arch_work_dir_and_export_source(self):
- """
- Test for archiving the work directory and exporting the source files.
- """
- self.add_command_to_tearDown('cleanup-workdir')
- self.write_config("INHERIT += \"archiver\"\nARCHIVER_MODE[src] = \"original\"\nARCHIVER_MODE[srpm] = \"1\"")
- res = bitbake("xcursor-transparent-theme", ignore_status=True)
- self.assertEqual(res.status, 0, "\nCouldn't build xcursortransparenttheme.\nbitbake output %s" % res.output)
- pkgs_path = g.glob(str(self.builddir) + "/tmp/deploy/sources/allarch*/xcurs*")
- src_file_glob = str(pkgs_path[0]) + "/xcursor*.src.rpm"
- tar_file_glob = str(pkgs_path[0]) + "/xcursor*.tar.gz"
- self.assertTrue((g.glob(src_file_glob) and g.glob(tar_file_glob)), "Couldn't find .src.rpm and .tar.gz files under tmp/deploy/sources/allarch*/xcursor*")
diff --git a/meta/lib/oeqa/selftest/case.py b/meta/lib/oeqa/selftest/case.py
new file mode 100644
index 0000000000..dcad4f76ec
--- /dev/null
+++ b/meta/lib/oeqa/selftest/case.py
@@ -0,0 +1,262 @@
+#
+# Copyright (C) 2013-2017 Intel Corporation
+#
+# SPDX-License-Identifier: MIT
+#
+
+import sys
+import os
+import glob
+import errno
+from unittest.util import safe_repr
+
+import oeqa.utils.ftools as ftools
+from oeqa.utils.commands import runCmd, bitbake, get_bb_var
+from oeqa.core.case import OETestCase
+
+import bb.utils
+
+class OESelftestTestCase(OETestCase):
+ def __init__(self, methodName="runTest"):
+ self._extra_tear_down_commands = []
+ super(OESelftestTestCase, self).__init__(methodName)
+
+ @classmethod
+ def setUpClass(cls):
+ super(OESelftestTestCase, cls).setUpClass()
+
+ cls.testlayer_path = cls.tc.config_paths['testlayer_path']
+ cls.builddir = cls.tc.config_paths['builddir']
+
+ cls.localconf_path = cls.tc.config_paths['localconf']
+ cls.local_bblayers_path = cls.tc.config_paths['bblayers']
+
+ cls.testinc_path = os.path.join(cls.tc.config_paths['builddir'],
+ "conf/selftest.inc")
+ cls.testinc_bblayers_path = os.path.join(cls.tc.config_paths['builddir'],
+ "conf/bblayers.inc")
+ cls.machineinc_path = os.path.join(cls.tc.config_paths['builddir'],
+ "conf/machine.inc")
+
+ cls._track_for_cleanup = [
+ cls.testinc_path, cls.testinc_bblayers_path,
+ cls.machineinc_path]
+
+ cls.add_include()
+
+ @classmethod
+ def tearDownClass(cls):
+ cls.remove_include()
+ cls.remove_inc_files()
+ super(OESelftestTestCase, cls).tearDownClass()
+
+ @classmethod
+ def add_include(cls):
+ if "#include added by oe-selftest" \
+ not in ftools.read_file(os.path.join(cls.builddir, "conf/local.conf")):
+ cls.logger.info("Adding: \"include selftest.inc\" in %s" % os.path.join(cls.builddir, "conf/local.conf"))
+ ftools.append_file(os.path.join(cls.builddir, "conf/local.conf"), \
+ "\n#include added by oe-selftest\ninclude machine.inc\ninclude selftest.inc")
+
+ if "#include added by oe-selftest" \
+ not in ftools.read_file(os.path.join(cls.builddir, "conf/bblayers.conf")):
+ cls.logger.info("Adding: \"include bblayers.inc\" in bblayers.conf")
+ ftools.append_file(os.path.join(cls.builddir, "conf/bblayers.conf"), \
+ "\n#include added by oe-selftest\ninclude bblayers.inc")
+
+ @classmethod
+ def remove_include(cls):
+ if "#include added by oe-selftest.py" \
+ in ftools.read_file(os.path.join(cls.builddir, "conf/local.conf")):
+ cls.logger.info("Removing the include from local.conf")
+ ftools.remove_from_file(os.path.join(cls.builddir, "conf/local.conf"), \
+ "\n#include added by oe-selftest.py\ninclude machine.inc\ninclude selftest.inc")
+
+ if "#include added by oe-selftest.py" \
+ in ftools.read_file(os.path.join(cls.builddir, "conf/bblayers.conf")):
+ cls.logger.info("Removing the include from bblayers.conf")
+ ftools.remove_from_file(os.path.join(cls.builddir, "conf/bblayers.conf"), \
+ "\n#include added by oe-selftest.py\ninclude bblayers.inc")
+
+ @classmethod
+ def remove_inc_files(cls):
+ try:
+ os.remove(os.path.join(cls.builddir, "conf/selftest.inc"))
+ for root, _, files in os.walk(cls.testlayer_path):
+ for f in files:
+ if f == 'test_recipe.inc':
+ os.remove(os.path.join(root, f))
+ except OSError as e:
+ pass
+
+ for incl_file in ['conf/bblayers.inc', 'conf/machine.inc']:
+ try:
+ os.remove(os.path.join(cls.builddir, incl_file))
+ except:
+ pass
+
+ def setUp(self):
+ super(OESelftestTestCase, self).setUp()
+ os.chdir(self.builddir)
+ # we don't know what the previous test left around in config or inc files
+ # if it failed so we need a fresh start
+ try:
+ os.remove(self.testinc_path)
+ except OSError as e:
+ if e.errno != errno.ENOENT:
+ raise
+ for root, _, files in os.walk(self.testlayer_path):
+ for f in files:
+ if f == 'test_recipe.inc':
+ os.remove(os.path.join(root, f))
+
+ for incl_file in [self.testinc_bblayers_path, self.machineinc_path]:
+ try:
+ os.remove(incl_file)
+ except OSError as e:
+ if e.errno != errno.ENOENT:
+ raise
+
+ if self.tc.custommachine:
+ machine_conf = 'MACHINE ??= "%s"\n' % self.tc.custommachine
+ self.set_machine_config(machine_conf)
+
+ # tests might need their own setup
+ # but if they overwrite this one they have to call
+ # super each time, so let's give them an alternative
+ self.setUpLocal()
+
+ def setUpLocal(self):
+ pass
+
+ def tearDown(self):
+ if self._extra_tear_down_commands:
+ failed_extra_commands = []
+ for command in self._extra_tear_down_commands:
+ result = runCmd(command, ignore_status=True)
+ if not result.status == 0:
+ failed_extra_commands.append(command)
+ if failed_extra_commands:
+ self.logger.warning("tearDown commands have failed: %s" % ', '.join(map(str, failed_extra_commands)))
+ self.logger.debug("Trying to move on.")
+ self._extra_tear_down_commands = []
+
+ if self._track_for_cleanup:
+ for path in self._track_for_cleanup:
+ if os.path.isdir(path):
+ bb.utils.remove(path, recurse=True)
+ if os.path.isfile(path):
+ os.remove(path)
+ self._track_for_cleanup = []
+
+ self.tearDownLocal()
+ super(OESelftestTestCase, self).tearDown()
+
+ def tearDownLocal(self):
+ pass
+
+ def add_command_to_tearDown(self, command):
+ """Add test specific commands to the tearDown method"""
+ self.logger.debug("Adding command '%s' to tearDown for this test." % command)
+ self._extra_tear_down_commands.append(command)
+
+ def track_for_cleanup(self, path):
+ """Add test specific files or directories to be removed in the tearDown method"""
+ self.logger.debug("Adding path '%s' to be cleaned up when test is over" % path)
+ self._track_for_cleanup.append(path)
+
+ def write_config(self, data, multiconfig=None):
+ """Write to config file"""
+ if multiconfig:
+ multiconfigdir = "%s/conf/multiconfig" % self.builddir
+ os.makedirs(multiconfigdir, exist_ok=True)
+ dest_path = '%s/%s.conf' % (multiconfigdir, multiconfig)
+ self.track_for_cleanup(dest_path)
+ else:
+ dest_path = self.testinc_path
+
+ self.logger.debug("Writing to: %s\n%s\n" % (dest_path, data))
+ ftools.write_file(dest_path, data)
+
+ if not multiconfig and self.tc.custommachine and 'MACHINE' in data:
+ machine = get_bb_var('MACHINE')
+ self.logger.warning('MACHINE overridden: %s' % machine)
+
+ def append_config(self, data):
+ """Append to <builddir>/conf/selftest.inc"""
+ self.logger.debug("Appending to: %s\n%s\n" % (self.testinc_path, data))
+ ftools.append_file(self.testinc_path, data)
+
+ if self.tc.custommachine and 'MACHINE' in data:
+ machine = get_bb_var('MACHINE')
+ self.logger.warning('MACHINE overridden: %s' % machine)
+
+ def remove_config(self, data):
+ """Remove data from <builddir>/conf/selftest.inc"""
+ self.logger.debug("Removing from: %s\n%s\n" % (self.testinc_path, data))
+ ftools.remove_from_file(self.testinc_path, data)
+
+ def recipeinc(self, recipe):
+ """Return absolute path of meta-selftest/recipes-test/<recipe>/test_recipe.inc"""
+ return os.path.join(self.testlayer_path, 'recipes-test', recipe, 'test_recipe.inc')
+
+ def write_recipeinc(self, recipe, data):
+ """Write to meta-selftest/recipes-test/<recipe>/test_recipe.inc"""
+ inc_file = self.recipeinc(recipe)
+ self.logger.debug("Writing to: %s\n%s\n" % (inc_file, data))
+ ftools.write_file(inc_file, data)
+ return inc_file
+
+ def append_recipeinc(self, recipe, data):
+ """Append data to meta-selftest/recipes-test/<recipe>/test_recipe.inc"""
+ inc_file = self.recipeinc(recipe)
+ self.logger.debug("Appending to: %s\n%s\n" % (inc_file, data))
+ ftools.append_file(inc_file, data)
+ return inc_file
+
+ def remove_recipeinc(self, recipe, data):
+ """Remove data from meta-selftest/recipes-test/<recipe>/test_recipe.inc"""
+ inc_file = self.recipeinc(recipe)
+ self.logger.debug("Removing from: %s\n%s\n" % (inc_file, data))
+ ftools.remove_from_file(inc_file, data)
+
+ def delete_recipeinc(self, recipe):
+ """Delete meta-selftest/recipes-test/<recipe>/test_recipe.inc file"""
+ inc_file = self.recipeinc(recipe)
+ self.logger.debug("Deleting file: %s" % inc_file)
+ try:
+ os.remove(inc_file)
+ except OSError as e:
+ if e.errno != errno.ENOENT:
+ raise
+ def write_bblayers_config(self, data):
+ """Write to <builddir>/conf/bblayers.inc"""
+ self.logger.debug("Writing to: %s\n%s\n" % (self.testinc_bblayers_path, data))
+ ftools.write_file(self.testinc_bblayers_path, data)
+
+ def append_bblayers_config(self, data):
+ """Append to <builddir>/conf/bblayers.inc"""
+ self.logger.debug("Appending to: %s\n%s\n" % (self.testinc_bblayers_path, data))
+ ftools.append_file(self.testinc_bblayers_path, data)
+
+ def remove_bblayers_config(self, data):
+ """Remove data from <builddir>/conf/bblayers.inc"""
+ self.logger.debug("Removing from: %s\n%s\n" % (self.testinc_bblayers_path, data))
+ ftools.remove_from_file(self.testinc_bblayers_path, data)
+
+ def set_machine_config(self, data):
+ """Write to <builddir>/conf/machine.inc"""
+ self.logger.debug("Writing to: %s\n%s\n" % (self.machineinc_path, data))
+ ftools.write_file(self.machineinc_path, data)
+
+ # check does path exist
+ def assertExists(self, expr, msg=None):
+ if not os.path.exists(expr):
+ msg = self._formatMessage(msg, "%s does not exist" % safe_repr(expr))
+ raise self.failureException(msg)
+
+ # check does path not exist
+ def assertNotExists(self, expr, msg=None):
+ if os.path.exists(expr):
+ msg = self._formatMessage(msg, "%s exists when it should not" % safe_repr(expr))
+ raise self.failureException(msg)
diff --git a/meta/lib/oeqa/selftest/_sstatetests_noauto.py b/meta/lib/oeqa/selftest/cases/_sstatetests_noauto.py
index fc9ae7efb9..5f1c8df2d4 100644
--- a/meta/lib/oeqa/selftest/_sstatetests_noauto.py
+++ b/meta/lib/oeqa/selftest/cases/_sstatetests_noauto.py
@@ -1,19 +1,22 @@
-import datetime
-import unittest
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
import os
-import re
import shutil
import oeqa.utils.ftools as ftools
-from oeqa.selftest.base import oeSelfTest
-from oeqa.utils.commands import runCmd, bitbake, get_bb_var, get_test_layer
-from oeqa.selftest.sstate import SStateBase
+from oeqa.utils.commands import runCmd, bitbake, get_bb_var
+from oeqa.selftest.cases.sstate import SStateBase
class RebuildFromSState(SStateBase):
@classmethod
def setUpClass(self):
+ super(RebuildFromSState, self).setUpClass()
self.builddir = os.path.join(os.environ.get('BUILDDIR'))
def get_dep_targets(self, primary_targets):
@@ -89,7 +92,7 @@ class RebuildFromSState(SStateBase):
self.assertFalse(failed_cleansstate, msg="The following recipes have failed cleansstate(all others have passed both cleansstate and rebuild from sstate tests): %s" % ' '.join(map(str, failed_cleansstate)))
def test_sstate_relocation(self):
- self.run_test_sstate_rebuild(['core-image-sato-sdk'], relocate=True, rebuild_dependencies=True)
+ self.run_test_sstate_rebuild(['core-image-weston-sdk'], relocate=True, rebuild_dependencies=True)
def test_sstate_rebuild(self):
- self.run_test_sstate_rebuild(['core-image-sato-sdk'], relocate=False, rebuild_dependencies=True)
+ self.run_test_sstate_rebuild(['core-image-weston-sdk'], relocate=False, rebuild_dependencies=True)
diff --git a/meta/lib/oeqa/selftest/cases/archiver.py b/meta/lib/oeqa/selftest/cases/archiver.py
new file mode 100644
index 0000000000..3fa59fff51
--- /dev/null
+++ b/meta/lib/oeqa/selftest/cases/archiver.py
@@ -0,0 +1,345 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
+import os
+import glob
+import re
+from oeqa.utils.commands import bitbake, get_bb_vars
+from oeqa.selftest.case import OESelftestTestCase
+
+class Archiver(OESelftestTestCase):
+
+ def test_archiver_allows_to_filter_on_recipe_name(self):
+ """
+ Summary: The archiver should offer the possibility to filter on the recipe. (#6929)
+ Expected: 1. Included recipe (busybox) should be included
+ 2. Excluded recipe (zlib) should be excluded
+ Product: oe-core
+ Author: Daniel Istrate <daniel.alexandrux.istrate@intel.com>
+ AutomatedBy: Daniel Istrate <daniel.alexandrux.istrate@intel.com>
+ """
+
+ include_recipe = 'selftest-ed'
+ exclude_recipe = 'initscripts'
+
+ features = 'INHERIT += "archiver"\n'
+ features += 'ARCHIVER_MODE[src] = "original"\n'
+ features += 'COPYLEFT_PN_INCLUDE = "%s"\n' % include_recipe
+ features += 'COPYLEFT_PN_EXCLUDE = "%s"\n' % exclude_recipe
+ self.write_config(features)
+
+ bitbake('-c clean %s %s' % (include_recipe, exclude_recipe))
+ bitbake("-c deploy_archives %s %s" % (include_recipe, exclude_recipe))
+
+ bb_vars = get_bb_vars(['DEPLOY_DIR_SRC', 'TARGET_SYS'])
+ src_path = os.path.join(bb_vars['DEPLOY_DIR_SRC'], bb_vars['TARGET_SYS'])
+
+ # Check that include_recipe was included
+ included_present = len(glob.glob(src_path + '/%s-*/*' % include_recipe))
+ self.assertTrue(included_present, 'Recipe %s was not included.' % include_recipe)
+
+ # Check that exclude_recipe was excluded
+ excluded_present = len(glob.glob(src_path + '/%s-*/*' % exclude_recipe))
+ self.assertFalse(excluded_present, 'Recipe %s was not excluded.' % exclude_recipe)
+
+ def test_archiver_filters_by_type(self):
+ """
+ Summary: The archiver is documented to filter on the recipe type.
+ Expected: 1. included recipe type (target) should be included
+ 2. other types should be excluded
+ Product: oe-core
+ Author: André Draszik <adraszik@tycoint.com>
+ """
+
+ target_recipe = 'selftest-ed'
+ native_recipe = 'selftest-ed-native'
+
+ features = 'INHERIT += "archiver"\n'
+ features += 'ARCHIVER_MODE[src] = "original"\n'
+ features += 'COPYLEFT_RECIPE_TYPES = "target"\n'
+ self.write_config(features)
+
+ bitbake('-c clean %s %s' % (target_recipe, native_recipe))
+ bitbake("%s -c deploy_archives %s" % (target_recipe, native_recipe))
+
+ bb_vars = get_bb_vars(['DEPLOY_DIR_SRC', 'TARGET_SYS', 'BUILD_SYS'])
+ src_path_target = os.path.join(bb_vars['DEPLOY_DIR_SRC'], bb_vars['TARGET_SYS'])
+ src_path_native = os.path.join(bb_vars['DEPLOY_DIR_SRC'], bb_vars['BUILD_SYS'])
+
+ # Check that target_recipe was included
+ included_present = len(glob.glob(src_path_target + '/%s-*/*' % target_recipe))
+ self.assertTrue(included_present, 'Recipe %s was not included.' % target_recipe)
+
+ # Check that native_recipe was excluded
+ excluded_present = len(glob.glob(src_path_native + '/%s-*/*' % native_recipe))
+ self.assertFalse(excluded_present, 'Recipe %s was not excluded.' % native_recipe)
+
+ def test_archiver_filters_by_type_and_name(self):
+ """
+ Summary: Test that the archiver archives by recipe type, taking the
+ recipe name into account.
+ Expected: 1. included recipe type (target) should be included
+ 2. other types should be excluded
+ 3. recipe by name should be included / excluded,
+ overriding previous decision by type
+ Product: oe-core
+ Author: André Draszik <adraszik@tycoint.com>
+ """
+
+ target_recipes = [ 'initscripts', 'selftest-ed' ]
+ native_recipes = [ 'update-rc.d-native', 'selftest-ed-native' ]
+
+ features = 'INHERIT += "archiver"\n'
+ features += 'ARCHIVER_MODE[src] = "original"\n'
+ features += 'COPYLEFT_RECIPE_TYPES = "target"\n'
+ features += 'COPYLEFT_PN_INCLUDE = "%s"\n' % native_recipes[1]
+ features += 'COPYLEFT_PN_EXCLUDE = "%s"\n' % target_recipes[1]
+ self.write_config(features)
+
+ bitbake('-c clean %s %s' % (' '.join(target_recipes), ' '.join(native_recipes)))
+ bitbake('-c deploy_archives %s %s' % (' '.join(target_recipes), ' '.join(native_recipes)))
+
+ bb_vars = get_bb_vars(['DEPLOY_DIR_SRC', 'TARGET_SYS', 'BUILD_SYS'])
+ src_path_target = os.path.join(bb_vars['DEPLOY_DIR_SRC'], bb_vars['TARGET_SYS'])
+ src_path_native = os.path.join(bb_vars['DEPLOY_DIR_SRC'], bb_vars['BUILD_SYS'])
+
+ # Check that target_recipe[0] and native_recipes[1] were included
+ included_present = len(glob.glob(src_path_target + '/%s-*/*' % target_recipes[0]))
+ self.assertTrue(included_present, 'Recipe %s was not included.' % target_recipes[0])
+
+ included_present = len(glob.glob(src_path_native + '/%s-*/*' % native_recipes[1]))
+ self.assertTrue(included_present, 'Recipe %s was not included.' % native_recipes[1])
+
+ # Check that native_recipes[0] and target_recipes[1] were excluded
+ excluded_present = len(glob.glob(src_path_native + '/%s-*/*' % native_recipes[0]))
+ self.assertFalse(excluded_present, 'Recipe %s was not excluded.' % native_recipes[0])
+
+ excluded_present = len(glob.glob(src_path_target + '/%s-*/*' % target_recipes[1]))
+ self.assertFalse(excluded_present, 'Recipe %s was not excluded.' % target_recipes[1])
+
+ def test_archiver_multiconfig_shared_unpack_and_patch(self):
+ """
+ Test that shared recipes in original mode with diff enabled works in multiconfig,
+ otherwise it will not build when using the same TMP dir.
+ """
+
+ features = 'BBMULTICONFIG = "mc1 mc2"\n'
+ features += 'INHERIT += "archiver"\n'
+ features += 'ARCHIVER_MODE[src] = "original"\n'
+ features += 'ARCHIVER_MODE[diff] = "1"\n'
+ self.write_config(features)
+
+ # We can use any machine in multiconfig as long as they are different
+ self.write_config('MACHINE = "qemuarm"\n', 'mc1')
+ self.write_config('MACHINE = "qemux86"\n', 'mc2')
+
+ task = 'do_unpack_and_patch'
+ # Use gcc-source as it is a shared recipe (appends the pv to the pn)
+ pn = 'gcc-source-%s' % get_bb_vars(['PV'], 'gcc')['PV']
+
+ # Generate the tasks signatures
+ bitbake('mc:mc1:%s mc:mc2:%s -c %s -S none' % (pn, pn, task))
+
+ # Check the tasks signatures
+ # To be machine agnostic the tasks needs to generate the same signature for each machine
+ locked_sigs_inc = "%s/locked-sigs.inc" % self.builddir
+ locked_sigs = open(locked_sigs_inc).read()
+ task_sigs = re.findall(r"%s:%s:.*" % (pn, task), locked_sigs)
+ uniq_sigs = set(task_sigs)
+ self.assertFalse(len(uniq_sigs) - 1, \
+ 'The task "%s" of the recipe "%s" has different signatures in "%s" for each machine in multiconfig' \
+ % (task, pn, locked_sigs_inc))
+
+ def test_archiver_srpm_mode(self):
+ """
+ Test that in srpm mode, the added recipe dependencies at least exist/work [YOCTO #11121]
+ """
+
+ features = 'INHERIT += "archiver"\n'
+ features += 'ARCHIVER_MODE[srpm] = "1"\n'
+ features += 'PACKAGE_CLASSES = "package_rpm"\n'
+ self.write_config(features)
+
+ bitbake('-n selftest-nopackages selftest-ed')
+
+ def _test_archiver_mode(self, mode, target_file_name, extra_config=None):
+ target = 'selftest-ed-native'
+
+ features = 'INHERIT += "archiver"\n'
+ features += 'ARCHIVER_MODE[src] = "%s"\n' % (mode)
+ if extra_config:
+ features += extra_config
+ self.write_config(features)
+
+ bitbake('-c clean %s' % (target))
+ bitbake('-c deploy_archives %s' % (target))
+
+ bb_vars = get_bb_vars(['DEPLOY_DIR_SRC', 'BUILD_SYS'])
+ glob_str = os.path.join(bb_vars['DEPLOY_DIR_SRC'], bb_vars['BUILD_SYS'], '%s-*' % (target))
+ glob_result = glob.glob(glob_str)
+ self.assertTrue(glob_result, 'Missing archiver directory for %s' % (target))
+
+ archive_path = os.path.join(glob_result[0], target_file_name)
+ self.assertTrue(os.path.exists(archive_path), 'Missing archive file %s' % (target_file_name))
+
+ def test_archiver_mode_original(self):
+ """
+ Test that the archiver works with `ARCHIVER_MODE[src] = "original"`.
+ """
+
+ self._test_archiver_mode('original', 'ed-1.14.1.tar.lz')
+
+ def test_archiver_mode_patched(self):
+ """
+ Test that the archiver works with `ARCHIVER_MODE[src] = "patched"`.
+ """
+
+ self._test_archiver_mode('patched', 'selftest-ed-native-1.14.1-r0-patched.tar.xz')
+
+ def test_archiver_mode_configured(self):
+ """
+ Test that the archiver works with `ARCHIVER_MODE[src] = "configured"`.
+ """
+
+ self._test_archiver_mode('configured', 'selftest-ed-native-1.14.1-r0-configured.tar.xz')
+
+ def test_archiver_mode_recipe(self):
+ """
+ Test that the archiver works with `ARCHIVER_MODE[recipe] = "1"`.
+ """
+
+ self._test_archiver_mode('patched', 'selftest-ed-native-1.14.1-r0-recipe.tar.xz',
+ 'ARCHIVER_MODE[recipe] = "1"\n')
+
+ def test_archiver_mode_diff(self):
+ """
+ Test that the archiver works with `ARCHIVER_MODE[diff] = "1"`.
+ Exclusions controlled by `ARCHIVER_MODE[diff-exclude]` are not yet tested.
+ """
+
+ self._test_archiver_mode('patched', 'selftest-ed-native-1.14.1-r0-diff.gz',
+ 'ARCHIVER_MODE[diff] = "1"\n')
+
+ def test_archiver_mode_dumpdata(self):
+ """
+ Test that the archiver works with `ARCHIVER_MODE[dumpdata] = "1"`.
+ """
+
+ self._test_archiver_mode('patched', 'selftest-ed-native-1.14.1-r0-showdata.dump',
+ 'ARCHIVER_MODE[dumpdata] = "1"\n')
+
+ def test_archiver_mode_mirror(self):
+ """
+ Test that the archiver works with `ARCHIVER_MODE[src] = "mirror"`.
+ """
+
+ self._test_archiver_mode('mirror', 'ed-1.14.1.tar.lz',
+ 'BB_GENERATE_MIRROR_TARBALLS = "1"\n')
+
+ def test_archiver_mode_mirror_excludes(self):
+ """
+ Test that the archiver works with `ARCHIVER_MODE[src] = "mirror"` and
+ correctly excludes an archive when its URL matches
+ `ARCHIVER_MIRROR_EXCLUDE`.
+ """
+
+ target='selftest-ed'
+ target_file_name = 'ed-1.14.1.tar.lz'
+
+ features = 'INHERIT += "archiver"\n'
+ features += 'ARCHIVER_MODE[src] = "mirror"\n'
+ features += 'BB_GENERATE_MIRROR_TARBALLS = "1"\n'
+ features += 'ARCHIVER_MIRROR_EXCLUDE = "${GNU_MIRROR}"\n'
+ self.write_config(features)
+
+ bitbake('-c clean %s' % (target))
+ bitbake('-c deploy_archives %s' % (target))
+
+ bb_vars = get_bb_vars(['DEPLOY_DIR_SRC', 'TARGET_SYS'])
+ glob_str = os.path.join(bb_vars['DEPLOY_DIR_SRC'], bb_vars['TARGET_SYS'], '%s-*' % (target))
+ glob_result = glob.glob(glob_str)
+ self.assertTrue(glob_result, 'Missing archiver directory for %s' % (target))
+
+ archive_path = os.path.join(glob_result[0], target_file_name)
+ self.assertFalse(os.path.exists(archive_path), 'Failed to exclude archive file %s' % (target_file_name))
+
+ def test_archiver_mode_mirror_combined(self):
+ """
+ Test that the archiver works with `ARCHIVER_MODE[src] = "mirror"`
+ and `ARCHIVER_MODE[mirror] = "combined"`. Archives for multiple recipes
+ should all end up in the 'mirror' directory.
+ """
+
+ features = 'INHERIT += "archiver"\n'
+ features += 'ARCHIVER_MODE[src] = "mirror"\n'
+ features += 'ARCHIVER_MODE[mirror] = "combined"\n'
+ features += 'BB_GENERATE_MIRROR_TARBALLS = "1"\n'
+ features += 'COPYLEFT_LICENSE_INCLUDE = "*"\n'
+ self.write_config(features)
+
+ for target in ['selftest-ed', 'selftest-hardlink']:
+ bitbake('-c clean %s' % (target))
+ bitbake('-c deploy_archives %s' % (target))
+
+ bb_vars = get_bb_vars(['DEPLOY_DIR_SRC'])
+ for target_file_name in ['ed-1.14.1.tar.lz', 'hello.c']:
+ glob_str = os.path.join(bb_vars['DEPLOY_DIR_SRC'], 'mirror', target_file_name)
+ glob_result = glob.glob(glob_str)
+ self.assertTrue(glob_result, 'Missing archive file %s' % (target_file_name))
+
+ def test_archiver_mode_mirror_gitsm(self):
+ """
+ Test that the archiver correctly handles git submodules with
+ `ARCHIVER_MODE[src] = "mirror"`.
+ """
+ features = 'INHERIT += "archiver"\n'
+ features += 'ARCHIVER_MODE[src] = "mirror"\n'
+ features += 'ARCHIVER_MODE[mirror] = "combined"\n'
+ features += 'BB_GENERATE_MIRROR_TARBALLS = "1"\n'
+ features += 'COPYLEFT_LICENSE_INCLUDE = "*"\n'
+ self.write_config(features)
+
+ bitbake('-c clean git-submodule-test')
+ bitbake('-c deploy_archives -f git-submodule-test')
+
+ bb_vars = get_bb_vars(['DEPLOY_DIR_SRC'])
+ for target_file_name in [
+ 'git2_git.yoctoproject.org.git-submodule-test.tar.gz',
+ 'git2_git.yoctoproject.org.bitbake-gitsm-test1.tar.gz',
+ 'git2_git.yoctoproject.org.bitbake-gitsm-test2.tar.gz',
+ 'git2_git.openembedded.org.bitbake.tar.gz'
+ ]:
+ target_path = os.path.join(bb_vars['DEPLOY_DIR_SRC'], 'mirror', target_file_name)
+ self.assertTrue(os.path.exists(target_path))
+
+ def test_archiver_mode_mirror_gitsm_shallow(self):
+ """
+ Test that the archiver correctly handles git submodules with
+ `ARCHIVER_MODE[src] = "mirror"`.
+ """
+ features = 'INHERIT += "archiver"\n'
+ features += 'ARCHIVER_MODE[src] = "mirror"\n'
+ features += 'ARCHIVER_MODE[mirror] = "combined"\n'
+ features += 'BB_GENERATE_MIRROR_TARBALLS = "1"\n'
+ features += 'COPYLEFT_LICENSE_INCLUDE = "*"\n'
+ features += 'BB_GIT_SHALLOW = "1"\n'
+ features += 'BB_GENERATE_SHALLOW_TARBALLS = "1"\n'
+ features += 'DL_DIR = "${TOPDIR}/downloads-shallow"\n'
+ self.write_config(features)
+
+ bitbake('-c clean git-submodule-test')
+ bitbake('-c deploy_archives -f git-submodule-test')
+
+ bb_vars = get_bb_vars(['DEPLOY_DIR_SRC'])
+ for target_file_name in [
+ 'gitsmshallow_git.yoctoproject.org.git-submodule-test_a2885dd-1_master.tar.gz',
+ 'gitsmshallow_git.yoctoproject.org.bitbake-gitsm-test1_bare_120f4c7-1.tar.gz',
+ 'gitsmshallow_git.yoctoproject.org.bitbake-gitsm-test2_bare_f66699e-1.tar.gz',
+ 'gitsmshallow_git.openembedded.org.bitbake_bare_52a144a-1.tar.gz',
+ 'gitsmshallow_git.openembedded.org.bitbake_bare_c39b997-1.tar.gz'
+ ]:
+ target_path = os.path.join(bb_vars['DEPLOY_DIR_SRC'], 'mirror', target_file_name)
+ self.assertTrue(os.path.exists(target_path))
diff --git a/meta/lib/oeqa/selftest/cases/baremetal.py b/meta/lib/oeqa/selftest/cases/baremetal.py
new file mode 100644
index 0000000000..cadaea2f1a
--- /dev/null
+++ b/meta/lib/oeqa/selftest/cases/baremetal.py
@@ -0,0 +1,14 @@
+
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
+from oeqa.selftest.case import OESelftestTestCase
+from oeqa.utils.commands import bitbake
+
+class BaremetalTest(OESelftestTestCase):
+ def test_baremetal(self):
+ self.write_config('TCLIBC = "baremetal"')
+ bitbake('baremetal-helloworld')
diff --git a/meta/lib/oeqa/selftest/bblayers.py b/meta/lib/oeqa/selftest/cases/bblayers.py
index d23675e84a..b048948386 100644
--- a/meta/lib/oeqa/selftest/bblayers.py
+++ b/meta/lib/oeqa/selftest/cases/bblayers.py
@@ -1,39 +1,48 @@
-import unittest
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
import os
-import logging
import re
-import shutil
import oeqa.utils.ftools as ftools
-from oeqa.selftest.base import oeSelfTest
-from oeqa.utils.commands import runCmd, get_bb_var
-from oeqa.utils.decorators import testcase
+from oeqa.utils.commands import runCmd, get_bb_var, get_bb_vars, bitbake
+
+from oeqa.selftest.case import OESelftestTestCase
+
+class BitbakeLayers(OESelftestTestCase):
-class BitbakeLayers(oeSelfTest):
+ @classmethod
+ def setUpClass(cls):
+ super(BitbakeLayers, cls).setUpClass()
+ bitbake("python3-jsonschema-native")
+ bitbake("-c addto_recipe_sysroot python3-jsonschema-native")
+
+ def test_bitbakelayers_layerindexshowdepends(self):
+ result = runCmd('bitbake-layers layerindex-show-depends meta-poky')
+ find_in_contents = re.search("openembedded-core", result.output)
+ self.assertTrue(find_in_contents, msg = "openembedded-core should have been listed at this step. bitbake-layers layerindex-show-depends meta-poky output: %s" % result.output)
- @testcase(756)
def test_bitbakelayers_showcrossdepends(self):
result = runCmd('bitbake-layers show-cross-depends')
- self.assertTrue('aspell' in result.output, msg = "No dependencies were shown. bitbake-layers show-cross-depends output: %s" % result.output)
+ self.assertIn('aspell', result.output)
- @testcase(83)
def test_bitbakelayers_showlayers(self):
result = runCmd('bitbake-layers show-layers')
- self.assertTrue('meta-selftest' in result.output, msg = "No layers were shown. bitbake-layers show-layers output: %s" % result.output)
+ self.assertIn('meta-selftest', result.output)
- @testcase(93)
def test_bitbakelayers_showappends(self):
recipe = "xcursor-transparent-theme"
bb_file = self.get_recipe_basename(recipe)
result = runCmd('bitbake-layers show-appends')
- self.assertTrue(bb_file in result.output, msg="%s file was not recognised. bitbake-layers show-appends output: %s" % (bb_file, result.output))
+ self.assertIn(bb_file, result.output)
- @testcase(90)
def test_bitbakelayers_showoverlayed(self):
result = runCmd('bitbake-layers show-overlayed')
- self.assertTrue('aspell' in result.output, msg="aspell overlayed recipe was not recognised bitbake-layers show-overlayed %s" % result.output)
+ self.assertIn('aspell', result.output)
- @testcase(95)
def test_bitbakelayers_flatten(self):
recipe = "xcursor-transparent-theme"
recipe_path = "recipes-graphics/xcursor-transparent-theme"
@@ -48,7 +57,6 @@ class BitbakeLayers(oeSelfTest):
find_in_contents = re.search("##### bbappended from meta-selftest #####\n(.*\n)*include test_recipe.inc", contents)
self.assertTrue(find_in_contents, msg = "Flattening layers did not work. bitbake-layers flatten output: %s" % result.output)
- @testcase(1195)
def test_bitbakelayers_add_remove(self):
test_layer = os.path.join(get_bb_var('COREBASE'), 'meta-skeleton')
result = runCmd('bitbake-layers show-layers')
@@ -66,22 +74,16 @@ class BitbakeLayers(oeSelfTest):
result = runCmd('bitbake-layers show-layers')
self.assertNotIn('meta-skeleton', result.output, msg = "meta-skeleton should have been removed at this step. bitbake-layers show-layers output: %s" % result.output)
- @testcase(1384)
def test_bitbakelayers_showrecipes(self):
result = runCmd('bitbake-layers show-recipes')
self.assertIn('aspell:', result.output)
self.assertIn('mtd-utils:', result.output)
- self.assertIn('linux-yocto:', result.output)
self.assertIn('core-image-minimal:', result.output)
result = runCmd('bitbake-layers show-recipes mtd-utils')
self.assertIn('mtd-utils:', result.output)
self.assertNotIn('aspell:', result.output)
- result = runCmd('bitbake-layers show-recipes -i kernel')
- self.assertIn('linux-yocto:', result.output)
- self.assertNotIn('mtd-utils:', result.output)
result = runCmd('bitbake-layers show-recipes -i image')
self.assertIn('core-image-minimal', result.output)
- self.assertNotIn('linux-yocto:', result.output)
self.assertNotIn('mtd-utils:', result.output)
result = runCmd('bitbake-layers show-recipes -i cmake,pkgconfig')
self.assertIn('libproxy:', result.output)
@@ -92,6 +94,36 @@ class BitbakeLayers(oeSelfTest):
self.assertNotEqual(result.status, 0, 'bitbake-layers show-recipes -i nonexistentclass should have failed')
self.assertIn('ERROR:', result.output)
+ def test_bitbakelayers_createlayer(self):
+ priority = 10
+ layername = 'test-bitbakelayer-layercreate'
+ layerpath = os.path.join(self.builddir, layername)
+ self.assertFalse(os.path.exists(layerpath), '%s should not exist at this point in time' % layerpath)
+ result = runCmd('bitbake-layers create-layer --priority=%d %s' % (priority, layerpath))
+ self.track_for_cleanup(layerpath)
+ result = runCmd('bitbake-layers add-layer %s' % layerpath)
+ self.add_command_to_tearDown('bitbake-layers remove-layer %s' % layerpath)
+ result = runCmd('bitbake-layers show-layers')
+ find_in_contents = re.search(re.escape(layername) + r'\s+' + re.escape(layerpath) + r'\s+' + re.escape(str(priority)), result.output)
+ self.assertTrue(find_in_contents, "%s not found in layers\n%s" % (layername, result.output))
+
+ layervars = ['BBFILE_PRIORITY', 'BBFILE_PATTERN', 'LAYERDEPENDS', 'LAYERSERIES_COMPAT']
+ bb_vars = get_bb_vars(['BBFILE_COLLECTIONS'] + ['%s_%s' % (v, layername) for v in layervars])
+
+ for v in layervars:
+ varname = '%s_%s' % (v, layername)
+ self.assertIsNotNone(bb_vars[varname], "%s not found" % varname)
+
+ find_in_contents = re.search(r'(^|\s)' + re.escape(layername) + r'($|\s)', bb_vars['BBFILE_COLLECTIONS'])
+ self.assertTrue(find_in_contents, "%s not in BBFILE_COLLECTIONS" % layername)
+
+ self.assertEqual(bb_vars['BBFILE_PRIORITY_%s' % layername], str(priority), 'BBFILE_PRIORITY_%s != %d' % (layername, priority))
+
+ result = runCmd('bitbake-layers save-build-conf {} {}'.format(layerpath, "buildconf-1"))
+ for f in ('local.conf.sample', 'bblayers.conf.sample', 'conf-notes.txt'):
+ fullpath = os.path.join(layerpath, "conf", "templates", "buildconf-1", f)
+ self.assertTrue(os.path.exists(fullpath), "Template configuration file {} not found".format(fullpath))
+
def get_recipe_basename(self, recipe):
recipe_file = ""
result = runCmd("bitbake-layers show-recipes -f %s" % recipe)
@@ -102,3 +134,35 @@ class BitbakeLayers(oeSelfTest):
self.assertTrue(os.path.isfile(recipe_file), msg = "Can't find recipe file for %s" % recipe)
return os.path.basename(recipe_file)
+
+ def validate_layersjson(self, json):
+ python = os.path.join(get_bb_var('STAGING_BINDIR', 'python3-jsonschema-native'), 'nativepython3')
+ jsonvalidator = os.path.join(get_bb_var('STAGING_BINDIR', 'python3-jsonschema-native'), 'jsonschema')
+ jsonschema = os.path.join(get_bb_var('COREBASE'), 'meta/files/layers.schema.json')
+ result = runCmd("{} {} -i {} {}".format(python, jsonvalidator, json, jsonschema))
+
+ def test_validate_examplelayersjson(self):
+ json = os.path.join(get_bb_var('COREBASE'), "meta/files/layers.example.json")
+ self.validate_layersjson(json)
+
+ def test_bitbakelayers_setup(self):
+ result = runCmd('bitbake-layers create-layers-setup {}'.format(self.testlayer_path))
+ jsonfile = os.path.join(self.testlayer_path, "setup-layers.json")
+ self.validate_layersjson(jsonfile)
+
+ # The revision-under-test may not necessarily be available on the remote server,
+ # so replace it with a revision that has a yocto-4.0 tag.
+ import json
+ with open(jsonfile) as f:
+ data = json.load(f)
+ for s in data['sources']:
+ data['sources'][s]['git-remote']['rev'] = '00cfdde791a0176c134f31e5a09eff725e75b905'
+ with open(jsonfile, 'w') as f:
+ json.dump(data, f)
+
+ testcheckoutdir = os.path.join(self.builddir, 'test-layer-checkout')
+ result = runCmd('{}/setup-layers --destdir {}'.format(self.testlayer_path, testcheckoutdir))
+ # May not necessarily be named 'poky' or 'openembedded-core'
+ oecoredir = os.listdir(testcheckoutdir)[0]
+ testcheckoutfile = os.path.join(testcheckoutdir, oecoredir, "oe-init-build-env")
+ self.assertTrue(os.path.exists(testcheckoutfile), "File {} not found in test layer checkout".format(testcheckoutfile))
diff --git a/meta/lib/oeqa/selftest/cases/bblogging.py b/meta/lib/oeqa/selftest/cases/bblogging.py
new file mode 100644
index 0000000000..1534a36a85
--- /dev/null
+++ b/meta/lib/oeqa/selftest/cases/bblogging.py
@@ -0,0 +1,188 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
+
+from oeqa.selftest.case import OESelftestTestCase
+from oeqa.utils.commands import bitbake
+
+class BitBakeLogging(OESelftestTestCase):
+
+ def assertCount(self, item, entry, count):
+ self.assertEqual(item.count(entry), count, msg="Output:\n'''\n%s\n'''\ndoesn't contain %d copies of:\n'''\n%s\n'''\n" % (item, count, entry))
+
+ def test_shell_loggingA(self):
+ # no logs, no verbose
+ self.write_config('BBINCLUDELOGS = ""')
+ result = bitbake("logging-test -c shelltest -f", ignore_status = True)
+ self.assertIn("ERROR: Logfile of failure stored in:", result.output)
+ self.assertNotIn("This is shell stdout", result.output)
+ self.assertNotIn("This is shell stderr", result.output)
+
+ def test_shell_loggingB(self):
+ # logs, no verbose
+ self.write_config('BBINCLUDELOGS = "yes"')
+ result = bitbake("logging-test -c shelltest -f", ignore_status = True)
+ self.assertIn("ERROR: Logfile of failure stored in:", result.output)
+ self.assertCount(result.output, "This is shell stdout", 1)
+ self.assertCount(result.output, "This is shell stderr", 1)
+
+ def test_shell_loggingC(self):
+ # no logs, verbose
+ self.write_config('BBINCLUDELOGS = ""')
+ result = bitbake("logging-test -c shelltest -f -v", ignore_status = True)
+ self.assertIn("ERROR: Logfile of failure stored in:", result.output)
+ # two copies due to set +x
+ self.assertCount(result.output, "This is shell stdout", 2)
+ self.assertCount(result.output, "This is shell stderr", 2)
+
+ def test_shell_loggingD(self):
+ # logs, verbose
+ self.write_config('BBINCLUDELOGS = "yes"')
+ result = bitbake("logging-test -c shelltest -f -v", ignore_status = True)
+ self.assertIn("ERROR: Logfile of failure stored in:", result.output)
+ # two copies due to set +x
+ self.assertCount(result.output, "This is shell stdout", 2)
+ self.assertCount(result.output, "This is shell stderr", 2)
+
+ def test_python_exec_func_shell_loggingA(self):
+ # no logs, no verbose
+ self.write_config('BBINCLUDELOGS = ""')
+ result = bitbake("logging-test -c pythontest_exec_func_shell -f",
+ ignore_status = True)
+ self.assertIn("ERROR: Logfile of failure stored in:", result.output)
+ self.assertNotIn("This is shell stdout", result.output)
+ self.assertNotIn("This is shell stderr", result.output)
+
+ def test_python_exec_func_shell_loggingB(self):
+ # logs, no verbose
+ self.write_config('BBINCLUDELOGS = "yes"')
+ result = bitbake("logging-test -c pythontest_exec_func_shell -f",
+ ignore_status = True)
+ self.assertIn("ERROR: Logfile of failure stored in:", result.output)
+ self.assertCount(result.output, "This is shell stdout", 1)
+ self.assertCount(result.output, "This is shell stderr", 1)
+
+ def test_python_exec_func_shell_loggingC(self):
+ # no logs, verbose
+ self.write_config('BBINCLUDELOGS = ""')
+ result = bitbake("logging-test -c pythontest_exec_func_shell -f -v",
+ ignore_status = True)
+ self.assertIn("ERROR: Logfile of failure stored in:", result.output)
+ # two copies due to set +x
+ self.assertCount(result.output, "This is shell stdout", 2)
+ self.assertCount(result.output, "This is shell stderr", 2)
+
+ def test_python_exec_func_shell_loggingD(self):
+ # logs, verbose
+ self.write_config('BBINCLUDELOGS = "yes"')
+ result = bitbake("logging-test -c pythontest_exec_func_shell -f -v",
+ ignore_status = True)
+ self.assertIn("ERROR: Logfile of failure stored in:", result.output)
+ # two copies due to set +x
+ self.assertCount(result.output, "This is shell stdout", 2)
+ self.assertCount(result.output, "This is shell stderr", 2)
+
+ def test_python_exit_loggingA(self):
+ # no logs, no verbose
+ self.write_config('BBINCLUDELOGS = ""')
+ result = bitbake("logging-test -c pythontest_exit -f", ignore_status = True)
+ self.assertIn("ERROR: Logfile of failure stored in:", result.output)
+ self.assertNotIn("This is python stdout", result.output)
+
+ def test_python_exit_loggingB(self):
+ # logs, no verbose
+ self.write_config('BBINCLUDELOGS = "yes"')
+ result = bitbake("logging-test -c pythontest_exit -f", ignore_status = True)
+ self.assertIn("ERROR: Logfile of failure stored in:", result.output)
+ # A sys.exit() should include the output
+ self.assertCount(result.output, "This is python stdout", 1)
+
+ def test_python_exit_loggingC(self):
+ # no logs, verbose
+ self.write_config('BBINCLUDELOGS = ""')
+ result = bitbake("logging-test -c pythontest_exit -f -v", ignore_status = True)
+ self.assertIn("ERROR: Logfile of failure stored in:", result.output)
+ # python tasks don't log output with -v currently
+ #self.assertCount(result.output, "This is python stdout", 1)
+
+ def test_python_exit_loggingD(self):
+ # logs, verbose
+ self.write_config('BBINCLUDELOGS = "yes"')
+ result = bitbake("logging-test -c pythontest_exit -f -v", ignore_status = True)
+ self.assertIn("ERROR: Logfile of failure stored in:", result.output)
+ # python tasks don't log output with -v currently
+ #self.assertCount(result.output, "This is python stdout", 1)
+
+ def test_python_exec_func_python_loggingA(self):
+ # no logs, no verbose
+ self.write_config('BBINCLUDELOGS = ""')
+ result = bitbake("logging-test -c pythontest_exec_func_python -f",
+ ignore_status = True)
+ self.assertIn("ERROR: Logfile of failure stored in:", result.output)
+ self.assertNotIn("This is python stdout", result.output)
+
+ def test_python_exec_func_python_loggingB(self):
+ # logs, no verbose
+ self.write_config('BBINCLUDELOGS = "yes"')
+ result = bitbake("logging-test -c pythontest_exec_func_python -f",
+ ignore_status = True)
+ self.assertIn("ERROR: Logfile of failure stored in:", result.output)
+ # A sys.exit() should include the output
+ self.assertCount(result.output, "This is python stdout", 1)
+
+ def test_python_exec_func_python_loggingC(self):
+ # no logs, verbose
+ self.write_config('BBINCLUDELOGS = ""')
+ result = bitbake("logging-test -c pythontest_exec_func_python -f -v",
+ ignore_status = True)
+ self.assertIn("ERROR: Logfile of failure stored in:", result.output)
+ # python tasks don't log output with -v currently
+ #self.assertCount(result.output, "This is python stdout", 1)
+
+ def test_python_exec_func_python_loggingD(self):
+ # logs, verbose
+ self.write_config('BBINCLUDELOGS = "yes"')
+ result = bitbake("logging-test -c pythontest_exec_func_python -f -v",
+ ignore_status = True)
+ self.assertIn("ERROR: Logfile of failure stored in:", result.output)
+ # python tasks don't log output with -v currently
+ #self.assertCount(result.output, "This is python stdout", 1)
+
+ def test_python_fatal_loggingA(self):
+ # no logs, no verbose
+ self.write_config('BBINCLUDELOGS = ""')
+ result = bitbake("logging-test -c pythontest_fatal -f", ignore_status = True)
+ self.assertIn("ERROR: Logfile of failure stored in:", result.output)
+ self.assertNotIn("This is python fatal test stdout", result.output)
+ self.assertCount(result.output, "This is a fatal error", 1)
+
+ def test_python_fatal_loggingB(self):
+ # logs, no verbose
+ self.write_config('BBINCLUDELOGS = "yes"')
+ result = bitbake("logging-test -c pythontest_fatal -f", ignore_status = True)
+ self.assertIn("ERROR: Logfile of failure stored in:", result.output)
+ # A bb.fatal() should not include the output
+ self.assertNotIn("This is python fatal test stdout", result.output)
+ self.assertCount(result.output, "This is a fatal error", 1)
+
+ def test_python_fatal_loggingC(self):
+ # no logs, verbose
+ self.write_config('BBINCLUDELOGS = ""')
+ result = bitbake("logging-test -c pythontest_fatal -f -v", ignore_status = True)
+ self.assertIn("ERROR: Logfile of failure stored in:", result.output)
+ # python tasks don't log output with -v currently
+ #self.assertCount(result.output, "This is python fatal test stdout", 1)
+ self.assertCount(result.output, "This is a fatal error", 1)
+
+ def test_python_fatal_loggingD(self):
+ # logs, verbose
+ self.write_config('BBINCLUDELOGS = "yes"')
+ result = bitbake("logging-test -c pythontest_fatal -f -v", ignore_status = True)
+ self.assertIn("ERROR: Logfile of failure stored in:", result.output)
+ # python tasks don't log output with -v currently
+ #self.assertCount(result.output, "This is python fatal test stdout", 1)
+ self.assertCount(result.output, "This is a fatal error", 1)
+
diff --git a/meta/lib/oeqa/selftest/cases/bbtests.py b/meta/lib/oeqa/selftest/cases/bbtests.py
new file mode 100644
index 0000000000..d97bda13c2
--- /dev/null
+++ b/meta/lib/oeqa/selftest/cases/bbtests.py
@@ -0,0 +1,353 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
+import os
+import re
+
+import oeqa.utils.ftools as ftools
+from oeqa.utils.commands import runCmd, bitbake, get_bb_var, get_bb_vars
+
+from oeqa.selftest.case import OESelftestTestCase
+
+class BitbakeTests(OESelftestTestCase):
+
+ def getline(self, res, line):
+ for l in res.output.split('\n'):
+ if line in l:
+ return l
+
+ # Test bitbake can run from the <builddir>/conf directory
+ def test_run_bitbake_from_dir_1(self):
+ os.chdir(os.path.join(self.builddir, 'conf'))
+ self.assertEqual(bitbake('-e').status, 0, msg = "bitbake couldn't run from \"conf\" dir")
+
+ # Test bitbake can run from the <builddir>'s parent directory
+ def test_run_bitbake_from_dir_2(self):
+ my_env = os.environ.copy()
+ my_env['BBPATH'] = my_env['BUILDDIR']
+ os.chdir(os.path.dirname(os.environ['BUILDDIR']))
+ self.assertEqual(bitbake('-e', env=my_env).status, 0, msg = "bitbake couldn't run from builddir's parent directory")
+
+ # Test bitbake can run from some other random system location (we use /tmp/)
+ def test_run_bitbake_from_dir_3(self):
+ my_env = os.environ.copy()
+ my_env['BBPATH'] = my_env['BUILDDIR']
+ os.chdir("/tmp/")
+ self.assertEqual(bitbake('-e', env=my_env).status, 0, msg = "bitbake couldn't run from /tmp/")
+
+
+ def test_event_handler(self):
+ self.write_config("INHERIT += \"test_events\"")
+ result = bitbake('m4-native')
+ find_build_started = re.search(r"NOTE: Test for bb\.event\.BuildStarted(\n.*)*NOTE: Executing.*Tasks", result.output)
+ find_build_completed = re.search(r"Tasks Summary:.*(\n.*)*NOTE: Test for bb\.event\.BuildCompleted", result.output)
+ self.assertTrue(find_build_started, msg = "Match failed in:\n%s" % result.output)
+ self.assertTrue(find_build_completed, msg = "Match failed in:\n%s" % result.output)
+ self.assertNotIn('Test for bb.event.InvalidEvent', result.output)
+
+ def test_local_sstate(self):
+ bitbake('m4-native')
+ bitbake('m4-native -cclean')
+ result = bitbake('m4-native')
+ find_setscene = re.search("m4-native.*do_.*_setscene", result.output)
+ self.assertTrue(find_setscene, msg = "No \"m4-native.*do_.*_setscene\" message found during bitbake m4-native. bitbake output: %s" % result.output )
+
+ def test_bitbake_invalid_recipe(self):
+ result = bitbake('-b asdf', ignore_status=True)
+ self.assertTrue("ERROR: Unable to find any recipe file matching 'asdf'" in result.output, msg = "Though asdf recipe doesn't exist, bitbake didn't output any err. message. bitbake output: %s" % result.output)
+
+ def test_bitbake_invalid_target(self):
+ result = bitbake('asdf', ignore_status=True)
+ self.assertIn("ERROR: Nothing PROVIDES 'asdf'", result.output)
+
+ def test_warnings_errors(self):
+ result = bitbake('-b asdf', ignore_status=True)
+ find_warnings = re.search("Summary: There w.{2,3}? [1-9][0-9]* WARNING messages*", result.output)
+ find_errors = re.search("Summary: There w.{2,3}? [1-9][0-9]* ERROR messages*", result.output)
+ self.assertTrue(find_warnings, msg="Did not find the mumber of warnings at the end of the build:\n" + result.output)
+ self.assertTrue(find_errors, msg="Did not find the mumber of errors at the end of the build:\n" + result.output)
+
+ def test_invalid_patch(self):
+ # This patch should fail to apply.
+ self.write_recipeinc('man-db', 'FILESEXTRAPATHS:prepend := "${THISDIR}/files:"\nSRC_URI += "file://0001-Test-patch-here.patch"')
+ self.write_config("INHERIT:remove = \"report-error\"")
+ result = bitbake('man-db -c patch', ignore_status=True)
+ self.delete_recipeinc('man-db')
+ bitbake('-cclean man-db')
+ found = False
+ for l in result.output.split('\n'):
+ if l.startswith("ERROR:") and "failed" in l and "do_patch" in l:
+ found = l
+ self.assertTrue(found and found.startswith("ERROR:"), msg = "Incorrectly formed patch application didn't fail. bitbake output: %s" % result.output)
+
+ def test_force_task_1(self):
+ # test 1 from bug 5875
+ import uuid
+ test_recipe = 'zlib'
+ # Need to use uuid otherwise hash equivlance would change the workflow
+ test_data = "Microsoft Made No Profit From Anyone's Zunes Yo %s" % uuid.uuid1()
+ bb_vars = get_bb_vars(['D', 'PKGDEST', 'mandir'], test_recipe)
+ image_dir = bb_vars['D']
+ pkgsplit_dir = bb_vars['PKGDEST']
+ man_dir = bb_vars['mandir']
+ self.write_config("PACKAGE_CLASSES = \"package_rpm\"")
+
+ bitbake('-c clean %s' % test_recipe)
+ bitbake('-c package -f %s' % test_recipe)
+ self.add_command_to_tearDown('bitbake -c clean %s' % test_recipe)
+
+ man_file = os.path.join(image_dir + man_dir, 'man3/zlib.3')
+ ftools.append_file(man_file, test_data)
+ bitbake('-c package -f %s' % test_recipe)
+
+ man_split_file = os.path.join(pkgsplit_dir, 'zlib-doc' + man_dir, 'man3/zlib.3')
+ man_split_content = ftools.read_file(man_split_file)
+ self.assertIn(test_data, man_split_content, 'The man file has not changed in packages-split.')
+
+ ret = bitbake(test_recipe)
+ self.assertIn('task do_package_write_rpm:', ret.output, 'Task do_package_write_rpm did not re-executed.')
+
+ def test_force_task_2(self):
+ # test 2 from bug 5875
+ test_recipe = 'zlib'
+
+ bitbake(test_recipe)
+ self.add_command_to_tearDown('bitbake -c clean %s' % test_recipe)
+
+ result = bitbake('-C compile %s' % test_recipe)
+ look_for_tasks = ['do_compile:', 'do_install:', 'do_populate_sysroot:', 'do_package:']
+ for task in look_for_tasks:
+ self.assertIn(task, result.output, msg="Couldn't find %s task.")
+
+ def test_bitbake_g(self):
+ recipe = 'base-files'
+ result = bitbake('-g %s' % recipe)
+ for f in ['pn-buildlist', 'task-depends.dot']:
+ self.addCleanup(os.remove, f)
+ self.assertTrue('Task dependencies saved to \'task-depends.dot\'' in result.output, msg = "No task dependency \"task-depends.dot\" file was generated for the given task target. bitbake output: %s" % result.output)
+ self.assertIn(recipe, ftools.read_file(os.path.join(self.builddir, 'task-depends.dot')))
+
+ def test_image_manifest(self):
+ bitbake('core-image-minimal')
+ bb_vars = get_bb_vars(["DEPLOY_DIR_IMAGE", "IMAGE_LINK_NAME"], "core-image-minimal")
+ deploydir = bb_vars["DEPLOY_DIR_IMAGE"]
+ imagename = bb_vars["IMAGE_LINK_NAME"]
+ manifest = os.path.join(deploydir, imagename + ".manifest")
+ self.assertTrue(os.path.islink(manifest), msg="No manifest file created for image. It should have been created in %s" % manifest)
+
+ def test_invalid_recipe_src_uri(self):
+ data = 'SRC_URI = "file://invalid"'
+ self.write_recipeinc('man-db', data)
+ self.write_config("""DL_DIR = \"${TOPDIR}/download-selftest\"
+SSTATE_DIR = \"${TOPDIR}/download-selftest\"
+INHERIT:remove = \"report-error\"
+""")
+ self.track_for_cleanup(os.path.join(self.builddir, "download-selftest"))
+
+ result = bitbake('-c fetch man-db', ignore_status=True)
+ self.delete_recipeinc('man-db')
+ self.assertEqual(result.status, 1, msg="Command succeded when it should have failed. bitbake output: %s" % result.output)
+ self.assertIn('Unable to get checksum for man-db SRC_URI entry invalid: file could not be found', result.output)
+
+ def test_rename_downloaded_file(self):
+ # TODO unique dldir instead of using cleanall
+ # TODO: need to set sstatedir?
+ self.write_config("""DL_DIR = \"${TOPDIR}/download-selftest\"
+SSTATE_DIR = \"${TOPDIR}/download-selftest\"
+""")
+ self.track_for_cleanup(os.path.join(self.builddir, "download-selftest"))
+
+ data = 'SRC_URI = "https://downloads.yoctoproject.org/mirror/sources/aspell-${PV}.tar.gz;downloadfilename=test-aspell.tar.gz"'
+ self.write_recipeinc('aspell', data)
+ result = bitbake('-f -c fetch aspell', ignore_status=True)
+ self.delete_recipeinc('aspell')
+ self.assertEqual(result.status, 0, msg = "Couldn't fetch aspell. %s" % result.output)
+ dl_dir = get_bb_var("DL_DIR")
+ self.assertTrue(os.path.isfile(os.path.join(dl_dir, 'test-aspell.tar.gz')), msg = "File rename failed. No corresponding test-aspell.tar.gz file found under %s" % dl_dir)
+ self.assertTrue(os.path.isfile(os.path.join(dl_dir, 'test-aspell.tar.gz.done')), "File rename failed. No corresponding test-aspell.tar.gz.done file found under %s" % dl_dir)
+
+ def test_environment(self):
+ self.write_config("TEST_ENV=\"localconf\"")
+ result = runCmd('bitbake -e | grep TEST_ENV=')
+ self.assertIn('localconf', result.output)
+
+ def test_dry_run(self):
+ result = runCmd('bitbake -n m4-native')
+ self.assertEqual(0, result.status, "bitbake dry run didn't run as expected. %s" % result.output)
+
+ def test_just_parse(self):
+ result = runCmd('bitbake -p')
+ self.assertEqual(0, result.status, "errors encountered when parsing recipes. %s" % result.output)
+
+ def test_version(self):
+ result = runCmd('bitbake -s | grep wget')
+ find = re.search(r"wget *:([0-9a-zA-Z\.\-]+)", result.output)
+ self.assertTrue(find, "No version returned for searched recipe. bitbake output: %s" % result.output)
+
+ def test_prefile(self):
+ preconf = os.path.join(self.builddir, 'conf/prefile.conf')
+ self.track_for_cleanup(preconf)
+ ftools.write_file(preconf ,"TEST_PREFILE=\"prefile\"")
+ result = runCmd('bitbake -r conf/prefile.conf -e | grep TEST_PREFILE=')
+ self.assertIn('prefile', result.output)
+ self.write_config("TEST_PREFILE=\"localconf\"")
+ result = runCmd('bitbake -r conf/prefile.conf -e | grep TEST_PREFILE=')
+ self.assertIn('localconf', result.output)
+
+ def test_postfile(self):
+ postconf = os.path.join(self.builddir, 'conf/postfile.conf')
+ self.track_for_cleanup(postconf)
+ ftools.write_file(postconf , "TEST_POSTFILE=\"postfile\"")
+ self.write_config("TEST_POSTFILE=\"localconf\"")
+ result = runCmd('bitbake -R conf/postfile.conf -e | grep TEST_POSTFILE=')
+ self.assertIn('postfile', result.output)
+
+ def test_checkuri(self):
+ result = runCmd('bitbake -c checkuri m4')
+ self.assertEqual(0, result.status, msg = "\"checkuri\" task was not executed. bitbake output: %s" % result.output)
+
+ def test_continue(self):
+ self.write_config("""DL_DIR = \"${TOPDIR}/download-selftest\"
+SSTATE_DIR = \"${TOPDIR}/download-selftest\"
+INHERIT:remove = \"report-error\"
+""")
+ self.track_for_cleanup(os.path.join(self.builddir, "download-selftest"))
+ self.write_recipeinc('man-db',"\ndo_fail_task () {\nexit 1 \n}\n\naddtask do_fail_task before do_fetch\n" )
+ runCmd('bitbake -c cleanall man-db xcursor-transparent-theme')
+ result = runCmd('bitbake -c unpack -k man-db xcursor-transparent-theme', ignore_status=True)
+ errorpos = result.output.find('ERROR: Function failed: do_fail_task')
+ manver = re.search("NOTE: recipe xcursor-transparent-theme-(.*?): task do_unpack: Started", result.output)
+ continuepos = result.output.find('NOTE: recipe xcursor-transparent-theme-%s: task do_unpack: Started' % manver.group(1))
+ self.assertLess(errorpos,continuepos, msg = "bitbake didn't pass do_fail_task. bitbake output: %s" % result.output)
+
+ def test_non_gplv3(self):
+ self.write_config('INCOMPATIBLE_LICENSE = "GPL-3.0-or-later"')
+ result = bitbake('selftest-ed', ignore_status=True)
+ self.assertEqual(result.status, 0, "Bitbake failed, exit code %s, output %s" % (result.status, result.output))
+ lic_dir = get_bb_var('LICENSE_DIRECTORY')
+ self.assertFalse(os.path.isfile(os.path.join(lic_dir, 'selftest-ed/generic_GPL-3.0-or-later')))
+ self.assertTrue(os.path.isfile(os.path.join(lic_dir, 'selftest-ed/generic_GPL-2.0-or-later')))
+
+ def test_setscene_only(self):
+ """ Bitbake option to restore from sstate only within a build (i.e. execute no real tasks, only setscene)"""
+ test_recipe = 'ed'
+
+ bitbake(test_recipe)
+ bitbake('-c clean %s' % test_recipe)
+ ret = bitbake('--setscene-only %s' % test_recipe)
+
+ tasks = re.findall(r'task\s+(do_\S+):', ret.output)
+
+ for task in tasks:
+ self.assertIn('_setscene', task, 'A task different from _setscene ran: %s.\n'
+ 'Executed tasks were: %s' % (task, str(tasks)))
+
+ def test_skip_setscene(self):
+ test_recipe = 'ed'
+
+ bitbake(test_recipe)
+ bitbake('-c clean %s' % test_recipe)
+
+ ret = bitbake('--setscene-only %s' % test_recipe)
+ tasks = re.findall(r'task\s+(do_\S+):', ret.output)
+
+ for task in tasks:
+ self.assertIn('_setscene', task, 'A task different from _setscene ran: %s.\n'
+ 'Executed tasks were: %s' % (task, str(tasks)))
+
+ # Run without setscene. Should do nothing
+ ret = bitbake('--skip-setscene %s' % test_recipe)
+ tasks = re.findall(r'task\s+(do_\S+):', ret.output)
+
+ self.assertFalse(tasks, 'Tasks %s ran when they should not have' % (str(tasks)))
+
+ # Clean (leave sstate cache) and run with --skip-setscene. No setscene
+ # tasks should run
+ bitbake('-c clean %s' % test_recipe)
+
+ ret = bitbake('--skip-setscene %s' % test_recipe)
+ tasks = re.findall(r'task\s+(do_\S+):', ret.output)
+
+ for task in tasks:
+ self.assertNotIn('_setscene', task, 'A _setscene task ran: %s.\n'
+ 'Executed tasks were: %s' % (task, str(tasks)))
+
+ def test_bbappend_order(self):
+ """ Bitbake should bbappend to recipe in a predictable order """
+ test_recipe = 'ed'
+ bb_vars = get_bb_vars(['SUMMARY', 'PV'], test_recipe)
+ test_recipe_summary_before = bb_vars['SUMMARY']
+ test_recipe_pv = bb_vars['PV']
+ recipe_append_file = test_recipe + '_' + test_recipe_pv + '.bbappend'
+ expected_recipe_summary = test_recipe_summary_before
+
+ for i in range(5):
+ recipe_append_dir = test_recipe + '_test_' + str(i)
+ recipe_append_path = os.path.join(self.testlayer_path, 'recipes-test', recipe_append_dir, recipe_append_file)
+ os.mkdir(os.path.join(self.testlayer_path, 'recipes-test', recipe_append_dir))
+ feature = 'SUMMARY += "%s"\n' % i
+ ftools.write_file(recipe_append_path, feature)
+ expected_recipe_summary += ' %s' % i
+
+ self.add_command_to_tearDown('rm -rf %s' % os.path.join(self.testlayer_path, 'recipes-test',
+ test_recipe + '_test_*'))
+
+ test_recipe_summary_after = get_bb_var('SUMMARY', test_recipe)
+ self.assertEqual(expected_recipe_summary, test_recipe_summary_after)
+
+ def test_git_patchtool(self):
+ """ PATCHTOOL=git should work with non-git sources like tarballs
+ test recipe for the test must NOT containt git:// repository in SRC_URI
+ """
+ test_recipe = "man-db"
+ self.write_recipeinc(test_recipe, 'PATCHTOOL=\"git\"')
+ src = get_bb_var("SRC_URI",test_recipe)
+ gitscm = re.search("git://", src)
+ self.assertFalse(gitscm, "test_git_patchtool pre-condition failed: {} test recipe contains git repo!".format(test_recipe))
+ result = bitbake('{} -c patch'.format(test_recipe), ignore_status=False)
+ fatal = re.search("fatal: not a git repository (or any of the parent directories)", result.output)
+ self.assertFalse(fatal, "Failed to patch using PATCHTOOL=\"git\"")
+ self.delete_recipeinc(test_recipe)
+ bitbake('-cclean {}'.format(test_recipe))
+
+ def test_git_patchtool2(self):
+ """ Test if PATCHTOOL=git works with git repo and doesn't reinitialize it
+ """
+ test_recipe = "gitrepotest"
+ src = get_bb_var("SRC_URI",test_recipe)
+ gitscm = re.search("git://", src)
+ self.assertTrue(gitscm, "test_git_patchtool pre-condition failed: {} test recipe doesn't contains git repo!".format(test_recipe))
+ result = bitbake('{} -c patch'.format(test_recipe), ignore_status=False)
+ srcdir = get_bb_var('S', test_recipe)
+ result = runCmd("git log", cwd = srcdir)
+ self.assertFalse("bitbake_patching_started" in result.output, msg = "Repository has been reinitialized. {}".format(srcdir))
+ self.delete_recipeinc(test_recipe)
+ bitbake('-cclean {}'.format(test_recipe))
+
+
+ def test_git_unpack_nonetwork(self):
+ """
+ Test that a recipe with a floating tag that needs to be resolved upstream doesn't
+ access the network in a patch task run in a separate builld invocation
+ """
+
+ # Enable the recipe to float using a distro override
+ self.write_config("DISTROOVERRIDES .= \":gitunpack-enable-recipe\"")
+
+ bitbake('gitunpackoffline -c fetch')
+ bitbake('gitunpackoffline -c patch')
+
+ def test_git_unpack_nonetwork_fail(self):
+ """
+ Test that a recipe with a floating tag which doesn't call get_srcrev() in the fetcher
+ raises an error when the fetcher is called.
+ """
+
+ # Enable the recipe to float using a distro override
+ self.write_config("DISTROOVERRIDES .= \":gitunpack-enable-recipe\"")
+
+ result = bitbake('gitunpackoffline-fail -c fetch', ignore_status=True)
+ self.assertTrue(re.search("Recipe uses a floating tag/branch .* for repo .* without a fixed SRCREV yet doesn't call bb.fetch2.get_srcrev()", result.output), msg = "Recipe without PV set to SRCPV should have failed: %s" % result.output)
diff --git a/meta/lib/oeqa/selftest/cases/binutils.py b/meta/lib/oeqa/selftest/cases/binutils.py
new file mode 100644
index 0000000000..bf6fdca0d9
--- /dev/null
+++ b/meta/lib/oeqa/selftest/cases/binutils.py
@@ -0,0 +1,51 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+import os
+from oeqa.core.decorator import OETestTag
+from oeqa.core.case import OEPTestResultTestCase
+from oeqa.selftest.case import OESelftestTestCase
+from oeqa.utils.commands import bitbake, get_bb_vars
+
+def parse_values(content):
+ for i in content:
+ for v in ["PASS", "FAIL", "XPASS", "XFAIL", "UNRESOLVED", "UNSUPPORTED", "UNTESTED", "ERROR", "WARNING"]:
+ if i.startswith(v + ": "):
+ yield i[len(v) + 2:].strip(), v
+ break
+
+@OETestTag("toolchain-user", "toolchain-system")
+class BinutilsCrossSelfTest(OESelftestTestCase, OEPTestResultTestCase):
+ def test_binutils(self):
+ self.run_binutils("binutils")
+
+ def test_gas(self):
+ self.run_binutils("gas")
+
+ def test_ld(self):
+ self.run_binutils("ld")
+
+ def run_binutils(self, suite):
+ features = []
+ features.append('CHECK_TARGETS = "{0}"'.format(suite))
+ self.write_config("\n".join(features))
+
+ recipe = "binutils-cross-testsuite"
+ bb_vars = get_bb_vars(["B", "TARGET_SYS", "T"], recipe)
+ builddir, target_sys, tdir = bb_vars["B"], bb_vars["TARGET_SYS"], bb_vars["T"]
+
+ bitbake("{0} -c check".format(recipe))
+
+ sumspath = os.path.join(builddir, suite, "{0}.sum".format(suite))
+ if not os.path.exists(sumspath):
+ sumspath = os.path.join(builddir, suite, "testsuite", "{0}.sum".format(suite))
+ logpath = os.path.splitext(sumspath)[0] + ".log"
+
+ ptestsuite = "binutils-{}".format(suite) if suite != "binutils" else suite
+ self.ptest_section(ptestsuite, logfile = logpath)
+ with open(sumspath, "r") as f:
+ for test, result in parse_values(f):
+ self.ptest_result(ptestsuite, test, result)
+
diff --git a/meta/lib/oeqa/selftest/buildhistory.py b/meta/lib/oeqa/selftest/cases/buildhistory.py
index 674da6205a..2d55994916 100644
--- a/meta/lib/oeqa/selftest/buildhistory.py
+++ b/meta/lib/oeqa/selftest/cases/buildhistory.py
@@ -1,16 +1,22 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
import os
import re
import datetime
-from oeqa.selftest.base import oeSelfTest
-from oeqa.utils.commands import bitbake, get_bb_var
-from oeqa.utils.decorators import testcase
+from oeqa.selftest.case import OESelftestTestCase
+from oeqa.utils.commands import bitbake, get_bb_vars
-class BuildhistoryBase(oeSelfTest):
+class BuildhistoryBase(OESelftestTestCase):
def config_buildhistory(self, tmp_bh_location=False):
- if (not 'buildhistory' in get_bb_var('USER_CLASSES')) and (not 'buildhistory' in get_bb_var('INHERIT')):
+ bb_vars = get_bb_vars(['USER_CLASSES', 'INHERIT'])
+ if (not 'buildhistory' in bb_vars['USER_CLASSES']) and (not 'buildhistory' in bb_vars['INHERIT']):
add_buildhistory_config = 'INHERIT += "buildhistory"\nBUILDHISTORY_COMMIT = "1"'
self.append_config(add_buildhistory_config)
diff --git a/meta/lib/oeqa/selftest/cases/buildoptions.py b/meta/lib/oeqa/selftest/cases/buildoptions.py
new file mode 100644
index 0000000000..01ea4dce39
--- /dev/null
+++ b/meta/lib/oeqa/selftest/cases/buildoptions.py
@@ -0,0 +1,239 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
+import os
+import re
+import glob as g
+import shutil
+import tempfile
+from oeqa.selftest.case import OESelftestTestCase
+from oeqa.selftest.cases.buildhistory import BuildhistoryBase
+from oeqa.core.decorator.data import skipIfMachine
+from oeqa.utils.commands import bitbake, get_bb_var, get_bb_vars
+import oeqa.utils.ftools as ftools
+
+class ImageOptionsTests(OESelftestTestCase):
+
+ def test_incremental_image_generation(self):
+ image_pkgtype = get_bb_var("IMAGE_PKGTYPE")
+ if image_pkgtype != 'rpm':
+ self.skipTest('Not using RPM as main package format')
+ bitbake("-c clean core-image-minimal")
+ self.write_config('INC_RPM_IMAGE_GEN = "1"')
+ self.append_config('IMAGE_FEATURES += "ssh-server-openssh"')
+ bitbake("core-image-minimal")
+ log_data_file = os.path.join(get_bb_var("WORKDIR", "core-image-minimal"), "temp/log.do_rootfs")
+ log_data_created = ftools.read_file(log_data_file)
+ incremental_created = re.search(r"Installing\s*:\s*packagegroup-core-ssh-openssh", log_data_created)
+ self.remove_config('IMAGE_FEATURES += "ssh-server-openssh"')
+ self.assertTrue(incremental_created, msg = "Match failed in:\n%s" % log_data_created)
+ bitbake("core-image-minimal")
+ log_data_removed = ftools.read_file(log_data_file)
+ incremental_removed = re.search(r"Erasing\s*:\s*packagegroup-core-ssh-openssh", log_data_removed)
+ self.assertTrue(incremental_removed, msg = "Match failed in:\n%s" % log_data_removed)
+
+ def test_ccache_tool(self):
+ bitbake("ccache-native")
+ bb_vars = get_bb_vars(['SYSROOT_DESTDIR', 'bindir'], 'ccache-native')
+ p = bb_vars['SYSROOT_DESTDIR'] + bb_vars['bindir'] + "/" + "ccache"
+ self.assertTrue(os.path.isfile(p), msg = "No ccache found (%s)" % p)
+ self.write_config('INHERIT += "ccache"')
+ recipe = "libgcc-initial"
+ self.add_command_to_tearDown('bitbake -c clean %s' % recipe)
+ bitbake("%s -c clean" % recipe)
+ bitbake("%s -f -c compile" % recipe)
+ log_compile = os.path.join(get_bb_var("WORKDIR", recipe), "temp/log.do_compile")
+ with open(log_compile, "r") as f:
+ loglines = "".join(f.readlines())
+ self.assertIn("ccache", loglines, msg="No match for ccache in %s log.do_compile. For further details: %s" % (recipe , log_compile))
+
+ # https://bugzilla.yoctoproject.org/show_bug.cgi?id=14962
+ @skipIfMachine("qemuarm64", "fails on qemuarm64 (uses SERIAL_CONSOLES_CHECK)")
+ def test_read_only_image(self):
+ distro_features = get_bb_var('DISTRO_FEATURES')
+ if not ('x11' in distro_features and 'opengl' in distro_features):
+ self.skipTest('core-image-sato/weston requires x11 and opengl in distro features')
+ self.write_config('IMAGE_FEATURES += "read-only-rootfs"')
+ bitbake("core-image-sato core-image-weston")
+ # do_image will fail if there are any pending postinsts
+
+class DiskMonTest(OESelftestTestCase):
+
+ def test_stoptask_behavior(self):
+ self.write_config('BB_DISKMON_DIRS = "STOPTASKS,${TMPDIR},100000G,100K"\nBB_HEARTBEAT_EVENT = "1"')
+ res = bitbake("delay -c delay", ignore_status = True)
+ self.assertTrue('ERROR: No new tasks can be executed since the disk space monitor action is "STOPTASKS"!' in res.output, msg = "Tasks should have stopped. Disk monitor is set to STOPTASK: %s" % res.output)
+ self.assertEqual(res.status, 1, msg = "bitbake reported exit code %s. It should have been 1. Bitbake output: %s" % (str(res.status), res.output))
+ self.write_config('BB_DISKMON_DIRS = "HALT,${TMPDIR},100000G,100K"\nBB_HEARTBEAT_EVENT = "1"')
+ res = bitbake("delay -c delay", ignore_status = True)
+ self.assertTrue('ERROR: Immediately halt since the disk space monitor action is "HALT"!' in res.output, "Tasks should have been halted immediately. Disk monitor is set to HALT: %s" % res.output)
+ self.assertEqual(res.status, 1, msg = "bitbake reported exit code %s. It should have been 1. Bitbake output: %s" % (str(res.status), res.output))
+ self.write_config('BB_DISKMON_DIRS = "WARN,${TMPDIR},100000G,100K"\nBB_HEARTBEAT_EVENT = "1"')
+ res = bitbake("delay -c delay")
+ self.assertTrue('WARNING: The free space' in res.output, msg = "A warning should have been displayed for disk monitor is set to WARN: %s" %res.output)
+
+class SanityOptionsTest(OESelftestTestCase):
+ def getline(self, res, line):
+ for l in res.output.split('\n'):
+ if line in l:
+ return l
+
+ def test_options_warnqa_errorqa_switch(self):
+
+ self.write_config("INHERIT:remove = \"report-error\"")
+ if "packages-list" not in get_bb_var("ERROR_QA"):
+ self.append_config("ERROR_QA:append = \" packages-list\"")
+
+ self.write_recipeinc('xcursor-transparent-theme', 'PACKAGES += \"${PN}-dbg\"')
+ self.add_command_to_tearDown('bitbake -c clean xcursor-transparent-theme')
+ res = bitbake("xcursor-transparent-theme -f -c package", ignore_status=True)
+ self.delete_recipeinc('xcursor-transparent-theme')
+ line = self.getline(res, "QA Issue: xcursor-transparent-theme-dbg is listed in PACKAGES multiple times, this leads to packaging errors.")
+ self.assertTrue(line and line.startswith("ERROR:"), msg=res.output)
+ self.assertEqual(res.status, 1, msg = "bitbake reported exit code %s. It should have been 1. Bitbake output: %s" % (str(res.status), res.output))
+ self.write_recipeinc('xcursor-transparent-theme', 'PACKAGES += \"${PN}-dbg\"')
+ self.append_config('ERROR_QA:remove = "packages-list"')
+ self.append_config('WARN_QA:append = " packages-list"')
+ res = bitbake("xcursor-transparent-theme -f -c package")
+ self.delete_recipeinc('xcursor-transparent-theme')
+ line = self.getline(res, "QA Issue: xcursor-transparent-theme-dbg is listed in PACKAGES multiple times, this leads to packaging errors.")
+ self.assertTrue(line and line.startswith("WARNING:"), msg=res.output)
+
+ def test_layer_without_git_dir(self):
+ """
+ Summary: Test that layer git revisions are displayed and do not fail without git repository
+ Expected: The build to be successful and without "fatal" errors
+ Product: oe-core
+ Author: Daniel Istrate <daniel.alexandrux.istrate@intel.com>
+ AutomatedBy: Daniel Istrate <daniel.alexandrux.istrate@intel.com>
+ """
+
+ dirpath = tempfile.mkdtemp()
+
+ dummy_layer_name = 'meta-dummy'
+ dummy_layer_path = os.path.join(dirpath, dummy_layer_name)
+ dummy_layer_conf_dir = os.path.join(dummy_layer_path, 'conf')
+ os.makedirs(dummy_layer_conf_dir)
+ dummy_layer_conf_path = os.path.join(dummy_layer_conf_dir, 'layer.conf')
+
+ dummy_layer_content = 'BBPATH .= ":${LAYERDIR}"\n' \
+ 'BBFILES += "${LAYERDIR}/recipes-*/*/*.bb ${LAYERDIR}/recipes-*/*/*.bbappend"\n' \
+ 'BBFILE_COLLECTIONS += "%s"\n' \
+ 'BBFILE_PATTERN_%s = "^${LAYERDIR}/"\n' \
+ 'BBFILE_PRIORITY_%s = "6"\n' % (dummy_layer_name, dummy_layer_name, dummy_layer_name)
+
+ ftools.write_file(dummy_layer_conf_path, dummy_layer_content)
+
+ bblayers_conf = 'BBLAYERS += "%s"\n' % dummy_layer_path
+ self.write_bblayers_config(bblayers_conf)
+
+ test_recipe = 'ed'
+
+ ret = bitbake('-n %s' % test_recipe)
+
+ err = 'fatal: Not a git repository'
+
+ shutil.rmtree(dirpath)
+
+ self.assertNotIn(err, ret.output)
+
+
+class BuildhistoryTests(BuildhistoryBase):
+
+ def test_buildhistory_basic(self):
+ self.run_buildhistory_operation('xcursor-transparent-theme')
+ self.assertTrue(os.path.isdir(get_bb_var('BUILDHISTORY_DIR')), "buildhistory dir was not created.")
+
+ def test_buildhistory_buildtime_pr_backwards(self):
+ target = 'xcursor-transparent-theme'
+ error = "ERROR:.*QA Issue: Package version for package %s went backwards which would break package feeds \(from .*-r1.* to .*-r0.*\)" % target
+ self.run_buildhistory_operation(target, target_config="PR = \"r1\"", change_bh_location=True)
+ self.run_buildhistory_operation(target, target_config="PR = \"r0\"", change_bh_location=False, expect_error=True, error_regex=error)
+
+ def test_fileinfo(self):
+ self.config_buildhistory()
+ bitbake('hicolor-icon-theme')
+ history_dir = get_bb_var('BUILDHISTORY_DIR_PACKAGE', 'hicolor-icon-theme')
+ self.assertTrue(os.path.isdir(history_dir), 'buildhistory dir was not created.')
+
+ def load_bh(f):
+ d = {}
+ for line in open(f):
+ split = [s.strip() for s in line.split('=', 1)]
+ if len(split) > 1:
+ d[split[0]] = split[1]
+ return d
+
+ data = load_bh(os.path.join(history_dir, 'hicolor-icon-theme', 'latest'))
+ self.assertIn('FILELIST', data)
+ self.assertEqual(data['FILELIST'], '/usr/share/icons/hicolor/index.theme')
+ self.assertGreater(int(data['PKGSIZE']), 0)
+
+ data = load_bh(os.path.join(history_dir, 'hicolor-icon-theme-dev', 'latest'))
+ if 'FILELIST' in data:
+ self.assertEqual(data['FILELIST'], '')
+ self.assertEqual(int(data['PKGSIZE']), 0)
+
+class ArchiverTest(OESelftestTestCase):
+ def test_arch_work_dir_and_export_source(self):
+ """
+ Test for archiving the work directory and exporting the source files.
+ """
+ self.write_config("""
+INHERIT += "archiver"
+PACKAGE_CLASSES = "package_rpm"
+ARCHIVER_MODE[src] = "original"
+ARCHIVER_MODE[srpm] = "1"
+""")
+ res = bitbake("xcursor-transparent-theme", ignore_status=True)
+ self.assertEqual(res.status, 0, "\nCouldn't build xcursortransparenttheme.\nbitbake output %s" % res.output)
+ deploy_dir_src = get_bb_var('DEPLOY_DIR_SRC')
+ pkgs_path = g.glob(str(deploy_dir_src) + "/allarch*/xcurs*")
+ src_file_glob = str(pkgs_path[0]) + "/xcursor*.src.rpm"
+ tar_file_glob = str(pkgs_path[0]) + "/xcursor*.tar.xz"
+ self.assertTrue((g.glob(src_file_glob) and g.glob(tar_file_glob)), "Couldn't find .src.rpm and .tar.xz files under %s/allarch*/xcursor*" % deploy_dir_src)
+
+class ToolchainOptions(OESelftestTestCase):
+ def test_toolchain_fortran(self):
+ """
+ Test that Fortran works by building a Hello, World binary.
+ """
+
+ features = 'FORTRAN:forcevariable = ",fortran"\n'
+ self.write_config(features)
+ bitbake('fortran-helloworld')
+
+class SourceMirroring(OESelftestTestCase):
+ # Can we download everything from the Yocto Sources Mirror over http only
+ def test_yocto_source_mirror(self):
+ self.write_config("""
+BB_ALLOWED_NETWORKS = "downloads.yoctoproject.org"
+MIRRORS = ""
+DL_DIR = "${TMPDIR}/test_downloads"
+STAMPS_DIR = "${TMPDIR}/test_stamps"
+SSTATE_DIR = "${TMPDIR}/test_sstate-cache"
+PREMIRRORS = "\\
+ bzr://.*/.* http://downloads.yoctoproject.org/mirror/sources/ \\n \\
+ cvs://.*/.* http://downloads.yoctoproject.org/mirror/sources/ \\n \\
+ git://.*/.* http://downloads.yoctoproject.org/mirror/sources/ \\n \\
+ gitsm://.*/.* http://downloads.yoctoproject.org/mirror/sources/ \\n \\
+ hg://.*/.* http://downloads.yoctoproject.org/mirror/sources/ \\n \\
+ osc://.*/.* http://downloads.yoctoproject.org/mirror/sources/ \\n \\
+ p4://.*/.* http://downloads.yoctoproject.org/mirror/sources/ \\n \\
+ svn://.*/.* http://downloads.yoctoproject.org/mirror/sources/ \\n \\
+ ftp://.*/.* http://downloads.yoctoproject.org/mirror/sources/ \\n \\
+ http://.*/.* http://downloads.yoctoproject.org/mirror/sources/ \\n \\
+ https://.*/.* http://downloads.yoctoproject.org/mirror/sources/ \\n"
+""")
+
+ bitbake("world --runall fetch")
+
+
+class Poisoning(OESelftestTestCase):
+ def test_poisoning(self):
+ res = bitbake("poison", ignore_status=True)
+ self.assertNotEqual(res.status, 0)
+ self.assertTrue("is unsafe for cross-compilation" in res.output)
diff --git a/meta/lib/oeqa/selftest/cases/containerimage.py b/meta/lib/oeqa/selftest/cases/containerimage.py
new file mode 100644
index 0000000000..23c0a1408a
--- /dev/null
+++ b/meta/lib/oeqa/selftest/cases/containerimage.py
@@ -0,0 +1,89 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
+import os
+
+from oeqa.selftest.case import OESelftestTestCase
+from oeqa.utils.commands import bitbake, get_bb_vars, runCmd
+
+# This test builds an image with using the "container" IMAGE_FSTYPE, and
+# ensures that then files in the image are only the ones expected.
+#
+# The only package added to the image is container_image_testpkg, which
+# contains one file. However, due to some other things not cleaning up during
+# rootfs creation, there is some cruft. Ideally bugs will be filed and the
+# cruft removed, but for now we ignore some known set.
+#
+# Also for performance reasons we're only checking the cruft when using ipk.
+# When using deb, and rpm it is a bit different and we could test all
+# of them, but this test is more to catch if other packages get added by
+# default other than what is in ROOTFS_BOOTSTRAP_INSTALL.
+#
+class ContainerImageTests(OESelftestTestCase):
+
+ # Verify that when specifying a IMAGE_TYPEDEP: of the form "foo.bar" that
+ # the conversion type bar gets added as a dep as well
+ def test_expected_files(self):
+
+ def get_each_path_part(path):
+ if path:
+ part = [ '.' + path + '/' ]
+ result = get_each_path_part(path.rsplit('/', 1)[0])
+ if result:
+ return part + result
+ else:
+ return part
+ else:
+ return None
+
+ self.write_config("""PREFERRED_PROVIDER_virtual/kernel = "linux-dummy"
+IMAGE_FSTYPES = "container"
+PACKAGE_CLASSES = "package_ipk"
+IMAGE_FEATURES = ""
+IMAGE_BUILDINFO_FILE = ""
+INIT_MANAGER = "sysvinit"
+IMAGE_INSTALL:remove = "ssh-pregen-hostkeys"
+
+""")
+
+ bbvars = get_bb_vars(['bindir', 'sysconfdir', 'localstatedir',
+ 'DEPLOY_DIR_IMAGE', 'IMAGE_LINK_NAME'],
+ target='container-test-image')
+ expected_files = [
+ './',
+ '.{bindir}/theapp',
+ '.{sysconfdir}/default/',
+ '.{sysconfdir}/default/postinst',
+ '.{sysconfdir}/ld.so.cache',
+ '.{sysconfdir}/timestamp',
+ '.{sysconfdir}/version',
+ './run/',
+ '.{localstatedir}/cache/',
+ '.{localstatedir}/lib/'
+ ]
+
+ expected_files = [ x.format(bindir=bbvars['bindir'],
+ sysconfdir=bbvars['sysconfdir'],
+ localstatedir=bbvars['localstatedir'])
+ for x in expected_files ]
+
+ # Since tar lists all directories individually, make sure each element
+ # from bindir, sysconfdir, etc is added
+ expected_files += get_each_path_part(bbvars['bindir'])
+ expected_files += get_each_path_part(bbvars['sysconfdir'])
+ expected_files += get_each_path_part(bbvars['localstatedir'])
+
+ expected_files = sorted(expected_files)
+
+ # Build the image of course
+ bitbake('container-test-image')
+
+ image = os.path.join(bbvars['DEPLOY_DIR_IMAGE'],
+ bbvars['IMAGE_LINK_NAME'] + '.tar.bz2')
+
+ # Ensure the files in the image are what we expect
+ result = runCmd("tar tf {} | sort".format(image), shell=True)
+ self.assertEqual(result.output.split('\n'), expected_files)
diff --git a/meta/lib/oeqa/selftest/cases/cve_check.py b/meta/lib/oeqa/selftest/cases/cve_check.py
new file mode 100644
index 0000000000..ac47af1990
--- /dev/null
+++ b/meta/lib/oeqa/selftest/cases/cve_check.py
@@ -0,0 +1,207 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
+import json
+import os
+from oeqa.selftest.case import OESelftestTestCase
+from oeqa.utils.commands import bitbake, get_bb_vars
+
+class CVECheck(OESelftestTestCase):
+
+ def test_version_compare(self):
+ from oe.cve_check import Version
+
+ result = Version("100") > Version("99")
+ self.assertTrue( result, msg="Failed to compare version '100' > '99'")
+ result = Version("2.3.1") > Version("2.2.3")
+ self.assertTrue( result, msg="Failed to compare version '2.3.1' > '2.2.3'")
+ result = Version("2021-01-21") > Version("2020-12-25")
+ self.assertTrue( result, msg="Failed to compare version '2021-01-21' > '2020-12-25'")
+ result = Version("1.2-20200910") < Version("1.2-20200920")
+ self.assertTrue( result, msg="Failed to compare version '1.2-20200910' < '1.2-20200920'")
+
+ result = Version("1.0") >= Version("1.0beta")
+ self.assertTrue( result, msg="Failed to compare version '1.0' >= '1.0beta'")
+ result = Version("1.0-rc2") > Version("1.0-rc1")
+ self.assertTrue( result, msg="Failed to compare version '1.0-rc2' > '1.0-rc1'")
+ result = Version("1.0.alpha1") < Version("1.0")
+ self.assertTrue( result, msg="Failed to compare version '1.0.alpha1' < '1.0'")
+ result = Version("1.0_dev") <= Version("1.0")
+ self.assertTrue( result, msg="Failed to compare version '1.0_dev' <= '1.0'")
+
+ # ignore "p1" and "p2", so these should be equal
+ result = Version("1.0p2") == Version("1.0p1")
+ self.assertTrue( result ,msg="Failed to compare version '1.0p2' to '1.0p1'")
+ # ignore the "b" and "r"
+ result = Version("1.0b") == Version("1.0r")
+ self.assertTrue( result ,msg="Failed to compare version '1.0b' to '1.0r'")
+
+ # consider the trailing alphabet as patched level when comparing
+ result = Version("1.0b","alphabetical") < Version("1.0r","alphabetical")
+ self.assertTrue( result ,msg="Failed to compare version with suffix '1.0b' < '1.0r'")
+ result = Version("1.0b","alphabetical") > Version("1.0","alphabetical")
+ self.assertTrue( result ,msg="Failed to compare version with suffix '1.0b' > '1.0'")
+
+ # consider the trailing "p" and "patch" as patched released when comparing
+ result = Version("1.0","patch") < Version("1.0p1","patch")
+ self.assertTrue( result ,msg="Failed to compare version with suffix '1.0' < '1.0p1'")
+ result = Version("1.0p2","patch") > Version("1.0p1","patch")
+ self.assertTrue( result ,msg="Failed to compare version with suffix '1.0p2' > '1.0p1'")
+ result = Version("1.0_patch2","patch") < Version("1.0_patch3","patch")
+ self.assertTrue( result ,msg="Failed to compare version with suffix '1.0_patch2' < '1.0_patch3'")
+
+
+ def test_recipe_report_json(self):
+ config = """
+INHERIT += "cve-check"
+CVE_CHECK_FORMAT_JSON = "1"
+"""
+ self.write_config(config)
+
+ vars = get_bb_vars(["CVE_CHECK_SUMMARY_DIR", "CVE_CHECK_SUMMARY_FILE_NAME_JSON"])
+ summary_json = os.path.join(vars["CVE_CHECK_SUMMARY_DIR"], vars["CVE_CHECK_SUMMARY_FILE_NAME_JSON"])
+ recipe_json = os.path.join(vars["CVE_CHECK_SUMMARY_DIR"], "m4-native_cve.json")
+
+ try:
+ os.remove(summary_json)
+ os.remove(recipe_json)
+ except FileNotFoundError:
+ pass
+
+ bitbake("m4-native -c cve_check")
+
+ def check_m4_json(filename):
+ with open(filename) as f:
+ report = json.load(f)
+ self.assertEqual(report["version"], "1")
+ self.assertEqual(len(report["package"]), 1)
+ package = report["package"][0]
+ self.assertEqual(package["name"], "m4-native")
+ found_cves = { issue["id"]: issue["status"] for issue in package["issue"]}
+ self.assertIn("CVE-2008-1687", found_cves)
+ self.assertEqual(found_cves["CVE-2008-1687"], "Patched")
+
+ self.assertExists(summary_json)
+ check_m4_json(summary_json)
+ self.assertExists(recipe_json)
+ check_m4_json(recipe_json)
+
+
+ def test_image_json(self):
+ config = """
+INHERIT += "cve-check"
+CVE_CHECK_FORMAT_JSON = "1"
+"""
+ self.write_config(config)
+
+ vars = get_bb_vars(["CVE_CHECK_DIR", "CVE_CHECK_SUMMARY_DIR", "CVE_CHECK_SUMMARY_FILE_NAME_JSON"])
+ report_json = os.path.join(vars["CVE_CHECK_SUMMARY_DIR"], vars["CVE_CHECK_SUMMARY_FILE_NAME_JSON"])
+ print(report_json)
+ try:
+ os.remove(report_json)
+ except FileNotFoundError:
+ pass
+
+ bitbake("core-image-minimal-initramfs")
+ self.assertExists(report_json)
+
+ # Check that the summary report lists at least one package
+ with open(report_json) as f:
+ report = json.load(f)
+ self.assertEqual(report["version"], "1")
+ self.assertGreater(len(report["package"]), 1)
+
+ # Check that a random recipe wrote a recipe report to deploy/cve/
+ recipename = report["package"][0]["name"]
+ recipe_report = os.path.join(vars["CVE_CHECK_DIR"], recipename + "_cve.json")
+ self.assertExists(recipe_report)
+ with open(recipe_report) as f:
+ report = json.load(f)
+ self.assertEqual(report["version"], "1")
+ self.assertEqual(len(report["package"]), 1)
+ self.assertEqual(report["package"][0]["name"], recipename)
+
+
+ def test_recipe_report_json_unpatched(self):
+ config = """
+INHERIT += "cve-check"
+CVE_CHECK_FORMAT_JSON = "1"
+CVE_CHECK_REPORT_PATCHED = "0"
+"""
+ self.write_config(config)
+
+ vars = get_bb_vars(["CVE_CHECK_SUMMARY_DIR", "CVE_CHECK_SUMMARY_FILE_NAME_JSON"])
+ summary_json = os.path.join(vars["CVE_CHECK_SUMMARY_DIR"], vars["CVE_CHECK_SUMMARY_FILE_NAME_JSON"])
+ recipe_json = os.path.join(vars["CVE_CHECK_SUMMARY_DIR"], "m4-native_cve.json")
+
+ try:
+ os.remove(summary_json)
+ os.remove(recipe_json)
+ except FileNotFoundError:
+ pass
+
+ bitbake("m4-native -c cve_check")
+
+ def check_m4_json(filename):
+ with open(filename) as f:
+ report = json.load(f)
+ self.assertEqual(report["version"], "1")
+ self.assertEqual(len(report["package"]), 1)
+ package = report["package"][0]
+ self.assertEqual(package["name"], "m4-native")
+ #m4 had only Patched CVEs, so the issues array will be empty
+ self.assertEqual(package["issue"], [])
+
+ self.assertExists(summary_json)
+ check_m4_json(summary_json)
+ self.assertExists(recipe_json)
+ check_m4_json(recipe_json)
+
+
+ def test_recipe_report_json_ignored(self):
+ config = """
+INHERIT += "cve-check"
+CVE_CHECK_FORMAT_JSON = "1"
+CVE_CHECK_REPORT_PATCHED = "1"
+"""
+ self.write_config(config)
+
+ vars = get_bb_vars(["CVE_CHECK_SUMMARY_DIR", "CVE_CHECK_SUMMARY_FILE_NAME_JSON"])
+ summary_json = os.path.join(vars["CVE_CHECK_SUMMARY_DIR"], vars["CVE_CHECK_SUMMARY_FILE_NAME_JSON"])
+ recipe_json = os.path.join(vars["CVE_CHECK_SUMMARY_DIR"], "logrotate_cve.json")
+
+ try:
+ os.remove(summary_json)
+ os.remove(recipe_json)
+ except FileNotFoundError:
+ pass
+
+ bitbake("logrotate -c cve_check")
+
+ def check_m4_json(filename):
+ with open(filename) as f:
+ report = json.load(f)
+ self.assertEqual(report["version"], "1")
+ self.assertEqual(len(report["package"]), 1)
+ package = report["package"][0]
+ self.assertEqual(package["name"], "logrotate")
+ found_cves = { issue["id"]: issue["status"] for issue in package["issue"]}
+ # m4 CVE should not be in logrotate
+ self.assertNotIn("CVE-2008-1687", found_cves)
+ # logrotate has both Patched and Ignored CVEs
+ self.assertIn("CVE-2011-1098", found_cves)
+ self.assertEqual(found_cves["CVE-2011-1098"], "Patched")
+ self.assertIn("CVE-2011-1548", found_cves)
+ self.assertEqual(found_cves["CVE-2011-1548"], "Ignored")
+ self.assertIn("CVE-2011-1549", found_cves)
+ self.assertEqual(found_cves["CVE-2011-1549"], "Ignored")
+ self.assertIn("CVE-2011-1550", found_cves)
+ self.assertEqual(found_cves["CVE-2011-1550"], "Ignored")
+
+ self.assertExists(summary_json)
+ check_m4_json(summary_json)
+ self.assertExists(recipe_json)
+ check_m4_json(recipe_json)
diff --git a/meta/lib/oeqa/selftest/cases/debuginfod.py b/meta/lib/oeqa/selftest/cases/debuginfod.py
new file mode 100644
index 0000000000..37f51760fb
--- /dev/null
+++ b/meta/lib/oeqa/selftest/cases/debuginfod.py
@@ -0,0 +1,106 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+import os
+import socketserver
+import subprocess
+
+from oeqa.selftest.case import OESelftestTestCase
+from oeqa.utils.commands import bitbake, get_bb_var, runqemu
+
+
+class Debuginfod(OESelftestTestCase):
+
+ def wait_for_debuginfod(self, port):
+ """
+ debuginfod takes time to scan the packages and requesting too early may
+ result in a test failure if the right packages haven't been scanned yet.
+
+ Request the metrics endpoint periodically and wait for there to be no
+ busy scanning threads.
+
+ Returns True if debuginfod is ready, False if we timed out
+ """
+ import time, urllib
+
+ # Wait a minute
+ countdown = 6
+ delay = 10
+
+ while countdown:
+ time.sleep(delay)
+ try:
+ with urllib.request.urlopen("http://localhost:%d/metrics" % port) as f:
+ lines = f.read().decode("ascii").splitlines()
+ if "thread_busy{role=\"scan\"} 0" in lines:
+ return True
+ except urllib.error.URLError as e:
+ self.logger.error(e)
+ countdown -= 1
+ return False
+
+
+ def test_debuginfod(self):
+ self.write_config(
+ """
+DISTRO_FEATURES:append = " debuginfod"
+CORE_IMAGE_EXTRA_INSTALL += "elfutils"
+ """
+ )
+ bitbake("core-image-minimal elfutils-native:do_addto_recipe_sysroot")
+
+ native_sysroot = get_bb_var("RECIPE_SYSROOT_NATIVE", "elfutils-native")
+ cmd = [
+ os.path.join(native_sysroot, "usr", "bin", "debuginfod"),
+ "--verbose",
+ # In-memory database, this is a one-shot test
+ "--database=:memory:",
+ # Don't use all the host cores
+ "--concurrency=8",
+ "--connection-pool=8",
+ # Disable rescanning, this is a one-shot test
+ "--rescan-time=0",
+ "--groom-time=0",
+ get_bb_var("DEPLOY_DIR"),
+ ]
+
+ format = get_bb_var("PACKAGE_CLASSES").split()[0]
+ if format == "package_deb":
+ cmd.append("--scan-deb-dir")
+ elif format == "package_ipk":
+ cmd.append("--scan-deb-dir")
+ elif format == "package_rpm":
+ cmd.append("--scan-rpm-dir")
+ else:
+ self.fail("Unknown package class %s" % format)
+
+ # Find a free port
+ with socketserver.TCPServer(("localhost", 0), None) as s:
+ port = s.server_address[1]
+ cmd.append("--port=%d" % port)
+
+ try:
+ # Remove DEBUGINFOD_URLS from the environment so we don't try
+ # looking in the distro debuginfod
+ env = os.environ.copy()
+ if "DEBUGINFOD_URLS" in env:
+ del env["DEBUGINFOD_URLS"]
+
+ self.logger.info(f"Starting server {cmd}")
+ debuginfod = subprocess.Popen(cmd, env=env)
+
+ with runqemu("core-image-minimal", runqemuparams="nographic") as qemu:
+ self.assertTrue(self.wait_for_debuginfod(port))
+
+ cmd = (
+ "DEBUGINFOD_URLS=http://%s:%d/ debuginfod-find debuginfo /usr/bin/debuginfod"
+ % (qemu.server_ip, port)
+ )
+ self.logger.info(f"Starting client {cmd}")
+ status, output = qemu.run_serial(cmd)
+ # This should be more comprehensive
+ self.assertIn("/.cache/debuginfod_client/", output)
+ finally:
+ debuginfod.kill()
diff --git a/meta/lib/oeqa/selftest/devtool.py b/meta/lib/oeqa/selftest/cases/devtool.py
index 08fe8df63e..86014d2557 100644
--- a/meta/lib/oeqa/selftest/devtool.py
+++ b/meta/lib/oeqa/selftest/cases/devtool.py
@@ -1,23 +1,129 @@
-import unittest
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
import os
-import logging
import re
import shutil
import tempfile
import glob
import fnmatch
-import oeqa.utils.ftools as ftools
-from oeqa.selftest.base import oeSelfTest
-from oeqa.utils.commands import runCmd, bitbake, get_bb_var, create_temp_layer, runqemu, get_test_layer
-from oeqa.utils.decorators import testcase
+from oeqa.selftest.case import OESelftestTestCase
+from oeqa.utils.commands import runCmd, bitbake, get_bb_var, create_temp_layer
+from oeqa.utils.commands import get_bb_vars, runqemu, get_test_layer
+from oeqa.core.decorator import OETestTag
+
+oldmetapath = None
+
+def setUpModule():
+ import bb.utils
+
+ global templayerdir
+ templayerdir = tempfile.mkdtemp(prefix='devtoolqa')
+ corecopydir = os.path.join(templayerdir, 'core-copy')
+ bblayers_conf = os.path.join(os.environ['BUILDDIR'], 'conf', 'bblayers.conf')
+ edited_layers = []
+
+ # We need to take a copy of the meta layer so we can modify it and not
+ # have any races against other tests that might be running in parallel
+ # however things like COREBASE mean that you can't just copy meta, you
+ # need the whole repository.
+ def bblayers_edit_cb(layerpath, canonical_layerpath):
+ global oldmetapath
+ if not canonical_layerpath.endswith('/'):
+ # This helps us match exactly when we're using this path later
+ canonical_layerpath += '/'
+ if not edited_layers and canonical_layerpath.endswith('/meta/'):
+ canonical_layerpath = os.path.realpath(canonical_layerpath) + '/'
+ edited_layers.append(layerpath)
+ oldmetapath = os.path.realpath(layerpath)
+ result = runCmd('git rev-parse --show-toplevel', cwd=canonical_layerpath)
+ oldreporoot = result.output.rstrip()
+ newmetapath = os.path.join(corecopydir, os.path.relpath(oldmetapath, oldreporoot))
+ runCmd('git clone %s %s' % (oldreporoot, corecopydir), cwd=templayerdir)
+ # Now we need to copy any modified files
+ # You might ask "why not just copy the entire tree instead of
+ # cloning and doing this?" - well, the problem with that is
+ # TMPDIR or an equally large subdirectory might exist
+ # under COREBASE and we don't want to copy that, so we have
+ # to be selective.
+ result = runCmd('git status --porcelain', cwd=oldreporoot)
+ for line in result.output.splitlines():
+ if line.startswith(' M ') or line.startswith('?? '):
+ relpth = line.split()[1]
+ pth = os.path.join(oldreporoot, relpth)
+ if pth.startswith(canonical_layerpath):
+ if relpth.endswith('/'):
+ destdir = os.path.join(corecopydir, relpth)
+ # avoid race condition by not copying .pyc files YPBZ#13421,13803
+ shutil.copytree(pth, destdir, ignore=shutil.ignore_patterns('*.pyc', '__pycache__'))
+ else:
+ destdir = os.path.join(corecopydir, os.path.dirname(relpth))
+ bb.utils.mkdirhier(destdir)
+ shutil.copy2(pth, destdir)
+ return newmetapath
+ else:
+ return layerpath
+ bb.utils.edit_bblayers_conf(bblayers_conf, None, None, bblayers_edit_cb)
+
+def tearDownModule():
+ if oldmetapath:
+ edited_layers = []
+ def bblayers_edit_cb(layerpath, canonical_layerpath):
+ if not edited_layers and canonical_layerpath.endswith('/meta'):
+ edited_layers.append(layerpath)
+ return oldmetapath
+ else:
+ return layerpath
+ bblayers_conf = os.path.join(os.environ['BUILDDIR'], 'conf', 'bblayers.conf')
+ bb.utils.edit_bblayers_conf(bblayers_conf, None, None, bblayers_edit_cb)
+ shutil.rmtree(templayerdir)
+
+class DevtoolTestCase(OESelftestTestCase):
+
+ def setUp(self):
+ """Test case setup function"""
+ super(DevtoolTestCase, self).setUp()
+ self.workspacedir = os.path.join(self.builddir, 'workspace')
+ self.assertTrue(not os.path.exists(self.workspacedir),
+ 'This test cannot be run with a workspace directory '
+ 'under the build directory')
+
+ def _check_src_repo(self, repo_dir):
+ """Check srctree git repository"""
+ self.assertTrue(os.path.isdir(os.path.join(repo_dir, '.git')),
+ 'git repository for external source tree not found')
+ result = runCmd('git status --porcelain', cwd=repo_dir)
+ self.assertEqual(result.output.strip(), "",
+ 'Created git repo is not clean')
+ result = runCmd('git symbolic-ref HEAD', cwd=repo_dir)
+ self.assertEqual(result.output.strip(), "refs/heads/devtool",
+ 'Wrong branch in git repo')
-class DevtoolBase(oeSelfTest):
+ def _check_repo_status(self, repo_dir, expected_status):
+ """Check the worktree status of a repository"""
+ result = runCmd('git status . --porcelain',
+ cwd=repo_dir)
+ for line in result.output.splitlines():
+ for ind, (f_status, fn_re) in enumerate(expected_status):
+ if re.match(fn_re, line[3:]):
+ if f_status != line[:2]:
+ self.fail('Unexpected status in line: %s' % line)
+ expected_status.pop(ind)
+ break
+ else:
+ self.fail('Unexpected modified file in line: %s' % line)
+ if expected_status:
+ self.fail('Missing file changes: %s' % expected_status)
def _test_recipe_contents(self, recipefile, checkvars, checkinherits):
with open(recipefile, 'r') as f:
invar = None
invalue = None
+ inherits = set()
for line in f:
var = None
if invar:
@@ -39,14 +145,17 @@ class DevtoolBase(oeSelfTest):
invar = var
continue
elif line.startswith('inherit '):
- inherits = line.split()[1:]
+ inherits.update(line.split()[1:])
if var and var in checkvars:
needvalue = checkvars.pop(var)
if needvalue is None:
- self.fail('Variable %s should not appear in recipe')
+ self.fail('Variable %s should not appear in recipe, but value is being set to "%s"' % (var, value))
if isinstance(needvalue, set):
- value = set(value.split())
+ if var == 'LICENSE':
+ value = set(value.split(' & '))
+ else:
+ value = set(value.split())
self.assertEqual(value, needvalue, 'values for %s do not match' % var)
@@ -111,49 +220,84 @@ class DevtoolBase(oeSelfTest):
filelist.append(' '.join(splitline))
return filelist
+ def _check_diff(self, diffoutput, addlines, removelines):
+ """Check output from 'git diff' matches expectation"""
+ remaining_addlines = addlines[:]
+ remaining_removelines = removelines[:]
+ for line in diffoutput.splitlines():
+ if line.startswith('+++') or line.startswith('---'):
+ continue
+ elif line.startswith('+'):
+ matched = False
+ for item in addlines:
+ if re.match(item, line[1:].strip()):
+ matched = True
+ remaining_addlines.remove(item)
+ break
+ self.assertTrue(matched, 'Unexpected diff add line: %s' % line)
+ elif line.startswith('-'):
+ matched = False
+ for item in removelines:
+ if re.match(item, line[1:].strip()):
+ matched = True
+ remaining_removelines.remove(item)
+ break
+ self.assertTrue(matched, 'Unexpected diff remove line: %s' % line)
+ if remaining_addlines:
+ self.fail('Expected added lines not found: %s' % remaining_addlines)
+ if remaining_removelines:
+ self.fail('Expected removed lines not found: %s' % remaining_removelines)
-class DevtoolTests(DevtoolBase):
+ def _test_devtool_add_git_url(self, git_url, version, pn, resulting_src_uri):
+ self.track_for_cleanup(self.workspacedir)
+ self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
+ result = runCmd('devtool add --version %s %s %s' % (version, pn, git_url))
+ self.assertExists(os.path.join(self.workspacedir, 'conf', 'layer.conf'), 'Workspace directory not created')
+ # Check the recipe name is correct
+ recipefile = get_bb_var('FILE', pn)
+ self.assertIn('%s_git.bb' % pn, recipefile, 'Recipe file incorrectly named')
+ self.assertIn(recipefile, result.output)
+ # Test devtool status
+ result = runCmd('devtool status')
+ self.assertIn(pn, result.output)
+ self.assertIn(recipefile, result.output)
+ checkvars = {}
+ checkvars['SRC_URI'] = resulting_src_uri
+ self._test_recipe_contents(recipefile, checkvars, [])
+
+class DevtoolBase(DevtoolTestCase):
+
+ @classmethod
+ def setUpClass(cls):
+ super(DevtoolBase, cls).setUpClass()
+ bb_vars = get_bb_vars(['TOPDIR', 'SSTATE_DIR'])
+ cls.original_sstate = bb_vars['SSTATE_DIR']
+ cls.devtool_sstate = os.path.join(bb_vars['TOPDIR'], 'sstate_devtool')
+ cls.sstate_conf = 'SSTATE_DIR = "%s"\n' % cls.devtool_sstate
+ cls.sstate_conf += ('SSTATE_MIRRORS += "file://.* file:///%s/PATH"\n'
+ % cls.original_sstate)
+
+ @classmethod
+ def tearDownClass(cls):
+ cls.logger.debug('Deleting devtool sstate cache on %s' % cls.devtool_sstate)
+ runCmd('rm -rf %s' % cls.devtool_sstate)
+ super(DevtoolBase, cls).tearDownClass()
def setUp(self):
"""Test case setup function"""
- super(DevtoolTests, self).setUp()
- self.workspacedir = os.path.join(self.builddir, 'workspace')
- self.assertTrue(not os.path.exists(self.workspacedir),
- 'This test cannot be run with a workspace directory '
- 'under the build directory')
+ super(DevtoolBase, self).setUp()
+ self.append_config(self.sstate_conf)
- def _check_src_repo(self, repo_dir):
- """Check srctree git repository"""
- self.assertTrue(os.path.isdir(os.path.join(repo_dir, '.git')),
- 'git repository for external source tree not found')
- result = runCmd('git status --porcelain', cwd=repo_dir)
- self.assertEqual(result.output.strip(), "",
- 'Created git repo is not clean')
- result = runCmd('git symbolic-ref HEAD', cwd=repo_dir)
- self.assertEqual(result.output.strip(), "refs/heads/devtool",
- 'Wrong branch in git repo')
- def _check_repo_status(self, repo_dir, expected_status):
- """Check the worktree status of a repository"""
- result = runCmd('git status . --porcelain',
- cwd=repo_dir)
- for line in result.output.splitlines():
- for ind, (f_status, fn_re) in enumerate(expected_status):
- if re.match(fn_re, line[3:]):
- if f_status != line[:2]:
- self.fail('Unexpected status in line: %s' % line)
- expected_status.pop(ind)
- break
- else:
- self.fail('Unexpected modified file in line: %s' % line)
- if expected_status:
- self.fail('Missing file changes: %s' % expected_status)
+class DevtoolTests(DevtoolBase):
- @testcase(1158)
def test_create_workspace(self):
# Check preconditions
result = runCmd('bitbake-layers show-layers')
- self.assertTrue('/workspace' not in result.output, 'This test cannot be run with a workspace layer in bblayers.conf')
+ self.assertTrue('\nworkspace' not in result.output, 'This test cannot be run with a workspace layer in bblayers.conf')
+ # remove conf/devtool.conf to avoid it corrupting tests
+ devtoolconf = os.path.join(self.builddir, 'conf', 'devtool.conf')
+ self.track_for_cleanup(devtoolconf)
# Try creating a workspace layer with a specific path
tempdir = tempfile.mkdtemp(prefix='devtoolqa')
self.track_for_cleanup(tempdir)
@@ -170,40 +314,52 @@ class DevtoolTests(DevtoolBase):
self.assertNotIn(tempdir, result.output)
self.assertIn(self.workspacedir, result.output)
- @testcase(1159)
+class DevtoolAddTests(DevtoolBase):
+
def test_devtool_add(self):
# Fetch source
tempdir = tempfile.mkdtemp(prefix='devtoolqa')
self.track_for_cleanup(tempdir)
- url = 'http://www.ivarch.com/programs/sources/pv-1.5.3.tar.bz2'
+ pn = 'pv'
+ pv = '1.5.3'
+ url = 'http://downloads.yoctoproject.org/mirror/sources/pv-1.5.3.tar.bz2'
result = runCmd('wget %s' % url, cwd=tempdir)
- result = runCmd('tar xfv pv-1.5.3.tar.bz2', cwd=tempdir)
- srcdir = os.path.join(tempdir, 'pv-1.5.3')
+ result = runCmd('tar xfv %s' % os.path.basename(url), cwd=tempdir)
+ srcdir = os.path.join(tempdir, '%s-%s' % (pn, pv))
self.assertTrue(os.path.isfile(os.path.join(srcdir, 'configure')), 'Unable to find configure script in source directory')
# Test devtool add
self.track_for_cleanup(self.workspacedir)
- self.add_command_to_tearDown('bitbake -c cleansstate pv')
+ self.add_command_to_tearDown('bitbake -c cleansstate %s' % pn)
self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
- result = runCmd('devtool add pv %s' % srcdir)
- self.assertTrue(os.path.exists(os.path.join(self.workspacedir, 'conf', 'layer.conf')), 'Workspace directory not created')
+ result = runCmd('devtool add %s %s' % (pn, srcdir))
+ self.assertExists(os.path.join(self.workspacedir, 'conf', 'layer.conf'), 'Workspace directory not created')
# Test devtool status
result = runCmd('devtool status')
- self.assertIn('pv', result.output)
+ recipepath = '%s/recipes/%s/%s_%s.bb' % (self.workspacedir, pn, pn, pv)
+ self.assertIn(recipepath, result.output)
self.assertIn(srcdir, result.output)
+ # Test devtool find-recipe
+ result = runCmd('devtool -q find-recipe %s' % pn)
+ self.assertEqual(recipepath, result.output.strip())
+ # Test devtool edit-recipe
+ result = runCmd('VISUAL="echo 123" devtool -q edit-recipe %s' % pn)
+ self.assertEqual('123 %s' % recipepath, result.output.strip())
# Clean up anything in the workdir/sysroot/sstate cache (have to do this *after* devtool add since the recipe only exists then)
- bitbake('pv -c cleansstate')
+ bitbake('%s -c cleansstate' % pn)
# Test devtool build
- result = runCmd('devtool build pv')
- installdir = get_bb_var('D', 'pv')
+ result = runCmd('devtool build %s' % pn)
+ bb_vars = get_bb_vars(['D', 'bindir'], pn)
+ installdir = bb_vars['D']
self.assertTrue(installdir, 'Could not query installdir variable')
- bindir = get_bb_var('bindir', 'pv')
+ bindir = bb_vars['bindir']
self.assertTrue(bindir, 'Could not query bindir variable')
if bindir[0] == '/':
bindir = bindir[1:]
self.assertTrue(os.path.isfile(os.path.join(installdir, bindir, 'pv')), 'pv binary not found in D')
- @testcase(1423)
def test_devtool_add_git_local(self):
+ # We need dbus built so that DEPENDS recognition works
+ bitbake('dbus')
# Fetch source from a remote URL, but do it outside of devtool
tempdir = tempfile.mkdtemp(prefix='devtoolqa')
self.track_for_cleanup(tempdir)
@@ -222,7 +378,7 @@ class DevtoolTests(DevtoolBase):
self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
# Don't specify a name since we should be able to auto-detect it
result = runCmd('devtool add %s' % srcdir)
- self.assertTrue(os.path.exists(os.path.join(self.workspacedir, 'conf', 'layer.conf')), 'Workspace directory not created')
+ self.assertExists(os.path.join(self.workspacedir, 'conf', 'layer.conf'), 'Workspace directory not created')
# Check the recipe name is correct
recipefile = get_bb_var('FILE', pn)
self.assertIn('%s_git.bb' % pn, recipefile, 'Recipe file incorrectly named')
@@ -233,19 +389,32 @@ class DevtoolTests(DevtoolBase):
self.assertIn(srcdir, result.output)
self.assertIn(recipefile, result.output)
checkvars = {}
- checkvars['LICENSE'] = 'GPLv2'
+ checkvars['LICENSE'] = 'GPL-2.0-only'
checkvars['LIC_FILES_CHKSUM'] = 'file://COPYING;md5=b234ee4d69f5fce4486a80fdaf4a4263'
checkvars['S'] = '${WORKDIR}/git'
checkvars['PV'] = '0.1+git${SRCPV}'
- checkvars['SRC_URI'] = 'git://git.yoctoproject.org/git/dbus-wait;protocol=https'
+ checkvars['SRC_URI'] = 'git://git.yoctoproject.org/git/dbus-wait;protocol=https;branch=master'
checkvars['SRCREV'] = srcrev
checkvars['DEPENDS'] = set(['dbus'])
self._test_recipe_contents(recipefile, checkvars, [])
- @testcase(1162)
+ def test_devtool_add_git_style1(self):
+ version = 'v3.1.0'
+ pn = 'mbedtls'
+ # this will trigger reformat_git_uri with branch parameter in url
+ git_url = "'git://git@github.com/ARMmbed/mbedtls.git;branch=mbedtls-2.28;protocol=https'"
+ resulting_src_uri = "git://git@github.com/ARMmbed/mbedtls.git;branch=mbedtls-2.28;protocol=https"
+ self._test_devtool_add_git_url(git_url, version, pn, resulting_src_uri)
+
+ def test_devtool_add_git_style2(self):
+ version = 'v3.1.0'
+ pn = 'mbedtls'
+ # this will trigger reformat_git_uri with branch parameter in url
+ git_url = "'git://git@github.com/ARMmbed/mbedtls.git;protocol=https'"
+ resulting_src_uri = "git://git@github.com/ARMmbed/mbedtls.git;protocol=https;branch=master"
+ self._test_devtool_add_git_url(git_url, version, pn, resulting_src_uri)
+
def test_devtool_add_library(self):
- # We don't have the ability to pick up this dependency automatically yet...
- bitbake('libusb1')
# Fetch source
tempdir = tempfile.mkdtemp(prefix='devtoolqa')
self.track_for_cleanup(tempdir)
@@ -259,7 +428,7 @@ class DevtoolTests(DevtoolBase):
self.track_for_cleanup(self.workspacedir)
self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
result = runCmd('devtool add libftdi %s -V %s' % (srcdir, version))
- self.assertTrue(os.path.exists(os.path.join(self.workspacedir, 'conf', 'layer.conf')), 'Workspace directory not created')
+ self.assertExists(os.path.join(self.workspacedir, 'conf', 'layer.conf'), 'Workspace directory not created')
# Test devtool status
result = runCmd('devtool status')
self.assertIn('libftdi', result.output)
@@ -273,14 +442,18 @@ class DevtoolTests(DevtoolBase):
recipefile = '%s/recipes/libftdi/libftdi_%s.bb' % (self.workspacedir, version)
result = runCmd('recipetool setvar %s EXTRA_OECMAKE -- \'-DPYTHON_BINDINGS=OFF -DLIBFTDI_CMAKE_CONFIG_DIR=${datadir}/cmake/Modules\'' % recipefile)
with open(recipefile, 'a') as f:
- f.write('\nFILES_${PN}-dev += "${datadir}/cmake/Modules"\n')
+ f.write('\nFILES:${PN}-dev += "${datadir}/cmake/Modules"\n')
+ # We don't have the ability to pick up this dependency automatically yet...
+ f.write('\nDEPENDS += "libusb1"\n')
+ f.write('\nTESTLIBOUTPUT = "${COMPONENTS_DIR}/${TUNE_PKGARCH}/${PN}/${libdir}"\n')
# Test devtool build
result = runCmd('devtool build libftdi')
- staging_libdir = get_bb_var('STAGING_LIBDIR', 'libftdi')
- self.assertTrue(staging_libdir, 'Could not query STAGING_LIBDIR variable')
+ bb_vars = get_bb_vars(['TESTLIBOUTPUT', 'STAMP'], 'libftdi')
+ staging_libdir = bb_vars['TESTLIBOUTPUT']
+ self.assertTrue(staging_libdir, 'Could not query TESTLIBOUTPUT variable')
self.assertTrue(os.path.isfile(os.path.join(staging_libdir, 'libftdi1.so.2.1.0')), "libftdi binary not found in STAGING_LIBDIR. Output of devtool build libftdi %s" % result.output)
# Test devtool reset
- stampprefix = get_bb_var('STAMP', 'libftdi')
+ stampprefix = bb_vars['STAMP']
result = runCmd('devtool reset libftdi')
result = runCmd('devtool status')
self.assertNotIn('libftdi', result.output)
@@ -289,13 +462,12 @@ class DevtoolTests(DevtoolBase):
self.assertFalse(matches, 'Stamp files exist for recipe libftdi that should have been cleaned')
self.assertFalse(os.path.isfile(os.path.join(staging_libdir, 'libftdi1.so.2.1.0')), 'libftdi binary still found in STAGING_LIBDIR after cleaning')
- @testcase(1160)
def test_devtool_add_fetch(self):
# Fetch source
tempdir = tempfile.mkdtemp(prefix='devtoolqa')
self.track_for_cleanup(tempdir)
testver = '0.23'
- url = 'https://pypi.python.org/packages/source/M/MarkupSafe/MarkupSafe-%s.tar.gz' % testver
+ url = 'https://files.pythonhosted.org/packages/c0/41/bae1254e0396c0cc8cf1751cb7d9afc90a602353695af5952530482c963f/MarkupSafe-%s.tar.gz' % testver
testrecipe = 'python-markupsafe'
srcdir = os.path.join(tempdir, testrecipe)
# Test devtool add
@@ -303,7 +475,7 @@ class DevtoolTests(DevtoolBase):
self.add_command_to_tearDown('bitbake -c cleansstate %s' % testrecipe)
self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
result = runCmd('devtool add %s %s -f %s' % (testrecipe, srcdir, url))
- self.assertTrue(os.path.exists(os.path.join(self.workspacedir, 'conf', 'layer.conf')), 'Workspace directory not created. %s' % result.output)
+ self.assertExists(os.path.join(self.workspacedir, 'conf', 'layer.conf'), 'Workspace directory not created. %s' % result.output)
self.assertTrue(os.path.isfile(os.path.join(srcdir, 'setup.py')), 'Unable to find setup.py in source directory')
self.assertTrue(os.path.isdir(os.path.join(srcdir, '.git')), 'git repository for external source tree was not created')
# Test devtool status
@@ -334,23 +506,22 @@ class DevtoolTests(DevtoolBase):
checkvars['S'] = '${WORKDIR}/MarkupSafe-%s' % testver
checkvars['SRC_URI'] = url
self._test_recipe_contents(recipefile, checkvars, [])
-
- @testcase(1161)
+
def test_devtool_add_fetch_git(self):
- # Fetch source
tempdir = tempfile.mkdtemp(prefix='devtoolqa')
self.track_for_cleanup(tempdir)
- url = 'git://git.yoctoproject.org/libmatchbox'
- checkrev = '462f0652055d89c648ddd54fd7b03f175c2c6973'
- testrecipe = 'libmatchbox2'
+ url = 'gitsm://git.yoctoproject.org/mraa'
+ url_branch = '%s;branch=master' % url
+ checkrev = 'ae127b19a50aa54255e4330ccfdd9a5d058e581d'
+ testrecipe = 'mraa'
srcdir = os.path.join(tempdir, testrecipe)
# Test devtool add
self.track_for_cleanup(self.workspacedir)
self.add_command_to_tearDown('bitbake -c cleansstate %s' % testrecipe)
self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
result = runCmd('devtool add %s %s -a -f %s' % (testrecipe, srcdir, url))
- self.assertTrue(os.path.exists(os.path.join(self.workspacedir, 'conf', 'layer.conf')), 'Workspace directory not created: %s' % result.output)
- self.assertTrue(os.path.isfile(os.path.join(srcdir, 'configure.ac')), 'Unable to find configure.ac in source directory')
+ self.assertExists(os.path.join(self.workspacedir, 'conf', 'layer.conf'), 'Workspace directory not created: %s' % result.output)
+ self.assertTrue(os.path.isfile(os.path.join(srcdir, 'imraa', 'imraa.c')), 'Unable to find imraa/imraa.c in source directory')
# Test devtool status
result = runCmd('devtool status')
self.assertIn(testrecipe, result.output)
@@ -360,8 +531,8 @@ class DevtoolTests(DevtoolBase):
self.assertIn('_git.bb', recipefile, 'Recipe file incorrectly named')
checkvars = {}
checkvars['S'] = '${WORKDIR}/git'
- checkvars['PV'] = '1.12+git${SRCPV}'
- checkvars['SRC_URI'] = url
+ checkvars['PV'] = '1.0+git${SRCPV}'
+ checkvars['SRC_URI'] = url_branch
checkvars['SRCREV'] = '${AUTOREV}'
self._test_recipe_contents(recipefile, checkvars, [])
# Try with revision and version specified
@@ -369,7 +540,7 @@ class DevtoolTests(DevtoolBase):
shutil.rmtree(srcdir)
url_rev = '%s;rev=%s' % (url, checkrev)
result = runCmd('devtool add %s %s -f "%s" -V 1.5' % (testrecipe, srcdir, url_rev))
- self.assertTrue(os.path.isfile(os.path.join(srcdir, 'configure.ac')), 'Unable to find configure.ac in source directory')
+ self.assertTrue(os.path.isfile(os.path.join(srcdir, 'imraa', 'imraa.c')), 'Unable to find imraa/imraa.c in source directory')
# Test devtool status
result = runCmd('devtool status')
self.assertIn(testrecipe, result.output)
@@ -380,11 +551,10 @@ class DevtoolTests(DevtoolBase):
checkvars = {}
checkvars['S'] = '${WORKDIR}/git'
checkvars['PV'] = '1.5+git${SRCPV}'
- checkvars['SRC_URI'] = url
+ checkvars['SRC_URI'] = url_branch
checkvars['SRCREV'] = checkrev
self._test_recipe_contents(recipefile, checkvars, [])
- @testcase(1391)
def test_devtool_add_fetch_simple(self):
# Fetch source from a remote URL, auto-detecting name
tempdir = tempfile.mkdtemp(prefix='devtoolqa')
@@ -397,14 +567,14 @@ class DevtoolTests(DevtoolBase):
self.track_for_cleanup(self.workspacedir)
self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
result = runCmd('devtool add %s' % url)
- self.assertTrue(os.path.exists(os.path.join(self.workspacedir, 'conf', 'layer.conf')), 'Workspace directory not created. %s' % result.output)
+ self.assertExists(os.path.join(self.workspacedir, 'conf', 'layer.conf'), 'Workspace directory not created. %s' % result.output)
self.assertTrue(os.path.isfile(os.path.join(srcdir, 'configure')), 'Unable to find configure script in source directory')
self.assertTrue(os.path.isdir(os.path.join(srcdir, '.git')), 'git repository for external source tree was not created')
# Test devtool status
result = runCmd('devtool status')
self.assertIn(testrecipe, result.output)
self.assertIn(srcdir, result.output)
- # Check recipe
+ # Check recipedevtool add
recipefile = get_bb_var('FILE', testrecipe)
self.assertIn('%s_%s.bb' % (testrecipe, testver), recipefile, 'Recipe file incorrectly named')
checkvars = {}
@@ -412,52 +582,149 @@ class DevtoolTests(DevtoolBase):
checkvars['SRC_URI'] = url.replace(testver, '${PV}')
self._test_recipe_contents(recipefile, checkvars, [])
- @testcase(1164)
- def test_devtool_modify(self):
- # Clean up anything in the workdir/sysroot/sstate cache
- bitbake('mdadm -c cleansstate')
- # Try modifying a recipe
+ def test_devtool_add_npm(self):
+ collections = get_bb_var('BBFILE_COLLECTIONS').split()
+ if "openembedded-layer" not in collections:
+ self.skipTest("Test needs meta-oe for nodejs")
+
+ pn = 'savoirfairelinux-node-server-example'
+ pv = '1.0.0'
+ url = 'npm://registry.npmjs.org;package=@savoirfairelinux/node-server-example;version=' + pv
+ # Test devtool add
+ self.track_for_cleanup(self.workspacedir)
+ self.add_command_to_tearDown('bitbake -c cleansstate %s' % pn)
+ self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
+ result = runCmd('devtool add \'%s\'' % url)
+ self.assertExists(os.path.join(self.workspacedir, 'conf', 'layer.conf'), 'Workspace directory not created')
+ self.assertExists(os.path.join(self.workspacedir, 'recipes', pn, '%s_%s.bb' % (pn, pv)), 'Recipe not created')
+ self.assertExists(os.path.join(self.workspacedir, 'recipes', pn, pn, 'npm-shrinkwrap.json'), 'Shrinkwrap not created')
+ # Test devtool status
+ result = runCmd('devtool status')
+ self.assertIn(pn, result.output)
+ # Clean up anything in the workdir/sysroot/sstate cache (have to do this *after* devtool add since the recipe only exists then)
+ bitbake('%s -c cleansstate' % pn)
+ # Test devtool build
+ result = runCmd('devtool build %s' % pn)
+
+ def test_devtool_add_python_egg_requires(self):
+ # Fetch source
tempdir = tempfile.mkdtemp(prefix='devtoolqa')
self.track_for_cleanup(tempdir)
+ testver = '0.14.0'
+ url = 'https://files.pythonhosted.org/packages/e9/9e/25d59f5043cf763833b2581c8027fa92342c4cf8ee523b498ecdf460c16d/uvicorn-%s.tar.gz' % testver
+ testrecipe = 'python3-uvicorn'
+ srcdir = os.path.join(tempdir, testrecipe)
+ # Test devtool add
self.track_for_cleanup(self.workspacedir)
self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
+ result = runCmd('devtool add %s %s -f %s' % (testrecipe, srcdir, url))
+
+class DevtoolModifyTests(DevtoolBase):
+
+ def test_devtool_modify(self):
+ import oe.path
+
+ tempdir = tempfile.mkdtemp(prefix='devtoolqa')
+ self.track_for_cleanup(tempdir)
+ self.track_for_cleanup(self.workspacedir)
self.add_command_to_tearDown('bitbake -c clean mdadm')
+ self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
result = runCmd('devtool modify mdadm -x %s' % tempdir)
- self.assertTrue(os.path.exists(os.path.join(tempdir, 'Makefile')), 'Extracted source could not be found')
- self.assertTrue(os.path.exists(os.path.join(self.workspacedir, 'conf', 'layer.conf')), 'Workspace directory not created')
+ self.assertExists(os.path.join(tempdir, 'Makefile'), 'Extracted source could not be found')
+ self.assertExists(os.path.join(self.workspacedir, 'conf', 'layer.conf'), 'Workspace directory not created')
matches = glob.glob(os.path.join(self.workspacedir, 'appends', 'mdadm_*.bbappend'))
self.assertTrue(matches, 'bbappend not created %s' % result.output)
+
# Test devtool status
result = runCmd('devtool status')
self.assertIn('mdadm', result.output)
self.assertIn(tempdir, result.output)
- # Check git repo
self._check_src_repo(tempdir)
- # Try building
- bitbake('mdadm')
- # Try making (minor) modifications to the source
- result = runCmd("sed -i 's!^\.TH.*!.TH MDADM 8 \"\" v9.999-custom!' %s" % os.path.join(tempdir, 'mdadm.8.in'))
- bitbake('mdadm -c package')
- pkgd = get_bb_var('PKGD', 'mdadm')
+
+ bitbake('mdadm -C unpack')
+
+ def check_line(checkfile, expected, message, present=True):
+ # Check for $expected, on a line on its own, in checkfile.
+ with open(checkfile, 'r') as f:
+ if present:
+ self.assertIn(expected + '\n', f, message)
+ else:
+ self.assertNotIn(expected + '\n', f, message)
+
+ modfile = os.path.join(tempdir, 'mdadm.8.in')
+ bb_vars = get_bb_vars(['PKGD', 'mandir'], 'mdadm')
+ pkgd = bb_vars['PKGD']
self.assertTrue(pkgd, 'Could not query PKGD variable')
- mandir = get_bb_var('mandir', 'mdadm')
+ mandir = bb_vars['mandir']
self.assertTrue(mandir, 'Could not query mandir variable')
- if mandir[0] == '/':
- mandir = mandir[1:]
- with open(os.path.join(pkgd, mandir, 'man8', 'mdadm.8'), 'r') as f:
- for line in f:
- if line.startswith('.TH'):
- self.assertEqual(line.rstrip(), '.TH MDADM 8 "" v9.999-custom', 'man file not modified. man searched file path: %s' % os.path.join(pkgd, mandir, 'man8', 'mdadm.8'))
- # Test devtool reset
- stampprefix = get_bb_var('STAMP', 'mdadm')
+ manfile = oe.path.join(pkgd, mandir, 'man8', 'mdadm.8')
+
+ check_line(modfile, 'Linux Software RAID', 'Could not find initial string')
+ check_line(modfile, 'antique pin sardine', 'Unexpectedly found replacement string', present=False)
+
+ result = runCmd("sed -i 's!^Linux Software RAID$!antique pin sardine!' %s" % modfile)
+ check_line(modfile, 'antique pin sardine', 'mdadm.8.in file not modified (sed failed)')
+
+ bitbake('mdadm -c package')
+ check_line(manfile, 'antique pin sardine', 'man file not modified. man searched file path: %s' % manfile)
+
+ result = runCmd('git checkout -- %s' % modfile, cwd=tempdir)
+ check_line(modfile, 'Linux Software RAID', 'man .in file not restored (git failed)')
+
+ bitbake('mdadm -c package')
+ check_line(manfile, 'Linux Software RAID', 'man file not updated. man searched file path: %s' % manfile)
+
result = runCmd('devtool reset mdadm')
result = runCmd('devtool status')
self.assertNotIn('mdadm', result.output)
- self.assertTrue(stampprefix, 'Unable to get STAMP value for recipe mdadm')
- matches = glob.glob(stampprefix + '*')
- self.assertFalse(matches, 'Stamp files exist for recipe mdadm that should have been cleaned')
- @testcase(1166)
+ def test_devtool_buildclean(self):
+ def assertFile(path, *paths):
+ f = os.path.join(path, *paths)
+ self.assertExists(f)
+ def assertNoFile(path, *paths):
+ f = os.path.join(path, *paths)
+ self.assertNotExists(f)
+
+ # Clean up anything in the workdir/sysroot/sstate cache
+ bitbake('mdadm m4 -c cleansstate')
+ # Try modifying a recipe
+ tempdir_mdadm = tempfile.mkdtemp(prefix='devtoolqa')
+ tempdir_m4 = tempfile.mkdtemp(prefix='devtoolqa')
+ builddir_m4 = tempfile.mkdtemp(prefix='devtoolqa')
+ self.track_for_cleanup(tempdir_mdadm)
+ self.track_for_cleanup(tempdir_m4)
+ self.track_for_cleanup(builddir_m4)
+ self.track_for_cleanup(self.workspacedir)
+ self.add_command_to_tearDown('bitbake -c clean mdadm m4')
+ self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
+ self.write_recipeinc('m4', 'EXTERNALSRC_BUILD = "%s"\ndo_clean() {\n\t:\n}\n' % builddir_m4)
+ try:
+ runCmd('devtool modify mdadm -x %s' % tempdir_mdadm)
+ runCmd('devtool modify m4 -x %s' % tempdir_m4)
+ assertNoFile(tempdir_mdadm, 'mdadm')
+ assertNoFile(builddir_m4, 'src/m4')
+ result = bitbake('m4 -e')
+ result = bitbake('mdadm m4 -c compile')
+ self.assertEqual(result.status, 0)
+ assertFile(tempdir_mdadm, 'mdadm')
+ assertFile(builddir_m4, 'src/m4')
+ # Check that buildclean task exists and does call make clean
+ bitbake('mdadm m4 -c buildclean')
+ assertNoFile(tempdir_mdadm, 'mdadm')
+ assertNoFile(builddir_m4, 'src/m4')
+ runCmd('echo "#Trigger rebuild" >> %s/Makefile' % tempdir_mdadm)
+ bitbake('mdadm m4 -c compile')
+ assertFile(tempdir_mdadm, 'mdadm')
+ assertFile(builddir_m4, 'src/m4')
+ bitbake('mdadm m4 -c clean')
+ # Check that buildclean task is run before clean for B == S
+ assertNoFile(tempdir_mdadm, 'mdadm')
+ # Check that buildclean task is not run before clean for B != S
+ assertFile(builddir_m4, 'src/m4')
+ finally:
+ self.delete_recipeinc('m4')
+
def test_devtool_modify_invalid(self):
# Try modifying some recipes
tempdir = tempfile.mkdtemp(prefix='devtoolqa')
@@ -465,7 +732,7 @@ class DevtoolTests(DevtoolBase):
self.track_for_cleanup(self.workspacedir)
self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
- testrecipes = 'perf kernel-devsrc package-index core-image-minimal meta-toolchain packagegroup-core-sdk meta-ide-support'.split()
+ testrecipes = 'perf kernel-devsrc package-index core-image-minimal meta-toolchain packagegroup-core-sdk'.split()
# Find actual name of gcc-source since it now includes the version - crude, but good enough for this purpose
result = runCmd('bitbake-layers show-recipes gcc-source*')
for line in result.output.splitlines():
@@ -486,7 +753,6 @@ class DevtoolTests(DevtoolBase):
self.assertNotEqual(result.status, 0, 'devtool modify on %s should have failed. devtool output: %s' % (testrecipe, result.output))
self.assertIn('ERROR: ', result.output, 'devtool modify on %s should have given an ERROR' % testrecipe)
- @testcase(1365)
def test_devtool_modify_native(self):
# Check preconditions
self.assertTrue(not os.path.exists(self.workspacedir), 'This test cannot be run with a workspace directory under the build directory')
@@ -498,7 +764,7 @@ class DevtoolTests(DevtoolBase):
bbclassextended = False
inheritnative = False
- testrecipes = 'mtools-native apt-native desktop-file-utils-native'.split()
+ testrecipes = 'cdrtools-native mtools-native apt-native desktop-file-utils-native'.split()
for testrecipe in testrecipes:
checkextend = 'native' in (get_bb_var('BBCLASSEXTEND', testrecipe) or '').split()
if not bbclassextended:
@@ -515,11 +781,48 @@ class DevtoolTests(DevtoolBase):
self.assertTrue(bbclassextended, 'None of these recipes are BBCLASSEXTENDed to native - need to adjust testrecipes list: %s' % ', '.join(testrecipes))
self.assertTrue(inheritnative, 'None of these recipes do "inherit native" - need to adjust testrecipes list: %s' % ', '.join(testrecipes))
+ def test_devtool_modify_localfiles_only(self):
+ # Check preconditions
+ testrecipe = 'base-files'
+ src_uri = (get_bb_var('SRC_URI', testrecipe) or '').split()
+ foundlocalonly = False
+ correct_symlink = False
+ for item in src_uri:
+ if item.startswith('file://'):
+ if '.patch' not in item:
+ foundlocalonly = True
+ else:
+ foundlocalonly = False
+ break
+ self.assertTrue(foundlocalonly, 'This test expects the %s recipe to fetch local files only and it seems that it no longer does' % testrecipe)
+ # Clean up anything in the workdir/sysroot/sstate cache
+ bitbake('%s -c cleansstate' % testrecipe)
+ # Try modifying a recipe
+ tempdir = tempfile.mkdtemp(prefix='devtoolqa')
+ self.track_for_cleanup(tempdir)
+ self.track_for_cleanup(self.workspacedir)
+ self.add_command_to_tearDown('bitbake -c clean %s' % testrecipe)
+ self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
+ result = runCmd('devtool modify %s -x %s' % (testrecipe, tempdir))
+ srcfile = os.path.join(tempdir, 'oe-local-files/share/dot.bashrc')
+ srclink = os.path.join(tempdir, 'share/dot.bashrc')
+ self.assertExists(srcfile, 'Extracted source could not be found')
+ if os.path.islink(srclink) and os.path.exists(srclink) and os.path.samefile(srcfile, srclink):
+ correct_symlink = True
+ self.assertTrue(correct_symlink, 'Source symlink to oe-local-files is broken')
+
+ matches = glob.glob(os.path.join(self.workspacedir, 'appends', '%s_*.bbappend' % testrecipe))
+ self.assertTrue(matches, 'bbappend not created')
+ # Test devtool status
+ result = runCmd('devtool status')
+ self.assertIn(testrecipe, result.output)
+ self.assertIn(tempdir, result.output)
+ # Try building
+ bitbake(testrecipe)
- @testcase(1165)
def test_devtool_modify_git(self):
# Check preconditions
- testrecipe = 'mkelfimage'
+ testrecipe = 'psplash'
src_uri = get_bb_var('SRC_URI', testrecipe)
self.assertIn('git://', src_uri, 'This test expects the %s recipe to be a git recipe' % testrecipe)
# Clean up anything in the workdir/sysroot/sstate cache
@@ -528,12 +831,12 @@ class DevtoolTests(DevtoolBase):
tempdir = tempfile.mkdtemp(prefix='devtoolqa')
self.track_for_cleanup(tempdir)
self.track_for_cleanup(self.workspacedir)
- self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
self.add_command_to_tearDown('bitbake -c clean %s' % testrecipe)
+ self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
result = runCmd('devtool modify %s -x %s' % (testrecipe, tempdir))
- self.assertTrue(os.path.exists(os.path.join(tempdir, 'Makefile')), 'Extracted source could not be found')
- self.assertTrue(os.path.exists(os.path.join(self.workspacedir, 'conf', 'layer.conf')), 'Workspace directory not created. devtool output: %s' % result.output)
- matches = glob.glob(os.path.join(self.workspacedir, 'appends', 'mkelfimage_*.bbappend'))
+ self.assertExists(os.path.join(tempdir, 'Makefile.am'), 'Extracted source could not be found')
+ self.assertExists(os.path.join(self.workspacedir, 'conf', 'layer.conf'), 'Workspace directory not created. devtool output: %s' % result.output)
+ matches = glob.glob(os.path.join(self.workspacedir, 'appends', 'psplash_*.bbappend'))
self.assertTrue(matches, 'bbappend not created')
# Test devtool status
result = runCmd('devtool status')
@@ -544,7 +847,6 @@ class DevtoolTests(DevtoolBase):
# Try building
bitbake(testrecipe)
- @testcase(1167)
def test_devtool_modify_localfiles(self):
# Check preconditions
testrecipe = 'lighttpd'
@@ -561,11 +863,11 @@ class DevtoolTests(DevtoolBase):
tempdir = tempfile.mkdtemp(prefix='devtoolqa')
self.track_for_cleanup(tempdir)
self.track_for_cleanup(self.workspacedir)
- self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
self.add_command_to_tearDown('bitbake -c clean %s' % testrecipe)
+ self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
result = runCmd('devtool modify %s -x %s' % (testrecipe, tempdir))
- self.assertTrue(os.path.exists(os.path.join(tempdir, 'configure.ac')), 'Extracted source could not be found')
- self.assertTrue(os.path.exists(os.path.join(self.workspacedir, 'conf', 'layer.conf')), 'Workspace directory not created')
+ self.assertExists(os.path.join(tempdir, 'configure.ac'), 'Extracted source could not be found')
+ self.assertExists(os.path.join(self.workspacedir, 'conf', 'layer.conf'), 'Workspace directory not created')
matches = glob.glob(os.path.join(self.workspacedir, 'appends', '%s_*.bbappend' % testrecipe))
self.assertTrue(matches, 'bbappend not created')
# Test devtool status
@@ -575,18 +877,17 @@ class DevtoolTests(DevtoolBase):
# Try building
bitbake(testrecipe)
- @testcase(1378)
def test_devtool_modify_virtual(self):
# Try modifying a virtual recipe
- virtrecipe = 'virtual/libx11'
- realrecipe = 'libx11'
+ virtrecipe = 'virtual/make'
+ realrecipe = 'make'
tempdir = tempfile.mkdtemp(prefix='devtoolqa')
self.track_for_cleanup(tempdir)
self.track_for_cleanup(self.workspacedir)
self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
result = runCmd('devtool modify %s -x %s' % (virtrecipe, tempdir))
- self.assertTrue(os.path.exists(os.path.join(tempdir, 'Makefile.am')), 'Extracted source could not be found')
- self.assertTrue(os.path.exists(os.path.join(self.workspacedir, 'conf', 'layer.conf')), 'Workspace directory not created')
+ self.assertExists(os.path.join(tempdir, 'Makefile.am'), 'Extracted source could not be found')
+ self.assertExists(os.path.join(self.workspacedir, 'conf', 'layer.conf'), 'Workspace directory not created')
matches = glob.glob(os.path.join(self.workspacedir, 'appends', '%s_*.bbappend' % realrecipe))
self.assertTrue(matches, 'bbappend not created %s' % result.output)
# Test devtool status
@@ -597,13 +898,34 @@ class DevtoolTests(DevtoolBase):
self._check_src_repo(tempdir)
# This is probably sufficient
+ def test_devtool_modify_overrides(self):
+ # Try modifying a recipe with patches in overrides
+ tempdir = tempfile.mkdtemp(prefix='devtoolqa')
+ self.track_for_cleanup(tempdir)
+ self.track_for_cleanup(self.workspacedir)
+ self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
+ result = runCmd('devtool modify devtool-patch-overrides -x %s' % (tempdir))
+
+ self._check_src_repo(tempdir)
+ source = os.path.join(tempdir, "source")
+ def check(branch, expected):
+ runCmd('git -C %s checkout %s' % (tempdir, branch))
+ with open(source, "rt") as f:
+ content = f.read()
+ self.assertEquals(content, expected)
+ check('devtool', 'This is a test for something\n')
+ check('devtool-no-overrides', 'This is a test for something\n')
+ check('devtool-override-qemuarm', 'This is a test for qemuarm\n')
+ check('devtool-override-qemux86', 'This is a test for qemux86\n')
+
+class DevtoolUpdateTests(DevtoolBase):
- @testcase(1169)
def test_devtool_update_recipe(self):
# Check preconditions
testrecipe = 'minicom'
- recipefile = get_bb_var('FILE', testrecipe)
- src_uri = get_bb_var('SRC_URI', testrecipe)
+ bb_vars = get_bb_vars(['FILE', 'SRC_URI'], testrecipe)
+ recipefile = bb_vars['FILE']
+ src_uri = bb_vars['SRC_URI']
self.assertNotIn('git://', src_uri, 'This test expects the %s recipe to NOT be a git recipe' % testrecipe)
self._check_repo_status(os.path.dirname(recipefile), [])
# First, modify a recipe
@@ -630,12 +952,12 @@ class DevtoolTests(DevtoolBase):
('??', '.*/0002-Add-a-new-file.patch$')]
self._check_repo_status(os.path.dirname(recipefile), expected_status)
- @testcase(1172)
def test_devtool_update_recipe_git(self):
# Check preconditions
- testrecipe = 'mtd-utils'
- recipefile = get_bb_var('FILE', testrecipe)
- src_uri = get_bb_var('SRC_URI', testrecipe)
+ testrecipe = 'mtd-utils-selftest'
+ bb_vars = get_bb_vars(['FILE', 'SRC_URI'], testrecipe)
+ recipefile = bb_vars['FILE']
+ src_uri = bb_vars['SRC_URI']
self.assertIn('git://', src_uri, 'This test expects the %s recipe to be a git recipe' % testrecipe)
patches = []
for entry in src_uri.split():
@@ -654,7 +976,7 @@ class DevtoolTests(DevtoolBase):
self._check_src_repo(tempdir)
# Add a couple of commits
# FIXME: this only tests adding, need to also test update and remove
- result = runCmd('echo "# Additional line" >> Makefile', cwd=tempdir)
+ result = runCmd('echo "# Additional line" >> Makefile.am', cwd=tempdir)
result = runCmd('git commit -a -m "Change the Makefile"', cwd=tempdir)
result = runCmd('echo "A new file" > devtool-new-file', cwd=tempdir)
result = runCmd('git add devtool-new-file', cwd=tempdir)
@@ -666,28 +988,12 @@ class DevtoolTests(DevtoolBase):
self._check_repo_status(os.path.dirname(recipefile), expected_status)
result = runCmd('git diff %s' % os.path.basename(recipefile), cwd=os.path.dirname(recipefile))
- addlines = ['SRCREV = ".*"', 'SRC_URI = "git://git.infradead.org/mtd-utils.git"']
+ addlines = ['SRCREV = ".*"', 'SRC_URI = "git://git.infradead.org/mtd-utils.git;branch=master"']
srcurilines = src_uri.split()
srcurilines[0] = 'SRC_URI = "' + srcurilines[0]
srcurilines.append('"')
removelines = ['SRCREV = ".*"'] + srcurilines
- for line in result.output.splitlines():
- if line.startswith('+++') or line.startswith('---'):
- continue
- elif line.startswith('+'):
- matched = False
- for item in addlines:
- if re.match(item, line[1:].strip()):
- matched = True
- break
- self.assertTrue(matched, 'Unexpected diff add line: %s' % line)
- elif line.startswith('-'):
- matched = False
- for item in removelines:
- if re.match(item, line[1:].strip()):
- matched = True
- break
- self.assertTrue(matched, 'Unexpected diff remove line: %s' % line)
+ self._check_diff(result.output, addlines, removelines)
# Now try with auto mode
runCmd('cd %s; git checkout %s %s' % (os.path.dirname(recipefile), testrecipe, os.path.basename(recipefile)))
result = runCmd('devtool update-recipe %s' % testrecipe)
@@ -699,12 +1005,12 @@ class DevtoolTests(DevtoolBase):
('??', '%s/0002-Add-a-new-file.patch' % relpatchpath)]
self._check_repo_status(os.path.dirname(recipefile), expected_status)
- @testcase(1170)
def test_devtool_update_recipe_append(self):
# Check preconditions
testrecipe = 'mdadm'
- recipefile = get_bb_var('FILE', testrecipe)
- src_uri = get_bb_var('SRC_URI', testrecipe)
+ bb_vars = get_bb_vars(['FILE', 'SRC_URI'], testrecipe)
+ recipefile = bb_vars['FILE']
+ src_uri = bb_vars['SRC_URI']
self.assertNotIn('git://', src_uri, 'This test expects the %s recipe to NOT be a git recipe' % testrecipe)
self._check_repo_status(os.path.dirname(recipefile), [])
# First, modify a recipe
@@ -734,10 +1040,10 @@ class DevtoolTests(DevtoolBase):
appenddir = os.path.join(templayerdir, splitpath[-2], splitpath[-1])
bbappendfile = self._check_bbappend(testrecipe, recipefile, appenddir)
patchfile = os.path.join(appenddir, testrecipe, '0001-Add-our-custom-version.patch')
- self.assertTrue(os.path.exists(patchfile), 'Patch file not created')
+ self.assertExists(patchfile, 'Patch file not created')
# Check bbappend contents
- expectedlines = ['FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"\n',
+ expectedlines = ['FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:"\n',
'\n',
'SRC_URI += "file://0001-Add-our-custom-version.patch"\n',
'\n']
@@ -751,8 +1057,8 @@ class DevtoolTests(DevtoolBase):
# Drop new commit and check patch gets deleted
result = runCmd('git reset HEAD^', cwd=tempsrcdir)
result = runCmd('devtool update-recipe %s -a %s' % (testrecipe, templayerdir))
- self.assertFalse(os.path.exists(patchfile), 'Patch file not deleted')
- expectedlines2 = ['FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"\n',
+ self.assertNotExists(patchfile, 'Patch file not deleted')
+ expectedlines2 = ['FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:"\n',
'\n']
with open(bbappendfile, 'r') as f:
self.assertEqual(expectedlines2, f.readlines())
@@ -762,17 +1068,18 @@ class DevtoolTests(DevtoolBase):
result = runCmd('bitbake-layers remove-layer %s' % templayerdir, cwd=self.builddir)
result = runCmd('devtool update-recipe %s -a %s' % (testrecipe, templayerdir))
self.assertIn('WARNING: Specified layer is not currently enabled in bblayers.conf', result.output)
- self.assertTrue(os.path.exists(patchfile), 'Patch file not created (with disabled layer)')
+ self.assertExists(patchfile, 'Patch file not created (with disabled layer)')
with open(bbappendfile, 'r') as f:
self.assertEqual(expectedlines, f.readlines())
# Deleting isn't expected to work under these circumstances
- @testcase(1171)
def test_devtool_update_recipe_append_git(self):
# Check preconditions
- testrecipe = 'mtd-utils'
- recipefile = get_bb_var('FILE', testrecipe)
- src_uri = get_bb_var('SRC_URI', testrecipe)
+ testrecipe = 'mtd-utils-selftest'
+ bb_vars = get_bb_vars(['FILE', 'SRC_URI', 'LAYERSERIES_CORENAMES'], testrecipe)
+ recipefile = bb_vars['FILE']
+ src_uri = bb_vars['SRC_URI']
+ corenames = bb_vars['LAYERSERIES_CORENAMES']
self.assertIn('git://', src_uri, 'This test expects the %s recipe to be a git recipe' % testrecipe)
for entry in src_uri.split():
if entry.startswith('git://'):
@@ -791,7 +1098,7 @@ class DevtoolTests(DevtoolBase):
# Check git repo
self._check_src_repo(tempsrcdir)
# Add a commit
- result = runCmd('echo "# Additional line" >> Makefile', cwd=tempsrcdir)
+ result = runCmd('echo "# Additional line" >> Makefile.am', cwd=tempsrcdir)
result = runCmd('git commit -a -m "Change the Makefile"', cwd=tempsrcdir)
self.add_command_to_tearDown('cd %s; rm -f %s/*.patch; git checkout .' % (os.path.dirname(recipefile), testrecipe))
# Create a temporary layer
@@ -803,6 +1110,7 @@ class DevtoolTests(DevtoolBase):
f.write('BBFILE_PATTERN_oeselftesttemplayer = "^${LAYERDIR}/"\n')
f.write('BBFILE_PRIORITY_oeselftesttemplayer = "999"\n')
f.write('BBFILE_PATTERN_IGNORE_EMPTY_oeselftesttemplayer = "1"\n')
+ f.write('LAYERSERIES_COMPAT_oeselftesttemplayer = "%s"\n' % corenames)
self.add_command_to_tearDown('bitbake-layers remove-layer %s || true' % templayerdir)
result = runCmd('bitbake-layers add-layer %s' % templayerdir, cwd=self.builddir)
# Create the bbappend
@@ -814,7 +1122,7 @@ class DevtoolTests(DevtoolBase):
splitpath = os.path.dirname(recipefile).split(os.sep)
appenddir = os.path.join(templayerdir, splitpath[-2], splitpath[-1])
bbappendfile = self._check_bbappend(testrecipe, recipefile, appenddir)
- self.assertFalse(os.path.exists(os.path.join(appenddir, testrecipe)), 'Patch directory should not be created')
+ self.assertNotExists(os.path.join(appenddir, testrecipe), 'Patch directory should not be created')
# Check bbappend contents
result = runCmd('git rev-parse HEAD', cwd=tempsrcdir)
@@ -832,7 +1140,7 @@ class DevtoolTests(DevtoolBase):
# Drop new commit and check SRCREV changes
result = runCmd('git reset HEAD^', cwd=tempsrcdir)
result = runCmd('devtool update-recipe -m srcrev %s -a %s' % (testrecipe, templayerdir))
- self.assertFalse(os.path.exists(os.path.join(appenddir, testrecipe)), 'Patch directory should not be created')
+ self.assertNotExists(os.path.join(appenddir, testrecipe), 'Patch directory should not be created')
result = runCmd('git rev-parse HEAD', cwd=tempsrcdir)
expectedlines = set(['SRCREV = "%s"\n' % result.output,
'\n',
@@ -846,7 +1154,7 @@ class DevtoolTests(DevtoolBase):
result = runCmd('bitbake-layers remove-layer %s' % templayerdir, cwd=self.builddir)
result = runCmd('devtool update-recipe -m srcrev %s -a %s' % (testrecipe, templayerdir))
self.assertIn('WARNING: Specified layer is not currently enabled in bblayers.conf', result.output)
- self.assertFalse(os.path.exists(os.path.join(appenddir, testrecipe)), 'Patch directory should not be created')
+ self.assertNotExists(os.path.join(appenddir, testrecipe), 'Patch directory should not be created')
result = runCmd('git rev-parse HEAD', cwd=tempsrcdir)
expectedlines = set(['SRCREV = "%s"\n' % result.output,
'\n',
@@ -856,7 +1164,6 @@ class DevtoolTests(DevtoolBase):
self.assertEqual(expectedlines, set(f.readlines()))
# Deleting isn't expected to work under these circumstances
- @testcase(1370)
def test_devtool_update_recipe_local_files(self):
"""Check that local source files are copied over instead of patched"""
testrecipe = 'makedevs'
@@ -871,6 +1178,8 @@ class DevtoolTests(DevtoolBase):
result = runCmd('devtool modify %s -x %s' % (testrecipe, tempdir))
# Check git repo
self._check_src_repo(tempdir)
+ # Try building just to ensure we haven't broken that
+ bitbake("%s" % testrecipe)
# Edit / commit local source
runCmd('echo "/* Foobar */" >> oe-local-files/makedevs.c', cwd=tempdir)
runCmd('echo "Foo" > oe-local-files/new-local', cwd=tempdir)
@@ -886,11 +1195,14 @@ class DevtoolTests(DevtoolBase):
('??', '.*/makedevs/0001-Add-new-file.patch$')]
self._check_repo_status(os.path.dirname(recipefile), expected_status)
- @testcase(1371)
def test_devtool_update_recipe_local_files_2(self):
"""Check local source files support when oe-local-files is in Git"""
- testrecipe = 'lzo'
+ testrecipe = 'devtool-test-local'
recipefile = get_bb_var('FILE', testrecipe)
+ recipedir = os.path.dirname(recipefile)
+ result = runCmd('git status --porcelain .', cwd=recipedir)
+ if result.output.strip():
+ self.fail('Recipe directory for %s contains uncommitted changes' % testrecipe)
# Setup srctree for modifying the recipe
tempdir = tempfile.mkdtemp(prefix='devtoolqa')
self.track_for_cleanup(tempdir)
@@ -904,9 +1216,9 @@ class DevtoolTests(DevtoolBase):
runCmd('git add oe-local-files', cwd=tempdir)
runCmd('git commit -m "Add local sources"', cwd=tempdir)
# Edit / commit local sources
- runCmd('echo "# Foobar" >> oe-local-files/acinclude.m4', cwd=tempdir)
+ runCmd('echo "# Foobar" >> oe-local-files/file1', cwd=tempdir)
runCmd('git commit -am "Edit existing file"', cwd=tempdir)
- runCmd('git rm oe-local-files/run-ptest', cwd=tempdir)
+ runCmd('git rm oe-local-files/file2', cwd=tempdir)
runCmd('git commit -m"Remove file"', cwd=tempdir)
runCmd('echo "Foo" > oe-local-files/new-local', cwd=tempdir)
runCmd('git add oe-local-files/new-local', cwd=tempdir)
@@ -918,39 +1230,229 @@ class DevtoolTests(DevtoolBase):
os.path.dirname(recipefile))
# Checkout unmodified file to working copy -> devtool should still pick
# the modified version from HEAD
- runCmd('git checkout HEAD^ -- oe-local-files/acinclude.m4', cwd=tempdir)
+ runCmd('git checkout HEAD^ -- oe-local-files/file1', cwd=tempdir)
runCmd('devtool update-recipe %s' % testrecipe)
expected_status = [(' M', '.*/%s$' % os.path.basename(recipefile)),
- (' M', '.*/acinclude.m4$'),
- (' D', '.*/run-ptest$'),
+ (' M', '.*/file1$'),
+ (' D', '.*/file2$'),
('??', '.*/new-local$'),
('??', '.*/0001-Add-new-file.patch$')]
self._check_repo_status(os.path.dirname(recipefile), expected_status)
- @testcase(1163)
+ def test_devtool_update_recipe_with_gitignore(self):
+ # First, modify the recipe
+ testrecipe = 'devtool-test-ignored'
+ bb_vars = get_bb_vars(['FILE'], testrecipe)
+ recipefile = bb_vars['FILE']
+ patchfile = os.path.join(os.path.dirname(recipefile), testrecipe, testrecipe + '.patch')
+ newpatchfile = os.path.join(os.path.dirname(recipefile), testrecipe, testrecipe + '.patch.expected')
+ tempdir = tempfile.mkdtemp(prefix='devtoolqa')
+ self.track_for_cleanup(tempdir)
+ self.track_for_cleanup(self.workspacedir)
+ self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
+ # (don't bother with cleaning the recipe on teardown, we won't be building it)
+ result = runCmd('devtool modify %s' % testrecipe)
+ self.add_command_to_tearDown('cd %s; rm %s/*; git checkout %s %s' % (os.path.dirname(recipefile), testrecipe, testrecipe, os.path.basename(recipefile)))
+ result = runCmd('devtool finish --force-patch-refresh %s meta-selftest' % testrecipe)
+ # Check recipe got changed as expected
+ with open(newpatchfile, 'r') as f:
+ desiredlines = f.readlines()
+ with open(patchfile, 'r') as f:
+ newlines = f.readlines()
+ # Ignore the initial lines, because oe-selftest creates own meta-selftest repo
+ # which changes the metadata subject which is added into the patch, but keep
+ # .patch.expected as it is in case someone runs devtool finish --force-patch-refresh
+ # devtool-test-ignored manually, then it should generate exactly the same .patch file
+ self.assertEqual(desiredlines[5:], newlines[5:])
+
+ def test_devtool_update_recipe_long_filename(self):
+ # First, modify the recipe
+ testrecipe = 'devtool-test-long-filename'
+ bb_vars = get_bb_vars(['FILE'], testrecipe)
+ recipefile = bb_vars['FILE']
+ patchfilename = '0001-I-ll-patch-you-only-if-devtool-lets-me-to-do-it-corr.patch'
+ patchfile = os.path.join(os.path.dirname(recipefile), testrecipe, patchfilename)
+ newpatchfile = os.path.join(os.path.dirname(recipefile), testrecipe, patchfilename + '.expected')
+ tempdir = tempfile.mkdtemp(prefix='devtoolqa')
+ self.track_for_cleanup(tempdir)
+ self.track_for_cleanup(self.workspacedir)
+ self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
+ # (don't bother with cleaning the recipe on teardown, we won't be building it)
+ result = runCmd('devtool modify %s' % testrecipe)
+ self.add_command_to_tearDown('cd %s; rm %s/*; git checkout %s %s' % (os.path.dirname(recipefile), testrecipe, testrecipe, os.path.basename(recipefile)))
+ result = runCmd('devtool finish --force-patch-refresh %s meta-selftest' % testrecipe)
+ # Check recipe got changed as expected
+ with open(newpatchfile, 'r') as f:
+ desiredlines = f.readlines()
+ with open(patchfile, 'r') as f:
+ newlines = f.readlines()
+ # Ignore the initial lines, because oe-selftest creates own meta-selftest repo
+ # which changes the metadata subject which is added into the patch, but keep
+ # .patch.expected as it is in case someone runs devtool finish --force-patch-refresh
+ # devtool-test-ignored manually, then it should generate exactly the same .patch file
+ self.assertEqual(desiredlines[5:], newlines[5:])
+
+ def test_devtool_update_recipe_local_files_3(self):
+ # First, modify the recipe
+ testrecipe = 'devtool-test-localonly'
+ bb_vars = get_bb_vars(['FILE', 'SRC_URI'], testrecipe)
+ recipefile = bb_vars['FILE']
+ src_uri = bb_vars['SRC_URI']
+ tempdir = tempfile.mkdtemp(prefix='devtoolqa')
+ self.track_for_cleanup(tempdir)
+ self.track_for_cleanup(self.workspacedir)
+ self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
+ # (don't bother with cleaning the recipe on teardown, we won't be building it)
+ result = runCmd('devtool modify %s' % testrecipe)
+ # Modify one file
+ runCmd('echo "Another line" >> file2', cwd=os.path.join(self.workspacedir, 'sources', testrecipe, 'oe-local-files'))
+ self.add_command_to_tearDown('cd %s; rm %s/*; git checkout %s %s' % (os.path.dirname(recipefile), testrecipe, testrecipe, os.path.basename(recipefile)))
+ result = runCmd('devtool update-recipe %s' % testrecipe)
+ expected_status = [(' M', '.*/%s/file2$' % testrecipe)]
+ self._check_repo_status(os.path.dirname(recipefile), expected_status)
+
+ def test_devtool_update_recipe_local_patch_gz(self):
+ # First, modify the recipe
+ testrecipe = 'devtool-test-patch-gz'
+ if get_bb_var('DISTRO') == 'poky-tiny':
+ self.skipTest("The DISTRO 'poky-tiny' does not provide the dependencies needed by %s" % testrecipe)
+ bb_vars = get_bb_vars(['FILE', 'SRC_URI'], testrecipe)
+ recipefile = bb_vars['FILE']
+ src_uri = bb_vars['SRC_URI']
+ tempdir = tempfile.mkdtemp(prefix='devtoolqa')
+ self.track_for_cleanup(tempdir)
+ self.track_for_cleanup(self.workspacedir)
+ self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
+ # (don't bother with cleaning the recipe on teardown, we won't be building it)
+ result = runCmd('devtool modify %s' % testrecipe)
+ # Modify one file
+ srctree = os.path.join(self.workspacedir, 'sources', testrecipe)
+ runCmd('echo "Another line" >> README', cwd=srctree)
+ runCmd('git commit -a --amend --no-edit', cwd=srctree)
+ self.add_command_to_tearDown('cd %s; rm %s/*; git checkout %s %s' % (os.path.dirname(recipefile), testrecipe, testrecipe, os.path.basename(recipefile)))
+ result = runCmd('devtool update-recipe %s' % testrecipe)
+ expected_status = [(' M', '.*/%s/readme.patch.gz$' % testrecipe)]
+ self._check_repo_status(os.path.dirname(recipefile), expected_status)
+ patch_gz = os.path.join(os.path.dirname(recipefile), testrecipe, 'readme.patch.gz')
+ result = runCmd('file %s' % patch_gz)
+ if 'gzip compressed data' not in result.output:
+ self.fail('New patch file is not gzipped - file reports:\n%s' % result.output)
+
+ def test_devtool_update_recipe_local_files_subdir(self):
+ # Try devtool update-recipe on a recipe that has a file with subdir= set in
+ # SRC_URI such that it overwrites a file that was in an archive that
+ # was also in SRC_URI
+ # First, modify the recipe
+ testrecipe = 'devtool-test-subdir'
+ bb_vars = get_bb_vars(['FILE', 'SRC_URI'], testrecipe)
+ recipefile = bb_vars['FILE']
+ src_uri = bb_vars['SRC_URI']
+ tempdir = tempfile.mkdtemp(prefix='devtoolqa')
+ self.track_for_cleanup(tempdir)
+ self.track_for_cleanup(self.workspacedir)
+ self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
+ # (don't bother with cleaning the recipe on teardown, we won't be building it)
+ result = runCmd('devtool modify %s' % testrecipe)
+ testfile = os.path.join(self.workspacedir, 'sources', testrecipe, 'testfile')
+ self.assertExists(testfile, 'Extracted source could not be found')
+ with open(testfile, 'r') as f:
+ contents = f.read().rstrip()
+ self.assertEqual(contents, 'Modified version', 'File has apparently not been overwritten as it should have been')
+ # Test devtool update-recipe without modifying any files
+ self.add_command_to_tearDown('cd %s; rm %s/*; git checkout %s %s' % (os.path.dirname(recipefile), testrecipe, testrecipe, os.path.basename(recipefile)))
+ result = runCmd('devtool update-recipe %s' % testrecipe)
+ expected_status = []
+ self._check_repo_status(os.path.dirname(recipefile), expected_status)
+
+ def test_devtool_finish_modify_git_subdir(self):
+ # Check preconditions
+ testrecipe = 'dos2unix'
+ bb_vars = get_bb_vars(['SRC_URI', 'S', 'WORKDIR', 'FILE'], testrecipe)
+ self.assertIn('git://', bb_vars['SRC_URI'], 'This test expects the %s recipe to be a git recipe' % testrecipe)
+ workdir_git = '%s/git/' % bb_vars['WORKDIR']
+ if not bb_vars['S'].startswith(workdir_git):
+ self.fail('This test expects the %s recipe to be building from a subdirectory of the git repo' % testrecipe)
+ subdir = bb_vars['S'].split(workdir_git, 1)[1]
+ # Clean up anything in the workdir/sysroot/sstate cache
+ bitbake('%s -c cleansstate' % testrecipe)
+ # Try modifying a recipe
+ tempdir = tempfile.mkdtemp(prefix='devtoolqa')
+ self.track_for_cleanup(tempdir)
+ self.track_for_cleanup(self.workspacedir)
+ self.add_command_to_tearDown('bitbake -c clean %s' % testrecipe)
+ self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
+ result = runCmd('devtool modify %s -x %s' % (testrecipe, tempdir))
+ testsrcfile = os.path.join(tempdir, subdir, 'dos2unix.c')
+ self.assertExists(testsrcfile, 'Extracted source could not be found')
+ self.assertExists(os.path.join(self.workspacedir, 'conf', 'layer.conf'), 'Workspace directory not created. devtool output: %s' % result.output)
+ self.assertNotExists(os.path.join(tempdir, subdir, '.git'), 'Subdirectory has been initialised as a git repo')
+ # Check git repo
+ self._check_src_repo(tempdir)
+ # Modify file
+ runCmd("sed -i '1s:^:/* Add a comment */\\n:' %s" % testsrcfile)
+ result = runCmd('git commit -a -m "Add a comment"', cwd=tempdir)
+ # Now try updating original recipe
+ recipefile = bb_vars['FILE']
+ recipedir = os.path.dirname(recipefile)
+ self.add_command_to_tearDown('cd %s; rm -f %s/*.patch; git checkout .' % (recipedir, testrecipe))
+ result = runCmd('devtool update-recipe %s' % testrecipe)
+ expected_status = [(' M', '.*/%s$' % os.path.basename(recipefile)),
+ ('??', '.*/%s/%s/$' % (testrecipe, testrecipe))]
+ self._check_repo_status(os.path.dirname(recipefile), expected_status)
+ result = runCmd('git diff %s' % os.path.basename(recipefile), cwd=os.path.dirname(recipefile))
+ removelines = ['SRC_URI = "git://.*"']
+ addlines = [
+ 'SRC_URI = "git://.* \\\\',
+ 'file://0001-Add-a-comment.patch;patchdir=.. \\\\',
+ '"'
+ ]
+ self._check_diff(result.output, addlines, removelines)
+ # Put things back so we can run devtool finish on a different layer
+ runCmd('cd %s; rm -f %s/*.patch; git checkout .' % (recipedir, testrecipe))
+ # Run devtool finish
+ res = re.search('recipes-.*', recipedir)
+ self.assertTrue(res, 'Unable to find recipe subdirectory')
+ recipesubdir = res[0]
+ self.add_command_to_tearDown('rm -rf %s' % os.path.join(self.testlayer_path, recipesubdir))
+ result = runCmd('devtool finish %s meta-selftest' % testrecipe)
+ # Check bbappend file contents
+ appendfn = os.path.join(self.testlayer_path, recipesubdir, '%s_%%.bbappend' % testrecipe)
+ with open(appendfn, 'r') as f:
+ appendlines = f.readlines()
+ expected_appendlines = [
+ 'FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:"\n',
+ '\n',
+ 'SRC_URI += "file://0001-Add-a-comment.patch;patchdir=.."\n',
+ '\n'
+ ]
+ self.assertEqual(appendlines, expected_appendlines)
+ self.assertExists(os.path.join(os.path.dirname(appendfn), testrecipe, '0001-Add-a-comment.patch'))
+ # Try building
+ bitbake('%s -c patch' % testrecipe)
+
+
+class DevtoolExtractTests(DevtoolBase):
+
def test_devtool_extract(self):
tempdir = tempfile.mkdtemp(prefix='devtoolqa')
# Try devtool extract
self.track_for_cleanup(tempdir)
- self.append_config('PREFERRED_PROVIDER_virtual/make = "remake"')
- result = runCmd('devtool extract remake %s' % tempdir)
- self.assertTrue(os.path.exists(os.path.join(tempdir, 'Makefile.am')), 'Extracted source could not be found')
- # devtool extract shouldn't create the workspace
- self.assertFalse(os.path.exists(self.workspacedir))
+ self.track_for_cleanup(self.workspacedir)
+ self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
+ result = runCmd('devtool extract matchbox-terminal %s' % tempdir)
+ self.assertExists(os.path.join(tempdir, 'Makefile.am'), 'Extracted source could not be found')
self._check_src_repo(tempdir)
- @testcase(1379)
def test_devtool_extract_virtual(self):
tempdir = tempfile.mkdtemp(prefix='devtoolqa')
# Try devtool extract
self.track_for_cleanup(tempdir)
- result = runCmd('devtool extract virtual/libx11 %s' % tempdir)
- self.assertTrue(os.path.exists(os.path.join(tempdir, 'Makefile.am')), 'Extracted source could not be found')
- # devtool extract shouldn't create the workspace
- self.assertFalse(os.path.exists(self.workspacedir))
+ self.track_for_cleanup(self.workspacedir)
+ self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
+ result = runCmd('devtool extract virtual/make %s' % tempdir)
+ self.assertExists(os.path.join(tempdir, 'Makefile.am'), 'Extracted source could not be found')
self._check_src_repo(tempdir)
- @testcase(1168)
def test_devtool_reset_all(self):
tempdir = tempfile.mkdtemp(prefix='devtoolqa')
self.track_for_cleanup(tempdir)
@@ -977,7 +1479,7 @@ class DevtoolTests(DevtoolBase):
matches2 = glob.glob(stampprefix2 + '*')
self.assertFalse(matches2, 'Stamp files exist for recipe %s that should have been cleaned' % testrecipe2)
- @testcase(1272)
+ @OETestTag("runqemu")
def test_devtool_deploy_target(self):
# NOTE: Whilst this test would seemingly be better placed as a runtime test,
# unfortunately the runtime tests run under bitbake and you can't run
@@ -1018,8 +1520,8 @@ class DevtoolTests(DevtoolBase):
tempdir = tempfile.mkdtemp(prefix='devtoolqa')
self.track_for_cleanup(tempdir)
self.track_for_cleanup(self.workspacedir)
- self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
self.add_command_to_tearDown('bitbake -c clean %s' % testrecipe)
+ self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
result = runCmd('devtool modify %s -x %s' % (testrecipe, tempdir))
# Test that deploy-target at this point fails (properly)
result = runCmd('devtool deploy-target -n %s root@localhost' % testrecipe, ignore_status=True)
@@ -1038,10 +1540,11 @@ class DevtoolTests(DevtoolBase):
result = runCmd('ssh %s root@%s %s' % (sshargs, qemu.ip, testcommand))
# Check if it deployed all of the files with the right ownership/perms
# First look on the host - need to do this under pseudo to get the correct ownership/perms
- installdir = get_bb_var('D', testrecipe)
- fakerootenv = get_bb_var('FAKEROOTENV', testrecipe)
- fakerootcmd = get_bb_var('FAKEROOTCMD', testrecipe)
- result = runCmd('%s %s find . -type f -exec ls -l {} \;' % (fakerootenv, fakerootcmd), cwd=installdir)
+ bb_vars = get_bb_vars(['D', 'FAKEROOTENV', 'FAKEROOTCMD'], testrecipe)
+ installdir = bb_vars['D']
+ fakerootenv = bb_vars['FAKEROOTENV']
+ fakerootcmd = bb_vars['FAKEROOTCMD']
+ result = runCmd('%s %s find . -type f -exec ls -l {} \\;' % (fakerootenv, fakerootcmd), cwd=installdir)
filelist1 = self._process_ls_output(result.output)
# Now look on the target
@@ -1062,15 +1565,14 @@ class DevtoolTests(DevtoolBase):
result = runCmd('ssh %s root@%s %s' % (sshargs, qemu.ip, testcommand), ignore_status=True)
self.assertNotEqual(result, 0, 'undeploy-target did not remove command as it should have')
- @testcase(1366)
def test_devtool_build_image(self):
"""Test devtool build-image plugin"""
# Check preconditions
self.assertTrue(not os.path.exists(self.workspacedir), 'This test cannot be run with a workspace directory under the build directory')
image = 'core-image-minimal'
self.track_for_cleanup(self.workspacedir)
- self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
self.add_command_to_tearDown('bitbake -c clean %s' % image)
+ self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
bitbake('%s -c clean' % image)
# Add target and native recipes to workspace
recipes = ['mdadm', 'parted-native']
@@ -1096,7 +1598,16 @@ class DevtoolTests(DevtoolBase):
if reqpkgs:
self.fail('The following packages were not present in the image as expected: %s' % ', '.join(reqpkgs))
- @testcase(1367)
+class DevtoolUpgradeTests(DevtoolBase):
+
+ def setUp(self):
+ super().setUp()
+ try:
+ runCmd("git config --global user.name")
+ runCmd("git config --global user.email")
+ except:
+ self.skip("Git user.name and user.email must be set")
+
def test_devtool_upgrade(self):
# Check preconditions
self.assertTrue(not os.path.exists(self.workspacedir), 'This test cannot be run with a workspace directory under the build directory')
@@ -1121,10 +1632,10 @@ class DevtoolTests(DevtoolBase):
# Check if srctree at least is populated
self.assertTrue(len(os.listdir(tempdir)) > 0, 'srctree (%s) should be populated with new (%s) source code' % (tempdir, version))
# Check new recipe subdirectory is present
- self.assertTrue(os.path.exists(os.path.join(self.workspacedir, 'recipes', recipe, '%s-%s' % (recipe, version))), 'Recipe folder should exist')
+ self.assertExists(os.path.join(self.workspacedir, 'recipes', recipe, '%s-%s' % (recipe, version)), 'Recipe folder should exist')
# Check new recipe file is present
newrecipefile = os.path.join(self.workspacedir, 'recipes', recipe, '%s_%s.bb' % (recipe, version))
- self.assertTrue(os.path.exists(newrecipefile), 'Recipe file should exist after upgrade')
+ self.assertExists(newrecipefile, 'Recipe file should exist after upgrade')
# Check devtool status and make sure recipe is present
result = runCmd('devtool status')
self.assertIn(recipe, result.output)
@@ -1139,9 +1650,8 @@ class DevtoolTests(DevtoolBase):
result = runCmd('devtool reset %s -n' % recipe)
result = runCmd('devtool status')
self.assertNotIn(recipe, result.output)
- self.assertFalse(os.path.exists(os.path.join(self.workspacedir, 'recipes', recipe)), 'Recipe directory should not exist after resetting')
+ self.assertNotExists(os.path.join(self.workspacedir, 'recipes', recipe), 'Recipe directory should not exist after resetting')
- @testcase(1433)
def test_devtool_upgrade_git(self):
# Check preconditions
self.assertTrue(not os.path.exists(self.workspacedir), 'This test cannot be run with a workspace directory under the build directory')
@@ -1161,7 +1671,7 @@ class DevtoolTests(DevtoolBase):
self.assertTrue(len(os.listdir(tempdir)) > 0, 'srctree (%s) should be populated with new (%s) source code' % (tempdir, commit))
# Check new recipe file is present
newrecipefile = os.path.join(self.workspacedir, 'recipes', recipe, os.path.basename(oldrecipefile))
- self.assertTrue(os.path.exists(newrecipefile), 'Recipe file should exist after upgrade')
+ self.assertExists(newrecipefile, 'Recipe file should exist after upgrade')
# Check devtool status and make sure recipe is present
result = runCmd('devtool status')
self.assertIn(recipe, result.output)
@@ -1176,9 +1686,8 @@ class DevtoolTests(DevtoolBase):
result = runCmd('devtool reset %s -n' % recipe)
result = runCmd('devtool status')
self.assertNotIn(recipe, result.output)
- self.assertFalse(os.path.exists(os.path.join(self.workspacedir, 'recipes', recipe)), 'Recipe directory should not exist after resetting')
+ self.assertNotExists(os.path.join(self.workspacedir, 'recipes', recipe), 'Recipe directory should not exist after resetting')
- @testcase(1352)
def test_devtool_layer_plugins(self):
"""Test that devtool can use plugins from other layers.
@@ -1191,6 +1700,53 @@ class DevtoolTests(DevtoolBase):
result = runCmd("devtool --quiet selftest-reverse \"%s\"" % s)
self.assertEqual(result.output, s[::-1])
+ def _copy_file_with_cleanup(self, srcfile, basedstdir, *paths):
+ dstdir = basedstdir
+ self.assertExists(dstdir)
+ for p in paths:
+ dstdir = os.path.join(dstdir, p)
+ if not os.path.exists(dstdir):
+ os.makedirs(dstdir)
+ if p == "lib":
+ # Can race with other tests
+ self.add_command_to_tearDown('rmdir --ignore-fail-on-non-empty %s' % dstdir)
+ else:
+ self.track_for_cleanup(dstdir)
+ dstfile = os.path.join(dstdir, os.path.basename(srcfile))
+ if srcfile != dstfile:
+ shutil.copy(srcfile, dstfile)
+ self.track_for_cleanup(dstfile)
+
+ def test_devtool_load_plugin(self):
+ """Test that devtool loads only the first found plugin in BBPATH."""
+
+ self.track_for_cleanup(self.workspacedir)
+ self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
+
+ devtool = runCmd("which devtool")
+ fromname = runCmd("devtool --quiet pluginfile")
+ srcfile = fromname.output
+ bbpath = get_bb_var('BBPATH')
+ searchpath = bbpath.split(':') + [os.path.dirname(devtool.output)]
+ plugincontent = []
+ with open(srcfile) as fh:
+ plugincontent = fh.readlines()
+ try:
+ self.assertIn('meta-selftest', srcfile, 'wrong bbpath plugin found')
+ for path in searchpath:
+ self._copy_file_with_cleanup(srcfile, path, 'lib', 'devtool')
+ result = runCmd("devtool --quiet count")
+ self.assertEqual(result.output, '1')
+ result = runCmd("devtool --quiet multiloaded")
+ self.assertEqual(result.output, "no")
+ for path in searchpath:
+ result = runCmd("devtool --quiet bbdir")
+ self.assertEqual(result.output, path)
+ os.unlink(os.path.join(result.output, 'lib', 'devtool', 'bbpath.py'))
+ finally:
+ with open(srcfile, 'w') as fh:
+ fh.writelines(plugincontent)
+
def _setup_test_devtool_finish_upgrade(self):
# Check preconditions
self.assertTrue(not os.path.exists(self.workspacedir), 'This test cannot be run with a workspace directory under the build directory')
@@ -1225,11 +1781,13 @@ class DevtoolTests(DevtoolBase):
recipedir = os.path.dirname(oldrecipefile)
olddir = os.path.join(recipedir, recipe + '-' + oldversion)
patchfn = '0001-Add-a-note-line-to-the-quick-reference.patch'
- self.assertTrue(os.path.exists(os.path.join(olddir, patchfn)), 'Original patch file does not exist')
- return recipe, oldrecipefile, recipedir, olddir, newversion, patchfn
+ backportedpatchfn = 'backported.patch'
+ self.assertExists(os.path.join(olddir, patchfn), 'Original patch file does not exist')
+ self.assertExists(os.path.join(olddir, backportedpatchfn), 'Backported patch file does not exist')
+ return recipe, oldrecipefile, recipedir, olddir, newversion, patchfn, backportedpatchfn
def test_devtool_finish_upgrade_origlayer(self):
- recipe, oldrecipefile, recipedir, olddir, newversion, patchfn = self._setup_test_devtool_finish_upgrade()
+ recipe, oldrecipefile, recipedir, olddir, newversion, patchfn, backportedpatchfn = self._setup_test_devtool_finish_upgrade()
# Ensure the recipe is where we think it should be (so that cleanup doesn't trash things)
self.assertIn('/meta-selftest/', recipedir)
# Try finish to the original layer
@@ -1237,17 +1795,26 @@ class DevtoolTests(DevtoolBase):
result = runCmd('devtool finish %s meta-selftest' % recipe)
result = runCmd('devtool status')
self.assertNotIn(recipe, result.output, 'Recipe should have been reset by finish but wasn\'t')
- self.assertFalse(os.path.exists(os.path.join(self.workspacedir, 'recipes', recipe)), 'Recipe directory should not exist after finish')
- self.assertFalse(os.path.exists(oldrecipefile), 'Old recipe file should have been deleted but wasn\'t')
- self.assertFalse(os.path.exists(os.path.join(olddir, patchfn)), 'Old patch file should have been deleted but wasn\'t')
+ self.assertNotExists(os.path.join(self.workspacedir, 'recipes', recipe), 'Recipe directory should not exist after finish')
+ self.assertNotExists(oldrecipefile, 'Old recipe file should have been deleted but wasn\'t')
+ self.assertNotExists(os.path.join(olddir, patchfn), 'Old patch file should have been deleted but wasn\'t')
+ self.assertNotExists(os.path.join(olddir, backportedpatchfn), 'Old backported patch file should have been deleted but wasn\'t')
newrecipefile = os.path.join(recipedir, '%s_%s.bb' % (recipe, newversion))
newdir = os.path.join(recipedir, recipe + '-' + newversion)
- self.assertTrue(os.path.exists(newrecipefile), 'New recipe file should have been copied into existing layer but wasn\'t')
- self.assertTrue(os.path.exists(os.path.join(newdir, patchfn)), 'Patch file should have been copied into new directory but wasn\'t')
- self.assertTrue(os.path.exists(os.path.join(newdir, '0002-Add-a-comment-to-the-code.patch')), 'New patch file should have been created but wasn\'t')
+ self.assertExists(newrecipefile, 'New recipe file should have been copied into existing layer but wasn\'t')
+ self.assertExists(os.path.join(newdir, patchfn), 'Patch file should have been copied into new directory but wasn\'t')
+ self.assertNotExists(os.path.join(newdir, backportedpatchfn), 'Backported patch file should not have been copied into new directory but was')
+ self.assertExists(os.path.join(newdir, '0002-Add-a-comment-to-the-code.patch'), 'New patch file should have been created but wasn\'t')
+ with open(newrecipefile, 'r') as f:
+ newcontent = f.read()
+ self.assertNotIn(backportedpatchfn, newcontent, "Backported patch should have been removed from the recipe but wasn't")
+ self.assertIn(patchfn, newcontent, "Old patch should have not been removed from the recipe but was")
+ self.assertIn("0002-Add-a-comment-to-the-code.patch", newcontent, "New patch should have been added to the recipe but wasn't")
+ self.assertIn("http://www.ivarch.com/programs/sources/pv-${PV}.tar.gz", newcontent, "New recipe no longer has upstream source in SRC_URI")
+
def test_devtool_finish_upgrade_otherlayer(self):
- recipe, oldrecipefile, recipedir, olddir, newversion, patchfn = self._setup_test_devtool_finish_upgrade()
+ recipe, oldrecipefile, recipedir, olddir, newversion, patchfn, backportedpatchfn = self._setup_test_devtool_finish_upgrade()
# Ensure the recipe is where we think it should be (so that cleanup doesn't trash things)
self.assertIn('/meta-selftest/', recipedir)
# Try finish to a different layer - should create a bbappend
@@ -1260,13 +1827,21 @@ class DevtoolTests(DevtoolBase):
result = runCmd('devtool finish %s oe-core' % recipe)
result = runCmd('devtool status')
self.assertNotIn(recipe, result.output, 'Recipe should have been reset by finish but wasn\'t')
- self.assertFalse(os.path.exists(os.path.join(self.workspacedir, 'recipes', recipe)), 'Recipe directory should not exist after finish')
- self.assertTrue(os.path.exists(oldrecipefile), 'Old recipe file should not have been deleted')
- self.assertTrue(os.path.exists(os.path.join(olddir, patchfn)), 'Old patch file should not have been deleted')
+ self.assertNotExists(os.path.join(self.workspacedir, 'recipes', recipe), 'Recipe directory should not exist after finish')
+ self.assertExists(oldrecipefile, 'Old recipe file should not have been deleted')
+ self.assertExists(os.path.join(olddir, patchfn), 'Old patch file should not have been deleted')
+ self.assertExists(os.path.join(olddir, backportedpatchfn), 'Old backported patch file should not have been deleted')
newdir = os.path.join(newrecipedir, recipe + '-' + newversion)
- self.assertTrue(os.path.exists(newrecipefile), 'New recipe file should have been copied into existing layer but wasn\'t')
- self.assertTrue(os.path.exists(os.path.join(newdir, patchfn)), 'Patch file should have been copied into new directory but wasn\'t')
- self.assertTrue(os.path.exists(os.path.join(newdir, '0002-Add-a-comment-to-the-code.patch')), 'New patch file should have been created but wasn\'t')
+ self.assertExists(newrecipefile, 'New recipe file should have been copied into existing layer but wasn\'t')
+ self.assertExists(os.path.join(newdir, patchfn), 'Patch file should have been copied into new directory but wasn\'t')
+ self.assertNotExists(os.path.join(newdir, backportedpatchfn), 'Backported patch file should not have been copied into new directory but was')
+ self.assertExists(os.path.join(newdir, '0002-Add-a-comment-to-the-code.patch'), 'New patch file should have been created but wasn\'t')
+ with open(newrecipefile, 'r') as f:
+ newcontent = f.read()
+ self.assertNotIn(backportedpatchfn, newcontent, "Backported patch should have been removed from the recipe but wasn't")
+ self.assertIn(patchfn, newcontent, "Old patch should have not been removed from the recipe but was")
+ self.assertIn("0002-Add-a-comment-to-the-code.patch", newcontent, "New patch should have been added to the recipe but wasn't")
+ self.assertIn("http://www.ivarch.com/programs/sources/pv-${PV}.tar.gz", newcontent, "New recipe no longer has upstream source in SRC_URI")
def _setup_test_devtool_finish_modify(self):
# Check preconditions
@@ -1283,7 +1858,7 @@ class DevtoolTests(DevtoolBase):
self.track_for_cleanup(tempdir)
self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
result = runCmd('devtool modify %s %s' % (recipe, tempdir))
- self.assertTrue(os.path.exists(os.path.join(tempdir, 'Makefile')), 'Extracted source could not be found')
+ self.assertExists(os.path.join(tempdir, 'Makefile'), 'Extracted source could not be found')
# Test devtool status
result = runCmd('devtool status')
self.assertIn(recipe, result.output)
@@ -1310,7 +1885,7 @@ class DevtoolTests(DevtoolBase):
result = runCmd('devtool finish %s meta' % recipe)
result = runCmd('devtool status')
self.assertNotIn(recipe, result.output, 'Recipe should have been reset by finish but wasn\'t')
- self.assertFalse(os.path.exists(os.path.join(self.workspacedir, 'recipes', recipe)), 'Recipe directory should not exist after finish')
+ self.assertNotExists(os.path.join(self.workspacedir, 'recipes', recipe), 'Recipe directory should not exist after finish')
expected_status = [(' M', '.*/%s$' % os.path.basename(oldrecipefile)),
('??', '.*/.*-Add-a-comment-to-the-code.patch$')]
self._check_repo_status(recipedir, expected_status)
@@ -1327,12 +1902,14 @@ class DevtoolTests(DevtoolBase):
result = runCmd('devtool finish %s meta-selftest' % recipe)
result = runCmd('devtool status')
self.assertNotIn(recipe, result.output, 'Recipe should have been reset by finish but wasn\'t')
- self.assertFalse(os.path.exists(os.path.join(self.workspacedir, 'recipes', recipe)), 'Recipe directory should not exist after finish')
+ self.assertNotExists(os.path.join(self.workspacedir, 'recipes', recipe), 'Recipe directory should not exist after finish')
result = runCmd('git status --porcelain .', cwd=recipedir)
if result.output.strip():
self.fail('Recipe directory for %s contains the following unexpected changes after finish:\n%s' % (recipe, result.output.strip()))
- appendfile = os.path.join(appenddir, os.path.splitext(os.path.basename(oldrecipefile))[0] + '.bbappend')
- self.assertTrue(os.path.exists(appendfile), 'bbappend %s should have been created but wasn\'t' % appendfile)
+ recipefn = os.path.splitext(os.path.basename(oldrecipefile))[0]
+ recipefn = recipefn.split('_')[0] + '_%'
+ appendfile = os.path.join(appenddir, recipefn + '.bbappend')
+ self.assertExists(appendfile, 'bbappend %s should have been created but wasn\'t' % appendfile)
newdir = os.path.join(appenddir, recipe)
files = os.listdir(newdir)
foundpatch = None
@@ -1344,3 +1921,139 @@ class DevtoolTests(DevtoolBase):
files.remove(foundpatch)
if files:
self.fail('Unexpected file(s) copied next to bbappend: %s' % ', '.join(files))
+
+ def test_devtool_rename(self):
+ # Check preconditions
+ self.assertTrue(not os.path.exists(self.workspacedir), 'This test cannot be run with a workspace directory under the build directory')
+ self.track_for_cleanup(self.workspacedir)
+ self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
+
+ # First run devtool add
+ # We already have this recipe in OE-Core, but that doesn't matter
+ recipename = 'i2c-tools'
+ recipever = '3.1.2'
+ recipefile = os.path.join(self.workspacedir, 'recipes', recipename, '%s_%s.bb' % (recipename, recipever))
+ url = 'http://downloads.yoctoproject.org/mirror/sources/i2c-tools-%s.tar.bz2' % recipever
+ def add_recipe():
+ result = runCmd('devtool add %s' % url)
+ self.assertExists(recipefile, 'Expected recipe file not created')
+ self.assertExists(os.path.join(self.workspacedir, 'sources', recipename), 'Source directory not created')
+ checkvars = {}
+ checkvars['S'] = None
+ checkvars['SRC_URI'] = url.replace(recipever, '${PV}')
+ self._test_recipe_contents(recipefile, checkvars, [])
+ add_recipe()
+ # Now rename it - change both name and version
+ newrecipename = 'mynewrecipe'
+ newrecipever = '456'
+ newrecipefile = os.path.join(self.workspacedir, 'recipes', newrecipename, '%s_%s.bb' % (newrecipename, newrecipever))
+ result = runCmd('devtool rename %s %s -V %s' % (recipename, newrecipename, newrecipever))
+ self.assertExists(newrecipefile, 'Recipe file not renamed')
+ self.assertNotExists(os.path.join(self.workspacedir, 'recipes', recipename), 'Old recipe directory still exists')
+ newsrctree = os.path.join(self.workspacedir, 'sources', newrecipename)
+ self.assertExists(newsrctree, 'Source directory not renamed')
+ checkvars = {}
+ checkvars['S'] = '${WORKDIR}/%s-%s' % (recipename, recipever)
+ checkvars['SRC_URI'] = url
+ self._test_recipe_contents(newrecipefile, checkvars, [])
+ # Try again - change just name this time
+ result = runCmd('devtool reset -n %s' % newrecipename)
+ add_recipe()
+ newrecipefile = os.path.join(self.workspacedir, 'recipes', newrecipename, '%s_%s.bb' % (newrecipename, recipever))
+ result = runCmd('devtool rename %s %s' % (recipename, newrecipename))
+ self.assertExists(newrecipefile, 'Recipe file not renamed')
+ self.assertNotExists(os.path.join(self.workspacedir, 'recipes', recipename), 'Old recipe directory still exists')
+ self.assertExists(os.path.join(self.workspacedir, 'sources', newrecipename), 'Source directory not renamed')
+ checkvars = {}
+ checkvars['S'] = '${WORKDIR}/%s-${PV}' % recipename
+ checkvars['SRC_URI'] = url.replace(recipever, '${PV}')
+ self._test_recipe_contents(newrecipefile, checkvars, [])
+ # Try again - change just version this time
+ result = runCmd('devtool reset -n %s' % newrecipename)
+ add_recipe()
+ newrecipefile = os.path.join(self.workspacedir, 'recipes', recipename, '%s_%s.bb' % (recipename, newrecipever))
+ result = runCmd('devtool rename %s -V %s' % (recipename, newrecipever))
+ self.assertExists(newrecipefile, 'Recipe file not renamed')
+ self.assertExists(os.path.join(self.workspacedir, 'sources', recipename), 'Source directory no longer exists')
+ checkvars = {}
+ checkvars['S'] = '${WORKDIR}/${BPN}-%s' % recipever
+ checkvars['SRC_URI'] = url
+ self._test_recipe_contents(newrecipefile, checkvars, [])
+
+ def test_devtool_virtual_kernel_modify(self):
+ """
+ Summary: The purpose of this test case is to verify that
+ devtool modify works correctly when building
+ the kernel.
+ Dependencies: NA
+ Steps: 1. Build kernel with bitbake.
+ 2. Save the config file generated.
+ 3. Clean the environment.
+ 4. Use `devtool modify virtual/kernel` to validate following:
+ 4.1 The source is checked out correctly.
+ 4.2 The resulting configuration is the same as
+ what was get on step 2.
+ 4.3 The Kernel can be build correctly.
+ 4.4 Changes made on the source are reflected on the
+ subsequent builds.
+ 4.5 Changes on the configuration are reflected on the
+ subsequent builds
+ Expected: devtool modify is able to checkout the source of the kernel
+ and modification to the source and configurations are reflected
+ when building the kernel.
+ """
+ kernel_provider = self.td['PREFERRED_PROVIDER_virtual/kernel']
+
+ # Clean up the environment
+ bitbake('%s -c clean' % kernel_provider)
+ tempdir = tempfile.mkdtemp(prefix='devtoolqa')
+ tempdir_cfg = tempfile.mkdtemp(prefix='config_qa')
+ self.track_for_cleanup(tempdir)
+ self.track_for_cleanup(tempdir_cfg)
+ self.track_for_cleanup(self.workspacedir)
+ self.add_command_to_tearDown('bitbake -c clean %s' % kernel_provider)
+ self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
+ #Step 1
+ #Here is just generated the config file instead of all the kernel to optimize the
+ #time of executing this test case.
+ bitbake('%s -c configure' % kernel_provider)
+ bbconfig = os.path.join(get_bb_var('B', kernel_provider),'.config')
+ #Step 2
+ runCmd('cp %s %s' % (bbconfig, tempdir_cfg))
+ self.assertExists(os.path.join(tempdir_cfg, '.config'), 'Could not copy .config file from kernel')
+
+ tmpconfig = os.path.join(tempdir_cfg, '.config')
+ #Step 3
+ bitbake('%s -c clean' % kernel_provider)
+ #Step 4.1
+ runCmd('devtool modify virtual/kernel -x %s' % tempdir)
+ self.assertExists(os.path.join(tempdir, 'Makefile'), 'Extracted source could not be found')
+ #Step 4.2
+ configfile = os.path.join(tempdir,'.config')
+ runCmd('diff %s %s' % (tmpconfig, configfile))
+
+ #Step 4.3
+ #NOTE: virtual/kernel is mapped to kernel_provider
+ runCmd('devtool build %s' % kernel_provider)
+ kernelfile = os.path.join(get_bb_var('KBUILD_OUTPUT', kernel_provider), 'vmlinux')
+ self.assertExists(kernelfile, 'Kernel was not build correctly')
+
+ #Modify the kernel source
+ modfile = os.path.join(tempdir, 'init/version.c')
+ # Moved to uts.h in 6.1 onwards
+ modfile2 = os.path.join(tempdir, 'include/linux/uts.h')
+ runCmd("sed -i 's/Linux/LiNuX/g' %s %s" % (modfile, modfile2))
+
+ #Modify the configuration
+ codeconfigfile = os.path.join(tempdir, '.config.new')
+ modconfopt = "CONFIG_SG_POOL=n"
+ runCmd("sed -i 's/CONFIG_SG_POOL=y/%s/' %s" % (modconfopt, codeconfigfile))
+
+ #Build again kernel with devtool
+ runCmd('devtool build %s' % kernel_provider)
+
+ #Step 4.4
+ runCmd("grep '%s' %s" % ('LiNuX', kernelfile))
+
+ #Step 4.5
+ runCmd("grep %s %s" % (modconfopt, codeconfigfile))
diff --git a/meta/lib/oeqa/selftest/cases/diffoscope/A/file.txt b/meta/lib/oeqa/selftest/cases/diffoscope/A/file.txt
new file mode 100644
index 0000000000..f70f10e4db
--- /dev/null
+++ b/meta/lib/oeqa/selftest/cases/diffoscope/A/file.txt
@@ -0,0 +1 @@
+A
diff --git a/meta/lib/oeqa/selftest/cases/diffoscope/B/file.txt b/meta/lib/oeqa/selftest/cases/diffoscope/B/file.txt
new file mode 100644
index 0000000000..223b7836fb
--- /dev/null
+++ b/meta/lib/oeqa/selftest/cases/diffoscope/B/file.txt
@@ -0,0 +1 @@
+B
diff --git a/meta/lib/oeqa/selftest/cases/distrodata.py b/meta/lib/oeqa/selftest/cases/distrodata.py
new file mode 100644
index 0000000000..b5554a6c3c
--- /dev/null
+++ b/meta/lib/oeqa/selftest/cases/distrodata.py
@@ -0,0 +1,153 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
+from oeqa.selftest.case import OESelftestTestCase
+
+import oe.recipeutils
+
+class Distrodata(OESelftestTestCase):
+
+ def test_checkpkg(self):
+ """
+ Summary: Test that upstream version checks do not regress
+ Expected: Upstream version checks should succeed except for the recipes listed in the exception list.
+ Product: oe-core
+ Author: Alexander Kanavin <alex.kanavin@gmail.com>
+ """
+ feature = 'LICENSE_FLAGS_ACCEPTED += " commercial"\n'
+ self.write_config(feature)
+
+ pkgs = oe.recipeutils.get_recipe_upgrade_status()
+
+ regressed_failures = [pkg[0] for pkg in pkgs if pkg[1] == 'UNKNOWN_BROKEN']
+ regressed_successes = [pkg[0] for pkg in pkgs if pkg[1] == 'KNOWN_BROKEN']
+ msg = ""
+ if len(regressed_failures) > 0:
+ msg = msg + """
+The following packages failed upstream version checks. Please fix them using UPSTREAM_CHECK_URI/UPSTREAM_CHECK_REGEX
+(when using tarballs) or UPSTREAM_CHECK_GITTAGREGEX (when using git). If an upstream version check cannot be performed
+(for example, if upstream does not use git tags), you can set UPSTREAM_VERSION_UNKNOWN to '1' in the recipe to acknowledge
+that the check cannot be performed.
+""" + "\n".join(regressed_failures)
+ if len(regressed_successes) > 0:
+ msg = msg + """
+The following packages have been checked successfully for upstream versions,
+but their recipes claim otherwise by setting UPSTREAM_VERSION_UNKNOWN. Please remove that line from the recipes.
+""" + "\n".join(regressed_successes)
+ self.assertTrue(len(regressed_failures) == 0 and len(regressed_successes) == 0, msg)
+
+ def test_missing_homepg(self):
+ """
+ Summary: Test for oe-core recipes that don't have a HOMEPAGE or DESCRIPTION
+ Expected: All oe-core recipes should have a DESCRIPTION entry
+ Expected: All oe-core recipes should have a HOMEPAGE entry except for recipes that are not fetched from external sources.
+ Product: oe-core
+ """
+ with bb.tinfoil.Tinfoil() as tinfoil:
+ tinfoil.prepare(config_only=False)
+ no_description = []
+ no_homepage = []
+ for fn in tinfoil.all_recipe_files(variants=False):
+ if not '/meta/recipes-' in fn:
+ # We are only interested in OE-Core
+ continue
+ rd = tinfoil.parse_recipe_file(fn, appends=False)
+ pn = rd.getVar('BPN')
+ srcfile = rd.getVar('SRC_URI').split()
+ #Since DESCRIPTION defaults to SUMMARY if not set, we are only interested in recipes without DESCRIPTION or SUMMARY
+ if not (rd.getVar('SUMMARY') or rd.getVar('DESCRIPTION')):
+ no_description.append((pn, fn))
+ if not rd.getVar('HOMEPAGE'):
+ if srcfile and srcfile[0].startswith('file') or not rd.getVar('SRC_URI'):
+ # We are only interested in recipes SRC_URI fetched from external sources
+ continue
+ no_homepage.append((pn, fn))
+ if no_homepage:
+ self.fail("""
+The following recipes do not have a HOMEPAGE. Please add an entry for HOMEPAGE in the recipe.
+""" + "\n".join(['%s (%s)' % i for i in no_homepage]))
+
+ if no_description:
+ self.fail("""
+The following recipes do not have a DESCRIPTION. Please add an entry for DESCRIPTION in the recipe.
+""" + "\n".join(['%s (%s)' % i for i in no_description]))
+
+ def test_maintainers(self):
+ """
+ Summary: Test that oe-core recipes have a maintainer and entries in maintainers list have a recipe
+ Expected: All oe-core recipes (except a few special static/testing ones) should have a maintainer listed in maintainers.inc file.
+ Expected: All entries in maintainers list should have a recipe file that matches them
+ Product: oe-core
+ Author: Alexander Kanavin <alex.kanavin@gmail.com>
+ """
+ def is_exception(pkg):
+ exceptions = ["packagegroup-", "initramfs-", "systemd-machine-units", "target-sdk-provides-dummy"]
+ for i in exceptions:
+ if i in pkg:
+ return True
+ return False
+
+ def is_maintainer_exception(entry):
+ exceptions = ["musl", "newlib", "linux-yocto", "linux-dummy", "mesa-gl", "libgfortran",
+ "cve-update-db-native", "rust"]
+ for i in exceptions:
+ if i in entry:
+ return True
+ return False
+
+ feature = 'require conf/distro/include/maintainers.inc\nLICENSE_FLAGS_ACCEPTED += " commercial"\nPARSE_ALL_RECIPES = "1"\nPACKAGE_CLASSES = "package_ipk package_deb package_rpm"\n'
+ self.write_config(feature)
+
+ with bb.tinfoil.Tinfoil() as tinfoil:
+ tinfoil.prepare(config_only=False)
+
+ with_maintainer_list = []
+ no_maintainer_list = []
+
+ missing_recipes = []
+ recipes = []
+ prefix = "RECIPE_MAINTAINER:pn-"
+
+ # We could have used all_recipes() here, but this method will find
+ # every recipe if we ever move to setting RECIPE_MAINTAINER in recipe files
+ # instead of maintainers.inc
+ for fn in tinfoil.all_recipe_files(variants=False):
+ if not '/meta/recipes-' in fn:
+ # We are only interested in OE-Core
+ continue
+ rd = tinfoil.parse_recipe_file(fn, appends=False)
+ pn = rd.getVar('PN')
+ recipes.append(pn)
+ if is_exception(pn):
+ continue
+ if rd.getVar('RECIPE_MAINTAINER'):
+ with_maintainer_list.append((pn, fn))
+ else:
+ no_maintainer_list.append((pn, fn))
+
+ maintainers = tinfoil.config_data.keys()
+ for key in maintainers:
+ if key.startswith(prefix):
+ recipe = tinfoil.config_data.expand(key[len(prefix):])
+ if is_maintainer_exception(recipe):
+ continue
+ if recipe not in recipes:
+ missing_recipes.append(recipe)
+
+ if no_maintainer_list:
+ self.fail("""
+The following recipes do not have a maintainer assigned to them. Please add an entry to meta/conf/distro/include/maintainers.inc file.
+""" + "\n".join(['%s (%s)' % i for i in no_maintainer_list]))
+
+ if not with_maintainer_list:
+ self.fail("""
+The list of oe-core recipes with maintainers is empty. This may indicate that the test has regressed and needs fixing.
+""")
+
+ if missing_recipes:
+ self.fail("""
+Unable to find recipes for the following entries in maintainers.inc:
+""" + "\n".join(['%s' % i for i in missing_recipes]))
diff --git a/meta/lib/oeqa/selftest/cases/eSDK.py b/meta/lib/oeqa/selftest/cases/eSDK.py
new file mode 100644
index 0000000000..9f5de2cde7
--- /dev/null
+++ b/meta/lib/oeqa/selftest/cases/eSDK.py
@@ -0,0 +1,122 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
+import tempfile
+import shutil
+import os
+import glob
+import time
+from oeqa.selftest.case import OESelftestTestCase
+from oeqa.utils.commands import runCmd, bitbake, get_bb_vars
+
+class oeSDKExtSelfTest(OESelftestTestCase):
+ """
+ # Bugzilla Test Plan: 6033
+ # This code is planned to be part of the automation for eSDK containig
+ # Install libraries and headers, image generation binary feeds, sdk-update.
+ """
+
+ @staticmethod
+ def get_esdk_environment(env_eSDK, tmpdir_eSDKQA):
+ # XXX: at this time use the first env need to investigate
+ # what environment load oe-selftest, i586, x86_64
+ pattern = os.path.join(tmpdir_eSDKQA, 'environment-setup-*')
+ return glob.glob(pattern)[0]
+
+ @staticmethod
+ def run_esdk_cmd(env_eSDK, tmpdir_eSDKQA, cmd, postconfig=None, **options):
+ if postconfig:
+ esdk_conf_file = os.path.join(tmpdir_eSDKQA, 'conf', 'local.conf')
+ with open(esdk_conf_file, 'a+') as f:
+ f.write(postconfig)
+ if not options:
+ options = {}
+ if not 'shell' in options:
+ options['shell'] = True
+
+ runCmd("cd %s; unset BBPATH; unset BUILDDIR; . %s; %s" % (tmpdir_eSDKQA, env_eSDK, cmd), **options)
+
+ @staticmethod
+ def generate_eSDK(image):
+ pn_task = '%s -c populate_sdk_ext' % image
+ bitbake(pn_task)
+
+ @staticmethod
+ def get_eSDK_toolchain(image):
+ pn_task = '%s -c populate_sdk_ext' % image
+
+ bb_vars = get_bb_vars(['SDK_DEPLOY', 'TOOLCHAINEXT_OUTPUTNAME'], pn_task)
+ sdk_deploy = bb_vars['SDK_DEPLOY']
+ toolchain_name = bb_vars['TOOLCHAINEXT_OUTPUTNAME']
+ return os.path.join(sdk_deploy, toolchain_name + '.sh')
+
+ @staticmethod
+ def update_configuration(cls, image, tmpdir_eSDKQA, env_eSDK, ext_sdk_path):
+ sstate_dir = os.path.join(os.environ['BUILDDIR'], 'sstate-cache')
+
+ oeSDKExtSelfTest.generate_eSDK(cls.image)
+
+ cls.ext_sdk_path = oeSDKExtSelfTest.get_eSDK_toolchain(cls.image)
+ runCmd("%s -y -d \"%s\"" % (cls.ext_sdk_path, cls.tmpdir_eSDKQA))
+
+ cls.env_eSDK = oeSDKExtSelfTest.get_esdk_environment('', cls.tmpdir_eSDKQA)
+
+ sstate_config="""
+ESDK_LOCALCONF_ALLOW = "SSTATE_MIRRORS"
+SSTATE_MIRRORS = "file://.* file://%s/PATH"
+CORE_IMAGE_EXTRA_INSTALL = "perl"
+ """ % sstate_dir
+
+ with open(os.path.join(cls.tmpdir_eSDKQA, 'conf', 'local.conf'), 'a+') as f:
+ f.write(sstate_config)
+
+ @classmethod
+ def setUpClass(cls):
+ super(oeSDKExtSelfTest, cls).setUpClass()
+ cls.image = 'core-image-minimal'
+
+ bb_vars = get_bb_vars(['SSTATE_DIR', 'WORKDIR'], cls.image)
+ bb.utils.mkdirhier(bb_vars["WORKDIR"])
+ cls.tmpdirobj = tempfile.TemporaryDirectory(prefix="selftest-esdk-", dir=bb_vars["WORKDIR"])
+ cls.tmpdir_eSDKQA = cls.tmpdirobj.name
+
+ oeSDKExtSelfTest.generate_eSDK(cls.image)
+
+ # Install eSDK
+ cls.ext_sdk_path = oeSDKExtSelfTest.get_eSDK_toolchain(cls.image)
+ runCmd("%s -y -d \"%s\"" % (cls.ext_sdk_path, cls.tmpdir_eSDKQA))
+
+ cls.env_eSDK = oeSDKExtSelfTest.get_esdk_environment('', cls.tmpdir_eSDKQA)
+
+ # Configure eSDK to use sstate mirror from poky
+ sstate_config="""
+ESDK_LOCALCONF_ALLOW = "SSTATE_MIRRORS"
+SSTATE_MIRRORS = "file://.* file://%s/PATH"
+ """ % bb_vars["SSTATE_DIR"]
+ with open(os.path.join(cls.tmpdir_eSDKQA, 'conf', 'local.conf'), 'a+') as f:
+ f.write(sstate_config)
+
+ @classmethod
+ def tearDownClass(cls):
+ for i in range(0, 10):
+ if os.path.exists(os.path.join(cls.tmpdir_eSDKQA, 'bitbake.lock')) or os.path.exists(os.path.join(cls.tmpdir_eSDKQA, 'cache/hashserv.db-wal')):
+ time.sleep(1)
+ else:
+ break
+ cls.tmpdirobj.cleanup()
+ super().tearDownClass()
+
+ def test_install_libraries_headers(self):
+ pn_sstate = 'bc'
+ bitbake(pn_sstate)
+ cmd = "devtool sdk-install %s " % pn_sstate
+ oeSDKExtSelfTest.run_esdk_cmd(self.env_eSDK, self.tmpdir_eSDKQA, cmd)
+
+ def test_image_generation_binary_feeds(self):
+ image = 'core-image-minimal'
+ cmd = "devtool build-image %s" % image
+ oeSDKExtSelfTest.run_esdk_cmd(self.env_eSDK, self.tmpdir_eSDKQA, cmd)
+
diff --git a/meta/lib/oeqa/selftest/cases/efibootpartition.py b/meta/lib/oeqa/selftest/cases/efibootpartition.py
new file mode 100644
index 0000000000..e17da9f9a0
--- /dev/null
+++ b/meta/lib/oeqa/selftest/cases/efibootpartition.py
@@ -0,0 +1,33 @@
+# Based on runqemu.py test file
+#
+# Copyright (c) 2017 Wind River Systems, Inc.
+#
+# SPDX-License-Identifier: MIT
+#
+
+from oeqa.selftest.case import OESelftestTestCase
+from oeqa.utils.commands import bitbake, runqemu
+from oeqa.core.decorator.data import skipIfNotMachine
+import oe.types
+
+class GenericEFITest(OESelftestTestCase):
+ """EFI booting test class"""
+ @skipIfNotMachine("qemux86-64", "test is qemux86-64 specific currently")
+ def test_boot_efi(self):
+ cmd = "runqemu nographic serial wic ovmf"
+ if oe.types.qemu_use_kvm(self.td['QEMU_USE_KVM'], self.td["TARGET_ARCH"]):
+ cmd += " kvm"
+ image = "core-image-minimal"
+
+ self.write_config("""
+EFI_PROVIDER = "systemd-boot"
+IMAGE_FSTYPES:pn-%s:append = " wic"
+MACHINE_FEATURES:append = " efi"
+WKS_FILE = "efi-bootdisk.wks.in"
+IMAGE_INSTALL:append = " grub-efi systemd-boot kernel-image-bzimage"
+"""
+% (image))
+
+ bitbake(image + " ovmf")
+ with runqemu(image, ssh=False, launch_cmd=cmd) as qemu:
+ self.assertTrue(qemu.runner.logged, "Failed: %s" % cmd)
diff --git a/meta/lib/oeqa/selftest/cases/externalsrc.py b/meta/lib/oeqa/selftest/cases/externalsrc.py
new file mode 100644
index 0000000000..1d800dc82c
--- /dev/null
+++ b/meta/lib/oeqa/selftest/cases/externalsrc.py
@@ -0,0 +1,44 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
+import os
+import shutil
+import tempfile
+
+from oeqa.selftest.case import OESelftestTestCase
+from oeqa.utils.commands import get_bb_var, runCmd
+
+class ExternalSrc(OESelftestTestCase):
+ # test that srctree_hash_files does not crash
+ # we should be actually checking do_compile[file-checksums] but oeqa currently does not support it
+ # so we check only that a recipe with externalsrc can be parsed
+ def test_externalsrc_srctree_hash_files(self):
+ test_recipe = "git-submodule-test"
+ git_url = "git://git.yoctoproject.org/git-submodule-test"
+ externalsrc_dir = tempfile.TemporaryDirectory(prefix="externalsrc").name
+
+ self.write_config(
+ """
+INHERIT += "externalsrc"
+EXTERNALSRC:pn-%s = "%s"
+""" % (test_recipe, externalsrc_dir)
+ )
+
+ # test with git without submodules
+ runCmd('git clone %s %s' % (git_url, externalsrc_dir))
+ os.unlink(externalsrc_dir + "/.gitmodules")
+ open(".gitmodules", 'w').close() # local file .gitmodules in cwd should not affect externalsrc parsing
+ self.assertEqual(get_bb_var("S", test_recipe), externalsrc_dir, msg = "S does not equal to EXTERNALSRC")
+ os.unlink(".gitmodules")
+
+ # test with git with submodules
+ runCmd('git checkout .gitmodules', cwd=externalsrc_dir)
+ runCmd('git submodule update --init --recursive', cwd=externalsrc_dir)
+ self.assertEqual(get_bb_var("S", test_recipe), externalsrc_dir, msg = "S does not equal to EXTERNALSRC")
+
+ # test without git
+ shutil.rmtree(os.path.join(externalsrc_dir, ".git"))
+ self.assertEqual(get_bb_var("S", test_recipe), externalsrc_dir, msg = "S does not equal to EXTERNALSRC")
diff --git a/meta/lib/oeqa/selftest/cases/fetch.py b/meta/lib/oeqa/selftest/cases/fetch.py
new file mode 100644
index 0000000000..3d01cf69f2
--- /dev/null
+++ b/meta/lib/oeqa/selftest/cases/fetch.py
@@ -0,0 +1,108 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
+import tempfile
+import textwrap
+import bb.tinfoil
+import oe.path
+from oeqa.selftest.case import OESelftestTestCase
+from oeqa.utils.commands import bitbake
+
+class Fetch(OESelftestTestCase):
+ def test_git_mirrors(self):
+ """
+ Verify that the git fetcher will fall back to the HTTP mirrors. The
+ recipe needs to be one that we have on the Yocto Project source mirror
+ and is hosted in git.
+ """
+
+ # TODO: mktempd instead of hardcoding
+ dldir = os.path.join(self.builddir, "download-git-mirrors")
+ self.track_for_cleanup(dldir)
+
+ # No mirrors, should use git to fetch successfully
+ features = """
+DL_DIR = "%s"
+MIRRORS:forcevariable = ""
+PREMIRRORS:forcevariable = ""
+""" % dldir
+ self.write_config(features)
+ oe.path.remove(dldir, recurse=True)
+ bitbake("dbus-wait -c fetch -f")
+
+ # No mirrors and broken git, should fail
+ features = """
+DL_DIR = "%s"
+GIT_PROXY_COMMAND = "false"
+MIRRORS:forcevariable = ""
+PREMIRRORS:forcevariable = ""
+""" % dldir
+ self.write_config(features)
+ oe.path.remove(dldir, recurse=True)
+ with self.assertRaises(AssertionError):
+ bitbake("dbus-wait -c fetch -f")
+
+ # Broken git but a specific mirror
+ features = """
+DL_DIR = "%s"
+GIT_PROXY_COMMAND = "false"
+MIRRORS:forcevariable = "git://.*/.* http://downloads.yoctoproject.org/mirror/sources/"
+""" % dldir
+ self.write_config(features)
+ oe.path.remove(dldir, recurse=True)
+ bitbake("dbus-wait -c fetch -f")
+
+
+class Dependencies(OESelftestTestCase):
+ def write_recipe(self, content, tempdir):
+ f = os.path.join(tempdir, "test.bb")
+ with open(f, "w") as fd:
+ fd.write(content)
+ return f
+
+ def test_dependencies(self):
+ """
+ Verify that the correct dependencies are generated for specific SRC_URI entries.
+ """
+
+ with bb.tinfoil.Tinfoil() as tinfoil, tempfile.TemporaryDirectory(prefix="selftest-fetch") as tempdir:
+ tinfoil.prepare(config_only=False, quiet=2)
+
+ r = """
+ LICENSE="CLOSED"
+ SRC_URI="http://example.com/tarball.zip"
+ """
+ f = self.write_recipe(textwrap.dedent(r), tempdir)
+ d = tinfoil.parse_recipe_file(f)
+ self.assertIn("wget-native", d.getVarFlag("do_fetch", "depends"))
+ self.assertIn("unzip-native", d.getVarFlag("do_unpack", "depends"))
+
+ # Verify that the downloadfilename overrides the URI
+ r = """
+ LICENSE="CLOSED"
+ SRC_URI="https://example.com/tarball;downloadfilename=something.zip"
+ """
+ f = self.write_recipe(textwrap.dedent(r), tempdir)
+ d = tinfoil.parse_recipe_file(f)
+ self.assertIn("wget-native", d.getVarFlag("do_fetch", "depends"))
+ self.assertIn("unzip-native", d.getVarFlag("do_unpack", "depends") or "")
+
+ r = """
+ LICENSE="CLOSED"
+ SRC_URI="ftp://example.com/tarball.lz"
+ """
+ f = self.write_recipe(textwrap.dedent(r), tempdir)
+ d = tinfoil.parse_recipe_file(f)
+ self.assertIn("wget-native", d.getVarFlag("do_fetch", "depends"))
+ self.assertIn("lzip-native", d.getVarFlag("do_unpack", "depends"))
+
+ r = """
+ LICENSE="CLOSED"
+ SRC_URI="git://example.com/repo;branch=master"
+ """
+ f = self.write_recipe(textwrap.dedent(r), tempdir)
+ d = tinfoil.parse_recipe_file(f)
+ self.assertIn("git-native", d.getVarFlag("do_fetch", "depends"))
diff --git a/meta/lib/oeqa/selftest/cases/fitimage.py b/meta/lib/oeqa/selftest/cases/fitimage.py
new file mode 100644
index 0000000000..1570d54dfb
--- /dev/null
+++ b/meta/lib/oeqa/selftest/cases/fitimage.py
@@ -0,0 +1,846 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
+from oeqa.selftest.case import OESelftestTestCase
+from oeqa.utils.commands import runCmd, bitbake, get_bb_var
+import os
+import re
+
+class FitImageTests(OESelftestTestCase):
+
+ def test_fit_image(self):
+ """
+ Summary: Check if FIT image and Image Tree Source (its) are built
+ and the Image Tree Source has the correct fields.
+ Expected: 1. fitImage and fitImage-its can be built
+ 2. The type, load address, entrypoint address and
+ default values of kernel and ramdisk are as expected
+ in the Image Tree Source. Not all the fields are tested,
+ only the key fields that wont vary between different
+ architectures.
+ Product: oe-core
+ Author: Usama Arif <usama.arif@arm.com>
+ """
+ config = """
+# Enable creation of fitImage
+KERNEL_IMAGETYPE = "Image"
+KERNEL_IMAGETYPES += " fitImage "
+KERNEL_CLASSES = " kernel-fitimage "
+
+# RAM disk variables including load address and entrypoint for kernel and RAM disk
+IMAGE_FSTYPES += "cpio.gz"
+INITRAMFS_IMAGE = "core-image-minimal"
+UBOOT_RD_LOADADDRESS = "0x88000000"
+UBOOT_RD_ENTRYPOINT = "0x88000000"
+UBOOT_LOADADDRESS = "0x80080000"
+UBOOT_ENTRYPOINT = "0x80080000"
+FIT_DESC = "A model description"
+"""
+ self.write_config(config)
+
+ # fitImage is created as part of linux recipe
+ bitbake("virtual/kernel")
+
+ image_type = "core-image-minimal"
+ deploy_dir_image = get_bb_var('DEPLOY_DIR_IMAGE')
+ machine = get_bb_var('MACHINE')
+ fitimage_its_path = os.path.join(deploy_dir_image,
+ "fitImage-its-%s-%s-%s" % (image_type, machine, machine))
+ fitimage_path = os.path.join(deploy_dir_image,
+ "fitImage-%s-%s-%s" % (image_type, machine, machine))
+
+ self.assertTrue(os.path.exists(fitimage_its_path),
+ "%s image tree source doesn't exist" % (fitimage_its_path))
+ self.assertTrue(os.path.exists(fitimage_path),
+ "%s FIT image doesn't exist" % (fitimage_path))
+
+ # Check that the type, load address, entrypoint address and default
+ # values for kernel and ramdisk in Image Tree Source are as expected.
+ # The order of fields in the below array is important. Not all the
+ # fields are tested, only the key fields that wont vary between
+ # different architectures.
+ its_field_check = [
+ 'description = "A model description";',
+ 'type = "kernel";',
+ 'load = <0x80080000>;',
+ 'entry = <0x80080000>;',
+ 'type = "ramdisk";',
+ 'load = <0x88000000>;',
+ 'entry = <0x88000000>;',
+ 'default = "conf-1";',
+ 'kernel = "kernel-1";',
+ 'ramdisk = "ramdisk-1";'
+ ]
+
+ with open(fitimage_its_path) as its_file:
+ field_index = 0
+ for line in its_file:
+ if field_index == len(its_field_check):
+ break
+ if its_field_check[field_index] in line:
+ field_index +=1
+
+ if field_index != len(its_field_check): # if its equal, the test passed
+ self.assertTrue(field_index == len(its_field_check),
+ "Fields in Image Tree Source File %s did not match, error in finding %s"
+ % (fitimage_its_path, its_field_check[field_index]))
+
+
+ def test_sign_fit_image(self):
+ """
+ Summary: Check if FIT image and Image Tree Source (its) are created
+ and signed correctly.
+ Expected: 1) its and FIT image are built successfully
+ 2) Scanning the its file indicates signing is enabled
+ as requested by UBOOT_SIGN_ENABLE (using keys generated
+ via FIT_GENERATE_KEYS)
+ 3) Dumping the FIT image indicates signature values
+ are present (including for images as enabled via
+ FIT_SIGN_INDIVIDUAL)
+ 4) Examination of the do_assemble_fitimage runfile/logfile
+ indicate that UBOOT_MKIMAGE, UBOOT_MKIMAGE_SIGN and
+ UBOOT_MKIMAGE_SIGN_ARGS are working as expected.
+ Product: oe-core
+ Author: Paul Eggleton <paul.eggleton@microsoft.com> based upon
+ work by Usama Arif <usama.arif@arm.com>
+ """
+ config = """
+# Enable creation of fitImage
+MACHINE = "beaglebone-yocto"
+KERNEL_IMAGETYPES += " fitImage "
+KERNEL_CLASSES = " kernel-fitimage test-mkimage-wrapper "
+UBOOT_SIGN_ENABLE = "1"
+FIT_GENERATE_KEYS = "1"
+UBOOT_SIGN_KEYDIR = "${TOPDIR}/signing-keys"
+UBOOT_SIGN_IMG_KEYNAME = "img-oe-selftest"
+UBOOT_SIGN_KEYNAME = "cfg-oe-selftest"
+FIT_SIGN_INDIVIDUAL = "1"
+UBOOT_MKIMAGE_SIGN_ARGS = "-c 'a smart comment'"
+"""
+ self.write_config(config)
+
+ # fitImage is created as part of linux recipe
+ bitbake("virtual/kernel")
+
+ image_type = "core-image-minimal"
+ deploy_dir_image = get_bb_var('DEPLOY_DIR_IMAGE')
+ machine = get_bb_var('MACHINE')
+ fitimage_its_path = os.path.join(deploy_dir_image,
+ "fitImage-its-%s" % (machine,))
+ fitimage_path = os.path.join(deploy_dir_image,
+ "fitImage-%s.bin" % (machine,))
+
+ self.assertTrue(os.path.exists(fitimage_its_path),
+ "%s image tree source doesn't exist" % (fitimage_its_path))
+ self.assertTrue(os.path.exists(fitimage_path),
+ "%s FIT image doesn't exist" % (fitimage_path))
+
+ req_itspaths = [
+ ['/', 'images', 'kernel-1'],
+ ['/', 'images', 'kernel-1', 'signature-1'],
+ ['/', 'images', 'fdt-am335x-boneblack.dtb'],
+ ['/', 'images', 'fdt-am335x-boneblack.dtb', 'signature-1'],
+ ['/', 'configurations', 'conf-am335x-boneblack.dtb'],
+ ['/', 'configurations', 'conf-am335x-boneblack.dtb', 'signature-1'],
+ ]
+
+ itspath = []
+ itspaths = []
+ linect = 0
+ sigs = {}
+ with open(fitimage_its_path) as its_file:
+ linect += 1
+ for line in its_file:
+ line = line.strip()
+ if line.endswith('};'):
+ itspath.pop()
+ elif line.endswith('{'):
+ itspath.append(line[:-1].strip())
+ itspaths.append(itspath[:])
+ elif itspath and itspath[-1] == 'signature-1':
+ itsdotpath = '.'.join(itspath)
+ if not itsdotpath in sigs:
+ sigs[itsdotpath] = {}
+ if not '=' in line or not line.endswith(';'):
+ self.fail('Unexpected formatting in %s sigs section line %d:%s' % (fitimage_its_path, linect, line))
+ key, value = line.split('=', 1)
+ sigs[itsdotpath][key.rstrip()] = value.lstrip().rstrip(';')
+
+ for reqpath in req_itspaths:
+ if not reqpath in itspaths:
+ self.fail('Missing section in its file: %s' % reqpath)
+
+ reqsigvalues_image = {
+ 'algo': '"sha256,rsa2048"',
+ 'key-name-hint': '"img-oe-selftest"',
+ }
+ reqsigvalues_config = {
+ 'algo': '"sha256,rsa2048"',
+ 'key-name-hint': '"cfg-oe-selftest"',
+ 'sign-images': '"kernel", "fdt"',
+ }
+
+ for itspath, values in sigs.items():
+ if 'conf-' in itspath:
+ reqsigvalues = reqsigvalues_config
+ else:
+ reqsigvalues = reqsigvalues_image
+ for reqkey, reqvalue in reqsigvalues.items():
+ value = values.get(reqkey, None)
+ if value is None:
+ self.fail('Missing key "%s" in its file signature section %s' % (reqkey, itspath))
+ self.assertEqual(value, reqvalue)
+
+ # Dump the image to see if it really got signed
+ bitbake("u-boot-tools-native -c addto_recipe_sysroot")
+ result = runCmd('bitbake -e u-boot-tools-native | grep ^RECIPE_SYSROOT_NATIVE=')
+ recipe_sysroot_native = result.output.split('=')[1].strip('"')
+ dumpimage_path = os.path.join(recipe_sysroot_native, 'usr', 'bin', 'dumpimage')
+ result = runCmd('%s -l %s' % (dumpimage_path, fitimage_path))
+ in_signed = None
+ signed_sections = {}
+ for line in result.output.splitlines():
+ if line.startswith((' Configuration', ' Image')):
+ in_signed = re.search('\((.*)\)', line).groups()[0]
+ elif re.match('^ *', line) in (' ', ''):
+ in_signed = None
+ elif in_signed:
+ if not in_signed in signed_sections:
+ signed_sections[in_signed] = {}
+ key, value = line.split(':', 1)
+ signed_sections[in_signed][key.strip()] = value.strip()
+ self.assertIn('kernel-1', signed_sections)
+ self.assertIn('fdt-am335x-boneblack.dtb', signed_sections)
+ self.assertIn('conf-am335x-boneblack.dtb', signed_sections)
+ for signed_section, values in signed_sections.items():
+ value = values.get('Sign algo', None)
+ if signed_section.startswith("conf"):
+ self.assertEqual(value, 'sha256,rsa2048:cfg-oe-selftest', 'Signature algorithm for %s not expected value' % signed_section)
+ else:
+ self.assertEqual(value, 'sha256,rsa2048:img-oe-selftest', 'Signature algorithm for %s not expected value' % signed_section)
+ value = values.get('Sign value', None)
+ self.assertEqual(len(value), 512, 'Signature value for section %s not expected length' % signed_section)
+
+ # Check for UBOOT_MKIMAGE_SIGN_ARGS
+ result = runCmd('bitbake -e virtual/kernel | grep ^T=')
+ tempdir = result.output.split('=', 1)[1].strip().strip('')
+ result = runCmd('grep "a smart comment" %s/run.do_assemble_fitimage' % tempdir, ignore_status=True)
+ self.assertEqual(result.status, 0, 'UBOOT_MKIMAGE_SIGN_ARGS value did not get used')
+
+ # Check for evidence of test-mkimage-wrapper class
+ result = runCmd('grep "### uboot-mkimage wrapper message" %s/log.do_assemble_fitimage' % tempdir, ignore_status=True)
+ self.assertEqual(result.status, 0, 'UBOOT_MKIMAGE did not work')
+ result = runCmd('grep "### uboot-mkimage signing wrapper message" %s/log.do_assemble_fitimage' % tempdir, ignore_status=True)
+ self.assertEqual(result.status, 0, 'UBOOT_MKIMAGE_SIGN did not work')
+
+ def test_uboot_fit_image(self):
+ """
+ Summary: Check if Uboot FIT image and Image Tree Source
+ (its) are built and the Image Tree Source has the
+ correct fields.
+ Expected: 1. u-boot-fitImage and u-boot-its can be built
+ 2. The type, load address, entrypoint address and
+ default values of U-boot image are correct in the
+ Image Tree Source. Not all the fields are tested,
+ only the key fields that wont vary between
+ different architectures.
+ Product: oe-core
+ Author: Klaus Heinrich Kiwi <klaus@linux.vnet.ibm.com>
+ based on work by Usama Arif <usama.arif@arm.com>
+ """
+ config = """
+# We need at least CONFIG_SPL_LOAD_FIT and CONFIG_SPL_OF_CONTROL set
+MACHINE = "qemuarm"
+UBOOT_MACHINE = "am57xx_evm_defconfig"
+SPL_BINARY = "MLO"
+
+# Enable creation of the U-Boot fitImage
+UBOOT_FITIMAGE_ENABLE = "1"
+
+# (U-boot) fitImage properties
+UBOOT_LOADADDRESS = "0x80080000"
+UBOOT_ENTRYPOINT = "0x80080000"
+UBOOT_FIT_DESC = "A model description"
+
+# Enable creation of Kernel fitImage
+KERNEL_IMAGETYPES += " fitImage "
+KERNEL_CLASSES = " kernel-fitimage"
+UBOOT_SIGN_ENABLE = "1"
+FIT_GENERATE_KEYS = "1"
+UBOOT_SIGN_KEYDIR = "${TOPDIR}/signing-keys"
+UBOOT_SIGN_IMG_KEYNAME = "img-oe-selftest"
+UBOOT_SIGN_KEYNAME = "cfg-oe-selftest"
+FIT_SIGN_INDIVIDUAL = "1"
+"""
+ self.write_config(config)
+
+ # The U-Boot fitImage is created as part of the U-Boot recipe
+ bitbake("virtual/bootloader")
+
+ deploy_dir_image = get_bb_var('DEPLOY_DIR_IMAGE')
+ machine = get_bb_var('MACHINE')
+ fitimage_its_path = os.path.join(deploy_dir_image,
+ "u-boot-its-%s" % (machine,))
+ fitimage_path = os.path.join(deploy_dir_image,
+ "u-boot-fitImage-%s" % (machine,))
+
+ self.assertTrue(os.path.exists(fitimage_its_path),
+ "%s image tree source doesn't exist" % (fitimage_its_path))
+ self.assertTrue(os.path.exists(fitimage_path),
+ "%s FIT image doesn't exist" % (fitimage_path))
+
+ # Check that the type, load address, entrypoint address and default
+ # values for kernel and ramdisk in Image Tree Source are as expected.
+ # The order of fields in the below array is important. Not all the
+ # fields are tested, only the key fields that wont vary between
+ # different architectures.
+ its_field_check = [
+ 'description = "A model description";',
+ 'type = "standalone";',
+ 'load = <0x80080000>;',
+ 'entry = <0x80080000>;',
+ 'default = "conf";',
+ 'loadables = "uboot";',
+ 'fdt = "fdt";'
+ ]
+
+ with open(fitimage_its_path) as its_file:
+ field_index = 0
+ for line in its_file:
+ if field_index == len(its_field_check):
+ break
+ if its_field_check[field_index] in line:
+ field_index +=1
+
+ if field_index != len(its_field_check): # if its equal, the test passed
+ self.assertTrue(field_index == len(its_field_check),
+ "Fields in Image Tree Source File %s did not match, error in finding %s"
+ % (fitimage_its_path, its_field_check[field_index]))
+
+ def test_uboot_sign_fit_image(self):
+ """
+ Summary: Check if Uboot FIT image and Image Tree Source
+ (its) are built and the Image Tree Source has the
+ correct fields, in the scenario where the Kernel
+ is also creating/signing it's fitImage.
+ Expected: 1. u-boot-fitImage and u-boot-its can be built
+ 2. The type, load address, entrypoint address and
+ default values of U-boot image are correct in the
+ Image Tree Source. Not all the fields are tested,
+ only the key fields that wont vary between
+ different architectures.
+ Product: oe-core
+ Author: Klaus Heinrich Kiwi <klaus@linux.vnet.ibm.com>
+ based on work by Usama Arif <usama.arif@arm.com>
+ """
+ config = """
+# We need at least CONFIG_SPL_LOAD_FIT and CONFIG_SPL_OF_CONTROL set
+MACHINE = "qemuarm"
+UBOOT_MACHINE = "am57xx_evm_defconfig"
+SPL_BINARY = "MLO"
+
+# Enable creation of the U-Boot fitImage
+UBOOT_FITIMAGE_ENABLE = "1"
+
+# (U-boot) fitImage properties
+UBOOT_LOADADDRESS = "0x80080000"
+UBOOT_ENTRYPOINT = "0x80080000"
+UBOOT_FIT_DESC = "A model description"
+KERNEL_IMAGETYPES += " fitImage "
+KERNEL_CLASSES = " kernel-fitimage "
+INHERIT += "test-mkimage-wrapper"
+UBOOT_SIGN_ENABLE = "1"
+FIT_GENERATE_KEYS = "1"
+UBOOT_SIGN_KEYDIR = "${TOPDIR}/signing-keys"
+UBOOT_SIGN_IMG_KEYNAME = "img-oe-selftest"
+UBOOT_SIGN_KEYNAME = "cfg-oe-selftest"
+FIT_SIGN_INDIVIDUAL = "1"
+UBOOT_MKIMAGE_SIGN_ARGS = "-c 'a smart U-Boot comment'"
+"""
+ self.write_config(config)
+
+ # The U-Boot fitImage is created as part of the U-Boot recipe
+ bitbake("virtual/bootloader")
+
+ deploy_dir_image = get_bb_var('DEPLOY_DIR_IMAGE')
+ machine = get_bb_var('MACHINE')
+ fitimage_its_path = os.path.join(deploy_dir_image,
+ "u-boot-its-%s" % (machine,))
+ fitimage_path = os.path.join(deploy_dir_image,
+ "u-boot-fitImage-%s" % (machine,))
+
+ self.assertTrue(os.path.exists(fitimage_its_path),
+ "%s image tree source doesn't exist" % (fitimage_its_path))
+ self.assertTrue(os.path.exists(fitimage_path),
+ "%s FIT image doesn't exist" % (fitimage_path))
+
+ # Check that the type, load address, entrypoint address and default
+ # values for kernel and ramdisk in Image Tree Source are as expected.
+ # The order of fields in the below array is important. Not all the
+ # fields are tested, only the key fields that wont vary between
+ # different architectures.
+ its_field_check = [
+ 'description = "A model description";',
+ 'type = "standalone";',
+ 'load = <0x80080000>;',
+ 'entry = <0x80080000>;',
+ 'default = "conf";',
+ 'loadables = "uboot";',
+ 'fdt = "fdt";'
+ ]
+
+ with open(fitimage_its_path) as its_file:
+ field_index = 0
+ for line in its_file:
+ if field_index == len(its_field_check):
+ break
+ if its_field_check[field_index] in line:
+ field_index +=1
+
+ if field_index != len(its_field_check): # if its equal, the test passed
+ self.assertTrue(field_index == len(its_field_check),
+ "Fields in Image Tree Source File %s did not match, error in finding %s"
+ % (fitimage_its_path, its_field_check[field_index]))
+
+
+ def test_sign_standalone_uboot_fit_image(self):
+ """
+ Summary: Check if U-Boot FIT image and Image Tree Source (its) are
+ created and signed correctly for the scenario where only
+ the U-Boot proper fitImage is being created and signed.
+ Expected: 1) U-Boot its and FIT image are built successfully
+ 2) Scanning the its file indicates signing is enabled
+ as requested by SPL_SIGN_ENABLE (using keys generated
+ via UBOOT_FIT_GENERATE_KEYS)
+ 3) Dumping the FIT image indicates signature values
+ are present
+ 4) Examination of the do_uboot_assemble_fitimage
+ runfile/logfile indicate that UBOOT_MKIMAGE, UBOOT_MKIMAGE_SIGN
+ and SPL_MKIMAGE_SIGN_ARGS are working as expected.
+ Product: oe-core
+ Author: Klaus Heinrich Kiwi <klaus@linux.vnet.ibm.com> based upon
+ work by Paul Eggleton <paul.eggleton@microsoft.com> and
+ Usama Arif <usama.arif@arm.com>
+ """
+ config = """
+# There's no U-boot deconfig with CONFIG_FIT_SIGNATURE yet, so we need at
+# least CONFIG_SPL_LOAD_FIT and CONFIG_SPL_OF_CONTROL set
+MACHINE = "qemuarm"
+UBOOT_MACHINE = "am57xx_evm_defconfig"
+SPL_BINARY = "MLO"
+# The kernel-fitimage class is a dependency even if we're only
+# creating/signing the U-Boot fitImage
+KERNEL_CLASSES = " kernel-fitimage"
+INHERIT += "test-mkimage-wrapper"
+# Enable creation and signing of the U-Boot fitImage
+UBOOT_FITIMAGE_ENABLE = "1"
+SPL_SIGN_ENABLE = "1"
+SPL_SIGN_KEYNAME = "spl-oe-selftest"
+SPL_SIGN_KEYDIR = "${TOPDIR}/signing-keys"
+UBOOT_DTB_BINARY = "u-boot.dtb"
+UBOOT_ENTRYPOINT = "0x80000000"
+UBOOT_LOADADDRESS = "0x80000000"
+UBOOT_DTB_LOADADDRESS = "0x82000000"
+UBOOT_ARCH = "arm"
+SPL_MKIMAGE_DTCOPTS = "-I dts -O dtb -p 2000"
+SPL_MKIMAGE_SIGN_ARGS = "-c 'a smart U-Boot comment'"
+UBOOT_EXTLINUX = "0"
+UBOOT_FIT_GENERATE_KEYS = "1"
+UBOOT_FIT_HASH_ALG = "sha256"
+"""
+ self.write_config(config)
+
+ # The U-Boot fitImage is created as part of the U-Boot recipe
+ bitbake("virtual/bootloader")
+
+ image_type = "core-image-minimal"
+ deploy_dir_image = get_bb_var('DEPLOY_DIR_IMAGE')
+ machine = get_bb_var('MACHINE')
+ fitimage_its_path = os.path.join(deploy_dir_image,
+ "u-boot-its-%s" % (machine,))
+ fitimage_path = os.path.join(deploy_dir_image,
+ "u-boot-fitImage-%s" % (machine,))
+
+ self.assertTrue(os.path.exists(fitimage_its_path),
+ "%s image tree source doesn't exist" % (fitimage_its_path))
+ self.assertTrue(os.path.exists(fitimage_path),
+ "%s FIT image doesn't exist" % (fitimage_path))
+
+ req_itspaths = [
+ ['/', 'images', 'uboot'],
+ ['/', 'images', 'uboot', 'signature'],
+ ['/', 'images', 'fdt'],
+ ['/', 'images', 'fdt', 'signature'],
+ ]
+
+ itspath = []
+ itspaths = []
+ linect = 0
+ sigs = {}
+ with open(fitimage_its_path) as its_file:
+ linect += 1
+ for line in its_file:
+ line = line.strip()
+ if line.endswith('};'):
+ itspath.pop()
+ elif line.endswith('{'):
+ itspath.append(line[:-1].strip())
+ itspaths.append(itspath[:])
+ elif itspath and itspath[-1] == 'signature':
+ itsdotpath = '.'.join(itspath)
+ if not itsdotpath in sigs:
+ sigs[itsdotpath] = {}
+ if not '=' in line or not line.endswith(';'):
+ self.fail('Unexpected formatting in %s sigs section line %d:%s' % (fitimage_its_path, linect, line))
+ key, value = line.split('=', 1)
+ sigs[itsdotpath][key.rstrip()] = value.lstrip().rstrip(';')
+
+ for reqpath in req_itspaths:
+ if not reqpath in itspaths:
+ self.fail('Missing section in its file: %s' % reqpath)
+
+ reqsigvalues_image = {
+ 'algo': '"sha256,rsa2048"',
+ 'key-name-hint': '"spl-oe-selftest"',
+ }
+
+ for itspath, values in sigs.items():
+ reqsigvalues = reqsigvalues_image
+ for reqkey, reqvalue in reqsigvalues.items():
+ value = values.get(reqkey, None)
+ if value is None:
+ self.fail('Missing key "%s" in its file signature section %s' % (reqkey, itspath))
+ self.assertEqual(value, reqvalue)
+
+ # Dump the image to see if it really got signed
+ bitbake("u-boot-tools-native -c addto_recipe_sysroot")
+ result = runCmd('bitbake -e u-boot-tools-native | grep ^RECIPE_SYSROOT_NATIVE=')
+ recipe_sysroot_native = result.output.split('=')[1].strip('"')
+ dumpimage_path = os.path.join(recipe_sysroot_native, 'usr', 'bin', 'dumpimage')
+ result = runCmd('%s -l %s' % (dumpimage_path, fitimage_path))
+ in_signed = None
+ signed_sections = {}
+ for line in result.output.splitlines():
+ if line.startswith((' Image')):
+ in_signed = re.search('\((.*)\)', line).groups()[0]
+ elif re.match(' \w', line):
+ in_signed = None
+ elif in_signed:
+ if not in_signed in signed_sections:
+ signed_sections[in_signed] = {}
+ key, value = line.split(':', 1)
+ signed_sections[in_signed][key.strip()] = value.strip()
+ self.assertIn('uboot', signed_sections)
+ self.assertIn('fdt', signed_sections)
+ for signed_section, values in signed_sections.items():
+ value = values.get('Sign algo', None)
+ self.assertEqual(value, 'sha256,rsa2048:spl-oe-selftest', 'Signature algorithm for %s not expected value' % signed_section)
+ value = values.get('Sign value', None)
+ self.assertEqual(len(value), 512, 'Signature value for section %s not expected length' % signed_section)
+
+ # Check for SPL_MKIMAGE_SIGN_ARGS
+ result = runCmd('bitbake -e virtual/bootloader | grep ^T=')
+ tempdir = result.output.split('=', 1)[1].strip().strip('')
+ result = runCmd('grep "a smart U-Boot comment" %s/run.do_uboot_assemble_fitimage' % tempdir, ignore_status=True)
+ self.assertEqual(result.status, 0, 'SPL_MKIMAGE_SIGN_ARGS value did not get used')
+
+ # Check for evidence of test-mkimage-wrapper class
+ result = runCmd('grep "### uboot-mkimage wrapper message" %s/log.do_uboot_assemble_fitimage' % tempdir, ignore_status=True)
+ self.assertEqual(result.status, 0, 'UBOOT_MKIMAGE did not work')
+ result = runCmd('grep "### uboot-mkimage signing wrapper message" %s/log.do_uboot_assemble_fitimage' % tempdir, ignore_status=True)
+ self.assertEqual(result.status, 0, 'UBOOT_MKIMAGE_SIGN did not work')
+
+ def test_sign_cascaded_uboot_fit_image(self):
+ """
+ Summary: Check if U-Boot FIT image and Image Tree Source (its) are
+ created and signed correctly for the scenario where both
+ U-Boot proper and Kernel fitImages are being created and
+ signed.
+ Expected: 1) U-Boot its and FIT image are built successfully
+ 2) Scanning the its file indicates signing is enabled
+ as requested by SPL_SIGN_ENABLE (using keys generated
+ via UBOOT_FIT_GENERATE_KEYS)
+ 3) Dumping the FIT image indicates signature values
+ are present
+ 4) Examination of the do_uboot_assemble_fitimage
+ runfile/logfile indicate that UBOOT_MKIMAGE, UBOOT_MKIMAGE_SIGN
+ and SPL_MKIMAGE_SIGN_ARGS are working as expected.
+ Product: oe-core
+ Author: Klaus Heinrich Kiwi <klaus@linux.vnet.ibm.com> based upon
+ work by Paul Eggleton <paul.eggleton@microsoft.com> and
+ Usama Arif <usama.arif@arm.com>
+ """
+ config = """
+# There's no U-boot deconfig with CONFIG_FIT_SIGNATURE yet, so we need at
+# least CONFIG_SPL_LOAD_FIT and CONFIG_SPL_OF_CONTROL set
+MACHINE = "qemuarm"
+UBOOT_MACHINE = "am57xx_evm_defconfig"
+SPL_BINARY = "MLO"
+# Enable creation and signing of the U-Boot fitImage
+UBOOT_FITIMAGE_ENABLE = "1"
+SPL_SIGN_ENABLE = "1"
+SPL_SIGN_KEYNAME = "spl-cascaded-oe-selftest"
+SPL_SIGN_KEYDIR = "${TOPDIR}/signing-keys"
+UBOOT_DTB_BINARY = "u-boot.dtb"
+UBOOT_ENTRYPOINT = "0x80000000"
+UBOOT_LOADADDRESS = "0x80000000"
+UBOOT_MKIMAGE_DTCOPTS = "-I dts -O dtb -p 2000"
+UBOOT_MKIMAGE_SIGN_ARGS = "-c 'a smart cascaded Kernel comment'"
+UBOOT_DTB_LOADADDRESS = "0x82000000"
+UBOOT_ARCH = "arm"
+SPL_MKIMAGE_DTCOPTS = "-I dts -O dtb -p 2000"
+SPL_MKIMAGE_SIGN_ARGS = "-c 'a smart cascaded U-Boot comment'"
+UBOOT_EXTLINUX = "0"
+UBOOT_FIT_GENERATE_KEYS = "1"
+UBOOT_FIT_HASH_ALG = "sha256"
+KERNEL_IMAGETYPES += " fitImage "
+KERNEL_CLASSES = " kernel-fitimage "
+INHERIT += "test-mkimage-wrapper"
+UBOOT_SIGN_ENABLE = "1"
+FIT_GENERATE_KEYS = "1"
+UBOOT_SIGN_KEYDIR = "${TOPDIR}/signing-keys"
+UBOOT_SIGN_IMG_KEYNAME = "img-oe-selftest"
+UBOOT_SIGN_KEYNAME = "cfg-oe-selftest"
+FIT_SIGN_INDIVIDUAL = "1"
+"""
+ self.write_config(config)
+
+ # The U-Boot fitImage is created as part of the U-Boot recipe
+ bitbake("virtual/bootloader")
+
+ image_type = "core-image-minimal"
+ deploy_dir_image = get_bb_var('DEPLOY_DIR_IMAGE')
+ machine = get_bb_var('MACHINE')
+ fitimage_its_path = os.path.join(deploy_dir_image,
+ "u-boot-its-%s" % (machine,))
+ fitimage_path = os.path.join(deploy_dir_image,
+ "u-boot-fitImage-%s" % (machine,))
+
+ self.assertTrue(os.path.exists(fitimage_its_path),
+ "%s image tree source doesn't exist" % (fitimage_its_path))
+ self.assertTrue(os.path.exists(fitimage_path),
+ "%s FIT image doesn't exist" % (fitimage_path))
+
+ req_itspaths = [
+ ['/', 'images', 'uboot'],
+ ['/', 'images', 'uboot', 'signature'],
+ ['/', 'images', 'fdt'],
+ ['/', 'images', 'fdt', 'signature'],
+ ]
+
+ itspath = []
+ itspaths = []
+ linect = 0
+ sigs = {}
+ with open(fitimage_its_path) as its_file:
+ linect += 1
+ for line in its_file:
+ line = line.strip()
+ if line.endswith('};'):
+ itspath.pop()
+ elif line.endswith('{'):
+ itspath.append(line[:-1].strip())
+ itspaths.append(itspath[:])
+ elif itspath and itspath[-1] == 'signature':
+ itsdotpath = '.'.join(itspath)
+ if not itsdotpath in sigs:
+ sigs[itsdotpath] = {}
+ if not '=' in line or not line.endswith(';'):
+ self.fail('Unexpected formatting in %s sigs section line %d:%s' % (fitimage_its_path, linect, line))
+ key, value = line.split('=', 1)
+ sigs[itsdotpath][key.rstrip()] = value.lstrip().rstrip(';')
+
+ for reqpath in req_itspaths:
+ if not reqpath in itspaths:
+ self.fail('Missing section in its file: %s' % reqpath)
+
+ reqsigvalues_image = {
+ 'algo': '"sha256,rsa2048"',
+ 'key-name-hint': '"spl-cascaded-oe-selftest"',
+ }
+
+ for itspath, values in sigs.items():
+ reqsigvalues = reqsigvalues_image
+ for reqkey, reqvalue in reqsigvalues.items():
+ value = values.get(reqkey, None)
+ if value is None:
+ self.fail('Missing key "%s" in its file signature section %s' % (reqkey, itspath))
+ self.assertEqual(value, reqvalue)
+
+ # Dump the image to see if it really got signed
+ bitbake("u-boot-tools-native -c addto_recipe_sysroot")
+ result = runCmd('bitbake -e u-boot-tools-native | grep ^RECIPE_SYSROOT_NATIVE=')
+ recipe_sysroot_native = result.output.split('=')[1].strip('"')
+ dumpimage_path = os.path.join(recipe_sysroot_native, 'usr', 'bin', 'dumpimage')
+ result = runCmd('%s -l %s' % (dumpimage_path, fitimage_path))
+ in_signed = None
+ signed_sections = {}
+ for line in result.output.splitlines():
+ if line.startswith((' Image')):
+ in_signed = re.search('\((.*)\)', line).groups()[0]
+ elif re.match(' \w', line):
+ in_signed = None
+ elif in_signed:
+ if not in_signed in signed_sections:
+ signed_sections[in_signed] = {}
+ key, value = line.split(':', 1)
+ signed_sections[in_signed][key.strip()] = value.strip()
+ self.assertIn('uboot', signed_sections)
+ self.assertIn('fdt', signed_sections)
+ for signed_section, values in signed_sections.items():
+ value = values.get('Sign algo', None)
+ self.assertEqual(value, 'sha256,rsa2048:spl-cascaded-oe-selftest', 'Signature algorithm for %s not expected value' % signed_section)
+ value = values.get('Sign value', None)
+ self.assertEqual(len(value), 512, 'Signature value for section %s not expected length' % signed_section)
+
+ # Check for SPL_MKIMAGE_SIGN_ARGS
+ result = runCmd('bitbake -e virtual/bootloader | grep ^T=')
+ tempdir = result.output.split('=', 1)[1].strip().strip('')
+ result = runCmd('grep "a smart cascaded U-Boot comment" %s/run.do_uboot_assemble_fitimage' % tempdir, ignore_status=True)
+ self.assertEqual(result.status, 0, 'SPL_MKIMAGE_SIGN_ARGS value did not get used')
+
+ # Check for evidence of test-mkimage-wrapper class
+ result = runCmd('grep "### uboot-mkimage wrapper message" %s/log.do_uboot_assemble_fitimage' % tempdir, ignore_status=True)
+ self.assertEqual(result.status, 0, 'UBOOT_MKIMAGE did not work')
+ result = runCmd('grep "### uboot-mkimage signing wrapper message" %s/log.do_uboot_assemble_fitimage' % tempdir, ignore_status=True)
+ self.assertEqual(result.status, 0, 'UBOOT_MKIMAGE_SIGN did not work')
+
+
+
+ def test_initramfs_bundle(self):
+ """
+ Summary: Verifies the content of the initramfs bundle node in the FIT Image Tree Source (its)
+ The FIT settings are set by the test case.
+ The machine used is beaglebone-yocto.
+ Expected: 1. The ITS is generated with initramfs bundle support
+ 2. All the fields in the kernel node are as expected (matching the
+ conf settings)
+ 3. The kernel is included in all the available configurations and
+ its hash is included in the configuration signature
+
+ Product: oe-core
+ Author: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+ """
+
+ config = """
+DISTRO="poky"
+MACHINE = "beaglebone-yocto"
+INITRAMFS_IMAGE_BUNDLE = "1"
+INITRAMFS_IMAGE = "core-image-minimal-initramfs"
+INITRAMFS_SCRIPTS = ""
+UBOOT_MACHINE = "am335x_evm_defconfig"
+KERNEL_CLASSES = " kernel-fitimage "
+KERNEL_IMAGETYPES = "fitImage"
+UBOOT_SIGN_ENABLE = "1"
+UBOOT_SIGN_KEYNAME = "beaglebonekey"
+UBOOT_SIGN_KEYDIR ?= "${DEPLOY_DIR_IMAGE}"
+UBOOT_DTB_BINARY = "u-boot.dtb"
+UBOOT_ENTRYPOINT = "0x80000000"
+UBOOT_LOADADDRESS = "0x80000000"
+UBOOT_DTB_LOADADDRESS = "0x82000000"
+UBOOT_ARCH = "arm"
+UBOOT_MKIMAGE_DTCOPTS = "-I dts -O dtb -p 2000"
+UBOOT_MKIMAGE_KERNEL_TYPE = "kernel"
+UBOOT_EXTLINUX = "0"
+FIT_GENERATE_KEYS = "1"
+KERNEL_IMAGETYPE_REPLACEMENT = "zImage"
+FIT_KERNEL_COMP_ALG = "none"
+FIT_HASH_ALG = "sha256"
+"""
+ self.write_config(config)
+
+ # fitImage is created as part of linux recipe
+ bitbake("virtual/kernel")
+
+ image_type = get_bb_var('INITRAMFS_IMAGE')
+ deploy_dir_image = get_bb_var('DEPLOY_DIR_IMAGE')
+ machine = get_bb_var('MACHINE')
+ fitimage_its_path = os.path.join(deploy_dir_image,
+ "fitImage-its-%s-%s-%s" % (image_type, machine, machine))
+ fitimage_path = os.path.join(deploy_dir_image,"fitImage")
+
+ self.assertTrue(os.path.exists(fitimage_its_path),
+ "%s image tree source doesn't exist" % (fitimage_its_path))
+ self.assertTrue(os.path.exists(fitimage_path),
+ "%s FIT image doesn't exist" % (fitimage_path))
+
+ kernel_load = str(get_bb_var('UBOOT_LOADADDRESS'))
+ kernel_entry = str(get_bb_var('UBOOT_ENTRYPOINT'))
+ kernel_type = str(get_bb_var('UBOOT_MKIMAGE_KERNEL_TYPE'))
+ kernel_compression = str(get_bb_var('FIT_KERNEL_COMP_ALG'))
+ uboot_arch = str(get_bb_var('UBOOT_ARCH'))
+ fit_hash_alg = str(get_bb_var('FIT_HASH_ALG'))
+
+ its_file = open(fitimage_its_path)
+
+ its_lines = [line.strip() for line in its_file.readlines()]
+
+ exp_node_lines = [
+ 'kernel-1 {',
+ 'description = "Linux kernel";',
+ 'data = /incbin/("linux.bin");',
+ 'type = "' + kernel_type + '";',
+ 'arch = "' + uboot_arch + '";',
+ 'os = "linux";',
+ 'compression = "' + kernel_compression + '";',
+ 'load = <' + kernel_load + '>;',
+ 'entry = <' + kernel_entry + '>;',
+ 'hash-1 {',
+ 'algo = "' + fit_hash_alg +'";',
+ '};',
+ '};'
+ ]
+
+ node_str = exp_node_lines[0]
+
+ test_passed = False
+
+ print ("checking kernel node\n")
+
+ if node_str in its_lines:
+ node_start_idx = its_lines.index(node_str)
+ node = its_lines[node_start_idx:(node_start_idx + len(exp_node_lines))]
+ if node == exp_node_lines:
+ print("kernel node verified")
+ else:
+ self.assertTrue(test_passed == True,"kernel node does not match expectation")
+
+ rx_configs = re.compile("^conf-.*")
+ its_configs = list(filter(rx_configs.match, its_lines))
+
+ for cfg_str in its_configs:
+ cfg_start_idx = its_lines.index(cfg_str)
+ line_idx = cfg_start_idx + 2
+ node_end = False
+ while node_end == False:
+ if its_lines[line_idx] == "};" and its_lines[line_idx-1] == "};" :
+ node_end = True
+ line_idx = line_idx + 1
+
+ node = its_lines[cfg_start_idx:line_idx]
+ print("checking configuration " + cfg_str.rstrip(" {"))
+ rx_desc_line = re.compile("^description.*1 Linux kernel.*")
+ if len(list(filter(rx_desc_line.match, node))) != 1:
+ self.assertTrue(test_passed == True,"kernel keyword not found in the description line")
+ break
+ else:
+ print("kernel keyword found in the description line")
+
+ if 'kernel = "kernel-1";' not in node:
+ self.assertTrue(test_passed == True,"kernel line not found")
+ break
+ else:
+ print("kernel line found")
+
+ rx_sign_line = re.compile("^sign-images.*kernel.*")
+ if len(list(filter(rx_sign_line.match, node))) != 1:
+ self.assertTrue(test_passed == True,"kernel hash not signed")
+ break
+ else:
+ print("kernel hash signed")
+
+ test_passed = True
+ self.assertTrue(test_passed == True,"Initramfs bundle test success")
diff --git a/meta/lib/oeqa/selftest/cases/gcc.py b/meta/lib/oeqa/selftest/cases/gcc.py
new file mode 100644
index 0000000000..6b9022e461
--- /dev/null
+++ b/meta/lib/oeqa/selftest/cases/gcc.py
@@ -0,0 +1,163 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+import os
+from oeqa.core.decorator import OETestTag
+from oeqa.core.case import OEPTestResultTestCase
+from oeqa.selftest.case import OESelftestTestCase
+from oeqa.utils.commands import bitbake, get_bb_var, get_bb_vars, runqemu
+
+def parse_values(content):
+ for i in content:
+ for v in ["PASS", "FAIL", "XPASS", "XFAIL", "UNRESOLVED", "UNSUPPORTED", "UNTESTED", "ERROR", "WARNING"]:
+ if i.startswith(v + ": "):
+ yield i[len(v) + 2:].strip(), v
+ break
+
+class GccSelfTestBase(OESelftestTestCase, OEPTestResultTestCase):
+ def check_skip(self, suite):
+ targets = get_bb_var("RUNTIMETARGET", "gcc-runtime").split()
+ if suite not in targets:
+ self.skipTest("Target does not use {0}".format(suite))
+
+ def run_check(self, *suites, ssh = None):
+ targets = set()
+ for s in suites:
+ if s == "gcc":
+ targets.add("check-gcc-c")
+ elif s == "g++":
+ targets.add("check-gcc-c++")
+ else:
+ targets.add("check-target-{}".format(s))
+
+ # configure ssh target
+ features = []
+ features.append('MAKE_CHECK_TARGETS = "{0}"'.format(" ".join(targets)))
+ if ssh is not None:
+ features.append('TOOLCHAIN_TEST_TARGET = "ssh"')
+ features.append('TOOLCHAIN_TEST_HOST = "{0}"'.format(ssh))
+ features.append('TOOLCHAIN_TEST_HOST_USER = "root"')
+ features.append('TOOLCHAIN_TEST_HOST_PORT = "22"')
+ self.write_config("\n".join(features))
+
+ recipe = "gcc-runtime"
+ bitbake("{} -c check".format(recipe))
+
+ bb_vars = get_bb_vars(["B", "TARGET_SYS"], recipe)
+ builddir, target_sys = bb_vars["B"], bb_vars["TARGET_SYS"]
+
+ for suite in suites:
+ sumspath = os.path.join(builddir, "gcc", "testsuite", suite, "{0}.sum".format(suite))
+ if not os.path.exists(sumspath): # check in target dirs
+ sumspath = os.path.join(builddir, target_sys, suite, "testsuite", "{0}.sum".format(suite))
+ if not os.path.exists(sumspath): # handle libstdc++-v3 -> libstdc++
+ sumspath = os.path.join(builddir, target_sys, suite, "testsuite", "{0}.sum".format(suite.split("-")[0]))
+ logpath = os.path.splitext(sumspath)[0] + ".log"
+
+ ptestsuite = "gcc-{}".format(suite) if suite != "gcc" else suite
+ ptestsuite = ptestsuite + "-user" if ssh is None else ptestsuite
+ self.ptest_section(ptestsuite, logfile = logpath)
+ with open(sumspath, "r") as f:
+ for test, result in parse_values(f):
+ self.ptest_result(ptestsuite, test, result)
+
+ def run_check_emulated(self, *args, **kwargs):
+ # build core-image-minimal with required packages
+ default_installed_packages = ["libgcc", "libstdc++", "libatomic", "libgomp"]
+ features = []
+ features.append('IMAGE_FEATURES += "ssh-server-openssh"')
+ features.append('CORE_IMAGE_EXTRA_INSTALL += "{0}"'.format(" ".join(default_installed_packages)))
+ self.write_config("\n".join(features))
+ bitbake("core-image-minimal")
+
+ # wrap the execution with a qemu instance
+ with runqemu("core-image-minimal", runqemuparams = "nographic") as qemu:
+ # validate that SSH is working
+ status, _ = qemu.run("uname")
+ self.assertEqual(status, 0)
+
+ return self.run_check(*args, ssh=qemu.ip, **kwargs)
+
+@OETestTag("toolchain-user")
+class GccCrossSelfTest(GccSelfTestBase):
+ def test_cross_gcc(self):
+ self.run_check("gcc")
+
+@OETestTag("toolchain-user")
+class GxxCrossSelfTest(GccSelfTestBase):
+ def test_cross_gxx(self):
+ self.run_check("g++")
+
+@OETestTag("toolchain-user")
+class GccLibAtomicSelfTest(GccSelfTestBase):
+ def test_libatomic(self):
+ self.run_check("libatomic")
+
+@OETestTag("toolchain-user")
+class GccLibGompSelfTest(GccSelfTestBase):
+ def test_libgomp(self):
+ self.run_check("libgomp")
+
+@OETestTag("toolchain-user")
+class GccLibStdCxxSelfTest(GccSelfTestBase):
+ def test_libstdcxx(self):
+ self.run_check("libstdc++-v3")
+
+@OETestTag("toolchain-user")
+class GccLibSspSelfTest(GccSelfTestBase):
+ def test_libssp(self):
+ self.check_skip("libssp")
+ self.run_check("libssp")
+
+@OETestTag("toolchain-user")
+class GccLibItmSelfTest(GccSelfTestBase):
+ def test_libitm(self):
+ self.check_skip("libitm")
+ self.run_check("libitm")
+
+@OETestTag("toolchain-system")
+@OETestTag("runqemu")
+class GccCrossSelfTestSystemEmulated(GccSelfTestBase):
+ def test_cross_gcc(self):
+ self.run_check_emulated("gcc")
+
+@OETestTag("toolchain-system")
+@OETestTag("runqemu")
+class GxxCrossSelfTestSystemEmulated(GccSelfTestBase):
+ def test_cross_gxx(self):
+ self.run_check_emulated("g++")
+
+@OETestTag("toolchain-system")
+@OETestTag("runqemu")
+class GccLibAtomicSelfTestSystemEmulated(GccSelfTestBase):
+ def test_libatomic(self):
+ self.run_check_emulated("libatomic")
+
+@OETestTag("toolchain-system")
+@OETestTag("runqemu")
+class GccLibGompSelfTestSystemEmulated(GccSelfTestBase):
+ def test_libgomp(self):
+ self.run_check_emulated("libgomp")
+
+@OETestTag("toolchain-system")
+@OETestTag("runqemu")
+class GccLibStdCxxSelfTestSystemEmulated(GccSelfTestBase):
+ def test_libstdcxx(self):
+ self.run_check_emulated("libstdc++-v3")
+
+@OETestTag("toolchain-system")
+@OETestTag("runqemu")
+class GccLibSspSelfTestSystemEmulated(GccSelfTestBase):
+ def test_libssp(self):
+ self.check_skip("libssp")
+ self.run_check_emulated("libssp")
+
+@OETestTag("toolchain-system")
+@OETestTag("runqemu")
+class GccLibItmSelfTestSystemEmulated(GccSelfTestBase):
+ def test_libitm(self):
+ self.check_skip("libitm")
+ self.run_check_emulated("libitm")
+
diff --git a/meta/lib/oeqa/selftest/cases/gdbserver.py b/meta/lib/oeqa/selftest/cases/gdbserver.py
new file mode 100644
index 0000000000..3621d9c13e
--- /dev/null
+++ b/meta/lib/oeqa/selftest/cases/gdbserver.py
@@ -0,0 +1,66 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+import os
+import time
+import tempfile
+import shutil
+import concurrent.futures
+
+from oeqa.selftest.case import OESelftestTestCase
+from oeqa.utils.commands import bitbake, get_bb_var, runqemu, runCmd
+
+class GdbServerTest(OESelftestTestCase):
+ def test_gdb_server(self):
+ target_arch = self.td["TARGET_ARCH"]
+ target_sys = self.td["TARGET_SYS"]
+ deploy_dir = get_bb_var("DEPLOY_DIR_IMAGE")
+
+ features = """
+IMAGE_GEN_DEBUGFS = "1"
+IMAGE_FSTYPES_DEBUGFS = "tar.bz2"
+CORE_IMAGE_EXTRA_INSTALL = "gdbserver"
+ """
+ self.write_config(features)
+
+ gdb_recipe = "gdb-cross-" + target_arch
+ gdb_binary = target_sys + "-gdb"
+
+ bitbake("core-image-minimal %s:do_addto_recipe_sysroot" % gdb_recipe)
+
+ native_sysroot = get_bb_var("RECIPE_SYSROOT_NATIVE", gdb_recipe)
+ r = runCmd("%s --version" % gdb_binary, native_sysroot=native_sysroot, target_sys=target_sys)
+ self.assertEqual(r.status, 0)
+ self.assertIn("GNU gdb", r.output)
+
+ with tempfile.TemporaryDirectory(prefix="debugfs-") as debugfs:
+ filename = os.path.join(deploy_dir, "core-image-minimal-%s-dbg.tar.bz2" % self.td["MACHINE"])
+ shutil.unpack_archive(filename, debugfs)
+ filename = os.path.join(deploy_dir, "core-image-minimal-%s.tar.bz2" % self.td["MACHINE"])
+ shutil.unpack_archive(filename, debugfs)
+
+ with runqemu("core-image-minimal", runqemuparams="nographic") as qemu:
+ status, output = qemu.run_serial("kmod --help")
+ self.assertIn("modprobe", output)
+
+ with concurrent.futures.ThreadPoolExecutor(max_workers=1) as executor:
+ def run_gdb():
+ for _ in range(5):
+ time.sleep(2)
+ cmd = "%s --batch -ex 'set sysroot %s' -ex \"target extended-remote %s:9999\" -ex \"info line kmod_help\"" % (gdb_binary, debugfs, qemu.ip)
+ self.logger.warning("starting gdb %s" % cmd)
+ r = runCmd(cmd, native_sysroot=native_sysroot, target_sys=target_sys)
+ self.assertEqual(0, r.status)
+ line_re = r"Line \d+ of \"/usr/src/debug/kmod/.*/tools/kmod.c\" starts at address 0x[0-9A-Fa-f]+ <kmod_help>"
+ self.assertRegex(r.output, line_re)
+ break
+ else:
+ self.fail("Timed out connecting to gdb")
+ future = executor.submit(run_gdb)
+
+ status, output = qemu.run_serial("gdbserver --once :9999 kmod --help")
+ self.assertEqual(status, 1)
+ # The future either returns None, or raises an exception
+ future.result()
diff --git a/meta/lib/oeqa/selftest/cases/glibc.py b/meta/lib/oeqa/selftest/cases/glibc.py
new file mode 100644
index 0000000000..a446543a17
--- /dev/null
+++ b/meta/lib/oeqa/selftest/cases/glibc.py
@@ -0,0 +1,94 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+import os
+import contextlib
+from oeqa.core.decorator import OETestTag
+from oeqa.core.case import OEPTestResultTestCase
+from oeqa.selftest.case import OESelftestTestCase
+from oeqa.utils.commands import bitbake, get_bb_var, runqemu
+from oeqa.utils.nfs import unfs_server
+
+def parse_values(content):
+ for i in content:
+ for v in ["PASS", "FAIL", "XPASS", "XFAIL", "UNRESOLVED", "UNSUPPORTED", "UNTESTED", "ERROR", "WARNING"]:
+ if i.startswith(v + ": "):
+ yield i[len(v) + 2:].strip(), v
+ break
+
+class GlibcSelfTestBase(OESelftestTestCase, OEPTestResultTestCase):
+ def run_check(self, ssh = None):
+ # configure ssh target
+ features = []
+ if ssh is not None:
+ features.append('TOOLCHAIN_TEST_TARGET = "ssh"')
+ features.append('TOOLCHAIN_TEST_HOST = "{0}"'.format(ssh))
+ features.append('TOOLCHAIN_TEST_HOST_USER = "root"')
+ features.append('TOOLCHAIN_TEST_HOST_PORT = "22"')
+ # force single threaded test execution
+ features.append('EGLIBCPARALLELISM_task-check:pn-glibc-testsuite = "PARALLELMFLAGS="-j1""')
+ self.write_config("\n".join(features))
+
+ bitbake("glibc-testsuite -c check")
+
+ builddir = get_bb_var("B", "glibc-testsuite")
+
+ ptestsuite = "glibc-user" if ssh is None else "glibc"
+ self.ptest_section(ptestsuite)
+ with open(os.path.join(builddir, "tests.sum"), "r", errors='replace') as f:
+ for test, result in parse_values(f):
+ self.ptest_result(ptestsuite, test, result)
+
+ def run_check_emulated(self):
+ with contextlib.ExitStack() as s:
+ # use the base work dir, as the nfs mount, since the recipe directory may not exist
+ tmpdir = get_bb_var("BASE_WORKDIR")
+ nfsport, mountport = s.enter_context(unfs_server(tmpdir))
+
+ # build core-image-minimal with required packages
+ default_installed_packages = [
+ "glibc-charmaps",
+ "libgcc",
+ "libstdc++",
+ "libatomic",
+ "libgomp",
+ # "python3",
+ # "python3-pexpect",
+ "nfs-utils",
+ ]
+ features = []
+ features.append('IMAGE_FEATURES += "ssh-server-openssh"')
+ features.append('CORE_IMAGE_EXTRA_INSTALL += "{0}"'.format(" ".join(default_installed_packages)))
+ self.write_config("\n".join(features))
+ bitbake("core-image-minimal")
+
+ # start runqemu
+ qemu = s.enter_context(runqemu("core-image-minimal", runqemuparams = "nographic"))
+
+ # validate that SSH is working
+ status, _ = qemu.run("uname")
+ self.assertEqual(status, 0)
+
+ # setup nfs mount
+ if qemu.run("mkdir -p \"{0}\"".format(tmpdir))[0] != 0:
+ raise Exception("Failed to setup NFS mount directory on target")
+ mountcmd = "mount -o noac,nfsvers=3,port={0},udp,mountport={1} \"{2}:{3}\" \"{3}\"".format(nfsport, mountport, qemu.server_ip, tmpdir)
+ status, output = qemu.run(mountcmd)
+ if status != 0:
+ raise Exception("Failed to setup NFS mount on target ({})".format(repr(output)))
+
+ self.run_check(ssh = qemu.ip)
+
+@OETestTag("toolchain-user")
+class GlibcSelfTest(GlibcSelfTestBase):
+ def test_glibc(self):
+ self.run_check()
+
+@OETestTag("toolchain-system")
+@OETestTag("runqemu")
+class GlibcSelfTestSystemEmulated(GlibcSelfTestBase):
+ def test_glibc(self):
+ self.run_check_emulated()
+
diff --git a/meta/lib/oeqa/selftest/cases/gotoolchain.py b/meta/lib/oeqa/selftest/cases/gotoolchain.py
new file mode 100644
index 0000000000..74c1c48117
--- /dev/null
+++ b/meta/lib/oeqa/selftest/cases/gotoolchain.py
@@ -0,0 +1,74 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
+import glob
+import os
+import shutil
+import tempfile
+from oeqa.selftest.case import OESelftestTestCase
+from oeqa.utils.commands import runCmd, bitbake, get_bb_vars
+
+
+class oeGoToolchainSelfTest(OESelftestTestCase):
+ """
+ Test cases for OE's Go toolchain
+ """
+
+ @staticmethod
+ def get_sdk_environment(tmpdir_SDKQA):
+ pattern = os.path.join(tmpdir_SDKQA, "environment-setup-*")
+ # FIXME: this is a very naive implementation
+ return glob.glob(pattern)[0]
+
+ @staticmethod
+ def get_sdk_toolchain():
+ bb_vars = get_bb_vars(['SDK_DEPLOY', 'TOOLCHAIN_OUTPUTNAME'],
+ "meta-go-toolchain")
+ sdk_deploy = bb_vars['SDK_DEPLOY']
+ toolchain_name = bb_vars['TOOLCHAIN_OUTPUTNAME']
+ return os.path.join(sdk_deploy, toolchain_name + ".sh")
+
+ @classmethod
+ def setUpClass(cls):
+ super(oeGoToolchainSelfTest, cls).setUpClass()
+ cls.tmpdir_SDKQA = tempfile.mkdtemp(prefix='SDKQA')
+ cls.go_path = os.path.join(cls.tmpdir_SDKQA, "go")
+ # Build the SDK and locate it in DEPLOYDIR
+ bitbake("meta-go-toolchain")
+ cls.sdk_path = oeGoToolchainSelfTest.get_sdk_toolchain()
+ # Install the SDK into the tmpdir
+ runCmd("sh %s -y -d \"%s\"" % (cls.sdk_path, cls.tmpdir_SDKQA))
+ cls.env_SDK = oeGoToolchainSelfTest.get_sdk_environment(cls.tmpdir_SDKQA)
+
+ @classmethod
+ def tearDownClass(cls):
+ shutil.rmtree(cls.tmpdir_SDKQA, ignore_errors=True)
+ super(oeGoToolchainSelfTest, cls).tearDownClass()
+
+ def run_sdk_go_command(self, gocmd, proj, name):
+ cmd = "cd %s/src/%s/%s; " % (self.go_path, proj, name)
+ cmd = cmd + ". %s; " % self.env_SDK
+ cmd = cmd + "export GOPATH=%s; " % self.go_path
+ cmd = cmd + "export GOFLAGS=-modcacherw; "
+ cmd = cmd + "export CGO_ENABLED=1; "
+ cmd = cmd + "${CROSS_COMPILE}go %s" % gocmd
+ return runCmd(cmd).status
+
+ def test_go_dep_build(self):
+ proj = "github.com/direnv"
+ name = "direnv"
+ ver = "v2.27.0"
+ archive = ".tar.gz"
+ url = "https://%s/%s/archive/%s%s" % (proj, name, ver, archive)
+
+ runCmd("cd %s; wget %s" % (self.tmpdir_SDKQA, url))
+ runCmd("cd %s; tar -xf %s" % (self.tmpdir_SDKQA, ver+archive))
+ runCmd("mkdir -p %s/src/%s" % (self.go_path, proj))
+ runCmd("mv %s/direnv-2.27.0 %s/src/%s/%s"
+ % (self.tmpdir_SDKQA, self.go_path, proj, name))
+ retv = self.run_sdk_go_command('build', proj, name)
+ self.assertEqual(retv, 0,
+ msg="Running go build failed for %s" % name)
diff --git a/meta/lib/oeqa/selftest/cases/image_typedep.py b/meta/lib/oeqa/selftest/cases/image_typedep.py
new file mode 100644
index 0000000000..17c98baf14
--- /dev/null
+++ b/meta/lib/oeqa/selftest/cases/image_typedep.py
@@ -0,0 +1,60 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
+import os
+
+from oeqa.selftest.case import OESelftestTestCase
+from oeqa.utils.commands import bitbake
+
+class ImageTypeDepTests(OESelftestTestCase):
+
+ # Verify that when specifying a IMAGE_TYPEDEP: of the form "foo.bar" that
+ # the conversion type bar gets added as a dep as well
+ def test_conversion_typedep_added(self):
+
+ self.write_recipeinc('emptytest', """
+# Try to empty out the default dependency list
+PACKAGE_INSTALL = ""
+DISTRO_EXTRA_RDEPENDS=""
+
+LICENSE = "MIT"
+IMAGE_FSTYPES = "testfstype"
+
+IMAGE_TYPES_MASKED += "testfstype"
+IMAGE_TYPEDEP:testfstype = "tar.bz2"
+
+inherit image
+
+""")
+ # First get the dependency that should exist for bz2, it will look
+ # like CONVERSION_DEPENDS_bz2="somedep"
+ result = bitbake('-e emptytest')
+
+ dep = None
+ for line in result.output.split('\n'):
+ if line.startswith('CONVERSION_DEPENDS_bz2'):
+ dep = line.split('=')[1].strip('"')
+ break
+
+ self.assertIsNotNone(dep, "CONVERSION_DEPENDS_bz2 dependency not found in bitbake -e output")
+
+ # Now get the dependency task list and check for the expected task
+ # dependency
+ bitbake('-g emptytest')
+
+ taskdependsfile = os.path.join(self.builddir, 'task-depends.dot')
+ dep = dep + ".do_populate_sysroot"
+ depfound = False
+ expectedline = '"emptytest.do_rootfs" -> "{}"'.format(dep)
+
+ with open(taskdependsfile, "r") as f:
+ for line in f:
+ if line.strip() == expectedline:
+ depfound = True
+ break
+
+ if not depfound:
+ raise AssertionError("\"{}\" not found".format(expectedline))
diff --git a/meta/lib/oeqa/selftest/cases/imagefeatures.py b/meta/lib/oeqa/selftest/cases/imagefeatures.py
new file mode 100644
index 0000000000..af38150613
--- /dev/null
+++ b/meta/lib/oeqa/selftest/cases/imagefeatures.py
@@ -0,0 +1,301 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
+from oeqa.selftest.case import OESelftestTestCase
+from oeqa.core.decorator import OETestTag
+from oeqa.utils.commands import runCmd, bitbake, get_bb_var, runqemu
+from oeqa.utils.sshcontrol import SSHControl
+import glob
+import os
+import json
+
+class ImageFeatures(OESelftestTestCase):
+
+ test_user = 'tester'
+ root_user = 'root'
+
+ @OETestTag("runqemu")
+ def test_non_root_user_can_connect_via_ssh_without_password(self):
+ """
+ Summary: Check if non root user can connect via ssh without password
+ Expected: 1. Connection to the image via ssh using root user without providing a password should be allowed.
+ 2. Connection to the image via ssh using tester user without providing a password should be allowed.
+ Product: oe-core
+ Author: Ionut Chisanovici <ionutx.chisanovici@intel.com>
+ AutomatedBy: Daniel Istrate <daniel.alexandrux.istrate@intel.com>
+ """
+
+ features = 'EXTRA_IMAGE_FEATURES = "ssh-server-openssh empty-root-password allow-empty-password allow-root-login"\n'
+ features += 'INHERIT += "extrausers"\n'
+ features += 'EXTRA_USERS_PARAMS = "useradd -p \'\' {}; usermod -s /bin/sh {};"'.format(self.test_user, self.test_user)
+ self.write_config(features)
+
+ # Build a core-image-minimal
+ bitbake('core-image-minimal')
+
+ with runqemu("core-image-minimal") as qemu:
+ # Attempt to ssh with each user into qemu with empty password
+ for user in [self.root_user, self.test_user]:
+ ssh = SSHControl(ip=qemu.ip, logfile=qemu.sshlog, user=user)
+ status, output = ssh.run("true")
+ self.assertEqual(status, 0, 'ssh to user %s failed with %s' % (user, output))
+
+ @OETestTag("runqemu")
+ def test_all_users_can_connect_via_ssh_without_password(self):
+ """
+ Summary: Check if all users can connect via ssh without password
+ Expected: 1. Connection to the image via ssh using root user without providing a password should NOT be allowed.
+ 2. Connection to the image via ssh using tester user without providing a password should be allowed.
+ Product: oe-core
+ Author: Ionut Chisanovici <ionutx.chisanovici@intel.com>
+ AutomatedBy: Daniel Istrate <daniel.alexandrux.istrate@intel.com>
+ """
+
+ features = 'EXTRA_IMAGE_FEATURES = "ssh-server-openssh allow-empty-password allow-root-login"\n'
+ features += 'INHERIT += "extrausers"\n'
+ features += 'EXTRA_USERS_PARAMS = "useradd -p \'\' {}; usermod -s /bin/sh {};"'.format(self.test_user, self.test_user)
+ self.write_config(features)
+
+ # Build a core-image-minimal
+ bitbake('core-image-minimal')
+
+ with runqemu("core-image-minimal") as qemu:
+ # Attempt to ssh with each user into qemu with empty password
+ for user in [self.root_user, self.test_user]:
+ ssh = SSHControl(ip=qemu.ip, logfile=qemu.sshlog, user=user)
+ status, output = ssh.run("true")
+ if user == 'root':
+ self.assertNotEqual(status, 0, 'ssh to user root was allowed when it should not have been')
+ else:
+ self.assertEqual(status, 0, 'ssh to user tester failed with %s' % output)
+
+
+ def test_wayland_support_in_image(self):
+ """
+ Summary: Check Wayland support in image
+ Expected: 1. Wayland image can be build
+ 2. Wayland feature can be installed
+ Product: oe-core
+ Author: Ionut Chisanovici <ionutx.chisanovici@intel.com>
+ AutomatedBy: Daniel Istrate <daniel.alexandrux.istrate@intel.com>
+ """
+
+ distro_features = get_bb_var('DISTRO_FEATURES')
+ if not ('opengl' in distro_features and 'wayland' in distro_features):
+ self.skipTest('neither opengl nor wayland present on DISTRO_FEATURES so core-image-weston cannot be built')
+
+ # Build a core-image-weston
+ bitbake('core-image-weston')
+
+ def test_bmap(self):
+ """
+ Summary: Check bmap support
+ Expected: 1. core-image-minimal can be build with bmap support
+ 2. core-image-minimal is sparse
+ Product: oe-core
+ Author: Ed Bartosh <ed.bartosh@linux.intel.com>
+ """
+
+ features = 'IMAGE_FSTYPES += " ext4 ext4.bmap ext4.bmap.gz"'
+ self.write_config(features)
+
+ image_name = 'core-image-minimal'
+ bitbake(image_name)
+
+ deploy_dir_image = get_bb_var('DEPLOY_DIR_IMAGE')
+ link_name = get_bb_var('IMAGE_LINK_NAME', image_name)
+ image_path = os.path.join(deploy_dir_image, "%s.ext4" % link_name)
+ bmap_path = "%s.bmap" % image_path
+ gzip_path = "%s.gz" % bmap_path
+
+ # check if result image, bmap and bmap.gz files are in deploy directory
+ self.assertTrue(os.path.exists(image_path))
+ self.assertTrue(os.path.exists(bmap_path))
+ self.assertTrue(os.path.exists(gzip_path))
+
+ # check if result image is sparse
+ image_stat = os.stat(image_path)
+ self.assertGreater(image_stat.st_size, image_stat.st_blocks * 512)
+
+ # check if the resulting gzip is valid
+ self.assertTrue(runCmd('gzip -t %s' % gzip_path))
+
+ def test_hypervisor_fmts(self):
+ """
+ Summary: Check various hypervisor formats
+ Expected: 1. core-image-minimal can be built with vmdk, vdi and
+ qcow2 support.
+ 2. qemu-img says each image has the expected format
+ Product: oe-core
+ Author: Tom Rini <trini@konsulko.com>
+ """
+
+ img_types = [ 'vmdk', 'vdi', 'qcow2' ]
+ features = ""
+ for itype in img_types:
+ features += 'IMAGE_FSTYPES += "ext4.%s"\n' % itype
+ self.write_config(features)
+
+ image_name = 'core-image-minimal'
+ bitbake(image_name)
+
+ deploy_dir_image = get_bb_var('DEPLOY_DIR_IMAGE')
+ link_name = get_bb_var('IMAGE_LINK_NAME', image_name)
+ for itype in img_types:
+ image_path = os.path.join(deploy_dir_image, "%s.ext4.%s" %
+ (link_name, itype))
+
+ # check if result image file is in deploy directory
+ self.assertTrue(os.path.exists(image_path))
+
+ # check if result image is vmdk
+ sysroot = get_bb_var('STAGING_DIR_NATIVE', 'core-image-minimal')
+ result = runCmd('qemu-img info --output json %s' % image_path,
+ native_sysroot=sysroot)
+ try:
+ data = json.loads(result.output)
+ self.assertEqual(data.get('format'), itype,
+ msg="Unexpected format in '%s'" % (result.output))
+ except json.decoder.JSONDecodeError:
+ self.fail("Could not parse '%ss'" % result.output)
+
+ def test_long_chain_conversion(self):
+ """
+ Summary: Check for chaining many CONVERSION_CMDs together
+ Expected: 1. core-image-minimal can be built with
+ ext4.bmap.gz.bz2.zst.xz.u-boot and also create a
+ sha256sum
+ 2. The above image has a valid sha256sum
+ Product: oe-core
+ Author: Tom Rini <trini@konsulko.com>
+ """
+
+ conv = "ext4.bmap.gz.bz2.zst.xz.u-boot"
+ features = 'IMAGE_FSTYPES += "%s %s.sha256sum"' % (conv, conv)
+ self.write_config(features)
+
+ image_name = 'core-image-minimal'
+ bitbake(image_name)
+
+ deploy_dir_image = get_bb_var('DEPLOY_DIR_IMAGE')
+ link_name = get_bb_var('IMAGE_LINK_NAME', image_name)
+ image_path = os.path.join(deploy_dir_image, "%s.%s" %
+ (link_name, conv))
+
+ # check if resulting image is in the deploy directory
+ self.assertTrue(os.path.exists(image_path))
+ self.assertTrue(os.path.exists(image_path + ".sha256sum"))
+
+ # check if the resulting sha256sum agrees
+ self.assertTrue(runCmd('cd %s;sha256sum -c %s.%s.sha256sum' %
+ (deploy_dir_image, link_name, conv)))
+
+ def test_image_fstypes(self):
+ """
+ Summary: Check if image of supported image fstypes can be built
+ Expected: core-image-minimal can be built for various image types
+ Product: oe-core
+ Author: Ed Bartosh <ed.bartosh@linux.intel.com>
+ """
+ image_name = 'core-image-minimal'
+
+ all_image_types = set(get_bb_var("IMAGE_TYPES", image_name).split())
+ skip_image_types = set(('container', 'elf', 'f2fs', 'multiubi', 'tar.zst', 'wic.zst', 'squashfs-lzo'))
+ img_types = all_image_types - skip_image_types
+
+ config = """
+IMAGE_FSTYPES += "%s"
+WKS_FILE = "wictestdisk.wks"
+MKUBIFS_ARGS ?= "-m 2048 -e 129024 -c 2047"
+UBINIZE_ARGS ?= "-m 2048 -p 128KiB -s 512"
+""" % ' '.join(img_types)
+ self.write_config(config)
+
+ bitbake(image_name)
+
+ deploy_dir_image = get_bb_var('DEPLOY_DIR_IMAGE')
+ link_name = get_bb_var('IMAGE_LINK_NAME', image_name)
+ for itype in img_types:
+ image_path = os.path.join(deploy_dir_image, "%s.%s" % (link_name, itype))
+ # check if result image is in deploy directory
+ self.assertTrue(os.path.exists(image_path),
+ "%s image %s doesn't exist" % (itype, image_path))
+
+ def test_useradd_static(self):
+ config = """
+USERADDEXTENSION = "useradd-staticids"
+USERADD_ERROR_DYNAMIC = "skip"
+USERADD_UID_TABLES += "files/static-passwd"
+USERADD_GID_TABLES += "files/static-group"
+"""
+ self.write_config(config)
+ bitbake("core-image-base")
+
+ def test_no_busybox_base_utils(self):
+ config = """
+# Enable wayland
+DISTRO_FEATURES:append = " pam opengl wayland"
+
+# Switch to systemd
+DISTRO_FEATURES:append = " systemd"
+VIRTUAL-RUNTIME_init_manager = "systemd"
+VIRTUAL-RUNTIME_initscripts = ""
+VIRTUAL-RUNTIME_syslog = ""
+VIRTUAL-RUNTIME_login_manager = "shadow-base"
+DISTRO_FEATURES_BACKFILL_CONSIDERED = "sysvinit"
+
+# Replace busybox
+PREFERRED_PROVIDER_virtual/base-utils = "packagegroup-core-base-utils"
+VIRTUAL-RUNTIME_base-utils = "packagegroup-core-base-utils"
+VIRTUAL-RUNTIME_base-utils-hwclock = "util-linux-hwclock"
+VIRTUAL-RUNTIME_base-utils-syslog = ""
+
+# Skip busybox
+SKIP_RECIPE[busybox] = "Don't build this"
+"""
+ self.write_config(config)
+
+ bitbake("--graphviz core-image-weston")
+
+ def test_image_gen_debugfs(self):
+ """
+ Summary: Check debugfs generation
+ Expected: 1. core-image-minimal can be build with IMAGE_GEN_DEBUGFS variable set
+ 2. debug filesystem is created when variable set
+ 3. debug symbols available
+ Product: oe-core
+ Author: Humberto Ibarra <humberto.ibarra.lopez@intel.com>
+ Yeoh Ee Peng <ee.peng.yeoh@intel.com>
+ """
+
+ image_name = 'core-image-minimal'
+ features = 'IMAGE_GEN_DEBUGFS = "1"\n'
+ features += 'IMAGE_FSTYPES_DEBUGFS = "tar.bz2"\n'
+ self.write_config(features)
+
+ bitbake(image_name)
+ deploy_dir_image = get_bb_var('DEPLOY_DIR_IMAGE')
+ dbg_tar_file = os.path.join(deploy_dir_image, "*-dbg.rootfs.tar.bz2")
+ debug_files = glob.glob(dbg_tar_file)
+ self.assertNotEqual(len(debug_files), 0, 'debug filesystem not generated at %s' % dbg_tar_file)
+ result = runCmd('cd %s; tar xvf %s' % (deploy_dir_image, dbg_tar_file))
+ self.assertEqual(result.status, 0, msg='Failed to extract %s: %s' % (dbg_tar_file, result.output))
+ result = runCmd('find %s -name %s' % (deploy_dir_image, "udevadm"))
+ self.assertTrue("udevadm" in result.output, msg='Failed to find udevadm: %s' % result.output)
+ dbg_symbols_targets = result.output.splitlines()
+ self.assertTrue(dbg_symbols_targets, msg='Failed to split udevadm: %s' % dbg_symbols_targets)
+ for t in dbg_symbols_targets:
+ result = runCmd('objdump --syms %s | grep debug' % t)
+ self.assertTrue("debug" in result.output, msg='Failed to find debug symbol: %s' % result.output)
+
+ def test_empty_image(self):
+ """Test creation of image with no packages"""
+ bitbake('test-empty-image')
+ res_dir = get_bb_var('DEPLOY_DIR_IMAGE')
+ images = os.path.join(res_dir, "test-empty-image-*.manifest")
+ result = glob.glob(images)
+ with open(result[1],"r") as f:
+ self.assertEqual(len(f.read().strip()),0)
diff --git a/meta/lib/oeqa/selftest/cases/incompatible_lic.py b/meta/lib/oeqa/selftest/cases/incompatible_lic.py
new file mode 100644
index 0000000000..4edf60fc55
--- /dev/null
+++ b/meta/lib/oeqa/selftest/cases/incompatible_lic.py
@@ -0,0 +1,162 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+from oeqa.selftest.case import OESelftestTestCase
+from oeqa.utils.commands import bitbake
+
+class IncompatibleLicenseTestObsolete(OESelftestTestCase):
+
+ def lic_test(self, pn, pn_lic, lic, error_msg=None):
+ if not error_msg:
+ error_msg = 'ERROR: Nothing PROVIDES \'%s\'\n%s was skipped: it has incompatible license(s): %s' % (pn, pn, pn_lic)
+
+ self.write_config("INCOMPATIBLE_LICENSE += \"%s\"" % (lic))
+
+ result = bitbake('%s --dry-run' % (pn), ignore_status=True)
+ if error_msg not in result.output:
+ raise AssertionError(result.output)
+
+ # Verify that a package with an SPDX license cannot be built when
+ # INCOMPATIBLE_LICENSE contains an alias (in SPDXLICENSEMAP) of this SPDX
+ # license
+ def test_incompatible_alias_spdx_license(self):
+ self.lic_test('incompatible-license', 'GPL-3.0-only', 'GPLv3', "is an obsolete license, please use an SPDX reference in INCOMPATIBLE_LICENSE")
+
+ # Verify that a package with an SPDX license cannot be built when
+ # INCOMPATIBLE_LICENSE contains a wildcarded alias license matching this
+ # SPDX license
+ def test_incompatible_alias_spdx_license_wildcard(self):
+ self.lic_test('incompatible-license', 'GPL-3.0-only', '*GPLv3', "*GPLv3 is an invalid license wildcard entry")
+
+ # Verify that a package with an alias (from SPDXLICENSEMAP) to an SPDX
+ # license cannot be built when INCOMPATIBLE_LICENSE contains this alias
+ def test_incompatible_alias_spdx_license_alias(self):
+ self.lic_test('incompatible-license-alias', 'GPL-3.0-only', 'GPLv3', "is an obsolete license, please use an SPDX reference in INCOMPATIBLE_LICENSE")
+
+ # Verify that a package with an alias (from SPDXLICENSEMAP) to an SPDX
+ # license cannot be built when INCOMPATIBLE_LICENSE contains a wildcarded
+ # license matching this SPDX license
+ def test_incompatible_spdx_license_alias_wildcard(self):
+ self.lic_test('incompatible-license-alias', 'GPL-3.0-only', '*GPL-3.0', "*GPL-3.0 is an invalid license wildcard entry")
+
+ # Verify that a package with an alias (from SPDXLICENSEMAP) to an SPDX
+ # license cannot be built when INCOMPATIBLE_LICENSE contains a wildcarded
+ # alias license matching the SPDX license
+ def test_incompatible_alias_spdx_license_alias_wildcard(self):
+ self.lic_test('incompatible-license-alias', 'GPL-3.0-only', '*GPLv3', "*GPLv3 is an invalid license wildcard entry")
+
+
+ # Verify that a package with multiple SPDX licenses cannot be built when
+ # INCOMPATIBLE_LICENSE contains a wildcard to some of them
+ def test_incompatible_spdx_licenses_wildcard(self):
+ self.lic_test('incompatible-licenses', 'GPL-3.0-only LGPL-3.0-only', '*GPL-3.0-only', "*GPL-3.0-only is an invalid license wildcard entry")
+
+
+ # Verify that a package with multiple SPDX licenses cannot be built when
+ # INCOMPATIBLE_LICENSE contains a wildcard matching all licenses
+ def test_incompatible_all_licenses_wildcard(self):
+ self.lic_test('incompatible-licenses', 'GPL-2.0-only GPL-3.0-only LGPL-3.0-only', '*', "* is an invalid license wildcard entry")
+
+class IncompatibleLicenseTests(OESelftestTestCase):
+
+ def lic_test(self, pn, pn_lic, lic):
+ error_msg = 'ERROR: Nothing PROVIDES \'%s\'\n%s was skipped: it has incompatible license(s): %s' % (pn, pn, pn_lic)
+
+ self.write_config("INCOMPATIBLE_LICENSE += \"%s\"" % (lic))
+
+ result = bitbake('%s --dry-run' % (pn), ignore_status=True)
+ if error_msg not in result.output:
+ raise AssertionError(result.output)
+
+ # Verify that a package with an SPDX license cannot be built when
+ # INCOMPATIBLE_LICENSE contains this SPDX license
+ def test_incompatible_spdx_license(self):
+ self.lic_test('incompatible-license', 'GPL-3.0-only', 'GPL-3.0-only')
+
+ # Verify that a package with an SPDX license cannot be built when
+ # INCOMPATIBLE_LICENSE contains a wildcarded license matching this SPDX
+ # license
+ def test_incompatible_spdx_license_wildcard(self):
+ self.lic_test('incompatible-license', 'GPL-3.0-only', 'GPL-3.0*')
+
+ # Verify that a package with an alias (from SPDXLICENSEMAP) to an SPDX
+ # license cannot be built when INCOMPATIBLE_LICENSE contains this SPDX
+ # license
+ def test_incompatible_spdx_license_alias(self):
+ self.lic_test('incompatible-license-alias', 'GPL-3.0-only', 'GPL-3.0-only')
+
+ # Verify that a package with multiple SPDX licenses cannot be built when
+ # INCOMPATIBLE_LICENSE contains some of them
+ def test_incompatible_spdx_licenses(self):
+ self.lic_test('incompatible-licenses', 'GPL-3.0-only LGPL-3.0-only', 'GPL-3.0-only LGPL-3.0-only')
+
+ # Verify that a package with a non-SPDX license cannot be built when
+ # INCOMPATIBLE_LICENSE contains this license
+ def test_incompatible_nonspdx_license(self):
+ self.lic_test('incompatible-nonspdx-license', 'FooLicense', 'FooLicense')
+
+class IncompatibleLicensePerImageTests(OESelftestTestCase):
+ def default_config(self):
+ return """
+IMAGE_INSTALL:append = " bash"
+INCOMPATIBLE_LICENSE:pn-core-image-minimal = "GPL-3.0* LGPL-3.0*"
+"""
+
+ def test_bash_default(self):
+ self.write_config(self.default_config())
+ error_msg = "ERROR: core-image-minimal-1.0-r0 do_rootfs: Package bash cannot be installed into the image because it has incompatible license(s): GPL-3.0-or-later"
+
+ result = bitbake('core-image-minimal', ignore_status=True)
+ if error_msg not in result.output:
+ raise AssertionError(result.output)
+
+ def test_bash_and_license(self):
+ self.write_config(self.default_config() + '\nLICENSE:append:pn-bash = " & SomeLicense"')
+ error_msg = "ERROR: core-image-minimal-1.0-r0 do_rootfs: Package bash cannot be installed into the image because it has incompatible license(s): GPL-3.0-or-later"
+
+ result = bitbake('core-image-minimal', ignore_status=True)
+ if error_msg not in result.output:
+ raise AssertionError(result.output)
+
+ def test_bash_or_license(self):
+ self.write_config(self.default_config() + '\nLICENSE:append:pn-bash = " | SomeLicense"')
+
+ bitbake('core-image-minimal')
+
+ def test_bash_license_exceptions(self):
+ self.write_config(self.default_config() + '\nINCOMPATIBLE_LICENSE_EXCEPTIONS:pn-core-image-minimal = "bash:GPL-3.0-or-later"')
+
+ bitbake('core-image-minimal')
+
+class NoGPL3InImagesTests(OESelftestTestCase):
+ def test_core_image_minimal(self):
+ self.write_config("""
+INCOMPATIBLE_LICENSE:pn-core-image-minimal = "GPL-3.0* LGPL-3.0*"
+""")
+ bitbake('core-image-minimal')
+
+ def test_core_image_full_cmdline_weston(self):
+ self.write_config("""
+IMAGE_CLASSES += "testimage"
+INCOMPATIBLE_LICENSE:pn-core-image-full-cmdline = "GPL-3.0* LGPL-3.0*"
+INCOMPATIBLE_LICENSE:pn-core-image-weston = "GPL-3.0* LGPL-3.0*"
+# Settings for full-cmdline
+RDEPENDS:packagegroup-core-full-cmdline-utils:remove = "bash bc coreutils cpio ed findutils gawk grep mc mc-fish mc-helpers mc-helpers-perl sed tar time"
+RDEPENDS:packagegroup-core-full-cmdline-dev-utils:remove = "diffutils m4 make patch"
+RDEPENDS:packagegroup-core-full-cmdline-multiuser:remove = "gzip"
+# Settings for weston
+# direct gpl3 dependencies
+RRECOMMENDS:packagegroup-base-vfat:remove = "dosfstools"
+PACKAGECONFIG:remove:pn-bluez5 = "readline"
+# dnf pulls in gpg which is gpl3; it also pulls in python3-rpm which pulls in rpm-build which pulls in bash
+# so install rpm but not dnf
+IMAGE_FEATURES:remove:pn-core-image-weston = "package-management"
+CORE_IMAGE_EXTRA_INSTALL:pn-core-image-weston += "rpm"
+# matchbox-terminal depends on vte, which is gpl3
+CORE_IMAGE_BASE_INSTALL:remove:pn-core-image-weston = "matchbox-terminal"
+""")
+ bitbake('core-image-full-cmdline core-image-weston')
+ bitbake('-c testimage core-image-full-cmdline core-image-weston')
+
diff --git a/meta/lib/oeqa/selftest/cases/intercept.py b/meta/lib/oeqa/selftest/cases/intercept.py
new file mode 100644
index 0000000000..12583c3099
--- /dev/null
+++ b/meta/lib/oeqa/selftest/cases/intercept.py
@@ -0,0 +1,21 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
+from oeqa.selftest.case import OESelftestTestCase
+from oeqa.utils.commands import bitbake
+
+class GitCheck(OESelftestTestCase):
+ def test_git_intercept(self):
+ """
+ Git binaries with CVE-2022-24765 fixed will refuse to operate on a
+ repository which is owned by a different user. This breaks our
+ do_install task as that runs inside pseudo, so the git repository is
+ owned by the build user but git is running as (fake)root.
+
+ We have an intercept which disables pseudo, so verify that it works.
+ """
+ bitbake("git-submodule-test -c test_git_as_user")
+ bitbake("git-submodule-test -c test_git_as_root")
diff --git a/meta/lib/oeqa/selftest/cases/kerneldevelopment.py b/meta/lib/oeqa/selftest/cases/kerneldevelopment.py
new file mode 100644
index 0000000000..4325f38598
--- /dev/null
+++ b/meta/lib/oeqa/selftest/cases/kerneldevelopment.py
@@ -0,0 +1,73 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
+import os
+from oeqa.selftest.case import OESelftestTestCase
+from oeqa.utils.commands import runCmd, get_bb_var
+from oeqa.utils.git import GitRepo
+
+class KernelDev(OESelftestTestCase):
+
+ @classmethod
+ def setUpClass(cls):
+ super(KernelDev, cls).setUpClass()
+ # Create the recipe directory structure inside the created layer
+ cls.layername = 'meta-kerneltest'
+ runCmd('bitbake-layers create-layer %s' % cls.layername)
+ runCmd('mkdir -p %s/recipes-kernel/linux/linux-yocto' % cls.layername)
+ cls.recipes_linuxyocto_dir = os.path.join \
+ (cls.builddir, cls.layername, 'recipes-kernel', 'linux', 'linux-yocto')
+ cls.recipeskernel_dir = os.path.dirname(cls.recipes_linuxyocto_dir)
+ runCmd('bitbake-layers add-layer %s' % cls.layername)
+
+ @classmethod
+ def tearDownClass(cls):
+ runCmd('bitbake-layers remove-layer %s' % cls.layername, ignore_status=True)
+ runCmd('rm -rf %s' % cls.layername)
+ super(KernelDev, cls).tearDownClass()
+
+ def setUp(self):
+ super(KernelDev, self).setUp()
+ self.set_machine_config('MACHINE = "qemux86-64"\n')
+
+ def test_apply_patches(self):
+ """
+ Summary: Able to apply a single patch to the Linux kernel source
+ Expected: The README file should exist and the patch changes should be
+ displayed at the end of the file.
+ Product: Kernel Development
+ Author: Yeoh Ee Peng <ee.peng.yeoh@intel.com>
+ AutomatedBy: Mazliana Mohamad <mazliana.mohamad@intel.com>
+ """
+ runCmd('bitbake virtual/kernel -c patch')
+ kernel_source = get_bb_var('STAGING_KERNEL_DIR')
+ readme = os.path.join(kernel_source, 'README')
+
+ # This test step adds modified file 'README' to git and creates a
+ # patch file '0001-KERNEL_DEV_TEST_CASE.patch' at the same location as file
+ patch_content = 'This is a test to apply a patch to the kernel'
+ with open(readme, 'a+') as f:
+ f.write(patch_content)
+ repo = GitRepo('%s' % kernel_source, is_topdir=True)
+ repo.run_cmd('add %s' % readme)
+ repo.run_cmd(['commit', '-m', 'KERNEL_DEV_TEST_CASE'])
+ repo.run_cmd(['format-patch', '-1'])
+ patch_name = '0001-KERNEL_DEV_TEST_CASE.patch'
+ patchpath = os.path.join(kernel_source, patch_name)
+ runCmd('mv %s %s' % (patchpath, self.recipes_linuxyocto_dir))
+ runCmd('rm %s ' % readme)
+ self.assertFalse(os.path.exists(readme))
+
+ recipe_append = os.path.join(self.recipeskernel_dir, 'linux-yocto_%.bbappend')
+ with open(recipe_append, 'w+') as fh:
+ fh.write('SRC_URI += "file://%s"\n' % patch_name)
+ fh.write('FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:"')
+
+ runCmd('bitbake virtual/kernel -c clean')
+ runCmd('bitbake virtual/kernel -c patch')
+ self.assertTrue(os.path.exists(readme))
+ result = runCmd('tail -n 1 %s' % readme)
+ self.assertEqual(result.output, patch_content)
diff --git a/meta/lib/oeqa/selftest/layerappend.py b/meta/lib/oeqa/selftest/cases/layerappend.py
index 4de5034a94..379ed589ad 100644
--- a/meta/lib/oeqa/selftest/layerappend.py
+++ b/meta/lib/oeqa/selftest/cases/layerappend.py
@@ -1,15 +1,16 @@
-import unittest
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
import os
-import logging
-import re
-from oeqa.selftest.base import oeSelfTest
-from oeqa.selftest.buildhistory import BuildhistoryBase
-from oeqa.utils.commands import runCmd, bitbake, get_bb_var
+from oeqa.selftest.case import OESelftestTestCase
+from oeqa.utils.commands import bitbake, get_bb_var
import oeqa.utils.ftools as ftools
-from oeqa.utils.decorators import testcase
-class LayerAppendTests(oeSelfTest):
+class LayerAppendTests(OESelftestTestCase):
layerconf = """
# We have a conf and classes directory, append to BBPATH
BBPATH .= ":${LAYERDIR}"
@@ -31,31 +32,31 @@ python do_build() {
addtask build
"""
append = """
-FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
+FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:"
-SRC_URI_append = " file://appendtest.txt"
+SRC_URI:append = " file://appendtest.txt"
-sysroot_stage_all_append() {
+sysroot_stage_all:append() {
install -m 644 ${WORKDIR}/appendtest.txt ${SYSROOT_DESTDIR}/
}
"""
append2 = """
-FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
+FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:"
-SRC_URI_append += "file://appendtest.txt"
+SRC_URI:append = " file://appendtest.txt"
"""
layerappend = ''
def tearDownLocal(self):
if self.layerappend:
ftools.remove_from_file(self.builddir + "/conf/bblayers.conf", self.layerappend)
+ super(LayerAppendTests, self).tearDownLocal()
- @testcase(1196)
def test_layer_appends(self):
corebase = get_bb_var("COREBASE")
- stagingdir = get_bb_var("STAGING_DIR_TARGET")
+
for l in ["0", "1", "2"]:
layer = os.path.join(corebase, "meta-layertest" + l)
self.assertFalse(os.path.exists(layer))
@@ -83,6 +84,7 @@ SRC_URI_append += "file://appendtest.txt"
self.layerappend = "BBLAYERS += \"{0}/meta-layertest0 {0}/meta-layertest1 {0}/meta-layertest2\"".format(corebase)
ftools.append_file(self.builddir + "/conf/bblayers.conf", self.layerappend)
+ stagingdir = get_bb_var("SYSROOT_DESTDIR", "layerappendtest")
bitbake("layerappendtest")
data = ftools.read_file(stagingdir + "/appendtest.txt")
self.assertEqual(data, "Layer 2 test")
@@ -95,5 +97,3 @@ SRC_URI_append += "file://appendtest.txt"
bitbake("layerappendtest")
data = ftools.read_file(stagingdir + "/appendtest.txt")
self.assertEqual(data, "Layer 2 test")
-
-
diff --git a/meta/lib/oeqa/selftest/cases/liboe.py b/meta/lib/oeqa/selftest/cases/liboe.py
new file mode 100644
index 0000000000..fab6929198
--- /dev/null
+++ b/meta/lib/oeqa/selftest/cases/liboe.py
@@ -0,0 +1,104 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
+from oeqa.selftest.case import OESelftestTestCase
+from oeqa.utils.commands import get_bb_var, get_bb_vars, bitbake, runCmd
+import oe.path
+import os
+
+class LibOE(OESelftestTestCase):
+
+ @classmethod
+ def setUpClass(cls):
+ super(LibOE, cls).setUpClass()
+ cls.tmp_dir = get_bb_var('TMPDIR')
+
+ def test_copy_tree_special(self):
+ """
+ Summary: oe.path.copytree() should copy files with special character
+ Expected: 'test file with sp£c!al @nd spaces' should exist in
+ copy destination
+ Product: OE-Core
+ Author: Joshua Lock <joshua.g.lock@intel.com>
+ """
+ testloc = oe.path.join(self.tmp_dir, 'liboetests')
+ src = oe.path.join(testloc, 'src')
+ dst = oe.path.join(testloc, 'dst')
+ bb.utils.mkdirhier(testloc)
+ bb.utils.mkdirhier(src)
+ testfilename = 'test file with sp£c!al @nd spaces'
+
+ # create the test file and copy it
+ open(oe.path.join(src, testfilename), 'w+b').close()
+ oe.path.copytree(src, dst)
+
+ # ensure path exists in dest
+ fileindst = os.path.isfile(oe.path.join(dst, testfilename))
+ self.assertTrue(fileindst, "File with spaces doesn't exist in dst")
+
+ oe.path.remove(testloc)
+
+ def test_copy_tree_xattr(self):
+ """
+ Summary: oe.path.copytree() should preserve xattr on copied files
+ Expected: testxattr file in destination should have user.oetest
+ extended attribute
+ Product: OE-Core
+ Author: Joshua Lock <joshua.g.lock@intel.com>
+ """
+ testloc = oe.path.join(self.tmp_dir, 'liboetests')
+ src = oe.path.join(testloc, 'src')
+ dst = oe.path.join(testloc, 'dst')
+ bb.utils.mkdirhier(testloc)
+ bb.utils.mkdirhier(src)
+ testfilename = 'testxattr'
+
+ # ensure we have setfattr available
+ bitbake("attr-native")
+
+ bb_vars = get_bb_vars(['SYSROOT_DESTDIR', 'bindir'], 'attr-native')
+ destdir = bb_vars['SYSROOT_DESTDIR']
+ bindir = bb_vars['bindir']
+ bindir = destdir + bindir
+
+ # create a file with xattr and copy it
+ open(oe.path.join(src, testfilename), 'w+b').close()
+ runCmd('%s/setfattr -n user.oetest -v "testing liboe" %s' % (bindir, oe.path.join(src, testfilename)))
+ oe.path.copytree(src, dst)
+
+ # ensure file in dest has user.oetest xattr
+ result = runCmd('%s/getfattr -n user.oetest %s' % (bindir, oe.path.join(dst, testfilename)))
+ self.assertIn('user.oetest="testing liboe"', result.output, 'Extended attribute not sert in dst')
+
+ oe.path.remove(testloc)
+
+ def test_copy_hardlink_tree_count(self):
+ """
+ Summary: oe.path.copyhardlinktree() shouldn't miss out files
+ Expected: src and dst should have the same number of files
+ Product: OE-Core
+ Author: Joshua Lock <joshua.g.lock@intel.com>
+ """
+ testloc = oe.path.join(self.tmp_dir, 'liboetests')
+ src = oe.path.join(testloc, 'src')
+ dst = oe.path.join(testloc, 'dst')
+ bb.utils.mkdirhier(testloc)
+ bb.utils.mkdirhier(src)
+ testfiles = ['foo', 'bar', '.baz', 'quux']
+
+ def touchfile(tf):
+ open(oe.path.join(src, tf), 'w+b').close()
+
+ for f in testfiles:
+ touchfile(f)
+
+ oe.path.copyhardlinktree(src, dst)
+
+ dstcnt = len(os.listdir(dst))
+ srccnt = len(os.listdir(src))
+ self.assertEquals(dstcnt, len(testfiles), "Number of files in dst (%s) differs from number of files in src(%s)." % (dstcnt, srccnt))
+
+ oe.path.remove(testloc)
diff --git a/meta/lib/oeqa/selftest/lic-checksum.py b/meta/lib/oeqa/selftest/cases/lic_checksum.py
index df44c97e80..2d0b805b90 100644
--- a/meta/lib/oeqa/selftest/lic-checksum.py
+++ b/meta/lib/oeqa/selftest/cases/lic_checksum.py
@@ -1,16 +1,38 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
import os
import tempfile
+import urllib
-from oeqa.selftest.base import oeSelfTest
+from oeqa.selftest.case import OESelftestTestCase
from oeqa.utils.commands import bitbake
-from oeqa.utils import CommandError
-from oeqa.utils.decorators import testcase
-class LicenseTests(oeSelfTest):
+class LicenseTests(OESelftestTestCase):
+
+ def test_checksum_with_space(self):
+ bitbake_cmd = '-c populate_lic emptytest'
+
+ lic_file, lic_path = tempfile.mkstemp(" -afterspace")
+ os.close(lic_file)
+ #self.track_for_cleanup(lic_path)
+
+ self.write_config("INHERIT:remove = \"report-error\"")
+
+ self.write_recipeinc('emptytest', """
+INHIBIT_DEFAULT_DEPS = "1"
+LIC_FILES_CHKSUM = "file://%s;md5=d41d8cd98f00b204e9800998ecf8427e"
+SRC_URI = "file://%s;md5=d41d8cd98f00b204e9800998ecf8427e"
+""" % (urllib.parse.quote(lic_path), urllib.parse.quote(lic_path)))
+ result = bitbake(bitbake_cmd)
+ self.delete_recipeinc('emptytest')
+
# Verify that changing a license file that has an absolute path causes
# the license qa to fail due to a mismatched md5sum.
- @testcase(1197)
def test_nonmatching_checksum(self):
bitbake_cmd = '-c populate_lic emptytest'
error_msg = 'emptytest: The new md5 checksum is 8d777f385d3dfec8815d20f7496026dc'
@@ -19,6 +41,8 @@ class LicenseTests(oeSelfTest):
os.close(lic_file)
self.track_for_cleanup(lic_path)
+ self.write_config("INHERIT:remove = \"report-error\"")
+
self.write_recipeinc('emptytest', """
INHIBIT_DEFAULT_DEPS = "1"
LIC_FILES_CHKSUM = "file://%s;md5=d41d8cd98f00b204e9800998ecf8427e"
@@ -30,5 +54,6 @@ SRC_URI = "file://%s;md5=d41d8cd98f00b204e9800998ecf8427e"
f.write("data")
result = bitbake(bitbake_cmd, ignore_status=True)
+ self.delete_recipeinc('emptytest')
if error_msg not in result.output:
raise AssertionError(result.output)
diff --git a/meta/lib/oeqa/selftest/cases/locales.py b/meta/lib/oeqa/selftest/cases/locales.py
new file mode 100644
index 0000000000..4ca8ffb7aa
--- /dev/null
+++ b/meta/lib/oeqa/selftest/cases/locales.py
@@ -0,0 +1,54 @@
+#
+# SPDX-License-Identifier: MIT
+#
+
+from oeqa.selftest.case import OESelftestTestCase
+from oeqa.core.decorator import OETestTag
+from oeqa.utils.commands import bitbake, runqemu
+
+class LocalesTest(OESelftestTestCase):
+
+ @OETestTag("runqemu")
+
+ def run_locales_test(self, binary_enabled):
+ features = []
+ features.append('EXTRA_IMAGE_FEATURES = "empty-root-password allow-empty-password allow-root-login"')
+ features.append('IMAGE_INSTALL:append = " glibc-utils localedef"')
+ features.append('GLIBC_GENERATE_LOCALES = "en_US.UTF-8 fr_FR.UTF-8"')
+ features.append('IMAGE_LINGUAS:append = " en-us fr-fr"')
+ if binary_enabled:
+ features.append('ENABLE_BINARY_LOCALE_GENERATION = "1"')
+ else:
+ features.append('ENABLE_BINARY_LOCALE_GENERATION = "0"')
+ self.write_config("\n".join(features))
+
+ # Build a core-image-minimal
+ bitbake('core-image-minimal')
+
+ with runqemu("core-image-minimal", ssh=False, runqemuparams='nographic') as qemu:
+ cmd = "locale -a"
+ status, output = qemu.run_serial(cmd)
+ # output must includes fr_FR or fr_FR.UTF-8
+ self.assertEqual(status, 1, msg='locale test command failed: output: %s' % output)
+ self.assertIn("fr_FR", output, msg='locale -a test failed: output: %s' % output)
+
+ cmd = "localedef --list-archive -v"
+ status, output = qemu.run_serial(cmd)
+ # output must includes fr_FR.utf8
+ self.assertEqual(status, 1, msg='localedef test command failed: output: %s' % output)
+ self.assertIn("fr_FR.utf8", output, msg='localedef test failed: output: %s' % output)
+
+ def test_locales_on(self):
+ """
+ Summary: Test the locales are generated
+ Expected: 1. Check the locale exist in the locale-archive
+ 2. Check the locale exist for the glibc
+ 3. Check the locale can be generated
+ Product: oe-core
+ Author: Louis Rannou <lrannou@baylibre.com>
+ AutomatedBy: Louis Rannou <lrannou@baylibre.com>
+ """
+ self.run_locales_test(True)
+
+ def test_locales_off(self):
+ self.run_locales_test(False)
diff --git a/meta/lib/oeqa/selftest/manifest.py b/meta/lib/oeqa/selftest/cases/manifest.py
index 44d0404c5d..07a6c80489 100644
--- a/meta/lib/oeqa/selftest/manifest.py
+++ b/meta/lib/oeqa/selftest/cases/manifest.py
@@ -1,9 +1,13 @@
-import unittest
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
import os
-from oeqa.selftest.base import oeSelfTest
+from oeqa.selftest.case import OESelftestTestCase
from oeqa.utils.commands import get_bb_var, bitbake
-from oeqa.utils.decorators import testcase
class ManifestEntry:
'''A manifest item of a collection able to list missing packages'''
@@ -11,7 +15,7 @@ class ManifestEntry:
self.file = entry
self.missing = []
-class VerifyManifest(oeSelfTest):
+class VerifyManifest(OESelftestTestCase):
'''Tests for the manifest files and contents of an image'''
@classmethod
@@ -21,14 +25,14 @@ class VerifyManifest(oeSelfTest):
with open(manifest, "r") as mfile:
for line in mfile:
manifest_entry = os.path.join(path, line.split()[0])
- self.log.debug("{}: looking for {}"\
+ self.logger.debug("{}: looking for {}"\
.format(self.classname, manifest_entry))
if not os.path.isfile(manifest_entry):
manifest_errors.append(manifest_entry)
- self.log.debug("{}: {} not found"\
+ self.logger.debug("{}: {} not found"\
.format(self.classname, manifest_entry))
except OSError as e:
- self.log.debug("{}: checking of {} failed"\
+ self.logger.debug("{}: checking of {} failed"\
.format(self.classname, manifest))
raise e
@@ -40,7 +44,7 @@ class VerifyManifest(oeSelfTest):
target == self.buildtarget if target == None else target
directory = get_bb_var(bb_var, target);
if not directory or not os.path.isdir(directory):
- self.log.debug("{}: {} points to {} when target = {}"\
+ self.logger.debug("{}: {} points to {} when target = {}"\
.format(self.classname, bb_var, directory, target))
raise OSError
return directory
@@ -48,18 +52,18 @@ class VerifyManifest(oeSelfTest):
@classmethod
def setUpClass(self):
+ super(VerifyManifest, self).setUpClass()
self.buildtarget = 'core-image-minimal'
self.classname = 'VerifyManifest'
- self.log.info("{}: doing bitbake {} as a prerequisite of the test"\
+ self.logger.info("{}: doing bitbake {} as a prerequisite of the test"\
.format(self.classname, self.buildtarget))
if bitbake(self.buildtarget).status:
- self.log.debug("{} Failed to setup {}"\
+ self.logger.debug("{} Failed to setup {}"\
.format(self.classname, self.buildtarget))
- unittest.SkipTest("{}: Cannot setup testing scenario"\
+ self.skipTest("{}: Cannot setup testing scenario"\
.format(self.classname))
- @testcase(1380)
def test_SDK_manifest_entries(self):
'''Verifying the SDK manifest entries exist, this may take a build'''
@@ -67,12 +71,12 @@ class VerifyManifest(oeSelfTest):
# to do an additional setup for the sdk
sdktask = '-c populate_sdk'
bbargs = sdktask + ' ' + self.buildtarget
- self.log.debug("{}: doing bitbake {} as a prerequisite of the test"\
+ self.logger.debug("{}: doing bitbake {} as a prerequisite of the test"\
.format(self.classname, bbargs))
if bitbake(bbargs).status:
- self.log.debug("{} Failed to bitbake {}"\
+ self.logger.debug("{} Failed to bitbake {}"\
.format(self.classname, bbargs))
- unittest.SkipTest("{}: Cannot setup testing scenario"\
+ self.skipTest("{}: Cannot setup testing scenario"\
.format(self.classname))
@@ -84,13 +88,11 @@ class VerifyManifest(oeSelfTest):
try:
mdir = self.get_dir_from_bb_var('SDK_DEPLOY', self.buildtarget)
for k in d_target.keys():
- mfilename[k] = "{}-toolchain-{}.{}.manifest".format(
- get_bb_var("SDK_NAME", self.buildtarget),
- get_bb_var("SDK_VERSION", self.buildtarget),
- k)
+ toolchain_outputname = get_bb_var('TOOLCHAIN_OUTPUTNAME', self.buildtarget)
+ mfilename[k] = "{}.{}.manifest".format(toolchain_outputname, k)
mpath[k] = os.path.join(mdir, mfilename[k])
if not os.path.isfile(mpath[k]):
- self.log.debug("{}: {} does not exist".format(
+ self.logger.debug("{}: {} does not exist".format(
self.classname, mpath[k]))
raise IOError
m_entry[k] = ManifestEntry(mpath[k])
@@ -100,11 +102,11 @@ class VerifyManifest(oeSelfTest):
reverse_dir[k] = os.path.join(pkgdata_dir[k],
'runtime-reverse')
if not os.path.exists(reverse_dir[k]):
- self.log.debug("{}: {} does not exist".format(
+ self.logger.debug("{}: {} does not exist".format(
self.classname, reverse_dir[k]))
raise IOError
except OSError:
- raise unittest.SkipTest("{}: Error in obtaining manifest dirs"\
+ raise self.skipTest("{}: Error in obtaining manifest dirs"\
.format(self.classname))
except IOError:
msg = "{}: Error cannot find manifests in the specified dir:\n{}"\
@@ -112,7 +114,7 @@ class VerifyManifest(oeSelfTest):
self.fail(msg)
for k in d_target.keys():
- self.log.debug("{}: Check manifest {}".format(
+ self.logger.debug("{}: Check manifest {}".format(
self.classname, m_entry[k].file))
m_entry[k].missing = self.check_manifest_entries(\
@@ -121,11 +123,10 @@ class VerifyManifest(oeSelfTest):
msg = '{}: {} Error has the following missing entries'\
.format(self.classname, m_entry[k].file)
logmsg = msg+':\n'+'\n'.join(m_entry[k].missing)
- self.log.debug(logmsg)
- self.log.info(msg)
+ self.logger.debug(logmsg)
+ self.logger.info(msg)
self.fail(logmsg)
- @testcase(1381)
def test_image_manifest_entries(self):
'''Verifying the image manifest entries exist'''
@@ -145,14 +146,14 @@ class VerifyManifest(oeSelfTest):
revdir = os.path.join(pkgdata_dir, 'runtime-reverse')
if not os.path.exists(revdir): raise IOError
except OSError:
- raise unittest.SkipTest("{}: Error in obtaining manifest dirs"\
+ raise self.skipTest("{}: Error in obtaining manifest dirs"\
.format(self.classname))
except IOError:
msg = "{}: Error cannot find manifests in dir:\n{}"\
.format(self.classname, mdir)
self.fail(msg)
- self.log.debug("{}: Check manifest {}"\
+ self.logger.debug("{}: Check manifest {}"\
.format(self.classname, m_entry.file))
m_entry.missing = self.check_manifest_entries(\
m_entry.file, revdir)
@@ -160,6 +161,6 @@ class VerifyManifest(oeSelfTest):
msg = '{}: {} Error has the following missing entries'\
.format(self.classname, m_entry.file)
logmsg = msg+':\n'+'\n'.join(m_entry.missing)
- self.log.debug(logmsg)
- self.log.info(msg)
+ self.logger.debug(logmsg)
+ self.logger.info(msg)
self.fail(logmsg)
diff --git a/meta/lib/oeqa/selftest/cases/meta_ide.py b/meta/lib/oeqa/selftest/cases/meta_ide.py
new file mode 100644
index 0000000000..bae98359e5
--- /dev/null
+++ b/meta/lib/oeqa/selftest/cases/meta_ide.py
@@ -0,0 +1,59 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
+from oeqa.selftest.case import OESelftestTestCase
+from oeqa.sdk.utils.sdkbuildproject import SDKBuildProject
+from oeqa.utils.commands import bitbake, get_bb_vars, runCmd
+from oeqa.core.decorator import OETestTag
+import tempfile
+import shutil
+
+@OETestTag("machine")
+class MetaIDE(OESelftestTestCase):
+
+ @classmethod
+ def setUpClass(cls):
+ super(MetaIDE, cls).setUpClass()
+ bitbake('meta-ide-support')
+ bitbake('build-sysroots')
+ bb_vars = get_bb_vars(['MULTIMACH_TARGET_SYS', 'DEPLOY_DIR_IMAGE', 'COREBASE'])
+ cls.environment_script = 'environment-setup-%s' % bb_vars['MULTIMACH_TARGET_SYS']
+ cls.deploydir = bb_vars['DEPLOY_DIR_IMAGE']
+ cls.environment_script_path = '%s/%s' % (cls.deploydir, cls.environment_script)
+ cls.corebasedir = bb_vars['COREBASE']
+ cls.tmpdir_metaideQA = tempfile.mkdtemp(prefix='metaide')
+
+ @classmethod
+ def tearDownClass(cls):
+ shutil.rmtree(cls.tmpdir_metaideQA, ignore_errors=True)
+ super(MetaIDE, cls).tearDownClass()
+
+ def test_meta_ide_had_installed_meta_ide_support(self):
+ self.assertExists(self.environment_script_path)
+
+ def test_meta_ide_can_compile_c_program(self):
+ runCmd('cp %s/test.c %s' % (self.tc.files_dir, self.tmpdir_metaideQA))
+ runCmd("cd %s; . %s; $CC test.c -lm" % (self.tmpdir_metaideQA, self.environment_script_path))
+ compiled_file = '%s/a.out' % self.tmpdir_metaideQA
+ self.assertExists(compiled_file)
+
+ def test_meta_ide_can_build_cpio_project(self):
+ dl_dir = self.td.get('DL_DIR', None)
+ self.project = SDKBuildProject(self.tmpdir_metaideQA + "/cpio/", self.environment_script_path,
+ "https://ftp.gnu.org/gnu/cpio/cpio-2.13.tar.gz",
+ self.tmpdir_metaideQA, self.td['DATETIME'], dl_dir=dl_dir)
+ self.project.download_archive()
+ self.assertEqual(self.project.run_configure('$CONFIGURE_FLAGS --disable-maintainer-mode','sed -i -e "/char \*program_name/d" src/global.c;'), 0,
+ msg="Running configure failed")
+ self.assertEqual(self.project.run_make(), 0,
+ msg="Running make failed")
+ self.assertEqual(self.project.run_install(), 0,
+ msg="Running make install failed")
+
+ def test_meta_ide_can_run_sdk_tests(self):
+ bitbake('-c populate_sysroot gtk+3')
+ bitbake('build-sysroots')
+ bitbake('-c testsdk meta-ide-support')
diff --git a/meta/lib/oeqa/selftest/cases/minidebuginfo.py b/meta/lib/oeqa/selftest/cases/minidebuginfo.py
new file mode 100644
index 0000000000..7947c3803c
--- /dev/null
+++ b/meta/lib/oeqa/selftest/cases/minidebuginfo.py
@@ -0,0 +1,43 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+import os
+import subprocess
+import tempfile
+import shutil
+
+from oeqa.selftest.case import OESelftestTestCase
+from oeqa.utils.commands import bitbake, get_bb_var, runCmd
+
+
+class Minidebuginfo(OESelftestTestCase):
+ def test_minidebuginfo(self):
+ target_sys = get_bb_var("TARGET_SYS")
+ binutils = "binutils-cross-{}".format(get_bb_var("TARGET_ARCH"))
+
+ self.write_config("""
+PACKAGE_MINIDEBUGINFO = "1"
+IMAGE_FSTYPES = "tar.bz2"
+""")
+ bitbake("core-image-minimal {}:do_addto_recipe_sysroot".format(binutils))
+
+ deploy_dir = get_bb_var("DEPLOY_DIR_IMAGE")
+ native_sysroot = get_bb_var("RECIPE_SYSROOT_NATIVE", binutils)
+ readelf = get_bb_var("READELF", "core-image-minimal")
+
+ # confirm that executables and shared libraries contain an ELF section
+ # ".gnu_debugdata" which stores minidebuginfo.
+ with tempfile.TemporaryDirectory(prefix = "unpackfs-") as unpackedfs:
+ filename = os.path.join(deploy_dir, "core-image-minimal-{}.tar.bz2".format(self.td["MACHINE"]))
+ shutil.unpack_archive(filename, unpackedfs)
+
+ r = runCmd([readelf, "-W", "-S", os.path.join(unpackedfs, "bin", "busybox")],
+ native_sysroot = native_sysroot, target_sys = target_sys)
+ self.assertIn(".gnu_debugdata", r.output)
+
+ r = runCmd([readelf, "-W", "-S", os.path.join(unpackedfs, "lib", "libc.so.6")],
+ native_sysroot = native_sysroot, target_sys = target_sys)
+ self.assertIn(".gnu_debugdata", r.output)
+
diff --git a/meta/lib/oeqa/selftest/cases/multiconfig.py b/meta/lib/oeqa/selftest/cases/multiconfig.py
new file mode 100644
index 0000000000..f509cbf607
--- /dev/null
+++ b/meta/lib/oeqa/selftest/cases/multiconfig.py
@@ -0,0 +1,87 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
+import os
+import textwrap
+from oeqa.selftest.case import OESelftestTestCase
+from oeqa.utils.commands import bitbake
+
+class MultiConfig(OESelftestTestCase):
+
+ def test_multiconfig(self):
+ """
+ Test that a simple multiconfig build works. This uses the mcextend class and the
+ multiconfig-image-packager test recipe to build a core-image-full-cmdline image which
+ contains a tiny core-image-minimal and a musl core-image-minimal, installed as packages.
+ """
+
+ config = """
+IMAGE_INSTALL:append:pn-core-image-full-cmdline = " multiconfig-image-packager-tiny multiconfig-image-packager-musl"
+BBMULTICONFIG = "tiny musl"
+"""
+ self.write_config(config)
+
+ muslconfig = """
+MACHINE = "qemux86-64"
+DISTRO = "poky"
+TCLIBC = "musl"
+TMPDIR = "${TOPDIR}/tmp-mc-musl"
+"""
+ self.write_config(muslconfig, 'musl')
+
+ tinyconfig = """
+MACHINE = "qemux86"
+DISTRO = "poky-tiny"
+TMPDIR = "${TOPDIR}/tmp-mc-tiny"
+"""
+ self.write_config(tinyconfig, 'tiny')
+
+ # Build a core-image-minimal
+ bitbake('core-image-full-cmdline')
+
+ def test_multiconfig_reparse(self):
+ """
+ Test that changes to a multiconfig conf file are correctly detected and
+ cause a reparse/rebuild of a recipe.
+ """
+ config = textwrap.dedent('''\
+ MCTESTVAR = "test"
+ BBMULTICONFIG = "test"
+ ''')
+ self.write_config(config)
+
+ testconfig = textwrap.dedent('''\
+ MCTESTVAR:append = "1"
+ ''')
+ self.write_config(testconfig, 'test')
+
+ # Check that the 1) the task executed and 2) that it output the correct
+ # value. Note "bitbake -e" is not used because it always reparses the
+ # recipe and we want to ensure that the automatic reparsing and parse
+ # caching is detected.
+ result = bitbake('mc:test:multiconfig-test-parse -c showvar')
+ self.assertIn('MCTESTVAR=test1', result.output.splitlines())
+
+ testconfig = textwrap.dedent('''\
+ MCTESTVAR:append = "2"
+ ''')
+ self.write_config(testconfig, 'test')
+
+ result = bitbake('mc:test:multiconfig-test-parse -c showvar')
+ self.assertIn('MCTESTVAR=test2', result.output.splitlines())
+
+ def test_multiconfig_inlayer(self):
+ """
+ Test that a multiconfig from meta-selftest works.
+ """
+
+ config = """
+BBMULTICONFIG = "muslmc"
+"""
+ self.write_config(config)
+
+ # Build a core-image-minimal, only dry run needed to check config is present
+ bitbake('mc:muslmc:bash -n')
diff --git a/meta/lib/oeqa/selftest/cases/newlib.py b/meta/lib/oeqa/selftest/cases/newlib.py
new file mode 100644
index 0000000000..fe57aa51f2
--- /dev/null
+++ b/meta/lib/oeqa/selftest/cases/newlib.py
@@ -0,0 +1,13 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
+from oeqa.selftest.case import OESelftestTestCase
+from oeqa.utils.commands import bitbake
+
+class NewlibTest(OESelftestTestCase):
+ def test_newlib(self):
+ self.write_config('TCLIBC = "newlib"')
+ bitbake("newlib libgloss")
diff --git a/meta/lib/oeqa/selftest/cases/oelib/__init__.py b/meta/lib/oeqa/selftest/cases/oelib/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/meta/lib/oeqa/selftest/cases/oelib/__init__.py
diff --git a/meta/lib/oeqa/selftest/cases/oelib/buildhistory.py b/meta/lib/oeqa/selftest/cases/oelib/buildhistory.py
new file mode 100644
index 0000000000..c3c15d83c0
--- /dev/null
+++ b/meta/lib/oeqa/selftest/cases/oelib/buildhistory.py
@@ -0,0 +1,147 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
+import os
+import sys
+from oeqa.selftest.case import OESelftestTestCase
+import tempfile
+import operator
+from oeqa.utils.commands import get_bb_var
+
+class TestBlobParsing(OESelftestTestCase):
+
+ def setUp(self):
+ self.repo_path = tempfile.mkdtemp(prefix='selftest-buildhistory',
+ dir=get_bb_var('TOPDIR'))
+
+ try:
+ from git import Repo
+ self.repo = Repo.init(self.repo_path)
+ except ImportError as e:
+ self.skipTest('Python module GitPython is not present (%s) (%s)' % (e, sys.path))
+
+ self.test_file = "test"
+ self.var_map = {}
+
+ def tearDown(self):
+ import shutil
+ shutil.rmtree(self.repo_path)
+
+ def commit_vars(self, to_add={}, to_remove = [], msg="A commit message"):
+ if len(to_add) == 0 and len(to_remove) == 0:
+ return
+
+ for k in to_remove:
+ self.var_map.pop(x,None)
+ for k in to_add:
+ self.var_map[k] = to_add[k]
+
+ with open(os.path.join(self.repo_path, self.test_file), 'w') as repo_file:
+ for k in self.var_map:
+ repo_file.write("%s = %s\n" % (k, self.var_map[k]))
+
+ self.repo.git.add("--all")
+ self.repo.git.commit(message=msg)
+
+ def test_blob_to_dict(self):
+ """
+ Test conversion of git blobs to dictionary
+ """
+ from oe.buildhistory_analysis import blob_to_dict
+ valuesmap = { "foo" : "1", "bar" : "2" }
+ self.commit_vars(to_add = valuesmap)
+
+ blob = self.repo.head.commit.tree.blobs[0]
+ self.assertEqual(valuesmap, blob_to_dict(blob),
+ "commit was not translated correctly to dictionary")
+
+ def test_compare_dict_blobs(self):
+ """
+ Test comparisson of dictionaries extracted from git blobs
+ """
+ from oe.buildhistory_analysis import compare_dict_blobs
+
+ changesmap = { "foo-2" : ("2", "8"), "bar" : ("","4"), "bar-2" : ("","5")}
+
+ self.commit_vars(to_add = { "foo" : "1", "foo-2" : "2", "foo-3" : "3" })
+ blob1 = self.repo.heads.master.commit.tree.blobs[0]
+
+ self.commit_vars(to_add = { "foo-2" : "8", "bar" : "4", "bar-2" : "5" })
+ blob2 = self.repo.heads.master.commit.tree.blobs[0]
+
+ change_records = compare_dict_blobs(os.path.join(self.repo_path, self.test_file),
+ blob1, blob2, False, False)
+
+ var_changes = { x.fieldname : (x.oldvalue, x.newvalue) for x in change_records}
+ self.assertEqual(changesmap, var_changes, "Changes not reported correctly")
+
+ def test_compare_dict_blobs_default(self):
+ """
+ Test default values for comparisson of git blob dictionaries
+ """
+ from oe.buildhistory_analysis import compare_dict_blobs
+ defaultmap = { x : ("default", "1") for x in ["PKG", "PKGE", "PKGV", "PKGR"]}
+
+ self.commit_vars(to_add = { "foo" : "1" })
+ blob1 = self.repo.heads.master.commit.tree.blobs[0]
+
+ self.commit_vars(to_add = { "PKG" : "1", "PKGE" : "1", "PKGV" : "1", "PKGR" : "1" })
+ blob2 = self.repo.heads.master.commit.tree.blobs[0]
+
+ change_records = compare_dict_blobs(os.path.join(self.repo_path, self.test_file),
+ blob1, blob2, False, False)
+
+ var_changes = {}
+ for x in change_records:
+ oldvalue = "default" if ("default" in x.oldvalue) else x.oldvalue
+ var_changes[x.fieldname] = (oldvalue, x.newvalue)
+
+ self.assertEqual(defaultmap, var_changes, "Defaults not set properly")
+
+class TestFileListCompare(OESelftestTestCase):
+
+ def test_compare_file_lists(self):
+ # Test that a directory tree that moves location such as /lib/modules/5.4.40-yocto-standard -> /lib/modules/5.4.43-yocto-standard
+ # is correctly identified as a move
+ from oe.buildhistory_analysis import compare_file_lists, FileChange
+
+ with open(self.tc.files_dir + "/buildhistory_filelist1.txt", "r") as f:
+ filelist1 = f.readlines()
+ with open(self.tc.files_dir + "/buildhistory_filelist2.txt", "r") as f:
+ filelist2 = f.readlines()
+
+ expectedResult = [
+ '/lib/libcap.so.2 changed symlink target from libcap.so.2.33 to libcap.so.2.34',
+ '/lib/libcap.so.2.33 moved to /lib/libcap.so.2.34',
+ '/lib/modules/5.4.40-yocto-standard moved to /lib/modules/5.4.43-yocto-standard',
+ '/lib/modules/5.4.43-yocto-standard/modules.builtin.alias.bin was added',
+ '/usr/bin/gawk-5.0.1 moved to /usr/bin/gawk-5.1.0',
+ '/usr/lib/libbtrfsutil.so changed symlink target from libbtrfsutil.so.1.1.1 to libbtrfsutil.so.1.2.0',
+ '/usr/lib/libbtrfsutil.so.1 changed symlink target from libbtrfsutil.so.1.1.1 to libbtrfsutil.so.1.2.0',
+ '/usr/lib/libbtrfsutil.so.1.1.1 moved to /usr/lib/libbtrfsutil.so.1.2.0',
+ '/usr/lib/libkmod.so changed symlink target from libkmod.so.2.3.4 to libkmod.so.2.3.5',
+ '/usr/lib/libkmod.so.2 changed symlink target from libkmod.so.2.3.4 to libkmod.so.2.3.5',
+ '/usr/lib/libkmod.so.2.3.4 moved to /usr/lib/libkmod.so.2.3.5',
+ '/usr/lib/libpixman-1.so.0 changed symlink target from libpixman-1.so.0.38.4 to libpixman-1.so.0.40.0',
+ '/usr/lib/libpixman-1.so.0.38.4 moved to /usr/lib/libpixman-1.so.0.40.0',
+ '/usr/lib/opkg/alternatives/rtcwake was added',
+ '/usr/lib/python3.8/site-packages/PyGObject-3.34.0.egg-info moved to /usr/lib/python3.8/site-packages/PyGObject-3.36.1.egg-info',
+ '/usr/lib/python3.8/site-packages/btrfsutil-1.1.1-py3.8.egg-info moved to /usr/lib/python3.8/site-packages/btrfsutil-1.2.0-py3.8.egg-info',
+ '/usr/lib/python3.8/site-packages/pycairo-1.19.0.egg-info moved to /usr/lib/python3.8/site-packages/pycairo-1.19.1.egg-info',
+ '/usr/sbin/rtcwake changed type from file to symlink',
+ '/usr/sbin/rtcwake changed permissions from rwxr-xr-x to rwxrwxrwx',
+ '/usr/sbin/rtcwake changed symlink target from None to /usr/sbin/rtcwake.util-linux',
+ '/usr/sbin/rtcwake.util-linux was added'
+ ]
+
+ result = compare_file_lists(filelist1, filelist2)
+ rendered = []
+ for entry in sorted(result, key=operator.attrgetter("path")):
+ rendered.append(str(entry))
+
+ self.maxDiff = None
+ self.assertCountEqual(rendered, expectedResult)
+
diff --git a/meta/lib/oeqa/selftest/cases/oelib/elf.py b/meta/lib/oeqa/selftest/cases/oelib/elf.py
new file mode 100644
index 0000000000..7bf550b6fd
--- /dev/null
+++ b/meta/lib/oeqa/selftest/cases/oelib/elf.py
@@ -0,0 +1,28 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
+from unittest.case import TestCase
+import oe.qa
+
+class TestElf(TestCase):
+ def test_machine_name(self):
+ """
+ Test elf_machine_to_string()
+ """
+ self.assertEqual(oe.qa.elf_machine_to_string(0x02), "SPARC")
+ self.assertEqual(oe.qa.elf_machine_to_string(0x03), "x86")
+ self.assertEqual(oe.qa.elf_machine_to_string(0x08), "MIPS")
+ self.assertEqual(oe.qa.elf_machine_to_string(0x14), "PowerPC")
+ self.assertEqual(oe.qa.elf_machine_to_string(0x28), "ARM")
+ self.assertEqual(oe.qa.elf_machine_to_string(0x2A), "SuperH")
+ self.assertEqual(oe.qa.elf_machine_to_string(0x32), "IA-64")
+ self.assertEqual(oe.qa.elf_machine_to_string(0x3E), "x86-64")
+ self.assertEqual(oe.qa.elf_machine_to_string(0xB7), "AArch64")
+ self.assertEqual(oe.qa.elf_machine_to_string(0xF7), "BPF")
+
+ self.assertEqual(oe.qa.elf_machine_to_string(0x00), "Unset")
+ self.assertEqual(oe.qa.elf_machine_to_string(0xDEADBEEF), "Unknown (3735928559)")
+ self.assertEqual(oe.qa.elf_machine_to_string("foobar"), "Unknown ('foobar')")
diff --git a/meta/lib/oeqa/selftest/cases/oelib/license.py b/meta/lib/oeqa/selftest/cases/oelib/license.py
new file mode 100644
index 0000000000..5eea12e761
--- /dev/null
+++ b/meta/lib/oeqa/selftest/cases/oelib/license.py
@@ -0,0 +1,105 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
+from unittest.case import TestCase
+import oe.license
+
+class SeenVisitor(oe.license.LicenseVisitor):
+ def __init__(self):
+ self.seen = []
+ oe.license.LicenseVisitor.__init__(self)
+
+ def visit_Str(self, node):
+ self.seen.append(node.s)
+
+class TestSingleLicense(TestCase):
+ licenses = [
+ "GPL-2.0-only",
+ "LGPL-2.0-only",
+ "Artistic-1.0",
+ "MIT",
+ "GPL-3.0-or-later",
+ "FOO_BAR",
+ ]
+ invalid_licenses = ["GPL/BSD"]
+
+ @staticmethod
+ def parse(licensestr):
+ visitor = SeenVisitor()
+ visitor.visit_string(licensestr)
+ return visitor.seen
+
+ def test_single_licenses(self):
+ for license in self.licenses:
+ licenses = self.parse(license)
+ self.assertListEqual(licenses, [license])
+
+ def test_invalid_licenses(self):
+ for license in self.invalid_licenses:
+ with self.assertRaises(oe.license.InvalidLicense) as cm:
+ self.parse(license)
+ self.assertEqual(cm.exception.license, license)
+
+class TestSimpleCombinations(TestCase):
+ tests = {
+ "FOO&BAR": ["FOO", "BAR"],
+ "BAZ & MOO": ["BAZ", "MOO"],
+ "ALPHA|BETA": ["ALPHA"],
+ "BAZ&MOO|FOO": ["FOO"],
+ "FOO&BAR|BAZ": ["FOO", "BAR"],
+ }
+ preferred = ["ALPHA", "FOO", "BAR"]
+
+ def test_tests(self):
+ def choose(a, b):
+ if all(lic in self.preferred for lic in b):
+ return b
+ else:
+ return a
+
+ for license, expected in self.tests.items():
+ licenses = oe.license.flattened_licenses(license, choose)
+ self.assertListEqual(licenses, expected)
+
+class TestComplexCombinations(TestSimpleCombinations):
+ tests = {
+ "FOO & (BAR | BAZ)&MOO": ["FOO", "BAR", "MOO"],
+ "(ALPHA|(BETA&THETA)|OMEGA)&DELTA": ["OMEGA", "DELTA"],
+ "((ALPHA|BETA)&FOO)|BAZ": ["BETA", "FOO"],
+ "(GPL-2.0-only|Proprietary)&BSD-4-clause&MIT": ["GPL-2.0-only", "BSD-4-clause", "MIT"],
+ }
+ preferred = ["BAR", "OMEGA", "BETA", "GPL-2.0-only"]
+
+class TestIsIncluded(TestCase):
+ tests = {
+ ("FOO | BAR", None, None):
+ [True, ["FOO"]],
+ ("FOO | BAR", None, "FOO"):
+ [True, ["BAR"]],
+ ("FOO | BAR", "BAR", None):
+ [True, ["BAR"]],
+ ("FOO | BAR & FOOBAR", "*BAR", None):
+ [True, ["BAR", "FOOBAR"]],
+ ("FOO | BAR & FOOBAR", None, "FOO*"):
+ [False, ["FOOBAR"]],
+ ("(FOO | BAR) & FOOBAR | BARFOO", None, "FOO"):
+ [True, ["BAR", "FOOBAR"]],
+ ("(FOO | BAR) & FOOBAR | BAZ & MOO & BARFOO", None, "FOO"):
+ [True, ["BAZ", "MOO", "BARFOO"]],
+ ("GPL-3.0-or-later & GPL-2.0-only & LGPL-2.1-only | Proprietary", None, None):
+ [True, ["GPL-3.0-or-later", "GPL-2.0-only", "LGPL-2.1-only"]],
+ ("GPL-3.0-or-later & GPL-2.0-only & LGPL-2.1-only | Proprietary", None, "GPL-3.0-or-later"):
+ [True, ["Proprietary"]],
+ ("GPL-3.0-or-later & GPL-2.0-only & LGPL-2.1-only | Proprietary", None, "GPL-3.0-or-later Proprietary"):
+ [False, ["GPL-3.0-or-later"]]
+ }
+
+ def test_tests(self):
+ for args, expected in self.tests.items():
+ is_included, licenses = oe.license.is_included(
+ args[0], (args[1] or '').split(), (args[2] or '').split())
+ self.assertEqual(is_included, expected[0])
+ self.assertListEqual(licenses, expected[1])
diff --git a/meta/lib/oe/tests/test_path.py b/meta/lib/oeqa/selftest/cases/oelib/path.py
index 44d068143e..b963e447e3 100644
--- a/meta/lib/oe/tests/test_path.py
+++ b/meta/lib/oeqa/selftest/cases/oelib/path.py
@@ -1,11 +1,17 @@
-import unittest
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
+from unittest.case import TestCase
import oe, oe.path
import tempfile
import os
import errno
import shutil
-class TestRealPath(unittest.TestCase):
+class TestRealPath(TestCase):
DIRS = [ "a", "b", "etc", "sbin", "usr", "usr/bin", "usr/binX", "usr/sbin", "usr/include", "usr/include/gdbm" ]
FILES = [ "etc/passwd", "b/file" ]
LINKS = [
@@ -38,13 +44,6 @@ class TestRealPath(unittest.TestCase):
( "b/test", errno.ENOENT ),
]
- def __del__(self):
- try:
- #os.system("tree -F %s" % self.tmpdir)
- shutil.rmtree(self.tmpdir)
- except:
- pass
-
def setUp(self):
self.tmpdir = tempfile.mkdtemp(prefix = "oe-test_path")
self.root = os.path.join(self.tmpdir, "R")
@@ -59,6 +58,9 @@ class TestRealPath(unittest.TestCase):
for l in self.LINKS:
os.symlink(l[1], os.path.join(self.root, l[0]))
+ def tearDown(self):
+ shutil.rmtree(self.tmpdir)
+
def __realpath(self, file, use_physdir, assume_dir = True):
return oe.path.realpath(os.path.join(self.root, file), self.root,
use_physdir, assume_dir = assume_dir)
diff --git a/meta/lib/oe/tests/test_types.py b/meta/lib/oeqa/selftest/cases/oelib/types.py
index 367cc30e45..58318b18b2 100644
--- a/meta/lib/oe/tests/test_types.py
+++ b/meta/lib/oeqa/selftest/cases/oelib/types.py
@@ -1,19 +1,13 @@
-import unittest
-from oe.maketype import create, factory
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
-class TestTypes(unittest.TestCase):
- def assertIsInstance(self, obj, cls):
- return self.assertTrue(isinstance(obj, cls))
+from unittest.case import TestCase
+from oe.maketype import create
- def assertIsNot(self, obj, other):
- return self.assertFalse(obj is other)
-
- def assertFactoryCreated(self, value, type, **flags):
- cls = factory(type)
- self.assertIsNot(cls, None)
- self.assertIsInstance(create(value, type, **flags), cls)
-
-class TestBooleanType(TestTypes):
+class TestBooleanType(TestCase):
def test_invalid(self):
self.assertRaises(ValueError, create, '', 'boolean')
self.assertRaises(ValueError, create, 'foo', 'boolean')
@@ -43,7 +37,7 @@ class TestBooleanType(TestTypes):
self.assertEqual(create('y', 'boolean'), True)
self.assertNotEqual(create('y', 'boolean'), False)
-class TestList(TestTypes):
+class TestList(TestCase):
def assertListEqual(self, value, valid, sep=None):
obj = create(value, 'list', separator=sep)
self.assertEqual(obj, valid)
diff --git a/meta/lib/oeqa/selftest/cases/oelib/utils.py b/meta/lib/oeqa/selftest/cases/oelib/utils.py
new file mode 100644
index 0000000000..0cb46425a0
--- /dev/null
+++ b/meta/lib/oeqa/selftest/cases/oelib/utils.py
@@ -0,0 +1,104 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
+import sys
+from unittest.case import TestCase
+from contextlib import contextmanager
+from io import StringIO
+from oe.utils import packages_filter_out_system, trim_version, multiprocess_launch
+
+class TestPackagesFilterOutSystem(TestCase):
+ def test_filter(self):
+ """
+ Test that oe.utils.packages_filter_out_system works.
+ """
+ try:
+ import bb
+ except ImportError:
+ self.skipTest("Cannot import bb")
+
+ d = bb.data_smart.DataSmart()
+ d.setVar("PN", "foo")
+
+ d.setVar("PACKAGES", "foo foo-doc foo-dev")
+ pkgs = packages_filter_out_system(d)
+ self.assertEqual(pkgs, [])
+
+ d.setVar("PACKAGES", "foo foo-doc foo-data foo-dev")
+ pkgs = packages_filter_out_system(d)
+ self.assertEqual(pkgs, ["foo-data"])
+
+ d.setVar("PACKAGES", "foo foo-locale-en-gb")
+ pkgs = packages_filter_out_system(d)
+ self.assertEqual(pkgs, [])
+
+ d.setVar("PACKAGES", "foo foo-data foo-locale-en-gb")
+ pkgs = packages_filter_out_system(d)
+ self.assertEqual(pkgs, ["foo-data"])
+
+
+class TestTrimVersion(TestCase):
+ def test_version_exception(self):
+ with self.assertRaises(TypeError):
+ trim_version(None, 2)
+ with self.assertRaises(TypeError):
+ trim_version((1, 2, 3), 2)
+
+ def test_num_exception(self):
+ with self.assertRaises(ValueError):
+ trim_version("1.2.3", 0)
+ with self.assertRaises(ValueError):
+ trim_version("1.2.3", -1)
+
+ def test_valid(self):
+ self.assertEqual(trim_version("1.2.3", 1), "1")
+ self.assertEqual(trim_version("1.2.3", 2), "1.2")
+ self.assertEqual(trim_version("1.2.3", 3), "1.2.3")
+ self.assertEqual(trim_version("1.2.3", 4), "1.2.3")
+
+
+class TestMultiprocessLaunch(TestCase):
+
+ def test_multiprocesslaunch(self):
+ import bb
+
+ def testfunction(item, d):
+ if item == "2":
+ raise KeyError("Invalid number %s" % item)
+ return "Found %s" % item
+
+ def dummyerror(msg):
+ print("ERROR: %s" % msg)
+ def dummyfatal(msg):
+ print("ERROR: %s" % msg)
+ raise bb.BBHandledException()
+
+ @contextmanager
+ def captured_output():
+ new_out, new_err = StringIO(), StringIO()
+ old_out, old_err = sys.stdout, sys.stderr
+ try:
+ sys.stdout, sys.stderr = new_out, new_err
+ yield sys.stdout, sys.stderr
+ finally:
+ sys.stdout, sys.stderr = old_out, old_err
+
+ d = bb.data_smart.DataSmart()
+ bb.error = dummyerror
+ bb.fatal = dummyfatal
+
+ # Assert the function returns the right results
+ result = multiprocess_launch(testfunction, ["3", "4", "5", "6"], d, extraargs=(d,))
+ self.assertIn("Found 3", result)
+ self.assertIn("Found 4", result)
+ self.assertIn("Found 5", result)
+ self.assertIn("Found 6", result)
+ self.assertEqual(len(result), 4)
+
+ # Assert the function prints exceptions
+ with captured_output() as (out, err):
+ self.assertRaises(bb.BBHandledException, multiprocess_launch, testfunction, ["1", "2", "3", "4", "5", "6"], d, extraargs=(d,))
+ self.assertIn("KeyError: 'Invalid number 2'", out.getvalue())
diff --git a/meta/lib/oeqa/selftest/cases/oescripts.py b/meta/lib/oeqa/selftest/cases/oescripts.py
new file mode 100644
index 0000000000..5b0691a9ff
--- /dev/null
+++ b/meta/lib/oeqa/selftest/cases/oescripts.py
@@ -0,0 +1,185 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
+import os
+import shutil
+import importlib
+import unittest
+from oeqa.selftest.case import OESelftestTestCase
+from oeqa.selftest.cases.buildhistory import BuildhistoryBase
+from oeqa.utils.commands import runCmd, bitbake, get_bb_var
+from oeqa.utils import CommandError
+
+class BuildhistoryDiffTests(BuildhistoryBase):
+
+ def test_buildhistory_diff(self):
+ target = 'xcursor-transparent-theme'
+ self.run_buildhistory_operation(target, target_config="PR = \"r1\"", change_bh_location=True)
+ self.run_buildhistory_operation(target, target_config="PR = \"r0\"", change_bh_location=False, expect_error=True)
+ result = runCmd("oe-pkgdata-util read-value PKGV %s" % target)
+ pkgv = result.output.rstrip()
+ result = runCmd("buildhistory-diff -p %s" % get_bb_var('BUILDHISTORY_DIR'))
+ expected_endlines = [
+ "xcursor-transparent-theme-dev: RRECOMMENDS: removed \"xcursor-transparent-theme (['= %s-r1'])\", added \"xcursor-transparent-theme (['= %s-r0'])\"" % (pkgv, pkgv),
+ "xcursor-transparent-theme-staticdev: RDEPENDS: removed \"xcursor-transparent-theme-dev (['= %s-r1'])\", added \"xcursor-transparent-theme-dev (['= %s-r0'])\"" % (pkgv, pkgv)
+ ]
+ for line in result.output.splitlines():
+ for el in expected_endlines:
+ if line.endswith(el):
+ expected_endlines.remove(el)
+ break
+ else:
+ self.fail('Unexpected line:\n%s\nExpected line endings:\n %s' % (line, '\n '.join(expected_endlines)))
+ if expected_endlines:
+ self.fail('Missing expected line endings:\n %s' % '\n '.join(expected_endlines))
+
+class OEScriptTests(OESelftestTestCase):
+ scripts_dir = os.path.join(get_bb_var('COREBASE'), 'scripts')
+
+@unittest.skipUnless(importlib.util.find_spec("cairo"), "Python cairo module is not present")
+class OEPybootchartguyTests(OEScriptTests):
+
+ @classmethod
+ def setUpClass(cls):
+ super(OEScriptTests, cls).setUpClass()
+ bitbake("core-image-minimal -c rootfs -f")
+ cls.tmpdir = get_bb_var('TMPDIR')
+ cls.buildstats = cls.tmpdir + "/buildstats/" + sorted(os.listdir(cls.tmpdir + "/buildstats"))[-1]
+
+ def test_pybootchartguy_help(self):
+ runCmd('%s/pybootchartgui/pybootchartgui.py --help' % self.scripts_dir)
+
+ def test_pybootchartguy_to_generate_build_png_output(self):
+ runCmd('%s/pybootchartgui/pybootchartgui.py %s -o %s/charts -f png' % (self.scripts_dir, self.buildstats, self.tmpdir))
+ self.assertTrue(os.path.exists(self.tmpdir + "/charts.png"))
+
+ def test_pybootchartguy_to_generate_build_svg_output(self):
+ runCmd('%s/pybootchartgui/pybootchartgui.py %s -o %s/charts -f svg' % (self.scripts_dir, self.buildstats, self.tmpdir))
+ self.assertTrue(os.path.exists(self.tmpdir + "/charts.svg"))
+
+ def test_pybootchartguy_to_generate_build_pdf_output(self):
+ runCmd('%s/pybootchartgui/pybootchartgui.py %s -o %s/charts -f pdf' % (self.scripts_dir, self.buildstats, self.tmpdir))
+ self.assertTrue(os.path.exists(self.tmpdir + "/charts.pdf"))
+
+
+class OEGitproxyTests(OEScriptTests):
+
+ def test_oegitproxy_help(self):
+ try:
+ res = runCmd('%s/oe-git-proxy --help' % self.scripts_dir, assert_error=False)
+ self.assertTrue(False)
+ except CommandError as e:
+ self.assertEqual(2, e.retcode)
+
+ def run_oegitproxy(self, custom_shell=None):
+ os.environ['SOCAT'] = shutil.which("echo")
+ os.environ['ALL_PROXY'] = "https://proxy.example.com:3128"
+ os.environ['NO_PROXY'] = "*.example.com,.no-proxy.org,192.168.42.0/24,127.*.*.*"
+
+ if custom_shell is None:
+ prefix = ''
+ else:
+ prefix = custom_shell + ' '
+
+ # outside, use the proxy
+ res = runCmd('%s%s/oe-git-proxy host.outside-example.com 9418' %
+ (prefix,self.scripts_dir))
+ self.assertIn('PROXY:', res.output)
+ # match with wildcard suffix
+ res = runCmd('%s%s/oe-git-proxy host.example.com 9418' %
+ (prefix, self.scripts_dir))
+ self.assertIn('TCP:', res.output)
+ # match just suffix
+ res = runCmd('%s%s/oe-git-proxy host.no-proxy.org 9418' %
+ (prefix, self.scripts_dir))
+ self.assertIn('TCP:', res.output)
+ # match IP subnet
+ res = runCmd('%s%s/oe-git-proxy 192.168.42.42 9418' %
+ (prefix, self.scripts_dir))
+ self.assertIn('TCP:', res.output)
+ # match IP wildcard
+ res = runCmd('%s%s/oe-git-proxy 127.1.2.3 9418' %
+ (prefix, self.scripts_dir))
+ self.assertIn('TCP:', res.output)
+
+ # test that * globbering is off
+ os.environ['NO_PROXY'] = "*"
+ res = runCmd('%s%s/oe-git-proxy host.example.com 9418' %
+ (prefix, self.scripts_dir))
+ self.assertIn('TCP:', res.output)
+
+ def test_oegitproxy_proxy(self):
+ self.run_oegitproxy()
+
+ def test_oegitproxy_proxy_dash(self):
+ dash = shutil.which("dash")
+ if dash is None:
+ self.skipTest("No \"dash\" found on test system.")
+ self.run_oegitproxy(custom_shell=dash)
+
+class OeRunNativeTest(OESelftestTestCase):
+ def test_oe_run_native(self):
+ bitbake("qemu-helper-native -c addto_recipe_sysroot")
+ result = runCmd("oe-run-native qemu-helper-native tunctl -h")
+ self.assertIn("Delete: tunctl -d device-name [-f tun-clone-device]", result.output)
+
+class OEListPackageconfigTests(OEScriptTests):
+ #oe-core.scripts.List_all_the_PACKAGECONFIG's_flags
+ def check_endlines(self, results, expected_endlines):
+ for line in results.output.splitlines():
+ for el in expected_endlines:
+ if line and line.split()[0] == el.split()[0] and \
+ ' '.join(sorted(el.split())) in ' '.join(sorted(line.split())):
+ expected_endlines.remove(el)
+ break
+
+ if expected_endlines:
+ self.fail('Missing expected listings:\n %s' % '\n '.join(expected_endlines))
+
+
+ #oe-core.scripts.List_all_the_PACKAGECONFIG's_flags
+ def test_packageconfig_flags_help(self):
+ runCmd('%s/contrib/list-packageconfig-flags.py -h' % self.scripts_dir)
+
+ def test_packageconfig_flags_default(self):
+ results = runCmd('%s/contrib/list-packageconfig-flags.py' % self.scripts_dir)
+ expected_endlines = []
+ expected_endlines.append("RECIPE NAME PACKAGECONFIG FLAGS")
+ expected_endlines.append("pinentry gtk2 ncurses qt secret")
+ expected_endlines.append("tar acl selinux")
+
+ self.check_endlines(results, expected_endlines)
+
+
+ def test_packageconfig_flags_option_flags(self):
+ results = runCmd('%s/contrib/list-packageconfig-flags.py -f' % self.scripts_dir)
+ expected_endlines = []
+ expected_endlines.append("PACKAGECONFIG FLAG RECIPE NAMES")
+ expected_endlines.append("qt nativesdk-pinentry pinentry pinentry-native")
+ expected_endlines.append("secret nativesdk-pinentry pinentry pinentry-native")
+
+ self.check_endlines(results, expected_endlines)
+
+ def test_packageconfig_flags_option_all(self):
+ results = runCmd('%s/contrib/list-packageconfig-flags.py -a' % self.scripts_dir)
+ expected_endlines = []
+ expected_endlines.append("pinentry-1.2.1")
+ expected_endlines.append("PACKAGECONFIG ncurses")
+ expected_endlines.append("PACKAGECONFIG[qt] --enable-pinentry-qt, --disable-pinentry-qt, qtbase-native qtbase")
+ expected_endlines.append("PACKAGECONFIG[gtk2] --enable-pinentry-gtk2, --disable-pinentry-gtk2, gtk+ glib-2.0")
+ expected_endlines.append("PACKAGECONFIG[ncurses] --enable-ncurses --with-ncurses-include-dir=${STAGING_INCDIR}, --disable-ncurses, ncurses")
+ expected_endlines.append("PACKAGECONFIG[secret] --enable-libsecret, --disable-libsecret, libsecret")
+
+ self.check_endlines(results, expected_endlines)
+
+ def test_packageconfig_flags_options_preferred_only(self):
+ results = runCmd('%s/contrib/list-packageconfig-flags.py -p' % self.scripts_dir)
+ expected_endlines = []
+ expected_endlines.append("RECIPE NAME PACKAGECONFIG FLAGS")
+ expected_endlines.append("pinentry gtk2 ncurses qt secret")
+
+ self.check_endlines(results, expected_endlines)
+
diff --git a/meta/lib/oeqa/selftest/cases/overlayfs.py b/meta/lib/oeqa/selftest/cases/overlayfs.py
new file mode 100644
index 0000000000..dfd9f1486d
--- /dev/null
+++ b/meta/lib/oeqa/selftest/cases/overlayfs.py
@@ -0,0 +1,488 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
+from oeqa.selftest.case import OESelftestTestCase
+from oeqa.utils.commands import bitbake, runqemu
+from oeqa.core.decorator import OETestTag
+from oeqa.core.decorator.data import skipIfNotMachine
+
+def getline_qemu(out, line):
+ for l in out.split('\n'):
+ if line in l:
+ return l
+
+def getline(res, line):
+ return getline_qemu(res.output, line)
+
+class OverlayFSTests(OESelftestTestCase):
+ """Overlayfs class usage tests"""
+
+ def add_overlay_conf_to_machine(self):
+ machine_inc = """
+OVERLAYFS_MOUNT_POINT[mnt-overlay] = "/mnt/overlay"
+"""
+ self.set_machine_config(machine_inc)
+
+ def test_distro_features_missing(self):
+ """
+ Summary: Check that required DISTRO_FEATURES are set
+ Expected: Fail when either systemd or overlayfs are not in DISTRO_FEATURES
+ Author: Vyacheslav Yurkov <uvv.mail@gmail.com>
+ """
+
+ config = """
+IMAGE_INSTALL:append = " overlayfs-user"
+"""
+ overlayfs_recipe_append = """
+inherit overlayfs
+"""
+ self.write_config(config)
+ self.add_overlay_conf_to_machine()
+ self.write_recipeinc('overlayfs-user', overlayfs_recipe_append)
+
+ res = bitbake('core-image-minimal', ignore_status=True)
+ line = getline(res, "overlayfs-user was skipped: missing required distro features")
+ self.assertTrue("overlayfs" in res.output, msg=res.output)
+ self.assertTrue("systemd" in res.output, msg=res.output)
+ self.assertTrue("ERROR: Required build target 'core-image-minimal' has no buildable providers." in res.output, msg=res.output)
+
+ def test_not_all_units_installed(self):
+ """
+ Summary: Test QA check that we have required mount units in the image
+ Expected: Fail because mount unit for overlay partition is not installed
+ Author: Vyacheslav Yurkov <uvv.mail@gmail.com>
+ """
+
+ config = """
+IMAGE_INSTALL:append = " overlayfs-user"
+DISTRO_FEATURES:append = " systemd overlayfs"
+"""
+
+ self.write_config(config)
+ self.add_overlay_conf_to_machine()
+
+ res = bitbake('core-image-minimal', ignore_status=True)
+ line = getline(res, " Mount path /mnt/overlay not found in fstab and unit mnt-overlay.mount not found in systemd unit directories")
+ self.assertTrue(line and line.startswith("WARNING:"), msg=res.output)
+ line = getline(res, "Not all mount paths and units are installed in the image")
+ self.assertTrue(line and line.startswith("ERROR:"), msg=res.output)
+
+ def test_not_all_units_installed_but_qa_skipped(self):
+ """
+ Summary: Test skipping the QA check
+ Expected: Image is created successfully
+ Author: Claudius Heine <ch@denx.de>
+ """
+
+ config = """
+IMAGE_INSTALL:append = " overlayfs-user"
+DISTRO_FEATURES += "systemd overlayfs"
+OVERLAYFS_QA_SKIP[mnt-overlay] = "mount-configured"
+"""
+
+ self.write_config(config)
+ self.add_overlay_conf_to_machine()
+
+ bitbake('core-image-minimal')
+
+ def test_mount_unit_not_set(self):
+ """
+ Summary: Test whether mount unit was set properly
+ Expected: Fail because mount unit was not set
+ Author: Vyacheslav Yurkov <uvv.mail@gmail.com>
+ """
+
+ config = """
+IMAGE_INSTALL:append = " overlayfs-user"
+DISTRO_FEATURES:append = " systemd overlayfs"
+"""
+
+ self.write_config(config)
+
+ res = bitbake('core-image-minimal', ignore_status=True)
+ line = getline(res, "A recipe uses overlayfs class but there is no OVERLAYFS_MOUNT_POINT set in your MACHINE configuration")
+ self.assertTrue(line and line.startswith("Parsing recipes...ERROR:"), msg=res.output)
+
+ def test_wrong_mount_unit_set(self):
+ """
+ Summary: Test whether mount unit was set properly
+ Expected: Fail because not the correct flag used for mount unit
+ Author: Vyacheslav Yurkov <uvv.mail@gmail.com>
+ """
+
+ config = """
+IMAGE_INSTALL:append = " overlayfs-user"
+DISTRO_FEATURES:append = " systemd overlayfs"
+"""
+
+ wrong_machine_config = """
+OVERLAYFS_MOUNT_POINT[usr-share-overlay] = "/usr/share/overlay"
+"""
+
+ self.write_config(config)
+ self.set_machine_config(wrong_machine_config)
+
+ res = bitbake('core-image-minimal', ignore_status=True)
+ line = getline(res, "Missing required mount point for OVERLAYFS_MOUNT_POINT[mnt-overlay] in your MACHINE configuration")
+ self.assertTrue(line and line.startswith("Parsing recipes...ERROR:"), msg=res.output)
+
+ def _test_correct_image(self, recipe, data):
+ """
+ Summary: Check that we can create an image when all parameters are
+ set correctly
+ Expected: Image is created successfully
+ Author: Vyacheslav Yurkov <uvv.mail@gmail.com>
+ """
+
+ config = """
+IMAGE_INSTALL:append = " overlayfs-user systemd-machine-units"
+DISTRO_FEATURES:append = " systemd overlayfs"
+
+# Use systemd as init manager
+VIRTUAL-RUNTIME_init_manager = "systemd"
+
+# enable overlayfs in the kernel
+KERNEL_EXTRA_FEATURES:append = " features/overlayfs/overlayfs.scc"
+"""
+
+ overlayfs_recipe_append = """
+OVERLAYFS_WRITABLE_PATHS[mnt-overlay] += "/usr/share/another-overlay-mount"
+
+SYSTEMD_SERVICE:${PN} += " \
+ my-application.service \
+"
+
+do_install:append() {
+ install -d ${D}${systemd_system_unitdir}
+ cat <<EOT > ${D}${systemd_system_unitdir}/my-application.service
+[Unit]
+Description=Sample application start-up unit
+After=overlayfs-user-overlays.service
+Requires=overlayfs-user-overlays.service
+
+[Service]
+Type=oneshot
+ExecStart=/bin/true
+RemainAfterExit=true
+
+[Install]
+WantedBy=multi-user.target
+EOT
+}
+"""
+
+ self.write_config(config)
+ self.add_overlay_conf_to_machine()
+ self.write_recipeinc(recipe, data)
+ self.write_recipeinc('overlayfs-user', overlayfs_recipe_append)
+
+ bitbake('core-image-minimal')
+
+ with runqemu('core-image-minimal') as qemu:
+ # Check that application service started
+ status, output = qemu.run_serial("systemctl status my-application")
+ self.assertTrue("active (exited)" in output, msg=output)
+
+ # Check that overlay mounts are dependencies of our application unit
+ status, output = qemu.run_serial("systemctl list-dependencies my-application")
+ self.assertTrue("overlayfs-user-overlays.service" in output, msg=output)
+
+ status, output = qemu.run_serial("systemctl list-dependencies overlayfs-user-overlays")
+ self.assertTrue("usr-share-another\\x2doverlay\\x2dmount.mount" in output, msg=output)
+ self.assertTrue("usr-share-my\\x2dapplication.mount" in output, msg=output)
+
+ # Check that we have /mnt/overlay fs mounted as tmpfs and
+ # /usr/share/my-application as an overlay (see overlayfs-user recipe)
+ status, output = qemu.run_serial("/bin/mount -t tmpfs,overlay")
+
+ line = getline_qemu(output, "on /mnt/overlay")
+ self.assertTrue(line and line.startswith("tmpfs"), msg=output)
+
+ line = getline_qemu(output, "upperdir=/mnt/overlay/upper/usr/share/my-application")
+ self.assertTrue(line and line.startswith("overlay"), msg=output)
+
+ line = getline_qemu(output, "upperdir=/mnt/overlay/upper/usr/share/another-overlay-mount")
+ self.assertTrue(line and line.startswith("overlay"), msg=output)
+
+ @OETestTag("runqemu")
+ def test_correct_image_fstab(self):
+ """
+ Summary: Check that we can create an image when all parameters are
+ set correctly via fstab
+ Expected: Image is created successfully
+ Author: Stefan Herbrechtsmeier <stefan.herbrechtsmeier@weidmueller.com>
+ """
+
+ base_files_append = """
+do_install:append() {
+ cat <<EOT >> ${D}${sysconfdir}/fstab
+tmpfs /mnt/overlay tmpfs mode=1777,strictatime,nosuid,nodev 0 0
+EOT
+}
+"""
+
+ self._test_correct_image('base-files', base_files_append)
+
+ @OETestTag("runqemu")
+ def test_correct_image_unit(self):
+ """
+ Summary: Check that we can create an image when all parameters are
+ set correctly via mount unit
+ Expected: Image is created successfully
+ Author: Vyacheslav Yurkov <uvv.mail@gmail.com>
+ """
+
+ systemd_machine_unit_append = """
+SYSTEMD_SERVICE:${PN} += " \
+ mnt-overlay.mount \
+"
+
+do_install:append() {
+ install -d ${D}${systemd_system_unitdir}
+ cat <<EOT > ${D}${systemd_system_unitdir}/mnt-overlay.mount
+[Unit]
+Description=Tmpfs directory
+DefaultDependencies=no
+
+[Mount]
+What=tmpfs
+Where=/mnt/overlay
+Type=tmpfs
+Options=mode=1777,strictatime,nosuid,nodev
+
+[Install]
+WantedBy=multi-user.target
+EOT
+}
+
+"""
+
+ self._test_correct_image('systemd-machine-units', systemd_machine_unit_append)
+
+@OETestTag("runqemu")
+class OverlayFSEtcRunTimeTests(OESelftestTestCase):
+ """overlayfs-etc class tests"""
+
+ def test_all_required_variables_set(self):
+ """
+ Summary: Check that required variables are set
+ Expected: Fail when any of required variables is missing
+ Author: Vyacheslav Yurkov <uvv.mail@gmail.com>
+ """
+
+ configBase = """
+DISTRO_FEATURES:append = " systemd"
+
+# Use systemd as init manager
+VIRTUAL-RUNTIME_init_manager = "systemd"
+
+# enable overlayfs in the kernel
+KERNEL_EXTRA_FEATURES:append = " features/overlayfs/overlayfs.scc"
+
+# Image configuration for overlayfs-etc
+EXTRA_IMAGE_FEATURES += "overlayfs-etc"
+IMAGE_FEATURES:remove = "package-management"
+"""
+ configMountPoint = """
+OVERLAYFS_ETC_MOUNT_POINT = "/data"
+"""
+ configDevice = """
+OVERLAYFS_ETC_DEVICE = "/dev/mmcblk0p1"
+"""
+
+ self.write_config(configBase)
+ res = bitbake('core-image-minimal', ignore_status=True)
+ line = getline(res, "OVERLAYFS_ETC_MOUNT_POINT must be set in your MACHINE configuration")
+ self.assertTrue(line, msg=res.output)
+
+ self.append_config(configMountPoint)
+ res = bitbake('core-image-minimal', ignore_status=True)
+ line = getline(res, "OVERLAYFS_ETC_DEVICE must be set in your MACHINE configuration")
+ self.assertTrue(line, msg=res.output)
+
+ self.append_config(configDevice)
+ res = bitbake('core-image-minimal', ignore_status=True)
+ line = getline(res, "OVERLAYFS_ETC_FSTYPE should contain a valid file system type on /dev/mmcblk0p1")
+ self.assertTrue(line, msg=res.output)
+
+ def test_image_feature_conflict(self):
+ """
+ Summary: Overlayfs-etc is not allowed to be used with package-management
+ Expected: Feature conflict
+ Author: Vyacheslav Yurkov <uvv.mail@gmail.com>
+ """
+
+ config = """
+DISTRO_FEATURES:append = " systemd"
+
+# Use systemd as init manager
+VIRTUAL-RUNTIME_init_manager = "systemd"
+
+# enable overlayfs in the kernel
+KERNEL_EXTRA_FEATURES:append = " features/overlayfs/overlayfs.scc"
+EXTRA_IMAGE_FEATURES += "overlayfs-etc"
+EXTRA_IMAGE_FEATURES += "package-management"
+"""
+
+ self.write_config(config)
+
+ res = bitbake('core-image-minimal', ignore_status=True)
+ line = getline(res, "contains conflicting IMAGE_FEATURES")
+ self.assertTrue("overlayfs-etc" in res.output, msg=res.output)
+ self.assertTrue("package-management" in res.output, msg=res.output)
+
+ # https://bugzilla.yoctoproject.org/show_bug.cgi?id=14963
+ @skipIfNotMachine("qemux86-64", "tests are qemux86-64 specific currently")
+ def test_image_feature_is_missing(self):
+ """
+ Summary: Overlayfs-etc class is not applied when image feature is not set
+ Expected: Image is created successfully but /etc is not an overlay
+ Author: Vyacheslav Yurkov <uvv.mail@gmail.com>
+ """
+
+ config = """
+DISTRO_FEATURES:append = " systemd"
+
+# Use systemd as init manager
+VIRTUAL-RUNTIME_init_manager = "systemd"
+
+# enable overlayfs in the kernel
+KERNEL_EXTRA_FEATURES:append = " features/overlayfs/overlayfs.scc"
+
+IMAGE_FSTYPES += "wic"
+WKS_FILE = "overlayfs_etc.wks.in"
+
+EXTRA_IMAGE_FEATURES += "read-only-rootfs"
+# Image configuration for overlayfs-etc
+OVERLAYFS_ETC_MOUNT_POINT = "/data"
+OVERLAYFS_ETC_DEVICE = "/dev/sda3"
+"""
+
+ self.write_config(config)
+
+ bitbake('core-image-minimal')
+
+ with runqemu('core-image-minimal', image_fstype='wic') as qemu:
+ status, output = qemu.run_serial("/bin/mount")
+
+ line = getline_qemu(output, "upperdir=/data/overlay-etc/upper")
+ self.assertFalse(line, msg=output)
+
+ @skipIfNotMachine("qemux86-64", "tests are qemux86-64 specific currently")
+ def test_sbin_init_preinit(self):
+ self.run_sbin_init(False)
+
+ @skipIfNotMachine("qemux86-64", "tests are qemux86-64 specific currently")
+ def test_sbin_init_original(self):
+ self.run_sbin_init(True)
+
+ def run_sbin_init(self, origInit):
+ """
+ Summary: Confirm we can replace original init and mount overlay on top of /etc
+ Expected: Image is created successfully and /etc is mounted as an overlay
+ Author: Vyacheslav Yurkov <uvv.mail@gmail.com>
+ """
+
+ config = self.get_working_config()
+
+ args = {
+ 'OVERLAYFS_INIT_OPTION': "" if origInit else "init=/sbin/preinit",
+ 'OVERLAYFS_ETC_USE_ORIG_INIT_NAME': int(origInit == True)
+ }
+
+ self.write_config(config.format(**args))
+
+ bitbake('core-image-minimal')
+ testFile = "/etc/my-test-data"
+
+ with runqemu('core-image-minimal', image_fstype='wic', discard_writes=False) as qemu:
+ status, output = qemu.run_serial("/bin/mount")
+
+ line = getline_qemu(output, "/dev/sda3")
+ self.assertTrue("/data" in output, msg=output)
+
+ line = getline_qemu(output, "upperdir=/data/overlay-etc/upper")
+ self.assertTrue(line and line.startswith("/data/overlay-etc/upper on /etc type overlay"), msg=output)
+
+ # check that lower layer is not available
+ status, output = qemu.run_serial("ls -1 /data/overlay-etc/lower")
+ line = getline_qemu(output, "No such file or directory")
+ self.assertTrue(line, msg=output)
+
+ status, output = qemu.run_serial("touch " + testFile)
+ status, output = qemu.run_serial("sync")
+ status, output = qemu.run_serial("ls -1 " + testFile)
+ line = getline_qemu(output, testFile)
+ self.assertTrue(line and line.startswith(testFile), msg=output)
+
+ # Check that file exists in /etc after reboot
+ with runqemu('core-image-minimal', image_fstype='wic') as qemu:
+ status, output = qemu.run_serial("ls -1 " + testFile)
+ line = getline_qemu(output, testFile)
+ self.assertTrue(line and line.startswith(testFile), msg=output)
+
+ @skipIfNotMachine("qemux86-64", "tests are qemux86-64 specific currently")
+ def test_lower_layer_access(self):
+ """
+ Summary: Test that lower layer of /etc is available read-only when configured
+ Expected: Can't write to lower layer. The files on lower and upper different after
+ modification
+ Author: Vyacheslav Yurkov <uvv.mail@gmail.com>
+ """
+
+ config = self.get_working_config()
+
+ configLower = """
+OVERLAYFS_ETC_EXPOSE_LOWER = "1"
+IMAGE_INSTALL:append = " overlayfs-user"
+"""
+ testFile = "lower-layer-test.txt"
+
+ args = {
+ 'OVERLAYFS_INIT_OPTION': "",
+ 'OVERLAYFS_ETC_USE_ORIG_INIT_NAME': 1
+ }
+
+ self.write_config(config.format(**args))
+
+ self.append_config(configLower)
+ bitbake('core-image-minimal')
+
+ with runqemu('core-image-minimal', image_fstype='wic') as qemu:
+ status, output = qemu.run_serial("echo \"Modified in upper\" > /etc/" + testFile)
+ status, output = qemu.run_serial("diff /etc/" + testFile + " /data/overlay-etc/lower/" + testFile)
+ line = getline_qemu(output, "Modified in upper")
+ self.assertTrue(line, msg=output)
+ line = getline_qemu(output, "Original file")
+ self.assertTrue(line, msg=output)
+
+ status, output = qemu.run_serial("touch /data/overlay-etc/lower/ro-test.txt")
+ line = getline_qemu(output, "Read-only file system")
+ self.assertTrue(line, msg=output)
+
+ def get_working_config(self):
+ return """
+DISTRO_FEATURES:append = " systemd"
+
+# Use systemd as init manager
+VIRTUAL-RUNTIME_init_manager = "systemd"
+
+# enable overlayfs in the kernel
+KERNEL_EXTRA_FEATURES:append = " features/overlayfs/overlayfs.scc"
+
+IMAGE_FSTYPES += "wic"
+OVERLAYFS_INIT_OPTION = "{OVERLAYFS_INIT_OPTION}"
+WKS_FILE = "overlayfs_etc.wks.in"
+
+EXTRA_IMAGE_FEATURES += "read-only-rootfs"
+# Image configuration for overlayfs-etc
+EXTRA_IMAGE_FEATURES += "overlayfs-etc"
+IMAGE_FEATURES:remove = "package-management"
+OVERLAYFS_ETC_MOUNT_POINT = "/data"
+OVERLAYFS_ETC_FSTYPE = "ext4"
+OVERLAYFS_ETC_DEVICE = "/dev/sda3"
+OVERLAYFS_ETC_USE_ORIG_INIT_NAME = "{OVERLAYFS_ETC_USE_ORIG_INIT_NAME}"
+"""
diff --git a/meta/lib/oeqa/selftest/cases/package.py b/meta/lib/oeqa/selftest/cases/package.py
new file mode 100644
index 0000000000..4f7cd10658
--- /dev/null
+++ b/meta/lib/oeqa/selftest/cases/package.py
@@ -0,0 +1,177 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
+from oeqa.selftest.case import OESelftestTestCase
+from oeqa.utils.commands import bitbake, get_bb_vars, get_bb_var, runqemu
+import subprocess, os
+import oe.path
+import re
+
+class VersionOrdering(OESelftestTestCase):
+ # version1, version2, sort order
+ tests = (
+ ("1.0", "1.0", 0),
+ ("1.0", "2.0", -1),
+ ("2.0", "1.0", 1),
+ ("2.0-rc", "2.0", 1),
+ ("2.0~rc", "2.0", -1),
+ ("1.2rc2", "1.2.0", -1)
+ )
+
+ @classmethod
+ def setUpClass(cls):
+ super().setUpClass()
+
+ # Build the tools we need and populate a sysroot
+ bitbake("dpkg-native opkg-native rpm-native python3-native")
+ bitbake("build-sysroots -c build_native_sysroot")
+
+ # Get the paths so we can point into the sysroot correctly
+ vars = get_bb_vars(["STAGING_DIR", "BUILD_ARCH", "bindir_native", "libdir_native"])
+ cls.staging = oe.path.join(vars["STAGING_DIR"], vars["BUILD_ARCH"])
+ cls.bindir = oe.path.join(cls.staging, vars["bindir_native"])
+ cls.libdir = oe.path.join(cls.staging, vars["libdir_native"])
+
+ def setUpLocal(self):
+ # Just for convenience
+ self.staging = type(self).staging
+ self.bindir = type(self).bindir
+ self.libdir = type(self).libdir
+
+ def test_dpkg(self):
+ for ver1, ver2, sort in self.tests:
+ op = { -1: "<<", 0: "=", 1: ">>" }[sort]
+ status = subprocess.call((oe.path.join(self.bindir, "dpkg"), "--compare-versions", ver1, op, ver2))
+ self.assertEqual(status, 0, "%s %s %s failed" % (ver1, op, ver2))
+
+ # Now do it again but with incorrect operations
+ op = { -1: ">>", 0: ">>", 1: "<<" }[sort]
+ status = subprocess.call((oe.path.join(self.bindir, "dpkg"), "--compare-versions", ver1, op, ver2))
+ self.assertNotEqual(status, 0, "%s %s %s failed" % (ver1, op, ver2))
+
+ # Now do it again but with incorrect operations
+ op = { -1: "=", 0: "<<", 1: "=" }[sort]
+ status = subprocess.call((oe.path.join(self.bindir, "dpkg"), "--compare-versions", ver1, op, ver2))
+ self.assertNotEqual(status, 0, "%s %s %s failed" % (ver1, op, ver2))
+
+ def test_opkg(self):
+ for ver1, ver2, sort in self.tests:
+ op = { -1: "<<", 0: "=", 1: ">>" }[sort]
+ status = subprocess.call((oe.path.join(self.bindir, "opkg"), "compare-versions", ver1, op, ver2))
+ self.assertEqual(status, 0, "%s %s %s failed" % (ver1, op, ver2))
+
+ # Now do it again but with incorrect operations
+ op = { -1: ">>", 0: ">>", 1: "<<" }[sort]
+ status = subprocess.call((oe.path.join(self.bindir, "opkg"), "compare-versions", ver1, op, ver2))
+ self.assertNotEqual(status, 0, "%s %s %s failed" % (ver1, op, ver2))
+
+ # Now do it again but with incorrect operations
+ op = { -1: "=", 0: "<<", 1: "=" }[sort]
+ status = subprocess.call((oe.path.join(self.bindir, "opkg"), "compare-versions", ver1, op, ver2))
+ self.assertNotEqual(status, 0, "%s %s %s failed" % (ver1, op, ver2))
+
+ def test_rpm(self):
+ # Need to tell the Python bindings where to find its configuration
+ env = os.environ.copy()
+ env["RPM_CONFIGDIR"] = oe.path.join(self.libdir, "rpm")
+
+ for ver1, ver2, sort in self.tests:
+ # The only way to test rpm is via the Python module, so we need to
+ # execute python3-native. labelCompare returns -1/0/1 (like strcmp)
+ # so add 100 and use that as the exit code.
+ command = (oe.path.join(self.bindir, "python3-native", "python3"), "-c",
+ "import sys, rpm; v1=(None, \"%s\", None); v2=(None, \"%s\", None); sys.exit(rpm.labelCompare(v1, v2) + 100)" % (ver1, ver2))
+ status = subprocess.call(command, env=env)
+ self.assertIn(status, (99, 100, 101))
+ self.assertEqual(status - 100, sort, "%s %s (%d) failed" % (ver1, ver2, sort))
+
+class PackageTests(OESelftestTestCase):
+ # Verify that a recipe which sets up hardlink files has those preserved into split packages
+ # Also test file sparseness is preserved
+ def test_preserve_sparse_hardlinks(self):
+ bitbake("selftest-hardlink -c package")
+
+ dest = get_bb_var('PKGDEST', 'selftest-hardlink')
+ bindir = get_bb_var('bindir', 'selftest-hardlink')
+
+ def checkfiles():
+ # Recipe creates 4 hardlinked files, there is a copy in package/ and a copy in packages-split/
+ # so expect 8 in total.
+ self.assertEqual(os.stat(dest + "/selftest-hardlink" + bindir + "/hello1").st_nlink, 8)
+
+ # Test a sparse file remains sparse
+ sparsestat = os.stat(dest + "/selftest-hardlink" + bindir + "/sparsetest")
+ self.assertEqual(sparsestat.st_blocks, 0)
+ self.assertEqual(sparsestat.st_size, 1048576)
+
+ checkfiles()
+
+ # Clean and reinstall so its now definitely from sstate, then retest.
+ bitbake("selftest-hardlink -c clean")
+ bitbake("selftest-hardlink -c package")
+
+ checkfiles()
+
+ # Verify gdb to read symbols from separated debug hardlink file correctly
+ def test_gdb_hardlink_debug(self):
+ features = 'IMAGE_INSTALL:append = " selftest-hardlink"\n'
+ features += 'IMAGE_INSTALL:append = " selftest-hardlink-dbg"\n'
+ features += 'IMAGE_INSTALL:append = " selftest-hardlink-gdb"\n'
+ self.write_config(features)
+ bitbake("core-image-minimal")
+
+ def gdbtest(qemu, binary):
+ """
+ Check that gdb ``binary`` to read symbols from separated debug file
+ """
+ self.logger.info("gdbtest %s" % binary)
+ status, output = qemu.run_serial('/usr/bin/gdb.sh %s' % binary, timeout=60)
+ for l in output.split('\n'):
+ # Check debugging symbols exists
+ if '(no debugging symbols found)' in l:
+ self.logger.error("No debugging symbols found. GDB result:\n%s" % output)
+ return False
+
+ # Check debugging symbols works correctly. Don't look for a
+ # source file as optimisation can put the breakpoint inside
+ # stdio.h.
+ elif "Breakpoint 1 at" in l:
+ return True
+
+ self.logger.error("GDB result:\n%d: %s", status, output)
+ return False
+
+ with runqemu('core-image-minimal') as qemu:
+ for binary in ['/usr/bin/hello1',
+ '/usr/bin/hello2',
+ '/usr/libexec/hello3',
+ '/usr/libexec/hello4']:
+ if not gdbtest(qemu, binary):
+ self.fail('GDB %s failed' % binary)
+
+ def test_preserve_ownership(self):
+ features = 'IMAGE_INSTALL:append = " selftest-chown"\n'
+ self.write_config(features)
+ bitbake("core-image-minimal")
+
+ def check_ownership(qemu, expected_gid, expected_uid, path):
+ self.logger.info("Check ownership of %s", path)
+ status, output = qemu.run_serial('stat -c "%U %G" ' + path)
+ self.assertEqual(status, 1, "stat failed: " + output)
+ try:
+ uid, gid = output.split()
+ self.assertEqual(uid, expected_uid)
+ self.assertEqual(gid, expected_gid)
+ except ValueError:
+ self.fail("Cannot parse output: " + output)
+
+ sysconfdir = get_bb_var('sysconfdir', 'selftest-chown')
+ with runqemu('core-image-minimal') as qemu:
+ for path in [ sysconfdir + "/selftest-chown/file",
+ sysconfdir + "/selftest-chown/dir",
+ sysconfdir + "/selftest-chown/symlink",
+ sysconfdir + "/selftest-chown/fifotest/fifo"]:
+ check_ownership(qemu, "test", "test", path)
diff --git a/meta/lib/oeqa/selftest/pkgdata.py b/meta/lib/oeqa/selftest/cases/pkgdata.py
index 5a63f89ff2..d786c33018 100644
--- a/meta/lib/oeqa/selftest/pkgdata.py
+++ b/meta/lib/oeqa/selftest/cases/pkgdata.py
@@ -1,81 +1,80 @@
-import unittest
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
import os
import tempfile
-import logging
import fnmatch
-import oeqa.utils.ftools as ftools
-from oeqa.selftest.base import oeSelfTest
-from oeqa.utils.commands import runCmd, bitbake, get_bb_var
-from oeqa.utils.decorators import testcase
+from oeqa.selftest.case import OESelftestTestCase
+from oeqa.utils.commands import runCmd, bitbake, get_bb_var, get_bb_vars
-class OePkgdataUtilTests(oeSelfTest):
+class OePkgdataUtilTests(OESelftestTestCase):
@classmethod
def setUpClass(cls):
+ super(OePkgdataUtilTests, cls).setUpClass()
# Ensure we have the right data in pkgdata
- logger = logging.getLogger("selftest")
- logger.info('Running bitbake to generate pkgdata')
- bitbake('glibc busybox zlib bash')
+ cls.logger.info('Running bitbake to generate pkgdata')
+ bitbake('target-sdk-provides-dummy -c clean')
+ bitbake('busybox zlib m4')
- @testcase(1203)
def test_lookup_pkg(self):
# Forward tests
- result = runCmd('oe-pkgdata-util lookup-pkg "glibc busybox"')
- self.assertEqual(result.output, 'libc6\nbusybox')
+ result = runCmd('oe-pkgdata-util lookup-pkg "zlib busybox"')
+ self.assertEqual(result.output, 'libz1\nbusybox')
result = runCmd('oe-pkgdata-util lookup-pkg zlib-dev')
self.assertEqual(result.output, 'libz-dev')
result = runCmd('oe-pkgdata-util lookup-pkg nonexistentpkg', ignore_status=True)
self.assertEqual(result.status, 1, "Status different than 1. output: %s" % result.output)
self.assertEqual(result.output, 'ERROR: The following packages could not be found: nonexistentpkg')
# Reverse tests
- result = runCmd('oe-pkgdata-util lookup-pkg -r "libc6 busybox"')
- self.assertEqual(result.output, 'glibc\nbusybox')
+ result = runCmd('oe-pkgdata-util lookup-pkg -r "libz1 busybox"')
+ self.assertEqual(result.output, 'zlib\nbusybox')
result = runCmd('oe-pkgdata-util lookup-pkg -r libz-dev')
self.assertEqual(result.output, 'zlib-dev')
result = runCmd('oe-pkgdata-util lookup-pkg -r nonexistentpkg', ignore_status=True)
self.assertEqual(result.status, 1, "Status different than 1. output: %s" % result.output)
self.assertEqual(result.output, 'ERROR: The following packages could not be found: nonexistentpkg')
- @testcase(1205)
def test_read_value(self):
result = runCmd('oe-pkgdata-util read-value PN libz1')
self.assertEqual(result.output, 'zlib')
- result = runCmd('oe-pkgdata-util read-value PKGSIZE bash')
+ result = runCmd('oe-pkgdata-util read-value PKG libz1')
+ self.assertEqual(result.output, 'libz1')
+ result = runCmd('oe-pkgdata-util read-value PKGSIZE m4')
pkgsize = int(result.output.strip())
self.assertGreater(pkgsize, 1, "Size should be greater than 1. %s" % result.output)
- @testcase(1198)
def test_find_path(self):
- result = runCmd('oe-pkgdata-util find-path /lib/libc.so.6')
- self.assertEqual(result.output, 'glibc: /lib/libc.so.6')
- result = runCmd('oe-pkgdata-util find-path /bin/bash')
- self.assertEqual(result.output, 'bash: /bin/bash')
+ result = runCmd('oe-pkgdata-util find-path /usr/lib/libz.so.1')
+ self.assertEqual(result.output, 'zlib: /usr/lib/libz.so.1')
+ result = runCmd('oe-pkgdata-util find-path /usr/bin/m4')
+ self.assertEqual(result.output, 'm4: /usr/bin/m4')
result = runCmd('oe-pkgdata-util find-path /not/exist', ignore_status=True)
self.assertEqual(result.status, 1, "Status different than 1. output: %s" % result.output)
self.assertEqual(result.output, 'ERROR: Unable to find any package producing path /not/exist')
- @testcase(1204)
def test_lookup_recipe(self):
- result = runCmd('oe-pkgdata-util lookup-recipe "libc6-staticdev busybox"')
- self.assertEqual(result.output, 'glibc\nbusybox')
+ result = runCmd('oe-pkgdata-util lookup-recipe "libz-staticdev busybox"')
+ self.assertEqual(result.output, 'zlib\nbusybox')
result = runCmd('oe-pkgdata-util lookup-recipe libz-dbg')
self.assertEqual(result.output, 'zlib')
result = runCmd('oe-pkgdata-util lookup-recipe nonexistentpkg', ignore_status=True)
self.assertEqual(result.status, 1, "Status different than 1. output: %s" % result.output)
self.assertEqual(result.output, 'ERROR: The following packages could not be found: nonexistentpkg')
- @testcase(1202)
def test_list_pkgs(self):
# No arguments
result = runCmd('oe-pkgdata-util list-pkgs')
pkglist = result.output.split()
- self.assertIn('glibc-utils', pkglist, "Listed packages: %s" % result.output)
+ self.assertIn('zlib', pkglist, "Listed packages: %s" % result.output)
self.assertIn('zlib-dev', pkglist, "Listed packages: %s" % result.output)
# No pkgspec, runtime
result = runCmd('oe-pkgdata-util list-pkgs -r')
pkglist = result.output.split()
- self.assertIn('libc6-utils', pkglist, "Listed packages: %s" % result.output)
self.assertIn('libz-dev', pkglist, "Listed packages: %s" % result.output)
# With recipe specified
result = runCmd('oe-pkgdata-util list-pkgs -p zlib')
@@ -84,7 +83,7 @@ class OePkgdataUtilTests(oeSelfTest):
pkglist.remove('zlib-ptest') # in case ptest is disabled
except ValueError:
pass
- self.assertEqual(pkglist, ['zlib', 'zlib-dbg', 'zlib-dev', 'zlib-doc', 'zlib-staticdev'], "Packages listed after remove: %s" % result.output)
+ self.assertEqual(pkglist, ['zlib', 'zlib-dbg', 'zlib-dev', 'zlib-doc', 'zlib-src', 'zlib-staticdev'], "Packages listed after remove: %s" % result.output)
# With recipe specified, runtime
result = runCmd('oe-pkgdata-util list-pkgs -p zlib -r')
pkglist = sorted(result.output.split())
@@ -92,7 +91,7 @@ class OePkgdataUtilTests(oeSelfTest):
pkglist.remove('libz-ptest') # in case ptest is disabled
except ValueError:
pass
- self.assertEqual(pkglist, ['libz-dbg', 'libz-dev', 'libz-doc', 'libz-staticdev', 'libz1'], "Packages listed after remove: %s" % result.output)
+ self.assertEqual(pkglist, ['libz-dbg', 'libz-dev', 'libz-doc', 'libz-src', 'libz-staticdev', 'libz1'], "Packages listed after remove: %s" % result.output)
# With recipe specified and unpackaged
result = runCmd('oe-pkgdata-util list-pkgs -p zlib -u')
pkglist = sorted(result.output.split())
@@ -110,7 +109,6 @@ class OePkgdataUtilTests(oeSelfTest):
pkglist = sorted(result.output.split())
self.assertEqual(pkglist, ['libz-dbg', 'libz-dev', 'libz-doc'], "Packages listed: %s" % result.output)
- @testcase(1201)
def test_list_pkg_files(self):
def splitoutput(output):
files = {}
@@ -124,10 +122,10 @@ class OePkgdataUtilTests(oeSelfTest):
curpkg = line.split(':')[0]
files[curpkg] = []
return files
- base_libdir = get_bb_var('base_libdir')
- libdir = get_bb_var('libdir')
- includedir = get_bb_var('includedir')
- mandir = get_bb_var('mandir')
+ bb_vars = get_bb_vars(['libdir', 'includedir', 'mandir'])
+ libdir = bb_vars['libdir']
+ includedir = bb_vars['includedir']
+ mandir = bb_vars['mandir']
# Test recipe-space package name
result = runCmd('oe-pkgdata-util list-pkg-files zlib-dev zlib-doc')
files = splitoutput(result.output)
@@ -141,7 +139,7 @@ class OePkgdataUtilTests(oeSelfTest):
self.assertIn('libz1', list(files.keys()), "listed pkgs. files: %s" %result.output)
self.assertIn('libz-dev', list(files.keys()), "listed pkgs. files: %s" %result.output)
self.assertGreater(len(files['libz1']), 1)
- libspec = os.path.join(base_libdir, 'libz.so.1.*')
+ libspec = os.path.join(libdir, 'libz.so.1.*')
found = False
for fileitem in files['libz1']:
if fnmatch.fnmatchcase(fileitem, libspec):
@@ -199,17 +197,15 @@ class OePkgdataUtilTests(oeSelfTest):
self.assertIn(os.path.join(mandir, 'man3/zlib.3'), files['libz-doc'])
self.assertIn(os.path.join(libdir, 'libz.a'), files['libz-staticdev'])
- @testcase(1200)
def test_glob(self):
tempdir = tempfile.mkdtemp(prefix='pkgdataqa')
self.track_for_cleanup(tempdir)
pkglistfile = os.path.join(tempdir, 'pkglist')
with open(pkglistfile, 'w') as f:
- f.write('libc6\n')
f.write('libz1\n')
f.write('busybox\n')
result = runCmd('oe-pkgdata-util glob %s "*-dev"' % pkglistfile)
- desiredresult = ['libc6-dev', 'libz-dev', 'busybox-dev']
+ desiredresult = ['libz-dev', 'busybox-dev']
self.assertEqual(sorted(result.output.split()), sorted(desiredresult))
# The following should not error (because when we use this during rootfs construction, sometimes the complementary package won't exist)
result = runCmd('oe-pkgdata-util glob %s "*-nonexistent"' % pkglistfile)
@@ -220,7 +216,12 @@ class OePkgdataUtilTests(oeSelfTest):
self.assertNotIn('libz-dev', resultlist)
self.assertNotIn('libz-dbg', resultlist)
- @testcase(1206)
def test_specify_pkgdatadir(self):
- result = runCmd('oe-pkgdata-util -p %s lookup-pkg glibc' % get_bb_var('PKGDATA_DIR'))
- self.assertEqual(result.output, 'libc6')
+ result = runCmd('oe-pkgdata-util -p %s lookup-pkg zlib' % get_bb_var('PKGDATA_DIR'))
+ self.assertEqual(result.output, 'libz1')
+
+ def test_no_param(self):
+ result = runCmd('oe-pkgdata-util', ignore_status=True)
+ self.assertEqual(result.status, 2, "Status different than 2. output: %s" % result.output)
+ currpos = result.output.find('usage: oe-pkgdata-util')
+ self.assertTrue(currpos != -1, msg = "Test is Failed. Help is not Displayed in %s" % result.output)
diff --git a/meta/lib/oeqa/selftest/prservice.py b/meta/lib/oeqa/selftest/cases/prservice.py
index 1b9a510fd4..cb95503c2c 100644
--- a/meta/lib/oeqa/selftest/prservice.py
+++ b/meta/lib/oeqa/selftest/cases/prservice.py
@@ -1,24 +1,31 @@
-import unittest
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
import os
-import logging
import re
import shutil
import datetime
import oeqa.utils.ftools as ftools
-from oeqa.selftest.base import oeSelfTest
+from oeqa.selftest.case import OESelftestTestCase
from oeqa.utils.commands import runCmd, bitbake, get_bb_var
-from oeqa.utils.decorators import testcase
from oeqa.utils.network import get_free_port
-class BitbakePrTests(oeSelfTest):
-
+class BitbakePrTests(OESelftestTestCase):
+
+ @classmethod
+ def setUpClass(cls):
+ super(BitbakePrTests, cls).setUpClass()
+ cls.pkgdata_dir = get_bb_var('PKGDATA_DIR')
+
def get_pr_version(self, package_name):
- pkgdata_dir = get_bb_var('PKGDATA_DIR')
- package_data_file = os.path.join(pkgdata_dir, 'runtime', package_name)
+ package_data_file = os.path.join(self.pkgdata_dir, 'runtime', package_name)
package_data = ftools.read_file(package_data_file)
- find_pr = re.search("PKGR: r[0-9]+\.([0-9]+)", package_data)
- self.assertTrue(find_pr, "No PKG revision found in %s" % package_data_file)
+ find_pr = re.search(r"PKGR: r[0-9]+\.([0-9]+)", package_data)
+ self.assertTrue(find_pr, "No PKG revision found via regex 'PKGR: r[0-9]+\.([0-9]+)' in %s" % package_data_file)
return int(find_pr.group(1))
def get_task_stamp(self, package_name, recipe_task):
@@ -27,7 +34,7 @@ class BitbakePrTests(oeSelfTest):
package_stamps_path = "/".join(stampdata[:-1])
stamps = []
for stamp in os.listdir(package_stamps_path):
- find_stamp = re.match("%s\.%s\.([a-z0-9]{32})" % (re.escape(prefix), recipe_task), stamp)
+ find_stamp = re.match(r"%s\.%s\.([a-z0-9]{32})" % (re.escape(prefix), recipe_task), stamp)
if find_stamp:
stamps.append(find_stamp.group(1))
self.assertFalse(len(stamps) == 0, msg="Cound not find stamp for task %s for recipe %s" % (recipe_task, package_name))
@@ -35,13 +42,11 @@ class BitbakePrTests(oeSelfTest):
return str(stamps[0])
def increment_package_pr(self, package_name):
- inc_data = "do_package_append() {\n bb.build.exec_func('do_test_prserv', d)\n}\ndo_test_prserv() {\necho \"The current date is: %s\"\n}" % datetime.datetime.now()
+ inc_data = "do_package:append() {\n bb.build.exec_func('do_test_prserv', d)\n}\ndo_test_prserv() {\necho \"The current date is: %s\" > ${PKGDESTWORK}/${PN}.datestamp\n}" % datetime.datetime.now()
self.write_recipeinc(package_name, inc_data)
- bitbake("-ccleansstate %s" % package_name)
res = bitbake(package_name, ignore_status=True)
self.delete_recipeinc(package_name)
self.assertEqual(res.status, 0, msg=res.output)
- self.assertTrue("NOTE: Started PRServer with DBfile" in res.output, msg=res.output)
def config_pr_tests(self, package_name, package_type='rpm', pr_socket='localhost:0'):
config_package_data = 'PACKAGE_CLASSES = "package_%s"' % package_type
@@ -60,8 +65,7 @@ class BitbakePrTests(oeSelfTest):
pr_2 = self.get_pr_version(package_name)
stamp_2 = self.get_task_stamp(package_name, track_task)
- bitbake("-ccleansstate %s" % package_name)
- self.assertTrue(pr_2 - pr_1 == 1, "Step between same pkg. revision is greater than 1")
+ self.assertTrue(pr_2 - pr_1 == 1, "New PR %s did not increment as expected (from %s), difference should be 1" % (pr_2, pr_1))
self.assertTrue(stamp_1 != stamp_2, "Different pkg rev. but same stamp: %s" % stamp_1)
def run_test_pr_export_import(self, package_name, replace_current_db=True):
@@ -73,6 +77,7 @@ class BitbakePrTests(oeSelfTest):
exported_db_path = os.path.join(self.builddir, 'export.inc')
export_result = runCmd("bitbake-prserv-tool export %s" % exported_db_path, ignore_status=True)
self.assertEqual(export_result.status, 0, msg="PR Service database export failed: %s" % export_result.output)
+ self.assertTrue(os.path.exists(exported_db_path))
if replace_current_db:
current_db_path = os.path.join(get_bb_var('PERSISTENT_DIR'), 'prserv.sqlite3')
@@ -86,42 +91,32 @@ class BitbakePrTests(oeSelfTest):
self.increment_package_pr(package_name)
pr_2 = self.get_pr_version(package_name)
- bitbake("-ccleansstate %s" % package_name)
- self.assertTrue(pr_2 - pr_1 == 1, "Step between same pkg. revision is greater than 1")
+ self.assertTrue(pr_2 - pr_1 == 1, "New PR %s did not increment as expected (from %s), difference should be 1" % (pr_2, pr_1))
- @testcase(930)
def test_import_export_replace_db(self):
self.run_test_pr_export_import('m4')
- @testcase(931)
def test_import_export_override_db(self):
self.run_test_pr_export_import('m4', replace_current_db=False)
- @testcase(932)
def test_pr_service_rpm_arch_dep(self):
self.run_test_pr_service('m4', 'rpm', 'do_package')
- @testcase(934)
def test_pr_service_deb_arch_dep(self):
self.run_test_pr_service('m4', 'deb', 'do_package')
- @testcase(933)
def test_pr_service_ipk_arch_dep(self):
self.run_test_pr_service('m4', 'ipk', 'do_package')
- @testcase(935)
def test_pr_service_rpm_arch_indep(self):
self.run_test_pr_service('xcursor-transparent-theme', 'rpm', 'do_package')
- @testcase(937)
def test_pr_service_deb_arch_indep(self):
self.run_test_pr_service('xcursor-transparent-theme', 'deb', 'do_package')
- @testcase(936)
def test_pr_service_ipk_arch_indep(self):
self.run_test_pr_service('xcursor-transparent-theme', 'ipk', 'do_package')
- @testcase(1419)
def test_stopping_prservice_message(self):
port = get_free_port()
diff --git a/meta/lib/oeqa/selftest/cases/pseudo.py b/meta/lib/oeqa/selftest/cases/pseudo.py
new file mode 100644
index 0000000000..3ef8786022
--- /dev/null
+++ b/meta/lib/oeqa/selftest/cases/pseudo.py
@@ -0,0 +1,29 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
+import glob
+import os
+import shutil
+from oeqa.utils.commands import bitbake, get_test_layer
+from oeqa.selftest.case import OESelftestTestCase
+
+class Pseudo(OESelftestTestCase):
+
+ def test_pseudo_pyc_creation(self):
+ self.write_config("")
+
+ metaselftestpath = get_test_layer()
+ pycache_path = os.path.join(metaselftestpath, 'lib/__pycache__')
+ if os.path.exists(pycache_path):
+ shutil.rmtree(pycache_path)
+
+ bitbake('pseudo-pyc-test -c install')
+
+ test1_pyc_present = len(glob.glob(os.path.join(pycache_path, 'pseudo_pyc_test1.*.pyc')))
+ self.assertTrue(test1_pyc_present, 'test1 pyc file missing, should be created outside of pseudo context.')
+
+ test2_pyc_present = len(glob.glob(os.path.join(pycache_path, 'pseudo_pyc_test2.*.pyc')))
+ self.assertFalse(test2_pyc_present, 'test2 pyc file present, should not be created in pseudo context.')
diff --git a/meta/lib/oeqa/selftest/recipetool.py b/meta/lib/oeqa/selftest/cases/recipetool.py
index f8f6be32a4..25b06cdcf0 100644
--- a/meta/lib/oeqa/selftest/recipetool.py
+++ b/meta/lib/oeqa/selftest/cases/recipetool.py
@@ -1,16 +1,20 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
import os
-import logging
+import shutil
import tempfile
import urllib.parse
-from oeqa.utils.commands import runCmd, bitbake, get_bb_var, create_temp_layer
-from oeqa.utils.decorators import testcase
-from oeqa.selftest import devtool
-
+from oeqa.utils.commands import runCmd, bitbake, get_bb_var
+from oeqa.utils.commands import get_bb_vars, create_temp_layer
+from oeqa.selftest.cases import devtool
templayerdir = None
-
def setUpModule():
global templayerdir
templayerdir = tempfile.mkdtemp(prefix='recipetoolqa')
@@ -23,8 +27,10 @@ def tearDownModule():
runCmd('rm -rf %s' % templayerdir)
-class RecipetoolBase(devtool.DevtoolBase):
+class RecipetoolBase(devtool.DevtoolTestCase):
+
def setUpLocal(self):
+ super(RecipetoolBase, self).setUpLocal()
self.templayerdir = templayerdir
self.tempdir = tempfile.mkdtemp(prefix='recipetoolqa')
self.track_for_cleanup(self.tempdir)
@@ -34,6 +40,7 @@ class RecipetoolBase(devtool.DevtoolBase):
def tearDownLocal(self):
runCmd('rm -rf %s/recipes-*' % self.templayerdir)
+ super(RecipetoolBase, self).tearDownLocal()
def _try_recipetool_appendcmd(self, cmd, testrecipe, expectedfiles, expectedlines=None):
result = runCmd(cmd)
@@ -63,18 +70,16 @@ class RecipetoolBase(devtool.DevtoolBase):
return bbappendfile, result.output
-class RecipetoolTests(RecipetoolBase):
+class RecipetoolAppendTests(RecipetoolBase):
+
@classmethod
def setUpClass(cls):
+ super(RecipetoolAppendTests, cls).setUpClass()
# Ensure we have the right data in shlibs/pkgdata
- logger = logging.getLogger("selftest")
- logger.info('Running bitbake to generate pkgdata')
+ cls.logger.info('Running bitbake to generate pkgdata')
bitbake('-c packagedata base-files coreutils busybox selftest-recipetool-appendfile')
-
- @classmethod
- def tearDownClass(cls):
- # Shouldn't leave any traces of this artificial recipe behind
- bitbake('-c cleansstate selftest-recipetool-appendfile')
+ bb_vars = get_bb_vars(['COREBASE'])
+ cls.corebase = bb_vars['COREBASE']
def _try_recipetool_appendfile(self, testrecipe, destfile, newfile, options, expectedlines, expectedfiles):
cmd = 'recipetool appendfile %s %s %s %s' % (self.templayerdir, destfile, newfile, options)
@@ -88,35 +93,31 @@ class RecipetoolTests(RecipetoolBase):
for errorstr in checkerror:
self.assertIn(errorstr, result.output)
- @testcase(1177)
def test_recipetool_appendfile_basic(self):
# Basic test
- expectedlines = ['FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"\n',
+ expectedlines = ['FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:"\n',
'\n']
_, output = self._try_recipetool_appendfile('base-files', '/etc/motd', self.testfile, '', expectedlines, ['motd'])
self.assertNotIn('WARNING: ', output)
- @testcase(1183)
def test_recipetool_appendfile_invalid(self):
# Test some commands that should error
self._try_recipetool_appendfile_fail('/etc/passwd', self.testfile, ['ERROR: /etc/passwd cannot be handled by this tool', 'useradd', 'extrausers'])
self._try_recipetool_appendfile_fail('/etc/timestamp', self.testfile, ['ERROR: /etc/timestamp cannot be handled by this tool'])
self._try_recipetool_appendfile_fail('/dev/console', self.testfile, ['ERROR: /dev/console cannot be handled by this tool'])
- @testcase(1176)
def test_recipetool_appendfile_alternatives(self):
# Now try with a file we know should be an alternative
# (this is very much a fake example, but one we know is reliably an alternative)
self._try_recipetool_appendfile_fail('/bin/ls', self.testfile, ['ERROR: File /bin/ls is an alternative possibly provided by the following recipes:', 'coreutils', 'busybox'])
- corebase = get_bb_var('COREBASE')
# Need a test file - should be executable
- testfile2 = os.path.join(corebase, 'oe-init-build-env')
+ testfile2 = os.path.join(self.corebase, 'oe-init-build-env')
testfile2name = os.path.basename(testfile2)
- expectedlines = ['FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"\n',
+ expectedlines = ['FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:"\n',
'\n',
'SRC_URI += "file://%s"\n' % testfile2name,
'\n',
- 'do_install_append() {\n',
+ 'do_install:append() {\n',
' install -d ${D}${base_bindir}\n',
' install -m 0755 ${WORKDIR}/%s ${D}${base_bindir}/ls\n' % testfile2name,
'}\n']
@@ -128,7 +129,6 @@ class RecipetoolTests(RecipetoolBase):
result = runCmd('diff -q %s %s' % (testfile2, copiedfile), ignore_status=True)
self.assertNotEqual(result.status, 0, 'New file should have been copied but was not %s' % result.output)
- @testcase(1178)
def test_recipetool_appendfile_binary(self):
# Try appending a binary file
# /bin/ls can be a symlink to /usr/bin/ls
@@ -137,142 +137,117 @@ class RecipetoolTests(RecipetoolBase):
self.assertIn('WARNING: ', result.output)
self.assertIn('is a binary', result.output)
- @testcase(1173)
def test_recipetool_appendfile_add(self):
- corebase = get_bb_var('COREBASE')
# Try arbitrary file add to a recipe
- expectedlines = ['FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"\n',
+ expectedlines = ['FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:"\n',
'\n',
'SRC_URI += "file://testfile"\n',
'\n',
- 'do_install_append() {\n',
+ 'do_install:append() {\n',
' install -d ${D}${datadir}\n',
' install -m 0644 ${WORKDIR}/testfile ${D}${datadir}/something\n',
'}\n']
self._try_recipetool_appendfile('netbase', '/usr/share/something', self.testfile, '-r netbase', expectedlines, ['testfile'])
# Try adding another file, this time where the source file is executable
# (so we're testing that, plus modifying an existing bbappend)
- testfile2 = os.path.join(corebase, 'oe-init-build-env')
+ testfile2 = os.path.join(self.corebase, 'oe-init-build-env')
testfile2name = os.path.basename(testfile2)
- expectedlines = ['FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"\n',
+ expectedlines = ['FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:"\n',
'\n',
'SRC_URI += "file://testfile \\\n',
' file://%s \\\n' % testfile2name,
' "\n',
'\n',
- 'do_install_append() {\n',
+ 'do_install:append() {\n',
' install -d ${D}${datadir}\n',
' install -m 0644 ${WORKDIR}/testfile ${D}${datadir}/something\n',
' install -m 0755 ${WORKDIR}/%s ${D}${datadir}/scriptname\n' % testfile2name,
'}\n']
self._try_recipetool_appendfile('netbase', '/usr/share/scriptname', testfile2, '-r netbase', expectedlines, ['testfile', testfile2name])
- @testcase(1174)
def test_recipetool_appendfile_add_bindir(self):
# Try arbitrary file add to a recipe, this time to a location such that should be installed as executable
- expectedlines = ['FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"\n',
+ expectedlines = ['FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:"\n',
'\n',
'SRC_URI += "file://testfile"\n',
'\n',
- 'do_install_append() {\n',
+ 'do_install:append() {\n',
' install -d ${D}${bindir}\n',
' install -m 0755 ${WORKDIR}/testfile ${D}${bindir}/selftest-recipetool-testbin\n',
'}\n']
_, output = self._try_recipetool_appendfile('netbase', '/usr/bin/selftest-recipetool-testbin', self.testfile, '-r netbase', expectedlines, ['testfile'])
self.assertNotIn('WARNING: ', output)
- @testcase(1175)
def test_recipetool_appendfile_add_machine(self):
# Try arbitrary file add to a recipe, this time to a location such that should be installed as executable
- expectedlines = ['FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"\n',
+ expectedlines = ['FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:"\n',
'\n',
'PACKAGE_ARCH = "${MACHINE_ARCH}"\n',
'\n',
- 'SRC_URI_append_mymachine = " file://testfile"\n',
+ 'SRC_URI:append:mymachine = " file://testfile"\n',
'\n',
- 'do_install_append_mymachine() {\n',
+ 'do_install:append:mymachine() {\n',
' install -d ${D}${datadir}\n',
' install -m 0644 ${WORKDIR}/testfile ${D}${datadir}/something\n',
'}\n']
_, output = self._try_recipetool_appendfile('netbase', '/usr/share/something', self.testfile, '-r netbase -m mymachine', expectedlines, ['mymachine/testfile'])
self.assertNotIn('WARNING: ', output)
- @testcase(1184)
def test_recipetool_appendfile_orig(self):
# A file that's in SRC_URI and in do_install with the same name
- expectedlines = ['FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"\n',
+ expectedlines = ['FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:"\n',
'\n']
_, output = self._try_recipetool_appendfile('selftest-recipetool-appendfile', '/usr/share/selftest-replaceme-orig', self.testfile, '', expectedlines, ['selftest-replaceme-orig'])
self.assertNotIn('WARNING: ', output)
- @testcase(1191)
def test_recipetool_appendfile_todir(self):
# A file that's in SRC_URI and in do_install with destination directory rather than file
- expectedlines = ['FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"\n',
+ expectedlines = ['FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:"\n',
'\n']
_, output = self._try_recipetool_appendfile('selftest-recipetool-appendfile', '/usr/share/selftest-replaceme-todir', self.testfile, '', expectedlines, ['selftest-replaceme-todir'])
self.assertNotIn('WARNING: ', output)
- @testcase(1187)
def test_recipetool_appendfile_renamed(self):
# A file that's in SRC_URI with a different name to the destination file
- expectedlines = ['FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"\n',
+ expectedlines = ['FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:"\n',
'\n']
_, output = self._try_recipetool_appendfile('selftest-recipetool-appendfile', '/usr/share/selftest-replaceme-renamed', self.testfile, '', expectedlines, ['file1'])
self.assertNotIn('WARNING: ', output)
- @testcase(1190)
def test_recipetool_appendfile_subdir(self):
# A file that's in SRC_URI in a subdir
- expectedlines = ['FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"\n',
+ expectedlines = ['FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:"\n',
'\n',
'SRC_URI += "file://testfile"\n',
'\n',
- 'do_install_append() {\n',
+ 'do_install:append() {\n',
' install -d ${D}${datadir}\n',
' install -m 0644 ${WORKDIR}/testfile ${D}${datadir}/selftest-replaceme-subdir\n',
'}\n']
_, output = self._try_recipetool_appendfile('selftest-recipetool-appendfile', '/usr/share/selftest-replaceme-subdir', self.testfile, '', expectedlines, ['testfile'])
self.assertNotIn('WARNING: ', output)
- @testcase(1189)
- def test_recipetool_appendfile_src_glob(self):
- # A file that's in SRC_URI as a glob
- expectedlines = ['FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"\n',
- '\n',
- 'SRC_URI += "file://testfile"\n',
- '\n',
- 'do_install_append() {\n',
- ' install -d ${D}${datadir}\n',
- ' install -m 0644 ${WORKDIR}/testfile ${D}${datadir}/selftest-replaceme-src-globfile\n',
- '}\n']
- _, output = self._try_recipetool_appendfile('selftest-recipetool-appendfile', '/usr/share/selftest-replaceme-src-globfile', self.testfile, '', expectedlines, ['testfile'])
- self.assertNotIn('WARNING: ', output)
-
- @testcase(1181)
def test_recipetool_appendfile_inst_glob(self):
# A file that's in do_install as a glob
- expectedlines = ['FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"\n',
+ expectedlines = ['FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:"\n',
'\n']
_, output = self._try_recipetool_appendfile('selftest-recipetool-appendfile', '/usr/share/selftest-replaceme-inst-globfile', self.testfile, '', expectedlines, ['selftest-replaceme-inst-globfile'])
self.assertNotIn('WARNING: ', output)
- @testcase(1182)
def test_recipetool_appendfile_inst_todir_glob(self):
# A file that's in do_install as a glob with destination as a directory
- expectedlines = ['FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"\n',
+ expectedlines = ['FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:"\n',
'\n']
_, output = self._try_recipetool_appendfile('selftest-recipetool-appendfile', '/usr/share/selftest-replaceme-inst-todir-globfile', self.testfile, '', expectedlines, ['selftest-replaceme-inst-todir-globfile'])
self.assertNotIn('WARNING: ', output)
- @testcase(1185)
def test_recipetool_appendfile_patch(self):
# A file that's added by a patch in SRC_URI
- expectedlines = ['FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"\n',
+ expectedlines = ['FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:"\n',
'\n',
'SRC_URI += "file://testfile"\n',
'\n',
- 'do_install_append() {\n',
+ 'do_install:append() {\n',
' install -d ${D}${sysconfdir}\n',
' install -m 0644 ${WORKDIR}/testfile ${D}${sysconfdir}/selftest-replaceme-patched\n',
'}\n']
@@ -284,45 +259,41 @@ class RecipetoolTests(RecipetoolBase):
else:
self.fail('Patch warning not found in output:\n%s' % output)
- @testcase(1188)
def test_recipetool_appendfile_script(self):
# Now, a file that's in SRC_URI but installed by a script (so no mention in do_install)
- expectedlines = ['FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"\n',
+ expectedlines = ['FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:"\n',
'\n',
'SRC_URI += "file://testfile"\n',
'\n',
- 'do_install_append() {\n',
+ 'do_install:append() {\n',
' install -d ${D}${datadir}\n',
' install -m 0644 ${WORKDIR}/testfile ${D}${datadir}/selftest-replaceme-scripted\n',
'}\n']
_, output = self._try_recipetool_appendfile('selftest-recipetool-appendfile', '/usr/share/selftest-replaceme-scripted', self.testfile, '', expectedlines, ['testfile'])
self.assertNotIn('WARNING: ', output)
- @testcase(1180)
def test_recipetool_appendfile_inst_func(self):
# A file that's installed from a function called by do_install
- expectedlines = ['FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"\n',
+ expectedlines = ['FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:"\n',
'\n']
_, output = self._try_recipetool_appendfile('selftest-recipetool-appendfile', '/usr/share/selftest-replaceme-inst-func', self.testfile, '', expectedlines, ['selftest-replaceme-inst-func'])
self.assertNotIn('WARNING: ', output)
- @testcase(1186)
def test_recipetool_appendfile_postinstall(self):
# A file that's created by a postinstall script (and explicitly mentioned in it)
# First try without specifying recipe
self._try_recipetool_appendfile_fail('/usr/share/selftest-replaceme-postinst', self.testfile, ['File /usr/share/selftest-replaceme-postinst may be written out in a pre/postinstall script of the following recipes:', 'selftest-recipetool-appendfile'])
# Now specify recipe
- expectedlines = ['FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"\n',
+ expectedlines = ['FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:"\n',
'\n',
'SRC_URI += "file://testfile"\n',
'\n',
- 'do_install_append() {\n',
+ 'do_install:append() {\n',
' install -d ${D}${datadir}\n',
' install -m 0644 ${WORKDIR}/testfile ${D}${datadir}/selftest-replaceme-postinst\n',
'}\n']
_, output = self._try_recipetool_appendfile('selftest-recipetool-appendfile', '/usr/share/selftest-replaceme-postinst', self.testfile, '-r selftest-recipetool-appendfile', expectedlines, ['testfile'])
- @testcase(1179)
def test_recipetool_appendfile_extlayer(self):
# Try creating a bbappend in a layer that's not in bblayers.conf and has a different structure
exttemplayerdir = os.path.join(self.tempdir, 'extlayer')
@@ -338,7 +309,6 @@ class RecipetoolTests(RecipetoolBase):
'metadata/recipes/recipes-test/selftest-recipetool-appendfile/selftest-recipetool-appendfile/selftest-replaceme-orig']
self.assertEqual(sorted(createdfiles), sorted(expectedfiles))
- @testcase(1192)
def test_recipetool_appendfile_wildcard(self):
def try_appendfile_wc(options):
@@ -363,25 +333,28 @@ class RecipetoolTests(RecipetoolBase):
filename = try_appendfile_wc('-w')
self.assertEqual(filename, recipefn.split('_')[0] + '_%.bbappend')
- @testcase(1193)
+
+class RecipetoolCreateTests(RecipetoolBase):
+
def test_recipetool_create(self):
# Try adding a recipe
tempsrc = os.path.join(self.tempdir, 'srctree')
os.makedirs(tempsrc)
- recipefile = os.path.join(self.tempdir, 'logrotate_3.8.7.bb')
- srcuri = 'https://fedorahosted.org/releases/l/o/logrotate/logrotate-3.8.7.tar.gz'
+ recipefile = os.path.join(self.tempdir, 'logrotate_3.12.3.bb')
+ srcuri = 'https://github.com/logrotate/logrotate/releases/download/3.12.3/logrotate-3.12.3.tar.xz'
result = runCmd('recipetool create -o %s %s -x %s' % (recipefile, srcuri, tempsrc))
self.assertTrue(os.path.isfile(recipefile))
checkvars = {}
- checkvars['LICENSE'] = 'GPLv2'
- checkvars['LIC_FILES_CHKSUM'] = 'file://COPYING;md5=18810669f13b87348459e611d31ab760'
- checkvars['SRC_URI'] = 'https://fedorahosted.org/releases/l/o/logrotate/logrotate-${PV}.tar.gz'
- checkvars['SRC_URI[md5sum]'] = '99e08503ef24c3e2e3ff74cc5f3be213'
- checkvars['SRC_URI[sha256sum]'] = 'f6ba691f40e30e640efa2752c1f9499a3f9738257660994de70a45fe00d12b64'
+ checkvars['LICENSE'] = 'GPL-2.0-only'
+ checkvars['LIC_FILES_CHKSUM'] = 'file://COPYING;md5=b234ee4d69f5fce4486a80fdaf4a4263'
+ checkvars['SRC_URI'] = 'https://github.com/logrotate/logrotate/releases/download/${PV}/logrotate-${PV}.tar.xz'
+ checkvars['SRC_URI[md5sum]'] = 'a560c57fac87c45b2fc17406cdf79288'
+ checkvars['SRC_URI[sha256sum]'] = '2e6a401cac9024db2288297e3be1a8ab60e7401ba8e91225218aaf4a27e82a07'
self._test_recipe_contents(recipefile, checkvars, [])
- @testcase(1194)
- def test_recipetool_create_git(self):
+ def test_recipetool_create_autotools(self):
+ if 'x11' not in get_bb_var('DISTRO_FEATURES'):
+ self.skipTest('Test requires x11 as distro feature')
# Ensure we have the right data in shlibs/pkgdata
bitbake('libpng pango libx11 libxext jpeg libcheck')
# Try adding a recipe
@@ -392,22 +365,21 @@ class RecipetoolTests(RecipetoolBase):
result = runCmd(['recipetool', 'create', '-o', recipefile, srcuri + ";rev=9f7cf8895ae2d39c465c04cc78e918c157420269", '-x', tempsrc])
self.assertTrue(os.path.isfile(recipefile), 'recipetool did not create recipe file; output:\n%s' % result.output)
checkvars = {}
- checkvars['LICENSE'] = 'LGPLv2.1'
+ checkvars['LICENSE'] = 'LGPL-2.1-only'
checkvars['LIC_FILES_CHKSUM'] = 'file://COPYING;md5=7fbc338309ac38fefcd64b04bb903e34'
checkvars['S'] = '${WORKDIR}/git'
checkvars['PV'] = '1.11+git${SRCPV}'
- checkvars['SRC_URI'] = srcuri
+ checkvars['SRC_URI'] = srcuri + ';branch=master'
checkvars['DEPENDS'] = set(['libcheck', 'libjpeg-turbo', 'libpng', 'libx11', 'libxext', 'pango'])
inherits = ['autotools', 'pkgconfig']
self._test_recipe_contents(recipefile, checkvars, inherits)
- @testcase(1392)
def test_recipetool_create_simple(self):
# Try adding a recipe
temprecipe = os.path.join(self.tempdir, 'recipe')
os.makedirs(temprecipe)
- pv = '1.7.3.0'
- srcuri = 'http://www.dest-unreach.org/socat/download/socat-%s.tar.bz2' % pv
+ pv = '1.7.4.1'
+ srcuri = 'http://www.dest-unreach.org/socat/download/Archive/socat-%s.tar.bz2' % pv
result = runCmd('recipetool create %s -o %s' % (srcuri, temprecipe))
dirlist = os.listdir(temprecipe)
if len(dirlist) > 1:
@@ -416,7 +388,7 @@ class RecipetoolTests(RecipetoolBase):
self.fail('recipetool did not create recipe file; output:\n%s\ndirlist:\n%s' % (result.output, str(dirlist)))
self.assertEqual(dirlist[0], 'socat_%s.bb' % pv, 'Recipe file incorrectly named')
checkvars = {}
- checkvars['LICENSE'] = set(['Unknown', 'GPLv2'])
+ checkvars['LICENSE'] = set(['Unknown', 'GPL-2.0-only'])
checkvars['LIC_FILES_CHKSUM'] = set(['file://COPYING.OpenSSL;md5=5c9bccc77f67a8328ef4ebaf468116f4', 'file://COPYING;md5=b234ee4d69f5fce4486a80fdaf4a4263'])
# We don't check DEPENDS since they are variable for this recipe depending on what's in the sysroot
checkvars['S'] = None
@@ -424,24 +396,308 @@ class RecipetoolTests(RecipetoolBase):
inherits = ['autotools']
self._test_recipe_contents(os.path.join(temprecipe, dirlist[0]), checkvars, inherits)
- @testcase(1418)
def test_recipetool_create_cmake(self):
- # Try adding a recipe
temprecipe = os.path.join(self.tempdir, 'recipe')
os.makedirs(temprecipe)
- recipefile = os.path.join(temprecipe, 'navit_0.5.0.bb')
- srcuri = 'http://downloads.sourceforge.net/project/navit/v0.5.0/navit-0.5.0.tar.gz'
+ recipefile = os.path.join(temprecipe, 'taglib_1.11.1.bb')
+ srcuri = 'http://taglib.github.io/releases/taglib-1.11.1.tar.gz'
result = runCmd('recipetool create -o %s %s' % (temprecipe, srcuri))
self.assertTrue(os.path.isfile(recipefile))
checkvars = {}
- checkvars['LICENSE'] = set(['Unknown', 'GPLv2', 'LGPLv2'])
- checkvars['SRC_URI'] = 'http://downloads.sourceforge.net/project/navit/v${PV}/navit-${PV}.tar.gz'
- checkvars['SRC_URI[md5sum]'] = '242f398e979a6b8c0f3c802b63435b68'
- checkvars['SRC_URI[sha256sum]'] = '13353481d7fc01a4f64e385dda460b51496366bba0fd2cc85a89a0747910e94d'
- checkvars['DEPENDS'] = set(['freetype', 'zlib', 'openssl', 'glib-2.0', 'virtual/libgl', 'virtual/egl', 'gtk+', 'libpng', 'libsdl', 'freeglut', 'dbus-glib'])
- inherits = ['cmake', 'python-dir', 'gettext', 'pkgconfig']
+ checkvars['LICENSE'] = set(['LGPL-2.1-only', 'MPL-1.1-only'])
+ checkvars['SRC_URI'] = 'http://taglib.github.io/releases/taglib-${PV}.tar.gz'
+ checkvars['SRC_URI[md5sum]'] = 'cee7be0ccfc892fa433d6c837df9522a'
+ checkvars['SRC_URI[sha256sum]'] = 'b6d1a5a610aae6ff39d93de5efd0fdc787aa9e9dc1e7026fa4c961b26563526b'
+ checkvars['DEPENDS'] = set(['boost', 'zlib'])
+ inherits = ['cmake']
+ self._test_recipe_contents(recipefile, checkvars, inherits)
+
+ def test_recipetool_create_npm(self):
+ collections = get_bb_var('BBFILE_COLLECTIONS').split()
+ if "openembedded-layer" not in collections:
+ self.skipTest("Test needs meta-oe for nodejs")
+
+ temprecipe = os.path.join(self.tempdir, 'recipe')
+ os.makedirs(temprecipe)
+ recipefile = os.path.join(temprecipe, 'savoirfairelinux-node-server-example_1.0.0.bb')
+ shrinkwrap = os.path.join(temprecipe, 'savoirfairelinux-node-server-example', 'npm-shrinkwrap.json')
+ srcuri = 'npm://registry.npmjs.org;package=@savoirfairelinux/node-server-example;version=1.0.0'
+ result = runCmd('recipetool create -o %s \'%s\'' % (temprecipe, srcuri))
+ self.assertTrue(os.path.isfile(recipefile))
+ self.assertTrue(os.path.isfile(shrinkwrap))
+ checkvars = {}
+ checkvars['SUMMARY'] = 'Node Server Example'
+ checkvars['HOMEPAGE'] = 'https://github.com/savoirfairelinux/node-server-example#readme'
+ checkvars['LICENSE'] = 'BSD-3-Clause & ISC & MIT & Unknown'
+ urls = []
+ urls.append('npm://registry.npmjs.org/;package=@savoirfairelinux/node-server-example;version=${PV}')
+ urls.append('npmsw://${THISDIR}/${BPN}/npm-shrinkwrap.json')
+ checkvars['SRC_URI'] = set(urls)
+ checkvars['S'] = '${WORKDIR}/npm'
+ checkvars['LICENSE:${PN}'] = 'MIT'
+ checkvars['LICENSE:${PN}-base64'] = 'Unknown'
+ checkvars['LICENSE:${PN}-accepts'] = 'MIT'
+ checkvars['LICENSE:${PN}-inherits'] = 'ISC'
+ inherits = ['npm']
self._test_recipe_contents(recipefile, checkvars, inherits)
+ def test_recipetool_create_github(self):
+ # Basic test to see if github URL mangling works
+ temprecipe = os.path.join(self.tempdir, 'recipe')
+ os.makedirs(temprecipe)
+ recipefile = os.path.join(temprecipe, 'meson_git.bb')
+ srcuri = 'https://github.com/mesonbuild/meson;rev=0.32.0'
+ result = runCmd(['recipetool', 'create', '-o', temprecipe, srcuri])
+ self.assertTrue(os.path.isfile(recipefile))
+ checkvars = {}
+ checkvars['LICENSE'] = set(['Apache-2.0'])
+ checkvars['SRC_URI'] = 'git://github.com/mesonbuild/meson;protocol=https;branch=master'
+ inherits = ['setuptools3']
+ self._test_recipe_contents(recipefile, checkvars, inherits)
+
+ def test_recipetool_create_python3_setuptools(self):
+ # Test creating python3 package from tarball (using setuptools3 class)
+ temprecipe = os.path.join(self.tempdir, 'recipe')
+ os.makedirs(temprecipe)
+ pn = 'python-magic'
+ pv = '0.4.15'
+ recipefile = os.path.join(temprecipe, '%s_%s.bb' % (pn, pv))
+ srcuri = 'https://files.pythonhosted.org/packages/84/30/80932401906eaf787f2e9bd86dc458f1d2e75b064b4c187341f29516945c/python-magic-%s.tar.gz' % pv
+ result = runCmd('recipetool create -o %s %s' % (temprecipe, srcuri))
+ self.assertTrue(os.path.isfile(recipefile))
+ checkvars = {}
+ checkvars['LICENSE'] = set(['MIT'])
+ checkvars['LIC_FILES_CHKSUM'] = 'file://LICENSE;md5=16a934f165e8c3245f241e77d401bb88'
+ checkvars['SRC_URI'] = 'https://files.pythonhosted.org/packages/84/30/80932401906eaf787f2e9bd86dc458f1d2e75b064b4c187341f29516945c/python-magic-${PV}.tar.gz'
+ checkvars['SRC_URI[md5sum]'] = 'e384c95a47218f66c6501cd6dd45ff59'
+ checkvars['SRC_URI[sha256sum]'] = 'f3765c0f582d2dfc72c15f3b5a82aecfae9498bd29ca840d72f37d7bd38bfcd5'
+ inherits = ['setuptools3']
+ self._test_recipe_contents(recipefile, checkvars, inherits)
+
+ def test_recipetool_create_github_tarball(self):
+ # Basic test to ensure github URL mangling doesn't apply to release tarballs
+ temprecipe = os.path.join(self.tempdir, 'recipe')
+ os.makedirs(temprecipe)
+ pv = '0.32.0'
+ recipefile = os.path.join(temprecipe, 'meson_%s.bb' % pv)
+ srcuri = 'https://github.com/mesonbuild/meson/releases/download/%s/meson-%s.tar.gz' % (pv, pv)
+ result = runCmd('recipetool create -o %s %s' % (temprecipe, srcuri))
+ self.assertTrue(os.path.isfile(recipefile))
+ checkvars = {}
+ checkvars['LICENSE'] = set(['Apache-2.0'])
+ checkvars['SRC_URI'] = 'https://github.com/mesonbuild/meson/releases/download/${PV}/meson-${PV}.tar.gz'
+ inherits = ['setuptools3']
+ self._test_recipe_contents(recipefile, checkvars, inherits)
+
+ def _test_recipetool_create_git(self, srcuri, branch=None):
+ # Basic test to check http git URL mangling works
+ temprecipe = os.path.join(self.tempdir, 'recipe')
+ os.makedirs(temprecipe)
+ name = srcuri.split(';')[0].split('/')[-1]
+ recipefile = os.path.join(temprecipe, name + '_git.bb')
+ options = ' -B %s' % branch if branch else ''
+ result = runCmd('recipetool create -o %s%s "%s"' % (temprecipe, options, srcuri))
+ self.assertTrue(os.path.isfile(recipefile))
+ checkvars = {}
+ checkvars['SRC_URI'] = srcuri
+ for scheme in ['http', 'https']:
+ if srcuri.startswith(scheme + ":"):
+ checkvars['SRC_URI'] = 'git%s;protocol=%s' % (srcuri[len(scheme):], scheme)
+ if ';branch=' not in srcuri:
+ checkvars['SRC_URI'] += ';branch=' + (branch or 'master')
+ self._test_recipe_contents(recipefile, checkvars, [])
+
+ def test_recipetool_create_git_http(self):
+ self._test_recipetool_create_git('http://git.yoctoproject.org/git/matchbox-keyboard')
+
+ def test_recipetool_create_git_srcuri_master(self):
+ self._test_recipetool_create_git('git://git.yoctoproject.org/matchbox-keyboard;branch=master')
+
+ def test_recipetool_create_git_srcuri_branch(self):
+ self._test_recipetool_create_git('git://git.yoctoproject.org/matchbox-keyboard;branch=matchbox-keyboard-0-1')
+
+ def test_recipetool_create_git_srcbranch(self):
+ self._test_recipetool_create_git('git://git.yoctoproject.org/matchbox-keyboard', 'matchbox-keyboard-0-1')
+
+
+class RecipetoolTests(RecipetoolBase):
+
+ @classmethod
+ def setUpClass(cls):
+ import sys
+
+ super(RecipetoolTests, cls).setUpClass()
+ bb_vars = get_bb_vars(['BBPATH'])
+ cls.bbpath = bb_vars['BBPATH']
+ libpath = os.path.join(get_bb_var('COREBASE'), 'scripts', 'lib', 'recipetool')
+ sys.path.insert(0, libpath)
+
+ def _copy_file_with_cleanup(self, srcfile, basedstdir, *paths):
+ dstdir = basedstdir
+ self.assertTrue(os.path.exists(dstdir))
+ for p in paths:
+ dstdir = os.path.join(dstdir, p)
+ if not os.path.exists(dstdir):
+ os.makedirs(dstdir)
+ if p == "lib":
+ # Can race with other tests
+ self.add_command_to_tearDown('rmdir --ignore-fail-on-non-empty %s' % dstdir)
+ else:
+ self.track_for_cleanup(dstdir)
+ dstfile = os.path.join(dstdir, os.path.basename(srcfile))
+ if srcfile != dstfile:
+ shutil.copy(srcfile, dstfile)
+ self.track_for_cleanup(dstfile)
+
+ def test_recipetool_load_plugin(self):
+ """Test that recipetool loads only the first found plugin in BBPATH."""
+
+ recipetool = runCmd("which recipetool")
+ fromname = runCmd("recipetool --quiet pluginfile")
+ srcfile = fromname.output
+ searchpath = self.bbpath.split(':') + [os.path.dirname(recipetool.output)]
+ plugincontent = []
+ with open(srcfile) as fh:
+ plugincontent = fh.readlines()
+ try:
+ self.assertIn('meta-selftest', srcfile, 'wrong bbpath plugin found')
+ for path in searchpath:
+ self._copy_file_with_cleanup(srcfile, path, 'lib', 'recipetool')
+ result = runCmd("recipetool --quiet count")
+ self.assertEqual(result.output, '1')
+ result = runCmd("recipetool --quiet multiloaded")
+ self.assertEqual(result.output, "no")
+ for path in searchpath:
+ result = runCmd("recipetool --quiet bbdir")
+ self.assertEqual(result.output, path)
+ os.unlink(os.path.join(result.output, 'lib', 'recipetool', 'bbpath.py'))
+ finally:
+ with open(srcfile, 'w') as fh:
+ fh.writelines(plugincontent)
+
+ def test_recipetool_handle_license_vars(self):
+ from create import handle_license_vars
+ from unittest.mock import Mock
+
+ commonlicdir = get_bb_var('COMMON_LICENSE_DIR')
+
+ d = bb.tinfoil.TinfoilDataStoreConnector
+ d.getVar = Mock(return_value=commonlicdir)
+
+ srctree = tempfile.mkdtemp(prefix='recipetoolqa')
+ self.track_for_cleanup(srctree)
+
+ # Multiple licenses
+ licenses = ['MIT', 'ISC', 'BSD-3-Clause', 'Apache-2.0']
+ for licence in licenses:
+ shutil.copy(os.path.join(commonlicdir, licence), os.path.join(srctree, 'LICENSE.' + licence))
+ # Duplicate license
+ shutil.copy(os.path.join(commonlicdir, 'MIT'), os.path.join(srctree, 'LICENSE'))
+
+ extravalues = {
+ # Duplicate and missing licenses
+ 'LICENSE': 'Zlib & BSD-2-Clause & Zlib',
+ 'LIC_FILES_CHKSUM': [
+ 'file://README.md;md5=0123456789abcdef0123456789abcd'
+ ]
+ }
+ lines_before = []
+ handled = []
+ licvalues = handle_license_vars(srctree, lines_before, handled, extravalues, d)
+ expected_lines_before = [
+ '# WARNING: the following LICENSE and LIC_FILES_CHKSUM values are best guesses - it is',
+ '# your responsibility to verify that the values are complete and correct.',
+ '# NOTE: Original package / source metadata indicates license is: BSD-2-Clause & Zlib',
+ '#',
+ '# NOTE: multiple licenses have been detected; they have been separated with &',
+ '# in the LICENSE value for now since it is a reasonable assumption that all',
+ '# of the licenses apply. If instead there is a choice between the multiple',
+ '# licenses then you should change the value to separate the licenses with |',
+ '# instead of &. If there is any doubt, check the accompanying documentation',
+ '# to determine which situation is applicable.',
+ 'LICENSE = "Apache-2.0 & BSD-2-Clause & BSD-3-Clause & ISC & MIT & Zlib"',
+ 'LIC_FILES_CHKSUM = "file://LICENSE;md5=0835ade698e0bcf8506ecda2f7b4f302 \\\n'
+ ' file://LICENSE.Apache-2.0;md5=89aea4e17d99a7cacdbeed46a0096b10 \\\n'
+ ' file://LICENSE.BSD-3-Clause;md5=550794465ba0ec5312d6919e203a55f9 \\\n'
+ ' file://LICENSE.ISC;md5=f3b90e78ea0cffb20bf5cca7947a896d \\\n'
+ ' file://LICENSE.MIT;md5=0835ade698e0bcf8506ecda2f7b4f302 \\\n'
+ ' file://README.md;md5=0123456789abcdef0123456789abcd"',
+ ''
+ ]
+ self.assertEqual(lines_before, expected_lines_before)
+ expected_licvalues = [
+ ('MIT', 'LICENSE', '0835ade698e0bcf8506ecda2f7b4f302'),
+ ('Apache-2.0', 'LICENSE.Apache-2.0', '89aea4e17d99a7cacdbeed46a0096b10'),
+ ('BSD-3-Clause', 'LICENSE.BSD-3-Clause', '550794465ba0ec5312d6919e203a55f9'),
+ ('ISC', 'LICENSE.ISC', 'f3b90e78ea0cffb20bf5cca7947a896d'),
+ ('MIT', 'LICENSE.MIT', '0835ade698e0bcf8506ecda2f7b4f302')
+ ]
+ self.assertEqual(handled, [('license', expected_licvalues)])
+ self.assertEqual(extravalues, {})
+ self.assertEqual(licvalues, expected_licvalues)
+
+
+ def test_recipetool_split_pkg_licenses(self):
+ from create import split_pkg_licenses
+ licvalues = [
+ # Duplicate licenses
+ ('BSD-2-Clause', 'x/COPYING', None),
+ ('BSD-2-Clause', 'x/LICENSE', None),
+ # Multiple licenses
+ ('MIT', 'x/a/LICENSE.MIT', None),
+ ('ISC', 'x/a/LICENSE.ISC', None),
+ # Alternative licenses
+ ('(MIT | ISC)', 'x/b/LICENSE', None),
+ # Alternative licenses without brackets
+ ('MIT | BSD-2-Clause', 'x/c/LICENSE', None),
+ # Multi licenses with alternatives
+ ('MIT', 'x/d/COPYING', None),
+ ('MIT | BSD-2-Clause', 'x/d/LICENSE', None),
+ # Multi licenses with alternatives and brackets
+ ('Apache-2.0 & ((MIT | ISC) & BSD-3-Clause)', 'x/e/LICENSE', None)
+ ]
+ packages = {
+ '${PN}': '',
+ 'a': 'x/a',
+ 'b': 'x/b',
+ 'c': 'x/c',
+ 'd': 'x/d',
+ 'e': 'x/e',
+ 'f': 'x/f',
+ 'g': 'x/g',
+ }
+ fallback_licenses = {
+ # Ignored
+ 'a': 'BSD-3-Clause',
+ # Used
+ 'f': 'BSD-3-Clause'
+ }
+ outlines = []
+ outlicenses = split_pkg_licenses(licvalues, packages, outlines, fallback_licenses)
+ expected_outlicenses = {
+ '${PN}': ['BSD-2-Clause'],
+ 'a': ['ISC', 'MIT'],
+ 'b': ['(ISC | MIT)'],
+ 'c': ['(BSD-2-Clause | MIT)'],
+ 'd': ['(BSD-2-Clause | MIT)', 'MIT'],
+ 'e': ['(ISC | MIT)', 'Apache-2.0', 'BSD-3-Clause'],
+ 'f': ['BSD-3-Clause'],
+ 'g': ['Unknown']
+ }
+ self.assertEqual(outlicenses, expected_outlicenses)
+ expected_outlines = [
+ 'LICENSE:${PN} = "BSD-2-Clause"',
+ 'LICENSE:a = "ISC & MIT"',
+ 'LICENSE:b = "(ISC | MIT)"',
+ 'LICENSE:c = "(BSD-2-Clause | MIT)"',
+ 'LICENSE:d = "(BSD-2-Clause | MIT) & MIT"',
+ 'LICENSE:e = "(ISC | MIT) & Apache-2.0 & BSD-3-Clause"',
+ 'LICENSE:f = "BSD-3-Clause"',
+ 'LICENSE:g = "Unknown"'
+ ]
+ self.assertEqual(outlines, expected_outlines)
+
+
class RecipetoolAppendsrcBase(RecipetoolBase):
def _try_recipetool_appendsrcfile(self, testrecipe, newfile, destfile, options, expectedlines, expectedfiles):
cmd = 'recipetool appendsrcfile %s %s %s %s %s' % (options, self.templayerdir, testrecipe, newfile, destfile)
@@ -500,7 +756,7 @@ class RecipetoolAppendsrcBase(RecipetoolBase):
else:
destpath = '.' + os.sep
- expectedlines = ['FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"\n',
+ expectedlines = ['FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:"\n',
'\n']
if has_src_uri:
uri = 'file://%s' % filename
@@ -517,27 +773,28 @@ class RecipetoolAppendsrcBase(RecipetoolBase):
self._try_recipetool_appendsrcfiles(testrecipe, newfiles, expectedfiles=expectedfiles, destdir=destdir, options=options)
- src_uri = get_bb_var('SRC_URI', testrecipe).split()
+ bb_vars = get_bb_vars(['SRC_URI', 'FILE', 'FILESEXTRAPATHS'], testrecipe)
+ src_uri = bb_vars['SRC_URI'].split()
for f in expectedfiles:
if destdir:
self.assertIn('file://%s;subdir=%s' % (f, destdir), src_uri)
else:
self.assertIn('file://%s' % f, src_uri)
- recipefile = get_bb_var('FILE', testrecipe)
+ recipefile = bb_vars['FILE']
bbappendfile = self._check_bbappend(testrecipe, recipefile, self.templayerdir)
filesdir = os.path.join(os.path.dirname(bbappendfile), testrecipe)
- filesextrapaths = get_bb_var('FILESEXTRAPATHS', testrecipe).split(':')
+ filesextrapaths = bb_vars['FILESEXTRAPATHS'].split(':')
self.assertIn(filesdir, filesextrapaths)
+
+
class RecipetoolAppendsrcTests(RecipetoolAppendsrcBase):
- @testcase(1273)
def test_recipetool_appendsrcfile_basic(self):
self._test_appendsrcfile('base-files', 'a-file')
- @testcase(1274)
def test_recipetool_appendsrcfile_basic_wildcard(self):
testrecipe = 'base-files'
self._test_appendsrcfile(testrecipe, 'a-file', options='-w')
@@ -545,30 +802,26 @@ class RecipetoolAppendsrcTests(RecipetoolAppendsrcBase):
bbappendfile = self._check_bbappend(testrecipe, recipefile, self.templayerdir)
self.assertEqual(os.path.basename(bbappendfile), '%s_%%.bbappend' % testrecipe)
- @testcase(1281)
def test_recipetool_appendsrcfile_subdir_basic(self):
self._test_appendsrcfile('base-files', 'a-file', 'tmp')
- @testcase(1282)
def test_recipetool_appendsrcfile_subdir_basic_dirdest(self):
self._test_appendsrcfile('base-files', destdir='tmp')
- @testcase(1280)
def test_recipetool_appendsrcfile_srcdir_basic(self):
testrecipe = 'bash'
- srcdir = get_bb_var('S', testrecipe)
- workdir = get_bb_var('WORKDIR', testrecipe)
+ bb_vars = get_bb_vars(['S', 'WORKDIR'], testrecipe)
+ srcdir = bb_vars['S']
+ workdir = bb_vars['WORKDIR']
subdir = os.path.relpath(srcdir, workdir)
self._test_appendsrcfile(testrecipe, 'a-file', srcdir=subdir)
- @testcase(1275)
def test_recipetool_appendsrcfile_existing_in_src_uri(self):
testrecipe = 'base-files'
filepath = self._get_first_file_uri(testrecipe)
self.assertTrue(filepath, 'Unable to test, no file:// uri found in SRC_URI for %s' % testrecipe)
self._test_appendsrcfile(testrecipe, filepath, has_src_uri=False)
- @testcase(1276)
def test_recipetool_appendsrcfile_existing_in_src_uri_diff_params(self):
testrecipe = 'base-files'
subdir = 'tmp'
@@ -578,19 +831,20 @@ class RecipetoolAppendsrcTests(RecipetoolAppendsrcBase):
output = self._test_appendsrcfile(testrecipe, filepath, subdir, has_src_uri=False)
self.assertTrue(any('with different parameters' in l for l in output))
- @testcase(1277)
def test_recipetool_appendsrcfile_replace_file_srcdir(self):
testrecipe = 'bash'
filepath = 'Makefile.in'
- srcdir = get_bb_var('S', testrecipe)
- workdir = get_bb_var('WORKDIR', testrecipe)
+ bb_vars = get_bb_vars(['S', 'WORKDIR'], testrecipe)
+ srcdir = bb_vars['S']
+ workdir = bb_vars['WORKDIR']
subdir = os.path.relpath(srcdir, workdir)
self._test_appendsrcfile(testrecipe, filepath, srcdir=subdir)
bitbake('%s:do_unpack' % testrecipe)
- self.assertEqual(open(self.testfile, 'r').read(), open(os.path.join(srcdir, filepath), 'r').read())
+ with open(self.testfile, 'r') as testfile:
+ with open(os.path.join(srcdir, filepath), 'r') as makefilein:
+ self.assertEqual(testfile.read(), makefilein.read())
- @testcase(1278)
def test_recipetool_appendsrcfiles_basic(self, destdir=None):
newfiles = [self.testfile]
for i in range(1, 5):
@@ -600,6 +854,5 @@ class RecipetoolAppendsrcTests(RecipetoolAppendsrcBase):
newfiles.append(testfile)
self._test_appendsrcfiles('gcc', newfiles, destdir=destdir, options='-W')
- @testcase(1279)
def test_recipetool_appendsrcfiles_basic_subdir(self):
self.test_recipetool_appendsrcfiles_basic(destdir='testdir')
diff --git a/meta/lib/oeqa/selftest/cases/recipeutils.py b/meta/lib/oeqa/selftest/cases/recipeutils.py
new file mode 100644
index 0000000000..6334f1c91a
--- /dev/null
+++ b/meta/lib/oeqa/selftest/cases/recipeutils.py
@@ -0,0 +1,138 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
+import bb.tinfoil
+
+from oeqa.selftest.case import OESelftestTestCase
+from oeqa.utils.commands import get_test_layer
+
+
+def setUpModule():
+ global tinfoil
+ global metaselftestpath
+ metaselftestpath = get_test_layer()
+ tinfoil = bb.tinfoil.Tinfoil(tracking=True)
+ tinfoil.prepare(config_only=False, quiet=2)
+
+
+def tearDownModule():
+ tinfoil.shutdown()
+
+
+class RecipeUtilsTests(OESelftestTestCase):
+ """ Tests for the recipeutils module functions """
+
+ def test_patch_recipe_varflag(self):
+ import oe.recipeutils
+ rd = tinfoil.parse_recipe('python3-async-test')
+ vals = {'SRC_URI[md5sum]': 'aaaaaa', 'LICENSE': 'something'}
+ patches = oe.recipeutils.patch_recipe(rd, rd.getVar('FILE'), vals, patch=True, relpath=metaselftestpath)
+
+ expected_patch = """
+--- a/recipes-devtools/python/python-async-test.inc
++++ b/recipes-devtools/python/python-async-test.inc
+@@ -1,14 +1,14 @@
+ SUMMARY = "Python framework to process interdependent tasks in a pool of workers"
+ HOMEPAGE = "http://github.com/gitpython-developers/async"
+ SECTION = "devel/python"
+-LICENSE = "BSD-3-Clause"
++LICENSE = "something"
+ LIC_FILES_CHKSUM = "file://PKG-INFO;beginline=8;endline=8;md5=88df8e78b9edfd744953862179f2d14e"
+
+ inherit pypi
+
+ PYPI_PACKAGE = "async"
+
+-SRC_URI[md5sum] = "9b06b5997de2154f3bc0273f80bcef6b"
++SRC_URI[md5sum] = "aaaaaa"
+ SRC_URI[sha256sum] = "ac6894d876e45878faae493b0cf61d0e28ec417334448ac0a6ea2229d8343051"
+
+ RDEPENDS:${PN} += "${PYTHON_PN}-threading"
+"""
+ patchlines = []
+ for f in patches:
+ for line in f:
+ patchlines.append(line)
+ self.maxDiff = None
+ self.assertEqual(''.join(patchlines).strip(), expected_patch.strip())
+
+
+ def test_patch_recipe_singleappend(self):
+ import oe.recipeutils
+ rd = tinfoil.parse_recipe('recipeutils-test')
+ val = rd.getVar('SRC_URI', False).split()
+ del val[1]
+ val = ' '.join(val)
+ vals = {'SRC_URI': val}
+ patches = oe.recipeutils.patch_recipe(rd, rd.getVar('FILE'), vals, patch=True, relpath=metaselftestpath)
+
+ expected_patch = """
+--- a/recipes-test/recipeutils/recipeutils-test_1.2.bb
++++ b/recipes-test/recipeutils/recipeutils-test_1.2.bb
+@@ -8,6 +8,4 @@
+
+ BBCLASSEXTEND = "native nativesdk"
+
+-SRC_URI += "file://somefile"
+-
+ SRC_URI:append = " file://anotherfile"
+"""
+ patchlines = []
+ for f in patches:
+ for line in f:
+ patchlines.append(line)
+ self.assertEqual(''.join(patchlines).strip(), expected_patch.strip())
+
+
+ def test_patch_recipe_appends(self):
+ import oe.recipeutils
+ rd = tinfoil.parse_recipe('recipeutils-test')
+ val = rd.getVar('SRC_URI', False).split()
+ vals = {'SRC_URI': val[0]}
+ patches = oe.recipeutils.patch_recipe(rd, rd.getVar('FILE'), vals, patch=True, relpath=metaselftestpath)
+
+ expected_patch = """
+--- a/recipes-test/recipeutils/recipeutils-test_1.2.bb
++++ b/recipes-test/recipeutils/recipeutils-test_1.2.bb
+@@ -8,6 +8,3 @@
+
+ BBCLASSEXTEND = "native nativesdk"
+
+-SRC_URI += "file://somefile"
+-
+-SRC_URI:append = " file://anotherfile"
+"""
+ patchlines = []
+ for f in patches:
+ for line in f:
+ patchlines.append(line)
+ self.assertEqual(''.join(patchlines).strip(), expected_patch.strip())
+
+
+ def test_validate_pn(self):
+ import oe.recipeutils
+ expected_results = {
+ 'test': '',
+ 'glib-2.0': '',
+ 'gtk+': '',
+ 'forcevariable': 'reserved',
+ 'pn-something': 'reserved',
+ 'test.bb': 'file',
+ 'test_one': 'character',
+ 'test!': 'character',
+ }
+
+ for pn, expected in expected_results.items():
+ result = oe.recipeutils.validate_pn(pn)
+ if expected:
+ self.assertIn(expected, result)
+ else:
+ self.assertEqual(result, '')
+
+ def test_split_var_value(self):
+ import oe.recipeutils
+ res = oe.recipeutils.split_var_value('test.1 test.2 ${@call_function("hi there world", false)} test.4')
+ self.assertEqual(res, ['test.1', 'test.2', '${@call_function("hi there world", false)}', 'test.4'])
diff --git a/meta/lib/oeqa/selftest/cases/reproducible.py b/meta/lib/oeqa/selftest/cases/reproducible.py
new file mode 100644
index 0000000000..f4dd779842
--- /dev/null
+++ b/meta/lib/oeqa/selftest/cases/reproducible.py
@@ -0,0 +1,316 @@
+#
+# SPDX-License-Identifier: MIT
+#
+# Copyright 2019-2020 by Garmin Ltd. or its subsidiaries
+
+from oeqa.selftest.case import OESelftestTestCase
+from oeqa.utils.commands import runCmd, bitbake, get_bb_var, get_bb_vars
+import bb.utils
+import functools
+import multiprocessing
+import textwrap
+import tempfile
+import shutil
+import stat
+import os
+import datetime
+
+exclude_packages = [
+ 'rust',
+ 'rust-dbg'
+ ]
+
+def is_excluded(package):
+ package_name = os.path.basename(package)
+ for i in exclude_packages:
+ if package_name.startswith(i):
+ return i
+ return None
+
+MISSING = 'MISSING'
+DIFFERENT = 'DIFFERENT'
+SAME = 'SAME'
+
+@functools.total_ordering
+class CompareResult(object):
+ def __init__(self):
+ self.reference = None
+ self.test = None
+ self.status = 'UNKNOWN'
+
+ def __eq__(self, other):
+ return (self.status, self.test) == (other.status, other.test)
+
+ def __lt__(self, other):
+ return (self.status, self.test) < (other.status, other.test)
+
+class PackageCompareResults(object):
+ def __init__(self):
+ self.total = []
+ self.missing = []
+ self.different = []
+ self.different_excluded = []
+ self.same = []
+ self.active_exclusions = set()
+
+ def add_result(self, r):
+ self.total.append(r)
+ if r.status == MISSING:
+ self.missing.append(r)
+ elif r.status == DIFFERENT:
+ exclusion = is_excluded(r.reference)
+ if exclusion:
+ self.different_excluded.append(r)
+ self.active_exclusions.add(exclusion)
+ else:
+ self.different.append(r)
+ else:
+ self.same.append(r)
+
+ def sort(self):
+ self.total.sort()
+ self.missing.sort()
+ self.different.sort()
+ self.different_excluded.sort()
+ self.same.sort()
+
+ def __str__(self):
+ return 'same=%i different=%i different_excluded=%i missing=%i total=%i\nunused_exclusions=%s' % (len(self.same), len(self.different), len(self.different_excluded), len(self.missing), len(self.total), self.unused_exclusions())
+
+ def unused_exclusions(self):
+ return sorted(set(exclude_packages) - self.active_exclusions)
+
+def compare_file(reference, test, diffutils_sysroot):
+ result = CompareResult()
+ result.reference = reference
+ result.test = test
+
+ if not os.path.exists(reference):
+ result.status = MISSING
+ return result
+
+ r = runCmd(['cmp', '--quiet', reference, test], native_sysroot=diffutils_sysroot, ignore_status=True, sync=False)
+
+ if r.status:
+ result.status = DIFFERENT
+ return result
+
+ result.status = SAME
+ return result
+
+def run_diffoscope(a_dir, b_dir, html_dir, max_report_size=0, **kwargs):
+ return runCmd(['diffoscope', '--no-default-limits', '--max-report-size', str(max_report_size),
+ '--exclude-directory-metadata', 'yes', '--html-dir', html_dir, a_dir, b_dir],
+ **kwargs)
+
+class DiffoscopeTests(OESelftestTestCase):
+ diffoscope_test_files = os.path.join(os.path.dirname(os.path.abspath(__file__)), "diffoscope")
+
+ def test_diffoscope(self):
+ bitbake("diffoscope-native -c addto_recipe_sysroot")
+ diffoscope_sysroot = get_bb_var("RECIPE_SYSROOT_NATIVE", "diffoscope-native")
+
+ # Check that diffoscope doesn't return an error when the files compare
+ # the same (a general check that diffoscope is working)
+ with tempfile.TemporaryDirectory() as tmpdir:
+ run_diffoscope('A', 'A', tmpdir,
+ native_sysroot=diffoscope_sysroot, cwd=self.diffoscope_test_files)
+
+ # Check that diffoscope generates an index.html file when the files are
+ # different
+ with tempfile.TemporaryDirectory() as tmpdir:
+ r = run_diffoscope('A', 'B', tmpdir,
+ native_sysroot=diffoscope_sysroot, ignore_status=True, cwd=self.diffoscope_test_files)
+
+ self.assertNotEqual(r.status, 0, msg="diffoscope was successful when an error was expected")
+ self.assertTrue(os.path.exists(os.path.join(tmpdir, 'index.html')), "HTML index not found!")
+
+class ReproducibleTests(OESelftestTestCase):
+ # Test the reproducibility of whatever is built between sstate_targets and targets
+
+ package_classes = ['deb', 'ipk', 'rpm']
+
+ # Maximum report size, in bytes
+ max_report_size = 250 * 1024 * 1024
+
+ # targets are the things we want to test the reproducibility of
+ targets = ['core-image-minimal', 'core-image-sato', 'core-image-full-cmdline', 'core-image-weston', 'world']
+ # sstate targets are things to pull from sstate to potentially cut build/debugging time
+ sstate_targets = []
+ save_results = False
+ if 'OEQA_DEBUGGING_SAVED_OUTPUT' in os.environ:
+ save_results = os.environ['OEQA_DEBUGGING_SAVED_OUTPUT']
+
+ # This variable controls if one of the test builds is allowed to pull from
+ # an sstate cache/mirror. The other build is always done clean as a point of
+ # comparison.
+ # If you know that your sstate archives are reproducible, enabling this
+ # will test that and also make the test run faster. If your sstate is not
+ # reproducible, disable this in your derived test class
+ build_from_sstate = True
+
+ def setUpLocal(self):
+ super().setUpLocal()
+ needed_vars = ['TOPDIR', 'TARGET_PREFIX', 'BB_NUMBER_THREADS']
+ bb_vars = get_bb_vars(needed_vars)
+ for v in needed_vars:
+ setattr(self, v.lower(), bb_vars[v])
+
+ self.extraresults = {}
+ self.extraresults.setdefault('reproducible.rawlogs', {})['log'] = ''
+ self.extraresults.setdefault('reproducible', {}).setdefault('files', {})
+
+ def append_to_log(self, msg):
+ self.extraresults['reproducible.rawlogs']['log'] += msg
+
+ def compare_packages(self, reference_dir, test_dir, diffutils_sysroot):
+ result = PackageCompareResults()
+
+ old_cwd = os.getcwd()
+ try:
+ file_result = {}
+ os.chdir(test_dir)
+ with multiprocessing.Pool(processes=int(self.bb_number_threads or 0)) as p:
+ for root, dirs, files in os.walk('.'):
+ async_result = []
+ for f in files:
+ reference_path = os.path.join(reference_dir, root, f)
+ test_path = os.path.join(test_dir, root, f)
+ async_result.append(p.apply_async(compare_file, (reference_path, test_path, diffutils_sysroot)))
+
+ for a in async_result:
+ result.add_result(a.get())
+
+ finally:
+ os.chdir(old_cwd)
+
+ result.sort()
+ return result
+
+ def write_package_list(self, package_class, name, packages):
+ self.extraresults['reproducible']['files'].setdefault(package_class, {})[name] = [
+ {'reference': p.reference, 'test': p.test} for p in packages]
+
+ def copy_file(self, source, dest):
+ bb.utils.mkdirhier(os.path.dirname(dest))
+ shutil.copyfile(source, dest)
+
+ def do_test_build(self, name, use_sstate):
+ capture_vars = ['DEPLOY_DIR_' + c.upper() for c in self.package_classes]
+
+ tmpdir = os.path.join(self.topdir, name, 'tmp')
+ if os.path.exists(tmpdir):
+ bb.utils.remove(tmpdir, recurse=True)
+
+ config = textwrap.dedent('''\
+ PACKAGE_CLASSES = "{package_classes}"
+ INHIBIT_PACKAGE_STRIP = "1"
+ TMPDIR = "{tmpdir}"
+ LICENSE_FLAGS_ACCEPTED = "commercial"
+ DISTRO_FEATURES:append = ' systemd pam'
+ USERADDEXTENSION = "useradd-staticids"
+ USERADD_ERROR_DYNAMIC = "skip"
+ USERADD_UID_TABLES += "files/static-passwd"
+ USERADD_GID_TABLES += "files/static-group"
+ ''').format(package_classes=' '.join('package_%s' % c for c in self.package_classes),
+ tmpdir=tmpdir)
+
+ if not use_sstate:
+ if self.sstate_targets:
+ self.logger.info("Building prebuild for %s (sstate allowed)..." % (name))
+ self.write_config(config)
+ bitbake(' '.join(self.sstate_targets))
+
+ # This config fragment will disable using shared and the sstate
+ # mirror, forcing a complete build from scratch
+ config += textwrap.dedent('''\
+ SSTATE_DIR = "${TMPDIR}/sstate"
+ SSTATE_MIRRORS = ""
+ ''')
+
+ self.logger.info("Building %s (sstate%s allowed)..." % (name, '' if use_sstate else ' NOT'))
+ self.write_config(config)
+ d = get_bb_vars(capture_vars)
+ # targets used to be called images
+ bitbake(' '.join(getattr(self, 'images', self.targets)))
+ return d
+
+ def test_reproducible_builds(self):
+ def strip_topdir(s):
+ if s.startswith(self.topdir):
+ return s[len(self.topdir):]
+ return s
+
+ # Build native utilities
+ self.write_config('')
+ bitbake("diffoscope-native diffutils-native jquery-native -c addto_recipe_sysroot")
+ diffutils_sysroot = get_bb_var("RECIPE_SYSROOT_NATIVE", "diffutils-native")
+ diffoscope_sysroot = get_bb_var("RECIPE_SYSROOT_NATIVE", "diffoscope-native")
+ jquery_sysroot = get_bb_var("RECIPE_SYSROOT_NATIVE", "jquery-native")
+
+ if self.save_results:
+ os.makedirs(self.save_results, exist_ok=True)
+ datestr = datetime.datetime.now().strftime('%Y%m%d')
+ save_dir = tempfile.mkdtemp(prefix='oe-reproducible-%s-' % datestr, dir=self.save_results)
+ os.chmod(save_dir, stat.S_IRWXU | stat.S_IRGRP | stat.S_IXGRP | stat.S_IROTH | stat.S_IXOTH)
+ self.logger.info('Non-reproducible packages will be copied to %s', save_dir)
+
+ vars_A = self.do_test_build('reproducibleA', self.build_from_sstate)
+
+ vars_B = self.do_test_build('reproducibleB', False)
+
+ # NOTE: The temp directories from the reproducible build are purposely
+ # kept after the build so it can be diffed for debugging.
+
+ fails = []
+
+ for c in self.package_classes:
+ with self.subTest(package_class=c):
+ package_class = 'package_' + c
+
+ deploy_A = vars_A['DEPLOY_DIR_' + c.upper()]
+ deploy_B = vars_B['DEPLOY_DIR_' + c.upper()]
+
+ self.logger.info('Checking %s packages for differences...' % c)
+ result = self.compare_packages(deploy_A, deploy_B, diffutils_sysroot)
+
+ self.logger.info('Reproducibility summary for %s: %s' % (c, result))
+
+ self.append_to_log('\n'.join("%s: %s" % (r.status, r.test) for r in result.total))
+
+ self.write_package_list(package_class, 'missing', result.missing)
+ self.write_package_list(package_class, 'different', result.different)
+ self.write_package_list(package_class, 'different_excluded', result.different_excluded)
+ self.write_package_list(package_class, 'same', result.same)
+
+ if self.save_results:
+ for d in result.different:
+ self.copy_file(d.reference, '/'.join([save_dir, 'packages', strip_topdir(d.reference)]))
+ self.copy_file(d.test, '/'.join([save_dir, 'packages', strip_topdir(d.test)]))
+
+ for d in result.different_excluded:
+ self.copy_file(d.reference, '/'.join([save_dir, 'packages-excluded', strip_topdir(d.reference)]))
+ self.copy_file(d.test, '/'.join([save_dir, 'packages-excluded', strip_topdir(d.test)]))
+
+ if result.missing or result.different:
+ fails.append("The following %s packages are missing or different and not in exclusion list: %s" %
+ (c, '\n'.join(r.test for r in (result.missing + result.different))))
+
+ # Clean up empty directories
+ if self.save_results:
+ if not os.listdir(save_dir):
+ os.rmdir(save_dir)
+ else:
+ self.logger.info('Running diffoscope')
+ package_dir = os.path.join(save_dir, 'packages')
+ package_html_dir = os.path.join(package_dir, 'diff-html')
+
+ # Copy jquery to improve the diffoscope output usability
+ self.copy_file(os.path.join(jquery_sysroot, 'usr/share/javascript/jquery/jquery.min.js'), os.path.join(package_html_dir, 'jquery.js'))
+
+ run_diffoscope('reproducibleA', 'reproducibleB', package_html_dir, max_report_size=self.max_report_size,
+ native_sysroot=diffoscope_sysroot, ignore_status=True, cwd=package_dir)
+
+ if fails:
+ self.fail('\n'.join(fails))
+
diff --git a/meta/lib/oeqa/selftest/cases/resulttooltests.py b/meta/lib/oeqa/selftest/cases/resulttooltests.py
new file mode 100644
index 0000000000..c2e76f1a44
--- /dev/null
+++ b/meta/lib/oeqa/selftest/cases/resulttooltests.py
@@ -0,0 +1,100 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
+import os
+import sys
+basepath = os.path.abspath(os.path.dirname(__file__) + '/../../../../../')
+lib_path = basepath + '/scripts/lib'
+sys.path = sys.path + [lib_path]
+from resulttool.report import ResultsTextReport
+from resulttool import regression as regression
+from resulttool import resultutils as resultutils
+from oeqa.selftest.case import OESelftestTestCase
+
+class ResultToolTests(OESelftestTestCase):
+ base_results_data = {'base_result1': {'configuration': {"TEST_TYPE": "runtime",
+ "TESTSERIES": "series1",
+ "IMAGE_BASENAME": "image",
+ "IMAGE_PKGTYPE": "ipk",
+ "DISTRO": "mydistro",
+ "MACHINE": "qemux86"},
+ 'result': {}},
+ 'base_result2': {'configuration': {"TEST_TYPE": "runtime",
+ "TESTSERIES": "series1",
+ "IMAGE_BASENAME": "image",
+ "IMAGE_PKGTYPE": "ipk",
+ "DISTRO": "mydistro",
+ "MACHINE": "qemux86-64"},
+ 'result': {}}}
+ target_results_data = {'target_result1': {'configuration': {"TEST_TYPE": "runtime",
+ "TESTSERIES": "series1",
+ "IMAGE_BASENAME": "image",
+ "IMAGE_PKGTYPE": "ipk",
+ "DISTRO": "mydistro",
+ "MACHINE": "qemux86"},
+ 'result': {}},
+ 'target_result2': {'configuration': {"TEST_TYPE": "runtime",
+ "TESTSERIES": "series1",
+ "IMAGE_BASENAME": "image",
+ "IMAGE_PKGTYPE": "ipk",
+ "DISTRO": "mydistro",
+ "MACHINE": "qemux86"},
+ 'result': {}},
+ 'target_result3': {'configuration': {"TEST_TYPE": "runtime",
+ "TESTSERIES": "series1",
+ "IMAGE_BASENAME": "image",
+ "IMAGE_PKGTYPE": "ipk",
+ "DISTRO": "mydistro",
+ "MACHINE": "qemux86-64"},
+ 'result': {}}}
+
+ def test_report_can_aggregate_test_result(self):
+ result_data = {'result': {'test1': {'status': 'PASSED'},
+ 'test2': {'status': 'PASSED'},
+ 'test3': {'status': 'FAILED'},
+ 'test4': {'status': 'ERROR'},
+ 'test5': {'status': 'SKIPPED'}}}
+ report = ResultsTextReport()
+ result_report = report.get_aggregated_test_result(None, result_data, 'DummyMachine')
+ self.assertTrue(result_report['passed'] == 2, msg="Passed count not correct:%s" % result_report['passed'])
+ self.assertTrue(result_report['failed'] == 2, msg="Failed count not correct:%s" % result_report['failed'])
+ self.assertTrue(result_report['skipped'] == 1, msg="Skipped count not correct:%s" % result_report['skipped'])
+
+ def test_regression_can_get_regression_base_target_pair(self):
+
+ results = {}
+ resultutils.append_resultsdata(results, ResultToolTests.base_results_data)
+ resultutils.append_resultsdata(results, ResultToolTests.target_results_data)
+ self.assertTrue('target_result1' in results['runtime/mydistro/qemux86/image'], msg="Pair not correct:%s" % results)
+ self.assertTrue('target_result3' in results['runtime/mydistro/qemux86-64/image'], msg="Pair not correct:%s" % results)
+
+ def test_regrresion_can_get_regression_result(self):
+ base_result_data = {'result': {'test1': {'status': 'PASSED'},
+ 'test2': {'status': 'PASSED'},
+ 'test3': {'status': 'FAILED'},
+ 'test4': {'status': 'ERROR'},
+ 'test5': {'status': 'SKIPPED'}}}
+ target_result_data = {'result': {'test1': {'status': 'PASSED'},
+ 'test2': {'status': 'FAILED'},
+ 'test3': {'status': 'PASSED'},
+ 'test4': {'status': 'ERROR'},
+ 'test5': {'status': 'SKIPPED'}}}
+ result, text = regression.compare_result(self.logger, "BaseTestRunName", "TargetTestRunName", base_result_data, target_result_data)
+ self.assertTrue(result['test2']['base'] == 'PASSED',
+ msg="regression not correct:%s" % result['test2']['base'])
+ self.assertTrue(result['test2']['target'] == 'FAILED',
+ msg="regression not correct:%s" % result['test2']['target'])
+ self.assertTrue(result['test3']['base'] == 'FAILED',
+ msg="regression not correct:%s" % result['test3']['base'])
+ self.assertTrue(result['test3']['target'] == 'PASSED',
+ msg="regression not correct:%s" % result['test3']['target'])
+
+ def test_merge_can_merged_results(self):
+ results = {}
+ resultutils.append_resultsdata(results, ResultToolTests.base_results_data, configmap=resultutils.flatten_map)
+ resultutils.append_resultsdata(results, ResultToolTests.target_results_data, configmap=resultutils.flatten_map)
+ self.assertEqual(len(results[''].keys()), 5, msg="Flattened results not correct %s" % str(results))
+
diff --git a/meta/lib/oeqa/selftest/cases/rootfspostcommandstests.py b/meta/lib/oeqa/selftest/cases/rootfspostcommandstests.py
new file mode 100644
index 0000000000..44e2c09a6f
--- /dev/null
+++ b/meta/lib/oeqa/selftest/cases/rootfspostcommandstests.py
@@ -0,0 +1,97 @@
+# SPDX-FileCopyrightText: Huawei Inc.
+#
+# SPDX-License-Identifier: MIT
+
+import os
+import oe
+import unittest
+from oeqa.selftest.case import OESelftestTestCase
+from oeqa.utils.commands import bitbake, get_bb_vars
+
+class ShadowUtilsTidyFiles(OESelftestTestCase):
+ """
+ Check if shadow image rootfs files are tidy.
+
+ The tests are focused on testing the functionality provided by the
+ 'tidy_shadowutils_files' rootfs postprocess command (via
+ SORT_PASSWD_POSTPROCESS_COMMAND).
+ """
+
+ def sysconf_build(self):
+ """
+ Verify if shadow tidy files tests are to be run and if yes, build a
+ test image and return its sysconf rootfs path.
+ """
+
+ test_image = "core-image-minimal"
+
+ config = 'IMAGE_CLASSES += "extrausers"\n'
+ config += 'EXTRA_USERS_PARAMS = "groupadd -g 1000 oeqatester; "\n'
+ config += 'EXTRA_USERS_PARAMS += "useradd -p \'\' -u 1000 -N -g 1000 oeqatester; "\n'
+ self.write_config(config)
+
+ vars = get_bb_vars(("IMAGE_ROOTFS", "SORT_PASSWD_POSTPROCESS_COMMAND", "sysconfdir"),
+ test_image)
+ passwd_postprocess_cmd = vars["SORT_PASSWD_POSTPROCESS_COMMAND"]
+ self.assertIsNotNone(passwd_postprocess_cmd)
+ if (passwd_postprocess_cmd.strip() != 'tidy_shadowutils_files;'):
+ raise unittest.SkipTest("Testcase skipped as 'tidy_shadowutils_files' "
+ "rootfs post process command is not the set SORT_PASSWD_POSTPROCESS_COMMAND.")
+
+ rootfs = vars["IMAGE_ROOTFS"]
+ self.assertIsNotNone(rootfs)
+ sysconfdir = vars["sysconfdir"]
+ bitbake(test_image)
+ self.assertIsNotNone(sysconfdir)
+
+ return oe.path.join(rootfs, sysconfdir)
+
+ def test_shadowutils_backup_files(self):
+ """
+ Test that the rootfs doesn't include any known shadow backup files.
+ """
+
+ backup_files = (
+ 'group-',
+ 'gshadow-',
+ 'passwd-',
+ 'shadow-',
+ 'subgid-',
+ 'subuid-',
+ )
+
+ rootfs_sysconfdir = self.sysconf_build()
+ found = []
+ for backup_file in backup_files:
+ backup_filepath = oe.path.join(rootfs_sysconfdir, backup_file)
+ if os.path.exists(backup_filepath):
+ found.append(backup_file)
+ if (found):
+ raise Exception('The following shadow backup files were found in '
+ 'the rootfs: %s' % found)
+
+ def test_shadowutils_sorted_files(self):
+ """
+ Test that the 'passwd' and the 'group' shadow utils files are ordered
+ by ID.
+ """
+
+ files = (
+ 'passwd',
+ 'group',
+ )
+
+ rootfs_sysconfdir = self.sysconf_build()
+ unsorted = []
+ for file in files:
+ filepath = oe.path.join(rootfs_sysconfdir, file)
+ with open(filepath, 'rb') as f:
+ ids = []
+ lines = f.readlines()
+ for line in lines:
+ entries = line.split(b':')
+ ids.append(int(entries[2]))
+ if (ids != sorted(ids)):
+ unsorted.append(file)
+ if (unsorted):
+ raise Exception("The following files were not sorted by ID as expected: %s" % unsorted)
diff --git a/meta/lib/oeqa/selftest/cases/rpmtests.py b/meta/lib/oeqa/selftest/cases/rpmtests.py
new file mode 100644
index 0000000000..902d7dca3d
--- /dev/null
+++ b/meta/lib/oeqa/selftest/cases/rpmtests.py
@@ -0,0 +1,14 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
+from oeqa.selftest.case import OESelftestTestCase
+from oeqa.utils.commands import bitbake
+
+class BitbakeTests(OESelftestTestCase):
+
+ def test_rpm_filenames(self):
+ test_recipe = "testrpm"
+ bitbake(test_recipe)
diff --git a/meta/lib/oeqa/selftest/cases/runcmd.py b/meta/lib/oeqa/selftest/cases/runcmd.py
new file mode 100644
index 0000000000..6fd96b8485
--- /dev/null
+++ b/meta/lib/oeqa/selftest/cases/runcmd.py
@@ -0,0 +1,124 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
+from oeqa.selftest.case import OESelftestTestCase
+from oeqa.utils.commands import runCmd
+from oeqa.utils import CommandError
+
+import subprocess
+import threading
+import time
+import signal
+
+class MemLogger(object):
+ def __init__(self):
+ self.info_msgs = []
+ self.error_msgs = []
+
+ def info(self, msg):
+ self.info_msgs.append(msg)
+
+ def error(self, msg):
+ self.error_msgs.append(msg)
+
+class RunCmdTests(OESelftestTestCase):
+ """ Basic tests for runCmd() utility function """
+
+ # The delta is intentionally smaller than the timeout, to detect cases where
+ # we incorrectly apply the timeout more than once.
+ TIMEOUT = 10
+ DELTA = 8
+
+ def test_result_okay(self):
+ result = runCmd("true")
+ self.assertEqual(result.status, 0)
+
+ def test_result_false(self):
+ result = runCmd("false", ignore_status=True)
+ self.assertEqual(result.status, 1)
+
+ def test_shell(self):
+ # A shell is used for all string commands.
+ result = runCmd("false; true", ignore_status=True)
+ self.assertEqual(result.status, 0)
+
+ def test_no_shell(self):
+ self.assertRaises(FileNotFoundError,
+ runCmd, "false; true", shell=False)
+
+ def test_list_not_found(self):
+ self.assertRaises(FileNotFoundError,
+ runCmd, ["false; true"])
+
+ def test_list_okay(self):
+ result = runCmd(["true"])
+ self.assertEqual(result.status, 0)
+
+ def test_result_assertion(self):
+ self.assertRaisesRegexp(AssertionError, "Command 'echo .* false' returned non-zero exit status 1:\nfoobar",
+ runCmd, "echo foobar >&2; false", shell=True)
+
+ def test_result_exception(self):
+ self.assertRaisesRegexp(CommandError, "Command 'echo .* false' returned non-zero exit status 1 with output: foobar",
+ runCmd, "echo foobar >&2; false", shell=True, assert_error=False)
+
+ def test_output(self):
+ result = runCmd("echo stdout; echo stderr >&2", shell=True, sync=False)
+ self.assertEqual("stdout\nstderr", result.output)
+ self.assertEqual("", result.error)
+
+ def test_output_split(self):
+ result = runCmd("echo stdout; echo stderr >&2", shell=True, stderr=subprocess.PIPE, sync=False)
+ self.assertEqual("stdout", result.output)
+ self.assertEqual("stderr", result.error)
+
+ def test_timeout(self):
+ numthreads = threading.active_count()
+ start = time.time()
+ # Killing a hanging process only works when not using a shell?!
+ result = runCmd(['sleep', '60'], timeout=self.TIMEOUT, ignore_status=True, sync=False)
+ self.assertEqual(result.status, -signal.SIGTERM)
+ end = time.time()
+ self.assertLess(end - start, self.TIMEOUT + self.DELTA)
+ self.assertEqual(numthreads, threading.active_count(), msg="Thread counts were not equal before (%s) and after (%s), active threads: %s" % (numthreads, threading.active_count(), threading.enumerate()))
+
+ def test_timeout_split(self):
+ numthreads = threading.active_count()
+ start = time.time()
+ # Killing a hanging process only works when not using a shell?!
+ result = runCmd(['sleep', '60'], timeout=self.TIMEOUT, ignore_status=True, stderr=subprocess.PIPE, sync=False)
+ self.assertEqual(result.status, -signal.SIGTERM)
+ end = time.time()
+ self.assertLess(end - start, self.TIMEOUT + self.DELTA)
+ self.assertEqual(numthreads, threading.active_count(), msg="Thread counts were not equal before (%s) and after (%s), active threads: %s" % (numthreads, threading.active_count(), threading.enumerate()))
+
+ def test_stdin(self):
+ numthreads = threading.active_count()
+ result = runCmd("cat", data=b"hello world", timeout=self.TIMEOUT, sync=False)
+ self.assertEqual("hello world", result.output)
+ self.assertEqual(numthreads, threading.active_count(), msg="Thread counts were not equal before (%s) and after (%s), active threads: %s" % (numthreads, threading.active_count(), threading.enumerate()))
+ self.assertEqual(numthreads, 1)
+
+ def test_stdin_timeout(self):
+ numthreads = threading.active_count()
+ start = time.time()
+ result = runCmd(['sleep', '60'], data=b"hello world", timeout=self.TIMEOUT, ignore_status=True, sync=False)
+ self.assertEqual(result.status, -signal.SIGTERM)
+ end = time.time()
+ self.assertLess(end - start, self.TIMEOUT + self.DELTA)
+ self.assertEqual(numthreads, threading.active_count(), msg="Thread counts were not equal before (%s) and after (%s), active threads: %s" % (numthreads, threading.active_count(), threading.enumerate()))
+
+ def test_log(self):
+ log = MemLogger()
+ result = runCmd("echo stdout; echo stderr >&2", shell=True, output_log=log, sync=False)
+ self.assertEqual(["Running: echo stdout; echo stderr >&2", "stdout", "stderr"], log.info_msgs)
+ self.assertEqual([], log.error_msgs)
+
+ def test_log_split(self):
+ log = MemLogger()
+ result = runCmd("echo stdout; echo stderr >&2", shell=True, output_log=log, stderr=subprocess.PIPE, sync=False)
+ self.assertEqual(["Running: echo stdout; echo stderr >&2", "stdout"], log.info_msgs)
+ self.assertEqual(["stderr"], log.error_msgs)
diff --git a/meta/lib/oeqa/selftest/cases/runqemu.py b/meta/lib/oeqa/selftest/cases/runqemu.py
new file mode 100644
index 0000000000..c2c3fbc924
--- /dev/null
+++ b/meta/lib/oeqa/selftest/cases/runqemu.py
@@ -0,0 +1,210 @@
+#
+# Copyright (c) 2017 Wind River Systems, Inc.
+#
+# SPDX-License-Identifier: MIT
+#
+
+import re
+import tempfile
+import time
+import oe.types
+from oeqa.core.decorator import OETestTag
+from oeqa.core.decorator.data import skipIfNotArch, skipIfNotMachine
+from oeqa.selftest.case import OESelftestTestCase
+from oeqa.utils.commands import bitbake, runqemu, get_bb_var, runCmd
+
+@OETestTag("runqemu")
+class RunqemuTests(OESelftestTestCase):
+ """Runqemu test class"""
+
+ image_is_ready = False
+ deploy_dir_image = ''
+
+ def setUpLocal(self):
+ super(RunqemuTests, self).setUpLocal()
+ self.recipe = 'core-image-minimal'
+ self.machine = self.td['MACHINE']
+
+ self.fstypes = "ext4"
+ if self.td["HOST_ARCH"] in ('i586', 'i686', 'x86_64'):
+ self.fstypes += " iso hddimg"
+ if self.machine == "qemux86-64":
+ self.fstypes += " wic.vmdk wic.qcow2 wic.vdi"
+
+ self.cmd_common = "runqemu nographic"
+ kvm = oe.types.qemu_use_kvm(get_bb_var('QEMU_USE_KVM'), self.td["TARGET_ARCH"])
+ if kvm:
+ self.cmd_common += " kvm"
+
+ self.write_config(
+"""
+IMAGE_FSTYPES = "%s"
+# 10 means 1 second
+SYSLINUX_TIMEOUT = "10"
+""" % self.fstypes)
+
+ if not RunqemuTests.image_is_ready:
+ RunqemuTests.deploy_dir_image = get_bb_var('DEPLOY_DIR_IMAGE')
+ bitbake(self.recipe)
+ RunqemuTests.image_is_ready = True
+
+ def test_boot_machine(self):
+ """Test runqemu machine"""
+ cmd = "%s %s" % (self.cmd_common, self.machine)
+ with runqemu(self.recipe, ssh=False, launch_cmd=cmd) as qemu:
+ with open(qemu.qemurunnerlog) as f:
+ self.assertTrue(qemu.runner.logged, "Failed: %s, %s" % (cmd, f.read()))
+
+ def test_boot_machine_ext4(self):
+ """Test runqemu machine ext4"""
+ cmd = "%s %s ext4" % (self.cmd_common, self.machine)
+ with runqemu(self.recipe, ssh=False, launch_cmd=cmd) as qemu:
+ with open(qemu.qemurunnerlog) as f:
+ self.assertIn('rootfs.ext4', f.read(), "Failed: %s" % cmd)
+
+ @skipIfNotArch(['i586', 'i686', 'x86_64'])
+ def test_boot_machine_iso(self):
+ """Test runqemu machine iso"""
+ cmd = "%s %s iso" % (self.cmd_common, self.machine)
+ with runqemu(self.recipe, ssh=False, launch_cmd=cmd) as qemu:
+ with open(qemu.qemurunnerlog) as f:
+ self.assertIn('media=cdrom', f.read(), "Failed: %s" % cmd)
+
+ def test_boot_recipe_image(self):
+ """Test runqemu recipe-image"""
+ cmd = "%s %s" % (self.cmd_common, self.recipe)
+ with runqemu(self.recipe, ssh=False, launch_cmd=cmd) as qemu:
+ with open(qemu.qemurunnerlog) as f:
+ self.assertTrue(qemu.runner.logged, "Failed: %s, %s" % (cmd, f.read()))
+
+ # https://bugzilla.yoctoproject.org/show_bug.cgi?id=14963
+ @skipIfNotMachine("qemux86-64", "tests are qemux86-64 specific currently")
+ def test_boot_recipe_image_vmdk(self):
+ """Test runqemu recipe-image vmdk"""
+ cmd = "%s %s wic.vmdk" % (self.cmd_common, self.recipe)
+ with runqemu(self.recipe, ssh=False, launch_cmd=cmd) as qemu:
+ with open(qemu.qemurunnerlog) as f:
+ self.assertIn('format=vmdk', f.read(), "Failed: %s" % cmd)
+
+ @skipIfNotMachine("qemux86-64", "tests are qemux86-64 specific currently")
+ def test_boot_recipe_image_vdi(self):
+ """Test runqemu recipe-image vdi"""
+ cmd = "%s %s wic.vdi" % (self.cmd_common, self.recipe)
+ with runqemu(self.recipe, ssh=False, launch_cmd=cmd) as qemu:
+ with open(qemu.qemurunnerlog) as f:
+ self.assertIn('format=vdi', f.read(), "Failed: %s" % cmd)
+
+ def test_boot_deploy(self):
+ """Test runqemu deploy_dir_image"""
+ cmd = "%s %s" % (self.cmd_common, self.deploy_dir_image)
+ with runqemu(self.recipe, ssh=False, launch_cmd=cmd) as qemu:
+ with open(qemu.qemurunnerlog) as f:
+ self.assertTrue(qemu.runner.logged, "Failed: %s, %s" % (cmd, f.read()))
+
+
+ @skipIfNotArch(['i586', 'i686', 'x86_64'])
+ def test_boot_deploy_hddimg(self):
+ """Test runqemu deploy_dir_image hddimg"""
+ cmd = "%s %s hddimg" % (self.cmd_common, self.deploy_dir_image)
+ with runqemu(self.recipe, ssh=False, launch_cmd=cmd) as qemu:
+ with open(qemu.qemurunnerlog) as f:
+ self.assertTrue(re.search('file=.*.hddimg', f.read()), "Failed: %s, %s" % (cmd, f.read()))
+
+ def test_boot_machine_slirp(self):
+ """Test runqemu machine slirp"""
+ cmd = "%s slirp %s" % (self.cmd_common, self.machine)
+ with runqemu(self.recipe, ssh=False, launch_cmd=cmd) as qemu:
+ with open(qemu.qemurunnerlog) as f:
+ self.assertIn(' -netdev user', f.read(), "Failed: %s" % cmd)
+
+ @skipIfNotMachine("qemux86-64", "tests are qemux86-64 specific currently")
+ def test_boot_machine_slirp_qcow2(self):
+ """Test runqemu machine slirp qcow2"""
+ cmd = "%s slirp wic.qcow2 %s" % (self.cmd_common, self.machine)
+ with runqemu(self.recipe, ssh=False, launch_cmd=cmd) as qemu:
+ with open(qemu.qemurunnerlog) as f:
+ self.assertIn('format=qcow2', f.read(), "Failed: %s" % cmd)
+
+ def test_boot_qemu_boot(self):
+ """Test runqemu /path/to/image.qemuboot.conf"""
+ qemuboot_conf = "%s-%s.qemuboot.conf" % (self.recipe, self.machine)
+ qemuboot_conf = os.path.join(self.deploy_dir_image, qemuboot_conf)
+ if not os.path.exists(qemuboot_conf):
+ self.skipTest("%s not found" % qemuboot_conf)
+ cmd = "%s %s" % (self.cmd_common, qemuboot_conf)
+ with runqemu(self.recipe, ssh=False, launch_cmd=cmd) as qemu:
+ with open(qemu.qemurunnerlog) as f:
+ self.assertTrue(qemu.runner.logged, "Failed: %s, %s" % (cmd, f.read()))
+
+ def test_boot_rootfs(self):
+ """Test runqemu /path/to/rootfs.ext4"""
+ rootfs = "%s-%s.ext4" % (self.recipe, self.machine)
+ rootfs = os.path.join(self.deploy_dir_image, rootfs)
+ if not os.path.exists(rootfs):
+ self.skipTest("%s not found" % rootfs)
+ cmd = "%s %s" % (self.cmd_common, rootfs)
+ with runqemu(self.recipe, ssh=False, launch_cmd=cmd) as qemu:
+ with open(qemu.qemurunnerlog) as f:
+ self.assertTrue(qemu.runner.logged, "Failed: %s, %s" % (cmd, f.read()))
+
+
+# This test was designed as a separate class to test that shutdown
+# command will shutdown qemu as expected on each qemu architecture
+# based on the MACHINE configuration inside the config file
+# (eg. local.conf).
+#
+# This was different compared to RunqemuTests, where RunqemuTests was
+# dedicated for MACHINE=qemux86-64 where it test that qemux86-64 will
+# bootup various filesystem types, including live image(iso and hddimg)
+# where live image was not supported on all qemu architecture.
+@OETestTag("machine")
+@OETestTag("runqemu")
+class QemuTest(OESelftestTestCase):
+
+ @classmethod
+ def setUpClass(cls):
+ super(QemuTest, cls).setUpClass()
+ cls.recipe = 'core-image-minimal'
+ cls.machine = get_bb_var('MACHINE')
+ cls.deploy_dir_image = get_bb_var('DEPLOY_DIR_IMAGE')
+ cls.cmd_common = "runqemu nographic"
+ cls.qemuboot_conf = "%s-%s.qemuboot.conf" % (cls.recipe, cls.machine)
+ cls.qemuboot_conf = os.path.join(cls.deploy_dir_image, cls.qemuboot_conf)
+ bitbake(cls.recipe)
+
+ def _start_qemu_shutdown_check_if_shutdown_succeeded(self, qemu, timeout):
+ # Allow the runner's LoggingThread instance to exit without errors
+ # (such as the exception "Console connection closed unexpectedly")
+ # as qemu will disappear when we shut it down
+ qemu.runner.allowexit()
+ qemu.run_serial("shutdown -h now")
+ time_track = 0
+ try:
+ while True:
+ is_alive = qemu.check()
+ if not is_alive:
+ return True
+ if time_track > timeout:
+ return False
+ time.sleep(1)
+ time_track += 1
+ except SystemExit:
+ return True
+
+ def test_qemu_can_shutdown(self):
+ self.assertExists(self.qemuboot_conf)
+ cmd = "%s %s" % (self.cmd_common, self.qemuboot_conf)
+ shutdown_timeout = 120
+ with runqemu(self.recipe, ssh=False, launch_cmd=cmd) as qemu:
+ qemu_shutdown_succeeded = self._start_qemu_shutdown_check_if_shutdown_succeeded(qemu, shutdown_timeout)
+ self.assertTrue(qemu_shutdown_succeeded, 'Failed: %s does not shutdown within timeout(%s)' % (self.machine, shutdown_timeout))
+
+ def test_qemu_can_boot_nfs_and_shutdown(self):
+ rootfs_tar = "%s-%s.tar.bz2" % (self.recipe, self.machine)
+ rootfs_tar = os.path.join(self.deploy_dir_image, rootfs_tar)
+ self.assertExists(rootfs_tar)
+ cmd = "%s %s" % (self.cmd_common, rootfs_tar)
+ shutdown_timeout = 120
+ with runqemu(self.recipe, ssh=False, launch_cmd=cmd) as qemu:
+ qemu_shutdown_succeeded = self._start_qemu_shutdown_check_if_shutdown_succeeded(qemu, shutdown_timeout)
+ self.assertTrue(qemu_shutdown_succeeded, 'Failed: %s does not shutdown within timeout(%s)' % (self.machine, shutdown_timeout))
diff --git a/meta/lib/oeqa/selftest/cases/runtime_test.py b/meta/lib/oeqa/selftest/cases/runtime_test.py
new file mode 100644
index 0000000000..7d99c158e5
--- /dev/null
+++ b/meta/lib/oeqa/selftest/cases/runtime_test.py
@@ -0,0 +1,480 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
+from oeqa.selftest.case import OESelftestTestCase
+from oeqa.utils.commands import runCmd, bitbake, get_bb_var, get_bb_vars, runqemu
+from oeqa.core.decorator import OETestTag
+import os
+import tempfile
+import oe.lsb
+from oeqa.core.decorator.data import skipIfNotQemu, skipIfNotMachine
+
+class TestExport(OESelftestTestCase):
+
+ @OETestTag("runqemu")
+ def test_testexport_basic(self):
+ """
+ Summary: Check basic testexport functionality with only ping test enabled.
+ Expected: 1. testexport directory must be created.
+ 2. runexported.py must run without any error/exception.
+ 3. ping test must succeed.
+ Product: oe-core
+ Author: Mariano Lopez <mariano.lopez@intel.com>
+ """
+
+ features = 'IMAGE_CLASSES += "testexport"\n'
+ # These aren't the actual IP addresses but testexport class needs something defined
+ features += 'TEST_SERVER_IP = "192.168.7.1"\n'
+ features += 'TEST_TARGET_IP = "192.168.7.1"\n'
+ features += 'TEST_SUITES = "ping"\n'
+ self.write_config(features)
+
+ # Build tesexport for core-image-minimal
+ bitbake('core-image-minimal')
+ bitbake('-c testexport core-image-minimal')
+
+ testexport_dir = get_bb_var('TEST_EXPORT_DIR', 'core-image-minimal')
+
+ # Verify if TEST_EXPORT_DIR was created
+ isdir = os.path.isdir(testexport_dir)
+ self.assertEqual(True, isdir, 'Failed to create testexport dir: %s' % testexport_dir)
+
+ with runqemu('core-image-minimal') as qemu:
+ # Attempt to run runexported.py to perform ping test
+ test_path = os.path.join(testexport_dir, "oe-test")
+ data_file = os.path.join(testexport_dir, 'data', 'testdata.json')
+ manifest = os.path.join(testexport_dir, 'data', 'manifest')
+ cmd = ("%s runtime --test-data-file %s --packages-manifest %s "
+ "--target-ip %s --server-ip %s --quiet"
+ % (test_path, data_file, manifest, qemu.ip, qemu.server_ip))
+ result = runCmd(cmd)
+ # Verify ping test was succesful
+ self.assertEqual(0, result.status, 'oe-test runtime returned a non 0 status')
+
+ def test_testexport_sdk(self):
+ """
+ Summary: Check sdk functionality for testexport.
+ Expected: 1. testexport directory must be created.
+ 2. SDK tarball must exists.
+ 3. Uncompressing of tarball must succeed.
+ 4. Check if the SDK directory is added to PATH.
+ 5. Run tar from the SDK directory.
+ Product: oe-core
+ Author: Mariano Lopez <mariano.lopez@intel.com>
+ """
+
+ features = 'IMAGE_CLASSES += "testexport"\n'
+ # These aren't the actual IP addresses but testexport class needs something defined
+ features += 'TEST_SERVER_IP = "192.168.7.1"\n'
+ features += 'TEST_TARGET_IP = "192.168.7.1"\n'
+ features += 'TEST_SUITES = "ping"\n'
+ features += 'TEST_EXPORT_SDK_ENABLED = "1"\n'
+ features += 'TEST_EXPORT_SDK_PACKAGES = "nativesdk-tar"\n'
+ self.write_config(features)
+
+ # Build tesexport for core-image-minimal
+ bitbake('core-image-minimal')
+ bitbake('-c testexport core-image-minimal')
+
+ needed_vars = ['TEST_EXPORT_DIR', 'TEST_EXPORT_SDK_DIR', 'TEST_EXPORT_SDK_NAME']
+ bb_vars = get_bb_vars(needed_vars, 'core-image-minimal')
+ testexport_dir = bb_vars['TEST_EXPORT_DIR']
+ sdk_dir = bb_vars['TEST_EXPORT_SDK_DIR']
+ sdk_name = bb_vars['TEST_EXPORT_SDK_NAME']
+
+ # Check for SDK
+ tarball_name = "%s.sh" % sdk_name
+ tarball_path = os.path.join(testexport_dir, sdk_dir, tarball_name)
+ msg = "Couldn't find SDK tarball: %s" % tarball_path
+ self.assertEqual(os.path.isfile(tarball_path), True, msg)
+
+ with tempfile.TemporaryDirectory() as tmpdirname:
+ # Extract SDK and run tar from SDK
+ result = runCmd("%s -y -d %s" % (tarball_path, tmpdirname))
+ self.assertEqual(0, result.status, "Couldn't extract SDK")
+
+ env_script = result.output.split()[-1]
+ result = runCmd(". %s; which tar" % env_script, shell=True)
+ self.assertEqual(0, result.status, "Couldn't setup SDK environment")
+ is_sdk_tar = True if tmpdirname in result.output else False
+ self.assertTrue(is_sdk_tar, "Couldn't setup SDK environment")
+
+ tar_sdk = result.output
+ result = runCmd("%s --version" % tar_sdk)
+ self.assertEqual(0, result.status, "Couldn't run tar from SDK")
+
+
+@OETestTag("runqemu")
+class TestImage(OESelftestTestCase):
+
+ def test_testimage_install(self):
+ """
+ Summary: Check install packages functionality for testimage/testexport.
+ Expected: 1. Import tests from a directory other than meta.
+ 2. Check install/uninstall of socat.
+ Product: oe-core
+ Author: Mariano Lopez <mariano.lopez@intel.com>
+ """
+ if get_bb_var('DISTRO') == 'poky-tiny':
+ self.skipTest('core-image-full-cmdline not buildable for poky-tiny')
+
+ features = 'IMAGE_CLASSES += "testimage"\n'
+ features += 'IMAGE_INSTALL:append = " libssl"\n'
+ features += 'TEST_SUITES = "ping ssh selftest"\n'
+ self.write_config(features)
+
+ bitbake('core-image-full-cmdline socat')
+ bitbake('-c testimage core-image-full-cmdline')
+
+ def test_testimage_dnf(self):
+ """
+ Summary: Check package feeds functionality for dnf
+ Expected: 1. Check that remote package feeds can be accessed
+ Product: oe-core
+ Author: Alexander Kanavin <alex.kanavin@gmail.com>
+ """
+ if get_bb_var('DISTRO') == 'poky-tiny':
+ self.skipTest('core-image-full-cmdline not buildable for poky-tiny')
+
+ features = 'IMAGE_CLASSES += "testimage"\n'
+ features += 'TEST_SUITES = "ping ssh dnf_runtime dnf.DnfBasicTest.test_dnf_help"\n'
+ # We don't yet know what the server ip and port will be - they will be patched
+ # in at the start of the on-image test
+ features += 'PACKAGE_FEED_URIS = "http://bogus_ip:bogus_port"\n'
+ features += 'EXTRA_IMAGE_FEATURES += "package-management"\n'
+ features += 'PACKAGE_CLASSES = "package_rpm"\n'
+
+ bitbake('gnupg-native -c addto_recipe_sysroot')
+
+ # Enable package feed signing
+ self.gpg_home = tempfile.mkdtemp(prefix="oeqa-feed-sign-")
+ self.track_for_cleanup(self.gpg_home)
+ signing_key_dir = os.path.join(self.testlayer_path, 'files', 'signing')
+ runCmd('gpgconf --list-dirs --homedir %s; gpg -v --batch --homedir %s --import %s' % (self.gpg_home, self.gpg_home, os.path.join(signing_key_dir, 'key.secret')), native_sysroot=get_bb_var("RECIPE_SYSROOT_NATIVE", "gnupg-native"), shell=True)
+ features += 'INHERIT += "sign_package_feed"\n'
+ features += 'PACKAGE_FEED_GPG_NAME = "testuser"\n'
+ features += 'PACKAGE_FEED_GPG_PASSPHRASE_FILE = "%s"\n' % os.path.join(signing_key_dir, 'key.passphrase')
+ features += 'GPG_PATH = "%s"\n' % self.gpg_home
+ features += 'PSEUDO_IGNORE_PATHS .= ",%s"\n' % self.gpg_home
+ self.write_config(features)
+
+ bitbake('core-image-full-cmdline socat')
+ bitbake('-c testimage core-image-full-cmdline')
+
+ def test_testimage_apt(self):
+ """
+ Summary: Check package feeds functionality for apt
+ Expected: 1. Check that remote package feeds can be accessed
+ Product: oe-core
+ Author: Ferry Toth <fntoth@gmail.com>
+ """
+ if get_bb_var('DISTRO') == 'poky-tiny':
+ self.skipTest('core-image-full-cmdline not buildable for poky-tiny')
+
+ features = 'IMAGE_CLASSES += "testimage"\n'
+ features += 'TEST_SUITES = "ping ssh apt.AptRepoTest.test_apt_install_from_repo"\n'
+ # We don't yet know what the server ip and port will be - they will be patched
+ # in at the start of the on-image test
+ features += 'PACKAGE_FEED_URIS = "http://bogus_ip:bogus_port"\n'
+ features += 'EXTRA_IMAGE_FEATURES += "package-management"\n'
+ features += 'PACKAGE_CLASSES = "package_deb"\n'
+ # We need gnupg on the target to install keys
+ features += 'IMAGE_INSTALL:append:pn-core-image-full-cmdline = " gnupg"\n'
+
+ bitbake('gnupg-native -c addto_recipe_sysroot')
+
+ # Enable package feed signing
+ self.gpg_home = tempfile.mkdtemp(prefix="oeqa-feed-sign-")
+ self.track_for_cleanup(self.gpg_home)
+ signing_key_dir = os.path.join(self.testlayer_path, 'files', 'signing')
+ runCmd('gpgconf --list-dirs --homedir %s; gpg -v --batch --homedir %s --import %s' % (self.gpg_home, self.gpg_home, os.path.join(signing_key_dir, 'key.secret')), native_sysroot=get_bb_var("RECIPE_SYSROOT_NATIVE", "gnupg-native"), shell=True)
+ features += 'INHERIT += "sign_package_feed"\n'
+ features += 'PACKAGE_FEED_GPG_NAME = "testuser"\n'
+ features += 'PACKAGE_FEED_GPG_PASSPHRASE_FILE = "%s"\n' % os.path.join(signing_key_dir, 'key.passphrase')
+ features += 'GPG_PATH = "%s"\n' % self.gpg_home
+ features += 'PSEUDO_IGNORE_PATHS .= ",%s"\n' % self.gpg_home
+ self.write_config(features)
+
+ # Build core-image-sato and testimage
+ bitbake('core-image-full-cmdline socat')
+ bitbake('-c testimage core-image-full-cmdline')
+
+ # https://bugzilla.yoctoproject.org/show_bug.cgi?id=14966
+ @skipIfNotMachine("qemux86-64", "test needs qemux86-64")
+ def test_testimage_virgl_gtk_sdl(self):
+ """
+ Summary: Check host-assisted accelerate OpenGL functionality in qemu with gtk and SDL frontends
+ Expected: 1. Check that virgl kernel driver is loaded and 3d acceleration is enabled
+ 2. Check that kmscube demo runs without crashing.
+ Product: oe-core
+ Author: Alexander Kanavin <alex.kanavin@gmail.com>
+ """
+ if "DISPLAY" not in os.environ:
+ self.skipTest("virgl gtk test must be run inside a X session")
+ distro = oe.lsb.distro_identifier()
+ if distro and distro == 'debian-8':
+ self.skipTest('virgl isn\'t working with Debian 8')
+ if distro and distro == 'debian-9':
+ self.skipTest('virgl isn\'t working with Debian 9')
+ if distro and distro == 'centos-7':
+ self.skipTest('virgl isn\'t working with Centos 7')
+ if distro and distro == 'opensuseleap-15.0':
+ self.skipTest('virgl isn\'t working with Opensuse 15.0')
+
+ qemu_packageconfig = get_bb_var('PACKAGECONFIG', 'qemu-system-native')
+ qemu_distrofeatures = get_bb_var('DISTRO_FEATURES', 'qemu-system-native')
+ features = 'IMAGE_CLASSES += "testimage"\n'
+ if 'gtk+' not in qemu_packageconfig:
+ features += 'PACKAGECONFIG:append:pn-qemu-system-native = " gtk+"\n'
+ if 'sdl' not in qemu_packageconfig:
+ features += 'PACKAGECONFIG:append:pn-qemu-system-native = " sdl"\n'
+ if 'opengl' not in qemu_distrofeatures:
+ features += 'DISTRO_FEATURES:append = " opengl"\n'
+ features += 'TEST_SUITES = "ping ssh virgl"\n'
+ features += 'IMAGE_FEATURES:append = " ssh-server-dropbear"\n'
+ features += 'IMAGE_INSTALL:append = " kmscube"\n'
+ features_gtk = features + 'TEST_RUNQEMUPARAMS = "gtk gl"\n'
+ self.write_config(features_gtk)
+ bitbake('core-image-minimal')
+ bitbake('-c testimage core-image-minimal')
+ features_sdl = features + 'TEST_RUNQEMUPARAMS = "sdl gl"\n'
+ self.write_config(features_sdl)
+ bitbake('core-image-minimal')
+ bitbake('-c testimage core-image-minimal')
+
+ @skipIfNotMachine("qemux86-64", "test needs qemux86-64")
+ def test_testimage_virgl_headless(self):
+ """
+ Summary: Check host-assisted accelerate OpenGL functionality in qemu with egl-headless frontend
+ Expected: 1. Check that virgl kernel driver is loaded and 3d acceleration is enabled
+ 2. Check that kmscube demo runs without crashing.
+ Product: oe-core
+ Author: Alexander Kanavin <alex.kanavin@gmail.com>
+ """
+ import subprocess, os
+
+ distro = oe.lsb.distro_identifier()
+ if distro and (distro in ['debian-9', 'debian-10', 'centos-7', 'centos-8', 'ubuntu-16.04', 'ubuntu-18.04'] or distro.startswith('almalinux')):
+ self.skipTest('virgl headless cannot be tested with %s' %(distro))
+
+ render_hint = """If /dev/dri/renderD* is absent due to lack of suitable GPU, 'modprobe vgem' will create one suitable for mesa llvmpipe software renderer."""
+ try:
+ content = os.listdir("/dev/dri")
+ if len([i for i in content if i.startswith('render')]) == 0:
+ self.fail("No render nodes found in /dev/dri: %s. %s" %(content, render_hint))
+ except FileNotFoundError:
+ self.fail("/dev/dri directory does not exist; no render nodes available on this machine. %s" %(render_hint))
+ try:
+ dripath = subprocess.check_output("PATH=/bin:/usr/bin:$PATH pkg-config --variable=dridriverdir dri", shell=True)
+ except subprocess.CalledProcessError as e:
+ self.fail("Could not determine the path to dri drivers on the host via pkg-config.\nPlease install Mesa development files (particularly, dri.pc) on the host machine.")
+ qemu_distrofeatures = get_bb_var('DISTRO_FEATURES', 'qemu-system-native')
+ features = 'IMAGE_CLASSES += "testimage"\n'
+ if 'opengl' not in qemu_distrofeatures:
+ features += 'DISTRO_FEATURES:append = " opengl"\n'
+ features += 'TEST_SUITES = "ping ssh virgl"\n'
+ features += 'IMAGE_FEATURES:append = " ssh-server-dropbear"\n'
+ features += 'IMAGE_INSTALL:append = " kmscube"\n'
+ features += 'TEST_RUNQEMUPARAMS = "egl-headless"\n'
+ self.write_config(features)
+ bitbake('core-image-minimal')
+ bitbake('-c testimage core-image-minimal')
+
+@OETestTag("runqemu")
+class Postinst(OESelftestTestCase):
+
+ def init_manager_loop(self, init_manager):
+ import oe.path
+
+ vars = get_bb_vars(("IMAGE_ROOTFS", "sysconfdir"), "core-image-minimal")
+ rootfs = vars["IMAGE_ROOTFS"]
+ self.assertIsNotNone(rootfs)
+ sysconfdir = vars["sysconfdir"]
+ self.assertIsNotNone(sysconfdir)
+ # Need to use oe.path here as sysconfdir starts with /
+ hosttestdir = oe.path.join(rootfs, sysconfdir, "postinst-test")
+ targettestdir = os.path.join(sysconfdir, "postinst-test")
+
+ for classes in ("package_rpm", "package_deb", "package_ipk"):
+ with self.subTest(init_manager=init_manager, package_class=classes):
+ features = 'CORE_IMAGE_EXTRA_INSTALL = "postinst-delayed-b"\n'
+ features += 'IMAGE_FEATURES += "package-management empty-root-password"\n'
+ features += 'PACKAGE_CLASSES = "%s"\n' % classes
+ if init_manager == "systemd":
+ features += 'DISTRO_FEATURES:append = " systemd"\n'
+ features += 'VIRTUAL-RUNTIME_init_manager = "systemd"\n'
+ features += 'DISTRO_FEATURES_BACKFILL_CONSIDERED = "sysvinit"\n'
+ features += 'VIRTUAL-RUNTIME_initscripts = ""\n'
+ self.write_config(features)
+
+ bitbake('core-image-minimal')
+
+ self.assertTrue(os.path.isfile(os.path.join(hosttestdir, "rootfs")),
+ "rootfs state file was not created")
+
+ with runqemu('core-image-minimal') as qemu:
+ # Make the test echo a string and search for that as
+ # run_serial()'s status code is useless.'
+ for filename in ("rootfs", "delayed-a", "delayed-b"):
+ status, output = qemu.run_serial("test -f %s && echo found" % os.path.join(targettestdir, filename))
+ self.assertIn("found", output, "%s was not present on boot" % filename)
+
+
+
+ @skipIfNotQemu()
+ def test_postinst_rootfs_and_boot_sysvinit(self):
+ """
+ Summary: The purpose of this test case is to verify Post-installation
+ scripts are called when rootfs is created and also test
+ that script can be delayed to run at first boot.
+ Dependencies: NA
+ Steps: 1. Add proper configuration to local.conf file
+ 2. Build a "core-image-minimal" image
+ 3. Verify that file created by postinst_rootfs recipe is
+ present on rootfs dir.
+ 4. Boot the image created on qemu and verify that the file
+ created by postinst_boot recipe is present on image.
+ Expected: The files are successfully created during rootfs and boot
+ time for 3 different package managers: rpm,ipk,deb and
+ for initialization managers: sysvinit.
+
+ """
+ self.init_manager_loop("sysvinit")
+
+
+ @skipIfNotQemu()
+ def test_postinst_rootfs_and_boot_systemd(self):
+ """
+ Summary: The purpose of this test case is to verify Post-installation
+ scripts are called when rootfs is created and also test
+ that script can be delayed to run at first boot.
+ Dependencies: NA
+ Steps: 1. Add proper configuration to local.conf file
+ 2. Build a "core-image-minimal" image
+ 3. Verify that file created by postinst_rootfs recipe is
+ present on rootfs dir.
+ 4. Boot the image created on qemu and verify that the file
+ created by postinst_boot recipe is present on image.
+ Expected: The files are successfully created during rootfs and boot
+ time for 3 different package managers: rpm,ipk,deb and
+ for initialization managers: systemd.
+
+ """
+
+ self.init_manager_loop("systemd")
+
+
+ def test_failing_postinst(self):
+ """
+ Summary: The purpose of this test case is to verify that post-installation
+ scripts that contain errors are properly reported.
+ Expected: The scriptlet failure is properly reported.
+ The file that is created after the error in the scriptlet is not present.
+ Product: oe-core
+ Author: Alexander Kanavin <alex.kanavin@gmail.com>
+ """
+
+ import oe.path
+
+ vars = get_bb_vars(("IMAGE_ROOTFS", "sysconfdir"), "core-image-minimal")
+ rootfs = vars["IMAGE_ROOTFS"]
+ self.assertIsNotNone(rootfs)
+ sysconfdir = vars["sysconfdir"]
+ self.assertIsNotNone(sysconfdir)
+ # Need to use oe.path here as sysconfdir starts with /
+ hosttestdir = oe.path.join(rootfs, sysconfdir, "postinst-test")
+
+ for classes in ("package_rpm", "package_deb", "package_ipk"):
+ with self.subTest(package_class=classes):
+ features = 'CORE_IMAGE_EXTRA_INSTALL = "postinst-rootfs-failing"\n'
+ features += 'PACKAGE_CLASSES = "%s"\n' % classes
+ self.write_config(features)
+ bb_result = bitbake('core-image-minimal', ignore_status=True)
+ self.assertGreaterEqual(bb_result.output.find("Postinstall scriptlets of ['postinst-rootfs-failing'] have failed."), 0,
+ "Warning about a failed scriptlet not found in bitbake output: %s" %(bb_result.output))
+
+ self.assertTrue(os.path.isfile(os.path.join(hosttestdir, "rootfs-before-failure")),
+ "rootfs-before-failure file was not created")
+ self.assertFalse(os.path.isfile(os.path.join(hosttestdir, "rootfs-after-failure")),
+ "rootfs-after-failure file was created")
+
+@OETestTag("runqemu")
+class SystemTap(OESelftestTestCase):
+ """
+ Summary: The purpose of this test case is to verify native crosstap
+ works while talking to a target.
+ Expected: The script should successfully connect to the qemu machine
+ and run some systemtap examples on a qemu machine.
+ """
+
+ @classmethod
+ def setUpClass(cls):
+ super(SystemTap, cls).setUpClass()
+ cls.image = "core-image-minimal"
+
+ def default_config(self):
+ return """
+# These aren't the actual IP addresses but testexport class needs something defined
+TEST_SERVER_IP = "192.168.7.1"
+TEST_TARGET_IP = "192.168.7.2"
+
+EXTRA_IMAGE_FEATURES += "tools-profile dbg-pkgs"
+IMAGE_FEATURES:append = " ssh-server-dropbear"
+
+# enables kernel debug symbols
+KERNEL_EXTRA_FEATURES:append = " features/debug/debug-kernel.scc"
+KERNEL_EXTRA_FEATURES:append = " features/systemtap/systemtap.scc"
+
+# add systemtap run-time into target image if it is not there yet
+IMAGE_INSTALL:append = " systemtap-runtime"
+"""
+
+ def test_crosstap_helloworld(self):
+ self.write_config(self.default_config())
+ bitbake('systemtap-native')
+ systemtap_examples = os.path.join(get_bb_var("WORKDIR","systemtap-native"), "usr/share/systemtap/examples")
+ bitbake(self.image)
+
+ with runqemu(self.image) as qemu:
+ cmd = "crosstap -r root@192.168.7.2 -s %s/general/helloworld.stp " % systemtap_examples
+ result = runCmd(cmd)
+ self.assertEqual(0, result.status, 'crosstap helloworld returned a non 0 status:%s' % result.output)
+
+ def test_crosstap_pstree(self):
+ self.write_config(self.default_config())
+
+ bitbake('systemtap-native')
+ systemtap_examples = os.path.join(get_bb_var("WORKDIR","systemtap-native"), "usr/share/systemtap/examples")
+ bitbake(self.image)
+
+ with runqemu(self.image) as qemu:
+ cmd = "crosstap -r root@192.168.7.2 -s %s/process/pstree.stp" % systemtap_examples
+ result = runCmd(cmd)
+ self.assertEqual(0, result.status, 'crosstap pstree returned a non 0 status:%s' % result.output)
+
+ def test_crosstap_syscalls_by_proc(self):
+ self.write_config(self.default_config())
+
+ bitbake('systemtap-native')
+ systemtap_examples = os.path.join(get_bb_var("WORKDIR","systemtap-native"), "usr/share/systemtap/examples")
+ bitbake(self.image)
+
+ with runqemu(self.image) as qemu:
+ cmd = "crosstap -r root@192.168.7.2 -s %s/process/ syscalls_by_proc.stp" % systemtap_examples
+ result = runCmd(cmd)
+ self.assertEqual(0, result.status, 'crosstap syscalls_by_proc returned a non 0 status:%s' % result.output)
+
+ def test_crosstap_syscalls_by_pid(self):
+ self.write_config(self.default_config())
+
+ bitbake('systemtap-native')
+ systemtap_examples = os.path.join(get_bb_var("WORKDIR","systemtap-native"), "usr/share/systemtap/examples")
+ bitbake(self.image)
+
+ with runqemu(self.image) as qemu:
+ cmd = "crosstap -r root@192.168.7.2 -s %s/process/ syscalls_by_pid.stp" % systemtap_examples
+ result = runCmd(cmd)
+ self.assertEqual(0, result.status, 'crosstap syscalls_by_pid returned a non 0 status:%s' % result.output)
diff --git a/meta/lib/oeqa/selftest/cases/selftest.py b/meta/lib/oeqa/selftest/cases/selftest.py
new file mode 100644
index 0000000000..a80a8651a5
--- /dev/null
+++ b/meta/lib/oeqa/selftest/cases/selftest.py
@@ -0,0 +1,54 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
+import importlib
+import oeqa.selftest
+from oeqa.selftest.case import OESelftestTestCase
+
+class ExternalLayer(OESelftestTestCase):
+
+ def test_list_imported(self):
+ """
+ Summary: Checks functionality to import tests from other layers.
+ Expected: 1. File "external-layer.py" must be in
+ oeqa.selftest.__path__
+ 2. test_unconditional_pas method must exists
+ in ImportedTests class
+ Product: oe-core
+ Author: Mariano Lopez <mariano.lopez@intel.com>
+ """
+
+ test_file = "external-layer.py"
+ test_module = "oeqa.selftest.cases.external-layer"
+ method_name = "test_unconditional_pass"
+
+ # Check if "external-layer.py" is in oeqa path
+ found_file = search_test_file(test_file)
+ self.assertTrue(found_file, msg="Can't find %s in the oeqa path" % test_file)
+
+ # Import oeqa.selftest.external-layer module and search for
+ # test_unconditional_pass method of ImportedTests class
+ found_method = search_method(test_module, method_name)
+ self.assertTrue(method_name, msg="Can't find %s method" % method_name)
+
+def search_test_file(file_name):
+ for layer_path in oeqa.selftest.__path__:
+ for _, _, files in os.walk(layer_path):
+ for f in files:
+ if f == file_name:
+ return True
+ return False
+
+def search_method(module, method):
+ modlib = importlib.import_module(module)
+ for var in vars(modlib):
+ klass = vars(modlib)[var]
+ if isinstance(klass, type(OESelftestTestCase)) and issubclass(klass, OESelftestTestCase):
+ for m in dir(klass):
+ if m == method:
+ return True
+ return False
+
diff --git a/meta/lib/oeqa/selftest/cases/signing.py b/meta/lib/oeqa/selftest/cases/signing.py
new file mode 100644
index 0000000000..322e753ed3
--- /dev/null
+++ b/meta/lib/oeqa/selftest/cases/signing.py
@@ -0,0 +1,228 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
+from oeqa.selftest.case import OESelftestTestCase
+from oeqa.utils.commands import runCmd, bitbake, get_bb_var, get_bb_vars, create_temp_layer
+import os
+import oe
+import glob
+import re
+import shutil
+import tempfile
+from contextlib import contextmanager
+from oeqa.utils.ftools import write_file
+
+
+class Signing(OESelftestTestCase):
+
+ gpg_dir = ""
+ pub_key_path = ""
+ secret_key_path = ""
+
+ def setup_gpg(self):
+ bitbake('gnupg-native -c addto_recipe_sysroot')
+
+ self.gpg_dir = tempfile.mkdtemp(prefix="oeqa-signing-")
+ self.track_for_cleanup(self.gpg_dir)
+
+ self.pub_key_path = os.path.join(self.testlayer_path, 'files', 'signing', "key.pub")
+ self.secret_key_path = os.path.join(self.testlayer_path, 'files', 'signing', "key.secret")
+
+ nsysroot = get_bb_var("RECIPE_SYSROOT_NATIVE", "gnupg-native")
+
+ runCmd('gpg --agent-program=`which gpg-agent`\|--auto-expand-secmem --batch --homedir %s --import %s %s' % (self.gpg_dir, self.pub_key_path, self.secret_key_path), native_sysroot=nsysroot)
+ return nsysroot + get_bb_var("bindir_native")
+
+
+ @contextmanager
+ def create_new_builddir(self, builddir, newbuilddir):
+ bb.utils.mkdirhier(newbuilddir)
+ oe.path.copytree(builddir + "/conf", newbuilddir + "/conf")
+ oe.path.copytree(builddir + "/cache", newbuilddir + "/cache")
+
+ origenv = os.environ.copy()
+
+ for e in os.environ:
+ if builddir + "/" in os.environ[e]:
+ os.environ[e] = os.environ[e].replace(builddir + "/", newbuilddir + "/")
+ if os.environ[e].endswith(builddir):
+ os.environ[e] = os.environ[e].replace(builddir, newbuilddir)
+
+ os.chdir(newbuilddir)
+ try:
+ yield
+ finally:
+ for e in origenv:
+ os.environ[e] = origenv[e]
+ os.chdir(builddir)
+
+ def test_signing_packages(self):
+ """
+ Summary: Test that packages can be signed in the package feed
+ Expected: Package should be signed with the correct key
+ Expected: Images can be created from signed packages
+ Product: oe-core
+ Author: Daniel Istrate <daniel.alexandrux.istrate@intel.com>
+ Author: Alexander Kanavin <alex.kanavin@gmail.com>
+ AutomatedBy: Daniel Istrate <daniel.alexandrux.istrate@intel.com>
+ """
+ import oe.packagedata
+
+ self.setup_gpg()
+
+ package_classes = get_bb_var('PACKAGE_CLASSES')
+ if 'package_rpm' not in package_classes:
+ self.skipTest('This test requires RPM Packaging.')
+
+ test_recipe = 'ed'
+
+ feature = 'INHERIT += "sign_rpm"\n'
+ feature += 'RPM_GPG_PASSPHRASE = "test123"\n'
+ feature += 'RPM_GPG_NAME = "testuser"\n'
+ feature += 'GPG_PATH = "%s"\n' % self.gpg_dir
+
+ self.write_config(feature)
+
+ bitbake('-c clean %s' % test_recipe)
+ bitbake('-f -c package_write_rpm %s' % test_recipe)
+
+ self.add_command_to_tearDown('bitbake -c clean %s' % test_recipe)
+
+ needed_vars = ['PKGDATA_DIR', 'DEPLOY_DIR_RPM', 'PACKAGE_ARCH', 'STAGING_BINDIR_NATIVE']
+ bb_vars = get_bb_vars(needed_vars, test_recipe)
+ pkgdatadir = bb_vars['PKGDATA_DIR']
+ pkgdata = oe.packagedata.read_pkgdatafile(pkgdatadir + "/runtime/ed")
+ if 'PKGE' in pkgdata:
+ pf = pkgdata['PN'] + "-" + pkgdata['PKGE'] + pkgdata['PKGV'] + '-' + pkgdata['PKGR']
+ else:
+ pf = pkgdata['PN'] + "-" + pkgdata['PKGV'] + '-' + pkgdata['PKGR']
+ deploy_dir_rpm = bb_vars['DEPLOY_DIR_RPM']
+ package_arch = bb_vars['PACKAGE_ARCH'].replace('-', '_')
+ staging_bindir_native = bb_vars['STAGING_BINDIR_NATIVE']
+
+ pkg_deploy = os.path.join(deploy_dir_rpm, package_arch, '.'.join((pf, package_arch, 'rpm')))
+
+ # Use a temporary rpmdb
+ rpmdb = tempfile.mkdtemp(prefix='oeqa-rpmdb')
+
+ runCmd('%s/rpmkeys --define "_dbpath %s" --import %s' %
+ (staging_bindir_native, rpmdb, self.pub_key_path))
+
+ ret = runCmd('%s/rpmkeys --define "_dbpath %s" --checksig %s' %
+ (staging_bindir_native, rpmdb, pkg_deploy))
+ # tmp/deploy/rpm/i586/ed-1.9-r0.i586.rpm: rsa sha1 md5 OK
+ self.assertIn('digests signatures OK', ret.output, 'Package signed incorrectly.')
+ shutil.rmtree(rpmdb)
+
+ #Check that an image can be built from signed packages
+ self.add_command_to_tearDown('bitbake -c clean core-image-minimal')
+ bitbake('-c clean core-image-minimal')
+ bitbake('core-image-minimal')
+
+
+ def test_signing_sstate_archive(self):
+ """
+ Summary: Test that sstate archives can be signed
+ Expected: Package should be signed with the correct key
+ Product: oe-core
+ Author: Daniel Istrate <daniel.alexandrux.istrate@intel.com>
+ AutomatedBy: Daniel Istrate <daniel.alexandrux.istrate@intel.com>
+ """
+
+ test_recipe = 'ed'
+
+ # Since we need gpg but we can't use gpg-native for sstate signatures, we
+ # build gpg-native in our original builddir then run the tests in a second one.
+ builddir = os.environ.get('BUILDDIR') + "-testsign"
+ sstatedir = os.path.join(builddir, 'test-sstate')
+
+ nsysroot = self.setup_gpg()
+
+ feature = 'SSTATE_SIG_KEY ?= "testuser"\n'
+ feature += 'SSTATE_SIG_PASSPHRASE ?= "test123"\n'
+ feature += 'SSTATE_VERIFY_SIG ?= "1"\n'
+ feature += 'GPG_PATH = "%s"\n' % self.gpg_dir
+ feature += 'SSTATE_DIR = "%s"\n' % sstatedir
+ # Any mirror might have partial sstate without .sig files, triggering failures
+ feature += 'SSTATE_MIRRORS:forcevariable = ""\n'
+
+ self.write_config(feature)
+
+ with self.create_new_builddir(os.environ['BUILDDIR'], builddir):
+
+ os.environ["PATH"] = nsysroot + ":" + os.environ["PATH"]
+ self.add_command_to_tearDown('bitbake -c clean %s' % test_recipe)
+ self.add_command_to_tearDown('rm -rf %s' % sstatedir)
+ self.add_command_to_tearDown('rm -rf %s' % builddir)
+
+ bitbake('-c clean %s' % test_recipe)
+ bitbake('-c populate_lic %s' % test_recipe)
+
+ recipe_sig = glob.glob(sstatedir + '/*/*/*:ed:*_populate_lic.tar.zst.sig')
+ recipe_archive = glob.glob(sstatedir + '/*/*/*:ed:*_populate_lic.tar.zst')
+
+ self.assertEqual(len(recipe_sig), 1, 'Failed to find .sig file.')
+ self.assertEqual(len(recipe_archive), 1, 'Failed to find .tar.zst file.')
+
+ ret = runCmd('gpg --homedir %s --verify %s %s' % (self.gpg_dir, recipe_sig[0], recipe_archive[0]))
+ # gpg: Signature made Thu 22 Oct 2015 01:45:09 PM EEST using RSA key ID 61EEFB30
+ # gpg: Good signature from "testuser (nocomment) <testuser@email.com>"
+ self.assertIn('gpg: Good signature from', ret.output, 'Package signed incorrectly.')
+
+
+class LockedSignatures(OESelftestTestCase):
+
+ def test_locked_signatures(self):
+ """
+ Summary: Test locked signature mechanism
+ Expected: Locked signatures will prevent task to run
+ Product: oe-core
+ Author: Daniel Istrate <daniel.alexandrux.istrate@intel.com>
+ AutomatedBy: Daniel Istrate <daniel.alexandrux.istrate@intel.com>
+ """
+
+ import uuid
+
+ test_recipe = 'ed'
+ locked_sigs_file = 'locked-sigs.inc'
+
+ bitbake(test_recipe)
+ # Generate locked sigs include file
+ bitbake('-S none %s' % test_recipe)
+
+ feature = 'require %s\n' % locked_sigs_file
+ feature += 'SIGGEN_LOCKEDSIGS_TASKSIG_CHECK = "warn"\n'
+ self.write_config(feature)
+
+ # Build a locked recipe
+ bitbake(test_recipe)
+
+ templayerdir = tempfile.mkdtemp(prefix='signingqa')
+ create_temp_layer(templayerdir, 'selftestsigning')
+ runCmd('bitbake-layers add-layer %s' % templayerdir)
+
+ # Make a change that should cause the locked task signature to change
+ # Use uuid so hash equivalance server isn't triggered
+ recipe_append_file = test_recipe + '_' + get_bb_var('PV', test_recipe) + '.bbappend'
+ recipe_append_path = os.path.join(templayerdir, 'recipes-test', test_recipe, recipe_append_file)
+ feature = 'SUMMARY:${PN} = "test locked signature%s"\n' % uuid.uuid4()
+
+ os.mkdir(os.path.join(templayerdir, 'recipes-test'))
+ os.mkdir(os.path.join(templayerdir, 'recipes-test', test_recipe))
+ write_file(recipe_append_path, feature)
+
+ self.add_command_to_tearDown('bitbake-layers remove-layer %s' % templayerdir)
+ self.add_command_to_tearDown('rm -f %s' % os.path.join(self.builddir, locked_sigs_file))
+ self.add_command_to_tearDown('rm -rf %s' % templayerdir)
+
+ # Build the recipe again
+ ret = bitbake(test_recipe)
+
+ # Verify you get the warning and that the real task *isn't* run (i.e. the locked signature has worked)
+ patt = r'The %s:do_package sig is computed to be \S+, but the sig is locked to \S+ in SIGGEN_LOCKEDSIGS\S+' % test_recipe
+ found_warn = re.search(patt, ret.output)
+
+ self.assertIsNotNone(found_warn, "Didn't find the expected warning message. Output: %s" % ret.output)
diff --git a/meta/lib/oeqa/selftest/sstate.py b/meta/lib/oeqa/selftest/cases/sstate.py
index 5989724432..e73bb94884 100644
--- a/meta/lib/oeqa/selftest/sstate.py
+++ b/meta/lib/oeqa/selftest/cases/sstate.py
@@ -1,21 +1,33 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
import datetime
-import unittest
import os
import re
-import shutil
-import oeqa.utils.ftools as ftools
-from oeqa.selftest.base import oeSelfTest
-from oeqa.utils.commands import runCmd, bitbake, get_bb_var, get_test_layer
+from oeqa.selftest.case import OESelftestTestCase
+from oeqa.utils.commands import get_bb_vars
-class SStateBase(oeSelfTest):
+class SStateBase(OESelftestTestCase):
def setUpLocal(self):
+ super(SStateBase, self).setUpLocal()
self.temp_sstate_location = None
- self.sstate_path = get_bb_var('SSTATE_DIR')
- self.distro = get_bb_var('NATIVELSBSTRING')
- self.distro_specific_sstate = os.path.join(self.sstate_path, self.distro)
+ needed_vars = ['SSTATE_DIR', 'NATIVELSBSTRING', 'TCLIBC', 'TUNE_ARCH',
+ 'TOPDIR', 'TARGET_VENDOR', 'TARGET_OS']
+ bb_vars = get_bb_vars(needed_vars)
+ self.sstate_path = bb_vars['SSTATE_DIR']
+ self.hostdistro = bb_vars['NATIVELSBSTRING']
+ self.tclibc = bb_vars['TCLIBC']
+ self.tune_arch = bb_vars['TUNE_ARCH']
+ self.topdir = bb_vars['TOPDIR']
+ self.target_vendor = bb_vars['TARGET_VENDOR']
+ self.target_os = bb_vars['TARGET_OS']
+ self.distro_specific_sstate = os.path.join(self.sstate_path, self.hostdistro)
# Creates a special sstate configuration with the option to add sstate mirrors
def config_sstate(self, temp_sstate_location=False, add_local_mirrors=[]):
@@ -26,9 +38,10 @@ class SStateBase(oeSelfTest):
config_temp_sstate = "SSTATE_DIR = \"%s\"" % temp_sstate_path
self.append_config(config_temp_sstate)
self.track_for_cleanup(temp_sstate_path)
- self.sstate_path = get_bb_var('SSTATE_DIR')
- self.distro = get_bb_var('NATIVELSBSTRING')
- self.distro_specific_sstate = os.path.join(self.sstate_path, self.distro)
+ bb_vars = get_bb_vars(['SSTATE_DIR', 'NATIVELSBSTRING'])
+ self.sstate_path = bb_vars['SSTATE_DIR']
+ self.hostdistro = bb_vars['NATIVELSBSTRING']
+ self.distro_specific_sstate = os.path.join(self.sstate_path, self.hostdistro)
if add_local_mirrors:
config_set_sstate_if_not_set = 'SSTATE_MIRRORS ?= ""'
@@ -42,11 +55,11 @@ class SStateBase(oeSelfTest):
def search_sstate(self, filename_regex, distro_specific=True, distro_nonspecific=True):
result = []
for root, dirs, files in os.walk(self.sstate_path):
- if distro_specific and re.search("%s/[a-z0-9]{2}$" % self.distro, root):
+ if distro_specific and re.search(r"%s/%s/[a-z0-9]{2}/[a-z0-9]{2}$" % (self.sstate_path, self.hostdistro), root):
for f in files:
if re.search(filename_regex, f):
result.append(f)
- if distro_nonspecific and re.search("%s/[a-z0-9]{2}$" % self.sstate_path, root):
+ if distro_nonspecific and re.search(r"%s/[a-z0-9]{2}/[a-z0-9]{2}$" % self.sstate_path, root):
for f in files:
if re.search(filename_regex, f):
result.append(f)
diff --git a/meta/lib/oeqa/selftest/cases/sstatetests.py b/meta/lib/oeqa/selftest/cases/sstatetests.py
new file mode 100644
index 0000000000..ae766f91bd
--- /dev/null
+++ b/meta/lib/oeqa/selftest/cases/sstatetests.py
@@ -0,0 +1,627 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
+import os
+import shutil
+import glob
+import subprocess
+import tempfile
+
+from oeqa.utils.commands import runCmd, bitbake, get_bb_var, create_temp_layer
+from oeqa.selftest.cases.sstate import SStateBase
+import oe
+
+import bb.siggen
+
+class SStateTests(SStateBase):
+ def test_autorev_sstate_works(self):
+ # Test that a git repository which changes is correctly handled by SRCREV = ${AUTOREV}
+ # when PV does not contain SRCPV
+
+ tempdir = tempfile.mkdtemp(prefix='sstate_autorev')
+ tempdldir = tempfile.mkdtemp(prefix='sstate_autorev_dldir')
+ self.track_for_cleanup(tempdir)
+ self.track_for_cleanup(tempdldir)
+ create_temp_layer(tempdir, 'selftestrecipetool')
+ self.add_command_to_tearDown('bitbake-layers remove-layer %s' % tempdir)
+ self.append_config("DL_DIR = \"%s\"" % tempdldir)
+ runCmd('bitbake-layers add-layer %s' % tempdir)
+
+ # Use dbus-wait as a local git repo we can add a commit between two builds in
+ pn = 'dbus-wait'
+ srcrev = '6cc6077a36fe2648a5f993fe7c16c9632f946517'
+ url = 'git://git.yoctoproject.org/dbus-wait'
+ result = runCmd('git clone %s noname' % url, cwd=tempdir)
+ srcdir = os.path.join(tempdir, 'noname')
+ result = runCmd('git reset --hard %s' % srcrev, cwd=srcdir)
+ self.assertTrue(os.path.isfile(os.path.join(srcdir, 'configure.ac')), 'Unable to find configure script in source directory')
+
+ recipefile = os.path.join(tempdir, "recipes-test", "dbus-wait-test", 'dbus-wait-test_git.bb')
+ os.makedirs(os.path.dirname(recipefile))
+ srcuri = 'git://' + srcdir + ';protocol=file;branch=master'
+ result = runCmd(['recipetool', 'create', '-o', recipefile, srcuri])
+ self.assertTrue(os.path.isfile(recipefile), 'recipetool did not create recipe file; output:\n%s' % result.output)
+
+ with open(recipefile, 'a') as f:
+ f.write('SRCREV = "${AUTOREV}"\n')
+ f.write('PV = "1.0"\n')
+
+ bitbake("dbus-wait-test -c fetch")
+ with open(os.path.join(srcdir, "bar.txt"), "w") as f:
+ f.write("foo")
+ result = runCmd('git add bar.txt; git commit -asm "add bar"', cwd=srcdir)
+ bitbake("dbus-wait-test -c unpack")
+
+
+ # Test sstate files creation and their location
+ def run_test_sstate_creation(self, targets, distro_specific=True, distro_nonspecific=True, temp_sstate_location=True, should_pass=True):
+ self.config_sstate(temp_sstate_location, [self.sstate_path])
+
+ if self.temp_sstate_location:
+ bitbake(['-cclean'] + targets)
+ else:
+ bitbake(['-ccleansstate'] + targets)
+
+ bitbake(targets)
+ file_tracker = []
+ results = self.search_sstate('|'.join(map(str, targets)), distro_specific, distro_nonspecific)
+ if distro_nonspecific:
+ for r in results:
+ if r.endswith(("_populate_lic.tar.zst", "_populate_lic.tar.zst.siginfo", "_fetch.tar.zst.siginfo", "_unpack.tar.zst.siginfo", "_patch.tar.zst.siginfo")):
+ continue
+ file_tracker.append(r)
+ else:
+ file_tracker = results
+
+ if should_pass:
+ self.assertTrue(file_tracker , msg="Could not find sstate files for: %s" % ', '.join(map(str, targets)))
+ else:
+ self.assertTrue(not file_tracker , msg="Found sstate files in the wrong place for: %s (found %s)" % (', '.join(map(str, targets)), str(file_tracker)))
+
+ def test_sstate_creation_distro_specific_pass(self):
+ self.run_test_sstate_creation(['binutils-cross-'+ self.tune_arch, 'binutils-native'], distro_specific=True, distro_nonspecific=False, temp_sstate_location=True)
+
+ def test_sstate_creation_distro_specific_fail(self):
+ self.run_test_sstate_creation(['binutils-cross-'+ self.tune_arch, 'binutils-native'], distro_specific=False, distro_nonspecific=True, temp_sstate_location=True, should_pass=False)
+
+ def test_sstate_creation_distro_nonspecific_pass(self):
+ self.run_test_sstate_creation(['linux-libc-headers'], distro_specific=False, distro_nonspecific=True, temp_sstate_location=True)
+
+ def test_sstate_creation_distro_nonspecific_fail(self):
+ self.run_test_sstate_creation(['linux-libc-headers'], distro_specific=True, distro_nonspecific=False, temp_sstate_location=True, should_pass=False)
+
+ # Test the sstate files deletion part of the do_cleansstate task
+ def run_test_cleansstate_task(self, targets, distro_specific=True, distro_nonspecific=True, temp_sstate_location=True):
+ self.config_sstate(temp_sstate_location, [self.sstate_path])
+
+ bitbake(['-ccleansstate'] + targets)
+
+ bitbake(targets)
+ archives_created = self.search_sstate('|'.join(map(str, [s + r'.*?\.tar.zst$' for s in targets])), distro_specific, distro_nonspecific)
+ self.assertTrue(archives_created, msg="Could not find sstate .tar.zst files for: %s (%s)" % (', '.join(map(str, targets)), str(archives_created)))
+
+ siginfo_created = self.search_sstate('|'.join(map(str, [s + r'.*?\.siginfo$' for s in targets])), distro_specific, distro_nonspecific)
+ self.assertTrue(siginfo_created, msg="Could not find sstate .siginfo files for: %s (%s)" % (', '.join(map(str, targets)), str(siginfo_created)))
+
+ bitbake(['-ccleansstate'] + targets)
+ archives_removed = self.search_sstate('|'.join(map(str, [s + r'.*?\.tar.zst$' for s in targets])), distro_specific, distro_nonspecific)
+ self.assertTrue(not archives_removed, msg="do_cleansstate didn't remove .tar.zst sstate files for: %s (%s)" % (', '.join(map(str, targets)), str(archives_removed)))
+
+ def test_cleansstate_task_distro_specific_nonspecific(self):
+ targets = ['binutils-cross-'+ self.tune_arch, 'binutils-native']
+ targets.append('linux-libc-headers')
+ self.run_test_cleansstate_task(targets, distro_specific=True, distro_nonspecific=True, temp_sstate_location=True)
+
+ def test_cleansstate_task_distro_nonspecific(self):
+ self.run_test_cleansstate_task(['linux-libc-headers'], distro_specific=False, distro_nonspecific=True, temp_sstate_location=True)
+
+ def test_cleansstate_task_distro_specific(self):
+ targets = ['binutils-cross-'+ self.tune_arch, 'binutils-native']
+ targets.append('linux-libc-headers')
+ self.run_test_cleansstate_task(targets, distro_specific=True, distro_nonspecific=False, temp_sstate_location=True)
+
+
+ # Test rebuilding of distro-specific sstate files
+ def run_test_rebuild_distro_specific_sstate(self, targets, temp_sstate_location=True):
+ self.config_sstate(temp_sstate_location, [self.sstate_path])
+
+ bitbake(['-ccleansstate'] + targets)
+
+ bitbake(targets)
+ results = self.search_sstate('|'.join(map(str, [s + r'.*?\.tar.zst$' for s in targets])), distro_specific=False, distro_nonspecific=True)
+ filtered_results = []
+ for r in results:
+ if r.endswith(("_populate_lic.tar.zst", "_populate_lic.tar.zst.siginfo")):
+ continue
+ filtered_results.append(r)
+ self.assertTrue(filtered_results == [], msg="Found distro non-specific sstate for: %s (%s)" % (', '.join(map(str, targets)), str(filtered_results)))
+ file_tracker_1 = self.search_sstate('|'.join(map(str, [s + r'.*?\.tar.zst$' for s in targets])), distro_specific=True, distro_nonspecific=False)
+ self.assertTrue(len(file_tracker_1) >= len(targets), msg = "Not all sstate files were created for: %s" % ', '.join(map(str, targets)))
+
+ self.track_for_cleanup(self.distro_specific_sstate + "_old")
+ shutil.copytree(self.distro_specific_sstate, self.distro_specific_sstate + "_old")
+ shutil.rmtree(self.distro_specific_sstate)
+
+ bitbake(['-cclean'] + targets)
+ bitbake(targets)
+ file_tracker_2 = self.search_sstate('|'.join(map(str, [s + r'.*?\.tar.zst$' for s in targets])), distro_specific=True, distro_nonspecific=False)
+ self.assertTrue(len(file_tracker_2) >= len(targets), msg = "Not all sstate files were created for: %s" % ', '.join(map(str, targets)))
+
+ not_recreated = [x for x in file_tracker_1 if x not in file_tracker_2]
+ self.assertTrue(not_recreated == [], msg="The following sstate files were not recreated: %s" % ', '.join(map(str, not_recreated)))
+
+ created_once = [x for x in file_tracker_2 if x not in file_tracker_1]
+ self.assertTrue(created_once == [], msg="The following sstate files were created only in the second run: %s" % ', '.join(map(str, created_once)))
+
+ def test_rebuild_distro_specific_sstate_cross_native_targets(self):
+ self.run_test_rebuild_distro_specific_sstate(['binutils-cross-' + self.tune_arch, 'binutils-native'], temp_sstate_location=True)
+
+ def test_rebuild_distro_specific_sstate_cross_target(self):
+ self.run_test_rebuild_distro_specific_sstate(['binutils-cross-' + self.tune_arch], temp_sstate_location=True)
+
+ def test_rebuild_distro_specific_sstate_native_target(self):
+ self.run_test_rebuild_distro_specific_sstate(['binutils-native'], temp_sstate_location=True)
+
+
+ # Test the sstate-cache-management script. Each element in the global_config list is used with the corresponding element in the target_config list
+ # global_config elements are expected to not generate any sstate files that would be removed by sstate-cache-management.sh (such as changing the value of MACHINE)
+ def run_test_sstate_cache_management_script(self, target, global_config=[''], target_config=[''], ignore_patterns=[]):
+ self.assertTrue(global_config)
+ self.assertTrue(target_config)
+ self.assertTrue(len(global_config) == len(target_config), msg='Lists global_config and target_config should have the same number of elements')
+ self.config_sstate(temp_sstate_location=True, add_local_mirrors=[self.sstate_path])
+
+ # If buildhistory is enabled, we need to disable version-going-backwards
+ # QA checks for this test. It may report errors otherwise.
+ self.append_config('ERROR_QA:remove = "version-going-backwards"')
+
+ # For now this only checks if random sstate tasks are handled correctly as a group.
+ # In the future we should add control over what tasks we check for.
+
+ sstate_archs_list = []
+ expected_remaining_sstate = []
+ for idx in range(len(target_config)):
+ self.append_config(global_config[idx])
+ self.append_recipeinc(target, target_config[idx])
+ sstate_arch = get_bb_var('SSTATE_PKGARCH', target)
+ if not sstate_arch in sstate_archs_list:
+ sstate_archs_list.append(sstate_arch)
+ if target_config[idx] == target_config[-1]:
+ target_sstate_before_build = self.search_sstate(target + r'.*?\.tar.zst$')
+ bitbake("-cclean %s" % target)
+ result = bitbake(target, ignore_status=True)
+ if target_config[idx] == target_config[-1]:
+ target_sstate_after_build = self.search_sstate(target + r'.*?\.tar.zst$')
+ expected_remaining_sstate += [x for x in target_sstate_after_build if x not in target_sstate_before_build if not any(pattern in x for pattern in ignore_patterns)]
+ self.remove_config(global_config[idx])
+ self.remove_recipeinc(target, target_config[idx])
+ self.assertEqual(result.status, 0, msg = "build of %s failed with %s" % (target, result.output))
+
+ runCmd("sstate-cache-management.sh -y --cache-dir=%s --remove-duplicated --extra-archs=%s" % (self.sstate_path, ','.join(map(str, sstate_archs_list))))
+ actual_remaining_sstate = [x for x in self.search_sstate(target + r'.*?\.tar.zst$') if not any(pattern in x for pattern in ignore_patterns)]
+
+ actual_not_expected = [x for x in actual_remaining_sstate if x not in expected_remaining_sstate]
+ self.assertFalse(actual_not_expected, msg="Files should have been removed but were not: %s" % ', '.join(map(str, actual_not_expected)))
+ expected_not_actual = [x for x in expected_remaining_sstate if x not in actual_remaining_sstate]
+ self.assertFalse(expected_not_actual, msg="Extra files were removed: %s" ', '.join(map(str, expected_not_actual)))
+
+ def test_sstate_cache_management_script_using_pr_1(self):
+ global_config = []
+ target_config = []
+ global_config.append('')
+ target_config.append('PR = "0"')
+ self.run_test_sstate_cache_management_script('m4', global_config, target_config, ignore_patterns=['populate_lic'])
+
+ def test_sstate_cache_management_script_using_pr_2(self):
+ global_config = []
+ target_config = []
+ global_config.append('')
+ target_config.append('PR = "0"')
+ global_config.append('')
+ target_config.append('PR = "1"')
+ self.run_test_sstate_cache_management_script('m4', global_config, target_config, ignore_patterns=['populate_lic'])
+
+ def test_sstate_cache_management_script_using_pr_3(self):
+ global_config = []
+ target_config = []
+ global_config.append('MACHINE = "qemux86-64"')
+ target_config.append('PR = "0"')
+ global_config.append(global_config[0])
+ target_config.append('PR = "1"')
+ global_config.append('MACHINE = "qemux86"')
+ target_config.append('PR = "1"')
+ self.run_test_sstate_cache_management_script('m4', global_config, target_config, ignore_patterns=['populate_lic'])
+
+ def test_sstate_cache_management_script_using_machine(self):
+ global_config = []
+ target_config = []
+ global_config.append('MACHINE = "qemux86-64"')
+ target_config.append('')
+ global_config.append('MACHINE = "qemux86"')
+ target_config.append('')
+ self.run_test_sstate_cache_management_script('m4', global_config, target_config, ignore_patterns=['populate_lic'])
+
+ def test_sstate_32_64_same_hash(self):
+ """
+ The sstate checksums for both native and target should not vary whether
+ they're built on a 32 or 64 bit system. Rather than requiring two different
+ build machines and running a builds, override the variables calling uname()
+ manually and check using bitbake -S.
+ """
+
+ self.write_config("""
+MACHINE = "qemux86"
+TMPDIR = "${TOPDIR}/tmp-sstatesamehash"
+TCLIBCAPPEND = ""
+BUILD_ARCH = "x86_64"
+BUILD_OS = "linux"
+SDKMACHINE = "x86_64"
+PACKAGE_CLASSES = "package_rpm package_ipk package_deb"
+BB_SIGNATURE_HANDLER = "OEBasicHash"
+""")
+ self.track_for_cleanup(self.topdir + "/tmp-sstatesamehash")
+ bitbake("core-image-weston -S none")
+ self.write_config("""
+MACHINE = "qemux86"
+TMPDIR = "${TOPDIR}/tmp-sstatesamehash2"
+TCLIBCAPPEND = ""
+BUILD_ARCH = "i686"
+BUILD_OS = "linux"
+SDKMACHINE = "i686"
+PACKAGE_CLASSES = "package_rpm package_ipk package_deb"
+BB_SIGNATURE_HANDLER = "OEBasicHash"
+""")
+ self.track_for_cleanup(self.topdir + "/tmp-sstatesamehash2")
+ bitbake("core-image-weston -S none")
+
+ def get_files(d):
+ f = []
+ for root, dirs, files in os.walk(d):
+ if "core-image-weston" in root:
+ # SDKMACHINE changing will change
+ # do_rootfs/do_testimage/do_build stamps of images which
+ # is safe to ignore.
+ continue
+ f.extend(os.path.join(root, name) for name in files)
+ return f
+ files1 = get_files(self.topdir + "/tmp-sstatesamehash/stamps/")
+ files2 = get_files(self.topdir + "/tmp-sstatesamehash2/stamps/")
+ files2 = [x.replace("tmp-sstatesamehash2", "tmp-sstatesamehash").replace("i686-linux", "x86_64-linux").replace("i686" + self.target_vendor + "-linux", "x86_64" + self.target_vendor + "-linux", ) for x in files2]
+ self.maxDiff = None
+ self.assertCountEqual(files1, files2)
+
+
+ def test_sstate_nativelsbstring_same_hash(self):
+ """
+ The sstate checksums should be independent of whichever NATIVELSBSTRING is
+ detected. Rather than requiring two different build machines and running
+ builds, override the variables manually and check using bitbake -S.
+ """
+
+ self.write_config("""
+TMPDIR = \"${TOPDIR}/tmp-sstatesamehash\"
+TCLIBCAPPEND = \"\"
+NATIVELSBSTRING = \"DistroA\"
+BB_SIGNATURE_HANDLER = "OEBasicHash"
+""")
+ self.track_for_cleanup(self.topdir + "/tmp-sstatesamehash")
+ bitbake("core-image-weston -S none")
+ self.write_config("""
+TMPDIR = \"${TOPDIR}/tmp-sstatesamehash2\"
+TCLIBCAPPEND = \"\"
+NATIVELSBSTRING = \"DistroB\"
+BB_SIGNATURE_HANDLER = "OEBasicHash"
+""")
+ self.track_for_cleanup(self.topdir + "/tmp-sstatesamehash2")
+ bitbake("core-image-weston -S none")
+
+ def get_files(d):
+ f = []
+ for root, dirs, files in os.walk(d):
+ f.extend(os.path.join(root, name) for name in files)
+ return f
+ files1 = get_files(self.topdir + "/tmp-sstatesamehash/stamps/")
+ files2 = get_files(self.topdir + "/tmp-sstatesamehash2/stamps/")
+ files2 = [x.replace("tmp-sstatesamehash2", "tmp-sstatesamehash") for x in files2]
+ self.maxDiff = None
+ self.assertCountEqual(files1, files2)
+
+ def test_sstate_allarch_samesigs(self):
+ """
+ The sstate checksums of allarch packages should be independent of whichever
+ MACHINE is set. Check this using bitbake -S.
+ Also, rather than duplicate the test, check nativesdk stamps are the same between
+ the two MACHINE values.
+ """
+
+ configA = """
+TMPDIR = \"${TOPDIR}/tmp-sstatesamehash\"
+TCLIBCAPPEND = \"\"
+MACHINE = \"qemux86-64\"
+BB_SIGNATURE_HANDLER = "OEBasicHash"
+"""
+ #OLDEST_KERNEL is arch specific so set to a different value here for testing
+ configB = """
+TMPDIR = \"${TOPDIR}/tmp-sstatesamehash2\"
+TCLIBCAPPEND = \"\"
+MACHINE = \"qemuarm\"
+OLDEST_KERNEL = \"3.3.0\"
+BB_SIGNATURE_HANDLER = "OEBasicHash"
+"""
+ self.sstate_common_samesigs(configA, configB, allarch=True)
+
+ def test_sstate_nativesdk_samesigs_multilib(self):
+ """
+ check nativesdk stamps are the same between the two MACHINE values.
+ """
+
+ configA = """
+TMPDIR = \"${TOPDIR}/tmp-sstatesamehash\"
+TCLIBCAPPEND = \"\"
+MACHINE = \"qemux86-64\"
+require conf/multilib.conf
+MULTILIBS = \"multilib:lib32\"
+DEFAULTTUNE:virtclass-multilib-lib32 = \"x86\"
+BB_SIGNATURE_HANDLER = "OEBasicHash"
+"""
+ configB = """
+TMPDIR = \"${TOPDIR}/tmp-sstatesamehash2\"
+TCLIBCAPPEND = \"\"
+MACHINE = \"qemuarm\"
+require conf/multilib.conf
+MULTILIBS = \"\"
+BB_SIGNATURE_HANDLER = "OEBasicHash"
+"""
+ self.sstate_common_samesigs(configA, configB)
+
+ def sstate_common_samesigs(self, configA, configB, allarch=False):
+
+ self.write_config(configA)
+ self.track_for_cleanup(self.topdir + "/tmp-sstatesamehash")
+ bitbake("world meta-toolchain -S none")
+ self.write_config(configB)
+ self.track_for_cleanup(self.topdir + "/tmp-sstatesamehash2")
+ bitbake("world meta-toolchain -S none")
+
+ def get_files(d, result):
+ for root, dirs, files in os.walk(d):
+ for name in files:
+ if "meta-environment" in root or "cross-canadian" in root:
+ continue
+ if "do_build" not in name:
+ # 1.4.1+gitAUTOINC+302fca9f4c-r0.do_package_write_ipk.sigdata.f3a2a38697da743f0dbed8b56aafcf79
+ (_, task, _, shash) = name.rsplit(".", 3)
+ result[os.path.join(os.path.basename(root), task)] = shash
+
+ files1 = {}
+ files2 = {}
+ subdirs = sorted(glob.glob(self.topdir + "/tmp-sstatesamehash/stamps/*-nativesdk*-linux"))
+ if allarch:
+ subdirs.extend(sorted(glob.glob(self.topdir + "/tmp-sstatesamehash/stamps/all-*-linux")))
+
+ for subdir in subdirs:
+ nativesdkdir = os.path.basename(subdir)
+ get_files(self.topdir + "/tmp-sstatesamehash/stamps/" + nativesdkdir, files1)
+ get_files(self.topdir + "/tmp-sstatesamehash2/stamps/" + nativesdkdir, files2)
+
+ self.maxDiff = None
+ self.assertEqual(files1, files2)
+
+ def test_sstate_sametune_samesigs(self):
+ """
+ The sstate checksums of two identical machines (using the same tune) should be the
+ same, apart from changes within the machine specific stamps directory. We use the
+ qemux86copy machine to test this. Also include multilibs in the test.
+ """
+
+ self.write_config("""
+TMPDIR = \"${TOPDIR}/tmp-sstatesamehash\"
+TCLIBCAPPEND = \"\"
+MACHINE = \"qemux86\"
+require conf/multilib.conf
+MULTILIBS = "multilib:lib32"
+DEFAULTTUNE:virtclass-multilib-lib32 = "x86"
+BB_SIGNATURE_HANDLER = "OEBasicHash"
+""")
+ self.track_for_cleanup(self.topdir + "/tmp-sstatesamehash")
+ bitbake("world meta-toolchain -S none")
+ self.write_config("""
+TMPDIR = \"${TOPDIR}/tmp-sstatesamehash2\"
+TCLIBCAPPEND = \"\"
+MACHINE = \"qemux86copy\"
+require conf/multilib.conf
+MULTILIBS = "multilib:lib32"
+DEFAULTTUNE:virtclass-multilib-lib32 = "x86"
+BB_SIGNATURE_HANDLER = "OEBasicHash"
+""")
+ self.track_for_cleanup(self.topdir + "/tmp-sstatesamehash2")
+ bitbake("world meta-toolchain -S none")
+
+ def get_files(d):
+ f = []
+ for root, dirs, files in os.walk(d):
+ for name in files:
+ if "meta-environment" in root or "cross-canadian" in root or 'meta-ide-support' in root:
+ continue
+ if "qemux86copy-" in root or "qemux86-" in root:
+ continue
+ if "do_build" not in name and "do_populate_sdk" not in name:
+ f.append(os.path.join(root, name))
+ return f
+ files1 = get_files(self.topdir + "/tmp-sstatesamehash/stamps")
+ files2 = get_files(self.topdir + "/tmp-sstatesamehash2/stamps")
+ files2 = [x.replace("tmp-sstatesamehash2", "tmp-sstatesamehash") for x in files2]
+ self.maxDiff = None
+ self.assertCountEqual(files1, files2)
+
+
+ def test_sstate_multilib_or_not_native_samesigs(self):
+ """The sstate checksums of two native recipes (and their dependencies)
+ where the target is using multilib in one but not the other
+ should be the same. We use the qemux86copy machine to test
+ this.
+ """
+
+ self.write_config("""
+TMPDIR = \"${TOPDIR}/tmp-sstatesamehash\"
+TCLIBCAPPEND = \"\"
+MACHINE = \"qemux86\"
+require conf/multilib.conf
+MULTILIBS = "multilib:lib32"
+DEFAULTTUNE:virtclass-multilib-lib32 = "x86"
+BB_SIGNATURE_HANDLER = "OEBasicHash"
+""")
+ self.track_for_cleanup(self.topdir + "/tmp-sstatesamehash")
+ bitbake("binutils-native -S none")
+ self.write_config("""
+TMPDIR = \"${TOPDIR}/tmp-sstatesamehash2\"
+TCLIBCAPPEND = \"\"
+MACHINE = \"qemux86copy\"
+BB_SIGNATURE_HANDLER = "OEBasicHash"
+""")
+ self.track_for_cleanup(self.topdir + "/tmp-sstatesamehash2")
+ bitbake("binutils-native -S none")
+
+ def get_files(d):
+ f = []
+ for root, dirs, files in os.walk(d):
+ for name in files:
+ f.append(os.path.join(root, name))
+ return f
+ files1 = get_files(self.topdir + "/tmp-sstatesamehash/stamps")
+ files2 = get_files(self.topdir + "/tmp-sstatesamehash2/stamps")
+ files2 = [x.replace("tmp-sstatesamehash2", "tmp-sstatesamehash") for x in files2]
+ self.maxDiff = None
+ self.assertCountEqual(files1, files2)
+
+
+ def test_sstate_noop_samesigs(self):
+ """
+ The sstate checksums of two builds with these variables changed or
+ classes inherits should be the same.
+ """
+
+ self.write_config("""
+TMPDIR = "${TOPDIR}/tmp-sstatesamehash"
+TCLIBCAPPEND = ""
+BB_NUMBER_THREADS = "${@oe.utils.cpu_count()}"
+PARALLEL_MAKE = "-j 1"
+DL_DIR = "${TOPDIR}/download1"
+TIME = "111111"
+DATE = "20161111"
+INHERIT:remove = "buildstats-summary buildhistory uninative"
+http_proxy = ""
+BB_SIGNATURE_HANDLER = "OEBasicHash"
+""")
+ self.track_for_cleanup(self.topdir + "/tmp-sstatesamehash")
+ self.track_for_cleanup(self.topdir + "/download1")
+ bitbake("world meta-toolchain -S none")
+ self.write_config("""
+TMPDIR = "${TOPDIR}/tmp-sstatesamehash2"
+TCLIBCAPPEND = ""
+BB_NUMBER_THREADS = "${@oe.utils.cpu_count()+1}"
+PARALLEL_MAKE = "-j 2"
+DL_DIR = "${TOPDIR}/download2"
+TIME = "222222"
+DATE = "20161212"
+# Always remove uninative as we're changing proxies
+INHERIT:remove = "uninative"
+INHERIT += "buildstats-summary buildhistory"
+http_proxy = "http://example.com/"
+BB_SIGNATURE_HANDLER = "OEBasicHash"
+""")
+ self.track_for_cleanup(self.topdir + "/tmp-sstatesamehash2")
+ self.track_for_cleanup(self.topdir + "/download2")
+ bitbake("world meta-toolchain -S none")
+
+ def get_files(d):
+ f = {}
+ for root, dirs, files in os.walk(d):
+ for name in files:
+ name, shash = name.rsplit('.', 1)
+ # Extract just the machine and recipe name
+ base = os.sep.join(root.rsplit(os.sep, 2)[-2:] + [name])
+ f[base] = shash
+ return f
+
+ def compare_sigfiles(files, files1, files2, compare=False):
+ for k in files:
+ if k in files1 and k in files2:
+ print("%s differs:" % k)
+ if compare:
+ sigdatafile1 = self.topdir + "/tmp-sstatesamehash/stamps/" + k + "." + files1[k]
+ sigdatafile2 = self.topdir + "/tmp-sstatesamehash2/stamps/" + k + "." + files2[k]
+ output = bb.siggen.compare_sigfiles(sigdatafile1, sigdatafile2)
+ if output:
+ print('\n'.join(output))
+ elif k in files1 and k not in files2:
+ print("%s in files1" % k)
+ elif k not in files1 and k in files2:
+ print("%s in files2" % k)
+ else:
+ assert "shouldn't reach here"
+
+ files1 = get_files(self.topdir + "/tmp-sstatesamehash/stamps/")
+ files2 = get_files(self.topdir + "/tmp-sstatesamehash2/stamps/")
+ # Remove items that are identical in both sets
+ for k,v in files1.items() & files2.items():
+ del files1[k]
+ del files2[k]
+ if not files1 and not files2:
+ # No changes, so we're done
+ return
+
+ files = list(files1.keys() | files2.keys())
+ # this is an expensive computation, thus just compare the first 'max_sigfiles_to_compare' k files
+ max_sigfiles_to_compare = 20
+ first, rest = files[:max_sigfiles_to_compare], files[max_sigfiles_to_compare:]
+ compare_sigfiles(first, files1, files2, compare=True)
+ compare_sigfiles(rest, files1, files2, compare=False)
+
+ self.fail("sstate hashes not identical.")
+
+ def test_sstate_movelayer_samesigs(self):
+ """
+ The sstate checksums of two builds with the same oe-core layer in two
+ different locations should be the same.
+ """
+ core_layer = os.path.join(
+ self.tc.td["COREBASE"], 'meta')
+ copy_layer_1 = self.topdir + "/meta-copy1/meta"
+ copy_layer_2 = self.topdir + "/meta-copy2/meta"
+
+ oe.path.copytree(core_layer, copy_layer_1)
+ os.symlink(os.path.dirname(core_layer) + "/scripts", self.topdir + "/meta-copy1/scripts")
+ self.write_config("""
+TMPDIR = "${TOPDIR}/tmp-sstatesamehash"
+""")
+ bblayers_conf = 'BBLAYERS += "%s"\nBBLAYERS:remove = "%s"' % (copy_layer_1, core_layer)
+ self.write_bblayers_config(bblayers_conf)
+ self.track_for_cleanup(self.topdir + "/tmp-sstatesamehash")
+ bitbake("bash -S none")
+
+ oe.path.copytree(core_layer, copy_layer_2)
+ os.symlink(os.path.dirname(core_layer) + "/scripts", self.topdir + "/meta-copy2/scripts")
+ self.write_config("""
+TMPDIR = "${TOPDIR}/tmp-sstatesamehash2"
+""")
+ bblayers_conf = 'BBLAYERS += "%s"\nBBLAYERS:remove = "%s"' % (copy_layer_2, core_layer)
+ self.write_bblayers_config(bblayers_conf)
+ self.track_for_cleanup(self.topdir + "/tmp-sstatesamehash2")
+ bitbake("bash -S none")
+
+ def get_files(d):
+ f = []
+ for root, dirs, files in os.walk(d):
+ for name in files:
+ f.append(os.path.join(root, name))
+ return f
+ files1 = get_files(self.topdir + "/tmp-sstatesamehash/stamps")
+ files2 = get_files(self.topdir + "/tmp-sstatesamehash2/stamps")
+ files2 = [x.replace("tmp-sstatesamehash2", "tmp-sstatesamehash") for x in files2]
+ self.maxDiff = None
+ self.assertCountEqual(files1, files2)
+
diff --git a/meta/lib/oeqa/selftest/cases/sysroot.py b/meta/lib/oeqa/selftest/cases/sysroot.py
new file mode 100644
index 0000000000..ef854f6fee
--- /dev/null
+++ b/meta/lib/oeqa/selftest/cases/sysroot.py
@@ -0,0 +1,86 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
+import uuid
+
+from oeqa.selftest.case import OESelftestTestCase
+from oeqa.utils.commands import bitbake
+
+class SysrootTests(OESelftestTestCase):
+ def test_sysroot_cleanup(self):
+ """
+ Build sysroot test which depends on virtual/sysroot-test for one machine,
+ switch machine, switch provider of virtual/sysroot-test and check that the
+ sysroot is correctly cleaned up. The files in the two providers overlap
+ so can cause errors if the sysroot code doesn't function correctly.
+ Yes, sysroot-test should be machine specific really to avoid this, however
+ the sysroot cleanup should also work [YOCTO #13702].
+ """
+
+ uuid1 = uuid.uuid4()
+ uuid2 = uuid.uuid4()
+
+ self.write_config("""
+PREFERRED_PROVIDER_virtual/sysroot-test = "sysroot-test-arch1"
+MACHINE = "qemux86"
+TESTSTRING:pn-sysroot-test-arch1 = "%s"
+TESTSTRING:pn-sysroot-test-arch2 = "%s"
+""" % (uuid1, uuid2))
+ bitbake("sysroot-test")
+ self.write_config("""
+PREFERRED_PROVIDER_virtual/sysroot-test = "sysroot-test-arch2"
+MACHINE = "qemux86copy"
+TESTSTRING:pn-sysroot-test-arch1 = "%s"
+TESTSTRING:pn-sysroot-test-arch2 = "%s"
+""" % (uuid1, uuid2))
+ bitbake("sysroot-test")
+
+ def test_sysroot_max_shebang(self):
+ """
+ Summary: Check max shebang triggers. To confirm [YOCTO #11053] is closed.
+ Expected: Fail when a shebang bigger than the max shebang-size is reached.
+ Author: Paulo Neves <ptsneves@gmail.com>
+ """
+ expected = "maximum shebang size exceeded, the maximum size is 128. [shebang-size]"
+ res = bitbake("sysroot-shebang-test-native -c populate_sysroot", ignore_status=True)
+ self.assertTrue(expected in res.output, msg=res.output)
+ self.assertTrue(res.status != 0)
+
+ def test_sysroot_la(self):
+ """
+ Summary: Check that workdir paths are not contained in .la files.
+ Expected: Fail when a workdir path is found in the file content.
+ Author: Paulo Neves <ptsneves@gmail.com>
+ """
+ expected = "la-test.la failed sanity test (workdir) in path"
+
+ res = bitbake("sysroot-la-test -c populate_sysroot", ignore_status=True)
+ self.assertTrue(expected in res.output, msg=res.output)
+ self.assertTrue('[la]' in res.output, msg=res.output)
+ self.assertTrue(res.status != 0)
+
+ res = bitbake("sysroot-la-test-native -c populate_sysroot", ignore_status=True)
+ self.assertTrue(expected in res.output, msg=res.output)
+ self.assertTrue('[la]' in res.output, msg=res.output)
+ self.assertTrue(res.status != 0)
+
+ def test_sysroot_pkgconfig(self):
+ """
+ Summary: Check that tmpdir paths are not contained in .pc files.
+ Expected: Fail when a tmpdir path is found in the file content.
+ Author: Paulo Neves <ptsneves@gmail.com>
+ """
+ expected = "test.pc failed sanity test (tmpdir) in path"
+
+ res = bitbake("sysroot-pc-test -c populate_sysroot", ignore_status=True)
+ self.assertTrue('[pkgconfig]' in res.output, msg=res.output)
+ self.assertTrue(expected in res.output, msg=res.output)
+ self.assertTrue(res.status != 0)
+
+ res = bitbake("sysroot-pc-test-native -c populate_sysroot", ignore_status=True)
+ self.assertTrue(expected in res.output, msg=res.output)
+ self.assertTrue('[pkgconfig]' in res.output, msg=res.output)
+ self.assertTrue(res.status != 0)
diff --git a/meta/lib/oeqa/selftest/cases/tinfoil.py b/meta/lib/oeqa/selftest/cases/tinfoil.py
new file mode 100644
index 0000000000..dd13c20402
--- /dev/null
+++ b/meta/lib/oeqa/selftest/cases/tinfoil.py
@@ -0,0 +1,229 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
+import os
+import re
+import time
+import logging
+import bb.tinfoil
+
+from oeqa.selftest.case import OESelftestTestCase
+
+class TinfoilTests(OESelftestTestCase):
+ """ Basic tests for the tinfoil API """
+
+ def test_getvar(self):
+ with bb.tinfoil.Tinfoil() as tinfoil:
+ tinfoil.prepare(True)
+ machine = tinfoil.config_data.getVar('MACHINE')
+ if not machine:
+ self.fail('Unable to get MACHINE value - returned %s' % machine)
+
+ def test_expand(self):
+ with bb.tinfoil.Tinfoil() as tinfoil:
+ tinfoil.prepare(True)
+ expr = '${@os.getpid()}'
+ pid = tinfoil.config_data.expand(expr)
+ if not pid:
+ self.fail('Unable to expand "%s" - returned %s' % (expr, pid))
+
+ def test_getvar_bb_origenv(self):
+ with bb.tinfoil.Tinfoil() as tinfoil:
+ tinfoil.prepare(True)
+ origenv = tinfoil.config_data.getVar('BB_ORIGENV', False)
+ if not origenv:
+ self.fail('Unable to get BB_ORIGENV value - returned %s' % origenv)
+ self.assertEqual(origenv.getVar('HOME', False), os.environ['HOME'])
+
+ def test_parse_recipe(self):
+ with bb.tinfoil.Tinfoil() as tinfoil:
+ tinfoil.prepare(config_only=False, quiet=2)
+ testrecipe = 'mdadm'
+ best = tinfoil.find_best_provider(testrecipe)
+ if not best:
+ self.fail('Unable to find recipe providing %s' % testrecipe)
+ rd = tinfoil.parse_recipe_file(best[3])
+ self.assertEqual(testrecipe, rd.getVar('PN'))
+
+ def test_parse_recipe_copy_expand(self):
+ with bb.tinfoil.Tinfoil() as tinfoil:
+ tinfoil.prepare(config_only=False, quiet=2)
+ testrecipe = 'mdadm'
+ best = tinfoil.find_best_provider(testrecipe)
+ if not best:
+ self.fail('Unable to find recipe providing %s' % testrecipe)
+ rd = tinfoil.parse_recipe_file(best[3])
+ # Check we can get variable values
+ self.assertEqual(testrecipe, rd.getVar('PN'))
+ # Check that expanding a value that includes a variable reference works
+ self.assertEqual(testrecipe, rd.getVar('BPN'))
+ # Now check that changing the referenced variable's value in a copy gives that
+ # value when expanding
+ localdata = bb.data.createCopy(rd)
+ localdata.setVar('PN', 'hello')
+ self.assertEqual('hello', localdata.getVar('BPN'))
+
+ # The config_data API tp parse_recipe_file is used by:
+ # layerindex-web layerindex/update_layer.py
+ def test_parse_recipe_custom_data(self):
+ with bb.tinfoil.Tinfoil() as tinfoil:
+ tinfoil.prepare(config_only=False, quiet=2)
+ localdata = bb.data.createCopy(tinfoil.config_data)
+ localdata.setVar("TESTVAR", "testval")
+ testrecipe = 'mdadm'
+ best = tinfoil.find_best_provider(testrecipe)
+ if not best:
+ self.fail('Unable to find recipe providing %s' % testrecipe)
+ rd = tinfoil.parse_recipe_file(best[3], config_data=localdata)
+ self.assertEqual("testval", rd.getVar('TESTVAR'))
+
+ def test_list_recipes(self):
+ with bb.tinfoil.Tinfoil() as tinfoil:
+ tinfoil.prepare(config_only=False, quiet=2)
+ # Check pkg_pn
+ checkpns = ['tar', 'automake', 'coreutils', 'm4-native', 'nativesdk-gcc']
+ pkg_pn = tinfoil.cooker.recipecaches[''].pkg_pn
+ for pn in checkpns:
+ self.assertIn(pn, pkg_pn)
+ # Check pkg_fn
+ checkfns = {'nativesdk-gcc': '^virtual:nativesdk:.*', 'coreutils': '.*/coreutils_.*.bb'}
+ for fn, pn in tinfoil.cooker.recipecaches[''].pkg_fn.items():
+ if pn in checkpns:
+ if pn in checkfns:
+ self.assertTrue(re.match(checkfns[pn], fn), 'Entry for %s: %s did not match %s' % (pn, fn, checkfns[pn]))
+ checkpns.remove(pn)
+ if checkpns:
+ self.fail('Unable to find pkg_fn entries for: %s' % ', '.join(checkpns))
+
+ def test_wait_event(self):
+ with bb.tinfoil.Tinfoil() as tinfoil:
+ tinfoil.prepare(config_only=True)
+
+ tinfoil.set_event_mask(['bb.event.FilesMatchingFound', 'bb.command.CommandCompleted', 'bb.command.CommandFailed', 'bb.command.CommandExit'])
+
+ # Need to drain events otherwise events that were masked may still be in the queue
+ while tinfoil.wait_event():
+ pass
+
+ pattern = 'conf'
+ res = tinfoil.run_command('testCookerCommandEvent', pattern, handle_events=False)
+ self.assertTrue(res)
+
+ eventreceived = False
+ commandcomplete = False
+ start = time.time()
+ # Wait for maximum 60s in total so we'd detect spurious heartbeat events for example
+ while (not (eventreceived == True and commandcomplete == True)
+ and (time.time() - start < 60)):
+ # if we received both events (on let's say a good day), we are done
+ event = tinfoil.wait_event(1)
+ if event:
+ if isinstance(event, bb.command.CommandCompleted):
+ commandcomplete = True
+ elif isinstance(event, bb.event.FilesMatchingFound):
+ self.assertEqual(pattern, event._pattern)
+ self.assertIn('A', event._matches)
+ self.assertIn('B', event._matches)
+ eventreceived = True
+ elif isinstance(event, logging.LogRecord):
+ continue
+ else:
+ self.fail('Unexpected event: %s' % event)
+
+ self.assertTrue(commandcomplete, 'Timed out waiting for CommandCompleted event from bitbake server (Matching event received: %s)' % str(eventreceived))
+ self.assertTrue(eventreceived, 'Did not receive FilesMatchingFound event from bitbake server')
+
+ def test_setvariable_clean(self):
+ # First check that setVariable affects the datastore
+ with bb.tinfoil.Tinfoil() as tinfoil:
+ tinfoil.prepare(config_only=True)
+ tinfoil.run_command('setVariable', 'TESTVAR', 'specialvalue')
+ self.assertEqual(tinfoil.config_data.getVar('TESTVAR'), 'specialvalue', 'Value set using setVariable is not reflected in client-side getVar()')
+
+ # Now check that the setVariable's effects are no longer present
+ # (this may legitimately break in future if we stop reinitialising
+ # the datastore, in which case we'll have to reconsider use of
+ # setVariable entirely)
+ with bb.tinfoil.Tinfoil() as tinfoil:
+ tinfoil.prepare(config_only=True)
+ self.assertNotEqual(tinfoil.config_data.getVar('TESTVAR'), 'specialvalue', 'Value set using setVariable is still present!')
+
+ # Now check that setVar on the main datastore works (uses setVariable internally)
+ with bb.tinfoil.Tinfoil() as tinfoil:
+ tinfoil.prepare(config_only=True)
+ tinfoil.config_data.setVar('TESTVAR', 'specialvalue')
+ value = tinfoil.run_command('getVariable', 'TESTVAR')
+ self.assertEqual(value, 'specialvalue', 'Value set using config_data.setVar() is not reflected in config_data.getVar()')
+
+ def test_datastore_operations(self):
+ with bb.tinfoil.Tinfoil() as tinfoil:
+ tinfoil.prepare(config_only=True)
+ # Test setVarFlag() / getVarFlag()
+ tinfoil.config_data.setVarFlag('TESTVAR', 'flagname', 'flagval')
+ value = tinfoil.config_data.getVarFlag('TESTVAR', 'flagname')
+ self.assertEqual(value, 'flagval', 'Value set using config_data.setVarFlag() is not reflected in config_data.getVarFlag()')
+ # Test delVarFlag()
+ tinfoil.config_data.setVarFlag('TESTVAR', 'otherflag', 'othervalue')
+ tinfoil.config_data.delVarFlag('TESTVAR', 'flagname')
+ value = tinfoil.config_data.getVarFlag('TESTVAR', 'flagname')
+ self.assertEqual(value, None, 'Varflag deleted using config_data.delVarFlag() is not reflected in config_data.getVarFlag()')
+ value = tinfoil.config_data.getVarFlag('TESTVAR', 'otherflag')
+ self.assertEqual(value, 'othervalue', 'Varflag deleted using config_data.delVarFlag() caused unrelated flag to be removed')
+ # Test delVar()
+ tinfoil.config_data.setVar('TESTVAR', 'varvalue')
+ value = tinfoil.config_data.getVar('TESTVAR')
+ self.assertEqual(value, 'varvalue', 'Value set using config_data.setVar() is not reflected in config_data.getVar()')
+ tinfoil.config_data.delVar('TESTVAR')
+ value = tinfoil.config_data.getVar('TESTVAR')
+ self.assertEqual(value, None, 'Variable deleted using config_data.delVar() appears to still have a value')
+ # Test renameVar()
+ tinfoil.config_data.setVar('TESTVAROLD', 'origvalue')
+ tinfoil.config_data.renameVar('TESTVAROLD', 'TESTVARNEW')
+ value = tinfoil.config_data.getVar('TESTVAROLD')
+ self.assertEqual(value, None, 'Variable renamed using config_data.renameVar() still seems to exist')
+ value = tinfoil.config_data.getVar('TESTVARNEW')
+ self.assertEqual(value, 'origvalue', 'Variable renamed using config_data.renameVar() does not appear with new name')
+ # Test overrides
+ tinfoil.config_data.setVar('TESTVAR', 'original')
+ tinfoil.config_data.setVar('TESTVAR:overrideone', 'one')
+ tinfoil.config_data.setVar('TESTVAR:overridetwo', 'two')
+ tinfoil.config_data.appendVar('OVERRIDES', ':overrideone')
+ value = tinfoil.config_data.getVar('TESTVAR')
+ self.assertEqual(value, 'one', 'Variable overrides not functioning correctly')
+
+ def test_variable_history(self):
+ # Basic test to ensure that variable history works when tracking=True
+ with bb.tinfoil.Tinfoil(tracking=True) as tinfoil:
+ tinfoil.prepare(config_only=False, quiet=2)
+ # Note that _tracking for any datastore we get will be
+ # false here, that's currently expected - so we can't check
+ # for that
+ history = tinfoil.config_data.varhistory.variable('DL_DIR')
+ for entry in history:
+ if entry['file'].endswith('/bitbake.conf'):
+ if entry['op'] in ['set', 'set?']:
+ break
+ else:
+ self.fail('Did not find history entry setting DL_DIR in bitbake.conf. History: %s' % history)
+ # Check it works for recipes as well
+ testrecipe = 'zlib'
+ rd = tinfoil.parse_recipe(testrecipe)
+ history = rd.varhistory.variable('LICENSE')
+ bbfound = -1
+ recipefound = -1
+ for i, entry in enumerate(history):
+ if entry['file'].endswith('/bitbake.conf'):
+ if entry['detail'] == 'INVALID' and entry['op'] in ['set', 'set?']:
+ bbfound = i
+ elif entry['file'].endswith('.bb'):
+ if entry['op'] == 'set':
+ recipefound = i
+ if bbfound == -1:
+ self.fail('Did not find history entry setting LICENSE in bitbake.conf parsing %s recipe. History: %s' % (testrecipe, history))
+ if recipefound == -1:
+ self.fail('Did not find history entry setting LICENSE in %s recipe. History: %s' % (testrecipe, history))
+ if bbfound > recipefound:
+ self.fail('History entry setting LICENSE in %s recipe and in bitbake.conf in wrong order. History: %s' % (testrecipe, history))
diff --git a/meta/lib/oeqa/selftest/cases/wic.py b/meta/lib/oeqa/selftest/cases/wic.py
new file mode 100644
index 0000000000..ca1abb970a
--- /dev/null
+++ b/meta/lib/oeqa/selftest/cases/wic.py
@@ -0,0 +1,1497 @@
+#
+# Copyright (c) 2015, Intel Corporation.
+#
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# AUTHORS
+# Ed Bartosh <ed.bartosh@linux.intel.com>
+
+"""Test cases for wic."""
+
+import os
+import sys
+import unittest
+import hashlib
+
+from glob import glob
+from shutil import rmtree, copy
+from tempfile import NamedTemporaryFile
+
+from oeqa.selftest.case import OESelftestTestCase
+from oeqa.core.decorator import OETestTag
+from oeqa.core.decorator.data import skipIfNotArch
+from oeqa.utils.commands import runCmd, bitbake, get_bb_var, get_bb_vars, runqemu
+
+
+def extract_files(debugfs_output):
+ """
+ extract file names from the output of debugfs -R 'ls -p',
+ which looks like this:
+
+ /2/040755/0/0/.//\n
+ /2/040755/0/0/..//\n
+ /11/040700/0/0/lost+found^M//\n
+ /12/040755/1002/1002/run//\n
+ /13/040755/1002/1002/sys//\n
+ /14/040755/1002/1002/bin//\n
+ /80/040755/1002/1002/var//\n
+ /92/040755/1002/1002/tmp//\n
+ """
+ # NOTE the occasional ^M in file names
+ return [line.split('/')[5].strip() for line in \
+ debugfs_output.strip().split('/\n')]
+
+def files_own_by_root(debugfs_output):
+ for line in debugfs_output.strip().split('/\n'):
+ if line.split('/')[3:5] != ['0', '0']:
+ print(debugfs_output)
+ return False
+ return True
+
+class WicTestCase(OESelftestTestCase):
+ """Wic test class."""
+
+ image_is_ready = False
+ wicenv_cache = {}
+
+ def setUpLocal(self):
+ """This code is executed before each test method."""
+ self.resultdir = os.path.join(self.builddir, "wic-tmp")
+ super(WicTestCase, self).setUpLocal()
+
+ # Do this here instead of in setUpClass as the base setUp does some
+ # clean up which can result in the native tools built earlier in
+ # setUpClass being unavailable.
+ if not WicTestCase.image_is_ready:
+ if self.td['USE_NLS'] != 'yes':
+ self.skipTest('wic-tools needs USE_NLS=yes')
+
+ bitbake('wic-tools core-image-minimal core-image-minimal-mtdutils')
+ WicTestCase.image_is_ready = True
+ rmtree(self.resultdir, ignore_errors=True)
+
+ def tearDownLocal(self):
+ """Remove resultdir as it may contain images."""
+ rmtree(self.resultdir, ignore_errors=True)
+ super(WicTestCase, self).tearDownLocal()
+
+ def _get_image_env_path(self, image):
+ """Generate and obtain the path to <image>.env"""
+ if image not in WicTestCase.wicenv_cache:
+ bitbake('%s -c do_rootfs_wicenv' % image)
+ stdir = get_bb_var('STAGING_DIR', image)
+ machine = self.td["MACHINE"]
+ WicTestCase.wicenv_cache[image] = os.path.join(stdir, machine, 'imgdata')
+ return WicTestCase.wicenv_cache[image]
+
+class CLITests(OESelftestTestCase):
+ def test_version(self):
+ """Test wic --version"""
+ runCmd('wic --version')
+
+ def test_help(self):
+ """Test wic --help and wic -h"""
+ runCmd('wic --help')
+ runCmd('wic -h')
+
+ def test_createhelp(self):
+ """Test wic create --help"""
+ runCmd('wic create --help')
+
+ def test_listhelp(self):
+ """Test wic list --help"""
+ runCmd('wic list --help')
+
+ def test_help_create(self):
+ """Test wic help create"""
+ runCmd('wic help create')
+
+ def test_help_list(self):
+ """Test wic help list"""
+ runCmd('wic help list')
+
+ def test_help_overview(self):
+ """Test wic help overview"""
+ runCmd('wic help overview')
+
+ def test_help_plugins(self):
+ """Test wic help plugins"""
+ runCmd('wic help plugins')
+
+ def test_help_kickstart(self):
+ """Test wic help kickstart"""
+ runCmd('wic help kickstart')
+
+ def test_list_images(self):
+ """Test wic list images"""
+ runCmd('wic list images')
+
+ def test_list_source_plugins(self):
+ """Test wic list source-plugins"""
+ runCmd('wic list source-plugins')
+
+ def test_listed_images_help(self):
+ """Test wic listed images help"""
+ output = runCmd('wic list images').output
+ imagelist = [line.split()[0] for line in output.splitlines()]
+ for image in imagelist:
+ runCmd('wic list %s help' % image)
+
+ def test_unsupported_subcommand(self):
+ """Test unsupported subcommand"""
+ self.assertNotEqual(0, runCmd('wic unsupported', ignore_status=True).status)
+
+ def test_no_command(self):
+ """Test wic without command"""
+ self.assertEqual(1, runCmd('wic', ignore_status=True).status)
+
+class Wic(WicTestCase):
+ def test_build_image_name(self):
+ """Test wic create wictestdisk --image-name=core-image-minimal"""
+ cmd = "wic create wictestdisk --image-name=core-image-minimal -o %s" % self.resultdir
+ runCmd(cmd)
+ self.assertEqual(1, len(glob(os.path.join (self.resultdir, "wictestdisk-*.direct"))))
+
+ @skipIfNotArch(['i586', 'i686', 'x86_64'])
+ def test_gpt_image(self):
+ """Test creation of core-image-minimal with gpt table and UUID boot"""
+ cmd = "wic create directdisk-gpt --image-name core-image-minimal -o %s" % self.resultdir
+ runCmd(cmd)
+ self.assertEqual(1, len(glob(os.path.join(self.resultdir, "directdisk-*.direct"))))
+
+ @skipIfNotArch(['i586', 'i686', 'x86_64'])
+ def test_iso_image(self):
+ """Test creation of hybrid iso image with legacy and EFI boot"""
+ config = 'INITRAMFS_IMAGE = "core-image-minimal-initramfs"\n'\
+ 'MACHINE_FEATURES:append = " efi"\n'\
+ 'DEPENDS:pn-core-image-minimal += "syslinux"\n'
+ self.append_config(config)
+ bitbake('core-image-minimal core-image-minimal-initramfs')
+ self.remove_config(config)
+ cmd = "wic create mkhybridiso --image-name core-image-minimal -o %s" % self.resultdir
+ runCmd(cmd)
+ self.assertEqual(1, len(glob(os.path.join(self.resultdir, "HYBRID_ISO_IMG-*.direct"))))
+ self.assertEqual(1, len(glob(os.path.join (self.resultdir, "HYBRID_ISO_IMG-*.iso"))))
+
+ @skipIfNotArch(['i586', 'i686', 'x86_64'])
+ def test_qemux86_directdisk(self):
+ """Test creation of qemux-86-directdisk image"""
+ cmd = "wic create qemux86-directdisk -e core-image-minimal -o %s" % self.resultdir
+ runCmd(cmd)
+ self.assertEqual(1, len(glob(os.path.join(self.resultdir, "qemux86-directdisk-*direct"))))
+
+ @skipIfNotArch(['i586', 'i686', 'x86_64', 'aarch64'])
+ def test_mkefidisk(self):
+ """Test creation of mkefidisk image"""
+ cmd = "wic create mkefidisk -e core-image-minimal -o %s" % self.resultdir
+ runCmd(cmd)
+ self.assertEqual(1, len(glob(os.path.join(self.resultdir, "mkefidisk-*direct"))))
+
+ @skipIfNotArch(['i586', 'i686', 'x86_64'])
+ def test_bootloader_config(self):
+ """Test creation of directdisk-bootloader-config image"""
+ config = 'DEPENDS:pn-core-image-minimal += "syslinux"\n'
+ self.append_config(config)
+ bitbake('core-image-minimal')
+ self.remove_config(config)
+ cmd = "wic create directdisk-bootloader-config -e core-image-minimal -o %s" % self.resultdir
+ runCmd(cmd)
+ self.assertEqual(1, len(glob(os.path.join(self.resultdir, "directdisk-bootloader-config-*direct"))))
+
+ @skipIfNotArch(['i586', 'i686', 'x86_64', 'aarch64'])
+ def test_systemd_bootdisk(self):
+ """Test creation of systemd-bootdisk image"""
+ config = 'MACHINE_FEATURES:append = " efi"\n'
+ self.append_config(config)
+ bitbake('core-image-minimal')
+ self.remove_config(config)
+ cmd = "wic create systemd-bootdisk -e core-image-minimal -o %s" % self.resultdir
+ runCmd(cmd)
+ self.assertEqual(1, len(glob(os.path.join(self.resultdir, "systemd-bootdisk-*direct"))))
+
+ def test_efi_bootpart(self):
+ """Test creation of efi-bootpart image"""
+ cmd = "wic create mkefidisk -e core-image-minimal -o %s" % self.resultdir
+ kimgtype = get_bb_var('KERNEL_IMAGETYPE', 'core-image-minimal')
+ self.append_config('IMAGE_EFI_BOOT_FILES = "%s;kernel"\n' % kimgtype)
+ runCmd(cmd)
+ sysroot = get_bb_var('RECIPE_SYSROOT_NATIVE', 'wic-tools')
+ images = glob(os.path.join(self.resultdir, "mkefidisk-*.direct"))
+ result = runCmd("wic ls %s:1/ -n %s" % (images[0], sysroot))
+ self.assertIn("kernel",result.output)
+
+ def test_sdimage_bootpart(self):
+ """Test creation of sdimage-bootpart image"""
+ cmd = "wic create sdimage-bootpart -e core-image-minimal -o %s" % self.resultdir
+ kimgtype = get_bb_var('KERNEL_IMAGETYPE', 'core-image-minimal')
+ self.write_config('IMAGE_BOOT_FILES = "%s"\n' % kimgtype)
+ runCmd(cmd)
+ self.assertEqual(1, len(glob(os.path.join(self.resultdir, "sdimage-bootpart-*direct"))))
+
+ # TODO this doesn't have to be x86-specific
+ @skipIfNotArch(['i586', 'i686', 'x86_64'])
+ def test_default_output_dir(self):
+ """Test default output location"""
+ for fname in glob("directdisk-*.direct"):
+ os.remove(fname)
+ config = 'DEPENDS:pn-core-image-minimal += "syslinux"\n'
+ self.append_config(config)
+ bitbake('core-image-minimal')
+ self.remove_config(config)
+ cmd = "wic create directdisk -e core-image-minimal"
+ runCmd(cmd)
+ self.assertEqual(1, len(glob("directdisk-*.direct")))
+
+ @skipIfNotArch(['i586', 'i686', 'x86_64'])
+ def test_build_artifacts(self):
+ """Test wic create directdisk providing all artifacts."""
+ bb_vars = get_bb_vars(['STAGING_DATADIR', 'RECIPE_SYSROOT_NATIVE'],
+ 'wic-tools')
+ bb_vars.update(get_bb_vars(['DEPLOY_DIR_IMAGE', 'IMAGE_ROOTFS'],
+ 'core-image-minimal'))
+ bbvars = {key.lower(): value for key, value in bb_vars.items()}
+ bbvars['resultdir'] = self.resultdir
+ runCmd("wic create directdisk "
+ "-b %(staging_datadir)s "
+ "-k %(deploy_dir_image)s "
+ "-n %(recipe_sysroot_native)s "
+ "-r %(image_rootfs)s "
+ "-o %(resultdir)s" % bbvars)
+ self.assertEqual(1, len(glob(os.path.join(self.resultdir, "directdisk-*.direct"))))
+
+ def test_compress_gzip(self):
+ """Test compressing an image with gzip"""
+ runCmd("wic create wictestdisk "
+ "--image-name core-image-minimal "
+ "-c gzip -o %s" % self.resultdir)
+ self.assertEqual(1, len(glob(os.path.join(self.resultdir, "wictestdisk-*.direct.gz"))))
+
+ def test_compress_bzip2(self):
+ """Test compressing an image with bzip2"""
+ runCmd("wic create wictestdisk "
+ "--image-name=core-image-minimal "
+ "-c bzip2 -o %s" % self.resultdir)
+ self.assertEqual(1, len(glob(os.path.join(self.resultdir, "wictestdisk-*.direct.bz2"))))
+
+ def test_compress_xz(self):
+ """Test compressing an image with xz"""
+ runCmd("wic create wictestdisk "
+ "--image-name=core-image-minimal "
+ "--compress-with=xz -o %s" % self.resultdir)
+ self.assertEqual(1, len(glob(os.path.join(self.resultdir, "wictestdisk-*.direct.xz"))))
+
+ def test_wrong_compressor(self):
+ """Test how wic breaks if wrong compressor is provided"""
+ self.assertEqual(2, runCmd("wic create wictestdisk "
+ "--image-name=core-image-minimal "
+ "-c wrong -o %s" % self.resultdir,
+ ignore_status=True).status)
+
+ def test_debug_short(self):
+ """Test -D option"""
+ runCmd("wic create wictestdisk "
+ "--image-name=core-image-minimal "
+ "-D -o %s" % self.resultdir)
+ self.assertEqual(1, len(glob(os.path.join(self.resultdir, "wictestdisk-*.direct"))))
+ self.assertEqual(1, len(glob(os.path.join(self.resultdir, "tmp.wic*"))))
+
+ def test_debug_long(self):
+ """Test --debug option"""
+ runCmd("wic create wictestdisk "
+ "--image-name=core-image-minimal "
+ "--debug -o %s" % self.resultdir)
+ self.assertEqual(1, len(glob(os.path.join(self.resultdir, "wictestdisk-*.direct"))))
+ self.assertEqual(1, len(glob(os.path.join(self.resultdir, "tmp.wic*"))))
+
+ def test_skip_build_check_short(self):
+ """Test -s option"""
+ runCmd("wic create wictestdisk "
+ "--image-name=core-image-minimal "
+ "-s -o %s" % self.resultdir)
+ self.assertEqual(1, len(glob(os.path.join(self.resultdir, "wictestdisk-*.direct"))))
+
+ def test_skip_build_check_long(self):
+ """Test --skip-build-check option"""
+ runCmd("wic create wictestdisk "
+ "--image-name=core-image-minimal "
+ "--skip-build-check "
+ "--outdir %s" % self.resultdir)
+ self.assertEqual(1, len(glob(os.path.join(self.resultdir, "wictestdisk-*.direct"))))
+
+ def test_build_rootfs_short(self):
+ """Test -f option"""
+ runCmd("wic create wictestdisk "
+ "--image-name=core-image-minimal "
+ "-f -o %s" % self.resultdir)
+ self.assertEqual(1, len(glob(os.path.join(self.resultdir, "wictestdisk-*.direct"))))
+
+ def test_build_rootfs_long(self):
+ """Test --build-rootfs option"""
+ runCmd("wic create wictestdisk "
+ "--image-name=core-image-minimal "
+ "--build-rootfs "
+ "--outdir %s" % self.resultdir)
+ self.assertEqual(1, len(glob(os.path.join(self.resultdir, "wictestdisk-*.direct"))))
+
+ # TODO this doesn't have to be x86-specific
+ @skipIfNotArch(['i586', 'i686', 'x86_64'])
+ def test_rootfs_indirect_recipes(self):
+ """Test usage of rootfs plugin with rootfs recipes"""
+ runCmd("wic create directdisk-multi-rootfs "
+ "--image-name=core-image-minimal "
+ "--rootfs rootfs1=core-image-minimal "
+ "--rootfs rootfs2=core-image-minimal "
+ "--outdir %s" % self.resultdir)
+ self.assertEqual(1, len(glob(os.path.join(self.resultdir, "directdisk-multi-rootfs*.direct"))))
+
+ # TODO this doesn't have to be x86-specific
+ @skipIfNotArch(['i586', 'i686', 'x86_64'])
+ def test_rootfs_artifacts(self):
+ """Test usage of rootfs plugin with rootfs paths"""
+ bb_vars = get_bb_vars(['STAGING_DATADIR', 'RECIPE_SYSROOT_NATIVE'],
+ 'wic-tools')
+ bb_vars.update(get_bb_vars(['DEPLOY_DIR_IMAGE', 'IMAGE_ROOTFS'],
+ 'core-image-minimal'))
+ bbvars = {key.lower(): value for key, value in bb_vars.items()}
+ bbvars['wks'] = "directdisk-multi-rootfs"
+ bbvars['resultdir'] = self.resultdir
+ runCmd("wic create %(wks)s "
+ "--bootimg-dir=%(staging_datadir)s "
+ "--kernel-dir=%(deploy_dir_image)s "
+ "--native-sysroot=%(recipe_sysroot_native)s "
+ "--rootfs-dir rootfs1=%(image_rootfs)s "
+ "--rootfs-dir rootfs2=%(image_rootfs)s "
+ "--outdir %(resultdir)s" % bbvars)
+ self.assertEqual(1, len(glob(os.path.join(self.resultdir, "%(wks)s-*.direct" % bbvars))))
+
+ def test_exclude_path(self):
+ """Test --exclude-path wks option."""
+
+ oldpath = os.environ['PATH']
+ os.environ['PATH'] = get_bb_var("PATH", "wic-tools")
+
+ try:
+ wks_file = 'temp.wks'
+ with open(wks_file, 'w') as wks:
+ rootfs_dir = get_bb_var('IMAGE_ROOTFS', 'core-image-minimal')
+ wks.write("""
+part / --source rootfs --ondisk mmcblk0 --fstype=ext4 --exclude-path usr
+part /usr --source rootfs --ondisk mmcblk0 --fstype=ext4 --rootfs-dir %s/usr
+part /etc --source rootfs --ondisk mmcblk0 --fstype=ext4 --exclude-path bin/ --rootfs-dir %s/usr"""
+ % (rootfs_dir, rootfs_dir))
+ runCmd("wic create %s -e core-image-minimal -o %s" \
+ % (wks_file, self.resultdir))
+
+ os.remove(wks_file)
+ wicout = glob(os.path.join(self.resultdir, "%s-*direct" % 'temp'))
+ self.assertEqual(1, len(wicout))
+
+ wicimg = wicout[0]
+
+ # verify partition size with wic
+ res = runCmd("parted -m %s unit b p 2>/dev/null" % wicimg)
+
+ # parse parted output which looks like this:
+ # BYT;\n
+ # /var/tmp/wic/build/tmpfwvjjkf_-201611101222-hda.direct:200MiB:file:512:512:msdos::;\n
+ # 1:0.00MiB:200MiB:200MiB:ext4::;\n
+ partlns = res.output.splitlines()[2:]
+
+ self.assertEqual(3, len(partlns))
+
+ for part in [1, 2, 3]:
+ part_file = os.path.join(self.resultdir, "selftest_img.part%d" % part)
+ partln = partlns[part-1].split(":")
+ self.assertEqual(7, len(partln))
+ start = int(partln[1].rstrip("B")) / 512
+ length = int(partln[3].rstrip("B")) / 512
+ runCmd("dd if=%s of=%s skip=%d count=%d" %
+ (wicimg, part_file, start, length))
+
+ # Test partition 1, should contain the normal root directories, except
+ # /usr.
+ res = runCmd("debugfs -R 'ls -p' %s 2>/dev/null" % \
+ os.path.join(self.resultdir, "selftest_img.part1"))
+ files = extract_files(res.output)
+ self.assertIn("etc", files)
+ self.assertNotIn("usr", files)
+
+ # Partition 2, should contain common directories for /usr, not root
+ # directories.
+ res = runCmd("debugfs -R 'ls -p' %s 2>/dev/null" % \
+ os.path.join(self.resultdir, "selftest_img.part2"))
+ files = extract_files(res.output)
+ self.assertNotIn("etc", files)
+ self.assertNotIn("usr", files)
+ self.assertIn("share", files)
+
+ # Partition 3, should contain the same as partition 2, including the bin
+ # directory, but not the files inside it.
+ res = runCmd("debugfs -R 'ls -p' %s 2>/dev/null" % \
+ os.path.join(self.resultdir, "selftest_img.part3"))
+ files = extract_files(res.output)
+ self.assertNotIn("etc", files)
+ self.assertNotIn("usr", files)
+ self.assertIn("share", files)
+ self.assertIn("bin", files)
+ res = runCmd("debugfs -R 'ls -p bin' %s 2>/dev/null" % \
+ os.path.join(self.resultdir, "selftest_img.part3"))
+ files = extract_files(res.output)
+ self.assertIn(".", files)
+ self.assertIn("..", files)
+ self.assertEqual(2, len(files))
+
+ for part in [1, 2, 3]:
+ part_file = os.path.join(self.resultdir, "selftest_img.part%d" % part)
+ os.remove(part_file)
+
+ finally:
+ os.environ['PATH'] = oldpath
+
+ def test_include_path(self):
+ """Test --include-path wks option."""
+
+ oldpath = os.environ['PATH']
+ os.environ['PATH'] = get_bb_var("PATH", "wic-tools")
+
+ try:
+ include_path = os.path.join(self.resultdir, 'test-include')
+ os.makedirs(include_path)
+ with open(os.path.join(include_path, 'test-file'), 'w') as t:
+ t.write("test\n")
+ wks_file = os.path.join(include_path, 'temp.wks')
+ with open(wks_file, 'w') as wks:
+ rootfs_dir = get_bb_var('IMAGE_ROOTFS', 'core-image-minimal')
+ wks.write("""
+part /part1 --source rootfs --ondisk mmcblk0 --fstype=ext4
+part /part2 --source rootfs --ondisk mmcblk0 --fstype=ext4 --include-path %s"""
+ % (include_path))
+ runCmd("wic create %s -e core-image-minimal -o %s" \
+ % (wks_file, self.resultdir))
+
+ part1 = glob(os.path.join(self.resultdir, 'temp-*.direct.p1'))[0]
+ part2 = glob(os.path.join(self.resultdir, 'temp-*.direct.p2'))[0]
+
+ # Test partition 1, should not contain 'test-file'
+ res = runCmd("debugfs -R 'ls -p' %s 2>/dev/null" % (part1))
+ files = extract_files(res.output)
+ self.assertNotIn('test-file', files)
+ self.assertEqual(True, files_own_by_root(res.output))
+
+ # Test partition 2, should contain 'test-file'
+ res = runCmd("debugfs -R 'ls -p' %s 2>/dev/null" % (part2))
+ files = extract_files(res.output)
+ self.assertIn('test-file', files)
+ self.assertEqual(True, files_own_by_root(res.output))
+
+ finally:
+ os.environ['PATH'] = oldpath
+
+ def test_include_path_embeded(self):
+ """Test --include-path wks option."""
+
+ oldpath = os.environ['PATH']
+ os.environ['PATH'] = get_bb_var("PATH", "wic-tools")
+
+ try:
+ include_path = os.path.join(self.resultdir, 'test-include')
+ os.makedirs(include_path)
+ with open(os.path.join(include_path, 'test-file'), 'w') as t:
+ t.write("test\n")
+ wks_file = os.path.join(include_path, 'temp.wks')
+ with open(wks_file, 'w') as wks:
+ wks.write("""
+part / --source rootfs --fstype=ext4 --include-path %s --include-path core-image-minimal-mtdutils export/"""
+ % (include_path))
+ runCmd("wic create %s -e core-image-minimal -o %s" \
+ % (wks_file, self.resultdir))
+
+ part1 = glob(os.path.join(self.resultdir, 'temp-*.direct.p1'))[0]
+
+ res = runCmd("debugfs -R 'ls -p' %s 2>/dev/null" % (part1))
+ files = extract_files(res.output)
+ self.assertIn('test-file', files)
+ self.assertEqual(True, files_own_by_root(res.output))
+
+ res = runCmd("debugfs -R 'ls -p /export/etc/' %s 2>/dev/null" % (part1))
+ files = extract_files(res.output)
+ self.assertIn('passwd', files)
+ self.assertEqual(True, files_own_by_root(res.output))
+
+ finally:
+ os.environ['PATH'] = oldpath
+
+ def test_include_path_errors(self):
+ """Test --include-path wks option error handling."""
+ wks_file = 'temp.wks'
+
+ # Absolute argument.
+ with open(wks_file, 'w') as wks:
+ wks.write("part / --source rootfs --fstype=ext4 --include-path core-image-minimal-mtdutils /export")
+ self.assertNotEqual(0, runCmd("wic create %s -e core-image-minimal -o %s" \
+ % (wks_file, self.resultdir), ignore_status=True).status)
+ os.remove(wks_file)
+
+ # Argument pointing to parent directory.
+ with open(wks_file, 'w') as wks:
+ wks.write("part / --source rootfs --fstype=ext4 --include-path core-image-minimal-mtdutils ././..")
+ self.assertNotEqual(0, runCmd("wic create %s -e core-image-minimal -o %s" \
+ % (wks_file, self.resultdir), ignore_status=True).status)
+ os.remove(wks_file)
+
+ # 3 Argument pointing to parent directory.
+ with open(wks_file, 'w') as wks:
+ wks.write("part / --source rootfs --fstype=ext4 --include-path core-image-minimal-mtdutils export/ dummy")
+ self.assertNotEqual(0, runCmd("wic create %s -e core-image-minimal -o %s" \
+ % (wks_file, self.resultdir), ignore_status=True).status)
+ os.remove(wks_file)
+
+ def test_exclude_path_errors(self):
+ """Test --exclude-path wks option error handling."""
+ wks_file = 'temp.wks'
+
+ # Absolute argument.
+ with open(wks_file, 'w') as wks:
+ wks.write("part / --source rootfs --ondisk mmcblk0 --fstype=ext4 --exclude-path /usr")
+ self.assertNotEqual(0, runCmd("wic create %s -e core-image-minimal -o %s" \
+ % (wks_file, self.resultdir), ignore_status=True).status)
+ os.remove(wks_file)
+
+ # Argument pointing to parent directory.
+ with open(wks_file, 'w') as wks:
+ wks.write("part / --source rootfs --ondisk mmcblk0 --fstype=ext4 --exclude-path ././..")
+ self.assertNotEqual(0, runCmd("wic create %s -e core-image-minimal -o %s" \
+ % (wks_file, self.resultdir), ignore_status=True).status)
+ os.remove(wks_file)
+
+ def test_permissions(self):
+ """Test permissions are respected"""
+
+ # prepare wicenv and rootfs
+ bitbake('core-image-minimal core-image-minimal-mtdutils -c do_rootfs_wicenv')
+
+ oldpath = os.environ['PATH']
+ os.environ['PATH'] = get_bb_var("PATH", "wic-tools")
+
+ t_normal = """
+part / --source rootfs --fstype=ext4
+"""
+ t_exclude = """
+part / --source rootfs --fstype=ext4 --exclude-path=home
+"""
+ t_multi = """
+part / --source rootfs --ondisk sda --fstype=ext4
+part /export --source rootfs --rootfs=core-image-minimal-mtdutils --fstype=ext4
+"""
+ t_change = """
+part / --source rootfs --ondisk sda --fstype=ext4 --exclude-path=etc/   
+part /etc --source rootfs --fstype=ext4 --change-directory=etc
+"""
+ tests = [t_normal, t_exclude, t_multi, t_change]
+
+ try:
+ for test in tests:
+ include_path = os.path.join(self.resultdir, 'test-include')
+ os.makedirs(include_path)
+ wks_file = os.path.join(include_path, 'temp.wks')
+ with open(wks_file, 'w') as wks:
+ wks.write(test)
+ runCmd("wic create %s -e core-image-minimal -o %s" \
+ % (wks_file, self.resultdir))
+
+ for part in glob(os.path.join(self.resultdir, 'temp-*.direct.p*')):
+ res = runCmd("debugfs -R 'ls -p' %s 2>/dev/null" % (part))
+ self.assertEqual(True, files_own_by_root(res.output))
+
+ config = 'IMAGE_FSTYPES += "wic"\nWKS_FILE = "%s"\n' % wks_file
+ self.append_config(config)
+ bitbake('core-image-minimal')
+ tmpdir = os.path.join(get_bb_var('WORKDIR', 'core-image-minimal'),'build-wic')
+
+ # check each partition for permission
+ for part in glob(os.path.join(tmpdir, 'temp-*.direct.p*')):
+ res = runCmd("debugfs -R 'ls -p' %s 2>/dev/null" % (part))
+ self.assertTrue(files_own_by_root(res.output)
+ ,msg='Files permission incorrect using wks set "%s"' % test)
+
+ # clean config and result directory for next cases
+ self.remove_config(config)
+ rmtree(self.resultdir, ignore_errors=True)
+
+ finally:
+ os.environ['PATH'] = oldpath
+
+ def test_change_directory(self):
+ """Test --change-directory wks option."""
+
+ oldpath = os.environ['PATH']
+ os.environ['PATH'] = get_bb_var("PATH", "wic-tools")
+
+ try:
+ include_path = os.path.join(self.resultdir, 'test-include')
+ os.makedirs(include_path)
+ wks_file = os.path.join(include_path, 'temp.wks')
+ with open(wks_file, 'w') as wks:
+ wks.write("part /etc --source rootfs --fstype=ext4 --change-directory=etc")
+ runCmd("wic create %s -e core-image-minimal -o %s" \
+ % (wks_file, self.resultdir))
+
+ part1 = glob(os.path.join(self.resultdir, 'temp-*.direct.p1'))[0]
+
+ res = runCmd("debugfs -R 'ls -p' %s 2>/dev/null" % (part1))
+ files = extract_files(res.output)
+ self.assertIn('passwd', files)
+
+ finally:
+ os.environ['PATH'] = oldpath
+
+ def test_change_directory_errors(self):
+ """Test --change-directory wks option error handling."""
+ wks_file = 'temp.wks'
+
+ # Absolute argument.
+ with open(wks_file, 'w') as wks:
+ wks.write("part / --source rootfs --fstype=ext4 --change-directory /usr")
+ self.assertNotEqual(0, runCmd("wic create %s -e core-image-minimal -o %s" \
+ % (wks_file, self.resultdir), ignore_status=True).status)
+ os.remove(wks_file)
+
+ # Argument pointing to parent directory.
+ with open(wks_file, 'w') as wks:
+ wks.write("part / --source rootfs --fstype=ext4 --change-directory ././..")
+ self.assertNotEqual(0, runCmd("wic create %s -e core-image-minimal -o %s" \
+ % (wks_file, self.resultdir), ignore_status=True).status)
+ os.remove(wks_file)
+
+ def test_no_fstab_update(self):
+ """Test --no-fstab-update wks option."""
+
+ oldpath = os.environ['PATH']
+ os.environ['PATH'] = get_bb_var("PATH", "wic-tools")
+
+ # Get stock fstab from base-files recipe
+ bitbake('base-files -c do_install')
+ bf_fstab = os.path.join(get_bb_var('D', 'base-files'), 'etc', 'fstab')
+ self.assertEqual(True, os.path.exists(bf_fstab))
+ bf_fstab_md5sum = runCmd('md5sum %s 2>/dev/null' % bf_fstab).output.split(" ")[0]
+
+ try:
+ no_fstab_update_path = os.path.join(self.resultdir, 'test-no-fstab-update')
+ os.makedirs(no_fstab_update_path)
+ wks_file = os.path.join(no_fstab_update_path, 'temp.wks')
+ with open(wks_file, 'w') as wks:
+ wks.writelines(['part / --source rootfs --fstype=ext4 --label rootfs\n',
+ 'part /mnt/p2 --source rootfs --rootfs-dir=core-image-minimal ',
+ '--fstype=ext4 --label p2 --no-fstab-update\n'])
+ runCmd("wic create %s -e core-image-minimal -o %s" \
+ % (wks_file, self.resultdir))
+
+ part_fstab_md5sum = []
+ for i in range(1, 3):
+ part = glob(os.path.join(self.resultdir, 'temp-*.direct.p') + str(i))[0]
+ part_fstab = runCmd("debugfs -R 'cat etc/fstab' %s 2>/dev/null" % (part))
+ part_fstab_md5sum.append(hashlib.md5((part_fstab.output + "\n\n").encode('utf-8')).hexdigest())
+
+ # '/etc/fstab' in partition 2 should contain the same stock fstab file
+ # as the one installed by the base-file recipe.
+ self.assertEqual(bf_fstab_md5sum, part_fstab_md5sum[1])
+
+ # '/etc/fstab' in partition 1 should contain an updated fstab file.
+ self.assertNotEqual(bf_fstab_md5sum, part_fstab_md5sum[0])
+
+ finally:
+ os.environ['PATH'] = oldpath
+
+ def test_no_fstab_update_errors(self):
+ """Test --no-fstab-update wks option error handling."""
+ wks_file = 'temp.wks'
+
+ # Absolute argument.
+ with open(wks_file, 'w') as wks:
+ wks.write("part / --source rootfs --fstype=ext4 --no-fstab-update /etc")
+ self.assertNotEqual(0, runCmd("wic create %s -e core-image-minimal -o %s" \
+ % (wks_file, self.resultdir), ignore_status=True).status)
+ os.remove(wks_file)
+
+ # Argument pointing to parent directory.
+ with open(wks_file, 'w') as wks:
+ wks.write("part / --source rootfs --fstype=ext4 --no-fstab-update ././..")
+ self.assertNotEqual(0, runCmd("wic create %s -e core-image-minimal -o %s" \
+ % (wks_file, self.resultdir), ignore_status=True).status)
+ os.remove(wks_file)
+
+ def test_extra_space(self):
+ """Test --extra-space wks option."""
+ extraspace = 1024**3
+ runCmd("wic create wictestdisk "
+ "--image-name core-image-minimal "
+ "--extra-space %i -o %s" % (extraspace ,self.resultdir))
+ wicout = glob(os.path.join(self.resultdir, "wictestdisk-*.direct"))
+ self.assertEqual(1, len(wicout))
+ size = os.path.getsize(wicout[0])
+ self.assertTrue(size > extraspace)
+
+class Wic2(WicTestCase):
+
+ def test_bmap_short(self):
+ """Test generation of .bmap file -m option"""
+ cmd = "wic create wictestdisk -e core-image-minimal -m -o %s" % self.resultdir
+ runCmd(cmd)
+ self.assertEqual(1, len(glob(os.path.join(self.resultdir, "wictestdisk-*direct"))))
+ self.assertEqual(1, len(glob(os.path.join(self.resultdir, "wictestdisk-*direct.bmap"))))
+
+ def test_bmap_long(self):
+ """Test generation of .bmap file --bmap option"""
+ cmd = "wic create wictestdisk -e core-image-minimal --bmap -o %s" % self.resultdir
+ runCmd(cmd)
+ self.assertEqual(1, len(glob(os.path.join(self.resultdir, "wictestdisk-*direct"))))
+ self.assertEqual(1, len(glob(os.path.join(self.resultdir, "wictestdisk-*direct.bmap"))))
+
+ def test_image_env(self):
+ """Test generation of <image>.env files."""
+ image = 'core-image-minimal'
+ imgdatadir = self._get_image_env_path(image)
+
+ bb_vars = get_bb_vars(['IMAGE_BASENAME', 'WICVARS'], image)
+ basename = bb_vars['IMAGE_BASENAME']
+ self.assertEqual(basename, image)
+ path = os.path.join(imgdatadir, basename) + '.env'
+ self.assertTrue(os.path.isfile(path))
+
+ wicvars = set(bb_vars['WICVARS'].split())
+ # filter out optional variables
+ wicvars = wicvars.difference(('DEPLOY_DIR_IMAGE', 'IMAGE_BOOT_FILES',
+ 'INITRD', 'INITRD_LIVE', 'ISODIR','INITRAMFS_IMAGE',
+ 'INITRAMFS_IMAGE_BUNDLE', 'INITRAMFS_LINK_NAME',
+ 'APPEND', 'IMAGE_EFI_BOOT_FILES'))
+ with open(path) as envfile:
+ content = dict(line.split("=", 1) for line in envfile)
+ # test if variables used by wic present in the .env file
+ for var in wicvars:
+ self.assertTrue(var in content, "%s is not in .env file" % var)
+ self.assertTrue(content[var])
+
+ def test_image_vars_dir_short(self):
+ """Test image vars directory selection -v option"""
+ image = 'core-image-minimal'
+ imgenvdir = self._get_image_env_path(image)
+ native_sysroot = get_bb_var("RECIPE_SYSROOT_NATIVE", "wic-tools")
+
+ runCmd("wic create wictestdisk "
+ "--image-name=%s -v %s -n %s -o %s"
+ % (image, imgenvdir, native_sysroot,
+ self.resultdir))
+ self.assertEqual(1, len(glob(os.path.join(self.resultdir, "wictestdisk-*direct"))))
+
+ def test_image_vars_dir_long(self):
+ """Test image vars directory selection --vars option"""
+ image = 'core-image-minimal'
+ imgenvdir = self._get_image_env_path(image)
+ native_sysroot = get_bb_var("RECIPE_SYSROOT_NATIVE", "wic-tools")
+
+ runCmd("wic create wictestdisk "
+ "--image-name=%s "
+ "--vars %s "
+ "--native-sysroot %s "
+ "--outdir %s"
+ % (image, imgenvdir, native_sysroot,
+ self.resultdir))
+ self.assertEqual(1, len(glob(os.path.join(self.resultdir, "wictestdisk-*direct"))))
+
+ # TODO this test could also work on aarch64
+ @skipIfNotArch(['i586', 'i686', 'x86_64'])
+ def test_wic_image_type(self):
+ """Test building wic images by bitbake"""
+ config = 'IMAGE_FSTYPES += "wic"\nWKS_FILE = "wic-image-minimal"\n'\
+ 'MACHINE_FEATURES:append = " efi"\n'
+ self.append_config(config)
+ bitbake('wic-image-minimal')
+ self.remove_config(config)
+
+ deploy_dir = get_bb_var('DEPLOY_DIR_IMAGE')
+ machine = self.td['MACHINE']
+ prefix = os.path.join(deploy_dir, 'wic-image-minimal-%s.' % machine)
+ # check if we have result image and manifests symlinks
+ # pointing to existing files
+ for suffix in ('wic', 'manifest'):
+ path = prefix + suffix
+ self.assertTrue(os.path.islink(path))
+ self.assertTrue(os.path.isfile(os.path.realpath(path)))
+
+ # TODO this should work on aarch64
+ @skipIfNotArch(['i586', 'i686', 'x86_64'])
+ @OETestTag("runqemu")
+ def test_qemu(self):
+ """Test wic-image-minimal under qemu"""
+ config = 'IMAGE_FSTYPES += "wic"\nWKS_FILE = "wic-image-minimal"\n'\
+ 'MACHINE_FEATURES:append = " efi"\n'
+ self.append_config(config)
+ bitbake('wic-image-minimal')
+ self.remove_config(config)
+
+ with runqemu('wic-image-minimal', ssh=False, runqemuparams='nographic') as qemu:
+ cmd = "mount | grep '^/dev/' | cut -f1,3 -d ' ' | egrep -c -e '/dev/sda1 /boot' " \
+ "-e '/dev/root /|/dev/sda2 /' -e '/dev/sda3 /media' -e '/dev/sda4 /mnt'"
+ status, output = qemu.run_serial(cmd)
+ self.assertEqual(1, status, 'Failed to run command "%s": %s' % (cmd, output))
+ self.assertEqual(output, '4')
+ cmd = "grep UUID=2c71ef06-a81d-4735-9d3a-379b69c6bdba /etc/fstab"
+ status, output = qemu.run_serial(cmd)
+ self.assertEqual(1, status, 'Failed to run command "%s": %s' % (cmd, output))
+ self.assertEqual(output, 'UUID=2c71ef06-a81d-4735-9d3a-379b69c6bdba\t/media\text4\tdefaults\t0\t0')
+
+ @skipIfNotArch(['i586', 'i686', 'x86_64'])
+ @OETestTag("runqemu")
+ def test_qemu_efi(self):
+ """Test core-image-minimal efi image under qemu"""
+ config = 'IMAGE_FSTYPES = "wic"\nWKS_FILE = "mkefidisk.wks"\n'
+ self.append_config(config)
+ bitbake('core-image-minimal ovmf')
+ self.remove_config(config)
+
+ with runqemu('core-image-minimal', ssh=False,
+ runqemuparams='nographic ovmf', image_fstype='wic') as qemu:
+ cmd = "grep sda. /proc/partitions |wc -l"
+ status, output = qemu.run_serial(cmd)
+ self.assertEqual(1, status, 'Failed to run command "%s": %s' % (cmd, output))
+ self.assertEqual(output, '3')
+
+ @staticmethod
+ def _make_fixed_size_wks(size):
+ """
+ Create a wks of an image with a single partition. Size of the partition is set
+ using --fixed-size flag. Returns a tuple: (path to wks file, wks image name)
+ """
+ with NamedTemporaryFile("w", suffix=".wks", delete=False) as tempf:
+ wkspath = tempf.name
+ tempf.write("part " \
+ "--source rootfs --ondisk hda --align 4 --fixed-size %d "
+ "--fstype=ext4\n" % size)
+
+ return wkspath
+
+ def _get_wic_partitions(self, wkspath, native_sysroot=None, ignore_status=False):
+ p = runCmd("wic create %s -e core-image-minimal -o %s" % (wkspath, self.resultdir),
+ ignore_status=ignore_status)
+
+ if p.status:
+ return (p, None)
+
+ wksname = os.path.splitext(os.path.basename(wkspath))[0]
+
+ wicout = glob(os.path.join(self.resultdir, "%s-*direct" % wksname))
+
+ if not wicout:
+ return (p, None)
+
+ wicimg = wicout[0]
+
+ if not native_sysroot:
+ native_sysroot = get_bb_var("RECIPE_SYSROOT_NATIVE", "wic-tools")
+
+ # verify partition size with wic
+ res = runCmd("parted -m %s unit kib p 2>/dev/null" % wicimg,
+ native_sysroot=native_sysroot)
+
+ # parse parted output which looks like this:
+ # BYT;\n
+ # /var/tmp/wic/build/tmpfwvjjkf_-201611101222-hda.direct:200MiB:file:512:512:msdos::;\n
+ # 1:0.00MiB:200MiB:200MiB:ext4::;\n
+ return (p, res.output.splitlines()[2:])
+
+ def test_fixed_size(self):
+ """
+ Test creation of a simple image with partition size controlled through
+ --fixed-size flag
+ """
+ wkspath = Wic2._make_fixed_size_wks(200)
+ _, partlns = self._get_wic_partitions(wkspath)
+ os.remove(wkspath)
+
+ self.assertEqual(partlns, [
+ "1:4.00kiB:204804kiB:204800kiB:ext4::;",
+ ])
+
+ def test_fixed_size_error(self):
+ """
+ Test creation of a simple image with partition size controlled through
+ --fixed-size flag. The size of partition is intentionally set to 1MiB
+ in order to trigger an error in wic.
+ """
+ wkspath = Wic2._make_fixed_size_wks(1)
+ p, _ = self._get_wic_partitions(wkspath, ignore_status=True)
+ os.remove(wkspath)
+
+ self.assertNotEqual(p.status, 0, "wic exited successfully when an error was expected:\n%s" % p.output)
+
+ def test_offset(self):
+ native_sysroot = get_bb_var("RECIPE_SYSROOT_NATIVE", "wic-tools")
+
+ with NamedTemporaryFile("w", suffix=".wks") as tempf:
+ # Test that partitions are placed at the correct offsets, default KB
+ tempf.write("bootloader --ptable gpt\n" \
+ "part / --source rootfs --ondisk hda --offset 32 --fixed-size 100M --fstype=ext4\n" \
+ "part /bar --ondisk hda --offset 102432 --fixed-size 100M --fstype=ext4\n")
+ tempf.flush()
+
+ _, partlns = self._get_wic_partitions(tempf.name, native_sysroot)
+ self.assertEqual(partlns, [
+ "1:32.0kiB:102432kiB:102400kiB:ext4:primary:;",
+ "2:102432kiB:204832kiB:102400kiB:ext4:primary:;",
+ ])
+
+ with NamedTemporaryFile("w", suffix=".wks") as tempf:
+ # Test that partitions are placed at the correct offsets, same with explicit KB
+ tempf.write("bootloader --ptable gpt\n" \
+ "part / --source rootfs --ondisk hda --offset 32K --fixed-size 100M --fstype=ext4\n" \
+ "part /bar --ondisk hda --offset 102432K --fixed-size 100M --fstype=ext4\n")
+ tempf.flush()
+
+ _, partlns = self._get_wic_partitions(tempf.name, native_sysroot)
+ self.assertEqual(partlns, [
+ "1:32.0kiB:102432kiB:102400kiB:ext4:primary:;",
+ "2:102432kiB:204832kiB:102400kiB:ext4:primary:;",
+ ])
+
+ with NamedTemporaryFile("w", suffix=".wks") as tempf:
+ # Test that partitions are placed at the correct offsets using MB
+ tempf.write("bootloader --ptable gpt\n" \
+ "part / --source rootfs --ondisk hda --offset 32K --fixed-size 100M --fstype=ext4\n" \
+ "part /bar --ondisk hda --offset 101M --fixed-size 100M --fstype=ext4\n")
+ tempf.flush()
+
+ _, partlns = self._get_wic_partitions(tempf.name, native_sysroot)
+ self.assertEqual(partlns, [
+ "1:32.0kiB:102432kiB:102400kiB:ext4:primary:;",
+ "2:103424kiB:205824kiB:102400kiB:ext4:primary:;",
+ ])
+
+ with NamedTemporaryFile("w", suffix=".wks") as tempf:
+ # Test that partitions can be placed on a 512 byte sector boundary
+ tempf.write("bootloader --ptable gpt\n" \
+ "part / --source rootfs --ondisk hda --offset 65s --fixed-size 99M --fstype=ext4\n" \
+ "part /bar --ondisk hda --offset 102432 --fixed-size 100M --fstype=ext4\n")
+ tempf.flush()
+
+ _, partlns = self._get_wic_partitions(tempf.name, native_sysroot)
+ self.assertEqual(partlns, [
+ "1:32.5kiB:101408kiB:101376kiB:ext4:primary:;",
+ "2:102432kiB:204832kiB:102400kiB:ext4:primary:;",
+ ])
+
+ with NamedTemporaryFile("w", suffix=".wks") as tempf:
+ # Test that a partition can be placed immediately after a MSDOS partition table
+ tempf.write("bootloader --ptable msdos\n" \
+ "part / --source rootfs --ondisk hda --offset 1s --fixed-size 100M --fstype=ext4\n")
+ tempf.flush()
+
+ _, partlns = self._get_wic_partitions(tempf.name, native_sysroot)
+ self.assertEqual(partlns, [
+ "1:0.50kiB:102400kiB:102400kiB:ext4::;",
+ ])
+
+ with NamedTemporaryFile("w", suffix=".wks") as tempf:
+ # Test that image creation fails if the partitions would overlap
+ tempf.write("bootloader --ptable gpt\n" \
+ "part / --source rootfs --ondisk hda --offset 32 --fixed-size 100M --fstype=ext4\n" \
+ "part /bar --ondisk hda --offset 102431 --fixed-size 100M --fstype=ext4\n")
+ tempf.flush()
+
+ p, _ = self._get_wic_partitions(tempf.name, ignore_status=True)
+ self.assertNotEqual(p.status, 0, "wic exited successfully when an error was expected:\n%s" % p.output)
+
+ with NamedTemporaryFile("w", suffix=".wks") as tempf:
+ # Test that partitions are not allowed to overlap with the booloader
+ tempf.write("bootloader --ptable gpt\n" \
+ "part / --source rootfs --ondisk hda --offset 8 --fixed-size 100M --fstype=ext4\n")
+ tempf.flush()
+
+ p, _ = self._get_wic_partitions(tempf.name, ignore_status=True)
+ self.assertNotEqual(p.status, 0, "wic exited successfully when an error was expected:\n%s" % p.output)
+
+ def test_extra_space(self):
+ native_sysroot = get_bb_var("RECIPE_SYSROOT_NATIVE", "wic-tools")
+
+ with NamedTemporaryFile("w", suffix=".wks") as tempf:
+ tempf.write("bootloader --ptable gpt\n" \
+ "part / --source rootfs --ondisk hda --extra-space 200M --fstype=ext4\n")
+ tempf.flush()
+
+ _, partlns = self._get_wic_partitions(tempf.name, native_sysroot)
+ self.assertEqual(len(partlns), 1)
+ size = partlns[0].split(':')[3]
+ self.assertRegex(size, r'^[0-9]+kiB$')
+ size = int(size[:-3])
+ self.assertGreaterEqual(size, 204800)
+
+ # TODO this test could also work on aarch64
+ @skipIfNotArch(['i586', 'i686', 'x86_64'])
+ @OETestTag("runqemu")
+ def test_rawcopy_plugin_qemu(self):
+ """Test rawcopy plugin in qemu"""
+ # build ext4 and then use it for a wic image
+ config = 'IMAGE_FSTYPES = "ext4"\n'
+ self.append_config(config)
+ bitbake('core-image-minimal')
+ self.remove_config(config)
+
+ config = 'IMAGE_FSTYPES = "wic"\nWKS_FILE = "test_rawcopy_plugin.wks.in"\n'
+ self.append_config(config)
+ bitbake('core-image-minimal-mtdutils')
+ self.remove_config(config)
+
+ with runqemu('core-image-minimal-mtdutils', ssh=False,
+ runqemuparams='nographic', image_fstype='wic') as qemu:
+ cmd = "grep sda. /proc/partitions |wc -l"
+ status, output = qemu.run_serial(cmd)
+ self.assertEqual(1, status, 'Failed to run command "%s": %s' % (cmd, output))
+ self.assertEqual(output, '2')
+
+ def _rawcopy_plugin(self, fstype):
+ """Test rawcopy plugin"""
+ img = 'core-image-minimal'
+ machine = self.td["MACHINE"]
+ params = ',unpack' if fstype.endswith('.gz') else ''
+ with NamedTemporaryFile("w", suffix=".wks") as wks:
+ wks.write('part / --source rawcopy --sourceparams="file=%s-%s.%s%s"\n'\
+ % (img, machine, fstype, params))
+ wks.flush()
+ cmd = "wic create %s -e %s -o %s" % (wks.name, img, self.resultdir)
+ runCmd(cmd)
+ wksname = os.path.splitext(os.path.basename(wks.name))[0]
+ out = glob(os.path.join(self.resultdir, "%s-*direct" % wksname))
+ self.assertEqual(1, len(out))
+
+ def test_rawcopy_plugin(self):
+ self._rawcopy_plugin('ext4')
+
+ def test_rawcopy_plugin_unpack(self):
+ fstype = 'ext4.gz'
+ config = 'IMAGE_FSTYPES = "%s"\n' % fstype
+ self.append_config(config)
+ self.assertEqual(0, bitbake('core-image-minimal').status)
+ self.remove_config(config)
+ self._rawcopy_plugin(fstype)
+
+ def test_empty_plugin(self):
+ """Test empty plugin"""
+ config = 'IMAGE_FSTYPES = "wic"\nWKS_FILE = "test_empty_plugin.wks"\n'
+ self.append_config(config)
+ bitbake('core-image-minimal')
+ self.remove_config(config)
+ deploy_dir = get_bb_var('DEPLOY_DIR_IMAGE')
+ machine = self.td['MACHINE']
+
+ image_path = os.path.join(deploy_dir, 'core-image-minimal-%s.wic' % machine)
+ self.assertTrue(os.path.exists(image_path))
+
+ sysroot = get_bb_var('RECIPE_SYSROOT_NATIVE', 'wic-tools')
+
+ # Fstype column from 'wic ls' should be empty for the second partition
+ # as listed in test_empty_plugin.wks
+ result = runCmd("wic ls %s -n %s | awk -F ' ' '{print $1 \" \" $5}' | grep '^2' | wc -w" % (image_path, sysroot))
+ self.assertEqual('1', result.output)
+
+ @skipIfNotArch(['i586', 'i686', 'x86_64'])
+ @OETestTag("runqemu")
+ def test_biosplusefi_plugin_qemu(self):
+ """Test biosplusefi plugin in qemu"""
+ config = 'IMAGE_FSTYPES = "wic"\nWKS_FILE = "test_biosplusefi_plugin.wks"\nMACHINE_FEATURES:append = " efi"\n'
+ self.append_config(config)
+ bitbake('core-image-minimal')
+ self.remove_config(config)
+
+ with runqemu('core-image-minimal', ssh=False,
+ runqemuparams='nographic', image_fstype='wic') as qemu:
+ # Check that we have ONLY two /dev/sda* partitions (/boot and /)
+ cmd = "grep sda. /proc/partitions | wc -l"
+ status, output = qemu.run_serial(cmd)
+ self.assertEqual(1, status, 'Failed to run command "%s": %s' % (cmd, output))
+ self.assertEqual(output, '2')
+ # Check that /dev/sda1 is /boot and that either /dev/root OR /dev/sda2 is /
+ cmd = "mount | grep '^/dev/' | cut -f1,3 -d ' ' | egrep -c -e '/dev/sda1 /boot' -e '/dev/root /|/dev/sda2 /'"
+ status, output = qemu.run_serial(cmd)
+ self.assertEqual(1, status, 'Failed to run command "%s": %s' % (cmd, output))
+ self.assertEqual(output, '2')
+ # Check that /boot has EFI bootx64.efi (required for EFI)
+ cmd = "ls /boot/EFI/BOOT/bootx64.efi | wc -l"
+ status, output = qemu.run_serial(cmd)
+ self.assertEqual(1, status, 'Failed to run command "%s": %s' % (cmd, output))
+ self.assertEqual(output, '1')
+ # Check that "BOOTABLE" flag is set on boot partition (required for PC-Bios)
+ # Trailing "cat" seems to be required; otherwise run_serial() sends back echo of the input command
+ cmd = "fdisk -l /dev/sda | grep /dev/sda1 | awk {print'$2'} | cat"
+ status, output = qemu.run_serial(cmd)
+ self.assertEqual(1, status, 'Failed to run command "%s": %s' % (cmd, output))
+ self.assertEqual(output, '*')
+
+ @skipIfNotArch(['i586', 'i686', 'x86_64'])
+ def test_biosplusefi_plugin(self):
+ """Test biosplusefi plugin"""
+ # Wic generation below may fail depending on the order of the unittests
+ # This is because bootimg-pcbios (that bootimg-biosplusefi uses) generate its MBR inside STAGING_DATADIR directory
+ # which may or may not exists depending on what was built already
+ # If an image hasn't been built yet, directory ${STAGING_DATADIR}/syslinux won't exists and _get_bootimg_dir()
+ # will raise with "Couldn't find correct bootimg_dir"
+ # The easiest way to work-around this issue is to make sure we already built an image here, hence the bitbake call
+ config = 'IMAGE_FSTYPES = "wic"\nWKS_FILE = "test_biosplusefi_plugin.wks"\nMACHINE_FEATURES:append = " efi"\n'
+ self.append_config(config)
+ bitbake('core-image-minimal')
+ self.remove_config(config)
+
+ img = 'core-image-minimal'
+ with NamedTemporaryFile("w", suffix=".wks") as wks:
+ wks.writelines(['part /boot --active --source bootimg-biosplusefi --sourceparams="loader=grub-efi"\n',
+ 'part / --source rootfs --fstype=ext4 --align 1024 --use-uuid\n'\
+ 'bootloader --timeout=0 --append="console=ttyS0,115200n8"\n'])
+ wks.flush()
+ cmd = "wic create %s -e %s -o %s" % (wks.name, img, self.resultdir)
+ runCmd(cmd)
+ wksname = os.path.splitext(os.path.basename(wks.name))[0]
+ out = glob(os.path.join(self.resultdir, "%s-*.direct" % wksname))
+ self.assertEqual(1, len(out))
+
+ # TODO this test could also work on aarch64
+ @skipIfNotArch(['i586', 'i686', 'x86_64'])
+ @OETestTag("runqemu")
+ def test_efi_plugin_unified_kernel_image_qemu(self):
+ """Test efi plugin's Unified Kernel Image feature in qemu"""
+ config = 'IMAGE_FSTYPES = "wic"\n'\
+ 'INITRAMFS_IMAGE = "core-image-minimal-initramfs"\n'\
+ 'WKS_FILE = "test_efi_plugin.wks"\n'\
+ 'MACHINE_FEATURES:append = " efi"\n'
+ self.append_config(config)
+ bitbake('core-image-minimal core-image-minimal-initramfs ovmf')
+ self.remove_config(config)
+
+ with runqemu('core-image-minimal', ssh=False,
+ runqemuparams='nographic ovmf', image_fstype='wic') as qemu:
+ # Check that /boot has EFI bootx64.efi (required for EFI)
+ cmd = "ls /boot/EFI/BOOT/bootx64.efi | wc -l"
+ status, output = qemu.run_serial(cmd)
+ self.assertEqual(1, status, 'Failed to run command "%s": %s' % (cmd, output))
+ self.assertEqual(output, '1')
+ # Check that /boot has EFI/Linux/linux.efi (required for Unified Kernel Images auto detection)
+ cmd = "ls /boot/EFI/Linux/linux.efi | wc -l"
+ status, output = qemu.run_serial(cmd)
+ self.assertEqual(1, status, 'Failed to run command "%s": %s' % (cmd, output))
+ self.assertEqual(output, '1')
+ # Check that /boot doesn't have loader/entries/boot.conf (Unified Kernel Images are auto detected by the bootloader)
+ cmd = "ls /boot/loader/entries/boot.conf 2&>/dev/null | wc -l"
+ status, output = qemu.run_serial(cmd)
+ self.assertEqual(1, status, 'Failed to run command "%s": %s' % (cmd, output))
+ self.assertEqual(output, '0')
+
+ def test_fs_types(self):
+ """Test filesystem types for empty and not empty partitions"""
+ img = 'core-image-minimal'
+ with NamedTemporaryFile("w", suffix=".wks") as wks:
+ wks.writelines(['part ext2 --fstype ext2 --source rootfs\n',
+ 'part btrfs --fstype btrfs --source rootfs --size 40M\n',
+ 'part squash --fstype squashfs --source rootfs\n',
+ 'part swap --fstype swap --size 1M\n',
+ 'part emptyvfat --fstype vfat --size 1M\n',
+ 'part emptymsdos --fstype msdos --size 1M\n',
+ 'part emptyext2 --fstype ext2 --size 1M\n',
+ 'part emptybtrfs --fstype btrfs --size 150M\n'])
+ wks.flush()
+ cmd = "wic create %s -e %s -o %s" % (wks.name, img, self.resultdir)
+ runCmd(cmd)
+ wksname = os.path.splitext(os.path.basename(wks.name))[0]
+ out = glob(os.path.join(self.resultdir, "%s-*direct" % wksname))
+ self.assertEqual(1, len(out))
+
+ def test_kickstart_parser(self):
+ """Test wks parser options"""
+ with NamedTemporaryFile("w", suffix=".wks") as wks:
+ wks.writelines(['part / --fstype ext3 --source rootfs --system-id 0xFF '\
+ '--overhead-factor 1.2 --size 100k\n'])
+ wks.flush()
+ cmd = "wic create %s -e core-image-minimal -o %s" % (wks.name, self.resultdir)
+ runCmd(cmd)
+ wksname = os.path.splitext(os.path.basename(wks.name))[0]
+ out = glob(os.path.join(self.resultdir, "%s-*direct" % wksname))
+ self.assertEqual(1, len(out))
+
+ def test_image_bootpart_globbed(self):
+ """Test globbed sources with image-bootpart plugin"""
+ img = "core-image-minimal"
+ cmd = "wic create sdimage-bootpart -e %s -o %s" % (img, self.resultdir)
+ config = 'IMAGE_BOOT_FILES = "%s*"' % get_bb_var('KERNEL_IMAGETYPE', img)
+ self.append_config(config)
+ runCmd(cmd)
+ self.remove_config(config)
+ self.assertEqual(1, len(glob(os.path.join(self.resultdir, "sdimage-bootpart-*direct"))))
+
+ def test_sparse_copy(self):
+ """Test sparse_copy with FIEMAP and SEEK_HOLE filemap APIs"""
+ libpath = os.path.join(self.td['COREBASE'], 'scripts', 'lib', 'wic')
+ sys.path.insert(0, libpath)
+ from filemap import FilemapFiemap, FilemapSeek, sparse_copy, ErrorNotSupp
+ with NamedTemporaryFile("w", suffix=".wic-sparse") as sparse:
+ src_name = sparse.name
+ src_size = 1024 * 10
+ sparse.truncate(src_size)
+ # write one byte to the file
+ with open(src_name, 'r+b') as sfile:
+ sfile.seek(1024 * 4)
+ sfile.write(b'\x00')
+ dest = sparse.name + '.out'
+ # copy src file to dest using different filemap APIs
+ for api in (FilemapFiemap, FilemapSeek, None):
+ if os.path.exists(dest):
+ os.unlink(dest)
+ try:
+ sparse_copy(sparse.name, dest, api=api)
+ except ErrorNotSupp:
+ continue # skip unsupported API
+ dest_stat = os.stat(dest)
+ self.assertEqual(dest_stat.st_size, src_size)
+ # 8 blocks is 4K (physical sector size)
+ self.assertEqual(dest_stat.st_blocks, 8)
+ os.unlink(dest)
+
+ def test_mkfs_extraopts(self):
+ """Test wks option --mkfs-extraopts for empty and not empty partitions"""
+ img = 'core-image-minimal'
+ with NamedTemporaryFile("w", suffix=".wks") as wks:
+ wks.writelines(
+ ['part ext2 --fstype ext2 --source rootfs --mkfs-extraopts "-D -F -i 8192"\n',
+ "part btrfs --fstype btrfs --source rootfs --size 40M --mkfs-extraopts='--quiet'\n",
+ 'part squash --fstype squashfs --source rootfs --mkfs-extraopts "-no-sparse -b 4096"\n',
+ 'part emptyvfat --fstype vfat --size 1M --mkfs-extraopts "-S 1024 -s 64"\n',
+ 'part emptymsdos --fstype msdos --size 1M --mkfs-extraopts "-S 1024 -s 64"\n',
+ 'part emptyext2 --fstype ext2 --size 1M --mkfs-extraopts "-D -F -i 8192"\n',
+ 'part emptybtrfs --fstype btrfs --size 100M --mkfs-extraopts "--mixed -K"\n'])
+ wks.flush()
+ cmd = "wic create %s -e %s -o %s" % (wks.name, img, self.resultdir)
+ runCmd(cmd)
+ wksname = os.path.splitext(os.path.basename(wks.name))[0]
+ out = glob(os.path.join(self.resultdir, "%s-*direct" % wksname))
+ self.assertEqual(1, len(out))
+
+ @skipIfNotArch(['i586', 'i686', 'x86_64'])
+ @OETestTag("runqemu")
+ def test_expand_mbr_image(self):
+ """Test wic write --expand command for mbr image"""
+ # build an image
+ config = 'IMAGE_FSTYPES = "wic"\nWKS_FILE = "directdisk.wks"\n'
+ self.append_config(config)
+ bitbake('core-image-minimal')
+
+ # get path to the image
+ deploy_dir = get_bb_var('DEPLOY_DIR_IMAGE')
+ machine = self.td['MACHINE']
+ image_path = os.path.join(deploy_dir, 'core-image-minimal-%s.wic' % machine)
+
+ self.remove_config(config)
+
+ try:
+ # expand image to 1G
+ new_image_path = None
+ with NamedTemporaryFile(mode='wb', suffix='.wic.exp',
+ dir=deploy_dir, delete=False) as sparse:
+ sparse.truncate(1024 ** 3)
+ new_image_path = sparse.name
+
+ sysroot = get_bb_var('RECIPE_SYSROOT_NATIVE', 'wic-tools')
+ cmd = "wic write -n %s --expand 1:0 %s %s" % (sysroot, image_path, new_image_path)
+ runCmd(cmd)
+
+ # check if partitions are expanded
+ orig = runCmd("wic ls %s -n %s" % (image_path, sysroot))
+ exp = runCmd("wic ls %s -n %s" % (new_image_path, sysroot))
+ orig_sizes = [int(line.split()[3]) for line in orig.output.split('\n')[1:]]
+ exp_sizes = [int(line.split()[3]) for line in exp.output.split('\n')[1:]]
+ self.assertEqual(orig_sizes[0], exp_sizes[0]) # first partition is not resized
+ self.assertTrue(orig_sizes[1] < exp_sizes[1])
+
+ # Check if all free space is partitioned
+ result = runCmd("%s/usr/sbin/sfdisk -F %s" % (sysroot, new_image_path))
+ self.assertTrue("0 B, 0 bytes, 0 sectors" in result.output)
+
+ os.rename(image_path, image_path + '.bak')
+ os.rename(new_image_path, image_path)
+
+ # Check if it boots in qemu
+ with runqemu('core-image-minimal', ssh=False, runqemuparams='nographic') as qemu:
+ cmd = "ls /etc/"
+ status, output = qemu.run_serial('true')
+ self.assertEqual(1, status, 'Failed to run command "%s": %s' % (cmd, output))
+ finally:
+ if os.path.exists(new_image_path):
+ os.unlink(new_image_path)
+ if os.path.exists(image_path + '.bak'):
+ os.rename(image_path + '.bak', image_path)
+
+class ModifyTests(WicTestCase):
+ def test_wic_ls(self):
+ """Test listing image content using 'wic ls'"""
+ runCmd("wic create wictestdisk "
+ "--image-name=core-image-minimal "
+ "-D -o %s" % self.resultdir)
+ images = glob(os.path.join(self.resultdir, "wictestdisk-*.direct"))
+ self.assertEqual(1, len(images))
+
+ sysroot = get_bb_var('RECIPE_SYSROOT_NATIVE', 'wic-tools')
+
+ # list partitions
+ result = runCmd("wic ls %s -n %s" % (images[0], sysroot))
+ self.assertEqual(3, len(result.output.split('\n')))
+
+ # list directory content of the first partition
+ result = runCmd("wic ls %s:1/ -n %s" % (images[0], sysroot))
+ self.assertEqual(6, len(result.output.split('\n')))
+
+ def test_wic_cp(self):
+ """Test copy files and directories to the the wic image."""
+ runCmd("wic create wictestdisk "
+ "--image-name=core-image-minimal "
+ "-D -o %s" % self.resultdir)
+ images = glob(os.path.join(self.resultdir, "wictestdisk-*.direct"))
+ self.assertEqual(1, len(images))
+
+ sysroot = get_bb_var('RECIPE_SYSROOT_NATIVE', 'wic-tools')
+
+ # list directory content of the first partition
+ result = runCmd("wic ls %s:1/ -n %s" % (images[0], sysroot))
+ self.assertEqual(6, len(result.output.split('\n')))
+
+ with NamedTemporaryFile("w", suffix=".wic-cp") as testfile:
+ testfile.write("test")
+
+ # copy file to the partition
+ runCmd("wic cp %s %s:1/ -n %s" % (testfile.name, images[0], sysroot))
+
+ # check if file is there
+ result = runCmd("wic ls %s:1/ -n %s" % (images[0], sysroot))
+ self.assertEqual(7, len(result.output.split('\n')))
+ self.assertTrue(os.path.basename(testfile.name) in result.output)
+
+ # prepare directory
+ testdir = os.path.join(self.resultdir, 'wic-test-cp-dir')
+ testsubdir = os.path.join(testdir, 'subdir')
+ os.makedirs(os.path.join(testsubdir))
+ copy(testfile.name, testdir)
+
+ # copy directory to the partition
+ runCmd("wic cp %s %s:1/ -n %s" % (testdir, images[0], sysroot))
+
+ # check if directory is there
+ result = runCmd("wic ls %s:1/ -n %s" % (images[0], sysroot))
+ self.assertEqual(8, len(result.output.split('\n')))
+ self.assertTrue(os.path.basename(testdir) in result.output)
+
+ # copy the file from the partition and check if it success
+ dest = '%s-cp' % testfile.name
+ runCmd("wic cp %s:1/%s %s -n %s" % (images[0],
+ os.path.basename(testfile.name), dest, sysroot))
+ self.assertTrue(os.path.exists(dest))
+
+
+ def test_wic_rm(self):
+ """Test removing files and directories from the the wic image."""
+ runCmd("wic create mkefidisk "
+ "--image-name=core-image-minimal "
+ "-D -o %s" % self.resultdir)
+ images = glob(os.path.join(self.resultdir, "mkefidisk-*.direct"))
+ self.assertEqual(1, len(images))
+
+ sysroot = get_bb_var('RECIPE_SYSROOT_NATIVE', 'wic-tools')
+ # Not bulletproof but hopefully sufficient
+ kerneltype = get_bb_var('KERNEL_IMAGETYPE', 'virtual/kernel')
+
+ # list directory content of the first partition
+ result = runCmd("wic ls %s:1 -n %s" % (images[0], sysroot))
+ self.assertIn('\n%s ' % kerneltype.upper(), result.output)
+ self.assertIn('\nEFI <DIR> ', result.output)
+
+ # remove file. EFI partitions are case-insensitive so exercise that too
+ runCmd("wic rm %s:1/%s -n %s" % (images[0], kerneltype.lower(), sysroot))
+
+ # remove directory
+ runCmd("wic rm %s:1/efi -n %s" % (images[0], sysroot))
+
+ # check if they're removed
+ result = runCmd("wic ls %s:1 -n %s" % (images[0], sysroot))
+ self.assertNotIn('\n%s ' % kerneltype.upper(), result.output)
+ self.assertNotIn('\nEFI <DIR> ', result.output)
+
+ def test_wic_ls_ext(self):
+ """Test listing content of the ext partition using 'wic ls'"""
+ runCmd("wic create wictestdisk "
+ "--image-name=core-image-minimal "
+ "-D -o %s" % self.resultdir)
+ images = glob(os.path.join(self.resultdir, "wictestdisk-*.direct"))
+ self.assertEqual(1, len(images))
+
+ sysroot = get_bb_var('RECIPE_SYSROOT_NATIVE', 'wic-tools')
+
+ # list directory content of the second ext4 partition
+ result = runCmd("wic ls %s:2/ -n %s" % (images[0], sysroot))
+ self.assertTrue(set(['bin', 'home', 'proc', 'usr', 'var', 'dev', 'lib', 'sbin']).issubset(
+ set(line.split()[-1] for line in result.output.split('\n') if line)))
+
+ def test_wic_cp_ext(self):
+ """Test copy files and directories to the ext partition."""
+ runCmd("wic create wictestdisk "
+ "--image-name=core-image-minimal "
+ "-D -o %s" % self.resultdir)
+ images = glob(os.path.join(self.resultdir, "wictestdisk-*.direct"))
+ self.assertEqual(1, len(images))
+
+ sysroot = get_bb_var('RECIPE_SYSROOT_NATIVE', 'wic-tools')
+
+ # list directory content of the ext4 partition
+ result = runCmd("wic ls %s:2/ -n %s" % (images[0], sysroot))
+ dirs = set(line.split()[-1] for line in result.output.split('\n') if line)
+ self.assertTrue(set(['bin', 'home', 'proc', 'usr', 'var', 'dev', 'lib', 'sbin']).issubset(dirs))
+
+ with NamedTemporaryFile("w", suffix=".wic-cp") as testfile:
+ testfile.write("test")
+
+ # copy file to the partition
+ runCmd("wic cp %s %s:2/ -n %s" % (testfile.name, images[0], sysroot))
+
+ # check if file is there
+ result = runCmd("wic ls %s:2/ -n %s" % (images[0], sysroot))
+ newdirs = set(line.split()[-1] for line in result.output.split('\n') if line)
+ self.assertEqual(newdirs.difference(dirs), set([os.path.basename(testfile.name)]))
+
+ # check if the file to copy is in the partition
+ result = runCmd("wic ls %s:2/etc/ -n %s" % (images[0], sysroot))
+ self.assertTrue('fstab' in [line.split()[-1] for line in result.output.split('\n') if line])
+
+ # copy file from the partition, replace the temporary file content with it and
+ # check for the file size to validate the copy
+ runCmd("wic cp %s:2/etc/fstab %s -n %s" % (images[0], testfile.name, sysroot))
+ self.assertTrue(os.stat(testfile.name).st_size > 0)
+
+
+ def test_wic_rm_ext(self):
+ """Test removing files from the ext partition."""
+ runCmd("wic create mkefidisk "
+ "--image-name=core-image-minimal "
+ "-D -o %s" % self.resultdir)
+ images = glob(os.path.join(self.resultdir, "mkefidisk-*.direct"))
+ self.assertEqual(1, len(images))
+
+ sysroot = get_bb_var('RECIPE_SYSROOT_NATIVE', 'wic-tools')
+
+ # list directory content of the /etc directory on ext4 partition
+ result = runCmd("wic ls %s:2/etc/ -n %s" % (images[0], sysroot))
+ self.assertTrue('fstab' in [line.split()[-1] for line in result.output.split('\n') if line])
+
+ # remove file
+ runCmd("wic rm %s:2/etc/fstab -n %s" % (images[0], sysroot))
+
+ # check if it's removed
+ result = runCmd("wic ls %s:2/etc/ -n %s" % (images[0], sysroot))
+ self.assertTrue('fstab' not in [line.split()[-1] for line in result.output.split('\n') if line])
+
+ # remove non-empty directory
+ runCmd("wic rm -r %s:2/etc/ -n %s" % (images[0], sysroot))
+
+ # check if it's removed
+ result = runCmd("wic ls %s:2/ -n %s" % (images[0], sysroot))
+ self.assertTrue('etc' not in [line.split()[-1] for line in result.output.split('\n') if line])
diff --git a/meta/lib/oeqa/selftest/cases/wrapper.py b/meta/lib/oeqa/selftest/cases/wrapper.py
new file mode 100644
index 0000000000..f2be44262c
--- /dev/null
+++ b/meta/lib/oeqa/selftest/cases/wrapper.py
@@ -0,0 +1,16 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+from oeqa.selftest.case import OESelftestTestCase
+from oeqa.utils.commands import bitbake
+
+class WrapperTests(OESelftestTestCase):
+ def test_shebang_wrapper(self):
+ """
+ Summary: Build a recipe which will fail if the cmdline_shebang_wrapper function is defective.
+ Expected: Exit status to be 0.
+ Author: Paulo Neves <ptsneves@gmail.com>
+ """
+ res = bitbake("cmdline-shebang-wrapper-test -c install", ignore_status=False)
diff --git a/meta/lib/oeqa/selftest/context.py b/meta/lib/oeqa/selftest/context.py
new file mode 100644
index 0000000000..c7dd03ce37
--- /dev/null
+++ b/meta/lib/oeqa/selftest/context.py
@@ -0,0 +1,412 @@
+#
+# Copyright (C) 2017 Intel Corporation
+#
+# SPDX-License-Identifier: MIT
+#
+
+import os
+import time
+import glob
+import sys
+import importlib
+import subprocess
+import unittest
+from random import choice
+
+import oeqa
+import oe
+import bb.utils
+
+from oeqa.core.context import OETestContext, OETestContextExecutor
+from oeqa.core.exception import OEQAPreRun, OEQATestNotFound
+
+from oeqa.utils.commands import runCmd, get_bb_vars, get_test_layer
+
+class NonConcurrentTestSuite(unittest.TestSuite):
+ def __init__(self, suite, processes, setupfunc, removefunc):
+ super().__init__([suite])
+ self.processes = processes
+ self.suite = suite
+ self.setupfunc = setupfunc
+ self.removefunc = removefunc
+
+ def run(self, result):
+ (builddir, newbuilddir) = self.setupfunc("-st", None, self.suite)
+ ret = super().run(result)
+ os.chdir(builddir)
+ if newbuilddir and ret.wasSuccessful() and self.removefunc:
+ self.removefunc(newbuilddir)
+
+def removebuilddir(d):
+ delay = 5
+ while delay and (os.path.exists(d + "/bitbake.lock") or os.path.exists(d + "/cache/hashserv.db-wal")):
+ time.sleep(1)
+ delay = delay - 1
+ # Deleting these directories takes a lot of time, use autobuilder
+ # clobberdir if its available
+ clobberdir = os.path.expanduser("~/yocto-autobuilder-helper/janitor/clobberdir")
+ if os.path.exists(clobberdir):
+ try:
+ subprocess.check_call([clobberdir, d])
+ return
+ except subprocess.CalledProcessError:
+ pass
+ bb.utils.prunedir(d, ionice=True)
+
+class OESelftestTestContext(OETestContext):
+ def __init__(self, td=None, logger=None, machines=None, config_paths=None, newbuilddir=None, keep_builddir=None):
+ super(OESelftestTestContext, self).__init__(td, logger)
+
+ self.machines = machines
+ self.custommachine = None
+ self.config_paths = config_paths
+ self.newbuilddir = newbuilddir
+
+ if keep_builddir:
+ self.removebuilddir = None
+ else:
+ self.removebuilddir = removebuilddir
+
+ def setup_builddir(self, suffix, selftestdir, suite):
+ builddir = os.environ['BUILDDIR']
+ if not selftestdir:
+ selftestdir = get_test_layer()
+ if self.newbuilddir:
+ newbuilddir = os.path.join(self.newbuilddir, 'build' + suffix)
+ else:
+ newbuilddir = builddir + suffix
+ newselftestdir = newbuilddir + "/meta-selftest"
+
+ if os.path.exists(newbuilddir):
+ self.logger.error("Build directory %s already exists, aborting" % newbuilddir)
+ sys.exit(1)
+
+ bb.utils.mkdirhier(newbuilddir)
+ oe.path.copytree(builddir + "/conf", newbuilddir + "/conf")
+ oe.path.copytree(builddir + "/cache", newbuilddir + "/cache")
+ oe.path.copytree(selftestdir, newselftestdir)
+
+ for e in os.environ:
+ if builddir + "/" in os.environ[e]:
+ os.environ[e] = os.environ[e].replace(builddir + "/", newbuilddir + "/")
+ if os.environ[e].endswith(builddir):
+ os.environ[e] = os.environ[e].replace(builddir, newbuilddir)
+
+ subprocess.check_output("git init; git add *; git commit -a -m 'initial'", cwd=newselftestdir, shell=True)
+
+ # Tried to used bitbake-layers add/remove but it requires recipe parsing and hence is too slow
+ subprocess.check_output("sed %s/conf/bblayers.conf -i -e 's#%s#%s#g'" % (newbuilddir, selftestdir, newselftestdir), cwd=newbuilddir, shell=True)
+
+ os.chdir(newbuilddir)
+
+ def patch_test(t):
+ if not hasattr(t, "tc"):
+ return
+ cp = t.tc.config_paths
+ for p in cp:
+ if selftestdir in cp[p] and newselftestdir not in cp[p]:
+ cp[p] = cp[p].replace(selftestdir, newselftestdir)
+ if builddir in cp[p] and newbuilddir not in cp[p]:
+ cp[p] = cp[p].replace(builddir, newbuilddir)
+
+ def patch_suite(s):
+ for x in s:
+ if isinstance(x, unittest.TestSuite):
+ patch_suite(x)
+ else:
+ patch_test(x)
+
+ patch_suite(suite)
+
+ return (builddir, newbuilddir)
+
+ def prepareSuite(self, suites, processes):
+ if processes:
+ from oeqa.core.utils.concurrencytest import ConcurrentTestSuite
+
+ return ConcurrentTestSuite(suites, processes, self.setup_builddir, self.removebuilddir)
+ else:
+ return NonConcurrentTestSuite(suites, processes, self.setup_builddir, self.removebuilddir)
+
+ def runTests(self, processes=None, machine=None, skips=[]):
+ if machine:
+ self.custommachine = machine
+ if machine == 'random':
+ self.custommachine = choice(self.machines)
+ self.logger.info('Run tests with custom MACHINE set to: %s' % \
+ self.custommachine)
+ return super(OESelftestTestContext, self).runTests(processes, skips)
+
+ def listTests(self, display_type, machine=None):
+ return super(OESelftestTestContext, self).listTests(display_type)
+
+class OESelftestTestContextExecutor(OETestContextExecutor):
+ _context_class = OESelftestTestContext
+ _script_executor = 'oe-selftest'
+
+ name = 'oe-selftest'
+ help = 'oe-selftest test component'
+ description = 'Executes selftest tests'
+
+ def register_commands(self, logger, parser):
+ group = parser.add_mutually_exclusive_group(required=True)
+
+ group.add_argument('-a', '--run-all-tests', default=False,
+ action="store_true", dest="run_all_tests",
+ help='Run all (unhidden) tests')
+ group.add_argument('-r', '--run-tests', required=False, action='store',
+ nargs='+', dest="run_tests", default=None,
+ help='Select what tests to run (modules, classes or test methods). Format should be: <module>.<class>.<test_method>')
+
+ group.add_argument('-m', '--list-modules', required=False,
+ action="store_true", default=False,
+ help='List all available test modules.')
+ group.add_argument('--list-classes', required=False,
+ action="store_true", default=False,
+ help='List all available test classes.')
+ group.add_argument('-l', '--list-tests', required=False,
+ action="store_true", default=False,
+ help='List all available tests.')
+
+ parser.add_argument('-R', '--skip-tests', required=False, action='store',
+ nargs='+', dest="skips", default=None,
+ help='Skip the tests specified. Format should be <module>[.<class>[.<test_method>]]')
+ parser.add_argument('-j', '--num-processes', dest='processes', action='store',
+ type=int, help="number of processes to execute in parallel with")
+
+ parser.add_argument('--machine', required=False, choices=['random', 'all'],
+ help='Run tests on different machines (random/all).')
+
+ parser.add_argument('-t', '--select-tag', dest="select_tags",
+ action='append', default=None,
+ help='Filter all (unhidden) tests to any that match any of the specified tag(s).')
+ parser.add_argument('-T', '--exclude-tag', dest="exclude_tags",
+ action='append', default=None,
+ help='Exclude all (unhidden) tests that match any of the specified tag(s). (exclude applies before select)')
+
+ parser.add_argument('-K', '--keep-builddir', action='store_true',
+ help='Keep the test build directory even if all tests pass')
+
+ parser.add_argument('-B', '--newbuilddir', help='New build directory to use for tests.')
+ parser.add_argument('-v', '--verbose', action='store_true')
+ parser.set_defaults(func=self.run)
+
+ def _get_available_machines(self):
+ machines = []
+
+ bbpath = self.tc_kwargs['init']['td']['BBPATH'].split(':')
+
+ for path in bbpath:
+ found_machines = glob.glob(os.path.join(path, 'conf', 'machine', '*.conf'))
+ if found_machines:
+ for i in found_machines:
+ # eg: '/home/<user>/poky/meta-intel/conf/machine/intel-core2-32.conf'
+ machines.append(os.path.splitext(os.path.basename(i))[0])
+
+ return machines
+
+ def _get_cases_paths(self, bbpath):
+ cases_paths = []
+ for layer in bbpath:
+ cases_dir = os.path.join(layer, 'lib', 'oeqa', 'selftest', 'cases')
+ if os.path.isdir(cases_dir):
+ cases_paths.append(cases_dir)
+ return cases_paths
+
+ def _process_args(self, logger, args):
+ args.test_start_time = time.strftime("%Y%m%d%H%M%S")
+ args.test_data_file = None
+ args.CASES_PATHS = None
+
+ bbvars = get_bb_vars()
+ logdir = os.environ.get("BUILDDIR")
+ if 'LOG_DIR' in bbvars:
+ logdir = bbvars['LOG_DIR']
+ bb.utils.mkdirhier(logdir)
+ args.output_log = logdir + '/%s-results-%s.log' % (self.name, args.test_start_time)
+
+ super(OESelftestTestContextExecutor, self)._process_args(logger, args)
+
+ if args.list_modules:
+ args.list_tests = 'module'
+ elif args.list_classes:
+ args.list_tests = 'class'
+ elif args.list_tests:
+ args.list_tests = 'name'
+
+ self.tc_kwargs['init']['td'] = bbvars
+ self.tc_kwargs['init']['machines'] = self._get_available_machines()
+
+ builddir = os.environ.get("BUILDDIR")
+ self.tc_kwargs['init']['config_paths'] = {}
+ self.tc_kwargs['init']['config_paths']['testlayer_path'] = get_test_layer()
+ self.tc_kwargs['init']['config_paths']['builddir'] = builddir
+ self.tc_kwargs['init']['config_paths']['localconf'] = os.path.join(builddir, "conf/local.conf")
+ self.tc_kwargs['init']['config_paths']['bblayers'] = os.path.join(builddir, "conf/bblayers.conf")
+ self.tc_kwargs['init']['newbuilddir'] = args.newbuilddir
+ self.tc_kwargs['init']['keep_builddir'] = args.keep_builddir
+
+ def tag_filter(tags):
+ if args.exclude_tags:
+ if any(tag in args.exclude_tags for tag in tags):
+ return True
+ if args.select_tags:
+ if not tags or not any(tag in args.select_tags for tag in tags):
+ return True
+ return False
+
+ if args.select_tags or args.exclude_tags:
+ self.tc_kwargs['load']['tags_filter'] = tag_filter
+
+ self.tc_kwargs['run']['skips'] = args.skips
+ self.tc_kwargs['run']['processes'] = args.processes
+
+ def _pre_run(self):
+ def _check_required_env_variables(vars):
+ for var in vars:
+ if not os.environ.get(var):
+ self.tc.logger.error("%s is not set. Did you forget to source your build environment setup script?" % var)
+ raise OEQAPreRun
+
+ def _check_presence_meta_selftest():
+ builddir = os.environ.get("BUILDDIR")
+ if os.getcwd() != builddir:
+ self.tc.logger.info("Changing cwd to %s" % builddir)
+ os.chdir(builddir)
+
+ if not "meta-selftest" in self.tc.td["BBLAYERS"]:
+ self.tc.logger.warning("meta-selftest layer not found in BBLAYERS, adding it")
+ meta_selftestdir = os.path.join(
+ self.tc.td["BBLAYERS_FETCH_DIR"], 'meta-selftest')
+ if os.path.isdir(meta_selftestdir):
+ runCmd("bitbake-layers add-layer %s" %meta_selftestdir)
+ # reload data is needed because a meta-selftest layer was add
+ self.tc.td = get_bb_vars()
+ self.tc.config_paths['testlayer_path'] = get_test_layer()
+ else:
+ self.tc.logger.error("could not locate meta-selftest in:\n%s" % meta_selftestdir)
+ raise OEQAPreRun
+
+ def _add_layer_libs():
+ bbpath = self.tc.td['BBPATH'].split(':')
+ layer_libdirs = [p for p in (os.path.join(l, 'lib') \
+ for l in bbpath) if os.path.exists(p)]
+ if layer_libdirs:
+ self.tc.logger.info("Adding layer libraries:")
+ for l in layer_libdirs:
+ self.tc.logger.info("\t%s" % l)
+
+ sys.path.extend(layer_libdirs)
+ importlib.reload(oeqa.selftest)
+
+ _check_required_env_variables(["BUILDDIR"])
+ _check_presence_meta_selftest()
+
+ if "buildhistory.bbclass" in self.tc.td["BBINCLUDED"]:
+ self.tc.logger.error("You have buildhistory enabled already and this isn't recommended for selftest, please disable it first.")
+ raise OEQAPreRun
+
+ if "rm_work.bbclass" in self.tc.td["BBINCLUDED"]:
+ self.tc.logger.error("You have rm_work enabled which isn't recommended while running oe-selftest. Please disable it before continuing.")
+ raise OEQAPreRun
+
+ if "PRSERV_HOST" in self.tc.td:
+ self.tc.logger.error("Please unset PRSERV_HOST in order to run oe-selftest")
+ raise OEQAPreRun
+
+ if "SANITY_TESTED_DISTROS" in self.tc.td:
+ self.tc.logger.error("Please unset SANITY_TESTED_DISTROS in order to run oe-selftest")
+ raise OEQAPreRun
+
+ _add_layer_libs()
+
+ self.tc.logger.info("Running bitbake -e to test the configuration is valid/parsable")
+ runCmd("bitbake -e")
+
+ def get_json_result_dir(self, args):
+ json_result_dir = os.path.join(self.tc.td["LOG_DIR"], 'oeqa')
+ if "OEQA_JSON_RESULT_DIR" in self.tc.td:
+ json_result_dir = self.tc.td["OEQA_JSON_RESULT_DIR"]
+
+ return json_result_dir
+
+ def get_configuration(self, args):
+ import platform
+ from oeqa.utils.metadata import metadata_from_bb
+ metadata = metadata_from_bb()
+ configuration = {'TEST_TYPE': 'oeselftest',
+ 'STARTTIME': args.test_start_time,
+ 'MACHINE': self.tc.td["MACHINE"],
+ 'HOST_DISTRO': oe.lsb.distro_identifier().replace(' ', '-'),
+ 'HOST_NAME': metadata['hostname'],
+ 'LAYERS': metadata['layers']}
+ return configuration
+
+ def get_result_id(self, configuration):
+ return '%s_%s_%s_%s' % (configuration['TEST_TYPE'], configuration['HOST_DISTRO'], configuration['MACHINE'], configuration['STARTTIME'])
+
+ def _internal_run(self, logger, args):
+ self.module_paths = self._get_cases_paths(
+ self.tc_kwargs['init']['td']['BBPATH'].split(':'))
+
+ self.tc = self._context_class(**self.tc_kwargs['init'])
+ try:
+ self.tc.loadTests(self.module_paths, **self.tc_kwargs['load'])
+ except OEQATestNotFound as ex:
+ logger.error(ex)
+ sys.exit(1)
+
+ if args.list_tests:
+ rc = self.tc.listTests(args.list_tests, **self.tc_kwargs['list'])
+ else:
+ self._pre_run()
+ rc = self.tc.runTests(**self.tc_kwargs['run'])
+ configuration = self.get_configuration(args)
+ rc.logDetails(self.get_json_result_dir(args),
+ configuration,
+ self.get_result_id(configuration))
+ rc.logSummary(self.name)
+
+ return rc
+
+ def run(self, logger, args):
+ self._process_args(logger, args)
+
+ rc = None
+ try:
+ if args.machine:
+ logger.info('Custom machine mode enabled. MACHINE set to %s' %
+ args.machine)
+
+ if args.machine == 'all':
+ results = []
+ for m in self.tc_kwargs['init']['machines']:
+ self.tc_kwargs['run']['machine'] = m
+ results.append(self._internal_run(logger, args))
+
+ # XXX: the oe-selftest script only needs to know if one
+ # machine run fails
+ for r in results:
+ rc = r
+ if not r.wasSuccessful():
+ break
+
+ else:
+ self.tc_kwargs['run']['machine'] = args.machine
+ return self._internal_run(logger, args)
+
+ else:
+ self.tc_kwargs['run']['machine'] = args.machine
+ rc = self._internal_run(logger, args)
+ finally:
+ config_paths = self.tc_kwargs['init']['config_paths']
+
+ output_link = os.path.join(os.path.dirname(args.output_log),
+ "%s-results.log" % self.name)
+ if os.path.lexists(output_link):
+ os.remove(output_link)
+ os.symlink(args.output_log, output_link)
+
+ return rc
+
+_executor_class = OESelftestTestContextExecutor
diff --git a/meta/lib/oeqa/selftest/imagefeatures.py b/meta/lib/oeqa/selftest/imagefeatures.py
deleted file mode 100644
index 08e382f2b7..0000000000
--- a/meta/lib/oeqa/selftest/imagefeatures.py
+++ /dev/null
@@ -1,127 +0,0 @@
-from oeqa.selftest.base import oeSelfTest
-from oeqa.utils.commands import runCmd, bitbake, get_bb_var, runqemu
-from oeqa.utils.decorators import testcase
-from oeqa.utils.sshcontrol import SSHControl
-import os
-import sys
-import logging
-
-class ImageFeatures(oeSelfTest):
-
- test_user = 'tester'
- root_user = 'root'
-
- @testcase(1107)
- def test_non_root_user_can_connect_via_ssh_without_password(self):
- """
- Summary: Check if non root user can connect via ssh without password
- Expected: 1. Connection to the image via ssh using root user without providing a password should be allowed.
- 2. Connection to the image via ssh using tester user without providing a password should be allowed.
- Product: oe-core
- Author: Ionut Chisanovici <ionutx.chisanovici@intel.com>
- AutomatedBy: Daniel Istrate <daniel.alexandrux.istrate@intel.com>
- """
-
- features = 'EXTRA_IMAGE_FEATURES = "ssh-server-openssh empty-root-password allow-empty-password"\n'
- features += 'INHERIT += "extrausers"\n'
- features += 'EXTRA_USERS_PARAMS = "useradd -p \'\' {}; usermod -s /bin/sh {};"'.format(self.test_user, self.test_user)
- self.write_config(features)
-
- # Build a core-image-minimal
- bitbake('core-image-minimal')
-
- with runqemu("core-image-minimal") as qemu:
- # Attempt to ssh with each user into qemu with empty password
- for user in [self.root_user, self.test_user]:
- ssh = SSHControl(ip=qemu.ip, logfile=qemu.sshlog, user=user)
- status, output = ssh.run("true")
- self.assertEqual(status, 0, 'ssh to user %s failed with %s' % (user, output))
-
- @testcase(1115)
- def test_all_users_can_connect_via_ssh_without_password(self):
- """
- Summary: Check if all users can connect via ssh without password
- Expected: 1. Connection to the image via ssh using root user without providing a password should NOT be allowed.
- 2. Connection to the image via ssh using tester user without providing a password should be allowed.
- Product: oe-core
- Author: Ionut Chisanovici <ionutx.chisanovici@intel.com>
- AutomatedBy: Daniel Istrate <daniel.alexandrux.istrate@intel.com>
- """
-
- features = 'EXTRA_IMAGE_FEATURES = "ssh-server-openssh allow-empty-password"\n'
- features += 'INHERIT += "extrausers"\n'
- features += 'EXTRA_USERS_PARAMS = "useradd -p \'\' {}; usermod -s /bin/sh {};"'.format(self.test_user, self.test_user)
- self.write_config(features)
-
- # Build a core-image-minimal
- bitbake('core-image-minimal')
-
- with runqemu("core-image-minimal") as qemu:
- # Attempt to ssh with each user into qemu with empty password
- for user in [self.root_user, self.test_user]:
- ssh = SSHControl(ip=qemu.ip, logfile=qemu.sshlog, user=user)
- status, output = ssh.run("true")
- if user == 'root':
- self.assertNotEqual(status, 0, 'ssh to user root was allowed when it should not have been')
- else:
- self.assertEqual(status, 0, 'ssh to user tester failed with %s' % output)
-
-
- @testcase(1116)
- def test_clutter_image_can_be_built(self):
- """
- Summary: Check if clutter image can be built
- Expected: 1. core-image-clutter can be built
- Product: oe-core
- Author: Ionut Chisanovici <ionutx.chisanovici@intel.com>
- AutomatedBy: Daniel Istrate <daniel.alexandrux.istrate@intel.com>
- """
-
- # Build a core-image-clutter
- bitbake('core-image-clutter')
-
- @testcase(1117)
- def test_wayland_support_in_image(self):
- """
- Summary: Check Wayland support in image
- Expected: 1. Wayland image can be build
- 2. Wayland feature can be installed
- Product: oe-core
- Author: Ionut Chisanovici <ionutx.chisanovici@intel.com>
- AutomatedBy: Daniel Istrate <daniel.alexandrux.istrate@intel.com>
- """
-
- features = 'DISTRO_FEATURES_append = " wayland"\n'
- features += 'CORE_IMAGE_EXTRA_INSTALL += "wayland weston"'
- self.write_config(features)
-
- # Build a core-image-weston
- bitbake('core-image-weston')
-
- def test_bmap(self):
- """
- Summary: Check bmap support
- Expected: 1. core-image-minimal can be build with bmap support
- 2. core-image-minimal is sparse
- Product: oe-core
- Author: Ed Bartosh <ed.bartosh@linux.intel.com>
- """
-
- features = 'IMAGE_FSTYPES += " ext4 ext4.bmap"'
- self.write_config(features)
-
- image_name = 'core-image-minimal'
- bitbake(image_name)
-
- deploy_dir = get_bb_var('DEPLOY_DIR_IMAGE')
- link_name = get_bb_var('IMAGE_LINK_NAME', image_name)
- image_path = os.path.join(deploy_dir, "%s.ext4" % link_name)
- bmap_path = "%s.bmap" % image_path
-
- # check if result image and bmap file are in deploy directory
- self.assertTrue(os.path.exists(image_path))
- self.assertTrue(os.path.exists(bmap_path))
-
- # check if result image is sparse
- image_stat = os.stat(image_path)
- self.assertTrue(image_stat.st_size > image_stat.st_blocks * 512)
diff --git a/meta/lib/oeqa/selftest/oescripts.py b/meta/lib/oeqa/selftest/oescripts.py
deleted file mode 100644
index 31cd50809c..0000000000
--- a/meta/lib/oeqa/selftest/oescripts.py
+++ /dev/null
@@ -1,54 +0,0 @@
-import datetime
-import unittest
-import os
-import re
-import shutil
-
-import oeqa.utils.ftools as ftools
-from oeqa.selftest.base import oeSelfTest
-from oeqa.selftest.buildhistory import BuildhistoryBase
-from oeqa.utils.commands import Command, runCmd, bitbake, get_bb_var, get_test_layer
-from oeqa.utils.decorators import testcase
-
-class TestScripts(oeSelfTest):
-
- @testcase(300)
- def test_cleanup_workdir(self):
- path = os.path.dirname(get_bb_var('WORKDIR', 'gzip'))
- old_version_recipe = os.path.join(get_bb_var('COREBASE'), 'meta/recipes-extended/gzip/gzip_1.3.12.bb')
- old_version = '1.3.12'
- bitbake("-ccleansstate gzip")
- bitbake("-ccleansstate -b %s" % old_version_recipe)
- if os.path.exists(get_bb_var('WORKDIR', "-b %s" % old_version_recipe)):
- shutil.rmtree(get_bb_var('WORKDIR', "-b %s" % old_version_recipe))
- if os.path.exists(get_bb_var('WORKDIR', 'gzip')):
- shutil.rmtree(get_bb_var('WORKDIR', 'gzip'))
-
- if os.path.exists(path):
- initial_contents = os.listdir(path)
- else:
- initial_contents = []
-
- bitbake('gzip')
- intermediary_contents = os.listdir(path)
- bitbake("-b %s" % old_version_recipe)
- runCmd('cleanup-workdir')
- remaining_contents = os.listdir(path)
-
- expected_contents = [x for x in intermediary_contents if x not in initial_contents]
- remaining_not_expected = [x for x in remaining_contents if x not in expected_contents]
- self.assertFalse(remaining_not_expected, msg="Not all necessary content has been deleted from %s: %s" % (path, ', '.join(map(str, remaining_not_expected))))
- expected_not_remaining = [x for x in expected_contents if x not in remaining_contents]
- self.assertFalse(expected_not_remaining, msg="The script removed extra contents from %s: %s" % (path, ', '.join(map(str, expected_not_remaining))))
-
-class BuildhistoryDiffTests(BuildhistoryBase):
-
- @testcase(295)
- def test_buildhistory_diff(self):
- self.add_command_to_tearDown('cleanup-workdir')
- target = 'xcursor-transparent-theme'
- self.run_buildhistory_operation(target, target_config="PR = \"r1\"", change_bh_location=True)
- self.run_buildhistory_operation(target, target_config="PR = \"r0\"", change_bh_location=False, expect_error=True)
- result = runCmd("buildhistory-diff -p %s" % get_bb_var('BUILDHISTORY_DIR'))
- expected_output = 'PR changed from "r1" to "r0"'
- self.assertTrue(expected_output in result.output, msg="Did not find expected output: %s" % result.output)
diff --git a/meta/lib/oeqa/selftest/signing.py b/meta/lib/oeqa/selftest/signing.py
deleted file mode 100644
index 4c12d6d940..0000000000
--- a/meta/lib/oeqa/selftest/signing.py
+++ /dev/null
@@ -1,178 +0,0 @@
-from oeqa.selftest.base import oeSelfTest
-from oeqa.utils.commands import runCmd, bitbake, get_bb_var
-import os
-import glob
-import re
-import shutil
-import tempfile
-from oeqa.utils.decorators import testcase
-from oeqa.utils.ftools import write_file
-
-
-class Signing(oeSelfTest):
-
- gpg_dir = ""
- pub_key_path = ""
- secret_key_path = ""
-
- @classmethod
- def setUpClass(cls):
- # Check that we can find the gpg binary and fail early if we can't
- if not shutil.which("gpg"):
- raise AssertionError("This test needs GnuPG")
-
- cls.gpg_home_dir = tempfile.TemporaryDirectory(prefix="oeqa-signing-")
- cls.gpg_dir = cls.gpg_home_dir.name
-
- cls.pub_key_path = os.path.join(cls.testlayer_path, 'files', 'signing', "key.pub")
- cls.secret_key_path = os.path.join(cls.testlayer_path, 'files', 'signing', "key.secret")
-
- runCmd('gpg --homedir %s --import %s %s' % (cls.gpg_dir, cls.pub_key_path, cls.secret_key_path))
-
- @testcase(1362)
- def test_signing_packages(self):
- """
- Summary: Test that packages can be signed in the package feed
- Expected: Package should be signed with the correct key
- Product: oe-core
- Author: Daniel Istrate <daniel.alexandrux.istrate@intel.com>
- AutomatedBy: Daniel Istrate <daniel.alexandrux.istrate@intel.com>
- """
- import oe.packagedata
-
- package_classes = get_bb_var('PACKAGE_CLASSES')
- if 'package_rpm' not in package_classes:
- self.skipTest('This test requires RPM Packaging.')
-
- test_recipe = 'ed'
-
- feature = 'INHERIT += "sign_rpm"\n'
- feature += 'RPM_GPG_PASSPHRASE = "test123"\n'
- feature += 'RPM_GPG_NAME = "testuser"\n'
- feature += 'RPM_GPG_PUBKEY = "%s"\n' % self.pub_key_path
- feature += 'GPG_PATH = "%s"\n' % self.gpg_dir
-
- self.write_config(feature)
-
- bitbake('-c cleansstate %s' % test_recipe)
- bitbake(test_recipe)
- self.add_command_to_tearDown('bitbake -c clean %s' % test_recipe)
-
- pkgdatadir = get_bb_var('PKGDATA_DIR', test_recipe)
- pkgdata = oe.packagedata.read_pkgdatafile(pkgdatadir + "/runtime/ed")
- if 'PKGE' in pkgdata:
- pf = pkgdata['PN'] + "-" + pkgdata['PKGE'] + pkgdata['PKGV'] + '-' + pkgdata['PKGR']
- else:
- pf = pkgdata['PN'] + "-" + pkgdata['PKGV'] + '-' + pkgdata['PKGR']
- deploy_dir_rpm = get_bb_var('DEPLOY_DIR_RPM', test_recipe)
- package_arch = get_bb_var('PACKAGE_ARCH', test_recipe).replace('-', '_')
- staging_bindir_native = get_bb_var('STAGING_BINDIR_NATIVE')
-
- pkg_deploy = os.path.join(deploy_dir_rpm, package_arch, '.'.join((pf, package_arch, 'rpm')))
-
- # Use a temporary rpmdb
- rpmdb = tempfile.mkdtemp(prefix='oeqa-rpmdb')
-
- runCmd('%s/rpm --define "_dbpath %s" --import %s' %
- (staging_bindir_native, rpmdb, self.pub_key_path))
-
- ret = runCmd('%s/rpm --define "_dbpath %s" --checksig %s' %
- (staging_bindir_native, rpmdb, pkg_deploy))
- # tmp/deploy/rpm/i586/ed-1.9-r0.i586.rpm: rsa sha1 md5 OK
- self.assertIn('rsa sha1 md5 OK', ret.output, 'Package signed incorrectly.')
- shutil.rmtree(rpmdb)
-
- @testcase(1382)
- def test_signing_sstate_archive(self):
- """
- Summary: Test that sstate archives can be signed
- Expected: Package should be signed with the correct key
- Product: oe-core
- Author: Daniel Istrate <daniel.alexandrux.istrate@intel.com>
- AutomatedBy: Daniel Istrate <daniel.alexandrux.istrate@intel.com>
- """
-
- test_recipe = 'ed'
-
- builddir = os.environ.get('BUILDDIR')
- sstatedir = os.path.join(builddir, 'test-sstate')
-
- self.add_command_to_tearDown('bitbake -c clean %s' % test_recipe)
- self.add_command_to_tearDown('bitbake -c cleansstate %s' % test_recipe)
- self.add_command_to_tearDown('rm -rf %s' % sstatedir)
-
- # Determine the pub key signature
- ret = runCmd('gpg --homedir %s --list-keys' % self.gpg_dir)
- pub_key = re.search(r'^pub\s+\S+/(\S+)\s+', ret.output, re.M)
- self.assertIsNotNone(pub_key, 'Failed to determine the public key signature.')
- pub_key = pub_key.group(1)
-
- feature = 'SSTATE_SIG_KEY ?= "%s"\n' % pub_key
- feature += 'SSTATE_SIG_PASSPHRASE ?= "test123"\n'
- feature += 'SSTATE_VERIFY_SIG ?= "1"\n'
- feature += 'GPG_PATH = "%s"\n' % self.gpg_dir
- feature += 'SSTATE_DIR = "%s"\n' % sstatedir
-
- self.write_config(feature)
-
- bitbake('-c cleansstate %s' % test_recipe)
- bitbake(test_recipe)
-
- recipe_sig = glob.glob(sstatedir + '/*/*:ed:*_package.tgz.sig')
- recipe_tgz = glob.glob(sstatedir + '/*/*:ed:*_package.tgz')
-
- self.assertEqual(len(recipe_sig), 1, 'Failed to find .sig file.')
- self.assertEqual(len(recipe_tgz), 1, 'Failed to find .tgz file.')
-
- ret = runCmd('gpg --homedir %s --verify %s %s' % (self.gpg_dir, recipe_sig[0], recipe_tgz[0]))
- # gpg: Signature made Thu 22 Oct 2015 01:45:09 PM EEST using RSA key ID 61EEFB30
- # gpg: Good signature from "testuser (nocomment) <testuser@email.com>"
- self.assertIn('gpg: Good signature from', ret.output, 'Package signed incorrectly.')
-
-
-class LockedSignatures(oeSelfTest):
-
- @testcase(1420)
- def test_locked_signatures(self):
- """
- Summary: Test locked signature mechanism
- Expected: Locked signatures will prevent task to run
- Product: oe-core
- Author: Daniel Istrate <daniel.alexandrux.istrate@intel.com>
- AutomatedBy: Daniel Istrate <daniel.alexandrux.istrate@intel.com>
- """
-
- test_recipe = 'ed'
- locked_sigs_file = 'locked-sigs.inc'
-
- self.add_command_to_tearDown('rm -f %s' % os.path.join(self.builddir, locked_sigs_file))
-
- bitbake(test_recipe)
- # Generate locked sigs include file
- bitbake('-S none %s' % test_recipe)
-
- feature = 'require %s\n' % locked_sigs_file
- feature += 'SIGGEN_LOCKEDSIGS_TASKSIG_CHECK = "warn"\n'
- self.write_config(feature)
-
- # Build a locked recipe
- bitbake(test_recipe)
-
- # Make a change that should cause the locked task signature to change
- recipe_append_file = test_recipe + '_' + get_bb_var('PV', test_recipe) + '.bbappend'
- recipe_append_path = os.path.join(self.testlayer_path, 'recipes-test', test_recipe, recipe_append_file)
- feature = 'SUMMARY += "test locked signature"\n'
-
- os.mkdir(os.path.join(self.testlayer_path, 'recipes-test', test_recipe))
- write_file(recipe_append_path, feature)
-
- self.add_command_to_tearDown('rm -rf %s' % os.path.join(self.testlayer_path, 'recipes-test', test_recipe))
-
- # Build the recipe again
- ret = bitbake(test_recipe)
-
- # Verify you get the warning and that the real task *isn't* run (i.e. the locked signature has worked)
- patt = r'WARNING: The %s:do_package sig is computed to be \S+, but the sig is locked to \S+ in SIGGEN_LOCKEDSIGS\S+' % test_recipe
- found_warn = re.search(patt, ret.output)
-
- self.assertIsNotNone(found_warn, "Didn't find the expected warning message. Output: %s" % ret.output)
diff --git a/meta/lib/oeqa/selftest/sstatetests.py b/meta/lib/oeqa/selftest/sstatetests.py
deleted file mode 100644
index 07212ac4f1..0000000000
--- a/meta/lib/oeqa/selftest/sstatetests.py
+++ /dev/null
@@ -1,467 +0,0 @@
-import datetime
-import unittest
-import os
-import re
-import shutil
-import glob
-import subprocess
-
-import oeqa.utils.ftools as ftools
-from oeqa.selftest.base import oeSelfTest
-from oeqa.utils.commands import runCmd, bitbake, get_bb_var, get_test_layer
-from oeqa.selftest.sstate import SStateBase
-from oeqa.utils.decorators import testcase
-
-class SStateTests(SStateBase):
-
- # Test sstate files creation and their location
- def run_test_sstate_creation(self, targets, distro_specific=True, distro_nonspecific=True, temp_sstate_location=True, should_pass=True):
- self.config_sstate(temp_sstate_location)
-
- if self.temp_sstate_location:
- bitbake(['-cclean'] + targets)
- else:
- bitbake(['-ccleansstate'] + targets)
-
- bitbake(targets)
- file_tracker = []
- results = self.search_sstate('|'.join(map(str, targets)), distro_specific, distro_nonspecific)
- if distro_nonspecific:
- for r in results:
- if r.endswith(("_populate_lic.tgz", "_populate_lic.tgz.siginfo", "_fetch.tgz.siginfo", "_unpack.tgz.siginfo", "_patch.tgz.siginfo")):
- continue
- file_tracker.append(r)
- else:
- file_tracker = results
-
- if should_pass:
- self.assertTrue(file_tracker , msg="Could not find sstate files for: %s" % ', '.join(map(str, targets)))
- else:
- self.assertTrue(not file_tracker , msg="Found sstate files in the wrong place for: %s (found %s)" % (', '.join(map(str, targets)), str(file_tracker)))
-
- @testcase(975)
- def test_sstate_creation_distro_specific_pass(self):
- targetarch = get_bb_var('TUNE_ARCH')
- self.run_test_sstate_creation(['binutils-cross-'+ targetarch, 'binutils-native'], distro_specific=True, distro_nonspecific=False, temp_sstate_location=True)
-
- @testcase(1374)
- def test_sstate_creation_distro_specific_fail(self):
- targetarch = get_bb_var('TUNE_ARCH')
- self.run_test_sstate_creation(['binutils-cross-'+ targetarch, 'binutils-native'], distro_specific=False, distro_nonspecific=True, temp_sstate_location=True, should_pass=False)
-
- @testcase(976)
- def test_sstate_creation_distro_nonspecific_pass(self):
- self.run_test_sstate_creation(['glibc-initial'], distro_specific=False, distro_nonspecific=True, temp_sstate_location=True)
-
- @testcase(1375)
- def test_sstate_creation_distro_nonspecific_fail(self):
- self.run_test_sstate_creation(['glibc-initial'], distro_specific=True, distro_nonspecific=False, temp_sstate_location=True, should_pass=False)
-
-
- # Test the sstate files deletion part of the do_cleansstate task
- def run_test_cleansstate_task(self, targets, distro_specific=True, distro_nonspecific=True, temp_sstate_location=True):
- self.config_sstate(temp_sstate_location)
-
- bitbake(['-ccleansstate'] + targets)
-
- bitbake(targets)
- tgz_created = self.search_sstate('|'.join(map(str, [s + '.*?\.tgz$' for s in targets])), distro_specific, distro_nonspecific)
- self.assertTrue(tgz_created, msg="Could not find sstate .tgz files for: %s (%s)" % (', '.join(map(str, targets)), str(tgz_created)))
-
- siginfo_created = self.search_sstate('|'.join(map(str, [s + '.*?\.siginfo$' for s in targets])), distro_specific, distro_nonspecific)
- self.assertTrue(siginfo_created, msg="Could not find sstate .siginfo files for: %s (%s)" % (', '.join(map(str, targets)), str(siginfo_created)))
-
- bitbake(['-ccleansstate'] + targets)
- tgz_removed = self.search_sstate('|'.join(map(str, [s + '.*?\.tgz$' for s in targets])), distro_specific, distro_nonspecific)
- self.assertTrue(not tgz_removed, msg="do_cleansstate didn't remove .tgz sstate files for: %s (%s)" % (', '.join(map(str, targets)), str(tgz_removed)))
-
- @testcase(977)
- def test_cleansstate_task_distro_specific_nonspecific(self):
- targetarch = get_bb_var('TUNE_ARCH')
- self.run_test_cleansstate_task(['binutils-cross-' + targetarch, 'binutils-native', 'glibc-initial'], distro_specific=True, distro_nonspecific=True, temp_sstate_location=True)
-
- @testcase(1376)
- def test_cleansstate_task_distro_nonspecific(self):
- self.run_test_cleansstate_task(['glibc-initial'], distro_specific=False, distro_nonspecific=True, temp_sstate_location=True)
-
- @testcase(1377)
- def test_cleansstate_task_distro_specific(self):
- targetarch = get_bb_var('TUNE_ARCH')
- self.run_test_cleansstate_task(['binutils-cross-'+ targetarch, 'binutils-native', 'glibc-initial'], distro_specific=True, distro_nonspecific=False, temp_sstate_location=True)
-
-
- # Test rebuilding of distro-specific sstate files
- def run_test_rebuild_distro_specific_sstate(self, targets, temp_sstate_location=True):
- self.config_sstate(temp_sstate_location)
-
- bitbake(['-ccleansstate'] + targets)
-
- bitbake(targets)
- results = self.search_sstate('|'.join(map(str, [s + '.*?\.tgz$' for s in targets])), distro_specific=False, distro_nonspecific=True)
- filtered_results = []
- for r in results:
- if r.endswith(("_populate_lic.tgz", "_populate_lic.tgz.siginfo")):
- continue
- filtered_results.append(r)
- self.assertTrue(filtered_results == [], msg="Found distro non-specific sstate for: %s (%s)" % (', '.join(map(str, targets)), str(filtered_results)))
- file_tracker_1 = self.search_sstate('|'.join(map(str, [s + '.*?\.tgz$' for s in targets])), distro_specific=True, distro_nonspecific=False)
- self.assertTrue(len(file_tracker_1) >= len(targets), msg = "Not all sstate files ware created for: %s" % ', '.join(map(str, targets)))
-
- self.track_for_cleanup(self.distro_specific_sstate + "_old")
- shutil.copytree(self.distro_specific_sstate, self.distro_specific_sstate + "_old")
- shutil.rmtree(self.distro_specific_sstate)
-
- bitbake(['-cclean'] + targets)
- bitbake(targets)
- file_tracker_2 = self.search_sstate('|'.join(map(str, [s + '.*?\.tgz$' for s in targets])), distro_specific=True, distro_nonspecific=False)
- self.assertTrue(len(file_tracker_2) >= len(targets), msg = "Not all sstate files ware created for: %s" % ', '.join(map(str, targets)))
-
- not_recreated = [x for x in file_tracker_1 if x not in file_tracker_2]
- self.assertTrue(not_recreated == [], msg="The following sstate files ware not recreated: %s" % ', '.join(map(str, not_recreated)))
-
- created_once = [x for x in file_tracker_2 if x not in file_tracker_1]
- self.assertTrue(created_once == [], msg="The following sstate files ware created only in the second run: %s" % ', '.join(map(str, created_once)))
-
- @testcase(175)
- def test_rebuild_distro_specific_sstate_cross_native_targets(self):
- targetarch = get_bb_var('TUNE_ARCH')
- self.run_test_rebuild_distro_specific_sstate(['binutils-cross-' + targetarch, 'binutils-native'], temp_sstate_location=True)
-
- @testcase(1372)
- def test_rebuild_distro_specific_sstate_cross_target(self):
- targetarch = get_bb_var('TUNE_ARCH')
- self.run_test_rebuild_distro_specific_sstate(['binutils-cross-' + targetarch], temp_sstate_location=True)
-
- @testcase(1373)
- def test_rebuild_distro_specific_sstate_native_target(self):
- self.run_test_rebuild_distro_specific_sstate(['binutils-native'], temp_sstate_location=True)
-
-
- # Test the sstate-cache-management script. Each element in the global_config list is used with the corresponding element in the target_config list
- # global_config elements are expected to not generate any sstate files that would be removed by sstate-cache-management.sh (such as changing the value of MACHINE)
- def run_test_sstate_cache_management_script(self, target, global_config=[''], target_config=[''], ignore_patterns=[]):
- self.assertTrue(global_config)
- self.assertTrue(target_config)
- self.assertTrue(len(global_config) == len(target_config), msg='Lists global_config and target_config should have the same number of elements')
- self.config_sstate(temp_sstate_location=True, add_local_mirrors=[self.sstate_path])
-
- # If buildhistory is enabled, we need to disable version-going-backwards QA checks for this test. It may report errors otherwise.
- if ('buildhistory' in get_bb_var('USER_CLASSES')) or ('buildhistory' in get_bb_var('INHERIT')):
- remove_errors_config = 'ERROR_QA_remove = "version-going-backwards"'
- self.append_config(remove_errors_config)
-
- # For not this only checks if random sstate tasks are handled correctly as a group.
- # In the future we should add control over what tasks we check for.
-
- sstate_archs_list = []
- expected_remaining_sstate = []
- for idx in range(len(target_config)):
- self.append_config(global_config[idx])
- self.append_recipeinc(target, target_config[idx])
- sstate_arch = get_bb_var('SSTATE_PKGARCH', target)
- if not sstate_arch in sstate_archs_list:
- sstate_archs_list.append(sstate_arch)
- if target_config[idx] == target_config[-1]:
- target_sstate_before_build = self.search_sstate(target + '.*?\.tgz$')
- bitbake("-cclean %s" % target)
- result = bitbake(target, ignore_status=True)
- if target_config[idx] == target_config[-1]:
- target_sstate_after_build = self.search_sstate(target + '.*?\.tgz$')
- expected_remaining_sstate += [x for x in target_sstate_after_build if x not in target_sstate_before_build if not any(pattern in x for pattern in ignore_patterns)]
- self.remove_config(global_config[idx])
- self.remove_recipeinc(target, target_config[idx])
- self.assertEqual(result.status, 0, msg = "build of %s failed with %s" % (target, result.output))
-
- runCmd("sstate-cache-management.sh -y --cache-dir=%s --remove-duplicated --extra-archs=%s" % (self.sstate_path, ','.join(map(str, sstate_archs_list))))
- actual_remaining_sstate = [x for x in self.search_sstate(target + '.*?\.tgz$') if not any(pattern in x for pattern in ignore_patterns)]
-
- actual_not_expected = [x for x in actual_remaining_sstate if x not in expected_remaining_sstate]
- self.assertFalse(actual_not_expected, msg="Files should have been removed but ware not: %s" % ', '.join(map(str, actual_not_expected)))
- expected_not_actual = [x for x in expected_remaining_sstate if x not in actual_remaining_sstate]
- self.assertFalse(expected_not_actual, msg="Extra files ware removed: %s" ', '.join(map(str, expected_not_actual)))
-
- @testcase(973)
- def test_sstate_cache_management_script_using_pr_1(self):
- global_config = []
- target_config = []
- global_config.append('')
- target_config.append('PR = "0"')
- self.run_test_sstate_cache_management_script('m4', global_config, target_config, ignore_patterns=['populate_lic'])
-
- @testcase(978)
- def test_sstate_cache_management_script_using_pr_2(self):
- global_config = []
- target_config = []
- global_config.append('')
- target_config.append('PR = "0"')
- global_config.append('')
- target_config.append('PR = "1"')
- self.run_test_sstate_cache_management_script('m4', global_config, target_config, ignore_patterns=['populate_lic'])
-
- @testcase(979)
- def test_sstate_cache_management_script_using_pr_3(self):
- global_config = []
- target_config = []
- global_config.append('MACHINE = "qemux86-64"')
- target_config.append('PR = "0"')
- global_config.append(global_config[0])
- target_config.append('PR = "1"')
- global_config.append('MACHINE = "qemux86"')
- target_config.append('PR = "1"')
- self.run_test_sstate_cache_management_script('m4', global_config, target_config, ignore_patterns=['populate_lic'])
-
- @testcase(974)
- def test_sstate_cache_management_script_using_machine(self):
- global_config = []
- target_config = []
- global_config.append('MACHINE = "qemux86-64"')
- target_config.append('')
- global_config.append('MACHINE = "qemux86"')
- target_config.append('')
- self.run_test_sstate_cache_management_script('m4', global_config, target_config, ignore_patterns=['populate_lic'])
-
- @testcase(1270)
- def test_sstate_32_64_same_hash(self):
- """
- The sstate checksums for both native and target should not vary whether
- they're built on a 32 or 64 bit system. Rather than requiring two different
- build machines and running a builds, override the variables calling uname()
- manually and check using bitbake -S.
- """
-
- topdir = get_bb_var('TOPDIR')
- targetvendor = get_bb_var('TARGET_VENDOR')
- self.write_config("""
-MACHINE = "qemux86"
-TMPDIR = "${TOPDIR}/tmp-sstatesamehash"
-BUILD_ARCH = "x86_64"
-BUILD_OS = "linux"
-SDKMACHINE = "x86_64"
-""")
- self.track_for_cleanup(topdir + "/tmp-sstatesamehash")
- bitbake("core-image-sato -S none")
- self.write_config("""
-MACHINE = "qemux86"
-TMPDIR = "${TOPDIR}/tmp-sstatesamehash2"
-BUILD_ARCH = "i686"
-BUILD_OS = "linux"
-SDKMACHINE = "i686"
-""")
- self.track_for_cleanup(topdir + "/tmp-sstatesamehash2")
- bitbake("core-image-sato -S none")
-
- def get_files(d):
- f = []
- for root, dirs, files in os.walk(d):
- if "core-image-sato" in root:
- # SDKMACHINE changing will change
- # do_rootfs/do_testimage/do_build stamps of images which
- # is safe to ignore.
- continue
- f.extend(os.path.join(root, name) for name in files)
- return f
- files1 = get_files(topdir + "/tmp-sstatesamehash/stamps/")
- files2 = get_files(topdir + "/tmp-sstatesamehash2/stamps/")
- files2 = [x.replace("tmp-sstatesamehash2", "tmp-sstatesamehash").replace("i686-linux", "x86_64-linux").replace("i686" + targetvendor + "-linux", "x86_64" + targetvendor + "-linux", ) for x in files2]
- self.maxDiff = None
- self.assertCountEqual(files1, files2)
-
-
- @testcase(1271)
- def test_sstate_nativelsbstring_same_hash(self):
- """
- The sstate checksums should be independent of whichever NATIVELSBSTRING is
- detected. Rather than requiring two different build machines and running
- builds, override the variables manually and check using bitbake -S.
- """
-
- topdir = get_bb_var('TOPDIR')
- self.write_config("""
-TMPDIR = \"${TOPDIR}/tmp-sstatesamehash\"
-NATIVELSBSTRING = \"DistroA\"
-""")
- self.track_for_cleanup(topdir + "/tmp-sstatesamehash")
- bitbake("core-image-sato -S none")
- self.write_config("""
-TMPDIR = \"${TOPDIR}/tmp-sstatesamehash2\"
-NATIVELSBSTRING = \"DistroB\"
-""")
- self.track_for_cleanup(topdir + "/tmp-sstatesamehash2")
- bitbake("core-image-sato -S none")
-
- def get_files(d):
- f = []
- for root, dirs, files in os.walk(d):
- f.extend(os.path.join(root, name) for name in files)
- return f
- files1 = get_files(topdir + "/tmp-sstatesamehash/stamps/")
- files2 = get_files(topdir + "/tmp-sstatesamehash2/stamps/")
- files2 = [x.replace("tmp-sstatesamehash2", "tmp-sstatesamehash") for x in files2]
- self.maxDiff = None
- self.assertCountEqual(files1, files2)
-
- @testcase(1368)
- def test_sstate_allarch_samesigs(self):
- """
- The sstate checksums of allarch packages should be independent of whichever
- MACHINE is set. Check this using bitbake -S.
- Also, rather than duplicate the test, check nativesdk stamps are the same between
- the two MACHINE values.
- """
-
- topdir = get_bb_var('TOPDIR')
- targetos = get_bb_var('TARGET_OS')
- targetvendor = get_bb_var('TARGET_VENDOR')
- self.write_config("""
-TMPDIR = \"${TOPDIR}/tmp-sstatesamehash\"
-MACHINE = \"qemux86\"
-""")
- self.track_for_cleanup(topdir + "/tmp-sstatesamehash")
- bitbake("world meta-toolchain -S none")
- self.write_config("""
-TMPDIR = \"${TOPDIR}/tmp-sstatesamehash2\"
-MACHINE = \"qemuarm\"
-""")
- self.track_for_cleanup(topdir + "/tmp-sstatesamehash2")
- bitbake("world meta-toolchain -S none")
-
- def get_files(d):
- f = {}
- for root, dirs, files in os.walk(d):
- for name in files:
- if "meta-environment" in root or "cross-canadian" in root:
- continue
- if "do_build" not in name:
- # 1.4.1+gitAUTOINC+302fca9f4c-r0.do_package_write_ipk.sigdata.f3a2a38697da743f0dbed8b56aafcf79
- (_, task, _, shash) = name.rsplit(".", 3)
- f[os.path.join(os.path.basename(root), task)] = shash
- return f
- files1 = get_files(topdir + "/tmp-sstatesamehash/stamps/all" + targetvendor + "-" + targetos)
- files2 = get_files(topdir + "/tmp-sstatesamehash2/stamps/all" + targetvendor + "-" + targetos)
- self.maxDiff = None
- self.assertEqual(files1, files2)
-
- nativesdkdir = os.path.basename(glob.glob(topdir + "/tmp-sstatesamehash/stamps/*-nativesdk*-linux")[0])
-
- files1 = get_files(topdir + "/tmp-sstatesamehash/stamps/" + nativesdkdir)
- files2 = get_files(topdir + "/tmp-sstatesamehash2/stamps/" + nativesdkdir)
- self.maxDiff = None
- self.assertEqual(files1, files2)
-
- @testcase(1369)
- def test_sstate_sametune_samesigs(self):
- """
- The sstate checksums of two identical machines (using the same tune) should be the
- same, apart from changes within the machine specific stamps directory. We use the
- qemux86copy machine to test this. Also include multilibs in the test.
- """
-
- topdir = get_bb_var('TOPDIR')
- targetos = get_bb_var('TARGET_OS')
- targetvendor = get_bb_var('TARGET_VENDOR')
- self.write_config("""
-TMPDIR = \"${TOPDIR}/tmp-sstatesamehash\"
-MACHINE = \"qemux86\"
-require conf/multilib.conf
-MULTILIBS = "multilib:lib32"
-DEFAULTTUNE_virtclass-multilib-lib32 = "x86"
-""")
- self.track_for_cleanup(topdir + "/tmp-sstatesamehash")
- bitbake("world meta-toolchain -S none")
- self.write_config("""
-TMPDIR = \"${TOPDIR}/tmp-sstatesamehash2\"
-MACHINE = \"qemux86copy\"
-require conf/multilib.conf
-MULTILIBS = "multilib:lib32"
-DEFAULTTUNE_virtclass-multilib-lib32 = "x86"
-""")
- self.track_for_cleanup(topdir + "/tmp-sstatesamehash2")
- bitbake("world meta-toolchain -S none")
-
- def get_files(d):
- f = []
- for root, dirs, files in os.walk(d):
- for name in files:
- if "meta-environment" in root or "cross-canadian" in root:
- continue
- if "qemux86copy-" in root or "qemux86-" in root:
- continue
- if "do_build" not in name and "do_populate_sdk" not in name:
- f.append(os.path.join(root, name))
- return f
- files1 = get_files(topdir + "/tmp-sstatesamehash/stamps")
- files2 = get_files(topdir + "/tmp-sstatesamehash2/stamps")
- files2 = [x.replace("tmp-sstatesamehash2", "tmp-sstatesamehash") for x in files2]
- self.maxDiff = None
- self.assertCountEqual(files1, files2)
-
-
- def test_sstate_noop_samesigs(self):
- """
- The sstate checksums of two builds with these variables changed or
- classes inherits should be the same.
- """
-
- topdir = get_bb_var('TOPDIR')
- targetvendor = get_bb_var('TARGET_VENDOR')
- self.write_config("""
-TMPDIR = "${TOPDIR}/tmp-sstatesamehash"
-BB_NUMBER_THREADS = "1"
-PARALLEL_MAKE = "-j 1"
-DL_DIR = "${TOPDIR}/download1"
-TIME = "111111"
-DATE = "20161111"
-INHERIT_remove = "buildstats-summary buildhistory uninative"
-http_proxy = ""
-""")
- self.track_for_cleanup(topdir + "/tmp-sstatesamehash")
- self.track_for_cleanup(topdir + "/download1")
- bitbake("world meta-toolchain -S none")
- self.write_config("""
-TMPDIR = "${TOPDIR}/tmp-sstatesamehash2"
-BB_NUMBER_THREADS = "2"
-PARALLEL_MAKE = "-j 2"
-DL_DIR = "${TOPDIR}/download2"
-TIME = "222222"
-DATE = "20161212"
-# Always remove uninative as we're changing proxies
-INHERIT_remove = "uninative"
-INHERIT += "buildstats-summary buildhistory"
-http_proxy = "http://example.com/"
-""")
- self.track_for_cleanup(topdir + "/tmp-sstatesamehash2")
- self.track_for_cleanup(topdir + "/download2")
- bitbake("world meta-toolchain -S none")
-
- def get_files(d):
- f = {}
- for root, dirs, files in os.walk(d):
- for name in files:
- name, shash = name.rsplit('.', 1)
- # Extract just the machine and recipe name
- base = os.sep.join(root.rsplit(os.sep, 2)[-2:] + [name])
- f[base] = shash
- return f
- files1 = get_files(topdir + "/tmp-sstatesamehash/stamps/")
- files2 = get_files(topdir + "/tmp-sstatesamehash2/stamps/")
- # Remove items that are identical in both sets
- for k,v in files1.items() & files2.items():
- del files1[k]
- del files2[k]
- if not files1 and not files2:
- # No changes, so we're done
- return
-
- for k in files1.keys() | files2.keys():
- if k in files1 and k in files2:
- print("%s differs:" % k)
- print(subprocess.check_output(("bitbake-diffsigs",
- topdir + "/tmp-sstatesamehash/stamps/" + k + "." + files1[k],
- topdir + "/tmp-sstatesamehash2/stamps/" + k + "." + files2[k])))
- elif k in files1 and k not in files2:
- print("%s in files1" % k)
- elif k not in files1 and k in files2:
- print("%s in files2" % k)
- else:
- assert "shouldn't reach here"
- self.fail("sstate hashes not identical.")
diff --git a/meta/lib/oeqa/selftest/testexport.py b/meta/lib/oeqa/selftest/testexport.py
deleted file mode 100644
index 5823b1303c..0000000000
--- a/meta/lib/oeqa/selftest/testexport.py
+++ /dev/null
@@ -1,44 +0,0 @@
-from oeqa.selftest.base import oeSelfTest
-from oeqa.utils.commands import runCmd, bitbake, get_bb_var, runqemu
-from oeqa.utils.decorators import testcase
-import os
-
-class TestExport(oeSelfTest):
-
- def test_testexport_basic(self):
- """
- Summary: Check basic testexport functionality with only ping test enabled.
- Expected: 1. testexport directory must be created.
- 2. runexported.py must run without any error/exception.
- 3. ping test must succeed.
- Product: oe-core
- Author: Mariano Lopez <mariano.lopez@intel.com>
- """
-
- features = 'INHERIT += "testexport"\n'
- # These aren't the actual IP addresses but testexport class needs something defined
- features += 'TEST_SERVER_IP = "192.168.7.1"\n'
- features += 'TEST_TARGET_IP = "192.168.7.1"\n'
- features += 'TEST_SUITES = "ping"\n'
- self.write_config(features)
-
- # Build tesexport for core-image-minimal
- bitbake('core-image-minimal')
- bitbake('-c testexport core-image-minimal')
-
- # Verify if TEST_EXPORT_DIR was created
- testexport_dir = get_bb_var('TEST_EXPORT_DIR', 'core-image-minimal')
- isdir = os.path.isdir(testexport_dir)
- self.assertEqual(True, isdir, 'Failed to create testexport dir: %s' % testexport_dir)
-
- with runqemu('core-image-minimal') as qemu:
- # Attempt to run runexported.py to perform ping test
- runexported_path = os.path.join(testexport_dir, "runexported.py")
- testdata_path = os.path.join(testexport_dir, "testdata.json")
- cmd = "%s -t %s -s %s %s" % (runexported_path, qemu.ip, qemu.server_ip, testdata_path)
- result = runCmd(cmd)
- self.assertEqual(0, result.status, 'runexported.py returned a non 0 status')
-
- # Verify ping test was succesful
- failure = True if 'FAIL' in result.output else False
- self.assertNotEqual(True, failure, 'ping test failed')
diff --git a/meta/lib/oeqa/selftest/wic.py b/meta/lib/oeqa/selftest/wic.py
deleted file mode 100644
index e550785fcf..0000000000
--- a/meta/lib/oeqa/selftest/wic.py
+++ /dev/null
@@ -1,286 +0,0 @@
-#!/usr/bin/env python
-# ex:ts=4:sw=4:sts=4:et
-# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
-#
-# Copyright (c) 2015, Intel Corporation.
-# All rights reserved.
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 2 as
-# published by the Free Software Foundation.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along
-# with this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# AUTHORS
-# Ed Bartosh <ed.bartosh@linux.intel.com>
-
-"""Test cases for wic."""
-
-import os
-
-from glob import glob
-from shutil import rmtree
-
-from oeqa.selftest.base import oeSelfTest
-from oeqa.utils.commands import runCmd, bitbake, get_bb_var, runqemu
-from oeqa.utils.decorators import testcase
-
-
-class Wic(oeSelfTest):
- """Wic test class."""
-
- resultdir = "/var/tmp/wic/build/"
- image_is_ready = False
-
- def setUpLocal(self):
- """This code is executed before each test method."""
- self.write_config('IMAGE_FSTYPES += " hddimg"\n'
- 'MACHINE_FEATURES_append = " efi"\n')
-
- # Do this here instead of in setUpClass as the base setUp does some
- # clean up which can result in the native tools built earlier in
- # setUpClass being unavailable.
- if not Wic.image_is_ready:
- bitbake('syslinux syslinux-native parted-native gptfdisk-native '
- 'dosfstools-native mtools-native bmap-tools-native')
- bitbake('core-image-minimal')
- Wic.image_is_ready = True
-
- rmtree(self.resultdir, ignore_errors=True)
-
- @testcase(1208)
- def test_help(self):
- """Test wic --help"""
- self.assertEqual(0, runCmd('wic --help').status)
-
- @testcase(1209)
- def test_createhelp(self):
- """Test wic create --help"""
- self.assertEqual(0, runCmd('wic create --help').status)
-
- @testcase(1210)
- def test_listhelp(self):
- """Test wic list --help"""
- self.assertEqual(0, runCmd('wic list --help').status)
-
- @testcase(1211)
- def test_build_image_name(self):
- """Test wic create directdisk --image-name core-image-minimal"""
- self.assertEqual(0, runCmd("wic create directdisk "
- "--image-name core-image-minimal").status)
- self.assertEqual(1, len(glob(self.resultdir + "directdisk-*.direct")))
-
- @testcase(1212)
- def test_build_artifacts(self):
- """Test wic create directdisk providing all artifacts."""
- bbvars = dict((var.lower(), get_bb_var(var, 'core-image-minimal')) \
- for var in ('STAGING_DATADIR', 'DEPLOY_DIR_IMAGE',
- 'STAGING_DIR_NATIVE', 'IMAGE_ROOTFS'))
- status = runCmd("wic create directdisk "
- "-b %(staging_datadir)s "
- "-k %(deploy_dir_image)s "
- "-n %(staging_dir_native)s "
- "-r %(image_rootfs)s" % bbvars).status
- self.assertEqual(0, status)
- self.assertEqual(1, len(glob(self.resultdir + "directdisk-*.direct")))
-
- @testcase(1157)
- def test_gpt_image(self):
- """Test creation of core-image-minimal with gpt table and UUID boot"""
- self.assertEqual(0, runCmd("wic create directdisk-gpt "
- "--image-name core-image-minimal").status)
- self.assertEqual(1, len(glob(self.resultdir + "directdisk-*.direct")))
-
- @testcase(1213)
- def test_unsupported_subcommand(self):
- """Test unsupported subcommand"""
- self.assertEqual(1, runCmd('wic unsupported',
- ignore_status=True).status)
-
- @testcase(1214)
- def test_no_command(self):
- """Test wic without command"""
- self.assertEqual(1, runCmd('wic', ignore_status=True).status)
-
- @testcase(1215)
- def test_help_overview(self):
- """Test wic help overview"""
- self.assertEqual(0, runCmd('wic help overview').status)
-
- @testcase(1216)
- def test_help_plugins(self):
- """Test wic help plugins"""
- self.assertEqual(0, runCmd('wic help plugins').status)
-
- @testcase(1217)
- def test_help_kickstart(self):
- """Test wic help kickstart"""
- self.assertEqual(0, runCmd('wic help kickstart').status)
-
- @testcase(1264)
- def test_compress_gzip(self):
- """Test compressing an image with gzip"""
- self.assertEqual(0, runCmd("wic create directdisk "
- "--image-name core-image-minimal "
- "-c gzip").status)
- self.assertEqual(1, len(glob(self.resultdir + \
- "directdisk-*.direct.gz")))
-
- @testcase(1265)
- def test_compress_bzip2(self):
- """Test compressing an image with bzip2"""
- self.assertEqual(0, runCmd("wic create directdisk "
- "--image-name core-image-minimal "
- "-c bzip2").status)
- self.assertEqual(1, len(glob(self.resultdir + \
- "directdisk-*.direct.bz2")))
-
- @testcase(1266)
- def test_compress_xz(self):
- """Test compressing an image with xz"""
- self.assertEqual(0, runCmd("wic create directdisk "
- "--image-name core-image-minimal "
- "-c xz").status)
- self.assertEqual(1, len(glob(self.resultdir + \
- "directdisk-*.direct.xz")))
-
- @testcase(1267)
- def test_wrong_compressor(self):
- """Test how wic breaks if wrong compressor is provided"""
- self.assertEqual(2, runCmd("wic create directdisk "
- "--image-name core-image-minimal "
- "-c wrong", ignore_status=True).status)
-
- @testcase(1268)
- def test_rootfs_indirect_recipes(self):
- """Test usage of rootfs plugin with rootfs recipes"""
- wks = "directdisk-multi-rootfs"
- self.assertEqual(0, runCmd("wic create %s "
- "--image-name core-image-minimal "
- "--rootfs rootfs1=core-image-minimal "
- "--rootfs rootfs2=core-image-minimal" \
- % wks).status)
- self.assertEqual(1, len(glob(self.resultdir + "%s*.direct" % wks)))
-
- @testcase(1269)
- def test_rootfs_artifacts(self):
- """Test usage of rootfs plugin with rootfs paths"""
- bbvars = dict((var.lower(), get_bb_var(var, 'core-image-minimal')) \
- for var in ('STAGING_DATADIR', 'DEPLOY_DIR_IMAGE',
- 'STAGING_DIR_NATIVE', 'IMAGE_ROOTFS'))
- bbvars['wks'] = "directdisk-multi-rootfs"
- status = runCmd("wic create %(wks)s "
- "-b %(staging_datadir)s "
- "-k %(deploy_dir_image)s "
- "-n %(staging_dir_native)s "
- "--rootfs-dir rootfs1=%(image_rootfs)s "
- "--rootfs-dir rootfs2=%(image_rootfs)s" \
- % bbvars).status
- self.assertEqual(0, status)
- self.assertEqual(1, len(glob(self.resultdir + \
- "%(wks)s-*.direct" % bbvars)))
-
- @testcase(1346)
- def test_iso_image(self):
- """Test creation of hybrid iso image with legacy and EFI boot"""
- self.assertEqual(0, runCmd("wic create mkhybridiso "
- "--image-name core-image-minimal").status)
- self.assertEqual(1, len(glob(self.resultdir + "HYBRID_ISO_IMG-*.direct")))
- self.assertEqual(1, len(glob(self.resultdir + "HYBRID_ISO_IMG-*.iso")))
-
- @testcase(1347)
- def test_image_env(self):
- """Test generation of <image>.env files."""
- image = 'core-image-minimal'
- self.assertEqual(0, bitbake('%s -c do_rootfs_wicenv' % image).status)
- stdir = get_bb_var('STAGING_DIR_TARGET', image)
- imgdatadir = os.path.join(stdir, 'imgdata')
-
- basename = get_bb_var('IMAGE_BASENAME', image)
- self.assertEqual(basename, image)
- path = os.path.join(imgdatadir, basename) + '.env'
- self.assertTrue(os.path.isfile(path))
-
- wicvars = set(get_bb_var('WICVARS', image).split())
- # filter out optional variables
- wicvars = wicvars.difference(('HDDDIR', 'IMAGE_BOOT_FILES',
- 'INITRD', 'ISODIR'))
- with open(path) as envfile:
- content = dict(line.split("=", 1) for line in envfile)
- # test if variables used by wic present in the .env file
- for var in wicvars:
- self.assertTrue(var in content, "%s is not in .env file" % var)
- self.assertTrue(content[var])
-
- @testcase(1351)
- def test_wic_image_type(self):
- """Test building wic images by bitbake"""
- self.assertEqual(0, bitbake('wic-image-minimal').status)
-
- deploy_dir = get_bb_var('DEPLOY_DIR_IMAGE')
- machine = get_bb_var('MACHINE')
- prefix = os.path.join(deploy_dir, 'wic-image-minimal-%s.' % machine)
- # check if we have result image and manifests symlinks
- # pointing to existing files
- for suffix in ('wic', 'manifest'):
- path = prefix + suffix
- self.assertTrue(os.path.islink(path))
- self.assertTrue(os.path.isfile(os.path.realpath(path)))
-
- @testcase(1348)
- def test_qemux86_directdisk(self):
- """Test creation of qemux-86-directdisk image"""
- image = "qemux86-directdisk"
- self.assertEqual(0, runCmd("wic create %s -e core-image-minimal" \
- % image).status)
- self.assertEqual(1, len(glob(self.resultdir + "%s-*direct" % image)))
-
- @testcase(1349)
- def test_mkgummidisk(self):
- """Test creation of mkgummidisk image"""
- image = "mkgummidisk"
- self.assertEqual(0, runCmd("wic create %s -e core-image-minimal" \
- % image).status)
- self.assertEqual(1, len(glob(self.resultdir + "%s-*direct" % image)))
-
- @testcase(1350)
- def test_mkefidisk(self):
- """Test creation of mkefidisk image"""
- image = "mkefidisk"
- self.assertEqual(0, runCmd("wic create %s -e core-image-minimal" \
- % image).status)
- self.assertEqual(1, len(glob(self.resultdir + "%s-*direct" % image)))
-
- @testcase(1385)
- def test_directdisk_bootloader_config(self):
- """Test creation of directdisk-bootloader-config image"""
- image = "directdisk-bootloader-config"
- self.assertEqual(0, runCmd("wic create %s -e core-image-minimal" \
- % image).status)
- self.assertEqual(1, len(glob(self.resultdir + "%s-*direct" % image)))
-
- @testcase(1422)
- def test_qemu(self):
- """Test wic-image-minimal under qemu"""
- self.assertEqual(0, bitbake('wic-image-minimal').status)
-
- with runqemu('wic-image-minimal', ssh=False) as qemu:
- command = "mount |grep '^/dev/' | cut -f1,3 -d ' '"
- status, output = qemu.run_serial(command)
- self.assertEqual(1, status, 'Failed to run command "%s": %s' % (command, output))
- self.assertEqual(output, '/dev/root /\r\n/dev/vda3 /mnt')
-
- def test_bmap(self):
- """Test generation of .bmap file"""
- image = "directdisk"
- status = runCmd("wic create %s -e core-image-minimal --bmap" % image).status
- self.assertEqual(0, status)
- self.assertEqual(1, len(glob(self.resultdir + "%s-*direct" % image)))
- self.assertEqual(1, len(glob(self.resultdir + "%s-*direct.bmap" % image)))
diff --git a/meta/lib/oeqa/targetcontrol.py b/meta/lib/oeqa/targetcontrol.py
index d3b49b770a..1fdff82889 100644
--- a/meta/lib/oeqa/targetcontrol.py
+++ b/meta/lib/oeqa/targetcontrol.py
@@ -1,6 +1,8 @@
+#
# Copyright (C) 2013 Intel Corporation
#
-# Released under the MIT license (see COPYING.MIT)
+# SPDX-License-Identifier: MIT
+#
# This module is used by testimage.bbclass for setting up and controlling a target machine.
@@ -15,45 +17,22 @@ from oeqa.utils.sshcontrol import SSHControl
from oeqa.utils.qemurunner import QemuRunner
from oeqa.utils.qemutinyrunner import QemuTinyRunner
from oeqa.utils.dump import TargetDumper
+from oeqa.utils.dump import MonitorDumper
from oeqa.controllers.testtargetloader import TestTargetLoader
from abc import ABCMeta, abstractmethod
-def get_target_controller(d):
- testtarget = d.getVar("TEST_TARGET", True)
- # old, simple names
- if testtarget == "qemu":
- return QemuTarget(d)
- elif testtarget == "simpleremote":
- return SimpleRemoteTarget(d)
- else:
- # use the class name
- try:
- # is it a core class defined here?
- controller = getattr(sys.modules[__name__], testtarget)
- except AttributeError:
- # nope, perhaps a layer defined one
- try:
- bbpath = d.getVar("BBPATH", True).split(':')
- testtargetloader = TestTargetLoader()
- controller = testtargetloader.get_controller_module(testtarget, bbpath)
- except ImportError as e:
- bb.fatal("Failed to import {0} from available controller modules:\n{1}".format(testtarget,traceback.format_exc()))
- except AttributeError as e:
- bb.fatal("Invalid TEST_TARGET - " + str(e))
- return controller(d)
-
-
class BaseTarget(object, metaclass=ABCMeta):
supported_image_fstypes = []
- def __init__(self, d):
+ def __init__(self, d, logger):
self.connection = None
self.ip = None
self.server_ip = None
- self.datetime = d.getVar('DATETIME', True)
- self.testdir = d.getVar("TEST_LOG_DIR", True)
- self.pn = d.getVar("PN", True)
+ self.datetime = d.getVar('DATETIME')
+ self.testdir = d.getVar("TEST_LOG_DIR")
+ self.pn = d.getVar("PN")
+ self.logger = logger
@abstractmethod
def deploy(self):
@@ -63,10 +42,10 @@ class BaseTarget(object, metaclass=ABCMeta):
if os.path.islink(sshloglink):
os.unlink(sshloglink)
os.symlink(self.sshlog, sshloglink)
- bb.note("SSH log file: %s" % self.sshlog)
+ self.logger.info("SSH log file: %s" % self.sshlog)
@abstractmethod
- def start(self, params=None, ssh=True):
+ def start(self, params=None, ssh=True, extra_bootparams=None):
pass
@abstractmethod
@@ -80,7 +59,7 @@ class BaseTarget(object, metaclass=ABCMeta):
@classmethod
def match_image_fstype(self, d, image_fstypes=None):
if not image_fstypes:
- image_fstypes = d.getVar('IMAGE_FSTYPES', True).split(' ')
+ image_fstypes = d.getVar('IMAGE_FSTYPES').split(' ')
possible_image_fstypes = [fstype for fstype in self.supported_image_fstypes if fstype in image_fstypes]
if possible_image_fstypes:
return possible_image_fstypes[0]
@@ -113,69 +92,88 @@ class QemuTarget(BaseTarget):
supported_image_fstypes = ['ext3', 'ext4', 'cpio.gz', 'wic']
- def __init__(self, d):
+ def __init__(self, d, logger, image_fstype=None):
- super(QemuTarget, self).__init__(d)
+ import oe.types
- self.image_fstype = self.get_image_fstype(d)
+ super(QemuTarget, self).__init__(d, logger)
+
+ self.rootfs = ''
+ self.kernel = ''
+ self.image_fstype = ''
+
+ if d.getVar('FIND_ROOTFS') == '1':
+ self.image_fstype = image_fstype or self.get_image_fstype(d)
+ self.rootfs = os.path.join(d.getVar("DEPLOY_DIR_IMAGE"), d.getVar("IMAGE_LINK_NAME") + '.' + self.image_fstype)
+ self.kernel = os.path.join(d.getVar("DEPLOY_DIR_IMAGE"), d.getVar("KERNEL_IMAGETYPE", False) + '-' + d.getVar('MACHINE', False) + '.bin')
self.qemulog = os.path.join(self.testdir, "qemu_boot_log.%s" % self.datetime)
- self.origrootfs = os.path.join(d.getVar("DEPLOY_DIR_IMAGE", True), d.getVar("IMAGE_LINK_NAME", True) + '.' + self.image_fstype)
- self.rootfs = os.path.join(self.testdir, d.getVar("IMAGE_LINK_NAME", True) + '-testimage.' + self.image_fstype)
- self.kernel = os.path.join(d.getVar("DEPLOY_DIR_IMAGE", True), d.getVar("KERNEL_IMAGETYPE", False) + '-' + d.getVar('MACHINE', False) + '.bin')
- dump_target_cmds = d.getVar("testimage_dump_target", True)
- dump_host_cmds = d.getVar("testimage_dump_host", True)
- dump_dir = d.getVar("TESTIMAGE_DUMP_DIR", True)
+ dump_target_cmds = d.getVar("testimage_dump_target")
+ dump_host_cmds = d.getVar("testimage_dump_host")
+ dump_monitor_cmds = d.getVar("testimage_dump_monitor")
+ dump_dir = d.getVar("TESTIMAGE_DUMP_DIR")
+ if not dump_dir:
+ dump_dir = os.path.join(d.getVar('LOG_DIR'), 'runtime-hostdump')
+ use_kvm = oe.types.qemu_use_kvm(d.getVar('QEMU_USE_KVM'), d.getVar('TARGET_ARCH'))
# Log QemuRunner log output to a file
import oe.path
bb.utils.mkdirhier(self.testdir)
self.qemurunnerlog = os.path.join(self.testdir, 'qemurunner_log.%s' % self.datetime)
- logger = logging.getLogger('BitBake.QemuRunner')
- loggerhandler = logging.FileHandler(self.qemurunnerlog)
- loggerhandler.setFormatter(logging.Formatter("%(levelname)s: %(message)s"))
- logger.addHandler(loggerhandler)
+ self.loggerhandler = logging.FileHandler(self.qemurunnerlog)
+ self.loggerhandler.setFormatter(logging.Formatter("%(levelname)s: %(message)s"))
+ self.logger.addHandler(self.loggerhandler)
oe.path.symlink(os.path.basename(self.qemurunnerlog), os.path.join(self.testdir, 'qemurunner_log'), force=True)
- if d.getVar("DISTRO", True) == "poky-tiny":
- self.runner = QemuTinyRunner(machine=d.getVar("MACHINE", True),
+ if d.getVar("DISTRO") == "poky-tiny":
+ self.runner = QemuTinyRunner(machine=d.getVar("MACHINE"),
rootfs=self.rootfs,
- tmpdir = d.getVar("TMPDIR", True),
- deploy_dir_image = d.getVar("DEPLOY_DIR_IMAGE", True),
- display = d.getVar("BB_ORIGENV", False).getVar("DISPLAY", True),
+ tmpdir = d.getVar("TMPDIR"),
+ deploy_dir_image = d.getVar("DEPLOY_DIR_IMAGE"),
+ display = d.getVar("BB_ORIGENV", False).getVar("DISPLAY"),
logfile = self.qemulog,
kernel = self.kernel,
- boottime = int(d.getVar("TEST_QEMUBOOT_TIMEOUT", True)))
+ boottime = int(d.getVar("TEST_QEMUBOOT_TIMEOUT")),
+ tmpfsdir = d.getVar("RUNQEMU_TMPFS_DIR"),
+ logger = logger)
else:
- self.runner = QemuRunner(machine=d.getVar("MACHINE", True),
+ self.runner = QemuRunner(machine=d.getVar("MACHINE"),
rootfs=self.rootfs,
- tmpdir = d.getVar("TMPDIR", True),
- deploy_dir_image = d.getVar("DEPLOY_DIR_IMAGE", True),
- display = d.getVar("BB_ORIGENV", False).getVar("DISPLAY", True),
+ tmpdir = d.getVar("TMPDIR"),
+ deploy_dir_image = d.getVar("DEPLOY_DIR_IMAGE"),
+ display = d.getVar("BB_ORIGENV", False).getVar("DISPLAY"),
logfile = self.qemulog,
- boottime = int(d.getVar("TEST_QEMUBOOT_TIMEOUT", True)),
+ boottime = int(d.getVar("TEST_QEMUBOOT_TIMEOUT")),
+ use_kvm = use_kvm,
dump_dir = dump_dir,
- dump_host_cmds = d.getVar("testimage_dump_host", True))
+ dump_host_cmds = d.getVar("testimage_dump_host"),
+ logger = logger,
+ tmpfsdir = d.getVar("RUNQEMU_TMPFS_DIR"),
+ serial_ports = len(d.getVar("SERIAL_CONSOLES").split()))
self.target_dumper = TargetDumper(dump_target_cmds, dump_dir, self.runner)
+ self.monitor_dumper = MonitorDumper(dump_monitor_cmds, dump_dir, self.runner)
+ if (self.monitor_dumper):
+ self.monitor_dumper.create_dir("qmp")
def deploy(self):
- try:
- bb.utils.mkdirhier(self.testdir)
- shutil.copyfile(self.origrootfs, self.rootfs)
- except Exception as e:
- bb.fatal("Error copying rootfs: %s" % e)
+ bb.utils.mkdirhier(self.testdir)
qemuloglink = os.path.join(self.testdir, "qemu_boot_log")
if os.path.islink(qemuloglink):
os.unlink(qemuloglink)
os.symlink(self.qemulog, qemuloglink)
- bb.note("rootfs file: %s" % self.rootfs)
- bb.note("Qemu log file: %s" % self.qemulog)
+ self.logger.info("rootfs file: %s" % self.rootfs)
+ self.logger.info("Qemu log file: %s" % self.qemulog)
super(QemuTarget, self).deploy()
- def start(self, params=None, ssh=True, extra_bootparams=None):
- if self.runner.start(params, get_ip=ssh, extra_bootparams=extra_bootparams):
+ def start(self, params=None, ssh=True, extra_bootparams='', runqemuparams='', launch_cmd='', discard_writes=True):
+ if launch_cmd:
+ start = self.runner.launch(get_ip=ssh, launch_cmd=launch_cmd, qemuparams=params)
+ else:
+ start = self.runner.start(params, get_ip=ssh, extra_bootparams=extra_bootparams, runqemuparams=runqemuparams, discard_writes=discard_writes)
+
+ if start:
if ssh:
self.ip = self.runner.ip
self.server_ip = self.runner.server_ip
@@ -185,13 +183,18 @@ class QemuTarget(BaseTarget):
if os.path.exists(self.qemulog):
with open(self.qemulog, 'r') as f:
bb.error("Qemu log output from %s:\n%s" % (self.qemulog, f.read()))
- raise bb.build.FuncFailed("%s - FAILED to start qemu - check the task log and the boot log" % self.pn)
+ raise RuntimeError("%s - FAILED to start qemu - check the task log and the boot log" % self.pn)
def check(self):
return self.runner.is_alive()
def stop(self):
- self.runner.stop()
+ try:
+ self.runner.stop()
+ except:
+ pass
+ self.logger.removeHandler(self.loggerhandler)
+ self.loggerhandler.close()
self.connection = None
self.ip = None
self.server_ip = None
@@ -202,35 +205,35 @@ class QemuTarget(BaseTarget):
self.server_ip = self.runner.server_ip
self.connection = SSHControl(ip=self.ip, logfile=self.sshlog)
else:
- raise bb.build.FuncFailed("%s - FAILED to re-start qemu - check the task log and the boot log" % self.pn)
+ raise RuntimError("%s - FAILED to re-start qemu - check the task log and the boot log" % self.pn)
- def run_serial(self, command):
- return self.runner.run_serial(command)
+ def run_serial(self, command, timeout=60):
+ return self.runner.run_serial(command, timeout=timeout)
class SimpleRemoteTarget(BaseTarget):
def __init__(self, d):
super(SimpleRemoteTarget, self).__init__(d)
- addr = d.getVar("TEST_TARGET_IP", True) or bb.fatal('Please set TEST_TARGET_IP with the IP address of the machine you want to run the tests on.')
+ addr = d.getVar("TEST_TARGET_IP") or bb.fatal('Please set TEST_TARGET_IP with the IP address of the machine you want to run the tests on.')
self.ip = addr.split(":")[0]
try:
self.port = addr.split(":")[1]
except IndexError:
self.port = None
- bb.note("Target IP: %s" % self.ip)
- self.server_ip = d.getVar("TEST_SERVER_IP", True)
+ self.logger.info("Target IP: %s" % self.ip)
+ self.server_ip = d.getVar("TEST_SERVER_IP")
if not self.server_ip:
try:
self.server_ip = subprocess.check_output(['ip', 'route', 'get', self.ip ]).split("\n")[0].split()[-1]
except Exception as e:
bb.fatal("Failed to determine the host IP address (alternatively you can set TEST_SERVER_IP with the IP address of this machine): %s" % e)
- bb.note("Server IP: %s" % self.server_ip)
+ self.logger.info("Server IP: %s" % self.server_ip)
def deploy(self):
super(SimpleRemoteTarget, self).deploy()
- def start(self, params=None, ssh=True):
+ def start(self, params=None, ssh=True, extra_bootparams=None):
if ssh:
self.connection = SSHControl(self.ip, logfile=self.sshlog, port=self.port)
diff --git a/meta/lib/oeqa/utils/__init__.py b/meta/lib/oeqa/utils/__init__.py
index 8f706f3637..fbc7f7d525 100644
--- a/meta/lib/oeqa/utils/__init__.py
+++ b/meta/lib/oeqa/utils/__init__.py
@@ -1,8 +1,12 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
# Enable other layers to have modules in the same named directory
from pkgutil import extend_path
__path__ = extend_path(__path__, __name__)
-
# Borrowed from CalledProcessError
class CommandError(Exception):
@@ -36,3 +40,53 @@ def avoid_paths_in_environ(paths):
new_path = new_path[:-1]
return new_path
+
+def make_logger_bitbake_compatible(logger):
+ import logging
+
+ """
+ We need to raise the log level of the info output so unittest
+ messages are visible on the console.
+ """
+ def _bitbake_log_info(msg, *args, **kwargs):
+ logger.log(logging.INFO + 1, msg, *args, **kwargs)
+
+ logger.info = _bitbake_log_info
+
+ return logger
+
+def load_test_components(logger, executor):
+ import sys
+ import os
+ import importlib
+
+ from oeqa.core.context import OETestContextExecutor
+
+ components = {}
+
+ for path in sys.path:
+ base_dir = os.path.join(path, 'oeqa')
+ if os.path.exists(base_dir) and os.path.isdir(base_dir):
+ for file in os.listdir(base_dir):
+ comp_name = file
+ comp_context = os.path.join(base_dir, file, 'context.py')
+ if os.path.exists(comp_context):
+ comp_plugin = importlib.import_module('oeqa.%s.%s' % \
+ (comp_name, 'context'))
+ try:
+ if not issubclass(comp_plugin._executor_class,
+ OETestContextExecutor):
+ raise TypeError("Component %s in %s, _executor_class "\
+ "isn't derived from OETestContextExecutor."\
+ % (comp_name, comp_context))
+
+ if comp_plugin._executor_class._script_executor \
+ != executor:
+ continue
+
+ components[comp_name] = comp_plugin._executor_class()
+ except AttributeError:
+ raise AttributeError("Component %s in %s don't have "\
+ "_executor_class defined." % (comp_name, comp_context))
+
+ return components
diff --git a/meta/lib/oeqa/utils/buildproject.py b/meta/lib/oeqa/utils/buildproject.py
new file mode 100644
index 0000000000..dfb9661868
--- /dev/null
+++ b/meta/lib/oeqa/utils/buildproject.py
@@ -0,0 +1,66 @@
+#
+# Copyright (C) 2013-2016 Intel Corporation
+#
+# SPDX-License-Identifier: MIT
+#
+
+# Provides a class for automating build tests for projects
+
+import os
+import re
+import subprocess
+import shutil
+import tempfile
+
+from abc import ABCMeta, abstractmethod
+
+class BuildProject(metaclass=ABCMeta):
+ def __init__(self, uri, foldername=None, tmpdir=None, dl_dir=None):
+ self.uri = uri
+ self.archive = os.path.basename(uri)
+ self.tempdirobj = None
+ if not tmpdir:
+ self.tempdirobj = tempfile.TemporaryDirectory(prefix='buildproject-')
+ tmpdir = self.tempdirobj.name
+ self.localarchive = os.path.join(tmpdir, self.archive)
+ self.dl_dir = dl_dir
+ if foldername:
+ self.fname = foldername
+ else:
+ self.fname = re.sub(r'\.tar\.bz2$|\.tar\.gz$|\.tar\.xz$', '', self.archive)
+ self.needclean = False
+
+ # Download self.archive to self.localarchive
+ def _download_archive(self):
+
+ self.needclean = True
+ if self.dl_dir and os.path.exists(os.path.join(self.dl_dir, self.archive)):
+ shutil.copyfile(os.path.join(self.dl_dir, self.archive), self.localarchive)
+ return
+
+ cmd = "wget -O %s %s" % (self.localarchive, self.uri)
+ subprocess.check_output(cmd, shell=True)
+
+ # This method should provide a way to run a command in the desired environment.
+ @abstractmethod
+ def _run(self, cmd):
+ pass
+
+ # The timeout parameter of target.run is set to 0 to make the ssh command
+ # run with no timeout.
+ def run_configure(self, configure_args='', extra_cmds=''):
+ return self._run('cd %s; gnu-configize; %s ./configure %s' % (self.targetdir, extra_cmds, configure_args))
+
+ def run_make(self, make_args=''):
+ return self._run('cd %s; make %s' % (self.targetdir, make_args))
+
+ def run_install(self, install_args=''):
+ return self._run('cd %s; make install %s' % (self.targetdir, install_args))
+
+ def clean(self):
+ if self.tempdirobj:
+ self.tempdirobj.cleanup()
+ if not self.needclean:
+ return
+ self._run('rm -rf %s' % self.targetdir)
+ subprocess.check_call('rm -f %s' % self.localarchive, shell=True)
diff --git a/meta/lib/oeqa/utils/commands.py b/meta/lib/oeqa/utils/commands.py
index 4f79d15bb8..f4daea2507 100644
--- a/meta/lib/oeqa/utils/commands.py
+++ b/meta/lib/oeqa/utils/commands.py
@@ -1,6 +1,8 @@
+#
# Copyright (c) 2013-2014 Intel Corporation
#
-# Released under the MIT license (see COPYING.MIT)
+# SPDX-License-Identifier: MIT
+#
# DESCRIPTION
# This module is mainly used by scripts/oe-selftest and modules under meta/oeqa/selftest
@@ -13,6 +15,7 @@ import sys
import signal
import subprocess
import threading
+import time
import logging
from oeqa.utils import CommandError
from oeqa.utils import ftools
@@ -25,7 +28,7 @@ except ImportError:
pass
class Command(object):
- def __init__(self, command, bg=False, timeout=None, data=None, **options):
+ def __init__(self, command, bg=False, timeout=None, data=None, output_log=None, **options):
self.defaultopts = {
"stdout": subprocess.PIPE,
@@ -48,38 +51,108 @@ class Command(object):
self.options.update(options)
self.status = None
+ # We collect chunks of output before joining them at the end.
+ self._output_chunks = []
+ self._error_chunks = []
self.output = None
self.error = None
- self.thread = None
+ self.threads = []
+ self.output_log = output_log
self.log = logging.getLogger("utils.commands")
def run(self):
self.process = subprocess.Popen(self.cmd, **self.options)
- def commThread():
- self.output, self.error = self.process.communicate(self.data)
-
- self.thread = threading.Thread(target=commThread)
- self.thread.start()
+ def readThread(output, stream, logfunc):
+ if logfunc:
+ for line in stream:
+ output.append(line)
+ logfunc(line.decode("utf-8", errors='replace').rstrip())
+ else:
+ output.append(stream.read())
+
+ def readStderrThread():
+ readThread(self._error_chunks, self.process.stderr, self.output_log.error if self.output_log else None)
+
+ def readStdoutThread():
+ readThread(self._output_chunks, self.process.stdout, self.output_log.info if self.output_log else None)
+
+ def writeThread():
+ try:
+ self.process.stdin.write(self.data)
+ self.process.stdin.close()
+ except OSError as ex:
+ # It's not an error when the command does not consume all
+ # of our data. subprocess.communicate() also ignores that.
+ if ex.errno != EPIPE:
+ raise
+
+ # We write in a separate thread because then we can read
+ # without worrying about deadlocks. The additional thread is
+ # expected to terminate by itself and we mark it as a daemon,
+ # so even it should happen to not terminate for whatever
+ # reason, the main process will still exit, which will then
+ # kill the write thread.
+ if self.data:
+ thread = threading.Thread(target=writeThread, daemon=True)
+ thread.start()
+ self.threads.append(thread)
+ if self.process.stderr:
+ thread = threading.Thread(target=readStderrThread)
+ thread.start()
+ self.threads.append(thread)
+ if self.output_log:
+ self.output_log.info('Running: %s' % self.cmd)
+ thread = threading.Thread(target=readStdoutThread)
+ thread.start()
+ self.threads.append(thread)
self.log.debug("Running command '%s'" % self.cmd)
if not self.bg:
- self.thread.join(self.timeout)
+ if self.timeout is None:
+ for thread in self.threads:
+ thread.join()
+ else:
+ deadline = time.time() + self.timeout
+ for thread in self.threads:
+ timeout = deadline - time.time()
+ if timeout < 0:
+ timeout = 0
+ thread.join(timeout)
self.stop()
def stop(self):
- if self.thread.isAlive():
- self.process.terminate()
+ for thread in self.threads:
+ if thread.is_alive():
+ self.process.terminate()
# let's give it more time to terminate gracefully before killing it
- self.thread.join(5)
- if self.thread.isAlive():
+ thread.join(5)
+ if thread.is_alive():
self.process.kill()
- self.thread.join()
+ thread.join()
- self.output = self.output.decode("utf-8").rstrip()
- self.status = self.process.poll()
+ def finalize_output(data):
+ if not data:
+ data = ""
+ else:
+ data = b"".join(data)
+ data = data.decode("utf-8", errors='replace').rstrip()
+ return data
+
+ self.output = finalize_output(self._output_chunks)
+ self._output_chunks = None
+ # self.error used to be a byte string earlier, probably unintentionally.
+ # Now it is a normal string, just like self.output.
+ self.error = finalize_output(self._error_chunks)
+ self._error_chunks = None
+ # At this point we know that the process has closed stdout/stderr, so
+ # it is safe and necessary to wait for the actual process completion.
+ self.status = self.process.wait()
+ self.process.stdout.close()
+ if self.process.stderr:
+ self.process.stderr.close()
self.log.debug("Command '%s' returned %d as exit code." % (self.cmd, self.status))
# logging the complete output is insane
@@ -94,12 +167,36 @@ class Result(object):
pass
-def runCmd(command, ignore_status=False, timeout=None, assert_error=True, **options):
+def runCmd(command, ignore_status=False, timeout=None, assert_error=True, sync=True,
+ native_sysroot=None, target_sys=None, limit_exc_output=0, output_log=None, **options):
result = Result()
- cmd = Command(command, timeout=timeout, **options)
+ if native_sysroot:
+ new_env = dict(options.get('env', os.environ))
+ paths = new_env["PATH"].split(":")
+ paths = [
+ os.path.join(native_sysroot, "bin"),
+ os.path.join(native_sysroot, "sbin"),
+ os.path.join(native_sysroot, "usr", "bin"),
+ os.path.join(native_sysroot, "usr", "sbin"),
+ ] + paths
+ if target_sys:
+ paths = [os.path.join(native_sysroot, "usr", "bin", target_sys)] + paths
+ new_env["PATH"] = ":".join(paths)
+ options['env'] = new_env
+
+ cmd = Command(command, timeout=timeout, output_log=output_log, **options)
cmd.run()
+ # tests can be heavy on IO and if bitbake can't write out its caches, we see timeouts.
+ # call sync around the tests to ensure the IO queue doesn't get too large, taking any IO
+ # hit here rather than in bitbake shutdown.
+ if sync:
+ p = os.environ['PATH']
+ os.environ['PATH'] = "/usr/bin:/bin:/usr/sbin:/sbin:" + p
+ os.system("sync")
+ os.environ['PATH'] = p
+
result.command = command
result.status = cmd.status
result.output = cmd.output
@@ -107,15 +204,21 @@ def runCmd(command, ignore_status=False, timeout=None, assert_error=True, **opti
result.pid = cmd.process.pid
if result.status and not ignore_status:
+ exc_output = result.output
+ if limit_exc_output > 0:
+ split = result.output.splitlines()
+ if len(split) > limit_exc_output:
+ exc_output = "\n... (last %d lines of output)\n" % limit_exc_output + \
+ '\n'.join(split[-limit_exc_output:])
if assert_error:
- raise AssertionError("Command '%s' returned non-zero exit status %d:\n%s" % (command, result.status, result.output))
+ raise AssertionError("Command '%s' returned non-zero exit status %d:\n%s" % (command, result.status, exc_output))
else:
- raise CommandError(result.status, command, result.output)
+ raise CommandError(result.status, command, exc_output)
return result
-def bitbake(command, ignore_status=False, timeout=None, postconfig=None, **options):
+def bitbake(command, ignore_status=False, timeout=None, postconfig=None, output_log=None, **options):
if postconfig:
postconfig_file = os.path.join(os.environ.get('BUILDDIR'), 'oeqa-post.conf')
@@ -130,7 +233,7 @@ def bitbake(command, ignore_status=False, timeout=None, postconfig=None, **optio
cmd = [ "bitbake" ] + [a for a in (command + extra_args.split(" ")) if a not in [""]]
try:
- return runCmd(cmd, ignore_status, timeout, **options)
+ return runCmd(cmd, ignore_status, timeout, output_log=output_log, **options)
finally:
if postconfig:
os.remove(postconfig_file)
@@ -146,7 +249,9 @@ def get_bb_vars(variables=None, target=None, postconfig=None):
"""Get values of multiple bitbake variables"""
bbenv = get_bb_env(target, postconfig=postconfig)
- var_re = re.compile(r'^(export )?(?P<var>\w+)="(?P<value>.*)"$')
+ if variables is not None:
+ variables = list(variables)
+ var_re = re.compile(r'^(export )?(?P<var>\w+(_.*)?)="(?P<value>.*)"$')
unset_re = re.compile(r'^unset (?P<var>\w+)$')
lastline = None
values = {}
@@ -195,6 +300,7 @@ def get_test_layer():
def create_temp_layer(templayerdir, templayername, priority=999, recipepathspec='recipes-*/*'):
os.makedirs(os.path.join(templayerdir, 'conf'))
+ corenames = get_bb_var('LAYERSERIES_CORENAMES')
with open(os.path.join(templayerdir, 'conf', 'layer.conf'), 'w') as f:
f.write('BBPATH .= ":${LAYERDIR}"\n')
f.write('BBFILES += "${LAYERDIR}/%s/*.bb \\' % recipepathspec)
@@ -203,64 +309,65 @@ def create_temp_layer(templayerdir, templayername, priority=999, recipepathspec=
f.write('BBFILE_PATTERN_%s = "^${LAYERDIR}/"\n' % templayername)
f.write('BBFILE_PRIORITY_%s = "%d"\n' % (templayername, priority))
f.write('BBFILE_PATTERN_IGNORE_EMPTY_%s = "1"\n' % templayername)
-
+ f.write('LAYERSERIES_COMPAT_%s = "%s"\n' % (templayername, corenames))
@contextlib.contextmanager
-def runqemu(pn, ssh=True):
+def runqemu(pn, ssh=True, runqemuparams='', image_fstype=None, launch_cmd=None, qemuparams=None, overrides={}, discard_writes=True):
+ """
+ launch_cmd means directly run the command, don't need set rootfs or env vars.
+ """
import bb.tinfoil
import bb.build
+ # Need a non-'BitBake' logger to capture the runner output
+ targetlogger = logging.getLogger('TargetRunner')
+ targetlogger.setLevel(logging.DEBUG)
+ handler = logging.StreamHandler(sys.stdout)
+ targetlogger.addHandler(handler)
+
tinfoil = bb.tinfoil.Tinfoil()
- tinfoil.prepare(False)
+ tinfoil.prepare(config_only=False, quiet=True)
try:
tinfoil.logger.setLevel(logging.WARNING)
import oeqa.targetcontrol
- tinfoil.config_data.setVar("TEST_LOG_DIR", "${WORKDIR}/testimage")
- tinfoil.config_data.setVar("TEST_QEMUBOOT_TIMEOUT", "1000")
- import oe.recipeutils
- recipefile = oe.recipeutils.pn_to_recipe(tinfoil.cooker, pn)
- recipedata = oe.recipeutils.parse_recipe(recipefile, [], tinfoil.config_data)
-
- # The QemuRunner log is saved out, but we need to ensure it is at the right
- # log level (and then ensure that since it's a child of the BitBake logger,
- # we disable propagation so we don't then see the log events on the console)
- logger = logging.getLogger('BitBake.QemuRunner')
- logger.setLevel(logging.DEBUG)
- logger.propagate = False
- logdir = recipedata.getVar("TEST_LOG_DIR", True)
-
- qemu = oeqa.targetcontrol.QemuTarget(recipedata)
+ recipedata = tinfoil.parse_recipe(pn)
+ recipedata.setVar("TEST_LOG_DIR", "${WORKDIR}/testimage")
+ recipedata.setVar("TEST_QEMUBOOT_TIMEOUT", "1000")
+ # Tell QemuTarget() whether need find rootfs/kernel or not
+ if launch_cmd:
+ recipedata.setVar("FIND_ROOTFS", '0')
+ else:
+ recipedata.setVar("FIND_ROOTFS", '1')
+
+ for key, value in overrides.items():
+ recipedata.setVar(key, value)
+
+ logdir = recipedata.getVar("TEST_LOG_DIR")
+
+ qemu = oeqa.targetcontrol.QemuTarget(recipedata, targetlogger, image_fstype)
finally:
# We need to shut down tinfoil early here in case we actually want
# to run tinfoil-using utilities with the running QEMU instance.
# Luckily QemuTarget doesn't need it after the constructor.
tinfoil.shutdown()
- # Setup bitbake logger as console handler is removed by tinfoil.shutdown
- bblogger = logging.getLogger('BitBake')
- bblogger.setLevel(logging.INFO)
- console = logging.StreamHandler(sys.stdout)
- bbformat = bb.msg.BBLogFormatter("%(levelname)s: %(message)s")
- if sys.stdout.isatty():
- bbformat.enable_color()
- console.setFormatter(bbformat)
- bblogger.addHandler(console)
-
try:
qemu.deploy()
try:
- qemu.start(ssh=ssh)
- except bb.build.FuncFailed:
- raise Exception('Failed to start QEMU - see the logs in %s' % logdir)
+ qemu.start(params=qemuparams, ssh=ssh, runqemuparams=runqemuparams, launch_cmd=launch_cmd, discard_writes=discard_writes)
+ except Exception as e:
+ msg = str(e) + '\nFailed to start QEMU - see the logs in %s' % logdir
+ if os.path.exists(qemu.qemurunnerlog):
+ with open(qemu.qemurunnerlog, 'r') as f:
+ msg = msg + "Qemurunner log output from %s:\n%s" % (qemu.qemurunnerlog, f.read())
+ raise Exception(msg)
yield qemu
finally:
- try:
- qemu.stop()
- except:
- pass
+ targetlogger.removeHandler(handler)
+ qemu.stop()
def updateEnv(env_file):
"""
diff --git a/meta/lib/oeqa/utils/decorators.py b/meta/lib/oeqa/utils/decorators.py
index 615fd956b5..ea90164e5e 100644
--- a/meta/lib/oeqa/utils/decorators.py
+++ b/meta/lib/oeqa/utils/decorators.py
@@ -1,6 +1,8 @@
+#
# Copyright (C) 2013 Intel Corporation
#
-# Released under the MIT license (see COPYING.MIT)
+# SPDX-License-Identifier: MIT
+#
# Some custom decorators that can be used by unittests
# Most useful is skipUnlessPassed which can be used for
@@ -14,91 +16,6 @@ import threading
import signal
from functools import wraps
-#get the "result" object from one of the upper frames provided that one of these upper frames is a unittest.case frame
-class getResults(object):
- def __init__(self):
- #dynamically determine the unittest.case frame and use it to get the name of the test method
- ident = threading.current_thread().ident
- upperf = sys._current_frames()[ident]
- while (upperf.f_globals['__name__'] != 'unittest.case'):
- upperf = upperf.f_back
-
- def handleList(items):
- ret = []
- # items is a list of tuples, (test, failure) or (_ErrorHandler(), Exception())
- for i in items:
- s = i[0].id()
- #Handle the _ErrorHolder objects from skipModule failures
- if "setUpModule (" in s:
- ret.append(s.replace("setUpModule (", "").replace(")",""))
- else:
- ret.append(s)
- # Append also the test without the full path
- testname = s.split('.')[-1]
- if testname:
- ret.append(testname)
- return ret
- self.faillist = handleList(upperf.f_locals['result'].failures)
- self.errorlist = handleList(upperf.f_locals['result'].errors)
- self.skiplist = handleList(upperf.f_locals['result'].skipped)
-
- def getFailList(self):
- return self.faillist
-
- def getErrorList(self):
- return self.errorlist
-
- def getSkipList(self):
- return self.skiplist
-
-class skipIfFailure(object):
-
- def __init__(self,testcase):
- self.testcase = testcase
-
- def __call__(self,f):
- @wraps(f)
- def wrapped_f(*args, **kwargs):
- res = getResults()
- if self.testcase in (res.getFailList() or res.getErrorList()):
- raise unittest.SkipTest("Testcase dependency not met: %s" % self.testcase)
- return f(*args, **kwargs)
- wrapped_f.__name__ = f.__name__
- return wrapped_f
-
-class skipIfSkipped(object):
-
- def __init__(self,testcase):
- self.testcase = testcase
-
- def __call__(self,f):
- @wraps(f)
- def wrapped_f(*args, **kwargs):
- res = getResults()
- if self.testcase in res.getSkipList():
- raise unittest.SkipTest("Testcase dependency not met: %s" % self.testcase)
- return f(*args, **kwargs)
- wrapped_f.__name__ = f.__name__
- return wrapped_f
-
-class skipUnlessPassed(object):
-
- def __init__(self,testcase):
- self.testcase = testcase
-
- def __call__(self,f):
- @wraps(f)
- def wrapped_f(*args, **kwargs):
- res = getResults()
- if self.testcase in res.getSkipList() or \
- self.testcase in res.getFailList() or \
- self.testcase in res.getErrorList():
- raise unittest.SkipTest("Testcase dependency not met: %s" % self.testcase)
- return f(*args, **kwargs)
- wrapped_f.__name__ = f.__name__
- wrapped_f._depends_on = self.testcase
- return wrapped_f
-
class testcase(object):
def __init__(self, test_case):
self.test_case = test_case
@@ -172,27 +89,42 @@ def LogResults(original_class):
#check status of tests and record it
+ tcid = self.id()
for (name, msg) in result.errors:
- if (self._testMethodName == str(name).split(' ')[0]) and (class_name in str(name).split(' ')[1]):
+ if tcid == name.id():
local_log.results("Testcase "+str(test_case)+": ERROR")
local_log.results("Testcase "+str(test_case)+":\n"+msg)
passed = False
for (name, msg) in result.failures:
- if (self._testMethodName == str(name).split(' ')[0]) and (class_name in str(name).split(' ')[1]):
+ if tcid == name.id():
local_log.results("Testcase "+str(test_case)+": FAILED")
local_log.results("Testcase "+str(test_case)+":\n"+msg)
passed = False
for (name, msg) in result.skipped:
- if (self._testMethodName == str(name).split(' ')[0]) and (class_name in str(name).split(' ')[1]):
+ if tcid == name.id():
local_log.results("Testcase "+str(test_case)+": SKIPPED")
passed = False
if passed:
local_log.results("Testcase "+str(test_case)+": PASSED")
+ # XXX: In order to avoid race condition when test if exists the linkfile
+ # use bb.utils.lock, the best solution is to create a unique name for the
+ # link file.
+ try:
+ import bb
+ has_bb = True
+ lockfilename = linkfile + '.lock'
+ except ImportError:
+ has_bb = False
+
+ if has_bb:
+ lf = bb.utils.lockfile(lockfilename, block=True)
# Create symlink to the current log
if os.path.lexists(linkfile):
os.remove(linkfile)
os.symlink(logfile, linkfile)
+ if has_bb:
+ bb.utils.unlockfile(lf)
original_class.run = run
diff --git a/meta/lib/oeqa/utils/dump.py b/meta/lib/oeqa/utils/dump.py
index 71422a9aea..d420b497f9 100644
--- a/meta/lib/oeqa/utils/dump.py
+++ b/meta/lib/oeqa/utils/dump.py
@@ -1,16 +1,17 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
import os
import sys
+import json
import errno
import datetime
import itertools
from .commands import runCmd
-def get_host_dumper(d):
- cmds = d.getVar("testimage_dump_host", True)
- parent_dir = d.getVar("TESTIMAGE_DUMP_DIR", True)
- return HostDumper(cmds, parent_dir)
-
-
class BaseDumper(object):
""" Base class to dump commands from host/target """
@@ -18,7 +19,8 @@ class BaseDumper(object):
self.cmds = []
# Some testing doesn't inherit testimage, so it is needed
# to set some defaults.
- self.parent_dir = parent_dir or "/tmp/oe-saved-tests"
+ self.parent_dir = parent_dir
+ self.dump_dir = parent_dir
dft_cmds = """ top -bn1
iostat -x -z -N -d -p ALL 20 2
ps -ef
@@ -48,11 +50,13 @@ class BaseDumper(object):
raise err
self.dump_dir = dump_dir
- def _write_dump(self, command, output):
+ def _construct_filename(self, command):
if isinstance(self, HostDumper):
prefix = "host"
elif isinstance(self, TargetDumper):
prefix = "target"
+ elif isinstance(self, MonitorDumper):
+ prefix = "qmp"
else:
prefix = "unknown"
for i in itertools.count():
@@ -60,9 +64,17 @@ class BaseDumper(object):
fullname = os.path.join(self.dump_dir, filename)
if not os.path.exists(fullname):
break
- with open(fullname, 'w') as dump_file:
- dump_file.write(output)
+ return fullname
+ def _write_dump(self, command, output):
+ fullname = self._construct_filename(command)
+ os.makedirs(os.path.dirname(fullname), exist_ok=True)
+ if isinstance(self, MonitorDumper):
+ with open(fullname, 'w') as json_file:
+ json.dump(output, json_file, indent=4)
+ else:
+ with open(fullname, 'w') as dump_file:
+ dump_file.write(output)
class HostDumper(BaseDumper):
""" Class to get dumps from the host running the tests """
@@ -73,26 +85,75 @@ class HostDumper(BaseDumper):
def dump_host(self, dump_dir=""):
if dump_dir:
self.dump_dir = dump_dir
+ env = os.environ.copy()
+ env['PATH'] = '/usr/sbin:/sbin:/usr/bin:/bin'
+ env['COLUMNS'] = '9999'
for cmd in self.cmds:
- result = runCmd(cmd, ignore_status=True)
+ result = runCmd(cmd, ignore_status=True, env=env)
self._write_dump(cmd.split()[0], result.output)
-
class TargetDumper(BaseDumper):
- """ Class to get dumps from target, it only works with QemuRunner """
+ """ Class to get dumps from target, it only works with QemuRunner.
+ Will give up permanently after 5 errors from running commands over
+ serial console. This helps to end testing when target is really dead, hanging
+ or unresponsive.
+ """
- def __init__(self, cmds, parent_dir, qemurunner):
+ def __init__(self, cmds, parent_dir, runner):
super(TargetDumper, self).__init__(cmds, parent_dir)
- self.runner = qemurunner
+ self.runner = runner
+ self.errors = 0
def dump_target(self, dump_dir=""):
+ if self.errors >= 5:
+ print("Too many errors when dumping data from target, assuming it is dead! Will not dump data anymore!")
+ return
if dump_dir:
self.dump_dir = dump_dir
for cmd in self.cmds:
# We can continue with the testing if serial commands fail
try:
(status, output) = self.runner.run_serial(cmd)
+ if status == 0:
+ self.errors = self.errors + 1
self._write_dump(cmd.split()[0], output)
except:
+ self.errors = self.errors + 1
print("Tried to dump info from target but "
"serial console failed")
+ print("Failed CMD: %s" % (cmd))
+
+class MonitorDumper(BaseDumper):
+ """ Class to get dumps via the Qemu Monitor, it only works with QemuRunner
+ Will stop completely if there are more than 5 errors when dumping monitor data.
+ This helps to end testing when target is really dead, hanging or unresponsive.
+ """
+
+ def __init__(self, cmds, parent_dir, runner):
+ super(MonitorDumper, self).__init__(cmds, parent_dir)
+ self.runner = runner
+ self.errors = 0
+
+ def dump_monitor(self, dump_dir=""):
+ if self.runner is None:
+ return
+ if dump_dir:
+ self.dump_dir = dump_dir
+ if self.errors >= 5:
+ print("Too many errors when dumping data from qemu monitor, assuming it is dead! Will not dump data anymore!")
+ return
+ for cmd in self.cmds:
+ cmd_name = cmd.split()[0]
+ try:
+ if len(cmd.split()) > 1:
+ cmd_args = cmd.split()[1]
+ if "%s" in cmd_args:
+ filename = self._construct_filename(cmd_name)
+ cmd_data = json.loads(cmd_args % (filename))
+ output = self.runner.run_monitor(cmd_name, cmd_data)
+ else:
+ output = self.runner.run_monitor(cmd_name)
+ self._write_dump(cmd_name, output)
+ except Exception as e:
+ self.errors = self.errors + 1
+ print("Failed to dump QMP CMD: %s with\nException: %s" % (cmd_name, e))
diff --git a/meta/lib/oeqa/utils/ftools.py b/meta/lib/oeqa/utils/ftools.py
index a7233d4ca6..a50aaa84c2 100644
--- a/meta/lib/oeqa/utils/ftools.py
+++ b/meta/lib/oeqa/utils/ftools.py
@@ -1,3 +1,9 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
import os
import re
import errno
diff --git a/meta/lib/oeqa/utils/git.py b/meta/lib/oeqa/utils/git.py
index a4c6741f4e..ea35a766eb 100644
--- a/meta/lib/oeqa/utils/git.py
+++ b/meta/lib/oeqa/utils/git.py
@@ -1,9 +1,11 @@
#
# Copyright (C) 2016 Intel Corporation
#
-# Released under the MIT license (see COPYING.MIT)
+# SPDX-License-Identifier: MIT
#
"""Git repository interactions"""
+import os
+
from oeqa.utils.commands import runCmd
@@ -13,9 +15,21 @@ class GitError(Exception):
class GitRepo(object):
"""Class representing a Git repository clone"""
- def __init__(self, cwd):
- self.top_dir = self._run_git_cmd_at(['rev-parse', '--show-toplevel'],
- cwd)
+ def __init__(self, path, is_topdir=False):
+ git_dir = self._run_git_cmd_at(['rev-parse', '--git-dir'], path)
+ git_dir = git_dir if os.path.isabs(git_dir) else os.path.join(path, git_dir)
+ self.git_dir = os.path.realpath(git_dir)
+
+ if self._run_git_cmd_at(['rev-parse', '--is-bare-repository'], path) == 'true':
+ self.bare = True
+ self.top_dir = self.git_dir
+ else:
+ self.bare = False
+ self.top_dir = self._run_git_cmd_at(['rev-parse', '--show-toplevel'],
+ path)
+ realpath = os.path.realpath(path)
+ if is_topdir and realpath != self.top_dir:
+ raise GitError("{} is not a Git top directory".format(realpath))
@staticmethod
def _run_git_cmd_at(git_args, cwd, **kwargs):
@@ -30,9 +44,37 @@ class GitRepo(object):
cmd_str, ret.status, ret.output))
return ret.output.strip()
- def run_cmd(self, git_args):
+ @staticmethod
+ def init(path, bare=False):
+ """Initialize a new Git repository"""
+ cmd = ['init']
+ if bare:
+ cmd.append('--bare')
+ GitRepo._run_git_cmd_at(cmd, cwd=path)
+ return GitRepo(path, is_topdir=True)
+
+ def run_cmd(self, git_args, env_update=None):
"""Run Git command"""
- return self._run_git_cmd_at(git_args, self.top_dir)
+ env = None
+ if env_update:
+ env = os.environ.copy()
+ env.update(env_update)
+ return self._run_git_cmd_at(git_args, self.top_dir, env=env)
+
+ def rev_parse(self, revision):
+ """Do git rev-parse"""
+ try:
+ return self.run_cmd(['rev-parse', '--verify', revision])
+ except GitError:
+ # Revision does not exist
+ return None
+ def get_current_branch(self):
+ """Get current branch"""
+ try:
+ # Strip 11 chars, i.e. 'refs/heads' from the beginning
+ return self.run_cmd(['symbolic-ref', 'HEAD'])[11:]
+ except GitError:
+ return None
diff --git a/meta/lib/oeqa/utils/gitarchive.py b/meta/lib/oeqa/utils/gitarchive.py
new file mode 100644
index 0000000000..6e8040eb5c
--- /dev/null
+++ b/meta/lib/oeqa/utils/gitarchive.py
@@ -0,0 +1,237 @@
+#
+# Helper functions for committing data to git and pushing upstream
+#
+# Copyright (c) 2017, Intel Corporation.
+# Copyright (c) 2019, Linux Foundation
+#
+# SPDX-License-Identifier: GPL-2.0-only
+#
+
+import os
+import re
+import sys
+from operator import attrgetter
+from collections import namedtuple
+from oeqa.utils.git import GitRepo, GitError
+
+class ArchiveError(Exception):
+ """Internal error handling of this script"""
+
+def format_str(string, fields):
+ """Format string using the given fields (dict)"""
+ try:
+ return string.format(**fields)
+ except KeyError as err:
+ raise ArchiveError("Unable to expand string '{}': unknown field {} "
+ "(valid fields are: {})".format(
+ string, err, ', '.join(sorted(fields.keys()))))
+
+
+def init_git_repo(path, no_create, bare, log):
+ """Initialize local Git repository"""
+ path = os.path.abspath(path)
+ if os.path.isfile(path):
+ raise ArchiveError("Invalid Git repo at {}: path exists but is not a "
+ "directory".format(path))
+ if not os.path.isdir(path) or not os.listdir(path):
+ if no_create:
+ raise ArchiveError("No git repo at {}, refusing to create "
+ "one".format(path))
+ if not os.path.isdir(path):
+ try:
+ os.mkdir(path)
+ except (FileNotFoundError, PermissionError) as err:
+ raise ArchiveError("Failed to mkdir {}: {}".format(path, err))
+ if not os.listdir(path):
+ log.info("Initializing a new Git repo at %s", path)
+ repo = GitRepo.init(path, bare)
+ try:
+ repo = GitRepo(path, is_topdir=True)
+ except GitError:
+ raise ArchiveError("Non-empty directory that is not a Git repository "
+ "at {}\nPlease specify an existing Git repository, "
+ "an empty directory or a non-existing directory "
+ "path.".format(path))
+ return repo
+
+
+def git_commit_data(repo, data_dir, branch, message, exclude, notes, log):
+ """Commit data into a Git repository"""
+ log.info("Committing data into to branch %s", branch)
+ tmp_index = os.path.join(repo.git_dir, 'index.oe-git-archive')
+ try:
+ # Create new tree object from the data
+ env_update = {'GIT_INDEX_FILE': tmp_index,
+ 'GIT_WORK_TREE': os.path.abspath(data_dir)}
+ repo.run_cmd('add .', env_update)
+
+ # Remove files that are excluded
+ if exclude:
+ repo.run_cmd(['rm', '--cached'] + [f for f in exclude], env_update)
+
+ tree = repo.run_cmd('write-tree', env_update)
+
+ # Create new commit object from the tree
+ parent = repo.rev_parse(branch)
+ if not parent:
+ parent = repo.rev_parse("origin/" + branch)
+ git_cmd = ['commit-tree', tree, '-m', message]
+ if parent:
+ git_cmd += ['-p', parent]
+ commit = repo.run_cmd(git_cmd, env_update)
+
+ # Create git notes
+ for ref, filename in notes:
+ ref = ref.format(branch_name=branch)
+ repo.run_cmd(['notes', '--ref', ref, 'add',
+ '-F', os.path.abspath(filename), commit])
+
+ # Update branch head
+ git_cmd = ['update-ref', 'refs/heads/' + branch, commit]
+ repo.run_cmd(git_cmd)
+
+ # Update current HEAD, if we're on branch 'branch'
+ if not repo.bare and repo.get_current_branch() == branch:
+ log.info("Updating %s HEAD to latest commit", repo.top_dir)
+ repo.run_cmd('reset --hard')
+
+ return commit
+ finally:
+ if os.path.exists(tmp_index):
+ os.unlink(tmp_index)
+
+
+def expand_tag_strings(repo, name_pattern, msg_subj_pattern, msg_body_pattern,
+ keywords):
+ """Generate tag name and message, with support for running id number"""
+ keyws = keywords.copy()
+ # Tag number is handled specially: if not defined, we autoincrement it
+ if 'tag_number' not in keyws:
+ # Fill in all other fields than 'tag_number'
+ keyws['tag_number'] = '{tag_number}'
+ tag_re = format_str(name_pattern, keyws)
+ # Replace parentheses for proper regex matching
+ tag_re = tag_re.replace('(', '\(').replace(')', '\)') + '$'
+ # Inject regex group pattern for 'tag_number'
+ tag_re = tag_re.format(tag_number='(?P<tag_number>[0-9]{1,5})')
+
+ keyws['tag_number'] = 0
+ for existing_tag in repo.run_cmd('tag').splitlines():
+ match = re.match(tag_re, existing_tag)
+
+ if match and int(match.group('tag_number')) >= keyws['tag_number']:
+ keyws['tag_number'] = int(match.group('tag_number')) + 1
+
+ tag_name = format_str(name_pattern, keyws)
+ msg_subj= format_str(msg_subj_pattern.strip(), keyws)
+ msg_body = format_str(msg_body_pattern, keyws)
+ return tag_name, msg_subj + '\n\n' + msg_body
+
+def gitarchive(data_dir, git_dir, no_create, bare, commit_msg_subject, commit_msg_body, branch_name, no_tag, tagname, tag_msg_subject, tag_msg_body, exclude, notes, push, keywords, log):
+
+ if not os.path.isdir(data_dir):
+ raise ArchiveError("Not a directory: {}".format(data_dir))
+
+ data_repo = init_git_repo(git_dir, no_create, bare, log)
+
+ # Expand strings early in order to avoid getting into inconsistent
+ # state (e.g. no tag even if data was committed)
+ commit_msg = format_str(commit_msg_subject.strip(), keywords)
+ commit_msg += '\n\n' + format_str(commit_msg_body, keywords)
+ branch_name = format_str(branch_name, keywords)
+ tag_name = None
+ if not no_tag and tagname:
+ tag_name, tag_msg = expand_tag_strings(data_repo, tagname,
+ tag_msg_subject,
+ tag_msg_body, keywords)
+
+ # Commit data
+ commit = git_commit_data(data_repo, data_dir, branch_name,
+ commit_msg, exclude, notes, log)
+
+ # Create tag
+ if tag_name:
+ log.info("Creating tag %s", tag_name)
+ data_repo.run_cmd(['tag', '-a', '-m', tag_msg, tag_name, commit])
+
+ # Push data to remote
+ if push:
+ cmd = ['push', '--tags']
+ # If no remote is given we push with the default settings from
+ # gitconfig
+ if push is not True:
+ notes_refs = ['refs/notes/' + ref.format(branch_name=branch_name)
+ for ref, _ in notes]
+ cmd.extend([push, branch_name] + notes_refs)
+ log.info("Pushing data to remote")
+ data_repo.run_cmd(cmd)
+
+# Container class for tester revisions
+TestedRev = namedtuple('TestedRev', 'commit commit_number tags')
+
+def get_test_runs(log, repo, tag_name, **kwargs):
+ """Get a sorted list of test runs, matching given pattern"""
+ # First, get field names from the tag name pattern
+ field_names = [m.group(1) for m in re.finditer(r'{(\w+)}', tag_name)]
+ undef_fields = [f for f in field_names if f not in kwargs.keys()]
+
+ # Fields for formatting tag name pattern
+ str_fields = dict([(f, '*') for f in field_names])
+ str_fields.update(kwargs)
+
+ # Get a list of all matching tags
+ tag_pattern = tag_name.format(**str_fields)
+ tags = repo.run_cmd(['tag', '-l', tag_pattern]).splitlines()
+ log.debug("Found %d tags matching pattern '%s'", len(tags), tag_pattern)
+
+ # Parse undefined fields from tag names
+ str_fields = dict([(f, r'(?P<{}>[\w\-.()]+)'.format(f)) for f in field_names])
+ str_fields['branch'] = r'(?P<branch>[\w\-.()/]+)'
+ str_fields['commit'] = '(?P<commit>[0-9a-f]{7,40})'
+ str_fields['commit_number'] = '(?P<commit_number>[0-9]{1,7})'
+ str_fields['tag_number'] = '(?P<tag_number>[0-9]{1,5})'
+ # escape parenthesis in fields in order to not messa up the regexp
+ fixed_fields = dict([(k, v.replace('(', r'\(').replace(')', r'\)')) for k, v in kwargs.items()])
+ str_fields.update(fixed_fields)
+ tag_re = re.compile(tag_name.format(**str_fields))
+
+ # Parse fields from tags
+ revs = []
+ for tag in tags:
+ m = tag_re.match(tag)
+ groups = m.groupdict()
+ revs.append([groups[f] for f in undef_fields] + [tag])
+
+ # Return field names and a sorted list of revs
+ return undef_fields, sorted(revs)
+
+def get_test_revs(log, repo, tag_name, **kwargs):
+ """Get list of all tested revisions"""
+ fields, runs = get_test_runs(log, repo, tag_name, **kwargs)
+
+ revs = {}
+ commit_i = fields.index('commit')
+ commit_num_i = fields.index('commit_number')
+ for run in runs:
+ commit = run[commit_i]
+ commit_num = run[commit_num_i]
+ tag = run[-1]
+ if not commit in revs:
+ revs[commit] = TestedRev(commit, commit_num, [tag])
+ else:
+ assert commit_num == revs[commit].commit_number, "Commit numbers do not match"
+ revs[commit].tags.append(tag)
+
+ # Return in sorted table
+ revs = sorted(revs.values(), key=attrgetter('commit_number'))
+ log.debug("Found %d tested revisions:\n %s", len(revs),
+ "\n ".join(['{} ({})'.format(rev.commit_number, rev.commit) for rev in revs]))
+ return revs
+
+def rev_find(revs, attr, val):
+ """Search from a list of TestedRev"""
+ for i, rev in enumerate(revs):
+ if getattr(rev, attr) == val:
+ return i
+ raise ValueError("Unable to find '{}' value '{}'".format(attr, val))
+
diff --git a/meta/lib/oeqa/utils/httpserver.py b/meta/lib/oeqa/utils/httpserver.py
index bd76f36468..80752c1377 100644
--- a/meta/lib/oeqa/utils/httpserver.py
+++ b/meta/lib/oeqa/utils/httpserver.py
@@ -1,35 +1,80 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
import http.server
+import logging
import multiprocessing
import os
+import signal
+from socketserver import ThreadingMixIn
-class HTTPServer(http.server.HTTPServer):
+class HTTPServer(ThreadingMixIn, http.server.HTTPServer):
- def server_start(self, root_dir):
- import signal
- signal.signal(signal.SIGTERM, signal.SIG_DFL)
+ def server_start(self, root_dir, logger):
os.chdir(root_dir)
+ self.logger = logger
self.serve_forever()
class HTTPRequestHandler(http.server.SimpleHTTPRequestHandler):
def log_message(self, format_str, *args):
- pass
+ self.server.logger.info(format_str, *args)
-class HTTPService(object):
+class HTTPService:
- def __init__(self, root_dir, host=''):
+ def __init__(self, root_dir, host='', port=0, logger=None):
self.root_dir = root_dir
self.host = host
- self.port = 0
+ self.port = port
+ if logger:
+ self.logger = logger.getChild("HTTPService")
+ else:
+ self.logger = logging.getLogger("HTTPService")
def start(self):
+ if not os.path.exists(self.root_dir):
+ self.logger.info("Not starting HTTPService for directory %s which doesn't exist" % (self.root_dir))
+ return
+
self.server = HTTPServer((self.host, self.port), HTTPRequestHandler)
if self.port == 0:
self.port = self.server.server_port
- self.process = multiprocessing.Process(target=self.server.server_start, args=[self.root_dir])
+ self.process = multiprocessing.Process(target=self.server.server_start, args=[self.root_dir, self.logger])
+
+ def handle_error(self, request, client_address):
+ import traceback
+ exception = traceback.format_exc()
+ self.logger.warn("Exception when handling %s: %s" % (request, exception))
+ self.server.handle_error = handle_error
+
+ # The signal handler from testimage.bbclass can cause deadlocks here
+ # if the HTTPServer is terminated before it can restore the standard
+ #signal behaviour
+ orig = signal.getsignal(signal.SIGTERM)
+ signal.signal(signal.SIGTERM, signal.SIG_DFL)
self.process.start()
+ signal.signal(signal.SIGTERM, orig)
+
+ if self.logger:
+ self.logger.info("Started HTTPService for %s on %s:%s" % (self.root_dir, self.host, self.port))
+
def stop(self):
- self.server.server_close()
- self.process.terminate()
- self.process.join()
+ if hasattr(self, "server"):
+ self.server.server_close()
+ if hasattr(self, "process"):
+ self.process.terminate()
+ self.process.join()
+ if self.logger:
+ self.logger.info("Stopped HTTPService on %s:%s" % (self.host, self.port))
+
+if __name__ == "__main__":
+ import sys, logging
+
+ logger = logging.getLogger(__name__)
+ logging.basicConfig(level=logging.DEBUG)
+ httpd = HTTPService(sys.argv[1], port=8888, logger=logger)
+ httpd.start()
diff --git a/meta/lib/oeqa/utils/logparser.py b/meta/lib/oeqa/utils/logparser.py
index b377dcd271..7cb79a8402 100644
--- a/meta/lib/oeqa/utils/logparser.py
+++ b/meta/lib/oeqa/utils/logparser.py
@@ -1,125 +1,163 @@
-#!/usr/bin/env python
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
import sys
import os
import re
-from . import ftools
-
# A parser that can be used to identify weather a line is a test result or a section statement.
-class Lparser(object):
-
- def __init__(self, test_0_pass_regex, test_0_fail_regex, section_0_begin_regex=None, section_0_end_regex=None, **kwargs):
- # Initialize the arguments dictionary
- if kwargs:
- self.args = kwargs
- else:
- self.args = {}
-
- # Add the default args to the dictionary
- self.args['test_0_pass_regex'] = test_0_pass_regex
- self.args['test_0_fail_regex'] = test_0_fail_regex
- if section_0_begin_regex:
- self.args['section_0_begin_regex'] = section_0_begin_regex
- if section_0_end_regex:
- self.args['section_0_end_regex'] = section_0_end_regex
-
- self.test_possible_status = ['pass', 'fail', 'error']
- self.section_possible_status = ['begin', 'end']
-
- self.initialized = False
-
-
- # Initialize the parser with the current configuration
- def init(self):
-
- # extra arguments can be added by the user to define new test and section categories. They must follow a pre-defined pattern: <type>_<category_name>_<status>_regex
- self.test_argument_pattern = "^test_(.+?)_(%s)_regex" % '|'.join(map(str, self.test_possible_status))
- self.section_argument_pattern = "^section_(.+?)_(%s)_regex" % '|'.join(map(str, self.section_possible_status))
-
- # Initialize the test and section regex dictionaries
- self.test_regex = {}
- self.section_regex ={}
-
- for arg, value in self.args.items():
- if not value:
- raise Exception('The value of provided argument %s is %s. Should have a valid value.' % (key, value))
- is_test = re.search(self.test_argument_pattern, arg)
- is_section = re.search(self.section_argument_pattern, arg)
- if is_test:
- if not is_test.group(1) in self.test_regex:
- self.test_regex[is_test.group(1)] = {}
- self.test_regex[is_test.group(1)][is_test.group(2)] = re.compile(value)
- elif is_section:
- if not is_section.group(1) in self.section_regex:
- self.section_regex[is_section.group(1)] = {}
- self.section_regex[is_section.group(1)][is_section.group(2)] = re.compile(value)
- else:
- # TODO: Make these call a traceback instead of a simple exception..
- raise Exception("The provided argument name does not correspond to any valid type. Please give one of the following types:\nfor tests: %s\nfor sections: %s" % (self.test_argument_pattern, self.section_argument_pattern))
-
- self.initialized = True
-
- # Parse a line and return a tuple containing the type of result (test/section) and its category, status and name
- def parse_line(self, line):
- if not self.initialized:
- raise Exception("The parser is not initialized..")
-
- for test_category, test_status_list in self.test_regex.items():
- for test_status, status_regex in test_status_list.items():
- test_name = status_regex.search(line)
- if test_name:
- return ['test', test_category, test_status, test_name.group(1)]
-
- for section_category, section_status_list in self.section_regex.items():
- for section_status, status_regex in section_status_list.items():
- section_name = status_regex.search(line)
- if section_name:
- return ['section', section_category, section_status, section_name.group(1)]
- return None
-
-
-class Result(object):
-
+class PtestParser(object):
def __init__(self):
- self.result_dict = {}
-
- def store(self, section, test, status):
- if not section in self.result_dict:
- self.result_dict[section] = []
-
- self.result_dict[section].append((test, status))
-
- # sort tests by the test name(the first element of the tuple), for each section. This can be helpful when using git to diff for changes by making sure they are always in the same order.
- def sort_tests(self):
- for package in self.result_dict:
- sorted_results = sorted(self.result_dict[package], key=lambda tup: tup[0])
- self.result_dict[package] = sorted_results
+ self.results = {}
+ self.sections = {}
+
+ def parse(self, logfile):
+ test_regex = {}
+ test_regex['PASSED'] = re.compile(r"^PASS:(.+)")
+ test_regex['FAILED'] = re.compile(r"^FAIL:([^(]+)")
+ test_regex['SKIPPED'] = re.compile(r"^SKIP:(.+)")
+
+ section_regex = {}
+ section_regex['begin'] = re.compile(r"^BEGIN: .*/(.+)/ptest")
+ section_regex['end'] = re.compile(r"^END: .*/(.+)/ptest")
+ section_regex['duration'] = re.compile(r"^DURATION: (.+)")
+ section_regex['exitcode'] = re.compile(r"^ERROR: Exit status is (.+)")
+ section_regex['timeout'] = re.compile(r"^TIMEOUT: .*/(.+)/ptest")
+
+ # Cache markers so we don't take the re.search() hit all the time.
+ markers = ("PASS:", "FAIL:", "SKIP:", "BEGIN:", "END:", "DURATION:", "ERROR: Exit", "TIMEOUT:")
+
+ def newsection():
+ return { 'name': "No-section", 'log': [] }
+
+ current_section = newsection()
+
+ with open(logfile, errors='replace') as f:
+ for line in f:
+ if not line.startswith(markers):
+ current_section['log'].append(line)
+ continue
+
+ result = section_regex['begin'].search(line)
+ if result:
+ current_section['name'] = result.group(1)
+ continue
+
+ result = section_regex['end'].search(line)
+ if result:
+ if current_section['name'] != result.group(1):
+ bb.warn("Ptest END log section mismatch %s vs. %s" % (current_section['name'], result.group(1)))
+ if current_section['name'] in self.sections:
+ bb.warn("Ptest duplicate section for %s" % (current_section['name']))
+ self.sections[current_section['name']] = current_section
+ del self.sections[current_section['name']]['name']
+ current_section = newsection()
+ continue
+
+ result = section_regex['timeout'].search(line)
+ if result:
+ if current_section['name'] != result.group(1):
+ bb.warn("Ptest TIMEOUT log section mismatch %s vs. %s" % (current_section['name'], result.group(1)))
+ current_section['timeout'] = True
+ continue
+
+ for t in ['duration', 'exitcode']:
+ result = section_regex[t].search(line)
+ if result:
+ current_section[t] = result.group(1)
+ continue
+
+ current_section['log'].append(line)
+
+ for t in test_regex:
+ result = test_regex[t].search(line)
+ if result:
+ if current_section['name'] not in self.results:
+ self.results[current_section['name']] = {}
+ self.results[current_section['name']][result.group(1).strip()] = t
+
+ # Python performance for repeatedly joining long strings is poor, do it all at once at the end.
+ # For 2.1 million lines in a log this reduces 18 hours to 12s.
+ for section in self.sections:
+ self.sections[section]['log'] = "".join(self.sections[section]['log'])
+
+ return self.results, self.sections
# Log the results as files. The file name is the section name and the contents are the tests in that section.
- def log_as_files(self, target_dir, test_status):
- status_regex = re.compile('|'.join(map(str, test_status)))
- if not type(test_status) == type([]):
- raise Exception("test_status should be a list. Got " + str(test_status) + " instead.")
+ def results_as_files(self, target_dir):
if not os.path.exists(target_dir):
raise Exception("Target directory does not exist: %s" % target_dir)
- for section, test_results in self.result_dict.items():
- prefix = ''
- for x in test_status:
- prefix +=x+'.'
- if (section != ''):
- prefix += section
+ for section in self.results:
+ prefix = 'No-section'
+ if section:
+ prefix = section
section_file = os.path.join(target_dir, prefix)
# purge the file contents if it exists
- open(section_file, 'w').close()
- for test_result in test_results:
- (test_name, status) = test_result
- # we log only the tests with status in the test_status list
- match_status = status_regex.search(status)
- if match_status:
- ftools.append_file(section_file, status + ": " + test_name)
-
- # Not yet implemented!
- def log_to_lava(self):
- pass
+ with open(section_file, 'w') as f:
+ for test_name in sorted(self.results[section]):
+ status = self.results[section][test_name]
+ f.write(status + ": " + test_name + "\n")
+
+
+# ltp log parsing
+class LtpParser(object):
+ def __init__(self):
+ self.results = {}
+ self.section = {'duration': "", 'log': ""}
+
+ def parse(self, logfile):
+ test_regex = {}
+ test_regex['PASSED'] = re.compile(r"PASS")
+ test_regex['FAILED'] = re.compile(r"FAIL")
+ test_regex['SKIPPED'] = re.compile(r"SKIP")
+
+ with open(logfile, errors='replace') as f:
+ for line in f:
+ for t in test_regex:
+ result = test_regex[t].search(line)
+ if result:
+ self.results[line.split()[0].strip()] = t
+
+ for test in self.results:
+ result = self.results[test]
+ self.section['log'] = self.section['log'] + ("%s: %s\n" % (result.strip()[:-2], test.strip()))
+
+ return self.results, self.section
+
+
+# ltp Compliance log parsing
+class LtpComplianceParser(object):
+ def __init__(self):
+ self.results = {}
+ self.section = {'duration': "", 'log': ""}
+
+ def parse(self, logfile):
+ test_regex = {}
+ test_regex['FAILED'] = re.compile(r"FAIL")
+
+ section_regex = {}
+ section_regex['test'] = re.compile(r"^Executing")
+
+ with open(logfile, errors='replace') as f:
+ name = logfile
+ result = "PASSED"
+ for line in f:
+ regex_result = section_regex['test'].search(line)
+ if regex_result:
+ name = line.split()[1].strip()
+
+ regex_result = test_regex['FAILED'].search(line)
+ if regex_result:
+ result = "FAILED"
+ self.results[name] = result
+
+ for test in self.results:
+ result = self.results[test]
+ print (self.results)
+ self.section['log'] = self.section['log'] + ("%s: %s\n" % (result.strip()[:-2], test.strip()))
+
+ return self.results, self.section
diff --git a/meta/lib/oeqa/utils/metadata.py b/meta/lib/oeqa/utils/metadata.py
new file mode 100644
index 0000000000..8013aa684d
--- /dev/null
+++ b/meta/lib/oeqa/utils/metadata.py
@@ -0,0 +1,124 @@
+# Copyright (C) 2016 Intel Corporation
+#
+# SPDX-License-Identifier: MIT
+#
+# Functions to get metadata from the testing host used
+# for analytics of test results.
+
+from collections import OrderedDict
+from collections.abc import MutableMapping
+from xml.dom.minidom import parseString
+from xml.etree.ElementTree import Element, tostring
+
+from oe.lsb import get_os_release
+from oeqa.utils.commands import runCmd, get_bb_vars
+
+
+def metadata_from_bb():
+ """ Returns test's metadata as OrderedDict.
+
+ Data will be gathered using bitbake -e thanks to get_bb_vars.
+ """
+ metadata_config_vars = ('MACHINE', 'BB_NUMBER_THREADS', 'PARALLEL_MAKE')
+
+ info_dict = OrderedDict()
+ hostname = runCmd('hostname')
+ info_dict['hostname'] = hostname.output
+ data_dict = get_bb_vars()
+
+ # Distro information
+ info_dict['distro'] = {'id': data_dict['DISTRO'],
+ 'version_id': data_dict['DISTRO_VERSION'],
+ 'pretty_name': '%s %s' % (data_dict['DISTRO'], data_dict['DISTRO_VERSION'])}
+
+ # Host distro information
+ os_release = get_os_release()
+ if os_release:
+ info_dict['host_distro'] = OrderedDict()
+ for key in ('ID', 'VERSION_ID', 'PRETTY_NAME'):
+ if key in os_release:
+ info_dict['host_distro'][key.lower()] = os_release[key]
+
+ info_dict['layers'] = get_layers(data_dict['BBLAYERS'])
+ info_dict['bitbake'] = git_rev_info(os.path.dirname(bb.__file__))
+
+ info_dict['config'] = OrderedDict()
+ for var in sorted(metadata_config_vars):
+ info_dict['config'][var] = data_dict[var]
+ return info_dict
+
+def metadata_from_data_store(d):
+ """ Returns test's metadata as OrderedDict.
+
+ Data will be collected from the provided data store.
+ """
+ # TODO: Getting metadata from the data store would
+ # be useful when running within bitbake.
+ pass
+
+def git_rev_info(path):
+ """Get git revision information as a dict"""
+ info = OrderedDict()
+
+ try:
+ from git import Repo, InvalidGitRepositoryError, NoSuchPathError
+ except ImportError:
+ import subprocess
+ try:
+ info['branch'] = subprocess.check_output(["git", "rev-parse", "--abbrev-ref", "HEAD"], cwd=path).decode('utf-8').strip()
+ except subprocess.CalledProcessError:
+ pass
+ try:
+ info['commit'] = subprocess.check_output(["git", "rev-parse", "HEAD"], cwd=path).decode('utf-8').strip()
+ except subprocess.CalledProcessError:
+ pass
+ try:
+ info['commit_count'] = int(subprocess.check_output(["git", "rev-list", "--count", "HEAD"], cwd=path).decode('utf-8').strip())
+ except subprocess.CalledProcessError:
+ pass
+ return info
+ try:
+ repo = Repo(path, search_parent_directories=True)
+ except (InvalidGitRepositoryError, NoSuchPathError):
+ return info
+ info['commit'] = repo.head.commit.hexsha
+ info['commit_count'] = repo.head.commit.count()
+ try:
+ info['branch'] = repo.active_branch.name
+ except TypeError:
+ info['branch'] = '(nobranch)'
+ return info
+
+def get_layers(layers):
+ """Returns layer information in dict format"""
+ layer_dict = OrderedDict()
+ for layer in layers.split():
+ layer_name = os.path.basename(layer)
+ layer_dict[layer_name] = git_rev_info(layer)
+ return layer_dict
+
+def write_metadata_file(file_path, metadata):
+ """ Writes metadata to a XML file in directory. """
+
+ xml = dict_to_XML('metadata', metadata)
+ xml_doc = parseString(tostring(xml).decode('UTF-8'))
+ with open(file_path, 'w') as f:
+ f.write(xml_doc.toprettyxml())
+
+def dict_to_XML(tag, dictionary, **kwargs):
+ """ Return XML element converting dicts recursively. """
+
+ elem = Element(tag, **kwargs)
+ for key, val in dictionary.items():
+ if tag == 'layers':
+ child = (dict_to_XML('layer', val, name=key))
+ elif isinstance(val, MutableMapping):
+ child = (dict_to_XML(key, val))
+ else:
+ if tag == 'config':
+ child = Element('variable', name=key)
+ else:
+ child = Element(key)
+ child.text = str(val)
+ elem.append(child)
+ return elem
diff --git a/meta/lib/oeqa/utils/network.py b/meta/lib/oeqa/utils/network.py
index 2768f6c5db..da4ffda9a9 100644
--- a/meta/lib/oeqa/utils/network.py
+++ b/meta/lib/oeqa/utils/network.py
@@ -1,7 +1,13 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
import socket
-def get_free_port():
- s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+def get_free_port(udp = False):
+ s = socket.socket(socket.AF_INET, socket.SOCK_STREAM if not udp else socket.SOCK_DGRAM)
s.bind(('', 0))
addr = s.getsockname()
s.close()
diff --git a/meta/lib/oeqa/utils/nfs.py b/meta/lib/oeqa/utils/nfs.py
new file mode 100644
index 0000000000..b66ed42a58
--- /dev/null
+++ b/meta/lib/oeqa/utils/nfs.py
@@ -0,0 +1,43 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+import os
+import sys
+import tempfile
+import contextlib
+import socket
+from oeqa.utils.commands import bitbake, get_bb_var, Command
+from oeqa.utils.network import get_free_port
+
+@contextlib.contextmanager
+def unfs_server(directory, logger = None):
+ unfs_sysroot = get_bb_var("RECIPE_SYSROOT_NATIVE", "unfs3-native")
+ if not os.path.exists(os.path.join(unfs_sysroot, "usr", "bin", "unfsd")):
+ # build native tool
+ bitbake("unfs3-native -c addto_recipe_sysroot")
+
+ exports = None
+ cmd = None
+ try:
+ # create the exports file
+ with tempfile.NamedTemporaryFile(delete = False) as exports:
+ exports.write("{0} (rw,no_root_squash,no_all_squash,insecure)\n".format(directory).encode())
+
+ # find some ports for the server
+ nfsport, mountport = get_free_port(udp = True), get_free_port(udp = True)
+
+ nenv = dict(os.environ)
+ nenv['PATH'] = "{0}/sbin:{0}/usr/sbin:{0}/usr/bin:".format(unfs_sysroot) + nenv.get('PATH', '')
+ cmd = Command(["unfsd", "-d", "-p", "-e", exports.name, "-n", str(nfsport), "-m", str(mountport)],
+ bg = True, env = nenv, output_log = logger)
+ cmd.run()
+ yield nfsport, mountport
+ finally:
+ if cmd is not None:
+ cmd.stop()
+ if exports is not None:
+ # clean up exports file
+ os.unlink(exports.name)
+
diff --git a/meta/lib/oeqa/utils/package_manager.py b/meta/lib/oeqa/utils/package_manager.py
index 099ecc9728..db799b64d6 100644
--- a/meta/lib/oeqa/utils/package_manager.py
+++ b/meta/lib/oeqa/utils/package_manager.py
@@ -1,29 +1,221 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
+import os
+import json
+import shutil
+
+from oeqa.core.utils.test import getCaseFile, getCaseMethod
+
def get_package_manager(d, root_path):
"""
Returns an OE package manager that can install packages in root_path.
"""
- from oe.package_manager import RpmPM, OpkgPM, DpkgPM
+ from oe.package_manager.rpm import RpmPM
+ from oe.package_manager.ipk import OpkgPM
+ from oe.package_manager.deb import DpkgPM
- pkg_class = d.getVar("IMAGE_PKGTYPE", True)
+ pkg_class = d.getVar("IMAGE_PKGTYPE")
if pkg_class == "rpm":
pm = RpmPM(d,
root_path,
- d.getVar('TARGET_VENDOR', True))
+ d.getVar('TARGET_VENDOR'),
+ filterbydependencies=False)
pm.create_configs()
elif pkg_class == "ipk":
pm = OpkgPM(d,
root_path,
- d.getVar("IPKGCONF_TARGET", True),
- d.getVar("ALL_MULTILIB_PACKAGE_ARCHS", True))
+ d.getVar("IPKGCONF_TARGET"),
+ d.getVar("ALL_MULTILIB_PACKAGE_ARCHS"),
+ filterbydependencies=False)
elif pkg_class == "deb":
pm = DpkgPM(d,
root_path,
- d.getVar('PACKAGE_ARCHS', True),
- d.getVar('DPKG_ARCH', True))
+ d.getVar('PACKAGE_ARCHS'),
+ d.getVar('DPKG_ARCH'),
+ filterbydependencies=False)
pm.write_index()
pm.update()
return pm
+
+def find_packages_to_extract(test_suite):
+ """
+ Returns packages to extract required by runtime tests.
+ """
+ from oeqa.core.utils.test import getSuiteCasesFiles
+
+ needed_packages = {}
+ files = getSuiteCasesFiles(test_suite)
+
+ for f in set(files):
+ json_file = _get_json_file(f)
+ if json_file:
+ needed_packages.update(_get_needed_packages(json_file))
+
+ return needed_packages
+
+def _get_json_file(module_path):
+ """
+ Returns the path of the JSON file for a module, empty if doesn't exitst.
+ """
+
+ json_file = '%s.json' % module_path.rsplit('.', 1)[0]
+ if os.path.isfile(module_path) and os.path.isfile(json_file):
+ return json_file
+ else:
+ return ''
+
+def _get_needed_packages(json_file, test=None):
+ """
+ Returns a dict with needed packages based on a JSON file.
+
+ If a test is specified it will return the dict just for that test.
+ """
+ needed_packages = {}
+
+ with open(json_file) as f:
+ test_packages = json.load(f)
+ for key,value in test_packages.items():
+ needed_packages[key] = value
+
+ if test:
+ if test in needed_packages:
+ needed_packages = needed_packages[test]
+ else:
+ needed_packages = {}
+
+ return needed_packages
+
+def extract_packages(d, needed_packages):
+ """
+ Extract packages that will be needed during runtime.
+ """
+
+ import bb
+ import oe.path
+
+ extracted_path = d.getVar('TEST_EXTRACTED_DIR')
+
+ for key,value in needed_packages.items():
+ packages = ()
+ if isinstance(value, dict):
+ packages = (value, )
+ elif isinstance(value, list):
+ packages = value
+ else:
+ bb.fatal('Failed to process needed packages for %s; '
+ 'Value must be a dict or list' % key)
+
+ for package in packages:
+ pkg = package['pkg']
+ rm = package.get('rm', False)
+ extract = package.get('extract', True)
+
+ if extract:
+ #logger.debug('Extracting %s' % pkg)
+ dst_dir = os.path.join(extracted_path, pkg)
+ # Same package used for more than one test,
+ # don't need to extract again.
+ if os.path.exists(dst_dir):
+ continue
+
+ # Extract package and copy it to TEST_EXTRACTED_DIR
+ pkg_dir = _extract_in_tmpdir(d, pkg)
+ oe.path.copytree(pkg_dir, dst_dir)
+ shutil.rmtree(pkg_dir)
+
+ else:
+ #logger.debug('Copying %s' % pkg)
+ _copy_package(d, pkg)
+
+def _extract_in_tmpdir(d, pkg):
+ """"
+ Returns path to a temp directory where the package was
+ extracted without dependencies.
+ """
+
+ from oeqa.utils.package_manager import get_package_manager
+
+ pkg_path = os.path.join(d.getVar('TEST_INSTALL_TMP_DIR'), pkg)
+ pm = get_package_manager(d, pkg_path)
+ extract_dir = pm.extract(pkg)
+ shutil.rmtree(pkg_path)
+
+ return extract_dir
+
+def _copy_package(d, pkg):
+ """
+ Copy the RPM, DEB or IPK package to dst_dir
+ """
+
+ from oeqa.utils.package_manager import get_package_manager
+
+ pkg_path = os.path.join(d.getVar('TEST_INSTALL_TMP_DIR'), pkg)
+ dst_dir = d.getVar('TEST_PACKAGED_DIR')
+ pm = get_package_manager(d, pkg_path)
+ pkg_info = pm.package_info(pkg)
+ file_path = pkg_info[pkg]['filepath']
+ shutil.copy2(file_path, dst_dir)
+ shutil.rmtree(pkg_path)
+
+def install_package(test_case):
+ """
+ Installs package in DUT if required.
+ """
+ needed_packages = test_needs_package(test_case)
+ if needed_packages:
+ _install_uninstall_packages(needed_packages, test_case, True)
+
+def uninstall_package(test_case):
+ """
+ Uninstalls package in DUT if required.
+ """
+ needed_packages = test_needs_package(test_case)
+ if needed_packages:
+ _install_uninstall_packages(needed_packages, test_case, False)
+
+def test_needs_package(test_case):
+ """
+ Checks if a test case requires to install/uninstall packages.
+ """
+ test_file = getCaseFile(test_case)
+ json_file = _get_json_file(test_file)
+
+ if json_file:
+ test_method = getCaseMethod(test_case)
+ needed_packages = _get_needed_packages(json_file, test_method)
+ if needed_packages:
+ return needed_packages
+
+ return None
+
+def _install_uninstall_packages(needed_packages, test_case, install=True):
+ """
+ Install/Uninstall packages in the DUT without using a package manager
+ """
+
+ if isinstance(needed_packages, dict):
+ packages = [needed_packages]
+ elif isinstance(needed_packages, list):
+ packages = needed_packages
+
+ for package in packages:
+ pkg = package['pkg']
+ rm = package.get('rm', False)
+ extract = package.get('extract', True)
+ src_dir = os.path.join(test_case.tc.extract_dir, pkg)
+
+ # Install package
+ if install and extract:
+ test_case.tc.target.copyDirTo(src_dir, '/')
+
+ # Uninstall package
+ elif not install and rm:
+ test_case.tc.target.deleteDirStructure(src_dir, '/')
diff --git a/meta/lib/oeqa/utils/qemurunner.py b/meta/lib/oeqa/utils/qemurunner.py
index df73120254..05385763ac 100644
--- a/meta/lib/oeqa/utils/qemurunner.py
+++ b/meta/lib/oeqa/utils/qemurunner.py
@@ -1,12 +1,15 @@
+#
# Copyright (C) 2013 Intel Corporation
#
-# Released under the MIT license (see COPYING.MIT)
+# SPDX-License-Identifier: MIT
+#
# This module provides a class for starting qemu images using runqemu.
# It's used by testimage.bbclass.
import subprocess
import os
+import sys
import time
import signal
import re
@@ -16,10 +19,11 @@ import errno
import string
import threading
import codecs
-from oeqa.utils.dump import HostDumper
-
import logging
-logger = logging.getLogger("BitBake.QemuRunner")
+import tempfile
+from oeqa.utils.dump import HostDumper
+from collections import defaultdict
+import importlib
# Get Unicode non printable control chars
control_range = list(range(0,32))+list(range(127,160))
@@ -29,16 +33,20 @@ re_control_char = re.compile('[%s]' % re.escape("".join(control_chars)))
class QemuRunner:
- def __init__(self, machine, rootfs, display, tmpdir, deploy_dir_image, logfile, boottime, dump_dir, dump_host_cmds):
+ def __init__(self, machine, rootfs, display, tmpdir, deploy_dir_image, logfile, boottime, dump_dir, dump_host_cmds,
+ use_kvm, logger, use_slirp=False, serial_ports=2, boot_patterns = defaultdict(str), use_ovmf=False, workdir=None, tmpfsdir=None):
# Popen object for runqemu
self.runqemu = None
+ self.runqemu_exited = False
# pid of the qemu process that runqemu will start
self.qemupid = None
- # target ip - from the command line
+ # target ip - from the command line or runqemu output
self.ip = None
# host ip - where qemu is running
self.server_ip = None
+ # target ip netmask
+ self.netmask = None
self.machine = machine
self.rootfs = rootfs
@@ -49,9 +57,43 @@ class QemuRunner:
self.boottime = boottime
self.logged = False
self.thread = None
-
- self.runqemutime = 60
+ self.use_kvm = use_kvm
+ self.use_ovmf = use_ovmf
+ self.use_slirp = use_slirp
+ self.serial_ports = serial_ports
+ self.msg = ''
+ self.boot_patterns = boot_patterns
+ self.tmpfsdir = tmpfsdir
+
+ self.runqemutime = 300
+ if not workdir:
+ workdir = os.getcwd()
+ self.qemu_pidfile = workdir + '/pidfile_' + str(os.getpid())
self.host_dumper = HostDumper(dump_host_cmds, dump_dir)
+ self.monitorpipe = None
+
+ self.logger = logger
+ # Whether we're expecting an exit and should show related errors
+ self.canexit = False
+
+ # Enable testing other OS's
+ # Set commands for target communication, and default to Linux ALWAYS
+ # Other OS's or baremetal applications need to provide their
+ # own implementation passing it through QemuRunner's constructor
+ # or by passing them through TESTIMAGE_BOOT_PATTERNS[flag]
+ # provided variables, where <flag> is one of the mentioned below.
+ accepted_patterns = ['search_reached_prompt', 'send_login_user', 'search_login_succeeded', 'search_cmd_finished']
+ default_boot_patterns = defaultdict(str)
+ # Default to the usual paterns used to communicate with the target
+ default_boot_patterns['search_reached_prompt'] = ' login:'
+ default_boot_patterns['send_login_user'] = 'root\n'
+ default_boot_patterns['search_login_succeeded'] = r"root@[a-zA-Z0-9\-]+:~#"
+ default_boot_patterns['search_cmd_finished'] = r"[a-zA-Z0-9]+@[a-zA-Z0-9\-]+:~#"
+
+ # Only override patterns that were set e.g. login user TESTIMAGE_BOOT_PATTERNS[send_login_user] = "webserver\n"
+ for pattern in accepted_patterns:
+ if not self.boot_patterns[pattern]:
+ self.boot_patterns[pattern] = default_boot_patterns[pattern]
def create_socket(self):
try:
@@ -60,19 +102,23 @@ class QemuRunner:
sock.bind(("127.0.0.1",0))
sock.listen(2)
port = sock.getsockname()[1]
- logger.info("Created listening socket for qemu serial console on: 127.0.0.1:%s" % port)
+ self.logger.debug("Created listening socket for qemu serial console on: 127.0.0.1:%s" % port)
return (sock, port)
except socket.error:
sock.close()
raise
+ def decode_qemulog(self, todecode):
+ # Sanitize the data received from qemu as it may contain control characters
+ msg = todecode.decode("utf-8", errors='ignore')
+ msg = re_control_char.sub('', msg)
+ return msg
+
def log(self, msg):
if self.logfile:
- # It is needed to sanitize the data received from qemu
- # because is possible to have control characters
- msg = msg.decode("utf-8")
- msg = re_control_char.sub('', msg)
+ msg = self.decode_qemulog(msg)
+ self.msg += msg
with codecs.open(self.logfile, "a", encoding="utf-8") as f:
f.write("%s" % msg)
@@ -80,74 +126,135 @@ class QemuRunner:
import fcntl
fl = fcntl.fcntl(o, fcntl.F_GETFL)
fcntl.fcntl(o, fcntl.F_SETFL, fl | os.O_NONBLOCK)
- return os.read(o.fileno(), 1000000).decode("utf-8")
+ try:
+ return os.read(o.fileno(), 1000000).decode("utf-8")
+ except BlockingIOError:
+ return ""
def handleSIGCHLD(self, signum, frame):
if self.runqemu and self.runqemu.poll():
if self.runqemu.returncode:
- logger.info('runqemu exited with code %d' % self.runqemu.returncode)
- logger.info("Output from runqemu:\n%s" % self.getOutput(self.runqemu.stdout))
+ self.logger.error('runqemu exited with code %d' % self.runqemu.returncode)
+ self.logger.error('Output from runqemu:\n%s' % self.getOutput(self.runqemu.stdout))
self.stop()
self._dump_host()
- raise SystemExit
- def start(self, qemuparams = None, get_ip = True, extra_bootparams = None):
+ def start(self, qemuparams = None, get_ip = True, extra_bootparams = None, runqemuparams='', launch_cmd=None, discard_writes=True):
+ env = os.environ.copy()
if self.display:
- os.environ["DISPLAY"] = self.display
+ env["DISPLAY"] = self.display
# Set this flag so that Qemu doesn't do any grabs as SDL grabs
# interact badly with screensavers.
- os.environ["QEMU_DONT_GRAB"] = "1"
+ env["QEMU_DONT_GRAB"] = "1"
if not os.path.exists(self.rootfs):
- logger.error("Invalid rootfs %s" % self.rootfs)
+ self.logger.error("Invalid rootfs %s" % self.rootfs)
return False
if not os.path.exists(self.tmpdir):
- logger.error("Invalid TMPDIR path %s" % self.tmpdir)
+ self.logger.error("Invalid TMPDIR path %s" % self.tmpdir)
return False
else:
- os.environ["OE_TMPDIR"] = self.tmpdir
+ env["OE_TMPDIR"] = self.tmpdir
if not os.path.exists(self.deploy_dir_image):
- logger.error("Invalid DEPLOY_DIR_IMAGE path %s" % self.deploy_dir_image)
+ self.logger.error("Invalid DEPLOY_DIR_IMAGE path %s" % self.deploy_dir_image)
return False
else:
- os.environ["DEPLOY_DIR_IMAGE"] = self.deploy_dir_image
+ env["DEPLOY_DIR_IMAGE"] = self.deploy_dir_image
+
+ if self.tmpfsdir:
+ env["RUNQEMU_TMPFS_DIR"] = self.tmpfsdir
+
+ if not launch_cmd:
+ launch_cmd = 'runqemu %s' % ('snapshot' if discard_writes else '')
+ if self.use_kvm:
+ self.logger.debug('Using kvm for runqemu')
+ launch_cmd += ' kvm'
+ else:
+ self.logger.debug('Not using kvm for runqemu')
+ if not self.display:
+ launch_cmd += ' nographic'
+ if self.use_slirp:
+ launch_cmd += ' slirp'
+ if self.use_ovmf:
+ launch_cmd += ' ovmf'
+ launch_cmd += ' %s %s' % (runqemuparams, self.machine)
+ if self.rootfs.endswith('.vmdk'):
+ self.logger.debug('Bypassing VMDK rootfs for runqemu')
+ else:
+ launch_cmd += ' %s' % (self.rootfs)
+
+ return self.launch(launch_cmd, qemuparams=qemuparams, get_ip=get_ip, extra_bootparams=extra_bootparams, env=env)
+
+ def launch(self, launch_cmd, get_ip = True, qemuparams = None, extra_bootparams = None, env = None):
+ # use logfile to determine the recipe-sysroot-native path and
+ # then add in the site-packages path components and add that
+ # to the python sys.path so qmp.py can be found.
+ python_path = os.path.dirname(os.path.dirname(self.logfile))
+ python_path += "/recipe-sysroot-native/usr/lib/qemu-python"
+ sys.path.append(python_path)
+ importlib.invalidate_caches()
+ try:
+ qmp = importlib.import_module("qmp")
+ except Exception as e:
+ self.logger.error("qemurunner: qmp.py missing, please ensure it's installed (%s)" % str(e))
+ return False
+ # Path relative to tmpdir used as cwd for qemu below to avoid unix socket path length issues
+ qmp_file = "." + next(tempfile._get_candidate_names())
+ qmp_param = ' -S -qmp unix:./%s,server,wait' % (qmp_file)
+ qmp_port = self.tmpdir + "/" + qmp_file
+ # Create a second socket connection for debugging use,
+ # note this will NOT cause qemu to block waiting for the connection
+ qmp_file2 = "." + next(tempfile._get_candidate_names())
+ qmp_param += ' -qmp unix:./%s,server,nowait' % (qmp_file2)
+ qmp_port2 = self.tmpdir + "/" + qmp_file2
+ self.logger.info("QMP Available for connection at %s" % (qmp_port2))
try:
- threadsock, threadport = self.create_socket()
+ if self.serial_ports >= 2:
+ self.threadsock, threadport = self.create_socket()
self.server_socket, self.serverport = self.create_socket()
except socket.error as msg:
- logger.error("Failed to create listening socket: %s" % msg[1])
+ self.logger.error("Failed to create listening socket: %s" % msg[1])
return False
-
- bootparams = 'console=tty1 console=ttyS0,115200n8 printk.time=1'
+ bootparams = ' printk.time=1'
if extra_bootparams:
bootparams = bootparams + ' ' + extra_bootparams
- self.qemuparams = 'bootparams="{0}" qemuparams="-serial tcp:127.0.0.1:{1}"'.format(bootparams, threadport)
- if not self.display:
- self.qemuparams = 'nographic ' + self.qemuparams
+ # Ask QEMU to store the QEMU process PID in file, this way we don't have to parse running processes
+ # and analyze descendents in order to determine it.
+ if os.path.exists(self.qemu_pidfile):
+ os.remove(self.qemu_pidfile)
+ self.qemuparams = 'bootparams="{0}" qemuparams="-pidfile {1} {2}"'.format(bootparams, self.qemu_pidfile, qmp_param)
+
if qemuparams:
self.qemuparams = self.qemuparams[:-1] + " " + qemuparams + " " + '\"'
+ if self.serial_ports >= 2:
+ launch_cmd += ' tcpserial=%s:%s %s' % (threadport, self.serverport, self.qemuparams)
+ else:
+ launch_cmd += ' tcpserial=%s %s' % (self.serverport, self.qemuparams)
+
self.origchldhandler = signal.getsignal(signal.SIGCHLD)
signal.signal(signal.SIGCHLD, self.handleSIGCHLD)
- launch_cmd = 'runqemu tcpserial=%s %s %s %s' % (self.serverport, self.machine, self.rootfs, self.qemuparams)
+ self.logger.debug('launchcmd=%s'%(launch_cmd))
+
# FIXME: We pass in stdin=subprocess.PIPE here to work around stty
# blocking at the end of the runqemu script when using this within
# oe-selftest (this makes stty error out immediately). There ought
# to be a proper fix but this will suffice for now.
- self.runqemu = subprocess.Popen(launch_cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, stdin=subprocess.PIPE, preexec_fn=os.setpgrp)
+ self.runqemu = subprocess.Popen(launch_cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, stdin=subprocess.PIPE, preexec_fn=os.setpgrp, env=env, cwd=self.tmpdir)
output = self.runqemu.stdout
+ launch_time = time.time()
#
- # We need the preexec_fn above so that all runqemu processes can easily be killed
+ # We need the preexec_fn above so that all runqemu processes can easily be killed
# (by killing their process group). This presents a problem if this controlling
- # process itself is killed however since those processes don't notice the death
+ # process itself is killed however since those processes don't notice the death
# of the parent and merrily continue on.
#
- # Rather than hack runqemu to deal with this, we add something here instead.
+ # Rather than hack runqemu to deal with this, we add something here instead.
# Basically we fork off another process which holds an open pipe to the parent
# and also is setpgrp. If/when the pipe sees EOF from the parent dieing, it kills
# the process group. This is like pctrl's PDEATHSIG but for a process group
@@ -165,157 +272,336 @@ class QemuRunner:
r = os.fdopen(r)
x = r.read()
os.killpg(os.getpgid(self.runqemu.pid), signal.SIGTERM)
- sys.exit(0)
+ os._exit(0)
- logger.info("runqemu started, pid is %s" % self.runqemu.pid)
- logger.info("waiting at most %s seconds for qemu pid" % self.runqemutime)
+ self.logger.debug("runqemu started, pid is %s" % self.runqemu.pid)
+ self.logger.debug("waiting at most %s seconds for qemu pid (%s)" %
+ (self.runqemutime, time.strftime("%D %H:%M:%S")))
endtime = time.time() + self.runqemutime
while not self.is_alive() and time.time() < endtime:
if self.runqemu.poll():
+ if self.runqemu_exited:
+ self.logger.warning("runqemu during is_alive() test")
+ return False
if self.runqemu.returncode:
# No point waiting any longer
- logger.info('runqemu exited with code %d' % self.runqemu.returncode)
+ self.logger.warning('runqemu exited with code %d' % self.runqemu.returncode)
self._dump_host()
+ self.logger.warning("Output from runqemu:\n%s" % self.getOutput(output))
self.stop()
- logger.info("Output from runqemu:\n%s" % self.getOutput(output))
return False
- time.sleep(1)
-
- if self.is_alive():
- logger.info("qemu started - qemu procces pid is %s" % self.qemupid)
- if get_ip:
- cmdline = ''
- with open('/proc/%s/cmdline' % self.qemupid) as p:
- cmdline = p.read()
- # It is needed to sanitize the data received
- # because is possible to have control characters
- cmdline = re_control_char.sub('', cmdline)
+ time.sleep(0.5)
+
+ if self.runqemu_exited:
+ self.logger.warning("runqemu after timeout")
+
+ if self.runqemu.returncode:
+ self.logger.warning('runqemu exited with code %d' % self.runqemu.returncode)
+
+ if not self.is_alive():
+ self.logger.error("Qemu pid didn't appear in %s seconds (%s)" %
+ (self.runqemutime, time.strftime("%D %H:%M:%S")))
+
+ qemu_pid = None
+ if os.path.isfile(self.qemu_pidfile):
+ with open(self.qemu_pidfile, 'r') as f:
+ qemu_pid = f.read().strip()
+
+ self.logger.error("Status information, poll status: %s, pidfile exists: %s, pidfile contents %s, proc pid exists %s"
+ % (self.runqemu.poll(), os.path.isfile(self.qemu_pidfile), str(qemu_pid), os.path.exists("/proc/" + str(qemu_pid))))
+
+ # Dump all processes to help us to figure out what is going on...
+ ps = subprocess.Popen(['ps', 'axww', '-o', 'pid,ppid,pri,ni,command '], stdout=subprocess.PIPE).communicate()[0]
+ processes = ps.decode("utf-8")
+ self.logger.debug("Running processes:\n%s" % processes)
+ self._dump_host()
+ op = self.getOutput(output)
+ self.stop()
+ if op:
+ self.logger.error("Output from runqemu:\n%s" % op)
+ else:
+ self.logger.error("No output from runqemu.\n")
+ return False
+
+ # Create the client socket for the QEMU Monitor Control Socket
+ # This will allow us to read status from Qemu if the the process
+ # is still alive
+ self.logger.debug("QMP Initializing to %s" % (qmp_port))
+ # chdir dance for path length issues with unix sockets
+ origpath = os.getcwd()
+ try:
+ os.chdir(os.path.dirname(qmp_port))
+ try:
+ from qmp.legacy import QEMUMonitorProtocol
+ self.qmp = QEMUMonitorProtocol(os.path.basename(qmp_port))
+ except OSError as msg:
+ self.logger.warning("Failed to initialize qemu monitor socket: %s File: %s" % (msg, msg.filename))
+ return False
+
+ self.logger.debug("QMP Connecting to %s" % (qmp_port))
+ if not os.path.exists(qmp_port) and self.is_alive():
+ self.logger.debug("QMP Port does not exist waiting for it to be created")
+ endtime = time.time() + self.runqemutime
+ while not os.path.exists(qmp_port) and self.is_alive() and time.time() < endtime:
+ self.logger.info("QMP port does not exist yet!")
+ time.sleep(0.5)
+ if not os.path.exists(qmp_port) and self.is_alive():
+ self.logger.warning("QMP Port still does not exist but QEMU is alive")
+ return False
+
+ try:
+ # set timeout value for all QMP calls
+ self.qmp.settimeout(self.runqemutime)
+ self.qmp.connect()
+ connect_time = time.time()
+ self.logger.info("QMP connected to QEMU at %s and took %s seconds" %
+ (time.strftime("%D %H:%M:%S"),
+ time.time() - launch_time))
+ except OSError as msg:
+ self.logger.warning("Failed to connect qemu monitor socket: %s File: %s" % (msg, msg.filename))
+ return False
+ except qmp.legacy.QMPError as msg:
+ self.logger.warning("Failed to communicate with qemu monitor: %s" % (msg))
+ return False
+ finally:
+ os.chdir(origpath)
+
+ # We worry that mmap'd libraries may cause page faults which hang the qemu VM for periods
+ # causing failures. Before we "start" qemu, read through it's mapped files to try and
+ # ensure we don't hit page faults later
+ mapdir = "/proc/" + str(self.qemupid) + "/map_files/"
+ try:
+ for f in os.listdir(mapdir):
try:
- ips = re.findall("((?:[0-9]{1,3}\.){3}[0-9]{1,3})", cmdline.split("ip=")[1])
- if not ips or len(ips) != 3:
- raise ValueError
- else:
- self.ip = ips[0]
- self.server_ip = ips[1]
- except (IndexError, ValueError):
- logger.info("Couldn't get ip from qemu process arguments! Here is the qemu command line used:\n%s\nand output from runqemu:\n%s" % (cmdline, self.getOutput(output)))
+ linktarget = os.readlink(os.path.join(mapdir, f))
+ if not linktarget.startswith("/") or linktarget.startswith("/dev") or "deleted" in linktarget:
+ continue
+ with open(linktarget, "rb") as readf:
+ data = True
+ while data:
+ data = readf.read(4096)
+ except FileNotFoundError:
+ continue
+ # Centos7 doesn't allow us to read /map_files/
+ except PermissionError:
+ pass
+
+ # Release the qemu process to continue running
+ self.run_monitor('cont')
+ self.logger.info("QMP released QEMU at %s and took %s seconds from connect" %
+ (time.strftime("%D %H:%M:%S"),
+ time.time() - connect_time))
+
+ # We are alive: qemu is running
+ out = self.getOutput(output)
+ netconf = False # network configuration is not required by default
+ self.logger.debug("qemu started in %s seconds - qemu procces pid is %s (%s)" %
+ (time.time() - (endtime - self.runqemutime),
+ self.qemupid, time.strftime("%D %H:%M:%S")))
+ cmdline = ''
+ if get_ip:
+ with open('/proc/%s/cmdline' % self.qemupid) as p:
+ cmdline = p.read()
+ # It is needed to sanitize the data received
+ # because is possible to have control characters
+ cmdline = re_control_char.sub(' ', cmdline)
+ try:
+ if self.use_slirp:
+ tcp_ports = cmdline.split("hostfwd=tcp:")[1]
+ ip, tcp_ports = tcp_ports.split(":")[:2]
+ host_port = tcp_ports[:tcp_ports.find('-')]
+ self.ip = "%s:%s" % (ip, host_port)
+ else:
+ ips = re.findall(r"((?:[0-9]{1,3}\.){3}[0-9]{1,3})", cmdline.split("ip=")[1])
+ self.ip = ips[0]
+ self.server_ip = ips[1]
+ self.logger.debug("qemu cmdline used:\n{}".format(cmdline))
+ except (IndexError, ValueError):
+ # Try to get network configuration from runqemu output
+ match = re.match(r'.*Network configuration: (?:ip=)*([0-9.]+)::([0-9.]+):([0-9.]+).*',
+ out, re.MULTILINE|re.DOTALL)
+ if match:
+ self.ip, self.server_ip, self.netmask = match.groups()
+ # network configuration is required as we couldn't get it
+ # from the runqemu command line, so qemu doesn't run kernel
+ # and guest networking is not configured
+ netconf = True
+ else:
+ self.logger.error("Couldn't get ip from qemu command line and runqemu output! "
+ "Here is the qemu command line used:\n%s\n"
+ "and output from runqemu:\n%s" % (cmdline, out))
self._dump_host()
self.stop()
return False
- logger.info("qemu cmdline used:\n{}".format(cmdline))
- logger.info("Target IP: %s" % self.ip)
- logger.info("Server IP: %s" % self.server_ip)
- self.thread = LoggingThread(self.log, threadsock, logger)
+ self.logger.debug("Target IP: %s" % self.ip)
+ self.logger.debug("Server IP: %s" % self.server_ip)
+
+ if self.serial_ports >= 2:
+ self.thread = LoggingThread(self.log, self.threadsock, self.logger)
self.thread.start()
if not self.thread.connection_established.wait(self.boottime):
- logger.error("Didn't receive a console connection from qemu. "
+ self.logger.error("Didn't receive a console connection from qemu. "
"Here is the qemu command line used:\n%s\nand "
- "output from runqemu:\n%s" % (cmdline,
- self.getOutput(output)))
+ "output from runqemu:\n%s" % (cmdline, out))
self.stop_thread()
return False
- logger.info("Output from runqemu:\n%s", self.getOutput(output))
- logger.info("Waiting at most %d seconds for login banner" % self.boottime)
- endtime = time.time() + self.boottime
- socklist = [self.server_socket]
- reachedlogin = False
- stopread = False
- qemusock = None
- bootlog = ''
- data = b''
- while time.time() < endtime and not stopread:
- sread, swrite, serror = select.select(socklist, [], [], 5)
- for sock in sread:
- if sock is self.server_socket:
- qemusock, addr = self.server_socket.accept()
- qemusock.setblocking(0)
- socklist.append(qemusock)
- socklist.remove(self.server_socket)
- logger.info("Connection from %s:%s" % addr)
- else:
- data = data + sock.recv(1024)
- if data:
- try:
- data = data.decode("utf-8", errors="surrogateescape")
- bootlog += data
- data = b''
- if re.search(".* login:", bootlog):
- self.server_socket = qemusock
- stopread = True
- reachedlogin = True
- logger.info("Reached login banner")
- except UnicodeDecodeError:
- continue
- else:
- socklist.remove(sock)
- sock.close()
- stopread = True
-
- if not reachedlogin:
- logger.info("Target didn't reached login boot in %d seconds" % self.boottime)
- lines = "\n".join(bootlog.splitlines()[-25:])
- logger.info("Last 25 lines of text:\n%s" % lines)
- logger.info("Check full boot log: %s" % self.logfile)
- self._dump_host()
- self.stop()
- return False
-
- # If we are not able to login the tests can continue
+ self.logger.debug("Output from runqemu:\n%s", out)
+ self.logger.debug("Waiting at most %d seconds for login banner (%s)" %
+ (self.boottime, time.strftime("%D %H:%M:%S")))
+ endtime = time.time() + self.boottime
+ socklist = [self.server_socket]
+ reachedlogin = False
+ stopread = False
+ qemusock = None
+ bootlog = b''
+ data = b''
+ while time.time() < endtime and not stopread:
try:
- (status, output) = self.run_serial("root\n", raw=True)
- if re.search("root@[a-zA-Z0-9\-]+:~#", output):
- self.logged = True
- logger.info("Logged as root in serial console")
+ sread, swrite, serror = select.select(socklist, [], [], 5)
+ except InterruptedError:
+ continue
+ for sock in sread:
+ if sock is self.server_socket:
+ qemusock, addr = self.server_socket.accept()
+ qemusock.setblocking(0)
+ socklist.append(qemusock)
+ socklist.remove(self.server_socket)
+ self.logger.debug("Connection from %s:%s" % addr)
else:
- logger.info("Couldn't login into serial console"
- " as root using blank password")
- except:
- logger.info("Serial console failed while trying to login")
-
- else:
- logger.info("Qemu pid didn't appeared in %s seconds" % self.runqemutime)
+ # try to avoid reading only a single character at a time
+ time.sleep(0.1)
+ data = data + sock.recv(1024)
+ if data:
+ bootlog += data
+ if self.serial_ports < 2:
+ # this socket has mixed console/kernel data, log it to logfile
+ self.log(data)
+
+ data = b''
+
+ decodedlog = self.decode_qemulog(bootlog)
+ if self.boot_patterns['search_reached_prompt'] in decodedlog:
+ self.server_socket = qemusock
+ stopread = True
+ reachedlogin = True
+ self.logger.debug("Reached login banner in %s seconds (%s, %s)" %
+ (time.time() - (endtime - self.boottime),
+ time.strftime("%D %H:%M:%S"), time.time()))
+ else:
+ # no need to check if reachedlogin unless we support multiple connections
+ self.logger.debug("QEMU socket disconnected before login banner reached. (%s)" %
+ time.strftime("%D %H:%M:%S"))
+ socklist.remove(sock)
+ sock.close()
+ stopread = True
+
+ if not reachedlogin:
+ if time.time() >= endtime:
+ self.logger.warning("Target didn't reach login banner in %d seconds (%s)" %
+ (self.boottime, time.strftime("%D %H:%M:%S")))
+ tail = lambda l: "\n".join(l.splitlines()[-25:])
+ bootlog = self.decode_qemulog(bootlog)
+ # in case bootlog is empty, use tail qemu log store at self.msg
+ lines = tail(bootlog if bootlog else self.msg)
+ self.logger.warning("Last 25 lines of text (%d):\n%s" % (len(bootlog), lines))
+ self.logger.warning("Check full boot log: %s" % self.logfile)
self._dump_host()
self.stop()
- logger.info("Output from runqemu:\n%s" % self.getOutput(output))
return False
- return self.is_alive()
+ # If we are not able to login the tests can continue
+ try:
+ (status, output) = self.run_serial(self.boot_patterns['send_login_user'], raw=True, timeout=120)
+ if re.search(self.boot_patterns['search_login_succeeded'], output):
+ self.logged = True
+ self.logger.debug("Logged as root in serial console")
+ if netconf:
+ # configure guest networking
+ cmd = "ifconfig eth0 %s netmask %s up\n" % (self.ip, self.netmask)
+ output = self.run_serial(cmd, raw=True)[1]
+ if re.search(r"root@[a-zA-Z0-9\-]+:~#", output):
+ self.logger.debug("configured ip address %s", self.ip)
+ else:
+ self.logger.debug("Couldn't configure guest networking")
+ else:
+ self.logger.warning("Couldn't login into serial console"
+ " as root using blank password")
+ self.logger.warning("The output:\n%s" % output)
+ except:
+ self.logger.warning("Serial console failed while trying to login")
+ return True
def stop(self):
- self.stop_thread()
if hasattr(self, "origchldhandler"):
signal.signal(signal.SIGCHLD, self.origchldhandler)
+ self.stop_thread()
+ self.stop_qemu_system()
if self.runqemu:
if hasattr(self, "monitorpid"):
os.kill(self.monitorpid, signal.SIGKILL)
- logger.info("Sending SIGTERM to runqemu")
+ self.logger.debug("Sending SIGTERM to runqemu")
try:
os.killpg(os.getpgid(self.runqemu.pid), signal.SIGTERM)
except OSError as e:
if e.errno != errno.ESRCH:
raise
- endtime = time.time() + self.runqemutime
- while self.runqemu.poll() is None and time.time() < endtime:
- time.sleep(1)
- if self.runqemu.poll() is None:
- logger.info("Sending SIGKILL to runqemu")
+ try:
+ outs, errs = self.runqemu.communicate(timeout = self.runqemutime)
+ if outs:
+ self.logger.info("Output from runqemu:\n%s", outs.decode("utf-8"))
+ if errs:
+ self.logger.info("Stderr from runqemu:\n%s", errs.decode("utf-8"))
+ except TimeoutExpired:
+ self.logger.debug("Sending SIGKILL to runqemu")
os.killpg(os.getpgid(self.runqemu.pid), signal.SIGKILL)
- self.runqemu = None
+ if not self.runqemu.stdout.closed:
+ self.logger.info("Output from runqemu:\n%s" % self.getOutput(self.runqemu.stdout))
+ self.runqemu.stdin.close()
+ self.runqemu.stdout.close()
+ self.runqemu_exited = True
+
+ if hasattr(self, 'qmp') and self.qmp:
+ self.qmp.close()
+ self.qmp = None
if hasattr(self, 'server_socket') and self.server_socket:
self.server_socket.close()
self.server_socket = None
+ if hasattr(self, 'threadsock') and self.threadsock:
+ self.threadsock.close()
+ self.threadsock = None
self.qemupid = None
self.ip = None
+ if os.path.exists(self.qemu_pidfile):
+ try:
+ os.remove(self.qemu_pidfile)
+ except FileNotFoundError as e:
+ # We raced, ignore
+ pass
+ if self.monitorpipe:
+ self.monitorpipe.close()
+
+ def stop_qemu_system(self):
+ if self.qemupid:
+ try:
+ # qemu-system behaves well and a SIGTERM is enough
+ os.kill(self.qemupid, signal.SIGTERM)
+ except ProcessLookupError as e:
+ self.logger.warning('qemu-system ended unexpectedly')
def stop_thread(self):
if self.thread and self.thread.is_alive():
self.thread.stop()
self.thread.join()
+ def allowexit(self):
+ self.canexit = True
+ if self.thread:
+ self.thread.allowexit()
+
def restart(self, qemuparams = None):
- logger.info("Restarting qemu process")
+ self.logger.warning("Restarting qemu process")
if self.runqemu.poll() is None:
self.stop()
if self.start(qemuparams):
@@ -323,59 +609,36 @@ class QemuRunner:
return False
def is_alive(self):
- if not self.runqemu:
+ if not self.runqemu or self.runqemu.poll() is not None or self.runqemu_exited:
return False
- qemu_child = self.find_child(str(self.runqemu.pid))
- if qemu_child:
- self.qemupid = qemu_child[0]
- if os.path.exists("/proc/" + str(self.qemupid)):
- return True
+ if os.path.isfile(self.qemu_pidfile):
+ # when handling pidfile, qemu creates the file, stat it, lock it and then write to it
+ # so it's possible that the file has been created but the content is empty
+ pidfile_timeout = time.time() + 3
+ while time.time() < pidfile_timeout:
+ with open(self.qemu_pidfile, 'r') as f:
+ qemu_pid = f.read().strip()
+ # file created but not yet written contents
+ if not qemu_pid:
+ time.sleep(0.5)
+ continue
+ else:
+ if os.path.exists("/proc/" + qemu_pid):
+ self.qemupid = int(qemu_pid)
+ return True
return False
- def find_child(self,parent_pid):
- #
- # Walk the process tree from the process specified looking for a qemu-system. Return its [pid'cmd]
- #
- ps = subprocess.Popen(['ps', 'axww', '-o', 'pid,ppid,command'], stdout=subprocess.PIPE).communicate()[0]
- processes = ps.decode("utf-8").split('\n')
- nfields = len(processes[0].split()) - 1
- pids = {}
- commands = {}
- for row in processes[1:]:
- data = row.split(None, nfields)
- if len(data) != 3:
- continue
- if data[1] not in pids:
- pids[data[1]] = []
-
- pids[data[1]].append(data[0])
- commands[data[0]] = data[2]
-
- if parent_pid not in pids:
- return []
-
- parents = []
- newparents = pids[parent_pid]
- while newparents:
- next = []
- for p in newparents:
- if p in pids:
- for n in pids[p]:
- if n not in parents and n not in next:
- next.append(n)
- if p not in parents:
- parents.append(p)
- newparents = next
- #print("Children matching %s:" % str(parents))
- for p in parents:
- # Need to be careful here since runqemu-internal runs "ldd qemu-system-xxxx"
- # Also, old versions of ldd (2.11) run "LD_XXXX qemu-system-xxxx"
- basecmd = commands[p].split()[0]
- basecmd = os.path.basename(basecmd)
- if "qemu-system" in basecmd and "-serial tcp" in commands[p]:
- return [int(p),commands[p]]
-
- def run_serial(self, command, raw=False):
+ def run_monitor(self, command, args=None, timeout=60):
+ if hasattr(self, 'qmp') and self.qmp:
+ self.qmp.settimeout(timeout)
+ if args is not None:
+ return self.qmp.cmd(command, args)
+ else:
+ return self.qmp.cmd(command)
+
+ def run_serial(self, command, raw=False, timeout=60):
+ # Returns (status, output) where status is 1 on success and 0 on error
+
# We assume target system have echo to get command status
if not raw:
command = "%s; echo $?\n" % command
@@ -383,20 +646,30 @@ class QemuRunner:
data = ''
status = 0
self.server_socket.sendall(command.encode('utf-8'))
- keepreading = True
- while keepreading:
- sread, _, _ = select.select([self.server_socket],[],[],5)
+ start = time.time()
+ end = start + timeout
+ while True:
+ now = time.time()
+ if now >= end:
+ data += "<<< run_serial(): command timed out after %d seconds without output >>>\r\n\r\n" % timeout
+ break
+ try:
+ sread, _, _ = select.select([self.server_socket],[],[], end - now)
+ except InterruptedError:
+ continue
if sread:
+ # try to avoid reading single character at a time
+ time.sleep(0.1)
answer = self.server_socket.recv(1024)
if answer:
data += answer.decode('utf-8')
# Search the prompt to stop
- if re.search("[a-zA-Z0-9]+@[a-zA-Z0-9\-]+:~#", data):
- keepreading = False
+ if re.search(self.boot_patterns['search_cmd_finished'], data):
+ break
else:
- raise Exception("No data on serial console socket")
- else:
- keepreading = False
+ if self.canexit:
+ return (1, "")
+ raise Exception("No data on serial console socket, connection closed?")
if data:
if raw:
@@ -418,7 +691,7 @@ class QemuRunner:
def _dump_host(self):
self.host_dumper.create_dir("qemu")
- logger.warn("Qemu ended unexpectedly, dump data from host"
+ self.logger.warning("Qemu ended unexpectedly, dump data from host"
" is in %s" % self.host_dumper.dump_dir)
self.host_dumper.dump_host()
@@ -434,6 +707,7 @@ class LoggingThread(threading.Thread):
self.logger = logger
self.readsock = None
self.running = False
+ self.canexit = False
self.errorevents = select.POLLERR | select.POLLHUP | select.POLLNVAL
self.readevents = select.POLLIN | select.POLLPRI
@@ -447,17 +721,17 @@ class LoggingThread(threading.Thread):
self.teardown()
def run(self):
- self.logger.info("Starting logging thread")
+ self.logger.debug("Starting logging thread")
self.readpipe, self.writepipe = os.pipe()
threading.Thread.run(self)
def stop(self):
- self.logger.info("Stopping logging thread")
+ self.logger.debug("Stopping logging thread")
if self.running:
os.write(self.writepipe, bytes("stop", "utf-8"))
def teardown(self):
- self.logger.info("Tearing down logging thread")
+ self.logger.debug("Tearing down logging thread")
self.close_socket(self.serversock)
if self.readsock is not None:
@@ -467,6 +741,9 @@ class LoggingThread(threading.Thread):
self.close_ignore_error(self.writepipe)
self.running = False
+ def allowexit(self):
+ self.canexit = True
+
def eventloop(self):
poll = select.poll()
event_read_mask = self.errorevents | self.readevents
@@ -475,7 +752,7 @@ class LoggingThread(threading.Thread):
breakout = False
self.running = True
- self.logger.info("Starting thread event loop")
+ self.logger.debug("Starting thread event loop")
while not breakout:
events = poll.poll()
for event in events:
@@ -485,19 +762,19 @@ class LoggingThread(threading.Thread):
# Event to stop the thread
if self.readpipe == event[0]:
- self.logger.info("Stop event received")
+ self.logger.debug("Stop event received")
breakout = True
break
# A connection request was received
elif self.serversock.fileno() == event[0]:
- self.logger.info("Connection request received")
+ self.logger.debug("Connection request received")
self.readsock, _ = self.serversock.accept()
self.readsock.setblocking(0)
poll.unregister(self.serversock.fileno())
poll.register(self.readsock.fileno(), event_read_mask)
- self.logger.info("Setting connection established event")
+ self.logger.debug("Setting connection established event")
self.connection_established.set()
# Actual data to be logged
@@ -512,7 +789,7 @@ class LoggingThread(threading.Thread):
data = self.readsock.recv(count)
except socket.error as e:
if e.errno == errno.EAGAIN or e.errno == errno.EWOULDBLOCK:
- return ''
+ return b''
else:
raise
@@ -523,7 +800,9 @@ class LoggingThread(threading.Thread):
# happened. But for this code it counts as an
# error since the connection shouldn't go away
# until qemu exits.
- raise Exception("Console connection closed unexpectedly")
+ if not self.canexit:
+ raise Exception("Console connection closed unexpectedly")
+ return b''
return data
diff --git a/meta/lib/oeqa/utils/qemutinyrunner.py b/meta/lib/oeqa/utils/qemutinyrunner.py
index c823157ad6..20009401ca 100644
--- a/meta/lib/oeqa/utils/qemutinyrunner.py
+++ b/meta/lib/oeqa/utils/qemutinyrunner.py
@@ -1,6 +1,8 @@
+#
# Copyright (C) 2015 Intel Corporation
#
-# Released under the MIT license (see COPYING.MIT)
+# SPDX-License-Identifier: MIT
+#
# This module provides a class for starting qemu images of poky tiny.
# It's used by testimage.bbclass.
@@ -17,7 +19,7 @@ from .qemurunner import QemuRunner
class QemuTinyRunner(QemuRunner):
- def __init__(self, machine, rootfs, display, tmpdir, deploy_dir_image, logfile, kernel, boottime):
+ def __init__(self, machine, rootfs, display, tmpdir, deploy_dir_image, logfile, kernel, boottime, logger, tmpfsdir=None):
# Popen object for runqemu
self.runqemu = None
@@ -35,11 +37,13 @@ class QemuTinyRunner(QemuRunner):
self.deploy_dir_image = deploy_dir_image
self.logfile = logfile
self.boottime = boottime
+ self.tmpfsdir = tmpfsdir
self.runqemutime = 60
self.socketfile = "console.sock"
self.server_socket = None
self.kernel = kernel
+ self.logger = logger
def create_socket(self):
@@ -60,7 +64,7 @@ class QemuTinyRunner(QemuRunner):
with open(self.logfile, "a") as f:
f.write("%s" % msg)
- def start(self, qemuparams = None):
+ def start(self, qemuparams = None, ssh=True, extra_bootparams=None, runqemuparams='', discard_writes=True):
if self.display:
os.environ["DISPLAY"] = self.display
@@ -80,6 +84,9 @@ class QemuTinyRunner(QemuRunner):
return False
else:
os.environ["DEPLOY_DIR_IMAGE"] = self.deploy_dir_image
+ if self.tmpfsdir:
+ env["RUNQEMU_TMPFS_DIR"] = self.tmpfsdir
+
# Set this flag so that Qemu doesn't do any grabs as SDL grabs interact
# badly with screensavers.
@@ -107,14 +114,17 @@ class QemuTinyRunner(QemuRunner):
return self.is_alive()
- def run_serial(self, command):
+ def run_serial(self, command, timeout=60):
self.server_socket.sendall(command+'\n')
data = ''
status = 0
stopread = False
- endtime = time.time()+5
+ endtime = time.time()+timeout
while time.time()<endtime and not stopread:
- sread, _, _ = select.select([self.server_socket],[],[],5)
+ try:
+ sread, _, _ = select.select([self.server_socket],[],[],1)
+ except InterruptedError:
+ continue
for sock in sread:
answer = sock.recv(1024)
if answer:
@@ -124,13 +134,15 @@ class QemuTinyRunner(QemuRunner):
stopread = True
if not data:
status = 1
+ if not stopread:
+ data += "<<< run_serial(): command timed out after %d seconds without output >>>\r\n\r\n" % timeout
return (status, str(data))
def find_child(self,parent_pid):
#
# Walk the process tree from the process specified looking for a qemu-system. Return its [pid'cmd]
#
- ps = subprocess.Popen(['ps', 'axww', '-o', 'pid,ppid,command'], stdout=subprocess.PIPE).communicate()[0]
+ ps = subprocess.Popen(['ps', 'axww', '-o', 'pid,ppid,pri,ni,command'], stdout=subprocess.PIPE).communicate()[0]
processes = ps.decode("utf-8").split('\n')
nfields = len(processes[0].split()) - 1
pids = {}
@@ -162,9 +174,9 @@ class QemuTinyRunner(QemuRunner):
newparents = next
#print("Children matching %s:" % str(parents))
for p in parents:
- # Need to be careful here since runqemu-internal runs "ldd qemu-system-xxxx"
+ # Need to be careful here since runqemu runs "ldd qemu-system-xxxx"
# Also, old versions of ldd (2.11) run "LD_XXXX qemu-system-xxxx"
basecmd = commands[p].split()[0]
basecmd = os.path.basename(basecmd)
if "qemu-system" in basecmd and "-serial unix" in commands[p]:
- return [int(p),commands[p]] \ No newline at end of file
+ return [int(p),commands[p]]
diff --git a/meta/lib/oeqa/utils/sshcontrol.py b/meta/lib/oeqa/utils/sshcontrol.py
index f5d46e03cc..36c2ecb3db 100644
--- a/meta/lib/oeqa/utils/sshcontrol.py
+++ b/meta/lib/oeqa/utils/sshcontrol.py
@@ -1,7 +1,8 @@
-# -*- coding: utf-8 -*-
+#
# Copyright (C) 2013 Intel Corporation
#
-# Released under the MIT license (see COPYING.MIT)
+# SPDX-License-Identifier: MIT
+#
# Provides a class for setting up ssh connections,
# running commands and copying files to/from a target.
@@ -22,7 +23,7 @@ class SSHProcess(object):
"stdin": None,
"shell": False,
"bufsize": -1,
- "preexec_fn": os.setsid,
+ "start_new_session": True,
}
self.options = dict(self.defaultopts)
self.options.update(options)
@@ -52,17 +53,19 @@ class SSHProcess(object):
endtime = self.starttime + timeout
eof = False
while time.time() < endtime and not eof:
- if select.select([self.process.stdout], [], [], 5)[0] != []:
- data = os.read(self.process.stdout.fileno(), 1024)
- if not data:
- self.process.stdout.close()
- eof = True
- else:
- data = data.decode("utf-8")
- output += data
- self.log(data)
- endtime = time.time() + timeout
-
+ try:
+ if select.select([self.process.stdout], [], [], 5)[0] != []:
+ data = os.read(self.process.stdout.fileno(), 1024)
+ if not data:
+ self.process.stdout.close()
+ eof = True
+ else:
+ data = data.decode("utf-8")
+ output += data
+ self.log(data)
+ endtime = time.time() + timeout
+ except InterruptedError:
+ continue
# process hasn't returned yet
if not eof:
@@ -147,6 +150,8 @@ class SSHControl(object):
return self._internal_run(command, timeout, self.ignore_status)
def copy_to(self, localpath, remotepath):
+ if os.path.islink(localpath):
+ localpath = os.path.dirname(localpath) + "/" + os.readlink(localpath)
command = self.scp + [localpath, '%s@%s:%s' % (self.user, self.ip, remotepath)]
return self._internal_run(command, ignore_status=False)
diff --git a/meta/lib/oeqa/utils/subprocesstweak.py b/meta/lib/oeqa/utils/subprocesstweak.py
new file mode 100644
index 0000000000..3e43ed547b
--- /dev/null
+++ b/meta/lib/oeqa/utils/subprocesstweak.py
@@ -0,0 +1,24 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+import subprocess
+
+class OETestCalledProcessError(subprocess.CalledProcessError):
+ def __str__(self):
+ def strify(o):
+ if isinstance(o, bytes):
+ return o.decode("utf-8", errors="replace")
+ else:
+ return o
+
+ s = "Command '%s' returned non-zero exit status %d" % (self.cmd, self.returncode)
+ if hasattr(self, "output") and self.output:
+ s = s + "\nStandard Output: " + strify(self.output)
+ if hasattr(self, "stderr") and self.stderr:
+ s = s + "\nStandard Error: " + strify(self.stderr)
+ return s
+
+def errors_have_output():
+ subprocess.CalledProcessError = OETestCalledProcessError
diff --git a/meta/lib/oeqa/utils/targetbuild.py b/meta/lib/oeqa/utils/targetbuild.py
index 59593f5ef3..09738add1d 100644
--- a/meta/lib/oeqa/utils/targetbuild.py
+++ b/meta/lib/oeqa/utils/targetbuild.py
@@ -1,6 +1,8 @@
+#
# Copyright (C) 2013 Intel Corporation
#
-# Released under the MIT license (see COPYING.MIT)
+# SPDX-License-Identifier: MIT
+#
# Provides a class for automating build tests for projects
@@ -8,15 +10,22 @@ import os
import re
import bb.utils
import subprocess
+import tempfile
from abc import ABCMeta, abstractmethod
class BuildProject(metaclass=ABCMeta):
- def __init__(self, d, uri, foldername=None, tmpdir="/tmp/"):
+ def __init__(self, d, uri, foldername=None, tmpdir=None):
self.d = d
self.uri = uri
self.archive = os.path.basename(uri)
- self.localarchive = os.path.join(tmpdir,self.archive)
+ self.tempdirobj = None
+ if not tmpdir:
+ tmpdir = self.d.getVar('WORKDIR')
+ if not tmpdir:
+ self.tempdirobj = tempfile.TemporaryDirectory(prefix='buildproject-')
+ tmpdir = self.tempdirobj.name
+ self.localarchive = os.path.join(tmpdir, self.archive)
if foldername:
self.fname = foldername
else:
@@ -24,8 +33,7 @@ class BuildProject(metaclass=ABCMeta):
# Download self.archive to self.localarchive
def _download_archive(self):
-
- dl_dir = self.d.getVar("DL_DIR", True)
+ dl_dir = self.d.getVar("DL_DIR")
if dl_dir and os.path.exists(os.path.join(dl_dir, self.archive)):
bb.utils.copyfile(os.path.join(dl_dir, self.archive), self.localarchive)
return
@@ -40,12 +48,12 @@ class BuildProject(metaclass=ABCMeta):
cmd = ''
for var in exportvars:
- val = self.d.getVar(var, True)
+ val = self.d.getVar(var)
if val:
cmd = 'export ' + var + '=\"%s\"; %s' % (val, cmd)
cmd = cmd + "wget -O %s %s" % (self.localarchive, self.uri)
- subprocess.check_call(cmd, shell=True)
+ subprocess.check_output(cmd, shell=True)
# This method should provide a way to run a command in the desired environment.
@abstractmethod
@@ -64,16 +72,17 @@ class BuildProject(metaclass=ABCMeta):
return self._run('cd %s; make install %s' % (self.targetdir, install_args))
def clean(self):
+ if self.tempdirobj:
+ self.tempdirobj.cleanup()
self._run('rm -rf %s' % self.targetdir)
- subprocess.call('rm -f %s' % self.localarchive, shell=True)
- pass
+ subprocess.check_call('rm -f %s' % self.localarchive, shell=True)
class TargetBuildProject(BuildProject):
def __init__(self, target, d, uri, foldername=None):
self.target = target
self.targetdir = "~/"
- BuildProject.__init__(self, d, uri, foldername, tmpdir="/tmp")
+ BuildProject.__init__(self, d, uri, foldername)
def download_archive(self):
@@ -103,8 +112,8 @@ class SDKBuildProject(BuildProject):
self.testdir = testpath
self.targetdir = testpath
bb.utils.mkdirhier(testpath)
- self.datetime = d.getVar('DATETIME', True)
- self.testlogdir = d.getVar("TEST_LOG_DIR", True)
+ self.datetime = d.getVar('DATETIME')
+ self.testlogdir = d.getVar("TEST_LOG_DIR")
bb.utils.mkdirhier(self.testlogdir)
self.logfile = os.path.join(self.testlogdir, "sdk_target_log.%s" % self.datetime)
BuildProject.__init__(self, d, uri, foldername, tmpdir=testpath)
@@ -114,7 +123,7 @@ class SDKBuildProject(BuildProject):
self._download_archive()
cmd = 'tar xf %s%s -C %s' % (self.targetdir, self.archive, self.targetdir)
- subprocess.check_call(cmd, shell=True)
+ subprocess.check_output(cmd, shell=True)
#Change targetdir to project folder
self.targetdir = os.path.join(self.targetdir, self.fname)
@@ -132,4 +141,4 @@ class SDKBuildProject(BuildProject):
def _run(self, cmd):
self.log("Running . %s; " % self.sdkenv + cmd)
- return subprocess.call(". %s; " % self.sdkenv + cmd, shell=True)
+ return subprocess.check_call(". %s; " % self.sdkenv + cmd, shell=True)
diff --git a/meta/lib/oeqa/utils/testexport.py b/meta/lib/oeqa/utils/testexport.py
index 57be2ca449..e89d130a9c 100644
--- a/meta/lib/oeqa/utils/testexport.py
+++ b/meta/lib/oeqa/utils/testexport.py
@@ -1,6 +1,8 @@
+#
# Copyright (C) 2015 Intel Corporation
#
-# Released under the MIT license (see COPYING.MIT)
+# SPDX-License-Identifier: MIT
+#
# Provides functions to help with exporting binaries obtained from built targets
@@ -72,9 +74,9 @@ def process_binaries(d, params):
return extract_bin_command
if determine_if_poky_env(): # machine with poky environment
- exportpath = d.getVar("TEST_EXPORT_DIR", True) if export_env else d.getVar("DEPLOY_DIR", True)
- rpm_deploy_dir = d.getVar("DEPLOY_DIR_RPM", True)
- arch = get_dest_folder(d.getVar("TUNE_FEATURES", True), os.listdir(rpm_deploy_dir))
+ exportpath = d.getVar("TEST_EXPORT_DIR") if export_env else d.getVar("DEPLOY_DIR")
+ rpm_deploy_dir = d.getVar("DEPLOY_DIR_RPM")
+ arch = get_dest_folder(d.getVar("TUNE_FEATURES"), os.listdir(rpm_deploy_dir))
arch_rpm_dir = os.path.join(rpm_deploy_dir, arch)
extracted_bin_dir = os.path.join(exportpath,"binaries", arch, "extracted_binaries")
packaged_bin_dir = os.path.join(exportpath,"binaries", arch, "packaged_binaries")
@@ -92,7 +94,7 @@ def process_binaries(d, params):
return ""
for item in native_rpm_file_list:# will copy all versions of package. Used version will be selected on remote machine
bb.plain("Copying native package file: %s" % item)
- sh.copy(os.path.join(rpm_deploy_dir, native_rpm_dir, item), os.path.join(d.getVar("TEST_EXPORT_DIR", True), "binaries", "native"))
+ sh.copy(os.path.join(rpm_deploy_dir, native_rpm_dir, item), os.path.join(d.getVar("TEST_EXPORT_DIR"), "binaries", "native"))
else: # nothing to do here; running tests under bitbake, so we asume native binaries are in sysroots dir.
if param_list[1] or param_list[4]:
bb.warn("Native binary %s %s%s. Running tests under bitbake environment. Version can't be checked except when the test itself does it"
@@ -148,7 +150,7 @@ def process_binaries(d, params):
else: # this is for target device
if param_list[2] == "rpm":
return "No need to extract, this is an .rpm file"
- arch = get_dest_folder(d.getVar("TUNE_FEATURES", True), os.listdir(binaries_path))
+ arch = get_dest_folder(d.getVar("TUNE_FEATURES"), os.listdir(binaries_path))
extracted_bin_path = os.path.join(binaries_path, arch, "extracted_binaries")
extracted_bin_list = [item for item in os.listdir(extracted_bin_path)]
packaged_bin_path = os.path.join(binaries_path, arch, "packaged_binaries")
@@ -206,9 +208,9 @@ def send_bin_to_DUT(d,params):
from oeqa.oetest import oeRuntimeTest
param_list = params
cleanup_list = list()
- bins_dir = os.path.join(d.getVar("TEST_EXPORT_DIR", True), "binaries") if determine_if_poky_env() \
+ bins_dir = os.path.join(d.getVar("TEST_EXPORT_DIR"), "binaries") if determine_if_poky_env() \
else os.getenv("bin_dir")
- arch = get_dest_folder(d.getVar("TUNE_FEATURES", True), os.listdir(bins_dir))
+ arch = get_dest_folder(d.getVar("TUNE_FEATURES"), os.listdir(bins_dir))
arch_rpms_dir = os.path.join(bins_dir, arch, "packaged_binaries")
extracted_bin_dir = os.path.join(bins_dir, arch, "extracted_binaries", param_list[0])
diff --git a/meta/lib/rootfspostcommands.py b/meta/lib/rootfspostcommands.py
new file mode 100644
index 0000000000..5386eea409
--- /dev/null
+++ b/meta/lib/rootfspostcommands.py
@@ -0,0 +1,90 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: GPL-2.0-only
+#
+
+import os
+
+def sort_shadowutils_file(filename, mapping):
+ """
+ Sorts a passwd or group file based on the numeric ID in the third column.
+ If a mapping is given, the name from the first column is mapped via that
+ dictionary instead (necessary for /etc/shadow and /etc/gshadow). If not,
+ a new mapping is created on the fly and returned.
+ """
+
+ new_mapping = {}
+ with open(filename, 'rb+') as f:
+ lines = f.readlines()
+ # No explicit error checking for the sake of simplicity. /etc
+ # files are assumed to be well-formed, causing exceptions if
+ # not.
+ for line in lines:
+ entries = line.split(b':')
+ name = entries[0]
+ if mapping is None:
+ id = int(entries[2])
+ else:
+ id = mapping[name]
+ new_mapping[name] = id
+ # Sort by numeric id first, with entire line as secondary key
+ # (just in case that there is more than one entry for the same id).
+ lines.sort(key=lambda line: (new_mapping[line.split(b':')[0]], line))
+ # We overwrite the entire file, i.e. no truncate() necessary.
+ f.seek(0)
+ f.write(b''.join(lines))
+
+ return new_mapping
+
+def sort_shadowutils_files(sysconfdir):
+ """
+ Sorts shadow-utils 'passwd' and 'group' files in a rootfs' /etc directory
+ by ID.
+ """
+
+ for main, shadow in (('passwd', 'shadow'),
+ ('group', 'gshadow')):
+ filename = os.path.join(sysconfdir, main)
+ if os.path.exists(filename):
+ mapping = sort_shadowutils_file(filename, None)
+ filename = os.path.join(sysconfdir, shadow)
+ if os.path.exists(filename):
+ sort_shadowutils_file(filename, mapping)
+
+def remove_shadowutils_backup_file(filename):
+ """
+ Remove shadow-utils backup file for files like /etc/passwd.
+ """
+
+ backup_filename = filename + '-'
+ if os.path.exists(backup_filename):
+ os.unlink(backup_filename)
+
+def remove_shadowutils_backup_files(sysconfdir):
+ """
+ Remove shadow-utils backup files in a rootfs /etc directory. They are not
+ needed in the initial root filesystem and sorting them can be inconsistent
+ (YOCTO #11043).
+ """
+
+ for filename in (
+ 'group',
+ 'gshadow',
+ 'passwd',
+ 'shadow',
+ 'subgid',
+ 'subuid',
+ ):
+ filepath = os.path.join(sysconfdir, filename)
+ remove_shadowutils_backup_file(filepath)
+
+def tidy_shadowutils_files(sysconfdir):
+ """
+ Tidy up shadow-utils files.
+ """
+
+ remove_shadowutils_backup_files(sysconfdir)
+ sort_shadowutils_files(sysconfdir)
+
+ return True