From 142d826bd7f2131fcd70548e8481bc5883905a6f Mon Sep 17 00:00:00 2001 From: probonopd Date: Thu, 28 Nov 2024 14:19:48 +0000 Subject: [PATCH 1/7] Remove files that are no longer used --- .github/workflows/build.yml | 58 - .gitmodules | 6 - CMakeLists.txt | 91 -- CONTRIBUTING.md | 41 - Makefile.runtime | 50 - build-tool-osx.sh | 116 -- ci/build-appdir.sh | 91 -- ci/build-binaries-and-appimage.sh | 105 -- ci/build.sh | 140 -- ci/test-appimage.sh | 46 - ci/test-appimagetool.sh | 145 --- cmake/cpack_debs.cmake | 46 - cmake/dependencies.cmake | 90 -- cmake/sanitizers-cmake | 1 - cmake/toolchains/aarch64-linux-gnu.cmake | 20 - cmake/toolchains/arm-linux-gnueabihf.cmake | 20 - cmake/toolchains/i386-linux-gnu.cmake | 31 - lib/CMakeLists.txt | 1 - lib/libappimage | 1 - resources/AppRun | 12 - resources/appimagetool.desktop | 9 - resources/appimagetool.png | Bin 9773 -> 0 bytes resources/appimagetool.svg | 320 ----- resources/liblz4.pc | 14 - resources/pubkey.asc | 30 - .../share/metainfo/appimagetool.appdata.xml | 31 - squashfs_osx.patch | 434 ------- src/AppRun.c | 219 ---- src/CMakeLists.txt | 169 --- src/appimagetool.c | 1153 ----------------- src/appimagetool_sign.c | 479 ------- src/appimagetool_sign.h | 5 - src/appimagetoolnoglib.c | 307 ----- src/binreloc.c | 766 ----------- src/binreloc.h | 80 -- src/build-runtime.cmake | 148 --- src/digest.c | 145 --- src/digest_md5.c | 98 -- src/embed-magic-bytes-in-file.sh | 8 - src/light_elf.h | 123 -- src/notify.c | 91 -- src/runtime.c | 958 -------------- src/validate.c | 204 --- testappimage | 205 --- 44 files changed, 7107 deletions(-) delete mode 100644 .github/workflows/build.yml delete mode 100644 .gitmodules delete mode 100644 CMakeLists.txt delete mode 100644 CONTRIBUTING.md delete mode 100644 Makefile.runtime delete mode 100755 build-tool-osx.sh delete mode 100755 ci/build-appdir.sh delete mode 100755 ci/build-binaries-and-appimage.sh delete mode 100755 ci/build.sh delete mode 100755 ci/test-appimage.sh delete mode 100755 ci/test-appimagetool.sh delete mode 100644 cmake/cpack_debs.cmake delete mode 100644 cmake/dependencies.cmake delete mode 160000 cmake/sanitizers-cmake delete mode 100644 cmake/toolchains/aarch64-linux-gnu.cmake delete mode 100644 cmake/toolchains/arm-linux-gnueabihf.cmake delete mode 100644 cmake/toolchains/i386-linux-gnu.cmake delete mode 100644 lib/CMakeLists.txt delete mode 160000 lib/libappimage delete mode 100755 resources/AppRun delete mode 100644 resources/appimagetool.desktop delete mode 100644 resources/appimagetool.png delete mode 100644 resources/appimagetool.svg delete mode 100644 resources/liblz4.pc delete mode 100644 resources/pubkey.asc delete mode 100644 resources/usr/share/metainfo/appimagetool.appdata.xml delete mode 100644 squashfs_osx.patch delete mode 100644 src/AppRun.c delete mode 100644 src/CMakeLists.txt delete mode 100644 src/appimagetool.c delete mode 100644 src/appimagetool_sign.c delete mode 100644 src/appimagetool_sign.h delete mode 100644 src/appimagetoolnoglib.c delete mode 100644 src/binreloc.c delete mode 100644 src/binreloc.h delete mode 100644 src/build-runtime.cmake delete mode 100644 src/digest.c delete mode 100644 src/digest_md5.c delete mode 100755 src/embed-magic-bytes-in-file.sh delete mode 100644 src/light_elf.h delete mode 100644 src/notify.c delete mode 100644 src/runtime.c delete mode 100644 src/validate.c delete mode 100644 testappimage diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml deleted file mode 100644 index 327e27302..000000000 --- a/.github/workflows/build.yml +++ /dev/null @@ -1,58 +0,0 @@ -name: Build - -on: [ push, pull_request, workflow_dispatch ] - - -jobs: - build: - name: Build - runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - ARCH: ['x86_64', 'i386', 'armhf', 'aarch64'] - - env: - ARCH: ${{ matrix.ARCH }} - - steps: - - uses: actions/checkout@v2 - with: - submodules: 'recursive' - - - name: Set up QEMU integration for Docker - run: docker run --rm --privileged multiarch/qemu-user-static --reset -p yes - - - name: Build - run: | - bash -ex ci/build.sh - - - name: List files - run: | - ls -lh out/ - - - name: Upload artifact - uses: actions/upload-artifact@v1.0.0 - with: - # Artifact name - name: appimagetool-${{ matrix.ARCH }}.build - path: out/ - - - upload: - name: Create release and upload artifacts - needs: - - build - runs-on: ubuntu-20.04 - steps: - - name: Download artifacts - uses: actions/download-artifact@v2 - - name: Inspect directory after downloading artifacts - run: ls -alFR - - name: Create release and upload artifacts - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - wget -q https://github.com/TheAssassin/pyuploadtool/releases/download/continuous/pyuploadtool-x86_64.AppImage - chmod +x pyuploadtool-x86_64.AppImage - ./pyuploadtool-x86_64.AppImage **/appimagetool*.AppImage* **/AppRun* **/runtime-* diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index a5daa46d3..000000000 --- a/.gitmodules +++ /dev/null @@ -1,6 +0,0 @@ -[submodule "cmake/sanitizers-cmake"] - path = cmake/sanitizers-cmake - url = https://github.com/arsenm/sanitizers-cmake -[submodule "lib/libappimage"] - path = lib/libappimage - url = https://github.com/AppImage/libappimage.git diff --git a/CMakeLists.txt b/CMakeLists.txt deleted file mode 100644 index 219f4b75e..000000000 --- a/CMakeLists.txt +++ /dev/null @@ -1,91 +0,0 @@ -cmake_minimum_required(VERSION 3.2) - -project(AppImageKit) - -include(ExternalProject) - -# enable testing globally -include(CTest) - -# support for ccache -# call CMake with -DUSE_CCACHE=ON to make use of it -set(USE_CCACHE OFF CACHE BOOL "") -if(USE_CCACHE) - find_program(CCACHE ccache) - if(CCACHE) - message(STATUS "Using ccache") - set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ${CCACHE}) - set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ${CCACHE}) - else() - message(WARNING "USE_CCACHE set, but could not find ccache") - endif() -endif() - - -##################### -# build information # -##################### - -# determine Git commit ID -execute_process( - COMMAND git rev-parse --short HEAD - WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} - OUTPUT_VARIABLE GIT_COMMIT - OUTPUT_STRIP_TRAILING_WHITESPACE -) - -# set version and build number -set(VERSION 1-alpha) -mark_as_advanced(VERSION) -if("$ENV{TRAVIS_BUILD_NUMBER}" STREQUAL "") - set(BUILD_NUMBER "") -else() - set(BUILD_NUMBER "$ENV{TRAVIS_BUILD_NUMBER}") -endif() -mark_as_advanced(BUILD_NUMBER) - -# get current date -execute_process( - COMMAND env LC_ALL=C date -u "+%Y-%m-%d %H:%M:%S %Z" - OUTPUT_VARIABLE DATE - OUTPUT_STRIP_TRAILING_WHITESPACE -) - -# C and C++ versions -set(CMAKE_C_STANDARD 99) -set(CMAKE_CXX_STANDARD 98) -set(CMAKE_C_STANDARD_REQUIRED ON) -set(CMAKE_CXX_STANDARD_REQUIRED ON) -set(CMAKE_POSITION_INDEPENDENT_CODE ON) - - -########################## -# configure dependencies # -########################## - -set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${PROJECT_SOURCE_DIR}/cmake) - -# configure dependencies -add_subdirectory(lib) - -include(lib/libappimage/cmake/tools.cmake) -include(cmake/dependencies.cmake) - - -################ -# Source files # -################ - -# sanitizer support -set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake/sanitizers-cmake/cmake" ${CMAKE_MODULE_PATH}) - -add_subdirectory(src) - -################################ -# packaging # -################################ -set(APPIMAGEKIT_PACKAGE_DEBS FALSE CACHE BOOL "") - -if(APPIMAGEKIT_PACKAGE_DEBS) - include(cmake/cpack_debs.cmake) -endif() diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md deleted file mode 100644 index 421a99a16..000000000 --- a/CONTRIBUTING.md +++ /dev/null @@ -1,41 +0,0 @@ -# Contributing - -Welcome to AppImage. A good starting point for most questions is our wiki at https://github.com/AppImage/AppImageKit/wiki - -## How to contribute - -### I would like to request an AppImage for an application - -If there is no AppImage of your favorite application available, please request it from the author(s) of the application, e.g., as a feature request in the issue tracker of the application. For example, if you would like to see an AppImage of Mozilla Firefox, then please leave a comment at https://bugzilla.mozilla.org/show_bug.cgi?id=1249971. The more people request an AppImage from the upstream authors, the more likely is that an AppImage will be provided. - -### I would like to provide an AppImage for my application - -If you are an application author and would like to make your application available as an AppImage, please start here: https://github.com/AppImage/AppImageKit/wiki/Creating-AppImages. Feel free to open a [GitHub Issue](https://github.com/AppImage/AppImageKit/issues) in the AppImageKit project if you need support using the tools provided by AppImageKit. - -### I would like to have my AppImage included in the AppImageHub central directory of available AppImages - -Please see the [AppImageHub Readme](https://github.com/AppImage/appimage.github.io/blob/master/README.md). - -### I would like to contribute to AppImageKit development - -Your contribution is especially welcome in these ares: - -* [__High-priority__ issues we need help with](https://github.com/search?utf8=%E2%9C%93&q=org%3AAppImage+label%3Ahelp-wanted+state%3Aopen+label%3Ahigh-priority&type=Issues) -* [Issues we need help with](https://github.com/search?utf8=%E2%9C%93&q=org%3AAppImage+state%3Aopen+label%3Ahigh-priority&type=Issues) -* [Open bugs](https://github.com/search?utf8=%E2%9C%93&q=org%3AAppImage+label%3Abug+state%3Aopen&type=Issues) - -If you would like to report issues with AppImageKit itself, or would like to contribute to its development, please see get in touch with us in `#AppImage` on `irc.libera.chat`. We welcome pull requests addressing any of the open issues and/or other bugfixes and/or feature additions. In the case of complex feature additions, it is best to contact us first, before you spend much time. - -## Project governance - -Founder and project leader Simon Peter (probonopd) reserves the right to define the AppImage format, brand, high-level architecture, user experience, and project governance - -## Rules for contributing - -* The only supported version is git master -* We do not bugfix any versions other than git master -* Versions other than git master are considered outdated and obsolete -* Our software comes in AppImage format. Everything else is unsupported by us -* If git master breaks, all other work stops and every contributor focuses exclusively on un-breaking master -* Every contribution shall be sent as a pull request, which must build "green" before it is merged -* Pinned issues shall be closed before other issues are being worked on diff --git a/Makefile.runtime b/Makefile.runtime deleted file mode 100644 index dcda0126d..000000000 --- a/Makefile.runtime +++ /dev/null @@ -1,50 +0,0 @@ -CC = gcc -CFLAGS = -std=gnu99 -Wall -Wno-unused-parameter -Wno-unused-result -Wformat-security -Os -g -STRIP = strip -MAGIC = echo "8: 414902" | xxd -r - -MKDIR = mkdir -p -COPY = cp -f -COPY_FILE = $(COPY) - -all: runtime -.PHONY: all embed mrproper - -# Prepare 1024 bytes of space for updateinformation -1024_blank_bytes: - #printf '\0%.0s' {0..1023} > $@ - echo "03FF: 00" | xxd -r > $@ - stat $@ - -# Compile runtime but do not link -runtime.o: runtime.c - $(CC) -c $(CFLAGS) $^ -DGIT_COMMIT=\"$(git describe --tags --always --abbrev=7)\" \ - -I./squashfuse/ -D_FILE_OFFSET_BITS=64 - -# Add .upd_info and .sha256_sig sections -embed: 1024_blank_bytes runtime - objcopy --add-section .upd_info=1024_blank_bytes \ - --set-section-flags .upd_info=noload,readonly runtime - objcopy --add-section .sha256_sig=1024_blank_bytes \ - --set-section-flags .sha256_sig=noload,readonly runtime - stat runtime - -# Now statically link against libsquashfuse_ll, libsquashfuse and liblzma -# TODO: generate runtime in function of the compressor we choose to avoid embeded unnecessary compression. -runtime: runtime.o notify.o elf.o getsection.o - $(CC) $(CFLAGS) $^ ./squashfuse/.libs/libsquashfuse_ll.a \ - ./squashfuse/.libs/libsquashfuse.a ./squashfuse/.libs/libfuseprivate.a \ - -lfuse -lpthread -lz -linotifytools -ldl `pkg-config --libs liblzma liblz4` -o runtime - -install: runtime embed - $(MKDIR) build - $(COPY_FILE) runtime build - $(STRIP) build/runtime - # Insert AppImage magic bytes at offset 8 - # verify with : xxd -ps -s 0x8 -l 3 build/runtime - $(MAGIC) build/runtime - -clean: - rm -f *.o 1024_blank_bytes - -mrproper: clean - rm -f runtime diff --git a/build-tool-osx.sh b/build-tool-osx.sh deleted file mode 100755 index f49c0c8cb..000000000 --- a/build-tool-osx.sh +++ /dev/null @@ -1,116 +0,0 @@ -#!/bin/bash -# -# This script installs the required build-time dependencies -# and builds AppImageTool on OSX -# - -small_FLAGS="-Os -ffunction-sections -fdata-sections" -CC="cc -O2 -Wall -Wno-deprecated-declarations -Wno-unused-result" - -STRIP="strip" -JOBS=${JOBS:-1} - -echo $KEY | md5sum - -set -e -set -x - -HERE="$(dirname "$(readlink -f "${0}")")" -cd "$HERE" - -# Fetch git submodules -git submodule init -git submodule update - -# Clean up from previous run -rm -rf build/ || true - -# Build lzma always static because the runtime gets distributed with -# the generated .AppImage file. -if [ ! -e "./xz-5.2.3/build/lib/liblzma.a" ] ; then - wget -c http://tukaani.org/xz/xz-5.2.3.tar.gz - tar xf xz-5.2.3.tar.gz - cd xz-5.2.3 - mkdir -p build/lib - CFLAGS="-Wall $small_FLAGS" ./configure --prefix=$(pwd)/build --libdir=$(pwd)/build/lib --enable-static --disable-shared - make -j$JOBS && make install - cd - -fi - -# Patch squashfuse_ll to be a library rather than an executable - -cd squashfuse -if [ ! -e ./ll.c.orig ]; then - patch -p1 --backup < ../squashfuse.patch - patch -p1 --backup < ../squashfuse_dlopen.patch -fi -if [ ! -e ./squashfuse_dlopen.c ]; then - cp ../squashfuse_dlopen.c . -fi -if [ ! -e ./squashfuse_dlopen.h ]; then - cp ../squashfuse_dlopen.h . -fi - -# Build libsquashfuse_ll library - -if [ ! -e ./Makefile ] ; then - export ACLOCAL_FLAGS="-I /usr/share/aclocal" - glibtoolize --force - aclocal - autoheader - automake --force-missing --add-missing - autoreconf -fi || true # Errors out, but the following succeeds then? - autoconf - sed -i "" '/PKG_CHECK_MODULES.*/,/,:./d' configure # https://github.com/vasi/squashfuse/issues/12 - CFLAGS="-Wall $small_FLAGS" ./configure --disable-demo --disable-high-level --without-lzo --without-lz4 --with-xz=$(pwd)/../xz-5.2.3/build - - # Patch Makefile to use static lzma - sed -i "" "s|XZ_LIBS = -llzma -L$(pwd)/../xz-5.2.3/build/lib|XZ_LIBS = -Bstatic -llzma -L$(pwd)/../xz-5.2.3/build/lib|g" Makefile -fi - -bash --version - -make -j$JOBS - -cd .. - -# Build mksquashfs with -offset option to skip n bytes -# https://github.com/plougher/squashfs-tools/pull/13 -cd squashfs-tools -if [ ! -e squashfs-tools/action.c.orig ] ; then - patch -p1 --backup < ../squashfs_osx.patch -fi -cd squashfs-tools - -# Patch squashfuse-tools Makefile to link against static llzma -sed -i "" "s|CFLAGS += -DXZ_SUPPORT|CFLAGS += -DXZ_SUPPORT -I../../xz-5.2.3/build/include|g" Makefile -sed -i "" "s|LIBS += -llzma|LIBS += -Bstatic -llzma -L../../xz-5.2.3/build/lib|g" Makefile - -make -j$JOBS XZ_SUPPORT=1 mksquashfs # LZ4_SUPPORT=1 did not build yet on CentOS 6 -$STRIP mksquashfs - -cd ../../ - -pwd - -mkdir build -cd build - -cp ../squashfs-tools/squashfs-tools/mksquashfs . - - -# Compile appimagetool but do not link - glib version - -$CC -DGIT_COMMIT=\"$(git describe --tags --always --abbrev=7)\" -D_FILE_OFFSET_BITS=64 -I../squashfuse/ \ - $(pkg-config --cflags glib-2.0) -g -Os ../getsection.c -c ../appimagetool.c - -# Now statically link against libsquashfuse - glib version - - # statically link against liblzma - $CC -o appimagetool appimagetool.o ../elf.c ../getsection.c -DENABLE_BINRELOC ../binreloc.c \ - ../squashfuse/.libs/libsquashfuse.a ../squashfuse/.libs/libfuseprivate.a \ - -L../xz-5.2.3/build/lib \ - -ldl -lpthread \ - $(pkg-config --cflags --libs glib-2.0) -lz -llzma - - diff --git a/ci/build-appdir.sh b/ci/build-appdir.sh deleted file mode 100755 index 6e5aa5ff2..000000000 --- a/ci/build-appdir.sh +++ /dev/null @@ -1,91 +0,0 @@ -#!/bin/bash - -set -e -set -x -set -o functrace - -if [[ "$3" == "" ]]; then - echo "Usage: bash $0 " - exit 2 -fi - -# using shift makes adding/removing parameters easier -repo_root="$1" -shift -install_prefix="$1" -shift -appimagetool_appdir="$1" - -if [[ ! -d "$install_prefix" ]]; then - echo "Error: could not find install-prefix directory: $install_prefix" - exit 3 -fi - -if [[ ! -d "$repo_root" ]]; then - echo "Error: could not find repo root directory: $repo_root" - exit 4 -fi - -if [[ -d "$appimagetool_appdir" ]]; then - echo "Warning: removing existing appimagetool AppDir: $appimagetool_appdir" - rm -rf "$appimagetool_appdir" -fi - -# Run make install only for the appimagetool component to deploy appimagetools files to -# the $appimagetool_appdir -DESTDIR="$appimagetool_appdir" cmake -DCOMPONENT=appimagetool -P cmake_install.cmake - -mkdir -p "$appimagetool_appdir"/usr/lib/appimagekit/ - -# Copy AppDir specific files -cp "$repo_root"/resources/AppRun "$appimagetool_appdir" -cp "$install_prefix"/usr/lib/appimagekit/mksquashfs "$appimagetool_appdir"/usr/lib/appimagekit/ - -# prefer binaries from /deps, if available -export PATH=/deps/bin:"$PATH" -cp "$(which desktop-file-validate)" "$appimagetool_appdir"/usr/bin/ -cp "$(which zsyncmake)" "$appimagetool_appdir"/usr/bin/ - -cp "$repo_root"/resources/appimagetool.desktop "$appimagetool_appdir" -cp "$repo_root"/resources/appimagetool.png "$appimagetool_appdir"/appimagetool.png -cp "$appimagetool_appdir"/appimagetool.png "$appimagetool_appdir"/.DirIcon - -# bundle desktop-file-validate -# https://github.com/AppImage/AppImageKit/issues/1171 -install -D "$(which desktop-file-validate)" "$appimagetool_appdir"/usr/bin/ - -if [ -d /deps/ ]; then - # deploy GLib, gpgme and gcrypt - mkdir -p "$appimagetool_appdir"/usr/lib/ - cp /deps/lib/lib*.so* "$appimagetool_appdir"/usr/lib/ - - - case "$ARCH" in - x86_64) - libarch=x86-64 - ;; - i686) - # for some reason, ldconfig -p does not list entries with an architecture for i386... - # thankfully, grepping for an empty string is a no-op - libarch= - ;; - armhf) - libarch=arm - ;; - *) - libarch="$ARCH" - ;; - esac - - # libffi is a runtime dynamic dependency - # see this thread for more information on the topic: - # https://mail.gnome.org/archives/gtk-devel-list/2012-July/msg00062.html - # libpcre is used by desktop-file-validate - for pattern in libffi libpcre; do - # even though it is likely not necessary, we deploy every viable version of the libraries just to make sure... - ldconfig -p | grep "$pattern" | grep "$libarch" | while read -r line; do - lib="$(echo "$line" | cut -d'>' -f2 | tr -d ' ')" - cp "$lib" "$appimagetool_appdir"/usr/lib/ - done - done -fi diff --git a/ci/build-binaries-and-appimage.sh b/ci/build-binaries-and-appimage.sh deleted file mode 100755 index 58620730f..000000000 --- a/ci/build-binaries-and-appimage.sh +++ /dev/null @@ -1,105 +0,0 @@ -#! /bin/bash - -set -e -set -x -set -o functrace - -# make sure the prebuilt libraries in the container will be found -# (in case we're building in an AppImageBuild container) -export LD_LIBRARY_PATH=/deps/lib:"$LD_LIBRARY_PATH" -export PKG_CONFIG_PATH=/deps/lib/pkgconfig/ -export PATH=/deps/bin:"$PATH" - -# note: signing is not working at the moment -# see ci-build.sh for more information -echo "$KEY" | md5sum - -# we always build in a temporary directory -# use RAM disk if possible and if enough space available -USE_SHM=0 -if [ -d /dev/shm ] && mount | grep /dev/shm | grep -v -q noexec; then - SHM_FREE_KIB_MIN=$((1 * 1024 * 1024)) - SHM_FREE_KIB=$(df -P -k /dev/shm | tail -n 1 | sed -e 's/ \+/ /g' | cut -d ' ' -f 4) - if [[ "$SHM_FREE_KIB" != "" ]] && [ $SHM_FREE_KIB -ge $SHM_FREE_KIB_MIN ]; then - USE_SHM=1 - fi -fi -if [[ "$USE_SHM" = "1" ]]; then - TEMP_BASE=/dev/shm -elif [ -d /docker-ramdisk ]; then - TEMP_BASE=/docker-ramdisk -else - TEMP_BASE=/tmp -fi - -BUILD_DIR="$(mktemp -d -p "$TEMP_BASE" AppImageKit-build-XXXXXX)" - -cleanup () { - if [ -d "$BUILD_DIR" ]; then - rm -rf "$BUILD_DIR" - fi -} - -trap cleanup EXIT - -REPO_ROOT="$(readlink -f "$(dirname "${BASH_SOURCE[0]}")"/..)" -OLD_CWD="$(readlink -f .)" - -pushd "$BUILD_DIR" - -# configure build and generate build files -cmake "$REPO_ROOT" \ - -DCMAKE_INSTALL_PREFIX=/usr \ - -DCMAKE_BUILD_TYPE=RelWithDebInfo \ - -DBUILD_TESTING=ON \ - -DAPPIMAGEKIT_PACKAGE_DEBS=ON - -# run build -if [[ "$CI" != "" ]]; then - nproc="$(nproc)" -else - nproc="$(nproc --ignore=1)" -fi - -make -j"$nproc" - -# install so-far-built binaries into some prefix -# this way, we can test them, use them to build the AppDir later, copy stuff from there into said AppDir, ... -install_prefix="install-prefix" -make install DESTDIR="$install_prefix" - -# print first few bytes in runtime -# allows checking whether the magic bytes are in place -xxd src/runtime | head -n1 - -# strip everything *but* runtime -find "$install_prefix"/usr/bin/ -not -iname runtime -print -exec "$STRIP" "{}" \; 2>/dev/null - -# more debugging -ls -lh "$install_prefix"/usr/bin -for FILE in "$install_prefix"/usr/bin/*; do - echo "$FILE" - ldd "$FILE" || true -done - -# continue building AppDir -appdir="appimagetool.AppDir" -bash "$REPO_ROOT"/ci/build-appdir.sh "$REPO_ROOT" "$install_prefix" "$appdir" - -# list result -ls -lh -find "$install_prefix" - -# test built appimagetool -"$REPO_ROOT"/ci/test-appimagetool.sh "$REPO_ROOT" "$install_prefix"/usr/bin/appimagetool - -# seems to work -- let's build an AppImage -# we start by putting the rest of the files into the AppDir - -"$appdir"/AppRun ./appimagetool.AppDir/ -v \ - -u "gh-releases-zsync|AppImage|AppImageKit|continuous|appimagetool-$ARCH.AppImage.zsync" \ - appimagetool-"$ARCH".AppImage - -mv -v appimagetool-"$ARCH".AppImage* "$OLD_CWD" -mv -v "$install_prefix"/usr/lib/appimagekit/runtime "$OLD_CWD" -mv -v "$install_prefix"/usr/bin/* "$OLD_CWD" diff --git a/ci/build.sh b/ci/build.sh deleted file mode 100755 index 390170dc2..000000000 --- a/ci/build.sh +++ /dev/null @@ -1,140 +0,0 @@ -#! /bin/bash - -set -e -set -x - -if [[ "$ARCH" == "" ]]; then - echo "Usage: env ARCH=... bash $0" - exit 2 -fi - -# TODO: fix inconsistency in architecture naming *everywhere* -docker_arch= - -case "$ARCH" in - "x86_64") - export ARCH="x86_64" - docker_dist=centos7 - ;; - "i386"|"i686") - export ARCH="i686" - docker_arch="i386" - docker_dist=centos7 - ;; - armhf|aarch64) - docker_dist=bionic - ;; - *) - echo "Unknown architecture: $ARCH" - exit 3 - ;; -esac - - -#### NOTE #### -# Signing is currently broken, as the secret to decrypt the key is not available at the moment. -# Even worse, putting key material in a third-party execution environment is not a good idea -# to begin with. -# The signing doesn't add anything security wise anyway, so it doesn't really matter if it works -# at the moment or not. -#### END NOTE #### - -# clean up and download data from GitHub -#rm -rf data.tar.g* .gnu* || true -#wget https://github.com/AppImage/AppImageKit/files/584665/data.zip -O data.tar.gz.gpg -#( set +x ; echo $KEY | gpg2 --batch --passphrase-fd 0 --no-tty --skip-verify --output data.tar.gz --decrypt data.tar.gz.gpg ) || true -#( tar xf data.tar.gz ; sudo chown -R $USER .gnu* ; rm -rf $HOME/.gnu* ; mv .gnu* $HOME/ ) || true - - -# make sure we're in the repository root directory -this_dir="$(readlink -f "$(dirname "$0")")" -repo_root="$this_dir"/.. - -# docker image name -docker_image=quay.io/appimage/appimagebuild:"$docker_dist"-"${docker_arch:-$ARCH}" -# make sure it's up to date -docker pull "$docker_image" - -# prepare output directory -mkdir -p out/ - -# we run all builds with non-privileged user accounts to make sure the build doesn't depend on such features -uid="$(id -u)" - -# When running under Podman (on hosts where `docker` is a shim that invokes `podman`), -# UID/GID mappings may lead to permission errors when copying artifacts to `/out`. -# We set the user namespace mode to `keep-id` to make sure that the host UID/GID -# are mapped to the same values inside the container, but using this environment -# variable (a) to not affect builds using Docker, and (b) to allow overriding the -# user namespace mode easily if necessary. -export PODMAN_USERNS="${PODMAN_USERNS:-keep-id}" - -# note: we cannot just use '-e ARCH', as this wouldn't overwrite the value set via ENV ARCH=... in the image -common_docker_opts=( - -e TERM="$TERM" - -e ARCH="$ARCH" - -i - -v "$repo_root":/ws - -v "$(readlink -f out/)":/out -) - -# make ctrl-c work -if [[ "$CI" == "" ]] && [[ "$TERM" != "" ]]; then - common_docker_opts+=("-t") -fi - -# build AppImageKit and appimagetool-"$ARCH".AppImage -# TODO: make gnupg home available, e.g., through "-v" "$HOME"/.gnupg:/root/.gnupg -# TODO: this ^ won't work since we don't build as root any more -# note: we enforce using the same UID in the container as outside, so that the created files are owned by the caller -docker run --rm \ - --user "$uid" \ - "${common_docker_opts[@]}" \ - "-v" "$HOME"/.gnupg:/root/.gnupg \ - "$docker_image" \ - /bin/bash -xc "cd /out && /ws/ci/build-binaries-and-appimage.sh --run-tests" - -# test appimagetool-"$ARCH".AppImage -# note: if we're in a CI system, we allow the use of FUSE in the container, to make sure that this functionality works as intended -# outside CI environments, we use APPIMAGE_EXTRACT_AND_RUN instead, which is safer, but gives less meaningful results -# note: FUSE and QEMU don't like each other, so if we're running in emulated mode, we can't run these tests -# therefore, by default, on ARM, these tests are not run -if [[ "$ARCH" != "arm"* ]] && [[ "$ARCH" != "aarch"* ]]; then - docker_test_opts=("${common_docker_opts[@]}") - - if [[ "$CI" != "" ]]; then - echo "Warning: assuming this is running in a CI environment, allowing the use of FUSE in the container" - docker_test_opts+=( - "--device" "/dev/fuse:mrw" - "--cap-add" "SYS_ADMIN" - "--security-opt" "apparmor:unconfined" - ) - else - echo "Note: this is not a CI environment, using APPIMAGE_EXTRACT_AND_RUN and patching out magic bytes" - docker_test_opts+=( - "-e" "APPIMAGE_EXTRACT_AND_RUN=1" - "-e" "PATCH_OUT_MAGIC_BYTES=1" - ) - fi - - # to make fuse happy, we need to use a "real" user - # as we don't want to use root, we use the user "build" we created in AppImageBuild - docker run --rm \ - --user build \ - "${docker_test_opts[@]}" \ - "$docker_image" \ - /bin/bash -xc "cd /out && bash /ws/ci/test-appimage.sh ./appimagetool-\"$ARCH\".AppImage" -fi - -# remove binaries from output directory -ls -al out/ -rm out/appimagetool -rm out/{validate,digest} - -# make sure the runtime contains the magic bytes -hexdump -Cv out/runtime | head -n 1 | grep "41 49 02 00" -# fix filename for upload -mv out/runtime out/runtime-"$ARCH" - -# fix filename for upload -mv out/AppRun out/AppRun-"$ARCH" diff --git a/ci/test-appimage.sh b/ci/test-appimage.sh deleted file mode 100755 index 62f6175c5..000000000 --- a/ci/test-appimage.sh +++ /dev/null @@ -1,46 +0,0 @@ -#! /bin/bash - -set -x -# important to allow for checking the exit code of timeout -set +e - -TIMEOUT=3 -ARCH="${ARCH:-"$(uname -m)"}" - -error() { - echo "Error: command failed" >&2 - exit 1 -} - -if [[ "$1" == "" ]] || [[ ! -x "$1" ]]; then - echo "Usage: env [PATCH_OUT_MAGIC_BYTES=1] bash $0 " - exit 2 -fi - -appimagetool="$1" - -if [[ "$PATCH_OUT_MAGIC_BYTES" != "" ]]; then - tmpdir="$(mktemp -d /tmp/appimage-test-XXXXX)" - cleanup() { - [[ -d "$tmpdir" ]] && rm -r "$tmpdir" - } - trap cleanup EXIT - - echo "Copying appimagetool and patching out magic bytes" - cp "$appimagetool" "$tmpdir/" - ls -al "$tmpdir" - appimagetool="$tmpdir"/"$(basename "$appimagetool")" - dd if=/dev/zero of="$appimagetool" bs=1 count=3 seek=8 conv=notrunc -fi - -# first of all, try to run appimagetool -"$appimagetool" && error # should fail due to missing parameter -"$appimagetool" -h || error # should not fail - -# print version and update information -"$appimagetool" --version || error # should not fail -"$appimagetool" --appimage-version || error # should not fail -"$appimagetool" --appimage-updateinformation || error # should not fail - -echo "" >&2 -echo "Tests successful!" >&2 diff --git a/ci/test-appimagetool.sh b/ci/test-appimagetool.sh deleted file mode 100755 index aaf9491e3..000000000 --- a/ci/test-appimagetool.sh +++ /dev/null @@ -1,145 +0,0 @@ -#! /bin/bash - -set -e -set -E -set -o functrace - -if [[ "$2" == "" ]]; then - echo "Usage: bash $0 " - exit 2 -fi - -# using shift makes adding/removing parameters easier -repo_root="$(readlink -f "$1")" -shift -appimagetool="$(readlink -f "$1")" - -if [[ ! -x "$appimagetool" ]]; then - echo "Error: appimagetool $appimagetool is not an executable" - exit 3 -fi - -# this script attempts to package appimagetool as an AppImage with... surprise, appimagetool - -# we always build in a temporary directory -# use RAM disk if possible -if [ -d /dev/shm ] && mount | grep /dev/shm | grep -v -q noexec; then - TEMP_BASE=/dev/shm -elif [ -d /docker-ramdisk ]; then - TEMP_BASE=/docker-ramdisk -else - TEMP_BASE=/tmp -fi - -BUILD_DIR="$(mktemp -d -p "$TEMP_BASE" appimagetool-test-XXXXXX)" - -cleanup () { - if [ -d "$BUILD_DIR" ]; then - rm -rf "$BUILD_DIR" - fi -} - -trap cleanup EXIT - -REPO_ROOT="$(readlink -f "$(dirname "${BASH_SOURCE[0]}")"/..)" -OLD_CWD="$(readlink -f .)" - -pushd "$BUILD_DIR" - -# make sure to use the built mksquashfs -export PATH="$(dirname "$appimagetool")":"$PATH" - -if [ "$CI" == true ]; then - # TODO: find way to get colored log on Travis - log() { echo -e "\n$*\n"; } -else - log() { echo -e "\n$(tput setaf 2)$(tput bold)$*$(tput sgr0)\n"; } -fi - -# debug log -trap '[[ $FUNCNAME = exithook ]] || { last_lineno=$real_lineno; real_lineno=$LINENO; }' DEBUG - -exithook() { - local exitcode="$1" - local lineno="${last_lineno:-$2}" - - if [ "$exitcode" -ne 0 ]; then - echo "$(tput setaf 1)$(tput bold)Test run failed: error in line $lineno$(tput sgr0)" - else - log "Tests succeeded!" - fi - - exit "$exitcode" -} - -trap 'exithook $? $LINENO ${BASH_LINENO[@]}' EXIT - -# real script begins here -log "create a sample AppDir" -mkdir -p appimagetool.AppDir/usr/share/metainfo/ -cp "$repo_root"/resources/{appimagetool.*,AppRun} appimagetool.AppDir/ -#cp "$repo_root"/resources/usr/share/metainfo/appimagetool.appdata.xml appimagetool.AppDir/usr/share/metainfo/ -cp "$appimagetool" appimagetool.AppDir/ -mkdir -p appimagetool.AppDir/usr/share/applications -cp appimagetool.AppDir/appimagetool.desktop appimagetool.AppDir/usr/share/applications - -log "create a file that should be ignored" -touch appimagetool.AppDir/to-be-ignored - -log "create an AppImage without an ignore file to make sure it is bundled" -"$appimagetool" appimagetool.AppDir appimagetool.AppImage || false -"$appimagetool" -l appimagetool.AppImage | grep -q to-be-ignored || false - -log "now set up the ignore file, and check that the file is properly ignored" -echo "to-be-ignored" > .appimageignore -"$appimagetool" appimagetool.AppDir appimagetool.AppImage -"$appimagetool" -l appimagetool.AppImage | grep -q to-be-ignored && false - -log "remove the default ignore file, and check if an explicitly passed one works, too" -rm .appimageignore -echo "to-be-ignored" > ignore -"$appimagetool" appimagetool.AppDir appimagetool.AppImage --exclude-file ignore || false -"$appimagetool" -l appimagetool.AppImage | grep -q to-be-ignored && false - -log "check whether files in both .appimageignore and the explicitly passed file work" -touch appimagetool.AppDir/to-be-ignored-too -echo "to-be-ignored-too" > .appimageignore -"$appimagetool" appimagetool.AppDir appimagetool.AppImage --exclude-file ignore -"$appimagetool" -l appimagetool.AppImage | grep -q to-be-ignored || true -"$appimagetool" -l appimagetool.AppImage | grep -q to-be-ignored-too || true - -log "check whether AppImages built from the exact same AppDir are the same files (reproducible builds, #625)" -"$appimagetool" appimagetool.AppDir appimagetool.AppImage.1 -"$appimagetool" appimagetool.AppDir appimagetool.AppImage.2 -hash1=$(sha256sum appimagetool.AppImage.1 | awk '{print $1}') -hash2=$(sha256sum appimagetool.AppImage.2 | awk '{print $1}') -if [ "$hash1" != "$hash2" ]; then - echo "Hash $hash1 doesn't match hash $hash2!" - exit 1 -fi - -log "check --mksquashfs-opt forwarding" -"$appimagetool" appimagetool.AppDir appimagetool.AppImage.1 -"$appimagetool" appimagetool.AppDir appimagetool.AppImage.2 --mksquashfs-opt "-mem" --mksquashfs-opt "100M" -"$appimagetool" appimagetool.AppDir appimagetool.AppImage.3 --mksquashfs-opt "-all-time" --mksquashfs-opt "12345" -hash1=$(sha256sum appimagetool.AppImage.1 | awk '{print $1}') -hash2=$(sha256sum appimagetool.AppImage.2 | awk '{print $1}') -hash3=$(sha256sum appimagetool.AppImage.3 | awk '{print $1}') -if [ "$hash1" != "$hash2" ]; then - echo "Hashes of regular and mem-restricted AppImages differ" - exit 1 -fi -if [ "$hash1" == "$hash3" ]; then - echo "Hashes of regular and mtime-modified AppImages don't differ" - exit 1 -fi - -log "check appimagetool dies when mksquashfs fails" -set +e # temporarily disable error trapping as next line is supposed to fail -out=$("$appimagetool" appimagetool.AppDir appimagetool.AppImage --mksquashfs-opt "-misspelt-option" 2>&1) -rc=$? -set -e -test ${rc} == 1 -echo "${out}" | grep -q "invalid option" -echo "${out}" | grep -qP 'mksquashfs \(pid \d+\) exited with code 1' -echo "${out}" | grep -q "sfs_mksquashfs error" diff --git a/cmake/cpack_debs.cmake b/cmake/cpack_debs.cmake deleted file mode 100644 index 7510862e4..000000000 --- a/cmake/cpack_debs.cmake +++ /dev/null @@ -1,46 +0,0 @@ -# required for DEB-DEFAULT to work as intended -cmake_minimum_required(VERSION 3.6) - -set(CPACK_GENERATOR "DEB") - -# versioning -# it appears setting CPACK_DEBIAN_PACKAGE_VERSION doesn't work, hence setting CPACK_PACKAGE_VERSION -set(CPACK_PACKAGE_VERSION ${VERSION}) - -# use git hash as package release -set(CPACK_DEBIAN_PACKAGE_RELEASE "git${GIT_COMMIT}") - -# append build ID, similar to AppImage naming -if(DEFINED ENV{TRAVIS_BUILD_NUMBER}) - set(CPACK_DEBIAN_PACKAGE_RELEASE "${CPACK_DEBIAN_PACKAGE_RELEASE}~travis$ENV{TRAVIS_BUILD_NUMBER}") -else() - set(CPACK_DEBIAN_PACKAGE_RELEASE "${CPACK_DEBIAN_PACKAGE_RELEASE}~local") -endif() - -if(DEFINED ENV{ARCH}) - set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE $ENV{ARCH}) - if(CPACK_DEBIAN_PACKAGE_ARCHITECTURE MATCHES "i686") - set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "i386") - endif() -endif() - -message("CPACK_DEBIAN_PACKAGE_ARCHITECTURE: ${CPACK_DEBIAN_PACKAGE_ARCHITECTURE}") - -set(CPACK_DEBIAN_PACKAGE_MAINTAINER "AppImage Team") -set(CPACK_DEBIAN_PACKAGE_HOMEPAGE "https://appimage.org/") -set(CPACK_DEBIAN_FILE_NAME DEB-DEFAULT) -set(CPACK_PACKAGE_DESCRIPTION_FILE "${PROJECT_SOURCE_DIR}/README.md") -set(CPACK_RESOURCE_FILE_LICENSE "${PROJECT_SOURCE_DIR}/LICENSE") - -set(CPACK_DEBIAN_LIBAPPIMAGE_PACKAGE_NAME "libappimage") -set(CPACK_DEBIAN_LIBAPPIMAGE_PACKAGE_DEPENDS "libarchive13, libc6 (>= 2.4), libglib2.0-0, zlib1g, fuse") -set(CPACK_DEBIAN_LIBAPPIMAGE_PACKAGE_DESCRIPTION "Utilities collection to handle AppImage files.") - -set(CPACK_DEBIAN_LIBAPPIMAGE-DEV_PACKAGE_NAME "libappimage-dev") -set(CPACK_DEBIAN_LIBAPPIMAGE-DEV_PACKAGE_DEPENDS "libappimage") -set(CPACK_DEBIAN_LIBAPPIMAGE-DEV_PACKAGE_DESCRIPTION "Utilities collection to handle AppImage files.") - -set(CPACK_COMPONENTS_ALL libappimage libappimage-dev) -set(CPACK_DEB_COMPONENT_INSTALL ON) - -include(CPack) diff --git a/cmake/dependencies.cmake b/cmake/dependencies.cmake deleted file mode 100644 index 896e3a8d9..000000000 --- a/cmake/dependencies.cmake +++ /dev/null @@ -1,90 +0,0 @@ -# >= 3.2 required for ExternalProject_Add_StepDependencies -cmake_minimum_required(VERSION 3.2) - - -include(${PROJECT_SOURCE_DIR}/lib/libappimage/cmake/scripts.cmake) - - -# the names of the targets need to differ from the library filenames -# this is especially an issue with libcairo, where the library is called libcairo -# therefore, all libs imported this way have been prefixed with lib -import_pkgconfig_target(TARGET_NAME libfuse PKGCONFIG_TARGET fuse) -# openssl is required for optional tools only, and doesn't need to be enforced -# FIXME: remove dependency to openssl by implementing own SHA hashes in libappimage_hashlib -import_pkgconfig_target(TARGET_NAME libssl PKGCONFIG_TARGET openssl OPTIONAL) -import_pkgconfig_target(TARGET_NAME libgio PKGCONFIG_TARGET gio OPTIONAL) - - -if(USE_CCACHE) - message(STATUS "Using CCache to build AppImageKit dependencies") - # TODO: find way to use find_program with all possible paths - # (might differ from distro to distro) - # these work on Debian and Ubuntu: - set(CC "/usr/lib/ccache/gcc") - set(CXX "/usr/lib/ccache/g++") -else() - set(CC "${CMAKE_C_COMPILER}") - set(CXX "${CMAKE_CXX_COMPILER}") -endif() - -set(CFLAGS ${DEPENDENCIES_CFLAGS}) -set(CPPFLAGS ${DEPENDENCIES_CPPFLAGS}) -set(LDFLAGS ${DEPENDENCIES_LDFLAGS}) - -set(USE_SYSTEM_MKSQUASHFS OFF CACHE BOOL "Use system mksquashfs instead of downloading and building our own. Warning: you need a recent version otherwise it might not work as intended.") - -if(NOT USE_SYSTEM_MKSQUASHFS) - set(mksquashfs_cflags "-DXZ_SUPPORT ${CFLAGS}") - - if(NOT xz_LIBRARIES OR xz_LIBRARIES STREQUAL "") - message(FATAL_ERROR "xz_LIBRARIES not set") - elseif(xz_LIBRARIES MATCHES "\\.a$") - set(mksquashfs_ldflags "${xz_LIBRARIES}") - else() - set(mksquashfs_ldflags "-l${xz_LIBRARIES}") - endif() - - if(xz_INCLUDE_DIRS) - set(mksquashfs_cflags "${mksquashfs_cflags} -I${xz_INCLUDE_DIRS}") - endif() - if(xz_LIBRARY_DIRS) - set(mksquashfs_ldflags "${mksquashfs_ldflags} -L${xz_LIBRARY_DIRS}") - endif() - - ExternalProject_Add(mksquashfs - GIT_REPOSITORY https://github.com/plougher/squashfs-tools/ - GIT_TAG 4.4 - UPDATE_COMMAND "" # Make sure CMake won't try to fetch updates unnecessarily and hence rebuild the dependency every time - CONFIGURE_COMMAND ${SED} -i "s|CFLAGS += -DXZ_SUPPORT|CFLAGS += ${mksquashfs_cflags}|g" /squashfs-tools/Makefile - COMMAND ${SED} -i "s|LIBS += -llzma|LIBS += -Bstatic ${mksquashfs_ldflags}|g" /squashfs-tools/Makefile - COMMAND ${SED} -i "s|install: mksquashfs unsquashfs|install: mksquashfs|g" squashfs-tools/Makefile - COMMAND ${SED} -i "/cp unsquashfs/d" squashfs-tools/Makefile - BUILD_COMMAND env CC=${CC} CXX=${CXX} LDFLAGS=${LDFLAGS} ${MAKE} -C squashfs-tools/ XZ_SUPPORT=1 mksquashfs - # ${MAKE} install unfortunately expects unsquashfs to be built as well, hence can't install the binary - # therefore using built file in SOURCE_DIR - # TODO: implement building out of source - BUILD_IN_SOURCE ON - INSTALL_COMMAND ${MAKE} -C squashfs-tools/ install INSTALL_DIR= - ) - - ExternalProject_Get_Property(mksquashfs INSTALL_DIR) - set(mksquashfs_INSTALL_DIR "${INSTALL_DIR}") - mark_as_advanced(mksquashfs_INSTALL_DIR) - - # for later use when packaging as an AppImage - set(mksquashfs_BINARY "${mksquashfs_INSTALL_DIR}/mksquashfs") - mark_as_advanced(mksquashfs_BINARY) -else() - message(STATUS "Using system mksquashfs") - - set(mksquashfs_BINARY "mksquashfs") -endif() - -#### build dependency configuration #### - -# only have to build custom xz when not using system libxz -if(TARGET xz-EXTERNAL) - if(TARGET mksquashfs) - ExternalProject_Add_StepDependencies(mksquashfs configure xz-EXTERNAL) - endif() -endif() diff --git a/cmake/sanitizers-cmake b/cmake/sanitizers-cmake deleted file mode 160000 index 6947cff3a..000000000 --- a/cmake/sanitizers-cmake +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 6947cff3a9c9305eb9c16135dd81da3feb4bf87f diff --git a/cmake/toolchains/aarch64-linux-gnu.cmake b/cmake/toolchains/aarch64-linux-gnu.cmake deleted file mode 100644 index 4b35337c3..000000000 --- a/cmake/toolchains/aarch64-linux-gnu.cmake +++ /dev/null @@ -1,20 +0,0 @@ -# toolchain file that can be used for cross-compiling AppImageKit using the respective AppImageBuild container - -set(CMAKE_SYSTEM_NAME Linux CACHE STRING "" FORCE) -set(CMAKE_SYSTEM_PROCESSOR arm CACHE STRING "" FORCE) - -set(triple aarch64-linux-gnu CACHE STRING "" FORCE) - -set(CMAKE_C_COMPILER "${triple}-gcc" CACHE STRING "" FORCE) -set(CMAKE_CXX_COMPILER "${triple}-g++" CACHE STRING "" FORCE) - -set(TOOLS_PREFIX "${triple}-" CACHE STRING "" FORCE) - -set(DEPENDENCIES_CFLAGS "-I/deps/include" CACHE STRING "" FORCE) -set(DEPENDENCIES_CPPFLAGS "${DEPENDENCIES_CFLAGS}" CACHE STRING "" FORCE) -set(DEPENDENCIES_LDFLAGS "-L/deps/lib/" CACHE STRING "" FORCE) - -# host = target system -# build = build system -# both must be specified -set(EXTRA_CONFIGURE_FLAGS "--host=${triple}" "--build=x86_64-pc-linux-gnu" "--target=${triple}" CACHE STRING "" FORCE) diff --git a/cmake/toolchains/arm-linux-gnueabihf.cmake b/cmake/toolchains/arm-linux-gnueabihf.cmake deleted file mode 100644 index 6c755e66e..000000000 --- a/cmake/toolchains/arm-linux-gnueabihf.cmake +++ /dev/null @@ -1,20 +0,0 @@ -# toolchain file that can be used for cross-compiling AppImageKit using the respective AppImageBuild container - -set(CMAKE_SYSTEM_NAME Linux CACHE STRING "" FORCE) -set(CMAKE_SYSTEM_PROCESSOR arm CACHE STRING "" FORCE) - -set(triple arm-linux-gnueabihf CACHE STRING "" FORCE) - -set(CMAKE_C_COMPILER "${triple}-gcc" CACHE STRING "" FORCE) -set(CMAKE_CXX_COMPILER "${triple}-g++" CACHE STRING "" FORCE) - -set(TOOLS_PREFIX "${triple}-" CACHE STRING "" FORCE) - -set(DEPENDENCIES_CFLAGS "-I/deps/include" CACHE STRING "" FORCE) -set(DEPENDENCIES_CPPFLAGS "${DEPENDENCIES_CFLAGS}" CACHE STRING "" FORCE) -set(DEPENDENCIES_LDFLAGS "-L/deps/lib/" CACHE STRING "" FORCE) - -# host = target system -# build = build system -# both must be specified -set(EXTRA_CONFIGURE_FLAGS "--host=${triple}" "--build=x86_64-pc-linux-gnu" "--target=${triple}" CACHE STRING "" FORCE) diff --git a/cmake/toolchains/i386-linux-gnu.cmake b/cmake/toolchains/i386-linux-gnu.cmake deleted file mode 100644 index dc6c28011..000000000 --- a/cmake/toolchains/i386-linux-gnu.cmake +++ /dev/null @@ -1,31 +0,0 @@ -# this toolchain file works for cross compiling on Ubuntu when the following prerequisites are given: -# - all dependencies that would be needed for a normal build must be installed as i386 versions -# - building XZ/liblzma doesn't work yet, so one has to install liblzma-dev:i386 and set -DUSE_SYSTEM_XZ=ON -# - building GTest doesn't work yet, so one has to install libgtest-dev:i386 and set -DUSE_SYSTEM_GTEST=ON -# - building libarchive doesn't work yet, so one has to install liblzma-dev:i386 and set -DUSE_SYSTEM_LIBARCHIVE=ON (TODO: link system libarchive statically like liblzma) -# some of the packets interfere with their x86_64 version (e.g., libfuse-dev:i386, libglib2-dev:i386), so building on a -# normal system will most likely not work, but on systems like Travis it should work fine - -set(CMAKE_SYSTEM_NAME Linux CACHE STRING "" FORCE) -set(CMAKE_SYSTEM_PROCESSOR i386 CACHE STRING "" FORCE) - -set(CMAKE_C_FLAGS "-m32" CACHE STRING "" FORCE) -set(CMAKE_CXX_FLAGS "-m32" CACHE STRING "" FORCE) - -# CMAKE_SHARED_LINKER_FLAGS, CMAKE_STATIC_LINKER_FLAGS etc. must not be set, but CMAKE_EXE_LINKER_FLAGS is necessary -set(CMAKE_EXE_LINKER_FLAGS "-m32" CACHE STRING "" FORCE) - -set(DEPENDENCIES_CFLAGS "-m32" CACHE STRING "" FORCE) -set(DEPENDENCIES_CPPFLAGS "-m32" CACHE STRING "" FORCE) -set(DEPENDENCIES_LDFLAGS "-m32" CACHE STRING "" FORCE) - -# host = target system -# build = build system -# both must be specified -set(EXTRA_CONFIGURE_FLAGS "--host=i686-pc-linux-gnu" "--build=x86_64-pc-linux-gnu" CACHE STRING "" FORCE) - -# may help with some rare issues -set(CMAKE_PREFIX_PATH /usr/lib/i386-linux-gnu CACHE STRING "" FORCE) - -# makes sure that at least on Ubuntu pkg-config will search for the :i386 packages -set(ENV{PKG_CONFIG_PATH} /usr/lib/i386-linux-gnu/pkgconfig/ CACHE STRING "" FORCE) diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt deleted file mode 100644 index 9ca1144be..000000000 --- a/lib/CMakeLists.txt +++ /dev/null @@ -1 +0,0 @@ -add_subdirectory(libappimage) diff --git a/lib/libappimage b/lib/libappimage deleted file mode 160000 index 9c1fae809..000000000 --- a/lib/libappimage +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 9c1fae809dedbb3015e9cd5b46e2b5aab06df36e diff --git a/resources/AppRun b/resources/AppRun deleted file mode 100755 index 2f9426cc2..000000000 --- a/resources/AppRun +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/sh -SELF=$(readlink -f "$0") -HERE=${SELF%/*} -export PATH="${HERE}/usr/bin/:${HERE}/usr/sbin/:${HERE}/usr/games/:${HERE}/bin/:${HERE}/sbin/${PATH:+:$PATH}" -export LD_LIBRARY_PATH="${HERE}/usr/lib/:${HERE}/usr/lib/i386-linux-gnu/:${HERE}/usr/lib/x86_64-linux-gnu/:${HERE}/usr/lib32/:${HERE}/usr/lib64/:${HERE}/lib/:${HERE}/lib/i386-linux-gnu/:${HERE}/lib/x86_64-linux-gnu/:${HERE}/lib32/:${HERE}/lib64/${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}" -export PYTHONPATH="${HERE}/usr/share/pyshared/${PYTHONPATH:+:$PYTHONPATH}" -export XDG_DATA_DIRS="${HERE}/usr/share/${XDG_DATA_DIRS:+:$XDG_DATA_DIRS}" -export PERLLIB="${HERE}/usr/share/perl5/:${HERE}/usr/lib/perl5/${PERLLIB:+:$PERLLIB}" -export GSETTINGS_SCHEMA_DIR="${HERE}/usr/share/glib-2.0/schemas/${GSETTINGS_SCHEMA_DIR:+:$GSETTINGS_SCHEMA_DIR}" -export QT_PLUGIN_PATH="${HERE}/usr/lib/qt4/plugins/:${HERE}/usr/lib/i386-linux-gnu/qt4/plugins/:${HERE}/usr/lib/x86_64-linux-gnu/qt4/plugins/:${HERE}/usr/lib32/qt4/plugins/:${HERE}/usr/lib64/qt4/plugins/:${HERE}/usr/lib/qt5/plugins/:${HERE}/usr/lib/i386-linux-gnu/qt5/plugins/:${HERE}/usr/lib/x86_64-linux-gnu/qt5/plugins/:${HERE}/usr/lib32/qt5/plugins/:${HERE}/usr/lib64/qt5/plugins/${QT_PLUGIN_PATH:+:$QT_PLUGIN_PATH}" -EXEC=$(grep -e '^Exec=.*' "${HERE}"/*.desktop | head -n 1 | cut -d "=" -f 2 | cut -d " " -f 1) -exec "${EXEC}" "$@" diff --git a/resources/appimagetool.desktop b/resources/appimagetool.desktop deleted file mode 100644 index 86eabaf3d..000000000 --- a/resources/appimagetool.desktop +++ /dev/null @@ -1,9 +0,0 @@ -[Desktop Entry] -Type=Application -Name=appimagetool -Exec=appimagetool -Comment=Tool to generate AppImages from AppDirs -Icon=appimagetool -Categories=Development; -Terminal=true - diff --git a/resources/appimagetool.png b/resources/appimagetool.png deleted file mode 100644 index a304efdfab107653faae17e85a254f7f50582e6f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9773 zcmV+|Ceqo7P)!@- z-tN5oe|os)T>A@mhLTf{9$Ejj0WRJc+Vg4n^lkxqqMRv+A|kST{vWP6*B%9)&U*Ku zd+yfY?*GyN7j6tCB=JTFtcD38C8V^z&H8oLUpMR*S$~!M9rD|_=2eI_65_3Dg7}{{ zz=iAmOG(f@A{wb+?4+sKymcE695?{SJ_6S{0qMB6g}bm@#)guXBv&H~J?HaQ4d3I1n9IFmmK5 ztXZ)XmLcCVKH_SdYiE zO4%PuFDsoCR7dzZc1q_^34Z*Nt0X2Chzo298p9S^n-tVpExM?QDY>FG%#eq^P$((n zP6nzSY87(yNbFqiuW)wc^JvUw_1R4qXq!8mySvpb>}g@2PBj<`yXOsle)}T(2S>u& zY>h{M{+^$oZ2mvM?%;R$_8kV~?S~Jtx4R?gR+7vAyQW+!5G&n^PLw zih@>d(Mr&<+_tf*;SSo$eaCD&F{`nMb`mh%!6t!7t{%fY4-L6~Zp+nETdtp45HuFr z%A=va*BE@39+#mPJ?YIEoTcXjXEKw|=rbF7CnK`E#^U$)z2N)KATn*cWyeAPyKS<2 z-az)lTYUWV5e-Lqwf}45Uw|!<*CyrcvSDZ7(-~aJ=>$boc&}U=Bqq zDO=!$R%L$|P+nO)WI%*zwSFKG#ab&?YiYF=YxM)F1R9fb66e;E(Y|4;l}wrFWAzCG z*K*M+C$=QMH*=hNcz%BF5g>K7r3gd^j4YZFx=W+AlDSEPA`gp*0>r8OdK|^gio2JH z+to_A-R~o>1cdX)*tpNNW~CnQC(}SAP!t*}jCs*K&dEx3=5kzsZv75G)o~uc*iuL5 zrwJaFcX8;aDsH9K!RV~<(ibVQrgp|+H-H`c}02vD5X$Cs>h!K4XCp%B@@-9H69 zhu2!i^V53qa0c)#5x@(5t0DpYJ6c4P*4k$v$Nozi=>eo4-<$&QcXO@L|7V(j@|{Is zuLD*J1M74kXag|mQH)!yXDpinkWRj-2wdwnnBX5m(OUgdp#UyG%+u=&%p^<1)UrnU z+591h-#;&{R0|KfS9&q@TIkZ2>#ayteO(Oc!iaj5c|M0D259=by8lBERmTMog3$hf zNrTtxL3x_M(MS;qW(uoei~*EQ3SO~*Z(fb?%D^~^`L-f3VGwODxV-QLA$S>D`w1!v zC}B;$t%!MgZSsB)fjU)bLzHs3G!~4bJ`y$-f&G9ceXKA&>KuS;VSum^DDn7C?`FlU z755M!dqEQ^#XWM*+`C!Q5+VF`X!OiGV<%)N467d-i$EqOk55@I_^cUXMwEx0IJ1_& zWsmw^TC1hjnpgK$0QL$I2_}GP2f%CRUbOd(mZZt7F>j(y!B~Y5A^#$Zk{&ij0BYbP zHxmqq^L0U_qd?-Qqt+vT)5bX-{3>+P1)=n*Cg$SY2mPLDPnudy!{{B?d|eg3qMCpT zpkUo#e-Vfv#&DSibS&UPQr7~E%di`6=c4(mHU)k>{@>TU-k#yU=wAgX-d*jLG`RaY z+9@3+W}N#;+1eZ~!$0W&v9$;kLeZ6}sEVPO7C2%^ylT1GiA&)h$2|`>E7s0@oX>&C zIji0SZ$}^=d)Z^J$KKZNwA9*%XTN$y1)a3vkE?%{EiQDiuLuP0AiWslYB{em3g}cI zYK91-9Bjg1z~Q;~{q+>^CvVpPElIL%cb4uQ+qP}v*|u%lwr$(*^?PH_boaP9Y7N`& zzE;%Fy)yRd^YfmLm4m9h>#VB085!C;PMkP_0???{P_Jo?Kfl+|+iFsjLFP%-!Myr? zdP(*Bt=}>JoUWj(J#1OKVg%X>a!BfH0n;Ko*m4=WVybJD+m_-v7cU6!L;6 z;C(N6JSgv_Jpb{J+6ZJE?|klsc-M0;0Oj5J_jf<Y=VN01VfMu}mY#c5LP^*gs`PT-+V%5fe{Cnz5jLSap<&kTE zgpB2C{+~C@!n*z;=7o7u-SEZ%zpVP(<+@8ZAgB8%E7lGhfnt~{$5Z3_pW`)iDnsA( znIZuzSn9peXdtWC_%L6#y$+Y&dgmlRKBsicQuRu`tLOi_=?*Miy@7dPUYIA<3G>`hcO#u6DSukwb)~pG64@5ccmf2PmL`{wnq zE%=dK1e97t*Wy*{@V}eyD)KAhDc|uvLuNdsmCEK%X!-Vo0=U{XSmJit2vp*sOaj50 zCV_RUdab~OvGG~rWN79U-p(>TkFAf!UmJhRt@AY-2OJ=)UzRwG>z`9+)5BMEFO4R$ zm^Sm!j9O??c_>xOTmk&HGhzycXx%dcgEE>GmR{NUPMdq3mX8Y)eCsHE}XfGbjz>i zGePKz5m-pD4oJi5N)~_T#S=(GYt{9FiKIgz*|GFr1DD>XqCZFdrg&6Fa+$N5!f#EIlh0pG6@tu zqUz7?S%1J}jgZyqRR0Q%T7$={6fWA8>-zDp8|GkqB8UW(N)|tzOaGoW2P?P(H#&M4 zw^C-BS&jF$#oIbb%pN*rPk^5sW%1tHWRwmXffUD>p;RYMGs)c!o?PJ_xtQcOK|hN2lx)(WgIFa<7OHL^ip{ez?TVL zB8@{RFHEA&+o7}T0Vc{I#BrdPAvo4OpI6of2_nFDLk<}V&s;4&FGdPkjO)tWg*$)o zCP$H4zU~(;U5(3U%!>m}Xp~XhNASy_Tgx74;H$TK3d%(C!ADT|ZW)25*ddWI#}%3w z20DFZRgGZYQOu2&86F}-JvwdJw@LO*O5J6;j)Tch*Ni~ePuIVlX1Q8i+Sv0|qbd~M0uYKkbv-S9M4x>|!!1tZPT+63 zQ)hMV+)+N(_6_Dk#@T#UjP>Q{0pCR)SCes?@_V5B`BWa0#-ZL%8;9<^iN&I;Mqqka zm*~SB#wUzDx02zJq0}-tKBw`fcsXQ~B|k(*Q9i!sv2FvyBlv6XIUE=nEiC+clVLYm z{4^#}vw*vx!_809ICNTl!iGu@8@piyT9qdkWQCTV=n{O}AVCDB;gUfjaN_W-RXB z0UYGP;}1?9;3rU7#khYzlvq(Wlfbl-O~p? zT~0%GPvs}v=B5FejUgT08pa_<04S!gDQ}mj4UniHzrsso5TOWAE)%%~5mUmIyQ;7P zSUH0dMbznFN|#H$%Uw-~gldPj1G+=VB*9C*4Oiv6lSl@K(D5~aW^-tIiqit@YlBKH z#Z{A*4CCXY7#SJH$k0$O!x+s!xkHBlGDIMFf!~YPP4M~d^Upm2AA0cgH1REu&)i$M6h9< z)+1mEG}SYKwc3Gz^Nc`B2u7`j0Ht;KzPn?)t+#aLxP$gC!kd;IC?Vuz8{*EN{F!x% zkszViwKO*7=GT@x1-#SheU*>N;0JWi2rLpb04L}9ecK>G1cmjr0)ZGCQ7cCwT*Eg$ zVL&T3l8lWG^Xa6&W}|TBDn5$tx7o7SSo%TQgM`aJgVjRJ1IehC9(N6mcp6JFdcddW zLlWx-6fUTqyJZ9hxgP|)ua=yR8i}D(Ijo}<2rw&{fC+e>;z{BE*&VQjDo-LrS(N&C zPLjU9KJ@qZm%2Gi_DxzxpG;52B0sr1Nadl;!L4KE){ZK`m&W#r!LM7rXE5oS5g6>! zFw4@!T)1x}`eSIM%-A`OkhH~Yh{INAT0YMLCK;mD zf8H?%;}b7`3J%|UH>kfK9V=R)J7i3p8x*YOvJwJYd^EX%r=NNhKKY8LV2_=)WoT{< zv)YIE+&?HFZC;XH1Kf!rf9B6>ixNH^)&NqACgVm#!Zrg9oFxok+da?cle@4@r+MWb_6n}E4kWOm=bA+m~e4TNtZDA=Q zAfX0LVOgPiZ=A=t#|Y2O)&5g+@Kp&k=rqOq+;dLANr&tUhE!g+>}}z3Cmx3P}(EAz*?6><)c>Pn)#PJ*sa)*(r;MYDm2Y;X4p?XlAw3-c&1iNg%jX>A%)Hta8 zk&bT&`t_$cEch^(*nD-c3!nszk6mq$E=a16bB2Y6-7FaYdCdNM;_0U!11;ki85zOg z;2@7|DGHTkc)@um<|Nn$TlO^ZipQS<+6YfN`N+J_-VS;-!x} z1)qM!Q*puZhX4fsNvDJU164fJqo}gERs0>#I*&i55&aPY9qfKo6XmY4dVRUAK4K6t z=~@>M((1_X!`y;7qlN?-l-A-k>tS~UEA8RoVUi(g0)Qm=_{*MxV-MUL+|zHhnZVP< zcPZ8txhtxbNWcw1O&9?`kG*^@aib<=PpL3U9Sq=;`T!w1L$Gjd~4I@dTLT{(*r3 z0ceHq(I-HFjdox^-+;;`;;^gPa?35DW#s&2v7cN#4Kd4Rr4etla$Tg|!?rGb4QuP3 zSakW2s8Dv>ww*pInQ>*_W4*0_xX?2L;&d&A&u?4sApUUmt(fphK(MvDm-hsn0Q22S z_730IJG>`hEcjb&u>}PF#(^Px1DCK;D-}c)k|IOgsiXL~sDmWn&5Q+$@%yW8fx3fcvq>VTe^)H>`cvq?zQ$u0K8q8Ylqd6PK*M)z9(($`GrlL!B={Z!>4ii)@|Xl zY}45Q)C4&Ru9>xd}vo0&Q(%(J{h8)e{6V|Gi>o^+$Kt7 z%8;?O#kh{%e~(Gyb1NhT0Vd!!-HFm{ATN=@E*ZDof(*>FjywP|RBKvCX#SXwFkW~h z>A<2LfkXp9(pXLpAA@C17Y>Os1*l2{N1aJZXZzR*7h5hHZ#z!9@bjdD_r`9yJ67X) zfuxHqnk`<}+P;DOT%o)1#Xntv5B_WlKK#r7;RjQu;+A<2U?kT#(iYaxgYg{*xHEGC zw3>BlDy~BiK(2ZZp{?@`Q(BK-ssgXN*YhqKfzkq=OVeYhzxvlD11m}I(e=xF5@L)~ zu#(|ICZd1;oTCr2L%B&?z1gDG+OM2351;$}<@w&fd$4kSKe%ypWON)0maM`bubz=V zyA1rzV1Z2H$fgiUMS|W|17{quKNwW4oH7=tiz)nW=L4t}cyB>RvYT{)H}}w@(C!+6 zsN&m3+UZdyLkJwU$?s1vM~cb{{;6N`#qYKAw*2ZI21W1%+`sbOzW=@HPPt7vn&2># zqA*-4p7-t7W6{#pG8m0bFxi86>;Ze)#U&E^zxeaDqXM1l2a+QnBv%u;yO6qR1ZoJ# zPgEd+r@nkLutlpP#iGa6wS>FUW=>}fzer_FnR=E<#ihh` z_6Rf{=*Y1;ubT1FA>(ke&;TTcJa-h{OuzGflE#_OdE_#ri%~q8-|y5l{KBd;S%M z;WrEpVPJUF#%C|4PY)qK%OYFE5Z`a<6r@{wa_OAHGdacA1tT!T%@}C|FsT(>&EPQI zRFwMOswaTzy`hmY>pw90vtGJdIShs81c?-zO(XsDvlLSfr=_P`d)g2TZT0`5TSlPm zyV*Wd%ewsq4;~pLC=o)RQp2>!OX7O|Y`I$CksyO1gcVyL5`YzM#R8!CBpQzGoi74W zgn>h__}q-yi?O;?Yut0N&#pUQi&n$NRrVN)fMs#l7#hGg4?3!DHl-LpKsSv*CWuF{ znG@}VX3)I|5sfk$Z#<}RBBTq(N-rB~8W!%j&6YTHuU++P9@fi9BhP9DuIJ-(KE%04 z9bn^fhnT5rbbJC!)@-nV0}1t>To#|)LT4IeH-0uQFu@8Vfg~Bc79fi`9?rxs%hzti zr*iMydw=>Ly!$7VDR_^O?@yU#hkfokMqbZ8{d5X`_+RD^+J0`zpV^k420c9jD8#zRJAPCw6AOh@-^`ib z=8ZTGS79@PS*t5Kx@>uZM=s-=WMUli7O&t!41wYv`_606yc>A+6HZ1A84x#lQvHu> z(rIMVrjwnw*$S_F(y4SXY4qWqC&=rbhgRA=F^>|nt(--Pc8Eq987hOGtYhKOmEQ}n z{cGa1u1SVo#ckdkpJ$DR2tkKUE-enxkktyQ@iR)hoq=V)>!B5l*PRNsWA$V68N+uy z`|O+y+Zt^)0hI>1oO;;4c<*!1#r9imVJ-Yg-HqbB>7ECo_Nv*u$)7;KL-E@N^_n3= z6Q~Nh{-0Po8DO<(2S)+M!ZyZ-KX2`x?3o~g-mlpsT8iezX`lMcseIpAj>c_5yD*0K25OCFDxo_{=75(|7e znB0@a?pv`I^OvkD(k|akCVt*o$Kc#!4z#U2sR_(whj=N_-Kk(++;i~S zC!T_%_uWk%M2sn~j5{Y2#e(f09+3t;?OBajm_Ky%d;sTcK2#-x{_koBiL?A%r-2as z(Gj^nbMTMGc}E{05Y>9+sL_JYgwrN@$@Q$bWMFD0kZDpATebvA%nWz1796#!3rN_~4P1iK`x<3^ywpTDj| zh9n^zD>~R=;)J|(c>M7PPa5l&U9^i=Z@{e!7Sr8pCvPO~UI78GtAA(|SI=I=#iB_P zaB=9%E;t@cS_e$pE$&DIu4ie`Q?samq?1OVG7aN=s73}`&`N|zkYa5g=LZJ$jy!X= z<>R5%>+$XXPQ|aTybWLc+cmg-;bIJrjPaTK6Ega)I9KQKUvk?#eDV*M@QG=gvZ=LW3YV160QsP_j6{(q)nV5sPSm#*o<&o93XANchp`03@hpx;^Kq3`o@ z$Ie&(aUDL9uNjXzeOPU~FH{SCges|4Gl>;?Hj10AO8J!u? z6zJAK41rQwPlyhU0+cJwqnBs6Dv?3rO^rIF;D!s0pXFZVv-SNW`1-$Y!18r{_FX)% zYCXO)WjY4f+5vhIMI4Mx1k7Bt41>dClln{DKe%cG?pwKD6E+;n>qjSW&(hWS-o-a^ zfr(uKOz`pBt7jtE{eUEt-5jd=kic!_Y0y0nt3t~l>!d5#W;+C91Xd-3PY7?=WBWG! zOq*QAypO*OHiB>EEuAEgYxdg&p8&TD@(@4*!cWDab$*^$e*;$ylR(_N&gV`2VZ>Wzg zreqr}OB5TI?iFA9cafdVvfd$(udo(zEhk7Q^Y@rb!ao znZSlxKAb&${*0ev4_Uw|soBFIf^@+Mlu+$Z(%Za!?cfl?pAX=3ml&FBcUqLbWK_ZI zCT!e_3oAAZ(0X@e`MQ4F;`PayNz`i%mzWfQY4)(?J3#xheJb zlZaB@4((;s(GJ!Sbi0fS#L#pxE&VM1)v{V)AhvpetQbC0v|>kb{B7Eu`1utxCdp4O zyA3n$U24`EDE&;vC>kV!Ni)lsW|JC$+9wILuhIp0dJ!!JPCW*Lhr)IKXXE6erTDEn zt>W!7-w3QojEt5(RdMVB)IXc|qeDiZ^81>;LEOG*=_HwT-*T=!)Xrh$#ai}^Pidk? zX|y!fPXnEp@RB6E2wz(Whc5qURM0BAv||U!KHp(>N>fmr9^I186N00l^>~I4kR_&m zYsEoSncmA7hfhGw>Lq}7>p;z^65vQXjdMc_n#(&PYMBBl^kxG)_VvUaGQOx{9ZBSLsn0Mn+90|2kfeV zn>tY%`llJ0aA|v6__Qb1JeCA#?78QjTekaF-=8Nukqi3QEQ^yt%AHZEFWyW@^KGNLV)-Zf*SJuxwr4@NewMc>MY5Nr=< zcf4dq$_pVg*k@MEyRh>A{0@U~H6M(l{8#kn#8jyme7Mt*K?Ge0S-nJ<=X{y-lfrJz-sYCux&n4EO6g*Kp!4(@9C=B};3;cY0l1^Xc zbn>m|62)WFgQ+L(Zd(7qJYu0Z#|QtfowKm98w#SR*ENO23a5o_C8;1xH6+5MfG{&N zS|82KINrI^GBduB&S$)5%;4(R;R?>+4i4dRr42BWB#BH!BTdubTIMg1gYK`NWfGp7 zST+m#f2IE0yOQ?hnPhx_E$P$w0bWTO_&yVLHsAR1Z!h_JVTR!A(hR`27aIevAT zU&jCI+#Ix-AUnzT`3s+om}QDqwrkR`S}a3;B4F-T*`2|k_Koyole6$ zJP>yiu4@3?pKosDfqRCCqIUdH>LT`~%(rIZt&DU%aW@EW{m52|KNDn*?8na$6y~9Q z+Wr0Z=5$x%?g%d7bfxnEm1S8)RaFI#N(%0#oWCq%(n$GyD^R|ktm5cWQ&(?WYKCYC z!RCR?o4R}p2fp(4RP_JrZMcCWxPmjdgG0Dn?NUHx7)ILb^%B0F@GjCZcT`jqMN~&_ z-~IjOy7}?ZsPpCN5$E&c1NNs!2l;xx_3_~$!TN)2$1^^F%*~IFN8tc2-~?{q2(I7^ z?%;5(i-9du@`ojzPA61VHQ=*n`ej-Ae9~o)&ywMB*SSRG0Pa2y*MjwCX12&2*~0-` zzzN*I5nRC;+^zS~!NgR9!636ND^?UG;M*>Lv90U6&0lN-(=-L^&t$&H8kr+|IDiW{ zfg6Tawk=@&s%2=LMzA5!IPH2#lbO9&qC^9T5)B|qG=QivUS0bAA2WK!00000NkvXX Hu0mjfS&vS> diff --git a/resources/appimagetool.svg b/resources/appimagetool.svg deleted file mode 100644 index 83ac5658b..000000000 --- a/resources/appimagetool.svg +++ /dev/null @@ -1,320 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - diff --git a/resources/liblz4.pc b/resources/liblz4.pc deleted file mode 100644 index d2c7f86fd..000000000 --- a/resources/liblz4.pc +++ /dev/null @@ -1,14 +0,0 @@ -# LZ4 - Fast LZ compression algorithm -# Copyright (C) 2011-2014, Yann Collet. -# BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) - -prefix=/usr -libdir=/usr/lib -includedir=/usr/include - -Name: lz4 -Description: fast lossless compression algorithm library -URL: http://code.google.com/p/lz4/ -Version: 131 -Libs: -L/usr/lib -llz4 -Cflags: -I/usr/include \ No newline at end of file diff --git a/resources/pubkey.asc b/resources/pubkey.asc deleted file mode 100644 index 49ce8c4f6..000000000 --- a/resources/pubkey.asc +++ /dev/null @@ -1,30 +0,0 @@ ------BEGIN PGP PUBLIC KEY BLOCK----- -Version: GnuPG v1 - -mQENBFgk9CwBCACs1C/QsJEGfrY4i6ppoCZ4YfNeRKNKIY7StV2ea/cWePEBTGlP -3uT4M2JGVpoXdwqZCQjpLS1d3gzIvldb6Z1aSOV7ylrcXsQuLQb93mt9kI7qtX1m -sSZOMuQj41ppdcg6z7Lt8H5k8AKKdlZvTAhm0tvvCWaevfTWf2WWBNUnYJf+eToO -IRZlVmXepFp9btQWdaOvHBfJ2rnCoA5f1yjlJ47K97UQKfBPYbYFwxYoKpB+DIHT -iALubIwB5xmsTqJr8jovEYP6hcqJe2tOEKNLmDNBw4/B6Vpf/R49WvpOS4RST2Ad -CUYCkL8HxmS9+QdBkWCdBMFiU5tIbmTIQFEfABEBAAG0MWFwcGltYWdlLm9yZyA8 -cHJvYm9ub3BkQHVzZXJzLm5vcmVwbHkuZ2l0aHViLmNvbT6JATgEEwECACIFAlgk -9CwCGwMGCwkIBwMCBhUIAgkKCwQWAgMBAh4BAheAAAoJEGW0OEAQGy3EV6kH/iGd -w2Rj93b/pSpLgxVgOPIjNGXIEjLIi6qbIoBq2S0jpitIj3kW3PmwMZyozNoytVp+ -2TrrrqaS7Zv3P1HkQ+3DlGef4uwCTob5KQW8GY/cErSE3aWpmIOPFo2kwhaBaaJ+ -7vlnTmyTKIVqKqZg0JWFy4/VDIP6DPlkV6X3ehj/9/y8L1tfskdww81wA4N7e/PX -sPKH0bqib3lej1sVnwukakpbJwV07B84Uah7AGxd5f/he6u8vLLxz1oQJl4pIY8v -2DNgN4VoaWYGBHYKWluDalK8ClFkvzE3Ep7+hiFTAReJuby4LP5LCfZIesyJhR7e -6C+vZ4UEm8KdUScaxgS5AQ0EWCT0LAEIAKvi5l6gq5qdpfUwUCiBq2YHyDIXtXQG -KzcLoYpPeKCKqKYxmbmW3SIIIsIt42WjpZ0vBNWYJ+SbykNR9Fh+F1CMqrPiKOvT -shVnsbQybk+ljeO3O4Qtg1kj6mpCL3m7lPAMJ9pGZ9292xovLG0q5qoJg5WvNTIq -O7FUxbDWcRjUJDlsg5kbRDI/p2h65TEgqF0pGv+sziFXqBAtHm9eVr+mDa10ln47 -uB9QCW7tFMiuSP4j2KPVbZz+sRr6V1RVf/sS/5G7A4cukzF57ZSwCLRn8W+Pb7HQ -B9wC+uOUlmoGVlKc+xLeFYDM3+ksd86TJMmiQ0nWFMTCLr1aquKh8C8AEQEAAYkB -HwQYAQIACQUCWCT0LAIbDAAKCRBltDhAEBstxHDEB/47Uw2zTXRATH/cdpLDRaJE -UngRaxmygMer+huw4Whgn4m2VwOvW0oYVwZQfwJfq+irNDa8AgqDQjl077OO/XXh -swiAJc/OZ9QDX5eTwTUyzecVWXCqkZPktXnzaRY/kHoiPhTQh5IP5rpfMIX+BfWv -IUYqtHrfXqPZLJuELg8EorrVwGysXZuOZ0MwjUrEnBBfqWyWFq/CSVvlib+FOAOu -OJTO1UYLslZENdjzTwSKrDkxkTsbnOdVzWGGQEqYqJlm4vD5+OZoaHdjuSoJbl/p -7GvM8kP7zjugUA9BPTVBz7xKDZaN4wZ8G3Q50QfsR6MozFHKOMnVGeNG7rdZNQ0g -=dor1 ------END PGP PUBLIC KEY BLOCK----- diff --git a/resources/usr/share/metainfo/appimagetool.appdata.xml b/resources/usr/share/metainfo/appimagetool.appdata.xml deleted file mode 100644 index 0f7da9c2f..000000000 --- a/resources/usr/share/metainfo/appimagetool.appdata.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - appimagetool.desktop - MIT - MIT - appimagetool - Create AppImage files - -

- appimagetool is a tool that lets you generate AppImage files. An AppImage - is a self-running bundle that contains an application and everything - it needs to run that cannot reasonably expected to be part of each target system. -

-

- This can include libraries that are not commonly available on target systems, - resources such as translations, icons, fonts, and other auxiliary files. - appimagetool makes it easy to take an AppDir (e.g., generated by linuxdeployqt) - and turn it into an AppImage. -

-

- You can also embed update information so that your users can update the AppImage - using binary delta updates with the AppImageUpdate tool. - You can also sign the AppImage with GPG. -

-
- https://github.com/AppImage/AppImageKit - AppImage - - appimagetool - -
diff --git a/squashfs_osx.patch b/squashfs_osx.patch deleted file mode 100644 index b08351b10..000000000 --- a/squashfs_osx.patch +++ /dev/null @@ -1,434 +0,0 @@ -diff --git a/squashfs-tools/action.c b/squashfs-tools/action.c -index 4b06ccb..40780ae 100644 ---- a/squashfs-tools/action.c -+++ b/squashfs-tools/action.c -@@ -38,6 +38,10 @@ - #include - #include - -+#ifndef FNM_EXTMATCH /* glibc extension */ -+ #define FNM_EXTMATCH 0 -+#endif -+ - #include "squashfs_fs.h" - #include "mksquashfs.h" - #include "action.h" -@@ -2284,9 +2288,12 @@ static char *get_start(char *s, int n) - - static int subpathname_fn(struct atom *atom, struct action_data *action_data) - { -- return fnmatch(atom->argv[0], get_start(strdupa(action_data->subpath), -+ char *path = strdup(action_data->subpath); -+ int is_match = fnmatch(atom->argv[0], get_start(path, - count_components(atom->argv[0])), - FNM_PATHNAME|FNM_PERIOD|FNM_EXTMATCH) == 0; -+ free(path); -+ return is_match; - } - - /* -diff --git a/squashfs-tools/info.c b/squashfs-tools/info.c -index 7968c77..56f26dc 100644 ---- a/squashfs-tools/info.c -+++ b/squashfs-tools/info.c -@@ -134,31 +134,22 @@ void dump_state() - void *info_thrd(void *arg) - { - sigset_t sigmask; -- struct timespec timespec = { .tv_sec = 1, .tv_nsec = 0 }; -- int sig, waiting = 0; -+ int sig, err, waiting = 0; - - sigemptyset(&sigmask); - sigaddset(&sigmask, SIGQUIT); - sigaddset(&sigmask, SIGHUP); -+ sigaddset(&sigmask, SIGALRM); - - while(1) { -- if(waiting) -- sig = sigtimedwait(&sigmask, NULL, ×pec); -- else -- sig = sigwaitinfo(&sigmask, NULL); -+ err = sigwait(&sigmask, &sig); - -- if(sig == -1) { -+ if(err == -1) { - switch(errno) { -- case EAGAIN: -- /* interval timed out */ -- waiting = 0; -- /* FALLTHROUGH */ - case EINTR: -- /* if waiting, the wait will be longer, but -- that's OK */ - continue; - default: -- BAD_ERROR("sigtimedwait/sigwaitinfo failed " -+ BAD_ERROR("sigwait failed " - "because %s\n", strerror(errno)); - } - } -@@ -169,8 +160,12 @@ void *info_thrd(void *arg) - /* set one second interval period, if ^\ received - within then, dump queue and cache status */ - waiting = 1; -- } else -+ alarm(1); -+ } else if (sig == SIGQUIT) { - dump_state(); -+ } else if (sig == SIGALRM) { -+ waiting = 0; -+ } - } - } - -diff --git a/squashfs-tools/mksquashfs.c b/squashfs-tools/mksquashfs.c -index e7965c4..44d62ce 100644 ---- a/squashfs-tools/mksquashfs.c -+++ b/squashfs-tools/mksquashfs.c -@@ -50,6 +50,10 @@ - #include - #include - -+#ifndef FNM_EXTMATCH /* glibc extension */ -+ #define FNM_EXTMATCH 0 -+#endif -+ - #ifndef linux - #define __BYTE_ORDER BYTE_ORDER - #define __BIG_ENDIAN BIG_ENDIAN -@@ -830,13 +834,13 @@ char *subpathname(struct dir_ent *dir_ent) - } - - --inline unsigned int get_inode_no(struct inode_info *inode) -+static inline unsigned int get_inode_no(struct inode_info *inode) - { - return inode->inode_number; - } - - --inline unsigned int get_parent_no(struct dir_info *dir) -+static inline unsigned int get_parent_no(struct dir_info *dir) - { - return dir->depth ? get_inode_no(dir->dir_ent->inode) : inode_no; - } -@@ -2029,7 +2033,7 @@ struct file_info *duplicate(long long file_size, long long bytes, - } - - --inline int is_fragment(struct inode_info *inode) -+static inline int is_fragment(struct inode_info *inode) - { - off_t file_size = inode->buf.st_size; - -@@ -2998,13 +3002,13 @@ struct inode_info *lookup_inode2(struct stat *buf, int pseudo, int id) - } - - --inline struct inode_info *lookup_inode(struct stat *buf) -+static inline struct inode_info *lookup_inode(struct stat *buf) - { - return lookup_inode2(buf, 0, 0); - } - - --inline void alloc_inode_no(struct inode_info *inode, unsigned int use_this) -+static inline void alloc_inode_no(struct inode_info *inode, unsigned int use_this) - { - if (inode->inode_number == 0) { - inode->inode_number = use_this ? : inode_no ++; -@@ -3015,7 +3019,7 @@ inline void alloc_inode_no(struct inode_info *inode, unsigned int use_this) - } - - --inline struct dir_ent *create_dir_entry(char *name, char *source_name, -+static inline struct dir_ent *create_dir_entry(char *name, char *source_name, - char *nonstandard_pathname, struct dir_info *dir) - { - struct dir_ent *dir_ent = malloc(sizeof(struct dir_ent)); -@@ -3033,7 +3037,7 @@ inline struct dir_ent *create_dir_entry(char *name, char *source_name, - } - - --inline void add_dir_entry(struct dir_ent *dir_ent, struct dir_info *sub_dir, -+static inline void add_dir_entry(struct dir_ent *dir_ent, struct dir_info *sub_dir, - struct inode_info *inode_info) - { - struct dir_info *dir = dir_ent->our_dir; -@@ -3049,7 +3053,7 @@ inline void add_dir_entry(struct dir_ent *dir_ent, struct dir_info *sub_dir, - } - - --inline void add_dir_entry2(char *name, char *source_name, -+static inline void add_dir_entry2(char *name, char *source_name, - char *nonstandard_pathname, struct dir_info *sub_dir, - struct inode_info *inode_info, struct dir_info *dir) - { -@@ -3061,7 +3065,7 @@ inline void add_dir_entry2(char *name, char *source_name, - } - - --inline void free_dir_entry(struct dir_ent *dir_ent) -+static inline void free_dir_entry(struct dir_ent *dir_ent) - { - if(dir_ent->name) - free(dir_ent->name); -@@ -3082,7 +3086,7 @@ inline void free_dir_entry(struct dir_ent *dir_ent) - } - - --inline void add_excluded(struct dir_info *dir) -+static inline void add_excluded(struct dir_info *dir) - { - dir->excluded ++; - } -@@ -4199,6 +4203,7 @@ void initialise_threads(int readq, int fragq, int bwriteq, int fwriteq, - sigemptyset(&sigmask); - sigaddset(&sigmask, SIGQUIT); - sigaddset(&sigmask, SIGHUP); -+ sigaddset(&sigmask, SIGALRM); - if(pthread_sigmask(SIG_BLOCK, &sigmask, NULL) == -1) - BAD_ERROR("Failed to set signal mask in intialise_threads\n"); - -@@ -4986,6 +4991,36 @@ int parse_num(char *arg, int *res) - - int get_physical_memory() - { -+ int phys_mem; -+#ifndef linux -+ #ifdef HW_MEMSIZE -+ #define SYSCTL_PHYSMEM HW_MEMSIZE -+ #elif defined(HW_PHYSMEM64) -+ #define SYSCTL_PHYSMEM HW_PHYSMEM64 -+ #else -+ #define SYSCTL_PHYSMEM HW_PHYSMEM -+ #endif -+ -+ int mib[2]; -+ uint64_t sysctl_physmem = 0; -+ size_t sysctl_len = sizeof(sysctl_physmem); -+ -+ mib[0] = CTL_HW; -+ mib[1] = SYSCTL_PHYSMEM; -+ -+ if(sysctl(mib, 2, &sysctl_physmem, &sysctl_len, NULL, 0) == 0) { -+ /* some systems use 32-bit values, work with what we're given */ -+ if (sysctl_len == 4) -+ sysctl_physmem = *(uint32_t*)&sysctl_physmem; -+ phys_mem = sysctl_physmem >> 20; -+ } else { -+ ERROR_START("Failed to get amount of available " -+ "memory."); -+ ERROR_EXIT(" Defaulting to least viable amount\n"); -+ phys_mem = SQUASHFS_LOWMEM; -+ } -+ #undef SYSCTL_PHYSMEM -+#else - /* - * Long longs are used here because with PAE, a 32-bit - * machine can have more than 4GB of physical memory -@@ -4993,10 +5028,11 @@ int get_physical_memory() - * sysconf(_SC_PHYS_PAGES) relies on /proc being mounted. - * If it isn't fail. - */ -- long long num_pages = sysconf(_SC_PHYS_PAGES); -- long long page_size = sysconf(_SC_PAGESIZE); - int phys_mem = num_pages * page_size >> 20; -+#endif - -+ long long num_pages = sysconf(_SC_PHYS_PAGES); -+ long long page_size = sysconf(_SC_PAGESIZE); - if(num_pages == -1 || page_size == -1) - return 0; - -diff --git a/squashfs-tools/mksquashfs.h b/squashfs-tools/mksquashfs.h -index 55708a3..d44d1fd 100644 ---- a/squashfs-tools/mksquashfs.h -+++ b/squashfs-tools/mksquashfs.h -@@ -24,6 +24,7 @@ - * mksquashfs.h - * - */ -+#include - - struct dir_info { - char *pathname; -diff --git a/squashfs-tools/pseudo.c b/squashfs-tools/pseudo.c -index cb74cf6..fe2b4bc 100644 ---- a/squashfs-tools/pseudo.c -+++ b/squashfs-tools/pseudo.c -@@ -30,6 +30,7 @@ - #include - #include - #include -+#include - #include - #include - #include -diff --git a/squashfs-tools/read_xattrs.c b/squashfs-tools/read_xattrs.c -index 42106f5..837d3fb 100644 ---- a/squashfs-tools/read_xattrs.c -+++ b/squashfs-tools/read_xattrs.c -@@ -39,13 +39,13 @@ - #include - #endif - -+#include -+ - #include "squashfs_fs.h" - #include "squashfs_swap.h" - #include "xattr.h" - #include "error.h" - --#include -- - extern int read_fs_bytes(int, long long, int, void *); - extern int read_block(int, long long, long long *, int, void *); - -diff --git a/squashfs-tools/unsquashfs.c b/squashfs-tools/unsquashfs.c -index c5e0876..e5566ff 100644 ---- a/squashfs-tools/unsquashfs.c -+++ b/squashfs-tools/unsquashfs.c -@@ -32,7 +32,12 @@ - #include "stdarg.h" - #include "fnmatch_compat.h" - -+#ifndef linux -+#include -+#else - #include -+#endif -+ - #include - #include - #include -@@ -2180,6 +2185,7 @@ void initialise_threads(int fragment_buffer_size, int data_buffer_size) - sigemptyset(&sigmask); - sigaddset(&sigmask, SIGQUIT); - sigaddset(&sigmask, SIGHUP); -+ sigaddset(&sigmask, SIGALRM); - if(pthread_sigmask(SIG_BLOCK, &sigmask, NULL) == -1) - EXIT_UNSQUASH("Failed to set signal mask in initialise_threads" - "\n"); -diff --git a/squashfs-tools/unsquashfs.h b/squashfs-tools/unsquashfs.h -index 0edbd25..cea9caa 100644 ---- a/squashfs-tools/unsquashfs.h -+++ b/squashfs-tools/unsquashfs.h -@@ -46,6 +46,10 @@ - #include - #include - -+#ifndef FNM_EXTMATCH /* glibc extension */ -+ #define FNM_EXTMATCH 0 -+#endif -+ - #ifndef linux - #define __BYTE_ORDER BYTE_ORDER - #define __BIG_ENDIAN BIG_ENDIAN -diff --git a/squashfs-tools/unsquashfs_info.c b/squashfs-tools/unsquashfs_info.c -index c8e2b9b..e26f0de 100644 ---- a/squashfs-tools/unsquashfs_info.c -+++ b/squashfs-tools/unsquashfs_info.c -@@ -97,31 +97,21 @@ void dump_state() - void *info_thrd(void *arg) - { - sigset_t sigmask; -- struct timespec timespec = { .tv_sec = 1, .tv_nsec = 0 }; -- int sig, waiting = 0; -+ int sig, err, waiting = 0; - - sigemptyset(&sigmask); - sigaddset(&sigmask, SIGQUIT); - sigaddset(&sigmask, SIGHUP); -+ sigaddset(&sigmask, SIGALRM); - - while(1) { -- if(waiting) -- sig = sigtimedwait(&sigmask, NULL, ×pec); -- else -- sig = sigwaitinfo(&sigmask, NULL); -- -- if(sig == -1) { -- switch(errno) { -- case EAGAIN: -- /* interval timed out */ -- waiting = 0; -- /* FALLTHROUGH */ -+ err = sigwait(&sigmask, &sig); -+ -+ if(err == -1) { - case EINTR: -- /* if waiting, the wait will be longer, but -- that's OK */ - continue; - default: -- BAD_ERROR("sigtimedwait/sigwaitinfo failed " -+ BAD_ERROR("sigwait failed " - "because %s\n", strerror(errno)); - } - } -@@ -133,8 +123,12 @@ void *info_thrd(void *arg) - /* set one second interval period, if ^\ received - within then, dump queue and cache status */ - waiting = 1; -- } else -- dump_state(); -+ alarm(1); -+ } else if (sig == SIGQUIT) { -+ dump_state(); -+ } else if (sig == SIGALRM) { -+ waiting = 0; -+ } - } - } - -diff --git a/squashfs-tools/unsquashfs_xattr.c b/squashfs-tools/unsquashfs_xattr.c -index 59f4aae..13f0e35 100644 ---- a/squashfs-tools/unsquashfs_xattr.c -+++ b/squashfs-tools/unsquashfs_xattr.c -@@ -27,6 +27,11 @@ - - #include - -+#ifdef XATTR_NOFOLLOW /* Apple's xattrs */ -+ #define lsetxattr(path_, name_, val_, sz_, flags_) \ -+ setxattr(path_, name_, val_, sz_, 0, flags_ | XATTR_NOFOLLOW) -+#endif -+ - #define NOSPACE_MAX 10 - - extern int root_process; -diff --git a/squashfs-tools/xattr.c b/squashfs-tools/xattr.c -index b46550c..5b32eca 100644 ---- a/squashfs-tools/xattr.c -+++ b/squashfs-tools/xattr.c -@@ -22,6 +22,14 @@ - * xattr.c - */ - -+#ifndef linux -+#define __BYTE_ORDER BYTE_ORDER -+#define __BIG_ENDIAN BIG_ENDIAN -+#define __LITTLE_ENDIAN LITTLE_ENDIAN -+#else -+#include -+#endif -+ - #define TRUE 1 - #define FALSE 0 - -@@ -36,6 +44,13 @@ - #include - #include - -+#ifdef XATTR_NOFOLLOW /* Apple's xattrs */ -+ #define llistxattr(path_, buf_, sz_) \ -+ listxattr(path_, buf_, sz_, XATTR_NOFOLLOW) -+ #define lgetxattr(path_, name_, val_, sz_) \ -+ getxattr(path_, name_, val_, sz_, 0, XATTR_NOFOLLOW) -+#endif -+ - #include "squashfs_fs.h" - #include "squashfs_swap.h" - #include "mksquashfs.h" diff --git a/src/AppRun.c b/src/AppRun.c deleted file mode 100644 index 3ff82af3f..000000000 --- a/src/AppRun.c +++ /dev/null @@ -1,219 +0,0 @@ -/************************************************************************** - -Copyright (c) 2004-18 Simon Peter -Portions Copyright (c) 2010 RazZziel - -All Rights Reserved. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -**************************************************************************/ - -#include -#include -#include -#include -#include -#include -#include - -#define die(...) \ - do { \ - fprintf(stderr, "Error: " __VA_ARGS__); \ - exit(1); \ - } while(0); -#define SET_NEW_ENV(str,len,fmt,...) \ - format = fmt; \ - length = strlen(format) + (len); \ - char *str = calloc(length, sizeof(char)); \ - snprintf(str, length, format, __VA_ARGS__); \ - putenv(str); -#define MAX(a,b) (a > b ? a : b) -#define bool int -#define false 0 -#define true -1 - -#define LINE_SIZE 255 - -int filter(const struct dirent *dir) { - char *p = (char*) &dir->d_name; - p = strrchr(p, '.'); - return p && !strcmp(p, ".desktop"); -} - -int main(int argc, char *argv[]) { - char *appdir = dirname(realpath("/proc/self/exe", NULL)); - if (!appdir) - die("Could not access /proc/self/exe\n"); - - int ret; - struct dirent **namelist; - ret = scandir(appdir, &namelist, filter, NULL); - - if (ret == 0) { - die("No .desktop files found\n"); - } else if(ret == -1) { - die("Could not scan directory %s\n", appdir); - } - - /* Extract executable from .desktop file */ - char *desktop_file = calloc(LINE_SIZE, sizeof(char)); - snprintf(desktop_file, LINE_SIZE, "%s/%s", appdir, namelist[0]->d_name); - FILE *f = fopen(desktop_file, "r"); - char *line = malloc(LINE_SIZE); - size_t n = LINE_SIZE; - - do { - if (getline(&line, &n, f) == -1) - die("Executable not found, make sure there is a line starting with 'Exec='\n"); - } while(strncmp(line, "Exec=", 5)); - fclose(f); - char *exe = line+5; - - // parse arguments - bool in_quotes = 0; - for (n = 0; n < LINE_SIZE; n++) { - if (!line[n]) // end of string - break; - else if (line[n] == 10 || line[n] == 13) { - line[n] = '\0'; - line[n+1] = '\0'; - line[n+2] = '\0'; - break; - } else if (line[n] == '"') { - in_quotes = !in_quotes; - } else if (line[n] == ' ' && !in_quotes) - line[n] = '\0'; - } - - // count arguments - char* arg = exe; - int argcount = 0; - while ((arg += (strlen(arg)+1)) && *arg) - argcount += 1; - - // merge args - char* outargptrs[argcount + argc + 1]; - outargptrs[0] = exe; - int outargindex = 1; - arg = exe; - int argc_ = argc - 1; // argv[0] is the filename - char** argv_ = argv + 1; - while ((arg += (strlen(arg)+1)) && *arg) { - if (arg[0] == '%' || (arg[0] == '"' && arg[1] == '%')) { // handle desktop file field codes - char code = arg[arg[0] == '%' ? 1 : 2]; - switch(code) { - case 'f': - case 'u': - if (argc_ > 0) { - outargptrs[outargindex++] = *argv_++; - argc_--; - } - break; - case 'F': - case 'U': - while (argc_ > 0) { - outargptrs[outargindex++] = *argv_++; - argc_--; - } - break; - case 'i': - case 'c': - case 'k': - fprintf(stderr, "WARNING: Desktop file field code %%%c is not currently supported\n", code); - break; - default: - fprintf(stderr, "WARNING: Invalid desktop file field code %%%c\n", code); - break; - } - } else { - outargptrs[outargindex++] = arg; - } - } - while (argc_ > 0) { - outargptrs[outargindex++] = *argv_++; - argc_--; - } - outargptrs[outargindex] = '\0'; // trailing null argument required by execvp() - - // change directory - size_t appdir_s = strlen(appdir); - char *usr_in_appdir = malloc(appdir_s + 5); - snprintf(usr_in_appdir, appdir_s + 5, "%s/usr", appdir); - ret = chdir(usr_in_appdir); - if (ret != 0) - die("Could not cd into %s\n", usr_in_appdir); - - // set environment variables - char *old_env; - size_t length; - const char *format; - - /* https://docs.python.org/2/using/cmdline.html#envvar-PYTHONHOME */ - SET_NEW_ENV(new_pythonhome, appdir_s, "PYTHONHOME=%s/usr/", appdir); - - old_env = getenv("PATH") ?: ""; - SET_NEW_ENV(new_path, appdir_s*5 + strlen(old_env), "PATH=%s/usr/bin/:%s/usr/sbin/:%s/usr/games/:%s/bin/:%s/sbin/:%s", appdir, appdir, appdir, appdir, appdir, old_env); - - old_env = getenv("LD_LIBRARY_PATH") ?: ""; - SET_NEW_ENV(new_ld_library_path, appdir_s*10 + strlen(old_env), "LD_LIBRARY_PATH=%s/usr/lib/:%s/usr/lib/i386-linux-gnu/:%s/usr/lib/x86_64-linux-gnu/:%s/usr/lib32/:%s/usr/lib64/:%s/lib/:%s/lib/i386-linux-gnu/:%s/lib/x86_64-linux-gnu/:%s/lib32/:%s/lib64/:%s", appdir, appdir, appdir, appdir, appdir, appdir, appdir, appdir, appdir, appdir, old_env); - - old_env = getenv("PYTHONPATH") ?: ""; - SET_NEW_ENV(new_pythonpath, appdir_s + strlen(old_env), "PYTHONPATH=%s/usr/share/pyshared/:%s", appdir, old_env); - - old_env = getenv("XDG_DATA_DIRS") ?: "/usr/local/share/:/usr/share/"; - SET_NEW_ENV(new_xdg_data_dirs, appdir_s + strlen(old_env), "XDG_DATA_DIRS=%s/usr/share/:%s", appdir, old_env); - - old_env = getenv("PERLLIB") ?: ""; - SET_NEW_ENV(new_perllib, appdir_s*2 + strlen(old_env), "PERLLIB=%s/usr/share/perl5/:%s/usr/lib/perl5/:%s", appdir, appdir, old_env); - - /* http://askubuntu.com/questions/251712/how-can-i-install-a-gsettings-schema-without-root-privileges */ - old_env = getenv("GSETTINGS_SCHEMA_DIR") ?: ""; - SET_NEW_ENV(new_gsettings_schema_dir, appdir_s + strlen(old_env), "GSETTINGS_SCHEMA_DIR=%s/usr/share/glib-2.0/schemas/:%s", appdir, old_env); - - old_env = getenv("QT_PLUGIN_PATH") ?: ""; - SET_NEW_ENV(new_qt_plugin_path, appdir_s*10 + strlen(old_env), "QT_PLUGIN_PATH=%s/usr/lib/qt4/plugins/:%s/usr/lib/i386-linux-gnu/qt4/plugins/:%s/usr/lib/x86_64-linux-gnu/qt4/plugins/:%s/usr/lib32/qt4/plugins/:%s/usr/lib64/qt4/plugins/:%s/usr/lib/qt5/plugins/:%s/usr/lib/i386-linux-gnu/qt5/plugins/:%s/usr/lib/x86_64-linux-gnu/qt5/plugins/:%s/usr/lib32/qt5/plugins/:%s/usr/lib64/qt5/plugins/:%s", appdir, appdir, appdir, appdir, appdir, appdir, appdir, appdir, appdir, appdir, old_env); - - SET_NEW_ENV(new_gspath, appdir_s + strlen(old_env), "GST_PLUGIN_SYSTEM_PATH=%s/usr/lib/gstreamer:%s", appdir, old_env); - SET_NEW_ENV(new_gspath1, appdir_s + strlen(old_env), "GST_PLUGIN_SYSTEM_PATH_1_0=%s/usr/lib/gstreamer-1.0:%s", appdir, old_env); - - /* Otherwise may get errors because Python cannot write __pycache__ bytecode cache */ - putenv("PYTHONDONTWRITEBYTECODE=1"); - - /* Run */ - ret = execvp(exe, outargptrs); - - int error = errno; - - if (ret == -1) - die("Error executing '%s': %s\n", exe, strerror(error)); - - free(line); - free(desktop_file); - free(usr_in_appdir); - free(new_pythonhome); - free(new_path); - free(new_ld_library_path); - free(new_pythonpath); - free(new_xdg_data_dirs); - free(new_perllib); - free(new_gsettings_schema_dir); - free(new_qt_plugin_path); - return 0; -} diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt deleted file mode 100644 index f2247b405..000000000 --- a/src/CMakeLists.txt +++ /dev/null @@ -1,169 +0,0 @@ -find_package(Sanitizers) - -if(NOT COMMAND add_sanitizers) - message(WARNING "Sanitizers CMake module not found, sanitizer support is not available") - # defining a no-op function to avoid CMake errors - function(add_sanitizers ...) - endfunction() -endif() - - -# allow setting different path for mksquashfs after installation -set(AUXILIARY_FILES_DESTINATION "lib/appimagekit" CACHE STRING "Target install directory for mksquashfs") - - -# the runtime build configuration is quite long, therefore it's managed in a separate CMake script -include(build-runtime.cmake) - - -add_executable(appimagetool - appimagetool.c - appimagetool_sign.c - binreloc.c - runtime_embed.o -) - -target_include_directories(appimagetool - PUBLIC $ - INTERFACE $ -) - -# required for appimagetool's signing -# we're using CMake's functionality directly, since we want to link those statically -find_package(PkgConfig) -pkg_check_modules(libgpgme REQUIRED gpgme IMPORTED_TARGET) -pkg_check_modules(libgcrypt REQUIRED libgcrypt IMPORTED_TARGET) - -# trick: list libraries on which imported static ones depend on in the PUBLIC section -# CMake then adds them after the PRIVATE ones in the linker command -target_link_libraries(appimagetool - ${CMAKE_DL_LIBS} - libsquashfuse - xdg-basedir - libappimage_shared - libglib - libgio - libzlib - PkgConfig::libgcrypt - PkgConfig::libgpgme - xz -) - -target_compile_definitions(appimagetool - PRIVATE -D_FILE_OFFSET_BITS=64 - PRIVATE -DGIT_COMMIT="${GIT_COMMIT}" - PRIVATE -DBUILD_NUMBER="${BUILD_NUMBER}" - PRIVATE -DBUILD_DATE="${DATE}" - PRIVATE -DENABLE_BINRELOC -) - -target_include_directories(appimagetool - PUBLIC $ - INTERFACE $ -) - -if(AUXILIARY_FILES_DESTINATION) - message(STATUS "Installing auxiliary files in path: ${AUXILIARY_FILES_DESTINATION}") - target_compile_definitions(appimagetool - PRIVATE -DAUXILIARY_FILES_DESTINATION="${AUXILIARY_FILES_DESTINATION}" - ) -endif() - -add_sanitizers(appimagetool) - - -add_executable(AppRun AppRun.c) - -target_compile_definitions(AppRun - PRIVATE -D_FILE_OFFSET_BITS=64 - PRIVATE -DGIT_COMMIT="${GIT_COMMIT}" - PRIVATE -DENABLE_BINRELOC -) - -add_sanitizers(AppRun) - - -if (NOT TARGET libssl) - message(WARNING "Could not find suitable libssl, skipping build of validate and digest") -else() - add_executable(validate validate.c) - - target_link_libraries(validate - libappimage_shared - libglib - libssl - ) - - target_include_directories(validate - PUBLIC $ - INTERFACE $ - INTERFACE $ -) - -target_link_libraries(digest_md5 - PRIVATE libglib - PRIVATE libappimage_shared -) - - -# install binaries -if(NOT USE_SYSTEM_MKSQUASHFS) - if(AUXILIARY_FILES_DESTINATION) - install( - PROGRAMS ${mksquashfs_INSTALL_DIR}/mksquashfs ${CMAKE_CURRENT_BINARY_DIR}/runtime - DESTINATION ${AUXILIARY_FILES_DESTINATION} - COMPONENT applications - ) - else() - install( - PROGRAMS ${mksquashfs_INSTALL_DIR}/mksquashfs ${CMAKE_CURRENT_BINARY_DIR}/runtime - DESTINATION bin - COMPONENT applications - ) - endif() -endif() - -set(optional_targets "") -foreach(target validate digest) - if(TARGET ${target}) - list(APPEND optional_targets ${target}) - endif() -endforeach() - -install( - TARGETS AppRun appimagetool ${optional_targets} - RUNTIME DESTINATION bin COMPONENT applications - LIBRARY DESTINATION lib COMPONENT applications - ARCHIVE DESTINATION lib/static COMPONENT applications - INCLUDES DESTINATION include COMPONENT applications -) - -# Configure appimagetool component -install( - TARGETS appimagetool AppRun - RUNTIME DESTINATION bin COMPONENT appimagetool EXCLUDE_FROM_ALL -) - -install(FILES "${PROJECT_SOURCE_DIR}/resources/appimagetool.desktop" DESTINATION share/applications COMPONENT appimagetool EXCLUDE_FROM_ALL) -install(FILES "${PROJECT_SOURCE_DIR}/resources/appimagetool.png" DESTINATION share/icons/hicolor/128x128/apps COMPONENT appimagetool EXCLUDE_FROM_ALL) -install(FILES "${PROJECT_SOURCE_DIR}/resources/usr/share/metainfo/appimagetool.appdata.xml" DESTINATION share/metainfo COMPONENT appimagetool EXCLUDE_FROM_ALL) diff --git a/src/appimagetool.c b/src/appimagetool.c deleted file mode 100644 index a4132649f..000000000 --- a/src/appimagetool.c +++ /dev/null @@ -1,1153 +0,0 @@ -/************************************************************************** - * - * Copyright (c) 2004-19 Simon Peter - * - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - **************************************************************************/ - -#ident "AppImage by Simon Peter, http://appimage.org/" - -#ifndef RELEASE_NAME - #define RELEASE_NAME "continuous build" -#endif - -#include -#include -#include -#include - -#include -#include - -#include -#include "squashfuse.h" - -#include -#include -#include - -#include "binreloc.h" - -#include - -#include -#include -#include -#include -#include -#include - -#include "appimage/appimage.h" -#include "appimagetool_sign.h" - -#ifdef __linux__ -#define HAVE_BINARY_RUNTIME -extern char runtime[]; -extern unsigned int runtime_len; -#endif - -enum fARCH { - fARCH_i386, - fARCH_x86_64, - fARCH_arm, - fARCH_aarch64 -}; - -static gchar const APPIMAGEIGNORE[] = ".appimageignore"; -static char _exclude_file_desc[256]; - -static gboolean list = FALSE; -static gboolean verbose = FALSE; -static gboolean showVersionOnly = FALSE; -static gboolean sign = FALSE; -static gboolean no_appstream = FALSE; -gchar **remaining_args = NULL; -gchar *updateinformation = NULL; -static gboolean guess_update_information = FALSE; -gchar *bintray_user = NULL; -gchar *bintray_repo = NULL; -gchar *sqfs_comp = "gzip"; -gchar **sqfs_opts = NULL; -gchar *exclude_file = NULL; -gchar *runtime_file = NULL; -gchar *sign_key = NULL; -gchar *pathToMksquashfs = NULL; - -// ##################################################################### - -static void die(const char *msg) { - fprintf(stderr, "%s\n", msg); - exit(1); -} - -/* Function that prints the contents of a squashfs file -* using libsquashfuse (#include "squashfuse.h") */ -int sfs_ls(char* image) { - sqfs_err err = SQFS_OK; - sqfs_traverse trv; - sqfs fs; - - ssize_t fs_offset = appimage_get_elf_size(image); - - // error check - if (fs_offset < 0) - die("failed to read elf size"); - - if ((err = sqfs_open_image(&fs, image, fs_offset))) - die("sqfs_open_image error"); - - if ((err = sqfs_traverse_open(&trv, &fs, sqfs_inode_root(&fs)))) - die("sqfs_traverse_open error"); - while (sqfs_traverse_next(&trv, &err)) { - if (!trv.dir_end) { - printf("%s\n", trv.path); - } - } - if (err) - die("sqfs_traverse_next error"); - sqfs_traverse_close(&trv); - - sqfs_fd_close(fs.fd); - return 0; -} - -/* Generate a squashfs filesystem using mksquashfs on the $PATH -* execlp(), execvp(), and execvpe() search on the $PATH */ -int sfs_mksquashfs(char *source, char *destination, int offset) { - pid_t pid = fork(); - if (pid == -1) { - perror("sfs_mksquashfs fork() failed"); - return(-1); - } - - if (pid > 0) { - // This is the parent process. Wait for the child to termiante and check its exit status. - int status; - if(waitpid(pid, &status, 0) == -1) { - perror("sfs_mksquashfs waitpid() failed"); - return(-1); - } - - int retcode = WEXITSTATUS(status); - if (retcode) { - fprintf(stderr, "mksquashfs (pid %d) exited with code %d\n", pid, retcode); - return(-1); - } - - return 0; - } else { - // we are the child - gchar* offset_string; - offset_string = g_strdup_printf("%i", offset); - - guint sqfs_opts_len = sqfs_opts ? g_strv_length(sqfs_opts) : 0; - - int max_num_args = sqfs_opts_len + 22; - char* args[max_num_args]; - bool use_xz = strcmp(sqfs_comp, "xz") >= 0; - - int i = 0; -#ifndef AUXILIARY_FILES_DESTINATION - args[i++] = "mksquashfs"; -#else - args[i++] = pathToMksquashfs; -#endif - args[i++] = source; - args[i++] = destination; - args[i++] = "-offset"; - args[i++] = offset_string; - - args[i++] = "-comp"; - if (use_xz) - args[i++] = "xz"; - else - args[i++] = sqfs_comp; - - args[i++] = "-root-owned"; - args[i++] = "-noappend"; - - if (use_xz) { - // https://jonathancarter.org/2015/04/06/squashfs-performance-testing/ says: - // improved performance by using a 16384 block size with a sacrifice of around 3% more squashfs image space - args[i++] = "-Xdict-size"; - args[i++] = "100%"; - args[i++] = "-b"; - args[i++] = "16384"; - } - - // check if ignore file exists and use it if possible - if (access(APPIMAGEIGNORE, F_OK) >= 0) { - printf("Including %s", APPIMAGEIGNORE); - args[i++] = "-wildcards"; - args[i++] = "-ef"; - - // avoid warning: assignment discards ‘const’ qualifier - char* buf = strdup(APPIMAGEIGNORE); - args[i++] = buf; - } - - // if an exclude file has been passed on the command line, should be used, too - if (exclude_file != 0 && strlen(exclude_file) > 0) { - if (access(exclude_file, F_OK) < 0) { - printf("WARNING: exclude file %s not found!", exclude_file); - return -1; - } - - args[i++] = "-wildcards"; - args[i++] = "-ef"; - args[i++] = exclude_file; - } - - args[i++] = "-mkfs-time"; - args[i++] = "0"; - - for (guint sqfs_opts_idx = 0; sqfs_opts_idx < sqfs_opts_len; ++sqfs_opts_idx) { - args[i++] = sqfs_opts[sqfs_opts_idx]; - } - - args[i++] = 0; - - if (verbose) { - printf("mksquashfs commandline: "); - for (char** t = args; *t != 0; t++) { - printf("%s ", *t); - } - printf("\n"); - } - -#ifndef AUXILIARY_FILES_DESTINATION - execvp("mksquashfs", args); - perror("execvp(\"mksquashfs\") failed"); -#else - execvp(pathToMksquashfs, args); - fprintf(stderr, "execvp(\"%s\") failed: %s\n", pathToMksquashfs, strerror(errno)); -#endif - return -1; // exec never returns - } - return 0; -} - -/* Validate desktop file using desktop-file-validate on the $PATH -* execlp(), execvp(), and execvpe() search on the $PATH */ -int validate_desktop_file(char *file) { - int statval; - int child_pid; - child_pid = fork(); - if(child_pid == -1) - { - printf("could not fork! \n"); - return 1; - } - else if(child_pid == 0) - { - execlp("desktop-file-validate", "desktop-file-validate", file, NULL); - } - else - { - waitpid(child_pid, &statval, WUNTRACED | WCONTINUED); - if(WIFEXITED(statval)){ - return(WEXITSTATUS(statval)); - } - } - return -1; -} - -/* Generate a squashfs filesystem -* The following would work if we link to mksquashfs.o after we renamed -* main() to mksquashfs_main() in mksquashfs.c but we don't want to actually do -* this because squashfs-tools is not under a permissive license -* i *nt sfs_mksquashfs(char *source, char *destination) { -* char *child_argv[5]; -* child_argv[0] = NULL; -* child_argv[1] = source; -* child_argv[2] = destination; -* child_argv[3] = "-root-owned"; -* child_argv[4] = "-noappend"; -* mksquashfs_main(5, child_argv); -* } -*/ - -/* in-place modification of the string, and assuming the buffer pointed to by -* line is large enough to hold the resulting string*/ -static void replacestr(char *line, const char *search, const char *replace) -{ - char *sp = NULL; - - if ((sp = strstr(line, search)) == NULL) { - return; - } - int search_len = strlen(search); - int replace_len = strlen(replace); - int tail_len = strlen(sp+search_len); - - memmove(sp+replace_len,sp+search_len,tail_len+1); - memcpy(sp, replace, replace_len); - - /* Do it recursively again until no more work to do */ - - if ((sp = strstr(line, search))) { - replacestr(line, search, replace); - } -} - -int count_archs(bool* archs) { - int countArchs = 0; - int i; - for (i = 0; i < 4; i++) { - countArchs += archs[i]; - } - return countArchs; -} - -gchar* getArchName(bool* archs) { - if (archs[fARCH_i386]) - return "i386"; - else if (archs[fARCH_x86_64]) - return "x86_64"; - else if (archs[fARCH_arm]) - return "armhf"; - else if (archs[fARCH_aarch64]) - return "aarch64"; - else - return "all"; -} - -void extract_arch_from_e_machine_field(int16_t e_machine, const gchar* sourcename, bool* archs) { - if (e_machine == 3) { - archs[fARCH_i386] = 1; - if(verbose) - fprintf(stderr, "%s used for determining architecture i386\n", sourcename); - } - - if (e_machine == 62) { - archs[fARCH_x86_64] = 1; - if(verbose) - fprintf(stderr, "%s used for determining architecture x86_64\n", sourcename); - } - - if (e_machine == 40) { - archs[fARCH_arm] = 1; - if(verbose) - fprintf(stderr, "%s used for determining architecture armhf\n", sourcename); - } - - if (e_machine == 183) { - archs[fARCH_aarch64] = 1; - if(verbose) - fprintf(stderr, "%s used for determining architecture aarch64\n", sourcename); - } -} - -void extract_arch_from_text(gchar *archname, const gchar* sourcename, bool* archs) { - if (archname) { - archname = g_strstrip(archname); - if (archname) { - replacestr(archname, "-", "_"); - replacestr(archname, " ", "_"); - if (g_ascii_strncasecmp("i386", archname, 20) == 0 - || g_ascii_strncasecmp("i486", archname, 20) == 0 - || g_ascii_strncasecmp("i586", archname, 20) == 0 - || g_ascii_strncasecmp("i686", archname, 20) == 0 - || g_ascii_strncasecmp("intel_80386", archname, 20) == 0 - || g_ascii_strncasecmp("intel_80486", archname, 20) == 0 - || g_ascii_strncasecmp("intel_80586", archname, 20) == 0 - || g_ascii_strncasecmp("intel_80686", archname, 20) == 0 - ) { - archs[fARCH_i386] = 1; - if (verbose) - fprintf(stderr, "%s used for determining architecture i386\n", sourcename); - } else if (g_ascii_strncasecmp("x86_64", archname, 20) == 0) { - archs[fARCH_x86_64] = 1; - if (verbose) - fprintf(stderr, "%s used for determining architecture x86_64\n", sourcename); - } else if (g_ascii_strncasecmp("arm", archname, 20) == 0) { - archs[fARCH_arm] = 1; - if (verbose) - fprintf(stderr, "%s used for determining architecture ARM\n", sourcename); - } else if (g_ascii_strncasecmp("arm_aarch64", archname, 20) == 0) { - archs[fARCH_aarch64] = 1; - if (verbose) - fprintf(stderr, "%s used for determining architecture ARM aarch64\n", sourcename); - } - } - } -} - -int16_t read_elf_e_machine_field(const gchar* file_path) { - int16_t e_machine = 0x00; - FILE* file = 0; - file = fopen(file_path, "rb"); - if (file) { - fseek(file, 0x12, SEEK_SET); - fgets((char*) (&e_machine), 0x02, file); - fclose(file); - } - - return e_machine; -} - -void guess_arch_of_file(const gchar *archfile, bool* archs) { - int16_t e_machine_field = read_elf_e_machine_field(archfile); - extract_arch_from_e_machine_field(e_machine_field, archfile, archs); -} - -void find_arch(const gchar *real_path, const gchar *pattern, bool* archs) { - GDir *dir; - gchar *full_name; - dir = g_dir_open(real_path, 0, NULL); - if (dir != NULL) { - const gchar *entry; - while ((entry = g_dir_read_name(dir)) != NULL) { - full_name = g_build_filename(real_path, entry, NULL); - if (g_file_test(full_name, G_FILE_TEST_IS_SYMLINK)) { - } else if (g_file_test(full_name, G_FILE_TEST_IS_DIR)) { - find_arch(full_name, pattern, archs); - } else if (g_file_test(full_name, G_FILE_TEST_IS_EXECUTABLE) || g_pattern_match_simple(pattern, entry) ) { - guess_arch_of_file(full_name, archs); - } - } - g_dir_close(dir); - } - else { - g_warning("%s: %s", real_path, g_strerror(errno)); - } -} - -gchar* find_first_matching_file_nonrecursive(const gchar *real_path, const gchar *pattern) { - GDir *dir; - gchar *full_name; - dir = g_dir_open(real_path, 0, NULL); - if (dir != NULL) { - const gchar *entry; - while ((entry = g_dir_read_name(dir)) != NULL) { - full_name = g_build_filename(real_path, entry, NULL); - if (g_file_test(full_name, G_FILE_TEST_IS_REGULAR)) { - if(g_pattern_match_simple(pattern, entry)) - return(full_name); - } - } - g_dir_close(dir); - } - else { - g_warning("%s: %s", real_path, g_strerror(errno)); - } - return NULL; -} - -gchar* get_desktop_entry(GKeyFile *kf, char *key) { - gchar *value = g_key_file_get_string (kf, "Desktop Entry", key, NULL); - if (! value){ - fprintf(stderr, "%s entry not found in desktop file\n", key); - } - return value; -} - -bool readFile(char* filename, int* size, char** buffer) { - FILE* f = fopen(filename, "rb"); - if (f==NULL) { - *buffer = 0; - *size = 0; - return false; - } - - fseek(f, 0, SEEK_END); - long fsize = ftell(f); - fseek(f, 0, SEEK_SET); - - char *indata = malloc(fsize); - fread(indata, fsize, 1, f); - fclose(f); - *size = (int)fsize; - *buffer = indata; - return TRUE; -} - -/* run a command outside the current appimage, block environs like LD_LIBRARY_PATH */ -int run_external(const char *filename, char *const argv []) { - int pid = fork(); - if (pid < 0) { - g_print("run_external: fork failed"); - // fork failed - exit(1); - } else if (pid == 0) { - // blocks env defined in resources/AppRun - unsetenv("LD_LIBRARY_PATH"); - unsetenv("PYTHONPATH"); - unsetenv("XDG_DATA_DIRS"); - unsetenv("PERLLIB"); - unsetenv("GSETTINGS_SCHEMA_DIR"); - unsetenv("QT_PLUGIN_PATH"); - // runs command - execv(filename, argv); - // execv(3) returns, indicating error - g_print("run_external: subprocess execv(3) got error %s", g_strerror(errno)); - exit(1); - } else { - int wstatus; - if (waitpid(pid, &wstatus, 0) == -1) { - g_print("run_external: wait failed"); - return -1; - } - if (WIFEXITED(wstatus) && (WEXITSTATUS(wstatus) == 0)) { - return 0; - } else { - g_print("run_external: subprocess exited with status %d", WEXITSTATUS(wstatus)); - return 1; - } - } -} - -// ##################################################################### - -static GOptionEntry entries[] = -{ - { "list", 'l', 0, G_OPTION_ARG_NONE, &list, "List files in SOURCE AppImage", NULL }, - { "updateinformation", 'u', 0, G_OPTION_ARG_STRING, &updateinformation, "Embed update information STRING; if zsyncmake is installed, generate zsync file", NULL }, - { "guess", 'g', 0, G_OPTION_ARG_NONE, &guess_update_information, "Guess update information based on Travis CI or GitLab environment variables", NULL }, - { "bintray-user", 0, 0, G_OPTION_ARG_STRING, &bintray_user, "Bintray user name", NULL }, - { "bintray-repo", 0, 0, G_OPTION_ARG_STRING, &bintray_repo, "Bintray repository", NULL }, - { "version", 0, 0, G_OPTION_ARG_NONE, &showVersionOnly, "Show version number", NULL }, - { "verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose, "Produce verbose output", NULL }, - { "sign", 's', 0, G_OPTION_ARG_NONE, &sign, "Sign with gpg[2]", NULL }, - { "comp", 0, 0, G_OPTION_ARG_STRING, &sqfs_comp, "Squashfs compression", NULL }, - { "mksquashfs-opt", 0, 0, G_OPTION_ARG_STRING_ARRAY, &sqfs_opts, "Argument to pass through to mksquashfs; can be specified multiple times", NULL }, - { "no-appstream", 'n', 0, G_OPTION_ARG_NONE, &no_appstream, "Do not check AppStream metadata", NULL }, - { "exclude-file", 0, 0, G_OPTION_ARG_STRING, &exclude_file, _exclude_file_desc, NULL }, - { "runtime-file", 0, 0, G_OPTION_ARG_STRING, &runtime_file, "Runtime file to use", NULL }, - { "sign-key", 0, 0, G_OPTION_ARG_STRING, &sign_key, "Key ID to use for gpg[2] signatures", NULL}, - { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &remaining_args, NULL, NULL }, - { 0,0,0,0,0,0,0 } -}; - -int -main (int argc, char *argv[]) -{ - - /* Parse Travis CI environment variables. - * https://docs.travis-ci.com/user/environment-variables/#Default-Environment-Variables - * TRAVIS_COMMIT: The commit that the current build is testing. - * TRAVIS_REPO_SLUG: The slug (in form: owner_name/repo_name) of the repository currently being built. - * TRAVIS_TAG: If the current build is for a git tag, this variable is set to the tag’s name. - * We cannot use g_environ_getenv (g_get_environ() since it is too new for CentOS 6 */ - // char* travis_commit; - // travis_commit = getenv("TRAVIS_COMMIT"); - char* travis_repo_slug; - travis_repo_slug = getenv("TRAVIS_REPO_SLUG"); - char* travis_tag; - travis_tag = getenv("TRAVIS_TAG"); - char* travis_pull_request; - travis_pull_request = getenv("TRAVIS_PULL_REQUEST"); - /* https://github.com/probonopd/uploadtool */ - char* github_token; - github_token = getenv("GITHUB_TOKEN"); - - /* Parse GitLab CI environment variables. - * https://docs.gitlab.com/ee/ci/variables/#predefined-variables-environment-variables - * echo "${CI_PROJECT_URL}/-/jobs/artifacts/${CI_COMMIT_REF_NAME}/raw/QtQuickApp-x86_64.AppImage?job=${CI_JOB_NAME}" - */ - char* CI_PROJECT_URL; - CI_PROJECT_URL = getenv("CI_PROJECT_URL"); - char* CI_COMMIT_REF_NAME; - CI_COMMIT_REF_NAME = getenv("CI_COMMIT_REF_NAME"); // The branch or tag name for which project is built - char* CI_JOB_NAME; - CI_JOB_NAME = getenv("CI_JOB_NAME"); // The name of the job as defined in .gitlab-ci.yml - - /* Parse OWD environment variable. - * If it is available then cd there. It is the original CWD prior to running AppRun */ - char* owd_env = NULL; - owd_env = getenv("OWD"); - if(NULL!=owd_env){ - int ret; - ret = chdir(owd_env); - if (ret != 0){ - fprintf(stderr, "Could not cd into %s\n", owd_env); - exit(1); - } - } - - GError *error = NULL; - GOptionContext *context; - - // initialize help text of argument - sprintf(_exclude_file_desc, "Uses given file as exclude file for mksquashfs, in addition to %s.", APPIMAGEIGNORE); - - context = g_option_context_new ("SOURCE [DESTINATION] - Generate, extract, and inspect AppImages"); - g_option_context_add_main_entries (context, entries, NULL); - // g_option_context_add_group (context, gtk_get_option_group (TRUE)); - if (!g_option_context_parse (context, &argc, &argv, &error)) - { - fprintf(stderr, "Option parsing failed: %s\n", error->message); - exit(1); - } - - fprintf( - stderr, - "appimagetool, %s (commit %s), build %s built on %s\n", - RELEASE_NAME, GIT_COMMIT, BUILD_NUMBER, BUILD_DATE - ); - - // always show version, but exit immediately if only the version number was requested - if (showVersionOnly) - exit(0); - - if(!((0 == strcmp(sqfs_comp, "gzip")) || (0 ==strcmp(sqfs_comp, "xz")))) - die("Only gzip (faster execution, larger files) and xz (slower execution, smaller files) compression is supported at the moment. Let us know if there are reasons for more, should be easy to add. You could help the project by doing some systematic size/performance measurements. Watch for size, execution speed, and zsync delta size."); - /* Check for dependencies here. Better fail early if they are not present. */ - if(! g_find_program_in_path ("file")) - die("file command is missing but required, please install it"); -#ifndef AUXILIARY_FILES_DESTINATION - if(! g_find_program_in_path ("mksquashfs")) - die("mksquashfs command is missing but required, please install it"); -#else - { - // build path relative to appimagetool binary - char *appimagetoolDirectory = dirname(realpath("/proc/self/exe", NULL)); - if (!appimagetoolDirectory) { - g_print("Could not access /proc/self/exe\n"); - exit(1); - } - - pathToMksquashfs = g_build_filename(appimagetoolDirectory, "..", AUXILIARY_FILES_DESTINATION, "mksquashfs", NULL); - - if (!g_file_test(pathToMksquashfs, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_EXECUTABLE)) { - g_printf("No such file or directory: %s\n", pathToMksquashfs); - g_free(pathToMksquashfs); - exit(1); - } - } -#endif - if(! g_find_program_in_path ("desktop-file-validate")) - die("desktop-file-validate command is missing, please install it"); - if(! g_find_program_in_path ("zsyncmake")) - g_print("WARNING: zsyncmake command is missing, please install it if you want to use binary delta updates\n"); - if(! no_appstream) - if(! g_find_program_in_path ("appstreamcli")) - g_print("WARNING: appstreamcli command is missing, please install it if you want to use AppStream metadata\n"); - if(! g_find_program_in_path ("gpg2") && ! g_find_program_in_path ("gpg")) - g_print("WARNING: gpg2 or gpg command is missing, please install it if you want to create digital signatures\n"); - if(! g_find_program_in_path ("sha256sum") && ! g_find_program_in_path ("shasum")) - g_print("WARNING: sha256sum or shasum command is missing, please install it if you want to create digital signatures\n"); - - if(!&remaining_args[0]) - die("SOURCE is missing"); - - /* If in list mode */ - if (list){ - sfs_ls(remaining_args[0]); - exit(0); - } - - /* If the first argument is a directory, then we assume that we should package it */ - if (g_file_test(remaining_args[0], G_FILE_TEST_IS_DIR)) { - /* Parse VERSION environment variable. - * We cannot use g_environ_getenv (g_get_environ() since it is too new for CentOS 6 - * Also, if VERSION is not set and -g is called and if git is on the path, use - * git rev-parse --short HEAD - * TODO: Might also want to somehow make use of - * git rev-parse --abbrev-ref HEAD - * git log -1 --format=%ci */ - gchar* version_env = getenv("VERSION"); - - if (guess_update_information) { - char* gitPath = g_find_program_in_path("git"); - - if (gitPath != NULL) { - if (version_env == NULL) { - GError* error = NULL; - gchar* out = NULL; - - char command_line[] = "git rev-parse --short HEAD"; - - // *not* the exit code! must be interpreted via g_spawn_check_exit_status! - int exit_status = -1; - - // g_spawn_command_line_sync returns whether the program succeeded - // its return value is buggy, hence we're using g_spawn_check_exit_status to check for errors - g_spawn_command_line_sync(command_line, &out, NULL, &exit_status, &error); - - // g_spawn_command_line_sync might have set error already, in that case we don't want to overwrite - if (error != NULL || !g_spawn_check_exit_status(exit_status, &error)) { - if (error == NULL) { - g_printerr("Failed to run 'git rev-parse --short HEAD, but failed to interpret GLib error state: %d\n", exit_status); - } else { - g_printerr("Failed to run 'git rev-parse --short HEAD: %s (code %d)\n", error->message, error->code); - } - } else { - version_env = g_strstrip(out); - - if (version_env != NULL) { - g_printerr("NOTE: Using the output of 'git rev-parse --short HEAD' as the version:\n"); - g_printerr(" %s\n", version_env); - g_printerr(" Please set the $VERSION environment variable if this is not intended\n"); - } - } - } - } - - free(gitPath); - } - - char *destination; - char source[PATH_MAX]; - realpath(remaining_args[0], source); - - /* Check if *.desktop file is present in source AppDir */ - gchar *desktop_file = find_first_matching_file_nonrecursive(source, "*.desktop"); - if(desktop_file == NULL){ - die("Desktop file not found, aborting"); - } - if(verbose) - fprintf (stdout, "Desktop file: %s\n", desktop_file); - - if(g_find_program_in_path ("desktop-file-validate")) { - if(validate_desktop_file(desktop_file) != 0){ - fprintf(stderr, "ERROR: Desktop file contains errors. Please fix them. Please see\n"); - fprintf(stderr, " https://standards.freedesktop.org/desktop-entry-spec/1.0/n"); - die(" for more information."); - } - } - - /* Read information from .desktop file */ - GKeyFile *kf = g_key_file_new (); - if (!g_key_file_load_from_file (kf, desktop_file, G_KEY_FILE_KEEP_TRANSLATIONS | G_KEY_FILE_KEEP_COMMENTS, NULL)) - die(".desktop file cannot be parsed"); - if (!get_desktop_entry(kf, "Categories")) - die(".desktop file is missing a Categories= key"); - - if(verbose){ - fprintf (stderr,"Name: %s\n", get_desktop_entry(kf, "Name")); - fprintf (stderr,"Icon: %s\n", get_desktop_entry(kf, "Icon")); - fprintf (stderr,"Exec: %s\n", get_desktop_entry(kf, "Exec")); - fprintf (stderr,"Comment: %s\n", get_desktop_entry(kf, "Comment")); - fprintf (stderr,"Type: %s\n", get_desktop_entry(kf, "Type")); - fprintf (stderr,"Categories: %s\n", get_desktop_entry(kf, "Categories")); - } - - /* Determine the architecture */ - bool archs[4] = {0, 0, 0, 0}; - extract_arch_from_text(getenv("ARCH"), "Environmental variable ARCH", archs); - if (count_archs(archs) != 1) { - /* If no $ARCH variable is set check a file */ - /* We use the next best .so that we can find to determine the architecture */ - find_arch(source, "*.so.*", archs); - int countArchs = count_archs(archs); - if (countArchs != 1) { - if (countArchs < 1) - fprintf(stderr, "Unable to guess the architecture of the AppDir source directory \"%s\"\n", remaining_args[0]); - else - fprintf(stderr, "More than one architectures were found of the AppDir source directory \"%s\"\n", remaining_args[0]); - fprintf(stderr, "A valid architecture with the ARCH environmental variable should be provided\ne.g. ARCH=x86_64 %s", argv[0]), - die(" ..."); - } - } - gchar* arch = getArchName(archs); - fprintf(stderr, "Using architecture %s\n", arch); - - char app_name_for_filename[PATH_MAX]; - sprintf(app_name_for_filename, "%s", get_desktop_entry(kf, "Name")); - replacestr(app_name_for_filename, " ", "_"); - - if(verbose) - fprintf (stderr,"App name for filename: %s\n", app_name_for_filename); - - if (remaining_args[1]) { - destination = remaining_args[1]; - } else { - /* No destination has been specified, to let's construct one - * TODO: Find out the architecture and use a $VERSION that might be around in the env */ - char dest_path[PATH_MAX]; - - // if $VERSION is specified, we embed it into the filename - if (version_env != NULL) { - sprintf(dest_path, "%s-%s-%s.AppImage", app_name_for_filename, version_env, arch); - } else { - sprintf(dest_path, "%s-%s.AppImage", app_name_for_filename, arch); - } - - destination = strdup(dest_path); - replacestr(destination, " ", "_"); - } - - // if $VERSION is specified, we embed its value into the desktop file - if (version_env != NULL) { - g_key_file_set_string(kf, G_KEY_FILE_DESKTOP_GROUP, "X-AppImage-Version", version_env); - - if (!g_key_file_save_to_file(kf, desktop_file, NULL)) { - fprintf(stderr, "Could not save modified desktop file\n"); - exit(1); - } - } - - fprintf (stdout, "%s should be packaged as %s\n", source, destination); - /* Check if the Icon file is how it is expected */ - gchar* icon_name = get_desktop_entry(kf, "Icon"); - gchar* icon_file_path = NULL; - gchar* icon_file_png; - gchar* icon_file_svg; - gchar* icon_file_xpm; - icon_file_png = g_strdup_printf("%s/%s.png", source, icon_name); - icon_file_svg = g_strdup_printf("%s/%s.svg", source, icon_name); - icon_file_xpm = g_strdup_printf("%s/%s.xpm", source, icon_name); - if (g_file_test(icon_file_png, G_FILE_TEST_IS_REGULAR)) { - icon_file_path = icon_file_png; - } else if(g_file_test(icon_file_svg, G_FILE_TEST_IS_REGULAR)) { - icon_file_path = icon_file_svg; - } else if(g_file_test(icon_file_xpm, G_FILE_TEST_IS_REGULAR)) { - icon_file_path = icon_file_xpm; - } else { - fprintf (stderr, "%s{.png,.svg,.xpm} defined in desktop file but not found\n", icon_name); - fprintf (stderr, "For example, you could put a 256x256 pixel png into\n"); - gchar *icon_name_with_png = g_strconcat(icon_name, ".png", NULL); - gchar *example_path = g_build_filename(source, "/", icon_name_with_png, NULL); - fprintf (stderr, "%s\n", example_path); - exit(1); - } - - /* Check if .DirIcon is present in source AppDir */ - gchar *diricon_path = g_build_filename(source, ".DirIcon", NULL); - - if (! g_file_test(diricon_path, G_FILE_TEST_EXISTS)){ - fprintf (stderr, "Deleting pre-existing .DirIcon\n"); - g_unlink(diricon_path); - } - if (! g_file_test(diricon_path, G_FILE_TEST_IS_REGULAR)){ - fprintf (stderr, "Creating .DirIcon symlink based on information from desktop file\n"); - int res = symlink(basename(icon_file_path), diricon_path); - if(res) - die("Could not symlink .DirIcon"); - } - - /* Check if AppStream upstream metadata is present in source AppDir */ - if(! no_appstream){ - char application_id[PATH_MAX]; - sprintf (application_id, "%s", basename(desktop_file)); - replacestr(application_id, ".desktop", ".appdata.xml"); - gchar *appdata_path = g_build_filename(source, "/usr/share/metainfo/", application_id, NULL); - if (! g_file_test(appdata_path, G_FILE_TEST_IS_REGULAR)){ - fprintf (stderr, "WARNING: AppStream upstream metadata is missing, please consider creating it\n"); - fprintf (stderr, " in usr/share/metainfo/%s\n", application_id); - fprintf (stderr, " Please see https://www.freedesktop.org/software/appstream/docs/chap-Quickstart.html#sect-Quickstart-DesktopApps\n"); - fprintf (stderr, " for more information or use the generator at http://output.jsbin.com/qoqukof.\n"); - } else { - fprintf (stderr, "AppStream upstream metadata found in usr/share/metainfo/%s\n", application_id); - /* Use ximion's appstreamcli to make sure that desktop file and appdata match together */ - if(g_find_program_in_path ("appstreamcli")) { - char *args[] = { - "appstreamcli", - "validate-tree", - source, - NULL - }; - g_print("Trying to validate AppStream information with the appstreamcli tool\n"); - g_print("In case of issues, please refer to https://github.com/ximion/appstream\n"); - int ret = run_external(g_find_program_in_path ("appstreamcli"), args); - if (ret != 0) - die("Failed to validate AppStream information with appstreamcli"); - } - /* It seems that hughsie's appstream-util does additional validations */ - if(g_find_program_in_path ("appstream-util")) { - char *args[] = { - "appstream-util", - "validate-relax", - appdata_path, - NULL - }; - g_print("Trying to validate AppStream information with the appstream-util tool\n"); - g_print("In case of issues, please refer to https://github.com/hughsie/appstream-glib\n"); - int ret = run_external(g_find_program_in_path ("appstream-util"), args); - if (ret != 0) - die("Failed to validate AppStream information with appstream-util"); - } - } - } - - /* Upstream mksquashfs can currently not start writing at an offset, - * so we need a patched one. https://github.com/plougher/squashfs-tools/pull/13 - * should hopefully change that. */ - - fprintf (stderr, "Generating squashfs...\n"); - int size = 0; - char* data = NULL; - bool using_external_data = false; - if (runtime_file != NULL) { - if (!readFile(runtime_file, &size, &data)) - die("Unable to load provided runtime file"); - using_external_data = true; - } else { -#ifdef HAVE_BINARY_RUNTIME - /* runtime is embedded into this executable - * http://stupefydeveloper.blogspot.de/2008/08/cc-embed-binary-data-into-elf.html */ - size = runtime_len; - data = runtime; -#else - die("No runtime file was provided"); -#endif - } - if (verbose) - printf("Size of the embedded runtime: %d bytes\n", size); - - int result = sfs_mksquashfs(source, destination, size); - if(result != 0) - die("sfs_mksquashfs error"); - - fprintf (stderr, "Embedding ELF...\n"); - FILE *fpdst = fopen(destination, "rb+"); - if (fpdst == NULL) { - die("Not able to open the AppImage for writing, aborting"); - } - - fseek(fpdst, 0, SEEK_SET); - fwrite(data, size, 1, fpdst); - fclose(fpdst); - if (using_external_data) - free(data); - - fprintf (stderr, "Marking the AppImage as executable...\n"); - if (chmod (destination, 0755) < 0) { - printf("Could not set executable bit, aborting\n"); - exit(1); - } - - if(bintray_user != NULL){ - if(bintray_repo != NULL){ - char buf[1024]; - sprintf(buf, "bintray-zsync|%s|%s|%s|%s-_latestVersion-%s.AppImage.zsync", bintray_user, bintray_repo, app_name_for_filename, app_name_for_filename, arch); - updateinformation = buf; - printf("%s\n", updateinformation); - } - } - - /* If the user has not provided update information but we know this is a Travis CI build, - * then fill in update information based on TRAVIS_REPO_SLUG */ - if(guess_update_information){ - if(travis_repo_slug){ - if(!github_token) { - printf("Will not guess update information since $GITHUB_TOKEN is missing,\n"); - if(0 != strcmp(travis_pull_request, "false")){ - printf("please set it in the Travis CI Repository Settings for this project.\n"); - printf("You can get one from https://github.com/settings/tokens\n"); - } else { - printf("which is expected since this is a pull request\n"); - } - } else { - gchar *zsyncmake_path = g_find_program_in_path ("zsyncmake"); - if(zsyncmake_path){ - char buf[1024]; - gchar **parts = g_strsplit (travis_repo_slug, "/", 2); - /* https://github.com/AppImage/AppImageSpec/blob/master/draft.md#github-releases - * gh-releases-zsync|probono|AppImages|latest|Subsurface*-x86_64.AppImage.zsync */ - gchar *channel = "continuous"; - if(travis_tag != NULL){ - if((strcmp(travis_tag, "") != 0) && (strcmp(travis_tag, "continuous") != 0)) { - channel = "latest"; - } - } - sprintf(buf, "gh-releases-zsync|%s|%s|%s|%s*-%s.AppImage.zsync", parts[0], parts[1], channel, app_name_for_filename, arch); - updateinformation = buf; - printf("Guessing update information based on $TRAVIS_TAG=%s and $TRAVIS_REPO_SLUG=%s\n", travis_tag, travis_repo_slug); - printf("%s\n", updateinformation); - } else { - printf("Will not guess update information since zsyncmake is missing\n"); - } - } - } else if(CI_COMMIT_REF_NAME){ - // ${CI_PROJECT_URL}/-/jobs/artifacts/${CI_COMMIT_REF_NAME}/raw/QtQuickApp-x86_64.AppImage?job=${CI_JOB_NAME} - gchar *zsyncmake_path = g_find_program_in_path ("zsyncmake"); - if(zsyncmake_path){ - char buf[1024]; - sprintf(buf, "zsync|%s/-/jobs/artifacts/%s/raw/%s-%s.AppImage.zsync?job=%s", CI_PROJECT_URL, CI_COMMIT_REF_NAME, app_name_for_filename, arch, CI_JOB_NAME); - updateinformation = buf; - printf("Guessing update information based on $CI_COMMIT_REF_NAME=%s and $CI_JOB_NAME=%s\n", CI_COMMIT_REF_NAME, CI_JOB_NAME); - printf("%s\n", updateinformation); - } else { - printf("Will not guess update information since zsyncmake is missing\n"); - } - } - } - - /* If updateinformation was provided, then we check and embed it */ - if(updateinformation != NULL){ - if(!g_str_has_prefix(updateinformation,"zsync|")) - if(!g_str_has_prefix(updateinformation,"bintray-zsync|")) - if(!g_str_has_prefix(updateinformation,"gh-releases-zsync|")) - if(!g_str_has_prefix(updateinformation,"pling-v1-zsync|")) - die("The provided updateinformation is not in a recognized format"); - - gchar **ui_type = g_strsplit_set(updateinformation, "|", -1); - - if(verbose) - printf("updateinformation type: %s\n", ui_type[0]); - /* TODO: Further checking of the updateinformation */ - - - unsigned long ui_offset = 0; - unsigned long ui_length = 0; - - bool rv = appimage_get_elf_section_offset_and_length(destination, ".upd_info", &ui_offset, &ui_length); - - if (!rv || ui_offset == 0 || ui_length == 0) { - die("Could not find section .upd_info in runtime"); - } - - if(verbose) { - printf("ui_offset: %lu\n", ui_offset); - printf("ui_length: %lu\n", ui_length); - } - if(ui_offset == 0) { - die("Could not determine offset for updateinformation"); - } else { - if(strlen(updateinformation)>ui_length) - die("updateinformation does not fit into segment, aborting"); - FILE *fpdst2 = fopen(destination, "r+"); - if (fpdst2 == NULL) - die("Not able to open the destination file for writing, aborting"); - fseek(fpdst2, ui_offset, SEEK_SET); - // fseek(fpdst2, ui_offset, SEEK_SET); - // fwrite(0x00, 1, 1024, fpdst); // FIXME: Segfaults; why? - // fseek(fpdst, ui_offset, SEEK_SET); - fwrite(updateinformation, strlen(updateinformation), 1, fpdst2); - fclose(fpdst2); - } - } - - // calculate and embed MD5 digest - { - fprintf(stderr, "Embedding MD5 digest\n"); - - unsigned long digest_md5_offset = 0; - unsigned long digest_md5_length = 0; - - bool rv = appimage_get_elf_section_offset_and_length(destination, ".digest_md5", &digest_md5_offset, &digest_md5_length); - - if (!rv || digest_md5_offset == 0 || digest_md5_length == 0) { - die("Could not find section .digest_md5 in runtime"); - } - - static const unsigned long section_size = 16; - - if (digest_md5_length < section_size) { - fprintf( - stderr, - ".digest_md5 section in runtime's ELF header is too small" - "(found %lu bytes, minimum required: %lu bytes)\n", - digest_md5_length, section_size - ); - exit(1); - } - - char digest_buffer[section_size]; - - if (!appimage_type2_digest_md5(destination, digest_buffer)) { - die("Failed to calculate MD5 digest"); - } - - FILE* destinationfp = fopen(destination, "r+"); - - if (destinationfp == NULL) { - die("Failed to open AppImage for updating"); - } - - if (fseek(destinationfp, digest_md5_offset, SEEK_SET) != 0) { - fclose(destinationfp); - die("Failed to embed MD5 digest: could not seek to section offset"); - } - - if (fwrite(digest_buffer, sizeof(char), section_size, destinationfp) != section_size) { - fclose(destinationfp); - die("Failed to embed MD5 digest: write failed"); - } - - fclose(destinationfp); - } - - if (sign) { - if (!sign_appimage(destination, sign_key, verbose)) { - if (getenv(FORCE_SIGN_ENV_VAR) != NULL) { - fprintf(stderr, "ERROR: signing failed, aborting\n"); - exit(1); - } else { - fprintf(stderr, "ERROR: signing failed, continuing\n"); - } - } - } - - /* If updateinformation was provided, then we also generate the zsync file (after having signed the AppImage) */ - if (updateinformation != NULL) { - gchar* zsyncmake_path = g_find_program_in_path("zsyncmake"); - if (!zsyncmake_path) { - fprintf(stderr, "zsyncmake is not installed/bundled, skipping\n"); - } else { - fprintf(stderr, "zsyncmake is available and updateinformation is provided, " - "hence generating zsync file\n"); - - const gchar* const zsyncmake_command[] = {zsyncmake_path, destination, "-u", basename(destination), NULL}; - - if (verbose) { - fprintf(stderr, "Running zsyncmake process: "); - for (gint j = 0; j < (sizeof(zsyncmake_command) / sizeof(char*) - 1); ++j) { - fprintf(stderr, "'%s' ", zsyncmake_command[j]); - } - fprintf(stderr, "\n"); - } - - GSubprocessFlags flags = G_SUBPROCESS_FLAGS_NONE; - - if (!verbose) { - flags = G_SUBPROCESS_FLAGS_STDERR_SILENCE | G_SUBPROCESS_FLAGS_STDOUT_SILENCE; - } - - GSubprocess* proc = g_subprocess_newv(zsyncmake_command, flags, &error); - - if (proc == NULL) { - fprintf(stderr, "ERROR: failed to create zsyncmake process: %s\n", error->message); - exit(1); - } - - if (!g_subprocess_wait_check(proc, NULL, &error)) { - fprintf(stderr, "ERROR: zsyncmake returned abnormal exit code: %s\n", error->message); - g_object_unref(proc); - exit(1); - } - - g_object_unref(proc); - } - } - - fprintf(stderr, "Success\n\n"); - fprintf(stderr, "Please consider submitting your AppImage to AppImageHub, the crowd-sourced\n"); - fprintf(stderr, "central directory of available AppImages, by opening a pull request\n"); - fprintf(stderr, "at https://github.com/AppImage/appimage.github.io\n"); - - return 0; - } else if (g_file_test(remaining_args[0], G_FILE_TEST_IS_REGULAR)) { - /* If the first argument is a regular file, then we assume that we should unpack it */ - fprintf(stdout, "%s is a file, assuming it is an AppImage and should be unpacked\n", remaining_args[0]); - die("To be implemented"); - return 1; - } else { - fprintf(stderr, "Error: no such file or directory: %s\n", remaining_args[0]); - return 1; - } - - // should never be reached - return 1; -} diff --git a/src/appimagetool_sign.c b/src/appimagetool_sign.c deleted file mode 100644 index 970c2b4c1..000000000 --- a/src/appimagetool_sign.c +++ /dev/null @@ -1,479 +0,0 @@ -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "binreloc.h" -#include "appimage/appimage_shared.h" -#include "appimagetool_sign.h" - -// used to identify calls to the callback -static const char gpgme_hook[] = "appimagetool gpgme hook"; -static const char signature_elf_section[] = ".sha256_sig"; -static const char key_elf_section[] = ".sig_key"; - -char* get_passphrase_from_environment() { - return getenv("APPIMAGETOOL_SIGN_PASSPHRASE"); -} - -gpgme_error_t gpgme_passphrase_callback(void* hook, const char* uid_hint, const char* passphrase_info, int prev_was_valid, int fd) { - (void) passphrase_info; - (void) prev_was_valid; - - assert(hook == gpgme_hook); - - // passing the passphrase via the environment is at least better than using a CLI parameter - char* passphrase_from_env = get_passphrase_from_environment(); - - if (passphrase_from_env == NULL) { - fprintf(stderr, "[sign] no passphrase available from environment\n"); - return GPG_ERR_NO_PASSPHRASE; - } - - fprintf(stderr, "[sign] providing passphrase for key %s\n", uid_hint); - - gpgme_io_writen(fd, passphrase_from_env, strlen(passphrase_from_env)); - - // need to write a newline character according to the docs - // maybe this would have solved the hanging issues we had with gpg(2) as a subprocess when writing to stdin...? - gpgme_io_writen(fd, "\n", 1); - - return GPG_ERR_NO_ERROR; -} - -gpgme_error_t gpgme_status_callback(void* hook, const char* keyword, const char* args) { - assert(hook == gpgme_hook); - - fprintf(stderr, "[gpgme] %s: %s\n", keyword, args); - return GPG_ERR_NO_ERROR; -} - -// all of these are from gpg based libraries, and are used exclusively in the code below -// whenever there is an error in sign_appimage, we can free() up these resources -static gpgme_ctx_t gpgme_ctx = NULL; -static gpgme_data_t gpgme_appimage_file_data = NULL; -static gpgme_data_t gpgme_sig_data = NULL; -// we support just a single key at the moment -static gpgme_key_t gpgme_key = NULL; -static gpgme_data_t gpgme_key_data = NULL; - -// this little helper can be called wherever the resources above must be released -void release_resources() { - if (gpgme_appimage_file_data != NULL) { - gpgme_data_release(gpgme_appimage_file_data); - gpgme_appimage_file_data = NULL; - } - if (gpgme_sig_data != NULL) { - gpgme_data_release(gpgme_sig_data); - gpgme_sig_data = NULL; - } - if (gpgme_ctx != NULL) { - gpgme_release(gpgme_ctx); - gpgme_ctx = NULL; - } - if (gpgme_key != NULL) { - gpgme_key_release(gpgme_key); - gpgme_key = NULL; - } - if (gpgme_key_data != NULL) { - gpgme_data_release(gpgme_key_data); - gpgme_key_data = NULL; - } -} - -// it's possible to use a single macro to error-check both gpgme and gcrypt, since both originate from the gpg project -// the error types gcry_error_t and gpgme_error_t are both aliases for gpg_error_t -#define gpg_check_call(call_to_function) \ - { \ - gpg_error_t error = (call_to_function); \ - if (error != GPG_ERR_NO_ERROR) { \ - fprintf(stderr, "[sign] %s: call failed: %s\n", #call_to_function, gpgme_strerror(error)); \ - release_resources(); \ - return false; \ - } \ - } - -char* calculate_sha256_hex_digest(char* filename) { - // like gcrypt, gcrypt must be initialized - { - static const char gcrypt_minimum_required_version[] = "1.8.1"; - const char* gcrypt_version = gcry_check_version(gcrypt_minimum_required_version); - - if (gcrypt_version == NULL) { - fprintf(stderr, "[sign] could not initialize gcrypt (>= %s)\n", gcrypt_minimum_required_version); - release_resources(); - return NULL; - } else { - fprintf(stderr, "[sign] found gcrypt version %s\n", gcrypt_version); - } - } - - // algo is defined by the spec - static const int hash_algo = GCRY_MD_SHA256; - - // open file and feed data chunk wise to gcrypt - FILE* file = fopen(filename, "r"); - if (file == NULL) { - fprintf(stderr, "[sign] could not calculate digest: opening file %s failed", filename); - release_resources(); - return NULL; - } - - gcry_md_hd_t gcry_md_handle = NULL; - - gpg_check_call(gcry_md_open(&gcry_md_handle, hash_algo, 0)); - - // 4k chunks should work well enough - char read_buffer[4096 * sizeof(char)]; - - for (;;) { - size_t bytes_read = fread(read_buffer, sizeof(char), sizeof(read_buffer), file); - - // if we have an error, we can stop immediately - if (ferror(file) != 0) { - fprintf(stderr, "[sign] failed to read chunk for hashing from file %s\n", filename); - fclose(file); - gcry_md_close(gcry_md_handle); - return NULL; - } - - gcry_md_write(gcry_md_handle, read_buffer, bytes_read); - - // once we read all the data, we can stop - if (feof(file) != 0) { - break; - } - } - - // done, we can close the file - // since we do no longer have to worry about the file pointer, we can use gpg_check_call just fine below - if (fclose(file) != 0) { - fprintf(stderr, "[sign] failed to close hashed file %s\n", filename); - gcry_md_close(gcry_md_handle); - return NULL; - } - - gpg_check_call(gcry_md_final(gcry_md_handle)); - - // conveniently, we can ask gcrypt for the digest size - unsigned int digest_size = gcry_md_get_algo_dlen(hash_algo); - - // read raw digest (i.e., memory-readable, not hexlified like, e.g., sha256sum would return) - unsigned char* digest_in_ctx = gcry_md_read(gcry_md_handle, hash_algo); - - if (digest_in_ctx == NULL) { - fprintf(stderr, "[sign] gcry_md_read failed\n"); - gcry_md_close(gcry_md_handle); - return NULL; - } - - // create "human-readable" version for the output - // the method allocates a suitable string buffer - // needs to be done before releasing the handle since this destroys digest_in_ctx - char* out_buffer = appimage_hexlify((const char*) digest_in_ctx, digest_size); - - // release all resources and return the result to the caller - gcry_md_close(gcry_md_handle); - - return out_buffer; -} - -bool add_signers(const char* key_id) { - // if a key id is specified, we ask gpgme to use this key explicitly, otherwise we use the first key in gpgme's list - if (key_id != NULL) { - // we could use the list stuff below, but using gpgme_get_key is a lot easier... - gpg_check_call(gpgme_get_key(gpgme_ctx, key_id, &gpgme_key, true)); - } else { - // searching the "first available secret key" is a little complex in gpgme... - // since we are just looking for the first one, we don't need a loop at least - gpg_check_call(gpgme_op_keylist_start(gpgme_ctx, NULL, true)); - gpg_check_call(gpgme_op_keylist_next(gpgme_ctx, &gpgme_key)); - } - - fprintf(stderr, "[sign] using key with fingerprint %s, issuer name %s\n", gpgme_key->fpr, gpgme_key->uids->name); - gpg_check_call(gpgme_signers_add(gpgme_ctx, gpgme_key)); - - return true; -} - -bool embed_data_in_elf_section(const char* filename, const char* elf_section, gpgme_data_t data, bool verbose) { - // first up: find the ELF section in the AppImage file - unsigned long key_section_offset = 0; - unsigned long key_section_length = 0; - - if (verbose) { - fprintf(stderr, "[sign] embedding data in ELF section %s\n", elf_section); - } - - bool rv = appimage_get_elf_section_offset_and_length( - filename, - elf_section, - &key_section_offset, - &key_section_length - ); - - if (!rv || key_section_offset == 0 || key_section_length == 0) { - fprintf(stderr, "[sign] could not determine offset for signature\n"); - release_resources(); - return false; - } - - if (verbose) { - fprintf(stderr, "[sign] key_offset: %lu\n", key_section_offset); - fprintf(stderr, "[sign] key_length: %lu\n", key_section_length); - } - - // next, read the exported key's size from the data object - const off_t data_size = gpgme_data_seek(data, 0, SEEK_END); - if (data_size < 0) { - fprintf(stderr, "[sign] failed to detect size of signature\n"); - release_resources(); - return false; - } - - if (verbose) { - fprintf(stderr, "[sign] data size: %lu\n", data_size); - } - - // rewind so we can later read the data - if (gpgme_data_seek(data, 0, SEEK_SET) < 0) { - fprintf(stderr, "[sign] failed to rewind data object\n"); - release_resources(); - return false; - } - - if (data_size > key_section_length) { - fprintf(stderr, "[sign] cannot embed key in AppImage: size exceeds reserved ELF section size\n"); - release_resources(); - return false; - } - - // we need to read the signature into a custom buffer - char data_buffer[data_size]; - - size_t total_bytes_read = 0; - size_t bytes_read = 0; - - for (;;) { - bytes_read = gpgme_data_read(data, data_buffer, data_size); - - // EOF - if (bytes_read == 0) { - break; - } - - // error - if (bytes_read < 0) { - fprintf(stderr, "[sign] failed to read from data object\n"); - release_resources(); - return false; - } - - total_bytes_read += bytes_read; - } - - if (total_bytes_read != data_size) { - fprintf( - stderr, - "[sign] failed to read entire data from data object (%lu != %lu)\n", - total_bytes_read, - data_size - ); - release_resources(); - return false; - } - - FILE* destinationfp = fopen(filename, "r+"); - - if (destinationfp == NULL) { - fprintf(stderr, "[sign] failed to open the destination file for writing\n"); - release_resources(); - return false; - } - - if (fseek(destinationfp, (long) key_section_offset, SEEK_SET) < 0) { - fprintf(stderr, "[sign] fseek failed: %s\n", strerror(errno)); - release_resources(); - fclose(destinationfp); - return false; - } - - // write at once - if (fwrite(data_buffer, sizeof(char), data_size, destinationfp) != data_size) { - fprintf(stderr, "[sign] failed to write signature to AppImage file\n"); - release_resources(); - fclose(destinationfp); - return false; - } - - // done -> release file descriptor - if (fclose(destinationfp) != 0) { - fprintf(stderr, "[sign] failed to close file descriptor: %s\n", strerror(errno)); - release_resources(); - return false; - } - - return true; -} - -bool sign_appimage(char* appimage_filename, char* key_id, bool verbose) { - fprintf(stderr, "[sign] signing requested\n"); - - // like gcrypt, gpgme must be initialized - { - static const char gpgme_minimum_required_version[] = "1.10.0"; - const char* gpgme_version = gpgme_check_version(gpgme_minimum_required_version); - - if (gpgme_version == NULL) { - fprintf(stderr, "[sign] could not initialize gpgme (>= %s)\n", gpgme_minimum_required_version); - release_resources(); - return false; - } else { - fprintf(stderr, "[sign] found gpgme version %s\n", gpgme_version); - } - } - - // as per the spec, an SHA256 hash is signed and the signature is then embedded in the AppImage - char* hex_digest = calculate_sha256_hex_digest(appimage_filename); - if (hex_digest == NULL) { - release_resources(); - return false; - } - - fprintf(stderr, "[sign] calculated digest: %s\n", hex_digest); - - gpg_check_call(gpgme_new(&gpgme_ctx)); - - - // make sure we have a compatible agent around - { - gpgme_engine_info_t engine_info; - gpg_check_call(gpgme_get_engine_info(&engine_info)); - - while (engine_info && engine_info->protocol != gpgme_get_protocol(gpgme_ctx)) { - engine_info = engine_info->next; - } - - if (engine_info == NULL) { - fprintf( - stderr, - "[sign] could not detect gpg version for an unknown reason (engine name: %s)\n", - gpgme_get_protocol_name(engine_info->protocol) - ); - exit(1); - } - - fprintf( - stderr, - "[sign] using engine %s (found in %s), version %s, gpgme requires at least version %s\n", - gpgme_get_protocol_name(engine_info->protocol), - engine_info->file_name, - engine_info->version, - engine_info->req_version - ); - - // check whether the version is problematic - // we just need the first two items, and we assume the format will be something like "2.1*" - unsigned int major; - unsigned int minor; - if (sscanf(engine_info->version, "%u.%u", &major, &minor) == 2) { - if (major == 2) { - if (minor == 0) { - fprintf(stderr, "[sign] warning: loopback pinentry mode not supported with gpg 2.0.x, %s may not work\n", FORCE_SIGN_ENV_VAR); - } else if (minor == 1) { - fprintf(stderr, "[sign] warning: gpg 2.1.x detected, %s can only work with allow-loopback-entry set within the gpg-agent configuration\n", FORCE_SIGN_ENV_VAR); - } - } else { - fprintf(stderr, "[sign] error: unsupported engine version, aborting\n"); - exit(1); - } - } else { - fprintf(stderr, "[sign] warning: failed to validate gpg version, expect problems\n"); - } - } - - if (verbose) { - // this should significantly increase the amount of logging we see in the status callback - fprintf(stderr, "[sign] running in verbose mode, enabling full-status flag on gpgme context\n"); - gpg_check_call(gpgme_set_ctx_flag(gpgme_ctx, "full-status", "1")); - } - - // we want an ASCII armored signature of plain text (hex string) - gpgme_set_textmode(gpgme_ctx, true); - gpgme_set_armor(gpgme_ctx, true); - - // in case the user provides a passphrase in the environment, we have to set the pinentry mode to loopback, like with the CLI - if (get_passphrase_from_environment() != NULL) { - fprintf(stderr, "[sign] passphrase available from environment, setting pinentry mode to loopback\n"); - gpgme_set_pinentry_mode(gpgme_ctx, GPGME_PINENTRY_MODE_LOOPBACK); - gpgme_set_passphrase_cb(gpgme_ctx, gpgme_passphrase_callback, (void*) gpgme_hook); - } - - // implement some fancy logging with log prefixes and stuff - gpgme_set_status_cb(gpgme_ctx, gpgme_status_callback, (void*) gpgme_hook); - - if (!add_signers(key_id)) { - release_resources(); - return false; - } - - assert(gpgme_key != NULL); - - // we don't have to let gpgme copy the data since we can ensure the buffer remains valid the entire time - gpg_check_call(gpgme_data_new_from_mem(&gpgme_appimage_file_data, hex_digest, strlen(hex_digest), 0)); - - // we further need an out buffer to store the signature, we let gpgme handle the allocation - gpg_check_call(gpgme_data_new(&gpgme_sig_data)); - - // now, we can sign the data - gpg_check_call(gpgme_op_sign(gpgme_ctx, gpgme_appimage_file_data, gpgme_sig_data, GPGME_SIG_MODE_DETACH)); - - gpgme_sign_result_t sign_result = gpgme_op_sign_result(gpgme_ctx); - - if (sign_result == NULL) { - fprintf(stderr, "[sign] signing failed\n"); - release_resources(); - exit(1); - } - - // we expect exactly one signature - assert(sign_result->signatures->next == NULL); - - fprintf( - stderr, - "[sign] signed using pubkey algo %s, hash algo %s, key fingerprint %s\n", - gpgme_pubkey_algo_name(sign_result->signatures->pubkey_algo), - gpgme_hash_algo_name(sign_result->signatures->hash_algo), - sign_result->signatures->fpr - ); - - fprintf(stderr, "[sign] embedding signature in AppImage\n"); - if (!embed_data_in_elf_section(appimage_filename, signature_elf_section, gpgme_sig_data, verbose)) { - fprintf(stderr, "[sign] failed to embed signature in AppImage\n"); - release_resources(); - return false; - } - - // exporting the key to a gpgme data object is relatively easy - gpgme_data_new(&gpgme_key_data); - gpgme_key_t keys_to_export[] = {gpgme_key, NULL}; - gpg_check_call(gpgme_op_export_keys(gpgme_ctx, keys_to_export, 0, gpgme_key_data)); - - fprintf(stderr, "[sign] embedding key in AppImage\n"); - if (!embed_data_in_elf_section(appimage_filename, key_elf_section, gpgme_key_data, verbose)) { - fprintf(stderr, "[sign] failed to embed key in AppImage\n"); - release_resources(); - return false; - } - - release_resources(); - return true; -} - - diff --git a/src/appimagetool_sign.h b/src/appimagetool_sign.h deleted file mode 100644 index 6ecee684e..000000000 --- a/src/appimagetool_sign.h +++ /dev/null @@ -1,5 +0,0 @@ -#pragma once - -static const char* const FORCE_SIGN_ENV_VAR = "APPIMAGETOOL_FORCE_SIGN"; - -bool sign_appimage(char* appimage_filename, char* key_id, bool verbose); diff --git a/src/appimagetoolnoglib.c b/src/appimagetoolnoglib.c deleted file mode 100644 index f900e76f6..000000000 --- a/src/appimagetoolnoglib.c +++ /dev/null @@ -1,307 +0,0 @@ -#include -#include - -#include -#include -#include "squashfuse.h" - -#include -#include - -#include "binreloc.h" -#ifndef NULL - #define NULL ((void *) 0) -#endif - -#include - -#include - -#include - -extern char runtime[]; -extern unsigned int runtime_len; - - -const char *argp_program_version = - "appimagetool 0.1"; - -const char *argp_program_bug_address = - ""; - -static char doc[] = - "appimagetool -- Generate, extract, and inspect AppImages"; - -/* This structure is used by main to communicate with parse_opt. */ -struct arguments -{ - char *args[2]; /* SOURCE and DESTINATION */ - int verbose; /* The -v flag */ - int list; /* The -l flag */ - char *dumpfile; /* Argument for -d */ -}; - - -static struct argp_option options[] = -{ - {"verbose", 'v', 0, 0, "Produce verbose output"}, - {"list", 'l', 0, 0, - "List files in SOURCE AppImage"}, - {"dump", 'd', "FILE", 0, - "Dump FILE from SOURCE AppImage to stdout"}, - {0} -}; - - -static error_t -parse_opt (int key, char *arg, struct argp_state *state) -{ - struct arguments *arguments = state->input; - - switch (key) - { - case 'v': - arguments->verbose = 1; - break; - case 'l': - arguments->list = 1; - break; - case 'd': - arguments->dumpfile = arg; - break; - case ARGP_KEY_ARG: - if (state->arg_num >= 3) - { - argp_usage(state); - } - arguments->args[state->arg_num] = arg; - break; - case ARGP_KEY_END: - if (state->arg_num < 1) - { - argp_usage (state); - } - break; - default: - return ARGP_ERR_UNKNOWN; - } - return 0; -} - - -static char args_doc[] = "SOURCE {DESTINATION}"; - - -static struct argp argp = {options, parse_opt, args_doc, doc}; - - -// ##################################################################### - - -static void die(const char *msg) { - fprintf(stderr, "%s\n", msg); - exit(1); -} - -int is_directory(const char *path) { - struct stat statbuf; - if (stat(path, &statbuf) != 0) - return 0; - return S_ISDIR(statbuf.st_mode); -} - -int is_regular_file(const char *path) -{ - struct stat path_stat; - stat(path, &path_stat); - return S_ISREG(path_stat.st_mode); -} - -/* Function that prints the contents of a squashfs file - * using libsquashfuse (#include "squashfuse.h") */ -int sfs_ls(char* image) { - sqfs_err err = SQFS_OK; - sqfs_traverse trv; - sqfs fs; - - if ((err = sqfs_open_image(&fs, image, 0))) - die("sqfs_open_image error"); - - if ((err = sqfs_traverse_open(&trv, &fs, sqfs_inode_root(&fs)))) - die("sqfs_traverse_open error"); - while (sqfs_traverse_next(&trv, &err)) { - if (!trv.dir_end) { - printf("%s\n", trv.path); - } - } - if (err) - die("sqfs_traverse_next error"); - sqfs_traverse_close(&trv); - - sqfs_fd_close(fs.fd); - return 0; -} - -/* Generate a squashfs filesystem using mksquashfs on the $PATH */ -int sfs_mksquashfs(char *source, char *destination) { - pid_t parent = getpid(); - pid_t pid = fork(); - - if (pid == -1) { - // error, failed to fork() - return(-1); - } else if (pid > 0) { - int status; - waitpid(pid, &status, 0); - } else { - // we are the child - execlp("mksquashfs", "mksquashfs", source, destination, "-root-owned", "-noappend", (char *)0); - perror("execlp"); // execvp() returns only on error - return(-1); // exec never returns - } - return(0); -} - -/* Generate a squashfs filesystem - * The following would work if we link to mksquashfs.o after we renamed - * main() to mksquashfs_main() in mksquashfs.c but we don't want to actually do - * this because squashfs-tools is not under a permissive license -int sfs_mksquashfs(char *source, char *destination) { - char *child_argv[5]; - child_argv[0] = NULL; - child_argv[1] = source; - child_argv[2] = destination; - child_argv[3] = "-root-owned"; - child_argv[4] = "-noappend"; - mksquashfs_main(5, child_argv); -} - */ - -// ##################################################################### - -int main (int argc, char **argv) -{ - - /* Initialize binreloc so that we always know where we live */ - BrInitError error; - if (br_init (&error) == 0) { - printf ("Warning: binreloc failed to initialize (error code %d)\n", error); - } - printf ("This tool is located at %s\n", br_find_exe_dir(NULL)); - - struct arguments arguments; - - /* Set argument defaults */ - arguments.list = 0; - arguments.verbose = 0; - arguments.dumpfile = NULL; - - /* Where the magic happens */ - argp_parse (&argp, argc, argv, 0, 0, &arguments); - - /* If in list mode */ - if (arguments.list){ - sfs_ls(arguments.args[0]); - exit(0); - } - - /* If in dumpfile mode */ - if (arguments.dumpfile){ - fprintf (stdout, "%s from the AppImage %s should be dumped to stdout\n", arguments.dumpfile, arguments.args[0]); - die("To be implemented"); - } - - /* Print argument values */ - if (arguments.verbose) - fprintf (stdout, "Original SOURCE = %s\nOriginal DESTINATION = %s\n", - arguments.args[0], - arguments.args[1]); - - /* If the first argument is a directory, then we assume that we should package it */ - if(is_directory(arguments.args[0])){ - char *destination; - char source[PATH_MAX]; - realpath(arguments.args[0], source); - if (arguments.args[1]) { - destination = arguments.args[1]; - } else { - /* No destination has been specified, to let's construct one - * TODO: Find out the architecture and use a $VERSION that might be around in the env */ - destination = basename(br_strcat(source, ".AppImage")); - fprintf (stdout, "DESTINATION not specified, so assuming %s\n", destination); - } - fprintf (stdout, "%s should be packaged as %s\n", arguments.args[0], destination); - - /* mksquashfs can currently not start writing at an offset, - * so we need a tempfile. https://github.com/plougher/squashfs-tools/pull/13 - * should hopefully change that. */ - char *tempfile; - fprintf (stderr, "Generating squashfs...\n"); - tempfile = br_strcat(destination, ".temp"); - int result = sfs_mksquashfs(source, tempfile); - if(result != 0) - die("sfs_mksquashfs error"); - - fprintf (stderr, "Generating AppImage...\n"); - FILE *fpsrc = fopen(tempfile, "rb"); - if (fpsrc == NULL) { - die("Not able to open the tempfile for reading, aborting"); - } - FILE *fpdst = fopen(destination, "w"); - if (fpdst == NULL) { - die("Not able to open the destination file for writing, aborting"); - } - - /* runtime is embedded into this executable - * http://stupefydeveloper.blogspot.de/2008/08/cc-embed-binary-data-into-elf.html */ - int size = runtime_len; - char *data = runtime; - if (arguments.verbose) - printf("Size of the embedded runtime: %d bytes\n", size); - /* Where to store updateinformation. Fixed offset preferred for easy manipulation - * after the fact. Proposal: 4 KB at the end of the 128 KB padding. - * Hence, offset 126976, max. 4096 bytes long. - * Possibly we might want to store additional information in the future. - * Assuming 4 blocks of 4096 bytes each. - */ - if(size > 128*1024-4*4096-2){ - die("Size of the embedded runtime is too large, aborting"); - } - // printf("%s", data); - fwrite(data, size, 1, fpdst); - - if(ftruncate(fileno(fpdst), 128*1024) != 0) { - die("Not able to write padding to destination file, aborting"); - } - - fseek (fpdst, 0, SEEK_END); - char byte; - - while (!feof(fpsrc)) - { - fread(&byte, sizeof(char), 1, fpsrc); - fwrite(&byte, sizeof(char), 1, fpdst); - } - - fclose(fpsrc); - fclose(fpdst); - - fprintf (stderr, "Marking the AppImage as executable...\n"); - if (chmod (destination, 0755) < 0) { - printf("Could not set executable bit, aborting\n"); - exit(1); - } - if(unlink(tempfile) != 0) { - die("Could not delete the tempfile, aborting"); - } - fprintf (stderr, "Success\n"); -} - - /* If the first argument is a regular file, then we assume that we should unpack it */ - if(is_regular_file(arguments.args[0])){ - fprintf (stdout, "%s is a file, assuming it is an AppImage and should be unpacked\n", arguments.args[0]); - die("To be implemented"); - } - - return 0; -} diff --git a/src/binreloc.c b/src/binreloc.c deleted file mode 100644 index c9b5db285..000000000 --- a/src/binreloc.c +++ /dev/null @@ -1,766 +0,0 @@ -/* - * BinReloc - a library for creating relocatable executables - * Written by: Hongli Lai - * http://autopackage.org/ - * - * This source code is public domain. You can relicense this code - * under whatever license you want. - * - * See http://autopackage.org/docs/binreloc/ for - * more information and how to use this. - */ - -#ifndef BINRELOC_C -#define BINRELOC_C - -#ifdef ENABLE_BINRELOC - #include - #include - #include -#endif /* ENABLE_BINRELOC */ -#include -#include -#include -#include -#include "binreloc.h" - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - - - -/** @internal - * Find the canonical filename of the executable. Returns the filename - * (which must be freed) or NULL on error. If the parameter 'error' is - * not NULL, the error code will be stored there, if an error occured. - */ -static char * -_br_find_exe (BrInitError *error) -{ -#ifndef ENABLE_BINRELOC - if (error) - *error = BR_INIT_ERROR_DISABLED; - return NULL; -#else - char *path, *path2, *line, *result; - size_t buf_size; - ssize_t size; - struct stat stat_buf; - FILE *f; - - /* Read from /proc/self/exe (symlink) */ - if (sizeof (path) > SSIZE_MAX) - buf_size = SSIZE_MAX - 1; - else - buf_size = PATH_MAX - 1; - path = (char *) malloc (buf_size); - if (path == NULL) { - /* Cannot allocate memory. */ - if (error) - *error = BR_INIT_ERROR_NOMEM; - return NULL; - } - path2 = (char *) malloc (buf_size); - if (path2 == NULL) { - /* Cannot allocate memory. */ - if (error) - *error = BR_INIT_ERROR_NOMEM; - free (path); - return NULL; - } - - strncpy (path2, "/proc/self/exe", buf_size - 1); - - while (1) { - int i; - - size = readlink (path2, path, buf_size - 1); - if (size == -1) { - /* Error. */ - free (path2); - break; - } - - /* readlink() success. */ - path[size] = '\0'; - - /* Check whether the symlink's target is also a symlink. - * We want to get the final target. */ - i = stat (path, &stat_buf); - if (i == -1) { - /* Error. */ - free (path2); - break; - } - - /* stat() success. */ - if (!S_ISLNK (stat_buf.st_mode)) { - /* path is not a symlink. Done. */ - free (path2); - return path; - } - - /* path is a symlink. Continue loop and resolve this. */ - strncpy (path, path2, buf_size - 1); - } - - - /* readlink() or stat() failed; this can happen when the program is - * running in Valgrind 2.2. Read from /proc/self/maps as fallback. */ - - buf_size = PATH_MAX + 128; - line = (char *) realloc (path, buf_size); - if (line == NULL) { - /* Cannot allocate memory. */ - free (path); - if (error) - *error = BR_INIT_ERROR_NOMEM; - return NULL; - } - - f = fopen ("/proc/self/maps", "r"); - if (f == NULL) { - free (line); - if (error) - *error = BR_INIT_ERROR_OPEN_MAPS; - return NULL; - } - - /* The first entry should be the executable name. */ - result = fgets (line, (int) buf_size, f); - if (result == NULL) { - fclose (f); - free (line); - if (error) - *error = BR_INIT_ERROR_READ_MAPS; - return NULL; - } - - /* Get rid of newline character. */ - buf_size = strlen (line); - if (buf_size <= 0) { - /* Huh? An empty string? */ - fclose (f); - free (line); - if (error) - *error = BR_INIT_ERROR_INVALID_MAPS; - return NULL; - } - if (line[buf_size - 1] == 10) - line[buf_size - 1] = 0; - - /* Extract the filename; it is always an absolute path. */ - path = strchr (line, '/'); - - /* Sanity check. */ - if (strstr (line, " r-xp ") == NULL || path == NULL) { - fclose (f); - free (line); - if (error) - *error = BR_INIT_ERROR_INVALID_MAPS; - return NULL; - } - - path = strdup (path); - free (line); - fclose (f); - return path; -#endif /* ENABLE_BINRELOC */ -} - - -/** @internal - * Find the canonical filename of the executable which owns symbol. - * Returns a filename which must be freed, or NULL on error. - */ -static char * -_br_find_exe_for_symbol (const void *symbol, BrInitError *error) -{ -#ifndef ENABLE_BINRELOC - if (error) - *error = BR_INIT_ERROR_DISABLED; - return (char *) NULL; -#else - #define SIZE PATH_MAX + 100 - FILE *f; - size_t address_string_len; - char *address_string, line[SIZE], *found; - - if (symbol == NULL) - return (char *) NULL; - - f = fopen ("/proc/self/maps", "r"); - if (f == NULL) - return (char *) NULL; - - address_string_len = 4; - address_string = (char *) malloc (address_string_len); - found = (char *) NULL; - - while (!feof (f)) { - char *start_addr, *end_addr, *end_addr_end, *file; - void *start_addr_p, *end_addr_p; - size_t len; - - if (fgets (line, SIZE, f) == NULL) - break; - - /* Sanity check. */ - if (strstr (line, " r-xp ") == NULL || strchr (line, '/') == NULL) - continue; - - /* Parse line. */ - start_addr = line; - end_addr = strchr (line, '-'); - file = strchr (line, '/'); - - /* More sanity check. */ - if (!(file > end_addr && end_addr != NULL && end_addr[0] == '-')) - continue; - - end_addr[0] = '\0'; - end_addr++; - end_addr_end = strchr (end_addr, ' '); - if (end_addr_end == NULL) - continue; - - end_addr_end[0] = '\0'; - len = strlen (file); - if (len == 0) - continue; - if (file[len - 1] == '\n') - file[len - 1] = '\0'; - - /* Get rid of "(deleted)" from the filename. */ - len = strlen (file); - if (len > 10 && strcmp (file + len - 10, " (deleted)") == 0) - file[len - 10] = '\0'; - - /* I don't know whether this can happen but better safe than sorry. */ - len = strlen (start_addr); - if (len != strlen (end_addr)) - continue; - - - /* Transform the addresses into a string in the form of 0xdeadbeef, - * then transform that into a pointer. */ - if (address_string_len < len + 3) { - address_string_len = len + 3; - address_string = (char *) realloc (address_string, address_string_len); - } - - memcpy (address_string, "0x", 2); - memcpy (address_string + 2, start_addr, len); - address_string[2 + len] = '\0'; - sscanf (address_string, "%p", &start_addr_p); - - memcpy (address_string, "0x", 2); - memcpy (address_string + 2, end_addr, len); - address_string[2 + len] = '\0'; - sscanf (address_string, "%p", &end_addr_p); - - - if (symbol >= start_addr_p && symbol < end_addr_p) { - found = file; - break; - } - } - - free (address_string); - fclose (f); - - if (found == NULL) - return (char *) NULL; - else - return strdup (found); -#endif /* ENABLE_BINRELOC */ -} - - -#ifndef BINRELOC_RUNNING_DOXYGEN - #undef NULL - #define NULL ((void *) 0) /* typecasted as char* for C++ type safeness */ -#endif - -static char *exe = (char *) NULL; - - -/** Initialize the BinReloc library (for applications). - * - * This function must be called before using any other BinReloc functions. - * It attempts to locate the application's canonical filename. - * - * @note If you want to use BinReloc for a library, then you should call - * br_init_lib() instead. - * - * @param error If BinReloc failed to initialize, then the error code will - * be stored in this variable. Set to NULL if you want to - * ignore this. See #BrInitError for a list of error codes. - * - * @returns 1 on success, 0 if BinReloc failed to initialize. - */ -int -br_init (BrInitError *error) -{ - exe = _br_find_exe (error); - return exe != NULL; -} - - -/** Initialize the BinReloc library (for libraries). - * - * This function must be called before using any other BinReloc functions. - * It attempts to locate the calling library's canonical filename. - * - * @note The BinReloc source code MUST be included in your library, or this - * function won't work correctly. - * - * @param error If BinReloc failed to initialize, then the error code will - * be stored in this variable. Set to NULL if you want to - * ignore this. See #BrInitError for a list of error codes. - * - * @returns 1 on success, 0 if a filename cannot be found. - */ -int -br_init_lib (BrInitError *error) -{ - exe = _br_find_exe_for_symbol ((const void *) "", error); - return exe != NULL; -} - - -/** Find the canonical filename of the current application. - * - * @param default_exe A default filename which will be used as fallback. - * @returns A string containing the application's canonical filename, - * which must be freed when no longer necessary. If BinReloc is - * not initialized, or if br_init() failed, then a copy of - * default_exe will be returned. If default_exe is NULL, then - * NULL will be returned. - */ -char * -br_find_exe (const char *default_exe) -{ - if (exe == (char *) NULL) { - /* BinReloc is not initialized. */ - if (default_exe != (const char *) NULL) - return strdup (default_exe); - else - return (char *) NULL; - } - return strdup (exe); -} - - -/** Locate the directory in which the current application is installed. - * - * The prefix is generated by the following pseudo-code evaluation: - * \code - * dirname(exename) - * \endcode - * - * @param default_dir A default directory which will used as fallback. - * @return A string containing the directory, which must be freed when no - * longer necessary. If BinReloc is not initialized, or if the - * initialization function failed, then a copy of default_dir - * will be returned. If default_dir is NULL, then NULL will be - * returned. - */ -char * -br_find_exe_dir (const char *default_dir) -{ - if (exe == NULL) { - /* BinReloc not initialized. */ - if (default_dir != NULL) - return strdup (default_dir); - else - return NULL; - } - - return br_dirname (exe); -} - - -/** Locate the prefix in which the current application is installed. - * - * The prefix is generated by the following pseudo-code evaluation: - * \code - * dirname(dirname(exename)) - * \endcode - * - * @param default_prefix A default prefix which will used as fallback. - * @return A string containing the prefix, which must be freed when no - * longer necessary. If BinReloc is not initialized, or if - * the initialization function failed, then a copy of default_prefix - * will be returned. If default_prefix is NULL, then NULL will be returned. - */ -char * -br_find_prefix (const char *default_prefix) -{ - char *dir1, *dir2; - - if (exe == (char *) NULL) { - /* BinReloc not initialized. */ - if (default_prefix != (const char *) NULL) - return strdup (default_prefix); - else - return (char *) NULL; - } - - dir1 = br_dirname (exe); - dir2 = br_dirname (dir1); - free (dir1); - return dir2; -} - - -/** Locate the application's binary folder. - * - * The path is generated by the following pseudo-code evaluation: - * \code - * prefix + "/bin" - * \endcode - * - * @param default_bin_dir A default path which will used as fallback. - * @return A string containing the bin folder's path, which must be freed when - * no longer necessary. If BinReloc is not initialized, or if - * the initialization function failed, then a copy of default_bin_dir will - * be returned. If default_bin_dir is NULL, then NULL will be returned. - */ -char * -br_find_bin_dir (const char *default_bin_dir) -{ - char *prefix, *dir; - - prefix = br_find_prefix ((const char *) NULL); - if (prefix == (char *) NULL) { - /* BinReloc not initialized. */ - if (default_bin_dir != (const char *) NULL) - return strdup (default_bin_dir); - else - return (char *) NULL; - } - - dir = br_build_path (prefix, "bin"); - free (prefix); - return dir; -} - - -/** Locate the application's superuser binary folder. - * - * The path is generated by the following pseudo-code evaluation: - * \code - * prefix + "/sbin" - * \endcode - * - * @param default_sbin_dir A default path which will used as fallback. - * @return A string containing the sbin folder's path, which must be freed when - * no longer necessary. If BinReloc is not initialized, or if the - * initialization function failed, then a copy of default_sbin_dir will - * be returned. If default_bin_dir is NULL, then NULL will be returned. - */ -char * -br_find_sbin_dir (const char *default_sbin_dir) -{ - char *prefix, *dir; - - prefix = br_find_prefix ((const char *) NULL); - if (prefix == (char *) NULL) { - /* BinReloc not initialized. */ - if (default_sbin_dir != (const char *) NULL) - return strdup (default_sbin_dir); - else - return (char *) NULL; - } - - dir = br_build_path (prefix, "sbin"); - free (prefix); - return dir; -} - - -/** Locate the application's data folder. - * - * The path is generated by the following pseudo-code evaluation: - * \code - * prefix + "/share" - * \endcode - * - * @param default_data_dir A default path which will used as fallback. - * @return A string containing the data folder's path, which must be freed when - * no longer necessary. If BinReloc is not initialized, or if the - * initialization function failed, then a copy of default_data_dir - * will be returned. If default_data_dir is NULL, then NULL will be - * returned. - */ -char * -br_find_data_dir (const char *default_data_dir) -{ - char *prefix, *dir; - - prefix = br_find_prefix ((const char *) NULL); - if (prefix == (char *) NULL) { - /* BinReloc not initialized. */ - if (default_data_dir != (const char *) NULL) - return strdup (default_data_dir); - else - return (char *) NULL; - } - - dir = br_build_path (prefix, "share"); - free (prefix); - return dir; -} - - -/** Locate the application's localization folder. - * - * The path is generated by the following pseudo-code evaluation: - * \code - * prefix + "/share/locale" - * \endcode - * - * @param default_locale_dir A default path which will used as fallback. - * @return A string containing the localization folder's path, which must be freed when - * no longer necessary. If BinReloc is not initialized, or if the - * initialization function failed, then a copy of default_locale_dir will be returned. - * If default_locale_dir is NULL, then NULL will be returned. - */ -char * -br_find_locale_dir (const char *default_locale_dir) -{ - char *data_dir, *dir; - - data_dir = br_find_data_dir ((const char *) NULL); - if (data_dir == (char *) NULL) { - /* BinReloc not initialized. */ - if (default_locale_dir != (const char *) NULL) - return strdup (default_locale_dir); - else - return (char *) NULL; - } - - dir = br_build_path (data_dir, "locale"); - free (data_dir); - return dir; -} - - -/** Locate the application's library folder. - * - * The path is generated by the following pseudo-code evaluation: - * \code - * prefix + "/lib" - * \endcode - * - * @param default_lib_dir A default path which will used as fallback. - * @return A string containing the library folder's path, which must be freed when - * no longer necessary. If BinReloc is not initialized, or if the initialization - * function failed, then a copy of default_lib_dir will be returned. - * If default_lib_dir is NULL, then NULL will be returned. - */ -char * -br_find_lib_dir (const char *default_lib_dir) -{ - char *prefix, *dir; - - prefix = br_find_prefix ((const char *) NULL); - if (prefix == (char *) NULL) { - /* BinReloc not initialized. */ - if (default_lib_dir != (const char *) NULL) - return strdup (default_lib_dir); - else - return (char *) NULL; - } - - dir = br_build_path (prefix, "lib"); - free (prefix); - return dir; -} - - -/** Locate the application's libexec folder. - * - * The path is generated by the following pseudo-code evaluation: - * \code - * prefix + "/libexec" - * \endcode - * - * @param default_libexec_dir A default path which will used as fallback. - * @return A string containing the libexec folder's path, which must be freed when - * no longer necessary. If BinReloc is not initialized, or if the initialization - * function failed, then a copy of default_libexec_dir will be returned. - * If default_libexec_dir is NULL, then NULL will be returned. - */ -char * -br_find_libexec_dir (const char *default_libexec_dir) -{ - char *prefix, *dir; - - prefix = br_find_prefix ((const char *) NULL); - if (prefix == (char *) NULL) { - /* BinReloc not initialized. */ - if (default_libexec_dir != (const char *) NULL) - return strdup (default_libexec_dir); - else - return (char *) NULL; - } - - dir = br_build_path (prefix, "libexec"); - free (prefix); - return dir; -} - - -/** Locate the application's configuration files folder. - * - * The path is generated by the following pseudo-code evaluation: - * \code - * prefix + "/etc" - * \endcode - * - * @param default_etc_dir A default path which will used as fallback. - * @return A string containing the etc folder's path, which must be freed when - * no longer necessary. If BinReloc is not initialized, or if the initialization - * function failed, then a copy of default_etc_dir will be returned. - * If default_etc_dir is NULL, then NULL will be returned. - */ -char * -br_find_etc_dir (const char *default_etc_dir) -{ - char *prefix, *dir; - - prefix = br_find_prefix ((const char *) NULL); - if (prefix == (char *) NULL) { - /* BinReloc not initialized. */ - if (default_etc_dir != (const char *) NULL) - return strdup (default_etc_dir); - else - return (char *) NULL; - } - - dir = br_build_path (prefix, "etc"); - free (prefix); - return dir; -} - - -/*********************** - * Utility functions - ***********************/ - -/** Concatenate str1 and str2 to a newly allocated string. - * - * @param str1 A string. - * @param str2 Another string. - * @returns A newly-allocated string. This string should be freed when no longer needed. - */ -char * -br_strcat (const char *str1, const char *str2) -{ - char *result; - size_t len1, len2; - - if (str1 == NULL) - str1 = ""; - if (str2 == NULL) - str2 = ""; - - len1 = strlen (str1); - len2 = strlen (str2); - - result = (char *) malloc (len1 + len2 + 1); - memcpy (result, str1, len1); - memcpy (result + len1, str2, len2); - result[len1 + len2] = '\0'; - - return result; -} - - -char * -br_build_path (const char *dir, const char *file) -{ - char *dir2, *result; - size_t len; - int must_free = 0; - - len = strlen (dir); - if (len > 0 && dir[len - 1] != '/') { - dir2 = br_strcat (dir, "/"); - must_free = 1; - } else - dir2 = (char *) dir; - - result = br_strcat (dir2, file); - if (must_free) - free (dir2); - return result; -} - - -/* Emulates glibc's strndup() */ -static char * -br_strndup (const char *str, size_t size) -{ - char *result = (char *) NULL; - size_t len; - - if (str == (const char *) NULL) - return (char *) NULL; - - len = strlen (str); - if (len == 0) - return strdup (""); - if (size > len) - size = len; - - result = (char *) malloc (len + 1); - memcpy (result, str, size); - result[size] = '\0'; - return result; -} - - -/** Extracts the directory component of a path. - * - * Similar to g_dirname() or the dirname commandline application. - * - * Example: - * \code - * br_dirname ("/usr/local/foobar"); --> Returns: "/usr/local" - * \endcode - * - * @param path A path. - * @returns A directory name. This string should be freed when no longer needed. - */ -char * -br_dirname (const char *path) -{ - char *end, *result; - - if (path == (const char *) NULL) - return (char *) NULL; - - end = strrchr (path, '/'); - if (end == (const char *) NULL) - return strdup ("."); - - while (end > path && *end == '/') - end--; - result = br_strndup (path, end - path + 1); - if (result[0] == 0) { - free (result); - return strdup ("/"); - } else - return result; -} - - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* BINRELOC_C */ diff --git a/src/binreloc.h b/src/binreloc.h deleted file mode 100644 index 93b71040f..000000000 --- a/src/binreloc.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - * BinReloc - a library for creating relocatable executables - * Written by: Hongli Lai - * http://autopackage.org/ - * - * This source code is public domain. You can relicense this code - * under whatever license you want. - * - * See http://autopackage.org/docs/binreloc/ for - * more information and how to use this. - */ - -#ifndef BINRELOC_H -#define BINRELOC_H - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - - -/** These error codes can be returned by br_init(), br_init_lib(), gbr_init() or gbr_init_lib(). */ -typedef enum { - /** Cannot allocate memory. */ - BR_INIT_ERROR_NOMEM, - /** Unable to open /proc/self/maps; see errno for details. */ - BR_INIT_ERROR_OPEN_MAPS, - /** Unable to read from /proc/self/maps; see errno for details. */ - BR_INIT_ERROR_READ_MAPS, - /** The file format of /proc/self/maps is invalid; kernel bug? */ - BR_INIT_ERROR_INVALID_MAPS, - /** BinReloc is disabled (the ENABLE_BINRELOC macro is not defined). */ - BR_INIT_ERROR_DISABLED -} BrInitError; - - -#ifndef BINRELOC_RUNNING_DOXYGEN -/* Mangle symbol names to avoid symbol collisions with other ELF objects. */ - #define br_init dJyi14798182285183_br_init - #define br_init_lib dJyi14798182285183_br_init_lib - #define br_find_exe dJyi14798182285183_br_find_exe - #define br_find_exe_dir dJyi14798182285183_br_find_exe_dir - #define br_find_prefix dJyi14798182285183_br_find_prefix - #define br_find_bin_dir dJyi14798182285183_br_find_bin_dir - #define br_find_sbin_dir dJyi14798182285183_br_find_sbin_dir - #define br_find_data_dir dJyi14798182285183_br_find_data_dir - #define br_find_locale_dir dJyi14798182285183_br_find_locale_dir - #define br_find_lib_dir dJyi14798182285183_br_find_lib_dir - #define br_find_libexec_dir dJyi14798182285183_br_find_libexec_dir - #define br_find_etc_dir dJyi14798182285183_br_find_etc_dir - #define br_strcat dJyi14798182285183_br_strcat - #define br_build_path dJyi14798182285183_br_build_path - #define br_dirname dJyi14798182285183_br_dirname - - -#endif -int br_init (BrInitError *error); -int br_init_lib (BrInitError *error); - -char *br_find_exe (const char *default_exe); -char *br_find_exe_dir (const char *default_dir); -char *br_find_prefix (const char *default_prefix); -char *br_find_bin_dir (const char *default_bin_dir); -char *br_find_sbin_dir (const char *default_sbin_dir); -char *br_find_data_dir (const char *default_data_dir); -char *br_find_locale_dir (const char *default_locale_dir); -char *br_find_lib_dir (const char *default_lib_dir); -char *br_find_libexec_dir (const char *default_libexec_dir); -char *br_find_etc_dir (const char *default_etc_dir); - -/* Utility functions */ -char *br_strcat (const char *str1, const char *str2); -char *br_build_path (const char *dir, const char *file); -char *br_dirname (const char *path); - - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* BINRELOC_H */ diff --git a/src/build-runtime.cmake b/src/build-runtime.cmake deleted file mode 100644 index dc9717506..000000000 --- a/src/build-runtime.cmake +++ /dev/null @@ -1,148 +0,0 @@ -set(APPIMAGEKIT_RUNTIME_ENABLE_SETPROCTITLE OFF CACHE BOOL "Useful for $TARGET_APPIMAGE; see issue #763") - -# if set to anything but ON, the magic bytes won't be embedded -# CAUTION: the magic bytes are a hard requirement for type 2 AppImages! This option should NEVER be used unless you are -# 100% sure what you are doing here! -set(APPIMAGEKIT_EMBED_MAGIC_BYTES ON CACHE BOOL "") -# mark as advanced so it won't show up in CMake GUIs etc., to prevent users from accidentally using this option -mark_as_advanced(APPIMAGEKIT_EMBED_MAGIC_BYTES) - -# check type of current build -string(TOUPPER "${CMAKE_BUILD_TYPE}" BUILD_TYPE_UPPER) -if (BUILD_TYPE_UPPER STREQUAL DEBUG) - set(BUILD_DEBUG TRUE) -else() - set(BUILD_DEBUG FALSE) -endif() - -if (NOT TARGET libsquashfuse) - message(FATAL_ERROR "TARGET NOT found libsquashfuse") -else() - get_target_property(squashfuse_INCLUDE_DIRS libsquashfuse INTERFACE_INCLUDE_DIRECTORIES) -endif() - -# must not include -flto in the following flags, otherwise the data sections will be stripped out -set(runtime_cflags - -std=c99 -ffunction-sections -fdata-sections - -DGIT_COMMIT=\\"${GIT_COMMIT}\\" - -I${squashfuse_INCLUDE_DIRS} - -I${PROJECT_SOURCE_DIR}/include - -I${PROJECT_SOURCE_DIR}/lib/libappimage/include - -I${PROJECT_SOURCE_DIR}/lib/libappimage/src/libappimage_hashlib/include - ${DEPENDENCIES_CFLAGS} -) -# must not include -Wl,--gc-sections in the following flags, otherwise the data sections will be stripped out -set(runtime_ldflags -s -ffunction-sections -fdata-sections -flto ${DEPENDENCIES_LDFLAGS}) - -if(BUILD_DEBUG) - message(WARNING "Debug build, adding debug information") - set(runtime_cflags -g ${runtime_cflags}) -else() - message(STATUS "Release build, optimizing runtime") - set(runtime_cflags -Os ${runtime_cflags}) -endif() - -if(NOT xz_INCLUDE_DIRS STREQUAL "") - list(APPEND runtime_cflags -I${xz_INCLUDE_DIRS}) -endif() - -if(APPIMAGEKIT_RUNTIME_ENABLE_SETPROCTITLE) - set(runtime_cflags ${runtime_cflags} -DENABLE_SETPROCTITLE) -endif() - -# objcopy requires actual files for creating new sections to populate the new section -# therefore, we generate 3 suitable files containing blank bytes in the right sizes -add_custom_command( - OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/16_blank_bytes - COMMAND dd if=/dev/zero bs=1 count=16 of=${CMAKE_CURRENT_BINARY_DIR}/16_blank_bytes -) -add_custom_command( - OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/1024_blank_bytes - COMMAND dd if=/dev/zero bs=1 count=1024 of=${CMAKE_CURRENT_BINARY_DIR}/1024_blank_bytes -) -add_custom_command( - OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/8192_blank_bytes - COMMAND dd if=/dev/zero bs=1 count=8192 of=${CMAKE_CURRENT_BINARY_DIR}/8192_blank_bytes -) - -# compile first raw object (not linked yet) into which the sections will be embedded -# TODO: find out how this .o object can be generated using a normal add_executable call -# that'd allow us to get rid of the -I parameters in runtime_cflags -add_custom_command( - MAIN_DEPENDENCY runtime.c - OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/runtime.0.o - COMMAND ${CMAKE_C_COMPILER} ${runtime_cflags} -c ${CMAKE_CURRENT_SOURCE_DIR}/runtime.c -o runtime.0.o - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} -) - -# embed the sections, one by one -# TODO: find out whether all the sections can be embedded in a single objcopy call -add_custom_command( - OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/runtime.1.o - COMMAND ${OBJCOPY} --add-section .digest_md5=16_blank_bytes --set-section-flags .digest_md5=noload,readonly runtime.0.o runtime.1.o - MAIN_DEPENDENCY ${CMAKE_CURRENT_BINARY_DIR}/runtime.0.o - DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/16_blank_bytes - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} -) -add_custom_command( - OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/runtime.2.o - COMMAND ${OBJCOPY} --add-section .upd_info=1024_blank_bytes --set-section-flags .upd_info=noload,readonly runtime.1.o runtime.2.o - MAIN_DEPENDENCY ${CMAKE_CURRENT_BINARY_DIR}/runtime.1.o - DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/1024_blank_bytes - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} -) -add_custom_command( - OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/runtime.3.o - COMMAND ${OBJCOPY} --add-section .sha256_sig=1024_blank_bytes --set-section-flags .sha256_sig=noload,readonly runtime.2.o runtime.3.o - MAIN_DEPENDENCY ${CMAKE_CURRENT_BINARY_DIR}/runtime.2.o - DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/1024_blank_bytes - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} -) -add_custom_command( - OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/runtime.4.o - COMMAND ${OBJCOPY} --add-section .sig_key=8192_blank_bytes --set-section-flags .sig_key=noload,readonly runtime.3.o runtime.4.o - MAIN_DEPENDENCY ${CMAKE_CURRENT_BINARY_DIR}/runtime.3.o - DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/8192_blank_bytes - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} -) - -# add the runtime as a normal executable -# CLion will recognize it as a normal executable, one can simply step into the code -add_executable(runtime ${CMAKE_CURRENT_BINARY_DIR}/runtime.4.o notify.c) -# CMake gets confused by the .o object, therefore we need to tell it that it shall link everything using the C compiler -set_property(TARGET runtime PROPERTY LINKER_LANGUAGE C) -target_link_libraries(runtime PRIVATE libsquashfuse dl xz libzlib pthread libappimage_shared libappimage_hashlib) -if(COMMAND target_link_options) - target_link_options(runtime PRIVATE ${runtime_ldflags}) -else() - message(WARNING "CMake version < 3.13, falling back to using target_link_libraries instead of target_link_options") - target_link_libraries(runtime PRIVATE ${runtime_ldflags}) -endif() -target_include_directories(runtime PRIVATE ${PROJECT_SOURCE_DIR}/include) - -if(BUILD_DEBUG) - message(WARNING "Debug build, not stripping runtime to allow debugging using gdb etc.") -else() - add_custom_command( - TARGET runtime - POST_BUILD - COMMAND ${STRIP} ${CMAKE_CURRENT_BINARY_DIR}/runtime - ) -endif() - -# embed the magic bytes after the runtime's build has finished -if(APPIMAGEKIT_EMBED_MAGIC_BYTES) - add_custom_command( - TARGET runtime - POST_BUILD - COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/embed-magic-bytes-in-file.sh ${CMAKE_CURRENT_BINARY_DIR}/runtime - ) -endif() - -# required for embedding in appimagetool -add_custom_command( - OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/runtime_embed.o - COMMAND ${XXD} -i runtime | ${CMAKE_C_COMPILER} -c -x c - -o runtime_embed.o - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - MAIN_DEPENDENCY runtime -) diff --git a/src/digest.c b/src/digest.c deleted file mode 100644 index fb6da7cd2..000000000 --- a/src/digest.c +++ /dev/null @@ -1,145 +0,0 @@ -/* - cc -o digest getsection.c digest.c -lssl -lcrypto -*/ - -#include -#include -#include -#include -#include -#include -#include - -#include "appimage/appimage_shared.h" - -typedef unsigned char byte; - -char segment_name[] = ".sha256_sig"; - -int sha256_file(char *path, char outputBuffer[65], int skip_offset, int skip_length) -{ - FILE *file = fopen(path, "rb"); - if(!file) return(1); - byte hash[SHA256_DIGEST_LENGTH]; - SHA256_CTX sha256; - SHA256_Init(&sha256); - const int bufSize = 1024*1024; - byte *buffer = malloc(bufSize); - int bytesRead = 0; - if(!buffer) { - fclose(file); - return ENOMEM; - } - - int totalBytesRead = 0; - if(skip_offset <= bufSize){ - bytesRead = fread(buffer, 1, skip_offset, file); - totalBytesRead += bytesRead; - // printf("totalBytesRead: %i\n", totalBytesRead); - // printf("bytesRead: %i\n", bytesRead); - SHA256_Update(&sha256, buffer, bytesRead); - } else { - int stillToRead = skip_offset-bytesRead; - // printf("Initial stillToRead: %i\n", stillToRead); - int readThisTime; - - if(stillToRead>bufSize){ - readThisTime = bufSize; - } else { - readThisTime = stillToRead; - } - while((bytesRead = fread(buffer, 1, readThisTime, file))) - { - totalBytesRead += bytesRead; - // printf("totalBytesRead: %i\n", totalBytesRead); - // printf("readThisTime: %i\n", readThisTime); - // printf("bytesRead: %i\n", bytesRead); - SHA256_Update(&sha256, buffer, bytesRead); - stillToRead = skip_offset-totalBytesRead; - // printf("stillToRead: %i\n", stillToRead); - - if(stillToRead>bufSize){ - readThisTime = bufSize; - } else { - readThisTime = stillToRead; - } - } - } - - fseek(file, skip_offset+skip_length, SEEK_SET); - - /* Instead of the skipped area, calculate the sha256 of the same amount if 0x00s */ - int i = 0; - for(i = 0; i < skip_length; i++) { - SHA256_Update(&sha256, "\0", 1); - totalBytesRead += 1; - } - - while((bytesRead = fread(buffer, 1, bufSize, file))) - { - totalBytesRead += bytesRead; - // printf("totalBytesRead: %i\n", totalBytesRead); - // printf("bytesRead: %i\n", bytesRead); - SHA256_Update(&sha256, buffer, bytesRead); - } - SHA256_Final(hash, &sha256); - - // fprintf(stderr, "totalBytesRead: %i\n", totalBytesRead); - - for(i = 0; i < SHA256_DIGEST_LENGTH; i++) - { - sprintf(outputBuffer + (i * 2), "%02x", hash[i]); - } - outputBuffer[64] = 0; - - fclose(file); - free(buffer); - - return 0; -} - -int main(int argc,char **argv) -{ - int res = 0; - - if(argc < 2){ - fprintf(stderr, "Usage: %s file offset length\n", argv[0]); - fprintf(stderr, "If no offset and length are provided, the ELF section '%s' is skipped\n\n", segment_name); - fprintf(stderr, "Calculate a sha256 of a file except a skipped area from offset to offset+length bytes\n"); - fprintf(stderr, "which is replaced with 0x00 during checksum calculation.\n"); - fprintf(stderr, "This is useful when a signature is placed in the skipped area.\n"); - exit(1); - } - - unsigned long skip_offset = 0; - unsigned long skip_length = 0; - char *filename = argv[1]; - - struct stat st; - if (stat(filename, &st) < 0) { - fprintf(stderr, "not existing file: %s\n", filename); - exit(1); - } - - if(argc < 4){ - appimage_get_elf_section_offset_and_length(filename, ".sha256_sig", &skip_offset, &skip_length); - if(skip_length > 0) - fprintf(stderr, "Skipping ELF section %s with offset %lu, length %lu\n", segment_name, skip_offset, skip_length); - } else if(argc == 4) { - skip_offset = atoi(argv[2]); - skip_length = atoi(argv[3]); - } else { - exit(1); - } - - int size = st.st_size; - if(size < skip_offset+skip_length){ - fprintf(stderr, "offset+length cannot be less than the file size\n"); - exit(1); - } - - static char buffer[65]; - res = sha256_file(filename, buffer, skip_offset, skip_length); - printf("%s\n", buffer); - return res; -} diff --git a/src/digest_md5.c b/src/digest_md5.c deleted file mode 100644 index 5285f20b5..000000000 --- a/src/digest_md5.c +++ /dev/null @@ -1,98 +0,0 @@ -#include -#include -#include - -#include "appimage/appimage_shared.h" -#include "getsection.h" - - -bool compare_byte_buffers(const char* buf1, const char* buf2, size_t num_bytes) { - for (size_t i = 0; i < num_bytes; i++) { - if (buf1[i] != buf2[i]) { - return false; - } - } - - return true; -} - - -int main(int argc, char* argv[]) { - if (argc != 2) { - printf("Usage: %s \n", argv[0]); - printf("\n"); - printf("Calculate AppImage MD5 digest, and compare it to embedded value (if available)\n"); - } - - const char* fname = argv[1]; - if (!g_file_test(fname, G_FILE_TEST_IS_REGULAR)) { - fprintf(stderr, "No such file or directory: %s\n", fname); - return 1; - } - - static const int digest_size = 16; - - // first, calculate MD5 digest using algorithm in libappimage - char expected_digest[digest_size]; - - if (!appimage_type2_digest_md5(fname, expected_digest)) { - fprintf(stderr, "Could not calculate MD5 digest\n"); - return 1; - } - - // print hex encoded digest - char* hexlified_expected_digest = appimage_hexlify(expected_digest, digest_size); - printf("calculated: %s\n", hexlified_expected_digest); - free(hexlified_expected_digest); - - unsigned long offset = 0, length = 0; - - static const char section_name[] = ".digest_md5"; - - if (!appimage_get_elf_section_offset_and_length(fname, section_name, &offset, &length) || offset == 0 || length == 0) { - fprintf(stderr, "Could not find %s section in file\n", section_name); - return 1; - } - - if (length < digest_size) { - fprintf(stderr, - "Invalid section length for section %s: expected %d bytes, found %lu bytes\n", - section_name, digest_size, length - ); - return 1; - } - - char embedded_digest[digest_size]; - FILE* fp = fopen(fname, "r"); - - if (fp == NULL) { - fprintf(stderr, "Failed to open AppImage for writing"); - return 1; - } - - if (fseek(fp, offset, SEEK_SET) != 0) { - fprintf(stderr, "Failed to read embedded digest: failed to seek to offset\n"); - fclose(fp); - return 1; - } - - if (fread(embedded_digest, sizeof(char), digest_size, fp) != digest_size) { - fprintf(stderr, "Failed to read embedded digest: read invalid amount of bytes from file\n"); - fclose(fp); - return 1; - } - - fclose(fp); - - char* hexlified_embedded_digest = appimage_hexlify(embedded_digest, digest_size); - printf(" embedded: %s\n", hexlified_embedded_digest); - free(hexlified_embedded_digest); - - if (compare_byte_buffers(expected_digest, embedded_digest, digest_size)) { - printf("Digests match\n"); - return 0; - } else { - printf("Digests don't match!"); - return 1; - } -} diff --git a/src/embed-magic-bytes-in-file.sh b/src/embed-magic-bytes-in-file.sh deleted file mode 100755 index 23a8a97a4..000000000 --- a/src/embed-magic-bytes-in-file.sh +++ /dev/null @@ -1,8 +0,0 @@ -#! /bin/bash - -if [ "$1" == "" ]; then - echo "Usage: bash $0 " - exit 2 -fi - -echo -ne 'AI\x02' | dd of="$1" bs=1 count=3 seek=8 conv=notrunc diff --git a/src/light_elf.h b/src/light_elf.h deleted file mode 100644 index f13b9817b..000000000 --- a/src/light_elf.h +++ /dev/null @@ -1,123 +0,0 @@ -/* - * - * Linux kernel - * Copyright (C) 2017 Linus Torvalds - * Modified work Copyright (C) 2017 @teras (https://github.com/teras) - * (Shortened version -- original work found here: - * https://github.com/torvalds/linux/blob/master/include/uapi/linux/elf.h) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License. - * - * 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 St, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#ifndef LIGHT_ELF_H -#define LIGHT_ELF_H - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -typedef uint16_t Elf32_Half; -typedef uint16_t Elf64_Half; -typedef uint32_t Elf32_Word; -typedef uint32_t Elf64_Word; -typedef uint64_t Elf64_Xword; -typedef uint32_t Elf32_Addr; -typedef uint64_t Elf64_Addr; -typedef uint32_t Elf32_Off; -typedef uint64_t Elf64_Off; - -#define EI_NIDENT 16 - -typedef struct elf32_hdr { - unsigned char e_ident[EI_NIDENT]; - Elf32_Half e_type; - Elf32_Half e_machine; - Elf32_Word e_version; - Elf32_Addr e_entry; /* Entry point */ - Elf32_Off e_phoff; - Elf32_Off e_shoff; - Elf32_Word e_flags; - Elf32_Half e_ehsize; - Elf32_Half e_phentsize; - Elf32_Half e_phnum; - Elf32_Half e_shentsize; - Elf32_Half e_shnum; - Elf32_Half e_shstrndx; -} Elf32_Ehdr; - -typedef struct elf64_hdr { - unsigned char e_ident[EI_NIDENT]; /* ELF "magic number" */ - Elf64_Half e_type; - Elf64_Half e_machine; - Elf64_Word e_version; - Elf64_Addr e_entry; /* Entry point virtual address */ - Elf64_Off e_phoff; /* Program header table file offset */ - Elf64_Off e_shoff; /* Section header table file offset */ - Elf64_Word e_flags; - Elf64_Half e_ehsize; - Elf64_Half e_phentsize; - Elf64_Half e_phnum; - Elf64_Half e_shentsize; - Elf64_Half e_shnum; - Elf64_Half e_shstrndx; -} Elf64_Ehdr; - -typedef struct elf32_shdr { - Elf32_Word sh_name; - Elf32_Word sh_type; - Elf32_Word sh_flags; - Elf32_Addr sh_addr; - Elf32_Off sh_offset; - Elf32_Word sh_size; - Elf32_Word sh_link; - Elf32_Word sh_info; - Elf32_Word sh_addralign; - Elf32_Word sh_entsize; -} Elf32_Shdr; - -typedef struct elf64_shdr { - Elf64_Word sh_name; /* Section name, index in string tbl */ - Elf64_Word sh_type; /* Type of section */ - Elf64_Xword sh_flags; /* Miscellaneous section attributes */ - Elf64_Addr sh_addr; /* Section virtual addr at execution */ - Elf64_Off sh_offset; /* Section file offset */ - Elf64_Xword sh_size; /* Size of section in bytes */ - Elf64_Word sh_link; /* Index of another section */ - Elf64_Word sh_info; /* Additional section information */ - Elf64_Xword sh_addralign; /* Section alignment */ - Elf64_Xword sh_entsize; /* Entry size if section holds table */ -} Elf64_Shdr; - -/* Note header in a PT_NOTE section */ -typedef struct elf32_note { - Elf32_Word n_namesz; /* Name size */ - Elf32_Word n_descsz; /* Content size */ - Elf32_Word n_type; /* Content type */ -} Elf32_Nhdr; - -#define ELFCLASS32 1 -#define ELFDATA2LSB 1 -#define ELFDATA2MSB 2 -#define ELFCLASS64 2 -#define EI_CLASS 4 -#define EI_DATA 5 - -#ifdef __cplusplus -} -#endif - -#endif /* elf.h */ diff --git a/src/notify.c b/src/notify.c deleted file mode 100644 index ca51e04d4..000000000 --- a/src/notify.c +++ /dev/null @@ -1,91 +0,0 @@ -#include -#include -#include -#include - -/* Try to show a notification on the GUI, fall back to the command line - * timeout is the timeout in milliseconds. timeout = NULL seems to trigger a - * GUI error dialog rather than a notification */ -int notify(char *title, char *body, int timeout) -{ - /* http://stackoverflow.com/questions/13204177/how-to-find-out-if-running-from-terminal-or-gui */ - if (isatty(fileno(stdin))){ - /* We were launched from the command line. */ - printf("\n%s\n", title); - printf("%s\n", body); - } - else - { - /* We were launched from inside the desktop */ - printf("\n%s\n", title); - printf("%s\n", body); - /* https://debian-administration.org/article/407/Creating_desktop_notifications */ - void *handle, *n; - typedef void (*notify_init_t)(char *); - typedef void *(*notify_notification_new_t)( char *, char *, char *, char *); - typedef void (*notify_notification_set_timeout_t)( void *, int ); - typedef void (*notify_notification_show_t)(void *, char *); - handle = NULL; - if(handle == NULL) - handle= dlopen("libnotify.so.3", RTLD_LAZY); - if(handle == NULL) - handle= dlopen("libnotify.so.4", RTLD_LAZY); - if(handle == NULL) - handle= dlopen("libnotify.so.5", RTLD_LAZY); - if(handle == NULL) - handle= dlopen("libnotify.so.6", RTLD_LAZY); - if(handle == NULL) - handle= dlopen("libnotify.so.7", RTLD_LAZY); - if(handle == NULL) - handle= dlopen("libnotify.so.8", RTLD_LAZY); - - if(handle == NULL) - { - printf("Failed to open libnotify.\n\n" ); - } - notify_init_t init = (notify_init_t)dlsym(handle, "notify_init"); - if ( init == NULL ) - { - dlclose( handle ); - return 1; - } - init("AppImage"); - - notify_notification_new_t nnn = (notify_notification_new_t)dlsym(handle, "notify_notification_new"); - if ( nnn == NULL ) - { - dlclose( handle ); - return 1; - } - n = nnn(title, body, NULL, NULL); - notify_notification_set_timeout_t nnst = (notify_notification_set_timeout_t)dlsym(handle, "notify_notification_set_timeout"); - if ( nnst == NULL ) - { - dlclose( handle ); - return 1; - } - nnst(n, timeout); - notify_notification_show_t show = (notify_notification_show_t)dlsym(handle, "notify_notification_show"); - if ( init == NULL ) - { - dlclose( handle ); - return 1; - } - show(n, NULL ); - dlclose(handle ); - } - return 0; -} - -/* -int main( int argc, char *argv[] ) -{ - char *title; - char *body; - printf("%s\n", "Test"); - title = "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua."; - body = "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet."; - notify(title, body, 3000); // 3 seconds timeout - return 0; -} -*/ diff --git a/src/runtime.c b/src/runtime.c deleted file mode 100644 index fa0aa7d31..000000000 --- a/src/runtime.c +++ /dev/null @@ -1,958 +0,0 @@ -/************************************************************************** - * - * Copyright (c) 2004-18 Simon Peter - * Portions Copyright (c) 2007 Alexander Larsson - * - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - **************************************************************************/ - -#ident "AppImage by Simon Peter, http://appimage.org/" - -#define _GNU_SOURCE - -#include "squashfuse.h" -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#ifndef ENABLE_DLOPEN -#define ENABLE_DLOPEN -#endif -#include "squashfuse_dlopen.h" - -/* Exit status to use when launching an AppImage fails. - * For applications that assign meanings to exit status codes (e.g. rsync), - * we avoid "cluttering" pre-defined exit status codes by using 127 which - * is known to alias an application exit status and also known as launcher - * error, see SYSTEM(3POSIX). - */ -#define EXIT_EXECERROR 127 /* Execution error exit status. */ - -//#include "notify.c" -extern int notify(char *title, char *body, int timeout); -struct stat st; - -static ssize_t fs_offset; // The offset at which a filesystem image is expected = end of this ELF - -static void die(const char *msg) { - fprintf(stderr, "%s\n", msg); - exit(EXIT_EXECERROR); -} - -/* Check whether directory is writable */ -bool is_writable_directory(char* str) { - if(access(str, W_OK) == 0) { - return true; - } else { - return false; - } -} - -bool startsWith(const char *pre, const char *str) -{ - size_t lenpre = strlen(pre), - lenstr = strlen(str); - return lenstr < lenpre ? false : strncmp(pre, str, lenpre) == 0; -} - -/* Fill in a stat structure. Does not set st_ino */ -sqfs_err private_sqfs_stat(sqfs *fs, sqfs_inode *inode, struct stat *st) { - sqfs_err err = SQFS_OK; - uid_t id; - - memset(st, 0, sizeof(*st)); - st->st_mode = inode->base.mode; - st->st_nlink = inode->nlink; - st->st_mtime = st->st_ctime = st->st_atime = inode->base.mtime; - - if (S_ISREG(st->st_mode)) { - /* FIXME: do symlinks, dirs, etc have a size? */ - st->st_size = inode->xtra.reg.file_size; - st->st_blocks = st->st_size / 512; - } else if (S_ISBLK(st->st_mode) || S_ISCHR(st->st_mode)) { - st->st_rdev = sqfs_makedev(inode->xtra.dev.major, - inode->xtra.dev.minor); - } else if (S_ISLNK(st->st_mode)) { - st->st_size = inode->xtra.symlink_size; - } - - st->st_blksize = fs->sb.block_size; /* seriously? */ - - err = sqfs_id_get(fs, inode->base.uid, &id); - if (err) - return err; - st->st_uid = id; - err = sqfs_id_get(fs, inode->base.guid, &id); - st->st_gid = id; - if (err) - return err; - - return SQFS_OK; -} - -/* ================= End ELF parsing */ - -extern int fusefs_main(int argc, char *argv[], void (*mounted) (void)); -// extern void ext2_quit(void); - -static pid_t fuse_pid; -static int keepalive_pipe[2]; - -static void * -write_pipe_thread (void *arg) -{ - char c[32]; - int res; - // sprintf(stderr, "Called write_pipe_thread"); - memset (c, 'x', sizeof (c)); - while (1) { - /* Write until we block, on broken pipe, exit */ - res = write (keepalive_pipe[1], c, sizeof (c)); - if (res == -1) { - kill (fuse_pid, SIGTERM); - break; - } - } - return NULL; -} - -void -fuse_mounted (void) -{ - pthread_t thread; - fuse_pid = getpid(); - pthread_create(&thread, NULL, write_pipe_thread, keepalive_pipe); -} - -char* getArg(int argc, char *argv[],char chr) -{ - int i; - for (i=1; i sizeof(_path)-1) { - errno = ENAMETOOLONG; - return -1; - } - strcpy(_path, path); - - /* Iterate the string */ - for (p = _path + 1; *p; p++) { - if (*p == '/') { - /* Temporarily truncate */ - *p = '\0'; - - if (mkdir(_path, 0755) != 0) { - if (errno != EEXIST) - return -1; - } - - *p = '/'; - } - } - - if (mkdir(_path, 0755) != 0) { - if (errno != EEXIST) - return -1; - } - - return 0; -} - -void -print_help(const char *appimage_path) -{ - // TODO: "--appimage-list List content from embedded filesystem image\n" - fprintf(stderr, - "AppImage options:\n\n" - " --appimage-extract [] Extract content from embedded filesystem image\n" - " If pattern is passed, only extract matching files\n" - " --appimage-help Print this help\n" - " --appimage-mount Mount embedded filesystem image and print\n" - " mount point and wait for kill with Ctrl-C\n" - " --appimage-offset Print byte offset to start of embedded\n" - " filesystem image\n" - " --appimage-portable-home Create a portable home folder to use as $HOME\n" - " --appimage-portable-config Create a portable config folder to use as\n" - " $XDG_CONFIG_HOME\n" - " --appimage-signature Print digital signature embedded in AppImage\n" - " --appimage-updateinfo[rmation] Print update info embedded in AppImage\n" - " --appimage-version Print version of AppImageKit\n" - "\n" - "Portable home:\n" - "\n" - " If you would like the application contained inside this AppImage to store its\n" - " data alongside this AppImage rather than in your home directory, then you can\n" - " place a directory named\n" - "\n" - " %s.home\n" - "\n" - " Or you can invoke this AppImage with the --appimage-portable-home option,\n" - " which will create this directory for you. As long as the directory exists\n" - " and is neither moved nor renamed, the application contained inside this\n" - " AppImage will store its data in this directory rather than in your home\n" - " directory\n" - , appimage_path); -} - -void -portable_option(const char *arg, const char *appimage_path, const char *name) -{ - char option[32]; - sprintf(option, "appimage-portable-%s", name); - - if (arg && strcmp(arg, option)==0) { - char portable_dir[PATH_MAX]; - char fullpath[PATH_MAX]; - - ssize_t length = readlink(appimage_path, fullpath, sizeof(fullpath)); - if (length < 0) { - fprintf(stderr, "Error getting realpath for %s\n", appimage_path); - exit(EXIT_FAILURE); - } - fullpath[length] = '\0'; - - sprintf(portable_dir, "%s.%s", fullpath, name); - if (!mkdir(portable_dir, S_IRWXU)) - fprintf(stderr, "Portable %s directory created at %s\n", name, portable_dir); - else - fprintf(stderr, "Error creating portable %s directory at %s: %s\n", name, portable_dir, strerror(errno)); - - exit(0); - } -} - -bool extract_appimage(const char* const appimage_path, const char* const _prefix, const char* const _pattern, const bool overwrite, const bool verbose) { - sqfs_err err = SQFS_OK; - sqfs_traverse trv; - sqfs fs; - char prefixed_path_to_extract[1024]; - - // local copy we can modify safely - // allocate 1 more byte than we would need so we can add a trailing slash if there is none yet - char* prefix = malloc(strlen(_prefix) + 2); - strcpy(prefix, _prefix); - - // sanitize prefix - if (prefix[strlen(prefix) - 1] != '/') - strcat(prefix, "/"); - - if (access(prefix, F_OK) == -1) { - if (mkdir_p(prefix) == -1) { - perror("mkdir_p error"); - return false; - } - } - - if ((err = sqfs_open_image(&fs, appimage_path, (size_t) fs_offset))) { - fprintf(stderr, "Failed to open squashfs image\n"); - return false; - }; - - // track duplicate inodes for hardlinks - char** created_inode = calloc(fs.sb.inodes, sizeof(char*)); - if (created_inode == NULL) { - fprintf(stderr, "Failed allocating memory to track hardlinks\n"); - return false; - } - - if ((err = sqfs_traverse_open(&trv, &fs, sqfs_inode_root(&fs)))) { - fprintf(stderr, "sqfs_traverse_open error\n"); - free(created_inode); - return false; - } - - bool rv = true; - - while (sqfs_traverse_next(&trv, &err)) { - if (!trv.dir_end) { - if (_pattern == NULL || fnmatch(_pattern, trv.path, FNM_FILE_NAME | FNM_LEADING_DIR) == 0) { - // fprintf(stderr, "trv.path: %s\n", trv.path); - // fprintf(stderr, "sqfs_inode_id: %lu\n", trv.entry.inode); - sqfs_inode inode; - if (sqfs_inode_get(&fs, &inode, trv.entry.inode)) { - fprintf(stderr, "sqfs_inode_get error\n"); - rv = false; - break; - } - // fprintf(stderr, "inode.base.inode_type: %i\n", inode.base.inode_type); - // fprintf(stderr, "inode.xtra.reg.file_size: %lu\n", inode.xtra.reg.file_size); - strcpy(prefixed_path_to_extract, ""); - strcat(strcat(prefixed_path_to_extract, prefix), trv.path); - - if (verbose) - fprintf(stdout, "%s\n", prefixed_path_to_extract); - - if (inode.base.inode_type == SQUASHFS_DIR_TYPE || inode.base.inode_type == SQUASHFS_LDIR_TYPE) { - // fprintf(stderr, "inode.xtra.dir.parent_inode: %ui\n", inode.xtra.dir.parent_inode); - // fprintf(stderr, "mkdir_p: %s/\n", prefixed_path_to_extract); - if (access(prefixed_path_to_extract, F_OK) == -1) { - if (mkdir_p(prefixed_path_to_extract) == -1) { - perror("mkdir_p error"); - rv = false; - break; - } - } - } else if (inode.base.inode_type == SQUASHFS_REG_TYPE || inode.base.inode_type == SQUASHFS_LREG_TYPE) { - // if we've already created this inode, then this is a hardlink - char* existing_path_for_inode = created_inode[inode.base.inode_number - 1]; - if (existing_path_for_inode != NULL) { - unlink(prefixed_path_to_extract); - if (link(existing_path_for_inode, prefixed_path_to_extract) == -1) { - fprintf(stderr, "Couldn't create hardlink from \"%s\" to \"%s\": %s\n", - prefixed_path_to_extract, existing_path_for_inode, strerror(errno)); - rv = false; - break; - } else { - continue; - } - } else { - struct stat st; - if (!overwrite && stat(prefixed_path_to_extract, &st) == 0 && st.st_size == inode.xtra.reg.file_size) { - fprintf(stderr, "File exists and file size matches, skipping\n"); - continue; - } - - // track the path we extract to for this inode, so that we can `link` if this inode is found again - created_inode[inode.base.inode_number - 1] = strdup(prefixed_path_to_extract); - // fprintf(stderr, "Extract to: %s\n", prefixed_path_to_extract); - if (private_sqfs_stat(&fs, &inode, &st) != 0) - die("private_sqfs_stat error"); - - // create parent dir - char* p = strrchr(prefixed_path_to_extract, '/'); - if (p) { - // set an \0 to end the split the string - *p = '\0'; - mkdir_p(prefixed_path_to_extract); - - // restore dir seprator - *p = '/'; - } - - // Read the file in chunks - off_t bytes_already_read = 0; - sqfs_off_t bytes_at_a_time = 64 * 1024; - FILE* f; - f = fopen(prefixed_path_to_extract, "w+"); - if (f == NULL) { - perror("fopen error"); - rv = false; - break; - } - while (bytes_already_read < inode.xtra.reg.file_size) { - char buf[bytes_at_a_time]; - if (sqfs_read_range(&fs, &inode, (sqfs_off_t) bytes_already_read, &bytes_at_a_time, buf)) { - perror("sqfs_read_range error"); - rv = false; - break; - } - // fwrite(buf, 1, bytes_at_a_time, stdout); - fwrite(buf, 1, bytes_at_a_time, f); - bytes_already_read = bytes_already_read + bytes_at_a_time; - } - fclose(f); - chmod(prefixed_path_to_extract, st.st_mode); - if (!rv) - break; - } - } else if (inode.base.inode_type == SQUASHFS_SYMLINK_TYPE || inode.base.inode_type == SQUASHFS_LSYMLINK_TYPE) { - size_t size; - sqfs_readlink(&fs, &inode, NULL, &size); - char buf[size]; - int ret = sqfs_readlink(&fs, &inode, buf, &size); - if (ret != 0) { - perror("symlink error"); - rv = false; - break; - } - // fprintf(stderr, "Symlink: %s to %s \n", prefixed_path_to_extract, buf); - unlink(prefixed_path_to_extract); - ret = symlink(buf, prefixed_path_to_extract); - if (ret != 0) - fprintf(stderr, "WARNING: could not create symlink\n"); - } else { - fprintf(stderr, "TODO: Implement inode.base.inode_type %i\n", inode.base.inode_type); - } - // fprintf(stderr, "\n"); - - if (!rv) - break; - } - } - } - for (int i = 0; i < fs.sb.inodes; i++) { - free(created_inode[i]); - } - free(created_inode); - - if (err != SQFS_OK) { - fprintf(stderr, "sqfs_traverse_next error\n"); - rv = false; - } - sqfs_traverse_close(&trv); - sqfs_fd_close(fs.fd); - - return rv; -} - -int rm_recursive_callback(const char* path, const struct stat* stat, const int type, struct FTW* ftw) { - (void) stat; - (void) ftw; - - switch (type) { - case FTW_NS: - case FTW_DNR: - fprintf(stderr, "%s: ftw error: %s\n", - path, strerror(errno)); - return 1; - - case FTW_D: - // ignore directories at first, will be handled by FTW_DP - break; - - case FTW_F: - case FTW_SL: - case FTW_SLN: - if (remove(path) != 0) { - fprintf(stderr, "Failed to remove %s: %s\n", path, strerror(errno)); - return false; - } - break; - - - case FTW_DP: - if (rmdir(path) != 0) { - fprintf(stderr, "Failed to remove directory %s: %s\n", path, strerror(errno)); - return false; - } - break; - - default: - fprintf(stderr, "Unexpected fts_info\n"); - return 1; - } - - return 0; -}; - -bool rm_recursive(const char* const path) { - // FTW_DEPTH: perform depth-first search to make sure files are deleted before the containing directories - // FTW_MOUNT: prevent deletion of files on other mounted filesystems - // FTW_PHYS: do not follow symlinks, but report symlinks as such; this way, the symlink targets, which might point - // to locations outside path will not be deleted accidentally (attackers might abuse this) - int rv = nftw(path, &rm_recursive_callback, 0, FTW_DEPTH | FTW_MOUNT | FTW_PHYS); - - return rv == 0; -} - -bool build_mount_point(char* mount_dir, const char* const argv0, char const* const temp_base, const size_t templen) { - const size_t maxnamelen = 6; - - // when running for another AppImage, we should use that for building the mountpoint name instead - char* target_appimage = getenv("TARGET_APPIMAGE"); - - char* path_basename; - if (target_appimage != NULL) { - path_basename = basename(target_appimage); - } else { - path_basename = basename(argv0); - } - - size_t namelen = strlen(path_basename); - // limit length of tempdir name - if (namelen > maxnamelen) { - namelen = maxnamelen; - } - - strcpy(mount_dir, temp_base); - strncpy(mount_dir + templen, "/.mount_", 8); - strncpy(mount_dir + templen + 8, path_basename, namelen); - strncpy(mount_dir+templen+8+namelen, "XXXXXX", 6); - mount_dir[templen+8+namelen+6] = 0; // null terminate destination -} - -void set_portable_home_and_config(char *basepath) { - char portable_home_dir[PATH_MAX]; - char portable_config_dir[PATH_MAX]; - - /* If there is a directory with the same name as the AppImage plus ".home", then export $HOME */ - strcpy (portable_home_dir, basepath); - strcat (portable_home_dir, ".home"); - if(is_writable_directory(portable_home_dir)){ - fprintf(stderr, "Setting $HOME to %s\n", portable_home_dir); - setenv("HOME",portable_home_dir,1); - } - - /* If there is a directory with the same name as the AppImage plus ".config", then export $XDG_CONFIG_HOME */ - strcpy (portable_config_dir, basepath); - strcat (portable_config_dir, ".config"); - if(is_writable_directory(portable_config_dir)){ - fprintf(stderr, "Setting $XDG_CONFIG_HOME to %s\n", portable_config_dir); - setenv("XDG_CONFIG_HOME",portable_config_dir,1); - } -} - -int main(int argc, char *argv[]) { - char appimage_path[PATH_MAX]; - char argv0_path[PATH_MAX]; - char * arg; - - /* We might want to operate on a target appimage rather than this file itself, - * e.g., for appimaged which must not run untrusted code from random AppImages. - * This variable is intended for use by e.g., appimaged and is subject to - * change any time. Do not rely on it being present. We might even limit this - * functionality specifically for builds used by appimaged. - */ - if (getenv("TARGET_APPIMAGE") == NULL) { - strcpy(appimage_path, "/proc/self/exe"); - strcpy(argv0_path, argv[0]); - } else { - strcpy(appimage_path, getenv("TARGET_APPIMAGE")); - strcpy(argv0_path, getenv("TARGET_APPIMAGE")); - -#ifdef ENABLE_SETPROCTITLE - // load libbsd dynamically to change proc title - // this is an optional feature, therefore we don't hard require it - void* libbsd = dlopen("libbsd.so", RTLD_NOW); - - if (libbsd != NULL) { - // clear error state - dlerror(); - - // try to load the two required symbols - void (*setproctitle_init)(int, char**, char**) = dlsym(libbsd, "setproctitle_init"); - - char* error; - - if ((error = dlerror()) == NULL) { - void (*setproctitle)(const char*, char*) = dlsym(libbsd, "setproctitle"); - - if (dlerror() == NULL) { - char buffer[1024]; - strcpy(buffer, getenv("TARGET_APPIMAGE")); - for (int i = 1; i < argc; i++) { - strcat(buffer, " "); - strcat(buffer, argv[i]); - } - - (*setproctitle_init)(argc, argv, environ); - (*setproctitle)("%s", buffer); - } - } - - dlclose(libbsd); - } -#endif - } - - // temporary directories are required in a few places - // therefore we implement the detection of the temp base dir at the top of the code to avoid redundancy - char temp_base[PATH_MAX] = P_tmpdir; - - { - const char* const TMPDIR = getenv("TMPDIR"); - if (TMPDIR != NULL) - strcpy(temp_base, getenv("TMPDIR")); - } - - fs_offset = appimage_get_elf_size(appimage_path); - - // error check - if (fs_offset < 0) { - fprintf(stderr, "Failed to get fs offset for %s\n", appimage_path); - exit(EXIT_EXECERROR); - } - - arg=getArg(argc,argv,'-'); - - /* Print the help and then exit */ - if(arg && strcmp(arg,"appimage-help")==0) { - char fullpath[PATH_MAX]; - - ssize_t length = readlink(appimage_path, fullpath, sizeof(fullpath)); - if (length < 0) { - fprintf(stderr, "Error getting realpath for %s\n", appimage_path); - exit(EXIT_EXECERROR); - } - fullpath[length] = '\0'; - - print_help(fullpath); - exit(0); - } - - /* Just print the offset and then exit */ - if(arg && strcmp(arg,"appimage-offset")==0) { - printf("%lu\n", fs_offset); - exit(0); - } - - arg=getArg(argc,argv,'-'); - - /* extract the AppImage */ - if(arg && strcmp(arg,"appimage-extract")==0) { - char* pattern; - - // default use case: use standard prefix - if (argc == 2) { - pattern = NULL; - } else if (argc == 3) { - pattern = argv[2]; - } else { - fprintf(stderr, "Unexpected argument count: %d\n", argc - 1); - fprintf(stderr, "Usage: %s --appimage-extract []\n", argv0_path); - exit(1); - } - - if (!extract_appimage(appimage_path, "squashfs-root/", pattern, true, true)) { - exit(1); - } - - exit(0); - } - - // calculate full path of AppImage - int length; - char fullpath[PATH_MAX]; - - if(getenv("TARGET_APPIMAGE") == NULL) { - // If we are operating on this file itself - ssize_t len = readlink(appimage_path, fullpath, sizeof(fullpath)); - if (len < 0) { - perror("Failed to obtain absolute path"); - exit(EXIT_EXECERROR); - } - fullpath[len] = '\0'; - } else { - char* abspath = realpath(appimage_path, NULL); - if (abspath == NULL) { - perror("Failed to obtain absolute path"); - exit(EXIT_EXECERROR); - } - strcpy(fullpath, abspath); - free(abspath); - } - - if (getenv("APPIMAGE_EXTRACT_AND_RUN") != NULL || (arg && strcmp(arg, "appimage-extract-and-run") == 0)) { - char* hexlified_digest = NULL; - - // calculate MD5 hash of file, and use it to make extracted directory name "content-aware" - // see https://github.com/AppImage/AppImageKit/issues/841 for more information - { - FILE* f = fopen(appimage_path, "rb"); - if (f == NULL) { - perror("Failed to open AppImage file"); - exit(EXIT_EXECERROR); - } - - Md5Context ctx; - Md5Initialise(&ctx); - - char buf[4096]; - for (size_t bytes_read; (bytes_read = fread(buf, sizeof(char), sizeof(buf), f)); bytes_read > 0) { - Md5Update(&ctx, buf, (uint32_t) bytes_read); - } - - MD5_HASH digest; - Md5Finalise(&ctx, &digest); - - hexlified_digest = appimage_hexlify(digest.bytes, sizeof(digest.bytes)); - } - - char* prefix = malloc(strlen(temp_base) + 20 + strlen(hexlified_digest) + 2); - strcpy(prefix, temp_base); - strcat(prefix, "/appimage_extracted_"); - strcat(prefix, hexlified_digest); - free(hexlified_digest); - - const bool verbose = (getenv("VERBOSE") != NULL); - - if (!extract_appimage(appimage_path, prefix, NULL, false, verbose)) { - fprintf(stderr, "Failed to extract AppImage\n"); - exit(EXIT_EXECERROR); - } - - int pid; - if ((pid = fork()) == -1) { - int error = errno; - fprintf(stderr, "fork() failed: %s\n", strerror(error)); - exit(EXIT_EXECERROR); - } else if (pid == 0) { - const char apprun_fname[] = "AppRun"; - char* apprun_path = malloc(strlen(prefix) + 1 + strlen(apprun_fname) + 1); - strcpy(apprun_path, prefix); - strcat(apprun_path, "/"); - strcat(apprun_path, apprun_fname); - - // create copy of argument list without the --appimage-extract-and-run parameter - char* new_argv[argc]; - int new_argc = 0; - new_argv[new_argc++] = strdup(apprun_path); - for (int i = 1; i < argc; ++i) { - if (strcmp(argv[i], "--appimage-extract-and-run") != 0) { - new_argv[new_argc++] = strdup(argv[i]); - } - } - new_argv[new_argc] = NULL; - - /* Setting some environment variables that the app "inside" might use */ - setenv("APPIMAGE", fullpath, 1); - setenv("ARGV0", argv0_path, 1); - setenv("APPDIR", prefix, 1); - - set_portable_home_and_config(fullpath); - - execv(apprun_path, new_argv); - - int error = errno; - fprintf(stderr, "Failed to run %s: %s\n", apprun_path, strerror(error)); - - free(apprun_path); - exit(EXIT_EXECERROR); - } - - int status = 0; - int rv = waitpid(pid, &status, 0); - status = rv > 0 && WIFEXITED (status) ? WEXITSTATUS (status) : EXIT_EXECERROR; - - if (getenv("NO_CLEANUP") == NULL) { - if (!rm_recursive(prefix)) { - fprintf(stderr, "Failed to clean up cache directory\n"); - if (status == 0) /* avoid messing existing failure exit status */ - status = EXIT_EXECERROR; - } - } - - // template == prefix, must be freed only once - free(prefix); - - exit(status); - } - - if(arg && strcmp(arg,"appimage-version")==0) { - fprintf(stderr,"Version: %s\n", GIT_COMMIT); - exit(0); - } - - if(arg && (strcmp(arg,"appimage-updateinformation")==0 || strcmp(arg,"appimage-updateinfo")==0)) { - unsigned long offset = 0; - unsigned long length = 0; - appimage_get_elf_section_offset_and_length(appimage_path, ".upd_info", &offset, &length); - // fprintf(stderr, "offset: %lu\n", offset); - // fprintf(stderr, "length: %lu\n", length); - // print_hex(appimage_path, offset, length); - appimage_print_binary(appimage_path, offset, length); - exit(0); - } - - if(arg && strcmp(arg,"appimage-signature")==0) { - unsigned long offset = 0; - unsigned long length = 0; - appimage_get_elf_section_offset_and_length(appimage_path, ".sha256_sig", &offset, &length); - // fprintf(stderr, "offset: %lu\n", offset); - // fprintf(stderr, "length: %lu\n", length); - // print_hex(appimage_path, offset, length); - appimage_print_binary(appimage_path, offset, length); - exit(0); - } - - portable_option(arg, appimage_path, "home"); - portable_option(arg, appimage_path, "config"); - - // If there is an argument starting with appimage- (but not appimage-mount which is handled further down) - // then stop here and print an error message - if((arg && strncmp(arg, "appimage-", 8) == 0) && (arg && strcmp(arg,"appimage-mount")!=0)) { - fprintf(stderr,"--%s is not yet implemented in version %s\n", arg, GIT_COMMIT); - exit(1); - } - - LOAD_LIBRARY; /* exit if libfuse is missing */ - - int dir_fd, res; - - size_t templen = strlen(temp_base); - - // allocate enough memory (size of name won't exceed 60 bytes) - char mount_dir[templen + 60]; - - build_mount_point(mount_dir, argv[0], temp_base, templen); - - size_t mount_dir_size = strlen(mount_dir); - pid_t pid; - char **real_argv; - int i; - - if (mkdtemp(mount_dir) == NULL) { - perror ("create mount dir error"); - exit (EXIT_EXECERROR); - } - - if (pipe (keepalive_pipe) == -1) { - perror ("pipe error"); - exit (EXIT_EXECERROR); - } - - pid = fork (); - if (pid == -1) { - perror ("fork error"); - exit (EXIT_EXECERROR); - } - - if (pid == 0) { - /* in child */ - - char *child_argv[5]; - - /* close read pipe */ - close (keepalive_pipe[0]); - - char *dir = realpath(appimage_path, NULL ); - - char options[100]; - sprintf(options, "ro,offset=%lu", fs_offset); - - child_argv[0] = dir; - child_argv[1] = "-o"; - child_argv[2] = options; - child_argv[3] = dir; - child_argv[4] = mount_dir; - - if(0 != fusefs_main (5, child_argv, fuse_mounted)){ - char *title; - char *body; - title = "Cannot mount AppImage, please check your FUSE setup."; - body = "You might still be able to extract the contents of this AppImage \n" - "if you run it with the --appimage-extract option. \n" - "See https://github.com/AppImage/AppImageKit/wiki/FUSE \n" - "for more information"; - notify(title, body, 0); // 3 seconds timeout - }; - } else { - /* in parent, child is $pid */ - int c; - - /* close write pipe */ - close (keepalive_pipe[1]); - - /* Pause until mounted */ - read (keepalive_pipe[0], &c, 1); - - /* Fuse process has now daemonized, reap our child */ - waitpid(pid, NULL, 0); - - dir_fd = open (mount_dir, O_RDONLY); - if (dir_fd == -1) { - perror ("open dir error"); - exit (EXIT_EXECERROR); - } - - res = dup2 (dir_fd, 1023); - if (res == -1) { - perror ("dup2 error"); - exit (EXIT_EXECERROR); - } - close (dir_fd); - - real_argv = malloc (sizeof (char *) * (argc + 1)); - for (i = 0; i < argc; i++) { - real_argv[i] = argv[i]; - } - real_argv[i] = NULL; - - if(arg && strcmp(arg, "appimage-mount") == 0) { - char real_mount_dir[PATH_MAX]; - - if (realpath(mount_dir, real_mount_dir) == real_mount_dir) { - printf("%s\n", real_mount_dir); - } else { - printf("%s\n", mount_dir); - } - - // stdout is, by default, buffered (unlike stderr), therefore in order to allow other processes to read - // the path from stdout, we need to flush the buffers now - // this is a less-invasive alternative to setbuf(stdout, NULL); - fflush(stdout); - - for (;;) pause(); - - exit(0); - } - - /* Setting some environment variables that the app "inside" might use */ - setenv( "APPIMAGE", fullpath, 1 ); - setenv( "ARGV0", argv0_path, 1 ); - setenv( "APPDIR", mount_dir, 1 ); - - set_portable_home_and_config(fullpath); - - /* Original working directory */ - char cwd[1024]; - if (getcwd(cwd, sizeof(cwd)) != NULL) { - setenv( "OWD", cwd, 1 ); - } - - char filename[mount_dir_size + 8]; /* enough for mount_dir + "/AppRun" */ - strcpy (filename, mount_dir); - strcat (filename, "/AppRun"); - - /* TODO: Find a way to get the exit status and/or output of this */ - execv (filename, real_argv); - /* Error if we continue here */ - perror("execv error"); - exit(EXIT_EXECERROR); - } - - return 0; -} diff --git a/src/validate.c b/src/validate.c deleted file mode 100644 index 7e8ce30c6..000000000 --- a/src/validate.c +++ /dev/null @@ -1,204 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "appimage/appimage.h" -#include "appimage/appimage_shared.h" -#include "light_elf.h" - -typedef unsigned char byte; - -char segment_name[] = ".sha256_sig"; -char segment_key_name[] = ".sig_key"; - -int sha256_file(char *path, char outputBuffer[65], int skip_offset, int skip_length) -{ - FILE *file = fopen(path, "rb"); - if(!file) return(1); - byte hash[SHA256_DIGEST_LENGTH]; - SHA256_CTX sha256; - SHA256_Init(&sha256); - const int bufSize = 1024*1024; - byte *buffer = malloc(bufSize); - int bytesRead = 0; - if(!buffer) { - fclose(file); - return ENOMEM; - } - - int totalBytesRead = 0; - if(skip_offset <= bufSize){ - bytesRead = fread(buffer, 1, skip_offset, file); - totalBytesRead += bytesRead; - // printf("totalBytesRead: %i\n", totalBytesRead); - // printf("bytesRead: %i\n", bytesRead); - SHA256_Update(&sha256, buffer, bytesRead); - } else { - int stillToRead = skip_offset-bytesRead; - // printf("Initial stillToRead: %i\n", stillToRead); - int readThisTime; - - if(stillToRead>bufSize){ - readThisTime = bufSize; - } else { - readThisTime = stillToRead; - } - while((bytesRead = fread(buffer, 1, readThisTime, file))) - { - totalBytesRead += bytesRead; - // printf("totalBytesRead: %i\n", totalBytesRead); - // printf("readThisTime: %i\n", readThisTime); - // printf("bytesRead: %i\n", bytesRead); - SHA256_Update(&sha256, buffer, bytesRead); - stillToRead = skip_offset-totalBytesRead; - // printf("stillToRead: %i\n", stillToRead); - - if(stillToRead>bufSize){ - readThisTime = bufSize; - } else { - readThisTime = stillToRead; - } - } - } - - fseek(file, skip_offset+skip_length, SEEK_SET); - - /* Instead of the skipped area, calculate the sha256 of the same amount if 0x00s */ - int i = 0; - for(i = 0; i < skip_length; i++) { - SHA256_Update(&sha256, "\0", 1); - totalBytesRead += 1; - } - - while((bytesRead = fread(buffer, 1, bufSize, file))) - { - totalBytesRead += bytesRead; - // printf("totalBytesRead: %i\n", totalBytesRead); - // printf("bytesRead: %i\n", bytesRead); - SHA256_Update(&sha256, buffer, bytesRead); - } - SHA256_Final(hash, &sha256); - - // fprintf(stderr, "totalBytesRead: %i\n", totalBytesRead); - - for(i = 0; i < SHA256_DIGEST_LENGTH; i++) - { - sprintf(outputBuffer + (i * 2), "%02x", hash[i]); - } - outputBuffer[64] = 0; - - fclose(file); - - return 0; -} - -int main(int argc,char **argv) { - if(argc < 2){ - fprintf(stderr, "Usage: %s Signed.AppImage\n", argv[0]); - exit(1); - } - - char *filename = argv[1]; - - unsigned long skip_offset_sig = 0; - unsigned long skip_length_sig = 0; - - unsigned long skip_offset_key = 0; - unsigned long skip_length_key = 0; - - if (!appimage_get_elf_section_offset_and_length(filename, ".sha256_sig", &skip_offset_sig, &skip_length_sig)) { - fprintf(stderr, "Failed to read .sha256_sig section"); - exit(1); - } - if (!appimage_get_elf_section_offset_and_length(filename, ".sig_key", &skip_offset_key, &skip_length_key)) { - skip_length_key = 0; - skip_offset_key = 0; - } - - if(skip_length_sig > 0) { - fprintf(stderr, "Skipping ELF section %s with offset %lu, length %lu\n", segment_name, skip_offset_sig, skip_length_sig); - } else { - fprintf(stderr, "ELF section %s not found, is the file signed?\n", segment_name); - exit(1); - } - if(skip_length_key > 0) { - fprintf(stderr, "Skipping ELF section %s with offset %lu, length %lu\n", segment_key_name, skip_offset_key, skip_length_key); - } else { - fprintf(stderr, "ELF section %s not found, assuming older AppImage Standard\n", segment_key_name); - } - if(skip_offset_sig + skip_length_sig != skip_offset_key && skip_length_key != 0) { - fprintf(stderr, "validate only works when .sha256_sig and .sig_key are contiguous in the ELF header\n"); - exit(0); - } - int skip_offset = skip_offset_sig; - int skip_length = skip_length_sig + skip_length_key; - - char *digestfile; - digestfile = g_strconcat("/tmp/", basename(g_strconcat(filename, ".digest", NULL)), NULL); - char *signaturefile; - signaturefile = g_strconcat("/tmp/", basename(g_strconcat(filename, ".sig", NULL)), NULL); - - uint8_t *data = malloc(skip_length_sig); - unsigned long k; - FILE* fd = fopen(filename, "r"); - fseek(fd, skip_offset_sig, SEEK_SET); - fread(data, skip_length_sig, sizeof(uint8_t), fd); - fclose(fd); - FILE *fpdst2 = fopen(signaturefile, "w"); - if (fpdst2 == NULL) { - fprintf(stderr, "Not able to open the signature file for writing, aborting"); - exit(1); - } - for (k = 0; k < skip_length_sig; k++) { - fprintf(fpdst2, "%c", data[k]); - } - fclose(fpdst2); - free(data); - - struct stat st; - stat(filename, &st); - int size = st.st_size; - if(size < skip_offset+skip_length){ - fprintf(stderr, "offset+length cannot be less than the file size\n"); - exit(1); - } - - static char buffer[65]; - sha256_file(filename, buffer, skip_offset, skip_length); - printf("%s\n", buffer); - - - FILE *f = fopen(digestfile, "w"); - if (f == NULL){ - printf("Error opening digestfile\n"); - exit(1); - } - fprintf(f, "%s", buffer); - fclose(f); - if (! g_file_test(digestfile, G_FILE_TEST_IS_REGULAR)) { - printf("Error writing digestfile\n"); - exit(1); - } - - char command[1024]; - gchar *gpg2_path = g_find_program_in_path ("gpg2"); - sprintf (command, "%s --verify %s %s", gpg2_path, signaturefile, digestfile); - fprintf (stderr, "%s\n", command); - FILE *fp = popen(command, "r"); - if (fp == NULL) - fprintf(stderr, "gpg2 command did not succeed"); - int exitcode = WEXITSTATUS(pclose(fp)); - unlink(digestfile); - unlink(signaturefile); - return exitcode; -} diff --git a/testappimage b/testappimage deleted file mode 100644 index 958bae546..000000000 --- a/testappimage +++ /dev/null @@ -1,205 +0,0 @@ -#!/bin/bash - -# -# Test an AppDir or AppImage on a given ISO or squashfs or ext3 base system -# TODO: -# - Make compatible with type 2 AppImages (currently we have to first mount them by hand) -# - Check https://github.com/FGrose/livecd-tools/blob/liveimage-mount/tools/liveimage-mount -# - -set -e -# set -x - -xhost + # Workaround for: QXcbConnection: Could not connect to display :0 - -HERE=$(dirname $(readlink -f "${0}")) -export PATH=$HERE:$HERE/usr/bin:$PATH - -if [ "$1x" == "x" ] ; then - echo "Please specify a ISO or squashfs base system to run the AppImage on" - exit 1 -fi - -if [ "$2x" == "x" ] ; then - echo "Please specify an AppDir or AppImage outside the ISO or command inside the ISO to be run" - exit 1 -fi - -export PREF=$RANDOM - -mkdir -p /tmp/$PREF/unionfs/ro -mkdir -p /tmp/$PREF/unionfs/root -mkdir -p /tmp/$PREF/unionfs/rw -mkdir -p /tmp/$PREF/union -mkdir -p /tmp/$PREF/iso -mkdir -p /tmp/$PREF/workdir - -# openSUSE LEAP 42.2 does not have a tmpfs in /tmp but we need this -mount | grep -q "/tmp type tmpfs" || sudo mount -t tmpfs tmpfs /tmp/ - -# If ISO was specified, then mount it and find contained filesystem -THEFS="$1" -if [ ${1: -4} == ".iso" ] ; then - ISO="$1" - mount -o loop,ro "$ISO" /tmp/$PREF/iso - # If there is a squashfs file named $ISO.buildsquash then we overlay- - # mount this as well. This can significantly speed up subsequent builds - # because dependencies can be installed there. The squashfs file can be - # generated by squashing the unionfs/rw directory. - if [ -e $ISO.buildsquash ] ; then - mount -o loop,ro "$ISO.buildsquash" /tmp/$PREF/unionfs/ro - fi -fi - -# If sfs was provided, then assume it contains a rootfs use just that -THEFS="$1" -if [ ${1: -4} == ".sfs" ] ; then - ISO="$1" - mount -o loop,ro "$ISO" /tmp/$PREF/unionfs/root -fi - -# If ext3 was provided, then assume it contains a rootfs use just that -THEFS="$1" -if [ ${1: -4} == "ext3" ] ; then - ISO="$1" - mount -o loop,ro "$ISO" /tmp/$PREF/unionfs/root -fi - -echo "" -echo "====================================================" -echo "" -echo $ISO - -# In case of Ubuntu-like ISOs -if [ -e /tmp/$PREF/iso/casper/filesystem.squashfs ] ; then - THEFS=/tmp/$PREF/iso/casper/filesystem.squashfs - mount "$THEFS" /tmp/$PREF/unionfs/root -o loop,ro || exit 1 -fi - -# In case of Fedora-like ISOs -if [ -e /tmp/$PREF/iso/LiveOS/squashfs.img ] ; then - mount -o loop,ro /tmp/$PREF/iso/LiveOS/squashfs.img /tmp/$PREF/iso/ - if [ -e /tmp/$PREF/iso/LiveOS/ext3fs.img ] ; then - # F23 and below use https://github.com/rhinstaller/livecd-tools - THEFS=/tmp/$PREF/iso/LiveOS/ext3fs.img || exit 1 - fi - if [ -e /tmp/$PREF/iso/LiveOS/rootfs.img ] ; then - # F24 and above use https://github.com/rhinstaller/lorax and livemedia-creator - THEFS=/tmp/$PREF/iso/LiveOS/rootfs.img || exit 1 - fi - mount "$THEFS" /tmp/$PREF/unionfs/root -o loop,ro || exit 1 -fi - -# In case of debian-like ISOs -if [ -e /tmp/$PREF/iso/live/filesystem.squashfs ] ; then - THEFS=/tmp/$PREF/iso/live/filesystem.squashfs - mount "$THEFS" /tmp/$PREF/unionfs/root -o loop,ro || exit 1 -fi - -# In case of openSUSE-like ISOs -if [ -e /tmp/$PREF/iso/*-read-only.* ] ; then - THEFS=$(ls /tmp/$PREF/iso/*-read-only.* | head -n 1) - mount "$THEFS" /tmp/$PREF/unionfs/root -o loop,ro || exit 1 -fi - -# In case of puppy-like ISOs -if [ -e /tmp/$PREF/iso/puppy_*.sfs ] ; then - THEFS=$(ls /tmp/$PREF/iso/puppy_*.sfs | head -n 1) - mount "$THEFS" /tmp/$PREF/unionfs/root -o loop,ro || exit 1 -fi - -trap atexit EXIT - -atexit() -{ set +e - umount -l /tmp/$PREF/union/var/lib/dbus 2>/dev/null - umount -l /tmp/$PREF/union/etc/resolv.conf 2>/dev/null - umount -l /tmp/$PREF/union/proc 2>/dev/null - umount -l /tmp/$PREF/union/dev 2>/dev/null - umount -l /tmp/$PREF/union/mnt 2>/dev/null - umount -l /tmp/$PREF/union 2>/dev/null - umount -l /tmp/$PREF/unionfs/ro 2>/dev/null - umount -l /tmp/$PREF/unionfs/root 2>/dev/null - umount -l /tmp/$PREF/iso 2>/dev/null - umount -l /tmp/$PREF/iso 2>/dev/null - umount -l /tmp/$PREF/iso 2>/dev/null - rm -r /tmp/$PREF/workdir - rm -r /tmp/$PREF/unionfs/root - rm -r /tmp/$PREF/unionfs/rw - rm -r /tmp/$PREF/unionfs/ro - rm -r /tmp/$PREF/unionfs - rm -r /tmp/$PREF/union - rm -r /tmp/$PREF/iso - rm -r /tmp/$PREF/ -} - -# Kernel 4.0 or newer required -kernel_major=$(uname -r | cut -d . -f 1) -if [ ! $kernel_major -ge 4 ] ; then - echo "Falling back to unionfs-fuse because kernel is not 4.x or newer" - echo "This can potentially be unreliable" - unionfs-fuse -o allow_other,use_ino,suid,dev,nonempty -ocow,chroot=/tmp/$PREF/unionfs/,max_files=32768 /rw=RW:/ro=RO:/root=RO /tmp/$PREF/union -else - echo "Using OverlayFS because kernel is 4.x or newer" - sudo mount -t overlay -o lowerdir=/tmp/$PREF/unionfs/ro:/tmp/$PREF/unionfs/root,upperdir=/tmp/$PREF/unionfs/rw,workdir=/tmp/$PREF/workdir none /tmp/$PREF/union -fi - -ls /tmp/$PREF/union/mnt >/dev/null && MNT=/mnt -# ls /tmp/$PREF/union/automake >/dev/null && MNT=/automake || echo "" # Puppy - -if [ "x$MNT" == "x" ] ; then - echo "Could not find free mountpoint" - exit 1 -fi -if [ -f "$2" ] ; then - mount "$2" /tmp/$PREF/union/$MNT -o loop,ro -elif [ -d "$2" ] ; then - mount "$2" /tmp/$PREF/union/$MNT -o bind -else - shift - export RUN_COMMAND=$1 - export RUN_INSIDE=$@ -fi - -cat > /tmp/$PREF/union/run.sh < '/etc/pango/pango.modules' 2>/dev/null # otherwise only squares instead of text -[ -f /si-chroot ] && ln -s /lib/ld-lsb.so.3 /lib/ld-linux.so.2 -# LD_LIBRARY_PATH=$MNT/usr/lib:$MNT/usr/lib32:$MNT/usr/lib64:$MNT/lib/:$LD_LIBRARY_PATH ldd $MNT/usr/bin/* $MNT/usr/lib/* 2>/dev/null | grep "not found" | sort | uniq -export HOME="/root" -export LANG="en_EN.UTF-8" -# export QT_PLUGIN_PATH=./lib/qt4/plugins ###################### !!! -#dbus-launch $MNT/AppRun || -export LIBGL_DEBUG=verbose -export QT_DEBUG_PLUGINS=1 -export LC_ALL=C.UTF-8 -mkdir -p /usr/share/appimagekit -touch /usr/share/appimagekit/no_desktopintegration -dbus-uuidgen --ensure ; dbus-launch # Needed for CentOS 6.7 to launch apps that talk to dbus -if [ -f $MNT/usr/lib/qt5/plugins/platforms/libqxcb.so ] ; then - export LD_LIBRARY_PATH=$MNT/usr/lib/:$LD_LIBRARY_PATH - ##ldd $MNT/usr/lib/qt5/plugins/platforms/libqxcb.so | grep not -fi -##find $MNT/usr/lib -type f -exec sh -c 'ldd {} | grep "not found"' 2>/dev/null \; -if [ $(which $RUN_COMMAND) ] ; then - exec $RUN_INSIDE -else - $MNT/AppRun && echo "+++++++++ SUCCESS $ISO $2 +++++++++" -fi -EOF -chmod a+x /tmp/$PREF/union/run.sh -mount -t proc proc /tmp/$PREF/union/proc -mkdir -p /tmp/$PREF/union/var/lib/dbus -mount --bind /dev /tmp/$PREF/union/dev -mount --bind /var/lib/dbus /tmp/$PREF/union/var/lib/dbus -touch /tmp/$PREF/union/etc/resolv.conf || echo "" -mount --bind /etc/resolv.conf /tmp/$PREF/union/etc/resolv.conf -xhost local: >/dev/null 2>&1 # otherwise "cannot open display: :0.0" -echo "" -chroot /tmp/$PREF/union/ /run.sh # $MNT/AppRun -echo "" -exit $? From 2c7c9ccf699c4cb8b7fdba8caed554a087022d82 Mon Sep 17 00:00:00 2001 From: probonopd Date: Thu, 28 Nov 2024 15:29:44 +0100 Subject: [PATCH 2/7] Remove outdated information --- README.md | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 39c797355..ad76d59b2 100644 --- a/README.md +++ b/README.md @@ -9,8 +9,6 @@ Copyright (c) 2004-24 Simon Peter and contributors. https://en.wikipedia.org/wiki/AppImage -__AppImageKit__ is a concrete implementation of the AppImage format, especially the tiny runtime that becomes part of each AppImage. - Providing an [AppImage](http://appimage.org/) for distributing application has, among others, these advantages: - Applications packaged as an AppImage can run on many distributions (including Ubuntu, Fedora, openSUSE, CentOS, elementaryOS, Linux Mint, and others) - One app = one file = super simple for users: just download one AppImage file, [make it executable](http://discourse.appimage.org/t/how-to-make-an-appimage-executable/80), and run @@ -26,7 +24,7 @@ Providing an [AppImage](http://appimage.org/) for distributing application has, - Can be listed in the [AppImageHub](https://appimage.github.io/apps) central directory of available AppImages - Can double as a self-extracting compressed archive with the `--appimage-extract` parameter -[Here is an overview](https://appimage.github.io/apps) of projects that are already distributing upstream-provided, official AppImages. +[Here is an overview](https://appimage.github.io/apps) of projects that are distributing AppImages. If you have questions, AppImage developers are on #AppImage on irc.libera.chat. @@ -84,7 +82,7 @@ AppImage to the rescue! ## AppImage usage -Running an AppImage mounts the filesystem image and transparently runs the contained application. So the usage of an AppImage normally should equal the usage of the application contained in it. However, there is special functionality, as described here. If an AppImage you have received does not support these options, ask the author of the AppImage to recreate it using the latest `appimagetool` (or `linuxdeployqt`). +Running an AppImage mounts the filesystem image and transparently runs the contained application. So the usage of an AppImage normally should equal the usage of the application contained in it. However, there is special functionality, as described here. If an AppImage you have received does not support these options, ask the author of the AppImage to recreate it using the latest tooling). ### Command line arguments @@ -109,7 +107,7 @@ Example: Imagine you want to use the Leafpad text editor, but carry its settings ```bash # Download Leafpad AppImage and make it executable -wget -c "https://bintray.com/probono/AppImages/download_file?file_path=Leafpad-0.8.18.1.glibc2.4-x86_64.AppImage" -O Leafpad-0.8.18.1.glibc2.4-x86_64.AppImage +Leafpad-0.8.18.1.glibc2.4-x86_64.AppImage chmod a+x Leafpad-0.8.18.1.glibc2.4-x86_64.AppImage # Create a directory with the same name as the AppImage plus the ".config" extension From 1f7981d8bae239b7da196d4712080c774928b2b0 Mon Sep 17 00:00:00 2001 From: probonopd Date: Thu, 28 Nov 2024 15:31:07 +0100 Subject: [PATCH 3/7] Update appimaged URL --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ad76d59b2..a5389ef7d 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ Providing an [AppImage](http://appimage.org/) for distributing application has, - No root needed - No system libraries changed - Works out of the box, no installation of runtimes needed -- Optional desktop integration with [appimaged](https://github.com/AppImage/appimaged) +- Optional desktop integration with [appimaged](https://github.com/probonopd/go-appimage/tree/master/src/appimaged#appimaged) - Optional binary delta updates, e.g., for continuous builds (only download the binary diff) using AppImageUpdate - Can optionally GPG2-sign your AppImages (inside the file) - Works on Live ISOs From a476e9d28a5e55805b7c14dae084d84d8ada0daa Mon Sep 17 00:00:00 2001 From: probonopd Date: Thu, 28 Nov 2024 15:35:13 +0100 Subject: [PATCH 4/7] Remove section "Motivation" --- README.md | 54 +----------------------------------------------------- 1 file changed, 1 insertion(+), 53 deletions(-) diff --git a/README.md b/README.md index a5389ef7d..6adfc803d 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ Copyright (c) 2004-24 Simon Peter and contributors. https://en.wikipedia.org/wiki/AppImage Providing an [AppImage](http://appimage.org/) for distributing application has, among others, these advantages: -- Applications packaged as an AppImage can run on many distributions (including Ubuntu, Fedora, openSUSE, CentOS, elementaryOS, Linux Mint, and others) +- Applications packaged as an AppImage can run on many distributions (including Debian, Ubuntu, Fedora, openSUSE, Linux Mint, and others) - One app = one file = super simple for users: just download one AppImage file, [make it executable](http://discourse.appimage.org/t/how-to-make-an-appimage-executable/80), and run - No unpacking or installation necessary - No root needed @@ -28,58 +28,6 @@ Providing an [AppImage](http://appimage.org/) for distributing application has, If you have questions, AppImage developers are on #AppImage on irc.libera.chat. -## Motivation - -Linus addresses some core issues of Linux on the desktop in his [DebConf 14_ QA with Linus Torvalds talk](https://www.youtube.com/watch?v=5PmHRSeA2c8). At 05:40 Linus highlights application packaging: - -> I'm talking about actual application writers that want to make a package of their application for Linux. And I've seen this firsthand with the other project I've been involved with, which is my divelog application. - -Obviously Linus is talking about [Subsurface](https://subsurface-divelog.org). - -> We make binaries for Windows and OS X. - -Both bundle not only the application itself, but also the required Qt libraries that the application needs to run. Also included are dependency libraries like `libssh2.1.dylib`and `libzip.2.dylib`. - -> We basically don't make binaries for Linux. Why? Because binaries for Linux desktop applications is a major f*ing pain in the ass. Right. You don't make binaries for Linux. You make binaries for Fedora 19, Fedora 20, maybe there's even like RHEL 5 from ten years ago, you make binaries for debian stable. - -So why not use the same approach as on Windows and OS X, namely, treat the base operating system as a _platform_ on top of which we run the application we care about. This means that we have to bundle the application with all their dependencies that are _not_ part of the base operating system. Welcome [application bundles](https://blogs.gnome.org/tvb/2013/12/10/application-bundles-for-glade/). - -> Or actually you don't make binaries for debian stable because debian stable has libraries that are so old that anything that was built in the last century doesn't work. But you might make binaries for debian... whatever the codename is for unstable. And even that is a major pain because (...) debian has those rules that you are supposed to use shared libraries. Right. - -This is why binaries going into an AppImage should be built against the oldest still-supported LTS or Enterprise distributions. - -> And if you don't use shared libraries, getting your package in, like, is just painful. - -"Getting your package in" means that the distribution accepts the package as part of the base operating system. For an application, that might not be desired at all. As long as we can package the application in a way that it seamlessly runs on top of the base operating system. - -> But using shared libraries is not an option when the libraries are experimental and the libraries are used by two people and one of them is crazy, so every other day some ABI breaks. - -One simple way to achieve this is to bundle private copies of the libraries in question with the application that uses them. Preferably in a way that does not interfere with anything else that is running on the base operating system. Note that this does not have to be true for all libraries; core libraries that are matured, have stable interfaces and can reasonably expected to be present in all distributions do not necessarily have to be bundled with the application. - -> So you actually want to just compile one binary and have it work. Preferably forever. And preferably across all Linux distributions. - -That is actually possible, as long as you stay away from any distribution-specific packaging, and as long as you do not use a too recent build system. The same will probably be true for Windows and OS X - if you compile on OS X 10.11 then I would not expect the resulting build products to run on OS X 10.5. - -> And I actually think distributions have done a horribly, horribly bad job. - -Distributions are all about building the base operating system. But I don't think distributions are a good way to get applications. Rather, I would prefer to get the latest versions of applications directly from the people who write them. And this is already a reality for software like Google Chrome, Eclipse, Arduino and other applications. Who uses the (mostly outdated and changed) versions that are part of the distributions? Probably most people don't. - -> One of the things that I do on the kernel - and I have to fight this every single release and I think it's sad - we have one rule in the kernel, one rule: we don't break userspace. (...) People break userspace, I get really, really angry. (...) - -Excellent. Thank you for this policy! This is why I can still run the Mosaic browser from over a decade ago on modern Linux-based operating systems. (I tried and it works.) - -> And then all the distributions come in and they screw it all up. Because they break binary compatibility left and right. - -Luckily, binaries built on older distributions tend to still work on newer distributions. At least that has been my experience over the last decade with building application bundles using AppImageKit, and before that, klik. - -> They update glibc and everything breaks. (...) - -There is a [way around this](https://blogs.gnome.org/tvb/2013/12/14/application-bundles-revisited/), although not many people actually care to use the workaround (yet). - -> So that's my rant. And that's what I really fundamentally think needs to change for Linux to work on the desktop because you can't have applications writers to do fifteen billion different versions. - -AppImage to the rescue! - ## AppImage usage Running an AppImage mounts the filesystem image and transparently runs the contained application. So the usage of an AppImage normally should equal the usage of the application contained in it. However, there is special functionality, as described here. If an AppImage you have received does not support these options, ask the author of the AppImage to recreate it using the latest tooling). From faf0a1023eb3bb5506acb5b49a13e23cb01b9089 Mon Sep 17 00:00:00 2001 From: probonopd Date: Thu, 28 Nov 2024 15:36:20 +0100 Subject: [PATCH 5/7] Create motivation.md --- motivation.md | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 motivation.md diff --git a/motivation.md b/motivation.md new file mode 100644 index 000000000..c23946ece --- /dev/null +++ b/motivation.md @@ -0,0 +1,51 @@ +# Motivation + +Linus addresses some core issues of Linux on the desktop in his [DebConf 14_ QA with Linus Torvalds talk](https://www.youtube.com/watch?v=5PmHRSeA2c8). At 05:40 Linus highlights application packaging: + +> I'm talking about actual application writers that want to make a package of their application for Linux. And I've seen this firsthand with the other project I've been involved with, which is my divelog application. + +Obviously Linus is talking about [Subsurface](https://subsurface-divelog.org). + +> We make binaries for Windows and OS X. + +Both bundle not only the application itself, but also the required Qt libraries that the application needs to run. Also included are dependency libraries like `libssh2.1.dylib`and `libzip.2.dylib`. + +> We basically don't make binaries for Linux. Why? Because binaries for Linux desktop applications is a major f*ing pain in the ass. Right. You don't make binaries for Linux. You make binaries for Fedora 19, Fedora 20, maybe there's even like RHEL 5 from ten years ago, you make binaries for debian stable. + +So why not use the same approach as on Windows and OS X, namely, treat the base operating system as a _platform_ on top of which we run the application we care about. This means that we have to bundle the application with all their dependencies that are _not_ part of the base operating system. Welcome [application bundles](https://blogs.gnome.org/tvb/2013/12/10/application-bundles-for-glade/). + +> Or actually you don't make binaries for debian stable because debian stable has libraries that are so old that anything that was built in the last century doesn't work. But you might make binaries for debian... whatever the codename is for unstable. And even that is a major pain because (...) debian has those rules that you are supposed to use shared libraries. Right. + +This is why binaries going into an AppImage should be built against the oldest still-supported LTS or Enterprise distributions, or _all_ dependencies should be privately bundled in the AppImage. + +> And if you don't use shared libraries, getting your package in, like, is just painful. + +"Getting your package in" means that the distribution accepts the package as part of the base operating system. For an application, that might not be desired at all. As long as we can package the application in a way that it seamlessly runs on top of the base operating system. + +> But using shared libraries is not an option when the libraries are experimental and the libraries are used by two people and one of them is crazy, so every other day some ABI breaks. + +One simple way to achieve this is to bundle private copies of the libraries in question with the application that uses them. Preferably in a way that does not interfere with anything else that is running on the base operating system. Note that this does not have to be true for all libraries; core libraries that are matured, have stable interfaces and can reasonably expected to be present in all distributions do not necessarily have to be bundled with the application. + +> So you actually want to just compile one binary and have it work. Preferably forever. And preferably across all Linux distributions. + +That is actually possible, as long as you stay away from any distribution-specific packaging, and as long as you privately bundle all dependencies. + +> And I actually think distributions have done a horribly, horribly bad job. + +Distributions are all about building the base operating system. But I don't think distributions are a good way to get applications. Rather, I would prefer to get the latest versions of applications directly from the people who write them. And this is already a reality for software like Google Chrome, Eclipse, Arduino and other applications. Who uses the (mostly outdated and changed) versions that are part of the distributions? Probably most people don't. + +> One of the things that I do on the kernel - and I have to fight this every single release and I think it's sad - we have one rule in the kernel, one rule: we don't break userspace. (...) People break userspace, I get really, really angry. (...) + +Excellent. Thank you for this policy! This is why I can still run the Mosaic browser from over a decade ago on modern Linux-based operating systems. (I tried and it works.) + +> And then all the distributions come in and they screw it all up. Because they break binary compatibility left and right. + +Luckily, binaries built on older distributions tend to still work on newer distributions. At least that has been my experience over the last decade with building application bundles using AppImageKit, and before that, klik. + +> They update glibc and everything breaks. (...) + +There is a [way around this](https://blogs.gnome.org/tvb/2013/12/14/application-bundles-revisited/), although not many people actually care to use the workaround (yet). + +> So that's my rant. And that's what I really fundamentally think needs to change for Linux to work on the desktop because you can't have applications writers to do fifteen billion different versions. + +AppImage to the rescue! From db405d11816bb4aa7fe21ad186492f71e043c5be Mon Sep 17 00:00:00 2001 From: probonopd Date: Thu, 28 Nov 2024 15:36:54 +0100 Subject: [PATCH 6/7] Update README.md --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index 6adfc803d..7394bc752 100644 --- a/README.md +++ b/README.md @@ -55,7 +55,6 @@ Example: Imagine you want to use the Leafpad text editor, but carry its settings ```bash # Download Leafpad AppImage and make it executable -Leafpad-0.8.18.1.glibc2.4-x86_64.AppImage chmod a+x Leafpad-0.8.18.1.glibc2.4-x86_64.AppImage # Create a directory with the same name as the AppImage plus the ".config" extension From 939ff4d4c033caa0170d0cac643098b5b5664528 Mon Sep 17 00:00:00 2001 From: Anstro Pleuton <121956207+anstropleuton@users.noreply.github.com> Date: Mon, 27 Jul 2026 00:08:02 +0530 Subject: [PATCH 7/7] Fix typo in appimagetool description (#1438) [ci skip] --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 7394bc752..36fff1180 100644 --- a/README.md +++ b/README.md @@ -74,7 +74,7 @@ Note that the file `leafpadrc` was written in the directory we have created befo ## appimagetool -`appimagetool` is a low-level tool used to convert a valid AppDir into an AppImage. It us usually used by [higher-level tools](https://github.com/AppImageCommunity/awesome-appimage?tab=readme-ov-file#appimage-developer-tools) that can be used by application developers to provide AppImages of their applications to end users. `appimagetool` itself is not needed by end users, and is normally not used directly by developers. +`appimagetool` is a low-level tool used to convert a valid AppDir into an AppImage. It is usually used by [higher-level tools](https://github.com/AppImageCommunity/awesome-appimage?tab=readme-ov-file#appimage-developer-tools) that can be used by application developers to provide AppImages of their applications to end users. `appimagetool` itself is not needed by end users, and is normally not used directly by developers. Please see https://github.com/AppImage/appimagetool. ## AppImage runtime